Beispiel #1
0
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;
	}
}
Beispiel #2
0
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);
}
Beispiel #3
0
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);
}
Beispiel #4
0
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);
}
Beispiel #5
0
// 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;
}
Beispiel #6
0
// Sets d->version, and certain header fields.
static int detect_bmp_version(deark *c, lctx *d)
{
	de_int64 pos;

	pos = 0;
	d->fsize = de_getui32le(pos+2);

	pos += FILEHEADER_SIZE;
	d->infohdrsize = de_getui32le(pos);

	if(d->infohdrsize<=12) {
		d->bitcount = de_getui16le(pos+10);
	}
	else {
		d->bitcount = de_getui16le(pos+14);
	}

	if(d->infohdrsize==12) {
		d->version = DE_BMPVER_OS2V1;
		return 1;
	}
	if(d->infohdrsize<16) {
		return 0;
	}

	if(d->infohdrsize>=20) {
		d->compression_field = (de_uint32)de_getui32le(pos+16);
	}

	if(d->infohdrsize>=16 && d->infohdrsize<=64) {
		if(d->fsize==FILEHEADER_SIZE+d->infohdrsize) {
			d->version = DE_BMPVER_OS2V2;
			return 1;
		}

		if((d->compression_field==3 && d->bitcount==1) ||
			(d->compression_field==4 && d->bitcount==24))
		{
			d->version = DE_BMPVER_OS2V2;
			return 1;
		}

		if(d->infohdrsize!=40 && d->infohdrsize!=52 && d->infohdrsize!=56) {
			d->version = DE_BMPVER_OS2V2;
			return 1;
		}
	}

	d->version = DE_BMPVER_WINV345;
	return 1;
}
Beispiel #7
0
static void do_img_app(deark *c, lctx *d)
{
	de_int64 i;
	de_int64 offset;
	de_int64 len;

	de_declare_fmt(c, "Psion IMG/APP");

	for(i=0; i<4; i++) {
		offset = de_getui16le(40 + 4*i);
		len = de_getui16le(40 + 4*i + 2);
		if(offset==0) break;
		handle_embedded_file(c, d, offset, len);
	}
}
Beispiel #8
0
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);
}
Beispiel #9
0
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);
}
Beispiel #10
0
static void do_psf1_unicode_table(deark *c, lctx *d, struct de_bitmap_font *font)
{
	de_int64 cur_idx;
	de_int64 pos;
	int got_cp;
	int found_fffe;
	de_int32 n;

	de_dbg(c, "Unicode table at %d\n", (int)d->unicode_table_pos);
	de_dbg_indent(c, 1);

	pos = d->unicode_table_pos;
	cur_idx = 0;
	got_cp = 0; // Have we set the codepoint for glyph[cur_idx]?
	found_fffe = 0;

	while(1) {
		if(cur_idx >= d->num_glyphs) break;
		if(pos+1 >= c->infile->len) break;
		n = (de_int32)de_getui16le(pos);
		pos+=2;

		if(n==0xffff) {
			if(!got_cp) {
				de_warn(c, "Missing codepoint for char #%d\n", (int)cur_idx);
			}
			cur_idx++;
			got_cp = 0;
			found_fffe = 0;
			continue;
		}
		else if(n==0xfffe) {
			found_fffe = 1;
		}

		if(found_fffe) {
			// Anything after 0xfffe is a multi-codepoint character, which we
			// don't support.
			continue;
		}

		if(!got_cp) {
			de_dbg2(c, "char[%d] = U+%04x\n", (int)cur_idx, (unsigned int)n);
			font->char_array[cur_idx].codepoint_unicode = n;
			got_cp = 1;
			continue;
		}

		// This is an "extra" codepoint for the current glyph.
		do_extra_codepoint(c, d, font, cur_idx, n);
	}

	font->has_unicode_codepoints = 1;
	font->prefer_unicode = 1;

	de_dbg_indent(c, -1);
}
Beispiel #11
0
static int de_identify_fnt(deark *c)
{
	de_int64 ver;

	// TODO: Better format detection.
	if(de_input_file_has_ext(c, "fnt")) {
		ver = de_getui16le(0);
		if(ver==0x0100 || ver==0x0200 || ver==0x0300)
			return 10;
	}
	return 0;
}
Beispiel #12
0
// Find the widest character.
static void do_prescan_chars(deark *c, lctx *d)
{
	de_int64 i;
	de_int64 pos;
	de_int64 char_width;

	for(i=0; i<d->num_chars_stored; i++) {
		pos = d->hdrsize + d->char_entry_size*i;
		char_width = de_getui16le(pos);

		if(char_width > d->detected_max_width) {
			d->detected_max_width = char_width;
		}
	}
	de_dbg(c, "detected max width: %d\n", (int)d->detected_max_width);
}
Beispiel #13
0
static void do_card_index(deark *c, lctx *d, de_int64 cardnum, de_int64 pos)
{
	de_int64 datapos;
	de_int64 bitmap_len;
	de_int64 w, h;
	de_int64 src_rowspan;
	de_int64 text_len;
	de_int64 text_pos;
	struct deark_bitmap *img = NULL;
	de_finfo *fi_bitmap = NULL;
	de_finfo *fi_text = NULL;
	const char *cardtype;
	de_ucstring *name = NULL;
	int saved_indent_level;

	de_dbg_indent_save(c, &saved_indent_level);

	datapos = de_getui32le(pos+6);
	de_dbg(c, "card #%d at %d, dpos=%d\n", (int)cardnum, (int)pos, (int)datapos);
	de_dbg_indent(c, 1);

	if(datapos>=c->infile->len) goto done;
	bitmap_len = de_getui16le(datapos);
	de_dbg(c, "bitmap length: %d\n", (int)bitmap_len);

	if(bitmap_len==0) {
		text_len = de_getui16le(datapos+2);
		text_pos = datapos+4;
	}
	else {
		text_len = de_getui16le(datapos + bitmap_len + 10);
		text_pos = datapos + bitmap_len + 10;
	}
	de_dbg(c, "text length: %d\n", (int)text_len);

	if(bitmap_len==0 && text_len==0) {
		cardtype = "empty";
	}
	else if(bitmap_len==0) {
		cardtype = "text-only";
	}
	else if(text_len==0) {
		cardtype = "graphics-only";
	}
	else {
		cardtype = "graphics+text";
	}
	de_dbg(c, "card type: %s\n", cardtype);

	if(bitmap_len==0 && text_len==0) {
		goto done;
	}

	name = ucstring_create(c);
	dbuf_read_to_ucstring(c->infile, pos+11, 40, name, DE_CONVFLAG_STOP_AT_NUL, DE_ENCODING_ASCII);
	de_dbg(c, "name: \"%s\"\n", ucstring_get_printable_sz(name));

	// Text

	if(text_len!=0 && c->extract_level>=2) {
		fi_text = de_finfo_create(c);
		if(c->filenames_from_file)
			de_finfo_set_name_from_ucstring(c, fi_text, name);

		do_text_data(c, d, fi_text, text_pos, text_len);
	}

	// Bitmap

	if(bitmap_len==0) goto done;

	fi_bitmap = de_finfo_create(c);
	if(c->filenames_from_file)
		de_finfo_set_name_from_ucstring(c, fi_bitmap, name);

	w = de_getui16le(datapos+2);
	h = de_getui16le(datapos+4);
	de_dbg(c, "bitmap dimensions: %dx%d\n", (int)w, (int)h);

	img = de_bitmap_create(c, w, h, 1);
	src_rowspan = ((w+15)/16)*2;

	de_convert_and_write_image_bilevel(c->infile, datapos+10,
		w, h, src_rowspan, 0, fi_bitmap, 0);

done:
	ucstring_destroy(name);
	de_bitmap_destroy(img);
	de_finfo_destroy(c, fi_bitmap);
	de_finfo_destroy(c, fi_text);
	de_dbg_indent_restore(c, saved_indent_level);
}
Beispiel #14
0
// Read any version of BITMAPINFOHEADER.
//
// Note: Some of this BMP parsing code is duplicated in the
// de_fmtutil_get_bmpinfo() library function. The BMP module's needs are
// not quite aligned with what that function is intended for, and it
// would be too messy to try to add the necessary features to it.
static int read_infoheader(deark *c, lctx *d, de_int64 pos)
{
	de_int64 height_raw;
	de_int64 clr_used_raw;
	int cmpr_ok;
	int retval = 0;

	de_dbg(c, "info header at %d\n", (int)pos);
	de_dbg_indent(c, 1);
	de_dbg(c, "info header size: %d\n", (int)d->infohdrsize);

	if(d->version==DE_BMPVER_OS2V1) {
		d->width = de_getui16le(pos+4);
		d->height = de_getui16le(pos+6);
	}
	else {
		d->width = dbuf_geti32le(c->infile, pos+4);
		height_raw = dbuf_geti32le(c->infile, pos+8);
		if(height_raw<0) {
			d->top_down = 1;
			d->height = -height_raw;
		}
		else {
			d->height = height_raw;
		}
	}
	de_dbg(c, "dimensions: %dx%d\n", (int)d->width, (int)d->height);
	if(!de_good_image_dimensions(c, d->width, d->height)) {
		goto done;
	}
	if(d->top_down) {
		de_dbg(c, "orientation: top-down\n");
	}

	// Already read, in detect_bmp_version()
	de_dbg(c, "bits/pixel: %d\n", (int)d->bitcount);

	if(d->bitcount!=0 && d->bitcount!=1 && d->bitcount!=2 && d->bitcount!=4 &&
		d->bitcount!=8 && d->bitcount!=16 && d->bitcount!=24 && d->bitcount!=32)
	{
		de_err(c, "Bad bits/pixel: %d\n", (int)d->bitcount);
		goto done;
	}

	if(d->version==DE_BMPVER_OS2V1) {
		d->bytes_per_pal_entry = 3;
	}
	else {
		// Already read, in detect_bmp_version()
		de_dbg(c, "compression (etc.): %d\n", (int)d->compression_field);
		d->bytes_per_pal_entry = 4;
	}

	d->compression_type = CMPR_NONE; // Temporary default

	cmpr_ok = 0;
	switch(d->compression_field) {
	case 0: // BI_RGB
		if(d->bitcount==16 || d->bitcount==32) {
			d->bitfields_type = BF_DEFAULT;
		}
		d->compression_type = CMPR_NONE;
		cmpr_ok = 1;
		break;
	case 1: // BI_RLE8
		d->compression_type=CMPR_RLE8;
		cmpr_ok = 1;
		break;
	case 2: // BI_RLE4
		d->compression_type=CMPR_RLE4;
		cmpr_ok = 1;
		break;
	case 3: // BI_BITFIELDS or Huffman_1D
		if(d->version==DE_BMPVER_OS2V2) {
			if(d->bitcount==1) {
				d->compression_type=CMPR_HUFFMAN1D;
				cmpr_ok = 1;
			}
		}
		else if(d->bitcount==16 || d->bitcount==32) {
			d->compression_type = CMPR_NONE;
			cmpr_ok = 1;
			if(d->infohdrsize>=52) {
				d->bitfields_type = BF_IN_HEADER;
			}
			else {
				d->bitfields_type = BF_SEGMENT;
				d->bitfields_segment_len = 12;
			}
		}
		break;
	case 4: // BI_JPEG or RLE24
		if(d->version==DE_BMPVER_OS2V2) {
			if(d->bitcount==24) {
				d->compression_type=CMPR_RLE24;
				cmpr_ok = 1;
			}
		}
		else {
			d->compression_type=CMPR_JPEG;
			cmpr_ok = 1;
		}
		break;
	case 5: // BI_PNG
		d->compression_type=CMPR_PNG;
		cmpr_ok = 1;
		break;
	case 6: // BI_ALPHABITFIELDS
		if(d->bitcount==16 || d->bitcount==32) {
			d->compression_type = CMPR_NONE;
			cmpr_ok = 1;
			if(d->infohdrsize>=56) {
				d->bitfields_type = BF_IN_HEADER;
			}
			else {
				d->bitfields_type = BF_SEGMENT;
				d->bitfields_segment_len = 16;
			}
		}
		break;
	}

	if(!cmpr_ok) {
		de_err(c, "Unsupported compression type: %d\n", (int)d->compression_field);
		goto done;
	}

	if(d->infohdrsize>=24) {
		d->size_image = de_getui32le(pos+20);
		de_dbg(c, "biSizeImage: %d\n", (int)d->size_image);
	}

	if(d->infohdrsize>=32) {
		d->xpelspermeter = dbuf_geti32le(c->infile, pos+24);
		d->ypelspermeter = dbuf_geti32le(c->infile, pos+28);
		de_dbg(c, "density: %dx%d pixels/meter\n", (int)d->xpelspermeter, (int)d->ypelspermeter);
	}

	if(d->infohdrsize>=36)
		clr_used_raw = de_getui32le(pos+32);
	else
		clr_used_raw = 0;

	if(d->bitcount>=1 && d->bitcount<=8 && clr_used_raw==0) {
		d->pal_entries = ((de_int64)1)<<d->bitcount;
	}
	else {
		d->pal_entries = clr_used_raw;
	}
	de_dbg(c, "number of palette colors: %d\n", (int)d->pal_entries);

	// Note that after 40 bytes, WINV345 and OS2V2 header fields are different,
	// so we have to pay more attention to the version.

	if(d->bitfields_type==BF_IN_HEADER) {
		do_read_bitfields(c, d, pos+40, d->infohdrsize>=56 ? 16 : 12);
	}

	if(d->bitfields_type==BF_DEFAULT) {
		set_default_bitfields(c, d);
	}

	if(d->version==DE_BMPVER_WINV345 && d->infohdrsize>=108) {
		dbuf_read_fourcc(c->infile, pos+56, &d->cstype4cc, 1);
		de_dbg(c, "CSType: 0x%08x ('%s')\n", (unsigned int)d->cstype4cc.id,
			d->cstype4cc.id_printable);
	}

	if(d->version==DE_BMPVER_WINV345 && d->infohdrsize>=124 &&
		(d->cstype4cc.id==CODE_MBED || d->cstype4cc.id==CODE_LINK))
	{
		d->profile_offset_raw = de_getui32le(pos+112);
		de_dbg(c, "profile offset: %d+%d\n", FILEHEADER_SIZE,
			(int)d->profile_offset_raw);
		d->profile_size = de_getui32le(pos+116);
		de_dbg(c, "profile size: %d\n", (int)d->profile_size);
	}

	retval = 1;
done:
	de_dbg_indent(c, -1);
	return retval;
}
Beispiel #15
0
// create bitmap_font object
static void do_make_image(deark *c, lctx *d)
{
	struct de_bitmap_font *font = NULL;
	de_int64 i;
	de_int64 pos;

	font = de_create_bitmap_font(c);

	font->has_nonunicode_codepoints = 1;
	if(d->encoding!=DE_ENCODING_UNKNOWN)
		font->has_unicode_codepoints = 1;
	font->prefer_unicode = 0;

	font->nominal_width = (int)d->nominal_char_width;
	font->nominal_height = (int)d->char_height;
	font->num_chars = d->num_chars_stored;
	font->char_array = de_malloc(c, font->num_chars * sizeof(struct de_bitmap_font_char));

	for(i=0; i<d->num_chars_stored; i++) {
		de_int64 char_width;
		de_int64 char_offset;
		de_int32 char_index;
		de_int64 num_tiles;
		de_int64 tile;
		de_int64 row;

		pos = d->hdrsize + d->char_entry_size*i;
		char_width = de_getui16le(pos);
		if(d->char_entry_size==6)
			char_offset = de_getui32le(pos+2);
		else
			char_offset = de_getui16le(pos+2);
		de_dbg2(c, "char[%d] width=%d offset=%d\n", (int)(d->first_char + i), (int)char_width, (int)char_offset);

		num_tiles = (char_width+7)/8;

		if(i == d->num_chars_stored-1) {
			// Arbitrarily put the "absolute space" char at codepoint 256,
			// and U+2002 EN SPACE (best I can do).
			font->char_array[i].codepoint_nonunicode = 256;
			font->char_array[i].codepoint_unicode = 0x2002;
		}
		else {
			char_index = (de_int32)d->first_char + (de_int32)i;

			font->char_array[i].codepoint_nonunicode = char_index;

			if(font->has_unicode_codepoints) {
				if(char_index<32 && d->dfCharSet==0) {
					// This kind of font usually doesn't have glyphs below 32.
					// If it does, assume that they are VT100 line drawing characters.
					font->char_array[i].codepoint_unicode =
						de_char_to_unicode(c, 95+char_index, DE_ENCODING_DEC_SPECIAL_GRAPHICS);
				}
				else {
					font->char_array[i].codepoint_unicode =
						de_char_to_unicode(c, char_index, d->encoding);
				}
			}
		}

		font->char_array[i].width = (int)char_width;
		font->char_array[i].height = (int)d->char_height;
		font->char_array[i].rowspan = num_tiles;
		font->char_array[i].bitmap = de_malloc(c, d->char_height * num_tiles);

		for(row=0; row<d->char_height; row++) {
			for(tile=0; tile<num_tiles; tile++) {
				font->char_array[i].bitmap[row * font->char_array[i].rowspan + tile] =
					de_getbyte(char_offset + tile*d->char_height + row);
			}
		}
	}

	de_font_bitmap_font_to_image(c, font, d->fi, 0);

	if(font) {
		if(font->char_array) {
			for(i=0; i<font->num_chars; i++) {
				de_free(c, font->char_array[i].bitmap);
			}
			de_free(c, font->char_array);
		}
		de_destroy_bitmap_font(c, font);
	}
}
Beispiel #16
0
static int do_gzip_read_member(deark *c, lctx *d, de_int64 pos1, de_int64 *member_size)
{
	de_byte b0, b1;
	de_int64 cmpr_code;
	de_int64 pos;
	de_int64 n;
	de_int64 foundpos;
	de_int64 string_len;
	de_int64 cmpr_data_len;
	de_int64 isize;
	de_int64 mod_time_unix;
	struct de_timestamp mod_time_ts;
	de_uint32 crc32_field;
	de_ucstring *member_name = NULL;
	de_finfo *fi = NULL;
	int saved_indent_level;
	int ret;
	int retval = 0;

	mod_time_ts.is_valid = 0;

	de_dbg_indent_save(c, &saved_indent_level);

	de_dbg(c, "gzip member at %d\n", (int)pos1);
	de_dbg_indent(c, 1);
	pos = pos1;

	b0 = de_getbyte(pos+0);
	b1 = de_getbyte(pos+1);
	if(b0!=0x1f || b1!=0x8b) {
		de_err(c, "Invalid gzip signature at %d. This is not a valid gzip file.\n",
			(int)pos1);
		goto done;
	}

	cmpr_code=de_getbyte(pos+2);
	if(cmpr_code!=0x08) {
		de_err(c, "Unsupported compression type (%d)\n", (int)cmpr_code);
		goto done;
	}

	d->flags = de_getbyte(pos+3);
	de_dbg(c, "flags: 0x%02x\n", (unsigned int)d->flags);
	pos += 4;

	mod_time_unix = de_getui32le(pos);
	de_unix_time_to_timestamp(mod_time_unix, &mod_time_ts);
	if(mod_time_ts.is_valid) {
		char timestamp_buf[64];
		de_timestamp_to_string(&mod_time_ts, timestamp_buf, sizeof(timestamp_buf), 1);
		de_dbg(c, "mod time: %" INT64_FMT " (%s)\n", mod_time_unix, timestamp_buf);
	}
	pos += 4;

	b0 = de_getbyte(pos++);
	de_dbg(c, "extra flags: 0x%02x\n", (unsigned int)b0);

	b0 = de_getbyte(pos++);
	de_dbg(c, "OS or filesystem: %d (%s)\n", (int)b0, get_os_name(b0));

	if(d->flags & GZIPFLAG_FEXTRA) {
		n = de_getui16le(pos); // XLEN
		// TODO: It might be interesting to dissect these extra fields, but it's
		// hard to find even a single file that uses them.
		de_dbg(c, "[extra fields at %d, dpos=%d, dlen=%d]\n",
			(int)pos, (int)(pos+2), (int)n);
		pos += 2;
		pos += n;
	}

	if(d->flags & GZIPFLAG_FNAME) {
		ret =  dbuf_search_byte(c->infile, 0x00, pos, c->infile->len - pos,
			&foundpos);
		if(!ret) {
			de_err(c, "Invalid NAME field\n");
			goto done;
		}

		string_len = foundpos - pos;

		member_name = ucstring_create(c);
		dbuf_read_to_ucstring_n(c->infile, pos, string_len, 300, member_name, 0, DE_ENCODING_LATIN1);
		de_dbg(c, "file name at %d, len=%d: \"%s\"\n", (int)pos, (int)string_len,
			ucstring_get_printable_sz(member_name));
		pos = foundpos + 1;
	}

	if(d->flags & GZIPFLAG_FCOMMENT) {
		ret =  dbuf_search_byte(c->infile, 0x00, pos, c->infile->len - pos,
			&foundpos);
		if(!ret) {
			de_err(c, "Invalid COMMENT field\n");
			goto done;
		}
		pos = foundpos + 1;
	}

	if(d->flags & GZIPFLAG_FHCRC) {
		pos += 2;
	}

	de_dbg(c, "compressed blocks at %d\n", (int)pos);

	if(!d->output_file) {
		fi = de_finfo_create(c);

		if(member_name && c->filenames_from_file) {
			de_finfo_set_name_from_ucstring(c, fi, member_name);
			fi->original_filename_flag = 1;
		}

		if(mod_time_ts.is_valid) {
			fi->mod_time = mod_time_ts;
		}

		d->output_file = dbuf_create_output_file(c, member_name?NULL:"bin", fi, 0);
	}

	ret = de_uncompress_deflate(c->infile, pos, c->infile->len - pos, d->output_file, &cmpr_data_len);

	if(!ret) goto done;
	pos += cmpr_data_len;

	crc32_field = (de_uint32)de_getui32le(pos);
	de_dbg(c, "crc32: 0x%08x\n", (unsigned int)crc32_field);
	pos += 4;
	// TODO: Validate CRCs

	isize = de_getui32le(pos);
	de_dbg(c, "uncompressed size (mod 2^32): %u\n", (unsigned int)isize);
	pos += 4;

	retval = 1;

done:
	if(retval)
		*member_size = pos - pos1;
	else
		*member_size = 0;
	ucstring_destroy(member_name);
	de_finfo_destroy(c, fi);
	de_dbg_indent_restore(c, saved_indent_level);
	return retval;
}
Beispiel #17
0
static int do_read_header(deark *c, lctx *d)
{
	de_int64 dfType;
	de_int64 dfPixWidth;
	de_int64 dfPixHeight;
	de_int64 dfMaxWidth;
	int is_vector = 0;
	int retval = 0;

	d->fnt_version = de_getui16le(0);
	de_dbg(c, "dfVersion: 0x%04x\n", (int)d->fnt_version);

	if(d->fnt_version==0x0300)
		d->hdrsize = 148;
	else
		d->hdrsize = 118;

	dfType = de_getui16le(66);
	de_dbg(c, "dfType: 0x%04x\n", (int)dfType);
	is_vector = (dfType&0x1)?1:0;
	de_dbg(c, "Font type: %s\n", is_vector?"vector":"bitmap");

	d->dfPoints = de_getui16le(68);
	de_dbg(c, "dfPoints: %d\n", (int)d->dfPoints);

	dfPixWidth = de_getui16le(86);
	de_dbg(c, "dfPixWidth: %d\n", (int)dfPixWidth);
	dfPixHeight = de_getui16le(88);
	de_dbg(c, "dfPixHeight: %d\n", (int)dfPixHeight);

	d->dfCharSet = de_getbyte(85);
	de_dbg(c, "charset: 0x%02x\n", (int)d->dfCharSet);
	if(d->dfCharSet==0x00) { // "ANSI"
		d->encoding = DE_ENCODING_WINDOWS1252; // Guess
	}
	else if(d->dfCharSet==0xff) { // "OEM"
		d->encoding = DE_ENCODING_CP437_G; // Guess
	}
	else {
		d->encoding = DE_ENCODING_UNKNOWN;
	}

	dfMaxWidth = de_getui16le(93);
	de_dbg(c, "dfMaxWidth: %d\n", (int)dfMaxWidth);

	if(dfPixWidth!=dfMaxWidth && dfPixWidth!=0) {
		de_warn(c, "dfMaxWidth (%d) does not equal dfPixWidth (%d)\n",
			(int)dfMaxWidth, (int)dfPixWidth);
	}

	d->first_char = de_getbyte(95);
	d->last_char = de_getbyte(96);
	de_dbg(c, "first char: %d, last char: %d\n", (int)d->first_char, (int)d->last_char);

	if(is_vector) {
		de_err(c, "This is a vector font. Not supported.\n");
		goto done;
	}

	// Apparently, the first 117 bytes (through the dfBitsOffset field) are
	// common to all versions
	if(d->fnt_version<0x0200) {
		de_err(c, "This version of FNT is not supported\n");
		goto done;
	}

	if(d->fnt_version >= 0x0200) {
		d->dfFace = de_getui32le(105);
	}

	// There is an extra character at the end of the table that is an
	// "absolute-space" character, and is guaranteed to be blank.
	d->num_chars_stored = (de_int64)d->last_char - d->first_char + 1 + 1;

	if(d->fnt_version==0x0300) {
		d->char_entry_size = 6;
	}
	else {
		d->char_entry_size = 4;
	}

	d->char_table_size = d->char_entry_size * d->num_chars_stored;
	de_dbg(c, "character index at %d, size %d, %d bytes/entry\n", (int)d->hdrsize,
		(int)d->char_table_size, (int)d->char_entry_size);

	do_prescan_chars(c, d);
	if(d->detected_max_width<1) goto done;
	d->nominal_char_width = d->detected_max_width;

	d->char_height = dfPixHeight;

	retval = 1;
done:
	return retval;
}