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