1 // This file is part of Deark.
2 // Copyright (C) 2016 Jason Summers
3 // See the file COPYING for terms of use.
6 // Supported: Most .MAG, .MKI
7 // Not supported: .MAX, some variant formats
9 #include <deark-config.h>
10 #include <deark-private.h>
11 DE_DECLARE_MODULE(de_module_makichan
);
13 typedef struct localctx_struct
{
25 i64 width_adj
, height_adj
;
36 static i64
de_int_round_up(i64 n
, i64 m
)
38 return ((n
+(m
-1))/m
)*m
;
41 static void read_palette(deark
*c
, lctx
*d
, i64 pos
)
46 de_dbg(c
, "palette at %d", (int)pos
);
49 for(k
=0; k
<d
->num_colors
; k
++) {
50 cg
= de_getbyte(pos
+3*k
);
51 cr
= de_getbyte(pos
+3*k
+1);
52 cb
= de_getbyte(pos
+3*k
+2);
53 d
->pal
[k
] = DE_MAKE_RGB(cr
,cg
,cb
);
54 de_dbg_pal_entry(c
, k
, d
->pal
[k
]);
60 static int read_mki_header(deark
*c
, lctx
*d
)
63 i64 width_raw
, height_raw
;
68 i64 expected_file_size
;
69 unsigned int extension_flags
;
72 de_dbg(c
, "MKI header at %d", (int)d
->header_pos
);
77 d
->flag_b_size
= de_getu16be(pos
+0);
78 pix_data_a_size
= de_getu16be(pos
+2);
79 pix_data_b_size
= de_getu16be(pos
+4);
80 d
->pixels_size
= pix_data_a_size
+ pix_data_b_size
;
82 extension_flags
= (unsigned int)de_getu16be(pos
+6);
83 de_dbg(c
, "extension flags: 0x%04x", extension_flags
);
85 d
->aspect_ratio_flag
= extension_flags
&0x0001;
86 if(extension_flags
&0x0002) {
91 d
->bits_per_pixel
= 4;
93 de_dbg(c
, "number of colors: %d", (int)d
->num_colors
);
96 xoffset
= de_getu16be(pos
+8);
97 yoffset
= de_getu16be(pos
+10);
98 de_dbg(c
, "image offset: (%d,%d)", (int)xoffset
, (int)yoffset
);
100 width_raw
= de_getu16be(pos
+12);
101 d
->width
= width_raw
- xoffset
;
102 height_raw
= de_getu16be(pos
+14);
103 d
->height
= height_raw
- yoffset
;
104 de_dbg_dimensions(c
, d
->width
, d
->height
);
105 if(d
->width
%64 != 0) {
106 de_warn(c
, "Width is not a multiple of 64. This image may not be handled correctly.");
108 d
->width_adj
= de_int_round_up(d
->width
, 64);
109 if(d
->height
%4 != 0) {
110 de_warn(c
, "Height is not a multiple of 4. This image may not be handled correctly.");
112 d
->height_adj
= de_int_round_up(d
->height
, 4);
114 d
->flag_a_offset
= pos
+ 16 + 48;
115 // The documentation seems to say that flag A is *always* 1000 bytes, regardless of
116 // how many bytes would actually be needed.
117 // This would imply that a MAKI image can't have more than 256000 pixels.
119 //flag_a_size = (d->width_adj*d->height_adj)/256;
121 d
->flag_b_offset
= d
->flag_a_offset
+ flag_a_size
;
122 d
->pixels_offset
= d
->flag_b_offset
+ d
->flag_b_size
;
123 expected_file_size
= d
->pixels_offset
+ d
->pixels_size
;
124 de_dbg(c
, "flag A offset=%d, size=%d", (int)d
->flag_a_offset
, (int)flag_a_size
);
125 de_dbg(c
, "flag B calculated_offset=%d, size=%d", (int)d
->flag_b_offset
, (int)d
->flag_b_size
);
126 de_dbg(c
, "pix data size_A=%d, size_B=%d", (int)pix_data_a_size
, (int)pix_data_b_size
);
127 de_dbg(c
, "pix data calculated_offset=%d, calculated_size=%d", (int)d
->pixels_offset
, (int)d
->pixels_size
);
128 de_dbg(c
, "calculated file size: %d", (int)expected_file_size
);
130 if(d
->bits_per_pixel
!=4 && d
->bits_per_pixel
!=8) {
131 de_err(c
, "Unsupported or unknown bits/pixel");
138 de_dbg_indent(c
, -1);
142 static void mki_decompress_virtual_screen(deark
*c
, lctx
*d
)
153 vs_rowspan
= d
->width_adj
/16;
154 a_pos
= d
->flag_a_offset
;
156 b_pos
= d
->flag_b_offset
;
157 d
->virtual_screen
= dbuf_create_membuf(c
, vs_rowspan
*d
->height_adj
, 1);
159 for(j
=0; j
<d
->height_adj
/4; j
++) {
160 for(i
=0; i
<d
->width_adj
/8; i
++) {
163 // Read next flag A bit
165 a_byte
= de_getbyte(a_pos
++);
168 flag_a_bit
= a_byte
& (1 << a_bitnum
--);
173 // Read the next two bytes from flag B, and split them into 4 nibbles.
174 tmpn
[0] = de_getbyte(b_pos
++);
175 tmpn
[2] = de_getbyte(b_pos
++);
176 tmpn
[1] = tmpn
[0]&0x0f;
177 tmpn
[3] = tmpn
[2]&0x0f;
184 vs_pos
= (4*j
+k
)*vs_rowspan
+ i
/2;
189 v
= dbuf_getbyte(d
->virtual_screen
, vs_pos
) | tmpn
[k
];
191 dbuf_writebyte_at(d
->virtual_screen
, vs_pos
, v
);
197 static void mki_decompress_pixels(deark
*c
, lctx
*d
)
206 d
->rowspan
= d
->width_adj
/2;
209 p_pos
= d
->pixels_offset
;
210 delta_y
= d
->is_mki_b
? 4 : 2;
211 d
->unc_pixels
= dbuf_create_membuf(c
, d
->rowspan
*d
->height_adj
, 1);
213 for(j
=0; j
<d
->height
; j
++) {
214 for(i
=0; i
<d
->rowspan
; i
++) {
218 // Read the next virtual-screen bit
220 vs_byte
= dbuf_getbyte(d
->virtual_screen
, vs_pos
++);
223 vs_bit
= vs_byte
& (1 << vs_bitnum
--);
226 v
= de_getbyte(p_pos
++);
233 v
^= dbuf_getbyte(d
->unc_pixels
, (j
-delta_y
)*d
->rowspan
+ i
);
235 dbuf_writebyte(d
->unc_pixels
, v
);
240 static int read_mag_header(deark
*c
, lctx
*d
)
242 i64 xoffset
, yoffset
;
243 i64 width_raw
, height_raw
;
251 de_dbg(c
, "header at %d", (int)d
->header_pos
);
256 model_code
= de_getbyte(pos
+1);
257 model_flags
= de_getbyte(pos
+2);
258 de_dbg(c
, "model code: 0x%02x, flags: 0x%02x",
259 (unsigned int)model_code
, (unsigned int)model_flags
);
260 if(model_code
==0x03) {
261 switch(model_flags
& 0xf8) {
262 case 0x00: case 0x10: case 0x50:
264 case 0x20: case 0x40: case 0x60:
266 if(d
->opt_allowbad
) break;
267 de_err(c
, "This looks like MAX format, which is not supported.");
270 de_err(c
, "Unknown image type");
275 screen_mode
= de_getbyte(pos
+3);
276 de_dbg(c
, "screen mode: %d", (int)screen_mode
);
278 d
->aspect_ratio_flag
= screen_mode
&0x01;
279 colors_code
= screen_mode
&0x82;
280 if(colors_code
==0x00) {
282 d
->bits_per_pixel
= 4;
284 else if(colors_code
==0x80) {
286 d
->bits_per_pixel
= 8;
288 else if(colors_code
==0x02) {
290 // TODO: Support 8 color images
292 de_dbg(c
, "number of colors: %d", (int)d
->num_colors
);
293 de_dbg_indent(c
, -1);
295 xoffset
= de_getu16le(pos
+4);
296 yoffset
= de_getu16le(pos
+6);
297 de_dbg(c
, "image offset: (%d,%d)", (int)xoffset
, (int)yoffset
);
299 width_raw
= de_getu16le(pos
+8);
300 height_raw
= de_getu16le(pos
+10);
301 d
->width
= width_raw
- xoffset
+ 1;
302 d
->height
= height_raw
- yoffset
+ 1;
303 de_dbg_dimensions(c
, d
->width
, d
->height
);
305 d
->flag_a_offset
= de_getu32le(pos
+12);
306 d
->flag_a_offset
+= d
->header_pos
;
307 de_dbg(c
, "flag A offset: %d", (int)d
->flag_a_offset
);
309 d
->flag_b_offset
= de_getu32le(pos
+16);
310 d
->flag_b_offset
+= d
->header_pos
;
311 d
->flag_b_size
= de_getu32le(pos
+20);
312 de_dbg(c
, "flag B offset: %d, size=%d", (int)d
->flag_b_offset
, (int)d
->flag_b_size
);
314 d
->pixels_offset
= de_getu32le(pos
+24);
315 d
->pixels_offset
+= d
->header_pos
;
316 d
->pixels_size
= de_getu32le(pos
+28);
317 de_dbg(c
, "pixels offset: %d, size=%d", (int)d
->pixels_offset
, (int)d
->pixels_size
);
319 if(d
->bits_per_pixel
!=4 && d
->bits_per_pixel
!=8) {
320 de_err(c
, "Unsupported or unknown bits/pixel");
326 de_dbg_indent(c
, -1);
330 static int do_mag_decompress(deark
*c
, lctx
*d
)
332 static const u8 delta_x
[16] = { 0,1,2,4,0,1,0,1,2,0,1,2,0,1,2, 0 };
333 static const u8 delta_y
[16] = { 0,0,0,0,1,1,2,2,2,4,4,4,8,8,8,16 };
337 int a_bitnum
; // Index of next bit to read. -1 = no more bits in a_byte.
342 u8
*action_byte_buf
= NULL
;
345 de_dbg(c
, "decompressing pixels");
347 // Presumably, due to the compression scheme, every row must have a
348 // multiple of 4 bytes.
349 d
->rowspan
= ((d
->width
* d
->bits_per_pixel
+ 31)/32)*4;
351 d
->unc_pixels
= dbuf_create_membuf(c
, d
->rowspan
* d
->height
, 1);
353 a_pos
= d
->flag_a_offset
;
355 b_pos
= d
->flag_b_offset
;
356 p_pos
= d
->pixels_offset
;
358 action_byte_buf
= de_malloc(c
, d
->rowspan
/4);
360 for(y
=0; y
<d
->height
; y
++) {
361 for(x
=0; x
<d
->rowspan
/4; x
++) {
365 // Read next flag A bit
367 a_byte
= de_getbyte(a_pos
++);
370 flag_a_bit
= a_byte
& (1 << a_bitnum
--);
373 // If flag_a_bit is unset, re-use the action byte from the
375 // If flag bit A is set, the new action byte is the one from the
376 // previous row XORed with the next B byte (don't ask me why).
377 b_byte
= de_getbyte(b_pos
++);
378 action_byte_buf
[x
] ^= b_byte
;
381 action_byte
= action_byte_buf
[x
];
383 // Produce 4 uncompressed bytes, 2 for each nibble in the
389 dcode
= (unsigned int)((action_byte
&0xf0)>>4);
391 dcode
= (unsigned int)(action_byte
&0x0f);
394 // An "uncompressed" data word. Read it from the source file.
395 de_read(wordbuf
, p_pos
, 2);
399 // Copy the data word from an earlier location in the image.
400 dpos
= d
->unc_pixels
->len
-
401 d
->rowspan
*(i64
)delta_y
[dcode
] -
402 2*(i64
)delta_x
[dcode
];
403 dbuf_read(d
->unc_pixels
, wordbuf
, dpos
, 2);
405 dbuf_write(d
->unc_pixels
, wordbuf
, 2);
410 de_free(c
, action_byte_buf
);
414 static void do_create_image(deark
*c
, lctx
*d
)
416 de_bitmap
*img
= NULL
;
419 img
= de_bitmap_create(c
, d
->width
, d
->height
, 3);
421 fi
= de_finfo_create(c
);
423 if(d
->aspect_ratio_flag
) {
424 fi
->density
.code
= DE_DENSITY_UNK_UNITS
;
425 fi
->density
.xdens
= 2.0;
426 fi
->density
.ydens
= 1.0;
429 de_convert_image_paletted(d
->unc_pixels
, 0,
430 d
->bits_per_pixel
, d
->rowspan
, d
->pal
, img
, 0);
432 de_bitmap_write_to_file_finfo(img
, fi
, 0);
433 de_bitmap_destroy(img
);
434 de_finfo_destroy(c
, fi
);
437 // Sets d->header_pos
438 static int find_mag_header(deark
*c
, lctx
*d
)
443 // Find the first 0x1a byte.
444 ret
= dbuf_search_byte(c
->infile
, '\x1a', 0, c
->infile
->len
, &pos_1a
);
446 // Find the first 0x00 byte after the first 0x1a byte.
447 // TODO: Is this the correct algorithm, or should we just assume the
448 // header starts immediately after the first 0x1a byte?
449 ret
= dbuf_search_byte(c
->infile
, '\0', pos_1a
+1, c
->infile
->len
-pos_1a
-1, &d
->header_pos
);
451 de_dbg(c
, "header found at %d", (int)d
->header_pos
);
456 de_err(c
, "Failed to find header. This is probably not a MAKIchan file.");
460 static void do_mag(deark
*c
, lctx
*d
)
462 if(!find_mag_header(c
, d
)) goto done
;
463 if(!read_mag_header(c
, d
)) goto done
;
464 read_palette(c
, d
, d
->header_pos
+32);
465 if(!de_good_image_dimensions(c
, d
->width
, d
->height
)) goto done
;
466 if(!do_mag_decompress(c
, d
)) goto done
;
467 do_create_image(c
, d
);
472 static void do_mki(deark
*c
, lctx
*d
)
475 if(!read_mki_header(c
, d
)) goto done
;
476 read_palette(c
, d
, d
->header_pos
+16);
477 if(!de_good_image_dimensions(c
, d
->width
, d
->height
)) goto done
;
478 mki_decompress_virtual_screen(c
, d
);
479 mki_decompress_pixels(c
, d
);
480 do_create_image(c
, d
);
485 static void de_run_makichan(deark
*c
, de_module_params
*mparams
)
489 d
= de_malloc(c
, sizeof(lctx
));
490 d
->opt_allowbad
= (u8
)de_get_ext_option_bool(c
, "makichan:allowbad", 0);
492 if(!dbuf_memcmp(c
->infile
, 0, "MAKI01", 6)) {
494 if(de_getbyte(6)=='B') {
506 dbuf_close(d
->unc_pixels
);
507 dbuf_close(d
->virtual_screen
);
511 static int de_identify_makichan(deark
*c
)
513 if(!dbuf_memcmp(c
->infile
, 0, "MAKI0", 5))
518 static void de_help_makichan(deark
*c
)
520 de_msg(c
, "-opt makichan:allowbad : Keep going after certain errors");
523 void de_module_makichan(deark
*c
, struct deark_module_info
*mi
)
526 mi
->desc
= "MAKIchan graphics";
527 mi
->run_fn
= de_run_makichan
;
528 mi
->identify_fn
= de_identify_makichan
;
529 mi
->help_fn
= de_help_makichan
;