CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

KEYFRAME.CPP (22446B)


      1 //
      2 // Copyright 2020 Electronic Arts Inc.
      3 //
      4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 
      5 // software: you can redistribute it and/or modify it under the terms of 
      6 // the GNU General Public License as published by the Free Software Foundation, 
      7 // either version 3 of the License, or (at your option) any later version.
      8 
      9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 
     10 // in the hope that it will be useful, but with permitted additional restrictions 
     11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
     12 // distributed with this program. You should have received a copy of the 
     13 // GNU General Public License along with permitted additional restrictions 
     14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
     15 
     16 /* $Header:   F:\projects\c&c\vcs\code\keyframe.cpv   2.14   16 Oct 1995 16:48:54   JOE_BOSTIC  $ */
     17 /***********************************************************************************************
     18  ***             C O N F I D E N T I A L  ---  W E S T W O O D   S T U D I O S               ***
     19  ***********************************************************************************************
     20  *                                                                                             *
     21  *                 Project Name : Command & Conquer                                            *
     22  *                                                                                             *
     23  *                    File Name : KEYFRAME.CPP                                                 *
     24  *                                                                                             *
     25  *                   Programmer : Joe L. Bostic                                                *
     26  *                                                                                             *
     27  *                   Start Date : 06/25/95                                                     *
     28  *                                                                                             *
     29  *                  Last Update : June 25, 1995 [JLB]                                          *
     30  *                                                                                             *
     31  *---------------------------------------------------------------------------------------------*
     32  * Functions:                                                                                  *
     33  *   Get_Build_Frame_Count -- Fetches the number of frames in data block.                      *
     34  *   Get_Build_Frame_Width -- Fetches the width of the shape image.                            *
     35  *   Get_Build_Frame_Height -- Fetches the height of the shape image.                          *
     36  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     37 
     38 
     39 #include "function.h"
     40 
     41 #define SUBFRAMEOFFS			7	// 3 1/2 frame offsets loaded (2 offsets/frame)
     42 
     43 
     44 #define	Apply_Delta(buffer, delta)		Apply_XOR_Delta((char*)(buffer), (char*)(delta))
     45 
     46 typedef struct {
     47 	unsigned short frames;
     48 	unsigned short x;
     49 	unsigned short y;
     50 	unsigned short width;
     51 	unsigned short height;
     52 	unsigned short largest_frame_size;
     53 	short				flags;
     54 } KeyFrameHeaderType;
     55 
     56 #define	INITIAL_BIG_SHAPE_BUFFER_SIZE	12000*1024
     57 #define	THEATER_BIG_SHAPE_BUFFER_SIZE 1000*1024
     58 #define	UNCOMPRESS_MAGIC_NUMBER			56789
     59 
     60 unsigned	BigShapeBufferLength = INITIAL_BIG_SHAPE_BUFFER_SIZE;
     61 unsigned	TheaterShapeBufferLength = THEATER_BIG_SHAPE_BUFFER_SIZE;
     62 extern "C"{
     63 	char		*BigShapeBufferStart = NULL;
     64 	char		*TheaterShapeBufferStart = NULL;
     65 	BOOL		UseBigShapeBuffer = FALSE;
     66 	bool		IsTheaterShape = false;
     67 }
     68 char		*BigShapeBufferPtr = NULL;
     69 int			TotalBigShapes=0;
     70 BOOL		ReallocShapeBufferFlag = FALSE;
     71 bool		OriginalUseBigShapeBuffer = false;
     72 
     73 char		*TheaterShapeBufferPtr = NULL;
     74 int			TotalTheaterShapes = 0;
     75 
     76 
     77 
     78 #define MAX_SLOTS 1500
     79 #define THEATER_SLOT_START 1000
     80 
     81 char	**KeyFrameSlots [MAX_SLOTS];
     82 int 	TotalSlotsUsed=0;
     83 int		TheaterSlotsUsed = THEATER_SLOT_START;
     84 
     85 
     86 typedef struct tShapeHeaderType{
     87 	unsigned draw_flags;
     88 	char		*shape_data;
     89 	int		shape_buffer;		//1 if shape is in theater buffer
     90 } ShapeHeaderType;
     91 
     92 static int Length;
     93 
     94 void *Get_Shape_Header_Data(void *ptr)
     95 {
     96 	if (UseBigShapeBuffer){
     97 
     98 		ShapeHeaderType *header = (ShapeHeaderType*) ptr;
     99 		return ((void*)  (header->shape_data + (long)(header->shape_buffer ? TheaterShapeBufferStart : BigShapeBufferStart) ) );
    100 
    101 	}else{
    102 		return (ptr);
    103 	}
    104 }
    105 
    106 int Get_Last_Frame_Length(void)
    107 {
    108 	return(Length);
    109 }
    110 
    111 
    112 
    113 void Reset_Theater_Shapes (void)
    114 {
    115 	/*
    116 	** Delete any previously allocated slots
    117 	*/
    118 	for (int i=THEATER_SLOT_START ; i<TheaterSlotsUsed ; i++){
    119 		delete [] KeyFrameSlots [i];
    120 	}
    121 
    122 	TheaterShapeBufferPtr = TheaterShapeBufferStart;
    123 	TotalTheaterShapes = 0;
    124 	TheaterSlotsUsed = THEATER_SLOT_START;
    125 }
    126 
    127 
    128 
    129 void Reallocate_Big_Shape_Buffer(void)
    130 {
    131 	if (ReallocShapeBufferFlag){
    132 		BigShapeBufferLength += 200 * 1024;							//Extra 2 Mb of uncompressed shape space
    133 		BigShapeBufferPtr -= (unsigned)BigShapeBufferStart;
    134 		Memory_Error = NULL;
    135 		BigShapeBufferStart = (char*)Resize_Alloc(BigShapeBufferStart, BigShapeBufferLength);
    136 		Memory_Error = &Memory_Error_Handler;
    137 		/*
    138 		** If we have run out of memory then disable the uncompressed shapes
    139 		** It may still be possible to continue with compressed shapes
    140 		*/
    141 		if (!BigShapeBufferStart){
    142 			UseBigShapeBuffer = false;
    143 			return;
    144 		}
    145 		BigShapeBufferPtr += (unsigned)BigShapeBufferStart;
    146 		ReallocShapeBufferFlag = FALSE;
    147 	}
    148 }
    149 
    150 
    151 
    152 
    153 void Check_Use_Compressed_Shapes (void)
    154 {
    155 	MEMORYSTATUS	mem_info;
    156 
    157 	mem_info.dwLength=sizeof(mem_info);
    158 	GlobalMemoryStatus(&mem_info);
    159 
    160 	UseBigShapeBuffer = (mem_info.dwTotalPhys > 16*1024*1024) ? TRUE : FALSE;
    161 	OriginalUseBigShapeBuffer = UseBigShapeBuffer;
    162 
    163 	// UseBigShapeBuffer = false;
    164 }
    165 
    166 
    167 
    168 
    169 /***********************************************************************************************
    170  * Disable_Uncompressed_Shapes -- Temporarily turns off shape decompression                    *
    171  *                                                                                             *
    172  *                                                                                             *
    173  *                                                                                             *
    174  * INPUT:    Nothing                                                                           *
    175  *                                                                                             *
    176  * OUTPUT:   Nothing                                                                           *
    177  *                                                                                             *
    178  * WARNINGS: None                                                                              *
    179  *                                                                                             *
    180  * HISTORY:                                                                                    *
    181  *    11/19/96 2:37PM ST : Created                                                             *
    182  *=============================================================================================*/
    183 void Disable_Uncompressed_Shapes (void)
    184 {
    185 	UseBigShapeBuffer = false;
    186 }
    187 
    188 
    189 
    190 /***********************************************************************************************
    191  * Enable_Uncompressed_Shapes -- Restores state of shape decompression before it was disabled  *
    192  *                                                                                             *
    193  *                                                                                             *
    194  *                                                                                             *
    195  * INPUT:    Nothing                                                                           *
    196  *                                                                                             *
    197  * OUTPUT:   Nothing                                                                           *
    198  *                                                                                             *
    199  * WARNINGS: None                                                                              *
    200  *                                                                                             *
    201  * HISTORY:                                                                                    *
    202  *    11/19/96 2:37PM ST : Created                                                             *
    203  *=============================================================================================*/
    204 void Enable_Uncompressed_Shapes (void)
    205 {
    206 	UseBigShapeBuffer = OriginalUseBigShapeBuffer;
    207 }
    208 
    209 
    210 #define FIXIT_SCORE_CRASH
    211 
    212 unsigned long Build_Frame(void const *dataptr, unsigned short framenumber, void *buffptr)
    213 {
    214 #ifdef FIXIT_SCORE_CRASH
    215 	char * ptr;
    216 	unsigned long offcurr, offdiff;
    217 #else
    218 	char * ptr, * lockptr;
    219 	unsigned long offcurr, off16, offdiff;
    220 #endif
    221 	unsigned long offset[SUBFRAMEOFFS];
    222 	KeyFrameHeaderType *keyfr;
    223 	unsigned short buffsize, currframe, subframe;
    224 	unsigned long length = 0;
    225 	char frameflags;
    226 	unsigned long return_value;
    227 	char *temp_shape_ptr;
    228 
    229 	//
    230 	// valid pointer??
    231 	//
    232 	Length = 0;
    233 	if ( !dataptr || !buffptr ) {
    234 		return(0);
    235 	}
    236 
    237 	//
    238 	// look at header then check that frame to build is not greater
    239 	// than total frames
    240 	//
    241 	keyfr = (KeyFrameHeaderType *) dataptr;
    242 
    243 	if ( framenumber >= keyfr->frames ) {
    244 		return(0);
    245 	}
    246 
    247 
    248 	if (UseBigShapeBuffer){
    249 		/*
    250 		** If we havnt yet allocated memory for uncompressed shapes then do so now.
    251 		**
    252 		*/
    253 		if (!BigShapeBufferStart){
    254 			BigShapeBufferStart = (char*)Alloc(BigShapeBufferLength, MEM_NORMAL);
    255 			BigShapeBufferPtr = BigShapeBufferStart;
    256 			/*
    257 			** Allocate memory for theater specific uncompressed shapes
    258 			*/
    259 			TheaterShapeBufferStart = (char*) Alloc (TheaterShapeBufferLength, MEM_NORMAL);
    260 			TheaterShapeBufferPtr = TheaterShapeBufferStart;
    261 		}
    262 
    263 
    264 		/*
    265 		** Track memory usage in uncompressed shape buffers.
    266 		*/
    267 		static bool show_info = true;
    268 
    269 		if ((Frame & 0xff) == 0){
    270 
    271 			if (show_info){
    272 
    273 				char debugstr [128];
    274 				sprintf (debugstr, "C&C95 - Big shape buffer is now %d Kb.\n", BigShapeBufferLength / 1024);
    275 				CCDebugString (debugstr);
    276 
    277 				sprintf (debugstr, "C&C95 - %d Kb Used in big shape buffer.\n", (unsigned)((unsigned)BigShapeBufferPtr - (unsigned)BigShapeBufferStart)/1024);
    278 				CCDebugString (debugstr);
    279 
    280 				sprintf (debugstr, "C&C95 - %d Kb Used in theater shape buffer.\n", (unsigned)((unsigned)TheaterShapeBufferPtr - (unsigned)TheaterShapeBufferStart)/1024);
    281 				CCDebugString (debugstr);
    282 				show_info = false;
    283 			}
    284 
    285 			}else{
    286 			show_info = true;
    287 
    288 		}
    289 
    290 
    291 		/*
    292 		** If we are running out of memory (<128k left) for uncompressed shapes
    293 		** then allocate some more.
    294 		*/
    295 		if (( (unsigned)BigShapeBufferStart + BigShapeBufferLength) - (unsigned)BigShapeBufferPtr < 128*1024){
    296 			ReallocShapeBufferFlag = TRUE;
    297 		}
    298 
    299 		/*
    300 		** If this animation was not previously uncompressed then
    301 		** allocate memory to keep the pointers to the uncompressed data
    302 		** for these animation frames
    303 		*/
    304 		if (keyfr->x != UNCOMPRESS_MAGIC_NUMBER){
    305 			keyfr->x = UNCOMPRESS_MAGIC_NUMBER;
    306 			if (IsTheaterShape){
    307 				keyfr->y = TheaterSlotsUsed;
    308 				TheaterSlotsUsed++;
    309 			}else{
    310 				keyfr->y = TotalSlotsUsed;
    311 				TotalSlotsUsed++;
    312 			}
    313 			/*
    314 			** Allocate and clear the memory for the shape info
    315 			*/
    316 			KeyFrameSlots[keyfr->y]= new char *[keyfr->frames];
    317 			memset (KeyFrameSlots[keyfr->y] , 0 , keyfr->frames*4);
    318 		}
    319 
    320 		/*
    321 		** If this frame was previously uncompressed then just return
    322 		** a pointer to the raw data
    323 		*/
    324 		if (*(KeyFrameSlots[keyfr->y]+framenumber)){
    325 			if (IsTheaterShape){
    326 				return ((unsigned long)TheaterShapeBufferStart + (unsigned long)*(KeyFrameSlots[keyfr->y]+framenumber));
    327 			}else{
    328 				return ((unsigned long)BigShapeBufferStart + (unsigned long)*(KeyFrameSlots[keyfr->y]+framenumber));
    329 			}
    330 		}
    331 	}
    332 
    333 	// calc buff size
    334 	buffsize = keyfr->width * keyfr->height;
    335 
    336 	// get offset into data
    337 	ptr = (char *)Add_Long_To_Pointer( dataptr, (((unsigned long)framenumber << 3) + sizeof(KeyFrameHeaderType)) );
    338 	Mem_Copy( ptr, &offset[0], 12L );
    339 	frameflags = (char)(offset[0] >> 24);
    340 
    341 
    342 	if ( (frameflags & KF_KEYFRAME) ) {
    343 
    344 		ptr = (char *)Add_Long_To_Pointer( dataptr, (offset[0] & 0x00FFFFFFL) );
    345 
    346 		if (keyfr->flags & 1 ) {
    347 			ptr = (char *)Add_Long_To_Pointer( ptr, 768L );
    348 		}
    349 		length = LCW_Uncompress( ptr, buffptr, buffsize );
    350 	} else {	// key delta or delta
    351 
    352 		if ( (frameflags & KF_DELTA) ) {
    353 			currframe = (unsigned short)offset[1];
    354 
    355 			ptr = (char *)Add_Long_To_Pointer( dataptr, (((unsigned long)currframe << 3) + sizeof(KeyFrameHeaderType)) );
    356 			Mem_Copy( ptr, &offset[0], (long)(SUBFRAMEOFFS * sizeof(unsigned long)) );
    357 		}
    358 
    359 		// key frame
    360 		offcurr = offset[1] & 0x00FFFFFFL;
    361 
    362 		// key delta
    363 		offdiff = (offset[0] & 0x00FFFFFFL) - offcurr;
    364 
    365 		ptr = (char *)Add_Long_To_Pointer( dataptr, offcurr );
    366 
    367 		if (keyfr->flags & 1 ) {
    368 			ptr = (char *)Add_Long_To_Pointer( ptr, 768L );
    369 		}
    370 
    371 #ifndef FIXIT_SCORE_CRASH
    372 		off16 = (unsigned long)lockptr & 0x00003FFFL;
    373 #endif
    374 		length = LCW_Uncompress( ptr, buffptr, buffsize );
    375 
    376 		if (length > buffsize) {
    377 			return(0);
    378 		}
    379 
    380 #ifndef FIXIT_SCORE_CRASH
    381 		if ( ((offset[2] & 0x00FFFFFFL) - offcurr) >= (0x00010000L - off16) ) {
    382 
    383 			ptr = (char *)Add_Long_To_Pointer( ptr, offdiff );
    384 			off16 = (unsigned long)ptr & 0x00003FFFL;
    385 
    386 			offcurr += offdiff;
    387 			offdiff = 0;
    388 		}
    389 #endif
    390 		length = buffsize;
    391 		Apply_Delta(buffptr, Add_Long_To_Pointer(ptr, offdiff));
    392 
    393 		if ( (frameflags & KF_DELTA) ) {
    394 			// adjust to delta after the keydelta
    395 
    396 			currframe++;
    397 			subframe = 2;
    398 
    399 			while (currframe <= framenumber) {
    400 				offdiff = (offset[subframe] & 0x00FFFFFFL) - offcurr;
    401 
    402 #ifndef FIXIT_SCORE_CRASH
    403 				if ( ((offset[subframe+2] & 0x00FFFFFFL) - offcurr) >= (0x00010000L - off16) ) {
    404 
    405 					ptr = (char *)Add_Long_To_Pointer( ptr, offdiff );
    406 					off16 = (unsigned long)lockptr & 0x00003FFFL;
    407 
    408 					offcurr += offdiff;
    409 					offdiff = 0;
    410 				}
    411 #endif
    412 
    413 				length = buffsize;
    414 				Apply_Delta(buffptr, Add_Long_To_Pointer(ptr, offdiff));
    415 
    416 				currframe++;
    417 				subframe += 2;
    418 
    419 				if ( subframe >= (SUBFRAMEOFFS - 1) &&
    420 					currframe <= framenumber ) {
    421 					Mem_Copy( Add_Long_To_Pointer( dataptr,
    422 									(((unsigned long)currframe << 3) +
    423 									sizeof(KeyFrameHeaderType)) ),
    424 						&offset[0], (long)(SUBFRAMEOFFS * sizeof(unsigned long)) );
    425 					subframe = 0;
    426 				}
    427 			}
    428 		}
    429 	}
    430 
    431 	if (UseBigShapeBuffer){
    432 		/*
    433 		** Save the uncompressed shape data so we dont have to uncompress it
    434 		** again next time its drawn.
    435 		** We keep a space free before the raw shape data so we can add line
    436 		** header info before the shape is drawn for the first time
    437 		*/
    438 
    439 		if (IsTheaterShape){
    440 			/*
    441 			** Shape is a theater specific shape
    442 			*/
    443 			return_value = (unsigned long) TheaterShapeBufferPtr;
    444 			temp_shape_ptr = TheaterShapeBufferPtr + keyfr->height+sizeof(ShapeHeaderType);
    445 			/*
    446 			** align the actual shape data
    447 			*/
    448 			if (3 & (unsigned)temp_shape_ptr){
    449 				temp_shape_ptr = (char *) ((unsigned)(temp_shape_ptr + 3) & 0xfffffffc);
    450 			}
    451 
    452 			memcpy (temp_shape_ptr , buffptr , length);
    453 			((ShapeHeaderType *)TheaterShapeBufferPtr)->draw_flags = -1;						//Flag that headers need to be generated
    454 			((ShapeHeaderType *)TheaterShapeBufferPtr)->shape_data = temp_shape_ptr - (unsigned)TheaterShapeBufferStart;		//pointer to old raw shape data
    455 			((ShapeHeaderType *)TheaterShapeBufferPtr)->shape_buffer = 1;	//Theater buffer
    456 			*(KeyFrameSlots[keyfr->y]+framenumber) = TheaterShapeBufferPtr - (unsigned)TheaterShapeBufferStart;
    457 			TheaterShapeBufferPtr = (char*)(length + (unsigned)temp_shape_ptr);
    458 			/*
    459 			** Align the next shape
    460 			*/
    461 			if (3 & (unsigned)TheaterShapeBufferPtr){
    462 				TheaterShapeBufferPtr = (char *)((unsigned)(TheaterShapeBufferPtr + 3) & 0xfffffffc);
    463 			}
    464 			Length = length;
    465 			return (return_value);
    466 
    467 		}else{
    468 
    469 
    470 			return_value=(unsigned long)BigShapeBufferPtr;
    471 			temp_shape_ptr = BigShapeBufferPtr + keyfr->height+sizeof(ShapeHeaderType);
    472 			/*
    473 			** align the actual shape data
    474 			*/
    475 			if (3 & (unsigned)temp_shape_ptr){
    476 				temp_shape_ptr = (char *) ((unsigned)(temp_shape_ptr + 3) & 0xfffffffc);
    477 			}
    478 			memcpy (temp_shape_ptr , buffptr , length);
    479 			((ShapeHeaderType *)BigShapeBufferPtr)->draw_flags = -1;						//Flag that headers need to be generated
    480 			((ShapeHeaderType *)BigShapeBufferPtr)->shape_data = temp_shape_ptr - (unsigned)BigShapeBufferStart;		//pointer to old raw shape data
    481 			((ShapeHeaderType *)BigShapeBufferPtr)->shape_buffer = 0;	//Normal Big Shape Buffer
    482 			*(KeyFrameSlots[keyfr->y]+framenumber) = BigShapeBufferPtr - (unsigned)BigShapeBufferStart;
    483 			BigShapeBufferPtr = (char*)(length + (unsigned)temp_shape_ptr);
    484 			// Align the next shape
    485 			if (3 & (unsigned)BigShapeBufferPtr){
    486 				BigShapeBufferPtr = (char *)((unsigned)(BigShapeBufferPtr + 3) & 0xfffffffc);
    487 			}
    488 			Length = length;
    489 			return (return_value);
    490 		}
    491 
    492 	}else{
    493 		return ((unsigned long)buffptr);
    494 	}
    495 }
    496 
    497 
    498 /***********************************************************************************************
    499  * Get_Build_Frame_Count -- Fetches the number of frames in data block.                        *
    500  *                                                                                             *
    501  *    Use this routine to determine the number of shapes within the data block.                *
    502  *                                                                                             *
    503  * INPUT:   dataptr  -- Pointer to the keyframe shape data block.                              *
    504  *                                                                                             *
    505  * OUTPUT:  Returns with the number of shapes in the data block.                               *
    506  *                                                                                             *
    507  * WARNINGS:   none                                                                            *
    508  *                                                                                             *
    509  * HISTORY:                                                                                    *
    510  *   06/25/1995 JLB : Commented.                                                               *
    511  *=============================================================================================*/
    512 unsigned short Get_Build_Frame_Count(void const *dataptr)
    513 {
    514 	if (dataptr) {
    515 		return(((KeyFrameHeaderType const *)dataptr)->frames);
    516 	}
    517 	return(0);
    518 }
    519 
    520 
    521 unsigned short Get_Build_Frame_X(void const *dataptr)
    522 {
    523 	if (dataptr) {
    524 		return(((KeyFrameHeaderType const *)dataptr)->x);
    525 	}
    526 	return(0);
    527 }
    528 
    529 
    530 unsigned short Get_Build_Frame_Y(void const *dataptr)
    531 {
    532 	if (dataptr) {
    533 		return(((KeyFrameHeaderType const *)dataptr)->y);
    534 	}
    535 	return(0);
    536 }
    537 
    538 
    539 /***********************************************************************************************
    540  * Get_Build_Frame_Width -- Fetches the width of the shape image.                              *
    541  *                                                                                             *
    542  *    Use this routine to fetch the width of the shapes within the keyframe shape data block.  *
    543  *    All shapes within the block have the same width.                                         *
    544  *                                                                                             *
    545  * INPUT:   dataptr  -- Pointer to the keyframe shape data block.                              *
    546  *                                                                                             *
    547  * OUTPUT:  Returns with the width of the shapes in the block -- expressed in pixels.          *
    548  *                                                                                             *
    549  * WARNINGS:   none                                                                            *
    550  *                                                                                             *
    551  * HISTORY:                                                                                    *
    552  *   06/25/1995 JLB : Commented                                                                *
    553  *=============================================================================================*/
    554 unsigned short Get_Build_Frame_Width(void const *dataptr)
    555 {
    556 	if (dataptr) {
    557 		return(((KeyFrameHeaderType const *)dataptr)->width);
    558 	}
    559 	return(0);
    560 }
    561 
    562 
    563 /***********************************************************************************************
    564  * Get_Build_Frame_Height -- Fetches the height of the shape image.                            *
    565  *                                                                                             *
    566  *    Use this routine to fetch the height of the shapes within the keyframe shape data block. *
    567  *    All shapes within the block have the same height.                                        *
    568  *                                                                                             *
    569  * INPUT:   dataptr  -- Pointer to the keyframe shape data block.                              *
    570  *                                                                                             *
    571  * OUTPUT:  Returns with the height of the shapes in the block -- expressed in pixels.         *
    572  *                                                                                             *
    573  * WARNINGS:   none                                                                            *
    574  *                                                                                             *
    575  * HISTORY:                                                                                    *
    576  *   06/25/1995 JLB : Commented                                                                *
    577  *=============================================================================================*/
    578 unsigned short Get_Build_Frame_Height(void const *dataptr)
    579 {
    580 	if (dataptr) {
    581 		return(((KeyFrameHeaderType const *)dataptr)->height);
    582 	}
    583 	return(0);
    584 }
    585 
    586 
    587 bool Get_Build_Frame_Palette(void const * dataptr, void * palette)
    588 {
    589 	if (dataptr && (((KeyFrameHeaderType const *)dataptr)->flags & 1)) {
    590 		char const * ptr = (char const *)Add_Long_To_Pointer( dataptr,
    591 							( (( (long)sizeof(unsigned long) << 1) *
    592 								((KeyFrameHeaderType *) dataptr)->frames ) +
    593 							16 + sizeof(KeyFrameHeaderType) ) );
    594 
    595 		memcpy(palette, ptr, 768L);
    596 		return(true);
    597 	}
    598 	return(false);
    599 }