コード例 #1
0
        private FastBinaryReader GetDataStream(ZFSFileInfo fileInfo)
        {
            ZFSFileInfo originalFile = null;

            if (fileInfo.ContainingPakFilename != null)
            {
                originalFile = fileInfo;
                fileInfo     = _files[fileInfo.ContainingPakFilename];
            }

            if (fileInfo.Compression == 0)
            {
                FastBinaryReader br = new FastBinaryReader(_zfsMemory)
                {
                    Position = fileInfo.Offset,
                    Length   = (int)(fileInfo.Offset + fileInfo.Length)
                };

                if (originalFile != null)
                {
                    br.Position += originalFile.Offset;
                    br.Length    = (int)(br.Position + originalFile.Length);
                }

                return(br);
            }

            CompressionAlgorithm compressionAlgorithm;

            if (fileInfo.Compression == 2)
            {
                compressionAlgorithm = CompressionAlgorithm.LZO1X;
            }
            else if (fileInfo.Compression == 4)
            {
                compressionAlgorithm = CompressionAlgorithm.LZO1Y;
            }
            else
            {
                throw new Exception("Unknown compression " + fileInfo.Compression);
            }

            byte[] fileData = new byte[fileInfo.Length];
            Buffer.BlockCopy(_zfsMemory, (int)fileInfo.Offset, fileData, 0, fileData.Length);

            byte[] decompressedData = new byte[fileInfo.DecompressedLength];
            uint   length           = LZO.Decompress(fileData, decompressedData, fileInfo.DecompressedLength, compressionAlgorithm);

            if (length != fileInfo.DecompressedLength)
            {
                throw new Exception("Decompressed length does not match expected decompressed length");
            }

            FastBinaryReader reader = new FastBinaryReader(decompressedData)
            {
                Position = 0,
                Length   = decompressedData.Length
            };

            if (originalFile != null)
            {
                reader.Position = originalFile.Offset;
                reader.Length   = (int)(originalFile.Offset + originalFile.Length);
            }

            return(reader);
        }
コード例 #2
0
        public void Init()
        {
            _zfsMemory = File.ReadAllBytes(ZFSFilepath);

            List <ZFSFileInfo> pixFiles = new List <ZFSFileInfo>();
            FastBinaryReader   br       = new FastBinaryReader(_zfsMemory);

            string magic = br.ReadCString(4);

            if (magic != "ZFSF")
            {
                throw new Exception("Not an ZFS file");
            }
            uint version = br.ReadUInt32();

            if (version != 1)
            {
                throw new Exception("Only version 1 ZFS files supported");
            }
            uint unk1 = br.ReadUInt32();
            uint numFilesInEachDirectory = br.ReadUInt32();
            uint numFilesTotal           = br.ReadUInt32();
            uint unk2 = br.ReadUInt32();
            uint unk3 = br.ReadUInt32();

            while (true)
            {
                uint nextDirOffset = br.ReadUInt32();
                for (int fileIdx = 0; fileIdx < numFilesInEachDirectory; fileIdx++)
                {
                    if (_files.Count == numFilesTotal)
                    {
                        break;
                    }
                    ZFSFileInfo zfsFileInfo = new ZFSFileInfo();
                    zfsFileInfo.Filename = br.ReadCString(16).ToLower();
                    zfsFileInfo.Offset   = br.ReadUInt32();
                    zfsFileInfo.Id       = br.ReadUInt32();
                    zfsFileInfo.Length   = br.ReadUInt32();
                    br.ReadUInt32(); // Unk
                    zfsFileInfo.Compression        = br.ReadByte();
                    zfsFileInfo.DecompressedLength = br.ReadUInt16();
                    zfsFileInfo.DecompressedLength =
                        (uint)(br.ReadByte() << 16) |
                        zfsFileInfo.DecompressedLength; // Unk perhaps decompressed length is 3 bytes

                    _files.Add(zfsFileInfo.Filename, zfsFileInfo);
                    if (zfsFileInfo.Filename.EndsWithFast(".pix"))
                    {
                        pixFiles.Add(zfsFileInfo);
                    }
                }

                if (_files.Count == numFilesTotal)
                {
                    break;
                }
                br.Position = nextDirOffset;
            }

            // Parse all .pix-files
            //var pakContents = new Dictionary<string, ZFSFileInfo>();
            foreach (ZFSFileInfo pixFile in pixFiles)
            {
                using (FastBinaryReader sr = GetDataStream(pixFile))
                {
                    string l        = sr.ReadLine();
                    int    numFiles = int.Parse(l);
                    for (int i = 0; i < numFiles; i++)
                    {
                        string   line     = sr.ReadLine();
                        string[] splitted = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                        string   filename = splitted[0].ToLower();
                        uint     offset   = uint.Parse(splitted[1]);
                        uint     length   = uint.Parse(splitted[2]);

                        if (_files.ContainsKey(filename))
                        {
                            continue;
                        }
                        _files.Add(filename, new ZFSFileInfo
                        {
                            Filename = filename,
                            Offset   = offset,
                            Length   = length,
                            ContainingPakFilename = pixFile.Filename.Replace(".pix", ".pak")
                        });
                    }
                }
            }
        }
コード例 #3
0
        public void Init(string gamepath)
        {
            var zfsPath = Path.Combine(gamepath, "I76.ZFS");

            _br = new BinaryReader(new FileStream(zfsPath, FileMode.Open));

            var magic = _br.ReadCString(4);

            if (magic != "ZFSF")
            {
                throw new Exception("Not an ZFS file");
            }
            var version = _br.ReadUInt32();

            if (version != 1)
            {
                throw new Exception("Only version 1 ZFS files supported");
            }
            var unk1 = _br.ReadUInt32();
            var numFilesInEachDirectory = _br.ReadUInt32();
            var numFilesTotal           = _br.ReadUInt32();
            var unk2 = _br.ReadUInt32();
            var unk3 = _br.ReadUInt32();

            var pixFiles = new List <string>();

            while (true)
            {
                var nextDirOffset = _br.ReadUInt32();
                for (int fileIdx = 0; fileIdx < numFilesInEachDirectory; fileIdx++)
                {
                    if (_files.Count == numFilesTotal)
                    {
                        break;
                    }
                    var zfsFileInfo = new ZFSFileInfo();
                    zfsFileInfo.Filename = _br.ReadCString(16).ToLower();
                    zfsFileInfo.Offset   = _br.ReadUInt32();
                    zfsFileInfo.Id       = _br.ReadUInt32();
                    zfsFileInfo.Length   = _br.ReadUInt32();
                    zfsFileInfo.Hashunk  = _br.ReadUInt32();
                    var nullmarker = _br.ReadUInt32();
                    _files.Add(zfsFileInfo.Filename, zfsFileInfo);
                    if (zfsFileInfo.Filename.EndsWith(".pix"))
                    {
                        pixFiles.Add(zfsFileInfo.Filename);
                    }
                }
                if (_files.Count == numFilesTotal)
                {
                    break;
                }
                _br.BaseStream.Position = nextDirOffset;
            }

            Gamepath = gamepath;

            // Parse all .pix-files
            //var pakContents = new Dictionary<string, ZFSFileInfo>();
            foreach (var pixFile in pixFiles)
            {
                using (var sr = new StreamReader(GetFileStream(pixFile), Encoding.ASCII))
                {
                    var l        = sr.ReadLine();
                    var numFiles = int.Parse(l);
                    for (var i = 0; i < numFiles; i++)
                    {
                        var line     = sr.ReadLine();
                        var splitted = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                        var filename = splitted[0].ToLower();
                        var offset   = uint.Parse(splitted[1]);
                        var length   = uint.Parse(splitted[2]);

                        if (_files.ContainsKey(filename))
                        {
                            continue;
                        }
                        _files.Add(filename, new ZFSFileInfo
                        {
                            Filename = filename,
                            Offset   = offset,
                            Length   = length,
                            ContainingPakFilename = pixFile.Replace(".pix", ".pak")
                        });
                    }
                }
            }
        }