2006-04-13 20:47:06 +00:00
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
/*
|
|
|
|
Copyright (C) 1996, 2003 - 3D Realms Entertainment
|
|
|
|
|
|
|
|
This file is part of Duke Nukem 3D version 1.5 - Atomic Edition
|
|
|
|
|
|
|
|
Duke Nukem 3D 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 2
|
|
|
|
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, write to the Free Software
|
|
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
|
|
|
|
Original Source: 1996 - Todd Replogle
|
|
|
|
Prepared for public release: 03/21/2003 - Charlie Wiederhold, 3D Realms
|
|
|
|
Modifications for JonoF's port by Jonathon Fowler (jonof@edgenetwk.com)
|
|
|
|
*/
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
|
|
|
|
#include "compat.h"
|
2009-04-26 05:57:42 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
#include "util_lib.h"
|
|
|
|
#include "animlib.h"
|
|
|
|
|
|
|
|
//****************************************************************************
|
|
|
|
//
|
|
|
|
// GLOBALS
|
|
|
|
//
|
|
|
|
//****************************************************************************
|
|
|
|
|
|
|
|
//****************************************************************************
|
|
|
|
//
|
|
|
|
// LOCALS
|
|
|
|
//
|
|
|
|
//****************************************************************************
|
|
|
|
static anim_t * anim=NULL;
|
2009-04-26 05:57:42 +00:00
|
|
|
static int32_t Anim_Started = FALSE;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
//****************************************************************************
|
|
|
|
//
|
|
|
|
// CheckAnimStarted ()
|
|
|
|
//
|
|
|
|
//****************************************************************************
|
|
|
|
|
2008-06-29 10:41:01 +00:00
|
|
|
static void CheckAnimStarted(char * funcname)
|
|
|
|
{
|
|
|
|
if (!Anim_Started)
|
|
|
|
Error("ANIMLIB_%s: Anim has not been initialized\n",funcname);
|
|
|
|
}
|
2010-03-15 00:06:48 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
//****************************************************************************
|
|
|
|
//
|
|
|
|
// findpage ()
|
|
|
|
// - given a frame number return the large page number it resides in
|
|
|
|
//
|
|
|
|
//****************************************************************************
|
|
|
|
|
2009-04-26 05:57:42 +00:00
|
|
|
uint16_t findpage(uint16_t framenumber)
|
2008-06-29 10:41:01 +00:00
|
|
|
{
|
2010-03-15 00:06:48 +00:00
|
|
|
// curlpnum is initialized to 0xffff, obviously
|
|
|
|
uint16_t i = (uint16_t)(anim->curlpnum & ~0xffff);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2008-06-29 10:41:01 +00:00
|
|
|
CheckAnimStarted("findpage");
|
2010-03-15 00:06:48 +00:00
|
|
|
|
|
|
|
if (framenumber < anim->currentframe)
|
|
|
|
i = 0;
|
|
|
|
|
|
|
|
for (; i<anim->lpheader.nLps; i++)
|
|
|
|
if (anim->LpArray[i].baseRecord <= framenumber &&
|
|
|
|
anim->LpArray[i].baseRecord + anim->LpArray[i].nRecords > framenumber)
|
2008-06-29 10:41:01 +00:00
|
|
|
return(i);
|
2010-03-15 00:06:48 +00:00
|
|
|
|
2008-06-29 10:41:01 +00:00
|
|
|
return(i);
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
|
|
|
|
//****************************************************************************
|
|
|
|
//
|
|
|
|
// loadpage ()
|
|
|
|
// - seek out and load in the large page specified
|
|
|
|
//
|
|
|
|
//****************************************************************************
|
|
|
|
|
2010-03-14 11:15:53 +00:00
|
|
|
void loadpage(uint16_t pagenumber, uint16_t **pagepointer)
|
2008-06-29 10:41:01 +00:00
|
|
|
{
|
|
|
|
CheckAnimStarted("loadpage");
|
2010-03-14 11:15:53 +00:00
|
|
|
|
2010-03-15 00:06:48 +00:00
|
|
|
if (anim->curlpnum == pagenumber)
|
|
|
|
return;
|
2010-03-14 11:15:53 +00:00
|
|
|
|
2010-03-15 00:06:48 +00:00
|
|
|
anim->curlp = &anim->LpArray[(anim->curlpnum = pagenumber)];
|
|
|
|
*pagepointer = (uint16_t *)(anim->buffer + 0xb00 + (pagenumber*IMAGEBUFFERSIZE) +
|
|
|
|
sizeof(lp_descriptor) + sizeof(uint16_t));
|
2008-06-29 10:41:01 +00:00
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
|
|
|
|
//****************************************************************************
|
|
|
|
//
|
|
|
|
// CPlayRunSkipDump ()
|
2010-03-15 00:06:48 +00:00
|
|
|
// - I found this less obfuscated version of the anm decompressor around,
|
|
|
|
// says it's (c) 1998 "Jari Komppa aka Sol/Trauma". This code is
|
|
|
|
// public domain and has been modified a bit by me.
|
|
|
|
//
|
|
|
|
// - As a side note, it looks like this format came about in 1989 and
|
|
|
|
// never went anywhere after that, and appears to have been the format
|
|
|
|
// used by Electronic Arts' DeluxePaint Animation, which never made it
|
|
|
|
// past version 1.0.
|
2006-04-13 20:47:06 +00:00
|
|
|
//
|
|
|
|
//****************************************************************************
|
|
|
|
|
2010-03-15 00:06:48 +00:00
|
|
|
static void CPlayRunSkipDump(uint8_t * srcP, uint8_t * dstP)
|
2008-06-29 10:41:01 +00:00
|
|
|
{
|
|
|
|
do
|
|
|
|
{
|
2010-03-15 00:06:48 +00:00
|
|
|
int32_t color, count=*srcP++;
|
|
|
|
|
|
|
|
if (count==0)
|
|
|
|
{
|
|
|
|
/* Short RLE */
|
|
|
|
count=*srcP;
|
|
|
|
color=*(srcP+1);
|
|
|
|
srcP += 2;
|
|
|
|
Bmemset(dstP,color,count);
|
|
|
|
dstP+=count;
|
|
|
|
}
|
|
|
|
else if ((count&0x80) == 0)
|
|
|
|
{
|
|
|
|
/* Short copy */
|
|
|
|
Bmemcpy(dstP,srcP,count);
|
|
|
|
dstP+=count;
|
|
|
|
srcP+=count;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* long op or short skip */
|
|
|
|
count &= ~0x80;
|
|
|
|
|
|
|
|
if (count > 0) /* short skip */
|
|
|
|
dstP+=count;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* long op */
|
|
|
|
count = *srcP+((*(srcP+1))<<8);
|
|
|
|
srcP += 2;
|
|
|
|
|
|
|
|
if (count==0) /* stop sign */
|
|
|
|
return;
|
|
|
|
|
|
|
|
if ((count&0x8000) == 0) /* long skip */
|
|
|
|
dstP+=count;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
count &= ~0x8000;
|
|
|
|
|
|
|
|
if ((count&0x4000) == 0)
|
|
|
|
{
|
|
|
|
/* long copy */
|
|
|
|
Bmemcpy(dstP,srcP,count);
|
|
|
|
dstP+=count;
|
|
|
|
srcP+=count;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* and finally, long RLE. */
|
|
|
|
count &= ~0x4000;
|
|
|
|
color=*srcP++;
|
|
|
|
Bmemset(dstP,color,count);
|
|
|
|
dstP+=count;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-06-29 10:41:01 +00:00
|
|
|
}
|
2010-03-15 00:06:48 +00:00
|
|
|
while (1);
|
2008-06-29 10:41:01 +00:00
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
|
|
|
|
//****************************************************************************
|
|
|
|
//
|
|
|
|
// renderframe ()
|
|
|
|
// - draw the frame sepcified from the large page in the buffer pointed to
|
|
|
|
//
|
|
|
|
//****************************************************************************
|
|
|
|
|
2009-04-26 05:57:42 +00:00
|
|
|
void renderframe(uint16_t framenumber, uint16_t *pagepointer)
|
2008-06-29 10:41:01 +00:00
|
|
|
{
|
2009-04-26 05:57:42 +00:00
|
|
|
uint16_t offset=0;
|
|
|
|
uint16_t i;
|
|
|
|
uint16_t destframe;
|
|
|
|
uint8_t *ppointer;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2008-06-29 10:41:01 +00:00
|
|
|
CheckAnimStarted("renderframe");
|
2010-03-14 11:15:53 +00:00
|
|
|
destframe = framenumber - anim->curlp->baseRecord;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2008-06-29 10:41:01 +00:00
|
|
|
for (i = 0; i < destframe; i++)
|
|
|
|
offset += B_LITTLE16(pagepointer[i]);
|
2010-03-14 11:15:53 +00:00
|
|
|
|
2009-04-26 05:57:42 +00:00
|
|
|
ppointer = (uint8_t *)pagepointer;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2010-03-14 11:15:53 +00:00
|
|
|
ppointer+=anim->curlp->nRecords*2+offset;
|
2008-06-29 10:41:01 +00:00
|
|
|
if (ppointer[1])
|
2009-04-26 05:57:42 +00:00
|
|
|
ppointer += (4 + B_LITTLE16(((uint16_t *)ppointer)[1]) + (B_LITTLE16(((uint16_t *)ppointer)[1]) & 1));
|
2008-06-29 10:41:01 +00:00
|
|
|
else
|
|
|
|
ppointer+=4;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2009-01-31 00:02:14 +00:00
|
|
|
CPlayRunSkipDump((uint8_t *)ppointer, (uint8_t *)anim->imagebuffer);
|
2008-06-29 10:41:01 +00:00
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
|
|
|
|
//****************************************************************************
|
|
|
|
//
|
|
|
|
// drawframe ()
|
|
|
|
// - high level frame draw routine
|
|
|
|
//
|
|
|
|
//****************************************************************************
|
|
|
|
|
2009-04-26 05:57:42 +00:00
|
|
|
void drawframe(uint16_t framenumber)
|
2008-06-29 10:41:01 +00:00
|
|
|
{
|
|
|
|
CheckAnimStarted("drawframe");
|
2010-03-14 11:15:53 +00:00
|
|
|
loadpage(findpage(framenumber), &anim->thepage);
|
2008-06-29 10:41:01 +00:00
|
|
|
renderframe(framenumber, anim->thepage);
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
|
|
|
|
//****************************************************************************
|
|
|
|
//
|
|
|
|
// ANIM_LoadAnim ()
|
|
|
|
//
|
|
|
|
//****************************************************************************
|
|
|
|
|
2008-06-29 10:41:01 +00:00
|
|
|
void ANIM_LoadAnim(char * buffer)
|
|
|
|
{
|
2009-04-26 05:57:42 +00:00
|
|
|
uint16_t i;
|
2008-06-29 10:41:01 +00:00
|
|
|
|
|
|
|
if (!Anim_Started)
|
|
|
|
{
|
2009-10-07 06:47:35 +00:00
|
|
|
anim = Bmalloc(sizeof(anim_t));
|
2009-04-26 05:57:42 +00:00
|
|
|
Anim_Started = TRUE;
|
2008-06-29 10:41:01 +00:00
|
|
|
}
|
|
|
|
|
2009-01-09 09:29:17 +00:00
|
|
|
anim->buffer = (uint8_t *)buffer;
|
2008-06-29 10:41:01 +00:00
|
|
|
anim->curlpnum = 0xffff;
|
|
|
|
anim->currentframe = -1;
|
2010-03-14 11:42:13 +00:00
|
|
|
Bmemcpy(&anim->lpheader, buffer, sizeof(lpfileheader));
|
2008-06-29 10:41:01 +00:00
|
|
|
|
|
|
|
anim->lpheader.id = B_LITTLE32(anim->lpheader.id);
|
|
|
|
anim->lpheader.maxLps = B_LITTLE16(anim->lpheader.maxLps);
|
|
|
|
anim->lpheader.nLps = B_LITTLE16(anim->lpheader.nLps);
|
|
|
|
anim->lpheader.nRecords = B_LITTLE32(anim->lpheader.nRecords);
|
|
|
|
anim->lpheader.maxRecsPerLp = B_LITTLE16(anim->lpheader.maxRecsPerLp);
|
|
|
|
anim->lpheader.lpfTableOffset = B_LITTLE16(anim->lpheader.lpfTableOffset);
|
|
|
|
anim->lpheader.contentType = B_LITTLE32(anim->lpheader.contentType);
|
|
|
|
anim->lpheader.width = B_LITTLE16(anim->lpheader.width);
|
|
|
|
anim->lpheader.height = B_LITTLE16(anim->lpheader.height);
|
|
|
|
anim->lpheader.nFrames = B_LITTLE32(anim->lpheader.nFrames);
|
|
|
|
anim->lpheader.framesPerSecond = B_LITTLE16(anim->lpheader.framesPerSecond);
|
|
|
|
|
2010-03-14 11:42:13 +00:00
|
|
|
buffer += sizeof(lpfileheader)+128;
|
2008-06-29 10:41:01 +00:00
|
|
|
// load the color palette
|
|
|
|
for (i = 0; i < 768; i += 3)
|
|
|
|
{
|
2010-03-14 11:42:13 +00:00
|
|
|
anim->pal[i+2] = (*buffer++)>>2;
|
|
|
|
anim->pal[i+1] = (*buffer++)>>2;
|
|
|
|
anim->pal[i] = (*buffer++)>>2;
|
2008-06-29 10:41:01 +00:00
|
|
|
buffer++;
|
|
|
|
}
|
|
|
|
// read in large page descriptors
|
2010-03-15 00:06:48 +00:00
|
|
|
|
2010-03-14 11:42:13 +00:00
|
|
|
Bmemcpy(&anim->LpArray, buffer,sizeof(anim->LpArray));
|
2008-06-29 10:41:01 +00:00
|
|
|
|
2010-03-14 11:42:13 +00:00
|
|
|
for (i = 0; i < sizeof(anim->LpArray)/sizeof(lp_descriptor); i++)
|
2008-06-29 10:41:01 +00:00
|
|
|
{
|
|
|
|
anim->LpArray[i].baseRecord = B_LITTLE16(anim->LpArray[i].baseRecord);
|
|
|
|
anim->LpArray[i].nRecords = B_LITTLE16(anim->LpArray[i].nRecords);
|
|
|
|
anim->LpArray[i].nBytes = B_LITTLE16(anim->LpArray[i].nBytes);
|
|
|
|
}
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
//****************************************************************************
|
|
|
|
//
|
|
|
|
// ANIM_FreeAnim ()
|
|
|
|
//
|
|
|
|
//****************************************************************************
|
|
|
|
|
2008-06-29 10:41:01 +00:00
|
|
|
void ANIM_FreeAnim(void)
|
|
|
|
{
|
|
|
|
if (Anim_Started)
|
|
|
|
{
|
2009-10-07 06:47:35 +00:00
|
|
|
Bfree(anim);
|
2009-04-26 05:57:42 +00:00
|
|
|
Anim_Started = FALSE;
|
2008-06-29 10:41:01 +00:00
|
|
|
}
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
//****************************************************************************
|
|
|
|
//
|
|
|
|
// ANIM_NumFrames ()
|
|
|
|
//
|
|
|
|
//****************************************************************************
|
|
|
|
|
2009-04-26 05:57:42 +00:00
|
|
|
int32_t ANIM_NumFrames(void)
|
2008-06-29 10:41:01 +00:00
|
|
|
{
|
|
|
|
CheckAnimStarted("NumFrames");
|
|
|
|
return anim->lpheader.nRecords;
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
//****************************************************************************
|
|
|
|
//
|
|
|
|
// ANIM_DrawFrame ()
|
|
|
|
//
|
|
|
|
//****************************************************************************
|
|
|
|
|
2009-04-26 05:57:42 +00:00
|
|
|
uint8_t * ANIM_DrawFrame(int32_t framenumber)
|
2008-06-29 10:41:01 +00:00
|
|
|
{
|
2009-04-26 05:57:42 +00:00
|
|
|
int32_t cnt;
|
2008-06-29 10:41:01 +00:00
|
|
|
|
|
|
|
CheckAnimStarted("DrawFrame");
|
|
|
|
if ((anim->currentframe != -1) && (anim->currentframe<=framenumber))
|
|
|
|
{
|
|
|
|
for (cnt = anim->currentframe; cnt < framenumber; cnt++)
|
|
|
|
drawframe(cnt);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (cnt = 0; cnt < framenumber; cnt++)
|
|
|
|
drawframe(cnt);
|
|
|
|
}
|
|
|
|
anim->currentframe = framenumber;
|
|
|
|
return anim->imagebuffer;
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
//****************************************************************************
|
|
|
|
//
|
|
|
|
// ANIM_GetPalette ()
|
|
|
|
//
|
|
|
|
//****************************************************************************
|
|
|
|
|
2009-04-26 05:57:42 +00:00
|
|
|
uint8_t * ANIM_GetPalette(void)
|
2008-06-29 10:41:01 +00:00
|
|
|
{
|
|
|
|
CheckAnimStarted("GetPalette");
|
|
|
|
return anim->pal;
|
|
|
|
}
|