1151 lines
45 KiB
C++
1151 lines
45 KiB
C++
![]() |
/*
|
||
|
** 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 {
|
||
|
UWORD current_frame;
|
||
|
UWORD total_frames;
|
||
|
UWORD pixel_x;
|
||
|
UWORD pixel_y;
|
||
|
UWORD pixel_width;
|
||
|
UWORD pixel_height;
|
||
|
UWORD largest_frame_size;
|
||
|
BYTE *delta_buffer;
|
||
|
BYTE *file_buffer;
|
||
|
BYTE file_name[ 13 ];
|
||
|
WORD flags;
|
||
|
// New fields that animate does not know about below this point. SEE EXTRA_BYTES_ANIMATE_NOT_KNOW_ABOUT
|
||
|
WORD file_handle;
|
||
|
ULONG 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 BYTES ON NOW FOR IT TO WORK.
|
||
|
#define EXTRA_BYTES_ANIMATE_NOT_KNOW_ABOUT (sizeof(WORD) + sizeof(ULONG))
|
||
|
|
||
|
|
||
|
//
|
||
|
// 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 {
|
||
|
UWORD total_frames;
|
||
|
UWORD pixel_x;
|
||
|
UWORD pixel_y;
|
||
|
UWORD pixel_width;
|
||
|
UWORD pixel_height;
|
||
|
UWORD largest_frame_size;
|
||
|
WORD flags;
|
||
|
ULONG frame0_offset;
|
||
|
ULONG frame0_end;
|
||
|
/* ULONG data_seek_offset, UWORD frame_size ... */
|
||
|
} WSA_FileHeaderType;
|
||
|
|
||
|
#define WSA_FILE_HEADER_SIZE ( sizeof(WSA_FileHeaderType) - (2 * sizeof(ULONG)) )
|
||
|
|
||
|
/*=========================================================================*/
|
||
|
/* The following PRIVATE functions are in this file: */
|
||
|
/*=========================================================================*/
|
||
|
|
||
|
PRIVATE ULONG Get_Resident_Frame_Offset( BYTE *file_buffer, WORD frame );
|
||
|
PRIVATE ULONG Get_File_Frame_Offset( WORD file_handle, WORD frame, WORD palette_adjust);
|
||
|
PRIVATE BOOL Apply_Delta(SysAnimHeaderType *sys_header, WORD curr_frame, BYTE *dest_ptr, WORD dest_w);
|
||
|
/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
|
||
|
|
||
|
|
||
|
/***************************************************************************
|
||
|
* OPEN_ANIMATION -- Opens an animation file and reads into buffer *
|
||
|
* *
|
||
|
* INPUT: BYTE *file_name of animation sequence file. *
|
||
|
* BYTE *user_buffer pointer if one exists (NULL ok) *
|
||
|
* ULONG user_buffer_size if known (NULL ok) *
|
||
|
* WSAOpenType user_flags - flags on how to open. *
|
||
|
* UBYTE *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(BYTE const *file_name, BYTE *user_buffer, LONG user_buffer_size, WSAOpenType user_flags, UBYTE *palette)
|
||
|
{
|
||
|
WORD fh, anim_flags;
|
||
|
WORD palette_adjust;
|
||
|
UWORD offsets_size;
|
||
|
UWORD frame0_size;
|
||
|
LONG target_buffer_size, delta_buffer_size, file_buffer_size;
|
||
|
LONG max_buffer_size, min_buffer_size;
|
||
|
BYTE *sys_anim_header_buffer;
|
||
|
BYTE *target_buffer;
|
||
|
BYTE *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, (BYTE *) &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(ULONG) * (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 = (UWORD) 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 = (ULONG) 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 BYTES ON NOW FOR IT TO WORK.
|
||
|
delta_buffer_size = (ULONG) file_header.largest_frame_size + EXTRA_BYTES_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 = (BYTE *) 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 = (BYTE *) Add_Long_To_Pointer(sys_anim_header_buffer, sizeof(SysAnimHeaderType));
|
||
|
delta_buffer = (BYTE *) 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, (UWORD) 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 =
|
||
|
(UWORD) 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 = (BYTE *)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 = (BYTE *)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 = (WORD) -1;
|
||
|
Close_File(fh);
|
||
|
}
|
||
|
else {
|
||
|
sys_header -> file_handle = fh;
|
||
|
}
|
||
|
|
||
|
LCW_Uncompress(delta_back, delta_buffer, sys_header->largest_frame_size);
|
||
|
|
||
|
// Finally set the flags,
|
||
|
sys_header->flags = 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. *
|
||
|
* WORD frame_number wanted to be displayed *
|
||
|
* WORD x_pixel position of left side of animation on page *
|
||
|
* WORD y_pixel position of top of animation on page *
|
||
|
* *
|
||
|
* OUTPUT: BOOL if successfull or not. *
|
||
|
* *
|
||
|
* WARNINGS: *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 11/27/1991 SB : Created. *
|
||
|
*=========================================================================*/
|
||
|
#pragma argsused
|
||
|
BOOL cdecl Animate_Frame(VOID *handle, VideoViewPortClass& view,
|
||
|
WORD frame_number, WORD x_pixel, WORD y_pixel,
|
||
|
WSAType flags_and_prio, VOID *magic_cols, VOID *magic)
|
||
|
{
|
||
|
SysAnimHeaderType *sys_header; // fix up the VOID pointer past in.
|
||
|
WORD curr_frame; // current frame we are on.
|
||
|
WORD total_frames; // number of frames in anim.
|
||
|
WORD distance; // distance to desired frame.
|
||
|
WORD search_dir; // direcion to search for desired frame.
|
||
|
WORD search_frames; // How many frames to search.
|
||
|
WORD loop; // Just a loop varible.
|
||
|
BYTE *frame_buffer; // our destination.
|
||
|
BOOL direct_to_dest; // are we going directly to the destination?
|
||
|
WORD 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 += (WORD)sys_header->pixel_x;
|
||
|
y_pixel += (WORD)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 = (BYTE *)Add_Long_To_Pointer(sys_header, sizeof(SysAnimHeaderType));
|
||
|
direct_to_dest = FALSE;
|
||
|
}
|
||
|
else {
|
||
|
frame_buffer = (BYTE *)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
|
||
|
WORD flags = ((UWORD)flags_and_prio & 0xFF00u) >> 12u;
|
||
|
WORD 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;
|
||
|
}
|
||
|
/***************************************************************************
|
||
|
* ANIMATE_FRAME -- Displays a frame of a given animation *
|
||
|
* *
|
||
|
* INPUT: VOID *handle to the animation. *
|
||
|
* WORD frame_number wanted to be displayed *
|
||
|
* WORD x_pixel position of left side of animation on page *
|
||
|
* WORD y_pixel position of top of animation on page *
|
||
|
* *
|
||
|
* OUTPUT: BOOL if successfull or not. *
|
||
|
* *
|
||
|
* WARNINGS: *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 11/27/1991 SB : Created. *
|
||
|
*=========================================================================*/
|
||
|
#pragma argsused
|
||
|
BOOL cdecl Animate_Frame(VOID *handle, GraphicViewPortClass& view,
|
||
|
WORD frame_number, WORD x_pixel, WORD y_pixel,
|
||
|
WSAType flags_and_prio, VOID *magic_cols, VOID *magic)
|
||
|
{
|
||
|
SysAnimHeaderType *sys_header; // fix up the VOID pointer past in.
|
||
|
WORD curr_frame; // current frame we are on.
|
||
|
WORD total_frames; // number of frames in anim.
|
||
|
WORD distance; // distance to desired frame.
|
||
|
WORD search_dir; // direcion to search for desired frame.
|
||
|
WORD search_frames; // How many frames to search.
|
||
|
WORD loop; // Just a loop varible.
|
||
|
BYTE *frame_buffer; // our destination.
|
||
|
BOOL direct_to_dest; // are we going directly to the destination?
|
||
|
WORD 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 += (WORD)sys_header->pixel_x;
|
||
|
y_pixel += (WORD)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 = (BYTE *)Add_Long_To_Pointer(sys_header, sizeof(SysAnimHeaderType));
|
||
|
direct_to_dest = FALSE;
|
||
|
}
|
||
|
else {
|
||
|
frame_buffer = (BYTE *)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
|
||
|
WORD flags = ((UWORD)flags_and_prio & 0xFF00u) >> 12u;
|
||
|
WORD 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;
|
||
|
}
|
||
|
|
||
|
|
||
|
/***************************************************************************
|
||
|
* ANIMATE_FRAME_COUNT -- Return Number of frames in an animation. *
|
||
|
* *
|
||
|
* INPUT: VOID *handle to the animation. *
|
||
|
* *
|
||
|
* OUTPUT: WORD number of frames in animation. *
|
||
|
* *
|
||
|
* WARNINGS: *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 12/05/1991 SB : Created. *
|
||
|
*=========================================================================*/
|
||
|
WORD cdecl Get_Animation_Frame_Count(VOID *handle)
|
||
|
{
|
||
|
SysAnimHeaderType *sys_header;
|
||
|
|
||
|
if (!handle) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
sys_header = (SysAnimHeaderType *) handle;
|
||
|
return((WORD)sys_header->total_frames);
|
||
|
}
|
||
|
|
||
|
|
||
|
/***************************************************************************
|
||
|
* GET_ANIM_X -- Gets the x from an animation *
|
||
|
* *
|
||
|
* *
|
||
|
* INPUT: VOID * to the animation that we are processing *
|
||
|
* *
|
||
|
* OUTPUT: WORD the x of the animation we are processing *
|
||
|
* *
|
||
|
* WARNINGS: *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 07/03/1992 DRD : Created. *
|
||
|
*=========================================================================*/
|
||
|
WORD 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: WORD the y of the animation we are processing *
|
||
|
* *
|
||
|
* WARNINGS: *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 10/14/1992 PWG : Created. *
|
||
|
*=========================================================================*/
|
||
|
WORD 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: WORD the width of the animation we are processing *
|
||
|
* *
|
||
|
* WARNINGS: *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 10/14/1992 PWG : Created. *
|
||
|
*=========================================================================*/
|
||
|
WORD 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: WORD the height of the animation we are processing *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 10/14/1992 PWG : Created. *
|
||
|
*=========================================================================*/
|
||
|
WORD 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: WORD True if the animation has a set palette. False if the *
|
||
|
* animation does not. *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 10/14/1992 PWG : Created. *
|
||
|
*=========================================================================*/
|
||
|
WORD 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: ULONG number of byte used by animation. *
|
||
|
* *
|
||
|
* WARNINGS: *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 05/23/1994 SKB : Created. *
|
||
|
*=========================================================================*/
|
||
|
ULONG 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: BYTE *file_buffer in RAM of animation file. *
|
||
|
* WORD frame number that we need the offset of. *
|
||
|
* *
|
||
|
* OUTPUT: WORD offset of frame requested. *
|
||
|
* *
|
||
|
* WARNINGS: *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 11/26/1991 SB : Created. *
|
||
|
*=========================================================================*/
|
||
|
PRIVATE ULONG Get_Resident_Frame_Offset( BYTE *file_buffer, WORD frame )
|
||
|
{
|
||
|
ULONG frame0_size;
|
||
|
ULONG *lptr;
|
||
|
|
||
|
// If there is a frame 0, the calculate its size.
|
||
|
lptr = (ULONG *) 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: WORD file_handle of animation file. *
|
||
|
* WORD frame number that we need the offset of. *
|
||
|
* *
|
||
|
* OUTPUT: WORD offset of frame requested. *
|
||
|
* *
|
||
|
* WARNINGS: *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 11/26/1991 SB : Created. *
|
||
|
*=========================================================================*/
|
||
|
PRIVATE ULONG Get_File_Frame_Offset( WORD file_handle, WORD frame, WORD palette_adjust)
|
||
|
{
|
||
|
ULONG offset;
|
||
|
|
||
|
Seek_File(file_handle, (frame << 2) + WSA_FILE_HEADER_SIZE, SEEK_SET);
|
||
|
|
||
|
if (Read_File(file_handle, (BYTE *) &offset, sizeof(ULONG)) != sizeof(ULONG)) {
|
||
|
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.*
|
||
|
* WORD 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, WORD curr_frame, BYTE *dest_ptr, WORD dest_w)
|
||
|
{
|
||
|
BYTE *data_ptr, *delta_back;
|
||
|
WORD file_handle, palette_adjust;
|
||
|
ULONG 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 = (BYTE *)Add_Long_To_Pointer(sys_header->file_buffer, frame_offset);
|
||
|
delta_back = (BYTE *)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 = (BYTE *)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);
|
||
|
}
|
||
|
|