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