aboutsummaryrefslogtreecommitdiff
path: root/engines/director
diff options
context:
space:
mode:
authorstevenhoefel2017-01-09 09:46:51 +1100
committerEugene Sandulenko2017-01-09 00:05:06 +0100
commit41ee83e3f02144da364b98b8f5b974087e6dac89 (patch)
tree66f2dee3ea886771e4159be756ee73b3381a4ae1 /engines/director
parent8c3c9df3508bdb18f0b083de93f0e88983660028 (diff)
downloadscummvm-rg350-41ee83e3f02144da364b98b8f5b974087e6dac89.tar.gz
scummvm-rg350-41ee83e3f02144da364b98b8f5b974087e6dac89.tar.bz2
scummvm-rg350-41ee83e3f02144da364b98b8f5b974087e6dac89.zip
DIRECTOR: D4 Image Decoding, Buttons, Text, Shapes.
Diffstat (limited to 'engines/director')
-rw-r--r--engines/director/frame.cpp360
-rw-r--r--engines/director/frame.h8
-rw-r--r--engines/director/images.cpp118
-rw-r--r--engines/director/images.h19
-rw-r--r--engines/director/sprite.h3
5 files changed, 376 insertions, 132 deletions
diff --git a/engines/director/frame.cpp b/engines/director/frame.cpp
index de0de6d4d0..7c52cf8ba7 100644
--- a/engines/director/frame.cpp
+++ b/engines/director/frame.cpp
@@ -114,54 +114,61 @@ void Frame::readChannel(Common::SeekableSubReadStreamEndian &stream, uint16 offs
}
void Frame::readChannels(Common::ReadStreamEndian *stream) {
- _actionId = stream->readByte();
- _soundType1 = stream->readByte(); // type: 0x17 for sounds (sound is cast id), 0x16 for MIDI (sound is cmd id)
- uint8 transFlags = stream->readByte(); // 0x80 is whole stage (vs changed area), rest is duration in 1/4ths of a second
-
- if (transFlags & 0x80)
- _transArea = 1;
- else
- _transArea = 0;
- _transDuration = transFlags & 0x7f;
-
- _transChunkSize = stream->readByte();
- _tempo = stream->readByte();
- _transType = static_cast<TransitionType>(stream->readByte());
- _sound1 = stream->readUint16();
- if (_vm->getPlatform() == Common::kPlatformMacintosh) {
- _sound2 = stream->readUint16();
- _soundType2 = stream->readByte();
- } else {
- byte unk[3];
- stream->read(unk, 3);
- warning("unk1: %x unk2: %x unk3: %x", unk[0], unk[1], unk[2]);
- }
- _skipFrameFlag = stream->readByte();
- _blend = stream->readByte();
+ byte unk[16];
- if (_vm->getPlatform() != Common::kPlatformMacintosh) {
- _sound2 = stream->readUint16();
- _soundType2 = stream->readByte();
- }
+ if (_vm->getVersion() < 4) {
+ _actionId = stream->readByte();
+ _soundType1 = stream->readByte(); // type: 0x17 for sounds (sound is cast id), 0x16 for MIDI (sound is cmd id)
+ uint8 transFlags = stream->readByte(); // 0x80 is whole stage (vs changed area), rest is duration in 1/4ths of a second
- uint16 palette = stream->readUint16();
+ if (transFlags & 0x80)
+ _transArea = 1;
+ else
+ _transArea = 0;
+ _transDuration = transFlags & 0x7f;
+
+ _transChunkSize = stream->readByte();
+ _tempo = stream->readByte();
+ _transType = static_cast<TransitionType>(stream->readByte());
+ _sound1 = stream->readUint16();
+ if (_vm->getPlatform() == Common::kPlatformMacintosh) {
+ _sound2 = stream->readUint16();
+ _soundType2 = stream->readByte();
+ } else {
+ stream->read(unk, 3);
+ warning("unk1: %x unk2: %x unk3: %x", unk[0], unk[1], unk[2]);
+ }
+ _skipFrameFlag = stream->readByte();
+ _blend = stream->readByte();
- if (palette) {
- warning("STUB: Palette info");
- }
+ if (_vm->getPlatform() != Common::kPlatformMacintosh) {
+ _sound2 = stream->readUint16();
+ _soundType2 = stream->readByte();
+ }
- debugC(kDebugLoading, 8, "%d %d %d %d %d %d %d %d %d %d %d", _actionId, _soundType1, _transDuration, _transChunkSize, _tempo, _transType, _sound1, _skipFrameFlag, _blend, _sound2, _soundType2);
+ uint16 palette = stream->readUint16();
- _palette = new PaletteInfo();
- _palette->firstColor = stream->readByte(); // for cycles. note: these start at 0x80 (for pal entry 0)!
- _palette->lastColor = stream->readByte();
- _palette->flags = stream->readByte();
- _palette->speed = stream->readByte();
- _palette->frameCount = stream->readUint16();
+ if (palette) {
+ warning("STUB: Palette info");
+ }
+
+ debugC(kDebugLoading, 8, "%d %d %d %d %d %d %d %d %d %d %d", _actionId, _soundType1, _transDuration, _transChunkSize, _tempo, _transType, _sound1, _skipFrameFlag, _blend, _sound2, _soundType2);
+
+ _palette = new PaletteInfo();
+ _palette->firstColor = stream->readByte(); // for cycles. note: these start at 0x80 (for pal entry 0)!
+ _palette->lastColor = stream->readByte();
+ _palette->flags = stream->readByte();
+ _palette->speed = stream->readByte();
+ _palette->frameCount = stream->readUint16();
+
+ _palette->cycleCount = stream->readUint16();
+ } else if (_vm->getVersion() < 5) {
+ stream->read(unk, 16);
+ _actionId = stream->readUint16();
+ stream->read(unk, 5);
+ }
- _palette->cycleCount = stream->readUint16();
- byte unk[11];
stream->read(unk, 6);
if (_vm->getPlatform() == Common::kPlatformMacintosh) {
@@ -181,8 +188,9 @@ void Frame::readChannels(Common::ReadStreamEndian *stream) {
for (int i = 0; i < CHANNEL_COUNT; i++) {
Sprite &sprite = *_sprites[i + 1];
- sprite._x1 = stream->readByte();
- sprite._enabled = (stream->readByte() != 0);
+ sprite._scriptId = stream->readByte();
+ sprite._spriteType = stream->readByte();
+ sprite._enabled = sprite._spriteType != 0;
sprite._x2 = stream->readUint16();
sprite._flags = stream->readUint16();
@@ -199,8 +207,6 @@ void Frame::readChannels(Common::ReadStreamEndian *stream) {
sprite._height = stream->readUint16();
sprite._width = stream->readUint16();
- debugC(kDebugLoading, 8, "%03d(%d)[%x,%x,%04x,%d/%d/%d/%d]", sprite._castId, sprite._enabled, sprite._x1, sprite._x2, sprite._flags, sprite._startPoint.x, sprite._startPoint.y, sprite._width, sprite._height);
-
if (_vm->getPlatform() == Common::kPlatformMacintosh && _vm->getVersion() >= 4) {
sprite._scriptId = stream->readUint16();
sprite._flags2 = stream->readByte(); // 0x40 editable, 0x80 moveable
@@ -209,6 +215,10 @@ void Frame::readChannels(Common::ReadStreamEndian *stream) {
if (_vm->getVersion() >= 5)
sprite._unk3 = stream->readUint32();
}
+
+ debugC(kDebugLoading, 8, "%03d(%d)[%x,%x,%04x,%d/%d/%d/%d] script:%d",
+ sprite._castId, sprite._enabled, sprite._x1, sprite._x2, sprite._flags,
+ sprite._startPoint.x, sprite._startPoint.y, sprite._width, sprite._height, sprite._scriptId);
}
}
@@ -360,6 +370,7 @@ void Frame::readSprite(Common::SeekableSubReadStreamEndian &stream, uint16 offse
}
void Frame::prepareFrame(Score *score) {
+ _drawRects.clear();
renderSprites(*score->_surface, false);
renderSprites(*score->_trailSurface, true);
@@ -529,82 +540,144 @@ void Frame::renderSprites(Graphics::ManagedSurface &surface, bool renderTrail) {
if ((_sprites[i]->_trails == 0 && renderTrail) || (_sprites[i]->_trails == 1 && !renderTrail))
continue;
+ CastType castType;
Cast *cast;
- if (!_vm->_currentScore->_casts.contains(_sprites[i]->_castId)) {
- if (!_vm->getSharedCasts()->contains(_sprites[i]->_castId)) {
- warning("Cast id %d not found", _sprites[i]->_castId);
- continue;
- } else {
- warning("Getting cast id %d from shared cast", _sprites[i]->_castId);
- cast = _vm->getSharedCasts()->getVal(_sprites[i]->_castId);
+ if (_vm->getVersion() < 4) {
+ switch (_sprites[i]->_spriteType) {
+ case 0x01:
+ case 0x0c: //this is actually a mouse-over shape? I don't think it's a real button.
+ castType = kCastBitmap;
+ break;
+ case 0x02:
+ castType = kCastShape;
+ break;
+ case 0x07:
+ castType = kCastText;
+ break;
}
} else {
- cast = _vm->_currentScore->_casts[_sprites[i]->_castId];
- }
-
- if (cast->type == kCastText) {
- renderText(surface, i);
- continue;
+ if (!_vm->_currentScore->_casts.contains(_sprites[i]->_castId)) {
+ if (!_vm->getSharedCasts()->contains(_sprites[i]->_castId)) {
+ warning("Cast id %d not found", _sprites[i]->_castId);
+ continue;
+ } else {
+ warning("Getting cast id %d from shared cast", _sprites[i]->_castId);
+ cast = _vm->getSharedCasts()->getVal(_sprites[i]->_castId);
+ }
+ } else {
+ cast = _vm->_currentScore->_casts[_sprites[i]->_castId];
+ }
+ castType = cast->type;
}
- Image::ImageDecoder *img = getImageFrom(_sprites[i]->_castId);
+ //this needs precedence to be hit first... D3 does something really tricky with cast IDs for shapes.
+ //I don't like this implementation 100% as the 'cast' above might not actually hit a member and be null?
+ if (castType == kCastShape) {
+ renderShape(surface, i);
+ } else if (castType == kCastText) {
+ renderText(surface, i, _vm->getVersion() < 4 ? _sprites[i]->_castId + 1024 : cast->children[0].index);
+ } else if (castType == kCastButton) {
+ renderButton(surface, i, _vm->getVersion() < 4 ? _sprites[i]->_castId + 1024 : cast->children[0].index);
+ } else {
+ Image::ImageDecoder *img = getImageFrom(_sprites[i]->_castId);
- if (!img) {
- warning("Image with id %d not found", _sprites[i]->_castId);
- continue;
- }
+ if (!img) {
+ warning("Image with id %d not found", _sprites[i]->_castId);
+ continue;
+ }
- if (!img->getSurface()) {
- warning("Frame::renderSprites: Could not load image %d", _sprites[i]->_castId);
- continue;
- }
+ if (!img->getSurface()) {
+ warning("Frame::renderSprites: Could not load image %d", _sprites[i]->_castId);
+ continue;
+ }
- assert(_sprites[i]->_cast);
-
- uint32 regX = static_cast<BitmapCast *>(_sprites[i]->_cast)->regX;
- uint32 regY = static_cast<BitmapCast *>(_sprites[i]->_cast)->regY;
- uint32 rectLeft = static_cast<BitmapCast *>(_sprites[i]->_cast)->initialRect.left;
- uint32 rectTop = static_cast<BitmapCast *>(_sprites[i]->_cast)->initialRect.top;
-
- int x = _sprites[i]->_startPoint.x - regX + rectLeft;
- int y = _sprites[i]->_startPoint.y - regY + rectTop;
- int height = _sprites[i]->_height;
- int width = _sprites[i]->_width;
-
- Common::Rect drawRect = Common::Rect(x, y, x + width, y + height);
- _drawRects.push_back(drawRect);
-
- switch (_sprites[i]->_ink) {
- case kInkTypeCopy:
- surface.blitFrom(*img->getSurface(), Common::Point(x, y));
- break;
- case kInkTypeTransparent:
- // FIXME: is it always white (last entry in pallette)?
- surface.transBlitFrom(*img->getSurface(), Common::Point(x, y), _vm->getPaletteColorCount() - 1);
- break;
- case kInkTypeBackgndTrans:
- drawBackgndTransSprite(surface, *img->getSurface(), drawRect);
- break;
- case kInkTypeMatte:
- drawMatteSprite(surface, *img->getSurface(), drawRect);
- break;
- case kInkTypeGhost:
- drawGhostSprite(surface, *img->getSurface(), drawRect);
- break;
- case kInkTypeReverse:
- drawReverseSprite(surface, *img->getSurface(), drawRect);
- break;
- default:
- warning("Unhandled ink type %d", _sprites[i]->_ink);
- surface.blitFrom(*img->getSurface(), Common::Point(x, y));
- break;
+ assert(_sprites[i]->_cast);
+
+ uint32 regX = static_cast<BitmapCast *>(_sprites[i]->_cast)->regX;
+ uint32 regY = static_cast<BitmapCast *>(_sprites[i]->_cast)->regY;
+ uint32 rectLeft = static_cast<BitmapCast *>(_sprites[i]->_cast)->initialRect.left;
+ uint32 rectTop = static_cast<BitmapCast *>(_sprites[i]->_cast)->initialRect.top;
+
+ int x = _sprites[i]->_startPoint.x - regX + rectLeft;
+ int y = _sprites[i]->_startPoint.y - regY + rectTop;
+ int height = _sprites[i]->_height;
+ int width = _sprites[i]->_width;
+
+ Common::Rect drawRect = Common::Rect(x, y, x + width, y + height);
+ _drawRects[i] = drawRect;
+
+ switch (_sprites[i]->_ink) {
+ case kInkTypeCopy:
+ surface.blitFrom(*img->getSurface(), Common::Point(x, y));
+ break;
+ case kInkTypeTransparent:
+ // FIXME: is it always white (last entry in pallette)?
+ surface.transBlitFrom(*img->getSurface(), Common::Point(x, y), _vm->getPaletteColorCount() - 1);
+ break;
+ case kInkTypeBackgndTrans:
+ drawBackgndTransSprite(surface, *img->getSurface(), drawRect);
+ break;
+ case kInkTypeMatte:
+ drawMatteSprite(surface, *img->getSurface(), drawRect);
+ break;
+ case kInkTypeGhost:
+ drawGhostSprite(surface, *img->getSurface(), drawRect);
+ break;
+ case kInkTypeReverse:
+ drawReverseSprite(surface, *img->getSurface(), drawRect);
+ break;
+ default:
+ warning("Unhandled ink type %d", _sprites[i]->_ink);
+ surface.blitFrom(*img->getSurface(), Common::Point(x, y));
+ break;
+ }
}
}
}
}
-void Frame::renderButton(Graphics::ManagedSurface &surface, uint16 spriteId) {
- renderText(surface, spriteId);
+void Frame::renderShape(Graphics::ManagedSurface &surface, uint16 spriteID) {
+ Common::Rect r = Common::Rect(_sprites[spriteID]->_startPoint.x,
+ _sprites[spriteID]->_startPoint.y,
+ _sprites[spriteID]->_startPoint.x + _sprites[spriteID]->_width,
+ _sprites[spriteID]->_startPoint.y + _sprites[spriteID]->_height);
+
+ Graphics::Surface tmpSurface;
+ tmpSurface.create(r.width(), r.height(), Graphics::PixelFormat::createFormatCLUT8());
+
+ tmpSurface.fillRect(Common::Rect(r.width(), r.height()), 0);
+
+ switch (_sprites[spriteID]->_ink) {
+ case kInkTypeCopy:
+ surface.blitFrom(tmpSurface, Common::Point(_sprites[spriteID]->_startPoint.x, _sprites[spriteID]->_startPoint.y));
+ break;
+ case kInkTypeTransparent:
+ // FIXME: is it always white (last entry in pallette)?
+ surface.transBlitFrom(tmpSurface, Common::Point(_sprites[spriteID]->_startPoint.x, _sprites[spriteID]->_startPoint.y), _vm->getPaletteColorCount() - 1);
+ break;
+ case kInkTypeBackgndTrans:
+ drawBackgndTransSprite(surface, tmpSurface, r);
+ break;
+ case kInkTypeMatte:
+ drawMatteSprite(surface, tmpSurface, r);
+ break;
+ case kInkTypeGhost:
+ drawGhostSprite(surface, tmpSurface, r);
+ break;
+ case kInkTypeReverse:
+ drawReverseSprite(surface, tmpSurface, r);
+ break;
+ default:
+ warning("Unhandled ink type %d", _sprites[spriteID]->_ink);
+ surface.blitFrom(tmpSurface, Common::Point(_sprites[spriteID]->_startPoint.x, _sprites[spriteID]->_startPoint.y));
+ break;
+ }
+
+ _drawRects[spriteID] = r;
+}
+
+void Frame::renderButton(Graphics::ManagedSurface &surface, uint16 spriteId, uint16 textId) {
+ renderText(surface, spriteId, _vm->getMainArchive()->getResource(MKTAG('S', 'T', 'X', 'T'), textId), true);
uint16 castID = _sprites[spriteId]->_castId;
ButtonCast *button = static_cast<ButtonCast *>(_vm->_currentScore->_casts[castID]);
@@ -617,13 +690,19 @@ void Frame::renderButton(Graphics::ManagedSurface &surface, uint16 spriteId) {
int height = _sprites[spriteId]->_height;
int width = _sprites[spriteId]->_width;
+ Common::Rect _rect;
+
switch (button->buttonType) {
case kTypeCheckBox:
// Magic numbers: checkbox square need to move left about 5px from text and 12px side size (D4)
- surface.frameRect(Common::Rect(x - 17, y, x + 12, y + 12), 0);
+ _rect = Common::Rect(x - 17, y, x + 12, y + 12);
+ surface.frameRect(_rect, 0);
+ _drawRects[spriteId] = _rect;
break;
case kTypeButton:
- surface.frameRect(Common::Rect(x, y, x + width, y + height), 0);
+ _rect = Common::Rect(x, y, x + width, y + height);
+ surface.frameRect(_rect, 0);
+ _drawRects[spriteId] = _rect;
break;
case kTypeRadio:
warning("STUB: renderButton: kTypeRadio");
@@ -633,6 +712,10 @@ void Frame::renderButton(Graphics::ManagedSurface &surface, uint16 spriteId) {
Image::ImageDecoder *Frame::getImageFrom(uint16 spriteId) {
uint16 imgId = spriteId + 1024;
+
+ if (_vm->getVersion() >= 4 && _vm->_currentScore->_casts[spriteId]->children.size() > 0)
+ imgId = _vm->_currentScore->_casts[spriteId]->children[0].index;
+
Image::ImageDecoder *img = NULL;
if (_vm->_currentScore->getArchive()->hasResource(MKTAG('D', 'I', 'B', ' '), imgId)) {
@@ -650,13 +733,20 @@ Image::ImageDecoder *Frame::getImageFrom(uint16 spriteId) {
if (_vm->_currentScore->getArchive()->hasResource(MKTAG('B', 'I', 'T', 'D'), imgId)) {
Common::SeekableReadStream *pic = _vm->_currentScore->getArchive()->getResource(MKTAG('B', 'I', 'T', 'D'), imgId);
- if (_vm->getVersion() <= 4) {
+ if (_vm->getVersion() < 4) {
BitmapCast *bc = static_cast<BitmapCast *>(_vm->_currentScore->_casts[spriteId]);
int w = bc->initialRect.width(), h = bc->initialRect.height();
debugC(2, kDebugImages, "id: %d, w: %d, h: %d, flags: %x, some: %x, unk1: %d, unk2: %d",
imgId, w, h, bc->flags, bc->someFlaggyThing, bc->unk1, bc->unk2);
img = new BITDDecoder(w, h);
+ } else if (_vm->getVersion() < 6) {
+ BitmapCast *bc = static_cast<BitmapCast *>(_vm->_currentScore->_casts[spriteId]);
+ int w = bc->initialRect.width(), h = bc->initialRect.height();
+
+ debugC(2, kDebugImages, "id: %d, w: %d, h: %d, flags: %x, some: %x, unk1: %d, unk2: %d",
+ imgId, w, h, bc->flags, bc->someFlaggyThing, bc->unk1, bc->unk2);
+ img = new BITDDecoderV4(w, h);
} else {
img = new Image::BitmapDecoder();
}
@@ -666,6 +756,7 @@ Image::ImageDecoder *Frame::getImageFrom(uint16 spriteId) {
byte buf[1024];
int n = s->read(buf, 1024);
Common::hexdump(buf, n);
+ s->seek(0);
}
img->loadStream(*pic);
@@ -683,17 +774,26 @@ Image::ImageDecoder *Frame::getImageFrom(uint16 spriteId) {
}
-void Frame::renderText(Graphics::ManagedSurface &surface, uint16 spriteID) {
- uint16 castID = _sprites[spriteID]->_castId;
-
- TextCast *textCast = static_cast<TextCast *>(_vm->_currentScore->_casts[castID]);
- Common::SeekableSubReadStreamEndian *textStream;
+void Frame::renderText(Graphics::ManagedSurface &surface, uint16 spriteID, uint16 castID) {
+ Common::SeekableSubReadStreamEndian *textStream = NULL;
- if (_vm->_currentScore->_movieArchive->hasResource(MKTAG('S','T','X','T'), castID + 1024)) {
- textStream = _vm->_currentScore->_movieArchive->getResource(MKTAG('S','T','X','T'), castID + 1024);
- } else {
+ if (_vm->_currentScore->_movieArchive->hasResource(MKTAG('S', 'T', 'X', 'T'), castID)) {
+ textStream = _vm->_currentScore->_movieArchive->getResource(MKTAG('S', 'T', 'X', 'T'), castID);
+ } else if (_vm->getSharedSTXT() != nullptr) {
textStream = _vm->getSharedSTXT()->getVal(spriteID + 1024);
}
+
+ renderText(surface, spriteID, textStream, false);
+}
+
+void Frame::renderText(Graphics::ManagedSurface &surface, uint16 spriteID, Common::SeekableSubReadStreamEndian *textStream, bool isButtonLabel) {
+ if (textStream == NULL) return;
+
+ uint16 castID = _sprites[spriteID]->_castId;
+ TextCast *textCast = static_cast<TextCast *>(_vm->_currentScore->_casts[castID]);
+
+
+
uint32 unk1 = textStream->readUint32();
uint32 strLen = textStream->readUint32();
uint32 dataLen = textStream->readUint32();
@@ -711,11 +811,11 @@ void Frame::renderText(Graphics::ManagedSurface &surface, uint16 spriteID) {
if (strLen < 200)
debugC(3, kDebugText, "text: '%s'", text.c_str());
- uint32 rectLeft = static_cast<TextCast *>(_sprites[spriteID]->_cast)->initialRect.left;
- uint32 rectTop = static_cast<TextCast *>(_sprites[spriteID]->_cast)->initialRect.top;
+ uint32 rectLeft = textCast->initialRect.left;
+ uint32 rectTop = textCast->initialRect.top;
- int x = _sprites[spriteID]->_startPoint.x + rectLeft;
- int y = _sprites[spriteID]->_startPoint.y + rectTop;
+ int x = _sprites[spriteID]->_startPoint.x;// +rectLeft;
+ int y = _sprites[spriteID]->_startPoint.y;// +rectTop;
int height = _sprites[spriteID]->_height;
int width = _sprites[spriteID]->_width;
@@ -730,7 +830,11 @@ void Frame::renderText(Graphics::ManagedSurface &surface, uint16 spriteID) {
debugC(3, kDebugText, "renderText: x: %d y: %d w: %d h: %d font: '%s'", x, y, width, height, _vm->_wm->_fontMan->getFontName(macFont));
- font->drawString(&surface, text, x, y, width, 0);
+ //TODO: the colour is wrong here... need to determine the correct colour for all versions!
+ font->drawString(&surface, text, x, y, width, (_sprites[spriteID]->_ink == kInkTypeReverse ? 255 : 0), (Graphics::TextAlign)textCast->textAlign);
+
+ if (isButtonLabel)
+ return;
if (textCast->borderSize != kSizeNone) {
uint16 size = textCast->borderSize;
@@ -884,10 +988,10 @@ void Frame::drawMatteSprite(Graphics::ManagedSurface &target, const Graphics::Su
uint16 Frame::getSpriteIDFromPos(Common::Point pos) {
// Find first from top to bottom
- for (uint16 i = _drawRects.size() - 1; i > 0; i--) {
- if (_drawRects[i].contains(pos))
- return i;
- }
+ //TODO: THIS NEEDS TO BE REVERSED!
+ for (Common::HashMap<uint16, Common::Rect>::const_iterator dr = _drawRects.begin(); dr != _drawRects.end(); dr++)
+ if (dr->_value.contains(pos))
+ return dr->_key;
return 0;
}
diff --git a/engines/director/frame.h b/engines/director/frame.h
index ce82fa527c..29ae9dd596 100644
--- a/engines/director/frame.h
+++ b/engines/director/frame.h
@@ -119,8 +119,10 @@ private:
void playTransition(Score *score);
void playSoundChannel();
void renderSprites(Graphics::ManagedSurface &surface, bool renderTrail);
- void renderText(Graphics::ManagedSurface &surface, uint16 spriteId);
- void renderButton(Graphics::ManagedSurface &surface, uint16 spriteId);
+ void renderText(Graphics::ManagedSurface &surface, uint16 spriteId, uint16 castID);
+ void renderText(Graphics::ManagedSurface &surface, uint16 spriteID, Common::SeekableSubReadStreamEndian *textStream, bool isButtonLabel);
+ void renderShape(Graphics::ManagedSurface &surface, uint16 spriteID);
+ void renderButton(Graphics::ManagedSurface &surface, uint16 spriteId, uint16 textId);
void readPaletteInfo(Common::SeekableSubReadStreamEndian &stream);
void readSprite(Common::SeekableSubReadStreamEndian &stream, uint16 offset, uint16 size);
void readMainChannels(Common::SeekableSubReadStreamEndian &stream, uint16 offset, uint16 size);
@@ -148,7 +150,7 @@ public:
uint8 _skipFrameFlag;
uint8 _blend;
Common::Array<Sprite *> _sprites;
- Common::Array<Common::Rect > _drawRects;
+ Common::HashMap<uint16, Common::Rect> _drawRects;
DirectorEngine *_vm;
};
diff --git a/engines/director/images.cpp b/engines/director/images.cpp
index 0ec84af0d3..9b55402a18 100644
--- a/engines/director/images.cpp
+++ b/engines/director/images.cpp
@@ -201,4 +201,122 @@ bool BITDDecoder::loadStream(Common::SeekableReadStream &stream) {
return true;
}
+/****************************
+* BITD V4+
+****************************/
+
+BITDDecoderV4::BITDDecoderV4(int w, int h) {
+ _surface = new Graphics::Surface();
+
+ // We make the surface pitch a multiple of 16.
+ int pitch = w;
+ if (w % 16)
+ pitch += 16 - (w % 16);
+
+ // HACK: Create a padded surface by adjusting w after create()
+ _surface->create(pitch, h, Graphics::PixelFormat::createFormatCLUT8());
+ _surface->w = w;
+
+ _palette = new byte[256 * 3];
+
+ _palette[0] = _palette[1] = _palette[2] = 0;
+ _palette[255 * 3 + 0] = _palette[255 * 3 + 1] = _palette[255 * 3 + 2] = 0xff;
+
+ _paletteColorCount = 2;
+}
+
+BITDDecoderV4::~BITDDecoderV4() {
+ destroy();
+}
+
+void BITDDecoderV4::destroy() {
+ _surface = 0;
+
+ delete[] _palette;
+ _palette = 0;
+ _paletteColorCount = 0;
+}
+
+void BITDDecoderV4::loadPalette(Common::SeekableReadStream &stream) {
+ // no op
+}
+
+bool BITDDecoderV4::loadStream(Common::SeekableReadStream &stream) {
+ int x = 0, y = 0;
+
+ // If the stream has exactly the required number of bits for this image,
+ // we assume it is uncompressed.
+ if (stream.size() * 8 == _surface->pitch * _surface->h) {
+ debugC(3, kDebugImages, "Skipping compression");
+ for (y = 0; y < _surface->h; y++) {
+ for (x = 0; x < _surface->pitch; ) {
+ byte color = stream.readByte();
+ for (int c = 0; c < 8; c++)
+ *((byte *)_surface->getBasePtr(x++, y)) = (color & (1 << (7 - c))) ? 0 : 0xff;
+ }
+ }
+
+ return true;
+ }
+
+ Common::Array<int> pixels;
+ pixels.reserve(4096);
+
+ while (!stream.eos()) {
+ int data = stream.readByte();
+ int len = data + 1;
+ if ((data & 0x80) != 0) {
+ len = ((data ^ 0xFF) & 0xff) + 2;
+ data = stream.readByte();
+ for (int p = 0; p < len; p++) {
+ pixels.push_back(data);
+ //*((byte *)_surface->getBasePtr(x, y)) = data;
+ }
+ //data = stream.readByte();
+ } else {
+ for (int p = 0; p < len; p++) {
+ data = stream.readByte();
+ pixels.push_back(data);
+ }
+ }
+ //if (bpp == 32 && pixels.Count % (w * 3) == 0)
+ // source += 2;
+ }
+
+ if (pixels.size() > 0) {
+ //this needs to be calculated a lot earlier!
+ int bpp = pixels.size() / (_surface->w * _surface->h);
+ switch (bpp) {
+ case 1:
+ for (uint pix = 0; pix < pixels.size(); pix++) {
+ //this calculation is wrong.. need a demo with colours.
+ *((byte *)_surface->getBasePtr(x, y)) = 0xff - pixels[pix];
+ x++;
+ if (x == _surface->w) {
+ y++;
+ x = 0;
+ }
+ }
+ break;
+ /*
+ case 32:
+ SetPixel(x, y, Color.FromArgb(
+ pixels[((y * dxr.nodes[c].w) * 3) + x],
+ pixels[(((y * dxr.nodes[c].w) * 3) + (dxr.nodes[c].w)) + x],
+ pixels[(((y * dxr.nodes[c].w) * 3) + (2 * dxr.nodes[c].w)) + x]));
+ break;
+ case 16:
+ SetPixel(x, y, Color.FromArgb(
+ (pixels[((y * dxr.nodes[c].w) * 2) + x] & 0x7c) << 1,
+ (pixels[((y * dxr.nodes[c].w) * 2) + x] & 0x03) << 6 |
+ (pixels[((y * dxr.nodes[c].w) * 2) + (dxr.nodes[c].w) + x] & 0xe0) >> 2,
+ (pixels[((y * dxr.nodes[c].w) * 2) + (dxr.nodes[c].w) + x] & 0x1f) << 3));
+ break;
+ */
+ }
+ }
+
+ return true;
+}
+
} // End of namespace Director
diff --git a/engines/director/images.h b/engines/director/images.h
index 54e824588f..3be0e11a9e 100644
--- a/engines/director/images.h
+++ b/engines/director/images.h
@@ -81,6 +81,25 @@ private:
uint8 _paletteColorCount;
};
+class BITDDecoderV4 : public Image::ImageDecoder {
+public:
+ BITDDecoderV4(int w, int h);
+ virtual ~BITDDecoderV4();
+
+ // ImageDecoder API
+ void destroy();
+ virtual bool loadStream(Common::SeekableReadStream &stream);
+ virtual const Graphics::Surface *getSurface() const { return _surface; }
+ const byte *getPalette() const { return _palette; }
+ void loadPalette(Common::SeekableReadStream &stream);
+ uint16 getPaletteColorCount() const { return _paletteColorCount; }
+
+private:
+ Graphics::Surface *_surface;
+ byte *_palette;
+ uint8 _paletteColorCount;
+};
+
} // End of namespace Director
#endif
diff --git a/engines/director/sprite.h b/engines/director/sprite.h
index d248036693..d9b7729a87 100644
--- a/engines/director/sprite.h
+++ b/engines/director/sprite.h
@@ -106,7 +106,8 @@ public:
uint32 _unk3;
bool _enabled;
- byte _castId;
+ uint16 _castId;
+ byte _spriteType;
InkType _ink;
uint16 _trails;
Cast *_cast;