Refactoring the iff decoder
[deark.git] / modules / megapaint.c
blob18ffe8f2456cdbbc3f98adbbd28cc23a1e6628ce
1 // This file is part of Deark.
2 // Copyright (C) 2018 Jason Summers
3 // See the file COPYING for terms of use.
5 // MegaPaint BLD image
6 // MegaPaint .PAT
7 // MegaPaint .LIB
9 #include <deark-config.h>
10 #include <deark-private.h>
11 DE_DECLARE_MODULE(de_module_bld);
12 DE_DECLARE_MODULE(de_module_megapaint_pat);
13 DE_DECLARE_MODULE(de_module_megapaint_lib);
15 // **************************************************************************
16 // MegaPaint BLD image
17 // **************************************************************************
19 static void de_run_bld(deark *c, de_module_params *mparams)
21 i64 w_raw, h_raw;
22 i64 w, h;
23 i64 rowspan;
24 i64 pos = 0;
25 int is_compressed;
26 dbuf *unc_pixels = NULL;
28 w_raw = de_geti16be_p(&pos);
29 h_raw = de_geti16be_p(&pos);
30 is_compressed = (w_raw<0);
31 w = is_compressed ? ((-w_raw)+1) : (w_raw+1);
32 h = h_raw+1;
33 de_dbg_dimensions(c, w, h);
34 de_dbg(c, "compressed: %d", is_compressed);
35 if(!de_good_image_dimensions(c, w, h)) goto done;
36 rowspan = (w+7)/8;
38 if(is_compressed) {
39 unc_pixels = dbuf_create_membuf(c, h*rowspan, 1);
40 while(1) {
41 u8 b1;
42 i64 count;
44 if(pos >= c->infile->len) break;
45 if(unc_pixels->len >= h*rowspan) break;
47 b1 = de_getbyte_p(&pos);
48 if(b1==0x00 || b1==0xff) {
49 count = 1+(i64)de_getbyte_p(&pos);
50 dbuf_write_run(unc_pixels, b1, count);
52 else {
53 dbuf_writebyte(unc_pixels, b1);
57 else {
58 unc_pixels = dbuf_open_input_subfile(c->infile, pos, c->infile->len-pos);
61 de_convert_and_write_image_bilevel2(unc_pixels, 0, w, h, rowspan,
62 DE_CVTF_WHITEISZERO, NULL, 0);
64 done:
65 dbuf_close(unc_pixels);
68 static int de_identify_bld(deark *c)
70 if(de_input_file_has_ext(c, "bld")) return 20;
71 // TODO: We could try to test if the dimensions are sane, but we'd risk
72 // getting it wrong, because we probably don't know what every edition of
73 // MegaPaint does.
74 return 0;
77 void de_module_bld(deark *c, struct deark_module_info *mi)
79 mi->id = "bld";
80 mi->desc = "MegaPaint BLD";
81 mi->run_fn = de_run_bld;
82 mi->identify_fn = de_identify_bld;
85 // **************************************************************************
86 // MegaPaint .PAT
87 // **************************************************************************
89 static void de_run_megapaint_pat(deark *c, de_module_params *mparams)
91 // Note: This module is based on guesswork, and may be incomplete.
92 de_bitmap *mainimg = NULL;
93 i64 main_w, main_h;
94 i64 pos = 0;
95 i64 k;
97 pos += 8;
98 main_w = 1+(32+1)*16;
99 main_h = 1+(32+1)*2;
101 mainimg = de_bitmap_create(c, main_w, main_h, 1);
102 de_bitmap_rect(mainimg, 0, 0, main_w, main_h, DE_MAKE_GRAY(128), 0);
104 for(k=0; k<32; k++) {
105 de_bitmap *img = NULL;
106 i64 imgpos_x, imgpos_y;
108 img = de_bitmap_create(c, 32, 32, 1);
109 de_convert_image_bilevel(c->infile, pos, 4, img, DE_CVTF_WHITEISZERO);
110 pos += 4*32;
112 imgpos_x = 1+(32+1)*(k%16);
113 imgpos_y = 1+(32+1)*(k/16);
114 de_bitmap_copy_rect(img, mainimg, 0, 0, 32, 32, imgpos_x, imgpos_y, 0);
115 de_bitmap_destroy(img);
118 de_bitmap_write_to_file(mainimg, NULL, 0);
119 de_bitmap_destroy(mainimg);
122 static int de_identify_megapaint_pat(deark *c)
124 if(dbuf_memcmp(c->infile, 0, "\x07" "PAT", 4))
125 return 0;
126 if(c->infile->len==4396) return 100;
127 return 40;
130 void de_module_megapaint_pat(deark *c, struct deark_module_info *mi)
132 mi->id = "megapaint_pat";
133 mi->desc = "MegaPaint Patterns";
134 mi->run_fn = de_run_megapaint_pat;
135 mi->identify_fn = de_identify_megapaint_pat;
138 // **************************************************************************
139 // MegaPaint .LIB
140 // **************************************************************************
142 static void de_run_megapaint_lib(deark *c, de_module_params *mparams)
144 // Note: This module is based on guesswork, and may be incomplete.
145 const i64 idxpos = 14;
146 i64 k;
147 i64 nsyms;
149 nsyms = 1+de_getu16be(12);
150 de_dbg(c, "number of symbols: %d", (int)nsyms);
152 for(k=0; k<nsyms; k++) {
153 i64 sym_offs;
154 i64 w, h, rowspan;
156 sym_offs = de_getu32be(idxpos+4*k);
157 de_dbg(c, "symbol #%d", (int)(1+k));
158 de_dbg_indent(c, 1);
159 de_dbg(c, "offset: %u", (unsigned int)sym_offs);
161 w = 1+de_getu16be(sym_offs);
162 h = 1+de_getu16be(sym_offs+2);
163 de_dbg_dimensions(c, w, h);
164 rowspan = ((w+15)/16)*2;
165 de_convert_and_write_image_bilevel(c->infile, sym_offs+4, w, h, rowspan,
166 DE_CVTF_WHITEISZERO, NULL, 0);
167 de_dbg_indent(c, -1);
171 static int de_identify_megapaint_lib(deark *c)
173 if(dbuf_memcmp(c->infile, 0, "\x07" "LIB", 4))
174 return 0;
175 if(de_input_file_has_ext(c, "lib")) return 100;
176 return 40;
179 void de_module_megapaint_lib(deark *c, struct deark_module_info *mi)
181 mi->id = "megapaint_lib";
182 mi->desc = "MegaPaint Symbol Library";
183 mi->run_fn = de_run_megapaint_lib;
184 mi->identify_fn = de_identify_megapaint_lib;