CnC_Remastered_Collection

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

WSA.CPP (46478B)


      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: g:/library/source/rcs/./wsa.c 1.16 1994/05/20 15:35:27 joe_bostic Exp $ */
     17 /***************************************************************************
     18  **   C O N F I D E N T I A L --- W E S T W O O D   A S S O C I A T E S   **
     19  ***************************************************************************
     20  *                                                                         *
     21  *                 Project Name : Library Animation System                 *
     22  *                                                                         *
     23  *                    File Name : WSA.C                                    *
     24  *                                                                         *
     25  *                   Programmer : Michael Legg                             *
     26  *                                                                         *
     27  *                   Start Date : November 20, 1991                        *
     28  *                                                                         *
     29  *-------------------------------------------------------------------------*
     30  *   There are many different ways that the user can use the WSA library   *
     31  * module.  The options are as follows :                                   *
     32  *                                                                         *
     33  *   System Allocation vs User Buffer - The user may request that the      *
     34  *       system allocate the needed buffer from the heap or the user may	*
     35  *       pass his own buffer in for the animator to use.                   *
     36  *                                                                         *
     37  *   Resident vs File based - If there is enough RAM, the user may put the *
     38  *       entire animation into RAM for fastest animations.  If there is    *
     39  *       not enouph RAM, the system will automatically make it so each     *
     40  *       frame will be read off disk when needed.                          *
     41  *                                                                         *
     42  *   Direct to Page vs Use of a user buffer -- Noramally Direct to page		*
     43  *       is the best method both in speed and in RAM need to hold anim.    *
     44  *       One may want to use the write to user buffer method if they       *
     45  *       are using the animation in a non sequencial order.                *
     46  *                                                                         *
     47  *-------------------------------------------------------------------------*
     48  * Functions:                                                              *
     49  *   Animate_Frame -- Displays a frame of a given animation                *
     50  *   Get_Animation_Frame_Count --  Return Number of frames in an animation.  *
     51  *   Get_Animation_X -- Gets the x from an animation                       *
     52  *   Get_Animation_Y -- Gets the y from an animation                       *
     53  *   Get_Animation_Width -- Gets the width from an animation               *
     54  *   Get_Animation_Height -- The height of the animation we are processing *
     55  *   Apply_Delta -- Copies frame into delta buffer, then applies to target *
     56  *   Close_Animation -- Close the animation, freeing the space if necessary*
     57  *   Get_File_Frame_Offset -- Get offset of a delta frame from animate file*
     58  *   Get_Resident_Frame_Offset -- Gets frame offset of animate file in RAM *
     59  *   Open_Animation -- Opens an animation file and reads into buffer       *
     60  *- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     61 
     62 
     63 #include <wwstd.h>
     64 #include "wsa.h"
     65 #include <wwmem.h>
     66 #include <file.h>
     67 #include <misc.h>
     68 #include <iff.h>
     69 //#include <mem.h>
     70 #include <string.h>
     71 
     72 //
     73 // WSA animation header allocation type.
     74 // If we need more then 8 flags for the flags variable, we can combine
     75 // USER_ALLOCATED with SYS_ALLOCATED  and combine FILE with RESIDENT.
     76 //
     77 #define	WSA_USER_ALLOCATED 	0x01
     78 #define	WSA_SYS_ALLOCATED  	0x02
     79 #define	WSA_FILE           	0x04
     80 #define	WSA_RESIDENT       	0x08
     81 #define	WSA_TARGET_IN_BUFFER	0x10
     82 #define	WSA_LINEAR_ONLY		0x20
     83 #define	WSA_FRAME_0_ON_PAGE  0x40
     84 #define	WSA_AMIGA_ANIMATION  0x80
     85 #define	WSA_PALETTE_PRESENT	0x100
     86 #define	WSA_FRAME_0_IS_DELTA	0x200
     87 
     88 // These are used to call Apply_XOR_Delta_To_Page_Or_Viewport() to setup flags parameter.  If
     89 // These change, make sure and change their values in lp_asm.asm.
     90 #define	DO_XOR					0x0
     91 #define	DO_COPY					0x01
     92 #define	TO_VIEWPORT				0x0
     93 #define	TO_PAGE					0x02
     94 
     95 
     96 
     97 
     98 typedef struct {
     99 	unsigned short current_frame;
    100 	unsigned short total_frames;
    101 	unsigned short pixel_x;
    102 	unsigned short pixel_y;
    103 	unsigned short pixel_width;
    104 	unsigned short pixel_height;
    105 	unsigned short largest_frame_size;
    106 	char *delta_buffer;
    107 	char *file_buffer;
    108 	char file_name[ 13 ];
    109 	short flags;
    110 	// New fields that animate does not know about below this point. SEE EXTRA_charS_ANIMATE_NOT_KNOW_ABOUT
    111 	short file_handle;
    112 	unsigned long anim_mem_size;
    113 } SysAnimHeaderType;
    114 
    115 // NOTE:"THIS IS A BAD THING. SINCE sizeof(SysAnimHeaderType) CHANGED, THE ANIMATE.EXE
    116 // UTILITY DID NOT KNOW I UPDATED IT, IT ADDS IT TO largest_frame_size BEFORE SAVING
    117 // IT TO THE FILE.  THIS MEANS I HAVE TO ADD THESE charS ON NOW FOR IT TO WORK.
    118 #define EXTRA_charS_ANIMATE_NOT_KNOW_ABOUT	(sizeof(short) + sizeof(unsigned long))
    119 
    120 
    121 //
    122 // Header structure for the file.
    123 // NOTE:  The 'total_frames' field is used to differentiate between Amiga and IBM
    124 // animations.  Amiga animations have the HIGH bit set.
    125 //
    126 typedef struct {
    127 	unsigned short total_frames;
    128 	unsigned short pixel_x;
    129 	unsigned short pixel_y;
    130 	unsigned short pixel_width;
    131 	unsigned short pixel_height;
    132 	unsigned short largest_frame_size;
    133 	short	flags;
    134 	unsigned long frame0_offset;
    135 	unsigned long frame0_end;
    136 	/* unsigned long data_seek_offset, unsigned short frame_size ... */
    137 } WSA_FileHeaderType;
    138 
    139 #define WSA_FILE_HEADER_SIZE	( sizeof(WSA_FileHeaderType) - (2 * sizeof(unsigned long)) )
    140 
    141 /*=========================================================================*/
    142 /* The following PRIVATE functions are in this file:                       */
    143 /*=========================================================================*/
    144 
    145 PRIVATE unsigned long Get_Resident_Frame_Offset( char *file_buffer, int frame );
    146 PRIVATE unsigned long Get_File_Frame_Offset( int file_handle, int frame, int palette_adjust);
    147 PRIVATE BOOL Apply_Delta(SysAnimHeaderType *sys_header, int curr_frame, char *dest_ptr, int dest_w);
    148 /*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
    149 
    150 
    151 /***************************************************************************
    152  * OPEN_ANIMATION -- Opens an animation file and reads into buffer         *
    153  *                                                                         *
    154  * INPUT:   char *file_name of animation sequence file.                    *
    155  *          char *user_buffer pointer if one exists  (NULL ok)             *
    156  *          unsigned long user_buffer_size if known  (NULL ok)                     *
    157  *          WSAOpenType user_flags - flags on how to open.                 *
    158  *          unsigned char *palette - pointer to palette space for return (NULL ok) *
    159  *                                                                         *
    160  * OUTPUT:  void *pointer to animation data.  Must be used for all 			*
    161  *               other WSA calls.                                          *
    162  *                                                                         *
    163  * WARNINGS: May return NULL, please check.                                *
    164  *                                                                         *
    165  * HISTORY:                                                                *
    166  *   11/26/1991  SB : Created.                                             *
    167  *=========================================================================*/
    168 void * __cdecl Open_Animation(char const *file_name, char *user_buffer, long user_buffer_size, WSAOpenType user_flags, unsigned char *palette)
    169 {
    170 	int						fh, anim_flags;
    171 	int						palette_adjust;
    172 	unsigned int						offsets_size;
    173 	unsigned int						frame0_size;
    174 	long						target_buffer_size, delta_buffer_size, file_buffer_size;
    175 	long						max_buffer_size,    min_buffer_size;
    176 	char						*sys_anim_header_buffer;
    177 	char						*target_buffer;
    178 	char						*delta_buffer, *delta_back;
    179 	SysAnimHeaderType		*sys_header;
    180 	WSA_FileHeaderType	file_header;
    181 
    182 	/*======================================================================*/
    183 	/* Open the file to get the header information									*/
    184 	/*======================================================================*/
    185 
    186 	anim_flags	= 0;
    187 	fh				= Open_File(file_name, READ);
    188 	Read_File(fh, (char *) &file_header, sizeof(WSA_FileHeaderType));
    189 
    190 	/*======================================================================*/
    191 	/* If the file has an attached palette then if we have a valid palette	*/
    192 	/*		pointer we need to read it in.												*/
    193 	/*======================================================================*/
    194 
    195 	if (file_header.flags & 1) {
    196 		anim_flags		|= WSA_PALETTE_PRESENT;
    197 		palette_adjust	 = 768;
    198 
    199 		if (palette != NULL) {
    200 			Seek_File(fh, sizeof(unsigned long) * (file_header.total_frames), SEEK_CUR);
    201 			Read_File(fh, palette, 768L);
    202 		}
    203 
    204 	} else {
    205 		palette_adjust = 0;
    206 	}
    207 
    208 	// Check for flag from ANIMATE indicating that this animation was
    209 	// created from a .LBM and a .ANM.  These means that the first
    210 	// frame is a XOR Delta from a picture, not black.
    211 	if (file_header.flags & 2) {
    212 		anim_flags		|= WSA_FRAME_0_IS_DELTA;
    213 	}
    214 
    215 
    216 	// Get the total file size minus the size of the first frame and the size
    217 	// of the file header.  These will not be read in to save even more space.
    218 	file_buffer_size = Seek_File(fh, 0L, SEEK_END);
    219 
    220 	if (file_header.frame0_offset) {
    221 		long tlong;
    222 
    223 		tlong = file_header.frame0_end - file_header.frame0_offset;
    224 		frame0_size = (unsigned short) tlong;
    225 	}
    226 	else {
    227 		anim_flags |= WSA_FRAME_0_ON_PAGE;
    228 		frame0_size = 0;
    229 	}
    230 
    231 	file_buffer_size -= palette_adjust + frame0_size + WSA_FILE_HEADER_SIZE;
    232 
    233 	// We need to determine the buffer sizes required for the animation.  At a
    234 	// minimum, we need a target buffer for the uncompressed frame and a delta
    235 	// buffer for the delta data.  We may be able to make the file resident,
    236 	// so we will determine the file size.
    237 	//
    238 	// If the target buffer is in the user buffer
    239 	// Then figure its size
    240 	// and set the allocation flag
    241 	// Else size is zero.
    242 	//
    243 	if (user_flags & WSA_OPEN_DIRECT) {
    244 	 	target_buffer_size = 0L;
    245 	}
    246 	else {
    247 		anim_flags |= WSA_TARGET_IN_BUFFER;
    248 		target_buffer_size = (unsigned long) file_header.pixel_width * file_header.pixel_height;
    249 	}
    250 
    251 	// NOTE:"THIS IS A BAD THING. SINCE sizeof(SysAnimHeaderType) CHANGED, THE ANIMATE.EXE
    252 	// UTILITY DID NOT KNOW I UPDATED IT, IT ADDS IT TO largest_frame_size BEFORE SAVING
    253 	// IT TO THE FILE.  THIS MEANS I HAVE TO ADD THESE charS ON NOW FOR IT TO WORK.
    254 	delta_buffer_size  = (unsigned long) file_header.largest_frame_size + EXTRA_charS_ANIMATE_NOT_KNOW_ABOUT;
    255 	min_buffer_size = target_buffer_size + delta_buffer_size;
    256 	max_buffer_size = min_buffer_size + file_buffer_size;
    257 
    258 	// check to see if buffer size is big enough for at least min required
    259 	if (user_buffer && (user_buffer_size < min_buffer_size)) {
    260 		Close_File(fh);
    261 		return(NULL);
    262 	}
    263 
    264 	// A buffer was not passed in, so do allocations
    265 	if (user_buffer == NULL) {
    266 
    267 		// If the user wants it from the disk, then let us give it to him,
    268 		// otherwise, try to give a max allocation he can have.
    269 		if (user_flags & WSA_OPEN_FROM_DISK) {
    270 			user_buffer_size = min_buffer_size;
    271 		}
    272 		// else no buffer size, then try max configuration.
    273 		else if (!user_buffer_size) {
    274 			user_buffer_size = max_buffer_size;
    275 		}
    276 		// else if buffer specified is less then max needed, give min.
    277 		else if (user_buffer_size < max_buffer_size) {
    278 			user_buffer_size = min_buffer_size;
    279 		}
    280 		// otherwise we only want to alloc what we need.
    281 		else {
    282 			user_buffer_size = max_buffer_size;
    283 		}
    284 
    285 
    286 		// Check to see if enough RAM available for buffer_size.
    287 		if (user_buffer_size > Ram_Free(MEM_NORMAL)) {
    288 
    289  			// If not enough room for even the min, return no buffer.
    290 
    291 			if (min_buffer_size > Ram_Free(MEM_NORMAL)) {
    292 				Close_File(fh);
    293 				return(NULL);
    294 			}
    295 
    296 			// Else make buffer size the min and allocate it.
    297 			user_buffer_size = min_buffer_size;
    298 		}
    299 
    300 		// allocate buffer needed
    301 		user_buffer = (char *) Alloc(user_buffer_size, MEM_CLEAR);
    302 
    303 		anim_flags |= WSA_SYS_ALLOCATED;
    304 	}
    305 	else {
    306 		// Check to see if the user_buffer_size should be min or max.
    307 		if ((user_flags & WSA_OPEN_FROM_DISK) || (user_buffer_size < max_buffer_size)) {
    308 		 	user_buffer_size = min_buffer_size;
    309 		}
    310 		else {
    311 		 	user_buffer_size = max_buffer_size;
    312 		}
    313 		anim_flags |= WSA_USER_ALLOCATED;
    314 	}
    315 
    316 
    317 	// Set the pointers to the RAM buffers
    318 	sys_anim_header_buffer = user_buffer;
    319 	target_buffer = (char *) Add_Long_To_Pointer(sys_anim_header_buffer, sizeof(SysAnimHeaderType));
    320 	delta_buffer  = (char *) Add_Long_To_Pointer(target_buffer, target_buffer_size);
    321 
    322 	//	Clear target buffer if it is in the user buffer.
    323 	if (target_buffer_size) {
    324 		memset( target_buffer, 0, (unsigned short) target_buffer_size );
    325 	}
    326 
    327 	// Poke data into the system animation header (start of user_buffer)
    328 	// current_frame is set to total_frames so that Animate_Frame() knows that
    329 	// it needs to clear the target buffer.
    330 
    331 	sys_header = ( SysAnimHeaderType * ) sys_anim_header_buffer;
    332 	sys_header -> current_frame =
    333 	sys_header -> total_frames  = file_header.total_frames;
    334 	sys_header -> pixel_x		 = file_header.pixel_x;
    335 	sys_header -> pixel_y		 = file_header.pixel_y;
    336 	sys_header -> pixel_width   = file_header.pixel_width;
    337 	sys_header -> pixel_height  = file_header.pixel_height;
    338 	sys_header -> anim_mem_size = user_buffer_size;
    339 	sys_header -> delta_buffer  = delta_buffer;
    340 	sys_header -> largest_frame_size =
    341                  (unsigned short) (delta_buffer_size - sizeof(SysAnimHeaderType));
    342 
    343 	strcpy(sys_header->file_name, file_name);
    344 
    345 	// Figure how much room the frame offsets take up in the file.
    346 	// Add 2 - one for the wrap around and one for the final end offset.
    347 	offsets_size = (file_header.total_frames + 2) << 2;
    348 
    349 	// Can the user_buffer_size handle the maximum case buffer?
    350 	if ( user_buffer_size == max_buffer_size) {
    351 
    352 		//
    353 		//	set the file buffer pointer,
    354 		// Skip over the header information.
    355 		// Read in the offsets.
    356 		// Skip over the first frame.
    357 		// Read in remaining frames.
    358 		//
    359 
    360 		sys_header->file_buffer = (char *)Add_Long_To_Pointer(delta_buffer,sys_header->largest_frame_size);
    361 		Seek_File( fh, WSA_FILE_HEADER_SIZE, SEEK_SET);
    362 		Read_File( fh, sys_header->file_buffer, offsets_size);
    363 		Seek_File( fh, frame0_size + palette_adjust, SEEK_CUR);
    364 		Read_File( fh, sys_header->file_buffer + offsets_size,
    365 		           file_buffer_size - offsets_size);
    366 
    367 		//
    368 		// Find out if there is an ending value for the last frame.
    369 		// If there is not, then this animation will not be able to
    370 		// loop back to the beginning.
    371 		//
    372 		if (Get_Resident_Frame_Offset( sys_header->file_buffer, sys_header->total_frames + 1))
    373 			anim_flags |= WSA_RESIDENT;
    374 		else
    375 			anim_flags |= WSA_LINEAR_ONLY | WSA_RESIDENT;
    376 	}
    377 	else {	// buffer cannot handle max_size of buffer
    378 
    379 		if(Get_File_Frame_Offset( fh, sys_header->total_frames + 1, palette_adjust))
    380 			anim_flags |= WSA_FILE;
    381 		else
    382 			anim_flags |= WSA_LINEAR_ONLY | WSA_FILE;
    383 ////
    384 		sys_header->file_buffer = NULL;
    385 	}
    386 
    387 	// Figure where to back load frame 0 into the delta buffer.
    388 	delta_back = (char *)Add_Long_To_Pointer(delta_buffer,
    389 					 sys_header->largest_frame_size - frame0_size);
    390 
    391 	// Read the first frame into the delta buffer and uncompress it.
    392 	// Then close it.
    393 	Seek_File( fh, WSA_FILE_HEADER_SIZE + offsets_size + palette_adjust, SEEK_SET);
    394 	Read_File( fh, delta_back, frame0_size);
    395 
    396 	// We do not use the file handle when it is in RAM.
    397 	if (anim_flags & WSA_RESIDENT) {
    398 		sys_header -> file_handle = (short) -1;
    399 	 	Close_File(fh);
    400 	}
    401 	else {
    402 		sys_header -> file_handle = (short)fh;
    403 	}
    404 
    405 	LCW_Uncompress(delta_back, delta_buffer, sys_header->largest_frame_size);
    406 
    407 	// Finally set the flags,
    408 	sys_header->flags = (short)anim_flags;
    409 
    410 	// return valid handle
    411 	return( user_buffer );
    412 }
    413 
    414 
    415 /***************************************************************************
    416  * CLOSE_ANIMATION -- Close the animation, freeing the space if necessary. *
    417  *                                                                         *
    418  * INPUT:      void *handle to the animation data buffer                   *
    419  *                                                                         *
    420  * OUTPUT:     none                                                        *
    421  *                                                                         *
    422  * WARNINGS:   handle MUST have been returned by Open_Animation            *
    423  *                                                                         *
    424  * HISTORY:                                                                *
    425  *   11/23/1991  ML : Created.                                             *
    426  *=========================================================================*/
    427 void __cdecl Close_Animation( void *handle )
    428 {
    429 	SysAnimHeaderType *sys_header;
    430 
    431 	// Assign our local system header pointer to the beginning of the handle space
    432 	sys_header = (SysAnimHeaderType *) handle;
    433 
    434 	// Close the WSA file in it was disk based.
    435 	if (sys_header->flags & WSA_FILE) {
    436 		Close_File(sys_header->file_handle);
    437 	}
    438 
    439 	// Check to see if the buffer was allocated OR the programmer provided the buffer
    440 	if (handle && sys_header->flags & WSA_SYS_ALLOCATED) {
    441 		Free(handle);
    442 	}
    443 }
    444 
    445 /***************************************************************************
    446  * ANIMATE_FRAME -- Displays a frame of a given animation                  *
    447  *                                                                         *
    448  * INPUT:   void *handle to the animation.                                 *
    449  *          int frame_number wanted to be displayed                       *
    450  *          int x_pixel position of left side of animation on page        *
    451  *          int y_pixel position of top of animation on page              *
    452  *                                                                         *
    453  * OUTPUT:  BOOL if successfull or not.                                   *
    454  *                                                                         *
    455  * WARNINGS:                                                               *
    456  *                                                                         *
    457  * HISTORY:                                                                *
    458  *   11/27/1991  SB : Created.                                             *
    459  *=========================================================================*/
    460 //#pragma off (unreferenced)
    461 BOOL __cdecl Animate_Frame(void *handle, GraphicViewPortClass& view,
    462                          int frame_number, int x_pixel, int y_pixel,
    463                          WSAType flags_and_prio, void *magic_cols, void *magic)
    464 {
    465 	SysAnimHeaderType 	*sys_header;		// fix up the void pointer past in.
    466 	int 						curr_frame;			// current frame we are on.
    467 	int						total_frames;		// number of frames in anim.
    468 	int						distance;			// distance to desired frame.
    469 	int						search_dir;			// direcion to search for desired frame.
    470 	int						search_frames;		// How many frames to search.
    471 	int						loop;					// Just a loop varible.
    472 	char						*frame_buffer;		// our destination.
    473 	BOOL						direct_to_dest;	// are we going directly to the destination?
    474 	int						dest_width;			// the width of the destination buffer or page.
    475 
    476 
    477 	// Assign local pointer to the beginning of the buffer where the system information
    478 	// resides
    479 	sys_header = (SysAnimHeaderType 	*)handle;
    480 
    481 	// Get the total number of frames
    482 	total_frames = sys_header->total_frames;
    483 
    484 	// Are the animation handle and the frame number valid?
    485 	if (!handle || (total_frames <= frame_number)) {
    486 		return FALSE;
    487 	}
    488 
    489 	if (view.Lock()!=TRUE) return (FALSE);
    490 
    491 	// Decide if we are going to a page or a viewport (part of a buffer).
    492 	dest_width	= view.Get_Width() + view.Get_XAdd() + view.Get_Pitch();
    493 
    494 	//
    495 	// adjust x_pixel and y_pixel by system pixel_x and pixel_y respectively.
    496 	//
    497 	x_pixel += (short)sys_header->pixel_x;
    498 	y_pixel += (short)sys_header->pixel_y;
    499 
    500 	//
    501 	// Check to see if we are using a buffer inside of the animation buffer or if
    502 	// it is being drawn directly to the destination page or buffer.
    503 	//
    504 	if (sys_header->flags & WSA_TARGET_IN_BUFFER) {
    505 		// Get a pointer to the frame in animation buffer.
    506 		frame_buffer = (char *)Add_Long_To_Pointer(sys_header, sizeof(SysAnimHeaderType));
    507 		direct_to_dest = FALSE;
    508 	}
    509 	else {
    510 		frame_buffer	= (char *)view.Get_Offset();
    511 		frame_buffer  += (y_pixel * dest_width) + x_pixel;
    512 		direct_to_dest	= TRUE;
    513 	}
    514 	//
    515 	// If current_frame is equal to tatal_frames, then no animations have taken place
    516 	// so must uncompress frame 0 in delta buffer to the frame_buffer/page if it
    517 	// exists.
    518 	//
    519 	if (sys_header->current_frame == total_frames) {
    520 
    521 		// Call apply delta telling it wether to copy or to xor depending on if the
    522 		// target is a page or a buffer.
    523 
    524 		if (!(sys_header->flags & WSA_FRAME_0_ON_PAGE)) {
    525 			if (direct_to_dest) {
    526 
    527 				// The last parameter says weather to copy or to XOR.  If  the
    528 				// first frame is a DELTA, then it must be XOR'd.  A TRUE is
    529 				// copy while FALSE is XOR.
    530 
    531 				Apply_XOR_Delta_To_Page_Or_Viewport(frame_buffer, sys_header->delta_buffer,
    532 				                        	sys_header->pixel_width, dest_width, //dest_width - sys_header->pixel_width,
    533 													(sys_header->flags & WSA_FRAME_0_IS_DELTA)? DO_XOR : DO_COPY);
    534 			}
    535 			else {
    536 				Apply_XOR_Delta(frame_buffer, sys_header->delta_buffer);
    537 			}
    538 		}
    539 		sys_header->current_frame = 0;
    540 	}
    541 
    542 	//
    543 	// Get the current frame
    544 	// If no looping aloud, are the trying to do it anyways?
    545 	//
    546 	curr_frame = sys_header->current_frame;
    547 #if (FALSE)
    548 	// This is commented out since we will let them loop even though they should
    549 	// not - it will be slower.
    550 	if ( (sys_header->flags & WSA_LINEAR_ONLY) && (frame_number < cur_frame) ) {
    551 		view.Unlock();
    552 	 	return FALSE;
    553 	}
    554 #endif
    555 
    556 	// Get absoulte distance from our current frame to the target frame
    557 	distance = ABS(curr_frame - frame_number);
    558 
    559 	// Assume we are searching right
    560 	search_dir = 1;
    561 
    562 	// Calculate the number of frames to search if we go right and wrap
    563 
    564 	if (frame_number > curr_frame) {
    565 		search_frames = total_frames - frame_number + curr_frame;
    566 
    567 		// Is going right faster than going backwards?
    568 		// Or are they trying to loop when the should not?
    569 		if ((search_frames < distance) && !(sys_header->flags & WSA_LINEAR_ONLY)) {
    570 			search_dir = -1;								// No, so go left
    571 		}
    572 		else {
    573 			search_frames = distance;
    574 		}
    575 	}
    576 	else {
    577 		search_frames = total_frames - curr_frame + frame_number;
    578 
    579 		// Is going right faster than going backwards?
    580 		// Or are they trying to loop when the should not?
    581 		if ((search_frames >= distance) || (sys_header->flags & WSA_LINEAR_ONLY)) {
    582 			search_dir = -1;								// No, so go left
    583 			search_frames = distance;
    584 		}
    585 	}
    586 
    587 	// Take care of the case when we are searching right (possibly right)
    588 
    589 	if (search_dir > 0) {
    590 		for (loop = 0; loop < search_frames; loop++) {
    591 
    592 			// Move the logical frame number ordinally right
    593 			curr_frame += search_dir;
    594 
    595 			Apply_Delta(sys_header, curr_frame, frame_buffer, dest_width);
    596 
    597 			// Adjust the current frame number, taking into consideration that we could
    598 			// have wrapped
    599 
    600 			if (curr_frame == total_frames) {
    601 				curr_frame = 0;
    602 			}
    603 		}
    604 	}
    605 	else {
    606 		for (loop = 0; loop < search_frames; loop++) {
    607 
    608 			// If we are going backwards and we are on frame 0, the delta to get
    609 			// to the last frame is the n + 1 delta (wrap delta)
    610 
    611 			if (curr_frame == 0) {
    612 				curr_frame = total_frames;
    613 			}
    614 
    615 			Apply_Delta(sys_header, curr_frame, frame_buffer, dest_width);
    616 
    617 			curr_frame += search_dir;
    618 		}
    619 	}
    620 
    621 	sys_header->current_frame = (short)frame_number;
    622 
    623 	// If we did this all in a hidden buffer, then copy it to the desired page or viewport.
    624 	if (sys_header->flags & WSA_TARGET_IN_BUFFER) {
    625 #if TRUE
    626 
    627 		Buffer_To_Page(x_pixel, y_pixel, sys_header->pixel_width, sys_header->pixel_height, frame_buffer, view);
    628 
    629 #else
    630 		int	flags = ((unsigned short)flags_and_prio & 0xFF00u) >> 12u;
    631 		int	pri = flags_and_prio & 0x00FF;
    632 
    633 		Buffer_Bitblit_To_LogicPage(x_pixel, y_pixel, sys_header->pixel_width,
    634 										  sys_header->pixel_height, 0, flags, frame_buffer, pri,
    635 										  magic_cols, magic);
    636 #endif
    637 	}
    638 
    639 	view.Unlock();
    640 	return TRUE;
    641 }
    642 /***************************************************************************
    643  * ANIMATE_FRAME -- Displays a frame of a given animation                  *
    644  *                                                                         *
    645  * INPUT:   void *handle to the animation.                                 *
    646  *          int frame_number wanted to be displayed                       *
    647  *          int x_pixel position of left side of animation on page        *
    648  *          int y_pixel position of top of animation on page              *
    649  *                                                                         *
    650  * OUTPUT:  BOOL if successfull or not.                                   *
    651  *                                                                         *
    652  * WARNINGS:                                                               *
    653  *                                                                         *
    654  * HISTORY:                                                                *
    655  *   11/27/1991  SB : Created.                                             *
    656  *=========================================================================*/
    657 //#pragma argsused
    658 #ifdef cuts
    659 BOOL __cdecl Animate_Frame(void *handle, GraphicViewPortClass& view,
    660                          int frame_number, int x_pixel, int y_pixel,
    661                          WSAType flags_and_prio, void *magic_cols, void *magic)
    662 {
    663 	SysAnimHeaderType 	*sys_header;		// fix up the void pointer past in.
    664 	int 						curr_frame;			// current frame we are on.
    665 	int						total_frames;		// number of frames in anim.
    666 	int						distance;			// distance to desired frame.
    667 	int						search_dir;			// direcion to search for desired frame.
    668 	int						search_frames;		// How many frames to search.
    669 	int						loop;					// Just a loop varible.
    670 	char						*frame_buffer;		// our destination.
    671 	BOOL						direct_to_dest;	// are we going directly to the destination?
    672 	int						dest_width;			// the width of the destination buffer or page.
    673 
    674 	// Assign local pointer to the beginning of the buffer where the system information
    675 	// resides
    676 	sys_header = (SysAnimHeaderType 	*)handle;
    677 
    678 	// Get the total number of frames
    679 	total_frames = sys_header->total_frames;
    680 
    681 	// Are the animation handle and the frame number valid?
    682 	if (!handle || (total_frames <= frame_number)) {
    683 		return FALSE;
    684 	}
    685 
    686 
    687 	// Decide if we are going to a page or a viewport (part of a buffer).
    688 	dest_width	= view.Get_Width() + view.Get_XAdd();
    689 
    690 	//
    691 	// adjust x_pixel and y_pixel by system pixel_x and pixel_y respectively.
    692 	//
    693 	x_pixel += (short)sys_header->pixel_x;
    694 	y_pixel += (short)sys_header->pixel_y;
    695 
    696 	//
    697 	// Check to see if we are using a buffer inside of the animation buffer or if
    698 	// it is being drawn directly to the destination page or buffer.
    699 	//
    700 	if (sys_header->flags & WSA_TARGET_IN_BUFFER) {
    701 		// Get a pointer to the frame in animation buffer.
    702 		frame_buffer = (char *)Add_Long_To_Pointer(sys_header, sizeof(SysAnimHeaderType));
    703 		direct_to_dest = FALSE;
    704 	}
    705 	else {
    706 		frame_buffer	= (char *)view.Get_Offset();
    707 		frame_buffer  += (y_pixel * dest_width) + x_pixel;
    708 		direct_to_dest	= TRUE;
    709 	}
    710 	//
    711 	// If current_frame is equal to tatal_frames, then no animations have taken place
    712 	// so must uncompress frame 0 in delta buffer to the frame_buffer/page if it
    713 	// exists.
    714 	//
    715 	if (sys_header->current_frame == total_frames) {
    716 
    717 		// Call apply delta telling it wether to copy or to xor depending on if the
    718 		// target is a page or a buffer.
    719 
    720 		if (!(sys_header->flags & WSA_FRAME_0_ON_PAGE)) {
    721 			if (direct_to_dest) {
    722 
    723 				// The last parameter says weather to copy or to XOR.  If  the
    724 				// first frame is a DELTA, then it must be XOR'd.  A TRUE is
    725 				// copy while FALSE is XOR.
    726 				Apply_XOR_Delta_To_Page_Or_Viewport(frame_buffer, sys_header->delta_buffer,
    727 				                        	sys_header->pixel_width, dest_width, //dest_width - sys_header->pixel_width,
    728 													(sys_header->flags & WSA_FRAME_0_IS_DELTA)? DO_XOR : DO_COPY);
    729 			}
    730 			else {
    731 				Apply_XOR_Delta(frame_buffer, sys_header->delta_buffer);
    732 			}
    733 		}
    734 		sys_header->current_frame = 0;
    735 	}
    736 
    737 	//
    738 	// Get the current frame
    739 	// If no looping aloud, are the trying to do it anyways?
    740 	//
    741 	curr_frame = sys_header->current_frame;
    742 #if (FALSE)
    743 	// This is commented out since we will let them loop even though they should
    744 	// not - it will be slower.
    745 	if ( (sys_header->flags & WSA_LINEAR_ONLY) && (frame_number < cur_frame) ) {
    746 	 	return FALSE;
    747 	}
    748 #endif
    749 
    750 	// Get absoulte distance from our current frame to the target frame
    751 	distance = ABS(curr_frame - frame_number);
    752 
    753 	// Assume we are searching right
    754 	search_dir = 1;
    755 
    756 	// Calculate the number of frames to search if we go right and wrap
    757 
    758 	if (frame_number > curr_frame) {
    759 		search_frames = total_frames - frame_number + curr_frame;
    760 
    761 		// Is going right faster than going backwards?
    762 		// Or are they trying to loop when the should not?
    763 		if ((search_frames < distance) && !(sys_header->flags & WSA_LINEAR_ONLY)) {
    764 			search_dir = -1;								// No, so go left
    765 		}
    766 		else {
    767 			search_frames = distance;
    768 		}
    769 	}
    770 	else {
    771 		search_frames = total_frames - curr_frame + frame_number;
    772 
    773 		// Is going right faster than going backwards?
    774 		// Or are they trying to loop when the should not?
    775 		if ((search_frames >= distance) || (sys_header->flags & WSA_LINEAR_ONLY)) {
    776 			search_dir = -1;								// No, so go left
    777 			search_frames = distance;
    778 		}
    779 	}
    780 
    781 	// Take care of the case when we are searching right (possibly right)
    782 
    783 	if (search_dir > 0) {
    784 		for (loop = 0; loop < search_frames; loop++) {
    785 
    786 			// Move the logical frame number ordinally right
    787 			curr_frame += search_dir;
    788 
    789 			Apply_Delta(sys_header, curr_frame, frame_buffer, dest_width);
    790 
    791 			// Adjust the current frame number, taking into consideration that we could
    792 			// have wrapped
    793 
    794 			if (curr_frame == total_frames) {
    795 				curr_frame = 0;
    796 			}
    797 		}
    798 	}
    799 	else {
    800 		for (loop = 0; loop < search_frames; loop++) {
    801 
    802 			// If we are going backwards and we are on frame 0, the delta to get
    803 			// to the last frame is the n + 1 delta (wrap delta)
    804 
    805 			if (curr_frame == 0) {
    806 				curr_frame = total_frames;
    807 			}
    808 
    809 			Apply_Delta(sys_header, curr_frame, frame_buffer, dest_width);
    810 
    811 			curr_frame += search_dir;
    812 		}
    813 	}
    814 
    815 	sys_header->current_frame = frame_number;
    816 
    817 	// If we did this all in a hidden buffer, then copy it to the desired page or viewport.
    818 	if (sys_header->flags & WSA_TARGET_IN_BUFFER) {
    819 #if TRUE
    820 
    821 		Buffer_To_Page(x_pixel, y_pixel, sys_header->pixel_width, sys_header->pixel_height, frame_buffer, view);
    822 
    823 #else
    824 		int	flags = ((unsigned short)flags_and_prio & 0xFF00u) >> 12u;
    825 		int	pri = flags_and_prio & 0x00FF;
    826 
    827 		Buffer_Bitblit_To_LogicPage(x_pixel, y_pixel, sys_header->pixel_width,
    828 										  sys_header->pixel_height, 0, flags, frame_buffer, pri,
    829 										  magic_cols, magic);
    830 #endif
    831 	}
    832 
    833 
    834 	return TRUE;
    835 }
    836 #endif
    837 
    838 
    839 /***************************************************************************
    840  * ANIMATE_FRAME_COUNT -- Return Number of frames in an animation.         *
    841  *                                                                         *
    842  * INPUT:   void *handle to the animation.                                 *
    843  *                                                                         *
    844  * OUTPUT:  int number of frames in animation.                            *
    845  *                                                                         *
    846  * WARNINGS:                                                               *
    847  *                                                                         *
    848  * HISTORY:                                                                *
    849  *   12/05/1991  SB : Created.                                             *
    850  *=========================================================================*/
    851 int __cdecl Get_Animation_Frame_Count(void *handle)
    852 {
    853 	SysAnimHeaderType *sys_header;
    854 
    855 	if (!handle) {
    856 		return FALSE;
    857 	}
    858 	sys_header = (SysAnimHeaderType *) handle;
    859 	return((short)sys_header->total_frames);
    860 }
    861 
    862 
    863 /***************************************************************************
    864  * GET_ANIM_X -- Gets the x from an animation                              *
    865  *                                                                         *
    866  *                                                                         *
    867  * INPUT:		void * to the animation that we are processing              *
    868  *                                                                         *
    869  * OUTPUT:     int the x of the animation we are processing				   *
    870  *                                                                         *
    871  * WARNINGS:                                                               *
    872  *                                                                         *
    873  * HISTORY:                                                                *
    874  *   07/03/1992 DRD : Created.                                             *
    875  *=========================================================================*/
    876 int __cdecl Get_Animation_X(void const *handle)
    877 {
    878  	SysAnimHeaderType const *sys_header;
    879 
    880 	if (!handle) {
    881 		return FALSE;
    882 	}
    883 	sys_header = (SysAnimHeaderType *) handle;
    884 	return(sys_header->pixel_x);
    885 }
    886 
    887 /***************************************************************************
    888  * GET_ANIM_Y -- Gets the y from an animation                              *
    889  *                                                                         *
    890  *                                                                         *
    891  * INPUT:		void * to the animation that we are processing              *
    892  *                                                                         *
    893  * OUTPUT:     int the y of the animation we are processing				   *
    894  *                                                                         *
    895  * WARNINGS:                                                               *
    896  *                                                                         *
    897  * HISTORY:                                                                *
    898  *   10/14/1992 PWG : Created.                                             *
    899  *=========================================================================*/
    900 int __cdecl Get_Animation_Y(void const *handle)
    901 {
    902  	SysAnimHeaderType const *sys_header;
    903 
    904 	if (!handle) {
    905 		return FALSE;
    906 	}
    907 	sys_header = (SysAnimHeaderType *) handle;
    908 	return(sys_header->pixel_y);
    909 }
    910 
    911 /***************************************************************************
    912  * GET_ANIM_WIDTH -- Gets the width from an animation                      *
    913  *                                                                         *
    914  *                                                                         *
    915  * INPUT:		void * to the animation that we are processing              *
    916  *                                                                         *
    917  * OUTPUT:     int the width of the animation we are processing				*
    918  *                                                                         *
    919  * WARNINGS:                                                               *
    920  *                                                                         *
    921  * HISTORY:                                                                *
    922  *   10/14/1992 PWG : Created.                                             *
    923  *=========================================================================*/
    924 int __cdecl Get_Animation_Width(void const *handle)
    925 {
    926  	SysAnimHeaderType const *sys_header;
    927 
    928 	if (!handle) {
    929 		return FALSE;
    930 	}
    931 	sys_header = (SysAnimHeaderType *) handle;
    932 	return(sys_header->pixel_width);
    933 }
    934 
    935 /***************************************************************************
    936  * GET_ANIM_HEIGHT -- The height of the animation we are processing        *
    937  *                                                                         *
    938  * INPUT:		void * to the animation that we are processing              *
    939  *                                                                         *
    940  * OUTPUT:     int the height of the animation we are processing				*
    941  *                                                                         *
    942  * HISTORY:                                                                *
    943  *   10/14/1992 PWG : Created.                                             *
    944  *=========================================================================*/
    945 int __cdecl Get_Animation_Height(void const *handle)
    946 {
    947  	SysAnimHeaderType const *sys_header;
    948 
    949 	if (!handle) {
    950 		return FALSE;
    951 	}
    952 	sys_header = (SysAnimHeaderType *) handle;
    953 	return(sys_header->pixel_height);
    954 }
    955 
    956 
    957 /***************************************************************************
    958  * GET_ANIM_PALETTE -- Returns true if the anim had an attached palette    *
    959  *                                                                         *
    960  * INPUT:		void * to the animation that we are processing              *
    961  *                                                                         *
    962  * OUTPUT:		int True if the animation has a set palette.  False if the	*
    963  *					animation does not.														*
    964  *                                                                         *
    965  * HISTORY:                                                                *
    966  *   10/14/1992 PWG : Created.                                             *
    967  *=========================================================================*/
    968 int __cdecl Get_Animation_Palette(void const *handle)
    969 {
    970  	SysAnimHeaderType const *sys_header;
    971 
    972 	if (!handle) {
    973 		return FALSE;
    974 	}
    975 	sys_header = (SysAnimHeaderType *) handle;
    976 	return(sys_header->flags & WSA_PALETTE_PRESENT);
    977 }
    978 
    979 
    980 /***************************************************************************
    981  * GET_ANIMATION_SIZE -- Return the amount of memory the animation is using*
    982  *                                                                         *
    983  *                                                                         *
    984  * INPUT:		void * to the animation that we are processing              *
    985  *                                                                         *
    986  * OUTPUT:		unsigned long number of byte used by animation. 							*
    987  *                                                                         *
    988  * WARNINGS:                                                               *
    989  *                                                                         *
    990  * HISTORY:                                                                *
    991  *   05/23/1994 SKB : Created.                                             *
    992  *=========================================================================*/
    993 unsigned long __cdecl Get_Animation_Size(void const *handle)
    994 {
    995  	SysAnimHeaderType const *sys_header;
    996 
    997 	if (!handle) {
    998 		return FALSE;
    999 	}
   1000 	sys_header = (SysAnimHeaderType *) handle;
   1001 	return(sys_header->anim_mem_size);
   1002 }
   1003 
   1004 /* ::::::::::::::::::::::::::::  PRIVATE FUNCTIONS  :::::::::::::::::::::::::::::: */
   1005 
   1006 
   1007 /***************************************************************************
   1008  * GET_RESIDENT_FRAME_OFFSET -- Gets frame offset of animate file in RAM   *
   1009  *                                                                         *
   1010  * INPUT:      char *file_buffer in RAM of animation file.                 *
   1011  *             int frame number that we need the offset of.               *
   1012  *                                                                         *
   1013  * OUTPUT:     int offset of frame requested.                             *
   1014  *                                                                         *
   1015  * WARNINGS:                                                               *
   1016  *                                                                         *
   1017  * HISTORY:                                                                *
   1018  *   11/26/1991  SB : Created.                                             *
   1019  *=========================================================================*/
   1020 PRIVATE unsigned long Get_Resident_Frame_Offset( char *file_buffer, int frame )
   1021 {
   1022 	unsigned long frame0_size;
   1023 	unsigned long *lptr;
   1024 
   1025 	// If there is a frame 0, the calculate its size.
   1026 	lptr = (unsigned long *) file_buffer;
   1027 
   1028 	if (*lptr) {
   1029 		frame0_size = lptr[1] - *lptr;
   1030 	} else {
   1031 	 	frame0_size = 0;
   1032 	}
   1033 
   1034 	// Return the offset into RAM for the frame.
   1035 	lptr += frame;
   1036 	if (*lptr)
   1037 			return (*lptr - (frame0_size + WSA_FILE_HEADER_SIZE));
   1038 	else
   1039 		return (0L);
   1040 }
   1041 
   1042 
   1043 /***************************************************************************
   1044  * GET_FILE_FRAME_OFFSET -- Get offset of a delta frame from animate file. *
   1045  *                                                                         *
   1046  * INPUT:      int file_handle of animation file.                         *
   1047  *             int frame number that we need the offset of.               *
   1048  *                                                                         *
   1049  * OUTPUT:     int offset of frame requested.                             *
   1050  *                                                                         *
   1051  * WARNINGS:                                                               *
   1052  *                                                                         *
   1053  * HISTORY:                                                                *
   1054  *   11/26/1991  SB : Created.                                             *
   1055  *=========================================================================*/
   1056 PRIVATE unsigned long Get_File_Frame_Offset( int file_handle, int frame, int palette_adjust)
   1057 {
   1058 	unsigned long offset;
   1059 
   1060 	Seek_File(file_handle, (frame << 2) + WSA_FILE_HEADER_SIZE, SEEK_SET);
   1061 
   1062 	if (Read_File(file_handle, (char *) &offset, sizeof(unsigned long)) != sizeof(unsigned long)) {
   1063 		offset = 0L;
   1064 	}
   1065 	offset += palette_adjust;
   1066 	return( offset );
   1067 }
   1068 
   1069 
   1070 /***************************************************************************
   1071  * APPLY_DELTA -- Copies frame into delta buffer, then applies to target   *
   1072  *                                                                         *
   1073  * INPUT:      SysAnimHeaderType *sys_header - pointer to animation buffer.*
   1074  *             int curr_frame - frame to put into target buffer.          *
   1075  *																									*
   1076  * OUTPUT:     BOOL - Return wether or not it worked.                      *
   1077  *                                                                         *
   1078  * WARNINGS:                                                               *
   1079  *                                                                         *
   1080  * HISTORY:                                                                *
   1081  *   11/26/1991  SB : Created.                                             *
   1082  *=========================================================================*/
   1083 PRIVATE BOOL Apply_Delta(SysAnimHeaderType *sys_header, int curr_frame, char *dest_ptr, int dest_w)
   1084 {
   1085 	char *data_ptr, *delta_back;
   1086 	int file_handle, palette_adjust;
   1087 	unsigned long frame_data_size, frame_offset;
   1088 
   1089 
   1090 	palette_adjust = ((sys_header->flags & WSA_PALETTE_PRESENT) ? 768 : 0);
   1091 	delta_back		= sys_header->delta_buffer;
   1092 
   1093 	if (sys_header->flags & WSA_RESIDENT) {
   1094 		// Get offset of the given frame in the resident file
   1095 		// Get the size of the frame <- (frame+1 offset) - (offset)
   1096 		// Point at the delta data
   1097 		// figure offset to load data into end of delta buffer
   1098 		// copy it into buffer
   1099 
   1100 		frame_offset = Get_Resident_Frame_Offset(sys_header->file_buffer, curr_frame);
   1101 		frame_data_size = Get_Resident_Frame_Offset(sys_header->file_buffer, curr_frame + 1) -	frame_offset;
   1102 
   1103 	  	data_ptr 	= (char *)Add_Long_To_Pointer(sys_header->file_buffer, frame_offset);
   1104 	  	delta_back 	= (char *)Add_Long_To_Pointer(delta_back,
   1105 	  						 sys_header->largest_frame_size - frame_data_size);
   1106 
   1107 		Mem_Copy( data_ptr, delta_back, frame_data_size );
   1108 
   1109 	} else if (sys_header -> flags & WSA_FILE) {
   1110 
   1111 		//	Open up file because not file not in RAM.
   1112 		// Get offset of the given frame in the file on disk
   1113 		// Get the size of the frame <- (frame+1 offset) - (offset)
   1114 		// Return if Get_.._offset() failed.  -- need error handling????
   1115 		//	Seek to delta data.
   1116 		// figure offset to load data into end of delta buffer
   1117 		//	Read it into buffer -- Return if correct amount not read.-- errors??
   1118 
   1119 		file_handle  = sys_header->file_handle;
   1120 		Seek_File(file_handle, 0L, SEEK_SET);
   1121 
   1122 		frame_offset = Get_File_Frame_Offset(file_handle, curr_frame, palette_adjust);
   1123 		frame_data_size = Get_File_Frame_Offset(file_handle, curr_frame + 1, palette_adjust) - frame_offset;
   1124 
   1125 		if (!frame_offset || !frame_data_size) {
   1126 			return(FALSE);
   1127 		}
   1128 
   1129 		Seek_File(file_handle, frame_offset, SEEK_SET);
   1130 		delta_back 	= (char *)Add_Long_To_Pointer(delta_back, sys_header->largest_frame_size - frame_data_size);
   1131 
   1132 		if (Read_File(file_handle, delta_back, frame_data_size) != frame_data_size) {
   1133 			return(FALSE);
   1134 		}
   1135 	}
   1136 
   1137 	// Uncompress data at end of delta buffer to the beginning of delta buffer.
   1138 	// Find start of target buffer.
   1139 	// Apply the XOR delta.
   1140 
   1141 	LCW_Uncompress(delta_back, sys_header->delta_buffer, sys_header->largest_frame_size);
   1142 
   1143 	if (sys_header->flags & WSA_TARGET_IN_BUFFER) {
   1144 		Apply_XOR_Delta(dest_ptr, sys_header->delta_buffer);
   1145 	}
   1146 	else {
   1147 		Apply_XOR_Delta_To_Page_Or_Viewport(dest_ptr, sys_header->delta_buffer,
   1148 		                        sys_header->pixel_width,  dest_w, DO_XOR);
   1149 	}
   1150 
   1151 	return(TRUE);
   1152 }
   1153