Exemplo n.º 1
0
        public static MemoryStream Decode(EndianBinaryReader reader)
        {
            if (reader.ReadUInt32() != 0x59617930) // "Yay0" Magic
            {
                throw new InvalidDataException("Invalid Magic, not a Yay0 File");
            }

            int uncompressedSize = reader.ReadInt32();
            int linkTableOffset = reader.ReadInt32();
            int byteChunkAndCountModifiersOffset = reader.ReadInt32();

            int maskBitCounter = 0;
            int currentOffsetInDestBuffer = 0;
            int currentMask = 0;

            byte[] uncompressedData = new byte[uncompressedSize];

            do
            {
                // If we're out of bits, get the next mask.
                if (maskBitCounter == 0)
                {
                    currentMask = reader.ReadInt32();
                    maskBitCounter = 32;
                }

                // If the next bit is set, the chunk is non-linked and just copy it from the non-link table.
                if (((uint)currentMask & (uint)0x80000000) == 0x80000000)
                {
                    uncompressedData[currentOffsetInDestBuffer] = reader.ReadByteAt(byteChunkAndCountModifiersOffset);
                    currentOffsetInDestBuffer++;
                    byteChunkAndCountModifiersOffset++;
                }
                // Do a copy otherwise.
                else
                {
                    // Read 16-bit from the link table
                    ushort link = reader.ReadUInt16At(linkTableOffset);
                    linkTableOffset += 2;

                    // Calculate the offset
                    int offset = currentOffsetInDestBuffer - (link & 0xfff);

                    // Calculate the count
                    int count = link >> 12;

                    if (count == 0)
                    {
                        byte countModifier;
                        countModifier = reader.ReadByteAt(byteChunkAndCountModifiersOffset);
                        byteChunkAndCountModifiersOffset++;
                        count = countModifier + 18;
                    }
                    else
                    {
                        count += 2;
                    }

                    // Copy the block
                    int blockCopy = offset;

                    for (int i = 0; i < count; i++)
                    {
                        uncompressedData[currentOffsetInDestBuffer] = uncompressedData[blockCopy - 1];
                        currentOffsetInDestBuffer++;
                        blockCopy++;
                    }
                }

                // Get the next bit in the mask.
                currentMask <<= 1;
                maskBitCounter--;

            } while (currentOffsetInDestBuffer < uncompressedSize);

            return new MemoryStream(uncompressedData);
        }
        public byte[] DecodeYaz0(EndianBinaryReader reader)
        {
            int uncompressedSize = reader.ReadInt32();

            byte[] dest = new byte[uncompressedSize];

            int srcPlace = 0x10, dstPlace = 0; //current read/write positions

            int validBitCount = 0; //number of valid bits left in "code" byte

            byte currCodeByte = 0;

            while (dstPlace < uncompressedSize)
            {
                //read new "code" byte if the current one is used up
                if (validBitCount == 0)
                {
                    currCodeByte = reader.ReadByteAt(srcPlace);

                    ++srcPlace;

                    validBitCount = 8;
                }

                if ((currCodeByte & 0x80) != 0)
                {
                    //straight copy
                    dest[dstPlace] = reader.ReadByteAt(srcPlace);

                    dstPlace++;

                    srcPlace++;
                }

                else
                {
                    //RLE part
                    byte byte1 = reader.ReadByteAt(srcPlace);

                    byte byte2 = reader.ReadByteAt(srcPlace + 1);

                    srcPlace += 2;

                    int dist = ((byte1 & 0xF) << 8) | byte2;

                    int copySource = dstPlace - (dist + 1);

                    int numBytes = byte1 >> 4;

                    if (numBytes == 0)
                    {
                        numBytes = reader.ReadByteAt(srcPlace) + 0x12;
                        srcPlace++;
                    }

                    else
                        numBytes += 2;

                    //copy run
                    for (int i = 0; i < numBytes; ++i)
                    {
                        dest[dstPlace] = dest[copySource];

                        copySource++;

                        dstPlace++;
                    }
                }

                //use next bit from "code" byte
                currCodeByte <<= 1;

                validBitCount -= 1;
            }

            return dest;
        }