summaryrefslogtreecommitdiff
path: root/rbutil/rbutilqt/mspack/lzxd.c
diff options
context:
space:
mode:
Diffstat (limited to 'rbutil/rbutilqt/mspack/lzxd.c')
-rw-r--r--rbutil/rbutilqt/mspack/lzxd.c793
1 files changed, 480 insertions, 313 deletions
diff --git a/rbutil/rbutilqt/mspack/lzxd.c b/rbutil/rbutilqt/mspack/lzxd.c
index 9b26bac3e0..88cfd90c2a 100644
--- a/rbutil/rbutilqt/mspack/lzxd.c
+++ b/rbutil/rbutilqt/mspack/lzxd.c
@@ -1,5 +1,5 @@
1/* This file is part of libmspack. 1/* This file is part of libmspack.
2 * (C) 2003-2004 Stuart Caie. 2 * (C) 2003-2013 Stuart Caie.
3 * 3 *
4 * The LZX method was created by Jonathan Forbes and Tomi Poutanen, adapted 4 * The LZX method was created by Jonathan Forbes and Tomi Poutanen, adapted
5 * by Microsoft Corporation. 5 * by Microsoft Corporation.
@@ -70,6 +70,10 @@
70 * The maximum window size has increased from 2MB to 32MB. This also 70 * The maximum window size has increased from 2MB to 32MB. This also
71 * increases the maximum number of position slots, etc. 71 * increases the maximum number of position slots, etc.
72 * 72 *
73 * If the match length is 257 (the maximum possible), this signals
74 * a further length decoding step, that allows for matches up to
75 * 33024 bytes long.
76 *
73 * The format now allows for "reference data", supplied by the caller. 77 * The format now allows for "reference data", supplied by the caller.
74 * If match offsets go further back than the number of bytes 78 * If match offsets go further back than the number of bytes
75 * decompressed so far, that is them accessing the reference data. 79 * decompressed so far, that is them accessing the reference data.
@@ -79,11 +83,11 @@
79#define BITS_TYPE struct lzxd_stream 83#define BITS_TYPE struct lzxd_stream
80#define BITS_VAR lzx 84#define BITS_VAR lzx
81#define BITS_ORDER_MSB 85#define BITS_ORDER_MSB
82#define READ_BYTES do { \ 86#define READ_BYTES do { \
83 unsigned char b0, b1; \ 87 unsigned char b0, b1; \
84 READ_IF_NEEDED; b0 = *i_ptr++; \ 88 READ_IF_NEEDED; b0 = *i_ptr++; \
85 READ_IF_NEEDED; b1 = *i_ptr++; \ 89 READ_IF_NEEDED; b1 = *i_ptr++; \
86 INJECT_BITS((b1 << 8) | b0, 16); \ 90 INJECT_BITS((b1 << 8) | b0, 16); \
87} while (0) 91} while (0)
88#include "readbits.h" 92#include "readbits.h"
89 93
@@ -96,43 +100,43 @@
96#include "readhuff.h" 100#include "readhuff.h"
97 101
98/* BUILD_TABLE(tbl) builds a huffman lookup table from code lengths */ 102/* BUILD_TABLE(tbl) builds a huffman lookup table from code lengths */
99#define BUILD_TABLE(tbl) \ 103#define BUILD_TABLE(tbl) \
100 if (make_decode_table(MAXSYMBOLS(tbl), TABLEBITS(tbl), \ 104 if (make_decode_table(MAXSYMBOLS(tbl), TABLEBITS(tbl), \
101 &HUFF_LEN(tbl,0), &HUFF_TABLE(tbl,0))) \ 105 &HUFF_LEN(tbl,0), &HUFF_TABLE(tbl,0))) \
102 { \ 106 { \
103 D(("failed to build %s table", #tbl)) \ 107 D(("failed to build %s table", #tbl)) \
104 return lzx->error = MSPACK_ERR_DECRUNCH; \ 108 return lzx->error = MSPACK_ERR_DECRUNCH; \
105 } 109 }
106 110
107#define BUILD_TABLE_MAYBE_EMPTY(tbl) do { \ 111#define BUILD_TABLE_MAYBE_EMPTY(tbl) do { \
108 lzx->tbl##_empty = 0; \ 112 lzx->tbl##_empty = 0; \
109 if (make_decode_table(MAXSYMBOLS(tbl), TABLEBITS(tbl), \ 113 if (make_decode_table(MAXSYMBOLS(tbl), TABLEBITS(tbl), \
110 &HUFF_LEN(tbl,0), &HUFF_TABLE(tbl,0))) \ 114 &HUFF_LEN(tbl,0), &HUFF_TABLE(tbl,0))) \
111 { \ 115 { \
112 for (i = 0; i < MAXSYMBOLS(tbl); i++) { \ 116 for (i = 0; i < MAXSYMBOLS(tbl); i++) { \
113 if (HUFF_LEN(tbl, i) > 0) { \ 117 if (HUFF_LEN(tbl, i) > 0) { \
114 D(("failed to build %s table", #tbl)) \ 118 D(("failed to build %s table", #tbl)) \
115 return lzx->error = MSPACK_ERR_DECRUNCH; \ 119 return lzx->error = MSPACK_ERR_DECRUNCH; \
116 } \ 120 } \
117 } \ 121 } \
118 /* empty tree - allow it, but don't decode symbols with it */ \ 122 /* empty tree - allow it, but don't decode symbols with it */ \
119 lzx->tbl##_empty = 1; \ 123 lzx->tbl##_empty = 1; \
120 } \ 124 } \
121} while (0) 125} while (0)
122 126
123/* READ_LENGTHS(tablename, first, last) reads in code lengths for symbols 127/* READ_LENGTHS(tablename, first, last) reads in code lengths for symbols
124 * first to last in the given table. The code lengths are stored in their 128 * first to last in the given table. The code lengths are stored in their
125 * own special LZX way. 129 * own special LZX way.
126 */ 130 */
127#define READ_LENGTHS(tbl, first, last) do { \ 131#define READ_LENGTHS(tbl, first, last) do { \
128 STORE_BITS; \ 132 STORE_BITS; \
129 if (lzxd_read_lens(lzx, &HUFF_LEN(tbl, 0), (first), \ 133 if (lzxd_read_lens(lzx, &HUFF_LEN(tbl, 0), (first), \
130 (unsigned int)(last))) return lzx->error; \ 134 (unsigned int)(last))) return lzx->error; \
131 RESTORE_BITS; \ 135 RESTORE_BITS; \
132} while (0) 136} while (0)
133 137
134static int lzxd_read_lens(struct lzxd_stream *lzx, unsigned char *lens, 138static int lzxd_read_lens(struct lzxd_stream *lzx, unsigned char *lens,
135 unsigned int first, unsigned int last) 139 unsigned int first, unsigned int last)
136{ 140{
137 /* bit buffer and huffman symbol decode variables */ 141 /* bit buffer and huffman symbol decode variables */
138 register unsigned int bit_buffer; 142 register unsigned int bit_buffer;
@@ -189,27 +193,70 @@ static int lzxd_read_lens(struct lzxd_stream *lzx, unsigned char *lens,
189 * a small 'position slot' number and a small offset from that slot are 193 * a small 'position slot' number and a small offset from that slot are
190 * encoded instead of one large offset. 194 * encoded instead of one large offset.
191 * 195 *
196 * The number of slots is decided by how many are needed to encode the
197 * largest offset for a given window size. This is easy when the gap between
198 * slots is less than 128Kb, it's a linear relationship. But when extra_bits
199 * reaches its limit of 17 (because LZX can only ensure reading 17 bits of
200 * data at a time), we can only jump 128Kb at a time and have to start
201 * using more and more position slots as each window size doubles.
202 *
192 * position_base[] is an index to the position slot bases 203 * position_base[] is an index to the position slot bases
193 * 204 *
194 * extra_bits[] states how many bits of offset-from-base data is needed. 205 * extra_bits[] states how many bits of offset-from-base data is needed.
195 * 206 *
196 * They are generated like so: 207 * They are calculated as follows:
197 * for (i = 0; i < 4; i++) extra_bits[i] = 0; 208 * extra_bits[i] = 0 where i < 4
198 * for (i = 4, j = 0; i < 36; i+=2) extra_bits[i] = extra_bits[i+1] = j++; 209 * extra_bits[i] = floor(i/2)-1 where i >= 4 && i < 36
199 * for (i = 36; i < 51; i++) extra_bits[i] = 17; 210 * extra_bits[i] = 17 where i >= 36
200 * for (i = 0, j = 0; i < 51; j += 1 << extra_bits[i++]) position_base[i] = j; 211 * position_base[0] = 0
212 * position_base[i] = position_base[i-1] + (1 << extra_bits[i-1])
201 */ 213 */
202static const unsigned int position_base[51] = { 214static const unsigned int position_slots[11] = {
203 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192, 256, 215 30, 32, 34, 36, 38, 42, 50, 66, 98, 162, 290
204 384, 512, 768, 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 216};
205 16384, 24576, 32768, 49152, 65536, 98304, 131072, 196608, 262144, 217static const unsigned char extra_bits[36] = {
206 393216, 524288, 655360, 786432, 917504, 1048576, 1179648, 1310720, 218 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8,
207 1441792, 1572864, 1703936, 1835008, 1966080, 2097152 219 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16
208}; 220};
209static const unsigned char extra_bits[51] = { 221static const unsigned int position_base[290] = {
210 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 222 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192, 256, 384, 512,
211 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 223 768, 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576, 32768,
212 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17 224 49152, 65536, 98304, 131072, 196608, 262144, 393216, 524288, 655360,
225 786432, 917504, 1048576, 1179648, 1310720, 1441792, 1572864, 1703936,
226 1835008, 1966080, 2097152, 2228224, 2359296, 2490368, 2621440, 2752512,
227 2883584, 3014656, 3145728, 3276800, 3407872, 3538944, 3670016, 3801088,
228 3932160, 4063232, 4194304, 4325376, 4456448, 4587520, 4718592, 4849664,
229 4980736, 5111808, 5242880, 5373952, 5505024, 5636096, 5767168, 5898240,
230 6029312, 6160384, 6291456, 6422528, 6553600, 6684672, 6815744, 6946816,
231 7077888, 7208960, 7340032, 7471104, 7602176, 7733248, 7864320, 7995392,
232 8126464, 8257536, 8388608, 8519680, 8650752, 8781824, 8912896, 9043968,
233 9175040, 9306112, 9437184, 9568256, 9699328, 9830400, 9961472, 10092544,
234 10223616, 10354688, 10485760, 10616832, 10747904, 10878976, 11010048,
235 11141120, 11272192, 11403264, 11534336, 11665408, 11796480, 11927552,
236 12058624, 12189696, 12320768, 12451840, 12582912, 12713984, 12845056,
237 12976128, 13107200, 13238272, 13369344, 13500416, 13631488, 13762560,
238 13893632, 14024704, 14155776, 14286848, 14417920, 14548992, 14680064,
239 14811136, 14942208, 15073280, 15204352, 15335424, 15466496, 15597568,
240 15728640, 15859712, 15990784, 16121856, 16252928, 16384000, 16515072,
241 16646144, 16777216, 16908288, 17039360, 17170432, 17301504, 17432576,
242 17563648, 17694720, 17825792, 17956864, 18087936, 18219008, 18350080,
243 18481152, 18612224, 18743296, 18874368, 19005440, 19136512, 19267584,
244 19398656, 19529728, 19660800, 19791872, 19922944, 20054016, 20185088,
245 20316160, 20447232, 20578304, 20709376, 20840448, 20971520, 21102592,
246 21233664, 21364736, 21495808, 21626880, 21757952, 21889024, 22020096,
247 22151168, 22282240, 22413312, 22544384, 22675456, 22806528, 22937600,
248 23068672, 23199744, 23330816, 23461888, 23592960, 23724032, 23855104,
249 23986176, 24117248, 24248320, 24379392, 24510464, 24641536, 24772608,
250 24903680, 25034752, 25165824, 25296896, 25427968, 25559040, 25690112,
251 25821184, 25952256, 26083328, 26214400, 26345472, 26476544, 26607616,
252 26738688, 26869760, 27000832, 27131904, 27262976, 27394048, 27525120,
253 27656192, 27787264, 27918336, 28049408, 28180480, 28311552, 28442624,
254 28573696, 28704768, 28835840, 28966912, 29097984, 29229056, 29360128,
255 29491200, 29622272, 29753344, 29884416, 30015488, 30146560, 30277632,
256 30408704, 30539776, 30670848, 30801920, 30932992, 31064064, 31195136,
257 31326208, 31457280, 31588352, 31719424, 31850496, 31981568, 32112640,
258 32243712, 32374784, 32505856, 32636928, 32768000, 32899072, 33030144,
259 33161216, 33292288, 33423360
213}; 260};
214 261
215static void lzxd_reset_state(struct lzxd_stream *lzx) { 262static void lzxd_reset_state(struct lzxd_stream *lzx) {
@@ -230,23 +277,37 @@ static void lzxd_reset_state(struct lzxd_stream *lzx) {
230/*-------- main LZX code --------*/ 277/*-------- main LZX code --------*/
231 278
232struct lzxd_stream *lzxd_init(struct mspack_system *system, 279struct lzxd_stream *lzxd_init(struct mspack_system *system,
233 struct mspack_file *input, 280 struct mspack_file *input,
234 struct mspack_file *output, 281 struct mspack_file *output,
235 int window_bits, 282 int window_bits,
236 int reset_interval, 283 int reset_interval,
237 int input_buffer_size, 284 int input_buffer_size,
238 off_t output_length) 285 off_t output_length,
286 char is_delta)
239{ 287{
240 unsigned int window_size = 1 << window_bits; 288 unsigned int window_size = 1 << window_bits;
241 struct lzxd_stream *lzx; 289 struct lzxd_stream *lzx;
242 290
243 if (!system) return NULL; 291 if (!system) return NULL;
244 292
245 /* LZX supports window sizes of 2^15 (32Kb) through 2^21 (2Mb) */ 293 /* LZX DELTA window sizes are between 2^17 (128KiB) and 2^25 (32MiB),
246 if (window_bits < 15 || window_bits > 21) return NULL; 294 * regular LZX windows are between 2^15 (32KiB) and 2^21 (2MiB)
295 */
296 if (is_delta) {
297 if (window_bits < 17 || window_bits > 25) return NULL;
298 }
299 else {
300 if (window_bits < 15 || window_bits > 21) return NULL;
301 }
247 302
303 if (reset_interval < 0 || output_length < 0) {
304 D(("reset interval or output length < 0"))
305 return NULL;
306 }
307
308 /* round up input buffer size to multiple of two */
248 input_buffer_size = (input_buffer_size + 1) & -2; 309 input_buffer_size = (input_buffer_size + 1) & -2;
249 if (!input_buffer_size) return NULL; 310 if (input_buffer_size < 2) return NULL;
250 311
251 /* allocate decompression state */ 312 /* allocate decompression state */
252 if (!(lzx = (struct lzxd_stream *) system->alloc(system, sizeof(struct lzxd_stream)))) { 313 if (!(lzx = (struct lzxd_stream *) system->alloc(system, sizeof(struct lzxd_stream)))) {
@@ -272,6 +333,7 @@ struct lzxd_stream *lzxd_init(struct mspack_system *system,
272 333
273 lzx->inbuf_size = input_buffer_size; 334 lzx->inbuf_size = input_buffer_size;
274 lzx->window_size = 1 << window_bits; 335 lzx->window_size = 1 << window_bits;
336 lzx->ref_data_size = 0;
275 lzx->window_posn = 0; 337 lzx->window_posn = 0;
276 lzx->frame_posn = 0; 338 lzx->frame_posn = 0;
277 lzx->frame = 0; 339 lzx->frame = 0;
@@ -280,11 +342,8 @@ struct lzxd_stream *lzxd_init(struct mspack_system *system,
280 lzx->intel_curpos = 0; 342 lzx->intel_curpos = 0;
281 lzx->intel_started = 0; 343 lzx->intel_started = 0;
282 lzx->error = MSPACK_ERR_OK; 344 lzx->error = MSPACK_ERR_OK;
283 345 lzx->num_offsets = position_slots[window_bits - 15] << 3;
284 /* window bits: 15 16 17 18 19 20 21 346 lzx->is_delta = is_delta;
285 * position slots: 30 32 34 36 38 42 50 */
286 lzx->posn_slots = ((window_bits == 21) ? 50 :
287 ((window_bits == 20) ? 42 : (window_bits << 1)));
288 347
289 lzx->o_ptr = lzx->o_end = &lzx->e8_buf[0]; 348 lzx->o_ptr = lzx->o_end = &lzx->e8_buf[0];
290 lzxd_reset_state(lzx); 349 lzxd_reset_state(lzx);
@@ -292,8 +351,44 @@ struct lzxd_stream *lzxd_init(struct mspack_system *system,
292 return lzx; 351 return lzx;
293} 352}
294 353
354int lzxd_set_reference_data(struct lzxd_stream *lzx,
355 struct mspack_system *system,
356 struct mspack_file *input,
357 unsigned int length)
358{
359 if (!lzx) return MSPACK_ERR_ARGS;
360
361 if (!lzx->is_delta) {
362 D(("only LZX DELTA streams support reference data"))
363 return MSPACK_ERR_ARGS;
364 }
365 if (lzx->offset) {
366 D(("too late to set reference data after decoding starts"))
367 return MSPACK_ERR_ARGS;
368 }
369 if (length > lzx->window_size) {
370 D(("reference length (%u) is longer than the window", length))
371 return MSPACK_ERR_ARGS;
372 }
373 if (length > 0 && (!system || !input)) {
374 D(("length > 0 but no system or input"))
375 return MSPACK_ERR_ARGS;
376 }
377
378 lzx->ref_data_size = length;
379 if (length > 0) {
380 /* copy reference data */
381 unsigned char *pos = &lzx->window[lzx->window_size - length];
382 int bytes = system->read(input, pos, length);
383 /* length can't be more than 2^25, so no signedness problem */
384 if (bytes < (int)length) return MSPACK_ERR_READ;
385 }
386 lzx->ref_data_size = length;
387 return MSPACK_ERR_OK;
388}
389
295void lzxd_set_output_length(struct lzxd_stream *lzx, off_t out_bytes) { 390void lzxd_set_output_length(struct lzxd_stream *lzx, off_t out_bytes) {
296 if (lzx) lzx->length = out_bytes; 391 if (lzx && out_bytes > 0) lzx->length = out_bytes;
297} 392}
298 393
299int lzxd_decompress(struct lzxd_stream *lzx, off_t out_bytes) { 394int lzxd_decompress(struct lzxd_stream *lzx, off_t out_bytes) {
@@ -304,7 +399,7 @@ int lzxd_decompress(struct lzxd_stream *lzx, off_t out_bytes) {
304 register unsigned short sym; 399 register unsigned short sym;
305 400
306 int match_length, length_footer, extra, verbatim_bits, bytes_todo; 401 int match_length, length_footer, extra, verbatim_bits, bytes_todo;
307 int this_run, main_element, aligned_bits, j; 402 int this_run, main_element, aligned_bits, j, warned = 0;
308 unsigned char *window, *runsrc, *rundest, buf[12]; 403 unsigned char *window, *runsrc, *rundest, buf[12];
309 unsigned int frame_size=0, end_frame, match_offset, window_posn; 404 unsigned int frame_size=0, end_frame, match_offset, window_posn;
310 unsigned int R0, R1, R2; 405 unsigned int R0, R1, R2;
@@ -340,8 +435,12 @@ int lzxd_decompress(struct lzxd_stream *lzx, off_t out_bytes) {
340 /* have we reached the reset interval? (if there is one?) */ 435 /* have we reached the reset interval? (if there is one?) */
341 if (lzx->reset_interval && ((lzx->frame % lzx->reset_interval) == 0)) { 436 if (lzx->reset_interval && ((lzx->frame % lzx->reset_interval) == 0)) {
342 if (lzx->block_remaining) { 437 if (lzx->block_remaining) {
343 D(("%d bytes remaining at reset interval", lzx->block_remaining)) 438 /* this is a file format error, we can make a best effort to extract what we can */
344 return lzx->error = MSPACK_ERR_DECRUNCH; 439 D(("%d bytes remaining at reset interval", lzx->block_remaining))
440 if (!warned) {
441 lzx->sys->message(NULL, "WARNING; invalid reset interval detected during LZX decompression");
442 warned++;
443 }
345 } 444 }
346 445
347 /* re-read the intel header and reset the huffman lengths */ 446 /* re-read the intel header and reset the huffman lengths */
@@ -351,6 +450,12 @@ int lzxd_decompress(struct lzxd_stream *lzx, off_t out_bytes) {
351 R2 = lzx->R2; 450 R2 = lzx->R2;
352 } 451 }
353 452
453 /* LZX DELTA format has chunk_size, not present in LZX format */
454 if (lzx->is_delta) {
455 ENSURE_BITS(16);
456 REMOVE_BITS(16);
457 }
458
354 /* read header if necessary */ 459 /* read header if necessary */
355 if (!lzx->header_read) { 460 if (!lzx->header_read) {
356 /* read 1 bit. if bit=0, intel filesize = 0. 461 /* read 1 bit. if bit=0, intel filesize = 0.
@@ -373,62 +478,61 @@ int lzxd_decompress(struct lzxd_stream *lzx, off_t out_bytes) {
373 while (bytes_todo > 0) { 478 while (bytes_todo > 0) {
374 /* initialise new block, if one is needed */ 479 /* initialise new block, if one is needed */
375 if (lzx->block_remaining == 0) { 480 if (lzx->block_remaining == 0) {
376 /* realign if previous block was an odd-sized UNCOMPRESSED block */ 481 /* realign if previous block was an odd-sized UNCOMPRESSED block */
377 if ((lzx->block_type == LZX_BLOCKTYPE_UNCOMPRESSED) && 482 if ((lzx->block_type == LZX_BLOCKTYPE_UNCOMPRESSED) &&
378 (lzx->block_length & 1)) 483 (lzx->block_length & 1))
379 { 484 {
380 READ_IF_NEEDED; 485 READ_IF_NEEDED;
381 i_ptr++; 486 i_ptr++;
382 } 487 }
383 488
384 /* read block type (3 bits) and block length (24 bits) */ 489 /* read block type (3 bits) and block length (24 bits) */
385 READ_BITS(lzx->block_type, 3); 490 READ_BITS(lzx->block_type, 3);
386 READ_BITS(i, 16); READ_BITS(j, 8); 491 READ_BITS(i, 16); READ_BITS(j, 8);
387 lzx->block_remaining = lzx->block_length = (i << 8) | j; 492 lzx->block_remaining = lzx->block_length = (i << 8) | j;
388 /*D(("new block t%d len %u", lzx->block_type, lzx->block_length))*/ 493 /*D(("new block t%d len %u", lzx->block_type, lzx->block_length))*/
389 494
390 /* read individual block headers */ 495 /* read individual block headers */
391 switch (lzx->block_type) { 496 switch (lzx->block_type) {
392 case LZX_BLOCKTYPE_ALIGNED: 497 case LZX_BLOCKTYPE_ALIGNED:
393 /* read lengths of and build aligned huffman decoding tree */ 498 /* read lengths of and build aligned huffman decoding tree */
394 for (i = 0; i < 8; i++) { READ_BITS(j, 3); lzx->ALIGNED_len[i] = j; } 499 for (i = 0; i < 8; i++) { READ_BITS(j, 3); lzx->ALIGNED_len[i] = j; }
395 BUILD_TABLE(ALIGNED); 500 BUILD_TABLE(ALIGNED);
396 /* no break -- rest of aligned header is same as verbatim */ 501 /* rest of aligned header is same as verbatim */ /*@fallthrough@*/
397 case LZX_BLOCKTYPE_VERBATIM: 502 case LZX_BLOCKTYPE_VERBATIM:
398 /* read lengths of and build main huffman decoding tree */ 503 /* read lengths of and build main huffman decoding tree */
399 READ_LENGTHS(MAINTREE, 0, 256); 504 READ_LENGTHS(MAINTREE, 0, 256);
400 READ_LENGTHS(MAINTREE, 256, LZX_NUM_CHARS + (lzx->posn_slots << 3)); 505 READ_LENGTHS(MAINTREE, 256, LZX_NUM_CHARS + lzx->num_offsets);
401 BUILD_TABLE(MAINTREE); 506 BUILD_TABLE(MAINTREE);
402 /* if the literal 0xE8 is anywhere in the block... */ 507 /* if the literal 0xE8 is anywhere in the block... */
403 if (lzx->MAINTREE_len[0xE8] != 0) lzx->intel_started = 1; 508 if (lzx->MAINTREE_len[0xE8] != 0) lzx->intel_started = 1;
404 /* read lengths of and build lengths huffman decoding tree */ 509 /* read lengths of and build lengths huffman decoding tree */
405 READ_LENGTHS(LENGTH, 0, LZX_NUM_SECONDARY_LENGTHS); 510 READ_LENGTHS(LENGTH, 0, LZX_NUM_SECONDARY_LENGTHS);
406 BUILD_TABLE_MAYBE_EMPTY(LENGTH); 511 BUILD_TABLE_MAYBE_EMPTY(LENGTH);
407 break; 512 break;
408 513
409 case LZX_BLOCKTYPE_UNCOMPRESSED: 514 case LZX_BLOCKTYPE_UNCOMPRESSED:
410 /* because we can't assume otherwise */ 515 /* because we can't assume otherwise */
411 lzx->intel_started = 1; 516 lzx->intel_started = 1;
412 517
413 /* read 1-16 (not 0-15) bits to align to bytes */ 518 /* read 1-16 (not 0-15) bits to align to bytes */
414 ENSURE_BITS(16); 519 if (bits_left == 0) ENSURE_BITS(16);
415 if (bits_left > 16) i_ptr -= 2; 520 bits_left = 0; bit_buffer = 0;
416 bits_left = 0; bit_buffer = 0; 521
417 522 /* read 12 bytes of stored R0 / R1 / R2 values */
418 /* read 12 bytes of stored R0 / R1 / R2 values */ 523 for (rundest = &buf[0], i = 0; i < 12; i++) {
419 for (rundest = &buf[0], i = 0; i < 12; i++) { 524 READ_IF_NEEDED;
420 READ_IF_NEEDED; 525 *rundest++ = *i_ptr++;
421 *rundest++ = *i_ptr++; 526 }
422 } 527 R0 = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
423 R0 = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); 528 R1 = buf[4] | (buf[5] << 8) | (buf[6] << 16) | (buf[7] << 24);
424 R1 = buf[4] | (buf[5] << 8) | (buf[6] << 16) | (buf[7] << 24); 529 R2 = buf[8] | (buf[9] << 8) | (buf[10] << 16) | (buf[11] << 24);
425 R2 = buf[8] | (buf[9] << 8) | (buf[10] << 16) | (buf[11] << 24); 530 break;
426 break; 531
427 532 default:
428 default: 533 D(("bad block type"))
429 D(("bad block type")) 534 return lzx->error = MSPACK_ERR_DECRUNCH;
430 return lzx->error = MSPACK_ERR_DECRUNCH; 535 }
431 }
432 } 536 }
433 537
434 /* decode more of the block: 538 /* decode more of the block:
@@ -443,208 +547,270 @@ int lzxd_decompress(struct lzxd_stream *lzx, off_t out_bytes) {
443 /* decode at least this_run bytes */ 547 /* decode at least this_run bytes */
444 switch (lzx->block_type) { 548 switch (lzx->block_type) {
445 case LZX_BLOCKTYPE_VERBATIM: 549 case LZX_BLOCKTYPE_VERBATIM:
446 while (this_run > 0) { 550 while (this_run > 0) {
447 READ_HUFFSYM(MAINTREE, main_element); 551 READ_HUFFSYM(MAINTREE, main_element);
448 if (main_element < LZX_NUM_CHARS) { 552 if (main_element < LZX_NUM_CHARS) {
449 /* literal: 0 to LZX_NUM_CHARS-1 */ 553 /* literal: 0 to LZX_NUM_CHARS-1 */
450 window[window_posn++] = main_element; 554 window[window_posn++] = main_element;
451 this_run--; 555 this_run--;
452 } 556 }
453 else { 557 else {
454 /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */ 558 /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
455 main_element -= LZX_NUM_CHARS; 559 main_element -= LZX_NUM_CHARS;
456 560
457 /* get match length */ 561 /* get match length */
458 match_length = main_element & LZX_NUM_PRIMARY_LENGTHS; 562 match_length = main_element & LZX_NUM_PRIMARY_LENGTHS;
459 if (match_length == LZX_NUM_PRIMARY_LENGTHS) { 563 if (match_length == LZX_NUM_PRIMARY_LENGTHS) {
460 if (lzx->LENGTH_empty) { 564 if (lzx->LENGTH_empty) {
461 D(("LENGTH symbol needed but tree is empty")) 565 D(("LENGTH symbol needed but tree is empty"))
462 return lzx->error = MSPACK_ERR_DECRUNCH; 566 return lzx->error = MSPACK_ERR_DECRUNCH;
463 } 567 }
464 READ_HUFFSYM(LENGTH, length_footer); 568 READ_HUFFSYM(LENGTH, length_footer);
465 match_length += length_footer; 569 match_length += length_footer;
466 } 570 }
467 match_length += LZX_MIN_MATCH; 571 match_length += LZX_MIN_MATCH;
468 572
469 /* get match offset */ 573 /* get match offset */
470 switch ((match_offset = (main_element >> 3))) { 574 switch ((match_offset = (main_element >> 3))) {
471 case 0: match_offset = R0; break; 575 case 0: match_offset = R0; break;
472 case 1: match_offset = R1; R1=R0; R0 = match_offset; break; 576 case 1: match_offset = R1; R1=R0; R0 = match_offset; break;
473 case 2: match_offset = R2; R2=R0; R0 = match_offset; break; 577 case 2: match_offset = R2; R2=R0; R0 = match_offset; break;
474 case 3: match_offset = 1; R2=R1; R1=R0; R0 = match_offset; break; 578 case 3: match_offset = 1; R2=R1; R1=R0; R0 = match_offset; break;
475 default: 579 default:
476 extra = extra_bits[match_offset]; 580 extra = (match_offset >= 36) ? 17 : extra_bits[match_offset];
477 READ_BITS(verbatim_bits, extra); 581 READ_BITS(verbatim_bits, extra);
478 match_offset = position_base[match_offset] - 2 + verbatim_bits; 582 match_offset = position_base[match_offset] - 2 + verbatim_bits;
479 R2 = R1; R1 = R0; R0 = match_offset; 583 R2 = R1; R1 = R0; R0 = match_offset;
480 } 584 }
481 585
482 if ((window_posn + match_length) > lzx->window_size) { 586 /* LZX DELTA uses max match length to signal even longer match */
483 D(("match ran over window wrap")) 587 if (match_length == LZX_MAX_MATCH && lzx->is_delta) {
484 return lzx->error = MSPACK_ERR_DECRUNCH; 588 int extra_len = 0;
485 } 589 ENSURE_BITS(3); /* 4 entry huffman tree */
486 590 if (PEEK_BITS(1) == 0) {
487 /* copy match */ 591 REMOVE_BITS(1); /* '0' -> 8 extra length bits */
488 rundest = &window[window_posn]; 592 READ_BITS(extra_len, 8);
489 i = match_length; 593 }
490 /* does match offset wrap the window? */ 594 else if (PEEK_BITS(2) == 2) {
491 if (match_offset > window_posn) { 595 REMOVE_BITS(2); /* '10' -> 10 extra length bits + 0x100 */
492 /* j = length from match offset to end of window */ 596 READ_BITS(extra_len, 10);
493 j = match_offset - window_posn; 597 extra_len += 0x100;
494 if (j > (int) lzx->window_size) { 598 }
495 D(("match offset beyond window boundaries")) 599 else if (PEEK_BITS(3) == 6) {
496 return lzx->error = MSPACK_ERR_DECRUNCH; 600 REMOVE_BITS(3); /* '110' -> 12 extra length bits + 0x500 */
497 } 601 READ_BITS(extra_len, 12);
498 runsrc = &window[lzx->window_size - j]; 602 extra_len += 0x500;
499 if (j < i) { 603 }
500 /* if match goes over the window edge, do two copy runs */ 604 else {
501 i -= j; while (j-- > 0) *rundest++ = *runsrc++; 605 REMOVE_BITS(3); /* '111' -> 15 extra length bits */
502 runsrc = window; 606 READ_BITS(extra_len, 15);
503 } 607 }
504 while (i-- > 0) *rundest++ = *runsrc++; 608 match_length += extra_len;
505 } 609 }
506 else { 610
507 runsrc = rundest - match_offset; 611 if ((window_posn + match_length) > lzx->window_size) {
508 while (i-- > 0) *rundest++ = *runsrc++; 612 D(("match ran over window wrap"))
509 } 613 return lzx->error = MSPACK_ERR_DECRUNCH;
510 614 }
511 this_run -= match_length; 615
512 window_posn += match_length; 616 /* copy match */
513 } 617 rundest = &window[window_posn];
514 } /* while (this_run > 0) */ 618 i = match_length;
515 break; 619 /* does match offset wrap the window? */
620 if (match_offset > window_posn) {
621 if (match_offset > lzx->offset &&
622 (match_offset - window_posn) > lzx->ref_data_size)
623 {
624 D(("match offset beyond LZX stream"))
625 return lzx->error = MSPACK_ERR_DECRUNCH;
626 }
627 /* j = length from match offset to end of window */
628 j = match_offset - window_posn;
629 if (j > (int) lzx->window_size) {
630 D(("match offset beyond window boundaries"))
631 return lzx->error = MSPACK_ERR_DECRUNCH;
632 }
633 runsrc = &window[lzx->window_size - j];
634 if (j < i) {
635 /* if match goes over the window edge, do two copy runs */
636 i -= j; while (j-- > 0) *rundest++ = *runsrc++;
637 runsrc = window;
638 }
639 while (i-- > 0) *rundest++ = *runsrc++;
640 }
641 else {
642 runsrc = rundest - match_offset;
643 while (i-- > 0) *rundest++ = *runsrc++;
644 }
645
646 this_run -= match_length;
647 window_posn += match_length;
648 }
649 } /* while (this_run > 0) */
650 break;
516 651
517 case LZX_BLOCKTYPE_ALIGNED: 652 case LZX_BLOCKTYPE_ALIGNED:
518 while (this_run > 0) { 653 while (this_run > 0) {
519 READ_HUFFSYM(MAINTREE, main_element); 654 READ_HUFFSYM(MAINTREE, main_element);
520 if (main_element < LZX_NUM_CHARS) { 655 if (main_element < LZX_NUM_CHARS) {
521 /* literal: 0 to LZX_NUM_CHARS-1 */ 656 /* literal: 0 to LZX_NUM_CHARS-1 */
522 window[window_posn++] = main_element; 657 window[window_posn++] = main_element;
523 this_run--; 658 this_run--;
524 } 659 }
525 else { 660 else {
526 /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */ 661 /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
527 main_element -= LZX_NUM_CHARS; 662 main_element -= LZX_NUM_CHARS;
528 663
529 /* get match length */ 664 /* get match length */
530 match_length = main_element & LZX_NUM_PRIMARY_LENGTHS; 665 match_length = main_element & LZX_NUM_PRIMARY_LENGTHS;
531 if (match_length == LZX_NUM_PRIMARY_LENGTHS) { 666 if (match_length == LZX_NUM_PRIMARY_LENGTHS) {
532 if (lzx->LENGTH_empty) { 667 if (lzx->LENGTH_empty) {
533 D(("LENGTH symbol needed but tree is empty")) 668 D(("LENGTH symbol needed but tree is empty"))
534 return lzx->error = MSPACK_ERR_DECRUNCH; 669 return lzx->error = MSPACK_ERR_DECRUNCH;
535 } 670 }
536 READ_HUFFSYM(LENGTH, length_footer); 671 READ_HUFFSYM(LENGTH, length_footer);
537 match_length += length_footer; 672 match_length += length_footer;
538 } 673 }
539 match_length += LZX_MIN_MATCH; 674 match_length += LZX_MIN_MATCH;
540 675
541 /* get match offset */ 676 /* get match offset */
542 switch ((match_offset = (main_element >> 3))) { 677 switch ((match_offset = (main_element >> 3))) {
543 case 0: match_offset = R0; break; 678 case 0: match_offset = R0; break;
544 case 1: match_offset = R1; R1 = R0; R0 = match_offset; break; 679 case 1: match_offset = R1; R1 = R0; R0 = match_offset; break;
545 case 2: match_offset = R2; R2 = R0; R0 = match_offset; break; 680 case 2: match_offset = R2; R2 = R0; R0 = match_offset; break;
546 default: 681 default:
547 extra = extra_bits[match_offset]; 682 extra = (match_offset >= 36) ? 17 : extra_bits[match_offset];
548 match_offset = position_base[match_offset] - 2; 683 match_offset = position_base[match_offset] - 2;
549 if (extra > 3) { 684 if (extra > 3) {
550 /* verbatim and aligned bits */ 685 /* verbatim and aligned bits */
551 extra -= 3; 686 extra -= 3;
552 READ_BITS(verbatim_bits, extra); 687 READ_BITS(verbatim_bits, extra);
553 match_offset += (verbatim_bits << 3); 688 match_offset += (verbatim_bits << 3);
554 READ_HUFFSYM(ALIGNED, aligned_bits); 689 READ_HUFFSYM(ALIGNED, aligned_bits);
555 match_offset += aligned_bits; 690 match_offset += aligned_bits;
556 } 691 }
557 else if (extra == 3) { 692 else if (extra == 3) {
558 /* aligned bits only */ 693 /* aligned bits only */
559 READ_HUFFSYM(ALIGNED, aligned_bits); 694 READ_HUFFSYM(ALIGNED, aligned_bits);
560 match_offset += aligned_bits; 695 match_offset += aligned_bits;
561 } 696 }
562 else if (extra > 0) { /* extra==1, extra==2 */ 697 else if (extra > 0) { /* extra==1, extra==2 */
563 /* verbatim bits only */ 698 /* verbatim bits only */
564 READ_BITS(verbatim_bits, extra); 699 READ_BITS(verbatim_bits, extra);
565 match_offset += verbatim_bits; 700 match_offset += verbatim_bits;
566 } 701 }
567 else /* extra == 0 */ { 702 else /* extra == 0 */ {
568 /* ??? not defined in LZX specification! */ 703 /* ??? not defined in LZX specification! */
569 match_offset = 1; 704 match_offset = 1;
570 } 705 }
571 /* update repeated offset LRU queue */ 706 /* update repeated offset LRU queue */
572 R2 = R1; R1 = R0; R0 = match_offset; 707 R2 = R1; R1 = R0; R0 = match_offset;
573 } 708 }
574 709
575 if ((window_posn + match_length) > lzx->window_size) { 710 /* LZX DELTA uses max match length to signal even longer match */
576 D(("match ran over window wrap")) 711 if (match_length == LZX_MAX_MATCH && lzx->is_delta) {
577 return lzx->error = MSPACK_ERR_DECRUNCH; 712 int extra_len = 0;
578 } 713 ENSURE_BITS(3); /* 4 entry huffman tree */
579 714 if (PEEK_BITS(1) == 0) {
580 /* copy match */ 715 REMOVE_BITS(1); /* '0' -> 8 extra length bits */
581 rundest = &window[window_posn]; 716 READ_BITS(extra_len, 8);
582 i = match_length; 717 }
583 /* does match offset wrap the window? */ 718 else if (PEEK_BITS(2) == 2) {
584 if (match_offset > window_posn) { 719 REMOVE_BITS(2); /* '10' -> 10 extra length bits + 0x100 */
585 /* j = length from match offset to end of window */ 720 READ_BITS(extra_len, 10);
586 j = match_offset - window_posn; 721 extra_len += 0x100;
587 if (j > (int) lzx->window_size) { 722 }
588 D(("match offset beyond window boundaries")) 723 else if (PEEK_BITS(3) == 6) {
589 return lzx->error = MSPACK_ERR_DECRUNCH; 724 REMOVE_BITS(3); /* '110' -> 12 extra length bits + 0x500 */
590 } 725 READ_BITS(extra_len, 12);
591 runsrc = &window[lzx->window_size - j]; 726 extra_len += 0x500;
592 if (j < i) { 727 }
593 /* if match goes over the window edge, do two copy runs */ 728 else {
594 i -= j; while (j-- > 0) *rundest++ = *runsrc++; 729 REMOVE_BITS(3); /* '111' -> 15 extra length bits */
595 runsrc = window; 730 READ_BITS(extra_len, 15);
596 } 731 }
597 while (i-- > 0) *rundest++ = *runsrc++; 732 match_length += extra_len;
598 } 733 }
599 else { 734
600 runsrc = rundest - match_offset; 735 if ((window_posn + match_length) > lzx->window_size) {
601 while (i-- > 0) *rundest++ = *runsrc++; 736 D(("match ran over window wrap"))
602 } 737 return lzx->error = MSPACK_ERR_DECRUNCH;
603 738 }
604 this_run -= match_length; 739
605 window_posn += match_length; 740 /* copy match */
606 } 741 rundest = &window[window_posn];
607 } /* while (this_run > 0) */ 742 i = match_length;
608 break; 743 /* does match offset wrap the window? */
744 if (match_offset > window_posn) {
745 if (match_offset > lzx->offset &&
746 (match_offset - window_posn) > lzx->ref_data_size)
747 {
748 D(("match offset beyond LZX stream"))
749 return lzx->error = MSPACK_ERR_DECRUNCH;
750 }
751 /* j = length from match offset to end of window */
752 j = match_offset - window_posn;
753 if (j > (int) lzx->window_size) {
754 D(("match offset beyond window boundaries"))
755 return lzx->error = MSPACK_ERR_DECRUNCH;
756 }
757 runsrc = &window[lzx->window_size - j];
758 if (j < i) {
759 /* if match goes over the window edge, do two copy runs */
760 i -= j; while (j-- > 0) *rundest++ = *runsrc++;
761 runsrc = window;
762 }
763 while (i-- > 0) *rundest++ = *runsrc++;
764 }
765 else {
766 runsrc = rundest - match_offset;
767 while (i-- > 0) *rundest++ = *runsrc++;
768 }
769
770 this_run -= match_length;
771 window_posn += match_length;
772 }
773 } /* while (this_run > 0) */
774 break;
609 775
610 case LZX_BLOCKTYPE_UNCOMPRESSED: 776 case LZX_BLOCKTYPE_UNCOMPRESSED:
611 /* as this_run is limited not to wrap a frame, this also means it 777 /* as this_run is limited not to wrap a frame, this also means it
612 * won't wrap the window (as the window is a multiple of 32k) */ 778 * won't wrap the window (as the window is a multiple of 32k) */
613 rundest = &window[window_posn]; 779 rundest = &window[window_posn];
614 window_posn += this_run; 780 window_posn += this_run;
615 while (this_run > 0) { 781 while (this_run > 0) {
616 if ((i = i_end - i_ptr) == 0) { 782 if ((i = i_end - i_ptr) == 0) {
617 READ_IF_NEEDED; 783 READ_IF_NEEDED;
618 } 784 }
619 else { 785 else {
620 if (i > this_run) i = this_run; 786 if (i > this_run) i = this_run;
621 lzx->sys->copy(i_ptr, rundest, (size_t) i); 787 lzx->sys->copy(i_ptr, rundest, (size_t) i);
622 rundest += i; 788 rundest += i;
623 i_ptr += i; 789 i_ptr += i;
624 this_run -= i; 790 this_run -= i;
625 } 791 }
626 } 792 }
627 break; 793 break;
628 794
629 default: 795 default:
630 return lzx->error = MSPACK_ERR_DECRUNCH; /* might as well */ 796 return lzx->error = MSPACK_ERR_DECRUNCH; /* might as well */
631 } 797 }
632 798
633 /* did the final match overrun our desired this_run length? */ 799 /* did the final match overrun our desired this_run length? */
634 if (this_run < 0) { 800 if (this_run < 0) {
635 if ((unsigned int)(-this_run) > lzx->block_remaining) { 801 if ((unsigned int)(-this_run) > lzx->block_remaining) {
636 D(("overrun went past end of block by %d (%d remaining)", 802 D(("overrun went past end of block by %d (%d remaining)",
637 -this_run, lzx->block_remaining )) 803 -this_run, lzx->block_remaining ))
638 return lzx->error = MSPACK_ERR_DECRUNCH; 804 return lzx->error = MSPACK_ERR_DECRUNCH;
639 } 805 }
640 lzx->block_remaining -= -this_run; 806 lzx->block_remaining -= -this_run;
641 } 807 }
642 } /* while (bytes_todo > 0) */ 808 } /* while (bytes_todo > 0) */
643 809
644 /* streams don't extend over frame boundaries */ 810 /* streams don't extend over frame boundaries */
645 if ((window_posn - lzx->frame_posn) != frame_size) { 811 if ((window_posn - lzx->frame_posn) != frame_size) {
646 D(("decode beyond output frame limits! %d != %d", 812 D(("decode beyond output frame limits! %d != %d",
647 window_posn - lzx->frame_posn, frame_size)) 813 window_posn - lzx->frame_posn, frame_size))
648 return lzx->error = MSPACK_ERR_DECRUNCH; 814 return lzx->error = MSPACK_ERR_DECRUNCH;
649 } 815 }
650 816
@@ -654,13 +820,14 @@ int lzxd_decompress(struct lzxd_stream *lzx, off_t out_bytes) {
654 820
655 /* check that we've used all of the previous frame first */ 821 /* check that we've used all of the previous frame first */
656 if (lzx->o_ptr != lzx->o_end) { 822 if (lzx->o_ptr != lzx->o_end) {
657 D(("%ld avail bytes, new %d frame", lzx->o_end-lzx->o_ptr, frame_size)) 823 D(("%ld avail bytes, new %d frame",
824 (long)(lzx->o_end - lzx->o_ptr), frame_size))
658 return lzx->error = MSPACK_ERR_DECRUNCH; 825 return lzx->error = MSPACK_ERR_DECRUNCH;
659 } 826 }
660 827
661 /* does this intel block _really_ need decoding? */ 828 /* does this intel block _really_ need decoding? */
662 if (lzx->intel_started && lzx->intel_filesize && 829 if (lzx->intel_started && lzx->intel_filesize &&
663 (lzx->frame <= 32768) && (frame_size > 10)) 830 (lzx->frame <= 32768) && (frame_size > 10))
664 { 831 {
665 unsigned char *data = &lzx->e8_buf[0]; 832 unsigned char *data = &lzx->e8_buf[0];
666 unsigned char *dataend = &lzx->e8_buf[frame_size - 10]; 833 unsigned char *dataend = &lzx->e8_buf[frame_size - 10];
@@ -673,17 +840,17 @@ int lzxd_decompress(struct lzxd_stream *lzx, off_t out_bytes) {
673 lzx->sys->copy(&lzx->window[lzx->frame_posn], data, frame_size); 840 lzx->sys->copy(&lzx->window[lzx->frame_posn], data, frame_size);
674 841
675 while (data < dataend) { 842 while (data < dataend) {
676 if (*data++ != 0xE8) { curpos++; continue; } 843 if (*data++ != 0xE8) { curpos++; continue; }
677 abs_off = data[0] | (data[1]<<8) | (data[2]<<16) | (data[3]<<24); 844 abs_off = data[0] | (data[1]<<8) | (data[2]<<16) | (data[3]<<24);
678 if ((abs_off >= -curpos) && (abs_off < filesize)) { 845 if ((abs_off >= -curpos) && (abs_off < filesize)) {
679 rel_off = (abs_off >= 0) ? abs_off - curpos : abs_off + filesize; 846 rel_off = (abs_off >= 0) ? abs_off - curpos : abs_off + filesize;
680 data[0] = (unsigned char) rel_off; 847 data[0] = (unsigned char) rel_off;
681 data[1] = (unsigned char) (rel_off >> 8); 848 data[1] = (unsigned char) (rel_off >> 8);
682 data[2] = (unsigned char) (rel_off >> 16); 849 data[2] = (unsigned char) (rel_off >> 16);
683 data[3] = (unsigned char) (rel_off >> 24); 850 data[3] = (unsigned char) (rel_off >> 24);
684 } 851 }
685 data += 4; 852 data += 4;
686 curpos += 5; 853 curpos += 5;
687 } 854 }
688 lzx->intel_curpos += frame_size; 855 lzx->intel_curpos += frame_size;
689 } 856 }