]> icculus.org git repositories - taylor/freespace2.git/blob - src/anim/packunpack.cpp
Initial revision
[taylor/freespace2.git] / src / anim / packunpack.cpp
1 /*
2  * $Logfile: /Freespace2/code/Anim/PackUnpack.cpp $
3  * $Revision$
4  * $Date$
5  * $Author$
6  *
7  * Code for handling packing and unpacking in Hoffoss's RLE format, used for
8  * Anim files.  Also handles Anim loading, creating Anim instances (for
9  * utilizing an Anim), and getting getting frames of the Anim.
10  *
11  * $Log$
12  * Revision 1.1  2002/05/03 03:28:08  root
13  * Initial revision
14  *
15  * 
16  * 12    7/30/99 10:10p Dave
17  * Fixed loading bar in 32 bit mode.
18  * 
19  * 11    7/18/99 1:59p Johnson
20  * Fixed potential anim locking problem.
21  * 
22  * 10    7/16/99 1:49p Dave
23  * 8 bit aabitmaps. yay.
24  * 
25  * 9     7/13/99 1:15p Dave
26  * 32 bit support. Whee!
27  * 
28  * 8     4/09/99 2:21p Dave
29  * Multiplayer beta stuff. CD checking.
30  * 
31  * 7     1/14/99 12:48a Dave
32  * Todo list bug fixes. Made a pass at putting briefing icons back into
33  * FRED. Sort of works :(
34  * 
35  * 6     12/01/98 5:53p Dave
36  * Simplified the way pixel data is swizzled. Fixed tga bitmaps to work
37  * properly in D3D and Glide.
38  * 
39  * 5     12/01/98 8:06a Dave
40  * Temporary checkin to fix some texture transparency problems in d3d.
41  * 
42  * 4     11/30/98 1:07p Dave
43  * 16 bit conversion, first run.
44  * 
45  * 3     10/22/98 6:14p Dave
46  * Optimized some #includes in Anim folder. Put in the beginnings of
47  * parse/localization support for externalized strings and tstrings.tbl
48  * 
49  * 2     10/07/98 10:52a Dave
50  * Initial checkin.
51  * 
52  * 1     10/07/98 10:48a Dave
53  * 
54  * 30    5/14/98 3:38p John
55  * Added in more non-darkening colors for Adam.  Had to fix some bugs in
56  * BmpMan and Ani stuff to get this to work.
57  * 
58  * 29    5/07/98 3:11a Lawrance
59  * Implement custom streaming code
60  * 
61  * 28    11/19/97 8:28p Dave
62  * Hooked in Main Hall screen. Put in Anim support for ping ponging
63  * animations as well as general reversal of anim direction.
64  * 
65  * 27    9/09/97 3:39p Sandeep
66  * warning level 4 bugs
67  * 
68  * 26    8/22/97 8:21a Lawrance
69  * short circuit key frame check if keyframe matches frame we are
70  * searching for
71  * 
72  * 25    8/21/97 5:11p Lawrance
73  * frame numbering for ANI's now is from 0 -> total_frames-1.
74  * 
75  * 24    8/19/97 10:59a Lawrance
76  * fix problem with accessing key frames
77  * 
78  * 23    7/28/97 10:42p Lawrance
79  * re-did interface to unpack_frame() to make more general
80  * 
81  * 22    7/28/97 10:52a Lawrance
82  * correctly set bitmap flags in anim_get_frame()
83  * 
84  * 21    7/21/97 5:10p Lawrance
85  * fix problem that was causing infinite recursion
86  * 
87  * 20    7/20/97 6:57p Lawrance
88  * supporting new RLE format
89  * 
90  * 19    6/27/97 4:36p Lawrance
91  * update pal translation table when gr_screen.signature changes
92  * 
93  * 18    6/26/97 12:12a Lawrance
94  * supporting anti-aliased bitmap animations
95  * 
96  * 17    6/25/97 3:03p Lawrance
97  * fix palette translation problem with anti-alised bitmaps
98  * 
99  * 16    5/19/97 2:28p Lawrance
100  * changes some variables to flags
101  * 
102  * 15    5/15/97 4:42p Lawrance
103  * supporting animations in-game
104  * 
105  * 14    2/25/97 11:06a Lawrance
106  * moved some higher level functions to from PackUnpack to AnimPlay
107  * 
108  * 13    2/19/97 9:51p Lawrance
109  * made keyframe decompression more effecient, moved 
110  * default anim FPS to header file
111  * 
112  * 12    2/19/97 4:00p Lawrance
113  * don't assert when cannot find anim filename, return a NULL instead
114  * 
115  * 11    2/17/97 4:17p Hoffoss
116  * modified packing internal format and added random access function to an
117  * Anim frame.
118  * 
119  * 10    2/17/97 2:59p Lawrance
120  * integrating into game
121  * 
122  * 9     2/14/97 11:27p Lawrance
123  * optimized unpacking some more (Jason)
124  * 
125  * 8     2/14/97 11:09p Hoffoss
126  * Made optimizations.
127  * 
128  * 7     2/14/97 10:48p Hoffoss
129  * fixed bug.
130  * 
131  * 6     2/14/97 10:38p Lawrance
132  * fixing bugs
133  * 
134  * 5     2/14/97 5:38p Hoffoss
135  * Changes to get AnimCoverter project to compile and link.
136  * 
137  * 4     2/14/97 3:29p Hoffoss
138  * Added header for MSDEV to fill in.
139  *
140  * $NoKeywords: $
141  */
142
143 #include "grinternal.h"
144 #include "bmpman.h"
145 #include "palman.h"
146 #include "2d.h"
147 #include "animplay.h"
148 #include "packunpack.h"
149
150 int packer_code = PACKER_CODE;
151 int transparent_code = 254;
152
153 void anim_check_for_palette_change(anim_instance *instance) {
154         if ( instance->parent->screen_sig != gr_screen.signature ) {
155                 instance->parent->screen_sig = gr_screen.signature;
156                 anim_set_palette(instance->parent);
157         }
158 }
159
160 anim_instance *init_anim_instance(anim *ptr, int bpp)
161 {
162         anim_instance *inst;
163
164         if (!ptr) {
165                 Int3();
166                 return NULL;
167         }
168
169         if ( ptr->flags & ANF_STREAMED ) {
170                 if ( ptr->file_offset < 0 ) {
171                         Int3();
172                         return NULL;
173                 }
174         } else {
175                 if ( !ptr->data ) {
176                         Int3();
177                         return NULL;
178                 }
179         }
180
181         ptr->instance_count++;
182         inst = (anim_instance *) malloc(sizeof(anim_instance));
183         Assert(inst);
184         inst->frame_num = -1;
185         inst->last_frame_num = -1;
186         inst->parent = ptr;
187         inst->data = ptr->data;
188         inst->file_offset = ptr->file_offset;
189         inst->stop_now = FALSE;
190         inst->aa_color = NULL;
191
192         if(bpp == 16){
193                 inst->frame = (ubyte *) malloc(inst->parent->width * inst->parent->height * 2);
194         } else {
195                 inst->frame = (ubyte *) malloc(inst->parent->width * inst->parent->height);
196         }
197         return inst;
198 }
199
200 void free_anim_instance(anim_instance *inst)
201 {
202         Assert(inst->frame);
203         free(inst->frame);
204         inst->frame = NULL;
205         inst->parent->instance_count--; 
206         inst->parent = NULL;
207         inst->data = NULL;
208         inst->file_offset = -1;
209
210         free(inst);     
211 }
212
213 int anim_get_next_frame(anim_instance *inst)
214 {
215         int bm, bitmap_flags;
216         int aabitmap = 0;
217         int bpp = 16;
218
219         if ( anim_instance_is_streamed(inst) ) {
220                 if ( inst->file_offset <= 0 ) {
221                         return -1;
222                 }
223         } else {
224                 if (!inst->data)
225                         return -1;
226         }
227
228         inst->frame_num++;
229         if (inst->frame_num >= inst->parent->total_frames) {
230                 inst->data = NULL;
231                 inst->file_offset = inst->parent->file_offset;
232                 return -1;
233         }
234
235         if (inst->parent->flags & ANF_XPARENT) {
236                 // bitmap_flags = BMP_XPARENT;
237                 bitmap_flags = 0;
238         } else {
239                 bitmap_flags = 0;
240         }
241
242         bpp = 16;
243         if(inst->aa_color != NULL){
244                 bitmap_flags |= BMP_AABITMAP;
245                 aabitmap = 1;
246                 bpp = 8;
247         }
248
249         anim_check_for_palette_change(inst);
250
251         // if we're using bitmap polys
252         if(Gr_bitmap_poly){
253                 BM_SELECT_TEX_FORMAT();
254         }
255
256         if ( anim_instance_is_streamed(inst) ) {
257                 inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation, aabitmap, bpp);
258         } else {
259                 inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation, aabitmap, bpp);
260         }
261
262         bm = bm_create(bpp, inst->parent->width, inst->parent->height, inst->frame, bitmap_flags);
263         bm_unload(bm);
264         return bm;
265 }
266
267 ubyte *anim_get_next_raw_buffer(anim_instance *inst, int xlate_pal, int aabitmap, int bpp)
268 {       
269         if ( anim_instance_is_streamed(inst) ) {
270                 if ( inst->file_offset < 0 ) {
271                         return NULL;
272                 }
273         } else {
274                 if (!inst->data){
275                         return NULL;
276                 }
277         }
278
279         inst->frame_num++;
280         if (inst->frame_num >= inst->parent->total_frames) {
281                 inst->data = NULL;
282                 inst->file_offset = inst->parent->file_offset;
283                 return NULL;
284         }
285
286         anim_check_for_palette_change(inst);
287
288         if ( anim_instance_is_streamed(inst) ) {
289                 if ( xlate_pal ){
290                         inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation, aabitmap, bpp);
291                 } else {
292                         inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, NULL, aabitmap, bpp);
293                 }
294         } else {
295                 if ( xlate_pal ){
296                         inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation, aabitmap, bpp);
297                 } else {
298                         inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, NULL, aabitmap, bpp);
299                 }
300         }
301
302         return inst->frame;
303 }
304
305 // --------------------------------------------------------------------
306 // anim_get_frame()
307 //
308 // Get a bitmap id from the anim_instance for the specified frame_num
309 //
310 //      input:  *inst                   =>              pointer to anim instance
311 //                              frame_num       =>              frame number to get (first frame is 0)
312 //                              xlate_pal       =>              DEFAULT PARM (value 1): whether to translate the palette
313 //                                                                              to the current game palette
314 //
315 int anim_get_frame(anim_instance *inst, int frame_num, int xlate_pal)
316 {
317         /*
318         int                     bm, bitmap_flags, key = 0, offset = 0;
319         int idx;
320
321         if ((frame_num < 0) || (frame_num >= inst->parent->total_frames))  // illegal frame number
322                 return -1;
323
324         int need_reset = 0;
325         if ( anim_instance_is_streamed(inst) ) {
326                 if ( inst->file_offset < 0 ) {
327                         need_reset = 1;
328                 }
329         } else {
330                 if ( !inst->data ) {
331                         need_reset = 1;
332                 }
333         }
334
335         if (need_reset || (inst->frame_num >= inst->parent->total_frames)) {  // reset to valid info
336                 inst->data = inst->parent->data;
337                 inst->file_offset = inst->parent->file_offset;
338                 inst->frame_num = 0;
339         }
340
341         bitmap_flags = 0;
342         if (inst->parent->flags & ANF_XPARENT) {
343                 // bitmap_flags = BMP_XPARENT;
344                 bitmap_flags = 0;
345         }
346
347         if ( inst->frame_num == frame_num ) {
348                 bm = bm_create(16, inst->parent->width, inst->parent->height, inst->frame, bitmap_flags);
349                 bm_unload(bm);
350                 return bm;
351         }
352
353         if (inst->parent->flags & ANF_XPARENT){
354                 // bitmap_flags = BMP_XPARENT;
355                 bitmap_flags = 0;
356         } else {
357                 bitmap_flags = 0;
358         }
359
360         idx = 0;
361         key = 0;
362         while(idx < inst->parent->num_keys){                    
363                 if (( (inst->parent->keys[idx].frame_num-1) <= frame_num) && ( (inst->parent->keys[idx].frame_num-1) > key)) {  // find closest key
364                         key = inst->parent->keys[idx].frame_num - 1;
365                         offset = inst->parent->keys[idx].offset;
366                                 
367                         if ( key == frame_num )
368                                 break;
369                 }
370                 idx++;
371         }
372                         
373         if ( key == frame_num ) {
374                 inst->frame_num = key;
375
376                 if ( anim_instance_is_streamed(inst) ) {
377                         inst->file_offset = inst->parent->file_offset + offset;
378                 } else {
379                         inst->data = inst->parent->data + offset;
380                 }
381
382                 anim_check_for_palette_change(inst);
383
384                 if ( anim_instance_is_streamed(inst) ) {
385                         if ( xlate_pal ){
386                                 inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation);
387                         } else {
388                                 inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, NULL);
389                         }
390                 } else {
391                         if ( xlate_pal ){
392                                 inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation);
393                         } else {
394                                 inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, NULL);
395                         }
396                 }
397
398                 goto create_bitmap;
399         }
400
401         if (key > inst->frame_num)  // best key is closer than current position
402         {
403                 inst->frame_num = key;
404
405                 if ( anim_instance_is_streamed(inst) ) {
406                         inst->file_offset = inst->parent->file_offset + offset;
407                 } else {
408                         inst->data = inst->parent->data + offset;
409                 }
410
411                 anim_check_for_palette_change(inst);
412
413                 if ( anim_instance_is_streamed(inst) ) {
414                         if ( xlate_pal )
415                                 inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation);
416                         else 
417                                 inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, NULL);
418                 } else {
419                         if ( xlate_pal )
420                                 inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation);
421                         else 
422                                 inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, NULL);
423                 }
424         }
425
426         while (inst->frame_num != frame_num) {
427                 anim_check_for_palette_change(inst);
428
429                 if ( anim_instance_is_streamed(inst) ) {
430                         if ( xlate_pal )
431                                 inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation);
432                         else 
433                                 inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, NULL);
434                 } else {
435                         if ( xlate_pal )
436                                 inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation);
437                         else 
438                                 inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, NULL);
439                 }
440                 inst->frame_num++;
441         }
442
443         create_bitmap:
444
445         bm = bm_create(16, inst->parent->width, inst->parent->height, inst->frame, bitmap_flags);
446         bm_unload(bm);
447         return bm;
448   */
449         Int3();
450         return -1;
451 }
452
453 // frame = frame pixel data to pack
454 // save = memory to store packed data to
455 // size = number of bytes to pack
456 // max = maximum number of packed bytes (size of buffer)
457 // returns: actual number of bytes data packed to or -1 if error
458 int pack_key_frame(ubyte *frame, ubyte *save, long size, long max, int compress_type)
459 {
460         int last = -32768, count = 0;
461         long packed_size = 1;
462
463         switch ( compress_type ) {
464                 case PACKING_METHOD_RLE_KEY:
465                         *save++ = PACKING_METHOD_RLE_KEY;
466                         while (size--) {
467                                 if (*frame != last || count > 255) {
468                                         if (packed_size + 3 >= max)
469                                                 return -1;
470
471                                         if (count < 3) {
472                                                 if (last == packer_code) {
473                                                         *save++ = (ubyte)packer_code;
474                                                         *save++ = (ubyte)(count - 1);
475                                                         packed_size += 2;
476
477                                                 } else
478                                                         while (count--) {
479                                                                 *save++ = (ubyte)last;
480                                                                 packed_size++;
481                                                         }
482
483                                         } else {
484                                                 *save++ = (ubyte)packer_code;
485                                                 *save++ = (ubyte)(count - 1);
486                                                 *save++ = (ubyte)last;
487                                                 packed_size += 3;
488                                         }
489
490                                         count = 0;
491                                         last = *frame;
492                                 }
493
494                                 count++;
495                                 frame++;
496                         }
497
498                         if (packed_size + 3 >= max)
499                                 return -1;
500
501                         if (count < 3) {
502                                 if (last == packer_code) {
503                                         *save++ = (ubyte)packer_code;
504                                         *save++ = (ubyte)(count - 1);
505                                         packed_size += 2;
506
507                                 } else
508                                         while (count--) {
509                                                 *save++ = (ubyte)last;
510                                                 packed_size++;
511                                         }
512
513                         } else {
514                                 *save++ = (ubyte)packer_code;
515                                 *save++ = (ubyte)(count - 1);
516                                 *save++ = (ubyte)last;
517                                 packed_size += 3;
518                         }
519                         break;
520
521                 case PACKING_METHOD_STD_RLE_KEY: {
522                         ubyte *dest_start;
523                         int i;
524
525                         dest_start = save;
526                         count = 1;
527
528                         last = *frame++;
529                         *save++ = PACKING_METHOD_STD_RLE_KEY;
530                         for (i=1; i < size; i++ )       {
531
532                                 if ( *frame != last ) {
533                                         if ( count ) {
534
535                                                 if (packed_size + 2 >= max)
536                                                         return -1;
537
538                                                 if ( (count == 1) && !(last & STD_RLE_CODE) ) {
539                                                         *save++ = (ubyte)last;
540                                                         packed_size++;
541                                                         Assert( last != STD_RLE_CODE );
542 //                                                      printf("Just packed %d 1 times, since pixel change, no count included\n",last);
543                                                 }
544                                                 else {
545                                                         count |= STD_RLE_CODE;
546                                                         *save++ = (ubyte)count;
547                                                         *save++ = (ubyte)last;
548                                                         packed_size += 2;
549 //                                                      printf("Just packed %d %d times, since pixel change\n",last,count);
550                                                 }
551                                         }
552                 
553                                         last = *frame;
554                                         count = 0;
555                                 }
556
557                                 count++;
558                                 frame++;
559
560                                 if ( count == 127 ) {
561                                         count |= STD_RLE_CODE;
562                                         *save++ = (ubyte)count;
563                                         *save++ = (ubyte)last;
564                                         packed_size += 2;
565                                         count = 0;
566 //                                      printf("Just packed %d %d times, since count overflow\n",last,count);
567
568                                 }
569                         }       // end for
570
571                         if (count)      {
572
573                                 if (packed_size + 2 >= max)
574                                         return -1;
575
576                                 if ( (count == 1) && !(last & STD_RLE_CODE) ) {
577                                         *save++ = (ubyte)last;
578                                         packed_size++;
579 //                                      printf("Just packed %d 1 times, at end since single pixel, no count\n",last);
580                                         Assert( last != STD_RLE_CODE );
581                                 }
582                                 else {
583                                         count |= STD_RLE_CODE;
584                                         *save++ = (ubyte)count;
585                                         *save++ = (ubyte)last;
586                                         packed_size += 2;
587 //                                      printf("Just packed %d %d times, at end since pixel change\n",last,count);
588                                 }
589                         }
590
591                         Assert(packed_size == (save-dest_start) );
592                         return packed_size;
593                         break;
594                         }
595
596                 default:
597                         Assert(0);
598                         return -1;
599                         break;
600         } // end switch
601
602         return packed_size;
603 }
604
605 // frame = frame pixel data to pack
606 // frame2 = previous frame's pixel data
607 // save = memory to store packed data to
608 // size = number of bytes to pack
609 // max = maximum number of packed bytes (size of buffer)
610 // returns: actual number of bytes data packed to or -1 if error
611 int pack_frame(ubyte *frame, ubyte *frame2, ubyte *save, long size, long max, int compress_type)
612 {
613         int pixel, last = -32768, count = 0, i;
614         long packed_size = 1;
615
616         switch ( compress_type ) {
617                 case PACKING_METHOD_RLE:                                        // Hoffoss RLE regular frame
618                         *save++ = PACKING_METHOD_RLE;
619                         while (size--) {
620                                 if (*frame != *frame2++)
621                                         pixel = *frame;
622                                 else
623                                         pixel = transparent_code;
624
625                                 if (pixel != last || count > 255) {
626                                         if (packed_size + 3 >= max)
627                                                 return -1;
628
629                                         if (count < 3) {
630                                                 if (last == packer_code) {
631                                                         *save++ = (ubyte)packer_code;
632                                                         *save++ = (ubyte)(count - 1);
633                                                         packed_size += 2;
634
635                                                 } else
636                                                         while (count--) {
637                                                                 *save++ = (ubyte)last;
638                                                                 packed_size++;
639                                                         }
640
641                                         } else {
642                                                 *save++ = (ubyte)packer_code;
643                                                 *save++ = (ubyte)(count - 1);
644                                                 *save++ = (ubyte)last;
645                                                 packed_size += 3;
646                                         }
647
648                                         count = 0;
649                                         last = pixel;
650                                 }
651
652                                 frame++;
653                                 count++;
654                         }
655
656                         if (packed_size + 3 >= max)
657                                 return -1;
658
659                         if (count < 3) {
660                                 if (last == packer_code) {
661                                         *save++ = (ubyte)packer_code;
662                                         *save++ = (ubyte)(count - 1);
663                                         packed_size += 2;
664
665                                 } else
666                                         while (count--) {
667                                                 *save++ = (ubyte)last;
668                                                 packed_size++;
669                                         }
670
671                         } else {
672                                 *save++ = (ubyte)(packer_code);
673                                 *save++ = (ubyte)(count - 1);
674                                 *save++ = (ubyte)(last);
675                                 packed_size += 3;
676                         }
677                         break;
678
679                 case PACKING_METHOD_STD_RLE: {          // high bit count regular RLE frame
680
681                         ubyte *dest_start;
682
683                         dest_start = save;
684                         count = 1;
685
686                         if (*frame++ != *frame2++)
687                                 last = *frame;
688                         else
689                                 last = transparent_code;
690
691                         *save++ = PACKING_METHOD_STD_RLE;
692                         for (i=1; i < size; i++ )       {
693
694                                 if (*frame != *frame2++)
695                                         pixel = *frame;
696                                 else
697                                         pixel = transparent_code;
698
699                                 if ( pixel != last ) {
700                                         if ( count ) {
701
702                                                 if (packed_size + 2 >= max)
703                                                         return -1;
704
705                                                 if ( (count == 1) && !(last & STD_RLE_CODE) ) {
706                                                         *save++ = (ubyte)last;
707                                                         packed_size++;
708                                                         Assert( last != STD_RLE_CODE );
709                                                 }
710                                                 else {
711                                                         count |= STD_RLE_CODE;
712                                                         *save++ = (ubyte)count;
713                                                         *save++ = (ubyte)last;
714                                                         packed_size += 2;
715                                                 }
716                                         }
717                 
718                                         last = pixel;
719                                         count = 0;
720                                 }
721
722                                 count++;
723                                 frame++;
724
725                                 if ( count == 127 ) {
726                                         count |= STD_RLE_CODE;
727                                         *save++ = (ubyte)count;
728                                         *save++ = (ubyte)last;
729                                         packed_size += 2;
730                                         count = 0;
731                                 }
732                         }       // end for
733
734                         if (count)      {
735
736                                 if (packed_size + 2 >= max)
737                                         return -1;
738
739                                 if ( (count == 1) && !(last & STD_RLE_CODE) ) {
740                                         *save++ = (ubyte)last;
741                                         packed_size++;
742                                         Assert( last != STD_RLE_CODE );
743                                 }
744                                 else {
745                                         count |= STD_RLE_CODE;
746                                         *save++ = (ubyte)count;
747                                         *save++ = (ubyte)last;
748                                         packed_size += 2;
749                                 }
750                         }
751
752                         Assert(packed_size == (save-dest_start) );
753                         return packed_size;
754                         break;
755                         }
756
757                 default:
758                         Assert(0);
759                         return -1;
760                         break;
761         } // end switch
762
763         return packed_size;
764 }
765
766 // unpack a pixel given the passed index and the anim_instance's palette, return bytes stuffed
767 int unpack_pixel(anim_instance *ai, ubyte *data, ubyte pix, int aabitmap, int bpp)
768 {
769         int bit_24;
770         ushort bit_16 = 0;      
771         ubyte bit_8 = 0;
772         ubyte al = 0;
773         ubyte r, g, b;
774         anim *a = ai->parent;
775         Assert(a);      
776
777         // if this is an aabitmap, don't run through the palette
778         if(aabitmap){
779                 switch(bpp){
780                 case 16 : 
781                         bit_16 = (ushort)pix;
782                         break;
783                 case 8:
784                         bit_8 = pix;
785                         break;
786                 default:
787                         Int3();
788                 }
789         } else {                
790                 // if the pixel value is 255, or is the xparent color, make it so               
791                 if(((a->palette[pix*3] == a->xparent_r) && (a->palette[pix*3+1] == a->xparent_g) && (a->palette[pix*3+2] == a->xparent_b)) ){
792                         r = b = 0;
793                         g = 255;
794                         bm_set_components((ubyte*)&bit_16, &r, &g, &b, &al);
795                 } else {
796                         // stuff the 24 bit value
797                         memcpy(&bit_24, &ai->parent->palette[pix * 3], 3);
798
799                         // convert to 16 bit
800                         bm_24_to_16(bit_24, &bit_16);
801                 }
802         }
803
804         // stuff the pixel
805         switch(bpp){
806         case 16 :
807                 memcpy(data, &bit_16, sizeof(ushort));
808                 return sizeof(ushort);
809
810         case 8 :
811                 *data = bit_8;          
812                 return sizeof(ubyte);   
813         }
814
815         Int3();
816         return 0;
817 }
818
819 // unpack a pixel given the passed index and the anim_instance's palette, return bytes stuffed
820 int unpack_pixel_count(anim_instance *ai, ubyte *data, ubyte pix, int count, int aabitmap, int bpp)
821 {
822         int bit_24;
823         int idx;
824         ubyte al = 0;
825         ushort bit_16 = 0;      
826         ubyte bit_8 = 0;
827         anim *a = ai->parent;
828         ubyte r, g, b;
829         Assert(a);      
830
831         // if this is an aabitmap, don't run through the palette
832         if(aabitmap){
833                 switch(bpp){
834                 case 16 : 
835                         bit_16 = (ushort)pix;
836                         break;
837                 case 8 :
838                         bit_8 = pix;
839                         break;
840                 default :
841                         Int3();                 
842                 }
843         } else {                
844                 // if the pixel value is 255, or is the xparent color, make it so               
845                 if(((a->palette[pix*3] == a->xparent_r) && (a->palette[pix*3+1] == a->xparent_g) && (a->palette[pix*3+2] == a->xparent_b)) ){
846                         r = b = 0;
847                         g = 255;
848                         bm_set_components((ubyte*)&bit_16, &r, &g, &b, &al);
849                 } else {
850                         // stuff the 24 bit value
851                         memcpy(&bit_24, &ai->parent->palette[pix * 3], 3);
852
853                         // convert to 16 bit
854                         bm_24_to_16(bit_24, &bit_16);
855                 }
856         }
857         
858         // stuff the pixel
859         for(idx=0; idx<count; idx++){
860                 switch(bpp){
861                 case 16 :
862                         memcpy(data + (idx*2), &bit_16, sizeof(ushort));
863                         break;
864                 case 8 :
865                         *(data + idx) = bit_8;
866                         break;
867                 }
868         }
869
870         if(bpp == 16){
871                 return sizeof(ushort) * count;
872         }
873         return sizeof(ubyte) * count;
874 }
875
876 // ptr = packed data to unpack
877 // frame = where to store unpacked data to
878 // size = total number of unpacked pixels requested
879 // pal_translate = color translation lookup table (NULL if no palette translation desired)
880 ubyte   *unpack_frame(anim_instance *ai, ubyte *ptr, ubyte *frame, int size, ubyte *pal_translate, int aabitmap, int bpp)
881 {
882         int     xlate_pal, value, count = 0;
883         int stuffed;                    
884         int pixel_size = (bpp == 16) ? 2 : 1;
885
886         if ( pal_translate == NULL ) {
887                 xlate_pal = 0;
888         }
889         else {
890                 xlate_pal = 1;
891         }
892
893         if (*ptr == PACKING_METHOD_RLE_KEY) {  // key frame, Hoffoss's RLE format
894                 ptr++;
895                 while (size > 0) {
896                         value = *ptr++;
897                         if (value != packer_code) {
898                                 if ( xlate_pal ){
899                                         stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
900                                 } else {
901                                         stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
902                                 }
903                                 frame += stuffed;
904                                 size--;
905                         } else {
906                                 count = *ptr++;
907                                 if (count < 2){
908                                         value = packer_code;
909                                 } else {
910                                         value = *ptr++;
911                                 }
912
913                                 if (++count > size){
914                                         count = size;
915                                 }
916
917                                 if ( xlate_pal ){
918                                         stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
919                                 } else {                                        
920                                         stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
921                                 }
922
923                                 frame += stuffed;
924                                 size -= count;
925                         }
926                 }
927         }
928         else if ( *ptr == PACKING_METHOD_STD_RLE_KEY) { // key frame, with high bit as count
929                 ptr++;
930                 while (size > 0) {
931                         value = *ptr++;
932                         if ( !(value & STD_RLE_CODE) ) {
933                                 if ( xlate_pal ){
934                                         stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
935                                 } else {
936                                         stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
937                                 }
938
939                                 frame += stuffed;
940                                 size--;
941                         } else {
942                                 count = value & (~STD_RLE_CODE);
943                                 value = *ptr++;
944
945                                 size -= count;
946                                 Assert(size >= 0);
947
948                                 if ( xlate_pal ){
949                                         stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
950                                 } else {
951                                         stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
952                                 }
953
954                                 frame += stuffed;
955                         }
956                 }
957         }
958         else if (*ptr == PACKING_METHOD_RLE) {  // normal frame, Hoffoss's RLE format
959
960 // test code, to show unused pixels
961 // memset(frame, 255, size);
962         
963                 ptr++;
964                 while (size > 0) {
965                         value = *ptr++;
966                         if (value != packer_code) {
967                                 if (value != transparent_code) {
968                                         if ( xlate_pal ){
969                                                 stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
970                                         } else {
971                                                 stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
972                                         }
973                                 } else {
974                                         // temporary pixel
975                                         stuffed = pixel_size;
976                                 }
977
978                                 frame += stuffed;
979                                 size--;
980                         } else {
981                                 count = *ptr++;
982                                 if (count < 2){
983                                         value = packer_code;
984                                 } else {
985                                         value = *ptr++;
986                                 }
987
988                                 if (++count > size){
989                                         count = size;
990                                 }
991
992                                 size -= count;
993                                 Assert(size >= 0);
994
995                                 if (value != transparent_code ) {
996                                         if ( xlate_pal ) {
997                                                 stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
998                                         } else {
999                                                 stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
1000                                         }
1001                                 } else {
1002                                         stuffed = count * pixel_size;
1003                                 }
1004
1005                                 frame += stuffed;
1006                         }
1007                 }
1008
1009         }
1010         else if ( *ptr == PACKING_METHOD_STD_RLE) {     // normal frame, with high bit as count
1011                 ptr++;
1012                 while (size > 0) {
1013                         value = *ptr++;
1014                         if ( !(value & STD_RLE_CODE) ) {
1015                                 if (value != transparent_code) {
1016                                         if ( xlate_pal ){
1017                                                 stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
1018                                         } else {
1019                                                 stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
1020                                         }
1021                                 } else {
1022                                         stuffed = pixel_size;
1023                                 }
1024
1025                                 frame += stuffed;
1026                                 size--;
1027                         } else {
1028                                 count = value & (~STD_RLE_CODE);
1029                                 value = *ptr++;
1030
1031                                 size -= count;
1032                                 Assert(size >= 0);
1033
1034                                 if (value != transparent_code) {
1035                                         if ( xlate_pal ){
1036                                                 stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
1037                                         } else {
1038                                                 stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
1039                                         }
1040                                 } else {                                        
1041                                         stuffed = pixel_size * count;
1042                                 }
1043
1044                                 frame += stuffed;
1045                         }
1046                 }
1047         }
1048         else {
1049                 Assert(0);  // unknown packing method
1050         }
1051
1052         return ptr;
1053 }
1054
1055 // ptr = packed data to unpack
1056 // frame = where to store unpacked data to
1057 // size = total number of unpacked pixels requested
1058 // pal_translate = color translation lookup table (NULL if no palette translation desired)
1059 int unpack_frame_from_file(anim_instance *ai, ubyte *frame, int size, ubyte *pal_translate, int aabitmap, int bpp)
1060 {
1061         int     xlate_pal, value, count = 0;
1062         int     offset = 0;
1063         int stuffed;    
1064         int pixel_size = (bpp == 16) ? 2 : 1;
1065
1066         if ( pal_translate == NULL ) {
1067                 xlate_pal = 0;
1068         }
1069         else {
1070                 xlate_pal = 1;
1071         }
1072
1073         if (anim_instance_get_byte(ai,offset) == PACKING_METHOD_RLE_KEY) {  // key frame, Hoffoss's RLE format
1074                 offset++;
1075                 while (size > 0) {
1076                         value = anim_instance_get_byte(ai,offset);
1077                         offset++;
1078                         if (value != packer_code) {
1079                                 if ( xlate_pal ){
1080                                         stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
1081                                 } else {
1082                                         stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
1083                                 }
1084
1085                                 frame += stuffed;
1086                                 size--;
1087                         } else {
1088                                 count = anim_instance_get_byte(ai,offset);
1089                                 offset++;
1090                                 if (count < 2) {
1091                                         value = packer_code;
1092                                 } else {
1093                                         value = anim_instance_get_byte(ai,offset);
1094                                         offset++;
1095                                 }
1096
1097                                 if (++count > size){
1098                                         count = size;
1099                                 }
1100
1101                                 if ( xlate_pal ){
1102                                         stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
1103                                 } else {
1104                                         stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
1105                                 }
1106
1107                                 frame += stuffed;
1108                                 size -= count;
1109                         }
1110                 }
1111         }
1112         else if ( anim_instance_get_byte(ai,offset) == PACKING_METHOD_STD_RLE_KEY) {    // key frame, with high bit as count
1113                 offset++;
1114                 while (size > 0) {
1115                         value = anim_instance_get_byte(ai,offset);
1116                         offset++;
1117                         if ( !(value & STD_RLE_CODE) ) {
1118                                 if ( xlate_pal ){
1119                                         stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
1120                                 } else {
1121                                         stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
1122                                 }
1123
1124                                 frame += stuffed;
1125                                 size--;
1126                         } else {
1127                                 count = value & (~STD_RLE_CODE);
1128                                 value = anim_instance_get_byte(ai,offset);
1129                                 offset++;
1130
1131                                 size -= count;
1132                                 Assert(size >= 0);
1133
1134                                 if ( xlate_pal ){
1135                                         stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
1136                                 } else {
1137                                         stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
1138                                 }
1139
1140                                 frame += stuffed;
1141                         }
1142                 }
1143         }
1144         else if (anim_instance_get_byte(ai,offset) == PACKING_METHOD_RLE) {  // normal frame, Hoffoss's RLE format
1145
1146 // test code, to show unused pixels
1147 // memset(frame, 255, size);
1148         
1149                 offset++;
1150                 while (size > 0) {
1151                         value = anim_instance_get_byte(ai,offset);
1152                         offset++;
1153                         if (value != packer_code) {
1154                                 if (value != transparent_code) {
1155                                         if ( xlate_pal ){
1156                                                 stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
1157                                         } else {
1158                                                 stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
1159                                         }
1160                                 } else {
1161                                         stuffed = pixel_size;
1162                                 }
1163
1164                                 frame += stuffed;
1165                                 size--;
1166                         } else {
1167                                 count = anim_instance_get_byte(ai,offset);
1168                                 offset++;
1169
1170                                 if (count < 2) {
1171                                         value = packer_code;
1172                                 } else {
1173                                         value = anim_instance_get_byte(ai,offset);
1174                                         offset++;
1175                                 }
1176                                 if (++count > size){
1177                                         count = size;
1178                                 }
1179
1180                                 size -= count;
1181                                 Assert(size >= 0);
1182
1183                                 if (value != transparent_code ) {
1184                                         if ( xlate_pal ) {
1185                                                 stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
1186                                         } else {
1187                                                 stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
1188                                         }
1189                                 } else {
1190                                         stuffed = pixel_size * count;
1191                                 }
1192
1193                                 frame += stuffed;
1194                         }
1195                 }
1196
1197         }
1198         else if ( anim_instance_get_byte(ai,offset) ) { // normal frame, with high bit as count
1199                 offset++;
1200                 while (size > 0) {
1201                         value = anim_instance_get_byte(ai,offset);
1202                         offset++;
1203                         if ( !(value & STD_RLE_CODE) ) {
1204                                 if (value != transparent_code) {
1205                                         if ( xlate_pal ){
1206                                                 stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
1207                                         } else {
1208                                                 stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
1209                                         }
1210                                 } else {
1211                                         stuffed = pixel_size;
1212                                 }
1213
1214                                 frame += stuffed;
1215                                 size--;
1216                         } else {
1217                                 count = value & (~STD_RLE_CODE);
1218                                 value = anim_instance_get_byte(ai,offset);
1219                                 offset++;
1220
1221                                 size -= count;
1222                                 Assert(size >= 0);
1223
1224                                 if (value != transparent_code) {
1225                                         if ( xlate_pal ){
1226                                                 stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
1227                                         } else {
1228                                                 stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
1229                                         }
1230                                 } else {                                        
1231                                         stuffed = pixel_size * count;
1232                                 }
1233
1234                                 frame += stuffed;
1235                         }
1236                 }
1237         }
1238         else {
1239                 Int3();  // unknown packing method
1240         }
1241
1242         return ai->file_offset + offset;
1243 }
1244
1245
1246 // TODO: actually convert the frame data to correct palette at this point
1247 void anim_set_palette(anim *ptr)
1248 {
1249         int i, xparent_found = 0;
1250         
1251         // create the palette translation look-up table
1252         for ( i = 0; i < 256; i++ ) {
1253
1254                 //if ( (ptr->palette[i*3] == ptr->xparent_r) && (ptr->palette[i*3+1] == ptr->xparent_g) && (ptr->palette[i*3+2] == ptr->xparent_b) ) {
1255                 //      ptr->palette_translation[i] = 255;
1256                 //      xparent_found = 1;
1257                 //} else        {
1258                         // ptr->palette_translation[i] = (ubyte)palette_find( ptr->palette[i*3], ptr->palette[i*3+1], ptr->palette[i*3+2] );
1259                         ptr->palette_translation[i] = (ubyte)i;
1260                 //}
1261         }       
1262
1263         if ( xparent_found ) {
1264                 ptr->flags |= ANF_XPARENT;
1265         }
1266         else {
1267                 ptr->flags &= ~ANF_XPARENT;
1268         }
1269 }
1270