aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorBenjamin Haisch2008-09-17 10:59:23 +0000
committerWillem Jan Palenstijn2011-11-20 22:43:06 +0100
commitade8eec8cf853c8f5fe16cbf410440e76e0ac23e (patch)
tree7718b51253e5468e6fdd953a26c732f66fa52dd8 /engines
parentca49ded9b346e702538a560ed9de391c3c532b9d (diff)
downloadscummvm-rg350-ade8eec8cf853c8f5fe16cbf410440e76e0ac23e.tar.gz
scummvm-rg350-ade8eec8cf853c8f5fe16cbf410440e76e0ac23e.tar.bz2
scummvm-rg350-ade8eec8cf853c8f5fe16cbf410440e76e0ac23e.zip
TOLTECS: Moved sprite drawing code to sprite.cpp
Diffstat (limited to 'engines')
-rw-r--r--engines/toltecs/module.mk3
-rw-r--r--engines/toltecs/screen.cpp340
-rw-r--r--engines/toltecs/screen.h153
-rw-r--r--engines/toltecs/sprite.cpp535
4 files changed, 537 insertions, 494 deletions
diff --git a/engines/toltecs/module.mk b/engines/toltecs/module.mk
index 0d658f6095..3cf88552ff 100644
--- a/engines/toltecs/module.mk
+++ b/engines/toltecs/module.mk
@@ -12,7 +12,8 @@ MODULE_OBJS = \
saveload.o \
screen.o \
script.o \
- segmap.o
+ segmap.o \
+ sprite.o
# This module can be built as a plugin
diff --git a/engines/toltecs/screen.cpp b/engines/toltecs/screen.cpp
index 4f7efaa423..fc981db511 100644
--- a/engines/toltecs/screen.cpp
+++ b/engines/toltecs/screen.cpp
@@ -266,346 +266,6 @@ void Screen::clearSprites() {
}
-void Screen::addDrawRequest(const DrawRequest &drawRequest) {
-
- int16 scaleValueX, scaleValueY;
- int16 xoffs, yoffs;
- byte *spriteData;
- int16 frameNum;
-
- SpriteDrawItem sprite;
- memset(&sprite, 0, sizeof(SpriteDrawItem));
-
- if (drawRequest.flags == 0xFFFF)
- return;
-
- sprite.flags = 0;
- sprite.baseColor = drawRequest.baseColor;
- sprite.x = drawRequest.x;
- sprite.y = drawRequest.y;
- sprite.ybottom = drawRequest.y;
- sprite.resIndex = drawRequest.resIndex;
-
- spriteData = _vm->_res->load(drawRequest.resIndex);
-
- if (drawRequest.flags & 0x1000) {
- sprite.flags |= 4;
- }
-
- if (drawRequest.flags & 0x2000) {
- sprite.flags |= 0x10;
- }
-
- if (drawRequest.flags & 0x4000) {
- sprite.flags |= 0x40;
- }
-
- frameNum = drawRequest.flags & 0x0FFF;
-
- // First initialize the sprite item with the values from the sprite resource
-
- SpriteFrameEntry spriteFrameEntry(spriteData + frameNum * 12);
-
- if (spriteFrameEntry.w == 0 || spriteFrameEntry.h == 0)
- return;
-
- sprite.offset = spriteFrameEntry.offset;
-
- sprite.width = spriteFrameEntry.w;
- sprite.height = spriteFrameEntry.h;
-
- sprite.origWidth = spriteFrameEntry.w;
- sprite.origHeight = spriteFrameEntry.h;
-
- if (drawRequest.flags & 0x1000) {
- xoffs = spriteFrameEntry.w - spriteFrameEntry.x;
- } else {
- xoffs = spriteFrameEntry.x;
- }
-
- yoffs = spriteFrameEntry.y;
-
- // If the sprite should be scaled we need to initialize some values now
-
- if (drawRequest.scaling != 0) {
-
- byte scaleValue = ABS(drawRequest.scaling);
-
- scaleValueX = scaleValue * sprite.origWidth;
- sprite.xdelta = (10000 * sprite.origWidth) / scaleValueX;
- scaleValueX /= 100;
-
- scaleValueY = scaleValue * sprite.origHeight;
- sprite.ydelta = (10000 * sprite.origHeight) / scaleValueY;
- scaleValueY /= 100;
-
- if (drawRequest.scaling > 0) {
- sprite.flags |= 2;
- sprite.width = sprite.origWidth + scaleValueX;
- sprite.height = sprite.origHeight + scaleValueY;
- xoffs += (xoffs * scaleValue) / 100;
- yoffs += (yoffs * scaleValue) / 100;
- } else {
- sprite.flags |= 1;
- sprite.width = sprite.origWidth - scaleValueX;
- sprite.height = sprite.origHeight - 1 - scaleValueY;
- if (sprite.width <= 0 || sprite.height <= 0)
- return;
- xoffs -= (xoffs * scaleValue) / 100;
- yoffs -= (yoffs * scaleValue) / 100;
- }
-
- }
-
- sprite.x -= xoffs;
- sprite.y -= yoffs;
-
- sprite.yerror = sprite.ydelta;
-
- // Now we check if the sprite needs to be clipped
-
- // Clip Y
- if (sprite.y - _vm->_cameraY < 0) {
-
- int16 clipHeight = ABS(sprite.y - _vm->_cameraY);
- int16 chopHeight, skipHeight, lineWidth;
- byte *spriteFrameData;
-
- sprite.height -= clipHeight;
- if (sprite.height <= 0)
- return;
-
- sprite.y = _vm->_cameraY;
-
- // If the sprite is scaled
- if (sprite.flags & 3) {
- chopHeight = sprite.ydelta;
- skipHeight = clipHeight;
- if ((sprite.flags & 2) == 0) {
- do {
- chopHeight -= 100;
- if (chopHeight <= 0) {
- skipHeight++;
- chopHeight += sprite.ydelta;
- } else {
- clipHeight--;
- }
- } while (clipHeight > 0);
- } else {
- do {
- chopHeight -= 100;
- if (chopHeight < 0) {
- skipHeight--;
- chopHeight += sprite.ydelta + 100;
- }
- clipHeight--;
- } while (clipHeight > 0);
- }
- sprite.yerror = chopHeight;
- }
-
- spriteFrameData = spriteData + sprite.offset;
-
- // Now the sprite's offset is adjusted to point to the starting line
- if ((sprite.flags & 0x10) == 0) {
- while (clipHeight--) {
- lineWidth = 0;
- while (lineWidth </*CHECKME was != */ sprite.origWidth) {
- sprite.offset++;
- lineWidth += (*spriteFrameData++) & 0x0F;
- }
- }
- } else {
- lineWidth = 0;
- while (clipHeight--) {
- while (lineWidth < sprite.origWidth) {
- sprite.offset += 2;
- spriteFrameData++;
- lineWidth += *spriteFrameData++;
- }
- }
- }
-
- }
-
- if (sprite.y + sprite.height - _vm->_cameraY - _vm->_cameraHeight > 0)
- sprite.height -= sprite.y + sprite.height - _vm->_cameraY - _vm->_cameraHeight;
- if (sprite.height <= 0)
- return;
-
- sprite.skipX = 0;
-
- if (drawRequest.flags & 0x1000) {
- // Left border
- if (sprite.x - _vm->_cameraX < 0) {
- sprite.width -= ABS(sprite.x - _vm->_cameraX);
- sprite.x = _vm->_cameraX;
- }
- // Right border
- if (sprite.x + sprite.width - _vm->_cameraX - 640 > 0) {
- sprite.flags |= 8;
- sprite.skipX = sprite.x + sprite.width - _vm->_cameraX - 640;
- sprite.width -= sprite.skipX;
- }
- } else {
- // Left border
- if (sprite.x - _vm->_cameraX < 0) {
- sprite.flags |= 8;
- sprite.skipX = ABS(sprite.x - _vm->_cameraX);
- sprite.width -= sprite.skipX;
- sprite.x = _vm->_cameraX;
- }
- // Right border
- if (sprite.x + sprite.width - _vm->_cameraX - 640 > 0) {
- sprite.flags |= 8;
- sprite.width -= sprite.x + sprite.width - _vm->_cameraX - 640;
- }
- }
-
- if (sprite.width <= 0)
- return;
-
- // Add sprite sorted by priority
- Common::List<SpriteDrawItem>::iterator iter = _spriteDrawList.begin();
- while (iter != _spriteDrawList.end() && (*iter).ybottom <= sprite.ybottom) {
- iter++;
- }
- _spriteDrawList.insert(iter, sprite);
-
-}
-
-void Screen::drawSprite(SpriteDrawItem *sprite) {
-
- debug(0, "Screen::drawSprite() x = %d; y = %d; flags = %04X; resIndex = %d; offset = %08X; drawX = %d; drawY = %d",
- sprite->x, sprite->y, sprite->flags, sprite->resIndex, sprite->offset,
- sprite->x - _vm->_cameraX, sprite->y - _vm->_cameraY);
- debug(0, "Screen::drawSprite() width = %d; height = %d; origWidth = %d; origHeight = %d",
- sprite->width, sprite->height, sprite->origWidth, sprite->origHeight);
-
- byte *source = _vm->_res->load(sprite->resIndex) + sprite->offset;
- byte *dest = _frontScreen + (sprite->x - _vm->_cameraX) + (sprite->y - _vm->_cameraY) * 640;
-
- SpriteReader spriteReader(source, sprite);
-
- if (sprite->flags & 0x40) {
- // Shadow sprites
- if (sprite->flags & 1) {
- SpriteFilterScaleDown spriteScaler(sprite, &spriteReader);
- drawSpriteCore(dest, spriteScaler, sprite);
- } else if (sprite->flags & 2) {
- SpriteFilterScaleUp spriteScaler(sprite, &spriteReader);
- drawSpriteCore(dest, spriteScaler, sprite);
- } else {
- drawSpriteCore(dest, spriteReader, sprite);
- }
- } else if (sprite->flags & 0x10) {
- // 256 color sprite
- drawSpriteCore(dest, spriteReader, sprite);
- } else {
- // 16 color sprite
- if (sprite->flags & 1) {
- SpriteFilterScaleDown spriteScaler(sprite, &spriteReader);
- drawSpriteCore(dest, spriteScaler, sprite);
- } else if (sprite->flags & 2) {
- SpriteFilterScaleUp spriteScaler(sprite, &spriteReader);
- drawSpriteCore(dest, spriteScaler, sprite);
- } else {
- drawSpriteCore(dest, spriteReader, sprite);
- }
- }
-
- debug(0, "Screen::drawSprite() ok");
-
-}
-
-void Screen::drawSpriteCore(byte *dest, SpriteFilter &reader, SpriteDrawItem *sprite) {
-
- int16 destInc;
-
- if (sprite->flags & 4) {
- destInc = -1;
- dest += sprite->width;
- } else {
- destInc = 1;
- }
-
- SpriteReaderStatus status;
- PixelPacket packet;
-
- byte *destp = dest;
- int16 skipX = sprite->skipX;
-
- int16 w = sprite->width;
- int16 h = sprite->height;
-
- do {
- status = reader.readPacket(packet);
-
- if (skipX > 0) {
- while (skipX > 0) {
- skipX -= packet.count;
- if (skipX < 0) {
- packet.count = ABS(skipX);
- break;
- }
- status = reader.readPacket(packet);
- }
- }
-
- if (w - packet.count < 0)
- packet.count = w;
-
- w -= packet.count;
-
- if (((sprite->flags & 0x40) && (packet.pixel != 0)) ||
- ((sprite->flags & 0x10) && (packet.pixel != 0xFF)) ||
- !(sprite->flags & 0x10) && (packet.pixel != 0))
- {
- if (sprite->flags & 0x40) {
- while (packet.count--) {
- *dest = _vm->_palette->getColorTransPixel(*dest);
- dest += destInc;
- }
- } else {
- if (sprite->flags & 0x10) {
- packet.pixel = ((packet.pixel << 4) & 0xF0) | ((packet.pixel >> 4) & 0x0F);
- } else {
- packet.pixel += sprite->baseColor - 1;
- }
- while (packet.count--) {
- *dest = packet.pixel;
- dest += destInc;
- }
- }
- } else {
- dest += packet.count * destInc;
- }
-
- if (status == kSrsEndOfLine || w <= 0) {
- if (w <= 0) {
- while (status == kSrsPixelsLeft) {
- status = reader.readPacket(packet);
- }
- }
- dest = destp + 640;
- destp = dest;
- skipX = sprite->skipX;
- w = sprite->width;
- h--;
- }
-
- } while (status != kSrsEndOfSprite && h > 0);
-
-}
-
-void Screen::drawSprites() {
- for (Common::List<SpriteDrawItem>::iterator iter = _spriteDrawList.begin(); iter != _spriteDrawList.end(); iter++) {
- SpriteDrawItem *sprite = &(*iter);
- drawSprite(sprite);
- _vm->_segmap->restoreMasksBySprite(sprite);
- }
-}
-
void Screen::updateVerbLine(int16 slotIndex, int16 slotOffset) {
debug(0, "Screen::updateVerbLine() _verbLineNum = %d; _verbLineX = %d; _verbLineY = %d; _verbLineWidth = %d; _verbLineCount = %d",
diff --git a/engines/toltecs/screen.h b/engines/toltecs/screen.h
index 6050257c1b..0e188607e6 100644
--- a/engines/toltecs/screen.h
+++ b/engines/toltecs/screen.h
@@ -120,8 +120,6 @@ protected:
byte *_fontData;
};
-//*BEGIN*TEST*CODE********************************************************************************************
-
struct PixelPacket {
byte count;
byte pixel;
@@ -142,157 +140,6 @@ protected:
SpriteDrawItem *_sprite;
};
-class SpriteReader : public SpriteFilter {
-public:
- SpriteReader(byte *source, SpriteDrawItem *sprite) : SpriteFilter(sprite), _source(source) {
- _curWidth = _sprite->origWidth;
- _curHeight = _sprite->origHeight;
- }
- SpriteReaderStatus readPacket(PixelPacket &packet) {
- if (_sprite->flags & 0x40) {
- // shadow sprite
- packet.count = _source[0] & 0x7F;
- if (_source[0] & 0x80)
- packet.pixel = 1;
- else
- packet.pixel = 0;
- _source++;
- } else if (_sprite->flags & 0x10) {
- // 256-color sprite
- packet.pixel = *_source++;
- packet.count = *_source++;
- } else {
- // 16-color sprite
- packet.count = _source[0] & 0x0F;
- packet.pixel = (_source[0] & 0xF0) >> 4;
- _source++;
- }
- _curWidth -= packet.count;
- if (_curWidth <= 0) {
- _curHeight--;
- if (_curHeight == 0) {
- return kSrsEndOfSprite;
- } else {
- _curWidth = _sprite->origWidth;
- return kSrsEndOfLine;
- }
- } else {
- return kSrsPixelsLeft;
- }
- }
- byte *getSource() {
- return _source;
- }
- void setSource(byte *source) {
- _source = source;
- _curHeight++;
- }
-protected:
- byte *_source;
- int16 _curWidth, _curHeight;
-};
-
-class SpriteFilterScaleDown : public SpriteFilter {
-public:
- SpriteFilterScaleDown(SpriteDrawItem *sprite, SpriteReader *reader) : SpriteFilter(sprite), _reader(reader) {
- _height = _sprite->height;
- _yerror = _sprite->yerror;
- _origHeight = _sprite->origHeight;
- _scalerStatus = 0;
- }
- SpriteReaderStatus readPacket(PixelPacket &packet) {
- SpriteReaderStatus status;
- if (_scalerStatus == 0) {
- _xerror = _sprite->xdelta;
- _yerror -= 100;
- while (_yerror <= 0) {
- do {
- status = _reader->readPacket(packet);
- } while (status == kSrsPixelsLeft);
- _yerror += _sprite->ydelta - 100;
- }
- if (status == kSrsEndOfSprite)
- return kSrsEndOfSprite;
- _scalerStatus = 1;
- }
- if (_scalerStatus == 1) {
- status = _reader->readPacket(packet);
- byte updcount = packet.count;
- while (updcount--) {
- _xerror -= 100;
- if (_xerror <= 0) {
- if (packet.count > 0)
- packet.count--;
- _xerror += _sprite->xdelta;
- }
- }
- if (status == kSrsEndOfLine) {
- if (--_height == 0)
- return kSrsEndOfSprite;
- _scalerStatus = 0;
- return kSrsEndOfLine;
- }
- }
- return kSrsPixelsLeft;
- }
-protected:
- SpriteReader *_reader;
- int16 _xerror, _yerror;
- int16 _height;
- int16 _origHeight;
- int _scalerStatus;
-};
-
-class SpriteFilterScaleUp : public SpriteFilter {
-public:
- SpriteFilterScaleUp(SpriteDrawItem *sprite, SpriteReader *reader) : SpriteFilter(sprite), _reader(reader) {
- _height = _sprite->height;
- _yerror = _sprite->yerror;
- _origHeight = _sprite->origHeight;
- _scalerStatus = 0;
- }
- SpriteReaderStatus readPacket(PixelPacket &packet) {
- SpriteReaderStatus status;
- if (_scalerStatus == 0) {
- _xerror = _sprite->xdelta;
- _sourcep = _reader->getSource();
- _scalerStatus = 1;
- }
- if (_scalerStatus == 1) {
- status = _reader->readPacket(packet);
- byte updcount = packet.count;
- while (updcount--) {
- _xerror -= 100;
- if (_xerror <= 0) {
- packet.count++;
- _xerror += _sprite->xdelta;
- }
- }
- if (status == kSrsEndOfLine) {
- if (--_height == 0)
- return kSrsEndOfSprite;
- _yerror -= 100;
- if (_yerror <= 0) {
- _reader->setSource(_sourcep);
- _yerror += _sprite->ydelta + 100;
- }
- _scalerStatus = 0;
- return kSrsEndOfLine;
- }
- }
- return kSrsPixelsLeft;
- }
-protected:
- SpriteReader *_reader;
- byte *_sourcep;
- int16 _xerror, _yerror;
- int16 _height;
- int16 _origHeight;
- int _scalerStatus;
-};
-
-//*END*TEST*CODE**********************************************************************************************
-
struct TextRect {
int16 x, y;
int16 width, length;
diff --git a/engines/toltecs/sprite.cpp b/engines/toltecs/sprite.cpp
new file mode 100644
index 0000000000..b9f8ffe0a4
--- /dev/null
+++ b/engines/toltecs/sprite.cpp
@@ -0,0 +1,535 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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.
+ *
+ *
+ */
+
+#include "common/events.h"
+#include "common/keyboard.h"
+#include "common/file.h"
+#include "common/savefile.h"
+#include "common/config-manager.h"
+
+#include "base/plugins.h"
+#include "base/version.h"
+
+#include "graphics/cursorman.h"
+
+#include "sound/mixer.h"
+
+#include "toltecs/toltecs.h"
+#include "toltecs/palette.h"
+#include "toltecs/resource.h"
+#include "toltecs/screen.h"
+#include "toltecs/script.h"
+#include "toltecs/segmap.h"
+
+namespace Toltecs {
+
+class SpriteReader : public SpriteFilter {
+public:
+ SpriteReader(byte *source, SpriteDrawItem *sprite) : SpriteFilter(sprite), _source(source) {
+ _curWidth = _sprite->origWidth;
+ _curHeight = _sprite->origHeight;
+ }
+ SpriteReaderStatus readPacket(PixelPacket &packet) {
+ if (_sprite->flags & 0x40) {
+ // shadow sprite
+ packet.count = _source[0] & 0x7F;
+ if (_source[0] & 0x80)
+ packet.pixel = 1;
+ else
+ packet.pixel = 0;
+ _source++;
+ } else if (_sprite->flags & 0x10) {
+ // 256-color sprite
+ packet.pixel = *_source++;
+ packet.count = *_source++;
+ } else {
+ // 16-color sprite
+ packet.count = _source[0] & 0x0F;
+ packet.pixel = (_source[0] & 0xF0) >> 4;
+ _source++;
+ }
+ _curWidth -= packet.count;
+ if (_curWidth <= 0) {
+ _curHeight--;
+ if (_curHeight == 0) {
+ return kSrsEndOfSprite;
+ } else {
+ _curWidth = _sprite->origWidth;
+ return kSrsEndOfLine;
+ }
+ } else {
+ return kSrsPixelsLeft;
+ }
+ }
+ byte *getSource() {
+ return _source;
+ }
+ void setSource(byte *source) {
+ _source = source;
+ _curHeight++;
+ }
+protected:
+ byte *_source;
+ int16 _curWidth, _curHeight;
+};
+
+class SpriteFilterScaleDown : public SpriteFilter {
+public:
+ SpriteFilterScaleDown(SpriteDrawItem *sprite, SpriteReader *reader) : SpriteFilter(sprite), _reader(reader) {
+ _height = _sprite->height;
+ _yerror = _sprite->yerror;
+ _origHeight = _sprite->origHeight;
+ _scalerStatus = 0;
+ }
+ SpriteReaderStatus readPacket(PixelPacket &packet) {
+ SpriteReaderStatus status;
+ if (_scalerStatus == 0) {
+ _xerror = _sprite->xdelta;
+ _yerror -= 100;
+ while (_yerror <= 0) {
+ do {
+ status = _reader->readPacket(packet);
+ } while (status == kSrsPixelsLeft);
+ _yerror += _sprite->ydelta - 100;
+ }
+ if (status == kSrsEndOfSprite)
+ return kSrsEndOfSprite;
+ _scalerStatus = 1;
+ }
+ if (_scalerStatus == 1) {
+ status = _reader->readPacket(packet);
+ byte updcount = packet.count;
+ while (updcount--) {
+ _xerror -= 100;
+ if (_xerror <= 0) {
+ if (packet.count > 0)
+ packet.count--;
+ _xerror += _sprite->xdelta;
+ }
+ }
+ if (status == kSrsEndOfLine) {
+ if (--_height == 0)
+ return kSrsEndOfSprite;
+ _scalerStatus = 0;
+ return kSrsEndOfLine;
+ }
+ }
+ return kSrsPixelsLeft;
+ }
+protected:
+ SpriteReader *_reader;
+ int16 _xerror, _yerror;
+ int16 _height;
+ int16 _origHeight;
+ int _scalerStatus;
+};
+
+class SpriteFilterScaleUp : public SpriteFilter {
+public:
+ SpriteFilterScaleUp(SpriteDrawItem *sprite, SpriteReader *reader) : SpriteFilter(sprite), _reader(reader) {
+ _height = _sprite->height;
+ _yerror = _sprite->yerror;
+ _origHeight = _sprite->origHeight;
+ _scalerStatus = 0;
+ }
+ SpriteReaderStatus readPacket(PixelPacket &packet) {
+ SpriteReaderStatus status;
+ if (_scalerStatus == 0) {
+ _xerror = _sprite->xdelta;
+ _sourcep = _reader->getSource();
+ _scalerStatus = 1;
+ }
+ if (_scalerStatus == 1) {
+ status = _reader->readPacket(packet);
+ byte updcount = packet.count;
+ while (updcount--) {
+ _xerror -= 100;
+ if (_xerror <= 0) {
+ packet.count++;
+ _xerror += _sprite->xdelta;
+ }
+ }
+ if (status == kSrsEndOfLine) {
+ if (--_height == 0)
+ return kSrsEndOfSprite;
+ _yerror -= 100;
+ if (_yerror <= 0) {
+ _reader->setSource(_sourcep);
+ _yerror += _sprite->ydelta + 100;
+ }
+ _scalerStatus = 0;
+ return kSrsEndOfLine;
+ }
+ }
+ return kSrsPixelsLeft;
+ }
+protected:
+ SpriteReader *_reader;
+ byte *_sourcep;
+ int16 _xerror, _yerror;
+ int16 _height;
+ int16 _origHeight;
+ int _scalerStatus;
+};
+
+void Screen::addDrawRequest(const DrawRequest &drawRequest) {
+
+ int16 scaleValueX, scaleValueY;
+ int16 xoffs, yoffs;
+ byte *spriteData;
+ int16 frameNum;
+
+ SpriteDrawItem sprite;
+ memset(&sprite, 0, sizeof(SpriteDrawItem));
+
+ if (drawRequest.flags == 0xFFFF)
+ return;
+
+ sprite.flags = 0;
+ sprite.baseColor = drawRequest.baseColor;
+ sprite.x = drawRequest.x;
+ sprite.y = drawRequest.y;
+ sprite.ybottom = drawRequest.y;
+ sprite.resIndex = drawRequest.resIndex;
+
+ spriteData = _vm->_res->load(drawRequest.resIndex);
+
+ if (drawRequest.flags & 0x1000) {
+ sprite.flags |= 4;
+ }
+
+ if (drawRequest.flags & 0x2000) {
+ sprite.flags |= 0x10;
+ }
+
+ if (drawRequest.flags & 0x4000) {
+ sprite.flags |= 0x40;
+ }
+
+ frameNum = drawRequest.flags & 0x0FFF;
+
+ // First initialize the sprite item with the values from the sprite resource
+
+ SpriteFrameEntry spriteFrameEntry(spriteData + frameNum * 12);
+
+ if (spriteFrameEntry.w == 0 || spriteFrameEntry.h == 0)
+ return;
+
+ sprite.offset = spriteFrameEntry.offset;
+
+ sprite.width = spriteFrameEntry.w;
+ sprite.height = spriteFrameEntry.h;
+
+ sprite.origWidth = spriteFrameEntry.w;
+ sprite.origHeight = spriteFrameEntry.h;
+
+ if (drawRequest.flags & 0x1000) {
+ xoffs = spriteFrameEntry.w - spriteFrameEntry.x;
+ } else {
+ xoffs = spriteFrameEntry.x;
+ }
+
+ yoffs = spriteFrameEntry.y;
+
+ // If the sprite should be scaled we need to initialize some values now
+
+ if (drawRequest.scaling != 0) {
+
+ byte scaleValue = ABS(drawRequest.scaling);
+
+ scaleValueX = scaleValue * sprite.origWidth;
+ sprite.xdelta = (10000 * sprite.origWidth) / scaleValueX;
+ scaleValueX /= 100;
+
+ scaleValueY = scaleValue * sprite.origHeight;
+ sprite.ydelta = (10000 * sprite.origHeight) / scaleValueY;
+ scaleValueY /= 100;
+
+ if (drawRequest.scaling > 0) {
+ sprite.flags |= 2;
+ sprite.width = sprite.origWidth + scaleValueX;
+ sprite.height = sprite.origHeight + scaleValueY;
+ xoffs += (xoffs * scaleValue) / 100;
+ yoffs += (yoffs * scaleValue) / 100;
+ } else {
+ sprite.flags |= 1;
+ sprite.width = sprite.origWidth - scaleValueX;
+ sprite.height = sprite.origHeight - 1 - scaleValueY;
+ if (sprite.width <= 0 || sprite.height <= 0)
+ return;
+ xoffs -= (xoffs * scaleValue) / 100;
+ yoffs -= (yoffs * scaleValue) / 100;
+ }
+
+ }
+
+ sprite.x -= xoffs;
+ sprite.y -= yoffs;
+
+ sprite.yerror = sprite.ydelta;
+
+ // Now we check if the sprite needs to be clipped
+
+ // Clip Y
+ if (sprite.y - _vm->_cameraY < 0) {
+
+ int16 clipHeight = ABS(sprite.y - _vm->_cameraY);
+ int16 chopHeight, skipHeight, lineWidth;
+ byte *spriteFrameData;
+
+ sprite.height -= clipHeight;
+ if (sprite.height <= 0)
+ return;
+
+ sprite.y = _vm->_cameraY;
+
+ // If the sprite is scaled
+ if (sprite.flags & 3) {
+ chopHeight = sprite.ydelta;
+ skipHeight = clipHeight;
+ if ((sprite.flags & 2) == 0) {
+ do {
+ chopHeight -= 100;
+ if (chopHeight <= 0) {
+ skipHeight++;
+ chopHeight += sprite.ydelta;
+ } else {
+ clipHeight--;
+ }
+ } while (clipHeight > 0);
+ } else {
+ do {
+ chopHeight -= 100;
+ if (chopHeight < 0) {
+ skipHeight--;
+ chopHeight += sprite.ydelta + 100;
+ }
+ clipHeight--;
+ } while (clipHeight > 0);
+ }
+ sprite.yerror = chopHeight;
+ }
+
+ spriteFrameData = spriteData + sprite.offset;
+
+ // Now the sprite's offset is adjusted to point to the starting line
+ if ((sprite.flags & 0x10) == 0) {
+ while (clipHeight--) {
+ lineWidth = 0;
+ while (lineWidth </*CHECKME was != */ sprite.origWidth) {
+ sprite.offset++;
+ lineWidth += (*spriteFrameData++) & 0x0F;
+ }
+ }
+ } else {
+ lineWidth = 0;
+ while (clipHeight--) {
+ while (lineWidth < sprite.origWidth) {
+ sprite.offset += 2;
+ spriteFrameData++;
+ lineWidth += *spriteFrameData++;
+ }
+ }
+ }
+
+ }
+
+ if (sprite.y + sprite.height - _vm->_cameraY - _vm->_cameraHeight > 0)
+ sprite.height -= sprite.y + sprite.height - _vm->_cameraY - _vm->_cameraHeight;
+ if (sprite.height <= 0)
+ return;
+
+ sprite.skipX = 0;
+
+ if (drawRequest.flags & 0x1000) {
+ // Left border
+ if (sprite.x - _vm->_cameraX < 0) {
+ sprite.width -= ABS(sprite.x - _vm->_cameraX);
+ sprite.x = _vm->_cameraX;
+ }
+ // Right border
+ if (sprite.x + sprite.width - _vm->_cameraX - 640 > 0) {
+ sprite.flags |= 8;
+ sprite.skipX = sprite.x + sprite.width - _vm->_cameraX - 640;
+ sprite.width -= sprite.skipX;
+ }
+ } else {
+ // Left border
+ if (sprite.x - _vm->_cameraX < 0) {
+ sprite.flags |= 8;
+ sprite.skipX = ABS(sprite.x - _vm->_cameraX);
+ sprite.width -= sprite.skipX;
+ sprite.x = _vm->_cameraX;
+ }
+ // Right border
+ if (sprite.x + sprite.width - _vm->_cameraX - 640 > 0) {
+ sprite.flags |= 8;
+ sprite.width -= sprite.x + sprite.width - _vm->_cameraX - 640;
+ }
+ }
+
+ if (sprite.width <= 0)
+ return;
+
+ // Add sprite sorted by priority
+ Common::List<SpriteDrawItem>::iterator iter = _spriteDrawList.begin();
+ while (iter != _spriteDrawList.end() && (*iter).ybottom <= sprite.ybottom) {
+ iter++;
+ }
+ _spriteDrawList.insert(iter, sprite);
+
+}
+
+void Screen::drawSprite(SpriteDrawItem *sprite) {
+
+ debug(0, "Screen::drawSprite() x = %d; y = %d; flags = %04X; resIndex = %d; offset = %08X; drawX = %d; drawY = %d",
+ sprite->x, sprite->y, sprite->flags, sprite->resIndex, sprite->offset,
+ sprite->x - _vm->_cameraX, sprite->y - _vm->_cameraY);
+ debug(0, "Screen::drawSprite() width = %d; height = %d; origWidth = %d; origHeight = %d",
+ sprite->width, sprite->height, sprite->origWidth, sprite->origHeight);
+
+ byte *source = _vm->_res->load(sprite->resIndex) + sprite->offset;
+ byte *dest = _frontScreen + (sprite->x - _vm->_cameraX) + (sprite->y - _vm->_cameraY) * 640;
+
+ SpriteReader spriteReader(source, sprite);
+
+ if (sprite->flags & 0x40) {
+ // Shadow sprites
+ if (sprite->flags & 1) {
+ SpriteFilterScaleDown spriteScaler(sprite, &spriteReader);
+ drawSpriteCore(dest, spriteScaler, sprite);
+ } else if (sprite->flags & 2) {
+ SpriteFilterScaleUp spriteScaler(sprite, &spriteReader);
+ drawSpriteCore(dest, spriteScaler, sprite);
+ } else {
+ drawSpriteCore(dest, spriteReader, sprite);
+ }
+ } else if (sprite->flags & 0x10) {
+ // 256 color sprite
+ drawSpriteCore(dest, spriteReader, sprite);
+ } else {
+ // 16 color sprite
+ if (sprite->flags & 1) {
+ SpriteFilterScaleDown spriteScaler(sprite, &spriteReader);
+ drawSpriteCore(dest, spriteScaler, sprite);
+ } else if (sprite->flags & 2) {
+ SpriteFilterScaleUp spriteScaler(sprite, &spriteReader);
+ drawSpriteCore(dest, spriteScaler, sprite);
+ } else {
+ drawSpriteCore(dest, spriteReader, sprite);
+ }
+ }
+
+ debug(0, "Screen::drawSprite() ok");
+
+}
+
+void Screen::drawSpriteCore(byte *dest, SpriteFilter &reader, SpriteDrawItem *sprite) {
+
+ int16 destInc;
+
+ if (sprite->flags & 4) {
+ destInc = -1;
+ dest += sprite->width;
+ } else {
+ destInc = 1;
+ }
+
+ SpriteReaderStatus status;
+ PixelPacket packet;
+
+ byte *destp = dest;
+ int16 skipX = sprite->skipX;
+
+ int16 w = sprite->width;
+ int16 h = sprite->height;
+
+ do {
+ status = reader.readPacket(packet);
+
+ if (skipX > 0) {
+ while (skipX > 0) {
+ skipX -= packet.count;
+ if (skipX < 0) {
+ packet.count = ABS(skipX);
+ break;
+ }
+ status = reader.readPacket(packet);
+ }
+ }
+
+ if (w - packet.count < 0)
+ packet.count = w;
+
+ w -= packet.count;
+
+ if (((sprite->flags & 0x40) && (packet.pixel != 0)) ||
+ ((sprite->flags & 0x10) && (packet.pixel != 0xFF)) ||
+ !(sprite->flags & 0x10) && (packet.pixel != 0))
+ {
+ if (sprite->flags & 0x40) {
+ while (packet.count--) {
+ *dest = _vm->_palette->getColorTransPixel(*dest);
+ dest += destInc;
+ }
+ } else {
+ if (sprite->flags & 0x10) {
+ packet.pixel = ((packet.pixel << 4) & 0xF0) | ((packet.pixel >> 4) & 0x0F);
+ } else {
+ packet.pixel += sprite->baseColor - 1;
+ }
+ while (packet.count--) {
+ *dest = packet.pixel;
+ dest += destInc;
+ }
+ }
+ } else {
+ dest += packet.count * destInc;
+ }
+
+ if (status == kSrsEndOfLine || w <= 0) {
+ if (w <= 0) {
+ while (status == kSrsPixelsLeft) {
+ status = reader.readPacket(packet);
+ }
+ }
+ dest = destp + 640;
+ destp = dest;
+ skipX = sprite->skipX;
+ w = sprite->width;
+ h--;
+ }
+
+ } while (status != kSrsEndOfSprite && h > 0);
+
+}
+
+void Screen::drawSprites() {
+ for (Common::List<SpriteDrawItem>::iterator iter = _spriteDrawList.begin(); iter != _spriteDrawList.end(); iter++) {
+ SpriteDrawItem *sprite = &(*iter);
+ drawSprite(sprite);
+ _vm->_segmap->restoreMasksBySprite(sprite);
+ }
+}
+
+} // End of namespace Toltecs