diff options
author | stevenhoefel | 2017-01-09 09:46:51 +1100 |
---|---|---|
committer | Eugene Sandulenko | 2017-01-09 00:05:06 +0100 |
commit | 41ee83e3f02144da364b98b8f5b974087e6dac89 (patch) | |
tree | 66f2dee3ea886771e4159be756ee73b3381a4ae1 /engines/director/frame.cpp | |
parent | 8c3c9df3508bdb18f0b083de93f0e88983660028 (diff) | |
download | scummvm-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/frame.cpp')
-rw-r--r-- | engines/director/frame.cpp | 360 |
1 files changed, 232 insertions, 128 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; } |