#include "../game/q_shared.h"
#include "../qcommon/qcommon.h"

#include "zip.h"
#include "inflate.h"

#ifdef _TIMING
int		totalInflateTime;
int		totalInflateCount;
#endif

// If you use the zlib library in a product, an acknowledgment is welcome
// in the documentation of your product. If for some reason you cannot
// include such an acknowledgment, I would appreciate that you keep this
// copyright string in the executable of your product.
const char inflate_copyright[] = "Inflate 1.1.3 Copyright 1995-1998 Mark Adler ";

static const char *inflate_error = "OK";

//	int inflate(z_stream *strm);
//
//    inflate decompresses as much data as possible, and stops when the input
//  buffer becomes empty or the output buffer becomes full. It may some
//  introduce some output latency (reading input without producing any output)
//  except when forced to flush.
//
//  The detailed semantics are as follows. inflate performs one or both of the
//  following actions:
//
//  - Decompress more input starting at next_in and update next_in and avail_in
//    accordingly. If not all input can be processed (because there is not
//    enough room in the output buffer), next_in is updated and processing
//    will resume at this point for the next call of inflate().
//
//  - Provide more output starting at next_out and update next_out and avail_out
//    accordingly.  inflate() provides as much output as possible, until there
//    is no more input data or no more space in the output buffer (see below
//    about the flush parameter).
//
//  Before the call of inflate(), the application should ensure that at least
//  one of the actions is possible, by providing more input and/or consuming
//  more output, and updating the next_* and avail_* values accordingly.
//  The application can consume the uncompressed output when it wants, for
//  example when the output buffer is full (avail_out == 0), or after each
//  call of inflate(). If inflate returns Z_OK and with zero avail_out, it
//  must be called again after making room in the output buffer because there
//  might be more output pending.
//
//    If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much
//  output as possible to the output buffer. The flushing behavior of inflate is
//  not specified for values of the flush parameter other than Z_SYNC_FLUSH
//  and Z_FINISH, but the current implementation actually flushes as much output
//  as possible anyway.
//
//    inflate() should normally be called until it returns Z_STREAM_END or an
//  error. However if all decompression is to be performed in a single step
//  (a single call of inflate), the parameter flush should be set to
//  Z_FINISH. In this case all pending input is processed and all pending
//  output is flushed; avail_out must be large enough to hold all the
//  uncompressed data. (The size of the uncompressed data may have been saved
//  by the compressor for this purpose.) The next operation on this stream must
//  be inflateEnd to deallocate the decompression state. The use of Z_FINISH
//  is never required, but can be used to inform inflate that a faster routine
//  may be used for the single inflate() call.
//
//    It sets strm->adler to the adler32 checksum of all output produced
//  so and returns Z_OK, Z_STREAM_END or
//  an error code as described below. At the end of the stream, inflate()
//  checks that its computed adler32 checksum is equal to that saved by the
//  compressor and returns Z_STREAM_END only if the checksum is correct.
//
//    inflate() returns Z_OK if some progress has been made (more input processed
//  or more output produced), Z_STREAM_END if the end of the compressed data has
//  been reached and all uncompressed output has been produced, 
//  Z_DATA_ERROR if the input data was
//  corrupted (input stream not conforming to the zlib format or incorrect
//  adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent
//  (for example if next_in or next_out was NULL),
//  Z_BUF_ERROR if no progress is possible or if there was not
//  enough room in the output buffer when Z_FINISH is used.

//	int inflateEnd (z_stream *strm);
//
//     All dynamically allocated data structures for this stream are freed.
//   This function discards any unprocessed input and does not flush any
//   pending output.
//
//     inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
//   was inconsistent. In the error case, msg may be set but then points to a
//   static string (which must not be deallocated).

//	EStatus inflateInit(z_stream *strm, EFlush flush, int noWrap = 0);
//
//      inflateInit returns Z_OK if success,
//   Z_STREAM_ERROR if a parameter is invalid.
//   msg is set to "OK" if there is no error message. inflateInit
//   does not perform any decompression apart from reading the zlib header if
//   present: this will be done by inflate(). (So next_in and avail_in may be
//   modified, but next_out and avail_out are unchanged.)

//   Notes beyond the 1.93a appnote.txt:
//
//   1. Distance pointers never point before the beginning of the output
//      stream.
//   2. Distance pointers can point back across blocks, up to 32k away.
//   3. There is an implied maximum of 7 bits for the bit length table and
//      15 bits for the actual data.
//   4. If only one code exists, then it is encoded using one bit.  (Zero
//      would be more efficient, but perhaps a little confusing.)  If two
//      codes exist, they are coded using one bit each (0 and 1).
//   5. There is no way of sending zero distance codes--a dummy must be
//      sent if there are none.  (History: a pre 2.0 version of PKZIP would
//      store blocks with no distance codes, but this was discovered to be
//      too harsh a criterion.)  Valid only for 1.93a.  2.04c does allow
//      zero distance codes, which is sent as one code of zero bits in
//      length.
//   6. There are up to 286 literal/length codes.  Code 256 represents the
//      end-of-block.  Note however that the static length tree defines
//      288 codes just to fill out the Huffman codes.  Codes 286 and 287
//      cannot be used though, since there is no length base or extra bits
//      defined for them.  Similarily, there are up to 30 distance codes.
//      However, static trees define 32 codes (all 5 bits) to fill out the
//      Huffman codes, but the last two had better not show up in the data.
//   7. Unzip can check dynamic Huffman blocks for complete code sets.
//      The exception is that a single code would not be complete (see #4).
//   8. The five bits following the block type is really the number of
//      literal codes sent minus 257.
//   9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
//      (1+6+6).  Therefore, to output three times the length, you output
//      three codes (1+1+1), whereas to output four times the same length,
//      you only need two codes (1+3).  Hmm.
//  10. In the tree reconstruction algorithm, Code = Code + Increment
//      only if BitLength(i) is not zero.  (Pretty obvious.)
//  11. Correction: 4 Bits: # of Bit Length codes - 4     (4 - 19)
//  12. Note: length code 284 can represent 227-258, but length code 285
//      really is 258.  The last length deserves its own, short code
//      since it gets used a lot in very redundant files.  The length
//      258 is special since 258 - 3 (the min match length) is 255.
//  13. The literal/length and distance code bit lengths are read as a
//      single stream of lengths.  It is possible (and advantageous) for
//      a repeat code (16, 17, or 18) to go across the boundary between
//      the two sets of lengths.

// And'ing with mask[n] masks the lower n bits
static const ulong inflate_mask[17] = 
{
    0x0000,
    0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
    0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
};

// Order of the bit length code lengths
static const ulong border[] = 
{ 
	16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
};

// Copy lengths for literal codes 257..285 (see note #13 above about 258)
static const ulong cplens[31] = 
{ 
	3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
	35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
};

// Extra bits for literal codes 257..285 (112 == invalid)
static const ulong cplext[31] = 
{ 
	0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
	3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112
}; 

// Copy offsets for distance codes 0..29
static const ulong cpdist[30] = 
{ 
	1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
	257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
	8193, 12289, 16385, 24577
};

static ulong fixed_bl = 9;
static ulong fixed_bd = 5;

static inflate_huft_t fixed_tl[] = 
{
    { 96, 7, 256 }, { 0, 8, 80  }, { 0, 8, 16 }, { 84,  8, 115 },
    { 82, 7, 31  }, { 0, 8, 112 }, { 0, 8, 48 }, { 0,   9, 192 },
    { 80, 7, 10  }, { 0, 8, 96  }, { 0, 8, 32 }, { 0,   9, 160 },
    { 0,  8, 0   }, { 0, 8, 128 }, { 0, 8, 64 }, { 0,   9, 224 },
    { 80, 7, 6   }, { 0, 8, 88  }, { 0, 8, 24 }, { 0,   9, 144 },
    { 83, 7, 59  }, { 0, 8, 120 }, { 0, 8, 56 }, { 0,   9, 208 },
    { 81, 7, 17  }, { 0, 8, 104 }, { 0, 8, 40 }, { 0,   9, 176 },
    { 0,  8, 8   }, { 0, 8, 136 }, { 0, 8, 72 }, { 0,   9, 240 },
    { 80, 7, 4   }, { 0, 8, 84  }, { 0, 8, 20 }, { 85,  8, 227 },
    { 83, 7, 43  }, { 0, 8, 116 }, { 0, 8, 52 }, { 0,   9, 200 },
    { 81, 7, 13  }, { 0, 8, 100 }, { 0, 8, 36 }, { 0,   9, 168 },
    { 0,  8, 4   }, { 0, 8, 132 }, { 0, 8, 68 }, { 0,   9, 232 },
    { 80, 7, 8   }, { 0, 8, 92  }, { 0, 8, 28 }, { 0,   9, 152 },
    { 84, 7, 83  }, { 0, 8, 124 }, { 0, 8, 60 }, { 0,   9, 216 },
    { 82, 7, 23  }, { 0, 8, 108 }, { 0, 8, 44 }, { 0,   9, 184 },
    { 0,  8, 12  }, { 0, 8, 140 }, { 0, 8, 76 }, { 0,   9, 248 },
    { 80, 7, 3   }, { 0, 8, 82  }, { 0, 8, 18 }, { 85,  8, 163 },
    { 83, 7, 35  }, { 0, 8, 114 }, { 0, 8, 50 }, { 0,   9, 196 },
    { 81, 7, 11  }, { 0, 8, 98  }, { 0, 8, 34 }, { 0,   9, 164 },
    { 0,  8, 2   }, { 0, 8, 130 }, { 0, 8, 66 }, { 0,   9, 228 },
    { 80, 7, 7   }, { 0, 8, 90  }, { 0, 8, 26 }, { 0,   9, 148 },
    { 84, 7, 67  }, { 0, 8, 122 }, { 0, 8, 58 }, { 0,   9, 212 },
    { 82, 7, 19  }, { 0, 8, 106 }, { 0, 8, 42 }, { 0,   9, 180 },
    { 0,  8, 10  }, { 0, 8, 138 }, { 0, 8, 74 }, { 0,   9, 244 },
    { 80, 7, 5   }, { 0, 8, 86  }, { 0, 8, 22 }, { 192, 8, 0   }, 
    { 83, 7, 51  }, { 0, 8, 118 }, { 0, 8, 54 }, { 0,   9, 204 },
    { 81, 7, 15  }, { 0, 8, 102 }, { 0, 8, 38 }, { 0,   9, 172 },
    { 0,  8, 6   }, { 0, 8, 134 }, { 0, 8, 70 }, { 0,   9, 236 },
    { 80, 7, 9   }, { 0, 8, 94  }, { 0, 8, 30 }, { 0,   9, 156 },
    { 84, 7, 99  }, { 0, 8, 126 }, { 0, 8, 62 }, { 0,   9, 220 },
    { 82, 7, 27  }, { 0, 8, 110 }, { 0, 8, 46 }, { 0,   9, 188 },
    { 0,  8, 14  }, { 0, 8, 142 }, { 0, 8, 78 }, { 0,   9, 252 },
    { 96, 7, 256 }, { 0, 8, 81  }, { 0, 8, 17 }, { 85,  8, 131 },
    { 82, 7, 31  }, { 0, 8, 113 }, { 0, 8, 49 }, { 0,   9, 194 },
    { 80, 7, 10  }, { 0, 8, 97  }, { 0, 8, 33 }, { 0,   9, 162 },
    { 0,  8, 1   }, { 0, 8, 129 }, { 0, 8, 65 }, { 0,   9, 226 },
    { 80, 7, 6   }, { 0, 8, 89  }, { 0, 8, 25 }, { 0,   9, 146 },
    { 83, 7, 59  }, { 0, 8, 121 }, { 0, 8, 57 }, { 0,   9, 210 },
    { 81, 7, 17  }, { 0, 8, 105 }, { 0, 8, 41 }, { 0,   9, 178 },
    { 0,  8, 9   }, { 0, 8, 137 }, { 0, 8, 73 }, { 0,   9, 242 },
    { 80, 7, 4   }, { 0, 8, 85  }, { 0, 8, 21 }, { 80,  8, 258 },
    { 83, 7, 43  }, { 0, 8, 117 }, { 0, 8, 53 }, { 0,   9, 202 },
    { 81, 7, 13  }, { 0, 8, 101 }, { 0, 8, 37 }, { 0,   9, 170 },
    { 0,  8, 5   }, { 0, 8, 133 }, { 0, 8, 69 }, { 0,   9, 234 },
    { 80, 7, 8   }, { 0, 8, 93  }, { 0, 8, 29 }, { 0,   9, 154 },
    { 84, 7, 83  }, { 0, 8, 125 }, { 0, 8, 61 }, { 0,   9, 218 },
    { 82, 7, 23  }, { 0, 8, 109 }, { 0, 8, 45 }, { 0,   9, 186 },
    { 0,  8, 13  }, { 0, 8, 141 }, { 0, 8, 77 }, { 0,   9, 250 },
    { 80, 7, 3   }, { 0, 8, 83  }, { 0, 8, 19 }, { 85,  8, 195 },
    { 83, 7, 35  }, { 0, 8, 115 }, { 0, 8, 51 }, { 0,   9, 198 },
    { 81, 7, 11  }, { 0, 8, 99  }, { 0, 8, 35 }, { 0,   9, 166 },
    { 0,  8, 3   }, { 0, 8, 131 }, { 0, 8, 67 }, { 0,   9, 230 },
    { 80, 7, 7   }, { 0, 8, 91  }, { 0, 8, 27 }, { 0,   9, 150 },
    { 84, 7, 67  }, { 0, 8, 123 }, { 0, 8, 59 }, { 0,   9, 214 },
    { 82, 7, 19  }, { 0, 8, 107 }, { 0, 8, 43 }, { 0,   9, 182 },
    { 0,  8, 11  }, { 0, 8, 139 }, { 0, 8, 75 }, { 0,   9, 246 },
    { 80, 7, 5   }, { 0, 8, 87  }, { 0, 8, 23 }, { 192, 8, 0   }, 
    { 83, 7, 51  }, { 0, 8, 119 }, { 0, 8, 55 }, { 0,   9, 206 },
    { 81, 7, 15  }, { 0, 8, 103 }, { 0, 8, 39 }, { 0,   9, 174 },
    { 0,  8, 7   }, { 0, 8, 135 }, { 0, 8, 71 }, { 0,   9, 238 },
    { 80, 7, 9   }, { 0, 8, 95  }, { 0, 8, 31 }, { 0,   9, 158 },
    { 84, 7, 99  }, { 0, 8, 127 }, { 0, 8, 63 }, { 0,   9, 222 },
    { 82, 7, 27  }, { 0, 8, 111 }, { 0, 8, 47 }, { 0,   9, 190 },
    { 0,  8, 15  }, { 0, 8, 143 }, { 0, 8, 79 }, { 0,   9, 254 },
    { 96, 7, 256 }, { 0, 8, 80  }, { 0, 8, 16 }, { 84,  8, 115 },
    { 82, 7, 31  }, { 0, 8, 112 }, { 0, 8, 48 }, { 0,   9, 193 },
    { 80, 7, 10  }, { 0, 8, 96  }, { 0, 8, 32 }, { 0,   9, 161 },
    { 0,  8, 0   }, { 0, 8, 128 }, { 0, 8, 64 }, { 0,   9, 225 },
    { 80, 7, 6   }, { 0, 8, 88  }, { 0, 8, 24 }, { 0,   9, 145 },
    { 83, 7, 59  }, { 0, 8, 120 }, { 0, 8, 56 }, { 0,   9, 209 },
    { 81, 7, 17  }, { 0, 8, 104 }, { 0, 8, 40 }, { 0,   9, 177 },
    { 0,  8, 8   }, { 0, 8, 136 }, { 0, 8, 72 }, { 0,   9, 241 },
    { 80, 7, 4   }, { 0, 8, 84  }, { 0, 8, 20 }, { 85,  8, 227 },
    { 83, 7, 43  }, { 0, 8, 116 }, { 0, 8, 52 }, { 0,   9, 201 },
    { 81, 7, 13  }, { 0, 8, 100 }, { 0, 8, 36 }, { 0,   9, 169 },
    { 0,  8, 4   }, { 0, 8, 132 }, { 0, 8, 68 }, { 0,   9, 233 },
    { 80, 7, 8   }, { 0, 8, 92  }, { 0, 8, 28 }, { 0,   9, 153 },
    { 84, 7, 83  }, { 0, 8, 124 }, { 0, 8, 60 }, { 0,   9, 217 },
    { 82, 7, 23  }, { 0, 8, 108 }, { 0, 8, 44 }, { 0,   9, 185 },
    { 0,  8, 12  }, { 0, 8, 140 }, { 0, 8, 76 }, { 0,   9, 249 },
    { 80, 7, 3   }, { 0, 8, 82  }, { 0, 8, 18 }, { 85,  8, 163 },
    { 83, 7, 35  }, { 0, 8, 114 }, { 0, 8, 50 }, { 0,   9, 197 },
    { 81, 7, 11  }, { 0, 8, 98  }, { 0, 8, 34 }, { 0,   9, 165 },
    { 0,  8, 2   }, { 0, 8, 130 }, { 0, 8, 66 }, { 0,   9, 229 },
    { 80, 7, 7   }, { 0, 8, 90  }, { 0, 8, 26 }, { 0,   9, 149 },
    { 84, 7, 67  }, { 0, 8, 122 }, { 0, 8, 58 }, { 0,   9, 213 },
    { 82, 7, 19  }, { 0, 8, 106 }, { 0, 8, 42 }, { 0,   9, 181 },
    { 0,  8, 10  }, { 0, 8, 138 }, { 0, 8, 74 }, { 0,   9, 245 },
    { 80, 7, 5   }, { 0, 8, 86  }, { 0, 8, 22 }, { 192, 8, 0   }, 
    { 83, 7, 51  }, { 0, 8, 118 }, { 0, 8, 54 }, { 0,   9, 205 },
    { 81, 7, 15  }, { 0, 8, 102 }, { 0, 8, 38 }, { 0,   9, 173 },
    { 0,  8, 6   }, { 0, 8, 134 }, { 0, 8, 70 }, { 0,   9, 237 },
    { 80, 7, 9   }, { 0, 8, 94  }, { 0, 8, 30 }, { 0,   9, 157 },
    { 84, 7, 99  }, { 0, 8, 126 }, { 0, 8, 62 }, { 0,   9, 221 },
    { 82, 7, 27  }, { 0, 8, 110 }, { 0, 8, 46 }, { 0,   9, 189 },
    { 0,  8, 14  }, { 0, 8, 142 }, { 0, 8, 78 }, { 0,   9, 253 },
    { 96, 7, 256 }, { 0, 8, 81  }, { 0, 8, 17 }, { 85,  8, 131 },
    { 82, 7, 31  }, { 0, 8, 113 }, { 0, 8, 49 }, { 0,   9, 195 },
    { 80, 7, 10  }, { 0, 8, 97  }, { 0, 8, 33 }, { 0,   9, 163 },
    { 0,  8, 1   }, { 0, 8, 129 }, { 0, 8, 65 }, { 0,   9, 227 },
    { 80, 7, 6   }, { 0, 8, 89  }, { 0, 8, 25 }, { 0,   9, 147 },
    { 83, 7, 59  }, { 0, 8, 121 }, { 0, 8, 57 }, { 0,   9, 211 },
    { 81, 7, 17  }, { 0, 8, 105 }, { 0, 8, 41 }, { 0,   9, 179 },
    { 0,  8, 9   }, { 0, 8, 137 }, { 0, 8, 73 }, { 0,   9, 243 },
    { 80, 7, 4   }, { 0, 8, 85  }, { 0, 8, 21 }, { 80,  8, 258 },
    { 83, 7, 43  }, { 0, 8, 117 }, { 0, 8, 53 }, { 0,   9, 203 },
    { 81, 7, 13  }, { 0, 8, 101 }, { 0, 8, 37 }, { 0,   9, 171 },
    { 0,  8, 5   }, { 0, 8, 133 }, { 0, 8, 69 }, { 0,   9, 235 },
    { 80, 7, 8   }, { 0, 8, 93  }, { 0, 8, 29 }, { 0,   9, 155 },
    { 84, 7, 83  }, { 0, 8, 125 }, { 0, 8, 61 }, { 0,   9, 219 },
    { 82, 7, 23  }, { 0, 8, 109 }, { 0, 8, 45 }, { 0,   9, 187 },
    { 0,  8, 13  }, { 0, 8, 141 }, { 0, 8, 77 }, { 0,   9, 251 },
    { 80, 7, 3   }, { 0, 8, 83  }, { 0, 8, 19 }, { 85,  8, 195 },
    { 83, 7, 35  }, { 0, 8, 115 }, { 0, 8, 51 }, { 0,   9, 199 },
    { 81, 7, 11  }, { 0, 8, 99  }, { 0, 8, 35 }, { 0,   9, 167 },
    { 0,  8, 3   }, { 0, 8, 131 }, { 0, 8, 67 }, { 0,   9, 231 },
    { 80, 7, 7   }, { 0, 8, 91  }, { 0, 8, 27 }, { 0,   9, 151 },
    { 84, 7, 67  }, { 0, 8, 123 }, { 0, 8, 59 }, { 0,   9, 215 },
    { 82, 7, 19  }, { 0, 8, 107 }, { 0, 8, 43 }, { 0,   9, 183 },
    { 0,  8, 11  }, { 0, 8, 139 }, { 0, 8, 75 }, { 0,   9, 247 },
    { 80, 7, 5   }, { 0, 8, 87  }, { 0, 8, 23 }, { 192, 8, 0   }, 
    { 83, 7, 51  }, { 0, 8, 119 }, { 0, 8, 55 }, { 0,   9, 207 },
    { 81, 7, 15  }, { 0, 8, 103 }, { 0, 8, 39 }, { 0,   9, 175 },
    { 0,  8, 7   }, { 0, 8, 135 }, { 0, 8, 71 }, { 0,   9, 239 },
    { 80, 7, 9   }, { 0, 8, 95  }, { 0, 8, 31 }, { 0,   9, 159 },
    { 84, 7, 99  }, { 0, 8, 127 }, { 0, 8, 63 }, { 0,   9, 223 },
    { 82, 7, 27  }, { 0, 8, 111 }, { 0, 8, 47 }, { 0,   9, 191 },
    { 0,  8, 15  }, { 0, 8, 143 }, { 0, 8, 79 }, { 0,   9, 255 }
};

static inflate_huft_t fixed_td[] = 
{
    { 80, 5, 1  }, { 87, 5, 257  }, { 83, 5, 17  }, { 91,  5, 4097  },
    { 81, 5, 5  }, { 89, 5, 1025 }, { 85, 5, 65  }, { 93,  5, 16385 },
    { 80, 5, 3  }, { 88, 5, 513  }, { 84, 5, 33  }, { 92,  5, 8193  },
    { 82, 5, 9  }, { 90, 5, 2049 }, { 86, 5, 129 }, { 192, 5, 24577 },
    { 80, 5, 2  }, { 87, 5, 385  }, { 83, 5, 25  }, { 91,  5, 6145  },
    { 81, 5, 7  }, { 89, 5, 1537 }, { 85, 5, 97  }, { 93,  5, 24577 },
    { 80, 5, 4  }, { 88, 5, 769  }, { 84, 5, 49  }, { 92,  5, 12289 },
    { 82, 5, 13 }, { 90, 5, 3073 }, { 86, 5, 193 }, { 192, 5, 24577 }
};

// ===============================================================================
// ===============================================================================

static void inflate_blocks_reset(z_stream *z, inflate_blocks_state_t *s)
{
	if((s->mode == BTREE) || (s->mode == DTREE))
	{
		Z_Free(s->trees.blens);
	}
	if(s->mode == CODES)
	{
		Z_Free(s->decode.codes);
	}
	s->mode = TYPE;
	s->bitk = 0;
	s->bitb = 0;
	s->write = s->window;
	s->read = s->window;
	z->istate->adler = 1;
}

// ===============================================================================
// ===============================================================================

static int inflate_blocks_free(z_stream *z, inflate_blocks_state_t *s)
{
	inflate_blocks_reset(z, s);
	Z_Free(s->hufts);
	s->hufts = NULL;
	Z_Free(s);
	return(Z_OK);
}

// ===============================================================================
// ===============================================================================

static inflate_blocks_state_t *inflate_blocks_new(z_stream *z, check_func check)
{
	inflate_blocks_state_t *s;

	s = (inflate_blocks_state_t *)Z_Malloc(sizeof(inflate_blocks_state_t), TAG_INFLATE, qtrue);
	s->hufts = (inflate_huft_t *)Z_Malloc(sizeof(inflate_huft_t) * MANY, TAG_INFLATE, qtrue);
	s->end = s->window + WINDOW_SIZE;
	s->mode = TYPE;
	inflate_blocks_reset(z, s);

	return(s);
}

// ===============================================================================
// copy as much as possible from the sliding window to the output area
// ===============================================================================

static void inflate_flush_copy(z_stream *z, inflate_blocks_state_t *s, ulong count)
{
	if(count > z->avail_out)
	{
		count = z->avail_out;
	}
	if(count && (z->error == Z_BUF_ERROR))
	{
		z->error = Z_OK;
	}

	// Calculate the checksum if required
	if(!z->istate->nowrap)
	{
		z->istate->adler = adler32(z->istate->adler, s->read, count);
	}

	// copy as as end of window
	memcpy(z->next_out, s->read, count);

	// update counters
	z->avail_out -= count;
	z->total_out += count;
	z->next_out += count;
	s->read += count;
}

// ===============================================================================
// ===============================================================================

static void inflate_flush(z_stream *z, inflate_blocks_state_t *s)
{
	ulong	count;

	// compute number of bytes to copy as as end of window
	count = (s->read <= s->write ? s->write : s->end) - s->read;

	inflate_flush_copy(z, s, count);

	// see if more to copy at beginning of window
	if(s->read == s->end)
	{
		// wrap pointers
		s->read = s->window;
		if(s->write == s->end)
		{
			s->write = s->window;
		}
		// compute bytes to copy
		count = s->write - s->read;
		inflate_flush_copy(z, s, count);
	}
}

// ===============================================================================
// get bytes and bits
// ===============================================================================

static bool getbits(z_stream *z, inflate_blocks_state_t *s, ulong bits)								 
{			
	while(s->bitk < bits) 							
	{											
		if(z->avail_in)
		{
			z->error = Z_OK;
		}
		else
		{										
			inflate_flush(z, s);
			return(false);
		}		  
		z->avail_in--;
		z->total_in++;
		s->bitb |= *z->next_in++ << s->bitk;			
		s->bitk += 8; 	 
	}		
	return(true);
}

// ===============================================================================
// output bytes
// ===============================================================================

static ulong needout(z_stream *z, inflate_blocks_state_t *s, ulong bytesToEnd) 
{ 
	if(!bytesToEnd)
	{ 
		if((s->write == s->end) && (s->read != s->window)) 
		{ 
			s->write = s->window;
			bytesToEnd = s->write < s->read ? s->read - s->write - 1 : s->end - s->write;
		}
		if(!bytesToEnd)
		{
			inflate_flush(z, s);
			bytesToEnd = s->write < s->read ? s->read - s->write - 1 : s->end - s->write;
			if((s->write == s->end) && (s->read != s->window))
			{
				s->write = s->window;
				bytesToEnd = s->write < s->read ? s->read - s->write - 1 : s->end - s->write;
			}
			if(!bytesToEnd)
			{
				inflate_flush(z, s);
				return(bytesToEnd);
			}
		}
	}
	z->error = Z_OK;
	return(bytesToEnd);
}

// ===============================================================================
// Called with number of bytes left to write in window at least 258
//	 (the maximum string length) and number of input bytes available
//	 at least ten.	The ten bytes are six bytes for the longest length/
//	 distance pair plus four bytes for overloading the bit buffer.
// ===============================================================================

inline byte *qcopy(byte *dst, byte *src, int count)
{
	byte 	*retval;
#ifdef _MSC_VER
	_asm
	{
		push ecx  
		push esi
		push edi

		mov edi, [dst]
		mov esi, [src]
		mov ecx, [count]
		rep movsb

		mov [retval], edi
		pop edi
		pop esi
		pop ecx
	}
#else
	asm("repe movsb;"
	    : "=D"(retval)
	    : "D"(dst), "S"(src), "c"(count)
	);
#endif
	return(retval);
}

inline ulong get_remaining(inflate_blocks_state_t *s)
{
	if(s->write < s->read)
	{
		return(s->read - s->write - 1);
	}
	return(s->end - s->write); 
}

static EStatus inflate_fast(ulong lengthMask, ulong distMask, inflate_huft_t *lengthTree, inflate_huft_t *distTree, inflate_blocks_state_t *s, z_stream *z)
{
	inflate_huft_t	*huft;			// temporary pointer
	byte			*data;			
	byte			*src; 			// copy source pointer
	byte			*dst;			
	ulong			extraBits;		// extra bits or operation
	ulong			bytesToEnd;		// bytes to end of window or read pointer
	ulong			count;			// bytes to copy
	ulong			dist;			// distance back to copy from
	ulong			bitb;
	ulong			bitk;
	ulong			availin;
	ulong			morebits;
	ulong			copymore;

	// load input, output, bit values
	data = z->next_in;
	dst = s->write;
	availin = z->avail_in;
	bitb = s->bitb;
	bitk = s->bitk;

	bytesToEnd = get_remaining(s);

	// do until not enough input or output space for fast loop
	// assume called with bytesToEnd >= 258 && availIn >= 10
	while((bytesToEnd >= 258) && (availin >= 10))
	{						   
		// get literal/length code
		while(bitk < 20)
		{
			bitb |= *data++ << bitk;
			bitk += 8;
			availin--;
		}

		huft = lengthTree + (bitb & lengthMask);
		if(!huft->Exop)
		{
			bitb >>= huft->Bits;
			bitk -= huft->Bits;
			*dst++ = (byte)huft->base;
			bytesToEnd--;
		}
		else
		{
			extraBits = huft->Exop;
			morebits = 1;
			do
			{
				bitb >>= huft->Bits; 
				bitk -= huft->Bits;
				if(extraBits & 16)
				{
					// get extra bits for length
					extraBits &= 15;
					count = huft->base + (bitb & inflate_mask[extraBits]);
					bitb >>= extraBits;
					bitk -= extraBits;
					// decode distance base of block to copy
					while(bitk < 15)
					{
						bitb |= *data++ << bitk;
						bitk += 8;
						availin--;
					}
					huft = distTree + (bitb & distMask);
					extraBits = huft->Exop;
	   				copymore = 1;
					do
					{
						bitb >>= huft->Bits;
						bitk -= huft->Bits;
						if(extraBits & 16)
						{
							// get extra bits to add to distance base
							extraBits &= 15;
							while(bitk < extraBits)
							{
								bitb |= *data++ << bitk;
								bitk += 8;
								availin--;
							}
							dist = huft->base + (bitb & inflate_mask[extraBits]);
							bitb >>= extraBits;
							bitk -= extraBits;

							// do the copy
							bytesToEnd -= count;
							// offset before dest
							if((dst - s->window) >= dist)	 
							{								   
								// just copy
								src = dst - dist;
							}
							// else offset after destination
							else						
							{
								// bytes from offset to end
								extraBits = dist - (dst - s->window);
								// pointer to offset
								src = s->end - extraBits; 		  
								// if source crosses,					  
								if(count > extraBits)				  
								{
									// copy to end of window
									dst = qcopy(dst, src, extraBits);
									// copy rest from start of window
									count -= extraBits; 				
									src = s->window;			
								}
							}
							// copy all or what's left
							dst = qcopy(dst, src, count);
							copymore = 0;
						}
						else
						{
							if(!(extraBits & 64))
							{
								huft += huft->base + (bitb & inflate_mask[extraBits]);
								extraBits = huft->Exop;
							}
							else
							{
								inflate_error = "Inflate data: Invalid distance code";
								return(Z_DATA_ERROR);
							}
						}
					} while(copymore);

					morebits = 0;
				}
				else
				{
					if(!(extraBits & 64))
					{
						huft += huft->base + (bitb & inflate_mask[extraBits]);
						extraBits = huft->Exop;
						if(!extraBits)								   
						{
							bitb >>= huft->Bits;
							bitk -= huft->Bits;
							*dst++ = (byte)huft->base;
							bytesToEnd--;
							morebits = 0;
						}
					}
					else if(extraBits & 32)									 
					{
						count = data - z->next_in;

						z->avail_in = availin;
						z->total_in += count;
						z->next_in = data;

						s->write = dst;

						count = (bitk >> 3) < count ? bitk >> 3 : count;

						s->bitb = bitb;
						s->bitk = bitk - (count << 3);
						z->avail_in += count;
						z->total_in -= count;
						z->next_in -= count ;
						return(Z_STREAM_END);
					}
					else
					{
						inflate_error = "Inflate data: Invalid literal/length code";
						return(Z_DATA_ERROR);
					}
				}
			} while(morebits);
		}
	}

	// not enough input or output--restore pointers and return
	count = data - z->next_in;

	z->avail_in = availin;
	z->total_in += count;
	z->next_in = data;

	s->write = dst;

	count = (bitk >> 3) < count ? bitk >> 3 : count;
	s->bitb = bitb;
	s->bitk = bitk - (count << 3);
	z->avail_in += count;
	z->total_in -= count;
	z->next_in -= count;

	return(Z_OK);
}

// ===============================================================================
// ===============================================================================

static void inflate_codes(z_stream *z, inflate_blocks_state_t *s)
{
	inflate_huft_t			*huft; 		// temporary pointer
	ulong					extraBits;	// extra bits or operation
	ulong					bytesToEnd;	// bytes to end of window or read pointer
	byte					*src; 		// pointer to copy strings from
	inflate_codes_state_t	*infCodes;	// codes state

	infCodes = s->decode.codes;

	// copy input/output information to locals
	bytesToEnd = get_remaining(s);

	// process input and output based on current state
	while(true)
	{
		// waiting for "i:"=input, "o:"=output, "x:"=nothing
		switch (infCodes->mode)
		{			  
		// x: set up for LEN
		case START:
			if((bytesToEnd >= 258) && (z->avail_in >= 10))
			{
				z->error = inflate_fast(inflate_mask[infCodes->lbits], inflate_mask[infCodes->dbits], infCodes->ltree, infCodes->dtree, s, z);
				bytesToEnd = get_remaining(s);
				if(z->error != Z_OK)
				{
					infCodes->mode = (z->error == Z_STREAM_END) ? WASH : BADCODE;
					break;
				}
			}
			infCodes->code.need = infCodes->lbits;
			infCodes->code.tree = infCodes->ltree;
			infCodes->mode = LEN;
		// i: get length/literal/eob next
		case LEN:			
			if(!getbits(z, s, infCodes->code.need))
			{
				// We could get here because we have run out of input data *or* the stream has ended
				if(z->status == Z_BUF_ERROR)
				{
					z->error = Z_STREAM_END;
				}
				return;
			}
			huft = infCodes->code.tree + (s->bitb & inflate_mask[infCodes->code.need]);
			s->bitb >>= huft->Bits;
			s->bitk -= huft->Bits; 
			extraBits = huft->Exop;
			// literal
			if(!extraBits)				 
			{
				infCodes->lit = huft->base;
				infCodes->mode = LIT;
				break;
			}
			// length
			if(extraBits & 16) 			  
			{
				infCodes->copy.get = extraBits & 15;
				infCodes->len = huft->base;
				infCodes->mode = LENEXT;
				break;
			}
			// next table
			if(!(extraBits & 64))
			{
				infCodes->code.need = extraBits;
				infCodes->code.tree = huft + huft->base;
				break;
			}
			// end of block
			if(extraBits & 32) 			  
			{
				infCodes->mode = WASH;
				break;
			}
			// invalid code
			infCodes->mode = BADCODE;		  
			inflate_error = "Inflate data: Invalid literal/length code";
			z->error = Z_DATA_ERROR;
			inflate_flush(z, s);
			return;
		// i: getting length extra (have base)
		case LENEXT:		
			if(!getbits(z, s, infCodes->copy.get))
			{
				return;
			}
			infCodes->len += s->bitb & inflate_mask[infCodes->copy.get];
			s->bitb >>= infCodes->copy.get;
			s->bitk -= infCodes->copy.get;
			infCodes->code.need = infCodes->dbits;
			infCodes->code.tree = infCodes->dtree;
			infCodes->mode = DIST;
		// i: get distance next
		case DIST:			
			if(!getbits(z, s, infCodes->code.need))
			{
				return;
			}
			huft = infCodes->code.tree + (s->bitb & inflate_mask[infCodes->code.need]);
			s->bitb >>= huft->Bits;
			s->bitk -= huft->Bits;
			extraBits = huft->Exop;
			// distance
			if(extraBits & 16) 			  
			{
				infCodes->copy.get = extraBits & 15;
				infCodes->copy.dist = huft->base;
				infCodes->mode = DISTEXT;
				break;
			}
			// next table
			if(!(extraBits & 64))
			{
				infCodes->code.need = extraBits;
				infCodes->code.tree = huft + huft->base;
				break;
			}
			// invalid code
			infCodes->mode = BADCODE;		  
			inflate_error = "Inflate data: Invalid distance code";
			z->error = Z_DATA_ERROR;
			inflate_flush(z, s);
			return;
		// i: getting distance extra
		case DISTEXT:		
			if(!getbits(z, s, infCodes->copy.get))
			{
				return;
			}
			infCodes->copy.dist += s->bitb & inflate_mask[infCodes->copy.get];
			s->bitb >>= infCodes->copy.get;
			s->bitk -= infCodes->copy.get;
			infCodes->mode = COPY;
		// o: copying bytes in window, waiting for space
		case COPY:			
			if(s->write - s->window < infCodes->copy.dist)
			{
				src = s->end - (infCodes->copy.dist - (s->write - s->window));
			}
			else
			{
				src = s->write - infCodes->copy.dist;
			}
			while(infCodes->len)
			{
				bytesToEnd = needout(z, s, bytesToEnd);
				if(!bytesToEnd)
				{
					return;
				}
				*s->write++ = (byte)(*src++);
				bytesToEnd--;
				if(src == s->end)
				{
					src = s->window;
				}
				infCodes->len--;
			}
			infCodes->mode = START;
			break;
		// o: got literal, waiting for output space
		case LIT:			
			bytesToEnd = needout(z, s, bytesToEnd);
			if(!bytesToEnd)
			{
				return;
			}
			*s->write++ = (byte)infCodes->lit; 
			bytesToEnd--;
			infCodes->mode = START;
			break;
		// o: got eob, possibly more output
		case WASH:			
			// return unused byte, if any
			if(s->bitk > 7)		  
			{
				s->bitk -= 8;
				z->avail_in++;
				z->total_in--;
				// can always return one
				z->next_in--;			
			}
			inflate_flush(z, s);
			bytesToEnd = get_remaining(s);
			if(s->read != s->write)
			{
				inflate_error = "Inflate data: read != write while in WASH";
				inflate_flush(z, s);
				return;
			}
			infCodes->mode = END;
		case END:
			z->error = Z_STREAM_END;
			inflate_flush(z, s);
			return;
		// x: got error
		case BADCODE:		
			z->error = Z_DATA_ERROR;
			inflate_flush(z, s);
			return;
		default:
			z->error = Z_STREAM_ERROR;
			inflate_flush(z, s);
			return;
		}
	}
}

// ===============================================================================
// ===============================================================================

static inflate_codes_state_t *inflate_codes_new(z_stream *z, ulong bl, ulong bd, inflate_huft_t *lengthTree, inflate_huft_t *distTree)
{
	inflate_codes_state_t		*c;

	c = (inflate_codes_state_t *)Z_Malloc(sizeof(inflate_codes_state_t), TAG_INFLATE, qtrue);
	c->mode = START;
	c->lbits = (byte)bl;
	c->dbits = (byte)bd;
	c->ltree = lengthTree;
	c->dtree = distTree;

	return(c);
}

// ===============================================================================
// Generate Huffman trees for efficient decoding

//	ulong b				// code lengths in bits (all assumed <= BMAX)
//	ulong n             // number of codes (assumed <= 288)
//	ulong s             // number of simple-valued codes (0..s-1)
//	const ulong *d      // list of base values for non-simple codes
//	const ulong *e      // list of extra bits for non-simple codes
//	inflate_huft ** t	// result: starting table
//	ulong *m            // maximum lookup bits, returns actual
//	inflate_huft *hp    // space for trees
//	ulong *hn           // hufts used in space
//	ulong *workspace    // working area: values in order of bit length
//
//   Given a list of code lengths and a maximum table size, make a set of
//   tables to decode that set of codes.  Return Z_OK on success, Z_BUF_ERROR
//   if the given code set is incomplete (the tables are still built in this
//   case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of
//   lengths).
//
//   Huffman code decoding is performed using a multi-level table lookup.
//   The fastest way to decode is to simply build a lookup table whose
//   size is determined by the longest code.  However, the time it takes
//   to build this table can also be a factor if the data being decoded
//   is not very long.  The most common codes are necessarily the
//   shortest codes, so those codes dominate the decoding time, and hence
//   the speed.  The idea is you can have a shorter table that decodes the
//   shorter, more probable codes, and then point to subsidiary tables for
//   the longer codes.  The time it costs to decode the longer codes is
//   then traded against the time it takes to make longer tables.
//
//   This results of this trade are in the variables lbits and dbits
//   below.  lbits is the number of bits the first level table for literal/
//   length codes can decode in one step, and dbits is the same thing for
//   the distance codes.  Subsequent tables are also less than or equal to
//   those sizes.  These values may be adjusted either when all of the
//   codes are shorter than that, in which case the longest code length in
//   bits is used, or when the shortest code is *longer* than the requested
//   table size, in which case the length of the shortest code in bits is
//   used.
//
//   There are two different values for the two tables, since they code a
//   different number of possibilities each.  The literal/length table
//   codes 286 possible values, or in a flat code, a little over eight
//   bits.  The distance table codes 30 possible values, or a little less
//   than five bits, flat.  The optimum values for speed end up being
//   about one bit more than those, so lbits is 8+1 and dbits is 5+1.
//   The optimum values may differ though from machine to machine, and
//   possibly even between compilers.  Your mileage may vary.
// ===============================================================================

static EStatus huft_build(ulong *b, ulong numCodes, ulong s, const ulong *d, const ulong *e, inflate_huft_t **t, ulong *m, inflate_huft_t *hp, ulong *hn, ulong *workspace)
{
	ulong			codeCounter;					// counter for codes of length bitsPerCode
	ulong			bitLengths[BMAX + 1] = { 0 };	// bit length count table
	ulong			bitOffsets[BMAX + 1];			// bit offsets, then code stack
	ulong			f;								// i repeats in table every f entries
	int 			maxCodeLen;						// maximum code length
	int 			tableLevel;						// table level
	ulong			i;								// counter, current code
	ulong			j;								// counter
	int 			bitsPerCode;					// number of bits in current code
	ulong 			bitsPerTable;					// bits per table (returned in m)
	int 			bitsBeforeTable;				// bits before this table == (bitsPerTable * tableLevel)
	ulong			*p; 							// pointer into bitLengths[], b[], or workspace[]
	inflate_huft_t	*q; 							// points to current table
	inflate_huft_t	r;								// table entry for structure assignment
	inflate_huft_t	*tableStack[BMAX];				// table stack
	ulong			*xp;							// pointer into bitOffsets
	int 			dummyCodes;						// number of dummy codes added
	ulong			entryCount;						// number of entries in current table

	// Generate counts for each bit length
	// assume all entries <= BMAX
	p = b;	
	i = numCodes;
	do
	{
		bitLengths[*p++]++;					
	} while(--i);

	// null input--all zero length codes
	if(bitLengths[0] == numCodes)				  
	{
		*t = NULL;
		*m = 0;
		return(Z_OK);
	}

	// Find minimum and maximum length, bound *m by those
	bitsPerTable = *m;
	for(j = 1; j <= BMAX; j++)
	{
		if(bitLengths[j])
		{
			break;
		}
	}
	// minimum code length
	bitsPerCode = j;						  

	if(bitsPerTable < j)
	{
		bitsPerTable = j;
	}
	for(i = BMAX; i; i--)
	{
		if(bitLengths[i])
		{
			break;
		}
	}
	// maximum code length
	maxCodeLen = i;						  

	if(bitsPerTable > i)
	{
		bitsPerTable = i;
	}
	*m = bitsPerTable;

	// Adjust last length count to fill out codes, if needed
	for(dummyCodes = 1 << j; j < i; j++, dummyCodes <<= 1)
	{
		dummyCodes -= bitLengths[j];
		if(dummyCodes < 0)
		{
			return(Z_DATA_ERROR);
		}
	}
	dummyCodes -= bitLengths[i];
	if(dummyCodes < 0)
	{
		return(Z_DATA_ERROR);
	}
	bitLengths[i] += dummyCodes;

	// Generate starting offsets into the value table for each length
	bitOffsets[1] = 0;
	j = 0;
	p = bitLengths + 1;
	xp = bitOffsets + 2;
	// note that i == maxCodeLen from above
	while(--i) 
	{			 
		j += *p++;
		*xp++ = j;
	}

	// Make a table of values in order of bit lengths
	p = b;
	i = 0;
	do
	{
		j = *p++;
		if(j)
		{
			workspace[bitOffsets[j]++] = i;
		}
	} while(++i < numCodes);

	// set numCodes to length of workspace
	numCodes = bitOffsets[maxCodeLen];					  

	// Generate the Huffman codes and for each, make the table entries
	bitOffsets[0] = 0;						// first Huffman code is zero
	i = 0;							
	p = workspace;							// grab values in bit order
	tableLevel = -1; 						// no tables yet--level -1
	bitsBeforeTable = bitsPerTable; 						// bits decoded == (bitsPerTable * tableLevel)
	bitsBeforeTable = -bitsBeforeTable;
	tableStack[0] = NULL;	// just to keep compilers happy
	q = NULL;		// ditto
	entryCount = 0;							// ditto

	// go through the bit lengths (bitsPerCode already is bits in shortest code)
	for(; bitsPerCode <= maxCodeLen; bitsPerCode++)
	{
		codeCounter = bitLengths[bitsPerCode];
		while(codeCounter--)
		{
			// here i is the Huffman code of length bitsPerCode bits for value *p
			// make tables up to required level
			while(bitsPerCode > bitsBeforeTable + bitsPerTable)
			{
				tableLevel++;
				bitsBeforeTable += bitsPerTable; 			// previous table always bitsPerTable bits

				// compute minimum size table less than or equal to bitsPerTable bits
				entryCount = maxCodeLen - bitsBeforeTable;
				entryCount = entryCount > bitsPerTable ? bitsPerTable : entryCount;				// table size upper limit
				j = bitsPerCode - bitsBeforeTable;
				f = 1 << j;
				if(f > codeCounter + 1)							// try a bitsPerCode-bitsBeforeTable bit table
				{										// too few codes for bitsPerCode-bitsBeforeTable bit table
					f -= codeCounter + 1; 						// deduct codes from patterns left
					xp = bitLengths + bitsPerCode;
					if(j < entryCount)
					{
						while(++j < entryCount) 					// try smaller tables up to entryCount bits
						{
							f <<= 1;
							if(f <= *++xp)
							{
								break;					// enough codes to use up j bits
							}
							f -= *xp;					// else deduct codes from patterns
						}
					}
				}
				entryCount = 1 << j; 							// table entries for j-bit table

				// allocate new table
				if(*hn + entryCount > MANY) 						// (note: doesn't matter for fixed)
				{
					return(Z_DATA_ERROR);				// not enough memory
				}
				q = hp + *hn;
				tableStack[tableLevel] = q;
				*hn += entryCount;

				// connect to last table, if there is one
				if(tableLevel)
				{
					bitOffsets[tableLevel] = i;							// save pattern for backing up
					r.Bits = (byte)bitsPerTable;   	 					// bits to dump before this table
					r.Exop = (byte)j;									// bits in this table
					j = i >> (bitsBeforeTable - bitsPerTable);
					r.base = q - tableStack[tableLevel - 1] - j; // offset to this table
					tableStack[tableLevel - 1][j] = r;					// connect to last table
				}
				else						   
				{
					*t = q; 							// first table is returned result
				}
			}

			// set up table entry in r
			r.Bits = (byte)(bitsPerCode - bitsBeforeTable);
			if(p >= workspace + numCodes)
			{
				r.Exop = 128 + 64;						// out of values--invalid code
			}
			else if(*p < s)
			{
				r.Exop = (byte)(*p < 256 ? 0 : 32 + 64);		// 256 is end-of-block
				r.base = *p++;							// simple code is just the value
			}
			else
			{
				r.Exop = (byte)(e[*p - s] + 16 + 64);		 	// non-simple--look up in lists
				r.base = d[*p++ - s];
			}

			// fill code-like entries with r
			f = 1 << (bitsPerCode - bitsBeforeTable);
			for(j = i >> bitsBeforeTable; j < entryCount; j += f)
			{
				q[j] = r;
			}

			// backwards increment the bitsPerCode-bit code i
			for(j = 1 << (bitsPerCode - 1); i & j; j >>= 1)
			{
				i ^= j;
			}
			i ^= j;

			// backup over finished tables
			while((i & ((1 << bitsBeforeTable) - 1)) != bitOffsets[tableLevel])
			{
				tableLevel--;									// don't need to update q
				bitsBeforeTable -= bitsPerTable;
			}
		}
	}

	// Return Z_BUF_ERROR if we were given an incomplete table
	if(dummyCodes && (maxCodeLen != 1))
	{
		return(Z_BUF_ERROR);
	}
	return(Z_OK);
}

// ===============================================================================
// ulong *c 				19 code lengths
// ulong *bb				bits tree desired/actual depth
// inflate_huft **tb		bits tree result
// inflate_huft *hp 		space for trees
// ===============================================================================

static void inflate_trees_bits(z_stream *z, ulong *c, ulong *bb, inflate_huft_t **tb, inflate_huft_t *hp)
{
	ulong	hn = 0;				// hufts used in space
	ulong	workspace[19];		// work area for huft_build

	z->error = huft_build(c, 19, 19, NULL, NULL, tb, bb, hp, &hn, workspace);
	if(z->error == Z_DATA_ERROR)
	{
		inflate_error = "Inflate data: Oversubscribed dynamic bit lengths tree";
	}
	else if((z->error == Z_BUF_ERROR) || !*bb)
	{
		inflate_error = "Inflate data: Incomplete dynamic bit lengths tree";
		z->error = Z_DATA_ERROR;
	}
}

// ===============================================================================
// ulong *c 				// that many (total) code lengths
// ulong *bl				// literal desired/actual bit depth
// ulong *bd				// distance desired/actual bit depth
// inflate_huft **tl		// literal/length tree result
// inflate_huft **td		// distance tree result
// inflate_huft *hp 		// space for trees
// ===============================================================================

static void inflate_trees_dynamic(z_stream *z, ulong numLiteral, ulong numDist, ulong *c, ulong *bl, ulong *bd, inflate_huft_t **tl, inflate_huft_t **td, inflate_huft_t *hp)
{
	ulong		hn = 0;				// hufts used in space
	ulong		workspace[288]; 	// work area for huft_build

	// build literal/length tree
	z->error = huft_build(c, numLiteral, 257, cplens, cplext, tl, bl, hp, &hn, workspace);
	if(z->error != Z_OK || !*bl)
	{
		inflate_error = "Inflate data: Erroneous literal/length tree";
		z->error = Z_DATA_ERROR;
		return;
	}
	// build distance tree
	z->error = huft_build(c + numLiteral, numDist, 0, cpdist, extra_dbits, td, bd, hp, &hn, workspace);
	if((z->error != Z_OK) || (!*bd && numLiteral > 257))
	{
		inflate_error = "Inflate data: Erroneous distance tree";
		z->error = Z_DATA_ERROR;
		return;
	}
}

// ===============================================================================
// ulong *bl				// literal desired/actual bit depth
// ulong *bd				// distance desired/actual bit depth
// inflate_huft **tl		// literal/length tree result
// inflate_huft **td		// distance tree result
// ===============================================================================

// Fixme: Calculate dynamically

static void inflate_trees_fixed(z_stream *z, ulong *bl, ulong *bd, inflate_huft_t **tl, inflate_huft_t **td)
{
	*bl = fixed_bl;
	*bd = fixed_bd;
	*tl = fixed_tl;
	*td = fixed_td;
	z->error = Z_OK;
}

// ===============================================================================
// ===============================================================================

static void inflate_blocks(inflate_blocks_state_t *s, z_stream *z)
{
	ulong					t;				// temporary storage
	ulong					bytesToEnd;		// bytes to end of window or read pointer
	ulong					bl, bd;
	inflate_huft_t			*lengthTree = NULL;
	inflate_huft_t			*distTree = NULL;
	inflate_codes_state_t	*c;

	// copy input/output information to locals (UPDATE macro restores)
	bytesToEnd = s->write < s->read ? s->read - s->write - 1 : s->end - s->write; 

	// process input based on current state
	while(true)
	{
		switch (s->mode)
		{
		case TYPE:
			if(!getbits(z, s, 3))
			{
				return;
			}
			t = s->bitb & 7;
			s->last = !!(t & 1);

			switch (t >> 1)
			{
			case STORED_BLOCK:
				s->bitb >>= 3;
				s->bitk -= 3;
				t = s->bitk & 7;				// go to byte boundary
				s->bitb >>= t;
				s->bitk -= t;
				s->mode = LENS; 				// get length of stored block
				break;
			case STATIC_TREES:
				inflate_trees_fixed(z, &bl, &bd, &lengthTree, &distTree);
				s->decode.codes = inflate_codes_new(z, bl, bd, lengthTree, distTree);
				s->bitb >>= 3;
				s->bitk -= 3;
				s->mode = CODES;
				break;
			case DYN_TREES:
				s->bitb >>= 3;
				s->bitk -= 3;
				s->mode = TABLE;
				break;
			case MODE_ILLEGAL:
				s->bitb >>= 3;
				s->bitk -= 3;
				s->mode = BAD;
				inflate_error = "Inflate data: Invalid block type";
				z->error = Z_DATA_ERROR;
				inflate_flush(z, s);
				return;
			}
			break;
		case LENS:
			if(!getbits(z, s, 32))
			{
				return;
			}
			if(((~s->bitb) >> 16) != (s->bitb & 0xffff))
			{
				s->mode = BAD;
				inflate_error = "Inflate data: Invalid stored block lengths";
				z->error = Z_DATA_ERROR;
				inflate_flush(z, s);
				return;
			}
			s->left = s->bitb & 0xffff;
			s->bitb = 0;
			s->bitk = 0;								// dump bits
			s->mode = s->left ? STORED : (s->last ? DRY : TYPE);
			break;
		case STORED:
			if(!z->avail_in)
			{
				inflate_flush(z, s);
				return;
			}
			bytesToEnd = needout(z, s, bytesToEnd);
			if(!bytesToEnd)
			{
				return;
			}
			t = s->left;
			if(t > z->avail_in) 
			{
				t = z->avail_in;
			}
			if(t > bytesToEnd) 
			{
				t = bytesToEnd;
			}
			memcpy(s->write, z->next_in, t);
			z->next_in += t;
			z->avail_in -= t;
			z->total_in += t;
			s->write += t;
			bytesToEnd -= t;
			s->left -= t;
			if(s->left)
			{
				break;
			}
			s->mode = s->last ? DRY : TYPE;
			break;
		case TABLE:
			if(!getbits(z, s, 14))
			{
				return;
			}
			t = s->bitb & 0x3fff;
			s->trees.table = t;
			if((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
			{
				s->mode = BAD;
				inflate_error = "Inflate data: Too many length or distance symbols";
				z->error = Z_DATA_ERROR;
				inflate_flush(z, s);
				return;
			}
			t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
			s->trees.blens = (ulong *)Z_Malloc(t * sizeof(ulong), TAG_INFLATE, qfalse);
			s->bitb >>= 14;
			s->bitk -= 14;
			s->trees.index = 0;
			s->mode = BTREE;
		case BTREE:
			while(s->trees.index < 4 + (s->trees.table >> 10))
			{
				if(!getbits(z, s, 3))
				{
					return;
				}
				s->trees.blens[border[s->trees.index++]] = s->bitb & 7;
				s->bitb >>= 3;
				s->bitk -= 3;
			}
			while(s->trees.index < 19)
			{
				s->trees.blens[border[s->trees.index++]] = 0;
			}
			s->trees.bb = 7;
			inflate_trees_bits(z, s->trees.blens, &s->trees.bb, &s->trees.tb, s->hufts);
			if(z->error != Z_OK)
			{
				Z_Free(s->trees.blens);
				s->mode = BAD;
				inflate_flush(z, s);
				return;
			}
			s->trees.index = 0;
			s->mode = DTREE;
		case DTREE:
			while(t = s->trees.table, s->trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))
			{
				inflate_huft_t *h;
				ulong i, j, c;

				t = s->trees.bb;
				if(!getbits(z, s, t))
				{
					return;
				}
				h = s->trees.tb + (s->bitb & inflate_mask[t]);
				t = h->Bits;
				c = h->base;
				if(c < 16)
				{
					s->bitb >>= t;
					s->bitk -= t;
					s->trees.blens[s->trees.index++] = c;
				}
				else	// c == 16..18
				{
					i = (c == 18) ? 7 : c - 14;
					j = (c == 18) ? 11 : 3;
					if(!getbits(z, s, t + i))
					{
						return;
					}
					s->bitb >>= t;
					s->bitk -= t;
					j += s->bitb & inflate_mask[i];
					s->bitb >>= i;
					s->bitk -= i;
					i = s->trees.index;
					t = s->trees.table;
					if(i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || (c == 16 && i < 1))
					{
						Z_Free(s->trees.blens);
						s->mode = BAD;
						inflate_error = "Inflate data: Invalid bit length repeat";
						z->error = Z_DATA_ERROR;
						inflate_flush(z, s);
						return;
					}
					c = (c == 16) ? s->trees.blens[i - 1] : 0;
					do
					{
						s->trees.blens[i++] = c;
					} while(--j);
					s->trees.index = i;
				}
			}
			s->trees.tb = NULL;

			bl = 9; 					// must be <= 9 for lookahead assumptions
			bd = 6; 					// must be <= 9 for lookahead assumptions
			t = s->trees.table;
			inflate_trees_dynamic(z, 257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), s->trees.blens, &bl, &bd, &lengthTree, &distTree, s->hufts);
			Z_Free(s->trees.blens);
			if(z->error != Z_OK)
			{
				s->mode = BAD;
				inflate_flush(z, s);
				return;
			}
			c = inflate_codes_new(z, bl, bd, lengthTree, distTree);
			s->decode.codes = c;
			s->mode = CODES;
		case CODES:
			inflate_codes(z, s);
			if(z->error != Z_STREAM_END)
			{
				inflate_flush(z, s);
				return;
			}
			z->error = Z_OK;
			Z_Free(s->decode.codes);
			bytesToEnd = s->write < s->read ? s->read - s->write - 1 : s->end - s->write; 
			if(!s->last)
			{
				s->mode = TYPE;
				break;
			}
			s->mode = DRY;
		case DRY:
			inflate_flush(z, s);
			bytesToEnd = s->write < s->read ? s->read - s->write - 1 : s->end - s->write;
			if(s->read != s->write)
			{
				inflate_error = "Inflate data: read != write in DRY";
				inflate_flush(z, s);
				return;
			}
			s->mode = DONE;
		case DONE:
			z->error = Z_STREAM_END;
			inflate_flush(z, s);
			return;
		case BAD:
		default:
			z->error = Z_DATA_ERROR;
			inflate_flush(z, s);
			return;
		}
	}
}

// -------------------------------------------------------------------------------------------------
// Controlling routines
// -------------------------------------------------------------------------------------------------

EStatus inflateEnd(z_stream *z)
{
	assert(z);

	if(z->istate->blocks)
	{
		inflate_blocks_free(z, z->istate->blocks);
		z->istate->blocks = NULL;
	}
	if(z->istate)
	{
		Z_Free(z->istate);
		z->istate = NULL;
	}
	return(Z_OK);
}

// ===============================================================================
// ===============================================================================

EStatus inflateInit(z_stream *z, EFlush flush, int noWrap)
{
	// initialize state
	assert(z);

	inflate_error = "OK";

	z->istate = (inflate_state *)Z_Malloc(sizeof(inflate_state), TAG_INFLATE, qtrue);
	z->istate->blocks = NULL;

	// handle nowrap option (no zlib header or check)
	z->istate->nowrap = noWrap;
	z->istate->wbits = MAX_WBITS;

	// create inflate_blocks state
	z->istate->blocks = inflate_blocks_new(z, NULL);

	z->status = Z_OK;
	if(flush == Z_FINISH)
	{
		z->status = Z_BUF_ERROR;
	}

	// reset state
	z->istate->mode = imMETHOD;
	if(z->istate->nowrap)
	{
		z->istate->mode = imBLOCKS;
	}
	inflate_blocks_reset(z, z->istate->blocks);
	return(Z_OK);
}

// ===============================================================================
// ===============================================================================

EStatus inflate(z_stream *z)
{
	ulong		b;

	// Sanity check data
	assert(z);
	assert(z->istate);

	while(true)
	{
		switch (z->istate->mode)
		{
		case imMETHOD:
			if(!z->avail_in)
			{
				return(z->status);
			}
			z->istate->method = *z->next_in++;
			z->avail_in--;
			z->total_in++;
			if((z->istate->method & 0xf) != ZF_DEFLATED)
			{
				z->istate->mode = imBAD;
				inflate_error = "Inflate data: Unknown compression method";
				return(Z_DATA_ERROR);
			}
			if((z->istate->method >> 4) + 8 > z->istate->wbits)
			{
				z->istate->mode = imBAD;
				inflate_error = "Inflate data: Invalid window size";
				return(Z_DATA_ERROR);
			}
			z->istate->mode = imFLAG;
			break;
		case imFLAG:
			if(!z->avail_in)
			{
				return(z->status);
			}
			b = *z->next_in++;
			z->avail_in--;
			z->total_in++;
			if(((z->istate->method << 8) + b) % 31)
			{
				z->istate->mode = imBAD;
				inflate_error = "Inflate data: Incorrect header check";
				return(Z_DATA_ERROR);
			}
			z->istate->mode = imBLOCKS;
			break;
		case imBLOCKS:
			inflate_blocks(z->istate->blocks, z);
			
			// Make sure everything processed ok
			if(z->error == Z_DATA_ERROR)
			{
				z->istate->mode = imBAD;
				return(Z_DATA_ERROR);
			}

			if(z->error != Z_STREAM_END)
			{
				return(z->status);
			}
			z->istate->calcadler = z->istate->adler;
			inflate_blocks_reset(z, z->istate->blocks);
			if(z->istate->nowrap)
			{
				z->istate->mode = imDONE;
				break;
			}
			z->istate->mode = imCHECK4;
			break;
		case imCHECK4:
			if(!z->avail_in)
			{
				return(z->status);
			}
			z->istate->adler = *z->next_in++ << 24;
			z->avail_in--;
			z->total_in++;
			z->istate->mode = imCHECK3;
			break;
		case imCHECK3:
			if(!z->avail_in)
			{
				return(z->status);
			}
			z->istate->adler += *z->next_in++ << 16;
			z->avail_in--;
			z->total_in++;
			z->istate->mode = imCHECK2;
			break;
		case imCHECK2:
			if(!z->avail_in)
			{
				return(z->status);
			}
			z->istate->adler += *z->next_in++ << 8;
			z->avail_in--;
			z->total_in++;
			z->istate->mode = imCHECK1;
			break;
		case imCHECK1:
			if(!z->avail_in)
			{
				return(z->status);
			}
			z->istate->adler += *z->next_in++;
			z->avail_in--;
			z->total_in++;

			if(z->istate->calcadler != z->istate->adler)
			{
				inflate_error = "Inflate data: Failed Adler checksum";
				z->istate->mode = imBAD;
				break;
			}
			z->istate->mode = imDONE;
			break;
		case imDONE:
			return(Z_STREAM_END);
		case imBAD:
			return(Z_DATA_ERROR);
		default:
			return(Z_STREAM_ERROR);
		}
	}
	assert(0);
	return(Z_OK);
}

// ===============================================================================
// ===============================================================================

const char *inflateError(void)
{
	return(inflate_error);
}

// ===============================================================================
// External calls
// ===============================================================================

bool InflateFile(byte *src, ulong compressedSize, byte *dst, ulong uncompressedSize, int noWrap)
{
	z_stream	z = { 0 };

	inflateInit(&z, Z_FINISH, noWrap);

	z.next_in = src;
	z.avail_in = compressedSize;
	z.next_out = dst;
	z.avail_out = uncompressedSize;

#ifdef _TIMING
	int temp = timeGetTime();
#endif
	if(inflate(&z) != Z_STREAM_END)
	{
		inflate_error = "Inflate data: Stream did not end";
		inflateEnd(&z);
		return(false);
	}
#ifdef _TIMING
	totalInflateTime += timeGetTime() - temp;
	totalInflateCount++;
#endif

	if(z.avail_in)
	{
		inflate_error = "Inflate data: Remaining input data at stream end";
		inflateEnd(&z);
		return(false);
	}
	if(z.avail_out)
	{
		inflate_error = "Inflate data: Remaining output space at stream end";
		inflateEnd(&z);
		return(false);
	}
	if(z.total_in != compressedSize)
	{
		inflate_error = "Inflate data: Number of processed bytes != compressed size";
		inflateEnd(&z);
		return(false);
	}
	if(z.total_out != uncompressedSize)
	{
		inflate_error = "Inflate data: Number of bytes output != uncompressed size";
		inflateEnd(&z);
		return(false);
	}
	inflateEnd(&z);
	return(true);
}

// end
