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