OSDN Git Service

wwww
[proj16/16.git] / 16 / v2 / source / ENGINE / FLI.C
1 /*\r
2 Copyright (C) 1998 BJ Eirich (aka vecna)\r
3 This program is free software; you can redistribute it and/or\r
4 modify it under the terms of the GNU General Public License\r
5 as published by the Free Software Foundation; either version 2\r
6 of the License, or (at your option) any later version.\r
7 This program is distributed in the hope that it will be useful,\r
8 but WITHOUT ANY WARRANTY; without even the implied warranty of\r
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\r
10 See the GNU General Public Lic\r
11 See the GNU General Public License for more details.\r
12 You should have received a copy of the GNU General Public License\r
13 along with this program; if not, write to the Free Software\r
14 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\r
15 */\r
16 \r
17 // ported by aen\r
18 \r
19 #define FLI_H\r
20 #include <sys/stat.h>\r
21 #include <fcntl.h>\r
22 #include <unistd.h>\r
23 #include "verge.h"\r
24 \r
25 // ================================= Data ====================================\r
26 \r
27 #ifndef __WATCOMC__\r
28 #define INT_MAX 0xFFFFFFFF\r
29 #define INT_MIN 0\r
30 #endif\r
31 \r
32 #ifndef MIN\r
33 #define MIN(x,y)     (((x) < (y)) ? (x) : (y))\r
34 #define MAX(x,y)     (((x) > (y)) ? (x) : (y))\r
35 #define MID(x,y,z)   MAX((x), MIN((y), (z)))\r
36 #endif\r
37 \r
38 #ifndef ABS\r
39 #define ABS(x)       (((x) >= 0) ? (x) : (-(x)))\r
40 #endif\r
41 \r
42 #ifndef SGN\r
43 #define SGN(x)       (((x) >= 0) ? 1 : -1)\r
44 #endif\r
45 \r
46 #define FLI_MAGIC            0xAF11      // file header magic number\r
47 #define FLC_MAGIC            0xAF12      // file magic number (Pro)\r
48 #define FLI_FRAME_MAGIC      0xF1FA      // frame header magic number\r
49 #define FLI_FRAME_PREFIX     0xF100      // FLC's prefix info\r
50 #define FLI_FRAME_USELESS    0x00A1      // FLC's garbage frame\r
51 \r
52 typedef struct\r
53 {\r
54   int w,h;\r
55   byte *data;\r
56 } BITMAP;\r
57 \r
58 #define FLI_OK          0              /* FLI player return values */\r
59 #define FLI_EOF         -1\r
60 #define FLI_ERROR       -2\r
61 #define FLI_NOT_OPEN    -3\r
62 \r
63 #ifdef __WATCOMC__\r
64 #define PACKED\r
65 #pragma pack(1);\r
66 #endif\r
67 \r
68 #ifdef __DJGPP__\r
69 #define PACKED __attribute__ ((packed))\r
70 #endif\r
71 \r
72 typedef struct\r
73 {\r
74   long size            PACKED;\r
75   word type            PACKED;\r
76   word frame_count     PACKED;\r
77   word width           PACKED;\r
78   word height          PACKED;\r
79   word bpp             PACKED;\r
80   word flags           PACKED;\r
81   word speed           PACKED;\r
82   long next_head       PACKED;\r
83   long frames_in_table PACKED;\r
84   char reserved[102]   PACKED;\r
85 } FLI_HEADER;\r
86 \r
87 typedef struct\r
88 {\r
89   quad size            PACKED;\r
90   word type            PACKED;\r
91   word chunks          PACKED;\r
92   char pad[8]          PACKED;\r
93 } FLI_FRAME;\r
94 \r
95 typedef struct\r
96 {\r
97   quad size            PACKED;\r
98   word type            PACKED;\r
99 } FLI_CHUNK;\r
100 \r
101 #ifdef __WATCOMC__\r
102 #pragma pack();\r
103 #endif\r
104 \r
105 static int fli_status = FLI_NOT_OPEN;  // current state of the FLI player\r
106 \r
107 int fli_bitmap_width = 0;\r
108 int fli_bitmap_height = 0;\r
109 byte *fli_bitmap_data = NULL;          // current frame of the FLI\r
110 byte fli_palette[768];                   // current palette the FLI is using\r
111 \r
112 int fli_bmp_dirty_from = INT_MAX;      // what part of fli_bitmap is dirty\r
113 int fli_bmp_dirty_to = INT_MIN;\r
114 int fli_pal_dirty_from = INT_MAX;      // what part of fli_palette is dirty\r
115 int fli_pal_dirty_to = INT_MIN;\r
116 \r
117 int fli_frame = 0;                     // current frame number in the FLI\r
118 long speed;\r
119 \r
120 static int fli_file = 0;               // the file we are reading\r
121 \r
122 static byte *fli_mem_data = NULL;      // the memory FLI we are playing\r
123 static int fli_mem_pos = 0;            // position in the memory FLI\r
124 \r
125 static FLI_HEADER fli_header;          // header structure\r
126 static FLI_FRAME frame_header;         // frame header structure\r
127 \r
128 // a block of temporary working memory\r
129 byte *_scratch_mem = NULL;\r
130 int _scratch_mem_size = 0;\r
131 \r
132 // ================================= Code ====================================\r
133 \r
134 void reset_fli_variables(void);\r
135 void close_fli(void);\r
136 int  next_fli_frame(int);\r
137 int  open_fli(char *);\r
138 int  open_memory_fli(byte *);\r
139 \r
140 void _grow_scratch_mem(int size)\r
141 {\r
142   if (size > _scratch_mem_size) {\r
143     size = (size+1023) & 0xFFFFFC00;\r
144     _scratch_mem = realloc(_scratch_mem, size);\r
145     _scratch_mem_size = size;\r
146   }\r
147 }\r
148 \r
149 void vsync()\r
150 {\r
151   while (!(inp(986) & 8));\r
152 }\r
153 \r
154 void set_palette_range(byte *pal, int from, int to, int sync)\r
155 {\r
156   int i;\r
157 \r
158   // swap?\r
159   if (to<from) { int t=from; from=to; to=t; }\r
160 \r
161   // keep valid\r
162   if (from<0) from=0;\r
163   if (to>=256) to=255;\r
164 \r
165   if (sync) vsync();\r
166 \r
167   outp(968, from);\r
168   for (i=from; i<=to; i++)\r
169   {\r
170     outp(969, pal[(i*3)+0]);\r
171     outp(969, pal[(i*3)+1]);\r
172     outp(969, pal[(i*3)+2]);\r
173   }\r
174 }\r
175 \r
176 static byte *fli_read(byte *buf, int size)\r
177 {\r
178   int result;\r
179 \r
180   if (fli_mem_data)\r
181   {\r
182     if (buf)\r
183       memcpy(buf, fli_mem_data+fli_mem_pos, size);\r
184     else\r
185       buf = fli_mem_data+fli_mem_pos;\r
186 \r
187     fli_mem_pos += size;\r
188   }\r
189   else\r
190   {\r
191     if (!buf)\r
192     {\r
193       _grow_scratch_mem(size);\r
194       buf = _scratch_mem;\r
195     }\r
196 \r
197     result = read(fli_file, buf, size);\r
198     if (result != size)\r
199       return NULL;\r
200   }\r
201   return buf;\r
202 }\r
203 \r
204 static void fli_seek(int offset, int mode)\r
205 {\r
206   if (fli_mem_data)\r
207   {\r
208     if (mode == SEEK_CUR)\r
209       fli_mem_pos += offset;\r
210     else\r
211       fli_mem_pos = offset;\r
212   }\r
213   else\r
214     lseek(fli_file, offset, mode);\r
215 }\r
216 \r
217 // helpers for reading FLI chunk data\r
218 #define READ_BYTE()  ((sz-- > 0)    ? *(((byte *)p)++) : 0)\r
219 #define READ_CHAR()  ((sz-- > 0)    ? *(((signed char  *)p)++) : 0)\r
220 #define READ_SHORT() (((sz-=2) > 0) ? *(((signed short *)p)++) : 0)\r
221 \r
222 #define READ_BLOCK(pos, size)             \\r
223   {                                       \\r
224     if (sz >= (size))                     \\r
225     {                                     \\r
226       memcpy(pos, p, size);               \\r
227       p += (size);                        \\r
228       sz -= (size);                       \\r
229     }                                     \\r
230     else                                  \\r
231     {                                     \\r
232       char *_p = (char *)(pos);           \\r
233       int _c;                             \\r
234                                           \\r
235       for (_c=0; _c < (size); _c++)       \\r
236         *(_p++) = READ_BYTE();            \\r
237     }                                     \\r
238   }\r
239 \r
240 #define READ_RLE_BYTE(pos, size)          \\r
241   {                                       \\r
242     memset(pos, READ_BYTE(), size);       \\r
243   }\r
244 \r
245 #define READ_RLE_WORD(pos, size)          \\r
246   {                                       \\r
247     short *_p = (short *)(pos);           \\r
248     short _v = READ_SHORT();              \\r
249     int _c;                               \\r
250                                           \\r
251     for (_c=0; _c < (size); _c++)         \\r
252       *(_p++) = _v;                       \\r
253   }\r
254 \r
255 static void do_fli_256_color(byte *p, int sz)\r
256 {\r
257   int packets;\r
258   int c, c2;\r
259   int offset;\r
260   int length;\r
261 \r
262   offset = 0;\r
263   packets = READ_SHORT();\r
264   for (c=0; c<packets; c++)\r
265   {\r
266     offset += READ_BYTE();\r
267     length = READ_BYTE();\r
268     if (length == 0) length = 256;\r
269     for (c2=0; c2<length; c2++)\r
270     {\r
271       fli_palette[((offset+c2)*3)+0] = READ_BYTE() / 4;\r
272       fli_palette[((offset+c2)*3)+1] = READ_BYTE() / 4;\r
273       fli_palette[((offset+c2)*3)+2] = READ_BYTE() / 4;\r
274     }\r
275     fli_pal_dirty_from = MIN(fli_pal_dirty_from, offset);\r
276     fli_pal_dirty_to = MAX(fli_pal_dirty_to, offset+length-1);\r
277     offset += length;\r
278   }\r
279 }\r
280 \r
281 static void do_fli_delta(byte *p, int sz)\r
282 {\r
283   int lines;\r
284   int packets;\r
285   int size;\r
286   int x, y;\r
287 \r
288   y = 0;\r
289   lines = READ_SHORT();\r
290 \r
291   // for each line...\r
292   while (lines-- > 0)\r
293   {\r
294     packets = READ_SHORT();\r
295 \r
296     while (packets < 0)\r
297     {\r
298       if (packets & 0x4000)\r
299         y -= packets;\r
300       else\r
301         fli_bitmap_data[(y*fli_bitmap_width)+fli_bitmap_width-1]=packets&0xff;\r
302         //fli_bitmap->line[y][fli_bitmap->w-1] = packets & 0xFF;\r
303 \r
304       packets = READ_SHORT();\r
305     }\r
306     x=0;\r
307     while (packets-- > 0)\r
308     {\r
309       // skip bytes\r
310       x += READ_BYTE();\r
311 \r
312       size = READ_CHAR();\r
313 \r
314       // copy size words\r
315       if (size > 0)\r
316       {\r
317         READ_BLOCK(fli_bitmap_data+(y*fli_bitmap_width)+x, size*2);\r
318         //READ_BLOCK(fli_bitmap->line[y]+x, size*2);\r
319         x += size*2;\r
320       }\r
321       // repeat word -size times\r
322       else if (size < 0)\r
323       {\r
324         READ_RLE_WORD(fli_bitmap_data+(y*fli_bitmap_width)+x, -size);\r
325         //READ_RLE_WORD(fli_bitmap->line[y]+x, -size);\r
326         x -= size*2;\r
327       }\r
328     }\r
329     fli_bmp_dirty_from = MIN(fli_bmp_dirty_from, y);\r
330     fli_bmp_dirty_to = MAX(fli_bmp_dirty_to, y);\r
331     y++;\r
332   }\r
333 }\r
334 \r
335 static void do_fli_color(byte *p, int sz)\r
336 {\r
337   int packets;\r
338   int c, c2;\r
339   int offset;\r
340   int length;\r
341 \r
342   offset = 0;\r
343   packets = READ_SHORT();\r
344 \r
345   for (c=0; c<packets; c++)\r
346   {\r
347     offset += READ_BYTE();\r
348     length = READ_BYTE();\r
349     if (length == 0) length = 256;\r
350 \r
351     for (c2=0; c2<length; c2++)\r
352     {\r
353       fli_palette[((offset+c2)*3)+0] = READ_BYTE();\r
354       fli_palette[((offset+c2)*3)+1] = READ_BYTE();\r
355       fli_palette[((offset+c2)*3)+2] = READ_BYTE();\r
356     }\r
357 \r
358     fli_pal_dirty_from = MIN(fli_pal_dirty_from, offset);\r
359     fli_pal_dirty_to = MAX(fli_pal_dirty_to, offset+length-1);\r
360     offset += length;\r
361   }\r
362 }\r
363 \r
364 static void do_fli_lc(byte *p, int sz)\r
365 {\r
366   int lines;\r
367   int packets;\r
368   int size;\r
369   int x, y;\r
370 \r
371   y = READ_SHORT();\r
372   lines = READ_SHORT();\r
373   fli_bmp_dirty_from = MIN(fli_bmp_dirty_from, y);\r
374   fli_bmp_dirty_to = MAX(fli_bmp_dirty_to, y+lines-1);\r
375 \r
376   // for each line...\r
377   while (lines-- > 0)\r
378   {\r
379     packets = READ_BYTE();\r
380     x = 0;\r
381     while (packets-- > 0)\r
382     {\r
383       x += READ_BYTE();\r
384       size = READ_CHAR();\r
385 \r
386       // copy size bytes\r
387       if (size > 0)\r
388       {\r
389         READ_BLOCK(fli_bitmap_data+(y*fli_bitmap_width)+x, size);\r
390         //READ_BLOCK(fli_bitmap->line[y]+x, size);\r
391         x += size;\r
392       }\r
393       else if (size < 0)\r
394       {\r
395         READ_RLE_BYTE(fli_bitmap_data+(y*fli_bitmap_width)+x, -size);\r
396         //READ_RLE_BYTE(fli_bitmap->line[y]+x, -size);\r
397         x -= size;\r
398       }\r
399     }\r
400     y++;\r
401   }\r
402 }\r
403 \r
404 static void do_fli_black(byte *p, int sz)\r
405 {\r
406   memset(fli_bitmap_data, 0, fli_bitmap_width*fli_bitmap_height);\r
407   //clear(fli_bitmap);\r
408 \r
409   fli_bmp_dirty_from = 0;\r
410   fli_bmp_dirty_to = fli_bitmap_height-1;\r
411 }\r
412 \r
413 static void do_fli_brun(byte *p, int sz)\r
414 {\r
415   int packets;\r
416   int size;\r
417   int x, y;\r
418 \r
419   // for each line...\r
420   for (y=0; y<fli_bitmap_height; y++)\r
421   {\r
422     packets = READ_BYTE();\r
423     x = 0;\r
424     while (packets-- > 0)\r
425     {\r
426       size = READ_CHAR();\r
427       if (size < 0)\r
428       {\r
429         READ_BLOCK(fli_bitmap_data+(y*fli_bitmap_width)+x, -size);\r
430         //READ_BLOCK(fli_bitmap->line[y]+x, -size);\r
431         x -= size;\r
432       }\r
433       // repeat byte size times\r
434       else if (size > 0)\r
435       {\r
436         READ_RLE_BYTE(fli_bitmap_data+(y*fli_bitmap_width)+x, size);\r
437         //READ_RLE_BYTE(fli_bitmap->line[y]+x, size);\r
438         x += size;\r
439       }\r
440     }\r
441   }\r
442   fli_bmp_dirty_from = 0;\r
443   fli_bmp_dirty_to = fli_bitmap_height-1;\r
444 }\r
445 \r
446 static void do_fli_copy(byte *p, int sz)\r
447 {\r
448   READ_BLOCK(fli_bitmap_data, fli_bitmap_width * fli_bitmap_height);\r
449   //READ_BLOCK(fli_bitmap->dat, fli_bitmap->w * fli_bitmap->h);\r
450 \r
451   fli_bmp_dirty_from = 0;\r
452   fli_bmp_dirty_to = fli_bitmap_height-1;\r
453 }\r
454 \r
455 static void read_frame()\r
456 {\r
457   byte *p;\r
458   FLI_CHUNK *chunk;\r
459   int c, sz;\r
460 \r
461   if (fli_status != FLI_OK)\r
462     return;\r
463 \r
464 get_another_frame:\r
465   if (!fli_read((byte *)&frame_header, sizeof(FLI_FRAME)))\r
466   {\r
467     fli_status = FLI_ERROR;\r
468     return;\r
469   }\r
470 \r
471   if ((frame_header.type == FLI_FRAME_PREFIX)\r
472   || (frame_header.type == FLI_FRAME_USELESS))\r
473   {\r
474     fli_seek(frame_header.size-sizeof(FLI_FRAME), SEEK_CUR);\r
475     fli_frame++;\r
476 \r
477     goto get_another_frame;\r
478   }\r
479 \r
480   if (frame_header.type != FLI_FRAME_MAGIC)\r
481   {\r
482     fli_status = FLI_ERROR;\r
483     return;\r
484   }\r
485 \r
486   if (frame_header.size == sizeof(FLI_FRAME))\r
487   {\r
488     fli_frame++;\r
489     return;\r
490   }\r
491   p = fli_read(NULL, frame_header.size-sizeof(FLI_FRAME));\r
492   if (!p)\r
493   {\r
494     fli_status = FLI_ERROR;\r
495     return;\r
496   }\r
497   for (c=0; c<frame_header.chunks; c++)\r
498   {\r
499     chunk = (FLI_CHUNK *)p;\r
500     sz = chunk->size - sizeof(FLI_CHUNK);\r
501     p += sizeof(FLI_CHUNK);\r
502     switch (chunk->type)\r
503     {\r
504       case 4:  do_fli_256_color(p, sz); break;\r
505       case 7:  do_fli_delta(p, sz); break;\r
506       case 11: do_fli_color(p, sz); break;\r
507       case 12: do_fli_lc(p, sz); break;\r
508       case 13: do_fli_black(p, sz); break;\r
509       case 15: do_fli_brun(p, sz); break;\r
510       case 16: do_fli_copy(p, sz); break;\r
511       default: err("Corrupt FLI chunk.");\r
512     }\r
513     p = ((byte *)chunk) + chunk->size;\r
514   }\r
515   fli_frame++;\r
516 }\r
517 \r
518 static int do_play_fli(BITMAP *bmp, int loop, int (*callback)())\r
519 {\r
520   int ret;\r
521 \r
522   ret = next_fli_frame(loop);\r
523   while (ret == FLI_OK)\r
524   {\r
525     if (fli_pal_dirty_from <= fli_pal_dirty_to)\r
526       set_palette_range(fli_palette, fli_pal_dirty_from, fli_pal_dirty_to, 1);\r
527 \r
528     if (fli_bmp_dirty_from <= fli_bmp_dirty_to)\r
529     {\r
530       int i,to=fli_bmp_dirty_to;\r
531       if (to>=bmp->h) to=bmp->h-1;\r
532 \r
533 //      vsync();\r
534       for (i=fli_bmp_dirty_from; i<=to; i++)\r
535       {\r
536         memcpy(bmp->data+(i*bmp->w), fli_bitmap_data+(i*fli_bitmap_width),\r
537           (fli_bitmap_width>bmp->w) ? bmp->w : fli_bitmap_width);\r
538       }\r
539 \r
540       //blit(\r
541       //  fli_bitmap, bmp, 0, fli_bmp_dirty_from, 0, fli_bmp_dirty_from,\r
542       //  fli_bitmap->w, 1+fli_bmp_dirty_to-fli_bmp_dirty_from);\r
543     }\r
544 \r
545     reset_fli_variables();\r
546 \r
547     if (callback)\r
548     {\r
549       ret = (*callback)();\r
550       if (ret != FLI_OK)\r
551         break;\r
552     }\r
553     ret = next_fli_frame(loop);\r
554     while (timer_count<speed) ShowPage();\r
555     timer_count=0;\r
556   }\r
557 \r
558   close_fli();\r
559 \r
560   return (ret == FLI_EOF) ? FLI_OK : ret;\r
561 }\r
562 \r
563 int play_fli(char *filename, BITMAP *bmp, int loop, int (*callback)())\r
564 {\r
565   if (open_fli(filename) != FLI_OK)\r
566     return FLI_ERROR;\r
567 \r
568   return do_play_fli(bmp, loop, callback);\r
569 }\r
570 \r
571 int play_memory_fli(byte *fli_data, BITMAP *bmp, int loop, int (*callback)())\r
572 {\r
573   if (open_memory_fli(fli_data) != FLI_OK)\r
574     return FLI_ERROR;\r
575 \r
576   return do_play_fli(bmp, loop, callback);\r
577 }\r
578 \r
579 static int do_open_fli()\r
580 {\r
581   // read the header\r
582   if (!fli_read((byte *)&fli_header, sizeof(FLI_HEADER)))\r
583   {\r
584     close_fli();\r
585     return FLI_ERROR;\r
586   }\r
587 \r
588   // check magic numbers\r
589   if (((fli_header.bpp != 8) && (fli_header.bpp != 0))\r
590   || ((fli_header.type != FLI_MAGIC) && (fli_header.type != FLC_MAGIC)))\r
591   {\r
592     close_fli();\r
593     return FLI_ERROR;\r
594   }\r
595 \r
596   if (fli_header.width == 0)\r
597     fli_header.width = 320;\r
598 \r
599   if (fli_header.height == 0)\r
600     fli_header.height = 200;\r
601 \r
602   // create the frame bitmap\r
603   fli_bitmap_width=fli_header.width;\r
604   fli_bitmap_height=fli_header.height;\r
605   fli_bitmap_data=(byte *)malloc(fli_bitmap_width*fli_bitmap_height);\r
606   if (!fli_bitmap_data)\r
607   {\r
608     close_fli();\r
609     return FLI_ERROR;\r
610   }\r
611 \r
612   reset_fli_variables();\r
613   fli_frame = 0;\r
614   fli_status = FLI_OK;\r
615 \r
616   if (fli_header.type == FLI_MAGIC)\r
617     speed = (long)fli_header.speed * 100 / 70;\r
618   else\r
619     speed = (long)fli_header.speed / 10;\r
620 \r
621   if (speed == 0)\r
622     speed = 100;\r
623 \r
624   return fli_status;\r
625 }\r
626 \r
627 int open_fli(char *filename)\r
628 {\r
629   if (fli_status != FLI_NOT_OPEN)\r
630     return FLI_ERROR;\r
631   fli_file = open(filename, O_RDONLY | O_BINARY, S_IRUSR | S_IWUSR);\r
632   if (fli_file < 0)\r
633   {\r
634     fli_file = 0;\r
635     return FLI_ERROR;\r
636   }\r
637   return do_open_fli();\r
638 }\r
639 \r
640 int open_memory_fli(byte *fli_data)\r
641 {\r
642   if (fli_status != FLI_NOT_OPEN)\r
643     return FLI_ERROR;\r
644   fli_mem_data = fli_data;\r
645   fli_mem_pos = 0;\r
646   return do_open_fli();\r
647 }\r
648 \r
649 void close_fli()\r
650 {\r
651   //remove_int(fli_timer_callback);\r
652 \r
653   if (fli_file)\r
654   {\r
655     close(fli_file);\r
656     fli_file = 0;\r
657   }\r
658 \r
659   if (fli_bitmap_data)\r
660   {\r
661     free(fli_bitmap_data);\r
662     fli_bitmap_data = NULL;\r
663   }\r
664 \r
665   fli_mem_data = NULL;\r
666   fli_mem_pos = 0;\r
667   reset_fli_variables();\r
668   fli_status = FLI_NOT_OPEN;\r
669 }\r
670 \r
671 int next_fli_frame(int loop)\r
672 {\r
673   if (fli_status != FLI_OK)\r
674     return fli_status;\r
675 \r
676   //fli_timer--;\r
677 \r
678   // end of file? should we loop?\r
679   if (fli_frame >= fli_header.frame_count)\r
680   {\r
681     if (loop)\r
682     {\r
683       fli_seek(sizeof(FLI_HEADER), SEEK_SET);\r
684       fli_frame = 0;\r
685     }\r
686     else\r
687     {\r
688       fli_status = FLI_EOF;\r
689       return fli_status;\r
690     }\r
691   }\r
692   read_frame();\r
693   return fli_status;\r
694 }\r
695 \r
696 void reset_fli_variables()\r
697 {\r
698   fli_bmp_dirty_from = INT_MAX;\r
699   fli_bmp_dirty_to = INT_MIN;\r
700   fli_pal_dirty_from = INT_MAX;\r
701   fli_pal_dirty_to = INT_MIN;\r
702 }\r