summaryrefslogtreecommitdiff
path: root/rbutil/rbutilqt/mspack/kwajd.c
diff options
context:
space:
mode:
Diffstat (limited to 'rbutil/rbutilqt/mspack/kwajd.c')
-rw-r--r--rbutil/rbutilqt/mspack/kwajd.c365
1 files changed, 188 insertions, 177 deletions
diff --git a/rbutil/rbutilqt/mspack/kwajd.c b/rbutil/rbutilqt/mspack/kwajd.c
index 440f1dcfdd..24e0b0613b 100644
--- a/rbutil/rbutilqt/mspack/kwajd.c
+++ b/rbutil/rbutilqt/mspack/kwajd.c
@@ -1,5 +1,5 @@
1/* This file is part of libmspack. 1/* This file is part of libmspack.
2 * (C) 2003-2010 Stuart Caie. 2 * (C) 2003-2011 Stuart Caie.
3 * 3 *
4 * KWAJ is a format very similar to SZDD. KWAJ method 3 (LZH) was 4 * KWAJ is a format very similar to SZDD. KWAJ method 3 (LZH) was
5 * written by Jeff Johnson. 5 * written by Jeff Johnson.
@@ -14,6 +14,7 @@
14 14
15#include "system-mspack.h" 15#include "system-mspack.h"
16#include "kwaj.h" 16#include "kwaj.h"
17#include "mszip.h"
17 18
18/* prototypes */ 19/* prototypes */
19static struct mskwajd_header *kwajd_open( 20static struct mskwajd_header *kwajd_open(
@@ -40,7 +41,7 @@ static void lzh_free(
40static int lzh_read_lens( 41static int lzh_read_lens(
41 struct kwajd_stream *kwaj, 42 struct kwajd_stream *kwaj,
42 unsigned int type, unsigned int numsyms, 43 unsigned int type, unsigned int numsyms,
43 unsigned char *lens, unsigned short *table); 44 unsigned char *lens);
44static int lzh_read_input( 45static int lzh_read_input(
45 struct kwajd_stream *kwaj); 46 struct kwajd_stream *kwaj);
46 47
@@ -79,8 +80,8 @@ void mspack_destroy_kwaj_decompressor(struct mskwaj_decompressor *base)
79{ 80{
80 struct mskwaj_decompressor_p *self = (struct mskwaj_decompressor_p *) base; 81 struct mskwaj_decompressor_p *self = (struct mskwaj_decompressor_p *) base;
81 if (self) { 82 if (self) {
82 struct mspack_system *sys = self->system; 83 struct mspack_system *sys = self->system;
83 sys->free(self); 84 sys->free(self);
84 } 85 }
85} 86}
86 87
@@ -90,7 +91,7 @@ void mspack_destroy_kwaj_decompressor(struct mskwaj_decompressor *base)
90 * opens a KWAJ file without decompressing, reads header 91 * opens a KWAJ file without decompressing, reads header
91 */ 92 */
92static struct mskwajd_header *kwajd_open(struct mskwaj_decompressor *base, 93static struct mskwajd_header *kwajd_open(struct mskwaj_decompressor *base,
93 const char *filename) 94 const char *filename)
94{ 95{
95 struct mskwaj_decompressor_p *self = (struct mskwaj_decompressor_p *) base; 96 struct mskwaj_decompressor_p *self = (struct mskwaj_decompressor_p *) base;
96 struct mskwajd_header *hdr; 97 struct mskwajd_header *hdr;
@@ -103,18 +104,18 @@ static struct mskwajd_header *kwajd_open(struct mskwaj_decompressor *base,
103 fh = sys->open(sys, filename, MSPACK_SYS_OPEN_READ); 104 fh = sys->open(sys, filename, MSPACK_SYS_OPEN_READ);
104 hdr = (struct mskwajd_header *) sys->alloc(sys, sizeof(struct mskwajd_header_p)); 105 hdr = (struct mskwajd_header *) sys->alloc(sys, sizeof(struct mskwajd_header_p));
105 if (fh && hdr) { 106 if (fh && hdr) {
106 ((struct mskwajd_header_p *) hdr)->fh = fh; 107 ((struct mskwajd_header_p *) hdr)->fh = fh;
107 self->error = kwajd_read_headers(sys, fh, hdr); 108 self->error = kwajd_read_headers(sys, fh, hdr);
108 } 109 }
109 else { 110 else {
110 if (!fh) self->error = MSPACK_ERR_OPEN; 111 if (!fh) self->error = MSPACK_ERR_OPEN;
111 if (!hdr) self->error = MSPACK_ERR_NOMEMORY; 112 if (!hdr) self->error = MSPACK_ERR_NOMEMORY;
112 } 113 }
113 114
114 if (self->error) { 115 if (self->error) {
115 if (fh) sys->close(fh); 116 if (fh) sys->close(fh);
116 if (hdr) sys->free(hdr); 117 sys->free(hdr);
117 hdr = NULL; 118 hdr = NULL;
118 } 119 }
119 120
120 return hdr; 121 return hdr;
@@ -126,7 +127,7 @@ static struct mskwajd_header *kwajd_open(struct mskwaj_decompressor *base,
126 * closes a KWAJ file 127 * closes a KWAJ file
127 */ 128 */
128static void kwajd_close(struct mskwaj_decompressor *base, 129static void kwajd_close(struct mskwaj_decompressor *base,
129 struct mskwajd_header *hdr) 130 struct mskwajd_header *hdr)
130{ 131{
131 struct mskwaj_decompressor_p *self = (struct mskwaj_decompressor_p *) base; 132 struct mskwaj_decompressor_p *self = (struct mskwaj_decompressor_p *) base;
132 struct mskwajd_header_p *hdr_p = (struct mskwajd_header_p *) hdr; 133 struct mskwajd_header_p *hdr_p = (struct mskwajd_header_p *) hdr;
@@ -148,22 +149,22 @@ static void kwajd_close(struct mskwaj_decompressor *base,
148 * reads the headers of a KWAJ format file 149 * reads the headers of a KWAJ format file
149 */ 150 */
150static int kwajd_read_headers(struct mspack_system *sys, 151static int kwajd_read_headers(struct mspack_system *sys,
151 struct mspack_file *fh, 152 struct mspack_file *fh,
152 struct mskwajd_header *hdr) 153 struct mskwajd_header *hdr)
153{ 154{
154 unsigned char buf[16]; 155 unsigned char buf[16];
155 int i; 156 int i;
156 157
157 /* read in the header */ 158 /* read in the header */
158 if (sys->read(fh, &buf[0], kwajh_SIZEOF) != kwajh_SIZEOF) { 159 if (sys->read(fh, &buf[0], kwajh_SIZEOF) != kwajh_SIZEOF) {
159 return MSPACK_ERR_READ; 160 return MSPACK_ERR_READ;
160 } 161 }
161 162
162 /* check for "KWAJ" signature */ 163 /* check for "KWAJ" signature */
163 if (((unsigned int) EndGetI32(&buf[kwajh_Signature1]) != 0x4A41574B) || 164 if (((unsigned int) EndGetI32(&buf[kwajh_Signature1]) != 0x4A41574B) ||
164 ((unsigned int) EndGetI32(&buf[kwajh_Signature2]) != 0xD127F088)) 165 ((unsigned int) EndGetI32(&buf[kwajh_Signature2]) != 0xD127F088))
165 { 166 {
166 return MSPACK_ERR_SIGNATURE; 167 return MSPACK_ERR_SIGNATURE;
167 } 168 }
168 169
169 /* basic header fields */ 170 /* basic header fields */
@@ -179,61 +180,67 @@ static int kwajd_read_headers(struct mspack_system *sys,
179 180
180 /* 4 bytes: length of unpacked file */ 181 /* 4 bytes: length of unpacked file */
181 if (hdr->headers & MSKWAJ_HDR_HASLENGTH) { 182 if (hdr->headers & MSKWAJ_HDR_HASLENGTH) {
182 if (sys->read(fh, &buf[0], 4) != 4) return MSPACK_ERR_READ; 183 if (sys->read(fh, &buf[0], 4) != 4) return MSPACK_ERR_READ;
183 hdr->length = EndGetI32(&buf[0]); 184 hdr->length = EndGetI32(&buf[0]);
184 } 185 }
185 186
186 /* 2 bytes: unknown purpose */ 187 /* 2 bytes: unknown purpose */
187 if (hdr->headers & MSKWAJ_HDR_HASUNKNOWN1) { 188 if (hdr->headers & MSKWAJ_HDR_HASUNKNOWN1) {
188 if (sys->read(fh, &buf[0], 2) != 2) return MSPACK_ERR_READ; 189 if (sys->read(fh, &buf[0], 2) != 2) return MSPACK_ERR_READ;
189 } 190 }
190 191
191 /* 2 bytes: length of section, then [length] bytes: unknown purpose */ 192 /* 2 bytes: length of section, then [length] bytes: unknown purpose */
192 if (hdr->headers & MSKWAJ_HDR_HASUNKNOWN2) { 193 if (hdr->headers & MSKWAJ_HDR_HASUNKNOWN2) {
193 if (sys->read(fh, &buf[0], 2) != 2) return MSPACK_ERR_READ; 194 if (sys->read(fh, &buf[0], 2) != 2) return MSPACK_ERR_READ;
194 i = EndGetI16(&buf[0]); 195 i = EndGetI16(&buf[0]);
195 if (sys->seek(fh, (off_t)i, MSPACK_SYS_SEEK_CUR)) return MSPACK_ERR_SEEK; 196 if (sys->seek(fh, (off_t)i, MSPACK_SYS_SEEK_CUR)) return MSPACK_ERR_SEEK;
196 } 197 }
197 198
198 /* filename and extension */ 199 /* filename and extension */
199 if (hdr->headers & (MSKWAJ_HDR_HASFILENAME | MSKWAJ_HDR_HASFILEEXT)) { 200 if (hdr->headers & (MSKWAJ_HDR_HASFILENAME | MSKWAJ_HDR_HASFILEEXT)) {
200 off_t pos = sys->tell(fh); 201 int len;
201 char *fn = (char *) sys->alloc(sys, (size_t) 13); 202 /* allocate memory for maximum length filename */
202 203 char *fn = (char *) sys->alloc(sys, (size_t) 13);
203 /* allocate memory for maximum length filename */ 204 if (!(hdr->filename = fn)) return MSPACK_ERR_NOMEMORY;
204 if (! fn) return MSPACK_ERR_NOMEMORY; 205
205 hdr->filename = fn; 206 /* copy filename if present */
206 207 if (hdr->headers & MSKWAJ_HDR_HASFILENAME) {
207 /* copy filename if present */ 208 /* read and copy up to 9 bytes of a null terminated string */
208 if (hdr->headers & MSKWAJ_HDR_HASFILENAME) { 209 if ((len = sys->read(fh, &buf[0], 9)) < 2) return MSPACK_ERR_READ;
209 if (sys->read(fh, &buf[0], 9) != 9) return MSPACK_ERR_READ; 210 for (i = 0; i < len; i++) if (!(*fn++ = buf[i])) break;
210 for (i = 0; i < 9; i++, fn++) if (!(*fn = buf[i])) break; 211 /* if string was 9 bytes with no null terminator, reject it */
211 pos += (i < 9) ? i+1 : 9; 212 if (i == 9 && buf[8] != '\0') return MSPACK_ERR_DATAFORMAT;
212 if (sys->seek(fh, pos, MSPACK_SYS_SEEK_START)) 213 /* seek to byte after string ended in file */
213 return MSPACK_ERR_SEEK; 214 if (sys->seek(fh, (off_t)(i + 1 - len), MSPACK_SYS_SEEK_CUR))
214 } 215 return MSPACK_ERR_SEEK;
215 216 fn--; /* remove the null terminator */
216 /* copy extension if present */ 217 }
217 if (hdr->headers & MSKWAJ_HDR_HASFILEEXT) { 218
218 *fn++ = '.'; 219 /* copy extension if present */
219 if (sys->read(fh, &buf[0], 4) != 4) return MSPACK_ERR_READ; 220 if (hdr->headers & MSKWAJ_HDR_HASFILEEXT) {
220 for (i = 0; i < 4; i++, fn++) if (!(*fn = buf[i])) break; 221 *fn++ = '.';
221 pos += (i < 4) ? i+1 : 4; 222 /* read and copy up to 4 bytes of a null terminated string */
222 if (sys->seek(fh, pos, MSPACK_SYS_SEEK_START)) 223 if ((len = sys->read(fh, &buf[0], 4)) < 2) return MSPACK_ERR_READ;
223 return MSPACK_ERR_SEEK; 224 for (i = 0; i < len; i++) if (!(*fn++ = buf[i])) break;
224 } 225 /* if string was 4 bytes with no null terminator, reject it */
225 *fn = '\0'; 226 if (i == 4 && buf[3] != '\0') return MSPACK_ERR_DATAFORMAT;
227 /* seek to byte after string ended in file */
228 if (sys->seek(fh, (off_t)(i + 1 - len), MSPACK_SYS_SEEK_CUR))
229 return MSPACK_ERR_SEEK;
230 fn--; /* remove the null terminator */
231 }
232 *fn = '\0';
226 } 233 }
227 234
228 /* 2 bytes: extra text length then [length] bytes of extra text data */ 235 /* 2 bytes: extra text length then [length] bytes of extra text data */
229 if (hdr->headers & MSKWAJ_HDR_HASEXTRATEXT) { 236 if (hdr->headers & MSKWAJ_HDR_HASEXTRATEXT) {
230 if (sys->read(fh, &buf[0], 2) != 2) return MSPACK_ERR_READ; 237 if (sys->read(fh, &buf[0], 2) != 2) return MSPACK_ERR_READ;
231 i = EndGetI16(&buf[0]); 238 i = EndGetI16(&buf[0]);
232 hdr->extra = (char *) sys->alloc(sys, (size_t)i+1); 239 hdr->extra = (char *) sys->alloc(sys, (size_t)i+1);
233 if (! hdr->extra) return MSPACK_ERR_NOMEMORY; 240 if (! hdr->extra) return MSPACK_ERR_NOMEMORY;
234 if (sys->read(fh, hdr->extra, i) != i) return MSPACK_ERR_READ; 241 if (sys->read(fh, hdr->extra, i) != i) return MSPACK_ERR_READ;
235 hdr->extra[i] = '\0'; 242 hdr->extra[i] = '\0';
236 hdr->extra_length = i; 243 hdr->extra_length = i;
237 } 244 }
238 return MSPACK_ERR_OK; 245 return MSPACK_ERR_OK;
239} 246}
@@ -244,7 +251,7 @@ static int kwajd_read_headers(struct mspack_system *sys,
244 * decompresses a KWAJ file 251 * decompresses a KWAJ file
245 */ 252 */
246static int kwajd_extract(struct mskwaj_decompressor *base, 253static int kwajd_extract(struct mskwaj_decompressor *base,
247 struct mskwajd_header *hdr, const char *filename) 254 struct mskwajd_header *hdr, const char *filename)
248{ 255{
249 struct mskwaj_decompressor_p *self = (struct mskwaj_decompressor_p *) base; 256 struct mskwaj_decompressor_p *self = (struct mskwaj_decompressor_p *) base;
250 struct mspack_system *sys; 257 struct mspack_system *sys;
@@ -258,51 +265,56 @@ static int kwajd_extract(struct mskwaj_decompressor *base,
258 265
259 /* seek to the compressed data */ 266 /* seek to the compressed data */
260 if (sys->seek(fh, hdr->data_offset, MSPACK_SYS_SEEK_START)) { 267 if (sys->seek(fh, hdr->data_offset, MSPACK_SYS_SEEK_START)) {
261 return self->error = MSPACK_ERR_SEEK; 268 return self->error = MSPACK_ERR_SEEK;
262 } 269 }
263 270
264 /* open file for output */ 271 /* open file for output */
265 if (!(outfh = sys->open(sys, filename, MSPACK_SYS_OPEN_WRITE))) { 272 if (!(outfh = sys->open(sys, filename, MSPACK_SYS_OPEN_WRITE))) {
266 return self->error = MSPACK_ERR_OPEN; 273 return self->error = MSPACK_ERR_OPEN;
267 } 274 }
268 275
269 self->error = MSPACK_ERR_OK; 276 self->error = MSPACK_ERR_OK;
270 277
271 /* decompress based on format */ 278 /* decompress based on format */
272 if (hdr->comp_type == MSKWAJ_COMP_NONE || 279 if (hdr->comp_type == MSKWAJ_COMP_NONE ||
273 hdr->comp_type == MSKWAJ_COMP_XOR) 280 hdr->comp_type == MSKWAJ_COMP_XOR)
274 { 281 {
275 /* NONE is a straight copy. XOR is a copy xored with 0xFF */ 282 /* NONE is a straight copy. XOR is a copy xored with 0xFF */
276 unsigned char *buf = (unsigned char *) sys->alloc(sys, (size_t) KWAJ_INPUT_SIZE); 283 unsigned char *buf = (unsigned char *) sys->alloc(sys, (size_t) KWAJ_INPUT_SIZE);
277 if (buf) { 284 if (buf) {
278 int read, i; 285 int read, i;
279 while ((read = sys->read(fh, buf, KWAJ_INPUT_SIZE)) > 0) { 286 while ((read = sys->read(fh, buf, KWAJ_INPUT_SIZE)) > 0) {
280 if (hdr->comp_type == MSKWAJ_COMP_XOR) { 287 if (hdr->comp_type == MSKWAJ_COMP_XOR) {
281 for (i = 0; i < read; i++) buf[i] ^= 0xFF; 288 for (i = 0; i < read; i++) buf[i] ^= 0xFF;
282 } 289 }
283 if (sys->write(outfh, buf, read) != read) { 290 if (sys->write(outfh, buf, read) != read) {
284 self->error = MSPACK_ERR_WRITE; 291 self->error = MSPACK_ERR_WRITE;
285 break; 292 break;
286 } 293 }
287 } 294 }
288 if (read < 0) self->error = MSPACK_ERR_READ; 295 if (read < 0) self->error = MSPACK_ERR_READ;
289 sys->free(buf); 296 sys->free(buf);
290 } 297 }
291 else { 298 else {
292 self->error = MSPACK_ERR_NOMEMORY; 299 self->error = MSPACK_ERR_NOMEMORY;
293 } 300 }
294 } 301 }
295 else if (hdr->comp_type == MSKWAJ_COMP_SZDD) { 302 else if (hdr->comp_type == MSKWAJ_COMP_SZDD) {
296 self->error = lzss_decompress(sys, fh, outfh, KWAJ_INPUT_SIZE, 303 self->error = lzss_decompress(sys, fh, outfh, KWAJ_INPUT_SIZE,
297 LZSS_MODE_EXPAND); 304 LZSS_MODE_EXPAND);
298 } 305 }
299 else if (hdr->comp_type == MSKWAJ_COMP_LZH) { 306 else if (hdr->comp_type == MSKWAJ_COMP_LZH) {
300 struct kwajd_stream *lzh = lzh_init(sys, fh, outfh); 307 struct kwajd_stream *lzh = lzh_init(sys, fh, outfh);
301 self->error = (lzh) ? lzh_decompress(lzh) : MSPACK_ERR_NOMEMORY; 308 self->error = (lzh) ? lzh_decompress(lzh) : MSPACK_ERR_NOMEMORY;
302 lzh_free(lzh); 309 lzh_free(lzh);
310 }
311 else if (hdr->comp_type == MSKWAJ_COMP_MSZIP) {
312 struct mszipd_stream *zip = mszipd_init(sys,fh,outfh,KWAJ_INPUT_SIZE,0);
313 self->error = (zip) ? mszipd_decompress_kwaj(zip) : MSPACK_ERR_NOMEMORY;
314 mszipd_free(zip);
303 } 315 }
304 else { 316 else {
305 self->error = MSPACK_ERR_DATAFORMAT; 317 self->error = MSPACK_ERR_DATAFORMAT;
306 } 318 }
307 319
308 /* close output file */ 320 /* close output file */
@@ -317,7 +329,7 @@ static int kwajd_extract(struct mskwaj_decompressor *base,
317 * unpacks directly from input to output 329 * unpacks directly from input to output
318 */ 330 */
319static int kwajd_decompress(struct mskwaj_decompressor *base, 331static int kwajd_decompress(struct mskwaj_decompressor *base,
320 const char *input, const char *output) 332 const char *input, const char *output)
321{ 333{
322 struct mskwaj_decompressor_p *self = (struct mskwaj_decompressor_p *) base; 334 struct mskwaj_decompressor_p *self = (struct mskwaj_decompressor_p *) base;
323 struct mskwajd_header *hdr; 335 struct mskwajd_header *hdr;
@@ -353,15 +365,15 @@ static int kwajd_error(struct mskwaj_decompressor *base)
353#define BITS_VAR lzh 365#define BITS_VAR lzh
354#define BITS_ORDER_MSB 366#define BITS_ORDER_MSB
355#define BITS_NO_READ_INPUT 367#define BITS_NO_READ_INPUT
356#define READ_BYTES do { \ 368#define READ_BYTES do { \
357 if (i_ptr >= i_end) { \ 369 if (i_ptr >= i_end) { \
358 if ((err = lzh_read_input(lzh))) return err; \ 370 if ((err = lzh_read_input(lzh))) return err; \
359 i_ptr = lzh->i_ptr; \ 371 i_ptr = lzh->i_ptr; \
360 i_end = lzh->i_end; \ 372 i_end = lzh->i_end; \
361 } \ 373 } \
362 INJECT_BITS(*i_ptr++, 8); \ 374 INJECT_BITS(*i_ptr++, 8); \
363} while (0) 375} while (0)
364#include "readbits.h" 376#include <readbits.h>
365 377
366/* import huffman-reading macros and code */ 378/* import huffman-reading macros and code */
367#define TABLEBITS(tbl) KWAJ_TABLEBITS 379#define TABLEBITS(tbl) KWAJ_TABLEBITS
@@ -369,7 +381,7 @@ static int kwajd_error(struct mskwaj_decompressor *base)
369#define HUFF_TABLE(tbl,idx) lzh->tbl##_table[idx] 381#define HUFF_TABLE(tbl,idx) lzh->tbl##_table[idx]
370#define HUFF_LEN(tbl,idx) lzh->tbl##_len[idx] 382#define HUFF_LEN(tbl,idx) lzh->tbl##_len[idx]
371#define HUFF_ERROR return MSPACK_ERR_DATAFORMAT 383#define HUFF_ERROR return MSPACK_ERR_DATAFORMAT
372#include "readhuff.h" 384#include <readhuff.h>
373 385
374/* In the KWAJ LZH format, there is no special 'eof' marker, it just 386/* In the KWAJ LZH format, there is no special 'eof' marker, it just
375 * ends. Depending on how many bits are left in the final byte when 387 * ends. Depending on how many bits are left in the final byte when
@@ -381,31 +393,30 @@ static int kwajd_error(struct mskwaj_decompressor *base)
381 * isn't how the default readbits.h read_input() works (it simply lets 393 * isn't how the default readbits.h read_input() works (it simply lets
382 * 2 fake bytes in then stops), so we implement our own. 394 * 2 fake bytes in then stops), so we implement our own.
383 */ 395 */
384#define READ_BITS_SAFE(val, n) do { \ 396#define READ_BITS_SAFE(val, n) do { \
385 READ_BITS(val, n); \ 397 READ_BITS(val, n); \
386 if (lzh->input_end && bits_left < lzh->input_end) \ 398 if (lzh->input_end && bits_left < lzh->input_end) \
387 return MSPACK_ERR_OK; \ 399 return MSPACK_ERR_OK; \
388} while (0) 400} while (0)
389 401
390#define READ_HUFFSYM_SAFE(tbl, val) do { \ 402#define READ_HUFFSYM_SAFE(tbl, val) do { \
391 READ_HUFFSYM(tbl, val); \ 403 READ_HUFFSYM(tbl, val); \
392 if (lzh->input_end && bits_left < lzh->input_end) \ 404 if (lzh->input_end && bits_left < lzh->input_end) \
393 return MSPACK_ERR_OK; \ 405 return MSPACK_ERR_OK; \
394} while (0) 406} while (0)
395 407
396#define BUILD_TREE(tbl, type) \ 408#define BUILD_TREE(tbl, type) \
397 STORE_BITS; \ 409 STORE_BITS; \
398 err = lzh_read_lens(lzh, type, MAXSYMBOLS(tbl), \ 410 err = lzh_read_lens(lzh, type, MAXSYMBOLS(tbl), &HUFF_LEN(tbl,0)); \
399 &HUFF_LEN(tbl,0), &HUFF_TABLE(tbl,0)); \ 411 if (err) return err; \
400 if (err) return err; \ 412 RESTORE_BITS; \
401 RESTORE_BITS; \ 413 if (make_decode_table(MAXSYMBOLS(tbl), TABLEBITS(tbl), \
402 if (make_decode_table(MAXSYMBOLS(tbl), TABLEBITS(tbl), \ 414 &HUFF_LEN(tbl,0), &HUFF_TABLE(tbl,0))) \
403 &HUFF_LEN(tbl,0), &HUFF_TABLE(tbl,0))) \ 415 return MSPACK_ERR_DATAFORMAT;
404 return MSPACK_ERR_DATAFORMAT; 416
405 417#define WRITE_BYTE do { \
406#define WRITE_BYTE do { \ 418 if (lzh->sys->write(lzh->output, &lzh->window[pos], 1) != 1) \
407 if (lzh->sys->write(lzh->output, &lzh->window[pos], 1) != 1) \ 419 return MSPACK_ERR_WRITE; \
408 return MSPACK_ERR_WRITE; \
409} while (0) 420} while (0)
410 421
411static struct kwajd_stream *lzh_init(struct mspack_system *sys, 422static struct kwajd_stream *lzh_init(struct mspack_system *sys,
@@ -447,33 +458,33 @@ static int lzh_decompress(struct kwajd_stream *lzh)
447 BUILD_TREE(LITERAL, types[4]); 458 BUILD_TREE(LITERAL, types[4]);
448 459
449 while (!lzh->input_end) { 460 while (!lzh->input_end) {
450 if (lit_run) READ_HUFFSYM_SAFE(MATCHLEN2, len); 461 if (lit_run) READ_HUFFSYM_SAFE(MATCHLEN2, len);
451 else READ_HUFFSYM_SAFE(MATCHLEN1, len); 462 else READ_HUFFSYM_SAFE(MATCHLEN1, len);
452 463
453 if (len > 0) { 464 if (len > 0) {
454 len += 2; 465 len += 2;
455 lit_run = 0; /* not the end of a literal run */ 466 lit_run = 0; /* not the end of a literal run */
456 READ_HUFFSYM_SAFE(OFFSET, j); offset = j << 6; 467 READ_HUFFSYM_SAFE(OFFSET, j); offset = j << 6;
457 READ_BITS_SAFE(j, 6); offset |= j; 468 READ_BITS_SAFE(j, 6); offset |= j;
458 469
459 /* copy match as output and into the ring buffer */ 470 /* copy match as output and into the ring buffer */
460 while (len-- > 0) { 471 while (len-- > 0) {
461 lzh->window[pos] = lzh->window[(pos+4096-offset) & 4095]; 472 lzh->window[pos] = lzh->window[(pos+4096-offset) & 4095];
462 WRITE_BYTE; 473 WRITE_BYTE;
463 pos++; pos &= 4095; 474 pos++; pos &= 4095;
464 } 475 }
465 } 476 }
466 else { 477 else {
467 READ_HUFFSYM_SAFE(LITLEN, len); len++; 478 READ_HUFFSYM_SAFE(LITLEN, len); len++;
468 lit_run = (len == 32) ? 0 : 1; /* end of a literal run? */ 479 lit_run = (len == 32) ? 0 : 1; /* end of a literal run? */
469 while (len-- > 0) { 480 while (len-- > 0) {
470 READ_HUFFSYM_SAFE(LITERAL, j); 481 READ_HUFFSYM_SAFE(LITERAL, j);
471 /* copy as output and into the ring buffer */ 482 /* copy as output and into the ring buffer */
472 lzh->window[pos] = j; 483 lzh->window[pos] = j;
473 WRITE_BYTE; 484 WRITE_BYTE;
474 pos++; pos &= 4095; 485 pos++; pos &= 4095;
475 } 486 }
476 } 487 }
477 } 488 }
478 return MSPACK_ERR_OK; 489 return MSPACK_ERR_OK;
479} 490}
@@ -487,8 +498,8 @@ static void lzh_free(struct kwajd_stream *lzh)
487} 498}
488 499
489static int lzh_read_lens(struct kwajd_stream *lzh, 500static int lzh_read_lens(struct kwajd_stream *lzh,
490 unsigned int type, unsigned int numsyms, 501 unsigned int type, unsigned int numsyms,
491 unsigned char *lens, unsigned short *table) 502 unsigned char *lens)
492{ 503{
493 register unsigned int bit_buffer; 504 register unsigned int bit_buffer;
494 register int bits_left; 505 register int bits_left;
@@ -499,33 +510,33 @@ static int lzh_read_lens(struct kwajd_stream *lzh,
499 RESTORE_BITS; 510 RESTORE_BITS;
500 switch (type) { 511 switch (type) {
501 case 0: 512 case 0:
502 i = numsyms; c = (i==16)?4: (i==32)?5: (i==64)?6: (i==256)?8 :0; 513 i = numsyms; c = (i==16)?4: (i==32)?5: (i==64)?6: (i==256)?8 :0;
503 for (i = 0; i < numsyms; i++) lens[i] = c; 514 for (i = 0; i < numsyms; i++) lens[i] = c;
504 break; 515 break;
505 516
506 case 1: 517 case 1:
507 READ_BITS_SAFE(c, 4); lens[0] = c; 518 READ_BITS_SAFE(c, 4); lens[0] = c;
508 for (i = 1; i < numsyms; i++) { 519 for (i = 1; i < numsyms; i++) {
509 READ_BITS_SAFE(sel, 1); if (sel == 0) lens[i] = c; 520 READ_BITS_SAFE(sel, 1); if (sel == 0) lens[i] = c;
510 else { READ_BITS_SAFE(sel, 1); if (sel == 0) lens[i] = ++c; 521 else { READ_BITS_SAFE(sel, 1); if (sel == 0) lens[i] = ++c;
511 else { READ_BITS_SAFE(c, 4); lens[i] = c; }} 522 else { READ_BITS_SAFE(c, 4); lens[i] = c; }}
512 } 523 }
513 break; 524 break;
514 525
515 case 2: 526 case 2:
516 READ_BITS_SAFE(c, 4); lens[0] = c; 527 READ_BITS_SAFE(c, 4); lens[0] = c;
517 for (i = 1; i < numsyms; i++) { 528 for (i = 1; i < numsyms; i++) {
518 READ_BITS_SAFE(sel, 2); 529 READ_BITS_SAFE(sel, 2);
519 if (sel == 3) READ_BITS_SAFE(c, 4); else c += (char) sel-1; 530 if (sel == 3) READ_BITS_SAFE(c, 4); else c += (char) sel-1;
520 lens[i] = c; 531 lens[i] = c;
521 } 532 }
522 break; 533 break;
523 534
524 case 3: 535 case 3:
525 for (i = 0; i < numsyms; i++) { 536 for (i = 0; i < numsyms; i++) {
526 READ_BITS_SAFE(c, 4); lens[i] = c; 537 READ_BITS_SAFE(c, 4); lens[i] = c;
527 } 538 }
528 break; 539 break;
529 } 540 }
530 STORE_BITS; 541 STORE_BITS;
531 return MSPACK_ERR_OK; 542 return MSPACK_ERR_OK;
@@ -534,18 +545,18 @@ static int lzh_read_lens(struct kwajd_stream *lzh,
534static int lzh_read_input(struct kwajd_stream *lzh) { 545static int lzh_read_input(struct kwajd_stream *lzh) {
535 int read; 546 int read;
536 if (lzh->input_end) { 547 if (lzh->input_end) {
537 lzh->input_end += 8; 548 lzh->input_end += 8;
538 lzh->inbuf[0] = 0; 549 lzh->inbuf[0] = 0;
539 read = 1; 550 read = 1;
540 } 551 }
541 else { 552 else {
542 read = lzh->sys->read(lzh->input, &lzh->inbuf[0], KWAJ_INPUT_SIZE); 553 read = lzh->sys->read(lzh->input, &lzh->inbuf[0], KWAJ_INPUT_SIZE);
543 if (read < 0) return MSPACK_ERR_READ; 554 if (read < 0) return MSPACK_ERR_READ;
544 if (read == 0) { 555 if (read == 0) {
545 lzh->input_end = 8; 556 lzh->input_end = 8;
546 lzh->inbuf[0] = 0; 557 lzh->inbuf[0] = 0;
547 read = 1; 558 read = 1;
548 } 559 }
549 } 560 }
550 561
551 /* update i_ptr and i_end */ 562 /* update i_ptr and i_end */