arc.c: Rearranged some functions
[deark.git] / modules / atari-img.c
blobc7e6ba20c377c9a69356f697fdbbf8e3c94df2fa
1 // This file is part of Deark.
2 // Copyright (C) 2016 Jason Summers
3 // See the file COPYING for terms of use.
5 #include <deark-config.h>
6 #include <deark-private.h>
7 #include <deark-fmtutil.h>
8 DE_DECLARE_MODULE(de_module_degas);
9 DE_DECLARE_MODULE(de_module_prismpaint);
10 DE_DECLARE_MODULE(de_module_ftc);
11 DE_DECLARE_MODULE(de_module_eggpaint);
12 DE_DECLARE_MODULE(de_module_indypaint);
13 DE_DECLARE_MODULE(de_module_godpaint);
14 DE_DECLARE_MODULE(de_module_tinystuff);
15 DE_DECLARE_MODULE(de_module_doodle);
16 DE_DECLARE_MODULE(de_module_neochrome);
17 DE_DECLARE_MODULE(de_module_neochrome_ani);
18 DE_DECLARE_MODULE(de_module_fpaint_pi4);
19 DE_DECLARE_MODULE(de_module_fpaint_pi9);
20 DE_DECLARE_MODULE(de_module_atari_pi7);
21 DE_DECLARE_MODULE(de_module_falcon_xga);
22 DE_DECLARE_MODULE(de_module_coke);
23 DE_DECLARE_MODULE(de_module_animatic);
25 static void fix_dark_pal(deark *c, struct atari_img_decode_data *adata);
27 static void help_respectpal(deark *c)
29 de_msg(c, "-opt atari:respectpal : Don't ignore a seemingly bad 2-color palette");
32 // **************************************************************************
33 // DEGAS / DEGAS Elite images
34 // **************************************************************************
36 typedef struct degasctx_struct {
37 unsigned int compression_code;
38 int degas_elite_flag;
39 u32 pal[16];
40 } degasctx;
42 static void do_degas_anim_fields(deark *c, degasctx *d, i64 pos)
44 i64 i;
45 i64 n;
47 for(i=0; i<4; i++) {
48 n = de_getu16be(pos + 2*i);
49 de_dbg2(c, "left_color_anim[%d] = %d", (int)i, (int)n);
51 for(i=0; i<4; i++) {
52 n = de_getu16be(pos + 8 + 2*i);
53 de_dbg2(c, "right_color_anim[%d] = %d", (int)i, (int)n);
55 for(i=0; i<4; i++) {
56 n = de_getu16be(pos + 16 + 2*i);
57 de_dbg2(c, "channel_direction[%d] = %d", (int)i, (int)n);
59 for(i=0; i<4; i++) {
60 n = de_getu16be(pos + 24 + 2*i);
61 de_dbg2(c, "channel_delay_code[%d] = %d", (int)i, (int)n);
64 // TODO: Can we determine if palette animation is actually used,
65 // and only show the warning if it is?
66 //de_warn(c, "This image may use palette cycling animation, which is not supported.");
69 // Try to figure out if this is a DEGAS Elite file (as opposed to original DEGAS).
70 static int is_degas_elite(deark *c, degasctx *d)
72 i64 n;
73 i64 x;
74 i64 pos;
75 int all_zero = 1;
77 if(d->compression_code) return 1; // Only DEGAS Elite supports compression.
78 if(c->infile->len < 32066) return 0;
80 // Test if the animation segment seems to have valid values, to try to distinguish
81 // it from meaningless padding. (This is overkill.)
82 pos = 32034;
83 for(n=0; n<8; n++) {
84 // The first 8 fields are "color numbers".
85 // Guessing that they should be 0-15.
86 x = de_getu16be(pos+n*2);
87 if(x>0x0f) return 0;
88 if(x) all_zero = 0;
90 pos += 8*2;
91 for(n=0; n<4; n++) {
92 // The next 4 fields (channel direction) should be 0, 1, or 2.
93 x = de_getu16be(pos+n*2);
94 if(x>2) return 0;
95 if(x) all_zero = 0;
97 pos += 4*2;
98 for(n=0; n<4; n++) {
99 // The next 4 fields (delay) must be from 0 to 128.
100 x = de_getu16be(pos+n*2);
101 if(x>128) return 0;
102 if(x) all_zero = 0;
105 if(all_zero && c->infile->len>32068) {
106 // If every field was 0, and the file size doesn't suggest Elite,
107 // just assume it's not valid.
108 return 0;
111 return 1;
114 static void de_run_degas(deark *c, de_module_params *mparams)
116 degasctx *d = NULL;
117 struct atari_img_decode_data *adata = NULL;
118 de_finfo *fi = NULL;
119 i64 pos;
120 unsigned int format_code, resolution_code;
121 int is_grayscale;
122 i64 cmpr_bytes_consumed = 0;
124 d = de_malloc(c, sizeof(degasctx));
125 adata = de_malloc(c, sizeof(struct atari_img_decode_data));
127 adata->pal = d->pal;
129 pos = 0;
130 format_code = (unsigned int)de_getu16be(pos);
131 de_dbg(c, "format code: 0x%04x", format_code);
132 resolution_code = format_code & 0x0003;
133 d->compression_code = (format_code & 0x8000)>>15;
134 de_dbg_indent(c, 1);
135 de_dbg(c, "resolution code: %u", resolution_code);
136 de_dbg(c, "compression code: %u", d->compression_code);
137 de_dbg_indent(c, -1);
138 pos += 2;
140 switch(resolution_code) {
141 case 0:
142 adata->bpp = 4;
143 adata->w = 320;
144 adata->h = 200;
145 break;
146 case 1:
147 adata->bpp = 2;
148 adata->w = 640;
149 adata->h = 200;
150 break;
151 case 2:
152 adata->bpp = 1;
153 adata->w = 640;
154 adata->h = 400;
155 break;
156 default:
157 de_dbg(c, "Invalid or unsupported resolution (%u)", resolution_code);
158 goto done;
160 adata->ncolors = de_pow2(adata->bpp);
162 de_dbg(c, "dimensions: %d"DE_CHAR_TIMES"%d, colors: %d", (int)adata->w, (int)adata->h, (int)adata->ncolors);
164 d->degas_elite_flag = is_degas_elite(c, d);
165 de_declare_fmtf(c, "DEGAS%s %d-color %scompressed",
166 d->degas_elite_flag?" Elite":"",
167 (int)adata->ncolors,
168 d->compression_code?"":"un");
170 fmtutil_read_atari_palette(c, c->infile, pos, adata->pal, 16, adata->ncolors, 0);
171 pos += 2*16;
172 fix_dark_pal(c, adata);
174 if(d->compression_code) {
175 adata->was_compressed = 1;
176 adata->unc_pixels = dbuf_create_membuf(c, 32000, 1);
178 if(!fmtutil_decompress_packbits(c->infile, pos, c->infile->len-pos, adata->unc_pixels, &cmpr_bytes_consumed))
179 goto done;
181 de_dbg(c, "Compressed bytes found: %d", (int)cmpr_bytes_consumed);
182 pos += cmpr_bytes_consumed;
184 else {
185 i64 avail_bytes = 32000;
186 if(pos+32000 > c->infile->len) {
187 avail_bytes = c->infile->len - pos;
188 de_warn(c, "Unexpected end of file (expected 32000 bytes, got %d)", (int)avail_bytes);
190 adata->unc_pixels = dbuf_open_input_subfile(c->infile, pos, avail_bytes);
191 pos += avail_bytes;
194 if(pos + 32 == c->infile->len) {
195 do_degas_anim_fields(c, d, pos);
198 is_grayscale = de_is_grayscale_palette(adata->pal, adata->ncolors);
200 adata->img = de_bitmap_create(c, adata->w, adata->h, is_grayscale?1:3);
202 fi = de_finfo_create(c);
203 fmtutil_atari_set_standard_density(c, adata, fi);
205 fmtutil_atari_decode_image(c, adata);
207 de_bitmap_write_to_file_finfo(adata->img, fi, 0);
209 done:
210 if(adata) {
211 dbuf_close(adata->unc_pixels);
212 de_bitmap_destroy(adata->img);
213 de_free(c, adata);
215 de_finfo_destroy(c, fi);
216 de_free(c, d);
219 static int de_identify_degas(deark *c)
221 static const char *exts[6] = {"pi1", "pi2", "pi3", "pc1", "pc2", "pc3" };
222 i64 i;
223 int flag;
224 i64 sig;
226 flag = 0;
227 for(i=0; i<6; i++) {
228 if(de_input_file_has_ext(c, exts[i])) {
229 flag = 1;
230 break;
233 if(!flag) return 0;
235 sig = de_getu16be(0);
236 if(sig==0x0000 || sig==0x0001 || sig==0x0002) {
237 if(c->infile->len==32034) return 100; // DEGAS
238 if(c->infile->len==32066) return 100; // DEGAS Elite
239 if(c->infile->len==32128) return 40; // Could be padded to a multiple of 128 bytes
240 if(c->infile->len>16000) return 10;
242 else if(sig==0x8000 || sig==0x8001 || sig==0x8002) {
243 return 60;
246 return 0;
249 static void de_help_degas(deark *c)
251 fmtutil_atari_help_palbits(c);
252 help_respectpal(c);
255 void de_module_degas(deark *c, struct deark_module_info *mi)
257 mi->id = "degas";
258 mi->desc = "Atari DEGAS or DEGAS Elite image";
259 mi->run_fn = de_run_degas;
260 mi->identify_fn = de_identify_degas;
261 mi->help_fn = de_help_degas;
264 // **************************************************************************
265 // Atari Prism Paint (.pnt)
266 // **************************************************************************
268 typedef struct prismctx_struct {
269 i64 pal_size;
270 i64 compression_code;
271 i64 pic_data_size;
272 u32 pal[256];
273 } prismctx;
275 // A color value of N does not necessarily refer to Nth color in the palette.
276 // Some of them are mixed up. Apparently this is called "VDI order".
277 // Reference: http://toshyp.atari.org/en/VDI_fundamentals.html
278 static unsigned int map_vdi_pal(i64 bpp, unsigned int v)
280 if(bpp==1) return v;
281 switch(v) {
282 case 1: return 2;
283 case 2: return 3;
284 case 3: return bpp>2 ? 6 : 1;
285 case 5: return 7;
286 case 6: return 5;
287 case 7: return 8;
288 case 8: return 9;
289 case 9: return 10;
290 case 10: return 11;
291 case 11: return 14;
292 case 13: return 15;
293 case 14: return 13;
294 case 15: return bpp==8 ? 255 : 1;
295 case 255: return 1;
297 return v;
300 static void do_prism_read_palette(deark *c, prismctx *d, struct atari_img_decode_data *adata)
302 i64 i;
303 i64 r1, g1, b1;
304 u8 r, g, b;
305 u32 pal1[256];
306 u32 clr;
307 char tmps[32];
309 de_zeromem(pal1, sizeof(pal1));
311 for(i=0; i<d->pal_size; i++) {
312 r1 = de_getu16be(128+6*i+0);
313 g1 = de_getu16be(128+6*i+2);
314 b1 = de_getu16be(128+6*i+4);
315 r = de_scale_1000_to_255(r1);
316 g = de_scale_1000_to_255(g1);
317 b = de_scale_1000_to_255(b1);
318 clr = DE_MAKE_RGB(r,g,b);
319 de_snprintf(tmps, sizeof(tmps), "(%4d,%4d,%4d) "DE_CHAR_RIGHTARROW" ",
320 (int)r1, (int)g1, (int)b1);
321 de_dbg_pal_entry2(c, i, clr, tmps, NULL, NULL);
322 if(i<256) {
323 pal1[i] = clr;
327 for(i=0; i<d->pal_size; i++) {
328 d->pal[i] = pal1[map_vdi_pal(adata->bpp, (unsigned int)i)];
332 static void de_run_prismpaint(deark *c, de_module_params *mparams)
334 prismctx *d = NULL;
335 i64 pixels_start;
336 struct atari_img_decode_data *adata = NULL;
338 d = de_malloc(c, sizeof(prismctx));
340 adata = de_malloc(c, sizeof(struct atari_img_decode_data));
342 adata->pal = d->pal;
343 d->pal_size = de_getu16be(6);
344 adata->w = de_getu16be(8);
345 adata->h = de_getu16be(10);
346 de_dbg(c, "pal_size: %d, dimensions: %d"DE_CHAR_TIMES"%d", (int)d->pal_size,
347 (int)adata->w, (int)adata->h);
348 if(!de_good_image_dimensions(c, adata->w, adata->h)) goto done;
350 adata->bpp = de_getu16be(12);
351 d->compression_code = de_getu16be(14);
352 de_dbg(c, "bits/pixel: %d, compression: %d", (int)adata->bpp,
353 (int)d->compression_code);
355 d->pic_data_size = de_getu32be(16);
356 de_dbg(c, "reported (uncompressed) picture data size: %d", (int)d->pic_data_size);
358 do_prism_read_palette(c, d, adata);
360 if(adata->bpp!=1 && adata->bpp!=2 && adata->bpp!=4
361 && adata->bpp!=8 && adata->bpp!=16)
363 de_err(c, "Unsupported bits/pixel (%d)", (int)adata->bpp);
364 goto done;
366 if(d->compression_code!=0 && d->compression_code!=1) {
367 de_err(c, "Unsupported compression (%d)", (int)d->compression_code);
368 goto done;
370 if(adata->bpp==16 && d->compression_code!=0) {
371 de_warn(c, "Compressed 16-bit image support is untested, and may not work.");
374 pixels_start = 128 + 2*3*d->pal_size;
375 de_dbg(c, "pixel data starts at %d", (int)pixels_start);
376 if(pixels_start >= c->infile->len) goto done;
378 if(d->compression_code==0) {
379 adata->unc_pixels = dbuf_open_input_subfile(c->infile, pixels_start,
380 c->infile->len - pixels_start);
382 else {
383 adata->was_compressed = 1;
384 // TODO: Calculate the initial size more accurately.
385 adata->unc_pixels = dbuf_create_membuf(c, adata->w*adata->h, 0);
386 //dbuf_set_max_length(unc_pixels, ...);
388 fmtutil_decompress_packbits(c->infile, pixels_start, c->infile->len - pixels_start,
389 adata->unc_pixels, NULL);
390 de_dbg(c, "decompressed to %d bytes", (int)adata->unc_pixels->len);
393 adata->img = de_bitmap_create(c, adata->w, adata->h, 3);
394 fmtutil_atari_decode_image(c, adata);
395 de_bitmap_write_to_file(adata->img, NULL, 0);
397 done:
398 if(adata) {
399 dbuf_close(adata->unc_pixels);
400 de_bitmap_destroy(adata->img);
401 de_free(c, adata);
403 de_free(c, d);
406 static int de_identify_prismpaint(deark *c)
408 if(!dbuf_memcmp(c->infile, 0, "PNT\x00", 4))
409 return 100;
410 return 0;
413 void de_module_prismpaint(deark *c, struct deark_module_info *mi)
415 mi->id = "prismpaint";
416 mi->desc = "Atari Prism Paint .PNT, a.k.a. TruePaint .TPI";
417 mi->run_fn = de_run_prismpaint;
418 mi->identify_fn = de_identify_prismpaint;
421 // **************************************************************************
422 // Atari Falcon True Color .FTC
423 // **************************************************************************
425 static void de_run_ftc(deark *c, de_module_params *mparams)
427 struct atari_img_decode_data *adata = NULL;
428 de_finfo *fi = NULL;
430 adata = de_malloc(c, sizeof(struct atari_img_decode_data));
431 adata->bpp = 16;
432 adata->w = 384;
433 adata->h = 240;
434 adata->unc_pixels = c->infile;
435 adata->img = de_bitmap_create(c, adata->w, adata->h, 3);
436 fi = de_finfo_create(c);
437 fi->density.code = DE_DENSITY_UNK_UNITS;
438 fi->density.xdens = 288;
439 fi->density.ydens = 240;
440 fmtutil_atari_decode_image(c, adata);
441 de_bitmap_write_to_file_finfo(adata->img, fi, 0);
442 de_bitmap_destroy(adata->img);
443 de_finfo_destroy(c, fi);
444 de_free(c, adata);
447 static int de_identify_ftc(deark *c)
449 if(c->infile->len != 184320) return 0;
450 if(!de_input_file_has_ext(c, "ftc")) return 0;
451 return 60;
454 void de_module_ftc(deark *c, struct deark_module_info *mi)
456 mi->id = "ftc";
457 mi->desc = "Atari Falcon True Color .FTC";
458 mi->run_fn = de_run_ftc;
459 mi->identify_fn = de_identify_ftc;
462 // **************************************************************************
463 // Atari Falcon EggPaint .TRP
464 // **************************************************************************
466 static void de_run_eggpaint(deark *c, de_module_params *mparams)
468 struct atari_img_decode_data *adata = NULL;
470 adata = de_malloc(c, sizeof(struct atari_img_decode_data));
472 if(!dbuf_memcmp(c->infile, 0, "tru?", 4)) {
473 de_declare_fmt(c, "Spooky Sprites");
475 else {
476 de_declare_fmt(c, "EggPaint");
479 adata->bpp = 16;
480 adata->w = de_getu16be(4);
481 adata->h = de_getu16be(6);
482 de_dbg_dimensions(c, adata->w, adata->h);
483 adata->unc_pixels = dbuf_open_input_subfile(c->infile, 8, c->infile->len-8);
484 adata->img = de_bitmap_create(c, adata->w, adata->h, 3);
485 fmtutil_atari_decode_image(c, adata);
486 de_bitmap_write_to_file(adata->img, NULL, 0);
488 dbuf_close(adata->unc_pixels);
489 de_bitmap_destroy(adata->img);
490 de_free(c, adata);
493 static int de_identify_eggpaint(deark *c)
495 if(!dbuf_memcmp(c->infile, 0, "TRUP", 4)) {
496 return 80;
498 if(!dbuf_memcmp(c->infile, 0, "tru?", 4)) {
499 return 100;
501 return 0;
504 void de_module_eggpaint(deark *c, struct deark_module_info *mi)
506 mi->id = "eggpaint";
507 mi->desc = "Atari EggPaint .TRP";
508 mi->run_fn = de_run_eggpaint;
509 mi->identify_fn = de_identify_eggpaint;
512 // **************************************************************************
513 // Atari Falcon IndyPaint .TRU
514 // **************************************************************************
516 static void de_run_indypaint(deark *c, de_module_params *mparams)
518 struct atari_img_decode_data *adata = NULL;
520 adata = de_malloc(c, sizeof(struct atari_img_decode_data));
521 adata->bpp = 16;
522 adata->w = de_getu16be(4);
523 adata->h = de_getu16be(6);
524 de_dbg_dimensions(c, adata->w, adata->h);
525 adata->unc_pixels = dbuf_open_input_subfile(c->infile, 256, c->infile->len-256);
526 adata->img = de_bitmap_create(c, adata->w, adata->h, 3);
527 fmtutil_atari_decode_image(c, adata);
528 de_bitmap_write_to_file(adata->img, NULL, 0);
530 dbuf_close(adata->unc_pixels);
531 de_bitmap_destroy(adata->img);
532 de_free(c, adata);
535 static int de_identify_indypaint(deark *c)
537 if(!dbuf_memcmp(c->infile, 0, "Indy", 4)) {
538 return 70;
540 return 0;
543 void de_module_indypaint(deark *c, struct deark_module_info *mi)
545 mi->id = "indypaint";
546 mi->desc = "Atari IndyPaint .TRU";
547 mi->run_fn = de_run_indypaint;
548 mi->identify_fn = de_identify_indypaint;
551 // **************************************************************************
552 // Atari Falcon GodPaint .GOD
553 // **************************************************************************
555 static void de_run_godpaint(deark *c, de_module_params *mparams)
557 struct atari_img_decode_data *adata = NULL;
559 adata = de_malloc(c, sizeof(struct atari_img_decode_data));
560 adata->bpp = 16;
561 adata->w = de_getu16be(2);
562 adata->h = de_getu16be(4);
563 de_dbg_dimensions(c, adata->w, adata->h);
564 adata->unc_pixels = dbuf_open_input_subfile(c->infile, 6, c->infile->len-6);
565 adata->img = de_bitmap_create(c, adata->w, adata->h, 3);
566 fmtutil_atari_decode_image(c, adata);
567 de_bitmap_write_to_file(adata->img, NULL, 0);
569 dbuf_close(adata->unc_pixels);
570 de_bitmap_destroy(adata->img);
571 de_free(c, adata);
574 static int de_identify_godpaint(deark *c)
576 i64 sig;
578 sig = de_getu16be(0);
579 if(sig!=0x4734 && sig!=0x0400) return 0;
580 if(de_input_file_has_ext(c, "god")) return 100;
581 if(sig==0x4734) return 5;
582 return 0;
585 void de_module_godpaint(deark *c, struct deark_module_info *mi)
587 mi->id = "godpaint";
588 mi->desc = "Atari Falcon GodPaint";
589 mi->run_fn = de_run_godpaint;
590 mi->identify_fn = de_identify_godpaint;
593 // **************************************************************************
594 // Tiny Stuff
595 // **************************************************************************
597 typedef struct tinyctx_struct {
598 u8 res_code;
599 i64 num_control_bytes;
600 i64 num_data_words;
601 u32 pal[16];
603 // Decompression params:
604 i64 numstripes;
605 i64 numscans;
606 i64 dst_rowspan;
608 // Decompression state:
609 int stopflag;
610 i64 ypos;
611 i64 stripe;
612 i64 scan;
613 i64 column;
614 i64 dcmpr_word_count;
615 } tinyctx;
617 static void tiny_setword(deark *c, tinyctx *d, struct atari_img_decode_data *adata, const u8 *wordbuf)
619 i64 dstpos;
621 // As each word is emitted from the decompressor, we store it in the unc_pixels buffer
622 // in a particular location. The location is chosen so as to make the pixel data more
623 // contiguous, but (for 2bpp and 4bpp images) more work will still have to be done when
624 // the image is generated.
626 if(d->stopflag) return;
627 d->dcmpr_word_count++;
628 dstpos = d->stripe * 8 + d->column*2 + (d->ypos * d->numscans + d->scan)*d->dst_rowspan;
629 dbuf_write_at(adata->unc_pixels, dstpos, wordbuf, 2);
630 d->ypos++;
631 if(d->ypos >= 200) {
632 d->ypos = 0;
633 d->stripe++;
634 if(d->stripe >= d->numstripes) {
635 d->stripe = 0;
636 d->scan++;
637 if(d->scan >= d->numscans) {
638 d->scan = 0;
639 d->column++;
640 if(d->column >= 4) {
641 d->stopflag = 1;
642 return;
649 // Uncompress to adata->unc_pixels.
650 static int tiny_uncompress(deark *c, tinyctx *d, struct atari_img_decode_data *adata, i64 pos)
652 u8 *control_bytes = NULL;
653 i64 k;
654 i64 count;
655 i64 cpos;
656 u8 ctrl;
657 u8 wordbuf[2];
659 if(adata->bpp==1) {
660 d->numscans = 2;
661 d->numstripes = 10;
662 d->dst_rowspan = 80;
664 else {
665 d->numscans = 1;
666 d->numstripes = 20;
667 d->dst_rowspan = 160;
670 de_dbg(c, "RLE control bytes at %d", (int)pos);
671 control_bytes = de_malloc(c, d->num_control_bytes +2);
672 de_read(control_bytes, pos, d->num_control_bytes);
673 pos += d->num_control_bytes;
675 de_dbg(c, "RLE data words at %d", (int)pos);
677 cpos = 0;
679 d->stopflag = 0;
680 d->scan = 0;
681 d->ypos = 0;
682 d->column = 0;
683 d->stripe = 0;
684 d->dcmpr_word_count = 0;
686 while(1) {
687 if(d->stopflag) break;
688 if(cpos >= d->num_control_bytes) break;
689 ctrl = control_bytes[cpos++];
691 if(ctrl >= 128) { // Uncompressed run, count encoded in control byte
692 count = 256 - (i64)ctrl;
693 for(k=0; k<count; k++) {
694 dbuf_read(c->infile, wordbuf, pos, 2);
695 pos += 2;
696 tiny_setword(c, d, adata, wordbuf);
699 else if(ctrl == 0) { // RLE, 16-bit count in next 2 control bytes
700 count = de_getu16be_direct(&control_bytes[cpos]);
701 cpos += 2;
702 dbuf_read(c->infile, wordbuf, pos, 2);
703 pos += 2;
704 for(k=0; k<count; k++) {
705 tiny_setword(c, d, adata, wordbuf);
708 else if(ctrl == 1) { // Uncompressed run, 16-bit count in next 2 control bytes
709 count = de_getu16be_direct(&control_bytes[cpos]);
710 cpos += 2;
712 for(k=0; k<count; k++) {
713 dbuf_read(c->infile, wordbuf, pos, 2);
714 pos += 2;
715 tiny_setword(c, d, adata, wordbuf);
718 else { // RLE, count encoded in control byte
719 count = (i64)ctrl;
720 dbuf_read(c->infile, wordbuf, pos, 2);
721 pos += 2;
722 for(k=0; k<count; k++) {
723 tiny_setword(c, d, adata, wordbuf);
728 de_dbg(c, "decompressed words: %d", (int)d->dcmpr_word_count);
729 if(d->dcmpr_word_count<16000) {
730 de_warn(c, "Expected 16000 decompressed words, got %d", (int)d->dcmpr_word_count);
733 de_free(c, control_bytes);
734 return 1;
737 static void do_tinystuff_1bpp(deark *c, tinyctx *d, struct atari_img_decode_data *adata)
739 de_convert_image_paletted(adata->unc_pixels, 0, 1, d->dst_rowspan, adata->pal,
740 adata->img, 0);
743 static void do_tinystuff_2or4bpp(deark *c, tinyctx *d, struct atari_img_decode_data *adata)
745 i64 x, y;
746 i64 pos = 0;
747 i64 width;
748 UI bpp;
750 bpp = (UI)adata->bpp;
751 if(bpp!=2 && bpp!=4) return;
753 if(bpp==2) width = 640;
754 else width = 320;
756 for(y=0; y<200; y++) {
757 for(x=0; x<width; x+=16) {
758 UI n[4];
759 UI b_idx;
760 UI k;
762 // 2bpp: Every 2 words (4 bytes; 32 bits) makes 16 pixels
763 // 4bpp: Every 4 words (8 bytes; 64 bits) makes 16 pixels
764 for(b_idx=0; b_idx<bpp; b_idx++) {
765 n[b_idx] = (UI)dbuf_getu16be_p(adata->unc_pixels, &pos);
768 for(k=0; k<16; k++) {
769 UI v = 0;
771 for(b_idx=0; b_idx<bpp; b_idx++) {
772 if(n[b_idx]&(1U<<(15-k))) v += (1U<<b_idx);
774 de_bitmap_setpixel_rgb(adata->img, x+(i64)k, y, adata->pal[v]);
780 static void do_tinystuff_image(deark *c, tinyctx *d, struct atari_img_decode_data *adata)
782 switch(adata->bpp) {
783 case 1:
784 do_tinystuff_1bpp(c, d, adata);
785 break;
786 case 2:
787 case 4:
788 do_tinystuff_2or4bpp(c, d, adata);
789 break;
793 // Some 1bpp images apparently have the palette set to [001, 000],
794 // or other nonsense, instead of [777, 000].
795 // Try to handle that.
796 static void fix_dark_pal(deark *c, struct atari_img_decode_data *adata)
798 u32 ap[2];
800 if(adata->bpp!=1) return;
802 ap[0] = adata->pal[0]&0xffffff;
803 ap[1] = adata->pal[1]&0xffffff;
805 // Always respect white/black and black/white palettes.
806 if(ap[0]==0xffffff && ap[1]==0x000000) return; // The usual palette
807 if(ap[0]==0x000000 && ap[1]==0xffffff) return;
809 // Otherwise assume white/black, unless the user told us not to.
810 if(de_get_ext_option(c, "atari:respectpal")) return;
812 adata->pal[0] = DE_STOCKCOLOR_WHITE;
813 adata->pal[1] = DE_STOCKCOLOR_BLACK;
816 static void de_run_tinystuff(deark *c, de_module_params *mparams)
818 struct atari_img_decode_data *adata = NULL;
819 de_finfo *fi = NULL;
820 tinyctx *d = NULL;
821 i64 pos = 0;
822 i64 expected_min_file_size;
823 i64 expected_max_file_size;
824 int is_grayscale;
826 d = de_malloc(c, sizeof(tinyctx));
828 adata = de_malloc(c, sizeof(struct atari_img_decode_data));
829 adata->pal = d->pal;
830 adata->was_compressed = 1;
832 d->res_code = de_getbyte(pos);
833 pos++;
834 de_dbg(c, "resolution code: %d", (int)d->res_code);
836 switch(d->res_code) {
837 case 0: case 3:
838 adata->bpp = 4;
839 adata->w = 320;
840 adata->h = 200;
841 break;
842 case 1: case 4:
843 adata->bpp = 2;
844 adata->w = 640;
845 adata->h = 200;
846 break;
847 case 2: case 5:
848 adata->bpp = 1;
849 adata->w = 640;
850 adata->h = 400;
851 break;
852 default:
853 de_err(c, "Invalid resolution code (%d). This is not a Tiny Stuff file.",
854 (int)d->res_code);
855 goto done;
858 adata->ncolors = de_pow2(adata->bpp);
860 de_dbg(c, "dimensions: %d"DE_CHAR_TIMES"%d, colors: %d", (int)adata->w, (int)adata->h, (int)adata->ncolors);
862 if(d->res_code>=3) {
863 de_warn(c, "This image uses palette cycling animation, which is not supported.");
864 pos += 4; // skip animation_info
867 fmtutil_read_atari_palette(c, c->infile, pos, adata->pal, 16, adata->ncolors, 0);
868 fix_dark_pal(c, adata);
869 pos += 16*2;
871 d->num_control_bytes = de_getu16be(pos);
872 pos += 2;
873 de_dbg(c, "number of RLE control bytes: %d", (int)d->num_control_bytes);
875 d->num_data_words = de_getu16be(pos);
876 pos += 2;
877 de_dbg(c, "number of RLE data words: %d (%d bytes)", (int)d->num_data_words,
878 2*(int)(d->num_data_words));
880 // It seems that files are often padded to the next multiple of 128 bytes,
881 // so don't warn about that.
882 expected_min_file_size = pos + d->num_control_bytes + 2*d->num_data_words;
883 expected_max_file_size = ((expected_min_file_size+127)/128)*128;
884 de_dbg(c, "expected file size: %d or %d", (int)expected_min_file_size, (int)expected_max_file_size);
885 if(c->infile->len<expected_min_file_size || c->infile->len>expected_max_file_size) {
886 de_warn(c, "Expected file size to be %d, but it is %d.", (int)expected_min_file_size,
887 (int)c->infile->len);
890 adata->unc_pixels = dbuf_create_membuf(c, 32000, 1);
892 if(!tiny_uncompress(c, d, adata, pos)) {
893 goto done;
896 is_grayscale = de_is_grayscale_palette(adata->pal, adata->ncolors);
898 adata->img = de_bitmap_create(c, adata->w, adata->h, is_grayscale?1:3);
900 fi = de_finfo_create(c);
901 fmtutil_atari_set_standard_density(c, adata, fi);
903 do_tinystuff_image(c, d, adata);
904 de_bitmap_write_to_file_finfo(adata->img, fi, 0);
906 done:
907 if(adata) {
908 de_bitmap_destroy(adata->img);
909 dbuf_close(adata->unc_pixels);
910 de_free(c, adata);
912 de_finfo_destroy(c, fi);
913 de_free(c, d);
916 static int de_identify_tinystuff(deark *c)
918 // TODO: Can we identify these files?
919 if(de_getbyte(0)>0x05) return 0;
920 if(de_input_file_has_ext(c, "tny") ||
921 de_input_file_has_ext(c, "tn1") ||
922 de_input_file_has_ext(c, "tn2") ||
923 de_input_file_has_ext(c, "tn3") ||
924 de_input_file_has_ext(c, "tn4"))
926 return 8;
928 return 0;
931 static void de_help_tinystuff(deark *c)
933 fmtutil_atari_help_palbits(c);
934 help_respectpal(c);
937 void de_module_tinystuff(deark *c, struct deark_module_info *mi)
939 mi->id = "tinystuff";
940 mi->desc = "Atari Tiny Stuff, a.k.a. Tiny image format";
941 mi->run_fn = de_run_tinystuff;
942 mi->identify_fn = de_identify_tinystuff;
943 mi->help_fn = de_help_tinystuff;
946 // **************************************************************************
947 // Doodle (.doo)
948 // **************************************************************************
950 static void de_run_doodle(deark *c, de_module_params *mparams)
952 struct atari_img_decode_data *adata = NULL;
953 de_finfo *fi = NULL;
954 u32 pal[2];
956 adata = de_malloc(c, sizeof(struct atari_img_decode_data));
957 adata->pal = pal;
958 adata->bpp = 1;
960 adata->w = 640;
961 adata->h = 400;
962 adata->ncolors = 2;
963 adata->pal[0] = DE_STOCKCOLOR_WHITE;
964 adata->pal[1] = DE_STOCKCOLOR_BLACK;
966 adata->unc_pixels = c->infile;
967 adata->img = de_bitmap_create(c, adata->w, adata->h, 1);
968 fi = de_finfo_create(c);
969 fmtutil_atari_set_standard_density(c, adata, fi);
970 fmtutil_atari_decode_image(c, adata);
971 de_bitmap_write_to_file_finfo(adata->img, fi, 0);
973 if(adata) {
974 de_bitmap_destroy(adata->img);
975 de_free(c, adata);
977 de_finfo_destroy(c, fi);
980 static int de_identify_doodle(deark *c)
982 if(c->infile->len!=32000) return 0;
983 if(de_input_file_has_ext(c, "doo")) {
984 return 10;
986 return 0;
989 void de_module_doodle(deark *c, struct deark_module_info *mi)
991 mi->id = "doodle";
992 mi->desc = "Atari Doodle";
993 mi->run_fn = de_run_doodle;
994 mi->identify_fn = de_identify_doodle;
997 // **************************************************************************
998 // NEOchrome (.neo)
999 // **************************************************************************
1001 static void de_run_neochrome(deark *c, de_module_params *mparams)
1003 struct atari_img_decode_data *adata = NULL;
1004 de_finfo *fi = NULL;
1005 unsigned int resolution_code;
1006 int is_grayscale;
1007 u32 pal[16];
1009 adata = de_malloc(c, sizeof(struct atari_img_decode_data));
1010 adata->pal = pal;
1012 resolution_code = (unsigned int)de_getu16be(2);
1013 de_dbg(c, "resolution code: %u", resolution_code);
1014 if(resolution_code!=0) {
1015 de_err(c, "Invalid or unsupported NEOchrome image (resolution=%d)", (int)resolution_code);
1016 goto done;
1019 // TODO: Warn about palette animation settings.
1020 // TODO: (Maybe) Use the embedded filename, if it seems valid.
1022 adata->bpp = 4;
1023 adata->w = 320;
1024 adata->h = 200;
1025 adata->ncolors = de_pow2(adata->bpp);
1026 de_dbg(c, "dimensions: %d"DE_CHAR_TIMES"%d, colors: %d", (int)adata->w, (int)adata->h, (int)adata->ncolors);
1028 fmtutil_read_atari_palette(c, c->infile, 4, adata->pal, 16, adata->ncolors, 0);
1029 adata->unc_pixels = dbuf_open_input_subfile(c->infile, 128, 32000);
1030 is_grayscale = de_is_grayscale_palette(adata->pal, adata->ncolors);
1031 adata->img = de_bitmap_create(c, adata->w, adata->h, is_grayscale?1:3);
1032 fi = de_finfo_create(c);
1033 fmtutil_atari_set_standard_density(c, adata, fi);
1034 fmtutil_atari_decode_image(c, adata);
1035 de_bitmap_write_to_file_finfo(adata->img, fi, 0);
1037 done:
1038 if(adata) {
1039 dbuf_close(adata->unc_pixels);
1040 de_bitmap_destroy(adata->img);
1041 de_free(c, adata);
1043 de_finfo_destroy(c, fi);
1046 static int de_identify_neochrome(deark *c)
1048 if(de_input_file_has_ext(c, "neo")) {
1049 if(c->infile->len == 32128) {
1050 return 100;
1052 else if(c->infile->len > 32128) {
1053 return 10;
1056 return 0;
1059 static void de_help_neochrome(deark *c)
1061 fmtutil_atari_help_palbits(c);
1064 void de_module_neochrome(deark *c, struct deark_module_info *mi)
1066 mi->id = "neochrome";
1067 mi->desc = "Atari NEOchrome image";
1068 mi->run_fn = de_run_neochrome;
1069 mi->identify_fn = de_identify_neochrome;
1070 mi->help_fn = de_help_neochrome;
1073 // **************************************************************************
1074 // NEOchrome animation (.ani)
1075 // **************************************************************************
1077 static void de_run_neochrome_ani(deark *c, de_module_params *mparams)
1079 struct atari_img_decode_data *adata = NULL;
1080 i64 width_in_bytes;
1081 i64 nframes;
1082 i64 bytes_per_frame;
1083 i64 frame;
1084 i64 k;
1085 u32 pal[16];
1087 de_declare_fmt(c, "NEOchrome Animation");
1089 de_warn(c, "NEOchrome Animation images may not be decoded correctly.");
1091 adata = de_malloc(c, sizeof(struct atari_img_decode_data));
1093 // TODO: What palette should we use?
1094 for(k=0; k<16; k++) {
1095 pal[k] = DE_MAKE_GRAY((unsigned int)(k*17));
1097 adata->pal = pal;
1098 adata->bpp = 4;
1099 adata->ncolors = 16;
1101 width_in_bytes = de_getu16be(4); // Always a multiple of 8
1102 adata->w = ((width_in_bytes+7)/8)*16;
1103 adata->h = de_getu16be(6);
1104 de_dbg_dimensions(c, adata->w, adata->h);
1105 if(!de_good_image_dimensions(c, adata->w, adata->h)) goto done;
1107 bytes_per_frame = de_getu16be(8);
1108 bytes_per_frame -= 10;
1109 de_dbg(c, "bytes/frame: %d", (int)bytes_per_frame);
1110 if(bytes_per_frame<1) goto done;
1112 nframes = de_getu16be(14);
1113 de_dbg(c, "number of frames: %d", (int)nframes);
1114 if(!de_good_image_count(c, nframes)) goto done;
1116 for(frame=0; frame<nframes; frame++) {
1117 adata->unc_pixels = dbuf_open_input_subfile(c->infile, 22 + frame*bytes_per_frame, bytes_per_frame);
1118 adata->img = de_bitmap_create(c, adata->w, adata->h, 3);
1120 fmtutil_atari_decode_image(c, adata);
1121 de_bitmap_write_to_file(adata->img, NULL, 0);
1123 de_bitmap_destroy(adata->img);
1124 adata->img = NULL;
1126 dbuf_close(adata->unc_pixels);
1127 adata->unc_pixels = NULL;
1130 done:
1131 de_free(c, adata);
1134 static int de_identify_neochrome_ani(deark *c)
1136 if(!dbuf_memcmp(c->infile, 0, "\xba\xbe\xeb\xea", 4)) {
1137 return 100;
1139 return 0;
1142 void de_module_neochrome_ani(deark *c, struct deark_module_info *mi)
1144 mi->id = "neochrome_ani";
1145 mi->desc = "NEOchrome Animation";
1146 mi->run_fn = de_run_neochrome_ani;
1147 mi->identify_fn = de_identify_neochrome_ani;
1148 mi->flags |= DE_MODFLAG_NONWORKING;
1151 // **************************************************************************
1152 // Animatic Film (.flm)
1153 // **************************************************************************
1155 static void de_run_animatic(deark *c, de_module_params *mparams)
1157 struct atari_img_decode_data *adata = NULL;
1158 i64 nframes;
1159 i64 frame;
1160 i64 planespan, rowspan, framespan;
1161 i64 frame_bitmap_pos;
1162 u32 pal[16];
1164 de_declare_fmt(c, "Animatic Film");
1166 adata = de_malloc(c, sizeof(struct atari_img_decode_data));
1168 nframes = de_getu16be(0);
1169 de_dbg(c, "number of frames: %d", (int)nframes);
1170 if(!de_good_image_count(c, nframes)) goto done;
1172 adata->bpp = 4;
1173 adata->ncolors = 16;
1174 adata->pal = pal;
1175 de_dbg_indent(c, 1);
1176 fmtutil_read_atari_palette(c, c->infile, 2, adata->pal, 16, adata->ncolors, 0);
1177 de_dbg_indent(c, -1);
1179 adata->w = de_getu16be(40);
1180 adata->h = de_getu16be(42);
1181 de_dbg_dimensions(c, adata->w, adata->h);
1182 if(!de_good_image_dimensions(c, adata->w, adata->h)) goto done;
1184 planespan = 2*((adata->w+15)/16);
1185 rowspan = planespan*adata->bpp;
1186 framespan = rowspan*adata->h;
1188 for(frame=0; frame<nframes; frame++) {
1189 frame_bitmap_pos = 64 + frame*framespan;
1190 de_dbg(c, "frame %d bitmap at %d", (int)frame, (int)frame_bitmap_pos);
1192 adata->unc_pixels = dbuf_open_input_subfile(c->infile, frame_bitmap_pos, framespan);
1193 adata->img = de_bitmap_create(c, adata->w, adata->h, 3);
1195 fmtutil_atari_decode_image(c, adata);
1196 de_bitmap_write_to_file(adata->img, NULL, 0);
1198 de_bitmap_destroy(adata->img);
1199 adata->img = NULL;
1201 dbuf_close(adata->unc_pixels);
1202 adata->unc_pixels = NULL;
1205 done:
1206 de_free(c, adata);
1209 static int de_identify_animatic(deark *c)
1211 if(!dbuf_memcmp(c->infile, 48, "\x27\x18\x28\x18", 4)) {
1212 return 100;
1214 return 0;
1217 static void de_help_animatic(deark *c)
1219 fmtutil_atari_help_palbits(c);
1222 void de_module_animatic(deark *c, struct deark_module_info *mi)
1224 mi->id = "animatic";
1225 mi->desc = "Animatic Film";
1226 mi->run_fn = de_run_animatic;
1227 mi->identify_fn = de_identify_animatic;
1228 mi->help_fn = de_help_animatic;
1231 // **************************************************************************
1232 // Atari .PI4/.PI9
1233 // **************************************************************************
1235 static void decode_falcon_8bit_image(deark *c, struct atari_img_decode_data *adata, i64 pos)
1237 i64 i, j, k;
1238 unsigned int v;
1239 unsigned int n;
1240 de_finfo *fi = NULL;
1242 adata->img = de_bitmap_create(c, adata->w, adata->h, 3);
1244 fi = de_finfo_create(c);
1245 if(adata->w==320 && adata->h==200) {
1246 fi->density.code = DE_DENSITY_UNK_UNITS;
1247 fi->density.xdens = 240.0;
1248 fi->density.ydens = 200.0;
1251 for(j=0; j<adata->h; j++) {
1252 for(i=0; i<adata->w; i++) {
1253 v = 0;
1254 for(k=0; k<8; k++) {
1255 n = (u32)de_getu16be(pos+j*adata->w + (i-i%16) +2*k);
1256 if(n&(1<<(15-i%16))) v |= 1<<k;
1258 de_bitmap_setpixel_rgb(adata->img, i, j, adata->pal[v]);
1262 de_bitmap_write_to_file_finfo(adata->img, fi, 0);
1263 de_bitmap_destroy(adata->img);
1264 adata->img = NULL;
1265 de_finfo_destroy(c, fi);
1268 static void do_atari_falcon_8bit_img(deark *c, i64 width, i64 height)
1270 struct atari_img_decode_data *adata = NULL;
1271 i64 k;
1272 u8 cr, cg, cb;
1273 u32 pal[256];
1275 adata = de_malloc(c, sizeof(struct atari_img_decode_data));
1276 de_zeromem(pal, sizeof(pal));
1277 adata->pal = pal;
1278 adata->bpp = 8;
1279 adata->ncolors = 256;
1280 adata->w = width;
1281 adata->h = height;
1282 de_dbg_dimensions(c, adata->w, adata->h);
1284 for(k=0; k<256; k++) {
1285 cr = de_getbyte(k*4+0);
1286 cg = de_getbyte(k*4+1);
1287 cb = de_getbyte(k*4+3);
1288 pal[k] = DE_MAKE_RGB(cr, cg, cb);
1289 de_dbg_pal_entry(c, k, pal[k]);
1292 decode_falcon_8bit_image(c, adata, 1024);
1294 de_free(c, adata);
1297 static void de_run_fpaint_pi4(deark *c, de_module_params *mparams)
1299 do_atari_falcon_8bit_img(c, 320, 240);
1302 // Atari falcon 320x240
1303 static int de_identify_fpaint_pi4(deark *c)
1305 if(c->infile->len==77824) {
1306 if(de_input_file_has_ext(c, "pi4") ||
1307 de_input_file_has_ext(c, "pi9"))
1309 return 50; // Must be lower than fpaint_pi9
1312 return 0;
1315 void de_module_fpaint_pi4(deark *c, struct deark_module_info *mi)
1317 mi->id = "fpaint_pi4";
1318 mi->desc = "Atari Falcon PI4 image";
1319 mi->run_fn = de_run_fpaint_pi4;
1320 mi->identify_fn = de_identify_fpaint_pi4;
1323 static void de_run_fpaint_pi9(deark *c, de_module_params *mparams)
1325 do_atari_falcon_8bit_img(c, 320, 200);
1328 // Atari falcon 320x200
1329 static int de_identify_fpaint_pi9(deark *c)
1331 int pi4_ext, pi9_ext;
1333 if(c->infile->len!=77824 && c->infile->len!=65024) return 0;
1335 pi4_ext = de_input_file_has_ext(c, "pi4");
1336 pi9_ext = de_input_file_has_ext(c, "pi9");
1337 if(!pi4_ext && !pi9_ext) return 0;
1339 if(c->infile->len==65024) return 60;
1341 // If file size is 77824, we need to distinguish between PI4 (320x240) and
1342 // PI9 (320x200) format.
1343 // Best guess is that if the last 12800 bytes are all 0, we should assume PI9.
1344 if(!dbuf_is_all_zeroes(c->infile, 65024, 12800)) {
1345 return 0; // Will be identified elsewhere as PI4.
1348 return 60; // PI9. Must be higher than the value PI4 uses.
1351 void de_module_fpaint_pi9(deark *c, struct deark_module_info *mi)
1353 mi->id = "fpaint_pi9";
1354 mi->desc = "Atari Falcon PI9 image";
1355 mi->run_fn = de_run_fpaint_pi9;
1356 mi->identify_fn = de_identify_fpaint_pi9;
1359 // **************************************************************************
1360 // Atari .PI7
1361 // **************************************************************************
1363 static void de_run_atari_pi7(deark *c, de_module_params *mparams)
1365 do_atari_falcon_8bit_img(c, 640, 480);
1368 static int de_identify_atari_pi7(deark *c)
1370 if(c->infile->len==308224) {
1371 if(de_input_file_has_ext(c, "pi7"))
1373 return 50;
1376 return 0;
1379 void de_module_atari_pi7(deark *c, struct deark_module_info *mi)
1381 mi->id = "atari_pi7";
1382 mi->desc = "Atari PI7 image";
1383 mi->run_fn = de_run_atari_pi7;
1384 mi->identify_fn = de_identify_atari_pi7;
1387 // **************************************************************************
1388 // Atari Falcon XGA
1389 // **************************************************************************
1391 static void de_run_falcon_xga(deark *c, de_module_params *mparams)
1393 struct atari_img_decode_data *adata = NULL;
1394 de_finfo *fi = NULL;
1396 adata = de_malloc(c, sizeof(struct atari_img_decode_data));
1397 if(c->infile->len==153600) {
1398 adata->bpp = 16;
1399 adata->w = 320;
1400 adata->h = 240;
1402 else {
1403 adata->bpp = 16;
1404 adata->w = 384;
1405 adata->h = 480;
1407 de_dbg_dimensions(c, adata->w, adata->h);
1408 adata->unc_pixels = c->infile;
1409 adata->img = de_bitmap_create(c, adata->w, adata->h, 3);
1410 fi = de_finfo_create(c);
1411 if(adata->w==384 && adata->h == 480) {
1412 fi->density.code = DE_DENSITY_UNK_UNITS;
1413 fi->density.xdens = 384;
1414 fi->density.ydens = 640;
1416 fmtutil_atari_decode_image(c, adata);
1417 de_bitmap_write_to_file_finfo(adata->img, fi, 0);
1418 de_bitmap_destroy(adata->img);
1419 de_finfo_destroy(c, fi);
1420 de_free(c, adata);
1423 static int de_identify_falcon_xga(deark *c)
1425 if(c->infile->len==153600 || c->infile->len==368640) {
1426 if(de_input_file_has_ext(c, "xga"))
1428 return 50;
1431 return 0;
1434 void de_module_falcon_xga(deark *c, struct deark_module_info *mi)
1436 mi->id = "falcon_xga";
1437 mi->desc = "Atari Falcon XGA image";
1438 mi->run_fn = de_run_falcon_xga;
1439 mi->identify_fn = de_identify_falcon_xga;
1442 // **************************************************************************
1443 // Atari Falcon COKE (.tg1)
1444 // **************************************************************************
1446 static void de_run_coke(deark *c, de_module_params *mparams)
1448 i64 imgdatapos;
1449 struct atari_img_decode_data *adata = NULL;
1450 de_finfo *fi = NULL;
1452 adata = de_malloc(c, sizeof(struct atari_img_decode_data));
1453 adata->bpp = 16;
1454 adata->w = de_getu16be(12);
1455 adata->h = de_getu16be(14);
1456 de_dbg_dimensions(c, adata->w, adata->h);
1457 imgdatapos = de_getu16be(16);
1458 de_dbg(c, "image data pos: %d", (int)imgdatapos);
1460 adata->unc_pixels = dbuf_open_input_subfile(c->infile,
1461 imgdatapos, c->infile->len-imgdatapos);
1462 adata->img = de_bitmap_create(c, adata->w, adata->h, 3);
1464 fi = de_finfo_create(c);
1465 fi->density.code = DE_DENSITY_UNK_UNITS;
1466 fi->density.xdens = 288;
1467 fi->density.ydens = 240;
1469 fmtutil_atari_decode_image(c, adata);
1470 de_bitmap_write_to_file_finfo(adata->img, fi, 0);
1472 if(adata) {
1473 dbuf_close(adata->unc_pixels);
1474 de_bitmap_destroy(adata->img);
1475 de_free(c, adata);
1477 de_finfo_destroy(c, fi);
1480 static int de_identify_coke(deark *c)
1482 if(!dbuf_memcmp(c->infile, 0, (const void*)"COKE format.", 12)) {
1483 return 100;
1485 return 0;
1488 void de_module_coke(deark *c, struct deark_module_info *mi)
1490 mi->id = "coke";
1491 mi->desc = "Atari Falcon COKE image (.TG1)";
1492 mi->run_fn = de_run_coke;
1493 mi->identify_fn = de_identify_coke;