fnt: Improved error handling, etc.
[deark.git] / modules / atari-img.c
blob0f2c024ae7f3830f4bbe6f50570d0de85e9f52ef
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);
24 DE_DECLARE_MODULE(de_module_videomaster);
26 static void fix_dark_pal(deark *c, struct atari_img_decode_data *adata);
28 static void help_respectpal(deark *c)
30 de_msg(c, "-opt atari:respectpal : Don't ignore a seemingly bad 2-color palette");
33 // **************************************************************************
34 // DEGAS / DEGAS Elite images
35 // **************************************************************************
37 typedef struct degasctx_struct {
38 unsigned int compression_code;
39 int degas_elite_flag;
40 u32 pal[16];
41 } degasctx;
43 static void do_degas_anim_fields(deark *c, degasctx *d, i64 pos)
45 i64 i;
46 i64 n;
48 for(i=0; i<4; i++) {
49 n = de_getu16be(pos + 2*i);
50 de_dbg2(c, "left_color_anim[%d] = %d", (int)i, (int)n);
52 for(i=0; i<4; i++) {
53 n = de_getu16be(pos + 8 + 2*i);
54 de_dbg2(c, "right_color_anim[%d] = %d", (int)i, (int)n);
56 for(i=0; i<4; i++) {
57 n = de_getu16be(pos + 16 + 2*i);
58 de_dbg2(c, "channel_direction[%d] = %d", (int)i, (int)n);
60 for(i=0; i<4; i++) {
61 n = de_getu16be(pos + 24 + 2*i);
62 de_dbg2(c, "channel_delay_code[%d] = %d", (int)i, (int)n);
65 // TODO: Can we determine if palette animation is actually used,
66 // and only show the warning if it is?
67 //de_warn(c, "This image may use palette cycling animation, which is not supported.");
70 // Try to figure out if this is a DEGAS Elite file (as opposed to original DEGAS).
71 static int is_degas_elite(deark *c, degasctx *d)
73 i64 n;
74 i64 x;
75 i64 pos;
76 int all_zero = 1;
78 if(d->compression_code) return 1; // Only DEGAS Elite supports compression.
79 if(c->infile->len < 32066) return 0;
81 // Test if the animation segment seems to have valid values, to try to distinguish
82 // it from meaningless padding. (This is overkill.)
83 pos = 32034;
84 for(n=0; n<8; n++) {
85 // The first 8 fields are "color numbers".
86 // Guessing that they should be 0-15.
87 x = de_getu16be(pos+n*2);
88 if(x>0x0f) return 0;
89 if(x) all_zero = 0;
91 pos += 8*2;
92 for(n=0; n<4; n++) {
93 // The next 4 fields (channel direction) should be 0, 1, or 2.
94 x = de_getu16be(pos+n*2);
95 if(x>2) return 0;
96 if(x) all_zero = 0;
98 pos += 4*2;
99 for(n=0; n<4; n++) {
100 // The next 4 fields (delay) must be from 0 to 128.
101 x = de_getu16be(pos+n*2);
102 if(x>128) return 0;
103 if(x) all_zero = 0;
106 if(all_zero && c->infile->len>32068) {
107 // If every field was 0, and the file size doesn't suggest Elite,
108 // just assume it's not valid.
109 return 0;
112 return 1;
115 static void de_run_degas(deark *c, de_module_params *mparams)
117 degasctx *d = NULL;
118 struct atari_img_decode_data *adata = NULL;
119 de_finfo *fi = NULL;
120 i64 pos;
121 unsigned int format_code, resolution_code;
122 int is_grayscale;
123 i64 cmpr_bytes_consumed = 0;
125 d = de_malloc(c, sizeof(degasctx));
126 adata = de_malloc(c, sizeof(struct atari_img_decode_data));
128 adata->pal = d->pal;
130 pos = 0;
131 format_code = (unsigned int)de_getu16be(pos);
132 de_dbg(c, "format code: 0x%04x", format_code);
133 resolution_code = format_code & 0x0003;
134 d->compression_code = (format_code & 0x8000)>>15;
135 de_dbg_indent(c, 1);
136 de_dbg(c, "resolution code: %u", resolution_code);
137 de_dbg(c, "compression code: %u", d->compression_code);
138 de_dbg_indent(c, -1);
139 pos += 2;
141 switch(resolution_code) {
142 case 0:
143 adata->bpp = 4;
144 adata->w = 320;
145 adata->h = 200;
146 break;
147 case 1:
148 adata->bpp = 2;
149 adata->w = 640;
150 adata->h = 200;
151 break;
152 case 2:
153 adata->bpp = 1;
154 adata->w = 640;
155 adata->h = 400;
156 break;
157 default:
158 de_dbg(c, "Invalid or unsupported resolution (%u)", resolution_code);
159 goto done;
161 adata->ncolors = de_pow2(adata->bpp);
163 de_dbg(c, "dimensions: %d"DE_CHAR_TIMES"%d, colors: %d", (int)adata->w, (int)adata->h, (int)adata->ncolors);
165 d->degas_elite_flag = is_degas_elite(c, d);
166 de_declare_fmtf(c, "DEGAS%s %d-color %scompressed",
167 d->degas_elite_flag?" Elite":"",
168 (int)adata->ncolors,
169 d->compression_code?"":"un");
171 fmtutil_read_atari_palette(c, c->infile, pos, adata->pal, 16, adata->ncolors, 0);
172 pos += 2*16;
173 fix_dark_pal(c, adata);
175 if(d->compression_code) {
176 adata->was_compressed = 1;
177 adata->unc_pixels = dbuf_create_membuf(c, 32000, 1);
178 dbuf_enable_wbuffer(adata->unc_pixels);
180 if(!fmtutil_decompress_packbits(c->infile, pos, c->infile->len-pos, adata->unc_pixels, &cmpr_bytes_consumed))
181 goto done;
182 dbuf_flush(adata->unc_pixels);
184 de_dbg(c, "Compressed bytes found: %d", (int)cmpr_bytes_consumed);
185 pos += cmpr_bytes_consumed;
187 else {
188 i64 avail_bytes = 32000;
189 if(pos+32000 > c->infile->len) {
190 avail_bytes = c->infile->len - pos;
191 de_warn(c, "Unexpected end of file (expected 32000 bytes, got %d)", (int)avail_bytes);
193 adata->unc_pixels = dbuf_open_input_subfile(c->infile, pos, avail_bytes);
194 pos += avail_bytes;
197 if(pos + 32 == c->infile->len) {
198 do_degas_anim_fields(c, d, pos);
201 is_grayscale = de_is_grayscale_palette(adata->pal, adata->ncolors);
203 adata->img = de_bitmap_create(c, adata->w, adata->h, is_grayscale?1:3);
205 fi = de_finfo_create(c);
206 fmtutil_atari_set_standard_density(c, adata, fi);
208 fmtutil_atari_decode_image(c, adata);
210 de_bitmap_write_to_file_finfo(adata->img, fi, 0);
212 done:
213 if(adata) {
214 dbuf_close(adata->unc_pixels);
215 de_bitmap_destroy(adata->img);
216 de_free(c, adata);
218 de_finfo_destroy(c, fi);
219 de_free(c, d);
222 static int de_identify_degas(deark *c)
224 static const char *exts[6] = {"pi1", "pi2", "pi3", "pc1", "pc2", "pc3" };
225 i64 i;
226 int flag;
227 i64 sig;
229 flag = 0;
230 for(i=0; i<6; i++) {
231 if(de_input_file_has_ext(c, exts[i])) {
232 flag = 1;
233 break;
236 if(!flag) return 0;
238 sig = de_getu16be(0);
239 if(sig==0x0000 || sig==0x0001 || sig==0x0002) {
240 if(c->infile->len==32034) return 100; // DEGAS
241 if(c->infile->len==32066) return 100; // DEGAS Elite
242 if(c->infile->len==32128) return 40; // Could be padded to a multiple of 128 bytes
243 if(c->infile->len>16000) return 10;
245 else if(sig==0x8000 || sig==0x8001 || sig==0x8002) {
246 return 60;
249 return 0;
252 static void de_help_degas(deark *c)
254 fmtutil_atari_help_palbits(c);
255 help_respectpal(c);
258 void de_module_degas(deark *c, struct deark_module_info *mi)
260 mi->id = "degas";
261 mi->desc = "Atari DEGAS or DEGAS Elite image";
262 mi->run_fn = de_run_degas;
263 mi->identify_fn = de_identify_degas;
264 mi->help_fn = de_help_degas;
267 // **************************************************************************
268 // Atari Prism Paint (.pnt)
269 // **************************************************************************
271 typedef struct prismctx_struct {
272 i64 pal_size;
273 UI compression_code;
274 i64 pic_data_size;
275 u32 pal[256];
276 } prismctx;
278 // A color value of N does not necessarily refer to Nth color in the palette.
279 // Some of them are mixed up. Apparently this is called "VDI order".
280 // Reference: http://toshyp.atari.org/en/VDI_fundamentals.html
281 static unsigned int map_vdi_pal(i64 bpp, unsigned int v)
283 if(bpp==1) return v;
284 switch(v) {
285 case 1: return 2;
286 case 2: return 3;
287 case 3: return bpp>2 ? 6 : 1;
288 case 5: return 7;
289 case 6: return 5;
290 case 7: return 8;
291 case 8: return 9;
292 case 9: return 10;
293 case 10: return 11;
294 case 11: return 14;
295 case 13: return 15;
296 case 14: return 13;
297 case 15: return bpp==8 ? 255 : 1;
298 case 255: return 1;
300 return v;
303 static void do_prism_read_palette(deark *c, prismctx *d, struct atari_img_decode_data *adata)
305 i64 i;
306 i64 r1, g1, b1;
307 u8 r, g, b;
308 u32 pal1[256];
309 u32 clr;
310 i64 num_entries_to_read;
311 char tmps[32];
313 de_zeromem(pal1, sizeof(pal1));
314 num_entries_to_read = de_min_int(d->pal_size, 256);
316 for(i=0; i<num_entries_to_read; i++) {
317 r1 = de_getu16be(128+6*i+0);
318 g1 = de_getu16be(128+6*i+2);
319 b1 = de_getu16be(128+6*i+4);
320 r = de_scale_1000_to_255(r1);
321 g = de_scale_1000_to_255(g1);
322 b = de_scale_1000_to_255(b1);
323 clr = DE_MAKE_RGB(r,g,b);
324 de_snprintf(tmps, sizeof(tmps), "(%4d,%4d,%4d) "DE_CHAR_RIGHTARROW" ",
325 (int)r1, (int)g1, (int)b1);
326 de_dbg_pal_entry2(c, i, clr, tmps, NULL, NULL);
327 pal1[i] = clr;
330 for(i=0; i<num_entries_to_read; i++) {
331 d->pal[i] = pal1[map_vdi_pal(adata->bpp, (unsigned int)i)];
335 static void de_run_prismpaint(deark *c, de_module_params *mparams)
337 prismctx *d = NULL;
338 i64 pixels_start;
339 struct atari_img_decode_data *adata = NULL;
341 d = de_malloc(c, sizeof(prismctx));
343 adata = de_malloc(c, sizeof(struct atari_img_decode_data));
345 adata->pal = d->pal;
346 d->pal_size = de_getu16be(6);
347 de_dbg(c, "pal_size: %d", (int)d->pal_size);
348 adata->w = de_getu16be(8);
349 adata->h = de_getu16be(10);
350 de_dbg_dimensions(c, adata->w, adata->h);
351 if(!de_good_image_dimensions(c, adata->w, adata->h)) goto done;
353 adata->bpp = de_getu16be(12);
354 de_dbg(c, "bits/pixel: %d", (int)adata->bpp);
355 d->compression_code = (UI)de_getu16be(14);
356 de_dbg(c, "compression: %u", d->compression_code);
358 d->pic_data_size = de_getu32be(16);
359 de_dbg(c, "reported (uncompressed) picture data size: %"I64_FMT, d->pic_data_size);
361 do_prism_read_palette(c, d, adata);
363 if(adata->bpp!=1 && adata->bpp!=2 && adata->bpp!=4
364 && adata->bpp!=8 && adata->bpp!=16)
366 de_err(c, "Unsupported bits/pixel: %d", (int)adata->bpp);
367 goto done;
369 if(d->compression_code!=0 && d->compression_code!=1) {
370 de_err(c, "Unsupported compression: %u", d->compression_code);
371 goto done;
373 if(adata->bpp==16 && d->compression_code!=0) {
374 de_warn(c, "Compressed 16-bit image support is untested, and may not work.");
377 pixels_start = 128 + 2*3*d->pal_size;
378 de_dbg(c, "pixel data starts at %"I64_FMT, pixels_start);
379 if(pixels_start >= c->infile->len) goto done;
381 if(d->compression_code==0) {
382 adata->unc_pixels = dbuf_open_input_subfile(c->infile, pixels_start,
383 c->infile->len - pixels_start);
385 else {
386 adata->was_compressed = 1;
387 // TODO: Calculate the initial size more accurately.
388 adata->unc_pixels = dbuf_create_membuf(c, adata->w*adata->h, 0);
389 //dbuf_set_max_length(unc_pixels, ...);
390 dbuf_enable_wbuffer(adata->unc_pixels);
392 fmtutil_decompress_packbits(c->infile, pixels_start, c->infile->len - pixels_start,
393 adata->unc_pixels, NULL);
394 dbuf_flush(adata->unc_pixels);
395 de_dbg(c, "decompressed to %"I64_FMT" bytes", adata->unc_pixels->len);
398 adata->img = de_bitmap_create(c, adata->w, adata->h, 3);
399 fmtutil_atari_decode_image(c, adata);
400 de_bitmap_write_to_file(adata->img, NULL, 0);
402 done:
403 if(adata) {
404 dbuf_close(adata->unc_pixels);
405 de_bitmap_destroy(adata->img);
406 de_free(c, adata);
408 de_free(c, d);
411 static int de_identify_prismpaint(deark *c)
413 if(!dbuf_memcmp(c->infile, 0, "PNT\x00", 4))
414 return 100;
415 return 0;
418 void de_module_prismpaint(deark *c, struct deark_module_info *mi)
420 mi->id = "prismpaint";
421 mi->desc = "Atari Prism Paint .PNT, a.k.a. TruePaint .TPI";
422 mi->run_fn = de_run_prismpaint;
423 mi->identify_fn = de_identify_prismpaint;
426 // **************************************************************************
427 // Atari Falcon True Color .FTC
428 // **************************************************************************
430 static void de_run_ftc(deark *c, de_module_params *mparams)
432 struct atari_img_decode_data *adata = NULL;
433 de_finfo *fi = NULL;
435 adata = de_malloc(c, sizeof(struct atari_img_decode_data));
436 adata->bpp = 16;
437 adata->w = 384;
438 adata->h = 240;
439 adata->unc_pixels = c->infile;
440 adata->img = de_bitmap_create(c, adata->w, adata->h, 3);
441 fi = de_finfo_create(c);
442 fi->density.code = DE_DENSITY_UNK_UNITS;
443 fi->density.xdens = 288;
444 fi->density.ydens = 240;
445 fmtutil_atari_decode_image(c, adata);
446 de_bitmap_write_to_file_finfo(adata->img, fi, 0);
447 de_bitmap_destroy(adata->img);
448 de_finfo_destroy(c, fi);
449 de_free(c, adata);
452 static int de_identify_ftc(deark *c)
454 if(c->infile->len != 184320) return 0;
455 if(!de_input_file_has_ext(c, "ftc")) return 0;
456 return 60;
459 void de_module_ftc(deark *c, struct deark_module_info *mi)
461 mi->id = "ftc";
462 mi->desc = "Atari Falcon True Color .FTC";
463 mi->run_fn = de_run_ftc;
464 mi->identify_fn = de_identify_ftc;
467 // **************************************************************************
468 // Atari Falcon EggPaint .TRP
469 // **************************************************************************
471 static void de_run_eggpaint(deark *c, de_module_params *mparams)
473 struct atari_img_decode_data *adata = NULL;
475 adata = de_malloc(c, sizeof(struct atari_img_decode_data));
477 if(!dbuf_memcmp(c->infile, 0, "tru?", 4)) {
478 de_declare_fmt(c, "Spooky Sprites");
480 else {
481 de_declare_fmt(c, "EggPaint");
484 adata->bpp = 16;
485 adata->w = de_getu16be(4);
486 adata->h = de_getu16be(6);
487 de_dbg_dimensions(c, adata->w, adata->h);
488 adata->unc_pixels = dbuf_open_input_subfile(c->infile, 8, c->infile->len-8);
489 adata->img = de_bitmap_create(c, adata->w, adata->h, 3);
490 fmtutil_atari_decode_image(c, adata);
491 de_bitmap_write_to_file(adata->img, NULL, 0);
493 dbuf_close(adata->unc_pixels);
494 de_bitmap_destroy(adata->img);
495 de_free(c, adata);
498 static int de_identify_eggpaint(deark *c)
500 if(!dbuf_memcmp(c->infile, 0, "TRUP", 4)) {
501 return 80;
503 if(!dbuf_memcmp(c->infile, 0, "tru?", 4)) {
504 return 100;
506 return 0;
509 void de_module_eggpaint(deark *c, struct deark_module_info *mi)
511 mi->id = "eggpaint";
512 mi->desc = "Atari EggPaint .TRP";
513 mi->run_fn = de_run_eggpaint;
514 mi->identify_fn = de_identify_eggpaint;
517 // **************************************************************************
518 // Atari Falcon IndyPaint .TRU
519 // **************************************************************************
521 static void de_run_indypaint(deark *c, de_module_params *mparams)
523 struct atari_img_decode_data *adata = NULL;
525 adata = de_malloc(c, sizeof(struct atari_img_decode_data));
526 adata->bpp = 16;
527 adata->w = de_getu16be(4);
528 adata->h = de_getu16be(6);
529 de_dbg_dimensions(c, adata->w, adata->h);
530 adata->unc_pixels = dbuf_open_input_subfile(c->infile, 256, c->infile->len-256);
531 adata->img = de_bitmap_create(c, adata->w, adata->h, 3);
532 fmtutil_atari_decode_image(c, adata);
533 de_bitmap_write_to_file(adata->img, NULL, 0);
535 dbuf_close(adata->unc_pixels);
536 de_bitmap_destroy(adata->img);
537 de_free(c, adata);
540 static int de_identify_indypaint(deark *c)
542 if(!dbuf_memcmp(c->infile, 0, "Indy", 4)) {
543 return 70;
545 return 0;
548 void de_module_indypaint(deark *c, struct deark_module_info *mi)
550 mi->id = "indypaint";
551 mi->desc = "Atari IndyPaint .TRU";
552 mi->run_fn = de_run_indypaint;
553 mi->identify_fn = de_identify_indypaint;
556 // **************************************************************************
557 // Atari Falcon GodPaint .GOD
558 // **************************************************************************
560 static void de_run_godpaint(deark *c, de_module_params *mparams)
562 struct atari_img_decode_data *adata = NULL;
564 adata = de_malloc(c, sizeof(struct atari_img_decode_data));
565 adata->bpp = 16;
566 adata->w = de_getu16be(2);
567 adata->h = de_getu16be(4);
568 de_dbg_dimensions(c, adata->w, adata->h);
569 adata->unc_pixels = dbuf_open_input_subfile(c->infile, 6, c->infile->len-6);
570 adata->img = de_bitmap_create(c, adata->w, adata->h, 3);
571 fmtutil_atari_decode_image(c, adata);
572 de_bitmap_write_to_file(adata->img, NULL, 0);
574 dbuf_close(adata->unc_pixels);
575 de_bitmap_destroy(adata->img);
576 de_free(c, adata);
579 static int de_identify_godpaint(deark *c)
581 i64 sig;
583 sig = de_getu16be(0);
584 if(sig!=0x4734 && sig!=0x0400) return 0;
585 if(de_input_file_has_ext(c, "god")) return 100;
586 if(sig==0x4734) return 5;
587 return 0;
590 void de_module_godpaint(deark *c, struct deark_module_info *mi)
592 mi->id = "godpaint";
593 mi->desc = "Atari Falcon GodPaint";
594 mi->run_fn = de_run_godpaint;
595 mi->identify_fn = de_identify_godpaint;
598 // **************************************************************************
599 // Tiny Stuff
600 // **************************************************************************
602 typedef struct tinyctx_struct {
603 u8 res_code;
604 i64 num_control_bytes;
605 i64 num_data_words;
606 i64 data_words_nbytes;
607 u32 pal[16];
609 // Decompression params:
610 i64 numstripes;
611 i64 numscans;
612 i64 dst_rowspan;
614 // Decompression state:
615 int stopflag;
616 i64 ypos;
617 i64 stripe;
618 i64 scan;
619 i64 column;
620 i64 dcmpr_word_count;
621 } tinyctx;
623 static void tiny_setword(deark *c, tinyctx *d, struct atari_img_decode_data *adata, const u8 *wordbuf)
625 i64 dstpos;
627 // As each word is emitted from the decompressor, we store it in the unc_pixels buffer
628 // in a particular location. The location is chosen so as to make the pixel data more
629 // contiguous, but (for 2bpp and 4bpp images) more work will still have to be done when
630 // the image is generated.
632 if(d->stopflag) return;
633 d->dcmpr_word_count++;
634 dstpos = d->stripe * 8 + d->column*2 + (d->ypos * d->numscans + d->scan)*d->dst_rowspan;
635 dbuf_write_at(adata->unc_pixels, dstpos, wordbuf, 2);
636 d->ypos++;
637 if(d->ypos >= 200) {
638 d->ypos = 0;
639 d->stripe++;
640 if(d->stripe >= d->numstripes) {
641 d->stripe = 0;
642 d->scan++;
643 if(d->scan >= d->numscans) {
644 d->scan = 0;
645 d->column++;
646 if(d->column >= 4) {
647 d->stopflag = 1;
648 return;
655 // Uncompress to adata->unc_pixels.
656 static int tiny_uncompress(deark *c, tinyctx *d, struct atari_img_decode_data *adata, i64 pos)
658 u8 *control_bytes = NULL;
659 i64 k;
660 i64 count;
661 i64 cpos;
662 u8 ctrl;
663 u8 wordbuf[2];
665 if(adata->bpp==1) {
666 d->numscans = 2;
667 d->numstripes = 10;
668 d->dst_rowspan = 80;
670 else {
671 d->numscans = 1;
672 d->numstripes = 20;
673 d->dst_rowspan = 160;
676 de_dbg(c, "RLE control bytes at %"I64_FMT, pos);
677 control_bytes = de_malloc(c, d->num_control_bytes +2);
678 de_read(control_bytes, pos, d->num_control_bytes);
679 pos += d->num_control_bytes;
681 de_dbg(c, "RLE data words at %"I64_FMT, pos);
683 cpos = 0;
685 d->stopflag = 0;
686 d->scan = 0;
687 d->ypos = 0;
688 d->column = 0;
689 d->stripe = 0;
690 d->dcmpr_word_count = 0;
692 while(1) {
693 if(d->stopflag) break;
694 if(cpos >= d->num_control_bytes) break;
695 ctrl = control_bytes[cpos++];
697 if(ctrl >= 128) { // Uncompressed run, count encoded in control byte
698 count = 256 - (i64)ctrl;
699 for(k=0; k<count; k++) {
700 dbuf_read(c->infile, wordbuf, pos, 2);
701 pos += 2;
702 tiny_setword(c, d, adata, wordbuf);
705 else if(ctrl == 0) { // RLE, 16-bit count in next 2 control bytes
706 count = de_getu16be_direct(&control_bytes[cpos]);
707 cpos += 2;
708 dbuf_read(c->infile, wordbuf, pos, 2);
709 pos += 2;
710 for(k=0; k<count; k++) {
711 tiny_setword(c, d, adata, wordbuf);
714 else if(ctrl == 1) { // Uncompressed run, 16-bit count in next 2 control bytes
715 count = de_getu16be_direct(&control_bytes[cpos]);
716 cpos += 2;
718 for(k=0; k<count; k++) {
719 dbuf_read(c->infile, wordbuf, pos, 2);
720 pos += 2;
721 tiny_setword(c, d, adata, wordbuf);
724 else { // RLE, count encoded in control byte
725 count = (i64)ctrl;
726 dbuf_read(c->infile, wordbuf, pos, 2);
727 pos += 2;
728 for(k=0; k<count; k++) {
729 tiny_setword(c, d, adata, wordbuf);
734 de_dbg(c, "decompressed words: %"I64_FMT, d->dcmpr_word_count);
735 if(d->dcmpr_word_count<16000) {
736 de_warn(c, "Expected 16000 decompressed words, got %"I64_FMT, d->dcmpr_word_count);
739 de_free(c, control_bytes);
740 return 1;
743 static void do_tinystuff_1bpp(deark *c, tinyctx *d, struct atari_img_decode_data *adata)
745 de_convert_image_paletted(adata->unc_pixels, 0, 1, d->dst_rowspan, adata->pal,
746 adata->img, 0);
749 static void do_tinystuff_2or4bpp(deark *c, tinyctx *d, struct atari_img_decode_data *adata)
751 i64 x, y;
752 i64 pos = 0;
753 i64 width;
754 UI bpp;
756 bpp = (UI)adata->bpp;
757 if(bpp!=2 && bpp!=4) return;
759 if(bpp==2) width = 640;
760 else width = 320;
762 for(y=0; y<200; y++) {
763 for(x=0; x<width; x+=16) {
764 UI n[4];
765 UI b_idx;
766 UI k;
768 // 2bpp: Every 2 words (4 bytes; 32 bits) makes 16 pixels
769 // 4bpp: Every 4 words (8 bytes; 64 bits) makes 16 pixels
770 for(b_idx=0; b_idx<bpp; b_idx++) {
771 n[b_idx] = (UI)dbuf_getu16be_p(adata->unc_pixels, &pos);
774 for(k=0; k<16; k++) {
775 UI v = 0;
777 for(b_idx=0; b_idx<bpp; b_idx++) {
778 if(n[b_idx]&(1U<<(15-k))) v += (1U<<b_idx);
780 de_bitmap_setpixel_rgb(adata->img, x+(i64)k, y, adata->pal[v]);
786 static void do_tinystuff_image(deark *c, tinyctx *d, struct atari_img_decode_data *adata)
788 switch(adata->bpp) {
789 case 1:
790 do_tinystuff_1bpp(c, d, adata);
791 break;
792 case 2:
793 case 4:
794 do_tinystuff_2or4bpp(c, d, adata);
795 break;
799 // Some 1bpp images apparently have the palette set to [001, 000],
800 // or other nonsense, instead of [777, 000].
801 // Try to handle that.
802 static void fix_dark_pal(deark *c, struct atari_img_decode_data *adata)
804 u32 ap[2];
806 if(adata->bpp!=1) return;
808 ap[0] = adata->pal[0]&0xffffff;
809 ap[1] = adata->pal[1]&0xffffff;
811 // Always respect white/black and black/white palettes.
812 if(ap[0]==0xffffff && ap[1]==0x000000) return; // The usual palette
813 if(ap[0]==0x000000 && ap[1]==0xffffff) return;
815 // Otherwise assume white/black, unless the user told us not to.
816 if(de_get_ext_option(c, "atari:respectpal")) return;
818 adata->pal[0] = DE_STOCKCOLOR_WHITE;
819 adata->pal[1] = DE_STOCKCOLOR_BLACK;
822 static void de_run_tinystuff(deark *c, de_module_params *mparams)
824 struct atari_img_decode_data *adata = NULL;
825 de_finfo *fi = NULL;
826 tinyctx *d = NULL;
827 i64 pos = 0;
828 i64 expected_min_file_size;
829 i64 expected_max_file_size;
830 int is_grayscale;
832 d = de_malloc(c, sizeof(tinyctx));
834 adata = de_malloc(c, sizeof(struct atari_img_decode_data));
835 adata->pal = d->pal;
836 adata->was_compressed = 1;
838 d->res_code = de_getbyte(pos);
839 pos++;
840 de_dbg(c, "resolution code: %u", (UI)d->res_code);
842 switch(d->res_code) {
843 case 0: case 3:
844 adata->bpp = 4;
845 adata->w = 320;
846 adata->h = 200;
847 break;
848 case 1: case 4:
849 adata->bpp = 2;
850 adata->w = 640;
851 adata->h = 200;
852 break;
853 case 2: case 5:
854 adata->bpp = 1;
855 adata->w = 640;
856 adata->h = 400;
857 break;
858 default:
859 de_err(c, "Invalid resolution code (%u). This is not a Tiny Stuff file.",
860 (UI)d->res_code);
861 goto done;
864 de_dbg_dimensions(c, adata->w, adata->h);
865 adata->ncolors = de_pow2(adata->bpp);
866 de_dbg(c, "colors: %d", (int)adata->ncolors);
868 if(d->res_code>=3) {
869 de_warn(c, "This image uses palette cycling animation, which is not supported.");
870 pos += 4; // skip animation_info
873 fmtutil_read_atari_palette(c, c->infile, pos, adata->pal, 16, adata->ncolors, 0);
874 fix_dark_pal(c, adata);
875 pos += 16*2;
877 d->num_control_bytes = de_getu16be(pos);
878 pos += 2;
879 de_dbg(c, "number of RLE control bytes: %d", (int)d->num_control_bytes);
881 d->num_data_words = de_getu16be(pos);
882 pos += 2;
883 d->data_words_nbytes = 2*d->num_data_words;
884 de_dbg(c, "number of RLE data words: %d (%d bytes)", (int)d->num_data_words,
885 (int)d->data_words_nbytes);
887 // It seems that files are often padded to the next multiple of 128 bytes,
888 // so don't warn about that.
889 expected_min_file_size = pos + d->num_control_bytes + d->data_words_nbytes;
890 expected_max_file_size = de_pad_to_n(expected_min_file_size, 128);
891 de_dbg(c, "expected file size: %"I64_FMT" or %"I64_FMT, expected_min_file_size,
892 expected_max_file_size);
893 if(c->infile->len<expected_min_file_size || c->infile->len>expected_max_file_size) {
894 de_warn(c, "Expected file size to be %"I64_FMT", but it is %"I64_FMT".",
895 expected_min_file_size, c->infile->len);
898 adata->unc_pixels = dbuf_create_membuf(c, 32000, 1);
900 if(!tiny_uncompress(c, d, adata, pos)) {
901 goto done;
904 is_grayscale = de_is_grayscale_palette(adata->pal, adata->ncolors);
906 adata->img = de_bitmap_create(c, adata->w, adata->h, is_grayscale?1:3);
908 fi = de_finfo_create(c);
909 fmtutil_atari_set_standard_density(c, adata, fi);
911 do_tinystuff_image(c, d, adata);
912 de_bitmap_write_to_file_finfo(adata->img, fi, 0);
914 done:
915 if(adata) {
916 de_bitmap_destroy(adata->img);
917 dbuf_close(adata->unc_pixels);
918 de_free(c, adata);
920 de_finfo_destroy(c, fi);
921 de_free(c, d);
924 static int de_identify_tinystuff(deark *c)
926 // TODO: Can we identify these files?
927 if(de_getbyte(0)>0x05) return 0;
928 if(de_input_file_has_ext(c, "tny") ||
929 de_input_file_has_ext(c, "tn1") ||
930 de_input_file_has_ext(c, "tn2") ||
931 de_input_file_has_ext(c, "tn3") ||
932 de_input_file_has_ext(c, "tn4"))
934 return 8;
936 return 0;
939 static void de_help_tinystuff(deark *c)
941 fmtutil_atari_help_palbits(c);
942 help_respectpal(c);
945 void de_module_tinystuff(deark *c, struct deark_module_info *mi)
947 mi->id = "tinystuff";
948 mi->desc = "Atari Tiny Stuff, a.k.a. Tiny image format";
949 mi->run_fn = de_run_tinystuff;
950 mi->identify_fn = de_identify_tinystuff;
951 mi->help_fn = de_help_tinystuff;
954 // **************************************************************************
955 // Doodle (.doo)
956 // **************************************************************************
958 static void de_run_doodle(deark *c, de_module_params *mparams)
960 struct atari_img_decode_data *adata = NULL;
961 de_finfo *fi = NULL;
962 u32 pal[2];
964 adata = de_malloc(c, sizeof(struct atari_img_decode_data));
965 adata->pal = pal;
966 adata->bpp = 1;
968 adata->w = 640;
969 adata->h = 400;
970 adata->ncolors = 2;
971 adata->pal[0] = DE_STOCKCOLOR_WHITE;
972 adata->pal[1] = DE_STOCKCOLOR_BLACK;
974 adata->unc_pixels = c->infile;
975 adata->img = de_bitmap_create(c, adata->w, adata->h, 1);
976 fi = de_finfo_create(c);
977 fmtutil_atari_set_standard_density(c, adata, fi);
978 fmtutil_atari_decode_image(c, adata);
979 de_bitmap_write_to_file_finfo(adata->img, fi, 0);
981 if(adata) {
982 de_bitmap_destroy(adata->img);
983 de_free(c, adata);
985 de_finfo_destroy(c, fi);
988 static int de_identify_doodle(deark *c)
990 if(c->infile->len!=32000) return 0;
991 if(de_input_file_has_ext(c, "doo")) {
992 return 10;
994 return 0;
997 void de_module_doodle(deark *c, struct deark_module_info *mi)
999 mi->id = "doodle";
1000 mi->desc = "Atari Doodle";
1001 mi->run_fn = de_run_doodle;
1002 mi->identify_fn = de_identify_doodle;
1005 // **************************************************************************
1006 // NEOchrome (.neo)
1007 // **************************************************************************
1009 static void de_run_neochrome(deark *c, de_module_params *mparams)
1011 struct atari_img_decode_data *adata = NULL;
1012 de_finfo *fi = NULL;
1013 unsigned int resolution_code;
1014 int is_grayscale;
1015 u32 pal[16];
1017 adata = de_malloc(c, sizeof(struct atari_img_decode_data));
1018 adata->pal = pal;
1020 resolution_code = (unsigned int)de_getu16be(2);
1021 de_dbg(c, "resolution code: %u", resolution_code);
1022 if(resolution_code!=0) {
1023 de_err(c, "Invalid or unsupported NEOchrome image (resolution=%d)", (int)resolution_code);
1024 goto done;
1027 // TODO: Warn about palette animation settings.
1028 // TODO: (Maybe) Use the embedded filename, if it seems valid.
1030 adata->bpp = 4;
1031 adata->w = 320;
1032 adata->h = 200;
1033 adata->ncolors = de_pow2(adata->bpp);
1034 de_dbg(c, "dimensions: %d"DE_CHAR_TIMES"%d, colors: %d", (int)adata->w, (int)adata->h, (int)adata->ncolors);
1036 fmtutil_read_atari_palette(c, c->infile, 4, adata->pal, 16, adata->ncolors, 0);
1037 adata->unc_pixels = dbuf_open_input_subfile(c->infile, 128, 32000);
1038 is_grayscale = de_is_grayscale_palette(adata->pal, adata->ncolors);
1039 adata->img = de_bitmap_create(c, adata->w, adata->h, is_grayscale?1:3);
1040 fi = de_finfo_create(c);
1041 fmtutil_atari_set_standard_density(c, adata, fi);
1042 fmtutil_atari_decode_image(c, adata);
1043 de_bitmap_write_to_file_finfo(adata->img, fi, 0);
1045 done:
1046 if(adata) {
1047 dbuf_close(adata->unc_pixels);
1048 de_bitmap_destroy(adata->img);
1049 de_free(c, adata);
1051 de_finfo_destroy(c, fi);
1054 static int de_identify_neochrome(deark *c)
1056 if(de_input_file_has_ext(c, "neo")) {
1057 if(c->infile->len == 32128) {
1058 return 100;
1060 else if(c->infile->len > 32128) {
1061 return 10;
1064 return 0;
1067 static void de_help_neochrome(deark *c)
1069 fmtutil_atari_help_palbits(c);
1072 void de_module_neochrome(deark *c, struct deark_module_info *mi)
1074 mi->id = "neochrome";
1075 mi->desc = "Atari NEOchrome image";
1076 mi->run_fn = de_run_neochrome;
1077 mi->identify_fn = de_identify_neochrome;
1078 mi->help_fn = de_help_neochrome;
1081 // **************************************************************************
1082 // NEOchrome animation (.ani)
1083 // **************************************************************************
1085 static void de_run_neochrome_ani(deark *c, de_module_params *mparams)
1087 struct atari_img_decode_data *adata = NULL;
1088 i64 width_in_bytes;
1089 i64 nframes;
1090 i64 bytes_per_frame;
1091 i64 frame;
1092 i64 k;
1093 u32 pal[16];
1095 de_declare_fmt(c, "NEOchrome Animation");
1097 de_warn(c, "NEOchrome Animation images may not be decoded correctly.");
1099 adata = de_malloc(c, sizeof(struct atari_img_decode_data));
1101 // TODO: What palette should we use?
1102 for(k=0; k<16; k++) {
1103 pal[k] = DE_MAKE_GRAY((unsigned int)(k*17));
1105 adata->pal = pal;
1106 adata->bpp = 4;
1107 adata->ncolors = 16;
1109 width_in_bytes = de_getu16be(4); // Always a multiple of 8
1110 adata->w = ((width_in_bytes+7)/8)*16;
1111 adata->h = de_getu16be(6);
1112 de_dbg_dimensions(c, adata->w, adata->h);
1113 if(!de_good_image_dimensions(c, adata->w, adata->h)) goto done;
1115 bytes_per_frame = de_getu16be(8);
1116 bytes_per_frame -= 10;
1117 de_dbg(c, "bytes/frame: %d", (int)bytes_per_frame);
1118 if(bytes_per_frame<1) goto done;
1120 nframes = de_getu16be(14);
1121 de_dbg(c, "number of frames: %d", (int)nframes);
1122 if(!de_good_image_count(c, nframes)) goto done;
1124 for(frame=0; frame<nframes; frame++) {
1125 adata->unc_pixels = dbuf_open_input_subfile(c->infile, 22 + frame*bytes_per_frame, bytes_per_frame);
1126 adata->img = de_bitmap_create(c, adata->w, adata->h, 3);
1128 fmtutil_atari_decode_image(c, adata);
1129 de_bitmap_write_to_file(adata->img, NULL, 0);
1131 de_bitmap_destroy(adata->img);
1132 adata->img = NULL;
1134 dbuf_close(adata->unc_pixels);
1135 adata->unc_pixels = NULL;
1138 done:
1139 de_free(c, adata);
1142 static int de_identify_neochrome_ani(deark *c)
1144 if(!dbuf_memcmp(c->infile, 0, "\xba\xbe\xeb\xea", 4)) {
1145 return 100;
1147 return 0;
1150 void de_module_neochrome_ani(deark *c, struct deark_module_info *mi)
1152 mi->id = "neochrome_ani";
1153 mi->desc = "NEOchrome Animation";
1154 mi->run_fn = de_run_neochrome_ani;
1155 mi->identify_fn = de_identify_neochrome_ani;
1156 mi->flags |= DE_MODFLAG_NONWORKING;
1159 // **************************************************************************
1160 // Animatic Film (.flm)
1161 // **************************************************************************
1163 static void de_run_animatic(deark *c, de_module_params *mparams)
1165 struct atari_img_decode_data *adata = NULL;
1166 i64 nframes;
1167 i64 frame;
1168 i64 planespan, rowspan, framespan;
1169 i64 frame_bitmap_pos;
1170 u32 pal[16];
1172 de_declare_fmt(c, "Animatic Film");
1174 adata = de_malloc(c, sizeof(struct atari_img_decode_data));
1176 nframes = de_getu16be(0);
1177 de_dbg(c, "number of frames: %d", (int)nframes);
1178 if(!de_good_image_count(c, nframes)) goto done;
1180 adata->bpp = 4;
1181 adata->ncolors = 16;
1182 adata->pal = pal;
1183 de_dbg_indent(c, 1);
1184 fmtutil_read_atari_palette(c, c->infile, 2, adata->pal, 16, adata->ncolors, 0);
1185 de_dbg_indent(c, -1);
1187 adata->w = de_getu16be(40);
1188 adata->h = de_getu16be(42);
1189 de_dbg_dimensions(c, adata->w, adata->h);
1190 if(!de_good_image_dimensions(c, adata->w, adata->h)) goto done;
1192 planespan = 2*((adata->w+15)/16);
1193 rowspan = planespan*adata->bpp;
1194 framespan = rowspan*adata->h;
1196 for(frame=0; frame<nframes; frame++) {
1197 frame_bitmap_pos = 64 + frame*framespan;
1198 de_dbg(c, "frame %d bitmap at %d", (int)frame, (int)frame_bitmap_pos);
1200 adata->unc_pixels = dbuf_open_input_subfile(c->infile, frame_bitmap_pos, framespan);
1201 adata->img = de_bitmap_create(c, adata->w, adata->h, 3);
1203 fmtutil_atari_decode_image(c, adata);
1204 de_bitmap_write_to_file(adata->img, NULL, 0);
1206 de_bitmap_destroy(adata->img);
1207 adata->img = NULL;
1209 dbuf_close(adata->unc_pixels);
1210 adata->unc_pixels = NULL;
1213 done:
1214 de_free(c, adata);
1217 static int de_identify_animatic(deark *c)
1219 if(!dbuf_memcmp(c->infile, 48, "\x27\x18\x28\x18", 4)) {
1220 return 100;
1222 return 0;
1225 static void de_help_animatic(deark *c)
1227 fmtutil_atari_help_palbits(c);
1230 void de_module_animatic(deark *c, struct deark_module_info *mi)
1232 mi->id = "animatic";
1233 mi->desc = "Animatic Film";
1234 mi->run_fn = de_run_animatic;
1235 mi->identify_fn = de_identify_animatic;
1236 mi->help_fn = de_help_animatic;
1239 // **************************************************************************
1240 // Atari .PI4/.PI9
1241 // **************************************************************************
1243 static void decode_falcon_8bit_image(deark *c, struct atari_img_decode_data *adata, i64 pos)
1245 i64 i, j, k;
1246 unsigned int v;
1247 unsigned int n;
1248 de_finfo *fi = NULL;
1250 adata->img = de_bitmap_create(c, adata->w, adata->h, 3);
1252 fi = de_finfo_create(c);
1253 if(adata->w==320 && adata->h==200) {
1254 fi->density.code = DE_DENSITY_UNK_UNITS;
1255 fi->density.xdens = 240.0;
1256 fi->density.ydens = 200.0;
1259 for(j=0; j<adata->h; j++) {
1260 for(i=0; i<adata->w; i++) {
1261 v = 0;
1262 for(k=0; k<8; k++) {
1263 n = (u32)de_getu16be(pos+j*adata->w + (i-i%16) +2*k);
1264 if(n&(1<<(15-i%16))) v |= 1<<k;
1266 de_bitmap_setpixel_rgb(adata->img, i, j, adata->pal[v]);
1270 de_bitmap_write_to_file_finfo(adata->img, fi, 0);
1271 de_bitmap_destroy(adata->img);
1272 adata->img = NULL;
1273 de_finfo_destroy(c, fi);
1276 static void do_atari_falcon_8bit_img(deark *c, i64 width, i64 height)
1278 struct atari_img_decode_data *adata = NULL;
1279 i64 k;
1280 u8 cr, cg, cb;
1281 u32 pal[256];
1283 adata = de_malloc(c, sizeof(struct atari_img_decode_data));
1284 de_zeromem(pal, sizeof(pal));
1285 adata->pal = pal;
1286 adata->bpp = 8;
1287 adata->ncolors = 256;
1288 adata->w = width;
1289 adata->h = height;
1290 de_dbg_dimensions(c, adata->w, adata->h);
1292 for(k=0; k<256; k++) {
1293 cr = de_getbyte(k*4+0);
1294 cg = de_getbyte(k*4+1);
1295 cb = de_getbyte(k*4+3);
1296 pal[k] = DE_MAKE_RGB(cr, cg, cb);
1297 de_dbg_pal_entry(c, k, pal[k]);
1300 decode_falcon_8bit_image(c, adata, 1024);
1302 de_free(c, adata);
1305 static void de_run_fpaint_pi4(deark *c, de_module_params *mparams)
1307 do_atari_falcon_8bit_img(c, 320, 240);
1310 // Atari falcon 320x240
1311 static int de_identify_fpaint_pi4(deark *c)
1313 if(c->infile->len==77824) {
1314 if(de_input_file_has_ext(c, "pi4") ||
1315 de_input_file_has_ext(c, "pi9"))
1317 return 50; // Must be lower than fpaint_pi9
1320 return 0;
1323 void de_module_fpaint_pi4(deark *c, struct deark_module_info *mi)
1325 mi->id = "fpaint_pi4";
1326 mi->desc = "Atari Falcon PI4 image";
1327 mi->run_fn = de_run_fpaint_pi4;
1328 mi->identify_fn = de_identify_fpaint_pi4;
1331 static void de_run_fpaint_pi9(deark *c, de_module_params *mparams)
1333 do_atari_falcon_8bit_img(c, 320, 200);
1336 // Atari falcon 320x200
1337 static int de_identify_fpaint_pi9(deark *c)
1339 int pi4_ext, pi9_ext;
1341 if(c->infile->len!=77824 && c->infile->len!=65024) return 0;
1343 pi4_ext = de_input_file_has_ext(c, "pi4");
1344 pi9_ext = de_input_file_has_ext(c, "pi9");
1345 if(!pi4_ext && !pi9_ext) return 0;
1347 if(c->infile->len==65024) return 60;
1349 // If file size is 77824, we need to distinguish between PI4 (320x240) and
1350 // PI9 (320x200) format.
1351 // Best guess is that if the last 12800 bytes are all 0, we should assume PI9.
1352 if(!dbuf_is_all_zeroes(c->infile, 65024, 12800)) {
1353 return 0; // Will be identified elsewhere as PI4.
1356 return 60; // PI9. Must be higher than the value PI4 uses.
1359 void de_module_fpaint_pi9(deark *c, struct deark_module_info *mi)
1361 mi->id = "fpaint_pi9";
1362 mi->desc = "Atari Falcon PI9 image";
1363 mi->run_fn = de_run_fpaint_pi9;
1364 mi->identify_fn = de_identify_fpaint_pi9;
1367 // **************************************************************************
1368 // Atari .PI7
1369 // **************************************************************************
1371 static void de_run_atari_pi7(deark *c, de_module_params *mparams)
1373 do_atari_falcon_8bit_img(c, 640, 480);
1376 static int de_identify_atari_pi7(deark *c)
1378 if(c->infile->len==308224) {
1379 if(de_input_file_has_ext(c, "pi7"))
1381 return 50;
1384 return 0;
1387 void de_module_atari_pi7(deark *c, struct deark_module_info *mi)
1389 mi->id = "atari_pi7";
1390 mi->desc = "Atari PI7 image";
1391 mi->run_fn = de_run_atari_pi7;
1392 mi->identify_fn = de_identify_atari_pi7;
1395 // **************************************************************************
1396 // Atari Falcon XGA
1397 // **************************************************************************
1399 static void de_run_falcon_xga(deark *c, de_module_params *mparams)
1401 struct atari_img_decode_data *adata = NULL;
1402 de_finfo *fi = NULL;
1404 adata = de_malloc(c, sizeof(struct atari_img_decode_data));
1405 if(c->infile->len==153600) {
1406 adata->bpp = 16;
1407 adata->w = 320;
1408 adata->h = 240;
1410 else {
1411 adata->bpp = 16;
1412 adata->w = 384;
1413 adata->h = 480;
1415 de_dbg_dimensions(c, adata->w, adata->h);
1416 adata->unc_pixels = c->infile;
1417 adata->img = de_bitmap_create(c, adata->w, adata->h, 3);
1418 fi = de_finfo_create(c);
1419 if(adata->w==384 && adata->h == 480) {
1420 fi->density.code = DE_DENSITY_UNK_UNITS;
1421 fi->density.xdens = 384;
1422 fi->density.ydens = 640;
1424 fmtutil_atari_decode_image(c, adata);
1425 de_bitmap_write_to_file_finfo(adata->img, fi, 0);
1426 de_bitmap_destroy(adata->img);
1427 de_finfo_destroy(c, fi);
1428 de_free(c, adata);
1431 static int de_identify_falcon_xga(deark *c)
1433 if(c->infile->len==153600 || c->infile->len==368640) {
1434 if(de_input_file_has_ext(c, "xga"))
1436 return 50;
1439 return 0;
1442 void de_module_falcon_xga(deark *c, struct deark_module_info *mi)
1444 mi->id = "falcon_xga";
1445 mi->desc = "Atari Falcon XGA image";
1446 mi->run_fn = de_run_falcon_xga;
1447 mi->identify_fn = de_identify_falcon_xga;
1450 // **************************************************************************
1451 // Atari Falcon COKE (.tg1)
1452 // **************************************************************************
1454 static void de_run_coke(deark *c, de_module_params *mparams)
1456 i64 imgdatapos;
1457 struct atari_img_decode_data *adata = NULL;
1458 de_finfo *fi = NULL;
1460 adata = de_malloc(c, sizeof(struct atari_img_decode_data));
1461 adata->bpp = 16;
1462 adata->w = de_getu16be(12);
1463 adata->h = de_getu16be(14);
1464 de_dbg_dimensions(c, adata->w, adata->h);
1465 imgdatapos = de_getu16be(16);
1466 de_dbg(c, "image data pos: %d", (int)imgdatapos);
1468 adata->unc_pixels = dbuf_open_input_subfile(c->infile,
1469 imgdatapos, c->infile->len-imgdatapos);
1470 adata->img = de_bitmap_create(c, adata->w, adata->h, 3);
1472 fi = de_finfo_create(c);
1473 fi->density.code = DE_DENSITY_UNK_UNITS;
1474 fi->density.xdens = 288;
1475 fi->density.ydens = 240;
1477 fmtutil_atari_decode_image(c, adata);
1478 de_bitmap_write_to_file_finfo(adata->img, fi, 0);
1480 if(adata) {
1481 dbuf_close(adata->unc_pixels);
1482 de_bitmap_destroy(adata->img);
1483 de_free(c, adata);
1485 de_finfo_destroy(c, fi);
1488 static int de_identify_coke(deark *c)
1490 if(!dbuf_memcmp(c->infile, 0, (const void*)"COKE format.", 12)) {
1491 return 100;
1493 return 0;
1496 void de_module_coke(deark *c, struct deark_module_info *mi)
1498 mi->id = "coke";
1499 mi->desc = "Atari Falcon COKE image (.TG1)";
1500 mi->run_fn = de_run_coke;
1501 mi->identify_fn = de_identify_coke;
1504 // **************************************************************************
1505 // Video Master .FLM, etc. (Amiga & Atari ST)
1506 // **************************************************************************
1508 #define VMAS_FRAME_PAL_SIZE 32
1509 #define VMAS_FRAME_BITMAP_SIZE 8000
1510 #define VMAS_FRAME_TOTAL_SIZE (VMAS_FRAME_PAL_SIZE+VMAS_FRAME_BITMAP_SIZE)
1512 static void de_run_videomaster(deark *c, de_module_params *mparams)
1514 struct atari_img_decode_data *adata = NULL;
1515 de_finfo *fi = NULL;
1516 i64 nframes;
1517 i64 frameidx;
1518 i64 frames_startpos;
1519 i64 pos;
1520 de_color pal[16];
1522 nframes = de_getu16be(6);
1523 de_dbg(c, "num frames: %u", (UI)nframes);
1524 frames_startpos = 32;
1525 if(frames_startpos + nframes*VMAS_FRAME_TOTAL_SIZE > c->infile->len) {
1526 de_err(c, "Invalid or truncated file");
1527 goto done;
1530 adata = de_malloc(c, sizeof(struct atari_img_decode_data));
1531 adata->bpp = 4;
1532 adata->w = 160;
1533 adata->h = 100;
1534 adata->pal = pal;
1535 adata->ncolors = 16;
1536 adata->unc_pixels = dbuf_create_membuf(c, VMAS_FRAME_BITMAP_SIZE, 0x1);
1537 adata->img = de_bitmap_create(c, adata->w, adata->h, 3);
1538 fi = de_finfo_create(c);
1539 // This might not be the right aspect ratio in all cases, but I think it's
1540 // probably better than nothing.
1541 fmtutil_atari_set_standard_density(c, adata, fi);
1543 pos = frames_startpos;
1544 for(frameidx=0; frameidx<nframes; frameidx++) {
1545 de_dbg(c, "frame #%d at %"I64_FMT, (int)frameidx, pos);
1546 de_dbg_indent(c, 1);
1547 de_read_simple_palette(c, c->infile, pos, 16, 2, adata->pal, 16, DE_RDPALTYPE_AMIGA12BIT, 0);
1548 pos += VMAS_FRAME_PAL_SIZE;
1550 de_dbg(c, "bitmap at %"I64_FMT, pos);
1551 dbuf_truncate(adata->unc_pixels, 0);
1552 dbuf_copy(c->infile, pos, VMAS_FRAME_BITMAP_SIZE, adata->unc_pixels);
1553 pos += VMAS_FRAME_BITMAP_SIZE;
1555 fmtutil_atari_decode_image(c, adata);
1556 de_bitmap_write_to_file_finfo(adata->img, fi, DE_CREATEFLAG_OPT_IMAGE);
1557 de_dbg_indent(c, -1);
1560 done:
1561 if(adata) {
1562 dbuf_close(adata->unc_pixels);
1563 de_bitmap_destroy(adata->img);
1564 de_free(c, adata);
1566 de_finfo_destroy(c, fi);
1569 static int de_identify_videomaster(deark *c)
1571 if(!dbuf_memcmp(c->infile, 0, (const void*)"VMAS1", 5)) {
1572 return 100;
1574 return 0;
1577 void de_module_videomaster(deark *c, struct deark_module_info *mi)
1579 mi->id = "videomaster";
1580 mi->desc = "Video Master (.flm/.vid/.vsq)";
1581 mi->run_fn = de_run_videomaster;
1582 mi->identify_fn = de_identify_videomaster;