static void do_vorbis_comment_block(deark *c, lctx *d, dbuf *f, i64 pos1) { i64 pos = pos1; i64 n; i64 ncomments; i64 k; de_ucstring *s = NULL; n = dbuf_getu32le_p(f, &pos); if(pos+n > f->len) goto done; s = ucstring_create(c); dbuf_read_to_ucstring_n(f, pos, n, DE_DBG_MAX_STRLEN, s, 0, DE_ENCODING_UTF8); de_dbg(c, "vendor: \"%s\"", ucstring_getpsz_d(s)); pos += n; ncomments = dbuf_getu32le_p(f, &pos); de_dbg(c, "number of comments: %d", (int)ncomments); for(k=0; k<ncomments; k++) { if(pos+4 > f->len) goto done; n = dbuf_getu32le_p(f, &pos); if(pos+n > f->len) goto done; ucstring_empty(s); dbuf_read_to_ucstring_n(f, pos, n, DE_DBG_MAX_STRLEN, s, 0, DE_ENCODING_UTF8); de_dbg(c, "comment[%d]: \"%s\"", (int)k, ucstring_getpsz_d(s)); pos += n; } done: ucstring_destroy(s); }
static void de_run_t64(deark *c, de_module_params *mparams) { lctx *d = NULL; de_int64 pos; de_int64 i; d = de_malloc(c, sizeof(lctx)); pos = 32; d->version = de_getui16le(pos); de_dbg(c, "version: 0x%04x\n", (int)d->version); if(d->version!=0x100 && d->version!=0x101) { de_warn(c, "Unexpected version number. This might not be a T64 file.\n"); } d->max_dir_entries = de_getui16le(pos+2); d->used_dir_entries = de_getui16le(pos+4); de_dbg(c, "max dir entries = %d, files = %d\n", (int)d->max_dir_entries, (int)d->used_dir_entries); pos += 32; for(i=0; i<d->max_dir_entries; i++) { do_dir_entry(c, d, i, pos+32*i); } de_free(c, d); }
static void do_psf1_header(deark *c, lctx *d) { de_int64 pos = 0; de_dbg(c, "PFXv1 header at %d\n", (int)pos); de_dbg_indent(c, 1); d->headersize = 4; d->mode = de_getbyte(2); de_dbg(c, "mode: 0x%02x\n", (unsigned int)d->mode); de_dbg_indent(c, 1); d->num_glyphs = (d->mode & 0x01) ? 512 : 256; de_dbg(c, "number of glyphs: %d\n", (int)d->num_glyphs); d->has_unicode_table = (d->mode & 0x02) ? 1 : 0; de_dbg(c, "has Unicode table: %s\n", d->has_unicode_table?"yes":"no"); de_dbg_indent(c, -1); d->bytes_per_glyph = (de_int64)de_getbyte(3); d->glyph_height = d->bytes_per_glyph; d->glyph_width = 8; de_dbg(c, "glyph dimensions: %dx%d\n", (int)d->glyph_width, (int)d->glyph_height); de_dbg_indent(c, -1); }
static void do_glyphs(deark *c, lctx *d) { struct de_bitmap_font *font = NULL; de_byte *font_data = NULL; de_int64 i; de_int64 glyph_rowspan; font = de_create_bitmap_font(c); font->has_nonunicode_codepoints = 1; font->nominal_width = (int)d->glyph_width; font->nominal_height = (int)d->glyph_height; font->num_chars = d->num_glyphs; // This may increase later glyph_rowspan = (d->glyph_width+7)/8; d->num_chars_alloc = d->num_glyphs; if(d->read_extra_codepoints) d->num_chars_alloc += MAX_EXTRA_CODEPOINTS; d->index_of_first_extra_codepoint = d->num_glyphs; d->num_extra_codepoints = 0; font->char_array = de_malloc(c, d->num_chars_alloc * sizeof(struct de_bitmap_font_char)); font_data = de_malloc(c, d->font_data_size); de_read(font_data, d->headersize, d->font_data_size); for(i=0; i<d->num_chars_alloc; i++) { font->char_array[i].width = font->nominal_width; font->char_array[i].height = font->nominal_height; font->char_array[i].rowspan = glyph_rowspan; if(i<d->num_glyphs) font->char_array[i].codepoint_nonunicode = (de_int32)i; else font->char_array[i].codepoint_nonunicode = DE_INVALID_CODEPOINT; font->char_array[i].codepoint_unicode = DE_INVALID_CODEPOINT; if(i<d->num_glyphs) font->char_array[i].bitmap = &font_data[i*d->bytes_per_glyph]; } if(d->has_unicode_table) { if(d->version==2) do_psf2_unicode_table(c, d, font); else do_psf1_unicode_table(c, d, font); } if(d->num_extra_codepoints>0) { font->num_chars = d->index_of_first_extra_codepoint + d->num_extra_codepoints; de_dbg(c, "codepoints aliases: %d\n", (int)d->num_extra_codepoints); de_dbg(c, "total characters: %d\n", (int)font->num_chars); } de_font_bitmap_font_to_image(c, font, NULL, 0); if(font) { de_free(c, font->char_array); de_destroy_bitmap_font(c, font); } de_free(c, font_data); }
static void handler_tRNS(deark *c, lctx *d, struct handler_params *hp) { i64 r, g, b; if(d->color_type==0) { if(hp->dlen<2) return; r = de_getu16be(hp->dpos); de_dbg(c, "transparent color gray shade: %d", (int)r); } else if(d->color_type==2) { if(hp->dlen<6) return; r = de_getu16be(hp->dpos); g = de_getu16be(hp->dpos+2); b = de_getu16be(hp->dpos+4); de_dbg(c, "transparent color: (%d,%d,%d)", (int)r, (int)g, (int)b); } else if(d->color_type==3) { i64 i; u8 a; de_dbg(c, "number of alpha values: %d", (int)hp->dlen); if(c->debug_level<2) return; for(i=0; i<hp->dlen && i<256; i++) { a = de_getbyte(hp->dpos+i); de_dbg2(c, "alpha[%3d] = %d", (int)i, (int)a); } } }
static void do_read_developer_area(deark *c, lctx *d, i64 pos) { i64 num_tags; i64 i; i64 tag_id, tag_data_pos, tag_data_size; de_dbg(c, "developer area at %d", (int)pos); if(pos > c->infile->len - 2) { de_warn(c, "Bad developer area offset: %u", (unsigned int)pos); return; } de_dbg_indent(c, 1); num_tags = de_getu16le(pos); de_dbg(c, "number of tags: %d", (int)num_tags); for(i=0; i<num_tags; i++) { if(i>=200) break; tag_id = de_getu16le(pos + 2 + 10*i); tag_data_pos = de_getu32le(pos + 2 + 10*i + 2); tag_data_size = de_getu32le(pos + 2 + 10*i + 6); de_dbg(c, "tag #%d: id=%d, pos=%d, size=%d", (int)i, (int)tag_id, (int)tag_data_pos, (int)tag_data_size); if(tag_id==20) { // Tag 20 seems to contain Photoshop resources, though this is unconfirmed. de_dbg_indent(c, 1); // TODO: We could retrieve the pixel density settings from the Photoshop data, // but it's not clear whether they are ever useful. de_fmtutil_handle_photoshop_rsrc(c, c->infile, tag_data_pos, tag_data_size, 0x0); de_dbg_indent(c, -1); } } de_dbg_indent(c, -1); }
static void de_run_gemmeta(deark *c, de_module_params *mparams) { lctx *d = NULL; de_int64 pos; de_int64 hdrlen_words; de_int64 version; de_int64 imgflag; de_int64 bytesused; d = de_malloc(c, sizeof(lctx)); de_msg(c, "Note: GEM VDI Metafiles can be parsed, but no files can be extracted from them.\n"); pos = 0; hdrlen_words = de_getui16le(pos+2); de_dbg(c, "header length: %d words\n", (int)hdrlen_words); version = de_getui16le(pos+4); de_dbg(c, "version number: %d\n", (int)version); // TODO: Read more header fields. imgflag = de_getui16le(pos+28); de_dbg(c, "image flag: %d\n", (int)imgflag); pos += hdrlen_words*2; while(1) { if(pos >= c->infile->len) break; if(!do_record(c, d, pos, &bytesused)) break; if(bytesused<=0) break; pos += bytesused; } de_free(c, d); }
static void handler_IHDR(deark *c, lctx *d, struct handler_params *hp) { i64 w, h; u8 n; const char *name; if(hp->dlen<13) return; w = de_getu32be(hp->dpos); h = de_getu32be(hp->dpos+4); de_dbg_dimensions(c, w, h); n = de_getbyte(hp->dpos+8); de_dbg(c, "depth: %d bits/sample", (int)n); d->color_type = de_getbyte(hp->dpos+9); switch(d->color_type) { case 0: name="grayscale"; break; case 2: name="truecolor"; break; case 3: name="palette"; break; case 4: name="grayscale+alpha"; break; case 6: name="truecolor+alpha"; break; default: name="?"; } de_dbg(c, "color type: %d (%s)", (int)d->color_type, name); n = de_getbyte(hp->dpos+12); de_dbg(c, "interlaced: %d", (int)n); }
static int read_pnm_header(deark *c, lctx *d, struct page_ctx *pg, de_int64 pos1) { char tokenbuf[100]; int retval = 0; de_dbg(c, "header at %d\n", (int)pos1); de_dbg_indent(c, 1); de_dbg(c, "format: %s\n", pg->fmt_name); pg->hdr_parse_pos = pos1+2; // Skip "P?" if(!read_next_token(c, d, pg, tokenbuf, sizeof(tokenbuf))) goto done; pg->width = de_atoi64(tokenbuf); if(!read_next_token(c, d, pg, tokenbuf, sizeof(tokenbuf))) goto done; pg->height = de_atoi64(tokenbuf); de_dbg(c, "dimensions: %dx%d\n", (int)pg->width, (int)pg->height); if(fmt_is_pbm(pg->fmt)) { pg->maxval = 1; } else { if(!read_next_token(c, d, pg, tokenbuf, sizeof(tokenbuf))) goto done; pg->maxval = de_atoi64(tokenbuf); de_dbg(c, "maxval: %d\n", (int)pg->maxval); if(pg->maxval<1 || pg->maxval>65535) { de_err(c, "Invalid maxval: %d\n", (int)pg->maxval); goto done; } } retval = 1; done: de_dbg_indent(c, -1); return retval; }
static void do_extract_file(deark *c, lctx *d, de_int64 dir_pos, de_byte filetype_c64s, de_byte filetype) { de_int64 load_addr; de_int64 end_addr; de_int64 offset; dbuf *f = NULL; de_int64 payload_size; // = file_size-2 de_ucstring *fname = NULL; de_int64 fname_len; de_int64 i; de_int64 fnpos; de_finfo *fi = NULL; load_addr = de_getui16le(dir_pos+2); end_addr = de_getui16le(dir_pos+4); offset = de_getui32le(dir_pos+8); de_dbg(c, "load_addr=%d end_addr=%d offset=%d\n", (int)load_addr, (int)end_addr, (int)offset); // File name at pos+16 fnpos = dir_pos+16; // Find the length of the (space-padded) filename. fname_len = 0; for(i=15; i>=0; i--) { if(de_getbyte(fnpos+i)!=' ') { fname_len = i+1; break; } } de_dbg2(c, "filename length: %d\n", (int)fname_len); fname = ucstring_create(c); dbuf_read_to_ucstring(c->infile, fnpos, fname_len, fname, 0, DE_ENCODING_PETSCII); de_dbg(c, "filename: \"%s\"\n", ucstring_get_printable_sz(fname)); ucstring_append_sz(fname, ".prg", DE_ENCODING_ASCII); fi = de_finfo_create(c); de_finfo_set_name_from_ucstring(c, fi, fname); fi->original_filename_flag = 1; payload_size = end_addr - load_addr; if(payload_size < 0) { // TODO: Try to support files that don't have end_addr set properly. de_err(c, "This type of T64 file is not supported.\n"); goto done; } f = dbuf_create_output_file(c, NULL, fi, 0); dbuf_copy(c->infile, dir_pos+2, 2, f); dbuf_copy(c->infile, offset, payload_size, f); done: dbuf_close(f); de_finfo_destroy(c, fi); ucstring_destroy(fname); }
static void do_dir_entry(deark *c, lctx *d, de_int64 entry_num, de_int64 pos) { de_byte filetype_c64s; de_byte filetype; filetype_c64s = de_getbyte(pos); if(filetype_c64s==0) { de_dbg2(c, "unused entry #%d at %d\n", (int)entry_num, (int)pos); return; } de_dbg(c, "entry #%d at %d\n", (int)entry_num, (int)pos); de_dbg_indent(c, 1); filetype = de_getbyte(pos+1); de_dbg(c, "c64s filetype=%d, filetype=0x%02x\n", (int)filetype_c64s, (int)filetype); if(filetype==0x00) { de_err(c, "Unsupported file type (0x%02x)\n", (int)filetype); } else { do_extract_file(c, d, pos, filetype_c64s, filetype); } de_dbg_indent(c, -1); }
static int read_fileheader(deark *c, lctx *d, de_int64 pos) { de_dbg(c, "file header at %d\n", (int)pos); de_dbg_indent(c, 1); de_dbg(c, "bfSize: %d\n", (int)d->fsize); d->bits_offset = de_getui32le(pos+10); de_dbg(c, "bfOffBits: %d\n", (int)d->bits_offset); de_dbg_indent(c, -1); return 1; }
static int do_header(deark *c, lctx *d, i64 pos) { de_dbg(c, "header at %d", (int)pos); de_dbg_indent(c, 1); d->nlumps = de_getu32le(pos+4); de_dbg(c, "#lumps: %d", (int)d->nlumps); d->dir_pos = de_getu32le(pos+8); de_dbg(c, "dir pos: %d", (int)d->dir_pos); de_dbg_indent(c, -1); return 1; }
// Some MacPaint files contain a collection of brush patterns. // Essentially, MacPaint saves workspace settings inside image files. // (But these patterns are the only setting.) static void do_read_patterns(deark *c, lctx *d, de_int64 pos) { de_int64 cell; de_int64 i, j; de_byte x; const de_int64 dispwidth = 19; const de_int64 dispheight = 17; de_int64 xpos, ypos; int is_blank; struct deark_bitmap *pat = NULL; de_uint32 patcrc; const char *patsetname; pos += 4; patcrc = x_dbuf_crc32(c->infile, pos, 38*8); patsetname = get_pattern_set_info(patcrc, &is_blank); de_dbg(c, "brush patterns crc: 0x%08x (%s)\n", (unsigned int)patcrc, patsetname); if(c->extract_level<2) { goto done; } if(is_blank) { de_dbg(c, "brush patterns are blank: not extracting\n"); goto done; } pat = de_bitmap_create(c, (dispwidth+1)*19+1, (dispheight+1)*2+1, 1); for(cell=0; cell<38; cell++) { xpos = (dispwidth+1)*(cell%19)+1; ypos = (dispheight+1)*(cell/19)+1; for(j=0; j<dispheight; j++) { for(i=0; i<dispwidth; i++) { // TODO: Figure out the proper "brush origin" of these patterns. // Some of them may be shifted differently than MacPaint displays them. x = de_get_bits_symbol(c->infile, 1, pos+cell*8+j%8, i%8); // 0 = white. Only need to set the white pixels, since they start out // black. if(x==0) { de_bitmap_setpixel_gray(pat, xpos+i, ypos+j, 255); } } } } de_bitmap_write_to_file(pat, "pat", DE_CREATEFLAG_IS_AUX); done: de_bitmap_destroy(pat); }
// Returns 0 if we should stop reading the file. static int do_record(deark *c, lctx *d, de_int64 pos, de_int64 *bytesused) { int retval = 0; struct opcode_data op; de_int64 ptsin_size_bytes; de_int64 intin_size_bytes; de_int64 data_size_bytes; const struct opcode_info *opinfo; const char *opcode_name; *bytesused = 0; de_memset(&op, 0, sizeof(struct opcode_data)); de_dbg(c, "record at %d\n", (int)pos); de_dbg_indent(c, 1); op.opcode = de_getui16le(pos); op.ptsin_count = de_getui16le(pos+2); op.intin_count = de_getui16le(pos+4); op.func_id = de_getui16le(pos+6); ptsin_size_bytes = 4*op.ptsin_count; intin_size_bytes = 2*op.intin_count; data_size_bytes = ptsin_size_bytes + intin_size_bytes; op.ptsin_pos = pos + 8; op.intin_pos = pos + 8 + ptsin_size_bytes; opinfo = find_opcode_info(op.opcode); if(opinfo && opinfo->name) opcode_name = opinfo->name; else opcode_name = "?"; de_dbg(c, "opcode=%d (%s), func_id=%d, #pts=%d, #int=%d (dlen=%d)\n", (int)op.opcode, opcode_name, (int)op.func_id, (int)op.ptsin_count, (int)op.intin_count, (int)data_size_bytes); *bytesused = 8 + data_size_bytes; if(opinfo && opinfo->fn) { opinfo->fn(c, d, &op); } if(op.opcode==65535) { goto done; } retval = 1; done: de_dbg_indent(c, -1); return retval; }
static void handler_sPLT(deark *c, lctx *d, struct handler_params *hp) { struct de_stringreaderdata *srd = NULL; i64 pos = hp->dpos; i64 nbytes_to_scan; u8 depth; i64 nentries; i64 stride; i64 i; nbytes_to_scan = hp->dlen; if(nbytes_to_scan>80) nbytes_to_scan=80; srd = dbuf_read_string(c->infile, pos, nbytes_to_scan, 79, DE_CONVFLAG_STOP_AT_NUL, DE_ENCODING_LATIN1); if(!srd->found_nul) goto done; de_dbg(c, "palette name: \"%s\"", ucstring_getpsz(srd->str)); pos += srd->bytes_consumed; if(pos >= hp->dpos+hp->dlen) goto done; depth = de_getbyte(pos++); de_dbg(c, "depth: %d", (int)depth); if(depth!=8 && depth!=16) goto done; stride = (depth==8) ? 6 : 10; nentries = (hp->dpos+hp->dlen-pos)/stride; de_dbg(c, "number of entries: %d", (int)nentries); if(c->debug_level<2) goto done; for(i=0; i<nentries; i++) { unsigned int cr, cg, cb, ca, cf; if(depth==8) { cr = (unsigned int)de_getbyte(pos); cg = (unsigned int)de_getbyte(pos+1); cb = (unsigned int)de_getbyte(pos+2); ca = (unsigned int)de_getbyte(pos+3); cf = (unsigned int)de_getu16be(pos+4); de_dbg2(c, "pal[%3d] = (%3u,%3u,%3u,A=%u) F=%u", (int)i, cr, cg, cb, ca, cf); } else { cr = (unsigned int)de_getu16be(pos); cg = (unsigned int)de_getu16be(pos+2); cb = (unsigned int)de_getu16be(pos+4); ca = (unsigned int)de_getu16be(pos+6); cf = (unsigned int)de_getu16be(pos+8); de_dbg2(c, "pal[%3d] = (%5u,%5u,%5u,A=%u) F=%u", (int)i, cr, cg, cb, ca, cf); } pos += stride; } done: de_destroy_stringreaderdata(c, srd); }
static void handler_acTL(deark *c, lctx *d, struct handler_params *hp) { unsigned int n; i64 pos = hp->dpos; if(hp->dlen<8) return; n = (unsigned int)de_getu32be_p(&pos); de_dbg(c, "num frames: %u", n); n = (unsigned int)de_getu32be_p(&pos); de_dbg(c, "num plays: %u%s", n, (n==0)?" (infinite)":""); }
static void handler_caNv(deark *c, lctx *d, struct handler_params *hp) { i64 x0, x1; if(hp->dlen<16) return; x0 = de_geti32be(hp->dpos); x1 = de_geti32be(hp->dpos+4); de_dbg(c, "caNv dimensions: %dx%d", (int)x0, (int)x1); x0 = de_geti32be(hp->dpos+8); x1 = de_geti32be(hp->dpos+12); de_dbg(c, "caNv position: %d,%d", (int)x0, (int)x1); }
static void de_run_macpaint(deark *c, de_module_params *mparams) { lctx *d; de_int64 pos; const char *s; d = de_malloc(c, sizeof(lctx)); d->has_macbinary_header = -1; s = de_get_ext_option(c, "macpaint:macbinary"); if(s) d->has_macbinary_header = de_atoi(s); if(d->has_macbinary_header == -1) { int v512; int v640; de_dbg(c, "trying to determine if file has a MacBinary header\n"); v512 = valid_file_at(c, d, 0); v640 = valid_file_at(c, d, 128); if(v512 > v640) { de_dbg(c, "assuming it has no MacBinary header\n"); d->has_macbinary_header = 0; } else if(v640 > v512) { de_dbg(c, "assuming it has a MacBinary header\n"); d->has_macbinary_header = 1; } else if(v512 && v640) { de_warn(c, "Can't determine if this file has a MacBinary header. " "Try \"-opt macpaint:macbinary=0\".\n"); d->has_macbinary_header = 1; } else { de_warn(c, "This is probably not a MacPaint file.\n"); d->has_macbinary_header = 1; } } if(d->has_macbinary_header) de_declare_fmt(c, "MacPaint with MacBinary header"); else de_declare_fmt(c, "MacPaint without MacBinary header"); pos = d->has_macbinary_header ? 128 : 0; do_read_bitmap(c, d, pos); do_read_patterns(c, d, pos); de_free(c, d); }
static void do_psf2_header(deark *c, lctx *d) { de_int64 pos = 0; de_dbg(c, "PFXv2 header at %d\n", (int)pos); de_dbg_indent(c, 1); d->psf2_version = (de_uint32)de_getui32le(pos+4); de_dbg(c, "PSFv2 version number: %d\n", (int)d->psf2_version); if(d->psf2_version!=0) { de_warn(c, "Unknown PSFv2 version number: %d\n", (int)d->psf2_version); } d->headersize = de_getui32le(pos+8); de_dbg(c, "header size: %d\n", (int)d->headersize); d->flags = (de_uint32)de_getui32le(pos+12); de_dbg(c, "flags: 0x%08x\n", (unsigned int)d->flags); de_dbg_indent(c, 1); d->has_unicode_table = (d->flags & 0x01) ? 1 : 0; de_dbg(c, "has Unicode table: %s\n", d->has_unicode_table?"yes":"no"); de_dbg_indent(c, -1); d->num_glyphs = de_getui32le(pos+16); de_dbg(c, "number of glyphs: %d\n", (int)d->num_glyphs); d->bytes_per_glyph = de_getui32le(pos+20); de_dbg(c, "bytes per glyph: %d\n", (int)d->bytes_per_glyph); d->glyph_height = de_getui32le(pos+24); d->glyph_width = de_getui32le(pos+28); de_dbg(c, "glyph dimensions: %dx%d\n", (int)d->glyph_width, (int)d->glyph_height); de_dbg_indent(c, -1); }
static void do_read_linked_profile(deark *c, lctx *d) { de_ucstring *fname = NULL; de_dbg(c, "linked profile filename at %d\n", (int)d->profile_offset); fname = ucstring_create(c); dbuf_read_to_ucstring_n(c->infile, d->profile_offset, d->profile_size, 300, fname, DE_CONVFLAG_STOP_AT_NUL, DE_ENCODING_WINDOWS1252); de_dbg_indent(c, 1); de_dbg(c, "profile filename: \"%s\"\n", ucstring_get_printable_sz(fname)); de_dbg_indent(c, -1); ucstring_destroy(fname); }
// This .vst (TrueVista) decoder is based on guesswork, on the limited information // in the TGA spec, and on the behavior of XnView. It may not be correct. static int do_read_vst_headers(deark *c, lctx *d) { int retval = 0; de_dbg(c, "header at %d", 0); de_dbg_indent(c, 1); d->id_field_len = (i64)de_getbyte(0); if(d->id_field_len==0) { // ??? XnView seems to do something like this. d->id_field_len=18; } d->cmpr_type = TGA_CMPR_NONE; d->cmpr_name = "none"; d->main_image.width = de_getu16le(12); d->main_image.height = de_getu16le(14); de_dbg_dimensions(c, d->main_image.width, d->main_image.height); d->pixel_depth = (i64)de_getbyte(16); de_dbg(c, "pixel depth: %d", (int)d->pixel_depth); if(d->pixel_depth==8) { d->color_map_type = 1; d->color_type = TGA_CLRTYPE_PALETTE; d->clrtype_name = "palette"; } else { d->color_type = TGA_CLRTYPE_TRUECOLOR; d->clrtype_name = "truecolor"; } if(d->color_type==TGA_CLRTYPE_PALETTE) { d->cmap_start = 0; d->cmap_length = 256; d->cmap_depth = 24; } do_read_image_descriptor(c, d); de_dbg_indent(c, -1); if(!de_good_image_dimensions(c, d->main_image.width, d->main_image.height)) goto done; retval = 1; done: return retval; }
static void do_picture_metafile(deark *c, lctx *d, struct para_info *pinfo) { i64 pos = pinfo->thisparapos; i64 cbHeader, cbSize; cbHeader = de_getu16le(pos+30); de_dbg(c, "cbHeader: %d", (int)cbHeader); cbSize = de_getu32le(pos+32); de_dbg(c, "cbSize: %d", (int)cbSize); if(cbHeader+cbSize <= pinfo->thisparalen) { dbuf_create_file_from_slice(c->infile, pos+cbHeader, cbSize, "wmf", NULL, 0); } }
static void do_paragraph(deark *c, lctx *d, struct para_info *pinfo) { if(pinfo->papflags&0x10) { de_dbg(c, "picture at %d, len=%d", (int)pinfo->thisparapos, (int)pinfo->thisparalen); de_dbg_indent(c, 1); do_picture(c, d, pinfo); de_dbg_indent(c, -1); } else { de_dbg(c, "text paragraph at %d, len=%d", (int)pinfo->thisparapos, (int)pinfo->thisparalen); do_text_paragraph(c, d, pinfo); } }
static void do_extract_png_or_jp2(deark *c, lctx *d, struct page_ctx *pg) { de_byte buf[8]; de_finfo *fi = NULL; de_dbg(c, "Trying to extract file at %d\n", (int)pg->image_pos); // Detect the format de_read(buf, pg->image_pos, sizeof(buf)); fi = de_finfo_create(c); de_finfo_set_name_from_sz(c, fi, pg->filename_token, DE_ENCODING_ASCII); if(buf[4]=='j' && buf[5]=='P') { dbuf_create_file_from_slice(c->infile, pg->image_pos, pg->image_len, "jp2", fi, 0); } else if(buf[0]==0x89 && buf[1]==0x50) { dbuf_create_file_from_slice(c->infile, pg->image_pos, pg->image_len, "png", fi, 0); } else { de_err(c, "(Image #%d) Unidentified file format\n", pg->image_num); } de_finfo_destroy(c, fi); }
static void de_run_cardfile(deark *c, de_module_params *mparams) { lctx *d = NULL; de_byte b; de_int64 pos; de_int64 n; d = de_malloc(c, sizeof(lctx)); pos = 0; b = de_getbyte(pos); if(b=='R') d->fmt=DE_CRDFMT_RRG; else d->fmt=DE_CRDFMT_MGC; if(d->fmt==DE_CRDFMT_RRG) { de_err(c, "CardFile RRG format is not supported\n"); goto done; } pos+=3; d->numcards = de_getui16le(pos); de_dbg(c, "number of cards: %d\n", (int)d->numcards); pos+=2; for(n=0; n<d->numcards; n++) { do_card_index(c, d, n, pos); pos+=52; } done: de_free(c, d); }
static void do_opo_opa(deark *c, lctx *d) { de_int64 offset_2ndheader; de_int64 pos; de_int64 n; de_int64 len; de_declare_fmt(c, "Psion OPO/OPA"); // The second header marks the end of the embedded files section, I guess. offset_2ndheader = de_getui16le(18); de_dbg(c, "offset of second header: %d\n", (int)offset_2ndheader); pos = 20; // Read length of source filename n = (de_int64)de_getbyte(pos); pos++; pos+=n; while(pos<offset_2ndheader) { // Read length of this embedded file len = de_getui16le(pos); pos+=2; handle_embedded_file(c, d, pos, len); pos+=len; } }
static int do_decode_rle(deark *c, lctx *d, i64 pos1, dbuf *unc_pixels) { u8 b; i64 count; i64 k; u8 buf[8]; i64 pos = pos1; while(1) { if(pos >= c->infile->len) break; if(unc_pixels->len >= d->main_image.img_size_in_bytes) break; b = de_getbyte(pos); pos++; if(b & 0x80) { // RLE block count = (i64)(b - 0x80) + 1; de_read(buf, pos, d->bytes_per_pixel); pos += d->bytes_per_pixel; for(k=0; k<count; k++) { dbuf_write(unc_pixels, buf, d->bytes_per_pixel); } } else { // uncompressed block count = (i64)(b) + 1; dbuf_copy(c->infile, pos, count * d->bytes_per_pixel, unc_pixels); pos += count * d->bytes_per_pixel; } } de_dbg(c, "decompressed %d bytes to %d bytes", (int)(pos-pos1), (int)unc_pixels->len); return 1; }
static void do_opcode_5(deark *c, lctx *d, struct opcode_data *op) { de_int64 sub_opcode_id; const char *name; if(op->func_id!=99) return; if(op->intin_count<1) return; sub_opcode_id = de_getui16le(op->intin_pos); switch(sub_opcode_id) { case 10: name="Start Group"; break; case 11: name="End Group"; break; case 49: name="Set No Line Style"; break; case 50: name="Set Attribute Shadow On"; break; case 51: name="Set Attribute Shadow Off"; break; case 80: name="Start Draw Area Type Primitive"; break; case 81: name="End Draw Area Type Primitive"; break; default: if(sub_opcode_id>100) { name="for developer use"; } else { name="?"; } } de_dbg(c, "sub-opcode id: %d (%s)\n", (int)sub_opcode_id, name); }
static void do_read_bitmap(deark *c, lctx *d, de_int64 pos) { de_int64 ver_num; dbuf *unc_pixels = NULL; ver_num = de_getui32be(pos); de_dbg(c, "version number: %u\n", (unsigned int)ver_num); if(ver_num!=0 && ver_num!=2 && ver_num!=3) { de_warn(c, "Unrecognized version number: %u\n", (unsigned int)ver_num); } pos += 512; unc_pixels = dbuf_create_membuf(c, MACPAINT_IMAGE_BYTES, 1); de_fmtutil_uncompress_packbits(c->infile, pos, c->infile->len - pos, unc_pixels, NULL); if(unc_pixels->len < MACPAINT_IMAGE_BYTES) { de_warn(c, "Image decompressed to %d bytes, expected %d.\n", (int)unc_pixels->len, (int)MACPAINT_IMAGE_BYTES); } de_convert_and_write_image_bilevel(unc_pixels, 0, MACPAINT_WIDTH, MACPAINT_HEIGHT, MACPAINT_WIDTH/8, DE_CVTF_WHITEISZERO, NULL, 0); dbuf_close(unc_pixels); }