コード例 #1
0
        private bool FlushOodleCompressedBlock(MemoryStream data, int blockLength)
        {
            byte[] compressed = Oodle.Compress(this._BlockBytes, blockLength, OodleFormat.Kraken, OodleCompressionLevel.Normal);
            Debug.Assert(compressed.Length != 0, "Compressed Block should not be empty");
            data.WriteBytes(compressed);

            // If it doesn't fit within the range of ratio, store as uncompressed.
            if (!IsWithinCompressionRatio(compressed.Length, blockLength))
            {
                return(false);
            }

            var compressedLength = (int)data.Length;

            if (data.Length < blockLength)
            {
                this._BaseStream.WriteValueS32(128 + compressedLength, this._Endian);
                this._BaseStream.WriteValueU8(1);
                CompressedBlockHeader compressedBlockHeader = new CompressedBlockHeader();
                compressedBlockHeader.SetOodlePreset();
                compressedBlockHeader.UncompressedSize = (uint)blockLength;
                compressedBlockHeader.CompressedSize   = (uint)compressedLength;
                compressedBlockHeader.ChunkSize        = 1;
                compressedBlockHeader.Unknown0C        = (uint)blockLength;
                compressedBlockHeader.Chunks[0]        = (ushort)compressedBlockHeader.CompressedSize;
                Console.WriteLine(compressedBlockHeader);
                compressedBlockHeader.Write(this._BaseStream, this._Endian);
                this._BaseStream.Write(new byte[96], 0, 96); // Empty padding.
                this._BaseStream.Write(data.GetBuffer(), 0, compressedLength);
                this._BlockOffset = 0;
                return(true);
            }

            return(false);
        }
コード例 #2
0
        private bool FlushZlibCompressedBlock(MemoryStream data, int blockLength)
        {
            var zlib = new ZLibStream(data, CompressionMode.Compress, CompressionLevel.Level9);

            zlib.Write(this._BlockBytes, 0, blockLength);
            zlib.Flush();
            var compressedLength = (int)data.Length;

            if (data.Length < blockLength)
            {
                this._BaseStream.WriteValueS32(32 + compressedLength, this._Endian);
                this._BaseStream.WriteValueU8(1);
                CompressedBlockHeader compressedBlockHeader = new CompressedBlockHeader();
                compressedBlockHeader.SetZlibPreset();
                compressedBlockHeader.UncompressedSize = (uint)blockLength; //TODO: I think this should actually be alignment?
                compressedBlockHeader.CompressedSize   = (uint)compressedLength;
                compressedBlockHeader.ChunkSize        = (short)_Alignment;
                compressedBlockHeader.Unknown0C        = 135200769;
                compressedBlockHeader.Chunks[0]        = (ushort)compressedBlockHeader.CompressedSize;
                compressedBlockHeader.Write(this._BaseStream, this._Endian);
                this._BaseStream.Write(data.GetBuffer(), 0, compressedLength);
                this._BlockOffset = 0;
                zlib.Close();
                zlib.Dispose();
                return(true);
            }

            return(false);
        }
コード例 #3
0
        public const uint Signature = 0x6C7A4555; // 'zlEU'

        public static BlockReaderStream FromStream(Stream baseStream, Endian endian)
        {
            var instance = new BlockReaderStream(baseStream);

            var magic     = baseStream.ReadValueU32(endian);
            var alignment = baseStream.ReadValueU32(endian);
            var flags     = baseStream.ReadValueU8();

            if (magic != Signature || /*alignment != 0x4000 ||*/ flags != 4)
            {
                throw new InvalidOperationException();
            }

            long virtualOffset = 0;

            while (true)
            {
                uint size         = baseStream.ReadValueU32(endian);
                bool isCompressed = baseStream.ReadValueU8() != 0;

                if (size == 0)
                {
                    break;
                }

                if (isCompressed == true)
                {
                    var compressedBlockHeader = CompressedBlockHeader.Read(baseStream, endian);
                    if (compressedBlockHeader.Unknown04 != 32 ||
                        compressedBlockHeader.Unknown08 != 81920 ||
                        compressedBlockHeader.Unknown0C != 135200769 ||
                        compressedBlockHeader.Unknown14 != 0 ||
                        compressedBlockHeader.Unknown18 != 0 ||
                        compressedBlockHeader.Unknown1C != 0)
                    {
                        throw new InvalidOperationException();
                    }

                    if (size - 32 != compressedBlockHeader.CompressedSize)
                    {
                        throw new InvalidOperationException();
                    }

                    instance.AddCompressedBlock(virtualOffset,
                                                compressedBlockHeader.UncompressedSize,
                                                baseStream.Position,
                                                compressedBlockHeader.CompressedSize);
                    baseStream.Seek(compressedBlockHeader.CompressedSize, SeekOrigin.Current);
                }
                else
                {
                    instance.AddUncompressedBlock(virtualOffset, size, baseStream.Position);
                    baseStream.Seek(size, SeekOrigin.Current);
                }

                virtualOffset += alignment;
            }

            return(instance);
        }
コード例 #4
0
        public const uint Signature = 0x6C7A4555; // 'zlEU'

        public static BlockReaderStream FromStream(Stream baseStream, Endian endian)
        {
            var instance = new BlockReaderStream(baseStream);

            var magic     = baseStream.ReadValueU32(endian);
            var alignment = baseStream.ReadValueU32(endian);
            var flags     = baseStream.ReadValueU8();

            if (magic != Signature || /*alignment != 0x4000 ||*/ flags != 4)
            {
                throw new InvalidOperationException();
            }

            long virtualOffset = 0;

            while (true)
            {
                uint size         = baseStream.ReadValueU32(endian);
                bool isCompressed = baseStream.ReadValueU8() != 0;

                if (size == 0)
                {
                    break;
                }

                if (isCompressed == true)
                {
                    var compressedBlockHeader = CompressedBlockHeader.Read(baseStream, endian);
                    if (compressedBlockHeader.Unknown04 != 32 ||
                        compressedBlockHeader.Unknown0C != 1 ||
                        compressedBlockHeader.Unknown0E != 15 ||
                        compressedBlockHeader.Unknown0F != 8)
                    {
                        throw new InvalidOperationException();
                    }

                    if (size - 32 != compressedBlockHeader.CompressedSize)
                    {
                        throw new InvalidOperationException();
                    }

                    long compressedPosition        = baseStream.Position;
                    uint remainingUncompressedSize = compressedBlockHeader.UncompressedSize;
                    for (int i = 0; i < compressedBlockHeader.ChunkCount; ++i)
                    {
                        uint UncompressedSize = Math.Min(alignment, remainingUncompressedSize);
                        instance.AddCompressedBlock(virtualOffset,
                                                    UncompressedSize, //compressedBlockHeader.UncompressedSize,
                                                    compressedPosition,
                                                    (uint)compressedBlockHeader.Chunks[i]);
                        compressedPosition        += (uint)compressedBlockHeader.Chunks[i];
                        virtualOffset             += UncompressedSize;
                        remainingUncompressedSize -= alignment;
                    }
                    baseStream.Seek(compressedBlockHeader.CompressedSize, SeekOrigin.Current);
                }
                else
                {
                    instance.AddUncompressedBlock(virtualOffset, size, baseStream.Position);
                    baseStream.Seek(size, SeekOrigin.Current);
                    virtualOffset += size;
                }
            }

            return(instance);
        }
コード例 #5
0
        public const uint Signature = 0x6C7A4555; // 'zlEU'

        public static BlockReaderStream FromStream(Stream baseStream, Endian endian)
        {
            var instance = new BlockReaderStream(baseStream);

            var magic     = baseStream.ReadValueU32(endian);
            var alignment = baseStream.ReadValueU32(endian);
            var flags     = baseStream.ReadValueU8();

            // We can check if this particular block uses Oodle compression.
            bool bUsesOodleCompression = (alignment & (0x1000000)) != 0;

            if (magic != Signature || flags != 4)
            {
                throw new InvalidOperationException();
            }

            long virtualOffset = 0;

            while (true)
            {
                uint size         = baseStream.ReadValueU32(endian);
                bool isCompressed = baseStream.ReadValueU8() != 0;

                if (size == 0)
                {
                    break;
                }

                if (isCompressed == true)
                {
                    // TODO: Consider if we can check if this is still a valid header.
                    var compressedBlockHeader = CompressedBlockHeader.Read(baseStream, endian);
                    int HeaderSize            = (int)compressedBlockHeader.HeaderSize;
                    Debug.Assert(HeaderSize != 32 || HeaderSize != 128, "The CompressedBlockheader did not equal 32 or 128.");

                    // Make sure the Size equals CompressedSize on the block header.
                    if (size - HeaderSize != compressedBlockHeader.CompressedSize)
                    {
                        throw new InvalidOperationException();
                    }

                    bool bIsUsingOodleCompression  = (HeaderSize == 128 && bUsesOodleCompression);
                    long compressedPosition        = baseStream.Position;
                    uint remainingUncompressedSize = compressedBlockHeader.UncompressedSize;

                    for (int i = 0; i < compressedBlockHeader.ChunkCount; ++i)
                    {
                        uint UncompressedSize = Math.Min(alignment, remainingUncompressedSize);
                        instance.AddCompressedBlock(virtualOffset,
                                                    UncompressedSize, //compressedBlockHeader.UncompressedSize,
                                                    compressedPosition,
                                                    compressedBlockHeader.Chunks[i],
                                                    bIsUsingOodleCompression);
                        compressedPosition        += compressedBlockHeader.Chunks[i];
                        virtualOffset             += UncompressedSize;
                        remainingUncompressedSize -= alignment;
                    }

                    // TODO: Consider if there is a better option for this.
                    int SeekStride = (compressedBlockHeader.HeaderSize == 128 ? 96 : 0);
                    baseStream.Seek(compressedBlockHeader.CompressedSize + SeekStride, SeekOrigin.Current);
                }
                else
                {
                    instance.AddUncompressedBlock(virtualOffset, size, baseStream.Position);
                    baseStream.Seek(size, SeekOrigin.Current);
                    virtualOffset += size;
                }
            }

            return(instance);
        }