示例#1
0
        public static S3D Load(string file)
        {
            S3D s3d = null;

            //var fileInfo = new FileInfo(file);
            //var s3dFile = new byte[fileInfo.Length];

            using (var fs = new FileStream(file, FileMode.Open, FileAccess.Read))
            {
                int size = Marshal.SizeOf(typeof(PFSHeader));
                var barray = new byte[size];

                fs.Read(barray, 0, size);
                PFSHeader header = Functions.ByteArrayToStructure<PFSHeader>(barray);

                unsafe
                {
                    if (header.MagicCookie[0] != 'P' && header.MagicCookie[1] != 'F' && header.MagicCookie[2] != 'S' && header.MagicCookie[3] != ' ')
                    {
                        throw new ArgumentException();
                    }
                }

                int uint32size = Marshal.SizeOf(typeof(UInt32));

                //determine the file count
                fs.Seek(header.Offset, SeekOrigin.Begin);
                barray = new byte[uint32size];
                fs.Read(barray, 0, uint32size);

                int filecount = BitConverter.ToInt32(barray, 0);
                //var files = new ArchiveFile[filecount];
                var files = new List<ArchiveFile>();
                size = Marshal.SizeOf(typeof(PFSMeta));

                ArchiveFile directory = new ArchiveFile();

                for (int i = 0; i < filecount; i++)
                {
                    barray = new byte[size];
                    fs.Read(barray, 0, size);
                    var block = Functions.ByteArrayToStructure<PFSMeta>(barray);

                    var f = new ArchiveFile();
                    f.Meta = block;

                    if (block.CRC == 0x61580AC9)
                    {
                        directory = f;
                    }
                    else
                    {
                        files.Add(f);
                    }
                }

                if (directory.Meta.Offset == 0 || directory.Meta.Size == 0) throw new Exception("Could not find directory in archive");

                fs.Seek(directory.Meta.Offset, SeekOrigin.Begin);
                size = Marshal.SizeOf(typeof(PFSData));
                barray = new byte[size];

                var tempBuffer = new ArrayList( (int)directory.Meta.Size);
                int inflatedSize = 0;
                while( inflatedSize < directory.Meta.Size )
                {
                    fs.Read(barray, 0, size);

                    var data = Functions.ByteArrayToStructure<PFSData>(barray);

                    var deflatedBuffer = new byte[data.DeflatedLength];
                    var inflatedBuffer = new byte[data.InflatedLength];

                    fs.Read(deflatedBuffer, 0, (int)data.DeflatedLength);

                    s3d = new S3D();
                    s3d.Decompress(deflatedBuffer, (int)data.DeflatedLength, inflatedBuffer, (int)data.InflatedLength);
                    tempBuffer.AddRange(inflatedBuffer);
                    inflatedSize += (int)data.InflatedLength;
                }

                if (directory.Meta.Size != tempBuffer.Count)
                {
                    throw new Exception("Directory size mismatch");
                }

                List<string> fileNames = new List<string>();
                using (var ms = new MemoryStream(tempBuffer.Cast<byte>().ToArray()))
                {
                    ms.Seek(8, SeekOrigin.Begin);
                    var encoding = new ASCIIEncoding();
                    for (int i = 0; i < filecount - 1; i++)
                    {
                        int val = -1;
                        List<byte> namechars = new List<byte>();

                        while (val != 0)
                        {
                            val = ms.ReadByte();

                            if (val != 0)
                            {
                                namechars.Add((byte)val);
                            }
                            else
                            {
                                fileNames.Add(encoding.GetString(namechars.ToArray()));
                                ms.Seek(4, SeekOrigin.Current);
                                break;
                            }
                        }
                    }
                }

                s3d._files = files.OrderBy(x => x.Meta.Offset);
                for (int i = 0; i < s3d._files.Count(); i++)
                {
                    s3d._files.ElementAt(i).Name = fileNames.ElementAt(i).ToLower();
                    s3d.DecompressFile(s3d._files.ElementAt(i), fs);
                }
            }
            return s3d;
        }
示例#2
0
        private void DecompressFile(ArchiveFile file, Stream stream)
        {
            int totalInflated = 0;
            int size = Marshal.SizeOf(typeof(PFSData));
            int offset = (int)file.Meta.Offset;
            List<byte> inflatedBytes = new List<byte>();

            stream.Seek(offset, SeekOrigin.Begin);

            while (totalInflated < file.Meta.Size)
            {
                var barray = new byte[size];
                stream.Read(barray, 0, size);

                var data = Functions.ByteArrayToStructure<PFSData>(barray);

                barray = new byte[data.DeflatedLength];
                stream.Read(barray, 0, (int)data.DeflatedLength);

                var inflated = new byte[data.InflatedLength];
                Decompress(barray, (int)data.DeflatedLength, inflated, (int)data.InflatedLength);
                inflatedBytes.AddRange(inflated);

                totalInflated += (int)data.InflatedLength;
            }
            file.Bytes = inflatedBytes.ToArray();
        }