Exemple #1
0
        /* ---------------------------------------------------------------------------------------------------------------------------------- */
        public static PackContents CreateFromWdtFile(WdtFile wdtFile)
        {
            Chapter contentsChapter = wdtFile.ChapterList[0];

            byte[] contentDecompressed = new byte [wdtFile.PageSize];
            var    memStream           = new MemoryStream(contentDecompressed);

            WdtDecompressor.DecompressChapter(wdtFile, contentsChapter, memStream);

            PackContents packContents;

            using (var decompressedStream = new MemoryStream(contentDecompressed))
            {
                packContents = new PackContents(decompressedStream);
            }

            return(packContents);
        }
Exemple #2
0
        /* ---------------------------------------------------------------------------------------------------------------------------------- */
        public static PackFile CreateFromWdtFile(WdtFile wdtFile)
        {
            var packFileStream = new MemoryStream(wdtFile.SizeDecompressed);

            for (int i = 0; i < wdtFile.ChapterList.Count; i++)
            {
                var chapter = wdtFile.ChapterList[i];

                byte[] decompressedChapter = new byte[wdtFile.PageSize];
                var    chapterMemoryStream = new MemoryStream(decompressedChapter);
                int    decompressedSize    = WdtDecompressor.DecompressChapter(wdtFile, chapter, chapterMemoryStream);

                decompressedSize = Math.Min(wdtFile.PageSize, decompressedSize);

                packFileStream.Write(decompressedChapter, 0, decompressedSize);
            }

            return(new PackFile(packFileStream));
        }
        /* ---------------------------------------------------------------------------------------------------------------------------------- */
        public static byte[] DecompressTzarFile(PackTzarFile fileInfo, WdtFile wdtFile)
        {
            byte[] fileBuffer = new byte[fileInfo.Size];

            int fileStartChapter = fileInfo.Offset / wdtFile.PageSize;
            int fileStartOffset  = fileInfo.Offset % wdtFile.PageSize;
            int fileChapterSpan  = (fileInfo.Size + fileStartOffset) / wdtFile.PageSize + 1;

            byte[] chaptersBuffer = new byte[fileChapterSpan * wdtFile.PageSize];
            var    chaptersStream = new MemoryStream(chaptersBuffer);

            for (int i = 0; i < fileChapterSpan; i++)
            {
                DecompressChapter(wdtFile, wdtFile.ChapterList[fileStartChapter + i], chaptersStream);
            }

            chaptersStream.Seek(fileStartOffset, SeekOrigin.Begin);
            chaptersStream.Read(fileBuffer, 0, fileInfo.Size);

            return(fileBuffer);
        }
Exemple #4
0
        /* ---------------------------------------------------------------------------------------------------------------------------------- */
        public ChapterList(WdtFile wdtFile)
        {
            using (var fileStream = new FileStream(wdtFile.Path, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                fileStream.Seek(WdtFile.HEADER_LENGTH, SeekOrigin.Begin);
                var reader = new BinaryReader(fileStream);

                int firstChapterPosition = reader.ReadInt32();
                int chapterCount         = (firstChapterPosition - WdtFile.HEADER_LENGTH) / 4 - 1;

                m_chapters = new List <Chapter> (chapterCount);

                int previousChapterEndPosition = firstChapterPosition;

                for (int i = 0; i < chapterCount; i++)
                {
                    int chapterEndPosition = reader.ReadInt32();
                    m_chapters.Add(new Chapter(previousChapterEndPosition, chapterEndPosition));
                    previousChapterEndPosition = chapterEndPosition;
                }

                m_chapters.Add(new Chapter(previousChapterEndPosition, (int)fileStream.Length));       // Last chapter end position = wdtFile end
            }
        }
        /* ---------------------------------------------------------------------------------------------------------------------------------- */
        public static int DecompressChapter(WdtFile wdtFile, Chapter chapter, Stream outStream)
        {
            int decompressedSize;

            var compressedBuffer = new byte[chapter.Size + 16];  // Additional safety bytes for LZSS

            using (var wdtFileStream = new FileStream(wdtFile.Path, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                wdtFileStream.Seek(chapter.StartPosition, SeekOrigin.Begin);
                wdtFileStream.Read(compressedBuffer, 0, chapter.Size);
            }

            // TODO: Cleanup gotos; decompose the method
            var compressedPartStream = new MemoryStream(compressedBuffer);
            var compressedReader     = new BinaryReader(compressedPartStream);
            var decompressedWriter   = new BinaryWriter(outStream);

            {
                ushort shifter               = 0;
                uint   processedValue        = 0;
                int    bytesDecompressed     = 0;
                bool   carryFlag             = false;
                long   outStreamBasePosition = outStream.Position;

mainPart:
                while (bytesDecompressed < chapter.Size - 1)
                {
                    compressedPartStream.Seek(bytesDecompressed, SeekOrigin.Begin);

                    processedValue = BinaryUtils.SwapBytes(compressedReader.ReadUInt32());

                    processedValue = processedValue << (byte)shifter;
                    bool isShiftCarry = (processedValue & 0x80000000) > 0;
                    processedValue = processedValue << 1;

                    if (!isShiftCarry)
                    {
                        break;
                    }

                    if (shifter == 57351)
                    {
                        shifter  += 0x2001;
                        carryFlag = true;
                    }
                    else
                    {
                        shifter  += 0x2001;
                        carryFlag = false;
                    }

                    bytesDecompressed += carryFlag ? 2 : 1;

                    shifter = (ushort)(shifter & 0xFF07);

                    processedValue = BinaryUtils.SwapBytes(processedValue);
                    decompressedWriter.Write((byte)processedValue);

                    if ((outStream.Position - outStreamBasePosition) >= wdtFile.PageSize)
                    {
                        goto endOfFile;
                    }
                }

                if (shifter == 57351)
                {
                    shifter  += 0x2001;
                    carryFlag = true;
                }
                else
                {
                    shifter  += 0x2001;
                    carryFlag = false;
                }

                BinaryUtils.AddWithCarry(ref bytesDecompressed, 2, carryFlag);
                shifter = (ushort)(shifter & 0xFF07);

                uint helper = (processedValue >> 0x14);

                {
                    bool shrCarryFlag = false;
                    if ((helper & 0x80000) > 0)
                    {
                        shrCarryFlag = true;
                    }

                    if (shrCarryFlag)
                    {
                        processedValue &= 0xF0000;
                        processedValue  = processedValue >> 0x10;

                        decompressedWriter.Seek((int)(outStreamBasePosition + processedValue) + 2, SeekOrigin.Current);

                        if (bytesDecompressed < chapter.Size - 1)
                        {
                            goto endOfFile;
                        }
                        else
                        {
                            goto mainPart;
                        }
                    }
                }

                {
                    processedValue &= 0xF0000;

                    bool shrCarryFlag = false;
                    if ((processedValue & 0x10000) > 0)
                    {
                        shrCarryFlag = true;
                    }

                    processedValue = processedValue >> 0x11;

                    if (shrCarryFlag)
                    {
                        long outStreamPosition = outStream.Position;
                        outStream.Seek(outStreamPosition + helper - 0x1000, SeekOrigin.Begin);
                        byte someByte = (byte)outStream.ReadByte();
                        outStream.Seek(outStreamPosition, SeekOrigin.Begin);
                        decompressedWriter.Write(someByte);
                    }
                }

                processedValue++;

                while (processedValue > 0)
                {
                    long outStreamPosition = outStream.Position;
                    outStream.Seek(outStreamPosition + helper - 0x1000, SeekOrigin.Begin);
                    byte copiedByte = (byte)outStream.ReadByte();
                    outStream.Seek(outStreamPosition, SeekOrigin.Begin);
                    decompressedWriter.Write(copiedByte);

                    outStreamPosition = outStream.Position;
                    outStream.Seek(outStreamPosition + helper - 0x1000, SeekOrigin.Begin);
                    copiedByte = (byte)outStream.ReadByte();
                    outStream.Seek(outStreamPosition, SeekOrigin.Begin);
                    decompressedWriter.Write(copiedByte);

                    processedValue--;
                }

                if (bytesDecompressed < chapter.Size - 1)
                {
                    goto mainPart;
                }

endOfFile:
                decompressedSize = (int)(outStream.Position - outStreamBasePosition);
            }

            compressedPartStream.Dispose();

            return(decompressedSize);
        }