From 40501547f42b6202a15582d974d88776d759aacb Mon Sep 17 00:00:00 2001 From: stevenhoefel Date: Fri, 10 Apr 2020 22:38:12 +1000 Subject: [PATCH] DIRECTOR: Extend Reverse Sprite drawing for shapes and controls. Translate 32-bit images into palette-based sprites. --- engines/director/frame.cpp | 59 ++++++++++++++++------- engines/director/frame.h | 4 +- engines/director/images.cpp | 95 ++++++++++++++++++++++++++----------- engines/director/images.h | 5 +- engines/director/score.cpp | 2 +- 5 files changed, 113 insertions(+), 52 deletions(-) diff --git a/engines/director/frame.cpp b/engines/director/frame.cpp index 02397797c58..145e24805d8 100644 --- a/engines/director/frame.cpp +++ b/engines/director/frame.cpp @@ -650,7 +650,7 @@ void Frame::renderSprites(Graphics::ManagedSurface &surface, bool renderTrail) { int width = _vm->getVersion() > 4 ? bc->_initialRect.width() : _sprites[i]->_width; Common::Rect drawRect(x, y, x + width, y + height); addDrawRect(i, drawRect); - inkBasedBlit(surface, *(bc->_surface), ink, drawRect); + inkBasedBlit(surface, *(bc->_surface), ink, drawRect, i); } } } @@ -671,9 +671,7 @@ void Frame::renderShape(Graphics::ManagedSurface &surface, uint16 spriteId) { byte backColor = sp->_backColor; int lineSize = sp->_thickness & 0x3; - // D3 Shared Cast Members don't have these values specified, they're provided when you add - // them to the score in each movie. - if (_vm->getVersion() > 3 && spriteType == kCastMemberSprite) { + if (_vm->getVersion() >= 3 && spriteType == kCastMemberSprite) { if (!sp->_cast) { warning("Frame::renderShape(): kCastMemberSprite has no cast defined"); return; @@ -698,10 +696,12 @@ void Frame::renderShape(Graphics::ManagedSurface &surface, uint16 spriteId) { default: break; } - foreColor = sc->_fgCol; - backColor = sc->_bgCol; - lineSize = sc->_lineThickness; - ink = sc->_ink; + if (_vm->getVersion() > 3) { + foreColor = sc->_fgCol; + backColor = sc->_bgCol; + lineSize = sc->_lineThickness; + ink = sc->_ink; + } // shapes should be rendered with transparency by default if (ink == kInkTypeCopy) { ink = kInkTypeTransparent; @@ -778,7 +778,7 @@ void Frame::renderShape(Graphics::ManagedSurface &surface, uint16 spriteId) { } addDrawRect(spriteId, shapeRect); - inkBasedBlit(surface, tmpSurface, ink, shapeRect); + inkBasedBlit(surface, tmpSurface, ink, shapeRect, spriteId); } @@ -1025,10 +1025,10 @@ void Frame::renderText(Graphics::ManagedSurface &surface, uint16 spriteId, Commo if (spriteId == _vm->getCurrentScore()->_currentMouseDownSpriteId) ink = kInkTypeReverse; - inkBasedBlit(surface, textWithFeatures, ink, Common::Rect(x, y, x + width, y + height)); + inkBasedBlit(surface, textWithFeatures, ink, Common::Rect(x, y, x + width, y + height), spriteId); } -void Frame::inkBasedBlit(Graphics::ManagedSurface &targetSurface, const Graphics::Surface &spriteSurface, InkType ink, Common::Rect drawRect) { +void Frame::inkBasedBlit(Graphics::ManagedSurface &targetSurface, const Graphics::Surface &spriteSurface, InkType ink, Common::Rect drawRect, uint spriteId) { // drawRect could be bigger than the spriteSurface. Clip it Common::Rect t(spriteSurface.w, spriteSurface.h); t.moveTo(drawRect.left, drawRect.top); @@ -1052,7 +1052,7 @@ void Frame::inkBasedBlit(Graphics::ManagedSurface &targetSurface, const Graphics drawGhostSprite(targetSurface, spriteSurface, drawRect); break; case kInkTypeReverse: - drawReverseSprite(targetSurface, spriteSurface, drawRect); + drawReverseSprite(targetSurface, spriteSurface, drawRect, spriteId); break; default: warning("Frame::inkBasedBlit(): Unhandled ink type %d", ink); @@ -1103,7 +1103,7 @@ void Frame::drawGhostSprite(Graphics::ManagedSurface &target, const Graphics::Su } } -void Frame::drawReverseSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect) { +void Frame::drawReverseSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect, uint16 spriteId) { Common::Rect srcRect(sprite.w, sprite.h); if (!target.clip(srcRect, drawRect)) @@ -1113,14 +1113,37 @@ void Frame::drawReverseSprite(Graphics::ManagedSurface &target, const Graphics:: for (int ii = 0; ii < srcRect.height(); ii++) { const byte *src = (const byte *)sprite.getBasePtr(srcRect.left, srcRect.top + ii); byte *dst = (byte *)target.getBasePtr(drawRect.left, drawRect.top + ii); + byte srcColor = *src; for (int j = 0; j < srcRect.width(); j++) { - if ((getSpriteIDFromPos(Common::Point(drawRect.left + j, drawRect.top + ii)) != 0)) { - if (*src != skipColor) { - *dst ^= _vm->transformColor(*src); + if (_sprites[spriteId]->_cast->_type == kCastShape) + srcColor = 0x0; + else + srcColor = *src; + uint16 targetSprite = getSpriteIDFromPos(Common::Point(drawRect.left + j, drawRect.top + ii)); + if ((targetSprite != 0)) { + // TODO: This entire reverse colour attempt needs a lot more testing on + // a lot more colour depths. + if (srcColor != skipColor) { + if (_sprites[targetSprite]->_cast->_type != kCastBitmap) { + if (*dst == 0 || *dst == 255) { + *dst = _vm->transformColor(*dst); + } else if (srcColor == 255 || srcColor == 0) { + *dst = _vm->transformColor(*dst - 40); + } else { + *dst = _vm->transformColor(*src - 40); + } + } else { + if (*dst == 0 && _vm->getVersion() == 3 && + ((BitmapCast*)_sprites[spriteId]->_cast)->_bitsPerPixel > 1) { + *dst = _vm->transformColor(*src - 40); + } else { + *dst ^= _vm->transformColor(srcColor); + } + } } - } else if (*src != skipColor) { - *dst = *src; + } else if (srcColor != skipColor) { + *dst = _vm->transformColor(srcColor); } src++; dst++; diff --git a/engines/director/frame.h b/engines/director/frame.h index fb9cdd253d2..1205daef5d4 100644 --- a/engines/director/frame.h +++ b/engines/director/frame.h @@ -94,8 +94,8 @@ private: void drawBackgndTransSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect); void drawMatteSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect); void drawGhostSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect); - void drawReverseSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect); - void inkBasedBlit(Graphics::ManagedSurface &targetSurface, const Graphics::Surface &spriteSurface, InkType ink, Common::Rect drawRect); + void drawReverseSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect, uint16 spriteId); + void inkBasedBlit(Graphics::ManagedSurface &targetSurface, const Graphics::Surface &spriteSurface, InkType ink, Common::Rect drawRect, uint spriteId); void addDrawRect(uint16 entityId, Common::Rect &rect); public: diff --git a/engines/director/images.cpp b/engines/director/images.cpp index 7e65d3aa2c6..129f3937905 100644 --- a/engines/director/images.cpp +++ b/engines/director/images.cpp @@ -103,7 +103,7 @@ bool DIBDecoder::loadStream(Common::SeekableReadStream &stream) { * BITD ****************************/ -BITDDecoder::BITDDecoder(int w, int h, uint16 bitsPerPixel, uint16 pitch) { +BITDDecoder::BITDDecoder(int w, int h, uint16 bitsPerPixel, uint16 pitch, const byte *palette) { _surface = new Graphics::Surface(); if (pitch < w) { @@ -133,12 +133,10 @@ BITDDecoder::BITDDecoder(int w, int h, uint16 bitsPerPixel, uint16 pitch) { _surface->create(pitch, h, pf); _surface->w = w; - _palette = new byte[256 * 3]; + _palette = palette; - _palette[0] = _palette[1] = _palette[2] = 0; - _palette[255 * 3 + 0] = _palette[255 * 3 + 1] = _palette[255 * 3 + 2] = 0xff; - - _paletteColorCount = 2; + // TODO: Bring this in from the main surface? + _paletteColorCount = 255; _bitsPerPixel = bitsPerPixel; } @@ -152,8 +150,6 @@ void BITDDecoder::destroy() { delete _surface; _surface = 0; - delete[] _palette; - _palette = 0; _paletteColorCount = 0; } @@ -161,6 +157,42 @@ void BITDDecoder::loadPalette(Common::SeekableReadStream &stream) { // no op } +void BITDDecoder::convertPixelIntoSurface(void* surfacePointer, uint fromBpp, uint toBpp, int red, int green, int blue) { + // Initial implementation of 32-bit images to palettised sprites. + switch (fromBpp) { + case 4: + switch (toBpp) { + case 1: + if (red == 255 && blue == 255 && green == 255) { + *((byte*)surfacePointer) = 255; + } else if (red == 0 && blue == 0 && green == 0) { + *((byte*)surfacePointer) = 0; + } else { + for (byte p = 0; p < _paletteColorCount; p++) + { + if (_palette[p * 3 + 0] == red && + _palette[p * 3 + 1] == green && + _palette[p * 3 + 2] == blue) + { + *((byte*)surfacePointer) = p; + } + } + } + break; + + default: + warning("BITDDecoder::convertPixelIntoSurface(): conversion from %d to %d not implemented", + fromBpp, toBpp); + } + break; + + default: + warning("BITDDecoder::convertPixelIntoSurface(): could not convert from %d to %d", + fromBpp, toBpp); + break; + } +} + bool BITDDecoder::loadStream(Common::SeekableReadStream &stream) { int x = 0, y = 0; @@ -180,26 +212,30 @@ bool BITDDecoder::loadStream(Common::SeekableReadStream &stream) { } Common::Array pixels; - 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(); + // TODO: D3 32-bit bitmap casts seem to just be ARGB pixels in a row and not RLE. + // Determine how to distinguish these different types. Maybe stage version. + if (_bitsPerPixel == 32) { + int data = stream.readByte(); + pixels.push_back(data); } else { - for (int p = 0; p < len; p++) { + int data = stream.readByte(); + int len = data + 1; + if ((data & 0x80) != 0) { + len = ((data ^ 0xFF) & 0xff) + 2; data = stream.readByte(); - pixels.push_back(data); + for (int p = 0; p < len; p++) { + pixels.push_back(data); + } + } else { + for (int p = 0; p < len; p++) { + data = stream.readByte(); + pixels.push_back(data); + } } + if (_bitsPerPixel == 32 && pixels.size() % (_surface->w * 3) == 0) + stream.readUint16BE(); } - if (_bitsPerPixel == 32 && pixels.size() % (_surface->w * 3) == 0) - stream.readUint16BE(); } if (pixels.size() < (uint32)_surface->w * _surface->h) { @@ -220,12 +256,11 @@ bool BITDDecoder::loadStream(Common::SeekableReadStream &stream) { for (y = 0; y < _surface->h; y++) { for (x = 0; x < _surface->w;) { switch (_bitsPerPixel) { - case 1: { + case 1: for (int c = 0; c < 8 && x < _surface->w; c++, x++) { *((byte *)_surface->getBasePtr(x, y)) = (pixels[(((y * _surface->pitch) + x) / 8)] & (1 << (7 - c))) ? 0 : 0xff; } break; - } case 8: // this calculation is wrong.. need a demo with colours. @@ -243,10 +278,12 @@ bool BITDDecoder::loadStream(Common::SeekableReadStream &stream) { break; case 32: - *((uint32*)_surface->getBasePtr(x, y)) = _surface->format.RGBToColor( - pixels[((y * _surface->w) * 3) + x], - pixels[(((y * _surface->w) * 3) + (_surface->w)) + x], - pixels[(((y * _surface->w) * 3) + (2 * _surface->w)) + x]); + convertPixelIntoSurface(_surface->getBasePtr(x, y), + (_bitsPerPixel / 8), + _surface->format.bytesPerPixel, + pixels[(((y * (_surface->w * 4))) + ((x * 4) + 1))], + pixels[(((y * (_surface->w * 4))) + ((x * 4) + 2))], + pixels[(((y * (_surface->w * 4))) + ((x * 4) + 3))]); x++; break; diff --git a/engines/director/images.h b/engines/director/images.h index c87796f6a0d..8a6c5e7f7af 100644 --- a/engines/director/images.h +++ b/engines/director/images.h @@ -61,7 +61,7 @@ private: class BITDDecoder : public Image::ImageDecoder { public: - BITDDecoder(int w, int h, uint16 bitsPerPixel, uint16 pitch); + BITDDecoder(int w, int h, uint16 bitsPerPixel, uint16 pitch, const byte *palette); ~BITDDecoder() override; // ImageDecoder API @@ -71,10 +71,11 @@ public: const byte *getPalette() const override { return _palette; } void loadPalette(Common::SeekableReadStream &stream); uint16 getPaletteColorCount() const override { return _paletteColorCount; } + void convertPixelIntoSurface(void* surfacePointer, uint fromBpp, uint toBpp, int red, int green, int blue); private: Graphics::Surface *_surface; - byte *_palette; + const byte *_palette; uint8 _paletteColorCount; uint16 _bitsPerPixel; }; diff --git a/engines/director/score.cpp b/engines/director/score.cpp index a0df293bb52..09ff870567c 100644 --- a/engines/director/score.cpp +++ b/engines/director/score.cpp @@ -376,7 +376,7 @@ void Score::loadSpriteImages(bool isSharedCast) { if (w > 0 && h > 0) { if (_vm->getVersion() < 6) { - img = new BITDDecoder(w, h, bitmapCast->_bitsPerPixel, bitmapCast->_pitch); + img = new BITDDecoder(w, h, bitmapCast->_bitsPerPixel, bitmapCast->_pitch, _vm->getPalette()); } else { img = new Image::BitmapDecoder(); }