Esempio n. 1
0
        public bool UnpackNode(FileInfoKey nodeKey, string filePath)
        {
            ulong offset           = DataOffset + (ulong)nodeKey.SegmentIndex * GTVolumeTOC.SEGMENT_SIZE;
            uint  uncompressedSize = nodeKey.UncompressedSize;

            if (!IsPatchVolume)
            {
                if (NoUnpack)
                {
                    return(false);
                }

                Stream.Position = (long)offset;
                if (nodeKey.Flags.HasFlag(FileInfoFlags.Compressed))
                {
                    if (!MiscUtils.DecryptCheckCompression(Stream, Keyset, nodeKey.FileIndex, uncompressedSize))
                    {
                        Program.Log($"[X] Failed to decompress file ({filePath}) while unpacking file info key {nodeKey.FileIndex}", forceConsolePrint: true);
                        return(false);
                    }

                    Directory.CreateDirectory(Path.GetDirectoryName(filePath));
                    Stream.Position -= 8;
                    MiscUtils.DecryptAndInflateToFile(Keyset, Stream, nodeKey.FileIndex, uncompressedSize, filePath, false);
                }
                else
                {
                    Directory.CreateDirectory(Path.GetDirectoryName(filePath));
                    MiscUtils.DecryptToFile(Keyset, Stream, nodeKey.FileIndex, uncompressedSize, filePath, false);
                }
            }
            else
            {
                string patchFilePath = PDIPFSPathResolver.GetPathFromSeed(nodeKey.FileIndex);
                string localPath     = this.PatchVolumeFolder + "/" + patchFilePath;

                if (NoUnpack)
                {
                    return(false);
                }

                /* I'm really not sure if there's a better way to do this.
                 * Volume files, at least nodes don't seem to even store any special flag whether
                 * it is located within an actual volume file or a patch volume. The only thing that is different is the sector index.. Sometimes node index when it's updated
                 * It's slow, but somewhat works I guess..
                 * */
                if (!File.Exists(localPath))
                {
                    return(false);
                }

                Program.Log($"[:] Unpacking: {patchFilePath} -> {filePath}");

                using var fs = new FileStream(localPath, FileMode.Open);
                if (fs.Length >= 7)
                {
                    Span <byte> magic = stackalloc byte[6];
                    fs.Read(magic);
                    if (Encoding.ASCII.GetString(magic).StartsWith("BSDIFF"))
                    {
                        Program.Log($"[X] Detected BSDIFF file for {filePath} ({patchFilePath}), can not unpack yet. (fileID {nodeKey.FileIndex})", forceConsolePrint: true);
                        return(false);
                    }

                    fs.Position = 0;
                }


                if (nodeKey.Flags.HasFlag(FileInfoFlags.Compressed))
                {
                    if (!MiscUtils.DecryptCheckCompression(fs, Keyset, nodeKey.FileIndex, uncompressedSize))
                    {
                        Program.Log($"[X] Failed to decompress file {filePath} ({patchFilePath}) while unpacking file info key {nodeKey.FileIndex}", forceConsolePrint: true);
                        return(false);
                    }

                    Directory.CreateDirectory(Path.GetDirectoryName(filePath));
                    fs.Position = 0;
                    MiscUtils.DecryptAndInflateToFile(Keyset, fs, nodeKey.FileIndex, filePath);
                }
                else
                {
                    Directory.CreateDirectory(Path.GetDirectoryName(filePath));
                    MiscUtils.DecryptToFile(Keyset, fs, nodeKey.FileIndex, filePath);
                }
            }

            return(true);
        }