| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156 |
- /*
- ** Command & Conquer Red Alert(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /* $Header: g:/library/source/rcs/./wsa.c 1.16 1994/05/20 15:35:27 joe_bostic Exp $ */
- /***************************************************************************
- ** 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 **
- ***************************************************************************
- * *
- * Project Name : Library Animation System *
- * *
- * File Name : WSA.C *
- * *
- * Programmer : Michael Legg *
- * *
- * Start Date : November 20, 1991 *
- * *
- *-------------------------------------------------------------------------*
- * There are many different ways that the user can use the WSA library *
- * module. The options are as follows : *
- * *
- * System Allocation vs User Buffer - The user may request that the *
- * system allocate the needed buffer from the heap or the user may *
- * pass his own buffer in for the animator to use. *
- * *
- * Resident vs File based - If there is enough RAM, the user may put the *
- * entire animation into RAM for fastest animations. If there is *
- * not enouph RAM, the system will automatically make it so each *
- * frame will be read off disk when needed. *
- * *
- * Direct to Page vs Use of a user buffer -- Noramally Direct to page *
- * is the best method both in speed and in RAM need to hold anim. *
- * One may want to use the write to user buffer method if they *
- * are using the animation in a non sequencial order. *
- * *
- *-------------------------------------------------------------------------*
- * Functions: *
- * Animate_Frame -- Displays a frame of a given animation *
- * Get_Animation_Frame_Count -- Return Number of frames in an animation. *
- * Get_Animation_X -- Gets the x from an animation *
- * Get_Animation_Y -- Gets the y from an animation *
- * Get_Animation_Width -- Gets the width from an animation *
- * Get_Animation_Height -- The height of the animation we are processing *
- * Apply_Delta -- Copies frame into delta buffer, then applies to target *
- * Close_Animation -- Close the animation, freeing the space if necessary*
- * Get_File_Frame_Offset -- Get offset of a delta frame from animate file*
- * Get_Resident_Frame_Offset -- Gets frame offset of animate file in RAM *
- * Open_Animation -- Opens an animation file and reads into buffer *
- *- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include <wwstd.h>
- #include "wsa.h"
- #include <wwmem.h>
- #include <file.h>
- #include <misc.h>
- #include <iff.h>
- #include <mem.h>
- #include <string.h>
- //
- // WSA animation header allocation type.
- // If we need more then 8 flags for the flags variable, we can combine
- // USER_ALLOCATED with SYS_ALLOCATED and combine FILE with RESIDENT.
- //
- #define WSA_USER_ALLOCATED 0x01
- #define WSA_SYS_ALLOCATED 0x02
- #define WSA_FILE 0x04
- #define WSA_RESIDENT 0x08
- #define WSA_TARGET_IN_BUFFER 0x10
- #define WSA_LINEAR_ONLY 0x20
- #define WSA_FRAME_0_ON_PAGE 0x40
- #define WSA_AMIGA_ANIMATION 0x80
- #define WSA_PALETTE_PRESENT 0x100
- #define WSA_FRAME_0_IS_DELTA 0x200
- // These are used to call Apply_XOR_Delta_To_Page_Or_Viewport() to setup flags parameter. If
- // These change, make sure and change their values in lp_asm.asm.
- #define DO_XOR 0x0
- #define DO_COPY 0x01
- #define TO_VIEWPORT 0x0
- #define TO_PAGE 0x02
- typedef struct {
- unsigned short current_frame;
- unsigned short total_frames;
- unsigned short pixel_x;
- unsigned short pixel_y;
- unsigned short pixel_width;
- unsigned short pixel_height;
- unsigned short largest_frame_size;
- char *delta_buffer;
- char *file_buffer;
- char file_name[ 13 ];
- short flags;
- // New fields that animate does not know about below this point. SEE EXTRA_charS_ANIMATE_NOT_KNOW_ABOUT
- short file_handle;
- unsigned long anim_mem_size;
- } SysAnimHeaderType;
- // NOTE:"THIS IS A BAD THING. SINCE sizeof(SysAnimHeaderType) CHANGED, THE ANIMATE.EXE
- // UTILITY DID NOT KNOW I UPDATED IT, IT ADDS IT TO largest_frame_size BEFORE SAVING
- // IT TO THE FILE. THIS MEANS I HAVE TO ADD THESE charS ON NOW FOR IT TO WORK.
- #define EXTRA_charS_ANIMATE_NOT_KNOW_ABOUT (sizeof(short) + sizeof(unsigned long))
- //
- // Header structure for the file.
- // NOTE: The 'total_frames' field is used to differentiate between Amiga and IBM
- // animations. Amiga animations have the HIGH bit set.
- //
- typedef struct {
- unsigned short total_frames;
- unsigned short pixel_x;
- unsigned short pixel_y;
- unsigned short pixel_width;
- unsigned short pixel_height;
- unsigned short largest_frame_size;
- short flags;
- unsigned long frame0_offset;
- unsigned long frame0_end;
- /* unsigned long data_seek_offset, unsigned short frame_size ... */
- } WSA_FileHeaderType;
- #define WSA_FILE_HEADER_SIZE ( sizeof(WSA_FileHeaderType) - (2 * sizeof(unsigned long)) )
- /*=========================================================================*/
- /* The following PRIVATE functions are in this file: */
- /*=========================================================================*/
- PRIVATE unsigned long Get_Resident_Frame_Offset( char *file_buffer, int frame );
- PRIVATE unsigned long Get_File_Frame_Offset( int file_handle, int frame, int palette_adjust);
- PRIVATE BOOL Apply_Delta(SysAnimHeaderType *sys_header, int curr_frame, char *dest_ptr, int dest_w);
- /*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
- /***************************************************************************
- * OPEN_ANIMATION -- Opens an animation file and reads into buffer *
- * *
- * INPUT: char *file_name of animation sequence file. *
- * char *user_buffer pointer if one exists (NULL ok) *
- * unsigned long user_buffer_size if known (NULL ok) *
- * WSAOpenType user_flags - flags on how to open. *
- * unsigned char *palette - pointer to palette space for return (NULL ok) *
- * *
- * OUTPUT: void *pointer to animation data. Must be used for all *
- * other WSA calls. *
- * *
- * WARNINGS: May return NULL, please check. *
- * *
- * HISTORY: *
- * 11/26/1991 SB : Created. *
- *=========================================================================*/
- void * __cdecl Open_Animation(char const *file_name, char *user_buffer, long user_buffer_size, WSAOpenType user_flags, unsigned char *palette)
- {
- int fh, anim_flags;
- int palette_adjust;
- unsigned int offsets_size;
- unsigned int frame0_size;
- long target_buffer_size, delta_buffer_size, file_buffer_size;
- long max_buffer_size, min_buffer_size;
- char *sys_anim_header_buffer;
- char *target_buffer;
- char *delta_buffer, *delta_back;
- SysAnimHeaderType *sys_header;
- WSA_FileHeaderType file_header;
- /*======================================================================*/
- /* Open the file to get the header information */
- /*======================================================================*/
- anim_flags = 0;
- fh = Open_File(file_name, READ);
- Read_File(fh, (char *) &file_header, sizeof(WSA_FileHeaderType));
- /*======================================================================*/
- /* If the file has an attached palette then if we have a valid palette */
- /* pointer we need to read it in. */
- /*======================================================================*/
- if (file_header.flags & 1) {
- anim_flags |= WSA_PALETTE_PRESENT;
- palette_adjust = 768;
- if (palette != NULL) {
- Seek_File(fh, sizeof(unsigned long) * (file_header.total_frames), SEEK_CUR);
- Read_File(fh, palette, 768L);
- }
- } else {
- palette_adjust = 0;
- }
- // Check for flag from ANIMATE indicating that this animation was
- // created from a .LBM and a .ANM. These means that the first
- // frame is a XOR Delta from a picture, not black.
- if (file_header.flags & 2) {
- anim_flags |= WSA_FRAME_0_IS_DELTA;
- }
- // Get the total file size minus the size of the first frame and the size
- // of the file header. These will not be read in to save even more space.
- file_buffer_size = Seek_File(fh, 0L, SEEK_END);
- if (file_header.frame0_offset) {
- long tlong;
- tlong = file_header.frame0_end - file_header.frame0_offset;
- frame0_size = (unsigned short) tlong;
- }
- else {
- anim_flags |= WSA_FRAME_0_ON_PAGE;
- frame0_size = 0;
- }
- file_buffer_size -= palette_adjust + frame0_size + WSA_FILE_HEADER_SIZE;
- // We need to determine the buffer sizes required for the animation. At a
- // minimum, we need a target buffer for the uncompressed frame and a delta
- // buffer for the delta data. We may be able to make the file resident,
- // so we will determine the file size.
- //
- // If the target buffer is in the user buffer
- // Then figure its size
- // and set the allocation flag
- // Else size is zero.
- //
- if (user_flags & WSA_OPEN_DIRECT) {
- target_buffer_size = 0L;
- }
- else {
- anim_flags |= WSA_TARGET_IN_BUFFER;
- target_buffer_size = (unsigned long) file_header.pixel_width * file_header.pixel_height;
- }
- // NOTE:"THIS IS A BAD THING. SINCE sizeof(SysAnimHeaderType) CHANGED, THE ANIMATE.EXE
- // UTILITY DID NOT KNOW I UPDATED IT, IT ADDS IT TO largest_frame_size BEFORE SAVING
- // IT TO THE FILE. THIS MEANS I HAVE TO ADD THESE charS ON NOW FOR IT TO WORK.
- delta_buffer_size = (unsigned long) file_header.largest_frame_size + EXTRA_charS_ANIMATE_NOT_KNOW_ABOUT;
- min_buffer_size = target_buffer_size + delta_buffer_size;
- max_buffer_size = min_buffer_size + file_buffer_size;
- // check to see if buffer size is big enough for at least min required
- if (user_buffer && (user_buffer_size < min_buffer_size)) {
- Close_File(fh);
- return(NULL);
- }
- // A buffer was not passed in, so do allocations
- if (user_buffer == NULL) {
- // If the user wants it from the disk, then let us give it to him,
- // otherwise, try to give a max allocation he can have.
- if (user_flags & WSA_OPEN_FROM_DISK) {
- user_buffer_size = min_buffer_size;
- }
- // else no buffer size, then try max configuration.
- else if (!user_buffer_size) {
- user_buffer_size = max_buffer_size;
- }
- // else if buffer specified is less then max needed, give min.
- else if (user_buffer_size < max_buffer_size) {
- user_buffer_size = min_buffer_size;
- }
- // otherwise we only want to alloc what we need.
- else {
- user_buffer_size = max_buffer_size;
- }
- // Check to see if enough RAM available for buffer_size.
- if (user_buffer_size > Ram_Free(MEM_NORMAL)) {
- // If not enough room for even the min, return no buffer.
- if (min_buffer_size > Ram_Free(MEM_NORMAL)) {
- Close_File(fh);
- return(NULL);
- }
- // Else make buffer size the min and allocate it.
- user_buffer_size = min_buffer_size;
- }
- // allocate buffer needed
- user_buffer = (char *) Alloc(user_buffer_size, MEM_CLEAR);
- anim_flags |= WSA_SYS_ALLOCATED;
- }
- else {
- // Check to see if the user_buffer_size should be min or max.
- if ((user_flags & WSA_OPEN_FROM_DISK) || (user_buffer_size < max_buffer_size)) {
- user_buffer_size = min_buffer_size;
- }
- else {
- user_buffer_size = max_buffer_size;
- }
- anim_flags |= WSA_USER_ALLOCATED;
- }
- // Set the pointers to the RAM buffers
- sys_anim_header_buffer = user_buffer;
- target_buffer = (char *) Add_Long_To_Pointer(sys_anim_header_buffer, sizeof(SysAnimHeaderType));
- delta_buffer = (char *) Add_Long_To_Pointer(target_buffer, target_buffer_size);
- // Clear target buffer if it is in the user buffer.
- if (target_buffer_size) {
- memset( target_buffer, 0, (unsigned short) target_buffer_size );
- }
- // Poke data into the system animation header (start of user_buffer)
- // current_frame is set to total_frames so that Animate_Frame() knows that
- // it needs to clear the target buffer.
- sys_header = ( SysAnimHeaderType * ) sys_anim_header_buffer;
- sys_header -> current_frame =
- sys_header -> total_frames = file_header.total_frames;
- sys_header -> pixel_x = file_header.pixel_x;
- sys_header -> pixel_y = file_header.pixel_y;
- sys_header -> pixel_width = file_header.pixel_width;
- sys_header -> pixel_height = file_header.pixel_height;
- sys_header -> anim_mem_size = user_buffer_size;
- sys_header -> delta_buffer = delta_buffer;
- sys_header -> largest_frame_size =
- (unsigned short) (delta_buffer_size - sizeof(SysAnimHeaderType));
- strcpy(sys_header->file_name, file_name);
- // Figure how much room the frame offsets take up in the file.
- // Add 2 - one for the wrap around and one for the final end offset.
- offsets_size = (file_header.total_frames + 2) << 2;
- // Can the user_buffer_size handle the maximum case buffer?
- if ( user_buffer_size == max_buffer_size) {
- //
- // set the file buffer pointer,
- // Skip over the header information.
- // Read in the offsets.
- // Skip over the first frame.
- // Read in remaining frames.
- //
- sys_header->file_buffer = (char *)Add_Long_To_Pointer(delta_buffer,sys_header->largest_frame_size);
- Seek_File( fh, WSA_FILE_HEADER_SIZE, SEEK_SET);
- Read_File( fh, sys_header->file_buffer, offsets_size);
- Seek_File( fh, frame0_size + palette_adjust, SEEK_CUR);
- Read_File( fh, sys_header->file_buffer + offsets_size,
- file_buffer_size - offsets_size);
- //
- // Find out if there is an ending value for the last frame.
- // If there is not, then this animation will not be able to
- // loop back to the beginning.
- //
- if (Get_Resident_Frame_Offset( sys_header->file_buffer, sys_header->total_frames + 1))
- anim_flags |= WSA_RESIDENT;
- else
- anim_flags |= WSA_LINEAR_ONLY | WSA_RESIDENT;
- }
- else { // buffer cannot handle max_size of buffer
- if(Get_File_Frame_Offset( fh, sys_header->total_frames + 1, palette_adjust))
- anim_flags |= WSA_FILE;
- else
- anim_flags |= WSA_LINEAR_ONLY | WSA_FILE;
- ////
- sys_header->file_buffer = NULL;
- }
- // Figure where to back load frame 0 into the delta buffer.
- delta_back = (char *)Add_Long_To_Pointer(delta_buffer,
- sys_header->largest_frame_size - frame0_size);
- // Read the first frame into the delta buffer and uncompress it.
- // Then close it.
- Seek_File( fh, WSA_FILE_HEADER_SIZE + offsets_size + palette_adjust, SEEK_SET);
- Read_File( fh, delta_back, frame0_size);
- // We do not use the file handle when it is in RAM.
- if (anim_flags & WSA_RESIDENT) {
- sys_header -> file_handle = (short) -1;
- Close_File(fh);
- }
- else {
- sys_header -> file_handle = (short)fh;
- }
- LCW_Uncompress(delta_back, delta_buffer, sys_header->largest_frame_size);
- // Finally set the flags,
- sys_header->flags = (short)anim_flags;
- // return valid handle
- return( user_buffer );
- }
- /***************************************************************************
- * CLOSE_ANIMATION -- Close the animation, freeing the space if necessary. *
- * *
- * INPUT: void *handle to the animation data buffer *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: handle MUST have been returned by Open_Animation *
- * *
- * HISTORY: *
- * 11/23/1991 ML : Created. *
- *=========================================================================*/
- void __cdecl Close_Animation( void *handle )
- {
- SysAnimHeaderType *sys_header;
- // Assign our local system header pointer to the beginning of the handle space
- sys_header = (SysAnimHeaderType *) handle;
- // Close the WSA file in it was disk based.
- if (sys_header->flags & WSA_FILE) {
- Close_File(sys_header->file_handle);
- }
- // Check to see if the buffer was allocated OR the programmer provided the buffer
- if (handle && sys_header->flags & WSA_SYS_ALLOCATED) {
- Free(handle);
- }
- }
- /***************************************************************************
- * ANIMATE_FRAME -- Displays a frame of a given animation *
- * *
- * INPUT: void *handle to the animation. *
- * int frame_number wanted to be displayed *
- * int x_pixel position of left side of animation on page *
- * int y_pixel position of top of animation on page *
- * *
- * OUTPUT: BOOL if successfull or not. *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 11/27/1991 SB : Created. *
- *=========================================================================*/
- #pragma off (unreferenced)
- BOOL __cdecl Animate_Frame(void *handle, GraphicViewPortClass& view,
- int frame_number, int x_pixel, int y_pixel,
- WSAType flags_and_prio, void *magic_cols, void *magic)
- {
- SysAnimHeaderType *sys_header; // fix up the void pointer past in.
- int curr_frame; // current frame we are on.
- int total_frames; // number of frames in anim.
- int distance; // distance to desired frame.
- int search_dir; // direcion to search for desired frame.
- int search_frames; // How many frames to search.
- int loop; // Just a loop varible.
- char *frame_buffer; // our destination.
- BOOL direct_to_dest; // are we going directly to the destination?
- int dest_width; // the width of the destination buffer or page.
- // Assign local pointer to the beginning of the buffer where the system information
- // resides
- sys_header = (SysAnimHeaderType *)handle;
- // Get the total number of frames
- total_frames = sys_header->total_frames;
- // Are the animation handle and the frame number valid?
- if (!handle || (total_frames <= frame_number)) {
- return FALSE;
- }
- if (view.Lock()!=TRUE) return (FALSE);
- // Decide if we are going to a page or a viewport (part of a buffer).
- dest_width = view.Get_Width() + view.Get_XAdd() + view.Get_Pitch();
- //
- // adjust x_pixel and y_pixel by system pixel_x and pixel_y respectively.
- //
- x_pixel += (short)sys_header->pixel_x;
- y_pixel += (short)sys_header->pixel_y;
- //
- // Check to see if we are using a buffer inside of the animation buffer or if
- // it is being drawn directly to the destination page or buffer.
- //
- if (sys_header->flags & WSA_TARGET_IN_BUFFER) {
- // Get a pointer to the frame in animation buffer.
- frame_buffer = (char *)Add_Long_To_Pointer(sys_header, sizeof(SysAnimHeaderType));
- direct_to_dest = FALSE;
- }
- else {
- frame_buffer = (char *)view.Get_Offset();
- frame_buffer += (y_pixel * dest_width) + x_pixel;
- direct_to_dest = TRUE;
- }
- //
- // If current_frame is equal to tatal_frames, then no animations have taken place
- // so must uncompress frame 0 in delta buffer to the frame_buffer/page if it
- // exists.
- //
- if (sys_header->current_frame == total_frames) {
- // Call apply delta telling it wether to copy or to xor depending on if the
- // target is a page or a buffer.
- if (!(sys_header->flags & WSA_FRAME_0_ON_PAGE)) {
- if (direct_to_dest) {
- // The last parameter says weather to copy or to XOR. If the
- // first frame is a DELTA, then it must be XOR'd. A TRUE is
- // copy while FALSE is XOR.
- Apply_XOR_Delta_To_Page_Or_Viewport(frame_buffer, sys_header->delta_buffer,
- sys_header->pixel_width, dest_width, //dest_width - sys_header->pixel_width,
- (sys_header->flags & WSA_FRAME_0_IS_DELTA)? DO_XOR : DO_COPY);
- }
- else {
- Apply_XOR_Delta(frame_buffer, sys_header->delta_buffer);
- }
- }
- sys_header->current_frame = 0;
- }
- //
- // Get the current frame
- // If no looping aloud, are the trying to do it anyways?
- //
- curr_frame = sys_header->current_frame;
- #if (FALSE)
- // This is commented out since we will let them loop even though they should
- // not - it will be slower.
- if ( (sys_header->flags & WSA_LINEAR_ONLY) && (frame_number < cur_frame) ) {
- view.Unlock();
- return FALSE;
- }
- #endif
- // Get absoulte distance from our current frame to the target frame
- distance = ABS(curr_frame - frame_number);
- // Assume we are searching right
- search_dir = 1;
- // Calculate the number of frames to search if we go right and wrap
- if (frame_number > curr_frame) {
- search_frames = total_frames - frame_number + curr_frame;
- // Is going right faster than going backwards?
- // Or are they trying to loop when the should not?
- if ((search_frames < distance) && !(sys_header->flags & WSA_LINEAR_ONLY)) {
- search_dir = -1; // No, so go left
- }
- else {
- search_frames = distance;
- }
- }
- else {
- search_frames = total_frames - curr_frame + frame_number;
- // Is going right faster than going backwards?
- // Or are they trying to loop when the should not?
- if ((search_frames >= distance) || (sys_header->flags & WSA_LINEAR_ONLY)) {
- search_dir = -1; // No, so go left
- search_frames = distance;
- }
- }
- // Take care of the case when we are searching right (possibly right)
- if (search_dir > 0) {
- for (loop = 0; loop < search_frames; loop++) {
- // Move the logical frame number ordinally right
- curr_frame += search_dir;
- Apply_Delta(sys_header, curr_frame, frame_buffer, dest_width);
- // Adjust the current frame number, taking into consideration that we could
- // have wrapped
- if (curr_frame == total_frames) {
- curr_frame = 0;
- }
- }
- }
- else {
- for (loop = 0; loop < search_frames; loop++) {
- // If we are going backwards and we are on frame 0, the delta to get
- // to the last frame is the n + 1 delta (wrap delta)
- if (curr_frame == 0) {
- curr_frame = total_frames;
- }
- Apply_Delta(sys_header, curr_frame, frame_buffer, dest_width);
- curr_frame += search_dir;
- }
- }
- sys_header->current_frame = (short)frame_number;
- // If we did this all in a hidden buffer, then copy it to the desired page or viewport.
- if (sys_header->flags & WSA_TARGET_IN_BUFFER) {
- #if TRUE
- Buffer_To_Page(x_pixel, y_pixel, sys_header->pixel_width, sys_header->pixel_height, frame_buffer, view);
- #else
- int flags = ((unsigned short)flags_and_prio & 0xFF00u) >> 12u;
- int pri = flags_and_prio & 0x00FF;
- Buffer_Bitblit_To_LogicPage(x_pixel, y_pixel, sys_header->pixel_width,
- sys_header->pixel_height, 0, flags, frame_buffer, pri,
- magic_cols, magic);
- #endif
- }
- view.Unlock();
- return TRUE;
- }
- /***************************************************************************
- * ANIMATE_FRAME -- Displays a frame of a given animation *
- * *
- * INPUT: void *handle to the animation. *
- * int frame_number wanted to be displayed *
- * int x_pixel position of left side of animation on page *
- * int y_pixel position of top of animation on page *
- * *
- * OUTPUT: BOOL if successfull or not. *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 11/27/1991 SB : Created. *
- *=========================================================================*/
- #pragma argsused
- #ifdef cuts
- BOOL __cdecl Animate_Frame(void *handle, GraphicViewPortClass& view,
- int frame_number, int x_pixel, int y_pixel,
- WSAType flags_and_prio, void *magic_cols, void *magic)
- {
- SysAnimHeaderType *sys_header; // fix up the void pointer past in.
- int curr_frame; // current frame we are on.
- int total_frames; // number of frames in anim.
- int distance; // distance to desired frame.
- int search_dir; // direcion to search for desired frame.
- int search_frames; // How many frames to search.
- int loop; // Just a loop varible.
- char *frame_buffer; // our destination.
- BOOL direct_to_dest; // are we going directly to the destination?
- int dest_width; // the width of the destination buffer or page.
- // Assign local pointer to the beginning of the buffer where the system information
- // resides
- sys_header = (SysAnimHeaderType *)handle;
- // Get the total number of frames
- total_frames = sys_header->total_frames;
- // Are the animation handle and the frame number valid?
- if (!handle || (total_frames <= frame_number)) {
- return FALSE;
- }
- // Decide if we are going to a page or a viewport (part of a buffer).
- dest_width = view.Get_Width() + view.Get_XAdd();
- //
- // adjust x_pixel and y_pixel by system pixel_x and pixel_y respectively.
- //
- x_pixel += (short)sys_header->pixel_x;
- y_pixel += (short)sys_header->pixel_y;
- //
- // Check to see if we are using a buffer inside of the animation buffer or if
- // it is being drawn directly to the destination page or buffer.
- //
- if (sys_header->flags & WSA_TARGET_IN_BUFFER) {
- // Get a pointer to the frame in animation buffer.
- frame_buffer = (char *)Add_Long_To_Pointer(sys_header, sizeof(SysAnimHeaderType));
- direct_to_dest = FALSE;
- }
- else {
- frame_buffer = (char *)view.Get_Offset();
- frame_buffer += (y_pixel * dest_width) + x_pixel;
- direct_to_dest = TRUE;
- }
- //
- // If current_frame is equal to tatal_frames, then no animations have taken place
- // so must uncompress frame 0 in delta buffer to the frame_buffer/page if it
- // exists.
- //
- if (sys_header->current_frame == total_frames) {
- // Call apply delta telling it wether to copy or to xor depending on if the
- // target is a page or a buffer.
- if (!(sys_header->flags & WSA_FRAME_0_ON_PAGE)) {
- if (direct_to_dest) {
- // The last parameter says weather to copy or to XOR. If the
- // first frame is a DELTA, then it must be XOR'd. A TRUE is
- // copy while FALSE is XOR.
- Apply_XOR_Delta_To_Page_Or_Viewport(frame_buffer, sys_header->delta_buffer,
- sys_header->pixel_width, dest_width, //dest_width - sys_header->pixel_width,
- (sys_header->flags & WSA_FRAME_0_IS_DELTA)? DO_XOR : DO_COPY);
- }
- else {
- Apply_XOR_Delta(frame_buffer, sys_header->delta_buffer);
- }
- }
- sys_header->current_frame = 0;
- }
- //
- // Get the current frame
- // If no looping aloud, are the trying to do it anyways?
- //
- curr_frame = sys_header->current_frame;
- #if (FALSE)
- // This is commented out since we will let them loop even though they should
- // not - it will be slower.
- if ( (sys_header->flags & WSA_LINEAR_ONLY) && (frame_number < cur_frame) ) {
- return FALSE;
- }
- #endif
- // Get absoulte distance from our current frame to the target frame
- distance = ABS(curr_frame - frame_number);
- // Assume we are searching right
- search_dir = 1;
- // Calculate the number of frames to search if we go right and wrap
- if (frame_number > curr_frame) {
- search_frames = total_frames - frame_number + curr_frame;
- // Is going right faster than going backwards?
- // Or are they trying to loop when the should not?
- if ((search_frames < distance) && !(sys_header->flags & WSA_LINEAR_ONLY)) {
- search_dir = -1; // No, so go left
- }
- else {
- search_frames = distance;
- }
- }
- else {
- search_frames = total_frames - curr_frame + frame_number;
- // Is going right faster than going backwards?
- // Or are they trying to loop when the should not?
- if ((search_frames >= distance) || (sys_header->flags & WSA_LINEAR_ONLY)) {
- search_dir = -1; // No, so go left
- search_frames = distance;
- }
- }
- // Take care of the case when we are searching right (possibly right)
- if (search_dir > 0) {
- for (loop = 0; loop < search_frames; loop++) {
- // Move the logical frame number ordinally right
- curr_frame += search_dir;
- Apply_Delta(sys_header, curr_frame, frame_buffer, dest_width);
- // Adjust the current frame number, taking into consideration that we could
- // have wrapped
- if (curr_frame == total_frames) {
- curr_frame = 0;
- }
- }
- }
- else {
- for (loop = 0; loop < search_frames; loop++) {
- // If we are going backwards and we are on frame 0, the delta to get
- // to the last frame is the n + 1 delta (wrap delta)
- if (curr_frame == 0) {
- curr_frame = total_frames;
- }
- Apply_Delta(sys_header, curr_frame, frame_buffer, dest_width);
- curr_frame += search_dir;
- }
- }
- sys_header->current_frame = frame_number;
- // If we did this all in a hidden buffer, then copy it to the desired page or viewport.
- if (sys_header->flags & WSA_TARGET_IN_BUFFER) {
- #if TRUE
- Buffer_To_Page(x_pixel, y_pixel, sys_header->pixel_width, sys_header->pixel_height, frame_buffer, view);
- #else
- int flags = ((unsigned short)flags_and_prio & 0xFF00u) >> 12u;
- int pri = flags_and_prio & 0x00FF;
- Buffer_Bitblit_To_LogicPage(x_pixel, y_pixel, sys_header->pixel_width,
- sys_header->pixel_height, 0, flags, frame_buffer, pri,
- magic_cols, magic);
- #endif
- }
- return TRUE;
- }
- #endif
- /***************************************************************************
- * ANIMATE_FRAME_COUNT -- Return Number of frames in an animation. *
- * *
- * INPUT: void *handle to the animation. *
- * *
- * OUTPUT: int number of frames in animation. *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 12/05/1991 SB : Created. *
- *=========================================================================*/
- int __cdecl Get_Animation_Frame_Count(void *handle)
- {
- SysAnimHeaderType *sys_header;
- if (!handle) {
- return FALSE;
- }
- sys_header = (SysAnimHeaderType *) handle;
- return((short)sys_header->total_frames);
- }
- /***************************************************************************
- * GET_ANIM_X -- Gets the x from an animation *
- * *
- * *
- * INPUT: void * to the animation that we are processing *
- * *
- * OUTPUT: int the x of the animation we are processing *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 07/03/1992 DRD : Created. *
- *=========================================================================*/
- int __cdecl Get_Animation_X(void const *handle)
- {
- SysAnimHeaderType const *sys_header;
- if (!handle) {
- return FALSE;
- }
- sys_header = (SysAnimHeaderType *) handle;
- return(sys_header->pixel_x);
- }
- /***************************************************************************
- * GET_ANIM_Y -- Gets the y from an animation *
- * *
- * *
- * INPUT: void * to the animation that we are processing *
- * *
- * OUTPUT: int the y of the animation we are processing *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 10/14/1992 PWG : Created. *
- *=========================================================================*/
- int __cdecl Get_Animation_Y(void const *handle)
- {
- SysAnimHeaderType const *sys_header;
- if (!handle) {
- return FALSE;
- }
- sys_header = (SysAnimHeaderType *) handle;
- return(sys_header->pixel_y);
- }
- /***************************************************************************
- * GET_ANIM_WIDTH -- Gets the width from an animation *
- * *
- * *
- * INPUT: void * to the animation that we are processing *
- * *
- * OUTPUT: int the width of the animation we are processing *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 10/14/1992 PWG : Created. *
- *=========================================================================*/
- int __cdecl Get_Animation_Width(void const *handle)
- {
- SysAnimHeaderType const *sys_header;
- if (!handle) {
- return FALSE;
- }
- sys_header = (SysAnimHeaderType *) handle;
- return(sys_header->pixel_width);
- }
- /***************************************************************************
- * GET_ANIM_HEIGHT -- The height of the animation we are processing *
- * *
- * INPUT: void * to the animation that we are processing *
- * *
- * OUTPUT: int the height of the animation we are processing *
- * *
- * HISTORY: *
- * 10/14/1992 PWG : Created. *
- *=========================================================================*/
- int __cdecl Get_Animation_Height(void const *handle)
- {
- SysAnimHeaderType const *sys_header;
- if (!handle) {
- return FALSE;
- }
- sys_header = (SysAnimHeaderType *) handle;
- return(sys_header->pixel_height);
- }
- /***************************************************************************
- * GET_ANIM_PALETTE -- Returns true if the anim had an attached palette *
- * *
- * INPUT: void * to the animation that we are processing *
- * *
- * OUTPUT: int True if the animation has a set palette. False if the *
- * animation does not. *
- * *
- * HISTORY: *
- * 10/14/1992 PWG : Created. *
- *=========================================================================*/
- int __cdecl Get_Animation_Palette(void const *handle)
- {
- SysAnimHeaderType const *sys_header;
- if (!handle) {
- return FALSE;
- }
- sys_header = (SysAnimHeaderType *) handle;
- return(sys_header->flags & WSA_PALETTE_PRESENT);
- }
- /***************************************************************************
- * GET_ANIMATION_SIZE -- Return the amount of memory the animation is using*
- * *
- * *
- * INPUT: void * to the animation that we are processing *
- * *
- * OUTPUT: unsigned long number of byte used by animation. *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 05/23/1994 SKB : Created. *
- *=========================================================================*/
- unsigned long __cdecl Get_Animation_Size(void const *handle)
- {
- SysAnimHeaderType const *sys_header;
- if (!handle) {
- return FALSE;
- }
- sys_header = (SysAnimHeaderType *) handle;
- return(sys_header->anim_mem_size);
- }
- /* :::::::::::::::::::::::::::: PRIVATE FUNCTIONS :::::::::::::::::::::::::::::: */
- /***************************************************************************
- * GET_RESIDENT_FRAME_OFFSET -- Gets frame offset of animate file in RAM *
- * *
- * INPUT: char *file_buffer in RAM of animation file. *
- * int frame number that we need the offset of. *
- * *
- * OUTPUT: int offset of frame requested. *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 11/26/1991 SB : Created. *
- *=========================================================================*/
- PRIVATE unsigned long Get_Resident_Frame_Offset( char *file_buffer, int frame )
- {
- unsigned long frame0_size;
- unsigned long *lptr;
- // If there is a frame 0, the calculate its size.
- lptr = (unsigned long *) file_buffer;
- if (*lptr) {
- frame0_size = lptr[1] - *lptr;
- } else {
- frame0_size = 0;
- }
- // Return the offset into RAM for the frame.
- lptr += frame;
- if (*lptr)
- return (*lptr - (frame0_size + WSA_FILE_HEADER_SIZE));
- else
- return (0L);
- }
- /***************************************************************************
- * GET_FILE_FRAME_OFFSET -- Get offset of a delta frame from animate file. *
- * *
- * INPUT: int file_handle of animation file. *
- * int frame number that we need the offset of. *
- * *
- * OUTPUT: int offset of frame requested. *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 11/26/1991 SB : Created. *
- *=========================================================================*/
- PRIVATE unsigned long Get_File_Frame_Offset( int file_handle, int frame, int palette_adjust)
- {
- unsigned long offset;
- Seek_File(file_handle, (frame << 2) + WSA_FILE_HEADER_SIZE, SEEK_SET);
- if (Read_File(file_handle, (char *) &offset, sizeof(unsigned long)) != sizeof(unsigned long)) {
- offset = 0L;
- }
- offset += palette_adjust;
- return( offset );
- }
- /***************************************************************************
- * APPLY_DELTA -- Copies frame into delta buffer, then applies to target *
- * *
- * INPUT: SysAnimHeaderType *sys_header - pointer to animation buffer.*
- * int curr_frame - frame to put into target buffer. *
- * *
- * OUTPUT: BOOL - Return wether or not it worked. *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 11/26/1991 SB : Created. *
- *=========================================================================*/
- PRIVATE BOOL Apply_Delta(SysAnimHeaderType *sys_header, int curr_frame, char *dest_ptr, int dest_w)
- {
- char *data_ptr, *delta_back;
- int file_handle, palette_adjust;
- unsigned long frame_data_size, frame_offset;
- palette_adjust = ((sys_header->flags & WSA_PALETTE_PRESENT) ? 768 : 0);
- delta_back = sys_header->delta_buffer;
- if (sys_header->flags & WSA_RESIDENT) {
- // Get offset of the given frame in the resident file
- // Get the size of the frame <- (frame+1 offset) - (offset)
- // Point at the delta data
- // figure offset to load data into end of delta buffer
- // copy it into buffer
- frame_offset = Get_Resident_Frame_Offset(sys_header->file_buffer, curr_frame);
- frame_data_size = Get_Resident_Frame_Offset(sys_header->file_buffer, curr_frame + 1) - frame_offset;
- data_ptr = (char *)Add_Long_To_Pointer(sys_header->file_buffer, frame_offset);
- delta_back = (char *)Add_Long_To_Pointer(delta_back,
- sys_header->largest_frame_size - frame_data_size);
- Mem_Copy( data_ptr, delta_back, frame_data_size );
- } else if (sys_header -> flags & WSA_FILE) {
- // Open up file because not file not in RAM.
- // Get offset of the given frame in the file on disk
- // Get the size of the frame <- (frame+1 offset) - (offset)
- // Return if Get_.._offset() failed. -- need error handling????
- // Seek to delta data.
- // figure offset to load data into end of delta buffer
- // Read it into buffer -- Return if correct amount not read.-- errors??
- file_handle = sys_header->file_handle;
- Seek_File(file_handle, 0L, SEEK_SET);
- frame_offset = Get_File_Frame_Offset(file_handle, curr_frame, palette_adjust);
- frame_data_size = Get_File_Frame_Offset(file_handle, curr_frame + 1, palette_adjust) - frame_offset;
- if (!frame_offset || !frame_data_size) {
- return(FALSE);
- }
- Seek_File(file_handle, frame_offset, SEEK_SET);
- delta_back = (char *)Add_Long_To_Pointer(delta_back, sys_header->largest_frame_size - frame_data_size);
- if (Read_File(file_handle, delta_back, frame_data_size) != frame_data_size) {
- return(FALSE);
- }
- }
- // Uncompress data at end of delta buffer to the beginning of delta buffer.
- // Find start of target buffer.
- // Apply the XOR delta.
- LCW_Uncompress(delta_back, sys_header->delta_buffer, sys_header->largest_frame_size);
- if (sys_header->flags & WSA_TARGET_IN_BUFFER) {
- Apply_XOR_Delta(dest_ptr, sys_header->delta_buffer);
- }
- else {
- Apply_XOR_Delta_To_Page_Or_Viewport(dest_ptr, sys_header->delta_buffer,
- sys_header->pixel_width, dest_w, DO_XOR);
- }
- return(TRUE);
- }
|