mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-10 04:31:34 -10:00
1421 lines
35 KiB
C++
1421 lines
35 KiB
C++
/*
|
|
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
|
*
|
|
* All source code herein is the property of Volition, Inc. You may not sell
|
|
* or otherwise commercially exploit the source or things you created based on the
|
|
* source.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* $Logfile: /Freespace2/code/Anim/PackUnpack.cpp $
|
|
* $Revision: 2.13.2.2 $
|
|
* $Date: 2007-10-28 16:32:06 $
|
|
* $Author: taylor $
|
|
*
|
|
* Code for handling packing and unpacking in Hoffoss's RLE format, used for
|
|
* Anim files. Also handles Anim loading, creating Anim instances (for
|
|
* utilizing an Anim), and getting getting frames of the Anim.
|
|
*
|
|
* $Log: not supported by cvs2svn $
|
|
* Revision 2.13.2.1 2006/06/22 14:59:44 taylor
|
|
* fix various things that Valgrind has been complaining about
|
|
*
|
|
* Revision 2.13 2006/03/21 00:27:27 taylor
|
|
* some minor cleanup
|
|
*
|
|
* Revision 2.12 2006/01/22 19:57:35 wmcoolmon
|
|
* 0...1...2...4?
|
|
*
|
|
* Revision 2.11 2005/11/13 06:40:19 taylor
|
|
* add support for 8/16/24/32 bit output from ani frame decoder
|
|
*
|
|
* Revision 2.10 2005/05/24 03:13:36 taylor
|
|
* extra check to make sure that RLE reading never goes over frame size in new ANI formats
|
|
*
|
|
* Revision 2.9 2005/05/23 05:58:31 taylor
|
|
* quick catch for some corrupted anis, only a partial fix but it will do until something
|
|
* a bit more heavy duty comes along in the near future
|
|
*
|
|
* Revision 2.8 2005/05/12 17:49:10 taylor
|
|
* use vm_malloc(), vm_free(), vm_realloc(), vm_strdup() rather than system named macros
|
|
* fixes various problems and is past time to make the switch
|
|
*
|
|
* Revision 2.7 2004/07/26 20:47:23 Kazan
|
|
* remove MCD complete
|
|
*
|
|
* Revision 2.6 2004/07/12 16:32:41 Kazan
|
|
* MCD - define _MCD_CHECK to use memory tracking
|
|
*
|
|
* Revision 2.5 2004/03/05 09:01:53 Goober5000
|
|
* Uber pass at reducing #includes
|
|
* --Goober5000
|
|
*
|
|
* Revision 2.4 2004/02/14 00:18:29 randomtiger
|
|
* Please note that from now on OGL will only run with a registry set by Launcher v4. See forum for details.
|
|
* OK, these changes effect a lot of file, I suggest everyone updates ASAP:
|
|
* Removal of many files from project.
|
|
* Removal of meanless Gr_bitmap_poly variable.
|
|
* Removal of glide, directdraw, software modules all links to them, and all code specific to those paths.
|
|
* Removal of redundant Fred paths that arent needed for Fred OGL.
|
|
* Have seriously tidied the graphics initialisation code and added generic non standard mode functionality.
|
|
* Fixed many D3D non standard mode bugs and brought OGL up to the same level.
|
|
* Removed texture section support for D3D8, voodoo 2 and 3 cards will no longer run under fs2_open in D3D, same goes for any card with a maximum texture size less than 1024.
|
|
*
|
|
* Revision 2.3 2003/10/24 17:35:04 randomtiger
|
|
* Implemented support for 32bit TGA and JPG for D3D
|
|
* Also 32 bit PCX, but it still has some bugs to be worked out
|
|
* Moved convert_24_to_16 out of the bitmap pfunction structures and into packunpack.cpp because thats the only place that uses it.
|
|
*
|
|
* Revision 2.2 2003/03/18 10:07:00 unknownplayer
|
|
* The big DX/main line merge. This has been uploaded to the main CVS since I can't manage to get it to upload to the DX branch. Apologies to all who may be affected adversely, but I'll work to debug it as fast as I can.
|
|
*
|
|
* Revision 2.1.2.1 2002/11/04 03:02:27 randomtiger
|
|
*
|
|
* I have made some fairly drastic changes to the bumpman system. Now functionality can be engine dependant.
|
|
* This is so D3D8 can call its own loading code that will allow good efficient loading and use of textures that it desparately needs without
|
|
* turning bumpman.cpp into a total hook infested nightmare. Note the new bumpman code is still relying on a few of the of the old functions and all of the old bumpman arrays.
|
|
*
|
|
* I have done this by adding to the gr_screen list of function pointers that are set up by the engines init functions.
|
|
* I have named the define calls the same name as the original 'bm_' functions so that I havent had to change names all through the code.
|
|
*
|
|
* Rolled back to an old version of bumpman and made a few changes.
|
|
* Added new files: grd3dbumpman.cpp and .h
|
|
* Moved the bitmap init function to after the 3D engine is initialised
|
|
* Added includes where needed
|
|
* Disabled (for now) the D3D8 TGA loading - RT
|
|
*
|
|
* Revision 2.1 2002/08/01 01:41:04 penguin
|
|
* The big include file move
|
|
*
|
|
* Revision 2.0 2002/06/03 04:02:21 penguin
|
|
* Warpcore CVS sync
|
|
*
|
|
* Revision 1.1 2002/05/02 18:03:04 mharris
|
|
* Initial checkin - converted filenames and includes to lower case
|
|
*
|
|
*
|
|
* 12 7/30/99 10:10p Dave
|
|
* Fixed loading bar in 32 bit mode.
|
|
*
|
|
* 11 7/18/99 1:59p Johnson
|
|
* Fixed potential anim locking problem.
|
|
*
|
|
* 10 7/16/99 1:49p Dave
|
|
* 8 bit aabitmaps. yay.
|
|
*
|
|
* 9 7/13/99 1:15p Dave
|
|
* 32 bit support. Whee!
|
|
*
|
|
* 8 4/09/99 2:21p Dave
|
|
* Multiplayer beta stuff. CD checking.
|
|
*
|
|
* 7 1/14/99 12:48a Dave
|
|
* Todo list bug fixes. Made a pass at putting briefing icons back into
|
|
* FRED. Sort of works :(
|
|
*
|
|
* 6 12/01/98 5:53p Dave
|
|
* Simplified the way pixel data is swizzled. Fixed tga bitmaps to work
|
|
* properly in D3D and Glide.
|
|
*
|
|
* 5 12/01/98 8:06a Dave
|
|
* Temporary checkin to fix some texture transparency problems in d3d.
|
|
*
|
|
* 4 11/30/98 1:07p Dave
|
|
* 16 bit conversion, first run.
|
|
*
|
|
* 3 10/22/98 6:14p Dave
|
|
* Optimized some #includes in Anim folder. Put in the beginnings of
|
|
* parse/localization support for externalized strings and tstrings.tbl
|
|
*
|
|
* 2 10/07/98 10:52a Dave
|
|
* Initial checkin.
|
|
*
|
|
* 1 10/07/98 10:48a Dave
|
|
*
|
|
* 30 5/14/98 3:38p John
|
|
* Added in more non-darkening colors for Adam. Had to fix some bugs in
|
|
* BmpMan and Ani stuff to get this to work.
|
|
*
|
|
* 29 5/07/98 3:11a Lawrance
|
|
* Implement custom streaming code
|
|
*
|
|
* 28 11/19/97 8:28p Dave
|
|
* Hooked in Main Hall screen. Put in Anim support for ping ponging
|
|
* animations as well as general reversal of anim direction.
|
|
*
|
|
* 27 9/09/97 3:39p Sandeep
|
|
* warning level 4 bugs
|
|
*
|
|
* 26 8/22/97 8:21a Lawrance
|
|
* short circuit key frame check if keyframe matches frame we are
|
|
* searching for
|
|
*
|
|
* 25 8/21/97 5:11p Lawrance
|
|
* frame numbering for ANI's now is from 0 -> total_frames-1.
|
|
*
|
|
* 24 8/19/97 10:59a Lawrance
|
|
* fix problem with accessing key frames
|
|
*
|
|
* 23 7/28/97 10:42p Lawrance
|
|
* re-did interface to unpack_frame() to make more general
|
|
*
|
|
* 22 7/28/97 10:52a Lawrance
|
|
* correctly set bitmap flags in anim_get_frame()
|
|
*
|
|
* 21 7/21/97 5:10p Lawrance
|
|
* fix problem that was causing infinite recursion
|
|
*
|
|
* 20 7/20/97 6:57p Lawrance
|
|
* supporting new RLE format
|
|
*
|
|
* 19 6/27/97 4:36p Lawrance
|
|
* update pal translation table when gr_screen.signature changes
|
|
*
|
|
* 18 6/26/97 12:12a Lawrance
|
|
* supporting anti-aliased bitmap animations
|
|
*
|
|
* 17 6/25/97 3:03p Lawrance
|
|
* fix palette translation problem with anti-alised bitmaps
|
|
*
|
|
* 16 5/19/97 2:28p Lawrance
|
|
* changes some variables to flags
|
|
*
|
|
* 15 5/15/97 4:42p Lawrance
|
|
* supporting animations in-game
|
|
*
|
|
* 14 2/25/97 11:06a Lawrance
|
|
* moved some higher level functions to from PackUnpack to AnimPlay
|
|
*
|
|
* 13 2/19/97 9:51p Lawrance
|
|
* made keyframe decompression more effecient, moved
|
|
* default anim FPS to header file
|
|
*
|
|
* 12 2/19/97 4:00p Lawrance
|
|
* don't assert when cannot find anim filename, return a NULL instead
|
|
*
|
|
* 11 2/17/97 4:17p Hoffoss
|
|
* modified packing internal format and added random access function to an
|
|
* Anim frame.
|
|
*
|
|
* 10 2/17/97 2:59p Lawrance
|
|
* integrating into game
|
|
*
|
|
* 9 2/14/97 11:27p Lawrance
|
|
* optimized unpacking some more (Jason)
|
|
*
|
|
* 8 2/14/97 11:09p Hoffoss
|
|
* Made optimizations.
|
|
*
|
|
* 7 2/14/97 10:48p Hoffoss
|
|
* fixed bug.
|
|
*
|
|
* 6 2/14/97 10:38p Lawrance
|
|
* fixing bugs
|
|
*
|
|
* 5 2/14/97 5:38p Hoffoss
|
|
* Changes to get AnimCoverter project to compile and link.
|
|
*
|
|
* 4 2/14/97 3:29p Hoffoss
|
|
* Added header for MSDEV to fill in.
|
|
*
|
|
* $NoKeywords: $
|
|
*/
|
|
|
|
#include "anim/packunpack.h"
|
|
#include "bmpman/bmpman.h"
|
|
#include "graphics/2d.h"
|
|
#include "anim/animplay.h"
|
|
|
|
|
|
|
|
|
|
const int packer_code = PACKER_CODE;
|
|
const int transparent_code = 254;
|
|
|
|
void anim_check_for_palette_change(anim_instance *instance) {
|
|
if ( instance->parent->screen_sig != gr_screen.signature ) {
|
|
instance->parent->screen_sig = gr_screen.signature;
|
|
anim_set_palette(instance->parent);
|
|
}
|
|
}
|
|
|
|
anim_instance *init_anim_instance(anim *ptr, int bpp)
|
|
{
|
|
anim_instance *inst;
|
|
|
|
if (!ptr) {
|
|
Int3();
|
|
return NULL;
|
|
}
|
|
|
|
if ( ptr->flags & ANF_STREAMED ) {
|
|
if ( ptr->file_offset < 0 ) {
|
|
Int3();
|
|
return NULL;
|
|
}
|
|
} else {
|
|
if ( !ptr->data ) {
|
|
Int3();
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
ptr->instance_count++;
|
|
inst = (anim_instance *) vm_malloc(sizeof(anim_instance));
|
|
Assert(inst);
|
|
inst->frame_num = -1;
|
|
inst->last_frame_num = -1;
|
|
inst->parent = ptr;
|
|
inst->data = ptr->data;
|
|
inst->file_offset = ptr->file_offset;
|
|
inst->stop_now = FALSE;
|
|
inst->aa_color = NULL;
|
|
|
|
inst->frame = (ubyte *) vm_malloc(inst->parent->width * inst->parent->height * (bpp >> 3));
|
|
Assert( inst->frame != NULL );
|
|
memset( inst->frame, 0, inst->parent->width * inst->parent->height * (bpp >> 3) );
|
|
|
|
return inst;
|
|
}
|
|
|
|
void free_anim_instance(anim_instance *inst)
|
|
{
|
|
Assert(inst->frame);
|
|
vm_free(inst->frame);
|
|
inst->frame = NULL;
|
|
inst->parent->instance_count--;
|
|
inst->parent = NULL;
|
|
inst->data = NULL;
|
|
inst->file_offset = -1;
|
|
|
|
vm_free(inst);
|
|
}
|
|
|
|
int anim_get_next_frame(anim_instance *inst)
|
|
{
|
|
int bm, bitmap_flags;
|
|
int aabitmap = 0;
|
|
int bpp = 16;
|
|
|
|
if ( anim_instance_is_streamed(inst) ) {
|
|
if ( inst->file_offset <= 0 ) {
|
|
return -1;
|
|
}
|
|
} else {
|
|
if (!inst->data)
|
|
return -1;
|
|
}
|
|
|
|
inst->frame_num++;
|
|
if (inst->frame_num >= inst->parent->total_frames) {
|
|
inst->data = NULL;
|
|
inst->file_offset = inst->parent->file_offset;
|
|
return -1;
|
|
}
|
|
|
|
if (inst->parent->flags & ANF_XPARENT) {
|
|
// bitmap_flags = BMP_XPARENT;
|
|
bitmap_flags = 0;
|
|
} else {
|
|
bitmap_flags = 0;
|
|
}
|
|
|
|
bpp = 16;
|
|
if(inst->aa_color != NULL){
|
|
bitmap_flags |= BMP_AABITMAP;
|
|
aabitmap = 1;
|
|
bpp = 8;
|
|
}
|
|
|
|
anim_check_for_palette_change(inst);
|
|
|
|
BM_SELECT_TEX_FORMAT();
|
|
|
|
if ( anim_instance_is_streamed(inst) ) {
|
|
inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation, aabitmap, bpp);
|
|
} else {
|
|
inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation, aabitmap, bpp);
|
|
}
|
|
|
|
bm = bm_create(bpp, inst->parent->width, inst->parent->height, inst->frame, bitmap_flags);
|
|
bm_unload(bm);
|
|
return bm;
|
|
}
|
|
|
|
ubyte *anim_get_next_raw_buffer(anim_instance *inst, int xlate_pal, int aabitmap, int bpp)
|
|
{
|
|
if ( anim_instance_is_streamed(inst) ) {
|
|
if ( inst->file_offset < 0 ) {
|
|
return NULL;
|
|
}
|
|
} else {
|
|
if (!inst->data){
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
inst->frame_num++;
|
|
if (inst->frame_num >= inst->parent->total_frames) {
|
|
inst->data = NULL;
|
|
inst->file_offset = inst->parent->file_offset;
|
|
return NULL;
|
|
}
|
|
|
|
anim_check_for_palette_change(inst);
|
|
|
|
if ( anim_instance_is_streamed(inst) ) {
|
|
if ( xlate_pal ){
|
|
inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation, aabitmap, bpp);
|
|
} else {
|
|
inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, NULL, aabitmap, bpp);
|
|
}
|
|
} else {
|
|
if ( xlate_pal ){
|
|
inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation, aabitmap, bpp);
|
|
} else {
|
|
inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, NULL, aabitmap, bpp);
|
|
}
|
|
}
|
|
|
|
return inst->frame;
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
// anim_get_frame()
|
|
//
|
|
// Get a bitmap id from the anim_instance for the specified frame_num
|
|
//
|
|
// input: *inst => pointer to anim instance
|
|
// frame_num => frame number to get (first frame is 0)
|
|
// xlate_pal => DEFAULT PARM (value 1): whether to translate the palette
|
|
// to the current game palette
|
|
//
|
|
int anim_get_frame(anim_instance *inst, int frame_num, int xlate_pal)
|
|
{
|
|
/*
|
|
int bm, bitmap_flags, key = 0, offset = 0;
|
|
int idx;
|
|
|
|
if ((frame_num < 0) || (frame_num >= inst->parent->total_frames)) // illegal frame number
|
|
return -1;
|
|
|
|
int need_reset = 0;
|
|
if ( anim_instance_is_streamed(inst) ) {
|
|
if ( inst->file_offset < 0 ) {
|
|
need_reset = 1;
|
|
}
|
|
} else {
|
|
if ( !inst->data ) {
|
|
need_reset = 1;
|
|
}
|
|
}
|
|
|
|
if (need_reset || (inst->frame_num >= inst->parent->total_frames)) { // reset to valid info
|
|
inst->data = inst->parent->data;
|
|
inst->file_offset = inst->parent->file_offset;
|
|
inst->frame_num = 0;
|
|
}
|
|
|
|
bitmap_flags = 0;
|
|
if (inst->parent->flags & ANF_XPARENT) {
|
|
// bitmap_flags = BMP_XPARENT;
|
|
bitmap_flags = 0;
|
|
}
|
|
|
|
if ( inst->frame_num == frame_num ) {
|
|
bm = bm_create(16, inst->parent->width, inst->parent->height, inst->frame, bitmap_flags);
|
|
bm_unload(bm);
|
|
return bm;
|
|
}
|
|
|
|
if (inst->parent->flags & ANF_XPARENT){
|
|
// bitmap_flags = BMP_XPARENT;
|
|
bitmap_flags = 0;
|
|
} else {
|
|
bitmap_flags = 0;
|
|
}
|
|
|
|
idx = 0;
|
|
key = 0;
|
|
while(idx < inst->parent->num_keys){
|
|
if (( (inst->parent->keys[idx].frame_num-1) <= frame_num) && ( (inst->parent->keys[idx].frame_num-1) > key)) { // find closest key
|
|
key = inst->parent->keys[idx].frame_num - 1;
|
|
offset = inst->parent->keys[idx].offset;
|
|
|
|
if ( key == frame_num )
|
|
break;
|
|
}
|
|
idx++;
|
|
}
|
|
|
|
if ( key == frame_num ) {
|
|
inst->frame_num = key;
|
|
|
|
if ( anim_instance_is_streamed(inst) ) {
|
|
inst->file_offset = inst->parent->file_offset + offset;
|
|
} else {
|
|
inst->data = inst->parent->data + offset;
|
|
}
|
|
|
|
anim_check_for_palette_change(inst);
|
|
|
|
if ( anim_instance_is_streamed(inst) ) {
|
|
if ( xlate_pal ){
|
|
inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation);
|
|
} else {
|
|
inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, NULL);
|
|
}
|
|
} else {
|
|
if ( xlate_pal ){
|
|
inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation);
|
|
} else {
|
|
inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, NULL);
|
|
}
|
|
}
|
|
|
|
goto create_bitmap;
|
|
}
|
|
|
|
if (key > inst->frame_num) // best key is closer than current position
|
|
{
|
|
inst->frame_num = key;
|
|
|
|
if ( anim_instance_is_streamed(inst) ) {
|
|
inst->file_offset = inst->parent->file_offset + offset;
|
|
} else {
|
|
inst->data = inst->parent->data + offset;
|
|
}
|
|
|
|
anim_check_for_palette_change(inst);
|
|
|
|
if ( anim_instance_is_streamed(inst) ) {
|
|
if ( xlate_pal )
|
|
inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation);
|
|
else
|
|
inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, NULL);
|
|
} else {
|
|
if ( xlate_pal )
|
|
inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation);
|
|
else
|
|
inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, NULL);
|
|
}
|
|
}
|
|
|
|
while (inst->frame_num != frame_num) {
|
|
anim_check_for_palette_change(inst);
|
|
|
|
if ( anim_instance_is_streamed(inst) ) {
|
|
if ( xlate_pal )
|
|
inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation);
|
|
else
|
|
inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, NULL);
|
|
} else {
|
|
if ( xlate_pal )
|
|
inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation);
|
|
else
|
|
inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, NULL);
|
|
}
|
|
inst->frame_num++;
|
|
}
|
|
|
|
create_bitmap:
|
|
|
|
bm = bm_create(16, inst->parent->width, inst->parent->height, inst->frame, bitmap_flags);
|
|
bm_unload(bm);
|
|
return bm;
|
|
*/
|
|
Int3();
|
|
return -1;
|
|
}
|
|
|
|
// frame = frame pixel data to pack
|
|
// save = memory to store packed data to
|
|
// size = number of bytes to pack
|
|
// max = maximum number of packed bytes (size of buffer)
|
|
// returns: actual number of bytes data packed to or -1 if error
|
|
int pack_key_frame(ubyte *frame, ubyte *save, long size, long max, int compress_type)
|
|
{
|
|
int last = -32768, count = 0;
|
|
long packed_size = 1;
|
|
|
|
switch ( compress_type ) {
|
|
case PACKING_METHOD_RLE_KEY:
|
|
*save++ = PACKING_METHOD_RLE_KEY;
|
|
while (size--) {
|
|
if (*frame != last || count > 255) {
|
|
if (packed_size + 3 >= max)
|
|
return -1;
|
|
|
|
if (count < 3) {
|
|
if (last == packer_code) {
|
|
*save++ = (ubyte)packer_code;
|
|
*save++ = (ubyte)(count - 1);
|
|
packed_size += 2;
|
|
|
|
} else
|
|
while (count--) {
|
|
*save++ = (ubyte)last;
|
|
packed_size++;
|
|
}
|
|
|
|
} else {
|
|
*save++ = (ubyte)packer_code;
|
|
*save++ = (ubyte)(count - 1);
|
|
*save++ = (ubyte)last;
|
|
packed_size += 3;
|
|
}
|
|
|
|
count = 0;
|
|
last = *frame;
|
|
}
|
|
|
|
count++;
|
|
frame++;
|
|
}
|
|
|
|
if (packed_size + 3 >= max)
|
|
return -1;
|
|
|
|
if (count < 3) {
|
|
if (last == packer_code) {
|
|
*save++ = (ubyte)packer_code;
|
|
*save++ = (ubyte)(count - 1);
|
|
packed_size += 2;
|
|
|
|
} else
|
|
while (count--) {
|
|
*save++ = (ubyte)last;
|
|
packed_size++;
|
|
}
|
|
|
|
} else {
|
|
*save++ = (ubyte)packer_code;
|
|
*save++ = (ubyte)(count - 1);
|
|
*save++ = (ubyte)last;
|
|
packed_size += 3;
|
|
}
|
|
break;
|
|
|
|
case PACKING_METHOD_STD_RLE_KEY: {
|
|
ubyte *dest_start;
|
|
int i;
|
|
|
|
dest_start = save;
|
|
count = 1;
|
|
|
|
last = *frame++;
|
|
*save++ = PACKING_METHOD_STD_RLE_KEY;
|
|
for (i=1; i < size; i++ ) {
|
|
|
|
if ( *frame != last ) {
|
|
if ( count ) {
|
|
|
|
if (packed_size + 2 >= max)
|
|
return -1;
|
|
|
|
if ( (count == 1) && !(last & STD_RLE_CODE) ) {
|
|
*save++ = (ubyte)last;
|
|
packed_size++;
|
|
Assert( last != STD_RLE_CODE );
|
|
// printf("Just packed %d 1 times, since pixel change, no count included\n",last);
|
|
}
|
|
else {
|
|
count |= STD_RLE_CODE;
|
|
*save++ = (ubyte)count;
|
|
*save++ = (ubyte)last;
|
|
packed_size += 2;
|
|
// printf("Just packed %d %d times, since pixel change\n",last,count);
|
|
}
|
|
}
|
|
|
|
last = *frame;
|
|
count = 0;
|
|
}
|
|
|
|
count++;
|
|
frame++;
|
|
|
|
if ( count == 127 ) {
|
|
count |= STD_RLE_CODE;
|
|
*save++ = (ubyte)count;
|
|
*save++ = (ubyte)last;
|
|
packed_size += 2;
|
|
count = 0;
|
|
// printf("Just packed %d %d times, since count overflow\n",last,count);
|
|
|
|
}
|
|
} // end for
|
|
|
|
if (count) {
|
|
|
|
if (packed_size + 2 >= max)
|
|
return -1;
|
|
|
|
if ( (count == 1) && !(last & STD_RLE_CODE) ) {
|
|
*save++ = (ubyte)last;
|
|
packed_size++;
|
|
// printf("Just packed %d 1 times, at end since single pixel, no count\n",last);
|
|
Assert( last != STD_RLE_CODE );
|
|
}
|
|
else {
|
|
count |= STD_RLE_CODE;
|
|
*save++ = (ubyte)count;
|
|
*save++ = (ubyte)last;
|
|
packed_size += 2;
|
|
// printf("Just packed %d %d times, at end since pixel change\n",last,count);
|
|
}
|
|
}
|
|
|
|
Assert(packed_size == (save-dest_start) );
|
|
return packed_size;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
Assert(0);
|
|
return -1;
|
|
break;
|
|
} // end switch
|
|
|
|
return packed_size;
|
|
}
|
|
|
|
// frame = frame pixel data to pack
|
|
// frame2 = previous frame's pixel data
|
|
// save = memory to store packed data to
|
|
// size = number of bytes to pack
|
|
// max = maximum number of packed bytes (size of buffer)
|
|
// returns: actual number of bytes data packed to or -1 if error
|
|
int pack_frame(ubyte *frame, ubyte *frame2, ubyte *save, long size, long max, int compress_type)
|
|
{
|
|
int pixel, last = -32768, count = 0, i;
|
|
long packed_size = 1;
|
|
|
|
switch ( compress_type ) {
|
|
case PACKING_METHOD_RLE: // Hoffoss RLE regular frame
|
|
*save++ = PACKING_METHOD_RLE;
|
|
while (size--) {
|
|
if (*frame != *frame2++)
|
|
pixel = *frame;
|
|
else
|
|
pixel = transparent_code;
|
|
|
|
if (pixel != last || count > 255) {
|
|
if (packed_size + 3 >= max)
|
|
return -1;
|
|
|
|
if (count < 3) {
|
|
if (last == packer_code) {
|
|
*save++ = (ubyte)packer_code;
|
|
*save++ = (ubyte)(count - 1);
|
|
packed_size += 2;
|
|
|
|
} else
|
|
while (count--) {
|
|
*save++ = (ubyte)last;
|
|
packed_size++;
|
|
}
|
|
|
|
} else {
|
|
*save++ = (ubyte)packer_code;
|
|
*save++ = (ubyte)(count - 1);
|
|
*save++ = (ubyte)last;
|
|
packed_size += 3;
|
|
}
|
|
|
|
count = 0;
|
|
last = pixel;
|
|
}
|
|
|
|
frame++;
|
|
count++;
|
|
}
|
|
|
|
if (packed_size + 3 >= max)
|
|
return -1;
|
|
|
|
if (count < 3) {
|
|
if (last == packer_code) {
|
|
*save++ = (ubyte)packer_code;
|
|
*save++ = (ubyte)(count - 1);
|
|
packed_size += 2;
|
|
|
|
} else
|
|
while (count--) {
|
|
*save++ = (ubyte)last;
|
|
packed_size++;
|
|
}
|
|
|
|
} else {
|
|
*save++ = (ubyte)(packer_code);
|
|
*save++ = (ubyte)(count - 1);
|
|
*save++ = (ubyte)(last);
|
|
packed_size += 3;
|
|
}
|
|
break;
|
|
|
|
case PACKING_METHOD_STD_RLE: { // high bit count regular RLE frame
|
|
|
|
ubyte *dest_start;
|
|
|
|
dest_start = save;
|
|
count = 1;
|
|
|
|
if (*frame++ != *frame2++)
|
|
last = *frame;
|
|
else
|
|
last = transparent_code;
|
|
|
|
*save++ = PACKING_METHOD_STD_RLE;
|
|
for (i=1; i < size; i++ ) {
|
|
|
|
if (*frame != *frame2++)
|
|
pixel = *frame;
|
|
else
|
|
pixel = transparent_code;
|
|
|
|
if ( pixel != last ) {
|
|
if ( count ) {
|
|
|
|
if (packed_size + 2 >= max)
|
|
return -1;
|
|
|
|
if ( (count == 1) && !(last & STD_RLE_CODE) ) {
|
|
*save++ = (ubyte)last;
|
|
packed_size++;
|
|
Assert( last != STD_RLE_CODE );
|
|
}
|
|
else {
|
|
count |= STD_RLE_CODE;
|
|
*save++ = (ubyte)count;
|
|
*save++ = (ubyte)last;
|
|
packed_size += 2;
|
|
}
|
|
}
|
|
|
|
last = pixel;
|
|
count = 0;
|
|
}
|
|
|
|
count++;
|
|
frame++;
|
|
|
|
if ( count == 127 ) {
|
|
count |= STD_RLE_CODE;
|
|
*save++ = (ubyte)count;
|
|
*save++ = (ubyte)last;
|
|
packed_size += 2;
|
|
count = 0;
|
|
}
|
|
} // end for
|
|
|
|
if (count) {
|
|
|
|
if (packed_size + 2 >= max)
|
|
return -1;
|
|
|
|
if ( (count == 1) && !(last & STD_RLE_CODE) ) {
|
|
*save++ = (ubyte)last;
|
|
packed_size++;
|
|
Assert( last != STD_RLE_CODE );
|
|
}
|
|
else {
|
|
count |= STD_RLE_CODE;
|
|
*save++ = (ubyte)count;
|
|
*save++ = (ubyte)last;
|
|
packed_size += 2;
|
|
}
|
|
}
|
|
|
|
Assert(packed_size == (save-dest_start) );
|
|
return packed_size;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
Assert(0);
|
|
return -1;
|
|
break;
|
|
} // end switch
|
|
|
|
return packed_size;
|
|
}
|
|
|
|
// convert a 24 bit value to a 16 bit value
|
|
void convert_24_to_16(int bit_24, ushort *bit_16)
|
|
{
|
|
ubyte *pixel = (ubyte*)&bit_24;
|
|
ubyte alpha = 1;
|
|
|
|
bm_set_components((ubyte*)bit_16, (ubyte*)&pixel[0], (ubyte*)&pixel[1], (ubyte*)&pixel[2], &alpha);
|
|
}
|
|
|
|
// unpack a pixel given the passed index and the anim_instance's palette, return bytes stuffed
|
|
int unpack_pixel(anim_instance *ai, ubyte *data, ubyte pix, int aabitmap, int bpp)
|
|
{
|
|
int bit_24;
|
|
ushort bit_16 = 0;
|
|
ubyte bit_8 = 0;
|
|
ubyte al = 0;
|
|
ubyte r, g, b;
|
|
int pixel_size = (bpp / 8);
|
|
anim *a = ai->parent;
|
|
Assert(a);
|
|
|
|
// if this is an aabitmap, don't run through the palette
|
|
if(aabitmap){
|
|
switch(bpp){
|
|
case 16 :
|
|
bit_16 = (ushort)pix;
|
|
break;
|
|
case 8:
|
|
bit_8 = pix;
|
|
break;
|
|
default:
|
|
Int3();
|
|
}
|
|
} else {
|
|
// if the pixel value is 255, or is the xparent color, make it so
|
|
if(((a->palette[pix*3] == a->xparent_r) && (a->palette[pix*3+1] == a->xparent_g) && (a->palette[pix*3+2] == a->xparent_b)) ){
|
|
if (pixel_size > 2) {
|
|
bit_24 = 0;
|
|
} else {
|
|
r = b = 0;
|
|
g = 255;
|
|
|
|
bm_set_components((ubyte*)&bit_16, &r, &g, &b, &al);
|
|
}
|
|
} else {
|
|
if (pixel_size > 2) {
|
|
ubyte pixel[4];
|
|
pixel[0] = ai->parent->palette[pix * 3 + 2];
|
|
pixel[1] = ai->parent->palette[pix * 3 + 1];
|
|
pixel[2] = ai->parent->palette[pix * 3];
|
|
pixel[3] = 255;
|
|
memcpy(&bit_24, pixel, sizeof(int));
|
|
|
|
if (pixel_size == 4) {
|
|
bit_24 = INTEL_INT(bit_24);
|
|
}
|
|
} else {
|
|
// stuff the 24 bit value
|
|
memcpy(&bit_24, &ai->parent->palette[pix * 3], 3);
|
|
|
|
// convert to 16 bit
|
|
convert_24_to_16(bit_24, &bit_16);
|
|
}
|
|
}
|
|
}
|
|
|
|
// stuff the pixel
|
|
switch (bpp) {
|
|
case 32:
|
|
case 24:
|
|
memcpy(data, &bit_24, pixel_size);
|
|
break;
|
|
|
|
case 16:
|
|
memcpy(data, &bit_16, pixel_size);
|
|
break;
|
|
|
|
case 8:
|
|
*data = bit_8;
|
|
break;
|
|
|
|
default:
|
|
Int3();
|
|
return 0;
|
|
}
|
|
|
|
return pixel_size;
|
|
}
|
|
|
|
// unpack a pixel given the passed index and the anim_instance's palette, return bytes stuffed
|
|
int unpack_pixel_count(anim_instance *ai, ubyte *data, ubyte pix, int count = 0, int aabitmap = 0, int bpp = 8)
|
|
{
|
|
int bit_24;
|
|
int idx;
|
|
ubyte al = 0;
|
|
ushort bit_16 = 0;
|
|
ubyte bit_8 = 0;
|
|
anim *a = ai->parent;
|
|
int pixel_size = (bpp / 8);
|
|
ubyte r, g, b;
|
|
Assert(a);
|
|
|
|
// if this is an aabitmap, don't run through the palette
|
|
if(aabitmap){
|
|
switch(bpp){
|
|
case 16 :
|
|
bit_16 = (ushort)pix;
|
|
break;
|
|
case 8 :
|
|
bit_8 = pix;
|
|
break;
|
|
default :
|
|
Int3();
|
|
}
|
|
} else {
|
|
// if the pixel value is 255, or is the xparent color, make it so
|
|
if(((a->palette[pix*3] == a->xparent_r) && (a->palette[pix*3+1] == a->xparent_g) && (a->palette[pix*3+2] == a->xparent_b)) ){
|
|
if (pixel_size > 2) {
|
|
bit_24 = 0;
|
|
} else {
|
|
r = b = 0;
|
|
g = 255;
|
|
|
|
bm_set_components((ubyte*)&bit_16, &r, &g, &b, &al);
|
|
}
|
|
} else {
|
|
if (pixel_size > 2) {
|
|
ubyte pixel[4];
|
|
pixel[0] = ai->parent->palette[pix * 3 + 2];
|
|
pixel[1] = ai->parent->palette[pix * 3 + 1];
|
|
pixel[2] = ai->parent->palette[pix * 3];
|
|
pixel[3] = 255;
|
|
memcpy(&bit_24, pixel, sizeof(int));
|
|
|
|
if (pixel_size == 4) {
|
|
bit_24 = INTEL_INT(bit_24);
|
|
}
|
|
} else {
|
|
// stuff the 24 bit value
|
|
memcpy(&bit_24, &ai->parent->palette[pix * 3], 3);
|
|
|
|
// convert to 16 bit
|
|
convert_24_to_16(bit_24, &bit_16);
|
|
}
|
|
}
|
|
}
|
|
|
|
// stuff the pixel
|
|
for (idx=0; idx<count; idx++) {
|
|
switch (bpp) {
|
|
case 32:
|
|
case 24:
|
|
memcpy(data + (idx * pixel_size), &bit_24, pixel_size);
|
|
break;
|
|
|
|
case 16:
|
|
memcpy(data + (idx * pixel_size), &bit_16, pixel_size);
|
|
break;
|
|
|
|
case 8:
|
|
*(data + idx) = bit_8;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return (pixel_size * count);
|
|
}
|
|
|
|
// ptr = packed data to unpack
|
|
// frame = where to store unpacked data to
|
|
// size = total number of unpacked pixels requested
|
|
// pal_translate = color translation lookup table (NULL if no palette translation desired)
|
|
ubyte *unpack_frame(anim_instance *ai, ubyte *ptr, ubyte *frame, int size, ubyte *pal_translate, int aabitmap, int bpp)
|
|
{
|
|
int xlate_pal, value, count = 0;
|
|
int stuffed;
|
|
int pixel_size = (bpp / 8);
|
|
|
|
if ( pal_translate == NULL ) {
|
|
xlate_pal = 0;
|
|
}
|
|
else {
|
|
xlate_pal = 1;
|
|
}
|
|
|
|
if (*ptr == PACKING_METHOD_RLE_KEY) { // key frame, Hoffoss's RLE format
|
|
ptr++;
|
|
while (size > 0) {
|
|
value = *ptr++;
|
|
if (value != packer_code) {
|
|
if ( xlate_pal ){
|
|
stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
|
|
} else {
|
|
stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
|
|
}
|
|
frame += stuffed;
|
|
size--;
|
|
} else {
|
|
count = *ptr++;
|
|
if (count < 2){
|
|
value = packer_code;
|
|
} else {
|
|
value = *ptr++;
|
|
}
|
|
|
|
if (++count > size){
|
|
count = size;
|
|
}
|
|
|
|
if ( xlate_pal ){
|
|
stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
|
|
} else {
|
|
stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
|
|
}
|
|
|
|
frame += stuffed;
|
|
size -= count;
|
|
}
|
|
}
|
|
}
|
|
else if ( *ptr == PACKING_METHOD_STD_RLE_KEY) { // key frame, with high bit as count
|
|
ptr++;
|
|
while (size > 0) {
|
|
value = *ptr++;
|
|
if ( !(value & STD_RLE_CODE) ) {
|
|
if ( xlate_pal ){
|
|
stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
|
|
} else {
|
|
stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
|
|
}
|
|
|
|
frame += stuffed;
|
|
size--;
|
|
} else {
|
|
count = value & (~STD_RLE_CODE);
|
|
value = *ptr++;
|
|
|
|
if (count > size)
|
|
count = size;
|
|
|
|
size -= count;
|
|
Assert(size >= 0);
|
|
|
|
if ( xlate_pal ){
|
|
stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
|
|
} else {
|
|
stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
|
|
}
|
|
|
|
frame += stuffed;
|
|
}
|
|
}
|
|
}
|
|
else if (*ptr == PACKING_METHOD_RLE) { // normal frame, Hoffoss's RLE format
|
|
|
|
// test code, to show unused pixels
|
|
// memset(frame, 255, size);
|
|
|
|
ptr++;
|
|
while (size > 0) {
|
|
value = *ptr++;
|
|
if (value != packer_code) {
|
|
if (value != transparent_code) {
|
|
if ( xlate_pal ){
|
|
stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
|
|
} else {
|
|
stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
|
|
}
|
|
} else {
|
|
// temporary pixel
|
|
stuffed = pixel_size;
|
|
}
|
|
|
|
frame += stuffed;
|
|
size--;
|
|
} else {
|
|
count = *ptr++;
|
|
if (count < 2){
|
|
value = packer_code;
|
|
} else {
|
|
value = *ptr++;
|
|
}
|
|
|
|
if (++count > size){
|
|
count = size;
|
|
}
|
|
|
|
size -= count;
|
|
Assert(size >= 0);
|
|
|
|
if (value != transparent_code ) {
|
|
if ( xlate_pal ) {
|
|
stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
|
|
} else {
|
|
stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
|
|
}
|
|
} else {
|
|
stuffed = count * pixel_size;
|
|
}
|
|
|
|
frame += stuffed;
|
|
}
|
|
}
|
|
|
|
}
|
|
else if ( *ptr == PACKING_METHOD_STD_RLE) { // normal frame, with high bit as count
|
|
ptr++;
|
|
while (size > 0) {
|
|
value = *ptr++;
|
|
if ( !(value & STD_RLE_CODE) ) {
|
|
if (value != transparent_code) {
|
|
if ( xlate_pal ){
|
|
stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
|
|
} else {
|
|
stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
|
|
}
|
|
} else {
|
|
stuffed = pixel_size;
|
|
}
|
|
|
|
frame += stuffed;
|
|
size--;
|
|
} else {
|
|
count = value & (~STD_RLE_CODE);
|
|
value = *ptr++;
|
|
|
|
if (count > size)
|
|
count = size;
|
|
|
|
size -= count;
|
|
Assert(size >= 0);
|
|
|
|
if (value != transparent_code) {
|
|
if ( xlate_pal ){
|
|
stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
|
|
} else {
|
|
stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
|
|
}
|
|
} else {
|
|
stuffed = pixel_size * count;
|
|
}
|
|
|
|
frame += stuffed;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
// Assert(0); // unknown packing method
|
|
return NULL;
|
|
}
|
|
|
|
return ptr;
|
|
}
|
|
|
|
// ptr = packed data to unpack
|
|
// frame = where to store unpacked data to
|
|
// size = total number of unpacked pixels requested
|
|
// pal_translate = color translation lookup table (NULL if no palette translation desired)
|
|
int unpack_frame_from_file(anim_instance *ai, ubyte *frame, int size, ubyte *pal_translate, int aabitmap, int bpp)
|
|
{
|
|
int xlate_pal, value, count = 0;
|
|
int offset = 0;
|
|
int stuffed;
|
|
int pixel_size = (bpp / 8);
|
|
|
|
if ( pal_translate == NULL ) {
|
|
xlate_pal = 0;
|
|
}
|
|
else {
|
|
xlate_pal = 1;
|
|
}
|
|
|
|
if (anim_instance_get_byte(ai,offset) == PACKING_METHOD_RLE_KEY) { // key frame, Hoffoss's RLE format
|
|
offset++;
|
|
while (size > 0) {
|
|
value = anim_instance_get_byte(ai,offset);
|
|
offset++;
|
|
if (value != packer_code) {
|
|
if ( xlate_pal ){
|
|
stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
|
|
} else {
|
|
stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
|
|
}
|
|
|
|
frame += stuffed;
|
|
size--;
|
|
} else {
|
|
count = anim_instance_get_byte(ai,offset);
|
|
offset++;
|
|
if (count < 2) {
|
|
value = packer_code;
|
|
} else {
|
|
value = anim_instance_get_byte(ai,offset);
|
|
offset++;
|
|
}
|
|
|
|
if (++count > size){
|
|
count = size;
|
|
}
|
|
|
|
if ( xlate_pal ){
|
|
stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
|
|
} else {
|
|
stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
|
|
}
|
|
|
|
frame += stuffed;
|
|
size -= count;
|
|
}
|
|
}
|
|
}
|
|
else if ( anim_instance_get_byte(ai,offset) == PACKING_METHOD_STD_RLE_KEY) { // key frame, with high bit as count
|
|
offset++;
|
|
while (size > 0) {
|
|
value = anim_instance_get_byte(ai,offset);
|
|
offset++;
|
|
if ( !(value & STD_RLE_CODE) ) {
|
|
if ( xlate_pal ){
|
|
stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
|
|
} else {
|
|
stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
|
|
}
|
|
|
|
frame += stuffed;
|
|
size--;
|
|
} else {
|
|
count = value & (~STD_RLE_CODE);
|
|
value = anim_instance_get_byte(ai,offset);
|
|
offset++;
|
|
|
|
if (count > size)
|
|
count = size;
|
|
|
|
size -= count;
|
|
Assert(size >= 0);
|
|
|
|
if ( xlate_pal ){
|
|
stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
|
|
} else {
|
|
stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
|
|
}
|
|
|
|
frame += stuffed;
|
|
}
|
|
}
|
|
}
|
|
else if (anim_instance_get_byte(ai,offset) == PACKING_METHOD_RLE) { // normal frame, Hoffoss's RLE format
|
|
|
|
// test code, to show unused pixels
|
|
// memset(frame, 255, size);
|
|
|
|
offset++;
|
|
while (size > 0) {
|
|
value = anim_instance_get_byte(ai,offset);
|
|
offset++;
|
|
if (value != packer_code) {
|
|
if (value != transparent_code) {
|
|
if ( xlate_pal ){
|
|
stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
|
|
} else {
|
|
stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
|
|
}
|
|
} else {
|
|
stuffed = pixel_size;
|
|
}
|
|
|
|
frame += stuffed;
|
|
size--;
|
|
} else {
|
|
count = anim_instance_get_byte(ai,offset);
|
|
offset++;
|
|
|
|
if (count < 2) {
|
|
value = packer_code;
|
|
} else {
|
|
value = anim_instance_get_byte(ai,offset);
|
|
offset++;
|
|
}
|
|
if (++count > size){
|
|
count = size;
|
|
}
|
|
|
|
size -= count;
|
|
Assert(size >= 0);
|
|
|
|
if (value != transparent_code ) {
|
|
if ( xlate_pal ) {
|
|
stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
|
|
} else {
|
|
stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
|
|
}
|
|
} else {
|
|
stuffed = pixel_size * count;
|
|
}
|
|
|
|
frame += stuffed;
|
|
}
|
|
}
|
|
|
|
}
|
|
else if ( anim_instance_get_byte(ai,offset) ) { // normal frame, with high bit as count
|
|
offset++;
|
|
while (size > 0) {
|
|
value = anim_instance_get_byte(ai,offset);
|
|
offset++;
|
|
if ( !(value & STD_RLE_CODE) ) {
|
|
if (value != transparent_code) {
|
|
if ( xlate_pal ){
|
|
stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
|
|
} else {
|
|
stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
|
|
}
|
|
} else {
|
|
stuffed = pixel_size;
|
|
}
|
|
|
|
frame += stuffed;
|
|
size--;
|
|
} else {
|
|
count = value & (~STD_RLE_CODE);
|
|
value = anim_instance_get_byte(ai,offset);
|
|
offset++;
|
|
|
|
if (count > size)
|
|
count = size;
|
|
|
|
size -= count;
|
|
Assert(size >= 0);
|
|
|
|
if (value != transparent_code) {
|
|
if ( xlate_pal ){
|
|
stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
|
|
} else {
|
|
stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
|
|
}
|
|
} else {
|
|
stuffed = pixel_size * count;
|
|
}
|
|
|
|
frame += stuffed;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
// Int3(); // unknown packing method
|
|
return -1;
|
|
}
|
|
|
|
return ai->file_offset + offset;
|
|
}
|
|
|
|
|
|
// TODO: actually convert the frame data to correct palette at this point
|
|
void anim_set_palette(anim *ptr)
|
|
{
|
|
int i, xparent_found = 0;
|
|
|
|
// create the palette translation look-up table
|
|
for ( i = 0; i < 256; i++ ) {
|
|
|
|
//if ( (ptr->palette[i*3] == ptr->xparent_r) && (ptr->palette[i*3+1] == ptr->xparent_g) && (ptr->palette[i*3+2] == ptr->xparent_b) ) {
|
|
// ptr->palette_translation[i] = 255;
|
|
// xparent_found = 1;
|
|
//} else {
|
|
// ptr->palette_translation[i] = (ubyte)palette_find( ptr->palette[i*3], ptr->palette[i*3+1], ptr->palette[i*3+2] );
|
|
ptr->palette_translation[i] = (ubyte)i;
|
|
//}
|
|
}
|
|
|
|
if ( xparent_found ) {
|
|
ptr->flags |= ANF_XPARENT;
|
|
}
|
|
else {
|
|
ptr->flags &= ~ANF_XPARENT;
|
|
}
|
|
}
|