diff options
Diffstat (limited to 'src/huffman/huff.cpp')
-rw-r--r-- | src/huffman/huff.cpp | 869 |
1 files changed, 869 insertions, 0 deletions
diff --git a/src/huffman/huff.cpp b/src/huffman/huff.cpp new file mode 100644 index 0000000..cf5ae05 --- /dev/null +++ b/src/huffman/huff.cpp @@ -0,0 +1,869 @@ +/*****************************************************************************/ +/* huffman.cpp Copyright (c) Ladislav Zezula 1998-2003 */ +/*---------------------------------------------------------------------------*/ +/* This module contains Huffmann (de)compression methods */ +/* */ +/* Authors : Ladislav Zezula (ladik@zezula.net) */ +/* ShadowFlare (BlakFlare@hotmail.com) */ +/* */ +/*---------------------------------------------------------------------------*/ +/* Date Ver Who Comment */ +/* -------- ---- --- ------- */ +/* xx.xx.xx 1.00 Lad The first version of dcmp.cpp */ +/* 03.05.03 1.00 Lad Added compression methods */ +/* 19.11.03 1.01 Dan Big endian handling */ +/* 08.12.03 2.01 Dan High-memory handling (> 0x80000000) */ +/* 09.01.13 3.00 Lad Refactored, beautified, documented :-) */ +/*****************************************************************************/ + +#include <assert.h> +#include <string.h> + +#include "../StormPort.h" +#include "huff.h" + +//----------------------------------------------------------------------------- +// Table of byte-to-weight values + +// Table for (de)compression. Every compression type has 258 entries +static unsigned char ByteToWeight_00[] = +{ + 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00 +}; + +// Data for compression type 0x01 +static unsigned char ByteToWeight_01[] = +{ + 0x54, 0x16, 0x16, 0x0D, 0x0C, 0x08, 0x06, 0x05, 0x06, 0x05, 0x06, 0x03, 0x04, 0x04, 0x03, 0x05, + 0x0E, 0x0B, 0x14, 0x13, 0x13, 0x09, 0x0B, 0x06, 0x05, 0x04, 0x03, 0x02, 0x03, 0x02, 0x02, 0x02, + 0x0D, 0x07, 0x09, 0x06, 0x06, 0x04, 0x03, 0x02, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, + 0x09, 0x06, 0x04, 0x04, 0x04, 0x04, 0x03, 0x02, 0x03, 0x02, 0x02, 0x02, 0x02, 0x03, 0x02, 0x04, + 0x08, 0x03, 0x04, 0x07, 0x09, 0x05, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02, + 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, + 0x06, 0x0A, 0x08, 0x08, 0x06, 0x07, 0x04, 0x03, 0x04, 0x04, 0x02, 0x02, 0x04, 0x02, 0x03, 0x03, + 0x04, 0x03, 0x07, 0x07, 0x09, 0x06, 0x04, 0x03, 0x03, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x0A, 0x02, 0x02, 0x03, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x06, 0x03, 0x05, 0x02, 0x03, + 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x03, 0x01, 0x01, 0x01, + 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x04, 0x04, 0x04, 0x07, 0x09, 0x08, 0x0C, 0x02, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x03, + 0x04, 0x01, 0x02, 0x04, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, + 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x06, 0x4B, + 0x00, 0x00 +}; + +// Data for compression type 0x02 +static unsigned char ByteToWeight_02[] = +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x27, 0x00, 0x00, 0x23, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x06, 0x0E, 0x10, 0x04, + 0x06, 0x08, 0x05, 0x04, 0x04, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03, 0x01, 0x01, 0x02, 0x01, 0x01, + 0x01, 0x04, 0x02, 0x04, 0x02, 0x02, 0x02, 0x01, 0x01, 0x04, 0x01, 0x01, 0x02, 0x03, 0x03, 0x02, + 0x03, 0x01, 0x03, 0x06, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x01, 0x01, + 0x01, 0x29, 0x07, 0x16, 0x12, 0x40, 0x0A, 0x0A, 0x11, 0x25, 0x01, 0x03, 0x17, 0x10, 0x26, 0x2A, + 0x10, 0x01, 0x23, 0x23, 0x2F, 0x10, 0x06, 0x07, 0x02, 0x09, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 +}; + +// Data for compression type 0x03 +static unsigned char ByteToWeight_03[] = +{ + 0xFF, 0x0B, 0x07, 0x05, 0x0B, 0x02, 0x02, 0x02, 0x06, 0x02, 0x02, 0x01, 0x04, 0x02, 0x01, 0x03, + 0x09, 0x01, 0x01, 0x01, 0x03, 0x04, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, + 0x05, 0x01, 0x01, 0x01, 0x0D, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x0A, 0x04, 0x02, 0x01, 0x06, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01, + 0x05, 0x02, 0x03, 0x04, 0x03, 0x03, 0x03, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x03, 0x03, + 0x01, 0x03, 0x01, 0x01, 0x02, 0x05, 0x01, 0x01, 0x04, 0x03, 0x05, 0x01, 0x03, 0x01, 0x03, 0x03, + 0x02, 0x01, 0x04, 0x03, 0x0A, 0x06, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x01, 0x0A, 0x02, 0x05, 0x01, 0x01, 0x02, 0x07, 0x02, 0x17, 0x01, 0x05, 0x01, 0x01, + 0x0E, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x06, 0x02, 0x01, 0x04, 0x05, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x11, + 0x00, 0x00 +}; + +// Data for compression type 0x04 +static unsigned char ByteToWeight_04[] = +{ + 0xFF, 0xFB, 0x98, 0x9A, 0x84, 0x85, 0x63, 0x64, 0x3E, 0x3E, 0x22, 0x22, 0x13, 0x13, 0x18, 0x17, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 +}; + +// Data for compression type 0x05 +static unsigned char ByteToWeight_05[] = +{ + 0xFF, 0xF1, 0x9D, 0x9E, 0x9A, 0x9B, 0x9A, 0x97, 0x93, 0x93, 0x8C, 0x8E, 0x86, 0x88, 0x80, 0x82, + 0x7C, 0x7C, 0x72, 0x73, 0x69, 0x6B, 0x5F, 0x60, 0x55, 0x56, 0x4A, 0x4B, 0x40, 0x41, 0x37, 0x37, + 0x2F, 0x2F, 0x27, 0x27, 0x21, 0x21, 0x1B, 0x1C, 0x17, 0x17, 0x13, 0x13, 0x10, 0x10, 0x0D, 0x0D, + 0x0B, 0x0B, 0x09, 0x09, 0x08, 0x08, 0x07, 0x07, 0x06, 0x05, 0x05, 0x04, 0x04, 0x04, 0x19, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 +}; + + // Data for compression type 0x06 +static unsigned char ByteToWeight_06[] = +{ + 0xC3, 0xCB, 0xF5, 0x41, 0xFF, 0x7B, 0xF7, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xBF, 0xCC, 0xF2, 0x40, 0xFD, 0x7C, 0xF7, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7A, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 +}; + +// Data for compression type 0x07 +static unsigned char ByteToWeight_07[] = +{ + 0xC3, 0xD9, 0xEF, 0x3D, 0xF9, 0x7C, 0xE9, 0x1E, 0xFD, 0xAB, 0xF1, 0x2C, 0xFC, 0x5B, 0xFE, 0x17, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xBD, 0xD9, 0xEC, 0x3D, 0xF5, 0x7D, 0xE8, 0x1D, 0xFB, 0xAE, 0xF0, 0x2C, 0xFB, 0x5C, 0xFF, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x70, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 +}; + +// Data for compression type 0x08 +static unsigned char ByteToWeight_08[] = +{ + 0xBA, 0xC5, 0xDA, 0x33, 0xE3, 0x6D, 0xD8, 0x18, 0xE5, 0x94, 0xDA, 0x23, 0xDF, 0x4A, 0xD1, 0x10, + 0xEE, 0xAF, 0xE4, 0x2C, 0xEA, 0x5A, 0xDE, 0x15, 0xF4, 0x87, 0xE9, 0x21, 0xF6, 0x43, 0xFC, 0x12, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xB0, 0xC7, 0xD8, 0x33, 0xE3, 0x6B, 0xD6, 0x18, 0xE7, 0x95, 0xD8, 0x23, 0xDB, 0x49, 0xD0, 0x11, + 0xE9, 0xB2, 0xE2, 0x2B, 0xE8, 0x5C, 0xDD, 0x15, 0xF1, 0x87, 0xE7, 0x20, 0xF7, 0x44, 0xFF, 0x13, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x5F, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 +}; + +static unsigned char * WeightTables[0x09] = +{ + ByteToWeight_00, + ByteToWeight_01, + ByteToWeight_02, + ByteToWeight_03, + ByteToWeight_04, + ByteToWeight_05, + ByteToWeight_06, + ByteToWeight_07, + ByteToWeight_08 +}; + +//----------------------------------------------------------------------------- +// Debug/diagnostics + +#ifdef _DEBUG +void DumpHuffmannTree(THTreeItem * pItem) +{ + THTreeItem * pChildLo; // Item with the lower weight + THTreeItem * pChildHi; // Item with the higher weight + + // Get the lower-weight branch + pChildLo = pItem->pChildLo; + if(pChildLo != NULL) + { + // Get the higher-weight branch + pChildHi = pChildLo->pPrev; + + // Parse the lower-weight branch + DumpHuffmannTree(pChildHi); + DumpHuffmannTree(pChildLo); + } +} +#endif + +//----------------------------------------------------------------------------- +// TInputStream functions + +TInputStream::TInputStream(void * pvInBuffer, size_t cbInBuffer) +{ + pbInBufferEnd = (unsigned char *)pvInBuffer + cbInBuffer; + pbInBuffer = (unsigned char *)pvInBuffer; + BitBuffer = 0; + BitCount = 0; +} + +// Gets 7 bits from the stream. DOES NOT remove the bits from input stream +unsigned int TInputStream::Peek7Bits() +{ + unsigned int dwReloadByte = 0; + + // If there is not enough bits to get the value, + // we have to add 8 more bits from the input buffer + if(BitCount < 7) + { + dwReloadByte = *pbInBuffer++; + BitBuffer |= dwReloadByte << BitCount; + BitCount += 8; + } + + // Return the first available 7 bits. DO NOT remove them from the input stream + return (BitBuffer & 0x7F); +} + +// Gets one bit from input stream +unsigned int TInputStream::Get1Bit() +{ + unsigned int OneBit = 0; + + // Ensure that the input stream is reloaded, if there are no bits left + if(BitCount == 0) + { + // Refill the bit buffer + BitBuffer = *pbInBuffer++; + BitCount = 8; + } + + // Copy the bit from bit buffer to the variable + OneBit = (BitBuffer & 0x01); + BitBuffer >>= 1; + BitCount--; + + return OneBit; +} + +// Gets the whole byte from the input stream. +unsigned int TInputStream::Get8Bits() +{ + unsigned int dwReloadByte = 0; + unsigned int dwOneByte = 0; + + // If there is not enough bits to get the value, + // we have to add 8 more bits from the input buffer + if(BitCount < 8) + { + dwReloadByte = *pbInBuffer++; + BitBuffer |= dwReloadByte << BitCount; + BitCount += 8; + } + + // Return the lowest 8 its + dwOneByte = (BitBuffer & 0xFF); + BitBuffer >>= 8; + BitCount -= 8; + return dwOneByte; +} + +void TInputStream::SkipBits(unsigned int dwBitsToSkip) +{ + unsigned int dwReloadByte = 0; + + // If there is not enough bits in the buffer, + // we have to add 8 more bits from the input buffer + if(BitCount < dwBitsToSkip) + { + dwReloadByte = *pbInBuffer++; + BitBuffer |= dwReloadByte << BitCount; + BitCount += 8; + } + + // Skip the remaining bits + BitBuffer >>= dwBitsToSkip; + BitCount -= dwBitsToSkip; +} + +//----------------------------------------------------------------------------- +// TOutputStream functions + +TOutputStream::TOutputStream(void * pvOutBuffer, size_t cbOutLength) +{ + pbOutBufferEnd = (unsigned char *)pvOutBuffer + cbOutLength; + pbOutBuffer = (unsigned char *)pvOutBuffer; + BitBuffer = 0; + BitCount = 0; +} + +void TOutputStream::PutBits(unsigned int dwValue, unsigned int nBitCount) +{ + BitBuffer |= (dwValue << BitCount); + BitCount += nBitCount; + + // Flush completed bytes + while(BitCount >= 8) + { + if(pbOutBuffer < pbOutBufferEnd) + *pbOutBuffer++ = (unsigned char)BitBuffer; + + BitBuffer >>= 8; + BitCount -= 8; + } +} + +void TOutputStream::Flush() +{ + while(BitCount != 0) + { + if(pbOutBuffer < pbOutBufferEnd) + *pbOutBuffer++ = (unsigned char)BitBuffer; + + BitBuffer >>= 8; + BitCount -= ((BitCount > 8) ? 8 : BitCount); + } +} + +//----------------------------------------------------------------------------- +// Methods of the THTreeItem struct + +void THTreeItem::RemoveItem() +{ + if(pNext != NULL) + { + pPrev->pNext = pNext; + pNext->pPrev = pPrev; + pNext = pPrev = NULL; + } +} + +//----------------------------------------------------------------------------- +// THuffmannTree class functions + +THuffmannTree::THuffmannTree(bool bCompression) +{ + // TODO: Obsolete, delete this!! +// InitializeHTListHead(&ItemLinks); + pFirst = pLast = LIST_HEAD(); + + MinValidValue = 1; + ItemsUsed = 0; + + // If we are going to decompress data, we need to invalidate all item links + // We do so by zeroing their ValidValue, so it becomes lower MinValidValue + if(bCompression == false) + { + memset(QuickLinks, 0, sizeof(QuickLinks)); + } +} + +THuffmannTree::~THuffmannTree() +{ + // Our Huffmann tree does not use any memory allocations, + // so we don't need to do eny code in the destructor +} + +void THuffmannTree::LinkTwoItems(THTreeItem * pItem1, THTreeItem * pItem2) +{ + pItem2->pNext = pItem1->pNext; + pItem2->pPrev = pItem1->pNext->pPrev; + pItem1->pNext->pPrev = pItem2; + pItem1->pNext = pItem2; +} + +// Inserts item into the tree (?) +void THuffmannTree::InsertItem(THTreeItem * pNewItem, TInsertPoint InsertPoint, THTreeItem * pInsertPoint) +{ + // Remove the item from the tree + pNewItem->RemoveItem(); + + if(pInsertPoint == NULL) + pInsertPoint = LIST_HEAD(); + + switch(InsertPoint) + { + case InsertAfter: + LinkTwoItems(pInsertPoint, pNewItem); + return; + + case InsertBefore: + pNewItem->pNext = pInsertPoint; // Set next item (or pointer to pointer to first item) + pNewItem->pPrev = pInsertPoint->pPrev; // Set prev item (or last item in the tree) + pInsertPoint->pPrev->pNext = pNewItem; + pInsertPoint->pPrev = pNewItem; // Set the next/last item + return; + } +} + +THTreeItem * THuffmannTree::FindHigherOrEqualItem(THTreeItem * pItem, unsigned int Weight) +{ + // Parse all existing items + if(pItem != NULL) + { + while(pItem != LIST_HEAD()) + { + if(pItem->Weight >= Weight) + return pItem; + + pItem = pItem->pPrev; + } + } + + // If not found, we just get the first item + return LIST_HEAD(); +} + +THTreeItem * THuffmannTree::CreateNewItem(unsigned int DecompressedValue, unsigned int Weight, TInsertPoint InsertPoint) +{ + THTreeItem * pNewItem; + + // Allocate new item from the item pool + pNewItem = &ItemBuffer[ItemsUsed++]; + + // Insert this item to the top of the tree + InsertItem(pNewItem, InsertPoint, NULL); + + // Fill the rest of the item + pNewItem->DecompressedValue = DecompressedValue; + pNewItem->Weight = Weight; + pNewItem->pParent = NULL; + pNewItem->pChildLo = NULL; + return pNewItem; +} + +unsigned int THuffmannTree::FixupItemPosByWeight(THTreeItem * pNewItem, unsigned int MaxWeight) +{ + THTreeItem * pHigherItem; + + if(pNewItem->Weight < MaxWeight) + { + // Find an item that has higher weight than this one + pHigherItem = FindHigherOrEqualItem(pLast, pNewItem->Weight); + + // Remove the item and put it to the new position + pNewItem->RemoveItem(); + LinkTwoItems(pHigherItem, pNewItem); + } + else + { + MaxWeight = pNewItem->Weight; + } + + // Return the (updated) maximum weight + return MaxWeight; +} + +// Builds Huffman tree. Called with the first 8 bits loaded from input stream +void THuffmannTree::BuildTree(unsigned int CompressionType) +{ + THTreeItem * pNewItem; + THTreeItem * pChildLo; + THTreeItem * pChildHi; + unsigned char * WeightTable; + unsigned int MaxWeight; // [ESP+10] - The greatest character found in table + + // Clear all pointers in HTree item array + memset(ItemsByByte, 0, sizeof(ItemsByByte)); + MaxWeight = 0; + + // Ensure that the compression type is in range + assert((CompressionType & 0x0F) <= 0x08); + WeightTable = WeightTables[CompressionType & 0x0F]; + + // Build the linear list of entries that is sorted by byte weight + for(unsigned int i = 0; i < 0x100; i++) + { + // Skip all the bytes which are zero. + if(WeightTable[i] != 0) + { + // Create new tree item + ItemsByByte[i] = pNewItem = CreateNewItem(i, WeightTable[i], InsertAfter); + + // We need to put the item to the right place in the list + MaxWeight = FixupItemPosByWeight(pNewItem, MaxWeight); + } + } + + // Insert termination entries at the end of the list + ItemsByByte[0x100] = CreateNewItem(0x100, 1, InsertBefore); + ItemsByByte[0x101] = CreateNewItem(0x101, 1, InsertBefore); + + // Now we need to build the tree. We start at the last entry + // and go backwards to the first one + pChildLo = pLast; + + // Work as long as both children are valid + // pChildHi is child with higher weight, pChildLo is the one with lower weight + while(pChildLo != LIST_HEAD()) + { + // Also get and verify the higher-weight child + pChildHi = pChildLo->pPrev; + if(pChildHi == LIST_HEAD()) + break; + + // Create new parent item for the children + pNewItem = CreateNewItem(0, pChildHi->Weight + pChildLo->Weight, InsertAfter); + + // Link both child items to their new parent + pChildLo->pParent = pNewItem; + pChildHi->pParent = pNewItem; + pNewItem->pChildLo = pChildLo; + + // Fixup the item's position by its weight + MaxWeight = FixupItemPosByWeight(pNewItem, MaxWeight); + + // Get the previous lower-weight child + pChildLo = pChildHi->pPrev; + } + + // Initialize the MinValidValue to 1, which invalidates all quick-link items + MinValidValue = 1; +} + +void THuffmannTree::IncWeightsAndRebalance(THTreeItem * pItem) +{ + THTreeItem * pHigherItem; // A previous item with greater or equal weight + THTreeItem * pChildHi; // The higher-weight child + THTreeItem * pChildLo; // The lower-weight child + THTreeItem * pParent; + + // Climb up the tree and increment weight of each tree item + for(; pItem != NULL; pItem = pItem->pParent) + { + // Increment the item's weight + pItem->Weight++; + + // Find a previous item with equal or greater weight, which is not equal to this item + pHigherItem = FindHigherOrEqualItem(pItem->pPrev, pItem->Weight); + pChildHi = pHigherItem->pNext; + + // If the item is not equal to the tree item, we need to rebalance the tree + if(pChildHi != pItem) + { + // Move the previous item to the RIGHT from the given item + pChildHi->RemoveItem(); + LinkTwoItems(pItem, pChildHi); + + // Move the given item AFTER the greater-weight tree item + pItem->RemoveItem(); + LinkTwoItems(pHigherItem, pItem); + + // We need to maintain the tree so that pChildHi->Weight is >= pChildLo->Weight. + // Rebalance the tree accordingly. + pChildLo = pChildHi->pParent->pChildLo; + pParent = pItem->pParent; + if(pParent->pChildLo == pItem) + pParent->pChildLo = pChildHi; + if(pChildLo == pChildHi) + pChildHi->pParent->pChildLo = pItem; + pParent = pItem->pParent; + pItem->pParent = pChildHi->pParent; + pChildHi->pParent = pParent; + + // Increment the global valid value. This invalidates all quick-link items. + MinValidValue++; + } + } +} + +void THuffmannTree::InsertNewBranchAndRebalance(unsigned int Value1, unsigned int Value2) +{ + THTreeItem * pLastItem = pLast; + THTreeItem * pChildHi; + THTreeItem * pChildLo; + + // Create higher-weight child + pChildHi = CreateNewItem(Value1, pLastItem->Weight, InsertBefore); + pChildHi->pParent = pLastItem; + ItemsByByte[Value1] = pChildHi; + + // Create lower-weight child + pChildLo = CreateNewItem(Value2, 0, InsertBefore); + pChildLo->pParent = pLastItem; + pLastItem->pChildLo = pChildLo; + ItemsByByte[Value2] = pChildLo; + + IncWeightsAndRebalance(pChildLo); +} + +void THuffmannTree::EncodeOneByte(TOutputStream * os, THTreeItem * pItem) +{ + THTreeItem * pParent = pItem->pParent; + unsigned int BitBuffer = 0; + unsigned int BitCount = 0; + + // Put 1's as long as there is parent + while(pParent != NULL) + { + // Fill the bit buffer + BitBuffer = (BitBuffer << 1) | ((pParent->pChildLo != pItem) ? 1 : 0); + BitCount++; + + // Move to the parent + pItem = pParent; + pParent = pParent->pParent; + } + + // Write the bits to the output stream + os->PutBits(BitBuffer, BitCount); +} + +unsigned int THuffmannTree::DecodeOneByte(TInputStream * is) +{ + THTreeItem * pItemLink = NULL; + THTreeItem * pItem; + unsigned int ItemLinkIndex; + unsigned int BitCount = 0; + + // Check for the end of the input stream + if(is->pbInBuffer >= is->pbInBufferEnd && is->BitCount < 7) + return 0x1FF; + + // Get the eventual quick-link index + ItemLinkIndex = is->Peek7Bits(); + + // Is the quick-link item valid? + if(QuickLinks[ItemLinkIndex].ValidValue > MinValidValue) + { + // If that item needs less than 7 bits, we can get decompressed value directly + if(QuickLinks[ItemLinkIndex].ValidBits <= 7) + { + is->SkipBits(QuickLinks[ItemLinkIndex].ValidBits); + return QuickLinks[ItemLinkIndex].DecompressedValue; + } + + // Otherwise we cannot get decompressed value directly + // but we can skip 7 levels of tree parsing + pItem = QuickLinks[ItemLinkIndex].pItem; + is->SkipBits(7); + } + else + { + // Just a sanity check + if(pFirst == LIST_HEAD()) + return 0x1FF; + + // We don't have the quick-link item, we need to parse the tree from its root + pItem = pFirst; + } + + // Step down the tree until we find a terminal item + while(pItem->pChildLo != NULL) + { + // If the next bit in the compressed stream is set, we get the higher-weight + // child. Otherwise, get the lower-weight child. + pItem = is->Get1Bit() ? pItem->pChildLo->pPrev : pItem->pChildLo; + BitCount++; + + // If the number of loaded bits reached 7, + // remember the current item for storing into quick-link item array + if(BitCount == 7) + pItemLink = pItem; + } + + // If we didn't get the item from the quick-link array, + // set the entry in it + if(QuickLinks[ItemLinkIndex].ValidValue < MinValidValue) + { + // If the current compressed byte was more than 7 bits, + // set a quick-link item with pointer to tree item + if(BitCount > 7) + { + QuickLinks[ItemLinkIndex].ValidValue = MinValidValue; + QuickLinks[ItemLinkIndex].ValidBits = BitCount; + QuickLinks[ItemLinkIndex].pItem = pItemLink; + } + else + { + // Limit the quick-decompress item to lower amount of bits + ItemLinkIndex &= (0xFFFFFFFF >> (32 - BitCount)); + while(ItemLinkIndex < LINK_ITEM_COUNT) + { + // Fill the quick-decompress item + QuickLinks[ItemLinkIndex].ValidValue = MinValidValue; + QuickLinks[ItemLinkIndex].ValidBits = BitCount; + QuickLinks[ItemLinkIndex].DecompressedValue = pItem->DecompressedValue; + + // Increment the index + ItemLinkIndex += (1 << BitCount); + } + } + } + + // Return the decompressed value from the found item + return pItem->DecompressedValue; +} + +unsigned int THuffmannTree::Compress(TOutputStream * os, void * pvInBuffer, int cbInBuffer, int CompressionType) +{ + unsigned char * pbInBufferEnd = (unsigned char *)pvInBuffer + cbInBuffer; + unsigned char * pbInBuffer = (unsigned char *)pvInBuffer; + unsigned char * pbOutBuff = os->pbOutBuffer; + unsigned char InputByte; + + BuildTree(CompressionType); + bIsCmp0 = (CompressionType == 0); + + // Store the compression type into output buffer + os->PutBits(CompressionType, 8); + + // Process the entire input buffer + while(pbInBuffer < pbInBufferEnd) + { + // Get the (next) byte from the input buffer + InputByte = *pbInBuffer++; + + // Do we have an item for such input value? + if(ItemsByByte[InputByte] == NULL) + { + // Encode the relationship + EncodeOneByte(os, ItemsByByte[0x101]); + + // Store the loaded byte into output stream + os->PutBits(InputByte, 8); + + InsertNewBranchAndRebalance(pLast->DecompressedValue, InputByte); + + if(bIsCmp0) + { + IncWeightsAndRebalance(ItemsByByte[InputByte]); + continue; + } + + IncWeightsAndRebalance(ItemsByByte[InputByte]); + } + else + { + EncodeOneByte(os, ItemsByByte[InputByte]); + } + + if(bIsCmp0) + { + IncWeightsAndRebalance(ItemsByByte[InputByte]); + } + } + + // Put the termination mark to the compressed stream + EncodeOneByte(os, ItemsByByte[0x100]); + + // Flush the remaining bits + os->Flush(); + return (unsigned int)(os->pbOutBuffer - pbOutBuff); +} + +// Decompression using Huffman tree (1500E450) +unsigned int THuffmannTree::Decompress(void * pvOutBuffer, unsigned int cbOutLength, TInputStream * is) +{ + unsigned char * pbOutBufferEnd = (unsigned char *)pvOutBuffer + cbOutLength; + unsigned char * pbOutBuffer = (unsigned char *)pvOutBuffer; + unsigned int DecompressedValue = 0; + unsigned int CompressionType = 0; + + // Test the output length. Must not be NULL. + if(cbOutLength == 0) + return 0; + + // Get the compression type from the input stream + CompressionType = is->Get8Bits(); + bIsCmp0 = (CompressionType == 0) ? 1 : 0; + + // Build the Huffman tree + BuildTree(CompressionType); + + // Process the entire input buffer until end of the stream + while((DecompressedValue = DecodeOneByte(is)) != 0x100) + { + // Did an error occur? + if(DecompressedValue == 0x1FF) // An error occurred + return 0; + + // Huffman tree needs to be modified + if(DecompressedValue == 0x101) + { + // The decompressed byte is stored in the next 8 bits + DecompressedValue = is->Get8Bits(); + + InsertNewBranchAndRebalance(pLast->DecompressedValue, DecompressedValue); + + if(bIsCmp0 == 0) + IncWeightsAndRebalance(ItemsByByte[DecompressedValue]); + } + + // A byte successfully decoded - store it in the output stream + *pbOutBuffer++ = (unsigned char)DecompressedValue; + if(pbOutBuffer >= pbOutBufferEnd) + break; + + if(bIsCmp0) + { + IncWeightsAndRebalance(ItemsByByte[DecompressedValue]); + } + } + + return (unsigned int)(pbOutBuffer - (unsigned char *)pvOutBuffer); +} + |