CnC_Remastered_Collection

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

2KEYFRAM.CPP (22397B)


      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: /CounterStrike/2KEYFRAM.CPP 1     3/03/97 10:24a 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	8000000
     57 #define	THEATER_BIG_SHAPE_BUFFER_SIZE 4000000
     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 #ifdef FIXIT_SCORE_CRASH
     69 /*
     70 ** Global required to fix the score screen crash bug by allowing disabling of uncompressed shapes.
     71 */
     72 bool		OriginalUseBigShapeBuffer = false;
     73 #endif	//FIXIT
     74 char		*BigShapeBufferPtr = NULL;
     75 int			TotalBigShapes=0;
     76 BOOL		ReallocShapeBufferFlag = FALSE;
     77 
     78 char		*TheaterShapeBufferPtr = NULL;
     79 int			TotalTheaterShapes = 0;
     80 
     81 
     82 #define MAX_SLOTS 1500
     83 #define THEATER_SLOT_START 1000
     84 
     85 char	**KeyFrameSlots [MAX_SLOTS];
     86 int 	TotalSlotsUsed=0;
     87 int		TheaterSlotsUsed = THEATER_SLOT_START;
     88 
     89 
     90 
     91 typedef struct tShapeHeaderType{
     92 	unsigned draw_flags;
     93 	char		*shape_data;
     94 	int		shape_buffer;		//1 if shape is in theater buffer
     95 } ShapeHeaderType;
     96 
     97 static int Length;
     98 
     99 void *Get_Shape_Header_Data(void *ptr)
    100 {
    101 	if (UseBigShapeBuffer) {
    102 
    103 		ShapeHeaderType *header = (ShapeHeaderType*) ptr;
    104 		return ((void*)  (header->shape_data + (long)(header->shape_buffer ? TheaterShapeBufferStart : BigShapeBufferStart) ) );
    105 
    106 	} else {
    107 		return (ptr);
    108 	}
    109 }
    110 
    111 int Get_Last_Frame_Length(void)
    112 {
    113 	return(Length);
    114 }
    115 
    116 
    117 void Reset_Theater_Shapes (void)
    118 {
    119 	/*
    120 	** Delete any previously allocated slots
    121 	*/
    122 	for (int i=THEATER_SLOT_START ; i<TheaterSlotsUsed ; i++) {
    123 		delete [] KeyFrameSlots [i];
    124 	}
    125 
    126 	TheaterShapeBufferPtr = TheaterShapeBufferStart;
    127 	TotalTheaterShapes = 0;
    128 	TheaterSlotsUsed = THEATER_SLOT_START;
    129 }
    130 
    131 
    132 void Reallocate_Big_Shape_Buffer(void)
    133 {
    134 	if (ReallocShapeBufferFlag) {
    135 		BigShapeBufferLength += 2000000;							//Extra 2 Mb of uncompressed shape space
    136 		BigShapeBufferPtr -= (unsigned)BigShapeBufferStart;
    137 		Memory_Error = NULL;
    138 		BigShapeBufferStart = (char*)Resize_Alloc(BigShapeBufferStart, BigShapeBufferLength);
    139 		Memory_Error = &Memory_Error_Handler;
    140 		/*
    141 		** If we have run out of memory then disable the uncompressed shapes
    142 		** It may still be possible to continue with compressed shapes
    143 		*/
    144 		if (!BigShapeBufferStart) {
    145 			UseBigShapeBuffer = false;
    146 			return;
    147 		}
    148 		BigShapeBufferPtr += (unsigned)BigShapeBufferStart;
    149 		ReallocShapeBufferFlag = FALSE;
    150 	}
    151 }
    152 
    153 
    154 //#ifdef FIXIT_SCORE_CRASH
    155 /***********************************************************************************************
    156  * Disable_Uncompressed_Shapes -- Temporarily turns off shape decompression                    *
    157  *                                                                                             *
    158  *                                                                                             *
    159  *                                                                                             *
    160  * INPUT:    Nothing                                                                           *
    161  *                                                                                             *
    162  * OUTPUT:   Nothing                                                                           *
    163  *                                                                                             *
    164  * WARNINGS: None                                                                              *
    165  *                                                                                             *
    166  * HISTORY:                                                                                    *
    167  *    11/19/96 2:37PM ST : Created                                                             *
    168  *=============================================================================================*/
    169 void Disable_Uncompressed_Shapes (void)
    170 {
    171 	UseBigShapeBuffer = false;
    172 }
    173 
    174 
    175 
    176 /***********************************************************************************************
    177  * Enable_Uncompressed_Shapes -- Restores state of shape decompression before it was disabled  *
    178  *                                                                                             *
    179  *                                                                                             *
    180  *                                                                                             *
    181  * INPUT:    Nothing                                                                           *
    182  *                                                                                             *
    183  * OUTPUT:   Nothing                                                                           *
    184  *                                                                                             *
    185  * WARNINGS: None                                                                              *
    186  *                                                                                             *
    187  * HISTORY:                                                                                    *
    188  *    11/19/96 2:37PM ST : Created                                                             *
    189  *=============================================================================================*/
    190 void Enable_Uncompressed_Shapes (void)
    191 {
    192 	UseBigShapeBuffer = OriginalUseBigShapeBuffer;
    193 }
    194 //#endif	//FIXIT
    195 
    196 void Check_Use_Compressed_Shapes (void)
    197 {
    198 #if (1)	// Uncompressed shapes enabled for performance reasons. We don't need to worry about memory. 
    199 			// Uncompressed shapes don't seem to work in RA for rotated/scaled objects so wherever scale/rotate is used, 
    200 			// we will need to disable it (like in Techno_Draw_Object). ST - 11/6/2019 2:09PM
    201 	UseBigShapeBuffer = true;
    202 	OriginalUseBigShapeBuffer = true;
    203 
    204 #else
    205 	MEMORYSTATUS	mem_info;
    206 
    207 	mem_info.dwLength=sizeof(mem_info);
    208 	GlobalMemoryStatus(&mem_info);
    209 
    210 	UseBigShapeBuffer = (mem_info.dwTotalPhys > 16*1024*1024) ? TRUE : FALSE;
    211 #ifdef FIXIT_SCORE_CRASH
    212 	/*
    213 	** Keep track of our original decision about whether to use cached shapes.
    214 	** This is needed for the score screen crash fix.
    215 	*/
    216 	OriginalUseBigShapeBuffer = UseBigShapeBuffer;
    217 #endif	//FIXIT
    218 #endif
    219 }
    220 
    221 
    222 
    223 
    224 
    225 unsigned long Build_Frame(void const *dataptr, unsigned short framenumber, void *buffptr)
    226 {
    227 #ifdef FIXIT_SCORE_CRASH
    228 	char *ptr;
    229 	unsigned long offcurr, offdiff;
    230 #else
    231 	char *ptr, *lockptr;//, *uncomp_ptr;
    232 	unsigned long offcurr, off16, offdiff;
    233 #endif
    234 	unsigned long offset[SUBFRAMEOFFS];
    235 	KeyFrameHeaderType *keyfr;
    236 	unsigned short buffsize, currframe, subframe;
    237 	unsigned long length = 0;
    238 	char frameflags;
    239 	unsigned long return_value;
    240 	char *temp_shape_ptr;
    241 
    242 	//
    243 	// valid pointer??
    244 	//
    245 	Length = 0;
    246 	if ( !dataptr || !buffptr ) {
    247 		return(0);
    248 	}
    249 
    250 	//
    251 	// look at header then check that frame to build is not greater
    252 	// than total frames
    253 	//
    254 	keyfr = (KeyFrameHeaderType *) dataptr;
    255 
    256 	if ( framenumber >= keyfr->frames ) {
    257 		return(0);
    258 	}
    259 
    260 
    261 	if (UseBigShapeBuffer) {
    262 		/*
    263 		** If we havnt yet allocated memory for uncompressed shapes then do so now.
    264 		**
    265 		*/
    266 		if (!BigShapeBufferStart) {
    267 			BigShapeBufferStart = (char*)Alloc(BigShapeBufferLength, MEM_NORMAL);
    268 			BigShapeBufferPtr = BigShapeBufferStart;
    269 
    270 			/*
    271 			** Allocate memory for theater specific uncompressed shapes
    272 			*/
    273 			TheaterShapeBufferStart = (char*) Alloc (TheaterShapeBufferLength, MEM_NORMAL);
    274 			TheaterShapeBufferPtr = TheaterShapeBufferStart;
    275 		}
    276 
    277 		/*
    278 		** If we are running out of memory (<10k left) for uncompressed shapes
    279 		** then allocate some more.
    280 		*/
    281 		if (( (unsigned)BigShapeBufferStart + BigShapeBufferLength) - (unsigned)BigShapeBufferPtr < 128000) {
    282 			ReallocShapeBufferFlag = TRUE;
    283 		}
    284 
    285 		/*
    286 		** If this animation was not previously uncompressed then
    287 		** allocate memory to keep the pointers to the uncompressed data
    288 		** for these animation frames
    289 		*/
    290 		if (keyfr->x != UNCOMPRESS_MAGIC_NUMBER) {
    291 			keyfr->x = UNCOMPRESS_MAGIC_NUMBER;
    292 			if (IsTheaterShape) {
    293 				keyfr->y = TheaterSlotsUsed;
    294 				TheaterSlotsUsed++;
    295 			} else {
    296 				keyfr->y = TotalSlotsUsed;
    297 				TotalSlotsUsed++;
    298 			}
    299 			/*
    300 			** Allocate and clear the memory for the shape info
    301 			*/
    302 			KeyFrameSlots[keyfr->y]= new char *[keyfr->frames];
    303 			memset (KeyFrameSlots[keyfr->y] , 0 , keyfr->frames*4);
    304 		}
    305 
    306 		/*
    307 		** If this frame was previously uncompressed then just return
    308 		** a pointer to the raw data
    309 		*/
    310 		if (*(KeyFrameSlots[keyfr->y]+framenumber)) {
    311 			if (IsTheaterShape) {
    312 				return ((unsigned long)TheaterShapeBufferStart + (unsigned long)*(KeyFrameSlots[keyfr->y]+framenumber));
    313 			} else {
    314 				return ((unsigned long)BigShapeBufferStart + (unsigned long)*(KeyFrameSlots[keyfr->y]+framenumber));
    315 			}
    316 		}
    317 	}
    318 
    319 	// calc buff size
    320 	buffsize = keyfr->width * keyfr->height;
    321 
    322 	// get offset into data
    323 	ptr = (char *)Add_Long_To_Pointer( dataptr, (((unsigned long)framenumber << 3) + sizeof(KeyFrameHeaderType)) );
    324 	Mem_Copy( ptr, &offset[0], 12L );
    325 	frameflags = (char)(offset[0] >> 24);
    326 
    327 
    328 	if ( (frameflags & KF_KEYFRAME) ) {
    329 
    330 		ptr = (char *)Add_Long_To_Pointer( dataptr, (offset[0] & 0x00FFFFFFL) );
    331 
    332 		if (keyfr->flags & 1 ) {
    333 			ptr = (char *)Add_Long_To_Pointer( ptr, 768L );
    334 		}
    335 		length = LCW_Uncompress( ptr, buffptr, buffsize );
    336 	} else {	// key delta or delta
    337 
    338 		if ( (frameflags & KF_DELTA) ) {
    339 			currframe = (unsigned short)offset[1];
    340 
    341 			ptr = (char *)Add_Long_To_Pointer( dataptr, (((unsigned long)currframe << 3) + sizeof(KeyFrameHeaderType)) );
    342 			Mem_Copy( ptr, &offset[0], (long)(SUBFRAMEOFFS * sizeof(unsigned long)) );
    343 		}
    344 
    345 		// key frame
    346 		offcurr = offset[1] & 0x00FFFFFFL;
    347 
    348 		// key delta
    349 		offdiff = (offset[0] & 0x00FFFFFFL) - offcurr;
    350 
    351 		ptr = (char *)Add_Long_To_Pointer( dataptr, offcurr );
    352 
    353 		if (keyfr->flags & 1 ) {
    354 			ptr = (char *)Add_Long_To_Pointer( ptr, 768L );
    355 		}
    356 
    357 #ifndef FIXIT_SCORE_CRASH
    358 		off16 = (unsigned long)lockptr & 0x00003FFFL;
    359 #endif
    360 
    361 		length = LCW_Uncompress( ptr, buffptr, buffsize );
    362 
    363 		if (length > buffsize) {
    364 			return(0);
    365 		}
    366 
    367 #ifndef FIXIT_SCORE_CRASH
    368 		if ( ((offset[2] & 0x00FFFFFFL) - offcurr) >= (0x00010000L - off16) ) {
    369 
    370 			ptr = (char *)Add_Long_To_Pointer( ptr, offdiff );
    371 			off16 = (unsigned long)ptr & 0x00003FFFL;
    372 
    373 			offcurr += offdiff;
    374 			offdiff = 0;
    375 		}
    376 #endif
    377 
    378 		length = buffsize;
    379 		Apply_Delta(buffptr, Add_Long_To_Pointer(ptr, offdiff));
    380 
    381 		if ( (frameflags & KF_DELTA) ) {
    382 			// adjust to delta after the keydelta
    383 
    384 			currframe++;
    385 			subframe = 2;
    386 
    387 			while (currframe <= framenumber) {
    388 				offdiff = (offset[subframe] & 0x00FFFFFFL) - offcurr;
    389 
    390 #ifndef FIXIT_SCORE_CRASH
    391 				if ( ((offset[subframe+2] & 0x00FFFFFFL) - offcurr) >= (0x00010000L - off16) ) {
    392 
    393 					ptr = (char *)Add_Long_To_Pointer( ptr, offdiff );
    394 					off16 = (unsigned long)lockptr & 0x00003FFFL;
    395 
    396 					offcurr += offdiff;
    397 					offdiff = 0;
    398 				}
    399 #endif
    400 
    401 				length = buffsize;
    402 				Apply_Delta(buffptr, Add_Long_To_Pointer(ptr, offdiff));
    403 
    404 				currframe++;
    405 				subframe += 2;
    406 
    407 				if ( subframe >= (SUBFRAMEOFFS - 1) &&
    408 					currframe <= framenumber ) {
    409 					Mem_Copy( Add_Long_To_Pointer( dataptr,
    410 									(((unsigned long)currframe << 3) +
    411 									sizeof(KeyFrameHeaderType)) ),
    412 						&offset[0], (long)(SUBFRAMEOFFS * sizeof(unsigned long)) );
    413 					subframe = 0;
    414 				}
    415 			}
    416 		}
    417 	}
    418 
    419 
    420 	if (UseBigShapeBuffer) {
    421 		/*
    422 		** Save the uncompressed shape data so we dont have to uncompress it
    423 		** again next time its drawn.
    424 		** We keep a space free before the raw shape data so we can add line
    425 		** header info before the shape is drawn for the first time
    426 		*/
    427 
    428 		if (IsTheaterShape) {
    429 			/*
    430 			** Shape is a theater specific shape
    431 			*/
    432 			return_value = (unsigned long) TheaterShapeBufferPtr;
    433 			temp_shape_ptr = TheaterShapeBufferPtr + keyfr->height+sizeof(ShapeHeaderType);
    434 			/*
    435 			** align the actual shape data
    436 			*/
    437 			if (3 & (unsigned)temp_shape_ptr) {
    438 				temp_shape_ptr = (char *) ((unsigned)(temp_shape_ptr + 3) & 0xfffffffc);
    439 			}
    440 
    441 			memcpy (temp_shape_ptr , buffptr , length);
    442 			((ShapeHeaderType *)TheaterShapeBufferPtr)->draw_flags = -1;						//Flag that headers need to be generated
    443 			((ShapeHeaderType *)TheaterShapeBufferPtr)->shape_data = temp_shape_ptr - (unsigned)TheaterShapeBufferStart;		//pointer to old raw shape data
    444 			((ShapeHeaderType *)TheaterShapeBufferPtr)->shape_buffer = 1;	//Theater buffer
    445 			*(KeyFrameSlots[keyfr->y]+framenumber) = TheaterShapeBufferPtr - (unsigned)TheaterShapeBufferStart;
    446 			TheaterShapeBufferPtr = (char*)(length + (unsigned)temp_shape_ptr);
    447 			/*
    448 			** Align the next shape
    449 			*/
    450 			if (3 & (unsigned)TheaterShapeBufferPtr) {
    451 				TheaterShapeBufferPtr = (char *)((unsigned)(TheaterShapeBufferPtr + 3) & 0xfffffffc);
    452 			}
    453 			Length = length;
    454 			return (return_value);
    455 
    456 		} else {
    457 
    458 
    459 			return_value=(unsigned long)BigShapeBufferPtr;
    460 			temp_shape_ptr = BigShapeBufferPtr + keyfr->height+sizeof(ShapeHeaderType);
    461 			/*
    462 			** align the actual shape data
    463 			*/
    464 			if (3 & (unsigned)temp_shape_ptr) {
    465 				temp_shape_ptr = (char *) ((unsigned)(temp_shape_ptr + 3) & 0xfffffffc);
    466 			}
    467 			memcpy (temp_shape_ptr , buffptr , length);
    468 			((ShapeHeaderType *)BigShapeBufferPtr)->draw_flags = -1;						//Flag that headers need to be generated
    469 			((ShapeHeaderType *)BigShapeBufferPtr)->shape_data = temp_shape_ptr - (unsigned)BigShapeBufferStart;		//pointer to old raw shape data
    470 			((ShapeHeaderType *)BigShapeBufferPtr)->shape_buffer = 0;	//Normal Big Shape Buffer
    471 			*(KeyFrameSlots[keyfr->y]+framenumber) = BigShapeBufferPtr - (unsigned)BigShapeBufferStart;
    472 			BigShapeBufferPtr = (char*)(length + (unsigned)temp_shape_ptr);
    473 			// Align the next shape
    474 			if (3 & (unsigned)BigShapeBufferPtr) {
    475 				BigShapeBufferPtr = (char *)((unsigned)(BigShapeBufferPtr + 3) & 0xfffffffc);
    476 			}
    477 			Length = length;
    478 			return (return_value);
    479 		}
    480 
    481 	} else {
    482 		return ((unsigned long)buffptr);
    483 	}
    484 }
    485 
    486 
    487 /***********************************************************************************************
    488  * Get_Build_Frame_Count -- Fetches the number of frames in data block.                        *
    489  *                                                                                             *
    490  *    Use this routine to determine the number of shapes within the data block.                *
    491  *                                                                                             *
    492  * INPUT:   dataptr  -- Pointer to the keyframe shape data block.                              *
    493  *                                                                                             *
    494  * OUTPUT:  Returns with the number of shapes in the data block.                               *
    495  *                                                                                             *
    496  * WARNINGS:   none                                                                            *
    497  *                                                                                             *
    498  * HISTORY:                                                                                    *
    499  *   06/25/1995 JLB : Commented.                                                               *
    500  *=============================================================================================*/
    501 unsigned short Get_Build_Frame_Count(void const *dataptr)
    502 {
    503 	if (dataptr) {
    504 		return(((KeyFrameHeaderType const *)dataptr)->frames);
    505 	}
    506 	return(0);
    507 }
    508 
    509 
    510 unsigned short Get_Build_Frame_X(void const *dataptr)
    511 {
    512 	if (dataptr) {
    513 		return(((KeyFrameHeaderType const *)dataptr)->x);
    514 	}
    515 	return(0);
    516 }
    517 
    518 
    519 unsigned short Get_Build_Frame_Y(void const *dataptr)
    520 {
    521 	if (dataptr) {
    522 		return(((KeyFrameHeaderType const *)dataptr)->y);
    523 	}
    524 	return(0);
    525 }
    526 
    527 
    528 /***********************************************************************************************
    529  * Get_Build_Frame_Width -- Fetches the width of the shape image.                              *
    530  *                                                                                             *
    531  *    Use this routine to fetch the width of the shapes within the keyframe shape data block.  *
    532  *    All shapes within the block have the same width.                                         *
    533  *                                                                                             *
    534  * INPUT:   dataptr  -- Pointer to the keyframe shape data block.                              *
    535  *                                                                                             *
    536  * OUTPUT:  Returns with the width of the shapes in the block -- expressed in pixels.          *
    537  *                                                                                             *
    538  * WARNINGS:   none                                                                            *
    539  *                                                                                             *
    540  * HISTORY:                                                                                    *
    541  *   06/25/1995 JLB : Commented                                                                *
    542  *=============================================================================================*/
    543 unsigned short Get_Build_Frame_Width(void const *dataptr)
    544 {
    545 	if (dataptr) {
    546 		return(((KeyFrameHeaderType const *)dataptr)->width);
    547 	}
    548 	return(0);
    549 }
    550 
    551 
    552 /***********************************************************************************************
    553  * Get_Build_Frame_Height -- Fetches the height of the shape image.                            *
    554  *                                                                                             *
    555  *    Use this routine to fetch the height of the shapes within the keyframe shape data block. *
    556  *    All shapes within the block have the same height.                                        *
    557  *                                                                                             *
    558  * INPUT:   dataptr  -- Pointer to the keyframe shape data block.                              *
    559  *                                                                                             *
    560  * OUTPUT:  Returns with the height of the shapes in the block -- expressed in pixels.         *
    561  *                                                                                             *
    562  * WARNINGS:   none                                                                            *
    563  *                                                                                             *
    564  * HISTORY:                                                                                    *
    565  *   06/25/1995 JLB : Commented                                                                *
    566  *=============================================================================================*/
    567 unsigned short Get_Build_Frame_Height(void const *dataptr)
    568 {
    569 	if (dataptr) {
    570 		return(((KeyFrameHeaderType const *)dataptr)->height);
    571 	}
    572 	return(0);
    573 }
    574 
    575 
    576 bool Get_Build_Frame_Palette(void const * dataptr, void * palette)
    577 {
    578 	if (dataptr && (((KeyFrameHeaderType const *)dataptr)->flags & 1)) {
    579 		char const * ptr = (char const *)Add_Long_To_Pointer( dataptr,
    580 							( (( (long)sizeof(unsigned long) << 1) *
    581 								((KeyFrameHeaderType *) dataptr)->frames ) +
    582 							16 + sizeof(KeyFrameHeaderType) ) );
    583 
    584 		memcpy(palette, ptr, 768L);
    585 		return(true);
    586 	}
    587 	return(false);
    588 }