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