From 5117482f7960018d184938447a3a10991472f4dc Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 22 Jul 2015 21:02:29 -0400 Subject: [PATCH] SHERLOCK: RT: Implement maskArea --- engines/sherlock/surface.cpp | 5 -- engines/sherlock/surface.h | 2 - engines/sherlock/tattoo/tattoo.cpp | 6 +- .../sherlock/tattoo/tattoo_user_interface.cpp | 57 ++++++++++++++----- .../sherlock/tattoo/tattoo_user_interface.h | 9 ++- 5 files changed, 53 insertions(+), 26 deletions(-) diff --git a/engines/sherlock/surface.cpp b/engines/sherlock/surface.cpp index 42194de7a3b6..9e84e290e751 100644 --- a/engines/sherlock/surface.cpp +++ b/engines/sherlock/surface.cpp @@ -299,9 +299,4 @@ void Surface::writeFancyString(const Common::String &str, const Common::Point &p writeString(str, Common::Point(pt.x + 1, pt.y + 1), overrideColor2); } -void Surface::maskArea(const ImageFrame &src, const Common::Point &pt) { - // TODO - error("TODO: maskArea"); -} - } // End of namespace Sherlock diff --git a/engines/sherlock/surface.h b/engines/sherlock/surface.h index 38e33396178b..dd1a199b1fc3 100644 --- a/engines/sherlock/surface.h +++ b/engines/sherlock/surface.h @@ -142,8 +142,6 @@ class Surface: public Fonts { void fill(uint16 color); - void maskArea(const ImageFrame &src, const Common::Point &pt); - /** * Clear the surface */ diff --git a/engines/sherlock/tattoo/tattoo.cpp b/engines/sherlock/tattoo/tattoo.cpp index 920bef1a4cab..aa8404f4daab 100644 --- a/engines/sherlock/tattoo/tattoo.cpp +++ b/engines/sherlock/tattoo/tattoo.cpp @@ -89,11 +89,11 @@ void TattooEngine::startScene() { case 53: case 68: // Load overlay mask(s) for the scene - ui._mask = new ImageFile(Common::String::format("res%02d.msk", _scene->_goToScene)); + ui._mask = _res->load(Common::String::format("res%02d.msk", _scene->_goToScene)); if (_scene->_goToScene == 8) - ui._mask1 = new ImageFile("res08a.msk"); + ui._mask1 = _res->load("res08a.msk"); else if (_scene->_goToScene == 18 || _scene->_goToScene == 68) - ui._mask1 = new ImageFile("res08a.msk"); + ui._mask1 = _res->load("res08a.msk"); break; case OVERHEAD_MAP: diff --git a/engines/sherlock/tattoo/tattoo_user_interface.cpp b/engines/sherlock/tattoo/tattoo_user_interface.cpp index 731c215a2733..751a46208853 100644 --- a/engines/sherlock/tattoo/tattoo_user_interface.cpp +++ b/engines/sherlock/tattoo/tattoo_user_interface.cpp @@ -750,50 +750,77 @@ void TattooUserInterface::doBgAnimEraseBackground() { void TattooUserInterface::drawMaskArea(bool mode) { Scene &scene = *_vm->_scene; - Screen &screen = *_vm->_screen; int xp = mode ? _maskOffset.x : 0; if (_mask != nullptr) { switch (scene._currentScene) { case 7: - screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x - SHERLOCK_SCREEN_WIDTH, 110)); - screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x, 110)); - screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x + SHERLOCK_SCREEN_WIDTH, 110)); + maskArea(*_mask, Common::Point(_maskOffset.x - SHERLOCK_SCREEN_WIDTH, 110)); + maskArea(*_mask, Common::Point(_maskOffset.x, 110)); + maskArea(*_mask, Common::Point(_maskOffset.x + SHERLOCK_SCREEN_WIDTH, 110)); break; case 8: - screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x - SHERLOCK_SCREEN_WIDTH, 180)); - screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x, 180)); - screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x + SHERLOCK_SCREEN_WIDTH, 180)); + maskArea(*_mask, Common::Point(_maskOffset.x - SHERLOCK_SCREEN_WIDTH, 180)); + maskArea(*_mask, Common::Point(_maskOffset.x, 180)); + maskArea(*_mask, Common::Point(_maskOffset.x + SHERLOCK_SCREEN_WIDTH, 180)); if (!_vm->readFlags(880)) - screen._backBuffer1.maskArea((*_mask1)[0], Common::Point(940, 300)); + maskArea(*_mask1, Common::Point(940, 300)); break; case 18: - screen._backBuffer1.maskArea((*_mask)[0], Common::Point(xp, 203)); + maskArea(*_mask, Common::Point(xp, 203)); if (!_vm->readFlags(189)) - screen._backBuffer1.maskArea((*_mask1)[0], Common::Point(124 + xp, 239)); + maskArea(*_mask1, Common::Point(124 + xp, 239)); break; case 53: - screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x, 110)); + maskArea(*_mask, Common::Point(_maskOffset.x, 110)); if (mode) - screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x - SHERLOCK_SCREEN_WIDTH, 110)); + maskArea(*_mask, Common::Point(_maskOffset.x - SHERLOCK_SCREEN_WIDTH, 110)); break; case 68: - screen._backBuffer1.maskArea((*_mask)[0], Common::Point(xp, 203)); - screen._backBuffer1.maskArea((*_mask1)[0], Common::Point(124 + xp, 239)); + maskArea(*_mask, Common::Point(xp, 203)); + maskArea(*_mask1, Common::Point(124 + xp, 239)); break; } } } +void TattooUserInterface::maskArea(Common::SeekableReadStream &mask, const Common::Point &pt) { + Screen &screen = *_vm->_screen; + Surface &bb1 = screen._backBuffer1; + mask.seek(0); + int xSize = mask.readUint16LE(); + int ySize = mask.readUint16LE(); + int pixel, len, xp, yp; + + for (yp = 0; yp < ySize; ++yp) { + byte *ptr = bb1.getBasePtr(pt.x, pt.y + yp); + + for (xp = 0; xp < xSize;) { + // The mask data consists of pairs of pixel/lengths, where all non-zero pixels means that the + // given pixel on the back buffer is darkened (the mask pixel value isn't otherwise used) + pixel = mask.readByte(); + len = mask.readByte(); + + for (; len > 0; --len, ++xp, ++ptr) { + if (pixel && (pt.x + xp) >= screen._currentScroll.x && (pt.x + xp) < (screen._currentScroll.x + SHERLOCK_SCREEN_WIDTH)) { + *ptr = _lookupTable1[*ptr]; + } + } + } + + assert(xp == xSize); + } +} + void TattooUserInterface::makeBGArea(const Common::Rect &r) { Screen &screen = *_vm->_screen; for (int yp = r.top; yp < r.bottom; ++yp) { - byte *ptr = screen._backBuffer1.getBasePtr(r.left, yp); + byte *ptr = screen._backBuffer1.getBasePtr(r.left + screen._currentScroll.x, yp); for (int xp = r.left; xp < r.right; ++xp, ++ptr) *ptr = _lookupTable[*ptr]; diff --git a/engines/sherlock/tattoo/tattoo_user_interface.h b/engines/sherlock/tattoo/tattoo_user_interface.h index b16f91134b4b..56d895dbfd8e 100644 --- a/engines/sherlock/tattoo/tattoo_user_interface.h +++ b/engines/sherlock/tattoo/tattoo_user_interface.h @@ -103,7 +103,7 @@ class TattooUserInterface : public UserInterface { Common::KeyState _keyState; Common::Point _lookPos; ScrollHighlight _scrollHighlight; - ImageFile *_mask, *_mask1; + Common::SeekableReadStream *_mask, *_mask1; Common::Point _maskOffset; int _maskCounter; ImageFile *_interfaceImages; @@ -180,6 +180,13 @@ class TattooUserInterface : public UserInterface { void drawMaskArea(bool mode); + /** + * Takes the data passed in the image and apply it to the surface at the given position. + * The src mask data is encoded with a different color for each item. To highlight one, + the runs that do not match the highlight number will be darkened + */ + void maskArea(Common::SeekableReadStream &mask, const Common::Point &pt); + /** * Translate a given area of the back buffer to greyscale shading */