Logo Search packages:      
Sourcecode: scummvm version File versions

graphics.cpp

/* 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: /cvsroot/scummvm/scummvm/queen/graphics.cpp,v 1.109 2004/12/03 22:39:54 cyx Exp $
 *
 */

#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;
}

static int compareBobDrawOrder(const void *a, const void *b) {
      const BobSlot *bob1 = *(const BobSlot * const *)a;
      const BobSlot *bob2 = *(const BobSlot * const *)b;
      int d = bob1->y - bob2->y;
      // As the qsort() function may reorder "equal" elements,
      // we use the bob slot number when needed. This is required 
      // during the introduction, to hide a crate behind the clock.
      if (d == 0) {
            d = bob1 - bob2;
      }
      return d;
}

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();
                        }
                  }
            }
      }
      qsort(_sortedBobs, _sortedBobsCount, sizeof(BobSlot *), compareBobDrawOrder);
}

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 = FRAMES_JOE + 1;
      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 = FRAMES_JOE;

      // 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 = FRAMES_JOE + _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() {
      static const BamDataBlock *fightDataBlocks[] = {
            _fight1Data,
            _fight2Data,
            _fight3Data
      };
      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;
                  _fightData = fightDataBlocks[_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

Generated by  Doxygen 1.6.0   Back to index