]> icculus.org git repositories - taylor/freespace2.git/blob - src/anim/packunpack.cpp
get rid of some platform specific stuff
[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         if(Gr_bitmap_poly){
264                 BM_SELECT_TEX_FORMAT();
265         }
266
267         if ( anim_instance_is_streamed(inst) ) {
268                 inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation, aabitmap, bpp);
269         } else {
270                 inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation, aabitmap, bpp);
271         }
272
273         bm = bm_create(bpp, inst->parent->width, inst->parent->height, inst->frame, bitmap_flags);
274         bm_unload(bm);
275         return bm;
276 }
277
278 ubyte *anim_get_next_raw_buffer(anim_instance *inst, int xlate_pal, int aabitmap, int bpp)
279 {       
280         if ( anim_instance_is_streamed(inst) ) {
281                 if ( inst->file_offset < 0 ) {
282                         return NULL;
283                 }
284         } else {
285                 if (!inst->data){
286                         return NULL;
287                 }
288         }
289
290         inst->frame_num++;
291         if (inst->frame_num >= inst->parent->total_frames) {
292                 inst->data = NULL;
293                 inst->file_offset = inst->parent->file_offset;
294                 return NULL;
295         }
296
297         anim_check_for_palette_change(inst);
298
299         if ( anim_instance_is_streamed(inst) ) {
300                 if ( xlate_pal ){
301                         inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation, aabitmap, bpp);
302                 } else {
303                         inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, NULL, aabitmap, bpp);
304                 }
305         } else {
306                 if ( xlate_pal ){
307                         inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation, aabitmap, bpp);
308                 } else {
309                         inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, NULL, aabitmap, bpp);
310                 }
311         }
312
313         return inst->frame;
314 }
315
316 // --------------------------------------------------------------------
317 // anim_get_frame()
318 //
319 // Get a bitmap id from the anim_instance for the specified frame_num
320 //
321 //      input:  *inst                   =>              pointer to anim instance
322 //                              frame_num       =>              frame number to get (first frame is 0)
323 //                              xlate_pal       =>              DEFAULT PARM (value 1): whether to translate the palette
324 //                                                                              to the current game palette
325 //
326 int anim_get_frame(anim_instance *inst, int frame_num, int xlate_pal)
327 {
328         /*
329         int                     bm, bitmap_flags, key = 0, offset = 0;
330         int idx;
331
332         if ((frame_num < 0) || (frame_num >= inst->parent->total_frames))  // illegal frame number
333                 return -1;
334
335         int need_reset = 0;
336         if ( anim_instance_is_streamed(inst) ) {
337                 if ( inst->file_offset < 0 ) {
338                         need_reset = 1;
339                 }
340         } else {
341                 if ( !inst->data ) {
342                         need_reset = 1;
343                 }
344         }
345
346         if (need_reset || (inst->frame_num >= inst->parent->total_frames)) {  // reset to valid info
347                 inst->data = inst->parent->data;
348                 inst->file_offset = inst->parent->file_offset;
349                 inst->frame_num = 0;
350         }
351
352         bitmap_flags = 0;
353         if (inst->parent->flags & ANF_XPARENT) {
354                 // bitmap_flags = BMP_XPARENT;
355                 bitmap_flags = 0;
356         }
357
358         if ( inst->frame_num == frame_num ) {
359                 bm = bm_create(16, inst->parent->width, inst->parent->height, inst->frame, bitmap_flags);
360                 bm_unload(bm);
361                 return bm;
362         }
363
364         if (inst->parent->flags & ANF_XPARENT){
365                 // bitmap_flags = BMP_XPARENT;
366                 bitmap_flags = 0;
367         } else {
368                 bitmap_flags = 0;
369         }
370
371         idx = 0;
372         key = 0;
373         while(idx < inst->parent->num_keys){                    
374                 if (( (inst->parent->keys[idx].frame_num-1) <= frame_num) && ( (inst->parent->keys[idx].frame_num-1) > key)) {  // find closest key
375                         key = inst->parent->keys[idx].frame_num - 1;
376                         offset = inst->parent->keys[idx].offset;
377                                 
378                         if ( key == frame_num )
379                                 break;
380                 }
381                 idx++;
382         }
383                         
384         if ( key == frame_num ) {
385                 inst->frame_num = key;
386
387                 if ( anim_instance_is_streamed(inst) ) {
388                         inst->file_offset = inst->parent->file_offset + offset;
389                 } else {
390                         inst->data = inst->parent->data + offset;
391                 }
392
393                 anim_check_for_palette_change(inst);
394
395                 if ( anim_instance_is_streamed(inst) ) {
396                         if ( xlate_pal ){
397                                 inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation);
398                         } else {
399                                 inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, NULL);
400                         }
401                 } else {
402                         if ( xlate_pal ){
403                                 inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation);
404                         } else {
405                                 inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, NULL);
406                         }
407                 }
408
409                 goto create_bitmap;
410         }
411
412         if (key > inst->frame_num)  // best key is closer than current position
413         {
414                 inst->frame_num = key;
415
416                 if ( anim_instance_is_streamed(inst) ) {
417                         inst->file_offset = inst->parent->file_offset + offset;
418                 } else {
419                         inst->data = inst->parent->data + offset;
420                 }
421
422                 anim_check_for_palette_change(inst);
423
424                 if ( anim_instance_is_streamed(inst) ) {
425                         if ( xlate_pal )
426                                 inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation);
427                         else 
428                                 inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, NULL);
429                 } else {
430                         if ( xlate_pal )
431                                 inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation);
432                         else 
433                                 inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, NULL);
434                 }
435         }
436
437         while (inst->frame_num != frame_num) {
438                 anim_check_for_palette_change(inst);
439
440                 if ( anim_instance_is_streamed(inst) ) {
441                         if ( xlate_pal )
442                                 inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation);
443                         else 
444                                 inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, NULL);
445                 } else {
446                         if ( xlate_pal )
447                                 inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation);
448                         else 
449                                 inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, NULL);
450                 }
451                 inst->frame_num++;
452         }
453
454         create_bitmap:
455
456         bm = bm_create(16, inst->parent->width, inst->parent->height, inst->frame, bitmap_flags);
457         bm_unload(bm);
458         return bm;
459   */
460         Int3();
461         return -1;
462 }
463
464 // frame = frame pixel data to pack
465 // save = memory to store packed data to
466 // size = number of bytes to pack
467 // max = maximum number of packed bytes (size of buffer)
468 // returns: actual number of bytes data packed to or -1 if error
469 int pack_key_frame(ubyte *frame, ubyte *save, long size, long max, int compress_type)
470 {
471         int last = -32768, count = 0;
472         long packed_size = 1;
473
474         switch ( compress_type ) {
475                 case PACKING_METHOD_RLE_KEY:
476                         *save++ = PACKING_METHOD_RLE_KEY;
477                         while (size--) {
478                                 if (*frame != last || count > 255) {
479                                         if (packed_size + 3 >= max)
480                                                 return -1;
481
482                                         if (count < 3) {
483                                                 if (last == packer_code) {
484                                                         *save++ = (ubyte)packer_code;
485                                                         *save++ = (ubyte)(count - 1);
486                                                         packed_size += 2;
487
488                                                 } else
489                                                         while (count--) {
490                                                                 *save++ = (ubyte)last;
491                                                                 packed_size++;
492                                                         }
493
494                                         } else {
495                                                 *save++ = (ubyte)packer_code;
496                                                 *save++ = (ubyte)(count - 1);
497                                                 *save++ = (ubyte)last;
498                                                 packed_size += 3;
499                                         }
500
501                                         count = 0;
502                                         last = *frame;
503                                 }
504
505                                 count++;
506                                 frame++;
507                         }
508
509                         if (packed_size + 3 >= max)
510                                 return -1;
511
512                         if (count < 3) {
513                                 if (last == packer_code) {
514                                         *save++ = (ubyte)packer_code;
515                                         *save++ = (ubyte)(count - 1);
516                                         packed_size += 2;
517
518                                 } else
519                                         while (count--) {
520                                                 *save++ = (ubyte)last;
521                                                 packed_size++;
522                                         }
523
524                         } else {
525                                 *save++ = (ubyte)packer_code;
526                                 *save++ = (ubyte)(count - 1);
527                                 *save++ = (ubyte)last;
528                                 packed_size += 3;
529                         }
530                         break;
531
532                 case PACKING_METHOD_STD_RLE_KEY: {
533                         ubyte *dest_start;
534                         int i;
535
536                         dest_start = save;
537                         count = 1;
538
539                         last = *frame++;
540                         *save++ = PACKING_METHOD_STD_RLE_KEY;
541                         for (i=1; i < size; i++ )       {
542
543                                 if ( *frame != last ) {
544                                         if ( count ) {
545
546                                                 if (packed_size + 2 >= max)
547                                                         return -1;
548
549                                                 if ( (count == 1) && !(last & STD_RLE_CODE) ) {
550                                                         *save++ = (ubyte)last;
551                                                         packed_size++;
552                                                         SDL_assert( last != STD_RLE_CODE );
553 //                                                      printf("Just packed %d 1 times, since pixel change, no count included\n",last);
554                                                 }
555                                                 else {
556                                                         count |= STD_RLE_CODE;
557                                                         *save++ = (ubyte)count;
558                                                         *save++ = (ubyte)last;
559                                                         packed_size += 2;
560 //                                                      printf("Just packed %d %d times, since pixel change\n",last,count);
561                                                 }
562                                         }
563                 
564                                         last = *frame;
565                                         count = 0;
566                                 }
567
568                                 count++;
569                                 frame++;
570
571                                 if ( count == 127 ) {
572                                         count |= STD_RLE_CODE;
573                                         *save++ = (ubyte)count;
574                                         *save++ = (ubyte)last;
575                                         packed_size += 2;
576                                         count = 0;
577 //                                      printf("Just packed %d %d times, since count overflow\n",last,count);
578
579                                 }
580                         }       // end for
581
582                         if (count)      {
583
584                                 if (packed_size + 2 >= max)
585                                         return -1;
586
587                                 if ( (count == 1) && !(last & STD_RLE_CODE) ) {
588                                         *save++ = (ubyte)last;
589                                         packed_size++;
590 //                                      printf("Just packed %d 1 times, at end since single pixel, no count\n",last);
591                                         SDL_assert( last != STD_RLE_CODE );
592                                 }
593                                 else {
594                                         count |= STD_RLE_CODE;
595                                         *save++ = (ubyte)count;
596                                         *save++ = (ubyte)last;
597                                         packed_size += 2;
598 //                                      printf("Just packed %d %d times, at end since pixel change\n",last,count);
599                                 }
600                         }
601
602                         SDL_assert(packed_size == (save-dest_start) );
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
692                         ubyte *dest_start;
693
694                         dest_start = save;
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
763                         SDL_assert(packed_size == (save-dest_start) );
764                         return packed_size;
765                         break;
766                         }
767
768                 default:
769                         SDL_assert(0);
770                         return -1;
771                         break;
772         } // end switch
773
774         return packed_size;
775 }
776
777 // unpack a pixel given the passed index and the anim_instance's palette, return bytes stuffed
778 int unpack_pixel(anim_instance *ai, ubyte *data, ubyte pix, int aabitmap, int bpp)
779 {
780         int bit_24;
781         ushort bit_16 = 0;      
782         ubyte bit_8 = 0;
783         ubyte al = 0;
784         ubyte r, g, b;
785         anim *a = ai->parent;
786         SDL_assert(a);  
787
788         // if this is an aabitmap, don't run through the palette
789         if(aabitmap){
790                 switch(bpp){
791                 case 16 : 
792                         bit_16 = (ushort)pix;
793                         break;
794                 case 8:
795                         bit_8 = pix;
796                         break;
797                 default:
798                         Int3();
799                 }
800         } else {                
801                 // if the pixel value is 255, or is the xparent color, make it so               
802                 if(((a->palette[pix*3] == a->xparent_r) && (a->palette[pix*3+1] == a->xparent_g) && (a->palette[pix*3+2] == a->xparent_b)) ){
803                         r = b = 0;
804                         g = 255;
805                         bm_set_components((ubyte*)&bit_16, &r, &g, &b, &al);
806                 } else {
807                         // stuff the 24 bit value
808                         memcpy(&bit_24, &ai->parent->palette[pix * 3], 3);
809
810                         // convert to 16 bit
811                         bm_24_to_16(bit_24, &bit_16);
812                 }
813         }
814
815         // stuff the pixel
816         switch(bpp){
817         case 16 :
818                 memcpy(data, &bit_16, sizeof(ushort));
819                 return sizeof(ushort);
820
821         case 8 :
822                 *data = bit_8;          
823                 return sizeof(ubyte);   
824         }
825
826         Int3();
827         return 0;
828 }
829
830 // unpack a pixel given the passed index and the anim_instance's palette, return bytes stuffed
831 int unpack_pixel_count(anim_instance *ai, ubyte *data, ubyte pix, int count, int aabitmap, int bpp)
832 {
833         int bit_24;
834         int idx;
835         ubyte al = 0;
836         ushort bit_16 = 0;      
837         ubyte bit_8 = 0;
838         anim *a = ai->parent;
839         ubyte r, g, b;
840         SDL_assert(a);  
841
842         // if this is an aabitmap, don't run through the palette
843         if(aabitmap){
844                 switch(bpp){
845                 case 16 : 
846                         bit_16 = (ushort)pix;
847                         break;
848                 case 8 :
849                         bit_8 = pix;
850                         break;
851                 default :
852                         Int3();                 
853                 }
854         } else {                
855                 // if the pixel value is 255, or is the xparent color, make it so               
856                 if(((a->palette[pix*3] == a->xparent_r) && (a->palette[pix*3+1] == a->xparent_g) && (a->palette[pix*3+2] == a->xparent_b)) ){
857                         r = b = 0;
858                         g = 255;
859                         bm_set_components((ubyte*)&bit_16, &r, &g, &b, &al);
860                 } else {
861                         // stuff the 24 bit value
862                         memcpy(&bit_24, &ai->parent->palette[pix * 3], 3);
863
864                         // convert to 16 bit
865                         bm_24_to_16(bit_24, &bit_16);
866                 }
867         }
868         
869         // stuff the pixel
870         for(idx=0; idx<count; idx++){
871                 switch(bpp){
872                 case 16 :
873                         memcpy(data + (idx*2), &bit_16, sizeof(ushort));
874                         break;
875                 case 8 :
876                         *(data + idx) = bit_8;
877                         break;
878                 }
879         }
880
881         if(bpp == 16){
882                 return sizeof(ushort) * count;
883         }
884         return sizeof(ubyte) * count;
885 }
886
887 // ptr = packed data to unpack
888 // frame = where to store unpacked data to
889 // size = total number of unpacked pixels requested
890 // pal_translate = color translation lookup table (NULL if no palette translation desired)
891 ubyte   *unpack_frame(anim_instance *ai, ubyte *ptr, ubyte *frame, int size, ubyte *pal_translate, int aabitmap, int bpp)
892 {
893         int     xlate_pal, value, count = 0;
894         int stuffed;                    
895         int pixel_size = (bpp == 16) ? 2 : 1;
896
897         if ( pal_translate == NULL ) {
898                 xlate_pal = 0;
899         }
900         else {
901                 xlate_pal = 1;
902         }
903
904         if (*ptr == PACKING_METHOD_RLE_KEY) {  // key frame, Hoffoss's RLE format
905                 ptr++;
906                 while (size > 0) {
907                         value = *ptr++;
908                         if (value != packer_code) {
909                                 if ( xlate_pal ){
910                                         stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
911                                 } else {
912                                         stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
913                                 }
914                                 frame += stuffed;
915                                 size--;
916                         } else {
917                                 count = *ptr++;
918                                 if (count < 2){
919                                         value = packer_code;
920                                 } else {
921                                         value = *ptr++;
922                                 }
923
924                                 if (++count > size){
925                                         count = size;
926                                 }
927
928                                 if ( xlate_pal ){
929                                         stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
930                                 } else {                                        
931                                         stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
932                                 }
933
934                                 frame += stuffed;
935                                 size -= count;
936                         }
937                 }
938         }
939         else if ( *ptr == PACKING_METHOD_STD_RLE_KEY) { // key frame, with high bit as count
940                 ptr++;
941                 while (size > 0) {
942                         value = *ptr++;
943                         if ( !(value & STD_RLE_CODE) ) {
944                                 if ( xlate_pal ){
945                                         stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
946                                 } else {
947                                         stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
948                                 }
949
950                                 frame += stuffed;
951                                 size--;
952                         } else {
953                                 count = value & (~STD_RLE_CODE);
954                                 value = *ptr++;
955
956                                 size -= count;
957                                 SDL_assert(size >= 0);
958
959                                 if ( xlate_pal ){
960                                         stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
961                                 } else {
962                                         stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
963                                 }
964
965                                 frame += stuffed;
966                         }
967                 }
968         }
969         else if (*ptr == PACKING_METHOD_RLE) {  // normal frame, Hoffoss's RLE format
970
971 // test code, to show unused pixels
972 // memset(frame, 255, size);
973         
974                 ptr++;
975                 while (size > 0) {
976                         value = *ptr++;
977                         if (value != packer_code) {
978                                 if (value != transparent_code) {
979                                         if ( xlate_pal ){
980                                                 stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
981                                         } else {
982                                                 stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
983                                         }
984                                 } else {
985                                         // temporary pixel
986                                         stuffed = pixel_size;
987                                 }
988
989                                 frame += stuffed;
990                                 size--;
991                         } else {
992                                 count = *ptr++;
993                                 if (count < 2){
994                                         value = packer_code;
995                                 } else {
996                                         value = *ptr++;
997                                 }
998
999                                 if (++count > size){
1000                                         count = size;
1001                                 }
1002
1003                                 size -= count;
1004                                 SDL_assert(size >= 0);
1005
1006                                 if (value != transparent_code ) {
1007                                         if ( xlate_pal ) {
1008                                                 stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
1009                                         } else {
1010                                                 stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
1011                                         }
1012                                 } else {
1013                                         stuffed = count * pixel_size;
1014                                 }
1015
1016                                 frame += stuffed;
1017                         }
1018                 }
1019
1020         }
1021         else if ( *ptr == PACKING_METHOD_STD_RLE) {     // normal frame, with high bit as count
1022                 ptr++;
1023                 while (size > 0) {
1024                         value = *ptr++;
1025                         if ( !(value & STD_RLE_CODE) ) {
1026                                 if (value != transparent_code) {
1027                                         if ( xlate_pal ){
1028                                                 stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
1029                                         } else {
1030                                                 stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
1031                                         }
1032                                 } else {
1033                                         stuffed = pixel_size;
1034                                 }
1035
1036                                 frame += stuffed;
1037                                 size--;
1038                         } else {
1039                                 count = value & (~STD_RLE_CODE);
1040                                 value = *ptr++;
1041
1042                                 size -= count;
1043                                 SDL_assert(size >= 0);
1044
1045                                 if (value != transparent_code) {
1046                                         if ( xlate_pal ){
1047                                                 stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
1048                                         } else {
1049                                                 stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
1050                                         }
1051                                 } else {                                        
1052                                         stuffed = pixel_size * count;
1053                                 }
1054
1055                                 frame += stuffed;
1056                         }
1057                 }
1058         }
1059         else {
1060                 SDL_assert(0);  // unknown packing method
1061         }
1062
1063         return ptr;
1064 }
1065
1066 // ptr = packed data to unpack
1067 // frame = where to store unpacked data to
1068 // size = total number of unpacked pixels requested
1069 // pal_translate = color translation lookup table (NULL if no palette translation desired)
1070 int unpack_frame_from_file(anim_instance *ai, ubyte *frame, int size, ubyte *pal_translate, int aabitmap, int bpp)
1071 {
1072         int     xlate_pal, value, count = 0;
1073         int     offset = 0;
1074         int stuffed;    
1075         int pixel_size = (bpp == 16) ? 2 : 1;
1076
1077         if ( pal_translate == NULL ) {
1078                 xlate_pal = 0;
1079         }
1080         else {
1081                 xlate_pal = 1;
1082         }
1083
1084         if (anim_instance_get_byte(ai,offset) == PACKING_METHOD_RLE_KEY) {  // key frame, Hoffoss's RLE format
1085                 offset++;
1086                 while (size > 0) {
1087                         value = anim_instance_get_byte(ai,offset);
1088                         offset++;
1089                         if (value != packer_code) {
1090                                 if ( xlate_pal ){
1091                                         stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
1092                                 } else {
1093                                         stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
1094                                 }
1095
1096                                 frame += stuffed;
1097                                 size--;
1098                         } else {
1099                                 count = anim_instance_get_byte(ai,offset);
1100                                 offset++;
1101                                 if (count < 2) {
1102                                         value = packer_code;
1103                                 } else {
1104                                         value = anim_instance_get_byte(ai,offset);
1105                                         offset++;
1106                                 }
1107
1108                                 if (++count > size){
1109                                         count = size;
1110                                 }
1111
1112                                 if ( xlate_pal ){
1113                                         stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
1114                                 } else {
1115                                         stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
1116                                 }
1117
1118                                 frame += stuffed;
1119                                 size -= count;
1120                         }
1121                 }
1122         }
1123         else if ( anim_instance_get_byte(ai,offset) == PACKING_METHOD_STD_RLE_KEY) {    // key frame, with high bit as count
1124                 offset++;
1125                 while (size > 0) {
1126                         value = anim_instance_get_byte(ai,offset);
1127                         offset++;
1128                         if ( !(value & STD_RLE_CODE) ) {
1129                                 if ( xlate_pal ){
1130                                         stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
1131                                 } else {
1132                                         stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
1133                                 }
1134
1135                                 frame += stuffed;
1136                                 size--;
1137                         } else {
1138                                 count = value & (~STD_RLE_CODE);
1139                                 value = anim_instance_get_byte(ai,offset);
1140                                 offset++;
1141
1142                                 size -= count;
1143                                 SDL_assert(size >= 0);
1144
1145                                 if ( xlate_pal ){
1146                                         stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
1147                                 } else {
1148                                         stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
1149                                 }
1150
1151                                 frame += stuffed;
1152                         }
1153                 }
1154         }
1155         else if (anim_instance_get_byte(ai,offset) == PACKING_METHOD_RLE) {  // normal frame, Hoffoss's RLE format
1156
1157 // test code, to show unused pixels
1158 // memset(frame, 255, size);
1159         
1160                 offset++;
1161                 while (size > 0) {
1162                         value = anim_instance_get_byte(ai,offset);
1163                         offset++;
1164                         if (value != packer_code) {
1165                                 if (value != transparent_code) {
1166                                         if ( xlate_pal ){
1167                                                 stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
1168                                         } else {
1169                                                 stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
1170                                         }
1171                                 } else {
1172                                         stuffed = pixel_size;
1173                                 }
1174
1175                                 frame += stuffed;
1176                                 size--;
1177                         } else {
1178                                 count = anim_instance_get_byte(ai,offset);
1179                                 offset++;
1180
1181                                 if (count < 2) {
1182                                         value = packer_code;
1183                                 } else {
1184                                         value = anim_instance_get_byte(ai,offset);
1185                                         offset++;
1186                                 }
1187                                 if (++count > size){
1188                                         count = size;
1189                                 }
1190
1191                                 size -= count;
1192                                 SDL_assert(size >= 0);
1193
1194                                 if (value != transparent_code ) {
1195                                         if ( xlate_pal ) {
1196                                                 stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
1197                                         } else {
1198                                                 stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
1199                                         }
1200                                 } else {
1201                                         stuffed = pixel_size * count;
1202                                 }
1203
1204                                 frame += stuffed;
1205                         }
1206                 }
1207
1208         }
1209         else if ( anim_instance_get_byte(ai,offset) ) { // normal frame, with high bit as count
1210                 offset++;
1211                 while (size > 0) {
1212                         value = anim_instance_get_byte(ai,offset);
1213                         offset++;
1214                         if ( !(value & STD_RLE_CODE) ) {
1215                                 if (value != transparent_code) {
1216                                         if ( xlate_pal ){
1217                                                 stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
1218                                         } else {
1219                                                 stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
1220                                         }
1221                                 } else {
1222                                         stuffed = pixel_size;
1223                                 }
1224
1225                                 frame += stuffed;
1226                                 size--;
1227                         } else {
1228                                 count = value & (~STD_RLE_CODE);
1229                                 value = anim_instance_get_byte(ai,offset);
1230                                 offset++;
1231
1232                                 size -= count;
1233                                 SDL_assert(size >= 0);
1234
1235                                 if (value != transparent_code) {
1236                                         if ( xlate_pal ){
1237                                                 stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
1238                                         } else {
1239                                                 stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
1240                                         }
1241                                 } else {                                        
1242                                         stuffed = pixel_size * count;
1243                                 }
1244
1245                                 frame += stuffed;
1246                         }
1247                 }
1248         }
1249         else {
1250                 Int3();  // unknown packing method
1251         }
1252
1253         return ai->file_offset + offset;
1254 }
1255
1256
1257 // TODO: actually convert the frame data to correct palette at this point
1258 void anim_set_palette(anim *ptr)
1259 {
1260         int i, xparent_found = 0;
1261         
1262         // create the palette translation look-up table
1263         for ( i = 0; i < 256; i++ ) {
1264
1265                 //if ( (ptr->palette[i*3] == ptr->xparent_r) && (ptr->palette[i*3+1] == ptr->xparent_g) && (ptr->palette[i*3+2] == ptr->xparent_b) ) {
1266                 //      ptr->palette_translation[i] = 255;
1267                 //      xparent_found = 1;
1268                 //} else        {
1269                         // ptr->palette_translation[i] = (ubyte)palette_find( ptr->palette[i*3], ptr->palette[i*3+1], ptr->palette[i*3+2] );
1270                         ptr->palette_translation[i] = (ubyte)i;
1271                 //}
1272         }       
1273
1274         if ( xparent_found ) {
1275                 ptr->flags |= ANF_XPARENT;
1276         }
1277         else {
1278                 ptr->flags &= ~ANF_XPARENT;
1279         }
1280 }
1281