aboutsummaryrefslogtreecommitdiff
path: root/engines/scumm/he/sprite_he.cpp
diff options
context:
space:
mode:
authorEugene Sandulenko2006-02-15 00:57:50 +0000
committerEugene Sandulenko2006-02-15 00:57:50 +0000
commit10c7835cfcdd8f0eb1eadf52ac9cfd39d2d6be61 (patch)
treedc3e12a02eb6befdf76c5fc0110f4cd9be82f569 /engines/scumm/he/sprite_he.cpp
parent0bea9cf47b027ad8936751f48779046ca0a48bf9 (diff)
downloadscummvm-rg350-10c7835cfcdd8f0eb1eadf52ac9cfd39d2d6be61.tar.gz
scummvm-rg350-10c7835cfcdd8f0eb1eadf52ac9cfd39d2d6be61.tar.bz2
scummvm-rg350-10c7835cfcdd8f0eb1eadf52ac9cfd39d2d6be61.zip
Moved all he-specific source files to engines/scumm/he/ subdirectory
svn-id: r20696
Diffstat (limited to 'engines/scumm/he/sprite_he.cpp')
-rw-r--r--engines/scumm/he/sprite_he.cpp1440
1 files changed, 1440 insertions, 0 deletions
diff --git a/engines/scumm/he/sprite_he.cpp b/engines/scumm/he/sprite_he.cpp
new file mode 100644
index 0000000000..7de5f0742a
--- /dev/null
+++ b/engines/scumm/he/sprite_he.cpp
@@ -0,0 +1,1440 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001 Ludvig Strigeus
+ * Copyright (C) 2001-2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/stdafx.h"
+
+#include "scumm/he/intern_he.h"
+#include "scumm/resource.h"
+#include "scumm/saveload.h"
+#include "scumm/scumm.h"
+#include "scumm/he/sprite_he.h"
+#include "scumm/usage_bits.h"
+#include "scumm/util.h"
+#include "scumm/he/wiz_he.h"
+
+namespace Scumm {
+
+Sprite::Sprite(ScummEngine_v90he *vm) : _vm(vm) {
+}
+
+Sprite::~Sprite() {
+ free(_spriteGroups);
+ free(_spriteTable);
+ free(_activeSpritesTable);
+}
+
+void ScummEngine_v90he::allocateArrays() {
+ ScummEngine::allocateArrays();
+ _sprite->allocTables(_numSprites, MAX(64, _numSprites / 4), 64);
+}
+
+void Sprite::getSpriteBounds(int spriteId, bool checkGroup, Common::Rect &bound) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+ int32 spr_wiz_x, spr_wiz_y;
+ int angle, scale, x1, y1;
+ int32 w, h;
+
+ SpriteInfo *spi = &_spriteTable[spriteId];
+
+ _vm->_wiz->getWizImageSpot(spi->image, spi->imageState, spr_wiz_x, spr_wiz_y);
+ if (checkGroup && spi->group) {
+ SpriteGroup *spg = &_spriteGroups[spi->group];
+
+ if (spg->scaling) {
+ x1 = spi->tx * spg->scale_x_ratio_mul / spg->scale_x_ratio_div - spr_wiz_x + spg->tx;
+ y1 = spi->ty * spg->scale_y_ratio_mul / spg->scale_y_ratio_div - spr_wiz_y + spg->ty;
+ } else {
+ x1 = spi->tx - spr_wiz_x + spg->tx;
+ y1 = spi->ty - spr_wiz_y + spg->ty;
+ }
+ } else {
+ x1 = spi->tx - spr_wiz_x;
+ y1 = spi->ty - spr_wiz_y;
+ }
+
+ if (spi->image) {
+ angle = spi->angle;
+ scale = spi->scale;
+ _vm->_wiz->getWizImageDim(spi->image, spi->imageState, w, h);
+ if (spi->flags & (kSFScaled | kSFRotated)) {
+ Common::Point pts[4];
+ _vm->_wiz->polygonTransform(spi->image, spi->imageState, x1, y1, angle, scale, pts);
+ _vm->_wiz->polygonCalcBoundBox(pts, 4, bound);
+ } else {
+ bound.left = x1;
+ bound.top = y1;
+ bound.right = x1 + w;
+ bound.bottom = y1 + h;
+ }
+ } else {
+ bound.left = 1234;
+ bound.top = 1234;
+ bound.right = -1234;
+ bound.bottom = -1234;
+ }
+}
+
+//
+// spriteInfoGet functions
+//
+int Sprite::findSpriteWithClassOf(int x_pos, int y_pos, int spriteGroupId, int type, int num, int *args) {
+ debug(2, "findSprite: x %d, y %d, spriteGroup %d, type %d, num %d", x_pos, y_pos, spriteGroupId, type, num);
+ Common::Point pos[1];
+ bool cond;
+ int code, classId;
+
+ for (int i = (_numSpritesToProcess - 1); i >= 0; i--) {
+ SpriteInfo *spi = _activeSpritesTable[i];
+ if (!spi->curImage)
+ continue;
+
+ if (spriteGroupId && spi->group != spriteGroupId)
+ continue;
+
+ cond = true;
+ for (int j = 0; j < num; j++) {
+ code = classId = args[j];
+ classId &= 0x7F;
+ checkRange(32, 1, classId, "class %d out of range in statement");
+ if (code & 0x80) {
+ if (!(spi->classFlags & (1 << (classId - 1))))
+ cond = 0;
+ } else {
+ if ((spi->classFlags & (1 << (classId - 1))))
+ cond = 0;
+ }
+ }
+ if (!cond)
+ continue;
+
+ if (type) {
+ if (spi->bbox.left > spi->bbox.right)
+ continue;
+ if (spi->bbox.top > spi->bbox.bottom)
+ continue;
+ if (spi->bbox.left > x_pos)
+ continue;
+ if (spi->bbox.top > y_pos)
+ continue;
+ if (spi->bbox.right < x_pos)
+ continue;
+ if (spi->bbox.bottom < y_pos)
+ continue;
+ return spi->id;
+ } else {
+ int image, imageState, angle, scale;
+ int32 w, h;
+
+ image = spi->curImage;
+ if (spi->maskImage) {
+ int32 x1, x2, y1, y2;
+
+ imageState = spi->curImageState % _vm->_wiz->getWizImageStates(spi->maskImage);
+
+ pos[0].x = x_pos - spi->pos.x;
+ pos[0].y = y_pos - spi->pos.y;
+
+ _vm->_wiz->getWizImageSpot(spi->curImage, imageState, x1, y1);
+ _vm->_wiz->getWizImageSpot(spi->maskImage, imageState, x2, y2);
+
+ pos[0].x += (x2 - x1);
+ pos[0].y += (y2 - y1);
+ } else {
+ if (spi->bbox.left > spi->bbox.right)
+ continue;
+ if (spi->bbox.top > spi->bbox.bottom)
+ continue;
+ if (spi->bbox.left > x_pos)
+ continue;
+ if (spi->bbox.top > y_pos)
+ continue;
+ if (spi->bbox.right < x_pos)
+ continue;
+ if (spi->bbox.bottom < y_pos)
+ continue;
+
+ pos[0].x = x_pos - spi->pos.x;
+ pos[0].y = y_pos - spi->pos.y;
+ imageState = spi->curImageState;
+ }
+
+ angle = spi->curAngle;
+ scale = spi->curScale;
+ if ((spi->flags & kSFScaled) || (spi->flags & kSFRotated)) {
+ if (spi->flags & kSFScaled && scale) {
+ pos[0].x = pos[0].x * 256 / scale;
+ pos[0].y = pos[0].y * 256 / scale;
+ }
+ if (spi->flags & kSFRotated && angle) {
+ angle = (360 - angle) % 360;
+ _vm->_wiz->polygonRotatePoints(pos, 1, angle);
+ }
+
+ _vm->_wiz->getWizImageDim(image, imageState, w, h);
+ pos[0].x += w / 2;
+ pos[0].y += h / 2;
+ }
+
+ if (_vm->_wiz->isWizPixelNonTransparent(image, imageState, pos[0].x, pos[0].y, spi->curImgFlags))
+ return spi->id;
+ }
+ }
+
+ return 0;
+}
+
+int Sprite::getSpriteClass(int spriteId, int num, int *args) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+ int code, classId;
+
+ if (num == 0)
+ return _spriteTable[spriteId].classFlags;
+
+ for (int i = 0; i < num; i++) {
+ code = classId = args[i];
+ classId &= 0x7F;
+ checkRange(32, 1, classId, "class %d out of range in statement");
+ if (code & 0x80) {
+ if (!(_spriteTable[spriteId].classFlags & (1 << (classId - 1))))
+ return 0;
+ } else {
+ if ((_spriteTable[spriteId].classFlags & (1 << (classId - 1))))
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+int Sprite::getSpriteFlagDoubleBuffered(int spriteId) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ return ((_spriteTable[spriteId].flags & kSFDoubleBuffered) != 0) ? 1 : 0;
+}
+
+int Sprite::getSpriteFlagYFlipped(int spriteId) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ return ((_spriteTable[spriteId].flags & kSFYFlipped) != 0) ? 1 : 0;
+}
+
+int Sprite::getSpriteFlagXFlipped(int spriteId) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ return ((_spriteTable[spriteId].flags & kSFXFlipped) != 0) ? 1 : 0;
+}
+
+int Sprite::getSpriteFlagActive(int spriteId) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ return ((_spriteTable[spriteId].flags & kSFActive) != 0) ? 1 : 0;
+}
+
+int Sprite::getSpriteFlagRemapPalette(int spriteId) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ return ((_spriteTable[spriteId].flags & kSFRemapPalette) != 0) ? 1 : 0;
+}
+
+int Sprite::getSpriteFlagAutoAnim(int spriteId) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ return ((_spriteTable[spriteId].flags & kSFAutoAnim) != 0) ? 1 : 0;
+}
+
+int Sprite::getSpriteFlagUpdateType(int spriteId) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ return ((_spriteTable[spriteId].flags & kSFMarkDirty) != 0) ? 1 : 0;
+}
+
+int Sprite::getSpriteFlagEraseType(int spriteId) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ return ((_spriteTable[spriteId].flags & kSFImageless) != 0) ? 1 : 0;
+}
+
+int Sprite::getSpriteImage(int spriteId) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ return _spriteTable[spriteId].image;
+}
+
+int Sprite::getSpriteImageState(int spriteId) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ return _spriteTable[spriteId].imageState;
+}
+
+int Sprite::getSpriteGroup(int spriteId) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ return _spriteTable[spriteId].group;
+}
+
+int Sprite::getSpritePalette(int spriteId) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ return _spriteTable[spriteId].palette;
+}
+
+int Sprite::getSpritePriority(int spriteId) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ return _spriteTable[spriteId].priority;
+}
+
+int Sprite::getSpriteDisplayX(int spriteId) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ if (_spriteTable[spriteId].group)
+ return _spriteTable[spriteId].tx + _spriteGroups[_spriteTable[spriteId].group].tx;
+ else
+ return _spriteTable[spriteId].tx;
+}
+
+int Sprite::getSpriteDisplayY(int spriteId) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ if (_spriteTable[spriteId].group)
+ return _spriteTable[spriteId].ty + _spriteGroups[_spriteTable[spriteId].group].ty;
+ else
+ return _spriteTable[spriteId].ty;
+}
+
+int Sprite::getSpriteUserValue(int spriteId) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ return _spriteTable[spriteId].userValue;
+}
+
+int Sprite::getSpriteShadow(int spriteId) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ return _spriteTable[spriteId].shadow;
+}
+
+int Sprite::getSpriteImageStateCount(int spriteId) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ return _spriteTable[spriteId].imageStateCount;
+}
+
+int Sprite::getSpriteScale(int spriteId) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ return _spriteTable[spriteId].scale;
+}
+
+int Sprite::getSpriteAnimSpeed(int spriteId) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ return _spriteTable[spriteId].animSpeed;
+}
+
+int Sprite::getSpriteSourceImage(int spriteId) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ return _spriteTable[spriteId].sourceImage;
+}
+
+int Sprite::getSpriteMaskImage(int spriteId) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ return _spriteTable[spriteId].maskImage;
+}
+
+int Sprite::getSpriteGeneralProperty(int spriteId, int type) {
+ debug(0, "getSpriteGeneralProperty: spriteId %d type 0x%x", spriteId, type);
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ // XXX U32 related check
+
+ switch(type) {
+ case 0x7B:
+ return _spriteTable[spriteId].imgFlags;
+ case 0x7D:
+ return _spriteTable[spriteId].field_90;
+ case 0x7E:
+ return _spriteTable[spriteId].animProgress;
+ default:
+ error("getSpriteGeneralProperty: Invalid type %d", type);
+ }
+}
+
+void Sprite::getSpriteImageDim(int spriteId, int32 &w, int32 &h) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ if (_spriteTable[spriteId].image) {
+ _vm->_wiz->getWizImageDim(_spriteTable[spriteId].image, _spriteTable[spriteId].imageState, w, h);
+ } else {
+ w = 0;
+ h = 0;
+ }
+}
+
+void Sprite::getSpritePosition(int spriteId, int32 &tx, int32 &ty) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ tx = _spriteTable[spriteId].tx;
+ ty = _spriteTable[spriteId].ty;
+}
+
+void Sprite::getSpriteDist(int spriteId, int32 &dx, int32 &dy) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ dx = _spriteTable[spriteId].dx;
+ dy = _spriteTable[spriteId].dy;
+}
+
+//
+// spriteGroupGet functions
+//
+int ScummEngine_v90he::getGroupSpriteArray(int spriteGroupId) {
+ int i, numSprites = 0;
+
+ checkRange(_sprite->_varNumSpriteGroups, 1, spriteGroupId, "Invalid sprite group %d");
+
+ for (i = (_sprite->_varNumSprites - 1); i > 0; i--) {
+ if (_sprite->_spriteTable[i].group == spriteGroupId)
+ numSprites++;
+ }
+
+ if (!numSprites)
+ return 0;
+
+ writeVar(0, 0);
+ defineArray(0, kDwordArray, 0, 0, 0, numSprites);
+ writeArray(0, 0, 0, numSprites);
+
+ numSprites = 1;
+ for (i = (_sprite->_varNumSprites - 1); i > 0; i--) {
+ if (_sprite->_spriteTable[i].group == spriteGroupId) {
+ writeArray(0, 0, numSprites, i);
+ numSprites++;
+ }
+ }
+
+ return readVar(0);
+}
+
+int Sprite::getGroupPriority(int spriteGroupId) {
+ checkRange(_varNumSpriteGroups, 1, spriteGroupId, "Invalid sprite group %d");
+
+ return _spriteGroups[spriteGroupId].priority;
+}
+
+int Sprite::getGroupDstResNum(int spriteGroupId) {
+ checkRange(_varNumSpriteGroups, 1, spriteGroupId, "Invalid sprite group %d");
+
+ return _spriteGroups[spriteGroupId].image;
+}
+
+int Sprite::getGroupXMul(int spriteGroupId) {
+ checkRange(_varNumSpriteGroups, 1, spriteGroupId, "Invalid sprite group %d");
+
+ return _spriteGroups[spriteGroupId].scale_x_ratio_mul;
+}
+
+int Sprite::getGroupXDiv(int spriteGroupId) {
+ checkRange(_varNumSpriteGroups, 1, spriteGroupId, "Invalid sprite group %d");
+
+ return _spriteGroups[spriteGroupId].scale_x_ratio_div;
+}
+
+int Sprite::getGroupYMul(int spriteGroupId) {
+ checkRange(_varNumSpriteGroups, 1, spriteGroupId, "Invalid sprite group %d");
+
+ return _spriteGroups[spriteGroupId].scale_y_ratio_mul;
+}
+
+int Sprite::getGroupYDiv(int spriteGroupId) {
+ checkRange(_varNumSpriteGroups, 1, spriteGroupId, "Invalid sprite group %d");
+
+ return _spriteGroups[spriteGroupId].scale_y_ratio_div;
+}
+
+void Sprite::getGroupPosition(int spriteGroupId, int32 &tx, int32 &ty) {
+ checkRange(_varNumSpriteGroups, 1, spriteGroupId, "Invalid sprite group %d");
+
+ tx = _spriteGroups[spriteGroupId].tx;
+ ty = _spriteGroups[spriteGroupId].ty;
+}
+
+//
+// spriteInfoSet functions
+//
+void Sprite::setSpritePalette(int spriteId, int value) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ if (_spriteTable[spriteId].palette != value) {
+ _spriteTable[spriteId].palette = value;
+ _spriteTable[spriteId].flags |= kSFChanged | kSFNeedRedraw;
+ }
+}
+
+void Sprite::setSpriteSourceImage(int spriteId, int value) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ if (_spriteTable[spriteId].sourceImage != value) {
+ _spriteTable[spriteId].sourceImage = value;
+ _spriteTable[spriteId].flags |= kSFChanged | kSFNeedRedraw;
+ }
+}
+
+void Sprite::setSpriteMaskImage(int spriteId, int value) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ _spriteTable[spriteId].maskImage = value;
+}
+
+void Sprite::setSpriteImageState(int spriteId, int state) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ if (_spriteTable[spriteId].image) {
+ int imageStateCount = _spriteTable[spriteId].imageStateCount - 1;
+ state = MAX(0, state);
+ state = MIN(state, imageStateCount);
+
+ if (_spriteTable[spriteId].imageState != state) {
+ _spriteTable[spriteId].imageState = state;
+ _spriteTable[spriteId].flags |= kSFChanged | kSFNeedRedraw;
+ }
+ }
+}
+
+void Sprite::setSpritePosition(int spriteId, int tx, int ty) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ if (_spriteTable[spriteId].tx != tx || _spriteTable[spriteId].ty != ty) {
+ _spriteTable[spriteId].tx = tx;
+ _spriteTable[spriteId].ty = ty;
+ _spriteTable[spriteId].flags |= kSFChanged | kSFNeedRedraw;
+ }
+}
+
+void Sprite::setSpriteGroup(int spriteId, int value) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+ checkRange(_varNumSpriteGroups, 0, value, "Invalid sprite group %d");
+
+ _spriteTable[spriteId].group = value;
+ _spriteTable[spriteId].flags |= kSFChanged | kSFNeedRedraw;
+}
+
+void Sprite::setSpriteDist(int spriteId, int value1, int value2) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ _spriteTable[spriteId].dx = value1;
+ _spriteTable[spriteId].dy = value2;
+}
+
+void Sprite::setSpriteShadow(int spriteId, int value) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ _spriteTable[spriteId].shadow = value;
+ if (_spriteTable[spriteId].image)
+ _spriteTable[spriteId].flags |= kSFChanged | kSFNeedRedraw;
+}
+
+void Sprite::setSpriteUserValue(int spriteId, int value1, int value2) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ _spriteTable[spriteId].userValue = value2;
+}
+
+void Sprite::setSpritePriority(int spriteId, int value) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ _spriteTable[spriteId].priority = value;
+}
+
+void Sprite::moveSprite(int spriteId, int value1, int value2) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ _spriteTable[spriteId].tx += value1;
+ _spriteTable[spriteId].ty += value2;
+
+ if (value1 || value2)
+ _spriteTable[spriteId].flags |= kSFChanged | kSFNeedRedraw;
+}
+
+void Sprite::setSpriteScale(int spriteId, int value) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ _spriteTable[spriteId].flags |= kSFScaled;
+
+ if (_spriteTable[spriteId].scale != value) {
+ _spriteTable[spriteId].scale = value;
+
+ if (_spriteTable[spriteId].image)
+ _spriteTable[spriteId].flags |= kSFChanged | kSFNeedRedraw;
+ }
+}
+
+void Sprite::setSpriteAngle(int spriteId, int value) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ _spriteTable[spriteId].flags |= kSFRotated;
+
+ if (_spriteTable[spriteId].angle != value) {
+ _spriteTable[spriteId].angle = value;
+
+ if (_spriteTable[spriteId].image)
+ _spriteTable[spriteId].flags |= kSFChanged | kSFNeedRedraw;
+ }
+}
+
+void Sprite::setSpriteFlagDoubleBuffered(int spriteId, int value) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ int oldFlags = _spriteTable[spriteId].flags;
+ if (value)
+ _spriteTable[spriteId].flags |= kSFDoubleBuffered;
+ else
+ _spriteTable[spriteId].flags &= ~kSFDoubleBuffered;
+
+ if (_spriteTable[spriteId].image && _spriteTable[spriteId].flags != oldFlags)
+ _spriteTable[spriteId].flags |= kSFChanged | kSFNeedRedraw;
+}
+
+void Sprite::setSpriteFlagYFlipped(int spriteId, int value) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ int oldFlags = _spriteTable[spriteId].flags;
+ if (value)
+ _spriteTable[spriteId].flags |= kSFYFlipped;
+ else
+ _spriteTable[spriteId].flags &= ~kSFYFlipped;
+
+ if (_spriteTable[spriteId].image && _spriteTable[spriteId].flags != oldFlags)
+ _spriteTable[spriteId].flags |= kSFChanged | kSFNeedRedraw;
+}
+
+void Sprite::setSpriteFlagXFlipped(int spriteId, int value) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ int oldFlags = _spriteTable[spriteId].flags;
+ if (value)
+ _spriteTable[spriteId].flags |= kSFXFlipped;
+ else
+ _spriteTable[spriteId].flags &= ~kSFXFlipped;
+
+ if (_spriteTable[spriteId].image && _spriteTable[spriteId].flags != oldFlags)
+ _spriteTable[spriteId].flags |= kSFChanged | kSFNeedRedraw;
+}
+
+void Sprite::setSpriteFlagActive(int spriteId, int value) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ if (value)
+ _spriteTable[spriteId].flags |= kSFActive;
+ else
+ _spriteTable[spriteId].flags &= ~kSFActive;
+}
+
+void Sprite::setSpriteFlagRemapPalette(int spriteId, int value) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ int oldFlags = _spriteTable[spriteId].flags;
+ if (value)
+ _spriteTable[spriteId].flags |= kSFRemapPalette;
+ else
+ _spriteTable[spriteId].flags &= ~kSFRemapPalette;
+
+ if (_spriteTable[spriteId].image && _spriteTable[spriteId].flags != oldFlags)
+ _spriteTable[spriteId].flags |= kSFChanged | kSFNeedRedraw;
+}
+
+void Sprite::setSpriteFlagAutoAnim(int spriteId, int value) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ if (value)
+ _spriteTable[spriteId].flags |= kSFAutoAnim;
+ else
+ _spriteTable[spriteId].flags &= ~kSFAutoAnim;
+}
+
+void Sprite::setSpriteFlagUpdateType(int spriteId, int value) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ switch(value) {
+ case 2:
+ _spriteTable[spriteId].flags &= ~(kSFMarkDirty);
+ _spriteTable[spriteId].flags |= kSFBlitDirectly;
+ break;
+ case 1:
+ _spriteTable[spriteId].flags |= kSFMarkDirty | kSFBlitDirectly;
+ break;
+ case 0:
+ _spriteTable[spriteId].flags &= ~(kSFMarkDirty | kSFBlitDirectly);
+ break;
+ default:
+ error("setSpriteFlagUpdateType: Invalid value %d", value);
+ }
+}
+
+void Sprite::setSpriteFlagEraseType(int spriteId, int value) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ // Note that condition is inverted
+ if (!value)
+ _spriteTable[spriteId].flags |= kSFImageless;
+ else
+ _spriteTable[spriteId].flags &= ~kSFImageless;
+}
+
+void Sprite::setSpriteAnimSpeed(int spriteId, int value) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ _spriteTable[spriteId].animSpeed = value;
+ _spriteTable[spriteId].animProgress = value;
+}
+
+void Sprite::setSpriteSetClass(int spriteId, int classId, int toggle) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+ checkRange(32, 1, classId, "class %d out of range in statement");
+
+ if (toggle) {
+ _spriteTable[spriteId].classFlags |= (1 << (classId - 1));
+ } else {
+ _spriteTable[spriteId].classFlags &= ~(1 << (classId - 1));
+ }
+}
+
+void Sprite::setSpriteResetClass(int spriteId) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ _spriteTable[spriteId].classFlags = 0;
+}
+
+void Sprite::setSpriteField84(int spriteId, int value) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ _spriteTable[spriteId].field_84 = value;
+}
+
+void Sprite::setSpriteGeneralProperty(int spriteId, int type, int value) {
+ debug(0, "setSpriteGeneralProperty: spriteId %d type 0x%x", spriteId, type);
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+ int32 delay;
+
+ // XXX U32 related check
+
+ switch(type) {
+ case 0x7B:
+ _spriteTable[spriteId].imgFlags = value;
+ _spriteTable[spriteId].flags |= kSFChanged | kSFNeedRedraw;
+ break;
+ case 0x7D:
+ _spriteTable[spriteId].field_90 = value;
+ _spriteTable[spriteId].flags |= kSFChanged | kSFNeedRedraw;
+ break;
+ case 0x7E:
+ delay = MAX(0, value);
+ delay = MIN(delay, _spriteTable[spriteId].animSpeed);
+
+ _spriteTable[spriteId].animProgress = delay;
+ break;
+ default:
+ error("setSpriteGeneralProperty: Invalid value %d", type);
+ }
+}
+
+void Sprite::resetSprite(int spriteId) {
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ _spriteTable[spriteId].angle = 0;
+ _spriteTable[spriteId].scale = 0;
+
+ setSpriteImage(spriteId, 0);
+
+ _spriteTable[spriteId].shadow = 0;
+ _spriteTable[spriteId].tx = 0;
+ _spriteTable[spriteId].ty = 0;
+
+ _spriteTable[spriteId].flags &= ~(kSFYFlipped | kSFXFlipped);
+ _spriteTable[spriteId].flags |= kSFChanged | kSFNeedRedraw;
+ _spriteTable[spriteId].dx = 0;
+ _spriteTable[spriteId].dy = 0;
+ _spriteTable[spriteId].userValue = 0;
+ _spriteTable[spriteId].group = 0;
+ _spriteTable[spriteId].animSpeed = 0;
+ _spriteTable[spriteId].animProgress = 0;
+ _spriteTable[spriteId].classFlags = 0;
+ _spriteTable[spriteId].palette = 0;
+ _spriteTable[spriteId].sourceImage = 0;
+ _spriteTable[spriteId].maskImage = 0;
+ _spriteTable[spriteId].priority = 0;
+ _spriteTable[spriteId].field_84 = 0;
+ _spriteTable[spriteId].imgFlags = 0;
+ _spriteTable[spriteId].field_90 = 0;
+}
+
+void Sprite::setSpriteImage(int spriteId, int imageNum) {
+ int origResId, origResWizStates;
+
+ checkRange(_varNumSprites, 1, spriteId, "Invalid sprite %d");
+
+ origResId = _spriteTable[spriteId].image;
+ origResWizStates = _spriteTable[spriteId].imageStateCount;
+
+ _spriteTable[spriteId].image = imageNum;
+ _spriteTable[spriteId].field_74 = 0;
+ _spriteTable[spriteId].imageState = 0;
+
+ if (_spriteTable[spriteId].image) {
+ _spriteTable[spriteId].imageStateCount = _vm->_wiz->getWizImageStates(_spriteTable[spriteId].image);
+ _spriteTable[spriteId].flags |= kSFActive | kSFAutoAnim | kSFMarkDirty | kSFBlitDirectly;
+
+ if (_spriteTable[spriteId].image != origResId || _spriteTable[spriteId].imageStateCount != origResWizStates)
+ _spriteTable[spriteId].flags |= kSFChanged | kSFNeedRedraw;
+ } else {
+ if (_spriteTable[spriteId].flags & kSFImageless)
+ _spriteTable[spriteId].flags = 0;
+ else
+ _spriteTable[spriteId].flags = kSFChanged | kSFBlitDirectly;
+ _spriteTable[spriteId].curImage = 0;
+ _spriteTable[spriteId].curImageState = 0;
+ _spriteTable[spriteId].imageStateCount = 0;
+ }
+}
+
+//
+// spriteGroupSet functions
+//
+void Sprite::redrawSpriteGroup(int spriteGroupId) {
+ for (int i = 0; i < _numSpritesToProcess; ++i) {
+ SpriteInfo *spi = _activeSpritesTable[i];
+ if (spi->group == spriteGroupId) {
+ spi->flags |= kSFChanged | kSFNeedRedraw;
+ }
+ }
+}
+
+void Sprite::moveGroupMembers(int spriteGroupId, int value1, int value2) {
+ checkRange(_varNumSpriteGroups, 1, spriteGroupId, "Invalid sprite group %d");
+
+ for (int i = 1; i < _varNumSprites; i++) {
+ if (_spriteTable[i].group == spriteGroupId) {
+ _spriteTable[i].tx += value1;
+ _spriteTable[i].ty += value2;
+
+ if (value1 || value2)
+ _spriteTable[i].flags |= kSFChanged | kSFNeedRedraw;
+ }
+ }
+}
+
+void Sprite::setGroupMembersPriority(int spriteGroupId, int value) {
+ checkRange(_varNumSpriteGroups, 1, spriteGroupId, "Invalid sprite group %d");
+
+ for (int i = 1; i < _varNumSprites; i++) {
+ if (_spriteTable[i].group == spriteGroupId)
+ _spriteTable[i].priority = value;
+ }
+}
+
+void Sprite::setGroupMembersGroup(int spriteGroupId, int value) {
+ checkRange(_varNumSpriteGroups, 1, spriteGroupId, "Invalid sprite group %d");
+
+ for (int i = 1; i < _varNumSprites; i++) {
+ if (_spriteTable[i].group == spriteGroupId) {
+ _spriteTable[i].group = value;
+ _spriteTable[i].flags |= kSFChanged | kSFNeedRedraw;
+ }
+ }
+}
+
+void Sprite::setGroupMembersUpdateType(int spriteGroupId, int value) {
+ checkRange(_varNumSpriteGroups, 1, spriteGroupId, "Invalid sprite group %d");
+
+ for (int i = 1; i < _varNumSprites; i++) {
+ if (_spriteTable[i].group == spriteGroupId)
+ setSpriteFlagUpdateType(i, value);
+ }
+}
+
+void Sprite::setGroupMembersResetSprite(int spriteGroupId) {
+ checkRange(_varNumSpriteGroups, 1, spriteGroupId, "Invalid sprite group %d");
+
+ for (int i = 1; i < _varNumSprites; i++) {
+ if (_spriteTable[i].group == spriteGroupId)
+ resetSprite(i);
+ }
+}
+
+void Sprite::setGroupMembersAnimationSpeed(int spriteGroupId, int value) {
+ checkRange(_varNumSpriteGroups, 1, spriteGroupId, "Invalid sprite group %d");
+
+ for (int i = 1; i < _varNumSprites; i++) {
+ if (_spriteTable[i].group == spriteGroupId) {
+ _spriteTable[i].animSpeed = value;
+ _spriteTable[i].animProgress = value;
+ }
+ }
+}
+
+void Sprite::setGroupMembersAutoAnimFlag(int spriteGroupId, int value) {
+ checkRange(_varNumSpriteGroups, 1, spriteGroupId, "Invalid sprite group %d");
+
+ for (int i = 1; i < _varNumSprites; i++) {
+ if (_spriteTable[i].group == spriteGroupId) {
+ if (value)
+ _spriteTable[i].flags |= kSFAutoAnim;
+ else
+ _spriteTable[i].flags &= ~kSFAutoAnim;
+ }
+ }
+}
+
+void Sprite::setGroupMembersShadow(int spriteGroupId, int value) {
+ checkRange(_varNumSpriteGroups, 1, spriteGroupId, "Invalid sprite group %d");
+
+ for (int i = 1; i < _varNumSprites; i++) {
+ if (_spriteTable[i].group == spriteGroupId) {
+ _spriteTable[i].shadow = value;
+ if (_spriteTable[i].image)
+ _spriteTable[i].flags |= kSFChanged | kSFNeedRedraw;
+ }
+ }
+}
+
+void Sprite::setGroupBounds(int spriteGroupId, int x1, int y1, int x2, int y2) {
+ checkRange(_varNumSpriteGroups, 1, spriteGroupId, "Invalid sprite group %d");
+
+ _spriteGroups[spriteGroupId].flags |= kSGFClipBox;
+ _spriteGroups[spriteGroupId].bbox.left = x1;
+ _spriteGroups[spriteGroupId].bbox.top = y1;
+ _spriteGroups[spriteGroupId].bbox.right = x2;
+ _spriteGroups[spriteGroupId].bbox.bottom = y2;
+
+ redrawSpriteGroup(spriteGroupId);
+}
+
+void Sprite::setGroupPriority(int spriteGroupId, int value) {
+ checkRange(_varNumSpriteGroups, 1, spriteGroupId, "Invalid sprite group %d");
+
+ if (_spriteGroups[spriteGroupId].priority != value) {
+ _spriteGroups[spriteGroupId].priority = value;
+ redrawSpriteGroup(spriteGroupId);
+ }
+}
+
+void Sprite::setGroupPosition(int spriteGroupId, int value1, int value2) {
+ checkRange(_varNumSpriteGroups, 1, spriteGroupId, "Invalid sprite group %d");
+
+ if (_spriteGroups[spriteGroupId].tx != value1 || _spriteGroups[spriteGroupId].ty != value2) {
+ _spriteGroups[spriteGroupId].tx = value1;
+ _spriteGroups[spriteGroupId].ty = value2;
+ redrawSpriteGroup(spriteGroupId);
+ }
+}
+
+void Sprite::moveGroup(int spriteGroupId, int value1, int value2) {
+ checkRange(_varNumSpriteGroups, 1, spriteGroupId, "Invalid sprite group %d");
+
+ if (value1 || value2) {
+ _spriteGroups[spriteGroupId].tx += value1;
+ _spriteGroups[spriteGroupId].ty += value2;
+ redrawSpriteGroup(spriteGroupId);
+ }
+}
+
+void Sprite::setGroupImage(int spriteGroupId, int value) {
+ checkRange(_varNumSpriteGroups, 1, spriteGroupId, "Invalid sprite group %d");
+
+ if (_spriteGroups[spriteGroupId].image != value) {
+ _spriteGroups[spriteGroupId].image = value;
+ redrawSpriteGroup(spriteGroupId);
+ }
+}
+
+void Sprite::setGroupScaling(int spriteGroupId) {
+ if ((_spriteGroups[spriteGroupId].scale_x_ratio_mul != _spriteGroups[spriteGroupId].scale_x_ratio_div) || (_spriteGroups[spriteGroupId].scale_y_ratio_mul != _spriteGroups[spriteGroupId].scale_y_ratio_div))
+ _spriteGroups[spriteGroupId].scaling = 1;
+ else
+ _spriteGroups[spriteGroupId].scaling = 0;
+
+}
+
+void Sprite::setGroupXMul(int spriteGroupId, int value) {
+ checkRange(_varNumSpriteGroups, 1, spriteGroupId, "Invalid sprite group %d");
+
+ if (_spriteGroups[spriteGroupId].scale_x_ratio_mul != value) {
+ _spriteGroups[spriteGroupId].scale_x_ratio_mul = value;
+ setGroupScaling(spriteGroupId);
+ redrawSpriteGroup(spriteGroupId);
+ }
+}
+
+void Sprite::setGroupXDiv(int spriteGroupId, int value) {
+ checkRange(_varNumSpriteGroups, 1, spriteGroupId, "Invalid sprite group %d");
+
+ if (value == 0)
+ error("setGroupXDiv: Divisor must not be 0");
+
+ if (_spriteGroups[spriteGroupId].scale_x_ratio_div != value) {
+ _spriteGroups[spriteGroupId].scale_x_ratio_div = value;
+ setGroupScaling(spriteGroupId);
+ redrawSpriteGroup(spriteGroupId);
+ }
+}
+
+void Sprite::setGroupYMul(int spriteGroupId, int value) {
+ checkRange(_varNumSpriteGroups, 1, spriteGroupId, "Invalid sprite group %d");
+
+ if (_spriteGroups[spriteGroupId].scale_y_ratio_mul != value) {
+ _spriteGroups[spriteGroupId].scale_y_ratio_mul = value;
+ setGroupScaling(spriteGroupId);
+ redrawSpriteGroup(spriteGroupId);
+ }
+}
+
+void Sprite::setGroupYDiv(int spriteGroupId, int value) {
+ checkRange(_varNumSpriteGroups, 1, spriteGroupId, "Invalid sprite group %d");
+
+ if (value == 0)
+ error("setGroupYDiv: Divisor must not be 0");
+
+ if (_spriteGroups[spriteGroupId].scale_y_ratio_div != value) {
+ _spriteGroups[spriteGroupId].scale_y_ratio_div = value;
+ setGroupScaling(spriteGroupId);
+ redrawSpriteGroup(spriteGroupId);
+ }
+}
+
+void Sprite::resetGroupBounds(int spriteGroupId) {
+ checkRange(_varNumSpriteGroups, 1, spriteGroupId, "Invalid sprite group %d");
+
+ _spriteGroups[spriteGroupId].flags &= ~(kSGFClipBox);
+ redrawSpriteGroup(spriteGroupId);
+}
+
+void Sprite::allocTables(int numSprites, int numGroups, int numMaxSprites) {
+ _varNumSpriteGroups = numGroups;
+ _numSpritesToProcess = 0;
+ _varNumSprites = numSprites;
+ _varMaxSprites = numMaxSprites;
+ _spriteGroups = (SpriteGroup *)malloc((_varNumSpriteGroups + 1) * sizeof(SpriteGroup));
+ _spriteTable = (SpriteInfo *)malloc((_varNumSprites + 1) * sizeof(SpriteInfo));
+ _activeSpritesTable = (SpriteInfo **)malloc((_varNumSprites + 1) * sizeof(SpriteInfo *));
+}
+
+void Sprite::resetGroup(int spriteGroupId) {
+ checkRange(_varNumSpriteGroups, 1, spriteGroupId, "Invalid sprite group %d");
+ SpriteGroup *spg = &_spriteGroups[spriteGroupId];
+
+ spg->priority = 0;
+ spg->tx = spg->ty = 0;
+
+ spg->flags &= ~kSGFClipBox;
+ redrawSpriteGroup(spriteGroupId);
+
+ spg->image = 0;
+ spg->scaling = 0;
+ spg->scale_x_ratio_mul = 1;
+ spg->scale_x_ratio_div = 1;
+ spg->scale_y_ratio_mul = 1;
+ spg->scale_y_ratio_div = 1;
+}
+
+void Sprite::resetTables(bool refreshScreen) {
+ memset(_spriteTable, 0, (_varNumSprites + 1) * sizeof(SpriteInfo));
+ memset(_spriteGroups, 0, (_varNumSpriteGroups + 1) * sizeof(SpriteGroup));
+ for (int curGrp = 1; curGrp < _varNumSpriteGroups; ++curGrp)
+ resetGroup(curGrp);
+
+ if (refreshScreen) {
+ _vm->gdi.copyVirtScreenBuffers(Common::Rect(_vm->_screenWidth, _vm->_screenHeight));
+ }
+ _numSpritesToProcess = 0;
+}
+
+void Sprite::resetBackground() {
+ int xmin, xmax, ymin, ymax;
+ xmin = ymin = 1234;
+ xmax = ymax = -1234;
+ bool firstLoop = true;
+ bool refreshScreen = false;
+
+ for (int i = 0; i < _numSpritesToProcess; ++i) {
+ SpriteInfo *spi = _activeSpritesTable[i];
+ if (!(spi->flags & kSFImageless) && (spi->flags & kSFChanged)) {
+ spi->flags &= ~kSFChanged;
+ if (spi->bbox.left <= spi->bbox.right && spi->bbox.top <= spi->bbox.bottom) {
+ if (spi->flags & kSFBlitDirectly) {
+ _vm->gdi.copyVirtScreenBuffers(spi->bbox, USAGE_BIT_RESTORED);
+ } else if (firstLoop) {
+ xmin = spi->bbox.left;
+ ymin = spi->bbox.top;
+ xmax = spi->bbox.right;
+ ymax = spi->bbox.bottom;
+ firstLoop = false;
+ refreshScreen = true;
+ } else {
+ if (xmin > spi->bbox.left) {
+ xmin = spi->bbox.left;
+ }
+ if (ymin > spi->bbox.top) {
+ ymin = spi->bbox.top;
+ }
+ if (xmax < spi->bbox.right) {
+ xmax = spi->bbox.right;
+ }
+ if (ymax < spi->bbox.bottom) {
+ ymax = spi->bbox.bottom;
+ }
+ refreshScreen = true;
+ }
+ if (!(spi->flags & kSFNeedRedraw) && spi->image)
+ spi->flags |= kSFNeedRedraw;
+ }
+ }
+ }
+ if (refreshScreen) {
+ _vm->gdi.copyVirtScreenBuffers(Common::Rect(xmin, ymin, xmax, ymax), USAGE_BIT_RESTORED);
+ }
+}
+
+void Sprite::setRedrawFlags(bool checkZOrder) {
+ VirtScreen *vs = &_vm->virtscr[kMainVirtScreen];
+ for (int i = 0; i < _numSpritesToProcess; ++i) {
+ SpriteInfo *spi = _activeSpritesTable[i];
+ if (!(spi->flags & kSFNeedRedraw)) {
+ if ((!checkZOrder || spi->priority >= 0) && (spi->flags & kSFMarkDirty)) {
+ int lp = spi->bbox.left / 8;
+ lp = MAX(0, lp);
+ lp = MIN(lp, 79);
+ int rp = (spi->bbox.right + 7) / 8;
+ rp = MAX(0, rp);
+ rp = MIN(rp, 79);
+ for (; lp <= rp; ++lp) {
+ if (vs->tdirty[lp] < vs->h && spi->bbox.bottom >= vs->tdirty[lp] && spi->bbox.top <= vs->bdirty[lp]) {
+ spi->flags |= kSFNeedRedraw;
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+void Sprite::updateImages() {
+ for (int i = 0; i < _numSpritesToProcess; ++i) {
+ SpriteInfo *spi = _activeSpritesTable[i];
+ if (spi->dx || spi->dy) {
+ int tx = spi->tx;
+ int ty = spi->ty;
+ spi->tx += spi->dx;
+ spi->ty += spi->dy;
+ if (tx != spi->tx || ty != spi->ty) {
+ spi->flags |= kSFChanged | kSFNeedRedraw;
+ }
+ }
+ if (spi->flags & kSFAutoAnim) {
+ if (spi->animSpeed) {
+ --spi->animProgress;
+ if (spi->animProgress)
+ continue;
+
+ spi->animProgress = spi->animSpeed;
+ }
+ int imageState = spi->imageState;
+ ++spi->imageState;
+ if (spi->imageState >= spi->imageStateCount) {
+ spi->imageState = 0;
+ if (imageState == 0)
+ continue;
+ }
+ spi->flags |= kSFChanged | kSFNeedRedraw;
+ }
+ }
+}
+
+static int compareSprTable(const void *a, const void *b) {
+ const SpriteInfo *spr1 = *(const SpriteInfo *const*)a;
+ const SpriteInfo *spr2 = *(const SpriteInfo *const*)b;
+
+ if (spr1->zorder > spr2->zorder)
+ return 1;
+
+ if (spr1->zorder < spr2->zorder)
+ return -1;
+
+ return 0;
+}
+
+void Sprite::sortActiveSprites() {
+ int groupZorder;
+
+ _numSpritesToProcess = 0;
+
+ if (_varNumSprites <= 1)
+ return;
+
+ for (int i = 1; i < _varNumSprites; i++) {
+ SpriteInfo *spi = &_spriteTable[i];
+
+ if (spi->flags & kSFActive) {
+ if (!(spi->flags & kSFMarkDirty)) {
+ spi->flags |= kSFNeedRedraw;
+ if (!(spi->flags & kSFImageless))
+ spi->flags |= kSFChanged;
+ }
+ if (spi->group)
+ groupZorder = _spriteGroups[spi->group].priority;
+ else
+ groupZorder = 0;
+
+ spi->id = i;
+ spi->zorder = spi->priority + groupZorder;
+
+ _activeSpritesTable[_numSpritesToProcess++] = spi;
+ }
+ }
+
+ if (_numSpritesToProcess < 2)
+ return;
+
+ qsort(_activeSpritesTable, _numSpritesToProcess, sizeof(SpriteInfo *), compareSprTable);
+}
+
+void Sprite::processImages(bool arg) {
+ int spr_flags;
+ int32 spr_wiz_x, spr_wiz_y;
+ int image, imageState;
+ Common::Rect *bboxPtr;
+ int angle, scale;
+ int32 w, h;
+ WizParameters wiz;
+
+ for (int i = 0; i < _numSpritesToProcess; i++) {
+ SpriteInfo *spi = _activeSpritesTable[i];
+
+ if (!(spi->flags & kSFNeedRedraw))
+ continue;
+
+ spr_flags = spi->flags;
+
+ if (arg) {
+ if (spi->zorder >= 0)
+ return;
+ } else {
+ if (spi->zorder < 0)
+ continue;
+ }
+
+ spi->flags &= ~kSFNeedRedraw;
+ image = spi->image;
+ imageState = spi->imageState;
+ _vm->_wiz->getWizImageSpot(spi->image, spi->imageState, spr_wiz_x, spr_wiz_y);
+
+ if (spi->group) {
+ SpriteGroup *spg = &_spriteGroups[spi->group];
+
+ if (spg->scaling) {
+ wiz.img.x1 = spi->tx * spg->scale_x_ratio_mul / spg->scale_x_ratio_div - spr_wiz_x + spg->tx;
+ wiz.img.y1 = spi->ty * spg->scale_y_ratio_mul / spg->scale_y_ratio_div - spr_wiz_y + spg->ty;
+ } else {
+ wiz.img.x1 = spi->tx - spr_wiz_x + spg->tx;
+ wiz.img.y1 = spi->ty - spr_wiz_y + spg->ty;
+ }
+ } else {
+ wiz.img.x1 = spi->tx - spr_wiz_x;
+ wiz.img.y1 = spi->ty - spr_wiz_y;
+ }
+
+ wiz.spriteId = spi->id;
+ wiz.spriteGroup = spi->group;
+ wiz.field_23EA = spi->field_90;
+ spi->curImageState = wiz.img.state = imageState;
+ spi->curImage = wiz.img.resNum = image;
+ wiz.processFlags = kWPFNewState | kWPFSetPos;
+ spi->curAngle = spi->angle;
+ spi->curScale = spi->scale;
+ spi->pos.x = wiz.img.x1;
+ spi->pos.y = wiz.img.y1;
+ bboxPtr = &spi->bbox;
+ if (image) {
+ angle = spi->angle;
+ scale = spi->scale;
+ _vm->_wiz->getWizImageDim(image, imageState, w, h);
+ if (spi->flags & (kSFScaled | kSFRotated)) {
+ Common::Point pts[4];
+ _vm->_wiz->polygonTransform(image, imageState, wiz.img.x1, wiz.img.y1, angle, scale, pts);
+ _vm->_wiz->polygonCalcBoundBox(pts, 4, spi->bbox);
+ } else {
+ bboxPtr->left = wiz.img.x1;
+ bboxPtr->top = wiz.img.y1;
+ bboxPtr->right = wiz.img.x1 + w;
+ bboxPtr->bottom = wiz.img.y1 + h;
+ }
+ } else {
+ bboxPtr->left = 1234;
+ bboxPtr->top = 1234;
+ bboxPtr->right = -1234;
+ bboxPtr->bottom = -1234;
+ }
+
+ wiz.img.flags = kWIFMarkBufferDirty;
+ wiz.img.zorder = 0;
+ if (spr_flags & kSFXFlipped)
+ wiz.img.flags |= kWIFFlipX;
+ if (spr_flags & kSFYFlipped)
+ wiz.img.flags |= kWIFFlipY;
+ if (spr_flags & kSFDoubleBuffered) {
+ wiz.img.flags &= ~kWIFMarkBufferDirty;
+ wiz.img.flags |= kWIFBlitToFrontVideoBuffer;
+ }
+ if (spi->shadow) {
+ wiz.img.flags |= 0x200;
+ wiz.processFlags |= kWPFShadow;
+ wiz.img.shadow = spi->shadow;
+ }
+ if (spr_flags & kSFRemapPalette)
+ wiz.img.flags |= kWIFRemapPalette;
+ if (spi->field_84) {
+ wiz.processFlags |= 0x200000;
+ wiz.img.field_390 = spi->field_84;
+ wiz.img.zorder = spi->priority;
+ }
+ if (spi->sourceImage) {
+ wiz.processFlags |= kWPFMaskImg;
+ wiz.sourceImage = spi->sourceImage;
+ }
+ wiz.processFlags |= kWPFNewFlags;
+ wiz.img.flags |= spi->imgFlags;
+
+ if (spr_flags & kSFRotated) {
+ wiz.processFlags |= kWPFRotate;
+ wiz.angle = spi->angle;
+ }
+ if (spr_flags & kSFScaled) {
+ wiz.processFlags |= kWPFScaled;
+ wiz.scale = spi->scale;
+ }
+ spi->curImgFlags = wiz.img.flags;
+
+ if (spi->group && (_spriteGroups[spi->group].flags & kSGFClipBox)) {
+ Common::Rect &spgBbox = _spriteGroups[spi->group].bbox;
+ if (spgBbox.isValidRect() && spi->bbox.intersects(spgBbox)) {
+ spi->bbox.clip(spgBbox);
+ wiz.processFlags |= kWPFClipBox;
+ wiz.box = spi->bbox;
+ } else {
+ bboxPtr->left = 1234;
+ bboxPtr->top = 1234;
+ bboxPtr->right = -1234;
+ bboxPtr->bottom = -1234;
+ continue;
+ }
+ }
+ if (spi->palette) {
+ wiz.processFlags |= kWPFPaletteNum;
+ wiz.img.palette = spi->palette;
+ }
+ if (spi->image && spi->group && _spriteGroups[spi->group].image) {
+ wiz.processFlags |= kWPFDstResNum;
+ wiz.dstResNum = _spriteGroups[spi->group].image;
+ }
+ _vm->_wiz->displayWizComplexImage(&wiz);
+ }
+}
+
+void Sprite::saveOrLoadSpriteData(Serializer *s) {
+ static const SaveLoadEntry spriteEntries[] = {
+ MKLINE(SpriteInfo, id, sleInt32, VER(48)),
+ MKLINE(SpriteInfo, zorder, sleInt32, VER(48)),
+ MKLINE(SpriteInfo, flags, sleInt32, VER(48)),
+ MKLINE(SpriteInfo, image, sleInt32, VER(48)),
+ MKLINE(SpriteInfo, imageState, sleInt32, VER(48)),
+ MKLINE(SpriteInfo, group, sleInt32, VER(48)),
+ MKLINE(SpriteInfo, palette, sleInt32, VER(48)),
+ MKLINE(SpriteInfo, priority, sleInt32, VER(48)),
+ MKLINE(SpriteInfo, bbox.left, sleInt32, VER(48)),
+ MKLINE(SpriteInfo, bbox.top, sleInt32, VER(48)),
+ MKLINE(SpriteInfo, bbox.right, sleInt32, VER(48)),
+ MKLINE(SpriteInfo, bbox.bottom, sleInt32, VER(48)),
+ MKLINE(SpriteInfo, dx, sleInt32, VER(48)),
+ MKLINE(SpriteInfo, dy, sleInt32, VER(48)),
+ MKLINE(SpriteInfo, pos.x, sleInt32, VER(48)),
+ MKLINE(SpriteInfo, pos.y, sleInt32, VER(48)),
+ MKLINE(SpriteInfo, tx, sleInt32, VER(48)),
+ MKLINE(SpriteInfo, ty, sleInt32, VER(48)),
+ MKLINE(SpriteInfo, userValue, sleInt32, VER(48)),
+ MKLINE(SpriteInfo, curImageState, sleInt32, VER(48)),
+ MKLINE(SpriteInfo, curImage, sleInt32, VER(48)),
+ MKLINE(SpriteInfo, imglistNum, sleInt32, VER(48)),
+ MKLINE(SpriteInfo, shadow, sleInt32, VER(48)),
+ MKLINE(SpriteInfo, imageStateCount, sleInt32, VER(48)),
+ MKLINE(SpriteInfo, angle, sleInt32, VER(48)),
+ MKLINE(SpriteInfo, scale, sleInt32, VER(48)),
+ MKLINE(SpriteInfo, animProgress, sleInt32, VER(48)),
+ MKLINE(SpriteInfo, curAngle, sleInt32, VER(48)),
+ MKLINE(SpriteInfo, curScale, sleInt32, VER(48)),
+ MKLINE(SpriteInfo, curImgFlags, sleInt32, VER(48)),
+ MKLINE(SpriteInfo, field_74, sleInt32, VER(48)),
+ MKLINE(SpriteInfo, animSpeed, sleInt32, VER(48)),
+ MKLINE(SpriteInfo, sourceImage, sleInt32, VER(48)),
+ MKLINE(SpriteInfo, maskImage, sleInt32, VER(48)),
+ MKLINE(SpriteInfo, field_84, sleInt32, VER(48)),
+ MKLINE(SpriteInfo, classFlags, sleInt32, VER(48)),
+ MKLINE(SpriteInfo, imgFlags, sleInt32, VER(48)),
+ MKLINE(SpriteInfo, field_90, sleInt32, VER(48)),
+ MKEND()
+ };
+
+ static const SaveLoadEntry spriteGroupEntries[] = {
+ MKLINE(SpriteGroup, bbox.left, sleInt32, VER(48)),
+ MKLINE(SpriteGroup, bbox.top, sleInt32, VER(48)),
+ MKLINE(SpriteGroup, bbox.right, sleInt32, VER(48)),
+ MKLINE(SpriteGroup, bbox.bottom, sleInt32, VER(48)),
+ MKLINE(SpriteGroup, priority, sleInt32, VER(48)),
+ MKLINE(SpriteGroup, flags, sleInt32, VER(48)),
+ MKLINE(SpriteGroup, tx, sleInt32, VER(48)),
+ MKLINE(SpriteGroup, ty, sleInt32, VER(48)),
+ MKLINE(SpriteGroup, image, sleInt32, VER(48)),
+ MKLINE(SpriteGroup, scaling, sleInt32, VER(48)),
+ MKLINE(SpriteGroup, scale_x_ratio_mul, sleInt32, VER(48)),
+ MKLINE(SpriteGroup, scale_x_ratio_div, sleInt32, VER(48)),
+ MKLINE(SpriteGroup, scale_y_ratio_mul, sleInt32, VER(48)),
+ MKLINE(SpriteGroup, scale_y_ratio_div, sleInt32, VER(48)),
+ MKEND()
+ };
+
+ if (s->getVersion() >= VER(64)) {
+ s->saveLoadArrayOf(_spriteTable, _varNumSprites + 1, sizeof(_spriteTable[0]), spriteEntries);
+ s->saveLoadArrayOf(_spriteGroups, _varNumSpriteGroups + 1, sizeof(_spriteGroups[0]), spriteGroupEntries);
+ } else {
+ s->saveLoadArrayOf(_activeSpritesTable, _varNumSprites, sizeof(_activeSpritesTable[0]), spriteEntries);
+ s->saveLoadArrayOf(_spriteTable, _varNumSprites, sizeof(_spriteTable[0]), spriteEntries);
+ s->saveLoadArrayOf(_spriteGroups, _varNumSpriteGroups, sizeof(_spriteGroups[0]), spriteGroupEntries);
+ }
+
+ // Reset active sprite table
+ if (s->isLoading())
+ _numSpritesToProcess = 0;
+
+}
+
+} // End of namespace Scumm