예제 #1
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);
        }
        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);
        }
예제 #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();

            // 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);
        }