bmp: Rewrote the RLE decompressor
[deark.git] / modules / misc.c
blobb4e00ff7b76441dd449695f1e0f2743f3a898e79
1 // This file is part of Deark.
2 // Copyright (C) 2016-2021 Jason Summers
3 // See the file COPYING for terms of use.
5 // This file is for miscellaneous formats that are easy to support.
7 #include <deark-private.h>
8 #include <deark-fmtutil.h>
9 DE_DECLARE_MODULE(de_module_copy);
10 DE_DECLARE_MODULE(de_module_null);
11 DE_DECLARE_MODULE(de_module_split);
12 DE_DECLARE_MODULE(de_module_xor);
13 DE_DECLARE_MODULE(de_module_plaintext);
14 DE_DECLARE_MODULE(de_module_cp437);
15 DE_DECLARE_MODULE(de_module_crc);
16 DE_DECLARE_MODULE(de_module_datetime);
17 DE_DECLARE_MODULE(de_module_hexdump);
18 DE_DECLARE_MODULE(de_module_bytefreq);
19 DE_DECLARE_MODULE(de_module_deflate);
20 DE_DECLARE_MODULE(de_module_zlib);
21 DE_DECLARE_MODULE(de_module_winzle);
22 DE_DECLARE_MODULE(de_module_mrw);
23 DE_DECLARE_MODULE(de_module_vgafont);
24 DE_DECLARE_MODULE(de_module_pcrfont);
25 DE_DECLARE_MODULE(de_module_zbr);
26 DE_DECLARE_MODULE(de_module_compress);
27 DE_DECLARE_MODULE(de_module_hpi);
28 DE_DECLARE_MODULE(de_module_dclimplode);
29 DE_DECLARE_MODULE(de_module_lzss_oku);
30 DE_DECLARE_MODULE(de_module_lzhuf);
31 DE_DECLARE_MODULE(de_module_compress_lzh);
32 DE_DECLARE_MODULE(de_module_lzstac);
33 DE_DECLARE_MODULE(de_module_npack);
34 DE_DECLARE_MODULE(de_module_lzs221);
35 DE_DECLARE_MODULE(de_module_xpk);
37 // **************************************************************************
38 // "copy" module
40 // This is a trivial module that makes a copy of the input file.
41 // **************************************************************************
43 static void de_run_copy(deark *c, de_module_params *mparams)
45 dbuf_create_file_from_slice(c->infile, 0, c->infile->len, "bin", NULL, 0);
48 void de_module_copy(deark *c, struct deark_module_info *mi)
50 mi->id = "copy";
51 mi->desc = "Copy the file unchanged";
52 mi->run_fn = de_run_copy;
55 // **************************************************************************
56 // "null" module
58 // This is a trivial module that does nothing.
59 // **************************************************************************
61 static void de_run_null(deark *c, de_module_params *mparams)
66 void de_module_null(deark *c, struct deark_module_info *mi)
68 mi->id = "null";
69 mi->desc = "Do nothing";
70 mi->run_fn = de_run_null;
71 mi->flags |= DE_MODFLAG_NOEXTRACT;
74 // **************************************************************************
75 // split
76 // Split the input file into equal-sized chunks.
77 // **************************************************************************
79 static void do_split_onechunk(deark *c, i64 chunknum, i64 offset, i64 size)
81 dbuf *outf = NULL;
82 char ext[32];
84 de_snprintf(ext, sizeof(ext), "part%"I64_FMT, chunknum);
85 outf = dbuf_create_output_file(c, ext, NULL, 0);
86 dbuf_copy(c->infile, offset, size, outf);
87 dbuf_close(outf);
90 static void de_run_split(deark *c, de_module_params *mparams)
92 const char *s;
93 i64 pos;
94 i64 chunknum;
95 i64 chunksize, chunkstride;
96 i64 chunkcount;
98 s = de_get_ext_option(c, "split:size");
99 if(!s) {
100 de_err(c, "\"-opt split:size=<n>\" is required.");
101 goto done;
103 chunksize = de_atoi64(s);
104 if(chunksize<1) {
105 de_err(c, "Invalid chunk size");
106 goto done;
109 s = de_get_ext_option(c, "split:stride");
110 if(s) {
111 chunkstride = de_atoi64(s);
112 if(chunkstride<chunksize) {
113 de_err(c, "Stride must be "DE_CHAR_GEQ" size");
114 goto done;
117 else {
118 chunkstride = chunksize;
121 chunkcount = (c->infile->len + (chunkstride-1)) / chunkstride;
123 if((chunkcount>256) && (!c->user_set_max_output_files)) {
124 de_err(c, "Large number of chunks; use \"-maxfiles %"I64_FMT"\" if you "
125 "really want to do this.", chunkcount);
126 goto done;
129 pos = 0;
130 for(chunknum = 0; chunknum<chunkcount; chunknum++) {
131 i64 this_chunk_size;
133 this_chunk_size = de_min_int(chunksize, c->infile->len-pos);
134 do_split_onechunk(c, chunknum, pos, this_chunk_size);
136 pos += chunkstride;
139 done:
143 static void de_help_split(deark *c)
145 de_msg(c, "-opt split:size=<n> : The size of each chunk, in bytes");
146 de_msg(c, "-opt split:stride=<n> : Source distance between chunks");
149 void de_module_split(deark *c, struct deark_module_info *mi)
151 mi->id = "split";
152 mi->desc = "Split the file into equal-sized chunks";
153 mi->run_fn = de_run_split;
154 mi->help_fn = de_help_split;
157 // **************************************************************************
158 // xor
159 // Apply an XOR key to the file. Can be used to de-obfuscate some files.
160 // **************************************************************************
162 struct xorctx_struct {
163 dbuf *outf;
164 UI key_len;
165 UI key_pos;
166 u8 key[100];
169 static int xor_cbfn(struct de_bufferedreadctx *brctx, const u8 *buf,
170 i64 buf_len)
172 i64 i;
173 struct xorctx_struct *xorctx = (struct xorctx_struct*)brctx->userdata;
175 for(i=0; i<buf_len; i++) {
176 dbuf_writebyte(xorctx->outf, buf[i] ^ xorctx->key[xorctx->key_pos]);
177 if(xorctx->key_len>1) {
178 xorctx->key_pos = (xorctx->key_pos+1) % xorctx->key_len;
181 return 1;
184 static void de_run_xor(deark *c, de_module_params *mparams)
186 struct xorctx_struct *xorctx = NULL;
187 int badkey_flag = 0;
188 const char *opt_key;
190 xorctx = de_malloc(c, sizeof(struct xorctx_struct));
191 xorctx->key[0] = 0xff;
192 xorctx->key_len = 1;
194 opt_key = de_get_ext_option(c, "xor:key");
195 if(opt_key) {
196 UI key_strlen;
197 UI k;
199 key_strlen = (UI)de_strlen(opt_key);
200 if(key_strlen%2) { badkey_flag = 1; goto done; }
201 xorctx->key_len = key_strlen/2;
202 if(xorctx->key_len<1 || (size_t)xorctx->key_len>sizeof(xorctx->key)) {
203 badkey_flag = 1;
204 goto done;
206 for(k=0; k<xorctx->key_len; k++) {
207 u8 d1, d2;
208 int errflag1 = 0;
209 int errflag2 = 0;
211 d1 = de_decode_hex_digit(opt_key[k*2], &errflag1);
212 d2 = de_decode_hex_digit(opt_key[k*2+1], &errflag2);
213 if(errflag1 || errflag2) { badkey_flag = 1; goto done; }
214 xorctx->key[k] = (d1<<4) | d2;
218 xorctx->outf = dbuf_create_output_file(c, "bin", NULL, 0);
219 dbuf_enable_wbuffer(xorctx->outf);
220 dbuf_buffered_read(c->infile, 0, c->infile->len, xor_cbfn, (void*)xorctx);
222 done:
223 if(badkey_flag) {
224 de_err(c, "Bad XOR key");
226 if(xorctx) {
227 dbuf_close(xorctx->outf);
228 de_free(c, xorctx);
232 static void de_help_xor(deark *c)
234 de_msg(c, "-opt xor:key=<aabbcc...> : Hex bytes to use as XOR key");
237 void de_module_xor(deark *c, struct deark_module_info *mi)
239 mi->id = "xor";
240 mi->desc = "Invert bits, or XOR with a key";
241 mi->run_fn = de_run_xor;
242 mi->help_fn = de_help_xor;
245 // **************************************************************************
246 // plaintext
247 // Convert text files to UTF-8.
248 // **************************************************************************
250 static de_encoding get_bom_enc(deark *c, UI *blen)
252 u8 buf[3];
254 de_read(buf, 0, 3);
255 if(buf[0]==0xef && buf[1]==0xbb && buf[2]==0xbf) {
256 *blen = 3;
257 return DE_ENCODING_UTF8;
259 else if(buf[0]==0xfe && buf[1]==0xff) {
260 *blen = 2;
261 return DE_ENCODING_UTF16BE;
263 else if(buf[0]==0xff && buf[1]==0xfe) {
264 *blen = 2;
265 return DE_ENCODING_UTF16LE;
267 *blen = 0;
268 return DE_ENCODING_UNKNOWN;
271 static void de_run_plaintext(deark *c, de_module_params *mparams)
273 de_encoding input_encoding;
274 de_encoding enc_from_bom;
275 UI existing_bom_len = 0;
276 i64 dpos, dlen;
277 dbuf *outf = NULL;
279 enc_from_bom = get_bom_enc(c, &existing_bom_len);
280 input_encoding = de_get_input_encoding(c, NULL, DE_ENCODING_UNKNOWN);
281 if(input_encoding==DE_ENCODING_UNKNOWN) {
282 if(enc_from_bom!=DE_ENCODING_UNKNOWN) {
283 input_encoding = enc_from_bom;
285 else {
286 input_encoding = DE_ENCODING_UTF8;
289 if(input_encoding!=enc_from_bom) {
290 // Even if there was something that looked like a BOM, ignore it.
291 existing_bom_len = 0;
294 dpos = (i64)existing_bom_len;
295 dlen = c->infile->len - dpos;
297 outf = dbuf_create_output_file(c, "txt", NULL, 0);
298 dbuf_enable_wbuffer(outf);
300 if(c->write_bom) {
301 dbuf_write_uchar_as_utf8(outf, 0xfeff);
304 dbuf_copy_slice_convert_to_utf8(c->infile, dpos, dlen,
305 DE_EXTENC_MAKE(input_encoding, DE_ENCSUBTYPE_HYBRID),
306 outf, 0);
308 dbuf_close(outf);
311 void de_module_plaintext(deark *c, struct deark_module_info *mi)
313 mi->id = "plaintext";
314 mi->desc = "Plain text";
315 mi->desc2 = "Convert to UTF-8";
316 mi->run_fn = de_run_plaintext;
319 // **************************************************************************
320 // CP437
321 // Convert CP437 text files to UTF-8.
322 // **************************************************************************
324 struct cp437ctx_struct {
325 dbuf *outf;
326 struct de_encconv_state es;
329 static int cp437_cbfn(struct de_bufferedreadctx *brctx, const u8 *buf,
330 i64 buf_len)
332 i32 u;
333 i64 i;
334 u8 ch;
335 struct cp437ctx_struct *cp437ctx = (struct cp437ctx_struct*)brctx->userdata;
337 for(i=0; i<buf_len; i++) {
338 ch = buf[i];
339 if(ch==0x09 || ch==0x0a || ch==0x0c || ch==0x0d) {
340 // Leave HT, NL, FF, CR as-is.
341 u = (i32)ch;
343 else if(ch==0x1a) {
344 // Lots of CP437 files end with a Ctrl+Z character, but modern files
345 // don't use any in-band character to signify end-of-file.
346 // I don't just want to delete the character, though, so I guess I'll
347 // change it to U+2404 SYMBOL FOR END OF TRANSMISSION.
348 u = 0x2404;
350 else {
351 u = de_char_to_unicode_ex((i32)ch, &cp437ctx->es);
353 dbuf_write_uchar_as_utf8(cp437ctx->outf, u);
356 return 1;
359 static void de_run_cp437(deark *c, de_module_params *mparams)
361 struct cp437ctx_struct cp437ctx;
363 cp437ctx.outf = dbuf_create_output_file(c, "txt", NULL, 0);
364 dbuf_enable_wbuffer(cp437ctx.outf);
365 de_encconv_init(&cp437ctx.es, DE_ENCODING_CP437_G);
366 if(c->write_bom) {
367 dbuf_write_uchar_as_utf8(cp437ctx.outf, 0xfeff);
369 dbuf_buffered_read(c->infile, 0, c->infile->len, cp437_cbfn, (void*)&cp437ctx);
370 dbuf_close(cp437ctx.outf);
373 void de_module_cp437(deark *c, struct deark_module_info *mi)
375 mi->id = "cp437";
376 mi->desc = "Code Page 437 text";
377 mi->run_fn = de_run_cp437;
380 // **************************************************************************
381 // crc
382 // Prints various CRCs and checksums. Does not create any files.
383 // **************************************************************************
385 struct crcm_alg_info {
386 UI crctype;
387 u8 flags; // 1 = computed by default
388 u8 nbits; // 0 = special
389 const char *name;
392 #define CRCM_NUMCRCS 11
393 static const struct crcm_alg_info crcm_map[CRCM_NUMCRCS] = {
394 { DE_CRCOBJ_CRC32_IEEE, 1, 32, "CRC-32-IEEE" },
395 { DE_CRCOBJ_CRC16_ARC, 1, 16, "CRC-16/ARC"},
396 { DE_CRCOBJ_CRC16_XMODEM, 1, 16, "CRC-16/XMODEM" },
397 { DE_CRCOBJ_CRC32_JAMCRC, 0, 32, "CRC-32/JAMCRC" },
398 { DE_CRCOBJ_CRC32_PL, 0, 32, "CRC-32/PL" },
399 { DE_CRCOBJ_ADLER32, 0, 32, "Adler-32" },
400 { DE_CRCOBJ_CRC16_IBMSDLC, 0, 16, "CRC-16/IBM-SDLC" },
401 { DE_CRCOBJ_CRC16_IBM3740, 0, 16, "CRC-16/IBM-3740" },
402 { DE_CRCOBJ_SUM_BYTES, 1, 0, "Sum of bytes" },
403 { DE_CRCOBJ_SUM_U16LE, 0, 0, "Sum of uint16-LE" },
404 { DE_CRCOBJ_SUM_U16BE, 0, 0, "Sum of uint16-BE" }
407 struct crcctx_struct {
408 u8 opt_all;
409 struct de_crcobj *crcos[CRCM_NUMCRCS];
412 static int crc_cbfn(struct de_bufferedreadctx *brctx, const u8 *buf,
413 i64 buf_len)
415 struct crcctx_struct *crcctx = (struct crcctx_struct*)brctx->userdata;
416 size_t n;
418 for(n=0; n<CRCM_NUMCRCS; n++) {
419 if(!crcctx->crcos[n]) continue;
420 de_crcobj_addbuf(crcctx->crcos[n], buf, buf_len);
423 return 1;
426 static void de_run_crc(deark *c, de_module_params *mparams)
428 struct crcctx_struct crcctx;
429 size_t n;
431 de_zeromem(&crcctx, sizeof(struct crcctx_struct));
432 crcctx.opt_all = (u8)de_get_ext_option_bool(c, "crc:all", 0xff);
433 if(crcctx.opt_all==0xff) {
434 if(c->extract_level>=2) {
435 crcctx.opt_all = 1;
437 else {
438 crcctx.opt_all = 0;
442 for(n=0; n<CRCM_NUMCRCS; n++) {
443 if((crcm_map[n].flags & 0x1)==0 && !crcctx.opt_all) continue;
444 crcctx.crcos[n] = de_crcobj_create(c, crcm_map[n].crctype);
447 dbuf_buffered_read(c->infile, 0, c->infile->len, crc_cbfn, (void*)&crcctx);
449 for(n=0; n<CRCM_NUMCRCS; n++) {
450 u32 val = 0;
451 u64 val64 = 0;
453 if(!crcctx.crcos[n]) continue;
455 if(crcm_map[n].nbits==0) {
456 val64 = de_crcobj_getval64(crcctx.crcos[n]);
458 else {
459 val = de_crcobj_getval(crcctx.crcos[n]);
462 if(crcm_map[n].nbits==0) {
463 de_msg(c, "%-18s: 0x%"U64_FMTx, crcm_map[n].name, val64);
465 else if(crcm_map[n].nbits==16) {
466 de_msg(c, "%-18s: 0x%04x", crcm_map[n].name, (UI)val);
468 else {
469 de_msg(c, "%-18s: 0x%08x", crcm_map[n].name, (UI)val);
473 for(n=0; n<CRCM_NUMCRCS; n++) {
474 de_crcobj_destroy(crcctx.crcos[n]);
478 static void de_help_crc(deark *c)
480 de_msg(c, "-a : Also compute uncommon checksum types");
483 void de_module_crc(deark *c, struct deark_module_info *mi)
485 mi->id = "crc";
486 mi->id_alias[0] = "crc32";
487 mi->desc = "Calculate various CRCs";
488 mi->run_fn = de_run_crc;
489 mi->help_fn = de_help_crc;
490 mi->flags |= DE_MODFLAG_NOEXTRACT;
493 // **************************************************************************
494 // datetime
495 // Interpret the start of the file as a date/time field, in various formats.
496 // **************************************************************************
498 static void datetime_msg(deark *c, struct de_timestamp *ts, const char *name)
500 char timestamp_buf[64];
502 de_timestamp_to_string(ts, timestamp_buf, sizeof(timestamp_buf), 0);
503 de_msg(c, "%s: %s", name, timestamp_buf);
506 static void de_run_datetime(deark *c, de_module_params *mparams)
508 struct de_timestamp timestamp;
509 i64 dtime, ddate;
510 i64 t;
512 dtime = de_getu16le(0);
513 ddate = de_getu16le(2);
514 de_dos_datetime_to_timestamp(&timestamp, ddate, dtime);
515 datetime_msg(c, &timestamp, "DOS time,date");
517 ddate = de_getu16le(0);
518 dtime = de_getu16le(2);
519 de_dos_datetime_to_timestamp(&timestamp, ddate, dtime);
520 datetime_msg(c, &timestamp, "DOS date,time");
522 t = de_geti32le(0);
523 de_unix_time_to_timestamp(t, &timestamp, 0x1);
524 datetime_msg(c, &timestamp, "Unix-LE");
526 t = de_geti32be(0);
527 de_unix_time_to_timestamp(t, &timestamp, 0x1);
528 datetime_msg(c, &timestamp, "Unix-BE");
530 t = de_getu32be(0);
531 de_mac_time_to_timestamp(t, &timestamp);
532 datetime_msg(c, &timestamp, "Mac/HFS-BE");
534 t = de_geti64le(0);
535 de_FILETIME_to_timestamp(t, &timestamp, 0x1);
536 datetime_msg(c, &timestamp, "Windows FILETIME");
539 void de_module_datetime(deark *c, struct deark_module_info *mi)
541 mi->id = "datetime";
542 mi->desc = "Interpret a date/time field";
543 mi->run_fn = de_run_datetime;
544 mi->flags |= DE_MODFLAG_HIDDEN | DE_MODFLAG_NOEXTRACT;
547 // **************************************************************************
548 // hexdump
549 // Prints a hex dump. Does not create any files.
550 // **************************************************************************
552 static void de_run_hexdump(deark *c, de_module_params *mparams)
554 de_hexdump2(c, c->infile, 0, c->infile->len,
555 c->infile->len, 0x3);
558 void de_module_hexdump(deark *c, struct deark_module_info *mi)
560 mi->id = "hexdump";
561 mi->desc = "Print a hex dump";
562 mi->run_fn = de_run_hexdump;
563 mi->flags |= DE_MODFLAG_NOEXTRACT;
566 // **************************************************************************
567 // bytefreq
568 // Prints a summary of how many times each byte value occurs.
569 // **************************************************************************
571 struct bytefreqentry {
572 i64 count;
573 #define DE_BYTEFREQ_NUMLOC 3
574 i64 locations[DE_BYTEFREQ_NUMLOC];
577 struct bytefreqctx_struct {
578 struct bytefreqentry e[256];
581 static int bytefreq_cbfn(struct de_bufferedreadctx *brctx, const u8 *buf,
582 i64 buf_len)
584 i64 k;
585 struct bytefreqctx_struct *bfctx = (struct bytefreqctx_struct*)brctx->userdata;
587 for(k=0; k<buf_len; k++) {
588 struct bytefreqentry *bf = &bfctx->e[(unsigned int)buf[k]];
590 // Save the location of the first few occurrences of this byte value.
591 if(bf->count<DE_BYTEFREQ_NUMLOC) {
592 bf->locations[bf->count] = brctx->offset + k;
594 bf->count++;
596 return 1;
599 static void de_run_bytefreq(deark *c, de_module_params *mparams)
601 struct bytefreqctx_struct *bfctx = NULL;
602 de_ucstring *s = NULL;
603 unsigned int k;
604 de_encoding input_encoding;
605 struct de_encconv_state es;
607 bfctx = de_malloc(c, sizeof(struct bytefreqctx_struct));
608 input_encoding = de_get_input_encoding(c, NULL, DE_ENCODING_WINDOWS1252);
609 if(input_encoding==DE_ENCODING_UTF8) {
610 input_encoding=DE_ENCODING_ASCII;
612 de_encconv_init(&es, input_encoding);
614 dbuf_buffered_read(c->infile, 0, c->infile->len, bytefreq_cbfn, (void*)bfctx);
616 de_msg(c, "====Byte==== ===Count=== ==Locations==");
617 s = ucstring_create(c);
618 for(k=0; k<256; k++) {
619 i32 ch;
620 int cflag;
621 unsigned int z;
622 struct bytefreqentry *bf = &bfctx->e[k];
624 if(bf->count==0) continue;
625 ucstring_empty(s);
627 ucstring_printf(s, DE_ENCODING_LATIN1, "%3u 0x%02x ", k, k);
629 ch = de_char_to_unicode_ex((i32)k, &es);
630 if(ch==DE_CODEPOINT_INVALID) {
631 cflag = 0;
633 else {
634 cflag = de_is_printable_uchar(ch);
637 if(cflag) {
638 ucstring_append_sz(s, "'", DE_ENCODING_LATIN1);
639 ucstring_append_char(s, ch);
640 ucstring_append_sz(s, "'", DE_ENCODING_LATIN1);
642 else {
643 ucstring_append_sz(s, " ", DE_ENCODING_LATIN1);
646 ucstring_printf(s, DE_ENCODING_LATIN1, " %11"I64_FMT" ", bf->count);
648 for(z=0; z<DE_BYTEFREQ_NUMLOC && z<bf->count; z++) {
649 ucstring_printf(s, DE_ENCODING_LATIN1, "%"I64_FMT, bf->locations[z]);
650 if(z<bf->count-1) {
651 ucstring_append_sz(s, ",", DE_ENCODING_LATIN1);
654 if(bf->count>DE_BYTEFREQ_NUMLOC) {
655 ucstring_append_sz(s, "...", DE_ENCODING_LATIN1);
658 de_msg(c, "%s", ucstring_getpsz(s));
660 de_msg(c, " Total: %11"I64_FMT, c->infile->len);
661 ucstring_destroy(s);
662 de_free(c, bfctx);
665 void de_module_bytefreq(deark *c, struct deark_module_info *mi)
667 mi->id = "bytefreq";
668 mi->desc = "Print a byte frequence analysis";
669 mi->run_fn = de_run_bytefreq;
670 mi->flags |= DE_MODFLAG_NOEXTRACT;
673 // **************************************************************************
674 // Raw "Deflate"-compressed data
675 // **************************************************************************
677 static void run_deflate_internal(deark *c, UI flags)
679 dbuf *outf = NULL;
680 struct de_dfilter_in_params dcmpri;
681 struct de_dfilter_out_params dcmpro;
682 struct de_dfilter_results dres;
683 struct de_deflate_params deflparams;
685 de_dfilter_init_objects(c, &dcmpri, &dcmpro, &dres);
686 de_zeromem(&deflparams, sizeof(struct de_deflate_params));
687 deflparams.flags = flags;
689 outf = dbuf_create_output_file(c, "unc", NULL, 0);
690 dbuf_enable_wbuffer(outf);
691 dcmpri.f = c->infile;
692 dcmpri.pos = 0;
693 dcmpri.len = c->infile->len;
694 dcmpro.f = outf;
695 fmtutil_decompress_deflate_ex(c, &dcmpri, &dcmpro, &dres, &deflparams);
696 dbuf_flush(outf);
697 if(dres.errcode) {
698 de_err(c, "Decompression failed: %s", de_dfilter_get_errmsg(c, &dres));
699 goto done;
701 if(dres.bytes_consumed_valid) {
702 de_dbg(c, "decompressed %"I64_FMT" bytes to %"I64_FMT, dres.bytes_consumed,
703 outf->len);
706 done:
707 dbuf_close(outf);
710 static void de_run_deflate(deark *c, de_module_params *mparams)
712 UI flags = 0;
714 if(de_get_ext_option_bool(c, "deflate:deflate64", 0)) {
715 flags |= DE_DEFLATEFLAG_DEFLATE64;
718 run_deflate_internal(c, flags);
721 void de_module_deflate(deark *c, struct deark_module_info *mi)
723 mi->id = "deflate";
724 mi->desc = "Raw Deflate compressed data";
725 mi->run_fn = de_run_deflate;
728 // **************************************************************************
729 // zlib module
731 // This module is for decompressing zlib-compressed files.
732 // **************************************************************************
734 static void de_run_zlib(deark *c, de_module_params *mparams)
736 run_deflate_internal(c, DE_DEFLATEFLAG_ISZLIB);
739 static int de_identify_zlib(deark *c)
741 u8 b[2];
742 de_read(b, 0, 2);
744 if((b[0]&0x0f) != 8)
745 return 0;
747 if(b[0]<0x08 || b[0]>0x78)
748 return 0;
750 if(((((unsigned int)b[0])<<8)|b[1])%31 != 0)
751 return 0;
753 return 50;
756 void de_module_zlib(deark *c, struct deark_module_info *mi)
758 mi->id = "zlib";
759 mi->desc = "Raw zlib compressed data";
760 mi->run_fn = de_run_zlib;
761 mi->identify_fn = de_identify_zlib;
764 // **************************************************************************
765 // Winzle! puzzle image
766 // **************************************************************************
768 static void de_run_winzle(deark *c, de_module_params *mparams)
770 u8 buf[256];
771 i64 xorsize;
772 i64 i;
773 dbuf *f = NULL;
775 xorsize = c->infile->len >= 256 ? 256 : c->infile->len;
776 de_read(buf, 0, xorsize);
777 for(i=0; i<xorsize; i++) {
778 buf[i] ^= 0x0d;
781 f = dbuf_create_output_file(c, "bmp", NULL, 0);
782 dbuf_write(f, buf, xorsize);
783 if(c->infile->len > 256) {
784 dbuf_copy(c->infile, 256, c->infile->len - 256, f);
786 dbuf_close(f);
789 static int de_identify_winzle(deark *c)
791 u8 b[18];
792 de_read(b, 0, sizeof(b));
794 if(b[0]==0x4f && b[1]==0x40) {
795 if(b[14]==0x25 && b[15]==0x0d && b[16]==0x0d && b[17]==0x0d) {
796 return 95;
798 return 40;
800 return 0;
803 void de_module_winzle(deark *c, struct deark_module_info *mi)
805 mi->id = "winzle";
806 mi->desc = "Winzle! puzzle image";
807 mi->run_fn = de_run_winzle;
808 mi->identify_fn = de_identify_winzle;
811 // **************************************************************************
812 // Minolta RAW (MRW)
813 // **************************************************************************
815 static void do_mrw_seg_list(deark *c, i64 pos1, i64 len)
817 i64 pos;
818 u8 seg_id[4];
819 i64 data_len;
821 pos = pos1;
822 while(pos < pos1+len) {
823 de_read(seg_id, pos, 4);
824 data_len = de_getu32be(pos+4);
825 pos+=8;
826 if(pos+data_len > pos1+len) break;
827 if(!de_memcmp(seg_id, "\0TTW", 4)) { // Exif
828 fmtutil_handle_exif(c, pos, data_len);
830 pos+=data_len;
834 static void de_run_mrw(deark *c, de_module_params *mparams)
836 i64 mrw_seg_size;
838 mrw_seg_size = de_getu32be(4);
839 do_mrw_seg_list(c, 8, mrw_seg_size);
842 static int de_identify_mrw(deark *c)
844 if(!dbuf_memcmp(c->infile, 0, "\x00\x4d\x52\x4d", 4))
845 return 100;
846 return 0;
849 void de_module_mrw(deark *c, struct deark_module_info *mi)
851 mi->id = "mrw";
852 mi->desc = "Minolta RAW";
853 mi->desc2 = "resources only";
854 mi->run_fn = de_run_mrw;
855 mi->identify_fn = de_identify_mrw;
858 // **************************************************************************
859 // 8xN "VGA" font (intended for development/debugging use)
860 // **************************************************************************
862 static void do_vgafont_internal(deark *c, dbuf *inf)
864 u8 *fontdata = NULL;
865 struct de_bitmap_font *font = NULL;
866 i64 i;
867 i64 height;
868 de_encoding encoding_req;
869 de_encoding encoding_to_use;
870 struct de_encconv_state es;
872 #define VGAFONT_MINH 3
873 #define VGAFONT_MAXH 20
874 height = inf->len / 256;
875 if((inf->len % 256) || height<VGAFONT_MINH || height>VGAFONT_MAXH) {
876 de_err(c, "Bad file size");
877 goto done;
880 fontdata = de_malloc(c, height*256);
881 dbuf_read(inf, fontdata, 0, height*256);
883 if(de_get_ext_option(c, "vgafont:c")) {
884 dbuf *ff;
885 ff = dbuf_create_output_file(c, "h", NULL, 0);
886 for(i=0; i<(height*256); i++) {
887 if(i%height==0) dbuf_puts(ff, "\t");
888 dbuf_printf(ff, "%d", (int)fontdata[i]);
889 if(i!=(height*256-1)) dbuf_puts(ff, ",");
890 if(i%height==(height-1)) dbuf_puts(ff, "\n");
892 dbuf_close(ff);
893 goto done;
896 encoding_req = de_get_input_encoding(c, NULL, DE_ENCODING_UNKNOWN);
897 if(encoding_req!=DE_ENCODING_UNKNOWN)
898 encoding_to_use = encoding_req;
899 else
900 encoding_to_use = DE_ENCODING_CP437;
902 font = de_create_bitmap_font(c);
903 font->num_chars = 256;
904 font->has_nonunicode_codepoints = 1;
905 font->has_unicode_codepoints = 1;
906 font->prefer_unicode = (encoding_req!=DE_ENCODING_UNKNOWN);
907 font->nominal_width = 8;
908 font->nominal_height = (int)height;
909 font->char_array = de_mallocarray(c, font->num_chars, sizeof(struct de_bitmap_font_char));
911 de_encconv_init(&es, encoding_to_use);
913 for(i=0; i<font->num_chars; i++) {
914 font->char_array[i].codepoint_nonunicode = (i32)i;
915 if(font->has_unicode_codepoints) {
916 font->char_array[i].codepoint_unicode = de_char_to_unicode_ex((i32)i, &es);
918 font->char_array[i].width = font->nominal_width;
919 font->char_array[i].height = font->nominal_height;
920 font->char_array[i].rowspan = 1;
921 font->char_array[i].bitmap = &fontdata[i*font->nominal_height];
924 de_font_bitmap_font_to_image(c, font, NULL, 0);
926 done:
927 if(font) {
928 de_free(c, font->char_array);
929 de_destroy_bitmap_font(c, font);
931 de_free(c, fontdata);
934 static void de_run_vgafont(deark *c, de_module_params *mparams)
936 do_vgafont_internal(c, c->infile);
939 static void de_help_vgafont(deark *c)
941 de_msg(c, "-opt vgafont:c : Emit C code");
944 void de_module_vgafont(deark *c, struct deark_module_info *mi)
946 mi->id = "vgafont";
947 mi->desc = "Raw 8xN bitmap font";
948 mi->run_fn = de_run_vgafont;
949 mi->help_fn = de_help_vgafont;
952 // **************************************************************************
953 // PCR font (OPTICKS)
954 // **************************************************************************
956 static void de_run_pcrfont(deark *c, de_module_params *mparams)
958 u8 hdr[11];
959 i64 h;
960 int need_errmsg = 0;
961 dbuf *inf = NULL;
963 de_read(hdr, 0, 11);
964 // I assume either hdr[7] or hdr[10] is the high byte of the font data size,
965 // but I don't know which.
966 if(hdr[6]!=0x1 || hdr[7]!=hdr[10] || hdr[8]!=0 || hdr[9]!=0) {
967 need_errmsg = 1;
968 goto done;
970 h = (i64)hdr[7];
971 de_dbg(c, "height: %d", (int)h);
972 if(h<VGAFONT_MINH || h>VGAFONT_MAXH || c->infile->len < 11+h*256) {
973 need_errmsg = 1;
974 goto done;
977 inf = dbuf_open_input_subfile(c->infile, 11, h*256);
978 do_vgafont_internal(c, inf);
980 done:
981 dbuf_close(inf);
982 if(need_errmsg) {
983 de_err(c, "Unsupported type of PCR font");
987 static int de_identify_pcrfont(deark *c)
989 u8 h;
991 if(dbuf_memcmp(c->infile, 0, "KPG", 3)) return 0;
992 if(de_getbyte(5)!=0x20) return 0;
993 h = de_getbyte(7);
994 if(h<6 || h>16) return 0;
995 if(de_getbyte(10)!=h) return 0;
996 return 80;
999 void de_module_pcrfont(deark *c, struct deark_module_info *mi)
1001 mi->id = "pcrfont";
1002 mi->desc = "PCR font";
1003 mi->run_fn = de_run_pcrfont;
1004 mi->identify_fn = de_identify_pcrfont;
1007 // **************************************************************************
1008 // ZBR (Zoner Zebra Metafile)
1009 // **************************************************************************
1011 static void de_run_zbr(deark *c, de_module_params *mparams)
1013 i64 pos = 0;
1014 dbuf *outf = NULL;
1015 static const u8 hdrs[54] = {
1016 0x42,0x4d,0xc6,0x14,0,0,0,0,0,0,0x76,0,0,0, // FILEHEADER
1017 0x28,0,0,0,0x64,0,0,0,0x64,0,0,0,0x01,0,0x04,0, // INFOHEADER...
1018 0,0,0,0,0x50,0x14,0,0,0,0,0,0,0,0,0,0,
1019 0x10,0,0,0,0,0,0,0 };
1021 pos += 4; // signature, version
1022 pos += 100; // comment
1024 de_dbg(c, "preview image at %d", (int)pos);
1025 // By design, this image is formatted as a headerless BMP/DIB. We'll just
1026 // add the 54 bytes of headers needed to make it a BMP, and call it done.
1027 outf = dbuf_create_output_file(c, "preview.bmp", NULL, DE_CREATEFLAG_IS_AUX);
1028 dbuf_write(outf, hdrs, 54);
1029 dbuf_copy(c->infile, pos, 16*4 + 100*52, outf);
1030 dbuf_close(outf);
1033 static int de_identify_zbr(deark *c)
1035 if(!dbuf_memcmp(c->infile, 0, "\x9a\x02", 2)) {
1036 if(de_input_file_has_ext(c, "zbr")) return 100;
1037 return 25;
1039 return 0;
1042 void de_module_zbr(deark *c, struct deark_module_info *mi)
1044 mi->id = "zbr";
1045 mi->desc = "ZBR (Zebra Metafile)";
1046 mi->desc2 = "extract preview image";
1047 mi->run_fn = de_run_zbr;
1048 mi->identify_fn = de_identify_zbr;
1051 // **************************************************************************
1052 // compress (.Z)
1053 // **************************************************************************
1055 static void de_run_compress(deark *c, de_module_params *mparams)
1057 struct de_dfilter_results dres;
1058 struct de_dfilter_in_params dcmpri;
1059 struct de_dfilter_out_params dcmpro;
1060 struct de_lzw_params delzwp;
1061 dbuf *f = NULL;
1063 f = dbuf_create_output_file(c, "bin", NULL, 0);
1064 dbuf_enable_wbuffer(f);
1066 de_dfilter_init_objects(c, &dcmpri, &dcmpro, &dres);
1067 dcmpri.f = c->infile;
1068 dcmpri.pos = 0;
1069 dcmpri.len = c->infile->len;
1070 dcmpro.f = f;
1071 dcmpro.len_known = 0;
1073 de_zeromem(&delzwp, sizeof(struct de_lzw_params));
1074 delzwp.fmt = DE_LZWFMT_UNIXCOMPRESS;
1075 delzwp.flags |= DE_LZWFLAG_HAS3BYTEHEADER;
1077 fmtutil_decompress_lzw(c, &dcmpri, &dcmpro, &dres, &delzwp);
1078 dbuf_flush(f);
1079 if(dres.errcode!=0) {
1080 de_err(c, "%s", de_dfilter_get_errmsg(c, &dres));
1082 dbuf_close(f);
1085 static int de_identify_compress(deark *c)
1087 if(!dbuf_memcmp(c->infile, 0, "\x1f\x9d", 2))
1088 return 100;
1089 return 0;
1092 void de_module_compress(deark *c, struct deark_module_info *mi)
1094 mi->id = "compress";
1095 mi->desc = "Compress (.Z)";
1096 mi->run_fn = de_run_compress;
1097 mi->identify_fn = de_identify_compress;
1100 // **************************************************************************
1101 // Hemera Photo-Object image (.hpi)
1102 // **************************************************************************
1104 static void de_run_hpi(deark *c, de_module_params *mparams)
1106 i64 jpgpos, pngpos;
1107 i64 jpglen, pnglen;
1108 i64 pos;
1110 pos = 12;
1111 jpgpos = de_getu32le_p(&pos);
1112 jpglen = de_getu32le_p(&pos);
1113 de_dbg(c, "jpeg: pos=%"I64_FMT", len=%"I64_FMT, jpgpos, jpglen);
1114 pngpos = de_getu32le_p(&pos);
1115 pnglen = de_getu32le_p(&pos);
1116 de_dbg(c, "png: pos=%"I64_FMT", len=%"I64_FMT, pngpos, pnglen);
1118 if(jpglen>0 && jpgpos+jpglen<=c->infile->len && de_getbyte(jpgpos)==0xff) {
1119 const char *ext;
1121 if(pnglen==0) ext="jpg";
1122 else ext="foreground.jpg";
1123 dbuf_create_file_from_slice(c->infile, jpgpos, jpglen, ext, NULL, 0);
1125 if(pnglen>0 && pngpos+pnglen<=c->infile->len && de_getbyte(pngpos)==0x89) {
1126 dbuf_create_file_from_slice(c->infile, pngpos, pnglen, "mask.png", NULL, 0);
1130 static int de_identify_hpi(deark *c)
1132 if(!dbuf_memcmp(c->infile, 0, "\x89\x48\x50\x49\x0d\x0a\x1a\x0a", 8)) return 100;
1133 return 0;
1136 void de_module_hpi(deark *c, struct deark_module_info *mi)
1138 mi->id = "hpi";
1139 mi->desc = "Hemera Photo-Object image";
1140 mi->run_fn = de_run_hpi;
1141 mi->identify_fn = de_identify_hpi;
1144 // **************************************************************************
1145 // PKWARE DCL Implode compressed file
1146 // **************************************************************************
1148 static void de_run_dclimplode(deark *c, de_module_params *mparams)
1150 dbuf *outf = NULL;
1151 struct de_dfilter_in_params dcmpri;
1152 struct de_dfilter_out_params dcmpro;
1153 struct de_dfilter_results dres;
1155 outf = dbuf_create_output_file(c, "unc", NULL, 0);
1156 dbuf_enable_wbuffer(outf);
1157 de_dfilter_init_objects(c, &dcmpri, &dcmpro, &dres);
1158 dcmpri.f = c->infile;
1159 dcmpri.pos = 0;
1160 dcmpri.len = c->infile->len;
1161 dcmpro.f = outf;
1163 fmtutil_dclimplode_codectype1(c, &dcmpri, &dcmpro, &dres, NULL);
1164 dbuf_flush(outf);
1165 if(dres.errcode) {
1166 de_err(c, "Decompression failed: %s", de_dfilter_get_errmsg(c, &dres));
1169 dbuf_close(outf);
1172 static int de_identify_dclimplode(deark *c)
1174 u8 b0, b1;
1175 int i;
1176 u32 x;
1178 if(c->infile->len<4) return 0;
1179 b0 = de_getbyte(0);
1180 if(b0>1) return 0;
1181 b1 = de_getbyte(1);
1182 if(b1<4 || b1>6) return 0;
1184 // Look for the end-of-data code in the last 2 or 3 bytes.
1185 // Assumes the last byte is padded with '0' bits, and there are
1186 // no extraneous bytes after that.
1187 x = (u32)de_getu32le(c->infile->len-4);
1188 for(i=0; i<8; i++) {
1189 if((x & 0xfffffe00U)==0x01fe0200U) {
1190 if(b0==0 && b1==6) return 40;
1191 return 10;
1193 x >>= 1;
1195 return 0;
1198 void de_module_dclimplode(deark *c, struct deark_module_info *mi)
1200 mi->id = "dclimplode";
1201 mi->id_alias[0] = "ttcomp";
1202 mi->desc = "PKWARE DCL Implode compressed file";
1203 mi->run_fn = de_run_dclimplode;
1204 mi->identify_fn = de_identify_dclimplode;
1207 // **************************************************************************
1208 // LZSS (Haruhiko Okumura) compressed file
1209 // **************************************************************************
1211 static void de_run_lzss_oku(deark *c, de_module_params *mparams)
1213 dbuf *outf = NULL;
1214 struct de_dfilter_in_params dcmpri;
1215 struct de_dfilter_out_params dcmpro;
1216 struct de_dfilter_results dres;
1218 outf = dbuf_create_output_file(c, "unc", NULL, 0);
1219 dbuf_enable_wbuffer(outf);
1220 de_dfilter_init_objects(c, &dcmpri, &dcmpro, &dres);
1221 dcmpri.f = c->infile;
1222 dcmpri.pos = 0;
1223 dcmpri.len = c->infile->len;
1224 dcmpro.f = outf;
1226 fmtutil_decompress_lzss1(c, &dcmpri, &dcmpro, &dres, 0x0);
1227 dbuf_flush(outf);
1228 if(dres.errcode) {
1229 de_err(c, "Decompression failed: %s", de_dfilter_get_errmsg(c, &dres));
1232 dbuf_close(outf);
1235 void de_module_lzss_oku(deark *c, struct deark_module_info *mi)
1237 mi->id = "lzss_oku";
1238 mi->desc = "LZSS.C by Haruhiko Okumura";
1239 mi->run_fn = de_run_lzss_oku;
1242 // **************************************************************************
1243 // LZHUF (Haruyasu Yoshizaki) compressed file
1244 // **************************************************************************
1246 static void de_run_lzhuf(deark *c, de_module_params *mparams)
1248 i64 unc_filesize;
1249 dbuf *outf = NULL;
1250 struct de_dfilter_in_params dcmpri;
1251 struct de_dfilter_out_params dcmpro;
1252 struct de_dfilter_results dres;
1254 // We're assuming the size field is 4 bytes, little-endian. (But it could
1255 // be platform-specific.)
1256 #define LZHUF_HDRSIZE 4
1257 #define LZHUF_IS_LE 1
1259 if(c->infile->len<LZHUF_HDRSIZE) goto done;
1260 unc_filesize = dbuf_getint_ext(c->infile, 0, LZHUF_HDRSIZE, LZHUF_IS_LE, 0);
1261 de_dbg(c, "orig filesize: %"I64_FMT, unc_filesize);
1263 outf = dbuf_create_output_file(c, "unc", NULL, 0);
1264 dbuf_enable_wbuffer(outf);
1265 de_dfilter_init_objects(c, &dcmpri, &dcmpro, &dres);
1266 dcmpri.f = c->infile;
1267 dcmpri.pos = LZHUF_HDRSIZE;
1268 dcmpri.len = c->infile->len-LZHUF_HDRSIZE;
1269 dcmpro.f = outf;
1270 dcmpro.len_known = 1;
1271 dcmpro.expected_len = unc_filesize;
1273 fmtutil_lh1_codectype1(c, &dcmpri, &dcmpro, &dres, NULL);
1274 dbuf_flush(outf);
1275 if(dres.errcode) {
1276 de_err(c, "Decompression failed: %s", de_dfilter_get_errmsg(c, &dres));
1278 done:
1279 dbuf_close(outf);
1282 void de_module_lzhuf(deark *c, struct deark_module_info *mi)
1284 mi->id = "lzhuf";
1285 mi->desc = "LZHUF compressed file";
1286 mi->run_fn = de_run_lzhuf;
1289 // **************************************************************************
1290 // SCO compress LZH
1291 // **************************************************************************
1293 static void de_run_compress_lzh(deark *c, de_module_params *mparams)
1295 dbuf *outf = NULL;
1296 struct de_dfilter_in_params dcmpri;
1297 struct de_dfilter_out_params dcmpro;
1298 struct de_dfilter_results dres;
1299 struct de_lh5x_params lzhparams;
1301 #define SCOLZH_HDRSIZE 2
1302 if(c->infile->len<SCOLZH_HDRSIZE) goto done;
1303 outf = dbuf_create_output_file(c, "unc", NULL, 0);
1304 dbuf_enable_wbuffer(outf);
1305 de_dfilter_init_objects(c, &dcmpri, &dcmpro, &dres);
1306 dcmpri.f = c->infile;
1307 dcmpri.pos = SCOLZH_HDRSIZE;
1308 dcmpri.len = c->infile->len-SCOLZH_HDRSIZE;
1309 dcmpro.f = outf;
1311 de_zeromem(&lzhparams, sizeof(struct de_lh5x_params));
1312 lzhparams.fmt = DE_LH5X_FMT_LH5;
1313 lzhparams.zero_codes_block_behavior = DE_LH5X_ZCB_STOP;
1315 fmtutil_decompress_lh5x(c, &dcmpri, &dcmpro, &dres, &lzhparams);
1316 dbuf_flush(outf);
1317 if(dres.errcode) {
1318 de_err(c, "Decompression failed: %s", de_dfilter_get_errmsg(c, &dres));
1320 done:
1321 dbuf_close(outf);
1324 static int de_identify_compress_lzh(deark *c)
1326 if((UI)de_getu16be(0) != 0x1fa0) return 0;
1327 if(de_input_file_has_ext(c, "z")) return 90;
1328 return 10;
1331 void de_module_compress_lzh(deark *c, struct deark_module_info *mi)
1333 mi->id = "compress_lzh";
1334 mi->desc = "SCO compress LZH";
1335 mi->run_fn = de_run_compress_lzh;
1336 mi->identify_fn = de_identify_compress_lzh;
1339 // **************************************************************************
1340 // Raw LZS (Stac) compressed data
1341 // **************************************************************************
1343 static void do_lzstac_internal(deark *c, i64 cmpr_pos, i64 cmpr_len, UI flags)
1345 dbuf *outf = NULL;
1346 struct de_dfilter_in_params dcmpri;
1347 struct de_dfilter_out_params dcmpro;
1348 struct de_dfilter_results dres;
1349 struct de_lzstac_params lzstacparams;
1351 outf = dbuf_create_output_file(c, "unc", NULL, 0);
1352 dbuf_enable_wbuffer(outf);
1353 de_dfilter_init_objects(c, &dcmpri, &dcmpro, &dres);
1354 dcmpri.f = c->infile;
1355 dcmpri.pos = cmpr_pos;
1356 dcmpri.len = cmpr_len;
1357 dcmpro.f = outf;
1359 de_zeromem(&lzstacparams, sizeof(struct de_lzstac_params));
1360 lzstacparams.flags = flags;
1361 fmtutil_lzstac_codectype1(c, &dcmpri, &dcmpro, &dres, (void*)&lzstacparams);
1363 dbuf_flush(outf);
1364 if(dres.errcode) {
1365 de_err(c, "Decompression failed: %s", de_dfilter_get_errmsg(c, &dres));
1366 goto done;
1368 if(dres.bytes_consumed_valid) {
1369 de_dbg(c, "decompressed %"I64_FMT" bytes to %"I64_FMT, dres.bytes_consumed,
1370 outf->len);
1371 if(dres.bytes_consumed<cmpr_len) {
1372 de_warn(c, "%"I64_FMT" extra bytes at end of file. File might not "
1373 "have decompressed correctly.", cmpr_len - dres.bytes_consumed);
1377 done:
1378 dbuf_close(outf);
1381 static void de_run_lzstac(deark *c, de_module_params *mparams)
1383 do_lzstac_internal(c, 0, c->infile->len, 0);
1386 void de_module_lzstac(deark *c, struct deark_module_info *mi)
1388 mi->id = "lzstac";
1389 mi->desc = "Raw LZS (Stac) compressed data";
1390 mi->run_fn = de_run_lzstac;
1393 // **************************************************************************
1394 // NPack
1395 // An installer format by Symantec & Stac
1396 // **************************************************************************
1398 static void de_run_npack(deark *c, de_module_params *mparams)
1400 // NPack decompresses at most 1 LZS block, hence the 0x2 flag.
1401 do_lzstac_internal(c, 5, c->infile->len-5, 0x2);
1404 static int de_identify_npack(deark *c)
1406 if(dbuf_memcmp(c->infile, 0, (const void*)"MSTSM", 5)) {
1407 return 0;
1409 return 85;
1412 void de_module_npack(deark *c, struct deark_module_info *mi)
1414 mi->id = "npack";
1415 mi->desc = "NPack compressed file";
1416 mi->run_fn = de_run_npack;
1417 mi->identify_fn = de_identify_npack;
1420 // **************************************************************************
1421 // LZS221
1422 // e.g. LZSDEMO v3.1 by Stac
1423 // **************************************************************************
1425 static void de_run_lzs221(deark *c, de_module_params *mparams)
1427 do_lzstac_internal(c, 4, c->infile->len-4, 0);
1430 static int de_identify_lzs221(deark *c)
1432 if(dbuf_memcmp(c->infile, 0, (const void*)"sTaC", 4)) {
1433 return 0;
1435 return 85;
1438 void de_module_lzs221(deark *c, struct deark_module_info *mi)
1440 mi->id = "lzs221";
1441 mi->desc = "LZS221 compressed file";
1442 mi->run_fn = de_run_lzs221;
1443 mi->identify_fn = de_identify_lzs221;
1446 // **************************************************************************
1447 // XPK compressed file format (XPKF)
1448 // **************************************************************************
1450 #define CODE_XPKF 0x58504b46U
1452 static void xpkf_internal(deark *c)
1454 dbuf *tmpoutf = NULL;
1455 dbuf *outf = NULL;
1456 struct de_dfilter_in_params dcmpri;
1457 struct de_dfilter_out_params dcmpro;
1458 struct de_dfilter_results dres;
1460 tmpoutf = dbuf_create_membuf(c, 0, 0);
1462 de_dfilter_init_objects(c, &dcmpri, &dcmpro, &dres);
1463 dcmpri.f = c->infile;
1464 dcmpri.pos = 0;
1465 dcmpri.len = c->infile->len;
1466 dcmpro.f = tmpoutf;
1468 fmtutil_xpk_codectype1(c, &dcmpri, &dcmpro, &dres, NULL);
1469 dbuf_flush(tmpoutf);
1471 if(dres.errcode==0 || tmpoutf->len>0) {
1472 outf = dbuf_create_output_file(c, "unc", NULL, 0);
1473 dbuf_copy(tmpoutf, 0, tmpoutf->len, outf);
1476 if(dres.errcode) {
1477 de_err(c, "Decompression failed: %s", dres.errmsg);
1478 goto done;
1481 done:
1482 dbuf_close(outf);
1483 dbuf_close(tmpoutf);
1486 static void de_run_xpk(deark *c, de_module_params *mparams)
1488 xpkf_internal(c);
1491 static int de_identify_xpk(deark *c)
1493 if((u32)de_getu32be(0)!=CODE_XPKF) return 0;
1494 return 85;
1497 void de_module_xpk(deark *c, struct deark_module_info *mi)
1499 mi->id = "xpk";
1500 mi->desc = "XPK compressed file";
1501 mi->run_fn = de_run_xpk;
1502 mi->identify_fn = de_identify_xpk;
1503 mi->flags |= DE_MODFLAG_HIDDEN;