Esempio n. 1
0
        private static SwitchFs OpenSdCard(string path, IProgressReport logger = null)
        {
            SwitchFs switchFs;
            Keyset   keyset = OpenKeyset();

            var baseFs = new LocalFileSystem(path);

            if (Directory.Exists(Path.Combine(path, "Nintendo", "Contents", "registered")))
            {
                logger?.LogMessage("Treating path as SD card storage");
                switchFs = SwitchFs.OpenSdCard(keyset, baseFs);
            }
            else if (Directory.Exists(Path.Combine(path, "Contents", "registered")))
            {
                logger?.LogMessage("Treating path as NAND storage");
                switchFs = SwitchFs.OpenNandPartition(keyset, baseFs);
            }
            else
            {
                logger?.LogMessage("Treating path as a directory of loose NCAs");
                switchFs = SwitchFs.OpenNcaDirectory(keyset, baseFs);
            }

            return(switchFs);
        }
Esempio n. 2
0
        private static void ReadTitleKeys(Keyset keyset, string filename, IProgressReport progress = null)
        {
            if (filename == null)
            {
                return;
            }

            using (var reader = new StreamReader(new FileStream(filename, FileMode.Open, FileAccess.Read)))
            {
                string line;
                while ((line = reader.ReadLine()) != null)
                {
                    string[] splitLine;

                    // Some people use pipes as delimiters
                    if (line.Contains('|'))
                    {
                        splitLine = line.Split('|');
                    }
                    else
                    {
                        splitLine = line.Split(',', '=');
                    }

                    if (splitLine.Length < 2)
                    {
                        continue;
                    }

                    if (!splitLine[0].Trim().TryToBytes(out byte[] rightsId))
                    {
                        progress?.LogMessage($"Invalid rights ID \"{splitLine[0].Trim()}\" in title key file");
                        continue;
                    }

                    if (!splitLine[1].Trim().TryToBytes(out byte[] titleKey))
                    {
                        progress?.LogMessage($"Invalid title key \"{splitLine[1].Trim()}\" in title key file");
                        continue;
                    }

                    if (rightsId.Length != TitleKeySize)
                    {
                        progress?.LogMessage($"Rights ID {rightsId.ToHexString()} had incorrect size {rightsId.Length}. (Expected {TitleKeySize})");
                        continue;
                    }

                    if (titleKey.Length != TitleKeySize)
                    {
                        progress?.LogMessage($"Title key {titleKey.ToHexString()} had incorrect size {titleKey.Length}. (Expected {TitleKeySize})");
                        continue;
                    }

                    keyset.TitleKeys[rightsId] = titleKey;
                }
            }
        }
Esempio n. 3
0
        public static void PrintAllTables(BdatStringCollection bdats, string jsonDir, IProgressReport progress = null)
        {
            progress?.LogMessage("Writing BDAT tables as JSON");
            progress?.SetTotal(bdats.Tables.Count);
            string bdatHtmlDir = Path.Combine(jsonDir, "json");

            Directory.CreateDirectory(bdatHtmlDir);

            foreach (string tableName in bdats.Tables.Keys)
            {
                string outDir        = bdatHtmlDir;
                string tableFilename = bdats[tableName].Filename;

                string json = PrintTable(bdats[tableName]);

                if (tableFilename != null)
                {
                    outDir = Path.Combine(outDir, tableFilename);
                }

                string filename = Path.Combine(outDir, tableName + ".json");
                Directory.CreateDirectory(outDir);
                File.WriteAllText(filename, json);
                progress?.ReportAdd(1);
            }
        }
Esempio n. 4
0
        public IEnumerable <byte[]> EnumerateFiles(IProgressReport progress = null)
        {
            FileListTab[] fileListTabs = Table20.FileList;

            progress?.SetTotal(fileListTabs.Length);

            for (int i = 0; i < fileListTabs.Length; i++)
            {
                bool   success = false;
                byte[] data    = new byte[0];

                try
                {
                    data    = GetFileFromIndex(i);
                    success = true;
                }
                catch (Exception)
                {
                    progress?.LogMessage($"Error getting file {i}");
                }

                if (success)
                {
                    yield return(data);
                }
                progress?.ReportAdd(1);
            }
        }
Esempio n. 5
0
        public static Validity VerifySection(this Nca nca, Nca patchNca, int index, IProgressReport logger = null, bool quiet = false)
        {
            NcaFsHeader sect     = nca.Header.GetFsHeader(index);
            NcaHashType hashType = sect.HashType;

            if (hashType != NcaHashType.Sha256 && hashType != NcaHashType.Ivfc)
            {
                return(Validity.Unchecked);
            }

            var stream = nca.OpenStorageWithPatch(patchNca, index, IntegrityCheckLevel.IgnoreOnInvalid)
                         as HierarchicalIntegrityVerificationStorage;

            if (stream == null)
            {
                return(Validity.Unchecked);
            }

            if (!quiet)
            {
                logger?.LogMessage($"Verifying section {index}...");
            }
            Validity validity = stream.Validate(true, logger);

            return(validity);
        }
Esempio n. 6
0
        public static bool AddHashIfExists(string value, bool addToAllHashList = true, IProgressReport progress = null)
        {
            value = value.ToLowerInvariant();
            uint hash = Archive.Crc32(value);
            long key  = (long)value.Length << 32 | hash;

            if (addToAllHashList)
            {
                AllHashStrings[key] = value;
            }

            if (Hashes.Contains(key) && !HashStrings.ContainsKey(key) && !value.Contains('%'))
            {
                HashStrings[key] = value;
                NewStrings[key]  = value;
                if (progress == null)
                {
                    Console.WriteLine($"Found new hash {value}");
                }
                else
                {
                    progress.LogMessage($"Found new hash {value}");
                }

                return(true);
            }

            return(false);
        }
Esempio n. 7
0
        private void DecryptKeyblobs(IProgressReport logger = null)
        {
            var cmac         = new byte[0x10];
            var expectedCmac = new byte[0x10];
            var counter      = new byte[0x10];

            for (int i = 0; i < UsedKeyblobCount; i++)
            {
                if (KeyblobKeys[i].IsEmpty() || KeyblobMacKeys[i].IsEmpty() || EncryptedKeyblobs[i].IsEmpty())
                {
                    continue;
                }

                Array.Copy(EncryptedKeyblobs[i], expectedCmac, 0x10);
                CryptoOld.CalculateAesCmac(KeyblobMacKeys[i], EncryptedKeyblobs[i], 0x10, cmac, 0, 0xa0);

                if (!Util.ArraysEqual(cmac, expectedCmac))
                {
                    logger?.LogMessage($"Warning: Keyblob MAC {i:x2} is invalid. Are SBK/TSEC key correct?");
                }

                Array.Copy(EncryptedKeyblobs[i], 0x10, counter, 0, 0x10);

                Aes.DecryptCtr128(EncryptedKeyblobs[i].AsSpan(0x20), Keyblobs[i], KeyblobKeys[i], counter);
            }
        }
Esempio n. 8
0
        public static void CopyDirectory(this IDirectory source, IDirectory dest, IProgressReport logger = null, CreateFileOptions options = CreateFileOptions.None)
        {
            IFileSystem sourceFs = source.ParentFileSystem;
            IFileSystem destFs   = dest.ParentFileSystem;

            foreach (DirectoryEntry entry in source.Read())
            {
                string subSrcPath = PathTools.Normalize(source.FullPath + '/' + entry.Name);
                string subDstPath = PathTools.Normalize(dest.FullPath + '/' + entry.Name);

                if (entry.Type == DirectoryEntryType.Directory)
                {
                    destFs.CreateDirectory(subDstPath);
                    IDirectory subSrcDir = sourceFs.OpenDirectory(subSrcPath, OpenDirectoryMode.All);
                    IDirectory subDstDir = destFs.OpenDirectory(subDstPath, OpenDirectoryMode.All);

                    subSrcDir.CopyDirectory(subDstDir, logger, options);
                }

                if (entry.Type == DirectoryEntryType.File)
                {
                    destFs.CreateFile(subDstPath, entry.Size, options);

                    using (IFile srcFile = sourceFs.OpenFile(subSrcPath, OpenMode.Read))
                        using (IFile dstFile = destFs.OpenFile(subDstPath, OpenMode.Write | OpenMode.Append))
                        {
                            logger?.LogMessage(subSrcPath);
                            srcFile.CopyTo(dstFile, logger);
                        }
                }
            }
        }
Esempio n. 9
0
        private void DecryptKeyblobs(IProgressReport logger = null)
        {
            var cmac         = new byte[0x10];
            var expectedCmac = new byte[0x10];
            var counter      = new byte[0x10];

            for (int i = 0; i < UsedKeyblobCount; i++)
            {
                if (KeyblobKeys[i].IsEmpty() || KeyblobMacKeys[i].IsEmpty() || EncryptedKeyblobs[i].IsEmpty())
                {
                    continue;
                }

                Array.Copy(EncryptedKeyblobs[i], expectedCmac, 0x10);
                Crypto.CalculateAesCmac(KeyblobMacKeys[i], EncryptedKeyblobs[i], 0x10, cmac, 0, 0xa0);

                if (!Util.ArraysEqual(cmac, expectedCmac))
                {
                    logger?.LogMessage($"Warning: Keyblob MAC {i:x2} is invalid. Are SBK/TSEC key correct?");
                }

                Array.Copy(EncryptedKeyblobs[i], 0x10, counter, 0, 0x10);

                using (var keyblobDec = new Aes128CtrStorage(
                           new MemoryStorage(EncryptedKeyblobs[i], 0x20, Keyblobs[i].Length), KeyblobKeys[i], counter, false))
                {
                    keyblobDec.Read(Keyblobs[i], 0);
                }
            }
        }
Esempio n. 10
0
        public static void CopyDirectory(this FileSystemManager fs, string sourcePath, string destPath,
                                         CreateFileOptions options = CreateFileOptions.None, IProgressReport logger = null)
        {
            using (DirectoryHandle sourceHandle = fs.OpenDirectory(sourcePath, OpenDirectoryMode.All))
            {
                foreach (DirectoryEntry entry in fs.ReadDirectory(sourceHandle))
                {
                    string subSrcPath = PathTools.Normalize(PathTools.Combine(sourcePath, entry.Name));
                    string subDstPath = PathTools.Normalize(PathTools.Combine(destPath, entry.Name));

                    if (entry.Type == DirectoryEntryType.Directory)
                    {
                        fs.EnsureDirectoryExists(subDstPath);

                        fs.CopyDirectory(subSrcPath, subDstPath, options, logger);
                    }

                    if (entry.Type == DirectoryEntryType.File)
                    {
                        logger?.LogMessage(subSrcPath);
                        fs.CreateOrOverwriteFile(subDstPath, entry.Size, options);

                        fs.CopyFile(subSrcPath, subDstPath, logger);
                    }
                }
            }
        }
Esempio n. 11
0
        private static void CopyDirectoryWithProgressInternal(FileSystemClient fs, string sourcePath, string destPath,
                                                              CreateFileOptions options, IProgressReport logger)
        {
            fs.OpenDirectory(out DirectoryHandle sourceHandle, sourcePath, OpenDirectoryMode.All).ThrowIfFailure();

            using (sourceHandle)
            {
                foreach (DirectoryEntryEx entry in fs.EnumerateEntries(sourcePath, "*", SearchOptions.Default))
                {
                    string subSrcPath = PathTools.Normalize(PathTools.Combine(sourcePath, entry.Name));
                    string subDstPath = PathTools.Normalize(PathTools.Combine(destPath, entry.Name));

                    if (entry.Type == DirectoryEntryType.Directory)
                    {
                        fs.EnsureDirectoryExists(subDstPath);

                        CopyDirectoryWithProgressInternal(fs, subSrcPath, subDstPath, options, logger);
                    }

                    if (entry.Type == DirectoryEntryType.File)
                    {
                        logger?.LogMessage(subSrcPath);
                        fs.CreateOrOverwriteFile(subDstPath, entry.Size, options);

                        CopyFileWithProgress(fs, subSrcPath, subDstPath, logger);
                    }
                }
            }
        }
Esempio n. 12
0
        private static Result CopyDirectoryWithProgressInternal(FileSystemClient fs, U8Span sourcePath, U8Span destPath,
                                                                CreateFileOptions options, IProgressReport logger)
        {
            string sourcePathStr = sourcePath.ToString();
            string destPathStr   = destPath.ToString();

            Result rc = fs.OpenDirectory(out DirectoryHandle sourceHandle, sourcePath, OpenDirectoryMode.All);

            if (rc.IsFailure())
            {
                return(rc);
            }

            try
            {
                foreach (DirectoryEntryEx entry in fs.EnumerateEntries(sourcePathStr, "*", SearchOptions.Default))
                {
                    string subSrcPath = PathTools.Normalize(PathTools.Combine(sourcePathStr, entry.Name));
                    string subDstPath = PathTools.Normalize(PathTools.Combine(destPathStr, entry.Name));

                    if (entry.Type == DirectoryEntryType.Directory)
                    {
                        fs.EnsureDirectoryExists(subDstPath);

                        rc = CopyDirectoryWithProgressInternal(fs, subSrcPath.ToU8Span(), subDstPath.ToU8Span(), options, logger);
                        if (rc.IsFailure())
                        {
                            return(rc);
                        }
                    }

                    if (entry.Type == DirectoryEntryType.File)
                    {
                        logger?.LogMessage(subSrcPath);

                        rc = fs.CreateOrOverwriteFile(subDstPath, entry.Size, options);
                        if (rc.IsFailure())
                        {
                            return(rc);
                        }

                        rc = CopyFileWithProgress(fs, subSrcPath.ToU8Span(), subDstPath.ToU8Span(), logger);
                        if (rc.IsFailure())
                        {
                            return(rc);
                        }
                    }
                }
            }
            finally
            {
                if (sourceHandle.IsValid)
                {
                    fs.CloseDirectory(sourceHandle);
                }
            }

            return(Result.Success);
        }
Esempio n. 13
0
        public static void PrintSeparateTables(BdatStringCollection bdats, string htmlDir, IProgressReport progress = null)
        {
            progress?.LogMessage("Writing BDAT tables as HTML");
            progress?.SetTotal(bdats.Tables.Count);
            string bdatHtmlDir = Path.Combine(htmlDir, "bdat");

            Directory.CreateDirectory(bdatHtmlDir);

            if (bdats.Game == Game.XB2)
            {
                PrintIndex(bdats, htmlDir);
            }
            PrintBdatIndex(bdats, bdatHtmlDir);
            foreach (string tableName in bdats.Tables.Keys)
            {
                string outDir        = bdatHtmlDir;
                string tableFilename = bdats[tableName].Filename;
                string indexPath     = tableFilename == null ? "index.html" : "../index.html";

                var sb = new Indenter(2);
                sb.AppendLine("<!DOCTYPE html>");
                sb.AppendLineAndIncrease("<html>");
                sb.AppendLineAndIncrease("<head>");
                sb.AppendLine("<meta charset=\"utf-8\" />");
                sb.AppendLine($"<title>{tableName}</title>");
                sb.AppendLineAndIncrease("<style>");
                sb.AppendLine(CssSticky);
                sb.AppendLine(CssSortable);
                sb.DecreaseAndAppendLine("</style>");
                sb.DecreaseAndAppendLine("</head>");

                sb.AppendLineAndIncrease("<body>");
                sb.AppendLine($"<a href=\"{indexPath}\">Return to BDAT index</a><br/>");
                sb.AppendLine("<input type=\"button\" value=\"Open all references\" onclick=\"openAll(true)\" />");
                sb.AppendLine("<input type=\"button\" value=\"Close all references\" onclick=\"openAll(false)\" />");
                PrintTable(bdats[tableName], sb);
                sb.AppendLineAndIncrease("<script>");
                sb.AppendLine(JsOpenAll);
                sb.AppendLine(JsSortable);
                sb.AppendLine(JsAnchor);
                sb.DecreaseAndAppendLine("</script>");
                sb.DecreaseAndAppendLine("</body>");
                sb.DecreaseAndAppendLine("</html>");

                if (tableFilename != null)
                {
                    outDir = Path.Combine(outDir, tableFilename);
                }

                string filename = Path.Combine(outDir, tableName + ".html");
                Directory.CreateDirectory(outDir);
                File.WriteAllText(filename, sb.ToString());
                progress?.ReportAdd(1);
            }
        }
Esempio n. 14
0
        public Crack(string path, IProgressReport progress = null)
        {
            Progress = progress;

            if (Directory.Exists(path))
            {
                Path = path;
            }
            else
            {
                Progress?.LogMessage($"Directory {path} does not exist.");
            }
        }
Esempio n. 15
0
        private static void ReadMainKeys(Keyset keyset, string filename, Dictionary <string, KeyValue> keyDict, IProgressReport logger = null)
        {
            if (filename == null)
            {
                return;
            }

            using (var reader = new StreamReader(new FileStream(filename, FileMode.Open, FileAccess.Read)))
            {
                string line;
                while ((line = reader.ReadLine()) != null)
                {
                    string[] a = line.Split(',', '=');
                    if (a.Length != 2)
                    {
                        continue;
                    }

                    string key      = a[0].Trim();
                    string valueStr = a[1].Trim();

                    if (!keyDict.TryGetValue(key, out KeyValue kv))
                    {
                        logger?.LogMessage($"Failed to match key {key}");
                        continue;
                    }

                    byte[] value = valueStr.ToBytes();
                    if (value.Length != kv.Size)
                    {
                        logger?.LogMessage($"Key {key} had incorrect size {value.Length}. (Expected {kv.Size})");
                        continue;
                    }

                    byte[] dest = kv.GetKey(keyset);
                    Array.Copy(value, dest, value.Length);
                }
            }
        }
Esempio n. 16
0
        public static void GenerateBdatHtml(IFileSystem fs, string outDir, IProgressReport progress)
        {
            var bdats = new BdatTables(fs, true, progress);
            BdatStringCollection tablesStr = DeserializeStrings.DeserializeTables(bdats, progress);

            Metadata.ApplyMetadata(tablesStr);
            HtmlGen.PrintSeparateTables(tablesStr, Path.Combine(outDir, BdatDir), progress);
            JsonGen.PrintAllTables(tablesStr, Path.Combine(outDir, JsonDir), progress);

            BdatCollection tables = Deserialize.DeserializeTables(bdats, progress);

            string dataDir = Path.Combine(outDir, DataDir);

            progress.SetTotal(0);
            progress.LogMessage("Creating salvaging tables");
            Directory.CreateDirectory(dataDir);
            string salvaging = SalvagingTable.Print(tables);

            File.WriteAllText(Path.Combine(dataDir, "salvaging.html"), salvaging);

            progress.LogMessage("Creating enemy tables");
            using (var writer = new StreamWriter(Path.Combine(dataDir, "enemies.csv")))
            {
                Enemies.PrintEnemies(tables, writer);
            }

            progress.LogMessage("Creating achievement tables");
            using (var writer = new StreamWriter(Path.Combine(dataDir, "achievements.csv")))
            {
                Achievements.PrintAchievements(tables, writer);
            }

            string gmkDir = Path.Combine(outDir, GmkDir);

            MapInfo[] gimmicks = ReadGmk.ReadAll(fs, tables, progress);
            progress.LogMessage("Writing map info and gimmick data");
            ExportMap.ExportCsv(gimmicks, gmkDir);
        }
Esempio n. 17
0
        public static Result CopyDirectory(this IFileSystem sourceFs, IFileSystem destFs, string sourcePath, string destPath,
                                           IProgressReport logger = null, CreateFileOptions options = CreateFileOptions.None)
        {
            Result rc;

            foreach (DirectoryEntryEx entry in sourceFs.EnumerateEntries(sourcePath, "*", SearchOptions.Default))
            {
                string subSrcPath = PathTools.Normalize(PathTools.Combine(sourcePath, entry.Name));
                string subDstPath = PathTools.Normalize(PathTools.Combine(destPath, entry.Name));

                if (entry.Type == DirectoryEntryType.Directory)
                {
                    destFs.EnsureDirectoryExists(subDstPath);

                    rc = sourceFs.CopyDirectory(destFs, subSrcPath, subDstPath, logger, options);
                    if (rc.IsFailure())
                    {
                        return(rc);
                    }
                }

                if (entry.Type == DirectoryEntryType.File)
                {
                    destFs.CreateOrOverwriteFile(subDstPath, entry.Size, options);

                    rc = sourceFs.OpenFile(out IFile srcFile, subSrcPath.ToU8Span(), OpenMode.Read);
                    if (rc.IsFailure())
                    {
                        return(rc);
                    }

                    using (srcFile)
                    {
                        rc = destFs.OpenFile(out IFile dstFile, subDstPath.ToU8Span(), OpenMode.Write | OpenMode.AllowAppend);
                        if (rc.IsFailure())
                        {
                            return(rc);
                        }

                        using (dstFile)
                        {
                            logger?.LogMessage(subSrcPath);
                            srcFile.CopyTo(dstFile, logger);
                        }
                    }
                }
            }

            return(Result.Success);
        }
Esempio n. 18
0
        public GuessAdx(string path, string executable, IProgressReport progress = null)
        {
            Progress = progress;
            Progress?.SetTotal(0x1000);

            if (Directory.Exists(path))
            {
                EncryptionType = LoadFiles(Directory.GetFiles(path, "*.adx"));
            }
            else if (File.Exists(path))
            {
                EncryptionType = LoadFiles(path);
            }
            else
            {
                Progress?.LogMessage($"{path} does not exist.");
            }

            switch (EncryptionType)
            {
            case 8:
                int[] primes = Common.GetPrimes(0x8000);

                // .NET returns the bitwise complement of the index of the first element
                // smaller than the search value if it is not found in the array
                int start = ~Array.BinarySearch(primes, 0x4000);
                PossibleMultipliers = new int[0x400];
                Array.Copy(primes, start, PossibleMultipliers, 0, 0x400);

                PossibleIncrements = PossibleMultipliers;
                PossibleSeeds      = new HashSet <int>(PossibleMultipliers);
                ValidationMask     = 0xE000;
                MaxSeed            = 0x8000;
                break;

            case 9:
                PossibleSeeds       = new HashSet <int>(Enumerable.Range(0, 0x2000));
                PossibleMultipliers = Enumerable.Range(0, 0x2000).Where(x => (x & 3) == 1).ToArray();
                PossibleIncrements  = Enumerable.Range(0, 0x2000).Where(x => (x & 1) == 1).ToArray();
                ValidationMask      = 0x1000;
                MaxSeed             = 0x2000;
                break;
            }

            if (EncryptionType == 8 && executable != null)
            {
                KeyStrings = LoadStrings(executable, path);
            }
        }
Esempio n. 19
0
        // Benchmarks encrypting each block separately, initializing a new cipher object for each one
        private static void CipherBenchmarkSeparate(ReadOnlySpan <byte> src, Span <byte> dst, CipherTaskSeparate function,
                                                    int iterations, string label, bool dotNetCrypto, IProgressReport logger)
        {
            Debug.Assert(src.Length == dst.Length);

            var watch = new Stopwatch();

            double[] runTimes = new double[iterations];

            ReadOnlySpan <byte> key1 = stackalloc byte[0x10];
            ReadOnlySpan <byte> key2 = stackalloc byte[0x10];
            ReadOnlySpan <byte> iv   = stackalloc byte[0x10];

            logger.SetTotal(iterations);

            const int blockSize  = BlockSizeSeparate;
            int       blockCount = src.Length / blockSize;

            for (int i = 0; i < iterations; i++)
            {
                watch.Restart();

                for (int b = 0; b < blockCount; b++)
                {
                    function(src.Slice(b * blockSize, blockSize), dst.Slice(b * blockSize, blockSize),
                             key1, key2, iv, dotNetCrypto);
                }

                watch.Stop();

                logger.ReportAdd(1);
                runTimes[i] = watch.Elapsed.TotalSeconds;
            }

            logger.SetTotal(0);

            long srcSize = src.Length;

            double fastestRun = runTimes.Min();
            double averageRun = runTimes.Average();
            double slowestRun = runTimes.Max();

            string fastestRate = Utilities.GetBytesReadable((long)(srcSize / fastestRun));
            string averageRate = Utilities.GetBytesReadable((long)(srcSize / averageRun));
            string slowestRate = Utilities.GetBytesReadable((long)(srcSize / slowestRun));

            logger.LogMessage($"{label}{averageRate}/s, fastest run: {fastestRate}/s, slowest run: {slowestRate}/s");
        }
Esempio n. 20
0
        public static BdatStringCollection DeserializeTables(BdatTables tables, IProgressReport progress = null)
        {
            var collection = new BdatStringCollection {
                Bdats = tables
            };

            progress?.LogMessage("Parsing BDAT tables");
            progress?.SetTotal(tables.Tables.Length);

            foreach (BdatTable table in tables.Tables)
            {
                var items = new BdatStringItem[table.ItemCount];

                var stringTable = new BdatStringTable
                {
                    Collection = collection,
                    Name       = table.Name,
                    BaseId     = table.BaseId,
                    Members    = table.Members,
                    Items      = items,
                    Filename   = table.Filename
                };

                if (tables.DisplayFields.TryGetValue(table.Name, out string displayMember))
                {
                    stringTable.DisplayMember = displayMember;
                }

                for (int i = 0; i < table.ItemCount; i++)
                {
                    BdatStringItem item = ReadItem(table, i);
                    item.Table = stringTable;
                    item.Id    = table.BaseId + i;

                    if (displayMember != null)
                    {
                        item.Display = item[displayMember];
                    }

                    items[i] = item;
                }

                collection.Add(stringTable);
                progress?.ReportAdd(1);
            }

            return(collection);
        }
Esempio n. 21
0
        public static BdatCollection DeserializeTables(BdatTables files, IProgressReport progress = null)
        {
            progress?.LogMessage("Deserializing BDAT tables");
            progress?.SetTotal(files.Tables.Length);
            var tables = new BdatCollection();

            foreach (BdatTable table in files.Tables)
            {
                ReadTable(table, tables);
                progress?.ReportAdd(1);
            }

            ReadFunctions.SetReferences(tables);

            return(tables);
        }
Esempio n. 22
0
        private static Ticket[] GetTickets(Keyset keyset, Nand nand, IProgressReport logger = null)
        {
            var tickets = new List <Ticket>();
            FatFileSystemProvider system = nand.OpenSystemPartition();

            IFile saveE1File = system.OpenFile("/save/80000000000000E1", OpenMode.Read);

            tickets.AddRange(ReadTickets(keyset, saveE1File.AsStream()));

            IFile saveE2 = system.OpenFile("/save/80000000000000E2", OpenMode.Read);

            tickets.AddRange(ReadTickets(keyset, saveE2.AsStream()));

            logger?.LogMessage($"Found {tickets.Count} tickets");

            return(tickets.ToArray());
        }
Esempio n. 23
0
        private static Ticket[] GetTickets(Keyset keyset, Nand nand, IProgressReport logger = null)
        {
            var           tickets = new List <Ticket>();
            NandPartition system  = nand.OpenSystemPartition();

            Stream saveE1File = system.OpenFile("save\\80000000000000E1", FileMode.Open, FileAccess.Read);

            tickets.AddRange(ReadTickets(keyset, saveE1File));

            Stream saveE2 = system.OpenFile("save\\80000000000000E2", FileMode.Open, FileAccess.Read);

            tickets.AddRange(ReadTickets(keyset, saveE2));

            logger?.LogMessage($"Found {tickets.Count} tickets");

            return(tickets.ToArray());
        }
Esempio n. 24
0
        private static void CipherBenchmarkBlocked(ReadOnlySpan <byte> src, Span <byte> dst, Func <ICipher> cipherGenerator,
                                                   int iterations, string label, IProgressReport logger)
        {
            cipherGenerator().Transform(src, dst);

            var watch = new Stopwatch();

            double[] runTimes = new double[iterations];

            logger.SetTotal(iterations);

            int blockCount = src.Length / BlockSizeBlocked;

            for (int i = 0; i < iterations; i++)
            {
                ICipher cipher = cipherGenerator();

                watch.Restart();

                for (int b = 0; b < blockCount; b++)
                {
                    cipher.Transform(src.Slice(b * BlockSizeBlocked, BlockSizeBlocked),
                                     dst.Slice(b * BlockSizeBlocked, BlockSizeBlocked));
                }

                watch.Stop();

                logger.ReportAdd(1);
                runTimes[i] = watch.Elapsed.TotalSeconds;
            }

            logger.SetTotal(0);

            long srcSize = src.Length;

            double fastestRun = runTimes.Min();
            double averageRun = runTimes.Average();
            double slowestRun = runTimes.Max();

            string fastestRate = Utilities.GetBytesReadable((long)(srcSize / fastestRun));
            string averageRate = Utilities.GetBytesReadable((long)(srcSize / averageRun));
            string slowestRate = Utilities.GetBytesReadable((long)(srcSize / slowestRun));

            logger.LogMessage($"{label}{averageRate}/s, fastest run: {fastestRate}/s, slowest run: {slowestRate}/s");
        }
        public static Result CopyDirectory(this FileSystemClient fs, string sourcePath, string destPath,
                                           CreateFileOptions options = CreateFileOptions.None, IProgressReport logger = null)
        {
            Result rc = fs.OpenDirectory(out DirectoryHandle sourceHandle, sourcePath.ToU8Span(), OpenDirectoryMode.All);

            if (rc.IsFailure())
            {
                return(rc);
            }

            using (sourceHandle)
            {
                foreach (DirectoryEntryEx entry in fs.EnumerateEntries(sourcePath, "*", SearchOptions.Default))
                {
                    string subSrcPath = PathTools.Normalize(PathTools.Combine(sourcePath, entry.Name));
                    string subDstPath = PathTools.Normalize(PathTools.Combine(destPath, entry.Name));

                    if (entry.Type == DirectoryEntryType.Directory)
                    {
                        fs.EnsureDirectoryExists(subDstPath);

                        rc = fs.CopyDirectory(subSrcPath, subDstPath, options, logger);
                        if (rc.IsFailure())
                        {
                            return(rc);
                        }
                    }

                    if (entry.Type == DirectoryEntryType.File)
                    {
                        logger?.LogMessage(subSrcPath);
                        fs.CreateOrOverwriteFile(subDstPath, entry.Size, options);

                        rc = fs.CopyFile(subSrcPath, subDstPath, logger);
                        if (rc.IsFailure())
                        {
                            return(rc);
                        }
                    }
                }
            }

            return(Result.Success);
        }
Esempio n. 26
0
        public static void Extract(FileArchive archive, string outDir, IProgressReport progress = null)
        {
            FileInfo[] fileInfos = archive.FileInfo.Where(x => !string.IsNullOrWhiteSpace(x.Filename)).ToArray();
            progress?.SetTotal(fileInfos.Length);
            progress?.LogMessage("Extracting ARD archive");

            foreach (FileInfo fileInfo in fileInfos)
            {
                string filename = Path.Combine(outDir, fileInfo.Filename.TrimStart('/'));
                string dir      = Path.GetDirectoryName(filename) ?? throw new InvalidOperationException();
                Directory.CreateDirectory(dir);

                using (var outStream = new FileStream(filename, FileMode.Create, FileAccess.Write))
                {
                    archive.OutputFile(fileInfo, outStream);
                }
                progress?.ReportAdd(1);
            }
        }
Esempio n. 27
0
        public static void Extract(this Romfs romfs, string outDir, IProgressReport logger = null)
        {
            foreach (RomfsFile file in romfs.Files)
            {
                Stream stream  = romfs.OpenFile(file);
                string outName = outDir + file.FullPath;
                string dir     = Path.GetDirectoryName(outName);
                if (!string.IsNullOrWhiteSpace(dir))
                {
                    Directory.CreateDirectory(dir);
                }

                using (var outFile = new FileStream(outName, FileMode.Create, FileAccess.ReadWrite))
                {
                    logger?.LogMessage(file.FullPath);
                    stream.CopyStream(outFile, stream.Length, logger);
                }
            }
        }
Esempio n. 28
0
        public static void Extract(this Pfs pfs, string outDir, IProgressReport logger = null)
        {
            foreach (PfsFileEntry file in pfs.Header.Files)
            {
                Stream stream  = pfs.OpenFile(file);
                string outName = Path.Combine(outDir, file.Name);
                string dir     = Path.GetDirectoryName(outName);
                if (!string.IsNullOrWhiteSpace(dir))
                {
                    Directory.CreateDirectory(dir);
                }

                using (var outFile = new FileStream(outName, FileMode.Create, FileAccess.ReadWrite))
                {
                    logger?.LogMessage(file.Name);
                    stream.CopyStream(outFile, stream.Length, logger);
                }
            }
        }
Esempio n. 29
0
        public static void Extract(this Savefile save, string outDir, IProgressReport logger = null)
        {
            foreach (FileEntry file in save.Files)
            {
                IStorage storage = save.OpenFile(file);
                string   outName = outDir + file.FullPath;
                string   dir     = Path.GetDirectoryName(outName);
                if (!string.IsNullOrWhiteSpace(dir))
                {
                    Directory.CreateDirectory(dir);
                }

                using (var outFile = new FileStream(outName, FileMode.Create, FileAccess.ReadWrite))
                {
                    logger?.LogMessage(file.FullPath);
                    storage.CopyToStream(outFile, storage.Length, logger);
                }
            }
        }
Esempio n. 30
0
        public static void ExtractTextures(string[] filenames, string outDir, IProgressReport progress = null)
        {
            progress?.SetTotal(filenames.Length);

            foreach (string filename in filenames)
            {
                try
                {
                    byte[] file = File.ReadAllBytes(filename);
                    string name = Path.GetFileNameWithoutExtension(filename);

                    ExportWilayTextures(file, name, outDir, progress);
                }
                catch (Exception ex)
                {
                    progress?.LogMessage($"{ex.Message} {filename}");
                }
                progress?.ReportAdd(1);
            }
        }