scummvm/scumm/akos.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

1725 lines
41 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/akos.h"
#include "scumm/bomp.h"
#include "scumm/imuse.h"
#include "scumm/imuse_digi/dimuse.h"
#include "scumm/sound.h"
#include "scumm/wiz_he.h"
namespace Scumm {
#if !defined(__GNUC__)
#pragma START_PACK_STRUCTS
#endif
struct AkosHeader {
byte unk_1[2];
byte flags;
byte unk_2;
uint16 num_anims;
uint16 unk_3;
uint16 codec;
} GCC_PACK;
struct AkosOffset {
uint32 akcd;
uint16 akci;
} GCC_PACK;
#if !defined(__GNUC__)
#pragma END_PACK_STRUCTS
#endif
enum AkosOpcodes {
AKC_Return = 0xC001,
AKC_SetVar = 0xC010,
AKC_CmdQue3 = 0xC015,
AKC_C016 = 0xC016,
AKC_C017 = 0xC017,
AKC_C018 = 0xC018,
AKC_C019 = 0xC019,
AKC_ComplexChan = 0xC020,
AKC_C021 = 0xC021,
AKC_C022 = 0xC022,
AKC_ComplexChan2 = 0xC025,
AKC_Jump = 0xC030,
AKC_JumpIfSet = 0xC031,
AKC_AddVar = 0xC040,
AKC_C042 = 0xC042,
AKC_C044 = 0xC044,
AKC_C045 = 0xC045,
AKC_C046 = 0xC046,
AKC_C047 = 0xC047,
AKC_C048 = 0xC048,
AKC_Ignore = 0xC050,
AKC_IncVar = 0xC060,
AKC_CmdQue3Quick = 0xC061,
AKC_JumpStart = 0xC070,
AKC_JumpE = 0xC070,
AKC_JumpNE = 0xC071,
AKC_JumpL = 0xC072,
AKC_JumpLE = 0xC073,
AKC_JumpG = 0xC074,
AKC_JumpGE = 0xC075,
AKC_StartAnim = 0xC080,
AKC_StartVarAnim = 0xC081,
AKC_Random = 0xC082,
AKC_SetActorClip = 0xC083,
AKC_StartAnimInActor = 0xC084,
AKC_SetVarInActor = 0xC085,
AKC_HideActor = 0xC086,
AKC_SetDrawOffs = 0xC087,
AKC_JumpTable = 0xC088,
AKC_SoundStuff = 0xC089,
AKC_Flip = 0xC08A,
AKC_Cmd3 = 0xC08B,
AKC_Ignore3 = 0xC08C,
AKC_Ignore2 = 0xC08D,
AKC_C08E = 0xC08E,
AKC_SkipStart = 0xC090,
AKC_SkipE = 0xC090,
AKC_SkipNE = 0xC091,
AKC_SkipL = 0xC092,
AKC_SkipLE = 0xC093,
AKC_SkipG = 0xC094,
AKC_SkipGE = 0xC095,
AKC_ClearFlag = 0xC09F,
AKC_C0A0 = 0xC0A0,
AKC_C0A1 = 0xC0A1,
AKC_C0A2 = 0xC0A2,
AKC_C0A3 = 0xC0A3,
AKC_C0A4 = 0xC0A4,
AKC_C0A5 = 0xC0A5,
AKC_C0A6 = 0xC0A6,
AKC_C0A7 = 0xC0A7,
AKC_EndSeq = 0xC0FF
};
static bool akos_compare(int a, int b, byte cmd) {
switch (cmd) {
case 0:
return a == b;
case 1:
return a != b;
case 2:
return a < b;
case 3:
return a <= b;
case 4:
return a > b;
default:
return a >= b;
}
}
bool ScummEngine::akos_hasManyDirections(int costume) {
byte *akos;
const AkosHeader *akhd;
akos = getResourceAddress(rtCostume, costume);
assert(akos);
akhd = (const AkosHeader *)findResourceData(MKID('AKHD'), akos);
return (akhd->flags & 2) != 0;
}
int ScummEngine::akos_frameToAnim(Actor *a, int frame) {
if (_version >= 7 && akos_hasManyDirections(a->_costume))
return toSimpleDir(1, a->getFacing()) + frame * 8;
else
return newDirToOldDir(a->getFacing()) + frame * 4;
}
void ScummEngine::akos_decodeData(Actor *a, int frame, uint usemask) {
uint anim;
const byte *akos, *r;
const AkosHeader *akhd;
uint offs;
int i;
byte code;
uint16 start, len;
uint16 mask;
if (a->_costume == 0)
return;
anim = akos_frameToAnim(a, frame);
akos = getResourceAddress(rtCostume, a->_costume);
assert(akos);
akhd = (const AkosHeader *)findResourceData(MKID('AKHD'), akos);
if (anim >= READ_LE_UINT16(&akhd->num_anims))
return;
r = findResourceData(MKID('AKCH'), akos);
assert(r);
offs = READ_LE_UINT16(r + anim * sizeof(uint16));
if (offs == 0)
return;
r += offs;
const uint8 *akst = findResourceData(MKID('AKST'), akos);
const uint8 *aksf = findResourceData(MKID('AKSF'), akos);
i = 0;
mask = READ_LE_UINT16(r); r += 2;
do {
if (mask & 0x8000) {
code = *r++;
if (usemask & 0x8000) {
switch (code) {
case 1:
a->_cost.active[i] = 0;
a->_cost.frame[i] = frame;
a->_cost.end[i] = 0;
a->_cost.start[i] = 0;
a->_cost.curpos[i] = 0;
a->_cost.seq3[i] = 0;
if (akst) {
int size = getResourceDataSize(akst) / 8;
if (size > 0) {
bool found = false;
while (size--) {
if (READ_LE_UINT32(akst) == 0) {
a->_cost.seq3[i] = READ_LE_UINT32(akst + 4);
found = true;
break;
}
akst += 8;
}
if (!found) {
warning("Sequence not found in actor 0x%X costume %d", a, a->_costume);
}
}
}
break;
case 4:
a->_cost.stopped |= 1 << i;
break;
case 5:
a->_cost.stopped &= ~(1 << i);
break;
default:
start = READ_LE_UINT16(r); r += 2;
len = READ_LE_UINT16(r); r += 2;
a->_cost.seq1[i] = 0;
a->_cost.seq2[i] = 0;
if (aksf) {
int size = getResourceDataSize(aksf) / 6;
if (size > 0) {
bool found = false;
while (size--) {
if (READ_LE_UINT16(aksf) == start) {
a->_cost.seq1[i] = READ_LE_UINT16(aksf + 2);
a->_cost.seq2[i] = READ_LE_UINT16(aksf + 4);
found = true;
break;
}
aksf += 6;
}
if (!found) {
warning("Sequence not found in actor 0x%X costume %d", a, a->_costume);
}
}
}
a->_cost.active[i] = code;
a->_cost.frame[i] = frame;
a->_cost.end[i] = start + len;
a->_cost.start[i] = start;
a->_cost.curpos[i] = start;
a->_cost.seq3[i] = 0;
if (akst) {
int size = getResourceDataSize(akst) / 8;
if (size > 0) {
bool found = false;
while (size--) {
if (READ_LE_UINT32(akst) == start) {
a->_cost.seq3[i] = READ_LE_UINT32(akst + 4);
found = true;
break;
}
akst += 8;
}
if (!found) {
warning("Sequence not found in actor 0x%X costume %d", a, a->_costume);
}
}
}
break;
}
} else {
if (code != 1 && code != 4 && code != 5)
r += sizeof(uint16) * 2;
}
}
i++;
mask <<= 1;
usemask <<= 1;
} while ((uint16)mask);
}
void AkosRenderer::setPalette(byte *new_palette) {
uint size, i;
size = _vm->getResourceDataSize(akpl);
if (size > 256)
error("akos_setPalette: %d is too many colors", size);
for (i = 0; i < size; i++) {
palette[i] = new_palette[i] != 0xFF ? new_palette[i] : akpl[i];
}
if (_paletteNum) {
// TODO
// Sets palette number to use for actor palette
}
if (_vm->_heversion == 70 && size) {
for (i = 0; i < size; i++)
palette[i] = _vm->_HEV7ActorPalette[palette[i]];
}
if (size == 256) {
byte color = new_palette[0];
if (color == 255) {
palette[0] = color;
} else {
_vm->_bompActorPalettePtr = palette;
}
}
}
void AkosRenderer::setCostume(int costume) {
akos = _vm->getResourceAddress(rtCostume, costume);
assert(akos);
akhd = (const AkosHeader *) _vm->findResourceData(MKID('AKHD'), akos);
akof = (const AkosOffset *) _vm->findResourceData(MKID('AKOF'), akos);
akci = _vm->findResourceData(MKID('AKCI'), akos);
aksq = _vm->findResourceData(MKID('AKSQ'), akos);
akcd = _vm->findResourceData(MKID('AKCD'), akos);
akpl = _vm->findResourceData(MKID('AKPL'), akos);
codec = READ_LE_UINT16(&akhd->codec);
akct = _vm->findResourceData(MKID('AKCT'), akos);
}
void AkosRenderer::setFacing(const Actor *a) {
_mirror = (newDirToOldDir(a->getFacing()) != 0 || akhd->flags & 1);
if (a->_flip)
_mirror = !_mirror;
}
byte AkosRenderer::drawLimb(const Actor *a, int limb) {
uint code;
const byte *p;
const AkosOffset *off;
const CostumeData &cost = a->_cost;
const CostumeInfo *costumeInfo;
uint i, extra;
byte result = 0;
int xmoveCur, ymoveCur;
uint32 seq3Idx[32];
uint8 hasSeq3Idx;
int lastDx, lastDy;
lastDx = lastDy = 0;
for (i = 0; i < 32; ++i) {
seq3Idx[i] = i;
}
if (_skipLimbs)
return 0;
if (_vm->_heversion >= 70 && cost.active[limb] == 8)
return 0;
if (!cost.active[limb] || cost.stopped & (1 << limb))
return 0;
hasSeq3Idx = 0;
p = aksq + cost.curpos[limb];
code = p[0];
if (code & 0x80)
code = (code << 8) | p[1];
if (code == AKC_C021 || code == AKC_C022) {
uint16 s = cost.curpos[limb] + 4;
uint j = 0;
extra = p[3];
uint8 n = extra;
assert(n < ARRAYSIZE(seq3Idx));
while (n--) {
seq3Idx[j++] = aksq[s++];
}
hasSeq3Idx = 1;
p += extra + 2;
code = (code == AKC_C021) ? AKC_ComplexChan : AKC_ComplexChan2;
}
if (code == AKC_Return || code == AKC_EndSeq)
return 0;
if (code != AKC_ComplexChan && code != AKC_ComplexChan2) {
off = akof + (code & 0xFFF);
assert((code & 0xFFF) * 6 < READ_BE_UINT32((const byte *)akof - 4) - 8);
assert((code & 0x7000) == 0);
_srcptr = akcd + READ_LE_UINT32(&off->akcd);
costumeInfo = (const CostumeInfo *) (akci + READ_LE_UINT16(&off->akci));
_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);
switch (codec) {
case 1:
result |= codec1(xmoveCur, ymoveCur);
break;
case 5:
result |= codec5(xmoveCur, ymoveCur);
break;
case 16:
result |= codec16(xmoveCur, ymoveCur);
break;
case 32:
result |= codec32(xmoveCur, ymoveCur);
break;
default:
error("akos_drawLimb: invalid codec %d", codec);
}
} else {
if (code == AKC_ComplexChan2) {
lastDx = (int16)READ_LE_UINT16(p + 2);
lastDy = (int16)READ_LE_UINT16(p + 4);
p += 4;
}
extra = p[2];
p += 3;
uint32 decflag = seq3Idx[0];
for (i = 0; i != extra; i++) {
code = p[4];
if (code & 0x80)
code = ((code & 0xF) << 8) | p[5];
off = akof + code;
_srcptr = akcd + READ_LE_UINT32(&off->akcd);
costumeInfo = (const CostumeInfo *) (akci + READ_LE_UINT16(&off->akci));
_width = READ_LE_UINT16(&costumeInfo->width);
_height = READ_LE_UINT16(&costumeInfo->height);
xmoveCur = _xmove + (int16)READ_LE_UINT16(p + 0);
ymoveCur = _ymove + (int16)READ_LE_UINT16(p + 2);
if (i == extra - 1) {
_xmove += lastDx;
_ymove -= lastDy;
}
if (!hasSeq3Idx || !akct) {
decflag = 1;
} else {
uint32 cond = READ_LE_UINT32(akct + cost.seq3[limb] + seq3Idx[i] * 4);
if (cond == 0) {
decflag = 1;
} else {
uint32 type = cond & 0xC0000000;
cond &= 0x3FFFFFFF;
if (type == 0x40000000) {
decflag = (a->_heCondMask & cond) ? 1 : 0;
} else if (type == 0x80000000) {
decflag = (a->_heCondMask & cond) ? 0 : 1;
} else {
decflag = (a->_heCondMask & cond) ? 1 : 0;
}
}
}
p += (p[4] & 0x80) ? 6 : 5;
if (decflag == 0)
continue;
switch (codec) {
case 1:
result |= codec1(xmoveCur, ymoveCur);
break;
case 5:
result |= codec5(xmoveCur, ymoveCur);
break;
case 16:
result |= codec16(xmoveCur, ymoveCur);
break;
case 32:
result |= codec32(xmoveCur, ymoveCur);
break;
default:
error("akos_drawLimb: invalid codec %d", codec);
}
}
}
return result;
}
void AkosRenderer::codec1_genericDecode(Codec1 &v1) {
const byte *mask, *src;
byte *dst;
byte len, maskbit;
int y;
uint color, height, pcolor;
const byte *scaleytab;
bool masked;
bool skip_column = false;
y = v1.y;
src = _srcptr;
dst = v1.destptr;
len = v1.replen;
color = v1.repcolor;
height = _height;
scaleytab = &v1.scaletable[v1.scaleYindex];
maskbit = revBitMask[v1.x & 7];
mask = _vm->getMaskBuffer(v1.x - (_vm->virtscr[0].xstart & 7), v1.y, _zbuf);
if (len)
goto StartPos;
do {
len = *src++;
color = len >> v1.shr;
len &= v1.mask;
if (!len)
len = *src++;
do {
if (*scaleytab++ < _scaleY) {
if (_actorHitMode) {
if (color && y == _actorHitY && v1.x == _actorHitX) {
_actorHitResult = true;
return;
}
} else {
masked = (y < 0 || y >= _out.h) || (*mask & maskbit);
if (color && !masked && !skip_column) {
pcolor = palette[color];
if (_shadow_mode == 1) {
if (pcolor == 13)
pcolor = _shadow_table[*dst];
} else if (_shadow_mode == 2) {
warning("codec1_spec2"); // TODO
} else if (_shadow_mode == 3) {
if (pcolor < 8) {
pcolor = (pcolor << 8) + *dst;
pcolor = _shadow_table[pcolor];
}
}
*dst = pcolor;
}
}
dst += _out.pitch;
mask += _numStrips;
y++;
}
if (!--height) {
if (!--v1.skip_width)
return;
height = _height;
y = v1.y;
scaleytab = &v1.scaletable[v1.scaleYindex];
if (_scaleX == 255 || v1.scaletable[v1.scaleXindex] < _scaleX) {
v1.x += v1.scaleXstep;
if (v1.x < 0 || v1.x >= _out.w)
return;
maskbit = revBitMask[v1.x & 7];
v1.destptr += v1.scaleXstep;
skip_column = false;
} else
skip_column = true;
v1.scaleXindex += v1.scaleXstep;
dst = v1.destptr;
mask = _vm->getMaskBuffer(v1.x - (_vm->virtscr[0].xstart & 7), v1.y, _zbuf);
}
StartPos:;
} while (--len);
} while (1);
}
#ifdef __PALM_OS__
const byte *defaultScaleTable;
const byte *oldScaleTable;
#else
const byte oldScaleTable[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
};
const byte defaultScaleTable[768] = {
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,
0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFE,
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,
0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFE,
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,
0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF,
};
#endif
byte AkosRenderer::codec1(int xmoveCur, int ymoveCur) {
int num_colors;
bool use_scaling;
int i, j;
int skip = 0, startScaleIndexX, startScaleIndexY;
Common::Rect rect;
int step;
byte drawFlag = 1;
Codec1 v1;
const int scaletableSize = (_vm->_features & GF_HUMONGOUS) ? 128 : 384;
/* implement custom scale table */
v1.scaletable = (_vm->_features & GF_HUMONGOUS) ? oldScaleTable : defaultScaleTable;
if (_vm->VAR_CUSTOMSCALETABLE != 0xFF && _vm->isResourceLoaded(rtString, _vm->VAR(_vm->VAR_CUSTOMSCALETABLE))) {
v1.scaletable = _vm->getStringAddressVar(_vm->VAR_CUSTOMSCALETABLE);
}
// Setup color decoding variables
num_colors = _vm->getResourceDataSize(akpl);
if (num_colors == 32) {
v1.mask = 7;
v1.shr = 3;
} else if (num_colors == 64) {
v1.mask = 3;
v1.shr = 2;
} else {
v1.mask = 15;
v1.shr = 4;
}
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 = j = scaletableSize - xmoveCur;
for (i = 0; i < xmoveCur; i++) {
if (v1.scaletable[j++] < _scaleX)
v1.x -= v1.scaleXstep;
}
rect.left = rect.right = v1.x;
j = startScaleIndexX;
for (i = 0, skip = 0; i < _width; i++) {
if (rect.right < 0) {
skip++;
startScaleIndexX = j;
}
if (v1.scaletable[j++] < _scaleX)
rect.right++;
}
} else {
/* No mirror */
/* Adjust X position */
startScaleIndexX = j = scaletableSize + xmoveCur;
for (i = 0; i < xmoveCur; i++) {
if (v1.scaletable[j--] < _scaleX)
v1.x += v1.scaleXstep;
}
rect.left = rect.right = v1.x;
j = startScaleIndexX;
for (i = 0; i < _width; i++) {
if (rect.left >= _out.w) {
startScaleIndexX = j;
skip++;
}
if (v1.scaletable[j--] < _scaleX)
rect.left--;
}
}
if (skip)
skip--;
step = -1;
if (ymoveCur < 0) {
ymoveCur = -ymoveCur;
step = -step;
}
startScaleIndexY = scaletableSize - ymoveCur;
for (i = 0; i < ymoveCur; i++) {
if (v1.scaletable[startScaleIndexY++] < _scaleY)
v1.y -= step;
}
rect.top = rect.bottom = v1.y;
startScaleIndexY = scaletableSize - ymoveCur;
for (i = 0; i < _height; i++) {
if (v1.scaletable[startScaleIndexY++] < _scaleY)
rect.bottom++;
}
startScaleIndexY = 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;
startScaleIndexX = scaletableSize;
startScaleIndexY = scaletableSize;
}
v1.scaleXindex = startScaleIndexX;
v1.scaleYindex = startScaleIndexY;
v1.skip_width = _width;
v1.scaleXstep = _mirror ? 1 : -1;
if (_vm->_heversion >= 71) {
rect.clip(_clipOverride);
}
if (_actorHitMode) {
if (_actorHitX < rect.left || _actorHitX >= rect.right || _actorHitY < rect.top || _actorHitY >= rect.bottom)
return 0;
} else
markRectAsDirty(rect);
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) {
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 + 1;
if (skip > 0) {
v1.skip_width -= skip;
codec1_ignorePakCols(v1, skip) ;
v1.x = _out.w - 1;
} else {
skip = -1 - rect.left;
if (skip <= 0)
drawFlag = 2;
else
v1.skip_width -= skip;
}
}
if (v1.skip_width <= 0 || _height <= 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;
v1.destptr = (byte *)_out.pixels + v1.y * _out.pitch + v1.x;
codec1_genericDecode(v1);
return drawFlag;
}
void AkosRenderer::markRectAsDirty(Common::Rect rect) {
rect.left -= _vm->virtscr[0].xstart & 7;
rect.right -= _vm->virtscr[0].xstart & 7;
_vm->markRectAsDirty(kMainVirtScreen, rect, _actorID);
}
byte AkosRenderer::codec5(int xmoveCur, int ymoveCur) {
Common::Rect clip;
int32 maxw, maxh;
if (_actorHitMode) {
warning("codec5: _actorHitMode not yet implemented");
return 0;
}
if (!_mirror) {
clip.left = (_actorX - xmoveCur - _width) + 1;
} else {
clip.left = _actorX + xmoveCur - 1;
}
clip.top = _actorY + ymoveCur;
clip.right = clip.left + _width;
clip.bottom = clip.top + _height;
maxw = _out.w;
maxh = _out.h;
markRectAsDirty(clip);
clip.clip(maxw, maxh);
if ((clip.left >= clip.right) || (clip.top >= clip.bottom))
return 0;
if (_draw_top > clip.top)
_draw_top = clip.top;
if (_draw_bottom < clip.bottom)
_draw_bottom = clip.bottom;
BompDrawData bdd;
bdd.srcwidth = _width;
bdd.srcheight = _height;
bdd.dst = _out;
bdd.dataptr = _srcptr;
bdd.scale_x = 255;
bdd.scale_y = 255;
bdd.shadowMode = _shadow_mode;
if (!_mirror) {
bdd.x = (_actorX - xmoveCur - _width) + 1;
} else {
bdd.x = _actorX + xmoveCur;
}
bdd.y = _actorY + ymoveCur;
bdd.maskPtr = _vm->getMaskBuffer(0, 0, _zbuf);
_vm->drawBomp(bdd, !_mirror);
_vm->_bompActorPalettePtr = NULL;
return 0;
}
void AkosRenderer::akos16SetupBitReader(const byte *src) {
akos16.unk5 = 0;
akos16.numbits = 16;
akos16.mask = (1 << *src) - 1;
akos16.shift = *(src);
akos16.color = *(src + 1);
akos16.bits = (*(src + 2) | *(src + 3) << 8);
akos16.dataptr = src + 4;
}
#define AKOS16_FILL_BITS() \
if (akos16.numbits <= 8) { \
akos16.bits |= (*akos16.dataptr++) << akos16.numbits; \
akos16.numbits += 8; \
}
#define AKOS16_EAT_BITS(n) \
akos16.numbits -= (n); \
akos16.bits >>= (n);
void AkosRenderer::akos16SkipData(int32 numbytes) {
akos16DecodeLine(0, numbytes, 0);
}
void AkosRenderer::akos16DecodeLine(byte *buf, int32 numbytes, int32 dir) {
uint16 bits, tmp_bits;
while (numbytes != 0) {
if (buf) {
*buf = akos16.color;
buf += dir;
}
if (akos16.unk5 == 0) {
AKOS16_FILL_BITS()
bits = akos16.bits & 3;
if (bits & 1) {
AKOS16_EAT_BITS(2)
if (bits & 2) {
tmp_bits = akos16.bits & 7;
AKOS16_EAT_BITS(3)
if (tmp_bits != 4) {
akos16.color += (tmp_bits - 4);
} else {
akos16.unk5 = 1;
AKOS16_FILL_BITS()
akos16.unk6 = (akos16.bits & 0xff) - 1;
AKOS16_EAT_BITS(8)
AKOS16_FILL_BITS()
}
} else {
AKOS16_FILL_BITS()
akos16.color = ((byte)akos16.bits) & akos16.mask;
AKOS16_EAT_BITS(akos16.shift)
AKOS16_FILL_BITS()
}
} else {
AKOS16_EAT_BITS(1);
}
} else {
if (--akos16.unk6 == 0) {
akos16.unk5 = 0;
}
}
numbytes--;
}
}
void AkosRenderer::akos16Decompress(byte *dest, int32 pitch, const byte *src, int32 t_width, int32 t_height, int32 dir,
int32 numskip_before, int32 numskip_after, byte transparency, int maskLeft, int maskTop, int zBuf) {
byte *tmp_buf = akos16.buffer;
int maskpitch;
byte *maskptr;
const byte maskbit = revBitMask[maskLeft & 7];
if (dir < 0) {
dest -= (t_width - 1);
tmp_buf += (t_width - 1);
}
akos16SetupBitReader(src);
if (numskip_before != 0) {
akos16SkipData(numskip_before);
}
maskpitch = _numStrips;
maskptr = _vm->getMaskBuffer(maskLeft, maskTop, zBuf);
assert(t_height > 0);
assert(t_width > 0);
while (t_height--) {
akos16DecodeLine(tmp_buf, t_width, dir);
bompApplyMask(akos16.buffer, maskptr, maskbit, t_width, transparency);
bool HE7Check = (_vm->_heversion == 70);
bompApplyShadow(_shadow_mode, _shadow_table, akos16.buffer, dest, t_width, transparency, HE7Check);
if (numskip_after != 0) {
akos16SkipData(numskip_after);
}
dest += pitch;
maskptr += maskpitch;
}
}
byte AkosRenderer::codec16(int xmoveCur, int ymoveCur) {
Common::Rect clip;
int32 maxw, maxh;
int32 skip_x, skip_y, cur_x, cur_y;
byte transparency = (_vm->_features & GF_HUMONGOUS) ? palette[0] : 255;
if (_actorHitMode) {
warning("codec16: _actorHitMode not yet implemented");
return 0;
}
if (!_mirror) {
clip.left = (_actorX - xmoveCur - _width) + 1;
} else {
clip.left = _actorX + xmoveCur;
}
clip.top = _actorY + ymoveCur;
clip.right = clip.left + _width;
clip.bottom = clip.top + _height;
maxw = _out.w;
maxh = _out.h;
if (_vm->_heversion >= 71) {
clip.clip(_clipOverride);
}
markRectAsDirty(clip);
skip_x = 0;
skip_y = 0;
cur_x = _width - 1;
cur_y = _height - 1;
if (clip.left < 0) {
skip_x = -clip.left;
clip.left = 0;
}
if (clip.right > maxw) {
cur_x -= clip.right - maxw;
clip.right = maxw;
}
if (clip.top < 0) {
skip_y -= clip.top;
clip.top = 0;
}
if (clip.bottom > maxh) {
cur_y -= clip.bottom - maxh;
clip.bottom = maxh;
}
if ((clip.left >= clip.right) || (clip.top >= clip.bottom))
return 0;
if (_draw_top > clip.top)
_draw_top = clip.top;
if (_draw_bottom < clip.bottom)
_draw_bottom = clip.bottom;
int32 width_unk, height_unk;
height_unk = clip.top;
int32 dir;
if (!_mirror) {
dir = -1;
int tmp_skip_x = skip_x;
skip_x = _width - 1 - cur_x;
cur_x = _width - 1 - tmp_skip_x;
width_unk = clip.right - 1;
} else {
dir = 1;
width_unk = clip.left;
}
int32 out_height;
out_height = cur_y - skip_y;
if (out_height < 0) {
out_height = -out_height;
}
out_height++;
cur_x -= skip_x;
if (cur_x < 0) {
cur_x = -cur_x;
}
cur_x++;
int32 numskip_before = skip_x + (skip_y * _width);
int32 numskip_after = _width - cur_x;
byte *dst = (byte *)_out.pixels + width_unk + height_unk * _out.pitch;
akos16Decompress(dst, _out.pitch, _srcptr, cur_x, out_height, dir, numskip_before, numskip_after, transparency, clip.left, clip.top, _zbuf);
return 0;
}
byte AkosRenderer::codec32(int xmoveCur, int ymoveCur) {
Common::Rect src, dst;
if (!_mirror) {
dst.left = (_actorX - xmoveCur - _width) + 1;
} else {
dst.left = _actorX + xmoveCur;
}
dst.top = _actorY + ymoveCur;
dst.right = dst.left + _width;
dst.bottom = dst.top + _height;
dst.clip(_clipOverride);
src = dst;
src.moveTo(0, 0);
markRectAsDirty(dst);
if (_draw_top > dst.top)
_draw_top = dst.top;
if (_draw_bottom < dst.bottom)
_draw_bottom = dst.bottom;
byte *dstPtr = (byte *)_out.pixels + dst.left + dst.top * _out.pitch;
Wiz::decompressWizImage(dstPtr, _out.pitch, dst, _srcptr, src);
return 0;
}
bool ScummEngine::akos_increaseAnims(const byte *akos, Actor *a) {
const byte *aksq, *akfo;
int i;
uint size;
bool result;
aksq = findResourceData(MKID('AKSQ'), akos);
akfo = findResourceData(MKID('AKFO'), akos);
size = getResourceDataSize(akfo) / 2;
result = false;
for (i = 0; i < 16; i++) {
if (a->_cost.active[i] != 0)
result |= akos_increaseAnim(a, i, aksq, (const uint16 *)akfo, size);
}
return result;
}
#define GW(o) ((int16)READ_LE_UINT16(aksq+curpos+(o)))
#define GUW(o) READ_LE_UINT16(aksq+curpos+(o))
#define GB(o) aksq[curpos+(o)]
bool ScummEngine::akos_increaseAnim(Actor *a, int chan, const byte *aksq, const uint16 *akfo, int numakfo) {
byte active;
uint old_curpos, curpos, end;
uint code;
bool flag_value, needRedraw;
int tmp, tmp2;
active = a->_cost.active[chan];
end = a->_cost.end[chan];
old_curpos = curpos = a->_cost.curpos[chan];
flag_value = false;
needRedraw = false;
do {
code = aksq[curpos];
if (code & 0x80)
code = (code << 8) | aksq[curpos + 1];
switch (active) {
case 6:
case 8:
switch (code) {
case AKC_JumpIfSet:
case AKC_AddVar:
case AKC_SetVar:
case AKC_SkipGE:
case AKC_SkipG:
case AKC_SkipLE:
case AKC_SkipL:
case AKC_SkipNE:
case AKC_SkipE:
case AKC_C016:
case AKC_C017:
case AKC_C018:
case AKC_C019:
curpos += 5;
break;
case AKC_JumpTable:
case AKC_SetActorClip:
case AKC_Ignore3:
case AKC_Ignore2:
case AKC_Ignore:
case AKC_StartAnim:
case AKC_StartVarAnim:
case AKC_CmdQue3:
case AKC_C042:
case AKC_C044:
case AKC_C0A3:
curpos += 3;
break;
case AKC_SoundStuff:
if (_features & GF_HUMONGOUS)
curpos += 6;
else
curpos += 8;
break;
case AKC_Cmd3:
case AKC_SetVarInActor:
case AKC_SetDrawOffs:
curpos += 6;
break;
case AKC_ClearFlag:
case AKC_HideActor:
case AKC_IncVar:
case AKC_CmdQue3Quick:
case AKC_Return:
case AKC_EndSeq:
curpos += 2;
break;
case AKC_JumpGE:
case AKC_JumpG:
case AKC_JumpLE:
case AKC_JumpL:
case AKC_JumpNE:
case AKC_JumpE:
case AKC_Random:
curpos += 7;
break;
case AKC_Flip:
case AKC_Jump:
case AKC_StartAnimInActor:
case AKC_C0A0:
case AKC_C0A1:
case AKC_C0A2:
curpos += 4;
break;
case AKC_ComplexChan2:
curpos += 4;
// Fall through
case AKC_ComplexChan:
curpos += 3;
tmp = aksq[curpos - 1];
while (--tmp >= 0) {
curpos += 4;
curpos += (aksq[curpos] & 0x80) ? 2 : 1;
}
break;
case AKC_C021:
case AKC_C022:
case AKC_C045:
case AKC_C046:
case AKC_C047:
case AKC_C048:
needRedraw = 1;
curpos += aksq[curpos + 2];
break;
case AKC_C08E:
akos_queCommand(7, a, GW(2), 0);
curpos += 4;
break;
default:
if ((code & 0xC000) == 0xC000)
error("akos_increaseAnim: invalid code %x", code);
curpos += (code & 0x8000) ? 2 : 1;
break;
}
break;
case 2:
curpos += (code & 0x8000) ? 2 : 1;
if (curpos > end)
curpos = a->_cost.start[chan];
break;
case 3:
if (curpos != end)
curpos += (code & 0x8000) ? 2 : 1;
break;
}
code = aksq[curpos];
if (code & 0x80)
code = (code << 8) | aksq[curpos + 1];
if (flag_value && code != AKC_ClearFlag)
continue;
switch (code) {
case AKC_StartAnimInActor:
akos_queCommand(4, derefActor(a->getAnimVar(GB(2)), "akos_increaseAnim:29"), a->getAnimVar(GB(3)), 0);
continue;
case AKC_Random:
a->setAnimVar(GB(6), _rnd.getRandomNumberRng(GW(2), GW(4)));
continue;
case AKC_JumpGE:
case AKC_JumpG:
case AKC_JumpLE:
case AKC_JumpL:
case AKC_JumpNE:
case AKC_JumpE:
if (akos_compare(a->getAnimVar(GB(4)), GW(5), code - AKC_JumpStart) != 0) {
curpos = GUW(2);
break;
}
continue;
case AKC_IncVar:
a->setAnimVar(0, a->getAnimVar(0) + 1);
continue;
case AKC_SetVar:
a->setAnimVar(GB(4), GW(2));
continue;
case AKC_AddVar:
a->setAnimVar(GB(4), a->getAnimVar(GB(4)) + GW(2));
continue;
case AKC_Flip:
a->_flip = GW(2) != 0;
continue;
case AKC_CmdQue3:
case AKC_C042:
if (_features & GF_HUMONGOUS)
tmp = GB(2);
else
tmp = GB(2) - 1;
if ((uint) tmp < 24)
akos_queCommand(3, a, a->_sound[tmp], 0);
continue;
case AKC_CmdQue3Quick:
akos_queCommand(3, a, a->_sound[0], 0);
continue;
case AKC_StartAnim:
akos_queCommand(4, a, GB(2), 0);
continue;
case AKC_StartVarAnim:
akos_queCommand(4, a, a->getAnimVar(GB(2)), 0);
continue;
case AKC_SetVarInActor:
derefActor(a->getAnimVar(GB(2)), "akos_increaseAnim:9")->setAnimVar(GB(3), GW(4));
continue;
case AKC_HideActor:
akos_queCommand(1, a, 0, 0);
continue;
case AKC_SetActorClip:
akos_queCommand(5, a, GB(2), 0);
continue;
case AKC_SoundStuff:
if (_features & GF_HUMONGOUS)
continue;
tmp = GB(2) - 1;
if (tmp >= 8)
continue;
tmp2 = GB(4);
if (tmp2 < 1 || tmp2 > 3)
error("akos_increaseAnim:8 invalid code %d", tmp2);
akos_queCommand(tmp2 + 6, a, a->_sound[tmp], GB(6));
continue;
case AKC_SetDrawOffs:
akos_queCommand(6, a, GW(2), GW(4));
continue;
case AKC_JumpTable:
if (akfo == NULL)
error("akos_increaseAnim: no AKFO table");
tmp = a->getAnimVar(GB(2)) - 1;
if (_heversion >= 80) {
if (tmp < 0 || tmp > a->_cost.seq2[chan] - 1)
error("akos_increaseAnim: invalid jump value %d", tmp);
curpos = READ_LE_UINT16(akfo + a->_cost.seq1[chan] + tmp * 2);
} else {
if (tmp < 0 || tmp > numakfo - 1)
error("akos_increaseAnim: invalid jump value %d", tmp);
curpos = READ_LE_UINT16(&akfo[tmp]);
}
break;
case AKC_JumpIfSet:
if (!a->getAnimVar(GB(4)))
continue;
a->setAnimVar(GB(4), 0);
curpos = GUW(2);
break;
case AKC_ClearFlag:
flag_value = false;
continue;
case AKC_Jump:
curpos = GUW(2);
break;
case AKC_Return:
case AKC_EndSeq:
case AKC_ComplexChan:
case AKC_C08E:
case AKC_ComplexChan2:
break;
case AKC_C021:
case AKC_C022:
needRedraw = 1;
break;
case AKC_Cmd3:
case AKC_Ignore:
case AKC_Ignore3:
continue;
case AKC_Ignore2:
if (_heversion >= 71)
akos_queCommand(3, a, a->_sound[a->getAnimVar(GB(2))], 0);
continue;
case AKC_SkipE:
case AKC_SkipNE:
case AKC_SkipL:
case AKC_SkipLE:
case AKC_SkipG:
case AKC_SkipGE:
if (akos_compare(a->getAnimVar(GB(4)), GW(2), code - AKC_SkipStart) == 0)
flag_value = true;
continue;
case AKC_C0A0:
akos_queCommand(8, a, GB(2), 0);
continue;
case AKC_C0A1:
if (a->_heTalking) {
curpos = GUW(2);
break;
}
continue;
case AKC_C0A2:
if (!a->_heTalking) {
curpos = GUW(2);
break;
}
continue;
case AKC_C0A3:
akos_queCommand(8, a, a->getAnimVar(GB(2)), 0);
continue;
case AKC_C016:
if (_sound->isSoundRunning( a->_sound[a->getAnimVar(GB(4))])) {
curpos = GUW(2);
break;
}
continue;
case AKC_C017:
if (!_sound->isSoundRunning(a->_sound[a->getAnimVar(GB(4))])) {
curpos = GUW(2);
break;
}
continue;
case AKC_C018:
if (_sound->isSoundRunning(a->_sound[GB(4)])) {
curpos = GUW(2);
break;
}
continue;
case AKC_C019:
if (!_sound->isSoundRunning(a->_sound[GB(4)])) {
curpos = GUW(2);
break;
}
continue;
case AKC_C044:
akos_queCommand(3, a, a->_sound[a->getAnimVar(GB(2))], 0);
continue;
case AKC_C045:
a->setUserCondition(GB(3), a->getAnimVar(GB(4)));
continue;
case AKC_C046:
a->setAnimVar(GB(4), a->isUserConditionSet(GB(3)));
continue;
case AKC_C047:
a->setTalkCondition(GB(3));
continue;
case AKC_C048:
a->setAnimVar(GB(4), a->isTalkConditionSet(GB(3)));
continue;
default:
if ((code & 0xC000) == 0xC000)
error("Undefined uSweat token %X", code);
}
break;
} while (1);
int code2 = aksq[curpos];
if (code2 & 0x80)
code2 = (code2 << 8) | aksq[curpos + 1];
assert((code2 & 0xC000) != 0xC000 || code2 == AKC_ComplexChan || code2 == AKC_Return || code2 == AKC_EndSeq || code2 == AKC_C08E || code2 == AKC_ComplexChan2 || code2 == AKC_C021 || code2 == AKC_C022);
a->_cost.curpos[chan] = curpos;
if (needRedraw)
return 1;
else
return curpos != old_curpos;
}
void ScummEngine::akos_queCommand(byte cmd, Actor *a, int param_1, int param_2) {
_akosQueuePos++;
checkRange(31, 0, _akosQueuePos, "akos_queCommand overflow");
_akosQueue[_akosQueuePos].cmd = cmd;
_akosQueue[_akosQueuePos].actor = a->_number;
_akosQueue[_akosQueuePos].param1 = param_1;
_akosQueue[_akosQueuePos].param2 = param_2;
}
void ScummEngine::akos_processQueue() {
byte cmd;
int actor, param_1, param_2;
while (_akosQueuePos) {
cmd = _akosQueue[_akosQueuePos].cmd;
actor = _akosQueue[_akosQueuePos].actor;
param_1 = _akosQueue[_akosQueuePos].param1;
param_2 = _akosQueue[_akosQueuePos].param2;
_akosQueuePos--;
Actor *a = derefActor(actor, "akos_processQueue");
switch (cmd) {
case 1:
a->putActor(0, 0, 0);
break;
case 2:
warning("unimplemented akos_queCommand(2,%d,%d,%d)", a->_number, param_1, param_2);
// start script token in actor
break;
case 3:
if (param_1 != 0) {
if (_features & GF_DIGI_IMUSE)
_imuseDigital->startSfx(param_1, 63);
else
_sound->addSoundToQueue(param_1);
}
break;
case 4:
a->startAnimActor(param_1);
break;
case 5:
a->_forceClip = param_1;
break;
case 6:
a->_offsX = param_1;
a->_offsY = param_2;
break;
case 7:
if (_heversion >= 71) {
queueAuxEntry(a->_number, param_1);
} else if (param_1 != 0) {
if (_imuseDigital) {
_imuseDigital->setVolume(param_1, param_2);
}
}
break;
case 8:
if (_heversion >= 71) {
_actorToPrintStrFor = a->_number;
a->_talkPosX = a->_heTalkQueue[param_1].posX;
a->_talkPosY = a->_heTalkQueue[param_1].posY;
a->_talkColor = a->_heTalkQueue[param_1].color;
_string[0].loadDefault();
actorTalk(a->_heTalkQueue[param_1].sentence);
} else if (param_1 != 0) {
if (_imuseDigital) {
_imuseDigital->setPan(param_1, param_2);
}
}
break;
case 9:
if (param_1 != 0) {
if (_imuseDigital) {
_imuseDigital->setPriority(param_1, param_2);
}
}
break;
default:
warning("akos_queCommand(%d,%d,%d,%d)", cmd, a->_number, param_1, param_2);
}
}
}
} // End of namespace Scumm
#ifdef __PALM_OS__
#include "scumm_globals.h"
_GINIT(Akos)
_GSETPTR(Scumm::defaultScaleTable, GBVARS_DEFAULTSCALETABLE_INDEX, byte, GBVARS_SCUMM)
_GSETPTR(Scumm::oldScaleTable, GBVARS_OLDSCALETABLE_INDEX, byte, GBVARS_SCUMM)
_GEND
_GRELEASE(Akos)
_GRELEASEPTR(GBVARS_DEFAULTSCALETABLE_INDEX, GBVARS_SCUMM)
_GRELEASEPTR(GBVARS_OLDSCALETABLE_INDEX, GBVARS_SCUMM)
_GEND
#endif