diff options
Diffstat (limited to 'rbutil/rbutilqt/mspack/kwajd.c')
-rw-r--r-- | rbutil/rbutilqt/mspack/kwajd.c | 365 |
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 */ |
19 | static struct mskwajd_header *kwajd_open( | 20 | static struct mskwajd_header *kwajd_open( |
@@ -40,7 +41,7 @@ static void lzh_free( | |||
40 | static int lzh_read_lens( | 41 | static 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); |
44 | static int lzh_read_input( | 45 | static 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 | */ |
92 | static struct mskwajd_header *kwajd_open(struct mskwaj_decompressor *base, | 93 | static 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 | */ |
128 | static void kwajd_close(struct mskwaj_decompressor *base, | 129 | static 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 | */ |
150 | static int kwajd_read_headers(struct mspack_system *sys, | 151 | static 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 | */ |
246 | static int kwajd_extract(struct mskwaj_decompressor *base, | 253 | static 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 | */ |
319 | static int kwajd_decompress(struct mskwaj_decompressor *base, | 331 | static 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 | ||
411 | static struct kwajd_stream *lzh_init(struct mspack_system *sys, | 422 | static 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 | ||
489 | static int lzh_read_lens(struct kwajd_stream *lzh, | 500 | static 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, | |||
534 | static int lzh_read_input(struct kwajd_stream *lzh) { | 545 | static 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 */ |