diff --git a/OpenRA.FileFormats/FileFormats/Blast.cs b/OpenRA.FileFormats/FileFormats/Blast.cs index 07554ffef4..0e8bbee749 100644 --- a/OpenRA.FileFormats/FileFormats/Blast.cs +++ b/OpenRA.FileFormats/FileFormats/Blast.cs @@ -5,6 +5,9 @@ * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, * see LICENSE. + * + * This file is based on the blast routines (version 1.1 by Mark Adler) + * included in zlib/contrib */ #endregion @@ -13,92 +16,11 @@ using System.IO; namespace OpenRA.FileFormats { - // A reimplementation of the Blast routines included in zlib public static class Blast { public static readonly int MAXBITS = 13; // maximum code length public static readonly int MAXWIN = 4096; // maximum window size - /* - * Decode a code from the stream s using huffman table h. Return the symbol or - * a negative value if there is an error. If all of the lengths are zero, i.e. - * an empty code, or if the code is incomplete and an invalid code is received, - * then -9 is returned after reading MAXBITS bits. - * - * Format notes: - * - * - The codes as stored in the compressed data are bit-reversed relative to - * a simple integer ordering of codes of the same lengths. Hence below the - * bits are pulled from the compressed data one at a time and used to - * build the code value reversed from what is in the stream in order to - * permit simple integer comparisons for decoding. - * - * - The first code for the shortest length is all ones. Subsequent codes of - * the same length are simply integer decrements of the previous code. When - * moving up a length, a one bit is appended to the code. For a complete - * code, the last code of the longest length will be all zeros. To support - * this ordering, the bits pulled during decoding are inverted to apply the - * more "natural" ordering starting with all zeros and incrementing. - */ - private static int Decode(Huffman h, BitReader br) - { - int code = 0; // len bits being decoded - int first = 0; // first code of length len - int index = 0; // index of first code of length len in symbol table - short next = 1; - while (true) - { - code |= br.ReadBits(1) ^ 1; // invert code - int count = h.Count[next++]; - if (code < first + count) - return h.Symbol[index + (code - first)]; - - index += count; - first += count; - first <<= 1; - code <<= 1; - } - } - - /* - * Decode PKWare Compression Library stream. - * - * Format notes: - * - * - First byte is 0 if literals are uncoded or 1 if they are coded. Second - * byte is 4, 5, or 6 for the number of extra bits in the distance code. - * This is the base-2 logarithm of the dictionary size minus six. - * - * - Compressed data is a combination of literals and length/distance pairs - * terminated by an end code. Literals are either Huffman coded or - * uncoded bytes. A length/distance pair is a coded length followed by a - * coded distance to represent a string that occurs earlier in the - * uncompressed data that occurs again at the current location. - * - * - A bit preceding a literal or length/distance pair indicates which comes - * next, 0 for literals, 1 for length/distance. - * - * - If literals are uncoded, then the next eight bits are the literal, in the - * normal bit order in th stream, i.e. no bit-reversal is needed. Similarly, - * no bit reversal is needed for either the length extra bits or the distance - * extra bits. - * - * - Literal bytes are simply written to the output. A length/distance pair is - * an instruction to copy previously uncompressed bytes to the output. The - * copy is from distance bytes back in the output stream, copying for length - * bytes. - * - * - Distances pointing before the beginning of the output data are not - * permitted. - * - * - Overlapped copies, where the length is greater than the distance, are - * allowed and common. For example, a distance of one and a length of 518 - * simply copies the last byte 518 times. A distance of four and a length of - * twelve copies the last four bytes three times. A simple forward copy - * ignoring whether the length is greater than the distance or not implements - * this correctly. - */ - static byte[] litlen = new byte[] { 11, 124, 8, 7, 28, 7, 188, 13, 76, 4, 10, 8, 12, 10, 12, 10, 8, 23, 8, 9, @@ -133,7 +55,8 @@ namespace OpenRA.FileFormats static Huffman litcode = new Huffman(litlen, litlen.Length, 256); static Huffman lencode = new Huffman(lenlen, lenlen.Length, 16); static Huffman distcode = new Huffman(distlen, distlen.Length, 64); - + + // Decode PKWare Compression Library stream. public static byte[] Decompress(byte[] src) { BitReader br = new BitReader(src); @@ -228,6 +151,27 @@ namespace OpenRA.FileFormats return ms.ToArray(); } + + // Decode a code using huffman table h. + private static int Decode(Huffman h, BitReader br) + { + int code = 0; // len bits being decoded + int first = 0; // first code of length len + int index = 0; // index of first code of length len in symbol table + short next = 1; + while (true) + { + code |= br.ReadBits(1) ^ 1; // invert code + int count = h.Count[next++]; + if (code < first + count) + return h.Symbol[index + (code - first)]; + + index += count; + first += count; + first <<= 1; + code <<= 1; + } + } } class BitReader