scummvm/queen/graphics.cpp
Gregory Montoir 4fef6d8972 fix for bug #928549.
Animations on objects/persons setup by cutaways can still be played after the end of the cutscene. (the only ?) one room in which this is reproducable is the first time you talk to the Oracle (first c44, then c47).

As a Cutaway object is created for each cutscene, the _cutAnim member should be moved to an more "persistant" object.
Otherwise we're reading data from free'd memory...

svn-id: r13488
2004-04-06 20:15:19 +00:00

1517 lines
46 KiB
C++

/* ScummVM - Scumm Interpreter
* Copyright (C) 2003-2004 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 "queen/graphics.h"
#include "queen/bankman.h"
#include "queen/display.h"
#include "queen/grid.h"
#include "queen/logic.h"
#include "queen/queen.h"
#include "queen/resource.h"
#include "queen/sound.h"
namespace Queen {
#ifdef __PALM_OS__
static const BamScene::BamDataBlock *_carData;
static const BamScene::BamDataBlock *_fight1Data;
static const BamScene::BamDataBlock *_fight2Data;
static const BamScene::BamDataBlock *_fight3Data;
#endif
const Box BobSlot::_defaultBox(-1, -1, -1, -1);
void BobSlot::curPos(int16 xx, int16 yy) {
active = true;
x = xx;
y = yy;
}
void BobSlot::move(int16 dstx, int16 dsty, int16 spd) {
active = true;
moving = true;
endx = dstx;
endy = dsty;
speed = (spd < 1) ? 1 : spd;
int16 deltax = endx - x;
if (deltax < 0) {
dx = -deltax;
xdir = -1;
} else {
dx = deltax;
xdir = 1;
}
int16 deltay = endy - y;
if (deltay < 0) {
dy = -deltay;
ydir = -1;
} else {
dy = deltay;
ydir = 1;
}
if (dx > dy) {
total = dy / 2;
xmajor = true;
} else {
total = dx / 2;
xmajor = false;
}
// move one step along line to avoid glitching
moveOneStep();
}
void BobSlot::moveOneStep() {
if(xmajor) {
if(x == endx) {
y = endy;
moving = false;
} else {
x += xdir;
total += dy;
if(total > dx) {
y += ydir;
total -= dx;
}
}
} else {
if(y == endy) {
x = endx;
moving = false;
} else {
y += ydir;
total += dx;
if(total > dy) {
x += xdir;
total -= dy;
}
}
}
}
void BobSlot::animOneStep() {
if (anim.string.buffer != NULL) {
--anim.speed;
if(anim.speed <= 0) {
// jump to next entry
++anim.string.curPos;
uint16 nextFrame = anim.string.curPos->frame;
if (nextFrame == 0) {
anim.string.curPos = anim.string.buffer;
frameNum = anim.string.curPos->frame;
} else {
frameNum = nextFrame;
}
anim.speed = anim.string.curPos->speed / 4;
}
} else {
// normal looping animation
--anim.speed;
if(anim.speed == 0) {
anim.speed = anim.speedBak;
int16 nextFrame = frameNum + frameDir;
if (nextFrame > anim.normal.lastFrame || nextFrame < anim.normal.firstFrame) {
if (anim.normal.rebound) {
frameDir *= -1;
} else {
frameNum = anim.normal.firstFrame - 1;
}
}
frameNum += frameDir;
}
}
}
void BobSlot::animString(const AnimFrame *animBuf) {
active = true;
animating = true;
anim.string.buffer = animBuf;
anim.string.curPos = animBuf;
frameNum = animBuf->frame;
anim.speed = animBuf->speed / 4;
}
void BobSlot::animNormal(uint16 firstFrame, uint16 lastFrame, uint16 spd, bool rebound, bool flip) {
active = true;
animating = true;
frameNum = firstFrame;
anim.speed = spd;
anim.speedBak = spd;
anim.string.buffer = NULL;
anim.normal.firstFrame = firstFrame;
anim.normal.lastFrame = lastFrame;
anim.normal.rebound = rebound;
frameDir = 1;
xflip = flip;
}
void BobSlot::scaleWalkSpeed(uint16 ms) {
if (!xmajor) {
ms /= 2;
}
speed = scale * ms / 100;
if (speed == 0) {
speed = 1;
}
}
void BobSlot::clear() {
active = false;
xflip = false;
animating = false;
anim.string.buffer = NULL;
moving = false;
scale = 100;
box = _defaultBox;
}
const Box Graphics::_gameScreenBox(0, 0, GAME_SCREEN_WIDTH - 1, ROOM_ZONE_HEIGHT - 1);
const Box Graphics::_fullScreenBox(0, 0, GAME_SCREEN_WIDTH - 1, GAME_SCREEN_HEIGHT - 1);
Graphics::Graphics(QueenEngine *vm)
: _cameraBob(0), _vm(vm) {
memset(_bobs, 0, sizeof(_bobs));
memset(_sortedBobs, 0, sizeof(_sortedBobs));
_sortedBobsCount = 0;
_shrinkBuffer.data = new uint8[ BOB_SHRINK_BUF_SIZE ];
}
Graphics::~Graphics() {
delete[] _shrinkBuffer.data;
}
void Graphics::unpackControlBank() {
_vm->bankMan()->load("control.BBK",17);
_vm->bankMan()->unpack(1, 1, 17); // Mouse pointer
// unpack arrows frames and change hotspot to be always on top
for (int i = 3; i <= 4; ++i) {
_vm->bankMan()->unpack(i, i, 17);
BobFrame *bf = _vm->bankMan()->fetchFrame(i);
bf->yhotspot += 200;
}
_vm->bankMan()->close(17);
}
void Graphics::setupArrows() {
int scrollX = _vm->display()->horizontalScroll();
BobSlot *arrow;
arrow = bob(ARROW_BOB_UP);
arrow->curPos(303 + 8 + scrollX, 150 + 1 + 200);
arrow->frameNum = 3;
arrow = bob(ARROW_BOB_DOWN);
arrow->curPos(303 + scrollX, 175 + 200);
arrow->frameNum = 4;
}
void Graphics::setupMouseCursor() {
BobFrame *bf = _vm->bankMan()->fetchFrame(1);
_vm->display()->setMouseCursor(bf->data, bf->width, bf->height);
}
void Graphics::drawBob(const BobSlot *bs, const BobFrame *bf, const Box *bbox, int16 x, int16 y) {
debug(9, "Graphics::drawBob(%d, %d, %d)", bs->frameNum, x, y);
uint16 w, h;
if (bs->scale < 100) {
shrinkFrame(bf, bs->scale);
bf = &_shrinkBuffer;
}
w = bf->width;
h = bf->height;
const Box *box = (bs->box == BobSlot::_defaultBox) ? bbox : &bs->box;
if(w != 0 && h != 0 && box->intersects(x, y, w, h)) {
uint8 *src = bf->data;
uint16 x_skip = 0;
uint16 y_skip = 0;
uint16 w_new = w;
uint16 h_new = h;
// compute bounding box intersection with frame
if (x < box->x1) {
x_skip = box->x1 - x;
w_new -= x_skip;
x = box->x1;
}
if (y < box->y1) {
y_skip = box->y1 - y;
h_new -= y_skip;
y = box->y1;
}
if (x + w_new > box->x2 + 1) {
w_new = box->x2 - x + 1;
}
if (y + h_new > box->y2 + 1) {
h_new = box->y2 - y + 1;
}
src += w * y_skip;
if (!bs->xflip) {
src += x_skip;
} else {
src += w - w_new - x_skip;
x += w_new - 1;
}
_vm->display()->drawBobSprite(src, x, y, w_new, h_new, w, bs->xflip);
}
}
void Graphics::drawInventoryItem(uint32 frameNum, uint16 x, uint16 y) {
if (frameNum != 0) {
BobFrame *bf = _vm->bankMan()->fetchFrame(frameNum);
_vm->display()->drawInventoryItem(bf->data, x, y, bf->width, bf->height);
} else {
_vm->display()->drawInventoryItem(NULL, x, y, 32, 32);
}
}
void Graphics::pasteBob(uint16 objNum, uint16 image) {
GraphicData *pgd = _vm->logic()->graphicData(objNum);
_vm->bankMan()->unpack(pgd->firstFrame, image, 15);
BobFrame *bf = _vm->bankMan()->fetchFrame(image);
_vm->display()->drawBobPasteDown(bf->data, pgd->x, pgd->y, bf->width, bf->height);
_vm->bankMan()->eraseFrame(image);
}
void Graphics::shrinkFrame(const BobFrame *bf, uint16 percentage) {
// computing new size, rounding to upper value
uint16 new_w = (bf->width * percentage + 50) / 100;
uint16 new_h = (bf->height * percentage + 50) / 100;
assert(new_w * new_h < BOB_SHRINK_BUF_SIZE);
if (new_w != 0 && new_h != 0) {
_shrinkBuffer.width = new_w;
_shrinkBuffer.height = new_h;
uint16 x, y;
uint16 sh[GAME_SCREEN_WIDTH];
for (x = 0; x < MAX(new_h, new_w); ++x) {
sh[x] = x * 100 / percentage;
}
uint8* dst = _shrinkBuffer.data;
for (y = 0; y < new_h; ++y) {
uint8 *p = bf->data + sh[y] * bf->width;
for(x = 0; x < new_w; ++x) {
*dst++ = *(p + sh[x]);
}
}
}
}
void Graphics::sortBobs() {
_sortedBobsCount = 0;
// animate/move the bobs
for (int32 i = 0; i < ARRAYSIZE(_bobs); ++i) {
BobSlot *pbs = &_bobs[i];
if (pbs->active) {
_sortedBobs[_sortedBobsCount] = pbs;
++_sortedBobsCount;
if (pbs->animating) {
pbs->animOneStep();
if (pbs->frameNum > 500) { // SFX frame
_vm->sound()->playSfx(_vm->logic()->currentRoomSfx(), false);
pbs->frameNum -= 500;
}
}
if (pbs->moving) {
int16 j;
for (j = 0; pbs->moving && j < pbs->speed; ++j) {
pbs->moveOneStep();
}
}
}
}
// bubble sort the bobs
for (int32 index = 0; index < _sortedBobsCount - 1; ++index) {
int32 smallest = index;
for (int32 compare = index + 1; compare <= _sortedBobsCount - 1; ++compare) {
if (_sortedBobs[compare]->y < _sortedBobs[smallest]->y) {
smallest = compare;
}
}
if (index != smallest) {
SWAP(_sortedBobs[index], _sortedBobs[smallest]);
}
}
}
void Graphics::drawBobs() {
const Box *bobBox = _vm->display()->fullscreen() ? &_fullScreenBox : &_gameScreenBox;
for (int i = 0; i < _sortedBobsCount; ++i) {
BobSlot *pbs = _sortedBobs[i];
if (pbs->active) {
BobFrame *pbf = _vm->bankMan()->fetchFrame(pbs->frameNum);
uint16 xh, yh, x, y;
xh = pbf->xhotspot;
yh = pbf->yhotspot;
if (pbs->xflip) {
xh = pbf->width - xh;
}
// adjusts hot spots when object is scaled
if (pbs->scale != 100) {
xh = (xh * pbs->scale) / 100;
yh = (yh * pbs->scale) / 100;
}
// adjusts position to hot-spot and screen scroll
x = pbs->x - xh - _vm->display()->horizontalScroll();
y = pbs->y - yh;
drawBob(pbs, pbf, bobBox, x, y);
}
}
}
void Graphics::clearBobs() {
for(int32 i = 0; i < ARRAYSIZE(_bobs); ++i) {
_bobs[i].clear();
}
}
void Graphics::stopBobs() {
for(int32 i = 0; i < ARRAYSIZE(_bobs); ++i) {
_bobs[i].moving = false;
}
}
BobSlot *Graphics::bob(int index) {
assert(index < MAX_BOBS_NUMBER);
return _bobs + index;
}
void Graphics::setBobText(
const BobSlot *pbs,
const char *text,
int textX, int textY,
int color, int flags) {
if (text[0] == '\0')
return;
// Duplicate string and append zero if needed
char textCopy[MAX_STRING_SIZE];
int length = strlen(text);
memcpy(textCopy, text, length);
if (textCopy[length - 1] >= 'A')
textCopy[length++] = '.';
textCopy[length] = '\0';
// Split text into lines
char lines[8][MAX_STRING_SIZE];
int lineCount = 0;
int lineLength = 0;
int i;
// Hebrew strings are written from right to left and should be cut
// to lines in reverse
if (_vm->resource()->getLanguage() == HEBREW) {
for (i = length - 1; i >= 0; i--) {
lineLength++;
if ((lineLength > 20 && textCopy[i] == ' ') || i == 0) {
memcpy(lines[lineCount], textCopy + i, lineLength);
lines[lineCount][lineLength] = '\0';
lineCount++;
lineLength = 0;
}
}
} else {
for (i = 0; i < length; i++) {
lineLength++;
if ((lineLength > 20 && textCopy[i] == ' ') || i == (length-1)) {
memcpy(lines[lineCount], textCopy + i + 1 - lineLength, lineLength);
lines[lineCount][lineLength] = '\0';
lineCount++;
lineLength = 0;
}
}
}
// Find width of widest line
int maxLineWidth = 0;
for (i = 0; i < lineCount; i++) {
int width = _vm->display()->textWidth(lines[i]);
if (maxLineWidth < width)
maxLineWidth = width;
}
// Calc text position
short x, y, width, height;
if (flags) {
if (flags == 2)
x = 160 - maxLineWidth / 2;
else
x = textX;
y = textY;
width = 0;
} else {
x = pbs->x;
y = pbs->y;
BobFrame *pbf = _vm->bankMan()->fetchFrame(pbs->frameNum);
width = (pbf->width * pbs->scale) / 100;
height = (pbf->height * pbs->scale) / 100;
y = y - height - 16 - lineCount * 9;
}
x -= _vm->display()->horizontalScroll();
if (y < 0) {
y = 0;
if (x < 160)
x += width / 2;
else
x -= width / 2 + maxLineWidth;
} else if (!flags)
x -= maxLineWidth / 2;
if (x < 0)
x = 4;
else if ((x + maxLineWidth) > 320)
x = 320 - maxLineWidth - 4;
_vm->display()->textCurrentColor(color);
for (i = 0; i < lineCount; i++) {
int lineX = x + (maxLineWidth - _vm->display()->textWidth(lines[i])) / 2;
debug(7, "Setting text '%s' at (%i, %i)", lines[i], lineX, y + 9 * i);
_vm->display()->setText(lineX, y + 9 * i, lines[i]);
}
}
void Graphics::handleParallax(uint16 roomNum) {
uint16 screenScroll = _vm->display()->horizontalScroll();
switch (roomNum) {
case ROOM_AMAZON_HIDEOUT:
_bobs[8].x = 250 - screenScroll / 2;
break;
case ROOM_TEMPLE_MAZE_5:
_bobs[5].x = 410 - screenScroll / 2;
_bobs[6].x = 790 - screenScroll / 2;
break;
case ROOM_TEMPLE_OUTSIDE:
_bobs[5].x = 320 - screenScroll / 2;
break;
case ROOM_TEMPLE_TREE:
_bobs[5].x = 280 - screenScroll / 2;
break;
case ROOM_VALLEY_CARCASS:
_bobs[5].x = 600 - screenScroll / 2;
break;
case ROOM_UNUSED_INTRO_1:
_bobs[5].x = 340 - screenScroll / 2;
_bobs[6].x = 50 - screenScroll / 2;
_bobs[7].x = 79 - screenScroll / 2;
break;
case ROOM_CAR_CHASE:
_vm->bam()->updateCarAnimation();
break;
case ROOM_FINAL_FIGHT:
_vm->bam()->updateFightAnimation();
break;
case ROOM_INTRO_RITA_JOE_HEADS:
_cameraBob = -1;
if (screenScroll < 80) {
_vm->display()->horizontalScroll(screenScroll + 4);
// Joe's body and head
_bobs[ 1].x += 4;
_bobs[20].x += 4;
// Rita's body and head
_bobs[ 2].x -= 2;
_bobs[21].x -= 2;
}
break;
case ROOM_INTRO_EXPLOSION:
_bobs[21].x += 2;
_bobs[21].y += 2;
break;
}
}
void Graphics::setupNewRoom(const char *room, uint16 roomNum, int16 *furniture, uint16 furnitureCount) {
// reset sprites table
clearBobs();
// load/setup objects associated to this room
char filename[20];
sprintf(filename, "%s.BBK", room);
_vm->bankMan()->load(filename, 15);
_numFrames = 37 + FRAMES_JOE_XTRA;
setupRoomFurniture(furniture, furnitureCount);
setupRoomObjects();
if (roomNum >= 90) {
putCameraOnBob(0);
}
}
void Graphics::setBobCutawayAnim(uint16 bobNum, bool xflip, const AnimFrame *af, uint8 frameCount) {
assert(bobNum < 21 && frameCount < 30);
memcpy(_cutAnim[bobNum], af, sizeof(AnimFrame) * frameCount);
_bobs[bobNum].xflip = xflip;
_bobs[bobNum].animString(_cutAnim[bobNum]);
}
void Graphics::fillAnimBuffer(const char *anim, AnimFrame *af) {
for (;;) {
// anim frame format is "%3hu,%3hu," (frame number, frame speed)
af->frame = atoi(anim);
anim += 4;
af->speed = atoi(anim);
anim += 4;
if (af->frame == 0)
break;
++af;
}
}
uint16 Graphics::countAnimFrames(const char *anim) {
AnimFrame afbuf[30];
fillAnimBuffer(anim, afbuf);
bool frames[256];
memset(frames, 0, sizeof(frames));
uint16 count = 0;
AnimFrame *af = afbuf;
for ( ; af->frame != 0; ++af) {
uint16 frameNum = af->frame;
if (frameNum > 500) {
frameNum -= 500;
}
if (!frames[frameNum]) {
frames[frameNum] = true;
++count;
}
}
return count;
}
void Graphics::setupObjectAnim(const GraphicData *gd, uint16 firstImage, uint16 bobNum, bool visible) {
int16 tempFrames[20];
memset(tempFrames, 0, sizeof(tempFrames));
uint16 numTempFrames = 0;
uint16 i, j;
for (i = 1; i <= _vm->logic()->graphicAnimCount(); ++i) {
const GraphicAnim *pga = _vm->logic()->graphicAnim(i);
if (pga->keyFrame == gd->firstFrame) {
int16 frame = pga->frame;
if (frame > 500) { // SFX
frame -= 500;
}
bool foundMatchingFrame = false;
for (j = 0; j < numTempFrames; ++j) {
if (tempFrames[j] == frame) {
foundMatchingFrame = true;
break;
}
}
if (!foundMatchingFrame) {
assert(numTempFrames < 20);
tempFrames[numTempFrames] = frame;
++numTempFrames;
}
}
}
// sort found frames ascending
bool swap = true;
while (swap) {
swap = false;
for (i = 0; i < numTempFrames - 1; ++i) {
if (tempFrames[i] > tempFrames[i + 1]) {
SWAP(tempFrames[i], tempFrames[i + 1]);
swap = true;
}
}
}
// queen.c l.962-980 / l.1269-1294
for (i = 0; i < gd->lastFrame; ++i) {
_vm->bankMan()->unpack(ABS(tempFrames[i]), firstImage + i, 15);
}
BobSlot *pbs = bob(bobNum);
pbs->animating = false;
if (visible) {
pbs->curPos(gd->x, gd->y);
if (tempFrames[0] < 0) {
pbs->xflip = true;
}
AnimFrame *paf = _newAnim[bobNum];
for (i = 1; i <= _vm->logic()->graphicAnimCount(); ++i) {
const GraphicAnim *pga = _vm->logic()->graphicAnim(i);
if (pga->keyFrame == gd->firstFrame) {
uint16 frameNr = 0;
for (j = 1; j <= gd->lastFrame; ++j) {
if (pga->frame > 500) {
if (pga->frame - 500 == tempFrames[j - 1]) {
frameNr = j + firstImage - 1 + 500;
}
} else if (pga->frame == tempFrames[j - 1]) {
frameNr = j + firstImage - 1;
}
}
paf->frame = frameNr;
paf->speed = pga->speed;
++paf;
}
}
paf->frame = 0;
paf->speed = 0;
pbs->animString(_newAnim[bobNum]);
}
}
uint16 Graphics::setupPersonAnim(const ActorData *ad, const char *anim, uint16 curImage) {
debug(9, "Graphics::setupPersonAnim(%s, %d)", anim, curImage);
_personFrames[ad->bobNum] = curImage + 1;
AnimFrame *animFrames = _newAnim[ad->bobNum];
fillAnimBuffer(anim, animFrames);
uint16 frameCount[256];
memset(frameCount, 0, sizeof(frameCount));
AnimFrame *af = animFrames;
for ( ; af->frame != 0; ++af) {
uint16 frameNum = af->frame;
if (frameNum > 500) {
frameNum -= 500;
}
if (!frameCount[frameNum]) {
frameCount[frameNum] = 1;
}
}
uint16 i, n = 1;
for (i = 1; i < 256; ++i) {
if (frameCount[i]) {
frameCount[i] = n;
++n;
}
}
af = animFrames;
for ( ; af->frame != 0; ++af) {
if (af->frame > 500) {
af->frame = curImage + frameCount[af->frame - 500] + 500;
} else {
af->frame = curImage + frameCount[af->frame];
}
}
// unpack necessary frames
for (i = 1; i < 256; ++i) {
if (frameCount[i]) {
++curImage;
_vm->bankMan()->unpack(i, curImage, ad->bankNum);
}
}
// start animation
bob(ad->bobNum)->animString(animFrames);
return curImage;
}
void Graphics::resetPersonAnim(uint16 bobNum) {
if (_newAnim[bobNum][0].frame != 0) {
bob(bobNum)->animString(_newAnim[bobNum]);
}
}
void Graphics::erasePersonAnim(uint16 bobNum) {
_newAnim[bobNum][0].frame = 0;
BobSlot *pbs = bob(bobNum);
pbs->animating = false;
pbs->anim.string.buffer = NULL;
}
void Graphics::eraseAllAnims() {
for (int i = 1; i <= 16; ++i) {
_newAnim[i][0].frame = 0;
}
}
uint16 Graphics::refreshObject(uint16 obj) {
debug(6, "Graphics::refreshObject(%X)", obj);
uint16 curImage = _numFrames;
ObjectData *pod = _vm->logic()->objectData(obj);
if (pod->image == 0) {
return curImage;
}
// check the object is in the current room
if (pod->room != _vm->logic()->currentRoom()) {
return curImage;
}
// find bob for the object
uint16 curBob = _vm->logic()->findBob(obj);
BobSlot *pbs = bob(curBob);
if (pod->image == -3 || pod->image == -4) {
// a person object
if (pod->name <= 0) {
pbs->clear();
} else {
// find person number
uint16 pNum = _vm->logic()->findPersonNumber(obj, _vm->logic()->currentRoom());
curImage = _personFrames[pNum] - 1;
if (_personFrames[pNum] == 0) {
_personFrames[pNum] = curImage = _numFrames;
}
curImage = setupPerson(obj - _vm->logic()->currentRoomData(), curImage);
}
return curImage;
}
// find frame used for object
curImage = _vm->logic()->findFrame(obj);
if (pod->name < 0 || pod->image < 0) {
// object is hidden or disabled
pbs->clear();
return curImage;
}
int image = pod->image;
if (image > 5000) {
image -= 5000;
}
GraphicData *pgd = _vm->logic()->graphicData(image);
bool rebound = false;
int16 lastFrame = pgd->lastFrame;
if (lastFrame < 0) {
lastFrame = -lastFrame;
rebound = true;
}
if (pgd->firstFrame < 0) {
setupObjectAnim(pgd, curImage, curBob, pod->name != 0);
curImage += pgd->lastFrame - 1;
} else if (lastFrame != 0) {
// turn on an animated bob
pbs->animating = false;
uint16 firstImage = curImage;
--curImage;
uint16 j;
for (j = pgd->firstFrame; j <= lastFrame; ++j) {
++curImage;
_vm->bankMan()->unpack(j, curImage, 15);
}
pbs->curPos(pgd->x, pgd->y);
pbs->frameNum = firstImage;
if (pgd->speed > 0) {
pbs->animNormal(firstImage, curImage, pgd->speed / 4, rebound, false);
}
} else {
_vm->bankMan()->unpack(pgd->firstFrame, curImage, 15);
pbs->curPos(pgd->x, pgd->y);
pbs->frameNum = curImage;
}
return curImage;
}
void Graphics::setupRoomFurniture(int16 *furniture, uint16 furnitureCount) {
uint16 i;
uint16 curImage = 36 + FRAMES_JOE_XTRA;
// unpack the static bobs
_numFurnitureStatic = 0;
for (i = 1; i <= furnitureCount; ++i) {
int16 obj = furniture[i];
if (obj > 0 && obj <= 5000) {
GraphicData *pgd = _vm->logic()->graphicData(obj);
if (pgd->lastFrame == 0) {
++_numFurnitureStatic;
++curImage;
_vm->bankMan()->unpack(pgd->firstFrame, curImage, 15);
++_numFrames;
BobSlot *pbs = bob(19 + _numFurnitureStatic);
pbs->curPos(pgd->x, pgd->y);
pbs->frameNum = curImage;
}
}
}
// unpack the animated bobs
_numFurnitureAnimated = 0;
_numFurnitureAnimatedLen = 0;
uint16 curBob = 0;
for (i = 1; i <= furnitureCount; ++i) {
int16 obj = furniture[i];
if (obj > 0 && obj <= 5000) {
GraphicData *pgd = _vm->logic()->graphicData(obj);
bool rebound = false;
int16 lastFrame = pgd->lastFrame;
if (lastFrame < 0) {
rebound = true;
lastFrame = -lastFrame;
}
if (lastFrame > 0) {
_numFurnitureAnimatedLen += lastFrame - pgd->firstFrame + 1;
++_numFurnitureAnimated;
uint16 image = curImage + 1;
int k;
for (k = pgd->firstFrame; k <= lastFrame; ++k) {
++curImage;
_vm->bankMan()->unpack(k, curImage, 15);
++_numFrames;
}
BobSlot *pbs = bob(5 + curBob);
pbs->animNormal(image, curImage, pgd->speed / 4, rebound, false);
pbs->curPos(pgd->x, pgd->y);
++curBob;
}
}
}
// unpack the paste downs
for (i = 1; i <= furnitureCount; ++i) {
if (furniture[i] > 5000) {;
pasteBob(furniture[i] - 5000, curImage + 1);
}
}
}
void Graphics::setupRoomObjects() {
uint16 i;
// furniture frames are reserved in ::setupRoomFurniture(), we append objects
// frames after the furniture ones.
uint16 curImage = 36 + FRAMES_JOE_XTRA + _numFurnitureStatic + _numFurnitureAnimatedLen;
uint16 firstRoomObj = _vm->logic()->currentRoomData() + 1;
uint16 lastRoomObj = _vm->logic()->roomData(_vm->logic()->currentRoom() + 1);
uint16 numObjectStatic = 0;
uint16 numObjectAnimated = 0;
uint16 curBob;
// invalidates all Bobs for persons (except Joe's one)
for (i = 1; i <= 3; ++i) {
_bobs[i].active = false;
}
// static/animated Bobs
for (i = firstRoomObj; i <= lastRoomObj; ++i) {
ObjectData *pod = _vm->logic()->objectData(i);
// setup blanks bobs for turned off objects (in case
// you turn them on again)
if (pod->image == -1) {
// static OFF Bob
curBob = 20 + _numFurnitureStatic + numObjectStatic;
++numObjectStatic;
// create a blank frame for the OFF object
++_numFrames;
++curImage;
} else if(pod->image == -2) {
// animated OFF Bob
curBob = 5 + _numFurnitureAnimated + numObjectAnimated;
++numObjectAnimated;
} else if(pod->image > 0 && pod->image < 5000) {
GraphicData *pgd = _vm->logic()->graphicData(pod->image);
int16 lastFrame = pgd->lastFrame;
bool rebound = false;
if (lastFrame < 0) {
lastFrame = -lastFrame;
rebound = true;
}
if (pgd->firstFrame < 0) {
curBob = 5 + _numFurnitureAnimated;
setupObjectAnim(pgd, curImage + 1, curBob + numObjectAnimated, pod->name > 0);
curImage += pgd->lastFrame;
++numObjectAnimated;
} else if (lastFrame != 0) {
// animated objects
uint16 j;
uint16 firstFrame = curImage + 1;
for (j = pgd->firstFrame; j <= lastFrame; ++j) {
++curImage;
_vm->bankMan()->unpack(j, curImage, 15);
++_numFrames;
}
curBob = 5 + _numFurnitureAnimated + numObjectAnimated;
if (pod->name > 0) {
BobSlot *pbs = bob(curBob);
pbs->curPos(pgd->x, pgd->y);
pbs->frameNum = firstFrame;
if (pgd->speed > 0) {
pbs->animNormal(firstFrame, curImage, pgd->speed / 4, rebound, false);
}
}
++numObjectAnimated;
} else {
// static objects
curBob = 20 + _numFurnitureStatic + numObjectStatic;
++curImage;
bob(curBob)->clear();
_vm->bankMan()->unpack(pgd->firstFrame, curImage, 15);
++_numFrames;
if (pod->name > 0) {
BobSlot *pbs = bob(curBob);
pbs->curPos(pgd->x, pgd->y);
pbs->frameNum = curImage;
}
++numObjectStatic;
}
}
}
// persons Bobs
for (i = firstRoomObj; i <= lastRoomObj; ++i) {
ObjectData *pod = _vm->logic()->objectData(i);
if (pod->image == -3 || pod->image == -4) {
debug(6, "Graphics::setupRoomObjects() - Setting up person %X, name=%X", i, pod->name);
uint16 noun = i - _vm->logic()->currentRoomData();
if (pod->name > 0) {
curImage = setupPerson(noun, curImage);
} else {
curImage = allocPerson(noun, curImage);
}
}
}
// paste downs list
++curImage;
_numFrames = curImage;
for (i = firstRoomObj; i <= lastRoomObj; ++i) {
ObjectData *pod = _vm->logic()->objectData(i);
if (pod->name > 0 && pod->image > 5000) {
pasteBob(pod->image - 5000, curImage);
}
}
}
uint16 Graphics::setupPerson(uint16 noun, uint16 curImage) {
if (noun == 0) {
warning("Trying to setup person 0");
return curImage;
}
Person p;
if (!_vm->logic()->initPerson(noun, "", true, &p)) {
return curImage;
}
const ActorData *pad = p.actor;
uint16 scale = 100;
uint16 a = _vm->grid()->findAreaForPos(GS_ROOM, pad->x, pad->y);
if (a != 0) {
// person is not standing in the area box, scale it accordingly
scale = _vm->grid()->area(_vm->logic()->currentRoom(), a)->calcScale(pad->y);
}
_vm->bankMan()->unpack(pad->bobFrameStanding, p.bobFrame, p.actor->bankNum);
uint16 obj = _vm->logic()->currentRoomData() + noun;
BobSlot *pbs = bob(pad->bobNum);
pbs->curPos(pad->x, pad->y);
pbs->scale = scale;
pbs->frameNum = p.bobFrame;
pbs->xflip = (_vm->logic()->objectData(obj)->image == -3); // person is facing left
debug(6, "Graphics::setupPerson(%d, %d) - bob = %d name = %s", noun, curImage, pad->bobNum, p.name);
if (p.anim != NULL) {
curImage = setupPersonAnim(pad, p.anim, curImage);
} else {
erasePersonAnim(pad->bobNum);
}
return curImage;
}
uint16 Graphics::allocPerson(uint16 noun, uint16 curImage) {
Person p;
if (_vm->logic()->initPerson(noun, "", false, &p) && p.anim != NULL) {
curImage += countAnimFrames(p.anim);
_personFrames[p.actor->bobNum] = curImage + 1;
}
return curImage;
}
void Graphics::update(uint16 room) {
sortBobs();
if (_cameraBob >= 0) {
_vm->display()->horizontalScrollUpdate(_bobs[_cameraBob].x);
}
handleParallax(room);
_vm->display()->prepareUpdate();
drawBobs();
}
BamScene::BamScene(QueenEngine *vm)
: _flag(F_STOP), _screenShaked(false), _fightData(_fight1Data), _vm(vm) {
}
void BamScene::playSfx() {
// FIXME - we don't play all sfx here. This is only necessary for
// the fight bam, where the number of 'sfx bam frames' is too much
// important / too much closer. The original game does not have
// this problem since their playSfx() function returns immediately
// if a sound is already being played.
if (_lastSoundIndex == 0 || _index - _lastSoundIndex >= SFX_SKIP) {
_vm->sound()->playSfx(_vm->logic()->currentRoomSfx(), false);
_lastSoundIndex = _index;
}
}
void BamScene::prepareAnimation() {
_obj1 = _vm->graphics()->bob(BOB_OBJ1);
_obj1->clear();
_obj1->active = true;
_obj2 = _vm->graphics()->bob(BOB_OBJ2);
_obj2->clear();
_obj2->active = true;
_objfx = _vm->graphics()->bob(BOB_FX);
_objfx->clear();
_objfx->active = true;
_index = 0;
_lastSoundIndex = 0;
}
void BamScene::updateCarAnimation() {
if (_flag != F_STOP) {
const BamDataBlock *bdb = &_carData[_index];
// Truck
_obj1->curPos(bdb->obj1.x, bdb->obj1.y);
_obj1->frameNum = 40 + bdb->obj1.frame;
// Rico
_obj2->curPos(bdb->obj2.x, bdb->obj2.y);
_obj2->frameNum = 30 + bdb->obj2.frame;
// FX
_objfx->curPos(bdb->fx.x, bdb->fx.y);
_objfx->frameNum = 41 + bdb->fx.frame;
if (bdb->sfx < 0) {
_vm->sound()->playSong(-bdb->sfx);
}
if (bdb->sfx == 99) {
_lastSoundIndex = _index = 0;
}
else {
++_index;
}
if (bdb->sfx == 2) {
playSfx();
}
}
}
void BamScene::updateFightAnimation() {
if (_flag != F_STOP) {
const BamDataBlock *bdb = &_fightData[_index];
// Frank
_obj1->curPos(bdb->obj1.x, bdb->obj1.y);
_obj1->frameNum = 40 + ABS(bdb->obj1.frame);
_obj1->xflip = (bdb->obj1.frame < 0);
// Robot
_obj2->curPos(bdb->obj2.x, bdb->obj2.y);
_obj2->frameNum = 40 + ABS(bdb->obj2.frame);
_obj2->xflip = (bdb->obj2.frame < 0);
// FX
_objfx->curPos(bdb->fx.x, bdb->fx.y);
_objfx->frameNum = 40 + ABS(bdb->fx.frame);
_objfx->xflip = (bdb->fx.frame < 0);
if (bdb->sfx < 0) {
_vm->sound()->playSong(-bdb->sfx);
}
++_index;
switch (bdb->sfx) {
case 0: // nothing, so reset shaked screen if necessary
if (_screenShaked) {
_vm->display()->shake(true);
_screenShaked = false;
}
break;
case 1: // shake screen
_vm->display()->shake(false);
_screenShaked = true;
break;
case 2: // play background sfx
playSfx();
break;
case 3: // play background sfx and shake screen
playSfx();
_vm->display()->shake(false);
_screenShaked = true;
break;
case 99: // end of BAM data
_lastSoundIndex = _index = 0;
const BamDataBlock *data[] = {
_fight1Data,
_fight2Data,
_fight3Data
};
_fightData = data[_vm->randomizer.getRandomNumber(2)];
if (_flag == F_REQ_STOP) {
_flag = F_STOP;
}
break;
}
}
}
void BamScene::saveState(byte *&ptr) {
WRITE_BE_UINT16(ptr, _flag); ptr += 2;
}
void BamScene::loadState(uint32 ver, byte *&ptr) {
_flag = READ_BE_UINT16(ptr); ptr += 2;
}
#ifndef __PALM_OS__
const BamScene::BamDataBlock BamScene::_carData[] = {
{ { 310, 105, 1 }, { 314, 106, 17 }, { 366, 101, 1 }, 0 },
{ { 303, 105, 1 }, { 307, 106, 17 }, { 214, 0, 10 }, 0 },
{ { 297, 104, 1 }, { 301, 105, 17 }, { 214, 0, 10 }, 0 },
{ { 294, 103, 1 }, { 298, 104, 17 }, { 214, 0, 10 }, 0 },
{ { 291, 102, 1 }, { 295, 103, 18 }, { 214, 0, 10 }, 0 },
{ { 287, 101, 1 }, { 291, 102, 18 }, { 266, 51, 10 }, 2 },
{ { 283, 100, 1 }, { 287, 101, 19 }, { 279, 47, 11 }, 0 },
{ { 279, 99, 1 }, { 283, 100, 20 }, { 294, 46, 12 }, 0 },
{ { 274, 98, 1 }, { 278, 99, 20 }, { 305, 44, 13 }, 0 },
{ { 269, 98, 1 }, { 273, 99, 20 }, { 320, 42, 14 }, 0 },
{ { 264, 98, 1 }, { 268, 99, 17 }, { 214, 0, 10 }, 0 },
{ { 261, 98, 1 }, { 265, 99, 17 }, { 214, 0, 10 }, 0 },
{ { 259, 98, 1 }, { 263, 99, 17 }, { 214, 0, 10 }, 0 },
{ { 258, 98, 1 }, { 262, 99, 17 }, { 214, 0, 10 }, 0 },
{ { 257, 98, 2 }, { 260, 99, 17 }, { 214, 0, 10 }, 0 },
{ { 255, 99, 3 }, { 258, 100, 17 }, { 214, 0, 10 }, 0 },
{ { 258, 99, 4 }, { 257, 100, 17 }, { 214, 0, 10 }, 0 },
{ { 264, 102, 4 }, { 263, 103, 17 }, { 214, 0, 10 }, 0 },
{ { 272, 105, 5 }, { 274, 106, 17 }, { 214, 0, 10 }, 0 },
{ { 276, 107, 5 }, { 277, 108, 17 }, { 214, 0, 10 }, 0 },
{ { 283, 108, 5 }, { 284, 109, 17 }, { 214, 0, 10 }, 0 },
{ { 288, 109, 5 }, { 288, 110, 17 }, { 214, 0, 10 }, 0 },
{ { 293, 110, 5 }, { 293, 111, 18 }, { 266, 59, 10 }, 2 },
{ { 298, 110, 5 }, { 299, 111, 18 }, { 277, 56, 11 }, 0 },
{ { 303, 110, 5 }, { 304, 111, 19 }, { 285, 55, 12 }, 0 },
{ { 308, 110, 4 }, { 307, 111, 20 }, { 296, 54, 13 }, 0 },
{ { 309, 110, 3 }, { 312, 111, 20 }, { 304, 53, 14 }, 0 },
{ { 310, 110, 3 }, { 313, 111, 20 }, { 214, 0, 10 }, 0 },
{ { 311, 110, 3 }, { 314, 111, 17 }, { 214, 0, 10 }, 0 },
{ { 309, 110, 2 }, { 312, 111, 17 }, { 214, 0, 10 }, 0 },
{ { 304, 111, 2 }, { 307, 112, 17 }, { 214, 0, 10 }, 0 },
{ { 300, 110, 2 }, { 303, 111, 17 }, { 214, 0, 10 }, 0 },
{ { 296, 109, 2 }, { 299, 110, 17 }, { 214, 0, 10 }, 0 },
{ { 292, 108, 1 }, { 296, 109, 17 }, { 214, 0, 10 }, 0 },
{ { 285, 107, 2 }, { 289, 108, 17 }, { 214, 0, 10 }, 0 },
{ { 282, 107, 3 }, { 285, 108, 17 }, { 214, 0, 10 }, 0 },
{ { 278, 107, 4 }, { 277, 108, 18 }, { 214, 0, 10 }, 0 },
{ { 279, 108, 4 }, { 278, 109, 18 }, { 252, 57, 10 }, 2 },
{ { 281, 108, 5 }, { 283, 109, 18 }, { 265, 55, 11 }, 0 },
{ { 284, 109, 5 }, { 285, 110, 19 }, { 277, 55, 12 }, 0 },
{ { 287, 110, 5 }, { 288, 111, 20 }, { 288, 54, 13 }, 0 },
{ { 289, 111, 5 }, { 290, 112, 20 }, { 299, 54, 14 }, 0 },
{ { 291, 112, 4 }, { 290, 113, 20 }, { 214, 0, 10 }, 0 },
{ { 293, 113, 3 }, { 295, 114, 17 }, { 214, 0, 10 }, 0 },
{ { 296, 114, 2 }, { 299, 115, 17 }, { 214, 0, 10 }, 0 },
{ { 295, 115, 2 }, { 298, 116, 17 }, { 214, 0, 10 }, 0 },
{ { 293, 116, 1 }, { 297, 117, 17 }, { 214, 0, 10 }, 0 },
{ { 289, 116, 1 }, { 292, 117, 17 }, { 214, 0, 10 }, 0 },
{ { 285, 115, 1 }, { 289, 116, 17 }, { 214, 0, 10 }, 0 },
{ { 281, 114, 1 }, { 284, 115, 17 }, { 214, 0, 10 }, 0 },
{ { 277, 113, 1 }, { 280, 114, 17 }, { 214, 0, 10 }, 0 },
{ { 274, 112, 1 }, { 277, 113, 17 }, { 214, 0, 10 }, 0 },
{ { 271, 111, 1 }, { 274, 112, 17 }, { 214, 0, 10 }, 0 },
{ { 267, 110, 1 }, { 270, 111, 17 }, { 214, 0, 10 }, 0 },
{ { 263, 109, 1 }, { 266, 110, 17 }, { 214, 0, 10 }, 0 },
{ { 260, 108, 1 }, { 263, 109, 17 }, { 214, 0, 10 }, 0 },
{ { 254, 108, 2 }, { 256, 109, 17 }, { 214, 0, 10 }, 0 },
{ { 252, 107, 3 }, { 254, 108, 17 }, { 214, 0, 10 }, 0 },
{ { 253, 108, 3 }, { 255, 109, 17 }, { 214, 0, 10 }, 0 },
{ { 255, 109, 3 }, { 257, 110, 18 }, { 231, 59, 10 }, 2 },
{ { 258, 111, 3 }, { 260, 112, 18 }, { 242, 57, 11 }, 0 },
{ { 263, 112, 4 }, { 262, 113, 19 }, { 256, 57, 12 }, 0 },
{ { 270, 111, 4 }, { 269, 112, 20 }, { 267, 57, 13 }, 0 },
{ { 274, 112, 5 }, { 276, 113, 20 }, { 281, 56, 14 }, 0 },
{ { 280, 111, 6 }, { 282, 112, 19 }, { 214, 0, 10 }, 0 },
{ { 284, 109, 6 }, { 285, 110, 17 }, { 214, 0, 10 }, 0 },
{ { 289, 108, 6 }, { 291, 109, 17 }, { 214, 0, 10 }, 0 },
{ { 294, 107, 6 }, { 296, 108, 17 }, { 214, 0, 10 }, 0 },
{ { 294, 107, 5 }, { 296, 108, 18 }, { 272, 57, 10 }, 2 },
{ { 295, 107, 5 }, { 297, 108, 18 }, { 282, 57, 11 }, 0 },
{ { 296, 108, 5 }, { 298, 109, 19 }, { 295, 57, 12 }, 0 },
{ { 300, 108, 4 }, { 299, 109, 20 }, { 303, 57, 13 }, 0 },
{ { 303, 108, 3 }, { 306, 109, 20 }, { 313, 57, 14 }, 0 },
{ { 307, 109, 2 }, { 311, 110, 17 }, { 214, 0, 10 }, 0 },
{ { 310, 110, 1 }, { 314, 111, 17 }, { 214, 0, 10 }, 99 }
};
const BamScene::BamDataBlock BamScene::_fight1Data[] = {
{ { 75, 96, 1 }, { 187, 96, -23 }, { 58, 37, 46 }, 0 },
{ { 75, 96, 2 }, { 187, 96, -23 }, { 58, 37, 46 }, 0 },
{ { 75, 96, 3 }, { 187, 96, -23 }, { 58, 37, 46 }, 0 },
{ { 75, 96, 4 }, { 187, 96, -23 }, { 58, 37, 46 }, 0 },
{ { 75, 96, 1 }, { 187, 96, -23 }, { 58, 37, 46 }, 0 },
{ { 75, 96, 2 }, { 187, 96, -23 }, { 58, 37, 46 }, 0 },
{ { 75, 96, 3 }, { 187, 96, -23 }, { 58, 37, 46 }, 0 },
{ { 75, 96, 4 }, { 187, 96, -24 }, { 58, 37, 46 }, 0 },
{ { 79, 96, 1 }, { 187, 96, -24 }, { 58, 37, 46 }, 0 },
{ { 85, 96, 2 }, { 187, 96, -24 }, { 58, 37, 46 }, 0 },
{ { 94, 96, 3 }, { 187, 96, -24 }, { 58, 37, 46 }, 0 },
{ { 100, 96, 4 }, { 187, 96, -24 }, { 58, 37, 46 }, 0 },
{ { 113, 96, 1 }, { 187, 96, -25 }, { 58, 37, 46 }, 0 },
{ { 121, 96, 1 }, { 187, 96, -25 }, { 58, 37, 46 }, 0 },
{ { 136, 96, 16 }, { 187, 96, -26 }, { 58, 37, 46 }, 0 },
{ { 151, 93, 6 }, { 187, 96, -27 }, { 58, 37, 46 }, 0 },
{ { 159, 83, 16 }, { 187, 96, -28 }, { 58, 37, 46 }, 0 },
{ { 170, 73, 16 }, { 187, 96, -29 }, { 182, 96, 48 }, 3 },
{ { 176, 69, 13 }, { 187, 96, -31 }, { 182, 94, 49 }, 1 },
{ { 168, 66, 13 }, { 187, 98, -32 }, { 182, 92, 50 }, 0 },
{ { 155, 75, 13 }, { 187, 96, -32 }, { 182, 88, 51 }, 3 },
{ { 145, 86, 13 }, { 187, 98, -32 }, { 182, 85, 52 }, 0 },
{ { 127, 104, 13 }, { 187, 98, -32 }, { 182, 25, 52 }, 1 },
{ { 122, 108, 13 }, { 187, 98, -32 }, { 182, 25, 52 }, 1 },
{ { 120, 104, 14 }, { 187, 96, -34 }, { 107, 145, 42 }, 2 },
{ { 111, 103, 13 }, { 187, 96, -23 }, { 107, 144, 43 }, 0 },
{ { 102, 105, 13 }, { 187, 96, -23 }, { 107, 142, 43 }, 0 },
{ { 97, 107, 13 }, { 187, 96, -23 }, { 107, 139, 44 }, 0 },
{ { 92, 101, 14 }, { 187, 96, -23 }, { 107, 34, 47 }, 3 },
{ { 90, 105, 14 }, { 187, 96, -23 }, { 107, 34, 47 }, 0 },
{ { 88, 104, 14 }, { 187, 96, -23 }, { 107, 34, 47 }, 0 },
{ { 87, 105, 14 }, { 187, 96, -23 }, { 107, 34, 47 }, 0 },
{ { 86, 105, 14 }, { 187, 96, -23 }, { 107, 34, 47 }, 0 },
{ { 86, 105, 14 }, { 187, 96, -23 }, { 107, 34, 47 }, 0 },
{ { 86, 105, 15 }, { 187, 96, -23 }, { 0, 0, 0 }, 0 },
{ { 85, 98, 16 }, { 187, 96, -23 }, { 0, 0, 0 }, 0 },
{ { 92, 96, 1 }, { 187, 96, -23 }, { 0, 0, 0 }, 0 },
{ { 92, 96, 1 }, { 187, 96, -23 }, { 0, 0, 0 }, 0 },
{ { 89, 96, 4 }, { 187, 96, -23 }, { 0, 0, 0 }, 0 },
{ { 86, 96, 3 }, { 187, 96, -23 }, { 0, 0, 0 }, 0 },
{ { 83, 96, 2 }, { 187, 96, -23 }, { 0, 0, 0 }, 0 },
{ { 81, 96, 1 }, { 187, 96, -23 }, { 0, 0, 0 }, 0 },
{ { 78, 96, 4 }, { 187, 96, -23 }, { 0, 0, 0 }, 0 },
{ { 75, 96, 3 }, { 187, 96, -23 }, { 0, 0, 0 }, 0 },
{ { 75, 96, 1 }, { 187, 96, -23 }, { 0, 0, 0 }, 0 },
{ { 75, 96, 1 }, { 187, 96, -23 }, { 0, 0, 0 }, 99 }
};
const BamScene::BamDataBlock BamScene::_fight2Data[] = {
{ { 75, 96, 1 }, { 187, 96, -23 }, { 150, 45, 35 }, 0 },
{ { 78, 96, 2 }, { 187, 96, -23 }, { 150, 45, 35 }, 0 },
{ { 81, 96, 3 }, { 189, 96, -18 }, { 150, 45, 35 }, 0 },
{ { 84, 96, 4 }, { 183, 96, -19 }, { 150, 45, 35 }, 0 },
{ { 87, 96, 1 }, { 181, 96, -20 }, { 150, 45, 35 }, 0 },
{ { 90, 96, 2 }, { 177, 96, -21 }, { 150, 45, 35 }, 0 },
{ { 93, 96, 3 }, { 171, 96, -22 }, { 150, 45, 35 }, 0 },
{ { 96, 96, 4 }, { 169, 96, -17 }, { 150, 45, 35 }, 0 },
{ { 99, 96, 1 }, { 165, 96, -18 }, { 150, 45, 35 }, 0 },
{ { 102, 96, 2 }, { 159, 96, -19 }, { 150, 45, 35 }, 0 },
{ { 105, 96, 3 }, { 157, 96, -20 }, { 150, 45, 35 }, 0 },
{ { 108, 96, 4 }, { 153, 96, -21 }, { 150, 45, 35 }, 0 },
{ { 111, 96, 1 }, { 147, 96, -22 }, { 150, 45, 35 }, 0 },
{ { 114, 96, 2 }, { 147, 96, -23 }, { 150, 45, 35 }, 0 },
{ { 117, 96, 3 }, { 147, 96, -23 }, { 150, 45, 35 }, 0 },
{ { 120, 96, 4 }, { 147, 96, -24 }, { 150, 45, 35 }, 0 },
{ { 123, 96, 1 }, { 147, 96, -25 }, { 150, 45, 35 }, 0 },
{ { 125, 96, 2 }, { 147, 96, -25 }, { 150, 45, 35 }, 0 },
{ { 127, 96, 12 }, { 147, 96, -69 }, { 122, 94, 36 }, 3 },
{ { 127, 95, 11 }, { 147, 96, -70 }, { 122, 94, 41 }, 0 },
{ { 127, 96, 12 }, { 147, 96, -71 }, { 122, 100, 36 }, 3 },
{ { 127, 97, 11 }, { 147, 96, -69 }, { 122, 100, 41 }, 0 },
{ { 127, 96, 12 }, { 147, 96, -70 }, { 127, 103, 36 }, 3 },
{ { 127, 95, 11 }, { 147, 96, -71 }, { 127, 103, 41 }, 0 },
{ { 127, 94, 12 }, { 147, 96, -69 }, { 123, 94, 36 }, 3 },
{ { 127, 95, 11 }, { 147, 96, -70 }, { 123, 94, 41 }, 0 },
{ { 127, 96, 12 }, { 147, 96, -71 }, { 120, 99, 36 }, 3 },
{ { 127, 96, 12 }, { 147, 96, -71 }, { 115, 98, 41 }, 0 },
{ { 117, 93, 11 }, { 147, 96, -25 }, { 115, 134, 42 }, 0 },
{ { 110, 92, 11 }, { 147, 96, -25 }, { 114, 133, 42 }, 0 },
{ { 102, 93, 11 }, { 147, 96, -25 }, { 114, 131, 43 }, 0 },
{ { 92, 93, 11 }, { 147, 96, -25 }, { 114, 130, 43 }, 0 },
{ { 82, 94, 11 }, { 147, 96, -25 }, { 114, 128, 44 }, 0 },
{ { 76, 95, 11 }, { 147, 96, -25 }, { 114, 127, 44 }, 0 },
{ { 70, 96, 11 }, { 147, 96, -25 }, { 114, 126, 45 }, 0 },
{ { 75, 96, 5 }, { 147, 96, -25 }, { 114, 125, 46 }, 1 },
{ { 75, 96, 6 }, { 147, 96, -25 }, { 114, 43, 46 }, 0 },
{ { 75, 96, 6 }, { 147, 96, -25 }, { 114, 43, 46 }, 0 },
{ { 75, 96, 5 }, { 147, 96, -25 }, { 114, 43, 46 }, 0 },
{ { 75, 96, 7 }, { 147, 96, -25 }, { 114, 43, 46 }, 0 },
{ { 75, 96, 68 }, { 147, 96, -25 }, { 114, 43, 46 }, 0 },
{ { 75, 96, 68 }, { 147, 96, -25 }, { 89, 104, 36 }, 2 },
{ { 75, 96, 68 }, { 147, 96, -25 }, { 94, 103, 62 }, 0 },
{ { 75, 96, 68 }, { 147, 96, -25 }, { 122, 103, 63 }, 0 },
{ { 75, 96, 68 }, { 147, 96, -25 }, { 141, 103, 64 }, 0 },
{ { 75, 96, 68 }, { 147, 96, -30 }, { 150, 103, 65 }, 3 },
{ { 75, 96, 68 }, { 156, 96, -30 }, { 160, 103, 66 }, 0 },
{ { 75, 96, 7 }, { 164, 96, -30 }, { 169, 103, 67 }, 0 },
{ { 75, 96, 5 }, { 169, 96, -30 }, { 177, 103, 48 }, 3 },
{ { 75, 96, 5 }, { 173, 96, -30 }, { 185, 103, 49 }, 0 },
{ { 75, 96, 6 }, { 178, 96, -30 }, { 198, 103, 50 }, 0 },
{ { 75, 96, 6 }, { 181, 96, -30 }, { 207, 103, 51 }, 1 },
{ { 75, 96, 5 }, { 184, 96, -30 }, { 221, 103, 52 }, 0 },
{ { 75, 96, 5 }, { 186, 96, -30 }, { 224, 53, 53 }, 0 },
{ { 75, 96, 5 }, { 187, 96, -23 }, { 224, 53, 53 }, 99 }
};
const BamScene::BamDataBlock BamScene::_fight3Data[] = {
{ { 75, 96, 1 }, { 187, 96, -23 }, { 150, 45, 35 }, 0 },
{ { 77, 96, 2 }, { 187, 96, -22 }, { 150, 45, 35 }, 0 },
{ { 80, 96, 3 }, { 185, 96, -17 }, { 150, 45, 35 }, 0 },
{ { 83, 96, 4 }, { 181, 96, -18 }, { 150, 45, 35 }, 0 },
{ { 86, 96, 1 }, { 175, 96, -19 }, { 150, 45, 35 }, 0 },
{ { 88, 96, 2 }, { 173, 96, -20 }, { 150, 45, 35 }, 0 },
{ { 91, 96, 3 }, { 169, 96, -21 }, { 150, 45, 35 }, 0 },
{ { 94, 96, 4 }, { 163, 96, -22 }, { 150, 45, 35 }, 0 },
{ { 97, 96, 1 }, { 161, 96, -17 }, { 150, 45, 35 }, 0 },
{ { 99, 96, 2 }, { 157, 96, -18 }, { 150, 45, 35 }, 0 },
{ { 102, 96, 3 }, { 151, 96, -19 }, { 150, 45, 35 }, 0 },
{ { 105, 96, 4 }, { 149, 96, -20 }, { 150, 45, 35 }, 0 },
{ { 108, 96, 1 }, { 145, 96, -21 }, { 150, 45, 35 }, 0 },
{ { 110, 96, 2 }, { 145, 96, -25 }, { 150, 45, 35 }, 0 },
{ { 113, 96, 3 }, { 145, 96, -26 }, { 132, 96, 36 }, 2 },
{ { 117, 96, 7 }, { 145, 96, -27 }, { 122, 97, 36 }, 0 },
{ { 117, 96, 7 }, { 145, 96, -28 }, { 117, 97, 37 }, 0 },
{ { 116, 96, 12 }, { 145, 96, -24 }, { 110, 96, 38 }, 3 },
{ { 109, 96, 12 }, { 145, 96, -24 }, { 103, 95, 39 }, 0 },
{ { 105, 96, 12 }, { 145, 96, -24 }, { 95, 90, 40 }, 1 },
{ { 96, 96, 11 }, { 145, 96, -24 }, { 86, 80, 41 }, 0 },
{ { 92, 96, 11 }, { 145, 96, -24 }, { 86, 80, 41 }, 0 },
{ { 93, 96, 5 }, { 145, 96, -24 }, { 86, 38, 41 }, 0 },
{ { 91, 96, 5 }, { 145, 96, -24 }, { 86, 38, 41 }, 0 },
{ { 89, 96, 5 }, { 145, 96, -24 }, { 86, 38, 41 }, 0 },
{ { 88, 96, 5 }, { 145, 96, -24 }, { 86, 38, 41 }, 0 },
{ { 87, 96, 6 }, { 145, 96, -24 }, { 86, 38, 41 }, 0 },
{ { 87, 96, 6 }, { 145, 96, -23 }, { 86, 38, 41 }, 0 },
{ { 87, 96, 6 }, { 145, 96, -23 }, { 86, 38, 41 }, 0 },
{ { 87, 96, 5 }, { 145, 96, -23 }, { 86, 38, 41 }, 0 },
{ { 87, 96, 5 }, { 145, 96, -23 }, { 86, 38, 41 }, 0 },
{ { 87, 96, 6 }, { 145, 96, -23 }, { 86, 38, 41 }, 0 },
{ { 87, 96, 6 }, { 145, 96, -23 }, { 86, 38, 41 }, 0 },
{ { 87, 96, 5 }, { 145, 96, -23 }, { 86, 38, 41 }, 0 },
{ { 87, 96, 5 }, { 145, 96, -23 }, { 86, 38, 41 }, 0 },
{ { 87, 96, 6 }, { 145, 96, -23 }, { 86, 38, 41 }, 0 },
{ { 87, 96, 6 }, { 145, 96, -26 }, { 86, 38, 41 }, 0 },
{ { 87, 96, 6 }, { 145, 96, -27 }, { 132, 97, 36 }, 2 },
{ { 87, 96, 5 }, { 145, 96, -28 }, { 118, 97, 36 }, 0 },
{ { 87, 96, 7 }, { 145, 96, -24 }, { 107, 97, 36 }, 0 },
{ { 87, 96, 8 }, { 145, 96, -24 }, { 101, 97, 36 }, 0 },
{ { 87, 96, 9 }, { 145, 96, -23 }, { 102, 97, 66 }, 3 },
{ { 87, 96, 10 }, { 145, 96, -23 }, { 120, 97, 67 }, 0 },
{ { 87, 96, 10 }, { 145, 96, -30 }, { 139, 97, 67 }, 1 },
{ { 87, 96, 7 }, { 146, 96, -30 }, { 144, 97, 62 }, 2 },
{ { 86, 96, 4 }, { 160, 96, -30 }, { 144, 97, 48 }, 1 },
{ { 83, 96, 3 }, { 170, 96, -31 }, { 154, 93, 49 }, 0 },
{ { 80, 96, 2 }, { 174, 96, -31 }, { 161, 89, 50 }, 0 },
{ { 78, 96, 1 }, { 178, 99, -31 }, { 169, 85, 51 }, 0 },
{ { 75, 96, 4 }, { 183, 104, -31 }, { 175, 79, 52 }, 0 },
{ { 75, 96, 1 }, { 185, 99, -32 }, { 180, 144, 42 }, 3 },
{ { 75, 96, 1 }, { 185, 106, -31 }, { 181, 141, 42 }, 0 },
{ { 75, 96, 5 }, { 185, 104, -31 }, { 181, 138, 43 }, 0 },
{ { 75, 96, 5 }, { 188, 106, -31 }, { 182, 135, 43 }, 0 },
{ { 75, 96, 6 }, { 191, 99, -32 }, { 183, 131, 44 }, 3 },
{ { 75, 96, 6 }, { 191, 99, -32 }, { 183, 127, 45 }, 0 },
{ { 75, 96, 5 }, { 191, 99, -32 }, { 184, 121, 46 }, 0 },
{ { 75, 96, 5 }, { 191, 99, -32 }, { 183, 115, 46 }, 0 },
{ { 75, 96, 6 }, { 191, 99, -32 }, { 183, 41, 47 }, 0 },
{ { 75, 96, 6 }, { 191, 99, -32 }, { 183, 41, 47 }, 0 },
{ { 75, 96, 6 }, { 191, 99, -32 }, { 183, 41, 47 }, 0 },
{ { 75, 96, 5 }, { 191, 99, -32 }, { 183, 41, 47 }, 0 },
{ { 75, 96, 5 }, { 191, 99, -32 }, { 183, 41, 47 }, 0 },
{ { 75, 96, 5 }, { 191, 99, -32 }, { 183, 41, 47 }, 0 },
{ { 75, 96, 5 }, { 191, 99, -32 }, { 183, 41, 47 }, 0 },
{ { 75, 96, 5 }, { 191, 99, -32 }, { 183, 41, 47 }, 0 },
{ { 75, 96, 6 }, { 191, 99, -32 }, { 183, 41, 47 }, 0 },
{ { 75, 96, 6 }, { 191, 99, -32 }, { 183, 41, 47 }, 0 },
{ { 75, 96, 5 }, { 195, 98, -33 }, { 183, 41, 47 }, 0 },
{ { 75, 96, 6 }, { 191, 96, -34 }, { 183, 41, 47 }, 0 },
{ { 75, 96, 6 }, { 193, 96, -25 }, { 183, 41, 47 }, 0 },
{ { 75, 96, 5 }, { 193, 96, -24 }, { 183, 41, 47 }, 0 },
{ { 75, 96, 5 }, { 193, 96, -24 }, { 183, 41, 47 }, 0 },
{ { 75, 96, 5 }, { 193, 96, -24 }, { 183, 41, 47 }, 0 },
{ { 75, 96, 6 }, { 191, 96, -18 }, { 183, 41, 47 }, 0 },
{ { 75, 96, 6 }, { 190, 96, -19 }, { 183, 41, 47 }, 0 },
{ { 75, 96, 6 }, { 187, 96, -20 }, { 183, 41, 47 }, 0 },
{ { 75, 96, 1 }, { 187, 96, -23 }, { 183, 41, 47 }, 0 },
{ { 75, 96, 1 }, { 187, 96, -23 }, { 183, 41, 47 }, 99 }
};
#endif
} // End of namespace Queen
#ifdef __PALM_OS__
#include "scumm_globals.h"
_GINIT(Queen_Graphics)
_GSETPTR(Queen::_carData, GBVARS_GRAPHICSCARDATA_INDEX, Queen::BamScene::BamDataBlock, GBVARS_QUEEN)
_GSETPTR(Queen::_fight1Data, GBVARS_GRAPHICSFIGHT1DATA_INDEX, Queen::BamScene::BamDataBlock, GBVARS_QUEEN)
_GSETPTR(Queen::_fight2Data, GBVARS_GRAPHICSFIGHT2DATA_INDEX, Queen::BamScene::BamDataBlock, GBVARS_QUEEN)
_GSETPTR(Queen::_fight3Data, GBVARS_GRAPHICSFIGHT3DATA_INDEX, Queen::BamScene::BamDataBlock, GBVARS_QUEEN)
_GEND
_GRELEASE(Queen_Graphics)
_GRELEASEPTR(GBVARS_GRAPHICSCARDATA_INDEX, GBVARS_QUEEN)
_GRELEASEPTR(GBVARS_GRAPHICSFIGHT1DATA_INDEX, GBVARS_QUEEN)
_GRELEASEPTR(GBVARS_GRAPHICSFIGHT2DATA_INDEX, GBVARS_QUEEN)
_GRELEASEPTR(GBVARS_GRAPHICSFIGHT3DATA_INDEX, GBVARS_QUEEN)
_GEND
#endif