scummvm/scumm/costume.cpp
Eugene Sandulenko 154c4af8dc Mass-renamed all variables of Actor object according to our current code
formatting standards. Earlier we had half of vars named with leading
underscore and half without it.

Now code in actor.cpp is considerably more readable.

svn-id: r17068
2005-03-11 01:10:06 +00:00

871 lines
20 KiB
C++

/* ScummVM - Scumm Interpreter
* Copyright (C) 2001 Ludvig Strigeus
* Copyright (C) 2001-2005 The ScummVM project
*
* 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 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.
*
* $Header$
*
*/
#include "stdafx.h"
#include "scumm/scumm.h"
#include "scumm/actor.h"
#include "scumm/costume.h"
#include "scumm/sound.h"
#if defined(__PALM_OS__)
#include "init_arm.h"
#include "arm/native.h"
#include "arm/macros.h"
#endif
namespace Scumm {
const byte revBitMask[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
#ifdef __PALM_OS__
const byte *cost_scaleTable;
#else
const byte cost_scaleTable[256] = {
0xFF, 0xFD, 0x7D, 0xBD, 0x3D, 0xDD, 0x5D, 0x9D,
0x1D, 0xED, 0x6D, 0xAD, 0x2D, 0xCD, 0x4D, 0x8D,
0x0D, 0xF5, 0x75, 0xB5, 0x35, 0xD5, 0x55, 0x95,
0x15, 0xE5, 0x65, 0xA5, 0x25, 0xC5, 0x45, 0x85,
0x05, 0xF9, 0x79, 0xB9, 0x39, 0xD9, 0x59, 0x99,
0x19, 0xE9, 0x69, 0xA9, 0x29, 0xC9, 0x49, 0x89,
0x09, 0xF1, 0x71, 0xB1, 0x31, 0xD1, 0x51, 0x91,
0x11, 0xE1, 0x61, 0xA1, 0x21, 0xC1, 0x41, 0x81,
0x01, 0xFB, 0x7B, 0xBB, 0x3B, 0xDB, 0x5B, 0x9B,
0x1B, 0xEB, 0x6B, 0xAB, 0x2B, 0xCB, 0x4B, 0x8B,
0x0B, 0xF3, 0x73, 0xB3, 0x33, 0xD3, 0x53, 0x93,
0x13, 0xE3, 0x63, 0xA3, 0x23, 0xC3, 0x43, 0x83,
0x03, 0xF7, 0x77, 0xB7, 0x37, 0xD7, 0x57, 0x97,
0x17, 0xE7, 0x67, 0xA7, 0x27, 0xC7, 0x47, 0x87,
0x07, 0xEF, 0x6F, 0xAF, 0x2F, 0xCF, 0x4F, 0x8F,
0x0F, 0xDF, 0x5F, 0x9F, 0x1F, 0xBF, 0x3F, 0x7F,
0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE
};
#endif
byte CostumeRenderer::mainRoutine(int xmoveCur, int ymoveCur) {
int i, skip = 0;
byte drawFlag = 1;
bool use_scaling;
byte startScaleIndexX;
int ex1, ex2;
Common::Rect rect;
int step;
Codec1 v1;
const int scaletableSize = 128;
const bool newAmiCost = (_vm->_version == 5) && (_vm->_features & GF_AMIGA);
CHECK_HEAP
v1.scaletable = cost_scaleTable;
if (_loaded._numColors == 32) {
v1.mask = 7;
v1.shr = 3;
} else {
v1.mask = 15;
v1.shr = 4;
}
switch (_loaded._format) {
case 0x60:
case 0x61:
// This format is used e.g. in the Sam&Max intro
ex1 = _srcptr[0];
ex2 = _srcptr[1];
_srcptr += 2;
if (ex1 != 0xFF || ex2 != 0xFF) {
ex1 = READ_LE_UINT16(_loaded._frameOffsets + ex1 * 2);
_srcptr = _loaded._baseptr + READ_LE_UINT16(_loaded._baseptr + ex1 + ex2 * 2) + 14;
}
}
use_scaling = (_scaleX != 0xFF) || (_scaleY != 0xFF);
v1.x = _actorX;
v1.y = _actorY;
if (use_scaling) {
/* Scale direction */
v1.scaleXstep = -1;
if (xmoveCur < 0) {
xmoveCur = -xmoveCur;
v1.scaleXstep = 1;
}
if (_mirror) {
/* Adjust X position */
startScaleIndexX = _scaleIndexX = scaletableSize - xmoveCur;
for (i = 0; i < xmoveCur; i++) {
if (v1.scaletable[_scaleIndexX++] < _scaleX)
v1.x -= v1.scaleXstep;
}
rect.left = rect.right = v1.x;
_scaleIndexX = startScaleIndexX;
for (i = 0; i < _width; i++) {
if (rect.right < 0) {
skip++;
startScaleIndexX = _scaleIndexX;
}
if (v1.scaletable[_scaleIndexX++] < _scaleX)
rect.right++;
}
} else {
/* No mirror */
/* Adjust X position */
startScaleIndexX = _scaleIndexX = xmoveCur + scaletableSize;
for (i = 0; i < xmoveCur; i++) {
if (v1.scaletable[_scaleIndexX--] < _scaleX)
v1.x += v1.scaleXstep;
}
rect.left = rect.right = v1.x;
_scaleIndexX = startScaleIndexX;
for (i = 0; i < _width; i++) {
if (rect.left >= _out.w) {
startScaleIndexX = _scaleIndexX;
skip++;
}
if (v1.scaletable[_scaleIndexX--] < _scaleX)
rect.left--;
}
}
_scaleIndexX = startScaleIndexX;
if (skip)
skip--;
step = -1;
if (ymoveCur < 0) {
ymoveCur = -ymoveCur;
step = 1;
}
_scaleIndexY = scaletableSize - ymoveCur;
for (i = 0; i < ymoveCur; i++) {
if (v1.scaletable[_scaleIndexY++] < _scaleY)
v1.y -= step;
}
rect.top = rect.bottom = v1.y;
_scaleIndexY = scaletableSize - ymoveCur;
for (i = 0; i < _height; i++) {
if (v1.scaletable[_scaleIndexY++] < _scaleY)
rect.bottom++;
}
_scaleIndexY = scaletableSize - ymoveCur;
} else {
if (!_mirror)
xmoveCur = -xmoveCur;
v1.x += xmoveCur;
v1.y += ymoveCur;
if (_mirror) {
rect.left = v1.x;
rect.right = v1.x + _width;
} else {
rect.left = v1.x - _width;
rect.right = v1.x;
}
rect.top = v1.y;
rect.bottom = rect.top + _height;
}
v1.skip_width = _width;
v1.scaleXstep = _mirror ? 1 : -1;
if (_vm->_version == 1)
// V1 games uses 8 x 8 pixels for actors
_vm->markRectAsDirty(kMainVirtScreen, rect.left, rect.right + 8, rect.top, rect.bottom, _actorID);
else
_vm->markRectAsDirty(kMainVirtScreen, rect.left, rect.right + 1, rect.top, rect.bottom, _actorID);
if (rect.top >= _out.h || rect.bottom <= 0)
return 0;
if (rect.left >= _out.w || rect.right <= 0)
return 0;
v1.replen = 0;
if (_mirror) {
if (!use_scaling)
skip = -v1.x;
if (skip > 0) {
if (!newAmiCost && _loaded._format != 0x57) {
v1.skip_width -= skip;
codec1_ignorePakCols(v1, skip);
v1.x = 0;
}
} else {
skip = rect.right - _out.w;
if (skip <= 0) {
drawFlag = 2;
} else {
v1.skip_width -= skip;
}
}
} else {
if (!use_scaling)
skip = rect.right - _out.w;
if (skip > 0) {
if (!newAmiCost && _loaded._format != 0x57) {
v1.skip_width -= skip;
codec1_ignorePakCols(v1, skip);
v1.x = _out.w - 1;
}
} else {
// V1 games uses 8 x 8 pixels for actors
if (_loaded._format == 0x57)
skip = -8 - rect.left;
else
skip = -1 - rect.left;
if (skip <= 0)
drawFlag = 2;
else
v1.skip_width -= skip;
}
}
if (v1.skip_width <= 0)
return 0;
if (rect.left < 0)
rect.left = 0;
if (rect.top < 0)
rect.top = 0;
if (rect.top > _out.h)
rect.top = _out.h;
if (rect.bottom > _out.h)
rect.bottom = _out.h;
if (_draw_top > rect.top)
_draw_top = rect.top;
if (_draw_bottom < rect.bottom)
_draw_bottom = rect.bottom;
if (_height + rect.top >= 256) {
CHECK_HEAP
return 2;
}
v1.destptr = (byte *)_out.pixels + v1.y * _out.pitch + v1.x;
v1.mask_ptr = _vm->getMaskBuffer(0, v1.y, _zbuf);
CHECK_HEAP
if (_loaded._format == 0x57) {
// The v1 costume renderer needs the actor number, which is
// the same thing as the costume renderer's _actorID.
procC64(v1, _actorID);
} else if (newAmiCost)
proc3_ami(v1);
else
proc3(v1);
CHECK_HEAP
return drawFlag;
}
static const int v1MMActorPalatte1[25] = {
8, 8, 8, 8, 4, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8
};
static const int v1MMActorPalatte2[25] = {
0, 7, 2, 6, 9, 1, 3, 7, 7, 1, 1, 9, 1, 4, 5, 5, 4, 1, 0, 5, 4, 2, 2, 7, 7
};
#define MASK_AT(xoff) \
(mask && (mask[((v1.x + xoff) / 8)] & revBitMask[(v1.x + xoff) & 7]))
#define LINE(c,p) \
pcolor = (color >> c) & 3; \
if (pcolor) { \
if (!MASK_AT(p)) \
dst[p] = palette[pcolor]; \
if (!MASK_AT(p + 1)) \
dst[p + 1] = palette[pcolor]; \
}
void CostumeRenderer::procC64(Codec1 &v1, int actor) {
const byte *mask, *src;
byte *dst;
byte len;
int y;
uint height;
byte color, pcolor;
bool rep;
y = v1.y;
src = _srcptr;
dst = v1.destptr;
len = v1.replen;
color = v1.repcolor;
height = _height;
v1.skip_width /= 8;
// Set up the palette data
byte palette[4] = { 0, 0, 0, 0 };
if (!(_vm->VAR(_vm->VAR_CURRENT_LIGHTS) & LIGHTMODE_actor_color)) {
palette[2] = 11;
palette[3] = 11;
} else if (_vm->_gameId == GID_MANIAC) {
palette[1] = v1MMActorPalatte1[actor];
palette[2] = v1MMActorPalatte2[actor];
} else {
palette[1] = 8;
palette[2] = _palette[actor];
}
mask = v1.mask_ptr;
if (len)
goto StartPos;
do {
len = *src++;
if (len & 0x80)
color = *src++;
StartPos:;
rep = (len & 0x80) != 0;
len &= 0x7f;
while (len--) {
if (!rep)
color = *src++;
if (0 <= y && y < _out.h && 0 <= v1.x && v1.x < _out.w) {
if (!_mirror) {
LINE(0, 0); LINE(2, 2); LINE(4, 4); LINE(6, 6);
} else {
LINE(6, 0); LINE(4, 2); LINE(2, 4); LINE(0, 6);
}
}
dst += _out.pitch;
y++;
mask += _numStrips;
if (!--height) {
if (!--v1.skip_width)
return;
height = _height;
y = v1.y;
v1.x += 8 * v1.scaleXstep;
if (v1.x < 0 || v1.x >= _out.w)
return;
mask = v1.mask_ptr;
v1.destptr += 8 * v1.scaleXstep;
dst = v1.destptr;
}
}
} while (1);
}
#undef LINE
#undef MASK_AT
void CostumeRenderer::proc3(Codec1 &v1) {
#ifdef __PALM_OS__
ARM_START(CostumeProc3Type)
ARM_INIT(SCUMM_PROC3)
ARM_ADDP(v1)
ARM_ADDM(revBitMask)
ARM_ADDM(_srcptr)
ARM_ADDM(_height)
ARM_ADDM(_scaleIndexX)
ARM_ADDM(_scaleIndexY)
ARM_ADDM(_scaleX)
ARM_ADDM(_scaleY)
ARM_ADDM(_numStrips)
ARM_ADDM(_shadow_mode)
ARM_ADDM(_shadow_table)
ARM_ADDM(_palette)
ARM_ADDV(_out_pitch, _out.pitch)
ARM_ADDV(_out_w, _out.w)
ARM_ADDV(_out_h, _out.h)
ARM_CALL_RETURN(ARM_ENGINE, PNO_DATA(), _scaleIndexX)
ARM_END()
#endif
const byte *mask, *src;
byte *dst;
byte len, maskbit;
int y;
uint color, height, pcolor;
const byte *scaleytab;
bool masked;
y = v1.y;
src = _srcptr;
dst = v1.destptr;
len = v1.replen;
color = v1.repcolor;
height = _height;
scaleytab = &v1.scaletable[_scaleIndexY];
maskbit = revBitMask[v1.x & 7];
mask = v1.mask_ptr + v1.x / 8;
if (len)
goto StartPos;
do {
len = *src++;
color = len >> v1.shr;
len &= v1.mask;
if (!len)
len = *src++;
do {
if (_scaleY == 255 || *scaleytab++ < _scaleY) {
masked = (y < 0 || y >= _out.h) || (v1.mask_ptr && (mask[0] & maskbit));
if (color && !masked) {
// FIXME: Fully implement _shadow_mode.in Sam & Max
// For now, it's enough for transparency.
if (_shadow_mode & 0x20) {
pcolor = _shadow_table[*dst];
} else {
pcolor = _palette[color];
if (pcolor == 13 && _shadow_table)
pcolor = _shadow_table[*dst];
}
*dst = pcolor;
}
dst += _out.pitch;
mask += _numStrips;
y++;
}
if (!--height) {
if (!--v1.skip_width)
return;
height = _height;
y = v1.y;
scaleytab = &v1.scaletable[_scaleIndexY];
if (_scaleX == 255 || v1.scaletable[_scaleIndexX] < _scaleX) {
v1.x += v1.scaleXstep;
if (v1.x < 0 || v1.x >= _out.w)
return;
maskbit = revBitMask[v1.x & 7];
v1.destptr += v1.scaleXstep;
}
_scaleIndexX += v1.scaleXstep;
dst = v1.destptr;
mask = v1.mask_ptr + v1.x / 8;
}
StartPos:;
} while (--len);
} while (1);
}
void CostumeRenderer::proc3_ami(Codec1 &v1) {
const byte *mask, *src;
byte *dst;
byte maskbit, len, height, width;
int color;
int y;
bool masked;
int oldXpos, oldScaleIndexX;
mask = v1.mask_ptr + v1.x / 8;
dst = v1.destptr;
height = _height;
width = _width;
src = _srcptr;
maskbit = revBitMask[v1.x & 7];
y = v1.y;
oldXpos = v1.x;
oldScaleIndexX = _scaleIndexX;
do {
len = *src++;
color = len >> v1.shr;
len &= v1.mask;
if (!len)
len = *src++;
do {
if (_scaleY == 255 || v1.scaletable[_scaleIndexY] < _scaleY) {
masked = (y < 0 || y >= _out.h) || (v1.mask_ptr && (mask[0] & maskbit));
if (color && v1.x >= 0 && v1.x < _out.w && !masked) {
*dst = _palette[color];
}
if (_scaleX == 255 || v1.scaletable[_scaleIndexX] < _scaleX) {
v1.x += v1.scaleXstep;
dst += v1.scaleXstep;
maskbit = revBitMask[v1.x & 7];
}
_scaleIndexX += v1.scaleXstep;
mask = v1.mask_ptr + v1.x / 8;
}
if (!--width) {
if (!--height)
return;
if (y >= _out.h)
return;
if (v1.x != oldXpos) {
dst += _out.pitch - (v1.x - oldXpos);
v1.mask_ptr += _numStrips;
mask = v1.mask_ptr;
y++;
}
width = _width;
v1.x = oldXpos;
_scaleIndexX = oldScaleIndexX;
_scaleIndexY++;
}
} while (--len);
} while (1);
}
void LoadedCostume::loadCostume(int id) {
_id = id;
byte *ptr = _vm->getResourceAddress(rtCostume, id);
if (_vm->_version >= 6)
ptr += 8;
else if (_vm->_features & GF_OLD_BUNDLE)
ptr += -2;
else if (_vm->_features & GF_SMALL_HEADER)
ptr += 0;
else
ptr += 2;
_baseptr = ptr;
_numAnim = ptr[6];
_format = ptr[7] & 0x7F;
_mirror = (ptr[7] & 0x80) != 0;
_palette = ptr + 8;
switch (_format) {
case 0x57: // Only used in V1 games
_numColors = 0;
break;
case 0x58:
_numColors = 16;
break;
case 0x59:
_numColors = 32;
break;
case 0x60: // New since version 6
_numColors = 16;
break;
case 0x61: // New since version 6
_numColors = 32;
break;
default:
error("Costume %d with format 0x%X is invalid", id, _format);
}
// In GF_OLD_BUNDLE games, there is no actual palette, just a single color byte.
// Don't forget, these games were designed around a fixed 16 color HW palette :-)
// In addition, all offsets are shifted by 2; we accomodate that via a separate
// _baseptr value (instead of adding tons of if's throughout the code).
if (_vm->_features & GF_OLD_BUNDLE) {
_numColors = (_format == 0x57) ? 0 : 1;
_baseptr += 2;
}
ptr += 8 + _numColors;
_frameOffsets = ptr + 2;
if (_format == 0x57) {
_dataOffsets = ptr + 18;
_baseptr += 4;
} else {
_dataOffsets = ptr + 34;
}
_animCmds = _baseptr + READ_LE_UINT16(ptr);
}
byte CostumeRenderer::drawLimb(const Actor *a, int limb) {
int i;
int code;
const byte *frameptr;
const CostumeData &cost = a->_cost;
// If the specified limb is stopped or not existing, do nothing.
if (cost.curpos[limb] == 0xFFFF || cost.stopped & (1 << limb))
return 0;
// Determine the position the limb is at
i = cost.curpos[limb] & 0x7FFF;
// Get the frame pointer for that limb
frameptr = _loaded._baseptr + READ_LE_UINT16(_loaded._frameOffsets + limb * 2);
// Determine the offset to the costume data for the limb at position i
code = _loaded._animCmds[i] & 0x7F;
// Code 0x7B indicates a limb for which there is nothing to draw
if (code != 0x7B) {
_srcptr = _loaded._baseptr + READ_LE_UINT16(frameptr + code * 2);
if (!(_vm->_features & GF_OLD256) || code < 0x79) {
const CostumeInfo *costumeInfo;
int xmoveCur, ymoveCur;
if (_loaded._format == 0x57) {
_width = _srcptr[0] * 8;
_height = _srcptr[1];
xmoveCur = _xmove + (int8)_srcptr[2] * 8;
ymoveCur = _ymove - (int8)_srcptr[3];
_xmove += (int8)_srcptr[4] * 8;
_ymove -= (int8)_srcptr[5];
_srcptr += 6;
} else {
costumeInfo = (const CostumeInfo *)_srcptr;
_width = READ_LE_UINT16(&costumeInfo->width);
_height = READ_LE_UINT16(&costumeInfo->height);
xmoveCur = _xmove + (int16)READ_LE_UINT16(&costumeInfo->rel_x);
ymoveCur = _ymove + (int16)READ_LE_UINT16(&costumeInfo->rel_y);
_xmove += (int16)READ_LE_UINT16(&costumeInfo->move_x);
_ymove -= (int16)READ_LE_UINT16(&costumeInfo->move_y);
_srcptr += 12;
}
return mainRoutine(xmoveCur, ymoveCur);
}
}
return 0;
}
int ScummEngine::cost_frameToAnim(Actor *a, int frame) {
return newDirToOldDir(a->getFacing()) + frame * 4;
}
void ScummEngine::cost_decodeData(Actor *a, int frame, uint usemask) {
const byte *r;
uint mask, j;
int i;
byte extra, cmd;
int anim;
LoadedCostume lc(this);
lc.loadCostume(a->_costume);
anim = cost_frameToAnim(a, frame);
if (anim > lc._numAnim) {
return;
}
r = lc._baseptr + READ_LE_UINT16(lc._dataOffsets + anim * 2);
if (r == lc._baseptr) {
return;
}
if (_version == 1) {
mask = *r++ << 8;
} else {
mask = READ_LE_UINT16(r);
r += 2;
}
i = 0;
do {
if (mask & 0x8000) {
if (_version <= 3) {
j = *r++;
if (j == 0xFF)
j = 0xFFFF;
} else {
j = READ_LE_UINT16(r);
r += 2;
}
if (usemask & 0x8000) {
if (j == 0xFFFF) {
a->_cost.curpos[i] = 0xFFFF;
a->_cost.start[i] = 0;
a->_cost.frame[i] = frame;
} else {
extra = *r++;
cmd = lc._animCmds[j];
if (cmd == 0x7A) {
a->_cost.stopped &= ~(1 << i);
} else if (cmd == 0x79) {
a->_cost.stopped |= (1 << i);
} else {
a->_cost.curpos[i] = a->_cost.start[i] = j;
a->_cost.end[i] = j + (extra & 0x7F);
if (extra & 0x80)
a->_cost.curpos[i] |= 0x8000;
a->_cost.frame[i] = frame;
}
}
} else {
if (j != 0xFFFF)
r++;
}
}
i++;
usemask <<= 1;
mask <<= 1;
} while (mask&0xFFFF);
}
void CostumeRenderer::setPalette(byte *palette) {
int i;
byte color;
if (_loaded._format == 0x57) {
memcpy(_palette, palette, 13);
} else if (_vm->_features & GF_OLD_BUNDLE) {
if ((_vm->VAR(_vm->VAR_CURRENT_LIGHTS) & LIGHTMODE_actor_color)) {
memcpy(_palette, palette, 16);
} else {
memset(_palette, 8, 16);
_palette[12] = 0;
}
_palette[_loaded._palette[0]] = _palette[0];
} else {
if ((_vm->_features & GF_NEW_OPCODES) || (_vm->VAR(_vm->VAR_CURRENT_LIGHTS) & LIGHTMODE_actor_color)) {
for (i = 0; i < _loaded._numColors; i++) {
color = palette[i];
if (color == 255)
color = _loaded._palette[i];
_palette[i] = color;
}
} else {
memset(_palette, 8, _loaded._numColors);
_palette[12] = 0;
}
}
}
void CostumeRenderer::setFacing(const Actor *a) {
_mirror = newDirToOldDir(a->getFacing()) != 0 || _loaded._mirror;
}
void CostumeRenderer::setCostume(int costume) {
_loaded.loadCostume(costume);
}
byte LoadedCostume::increaseAnims(Actor *a) {
int i;
byte r = 0;
for (i = 0; i != 16; i++) {
if (a->_cost.curpos[i] != 0xFFFF)
r += increaseAnim(a, i);
}
return r;
}
byte LoadedCostume::increaseAnim(Actor *a, int slot) {
int highflag;
int i, end;
byte code, nc;
if (a->_cost.curpos[slot] == 0xFFFF)
return 0;
highflag = a->_cost.curpos[slot] & 0x8000;
i = a->_cost.curpos[slot] & 0x7FFF;
end = a->_cost.end[slot];
code = _animCmds[i] & 0x7F;
if (_vm->_version <= 3) {
if (_animCmds[i] & 0x80)
a->_cost.soundCounter++;
}
do {
if (!highflag) {
if (i++ >= end)
i = a->_cost.start[slot];
} else {
if (i != end)
i++;
}
nc = _animCmds[i];
if (nc == 0x7C) {
a->_cost.animCounter++;
if (a->_cost.start[slot] != end)
continue;
} else {
if (_vm->_version >= 6) {
if (nc >= 0x71 && nc <= 0x78) {
uint sound = (_vm->_features & GF_HUMONGOUS) ? 0x78 - nc : nc - 0x71;
_vm->_sound->addSoundToQueue2(a->_sound[sound]);
if (a->_cost.start[slot] != end)
continue;
}
} else {
if (nc == 0x78) {
a->_cost.soundCounter++;
if (a->_cost.start[slot] != end)
continue;
}
}
}
a->_cost.curpos[slot] = i | highflag;
return (_animCmds[i] & 0x7F) != code;
} while (1);
}
} // End of namespace Scumm
#ifdef __PALM_OS__
#include "scumm_globals.h"
_GINIT(Costume)
_GSETPTR(Scumm::cost_scaleTable, GBVARS_COSTSCALETABLE_INDEX, byte, GBVARS_SCUMM)
_GEND
_GRELEASE(Costume)
_GRELEASEPTR(GBVARS_COSTSCALETABLE_INDEX, GBVARS_SCUMM)
_GEND
#endif