public MemoryStream Read(Stream input, DataDefinition data)
        {
            switch (data.Type.CompressionMode)
            {
            case CompressionMode.CompressedPerType:
            {
                var buffer = this.GetType(input, data.Type);
                buffer.Seek(data.Offset, SeekOrigin.Begin);
                return(buffer.ReadToMemoryStream(data.UncompressedSize));
            }

            case CompressionMode.CompressedPerResource:
            {
                input.Seek(data.Type.Offset, SeekOrigin.Begin);
                input.Seek(data.Offset, SeekOrigin.Current);

                var zlib = new InflaterInputStream(input);
                return(zlib.ReadToMemoryStream(data.UncompressedSize));
            }

            default:
            {
                throw new NotImplementedException();
            }
            }
        }
        protected MemoryStream GetType(Stream input, TypeDefinition type)
        {
            if (this.LoadedTypes.ContainsKey(type) == false)
            {
                input.Seek(type.Offset, SeekOrigin.Begin);

                var zlib = new InflaterInputStream(input);
                this.LoadedTypes[type] =
                    zlib.ReadToMemoryStream(type.UncompressedSize);
            }

            return(this.LoadedTypes[type]);
        }
示例#3
0
        public static MemoryStream Decompress(Stream input)
        {
            var dcx = new CompressedFile();

            dcx.Deserialize(input);

            if (dcx._Setup.Scheme == CompressionScheme.Zlib)
            {
                if (dcx._Setup.Unknown1C != 0 ||
                    dcx._Setup.Unknown20 != 0 ||
                    dcx._Setup.Unknown24 != 0 ||
                    dcx._Setup.Flags != 0x00010100)
                {
                    throw new FormatException();
                }

                using (var temp = input.ReadToMemoryStream(dcx._Size.CompressedSize))
                {
                    var zlib = new InflaterInputStream(temp);
                    return(zlib.ReadToMemoryStream(dcx._Size.UncompressedSize));
                }
            }
            else if (dcx._Setup.Scheme == CompressionScheme.Edge)
            {
                if (dcx._Setup.Unknown1C != 0x00010000 ||
                    dcx._Setup.Unknown20 != 0 ||
                    dcx._Setup.Unknown24 != 0 ||
                    dcx._Setup.Flags != 0x00100100)
                {
                    throw new FormatException();
                }

                using (var table = new MemoryStream(dcx._Extra.Data))
                {
                    if (table.ReadValueU32(Endian.Big) != 0x45676454) // EdgT = Edge Table?
                    {
                        throw new FormatException();
                    }

                    var unknown04                  = table.ReadValueU32(Endian.Big);
                    var tableOffset                = table.ReadValueU32(Endian.Big);
                    var alignment                  = table.ReadValueU32(Endian.Big);
                    var uncompressedBlockSize      = table.ReadValueU32(Endian.Big);
                    var finalUncompressedBlockSize = table.ReadValueU32(Endian.Big);
                    var extraSize                  = table.ReadValueU32(Endian.Big);
                    var blockCount                 = table.ReadValueU32(Endian.Big);
                    var unknown20                  = table.ReadValueU32(Endian.Big);

                    if (extraSize != table.Length)
                    {
                        throw new FormatException();
                    }

                    if (unknown04 != 0x00010100 ||
                        tableOffset != 36 ||
                        alignment != 16 ||
                        uncompressedBlockSize != 0x00010000 ||
                        unknown20 != 0x00100000)
                    {
                        throw new FormatException();
                    }

                    var data = new MemoryStream();

                    for (uint i = 0; i < blockCount; i++)
                    {
                        var bunknown0   = table.ReadValueU32(Endian.Big);
                        var blockOffset = table.ReadValueU32(Endian.Big);
                        var blockSize   = table.ReadValueU32(Endian.Big);
                        var blockFlags  = table.ReadValueU32(Endian.Big);

                        if (bunknown0 != 0 ||
                            (blockFlags != 0 && blockFlags != 1))
                        {
                            throw new FormatException();
                        }

                        using (var temp = input.ReadToMemoryStream(blockSize.Align(alignment)))
                        {
                            if (blockFlags == 1)
                            {
                                var zlib = new InflaterInputStream(temp, new Inflater(true));
                                data.WriteFromStream(zlib,
                                                     i + 1 < blockCount
                                                         ? uncompressedBlockSize
                                                         : finalUncompressedBlockSize);
                            }
                            else if (blockFlags == 0)
                            {
                                data.WriteFromStream(temp,
                                                     i + 1 < blockCount
                                                         ? uncompressedBlockSize
                                                         : finalUncompressedBlockSize);
                            }
                            else
                            {
                                throw new NotImplementedException();
                            }
                        }
                    }

                    if (data.Length != dcx._Size.UncompressedSize)
                    {
                        throw new InvalidOperationException();
                    }

                    data.Position = 0;
                    return(data);
                }
            }
            else
            {
                throw new NotImplementedException();
            }
        }