]> icculus.org git repositories - taylor/freespace2.git/blob - src/anim/packunpack.cpp
fix memory leak and properly initialize some structs
[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 #ifndef NDEBUG
532                         ubyte *dest_start = save;
533 #endif
534                         int i;
535
536                         count = 1;
537
538                         last = *frame++;
539                         *save++ = PACKING_METHOD_STD_RLE_KEY;
540                         for (i=1; i < size; i++ )       {
541
542                                 if ( *frame != last ) {
543                                         if ( count ) {
544
545                                                 if (packed_size + 2 >= max)
546                                                         return -1;
547
548                                                 if ( (count == 1) && !(last & STD_RLE_CODE) ) {
549                                                         *save++ = (ubyte)last;
550                                                         packed_size++;
551                                                         SDL_assert( last != STD_RLE_CODE );
552 //                                                      printf("Just packed %d 1 times, since pixel change, no count included\n",last);
553                                                 }
554                                                 else {
555                                                         count |= STD_RLE_CODE;
556                                                         *save++ = (ubyte)count;
557                                                         *save++ = (ubyte)last;
558                                                         packed_size += 2;
559 //                                                      printf("Just packed %d %d times, since pixel change\n",last,count);
560                                                 }
561                                         }
562                 
563                                         last = *frame;
564                                         count = 0;
565                                 }
566
567                                 count++;
568                                 frame++;
569
570                                 if ( count == 127 ) {
571                                         count |= STD_RLE_CODE;
572                                         *save++ = (ubyte)count;
573                                         *save++ = (ubyte)last;
574                                         packed_size += 2;
575                                         count = 0;
576 //                                      printf("Just packed %d %d times, since count overflow\n",last,count);
577
578                                 }
579                         }       // end for
580
581                         if (count)      {
582
583                                 if (packed_size + 2 >= max)
584                                         return -1;
585
586                                 if ( (count == 1) && !(last & STD_RLE_CODE) ) {
587                                         *save++ = (ubyte)last;
588                                         packed_size++;
589 //                                      printf("Just packed %d 1 times, at end since single pixel, no count\n",last);
590                                         SDL_assert( last != STD_RLE_CODE );
591                                 }
592                                 else {
593                                         count |= STD_RLE_CODE;
594                                         *save++ = (ubyte)count;
595                                         *save++ = (ubyte)last;
596                                         packed_size += 2;
597 //                                      printf("Just packed %d %d times, at end since pixel change\n",last,count);
598                                 }
599                         }
600 #ifndef NDEBUG
601                         SDL_assert(packed_size == (save-dest_start) );
602 #endif
603                         return packed_size;
604                         break;
605                         }
606
607                 default:
608                         SDL_assert(0);
609                         return -1;
610                         break;
611         } // end switch
612
613         return packed_size;
614 }
615
616 // frame = frame pixel data to pack
617 // frame2 = previous frame's pixel data
618 // save = memory to store packed data to
619 // size = number of bytes to pack
620 // max = maximum number of packed bytes (size of buffer)
621 // returns: actual number of bytes data packed to or -1 if error
622 int pack_frame(ubyte *frame, ubyte *frame2, ubyte *save, long size, long max, int compress_type)
623 {
624         int pixel, last = -32768, count = 0, i;
625         long packed_size = 1;
626
627         switch ( compress_type ) {
628                 case PACKING_METHOD_RLE:                                        // Hoffoss RLE regular frame
629                         *save++ = PACKING_METHOD_RLE;
630                         while (size--) {
631                                 if (*frame != *frame2++)
632                                         pixel = *frame;
633                                 else
634                                         pixel = transparent_code;
635
636                                 if (pixel != last || count > 255) {
637                                         if (packed_size + 3 >= max)
638                                                 return -1;
639
640                                         if (count < 3) {
641                                                 if (last == packer_code) {
642                                                         *save++ = (ubyte)packer_code;
643                                                         *save++ = (ubyte)(count - 1);
644                                                         packed_size += 2;
645
646                                                 } else
647                                                         while (count--) {
648                                                                 *save++ = (ubyte)last;
649                                                                 packed_size++;
650                                                         }
651
652                                         } else {
653                                                 *save++ = (ubyte)packer_code;
654                                                 *save++ = (ubyte)(count - 1);
655                                                 *save++ = (ubyte)last;
656                                                 packed_size += 3;
657                                         }
658
659                                         count = 0;
660                                         last = pixel;
661                                 }
662
663                                 frame++;
664                                 count++;
665                         }
666
667                         if (packed_size + 3 >= max)
668                                 return -1;
669
670                         if (count < 3) {
671                                 if (last == packer_code) {
672                                         *save++ = (ubyte)packer_code;
673                                         *save++ = (ubyte)(count - 1);
674                                         packed_size += 2;
675
676                                 } else
677                                         while (count--) {
678                                                 *save++ = (ubyte)last;
679                                                 packed_size++;
680                                         }
681
682                         } else {
683                                 *save++ = (ubyte)(packer_code);
684                                 *save++ = (ubyte)(count - 1);
685                                 *save++ = (ubyte)(last);
686                                 packed_size += 3;
687                         }
688                         break;
689
690                 case PACKING_METHOD_STD_RLE: {          // high bit count regular RLE frame
691 #ifndef NDEBUG
692                         ubyte *dest_start = save;
693 #endif
694
695                         count = 1;
696
697                         if (*frame++ != *frame2++)
698                                 last = *frame;
699                         else
700                                 last = transparent_code;
701
702                         *save++ = PACKING_METHOD_STD_RLE;
703                         for (i=1; i < size; i++ )       {
704
705                                 if (*frame != *frame2++)
706                                         pixel = *frame;
707                                 else
708                                         pixel = transparent_code;
709
710                                 if ( pixel != last ) {
711                                         if ( count ) {
712
713                                                 if (packed_size + 2 >= max)
714                                                         return -1;
715
716                                                 if ( (count == 1) && !(last & STD_RLE_CODE) ) {
717                                                         *save++ = (ubyte)last;
718                                                         packed_size++;
719                                                         SDL_assert( last != STD_RLE_CODE );
720                                                 }
721                                                 else {
722                                                         count |= STD_RLE_CODE;
723                                                         *save++ = (ubyte)count;
724                                                         *save++ = (ubyte)last;
725                                                         packed_size += 2;
726                                                 }
727                                         }
728                 
729                                         last = pixel;
730                                         count = 0;
731                                 }
732
733                                 count++;
734                                 frame++;
735
736                                 if ( count == 127 ) {
737                                         count |= STD_RLE_CODE;
738                                         *save++ = (ubyte)count;
739                                         *save++ = (ubyte)last;
740                                         packed_size += 2;
741                                         count = 0;
742                                 }
743                         }       // end for
744
745                         if (count)      {
746
747                                 if (packed_size + 2 >= max)
748                                         return -1;
749
750                                 if ( (count == 1) && !(last & STD_RLE_CODE) ) {
751                                         *save++ = (ubyte)last;
752                                         packed_size++;
753                                         SDL_assert( last != STD_RLE_CODE );
754                                 }
755                                 else {
756                                         count |= STD_RLE_CODE;
757                                         *save++ = (ubyte)count;
758                                         *save++ = (ubyte)last;
759                                         packed_size += 2;
760                                 }
761                         }
762 #ifndef NDEBUG
763                         SDL_assert(packed_size == (save-dest_start) );
764 #endif
765                         return packed_size;
766                         break;
767                         }
768
769                 default:
770                         SDL_assert(0);
771                         return -1;
772                         break;
773         } // end switch
774
775         return packed_size;
776 }
777
778 // unpack a pixel given the passed index and the anim_instance's palette, return bytes stuffed
779 int unpack_pixel(anim_instance *ai, ubyte *data, ubyte pix, int aabitmap, int bpp)
780 {
781         int bit_24;
782         ushort bit_16 = 0;      
783         ubyte bit_8 = 0;
784         ubyte al = 0;
785         ubyte r, g, b;
786         anim *a = ai->parent;
787         SDL_assert(a);  
788
789         // if this is an aabitmap, don't run through the palette
790         if(aabitmap){
791                 switch(bpp){
792                 case 16 : 
793                         bit_16 = (ushort)pix;
794                         break;
795                 case 8:
796                         bit_8 = pix;
797                         break;
798                 default:
799                         Int3();
800                 }
801         } else {                
802                 // if the pixel value is 255, or is the xparent color, make it so               
803                 if(((a->palette[pix*3] == a->xparent_r) && (a->palette[pix*3+1] == a->xparent_g) && (a->palette[pix*3+2] == a->xparent_b)) ){
804                         r = b = 0;
805                         g = 255;
806                         bm_set_components((ubyte*)&bit_16, &r, &g, &b, &al);
807                 } else {
808                         // stuff the 24 bit value
809                         memcpy(&bit_24, &ai->parent->palette[pix * 3], 3);
810
811                         // convert to 16 bit
812                         bm_24_to_16(bit_24, &bit_16);
813                 }
814         }
815
816         // stuff the pixel
817         switch(bpp){
818         case 16 :
819                 memcpy(data, &bit_16, sizeof(ushort));
820                 return sizeof(ushort);
821
822         case 8 :
823                 *data = bit_8;          
824                 return sizeof(ubyte);   
825         }
826
827         Int3();
828         return 0;
829 }
830
831 // unpack a pixel given the passed index and the anim_instance's palette, return bytes stuffed
832 int unpack_pixel_count(anim_instance *ai, ubyte *data, ubyte pix, int count, int aabitmap, int bpp)
833 {
834         int bit_24;
835         int idx;
836         ubyte al = 0;
837         ushort bit_16 = 0;      
838         ubyte bit_8 = 0;
839         anim *a = ai->parent;
840         ubyte r, g, b;
841         SDL_assert(a);  
842
843         // if this is an aabitmap, don't run through the palette
844         if(aabitmap){
845                 switch(bpp){
846                 case 16 : 
847                         bit_16 = (ushort)pix;
848                         break;
849                 case 8 :
850                         bit_8 = pix;
851                         break;
852                 default :
853                         Int3();                 
854                 }
855         } else {                
856                 // if the pixel value is 255, or is the xparent color, make it so               
857                 if(((a->palette[pix*3] == a->xparent_r) && (a->palette[pix*3+1] == a->xparent_g) && (a->palette[pix*3+2] == a->xparent_b)) ){
858                         r = b = 0;
859                         g = 255;
860                         bm_set_components((ubyte*)&bit_16, &r, &g, &b, &al);
861                 } else {
862                         // stuff the 24 bit value
863                         memcpy(&bit_24, &ai->parent->palette[pix * 3], 3);
864
865                         // convert to 16 bit
866                         bm_24_to_16(bit_24, &bit_16);
867                 }
868         }
869         
870         // stuff the pixel
871         for(idx=0; idx<count; idx++){
872                 switch(bpp){
873                 case 16 :
874                         memcpy(data + (idx*2), &bit_16, sizeof(ushort));
875                         break;
876                 case 8 :
877                         *(data + idx) = bit_8;
878                         break;
879                 }
880         }
881
882         if(bpp == 16){
883                 return sizeof(ushort) * count;
884         }
885         return sizeof(ubyte) * count;
886 }
887
888 // ptr = packed data to unpack
889 // frame = where to store unpacked data to
890 // size = total number of unpacked pixels requested
891 // pal_translate = color translation lookup table (NULL if no palette translation desired)
892 ubyte   *unpack_frame(anim_instance *ai, ubyte *ptr, ubyte *frame, int size, ubyte *pal_translate, int aabitmap, int bpp)
893 {
894         int     xlate_pal, value, count = 0;
895         int stuffed;                    
896         int pixel_size = (bpp == 16) ? 2 : 1;
897
898         if ( pal_translate == NULL ) {
899                 xlate_pal = 0;
900         }
901         else {
902                 xlate_pal = 1;
903         }
904
905         if (*ptr == PACKING_METHOD_RLE_KEY) {  // key frame, Hoffoss's RLE format
906                 ptr++;
907                 while (size > 0) {
908                         value = *ptr++;
909                         if (value != packer_code) {
910                                 if ( xlate_pal ){
911                                         stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
912                                 } else {
913                                         stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
914                                 }
915                                 frame += stuffed;
916                                 size--;
917                         } else {
918                                 count = *ptr++;
919                                 if (count < 2){
920                                         value = packer_code;
921                                 } else {
922                                         value = *ptr++;
923                                 }
924
925                                 if (++count > size){
926                                         count = size;
927                                 }
928
929                                 if ( xlate_pal ){
930                                         stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
931                                 } else {                                        
932                                         stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
933                                 }
934
935                                 frame += stuffed;
936                                 size -= count;
937                         }
938                 }
939         }
940         else if ( *ptr == PACKING_METHOD_STD_RLE_KEY) { // key frame, with high bit as count
941                 ptr++;
942                 while (size > 0) {
943                         value = *ptr++;
944                         if ( !(value & STD_RLE_CODE) ) {
945                                 if ( xlate_pal ){
946                                         stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
947                                 } else {
948                                         stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
949                                 }
950
951                                 frame += stuffed;
952                                 size--;
953                         } else {
954                                 count = value & (~STD_RLE_CODE);
955                                 value = *ptr++;
956
957                                 size -= count;
958                                 SDL_assert(size >= 0);
959
960                                 if ( xlate_pal ){
961                                         stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
962                                 } else {
963                                         stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
964                                 }
965
966                                 frame += stuffed;
967                         }
968                 }
969         }
970         else if (*ptr == PACKING_METHOD_RLE) {  // normal frame, Hoffoss's RLE format
971
972 // test code, to show unused pixels
973 // memset(frame, 255, size);
974         
975                 ptr++;
976                 while (size > 0) {
977                         value = *ptr++;
978                         if (value != packer_code) {
979                                 if (value != transparent_code) {
980                                         if ( xlate_pal ){
981                                                 stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
982                                         } else {
983                                                 stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
984                                         }
985                                 } else {
986                                         // temporary pixel
987                                         stuffed = pixel_size;
988                                 }
989
990                                 frame += stuffed;
991                                 size--;
992                         } else {
993                                 count = *ptr++;
994                                 if (count < 2){
995                                         value = packer_code;
996                                 } else {
997                                         value = *ptr++;
998                                 }
999
1000                                 if (++count > size){
1001                                         count = size;
1002                                 }
1003
1004                                 size -= count;
1005                                 SDL_assert(size >= 0);
1006
1007                                 if (value != transparent_code ) {
1008                                         if ( xlate_pal ) {
1009                                                 stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
1010                                         } else {
1011                                                 stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
1012                                         }
1013                                 } else {
1014                                         stuffed = count * pixel_size;
1015                                 }
1016
1017                                 frame += stuffed;
1018                         }
1019                 }
1020
1021         }
1022         else if ( *ptr == PACKING_METHOD_STD_RLE) {     // normal frame, with high bit as count
1023                 ptr++;
1024                 while (size > 0) {
1025                         value = *ptr++;
1026                         if ( !(value & STD_RLE_CODE) ) {
1027                                 if (value != transparent_code) {
1028                                         if ( xlate_pal ){
1029                                                 stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
1030                                         } else {
1031                                                 stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
1032                                         }
1033                                 } else {
1034                                         stuffed = pixel_size;
1035                                 }
1036
1037                                 frame += stuffed;
1038                                 size--;
1039                         } else {
1040                                 count = value & (~STD_RLE_CODE);
1041                                 value = *ptr++;
1042
1043                                 size -= count;
1044                                 SDL_assert(size >= 0);
1045
1046                                 if (value != transparent_code) {
1047                                         if ( xlate_pal ){
1048                                                 stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
1049                                         } else {
1050                                                 stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
1051                                         }
1052                                 } else {                                        
1053                                         stuffed = pixel_size * count;
1054                                 }
1055
1056                                 frame += stuffed;
1057                         }
1058                 }
1059         }
1060         else {
1061                 SDL_assert(0);  // unknown packing method
1062         }
1063
1064         return ptr;
1065 }
1066
1067 // ptr = packed data to unpack
1068 // frame = where to store unpacked data to
1069 // size = total number of unpacked pixels requested
1070 // pal_translate = color translation lookup table (NULL if no palette translation desired)
1071 int unpack_frame_from_file(anim_instance *ai, ubyte *frame, int size, ubyte *pal_translate, int aabitmap, int bpp)
1072 {
1073         int     xlate_pal, value, count = 0;
1074         int     offset = 0;
1075         int stuffed;    
1076         int pixel_size = (bpp == 16) ? 2 : 1;
1077
1078         if ( pal_translate == NULL ) {
1079                 xlate_pal = 0;
1080         }
1081         else {
1082                 xlate_pal = 1;
1083         }
1084
1085         if (anim_instance_get_byte(ai,offset) == PACKING_METHOD_RLE_KEY) {  // key frame, Hoffoss's RLE format
1086                 offset++;
1087                 while (size > 0) {
1088                         value = anim_instance_get_byte(ai,offset);
1089                         offset++;
1090                         if (value != packer_code) {
1091                                 if ( xlate_pal ){
1092                                         stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
1093                                 } else {
1094                                         stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
1095                                 }
1096
1097                                 frame += stuffed;
1098                                 size--;
1099                         } else {
1100                                 count = anim_instance_get_byte(ai,offset);
1101                                 offset++;
1102                                 if (count < 2) {
1103                                         value = packer_code;
1104                                 } else {
1105                                         value = anim_instance_get_byte(ai,offset);
1106                                         offset++;
1107                                 }
1108
1109                                 if (++count > size){
1110                                         count = size;
1111                                 }
1112
1113                                 if ( xlate_pal ){
1114                                         stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
1115                                 } else {
1116                                         stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
1117                                 }
1118
1119                                 frame += stuffed;
1120                                 size -= count;
1121                         }
1122                 }
1123         }
1124         else if ( anim_instance_get_byte(ai,offset) == PACKING_METHOD_STD_RLE_KEY) {    // key frame, with high bit as count
1125                 offset++;
1126                 while (size > 0) {
1127                         value = anim_instance_get_byte(ai,offset);
1128                         offset++;
1129                         if ( !(value & STD_RLE_CODE) ) {
1130                                 if ( xlate_pal ){
1131                                         stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
1132                                 } else {
1133                                         stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
1134                                 }
1135
1136                                 frame += stuffed;
1137                                 size--;
1138                         } else {
1139                                 count = value & (~STD_RLE_CODE);
1140                                 value = anim_instance_get_byte(ai,offset);
1141                                 offset++;
1142
1143                                 size -= count;
1144                                 SDL_assert(size >= 0);
1145
1146                                 if ( xlate_pal ){
1147                                         stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
1148                                 } else {
1149                                         stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
1150                                 }
1151
1152                                 frame += stuffed;
1153                         }
1154                 }
1155         }
1156         else if (anim_instance_get_byte(ai,offset) == PACKING_METHOD_RLE) {  // normal frame, Hoffoss's RLE format
1157
1158 // test code, to show unused pixels
1159 // memset(frame, 255, size);
1160         
1161                 offset++;
1162                 while (size > 0) {
1163                         value = anim_instance_get_byte(ai,offset);
1164                         offset++;
1165                         if (value != packer_code) {
1166                                 if (value != transparent_code) {
1167                                         if ( xlate_pal ){
1168                                                 stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
1169                                         } else {
1170                                                 stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
1171                                         }
1172                                 } else {
1173                                         stuffed = pixel_size;
1174                                 }
1175
1176                                 frame += stuffed;
1177                                 size--;
1178                         } else {
1179                                 count = anim_instance_get_byte(ai,offset);
1180                                 offset++;
1181
1182                                 if (count < 2) {
1183                                         value = packer_code;
1184                                 } else {
1185                                         value = anim_instance_get_byte(ai,offset);
1186                                         offset++;
1187                                 }
1188                                 if (++count > size){
1189                                         count = size;
1190                                 }
1191
1192                                 size -= count;
1193                                 SDL_assert(size >= 0);
1194
1195                                 if (value != transparent_code ) {
1196                                         if ( xlate_pal ) {
1197                                                 stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
1198                                         } else {
1199                                                 stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
1200                                         }
1201                                 } else {
1202                                         stuffed = pixel_size * count;
1203                                 }
1204
1205                                 frame += stuffed;
1206                         }
1207                 }
1208
1209         }
1210         else if ( anim_instance_get_byte(ai,offset) ) { // normal frame, with high bit as count
1211                 offset++;
1212                 while (size > 0) {
1213                         value = anim_instance_get_byte(ai,offset);
1214                         offset++;
1215                         if ( !(value & STD_RLE_CODE) ) {
1216                                 if (value != transparent_code) {
1217                                         if ( xlate_pal ){
1218                                                 stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
1219                                         } else {
1220                                                 stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
1221                                         }
1222                                 } else {
1223                                         stuffed = pixel_size;
1224                                 }
1225
1226                                 frame += stuffed;
1227                                 size--;
1228                         } else {
1229                                 count = value & (~STD_RLE_CODE);
1230                                 value = anim_instance_get_byte(ai,offset);
1231                                 offset++;
1232
1233                                 size -= count;
1234                                 SDL_assert(size >= 0);
1235
1236                                 if (value != transparent_code) {
1237                                         if ( xlate_pal ){
1238                                                 stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
1239                                         } else {
1240                                                 stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
1241                                         }
1242                                 } else {                                        
1243                                         stuffed = pixel_size * count;
1244                                 }
1245
1246                                 frame += stuffed;
1247                         }
1248                 }
1249         }
1250         else {
1251                 Int3();  // unknown packing method
1252         }
1253
1254         return ai->file_offset + offset;
1255 }
1256
1257
1258 // TODO: actually convert the frame data to correct palette at this point
1259 void anim_set_palette(anim *ptr)
1260 {
1261         int i, xparent_found = 0;
1262         
1263         // create the palette translation look-up table
1264         for ( i = 0; i < 256; i++ ) {
1265
1266                 //if ( (ptr->palette[i*3] == ptr->xparent_r) && (ptr->palette[i*3+1] == ptr->xparent_g) && (ptr->palette[i*3+2] == ptr->xparent_b) ) {
1267                 //      ptr->palette_translation[i] = 255;
1268                 //      xparent_found = 1;
1269                 //} else        {
1270                         // ptr->palette_translation[i] = (ubyte)palette_find( ptr->palette[i*3], ptr->palette[i*3+1], ptr->palette[i*3+2] );
1271                         ptr->palette_translation[i] = (ubyte)i;
1272                 //}
1273         }       
1274
1275         if ( xparent_found ) {
1276                 ptr->flags |= ANF_XPARENT;
1277         }
1278         else {
1279                 ptr->flags &= ~ANF_XPARENT;
1280         }
1281 }
1282