1 // This file is part of Deark.
2 // Copyright (C) 2020 Jason Summers
3 // See the file COPYING for terms of use.
7 #include <deark-config.h>
8 #include <deark-private.h>
9 DE_DECLARE_MODULE(de_module_fli
);
11 #define CHUNKTYPE_COLORMAP256 0x0004
12 #define CHUNKTYPE_DELTA_FLC 0x0007
13 #define CHUNKTYPE_COLORMAP64 0x000b
14 #define CHUNKTYPE_DELTA_FLI 0x000c
15 #define CHUNKTYPE_BLACK 0x000d
16 #define CHUNKTYPE_RLE 0x000f
17 #define CHUNKTYPE_COPY 0x0010
18 #define CHUNKTYPE_THUMBNAIL 0x0012
19 #define CHUNKTYPE_FLI 0xaf11
20 #define CHUNKTYPE_FLC 0xaf12
21 #define CHUNKTYPE_PREFIX 0xf100
22 #define CHUNKTYPE_FRAME 0xf1fa
24 // Unfortunately, the above chunk types are sometimes context-sensitive.
25 // So we'll define our own types that are not.
26 enum mapped_chunktype_enum
{
27 MCT_UNKNOWN
= 0x10001,
44 struct localctx_struct
;
45 typedef struct localctx_struct lctx
;
46 struct chunk_info_type
;
48 typedef void (*chunk_handler_type
)(deark
*c
, lctx
*d
, struct chunk_info_type
*ci
);
50 struct image_ctx_type
{
55 struct de_density_info density
;
60 struct chunk_info_type
{
63 enum mapped_chunktype_enum mct
;
67 struct chunk_info_type
*parent
;
68 chunk_handler_type handler_fn
;
69 const char *chunk_type_name
;
71 // Current image context. Can be NULL. Do not free this directly.
72 struct image_ctx_type
*ictx
;
75 struct localctx_struct
{
79 struct de_timestamp create_timestamp
;
80 struct de_timestamp mod_timestamp
;
86 // Caller supplies pal[256]
87 static void make_6cube_pal(u32
*pal
)
92 for(k
=0; k
<216; k
++) {
96 pal
[k
] = DE_MAKE_RGB(r
, g
, b
);
100 static struct image_ctx_type
*create_image_ctx(deark
*c
, lctx
*d
, i64 w
, i64 h
)
102 struct image_ctx_type
*ictx
;
104 ictx
= de_malloc(c
, sizeof(struct image_ctx_type
));
107 ictx
->img
= de_bitmap_create(c
, w
, h
, 3);
111 static void destroy_image_ctx(deark
*c
, struct image_ctx_type
*ictx
)
115 de_bitmap_destroy(ictx
->img
);
120 static void do_sequence_of_chunks(deark
*c
, lctx
*d
, struct chunk_info_type
*parent_ci
,
121 i64 pos1
, i64 max_nchunks
);
123 static void do_chunk_rle(deark
*c
, lctx
*d
, struct chunk_info_type
*ci
)
127 i64 pos
= ci
->pos
+ 6;
128 struct image_ctx_type
*ictx
;
130 if(!ci
->ictx
) goto done
;
131 de_dbg(c
, "doing RLE decompression");
134 pos
++; // First byte of each line is a packet count (not needed)
142 if(pos
>= ci
->pos
+ ci
->len
) break;
144 code
= de_getbyte_p(&pos
); // packet type/size
145 if(code
>= 128) { // "negative" = run of uncompressed pixels
146 count
= (i64
)256 - (i64
)code
;
147 for(k
=0; k
<count
; k
++) {
148 clridx
= (UI
)de_getbyte_p(&pos
);
149 de_bitmap_setpixel_rgb(ictx
->img
, xpos
, ypos
, ictx
->pal
[clridx
]);
153 else { // "positive" = RLE
155 clridx
= (UI
)de_getbyte_p(&pos
);
156 for(k
=0; k
<count
; k
++) {
157 de_bitmap_setpixel_rgb(ictx
->img
, xpos
, ypos
, ictx
->pal
[clridx
]);
162 if(xpos
>= ictx
->w
) {
165 pos
++; // packet count
166 if(ypos
>=ictx
->h
) break;
174 static void do_chunk_delta_fli(deark
*c
, lctx
*d
, struct chunk_info_type
*ci
)
177 i64 num_encoded_lines
;
179 i64 pos
= ci
->pos
+ 6;
180 struct image_ctx_type
*ictx
;
182 if(!ci
->ictx
) goto done
;
183 de_dbg(c
, "doing delta (FLI-style) decompression");
187 ypos
= de_getu16le_p(&pos
);
188 num_encoded_lines
= de_getu16le_p(&pos
);
190 for(line_idx
=0; line_idx
<num_encoded_lines
; line_idx
++) {
195 if(pos
>= ci
->pos
+ ci
->len
) goto done
;
197 npackets
= (UI
)de_getbyte_p(&pos
);
199 for(pkidx
=0; pkidx
<npackets
; pkidx
++) {
206 if(pos
>= ci
->pos
+ ci
->len
) goto done
;
207 skip_count
= (i64
)de_getbyte_p(&pos
);
209 code
= de_getbyte_p(&pos
);
210 if(code
<128) { // "positive" = run of uncompressed pixels
212 for(k
=0; k
<count
; k
++) {
213 clridx
= (UI
)de_getbyte_p(&pos
);
214 de_bitmap_setpixel_rgb(ictx
->img
, xpos
, ypos
, ictx
->pal
[clridx
]);
218 else { // "negative" = RLE
219 clridx
= (UI
)de_getbyte_p(&pos
);
220 count
= (i64
)256 - (i64
)code
;
221 for(k
=0; k
<count
; k
++) {
222 de_bitmap_setpixel_rgb(ictx
->img
, xpos
, ypos
, ictx
->pal
[clridx
]);
235 static void do_chunk_delta_flc(deark
*c
, lctx
*d
, struct chunk_info_type
*ci
)
238 i64 num_encoded_lines
;
240 i64 pos
= ci
->pos
+ 6;
241 struct image_ctx_type
*ictx
;
243 if(!ci
->ictx
) goto done
;
244 de_dbg(c
, "doing delta (FLC-style) decompression");
248 num_encoded_lines
= de_getu16le_p(&pos
);
250 for(line_idx
=0; line_idx
<num_encoded_lines
; line_idx
++) {
256 // Read code words until we find one the high 2 bits == 0.
258 if(pos
>= ci
->pos
+ ci
->len
) goto done
;
260 wcode
= (UI
)de_getu16le_p(&pos
);
261 wcode_hi
= wcode
>>14;
267 else if(wcode_hi
==3) {
268 ypos
+= (i64
)65536 - (i64
)wcode
;
270 else if(wcode_hi
==2) {
271 // Set the "last byte of current line".
272 // (UNTESTED) This feature is only expected to be used if the
273 // screen width is odd, and I haven't found such a file.
274 de_bitmap_setpixel_rgb(ictx
->img
, ictx
->w
-1, ypos
, ictx
->pal
[wcode
& 0x00ff]);
278 for(pkidx
=0; pkidx
<npackets
; pkidx
++) {
285 if(pos
>= ci
->pos
+ ci
->len
) goto done
;
286 skip_count
= (i64
)de_getbyte_p(&pos
);
288 code
= de_getbyte_p(&pos
);
289 if(code
<128) { // "positive" = run of uncompressed pixels
290 count
= 2 * (i64
)code
;
291 for(k
=0; k
<count
; k
++) {
292 clridx
= (UI
)de_getbyte_p(&pos
);
293 de_bitmap_setpixel_rgb(ictx
->img
, xpos
, ypos
, ictx
->pal
[clridx
]);
297 else { // "negative" = RLE
298 count
= (i64
)256 - (i64
)code
;
299 clridx
= (UI
)de_getbyte_p(&pos
);
300 clridx2
= (UI
)de_getbyte_p(&pos
);
301 for(k
=0; k
<count
; k
++) {
302 de_bitmap_setpixel_rgb(ictx
->img
, xpos
, ypos
, ictx
->pal
[clridx
]);
304 de_bitmap_setpixel_rgb(ictx
->img
, xpos
, ypos
, ictx
->pal
[clridx2
]);
318 static void do_chunk_copy(deark
*c
, lctx
*d
, struct chunk_info_type
*ci
)
320 if(!ci
->ictx
) return;
321 ci
->ictx
->use_count
++;
322 de_convert_image_paletted(c
->infile
, ci
->pos
, 8, ci
->ictx
->w
, ci
->ictx
->pal
,
327 static void do_chunk_black(deark
*c
, lctx
*d
, struct chunk_info_type
*ci
)
329 if(!ci
->ictx
) return;
330 de_bitmap_rect(ci
->ictx
->img
, 0, 0, ci
->ictx
->w
, ci
->ictx
->h
,
331 ci
->ictx
->pal
[0], 0);
334 static void do_chunk_colormap(deark
*c
, lctx
*d
, struct chunk_info_type
*ci
)
338 i64 pos
= ci
->pos
+ 6;
340 UI num_entries_total
= 0;
343 if(!ci
->ictx
) return;
344 if(ci
->chunktype
==CHUNKTYPE_COLORMAP256
)
348 npackets
= de_getu16le_p(&pos
);
350 for(pknum
=0; pknum
<npackets
; pknum
++) {
351 UI num_entries_to_skip
;
352 UI num_entries_to_set
;
355 if(pos
>= ci
->pos
+ ci
->len
) goto done
;
356 num_entries_to_skip
= (UI
)de_getbyte_p(&pos
);
357 next_idx
+= num_entries_to_skip
;
358 num_entries_to_set
= (UI
)de_getbyte_p(&pos
);
359 if(num_entries_to_set
==0) num_entries_to_set
= 256;
360 num_entries_total
+= num_entries_to_set
;
362 for(k
=0; k
<num_entries_to_set
; k
++) {
368 samp
[z
] = de_getbyte_p(&pos
);
370 samp
[z
] = de_scale_63_to_255(samp
[z
]);
374 clr
= DE_MAKE_RGB(samp
[0], samp
[1], samp
[2]);
376 ci
->ictx
->pal
[next_idx
] = clr
;
377 de_dbg_pal_entry(c
, (i64
)next_idx
, clr
);
383 de_dbg(c
, "number of entries: %u", num_entries_total
);
386 static void dbg_id(deark
*c
, lctx
*d
, i64 pos
, const char *name
)
389 struct de_fourcc id4cc
;
391 n
= de_getu32le(pos
);
393 de_dbg(c
, "%s: %"I64_FMT
,name
, n
);
396 dbuf_read_fourcc(c
->infile
, pos
, &id4cc
, 4, 0x0);
397 de_dbg(c
, "%s: %"I64_FMT
" (0x%08x, '%s')", name
, n
, (UI
)n
,
401 static void read_timestamp(deark
*c
, lctx
*d
, i64 pos
, struct de_timestamp
*ts
,
405 i64 date_raw
, time_raw
;
406 struct de_timestamp tmp_timestamp
;
407 char timestamp_buf
[64];
409 de_zeromem(ts
, sizeof(struct de_timestamp
));
411 // The timestamp is said to be "MS-DOS formatted", but that's uncomfortably
412 // vague, and bogus timestamps seem to be common.
414 datetime_raw
= de_getu32le_p(&pos
);
415 de_dbg(c
, "%s time: %"I64_FMT
, name
, datetime_raw
);
416 if(datetime_raw
==0) return;
419 time_raw
= datetime_raw
& 0xffff;
420 date_raw
= (datetime_raw
>> 16) & 0xffff;
422 de_zeromem(&tmp_timestamp
, sizeof(struct de_timestamp
));
423 de_dos_datetime_to_timestamp(&tmp_timestamp
, date_raw
, time_raw
);
424 tmp_timestamp
.tzcode
= DE_TZCODE_LOCAL
;
425 de_timestamp_to_string(&tmp_timestamp
, timestamp_buf
, sizeof(timestamp_buf
), 0);
426 de_dbg(c
, "... if DOS time/date: %s", timestamp_buf
);
428 // Autodesk animator was first released in 1989. Assume timestamps older than
429 // the middle of 1988 are bogus.
430 if(de_timestamp_to_unix_time(&tmp_timestamp
) >= 583718400) {
434 de_dbg_indent(c
, -1);
437 static void do_chunk_FLI_FLC(deark
*c
, lctx
*d
, struct chunk_info_type
*ci
)
439 i64 pos
= ci
->pos
+ 6;
440 i64 scr_width
, scr_height
;
442 struct image_ctx_type
*ictx
= NULL
;
444 int can_decode_images
= 1;
446 d
->main_chunktype
= ci
->chunktype
;
447 if(d
->main_chunktype
==CHUNKTYPE_FLI
) {
448 de_declare_fmt(c
, "FLI");
450 else if(d
->main_chunktype
==CHUNKTYPE_FLC
) {
451 de_declare_fmt(c
, "FLC");
454 de_warn(c
, "Unrecognized signature (0x%04x). This might not be a FLI/FLC file.",
458 d
->num_frames
= de_getu16le_p(&pos
);
459 de_dbg(c
, "num frames: %d", (int)d
->num_frames
);
461 scr_width
= de_getu16le_p(&pos
);
462 scr_height
= de_getu16le_p(&pos
);
463 de_dbg(c
, "screen dimensions: %"I64_FMT DE_CHAR_TIMES
"%"I64_FMT
, scr_width
, scr_height
);
465 d
->depth
= (int)de_getu16le_p(&pos
);
466 de_dbg(c
, "depth: %d", d
->depth
);
467 if(d
->depth
==0) d
->depth
= 8;
470 n
= de_getu32le_p(&pos
);
471 if(ci
->chunktype
==CHUNKTYPE_FLI
&& n
!=0) {
472 fps
= 70.0/(double)n
;
474 else if(ci
->chunktype
==CHUNKTYPE_FLC
&& n
!=0) {
475 fps
= 1000.0/(double)n
;
477 de_dbg(c
, "speed: %"I64_FMT
" (%.4f frames/sec)", n
, fps
);
479 pos
+= 2; // reserved
481 if(ci
->chunktype
==CHUNKTYPE_FLI
) {
482 if(scr_width
==320 && scr_height
==200) {
488 if(ci
->chunktype
==CHUNKTYPE_FLC
) {
489 read_timestamp(c
, d
, pos
, &d
->create_timestamp
, "create");
491 dbg_id(c
, d
, pos
, "creator ID");
494 read_timestamp(c
, d
, pos
, &d
->mod_timestamp
, "mod");
496 dbg_id(c
, d
, pos
, "updater ID");
499 d
->aspect_x
= de_getu16le_p(&pos
);
500 d
->aspect_y
= de_getu16le_p(&pos
);
501 de_dbg(c
, "aspect ratio: %d,%d", (int)d
->aspect_x
, (int)d
->aspect_y
);
504 can_decode_images
= 1;
506 de_err(c
, "Unsupported depth: %d", d
->depth
);
507 can_decode_images
= 0;
509 if(!de_good_image_dimensions(c
, scr_width
, scr_height
)) {
510 can_decode_images
= 0;
513 if(can_decode_images
) {
514 ictx
= create_image_ctx(c
, d
, scr_width
, scr_height
);
516 if(d
->aspect_x
&& d
->aspect_y
) {
517 ictx
->density
.code
= DE_DENSITY_UNK_UNITS
;
518 ictx
->density
.xdens
= (double)d
->aspect_x
;
519 ictx
->density
.ydens
= (double)d
->aspect_y
;
524 do_sequence_of_chunks(c
, d
, ci
, pos
, -1);
526 destroy_image_ctx(c
, ictx
);
530 static void do_chunk_frame(deark
*c
, lctx
*d
, struct chunk_info_type
*ci
)
534 i64 prev_use_count
= 0;
537 frame_idx
= d
->frame_count
;
539 de_dbg(c
, "frame number: %d", (int)frame_idx
);
541 num_subchunks
= de_getu16le(ci
->pos
+6);
542 de_dbg(c
, "num subchunks: %"I64_FMT
, num_subchunks
);
545 prev_use_count
= ci
->ictx
->use_count
;
548 do_sequence_of_chunks(c
, d
, ci
, ci
->pos
+16, num_subchunks
);
551 if(ci
->ictx
->use_count
> prev_use_count
&& !ci
->ictx
->error_flag
) {
552 if(d
->num_frames
>0 && frame_idx
==d
->num_frames
&& c
->extract_level
<2) {
553 de_dbg(c
, "[not extracting ring frame]");
557 fi
= de_finfo_create(c
);
558 fi
->density
= ci
->ictx
->density
;
559 fi
->internal_mod_time
= d
->mod_timestamp
;
560 de_bitmap_write_to_file_finfo(ci
->ictx
->img
, fi
, 0);
565 de_finfo_destroy(c
, fi
);
568 static void do_chunk_thumbnail(deark
*c
, lctx
*d
, struct chunk_info_type
*ci
)
572 struct image_ctx_type
*ictx
= NULL
;
573 i64 pos
= ci
->pos
+ 6;
576 h
= de_getu16le_p(&pos
);
577 w
= de_getu16le_p(&pos
);
578 de_dbg_dimensions(c
, w
, h
);
579 colortype
= (UI
)de_getu16le_p(&pos
);
580 de_dbg(c
, "color type: %u", colortype
);
581 if(colortype
!=1) goto done
;
583 ictx
= create_image_ctx(c
, d
, w
, h
);
585 make_6cube_pal(ictx
->pal
);
586 do_sequence_of_chunks(c
, d
, ci
, pos
, -1);
588 fi
= de_finfo_create(c
);
589 fi
->internal_mod_time
= d
->mod_timestamp
;
590 if(d
->aspect_x
&& d
->aspect_y
) {
591 // Evidence suggests the thumbnail has the same aspect ratio as the animation,
592 // at least approximately.
593 fi
->density
.code
= DE_DENSITY_UNK_UNITS
;
594 fi
->density
.xdens
= (double)d
->aspect_x
;
595 fi
->density
.ydens
= (double)d
->aspect_y
;
597 de_finfo_set_name_from_sz(c
, fi
, "thumb", 0, DE_ENCODING_LATIN1
);
599 if(ictx
->use_count
>0 && !ictx
->error_flag
) {
600 de_bitmap_write_to_file_finfo(ictx
->img
, fi
, DE_CREATEFLAG_IS_AUX
);
604 destroy_image_ctx(c
, ictx
);
606 de_finfo_destroy(c
, fi
);
609 static void do_chunk_prefix(deark
*c
, lctx
*d
, struct chunk_info_type
*ci
)
611 do_sequence_of_chunks(c
, d
, ci
, ci
->pos
+6, -1);
614 static void do_chunk_settings(deark
*c
, lctx
*d
, struct chunk_info_type
*ci
)
616 do_sequence_of_chunks(c
, d
, ci
, ci
->pos
+8, -1);
619 static void do_chunk_hexdump(deark
*c
, lctx
*d
, struct chunk_info_type
*ci
)
621 if(c
->debug_level
<2) return;
622 de_dbg_hexdump(c
, c
->infile
, ci
->pos
+6, ci
->len
-6, 256, NULL
, 0x1);
626 // ci->chunk_type_name (never to NULL),
627 // ci->handler_fn (sometimes to NULL)
628 static void identify_chunk(deark
*c
, lctx
*d
, struct chunk_info_type
*ci
)
630 enum mapped_chunktype_enum parent_mct
;
631 UI ct
= ci
->chunktype
;
633 parent_mct
= ci
->parent
? ci
->parent
->mct
: MCT_NONE
;
635 ci
->handler_fn
= NULL
;
636 ci
->chunk_type_name
= "?";
638 if(parent_mct
==MCT_NONE
) {
639 if(ct
==CHUNKTYPE_FLI
) {
640 ci
->chunk_type_name
= "FLI";
642 else if(ct
==CHUNKTYPE_FLC
) {
643 ci
->chunk_type_name
= "FLC";
645 ci
->mct
= MCT_FLI_OR_FLC
;
646 ci
->handler_fn
= do_chunk_FLI_FLC
;
650 if(parent_mct
==MCT_FLI_OR_FLC
) {
651 if(ct
==CHUNKTYPE_FRAME
) {
653 ci
->chunk_type_name
= "frame";
654 ci
->handler_fn
= do_chunk_frame
;
657 else if(ct
==0xf5fa) {
659 ci
->chunk_type_name
= "frame-variant";
660 ci
->handler_fn
= do_chunk_frame
;
663 else if(ct
==CHUNKTYPE_PREFIX
) {
664 ci
->mct
= MCT_PREFIX
;
665 ci
->chunk_type_name
= "prefix";
666 ci
->handler_fn
= do_chunk_prefix
;
671 if(parent_mct
==MCT_FRAME
|| parent_mct
==MCT_THUMBNAIL
) {
672 if(ct
==CHUNKTYPE_COLORMAP64
) {
673 ci
->mct
= MCT_COLORMAP
;
674 ci
->chunk_type_name
= "color map 64";
675 ci
->handler_fn
= do_chunk_colormap
;
678 else if(ct
==CHUNKTYPE_COLORMAP256
) {
679 ci
->mct
= MCT_COLORMAP
;
680 ci
->chunk_type_name
= "color map 256";
681 ci
->handler_fn
= do_chunk_colormap
;
684 else if(ct
==CHUNKTYPE_RLE
) {
686 ci
->chunk_type_name
= "RLE compressed data";
687 ci
->handler_fn
= do_chunk_rle
;
690 else if(ct
==CHUNKTYPE_DELTA_FLI
) {
691 ci
->mct
= MCT_DELTA_FLI
;
692 ci
->chunk_type_name
= "delta compressed data (old)";
693 ci
->handler_fn
= do_chunk_delta_fli
;
696 else if(ct
==CHUNKTYPE_DELTA_FLC
) {
697 ci
->mct
= MCT_DELTA_FLC
;
698 ci
->chunk_type_name
= "delta compressed data (new)";
699 ci
->handler_fn
= do_chunk_delta_flc
;
702 else if(ct
==CHUNKTYPE_COPY
) {
704 ci
->chunk_type_name
= "uncompressed data";
705 ci
->handler_fn
= do_chunk_copy
;
708 else if(ct
==CHUNKTYPE_BLACK
) {
710 ci
->chunk_type_name
= "clear screen";
711 ci
->handler_fn
= do_chunk_black
;
716 if(parent_mct
==MCT_FRAME
) {
717 if(ct
==CHUNKTYPE_THUMBNAIL
) {
718 ci
->mct
= MCT_THUMBNAIL
;
719 ci
->chunk_type_name
= "thumbnail image";
720 ci
->handler_fn
= do_chunk_thumbnail
;
725 if(parent_mct
==MCT_PREFIX
) {
727 ci
->mct
= MCT_SETTINGS
;
728 ci
->chunk_type_name
= "settings";
729 ci
->handler_fn
= do_chunk_settings
;
732 else if(ct
==0x0003) {
733 ci
->mct
= MCT_CELDATA
;
734 ci
->chunk_type_name
= "CEL data";
735 ci
->handler_fn
= do_chunk_hexdump
;
740 if(parent_mct
==MCT_SETTINGS
) {
741 ci
->mct
= MCT_ONESETTING
;
742 ci
->handler_fn
= do_chunk_hexdump
;
750 static int do_chunk(deark
*c
, lctx
*d
, struct chunk_info_type
*parent_ci
,
751 i64 pos1
, i64 bytes_avail
, int level
, i64
*pbytes_consumed
)
754 int saved_indent_level
;
756 struct chunk_info_type
*ci
= NULL
;
757 enum mapped_chunktype_enum parent_mct
;
759 de_dbg_indent_save(c
, &saved_indent_level
);
760 if(bytes_avail
<6) goto done
;
761 parent_mct
= parent_ci
? parent_ci
->mct
: MCT_NONE
;
763 ci
= de_malloc(c
, sizeof(struct chunk_info_type
));
764 ci
->parent
= parent_ci
;
768 // Inherit the image context.
770 ci
->ictx
= parent_ci
->ictx
;
773 de_dbg(c
, "chunk at %"I64_FMT
, ci
->pos
);
776 ci
->len
= de_getu32le_p(&pos
);
777 de_dbg(c
, "chunk len: %"I64_FMT
, ci
->len
);
778 if(ci
->len
==0 && level
==0) {
779 ci
->len
= c
->infile
->len
;
785 de_err(c
, "Bad chunk header at %"I64_FMT
, ci
->pos
);
788 if(ci
->len
> bytes_avail
) {
789 de_warn(c
, "Chunk at %"I64_FMT
" exceeds its parent's bounds (ends at %"I64_FMT
790 ", parent ends at %"I64_FMT
")", ci
->pos
, ci
->pos
+ci
->len
, ci
->pos
+bytes_avail
);
791 ci
->len
= bytes_avail
;
794 *pbytes_consumed
= ci
->len
;
797 ci
->chunktype
= (UI
)de_getu16le_p(&pos
);
799 identify_chunk(c
, d
, ci
);
800 de_dbg(c
, "chunk type: 0x%04x (%s)", ci
->chunktype
, ci
->chunk_type_name
);
803 ci
->handler_fn(c
, d
, ci
);
806 if(ci
->handler_fn
==NULL
&& (parent_mct
==MCT_FLI_OR_FLC
|| parent_mct
==MCT_FRAME
))
808 de_warn(c
, "Unknown chunk type 0x%04x at %"I64_FMT
, ci
->chunktype
, ci
->pos
);
813 de_dbg_indent_restore(c
, saved_indent_level
);
817 // if max_nchunks==-1, no maximum
818 static void do_sequence_of_chunks(deark
*c
, lctx
*d
, struct chunk_info_type
*parent_ci
,
819 i64 pos1
, i64 max_nchunks
)
822 i64 endpos
= parent_ci
->pos
+ parent_ci
->len
;
824 int saved_indent_level
;
826 de_dbg_indent_save(c
, &saved_indent_level
);
828 if(!parent_ci
) goto done
;
829 if(parent_ci
->level
> 10) goto done
;
830 if(pos
+6 >= endpos
) goto done
;
831 de_dbg(c
, "sequence of chunks at %"I64_FMT
, pos1
);
836 i64 bytes_consumed
= 0;
839 if(max_nchunks
>=0 && chunk_idx
>=max_nchunks
) break;
840 bytes_avail
= endpos
- pos
;
841 if(bytes_avail
<6) break;
843 ret
= do_chunk(c
, d
, parent_ci
, pos
, bytes_avail
, parent_ci
->level
+1, &bytes_consumed
);
844 if(!ret
|| bytes_consumed
<1) break;
845 pos
+= bytes_consumed
;
850 de_dbg_indent_restore(c
, saved_indent_level
);
853 static void de_run_fli(deark
*c
, de_module_params
*mparams
)
856 i64 bytes_consumed
= 0;
858 d
= de_malloc(c
, sizeof(lctx
));
860 (void)do_chunk(c
, d
, NULL
, 0, c
->infile
->len
, 0, &bytes_consumed
);
867 static int de_identify_fli(deark
*c
)
872 ct
= (UI
)de_getu16le(4);
873 if((ct
>>8) != 0xaf) return 0;
874 has_ext
= de_input_file_has_ext(c
, "fli") ||
875 de_input_file_has_ext(c
, "flc");
876 if(ct
==CHUNKTYPE_FLI
|| ct
==CHUNKTYPE_FLC
) {
877 if(has_ext
) return 100;
880 if(has_ext
) return 9;
884 void de_module_fli(deark
*c
, struct deark_module_info
*mi
)
887 mi
->desc
= "FLI/FLC animation";
888 mi
->run_fn
= de_run_fli
;
889 mi
->identify_fn
= de_identify_fli
;