From 5e52b0a5d46e4c5b230cba7464301484d27804f7 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Sat, 10 Mar 2012 13:50:27 -0500 Subject: MOHAWK: Split the graphics classes into their own files --- engines/mohawk/graphics.cpp | 1001 +------------------------------------------ 1 file changed, 1 insertion(+), 1000 deletions(-) (limited to 'engines/mohawk/graphics.cpp') diff --git a/engines/mohawk/graphics.cpp b/engines/mohawk/graphics.cpp index 2ffabf1e8c..a08d034ef7 100644 --- a/engines/mohawk/graphics.cpp +++ b/engines/mohawk/graphics.cpp @@ -20,30 +20,13 @@ * */ +#include "mohawk/mohawk.h" #include "mohawk/resource.h" #include "mohawk/graphics.h" -#include "mohawk/livingbooks.h" -#include "common/substream.h" #include "common/system.h" -#include "common/textconsole.h" #include "engines/util.h" #include "graphics/palette.h" -#include "graphics/primitives.h" -#include "gui/message.h" - -#ifdef ENABLE_CSTIME -#include "mohawk/cstime.h" -#endif - -#ifdef ENABLE_MYST -#include "mohawk/myst.h" -#include "graphics/jpeg.h" -#endif - -#ifdef ENABLE_RIVEN -#include "mohawk/riven.h" -#endif namespace Mohawk { @@ -262,986 +245,4 @@ void GraphicsManager::addImageToCache(uint16 id, MohawkSurface *surface) { _cache[id] = surface; } -#ifdef ENABLE_MYST - -MystGraphics::MystGraphics(MohawkEngine_Myst* vm) : GraphicsManager(), _vm(vm) { - _bmpDecoder = new MystBitmap(); - - _viewport = Common::Rect(544, 332); - - // The original version of Myst could run in 8bpp color too. - // However, it dithered videos to 8bpp and they looked considerably - // worse (than they already did :P). So we're not even going to - // support 8bpp mode in Myst (Myst ME required >8bpp anyway). - initGraphics(_viewport.width(), _viewport.height(), true, NULL); // What an odd screen size! - - _pixelFormat = _vm->_system->getScreenFormat(); - - if (_pixelFormat.bytesPerPixel == 1) - error("Myst requires greater than 256 colors to run"); - - if (_vm->getFeatures() & GF_ME) { - _jpegDecoder = new Graphics::JPEG(); - _pictDecoder = new Graphics::PictDecoder(_pixelFormat); - } else { - _jpegDecoder = NULL; - _pictDecoder = NULL; - } - - _pictureFile.entries = NULL; - - // Initialize our buffer - _backBuffer = new Graphics::Surface(); - _backBuffer->create(_vm->_system->getWidth(), _vm->_system->getHeight(), _pixelFormat); - - _nextAllowedDrawTime = _vm->_system->getMillis(); - _enableDrawingTimeSimulation = 0; -} - -MystGraphics::~MystGraphics() { - delete _bmpDecoder; - delete _jpegDecoder; - delete _pictDecoder; - delete[] _pictureFile.entries; - - _backBuffer->free(); - delete _backBuffer; -} - -static const char *s_picFileNames[] = { - "CHpics", - "", - "", - "DUpics", - "INpics", - "", - "MEpics", - "MYpics", - "SEpics", - "", - "", - "STpics" -}; - -void MystGraphics::loadExternalPictureFile(uint16 stack) { - if (_vm->getPlatform() != Common::kPlatformMacintosh) - return; - - if (_pictureFile.picFile.isOpen()) - _pictureFile.picFile.close(); - delete[] _pictureFile.entries; - - if (!scumm_stricmp(s_picFileNames[stack], "")) - return; - - if (!_pictureFile.picFile.open(s_picFileNames[stack])) - error ("Could not open external picture file \'%s\'", s_picFileNames[stack]); - - _pictureFile.pictureCount = _pictureFile.picFile.readUint32BE(); - _pictureFile.entries = new PictureFile::PictureEntry[_pictureFile.pictureCount]; - - for (uint32 i = 0; i < _pictureFile.pictureCount; i++) { - _pictureFile.entries[i].offset = _pictureFile.picFile.readUint32BE(); - _pictureFile.entries[i].size = _pictureFile.picFile.readUint32BE(); - _pictureFile.entries[i].id = _pictureFile.picFile.readUint16BE(); - _pictureFile.entries[i].type = _pictureFile.picFile.readUint16BE(); - _pictureFile.entries[i].width = _pictureFile.picFile.readUint16BE(); - _pictureFile.entries[i].height = _pictureFile.picFile.readUint16BE(); - } -} - -MohawkSurface *MystGraphics::decodeImage(uint16 id) { - MohawkSurface *mhkSurface = 0; - - // Myst ME uses JPEG/PICT images instead of compressed Windows Bitmaps for room images, - // though there are a few weird ones that use that format. For further nonsense with images, - // the Macintosh version stores images in external "picture files." We check them before - // going to check for a PICT resource. - if (_vm->getFeatures() & GF_ME && _vm->getPlatform() == Common::kPlatformMacintosh && _pictureFile.picFile.isOpen()) { - for (uint32 i = 0; i < _pictureFile.pictureCount; i++) - if (_pictureFile.entries[i].id == id) { - if (_pictureFile.entries[i].type == 0) { - Common::SeekableReadStream *stream = new Common::SeekableSubReadStream(&_pictureFile.picFile, _pictureFile.entries[i].offset, _pictureFile.entries[i].offset + _pictureFile.entries[i].size); - - if (!_jpegDecoder->read(stream)) - error("Could not decode Myst ME Mac JPEG"); - - mhkSurface = new MohawkSurface(_jpegDecoder->getSurface(_pixelFormat)); - delete stream; - } else if (_pictureFile.entries[i].type == 1) { - mhkSurface = new MohawkSurface(_pictDecoder->decodeImage(new Common::SeekableSubReadStream(&_pictureFile.picFile, _pictureFile.entries[i].offset, _pictureFile.entries[i].offset + _pictureFile.entries[i].size))); - } else - error ("Unknown Picture File type %d", _pictureFile.entries[i].type); - break; - } - } - - // We're not using the external Mac files, so it's time to delve into the main Mohawk - // archives. However, we still don't know if it's a PICT or WDIB resource. If it's Myst - // ME it's most likely a PICT, and if it's original it's definitely a WDIB. However, - // Myst ME throws us another curve ball in that PICT resources can contain WDIB's instead - // of PICT's. - if (!mhkSurface) { - bool isPict = false; - Common::SeekableReadStream *dataStream = NULL; - - if (_vm->getFeatures() & GF_ME && _vm->hasResource(ID_PICT, id)) { - // The PICT resource exists. However, it could still contain a MystBitmap - // instead of a PICT image... - dataStream = _vm->getResource(ID_PICT, id); - } else // No PICT, so the WDIB must exist. Let's go grab it. - dataStream = _vm->getResource(ID_WDIB, id); - - if (_vm->getFeatures() & GF_ME) { - // Here we detect whether it's really a PICT or a WDIB. Since a MystBitmap - // would be compressed, there's no way to detect for the BM without a hack. - // So, we search for the PICT version opcode for detection. - dataStream->seek(512 + 10); // 512 byte pict header - isPict = (dataStream->readUint32BE() == 0x001102FF); - dataStream->seek(0); - } - - if (isPict) - mhkSurface = new MohawkSurface(_pictDecoder->decodeImage(dataStream)); - else { - mhkSurface = _bmpDecoder->decodeImage(dataStream); - mhkSurface->convertToTrueColor(); - } - } - - assert(mhkSurface); - return mhkSurface; -} - -void MystGraphics::copyImageSectionToScreen(uint16 image, Common::Rect src, Common::Rect dest) { - Graphics::Surface *surface = findImage(image)->getSurface(); - - // Make sure the image is bottom aligned in the dest rect - dest.top = dest.bottom - MIN(surface->h, dest.height()); - - // Convert from bitmap coordinates to surface coordinates - uint16 top = surface->h - (src.top + MIN(surface->h, dest.height())); - - // Do not draw the top pixels if the image is too tall - if (dest.height() > _viewport.height()) - top += dest.height() - _viewport.height(); - - // Clip the destination rect to the screen - if (dest.right > _vm->_system->getWidth() || dest.bottom > _vm->_system->getHeight()) - dest.debugPrint(4, "Clipping destination rect to the screen"); - dest.right = CLIP(dest.right, 0, _vm->_system->getWidth()); - dest.bottom = CLIP(dest.bottom, 0, _vm->_system->getHeight()); - - uint16 width = MIN(surface->w, dest.width()); - uint16 height = MIN(surface->h, dest.height()); - - // Clamp Width and Height to within src surface dimensions - if (src.left + width > surface->w) - width = surface->w - src.left; - if (src.top + height > surface->h) - height = surface->h - src.top; - - debug(3, "MystGraphics::copyImageSectionToScreen()"); - debug(3, "\tImage: %d", image); - debug(3, "\tsrc.left: %d", src.left); - debug(3, "\tsrc.top: %d", src.top); - debug(3, "\tdest.left: %d", dest.left); - debug(3, "\tdest.top: %d", dest.top); - debug(3, "\twidth: %d", width); - debug(3, "\theight: %d", height); - - simulatePreviousDrawDelay(dest); - - _vm->_system->copyRectToScreen((byte *)surface->getBasePtr(src.left, top), surface->pitch, dest.left, dest.top, width, height); -} - -void MystGraphics::copyImageSectionToBackBuffer(uint16 image, Common::Rect src, Common::Rect dest) { - Graphics::Surface *surface = findImage(image)->getSurface(); - - // Make sure the image is bottom aligned in the dest rect - dest.top = dest.bottom - MIN(surface->h, dest.height()); - - // Convert from bitmap coordinates to surface coordinates - uint16 top = surface->h - (src.top + MIN(surface->h, dest.height())); - - // Do not draw the top pixels if the image is too tall - if (dest.height() > _viewport.height()) { - top += dest.height() - _viewport.height(); - } - - // Clip the destination rect to the screen - if (dest.right > _vm->_system->getWidth() || dest.bottom > _vm->_system->getHeight()) - dest.debugPrint(4, "Clipping destination rect to the screen"); - dest.right = CLIP(dest.right, 0, _vm->_system->getWidth()); - dest.bottom = CLIP(dest.bottom, 0, _vm->_system->getHeight()); - - uint16 width = MIN(surface->w, dest.width()); - uint16 height = MIN(surface->h, dest.height()); - - // Clamp Width and Height to within src surface dimensions - if (src.left + width > surface->w) - width = surface->w - src.left; - if (src.top + height > surface->h) - height = surface->h - src.top; - - debug(3, "MystGraphics::copyImageSectionToBackBuffer()"); - debug(3, "\tImage: %d", image); - debug(3, "\tsrc.left: %d", src.left); - debug(3, "\tsrc.top: %d", src.top); - debug(3, "\tdest.left: %d", dest.left); - debug(3, "\tdest.top: %d", dest.top); - debug(3, "\twidth: %d", width); - debug(3, "\theight: %d", height); - - for (uint16 i = 0; i < height; i++) - memcpy(_backBuffer->getBasePtr(dest.left, i + dest.top), surface->getBasePtr(src.left, top + i), width * surface->format.bytesPerPixel); -} - -void MystGraphics::copyImageToScreen(uint16 image, Common::Rect dest) { - copyImageSectionToScreen(image, Common::Rect(544, 333), dest); -} - -void MystGraphics::copyImageToBackBuffer(uint16 image, Common::Rect dest) { - copyImageSectionToBackBuffer(image, Common::Rect(544, 333), dest); -} - -void MystGraphics::copyBackBufferToScreen(Common::Rect r) { - r.clip(_viewport); - - simulatePreviousDrawDelay(r); - - _vm->_system->copyRectToScreen((byte *)_backBuffer->getBasePtr(r.left, r.top), _backBuffer->pitch, r.left, r.top, r.width(), r.height()); -} - -void MystGraphics::runTransition(uint16 type, Common::Rect rect, uint16 steps, uint16 delay) { - - // Do not artificially delay during transitions - int oldEnableDrawingTimeSimulation = _enableDrawingTimeSimulation; - _enableDrawingTimeSimulation = 0; - - switch (type) { - case 0: { - debugC(kDebugScript, "Left to Right"); - - uint16 step = (rect.right - rect.left) / steps; - Common::Rect area = rect; - for (uint i = 0; i < steps; i++) { - area.left = rect.left + step * i; - area.right = area.left + step; - - _vm->_system->delayMillis(delay); - - copyBackBufferToScreen(area); - _vm->_system->updateScreen(); - } - if (area.right < rect.right) { - area.left = area.right; - area.right = rect.right; - - copyBackBufferToScreen(area); - _vm->_system->updateScreen(); - } - } - break; - case 1: { - debugC(kDebugScript, "Right to Left"); - - uint16 step = (rect.right - rect.left) / steps; - Common::Rect area = rect; - for (uint i = 0; i < steps; i++) { - area.right = rect.right - step * i; - area.left = area.right - step; - - _vm->_system->delayMillis(delay); - - copyBackBufferToScreen(area); - _vm->_system->updateScreen(); - } - if (area.left > rect.left) { - area.right = area.left; - area.left = rect.left; - - copyBackBufferToScreen(area); - _vm->_system->updateScreen(); - } - } - break; - case 5: { - debugC(kDebugScript, "Top to Bottom"); - - uint16 step = (rect.bottom - rect.top) / steps; - Common::Rect area = rect; - for (uint i = 0; i < steps; i++) { - area.top = rect.top + step * i; - area.bottom = area.top + step; - - _vm->_system->delayMillis(delay); - - copyBackBufferToScreen(area); - _vm->_system->updateScreen(); - } - if (area.bottom < rect.bottom) { - area.top = area.bottom; - area.bottom = rect.bottom; - - copyBackBufferToScreen(area); - _vm->_system->updateScreen(); - } - } - break; - case 6: { - debugC(kDebugScript, "Bottom to Top"); - - uint16 step = (rect.bottom - rect.top) / steps; - Common::Rect area = rect; - for (uint i = 0; i < steps; i++) { - area.bottom = rect.bottom - step * i; - area.top = area.bottom - step; - - _vm->_system->delayMillis(delay); - - copyBackBufferToScreen(area); - _vm->_system->updateScreen(); - } - if (area.top > rect.top) { - area.bottom = area.top; - area.top = rect.top; - - copyBackBufferToScreen(area); - _vm->_system->updateScreen(); - } - } - break; - default: - warning("Unknown Update Direction"); - - //TODO: Replace minimal implementation - copyBackBufferToScreen(rect); - _vm->_system->updateScreen(); - break; - } - - _enableDrawingTimeSimulation = oldEnableDrawingTimeSimulation; -} - -void MystGraphics::drawRect(Common::Rect rect, RectState state) { - rect.clip(_viewport); - - // Useful with debugging. Shows where hotspots are on the screen and whether or not they're active. - if (!rect.isValidRect() || rect.width() == 0 || rect.height() == 0) - return; - - Graphics::Surface *screen = _vm->_system->lockScreen(); - - if (state == kRectEnabled) - screen->frameRect(rect, _pixelFormat.RGBToColor(0, 255, 0)); - else if (state == kRectUnreachable) - screen->frameRect(rect, _pixelFormat.RGBToColor(0, 0, 255)); - else - screen->frameRect(rect, _pixelFormat.RGBToColor(255, 0, 0)); - - _vm->_system->unlockScreen(); -} - -void MystGraphics::drawLine(const Common::Point &p1, const Common::Point &p2, uint32 color) { - _backBuffer->drawLine(p1.x, p1.y, p2.x, p2.y, color); -} - -void MystGraphics::enableDrawingTimeSimulation(bool enable) { - if (enable) - _enableDrawingTimeSimulation++; - else - _enableDrawingTimeSimulation--; - - if (_enableDrawingTimeSimulation < 0) - _enableDrawingTimeSimulation = 0; -} - -void MystGraphics::simulatePreviousDrawDelay(const Common::Rect &dest) { - uint32 time = 0; - - if (_enableDrawingTimeSimulation) { - time = _vm->_system->getMillis(); - - // Do not draw anything new too quickly after the previous draw call - // so that images stay at least a little while on screen - // This is enabled only for scripted draw calls - if (time < _nextAllowedDrawTime) - _vm->_system->delayMillis(_nextAllowedDrawTime - time); - } - - // Next draw call allowed at DELAY + AERA * COEFF milliseconds from now - time = _vm->_system->getMillis(); - _nextAllowedDrawTime = time + _constantDrawDelay + dest.height() * dest.width() / _proportionalDrawDelay; -} - -void MystGraphics::copyBackBufferToScreenWithSaturation(int16 saturation) { - Graphics::Surface *screen = _vm->_system->lockScreen(); - - for (uint16 y = 0; y < _viewport.height(); y++) - for (uint16 x = 0; x < _viewport.width(); x++) { - uint32 color; - uint8 r, g, b; - - if (_pixelFormat.bytesPerPixel == 2) - color = *(const uint16 *)_backBuffer->getBasePtr(x, y); - else - color = *(const uint32 *)_backBuffer->getBasePtr(x, y); - - _pixelFormat.colorToRGB(color, r, g, b); - - r = CLIP((int16)r - saturation, 0, 255); - g = CLIP((int16)g - saturation, 0, 255); - b = CLIP((int16)b - saturation, 0, 255); - - color = _pixelFormat.RGBToColor(r, g, b); - - if (_pixelFormat.bytesPerPixel == 2) { - uint16 *dst = (uint16 *)screen->getBasePtr(x, y); - *dst = color; - } else { - uint32 *dst = (uint32 *)screen->getBasePtr(x, y); - *dst = color; - } - } - - _vm->_system->unlockScreen(); - _vm->_system->updateScreen(); -} - -void MystGraphics::fadeToBlack() { - for (int16 i = 0; i < 256; i += 32) { - copyBackBufferToScreenWithSaturation(i); - } -} - -void MystGraphics::fadeFromBlack() { - for (int16 i = 256; i >= 0; i -= 32) { - copyBackBufferToScreenWithSaturation(i); - } -} - -#endif // ENABLE_MYST - -#ifdef ENABLE_RIVEN - -RivenGraphics::RivenGraphics(MohawkEngine_Riven* vm) : GraphicsManager(), _vm(vm) { - _bitmapDecoder = new MohawkBitmap(); - - // Give me the best you've got! - initGraphics(608, 436, true, NULL); - _pixelFormat = _vm->_system->getScreenFormat(); - - if (_pixelFormat.bytesPerPixel == 1) - error("Riven requires greater than 256 colors to run"); - - // The actual game graphics only take up the first 392 rows. The inventory - // occupies the rest of the screen and we don't use the buffer to hold that. - _mainScreen = new Graphics::Surface(); - _mainScreen->create(608, 392, _pixelFormat); - - _updatesEnabled = true; - _scheduledTransition = -1; // no transition - _dirtyScreen = false; - _inventoryDrawn = false; - - _creditsImage = 302; - _creditsPos = 0; -} - -RivenGraphics::~RivenGraphics() { - _mainScreen->free(); - delete _mainScreen; - delete _bitmapDecoder; -} - -MohawkSurface *RivenGraphics::decodeImage(uint16 id) { - MohawkSurface *surface = _bitmapDecoder->decodeImage(_vm->getResource(ID_TBMP, id)); - surface->convertToTrueColor(); - return surface; -} - -void RivenGraphics::copyImageToScreen(uint16 image, uint32 left, uint32 top, uint32 right, uint32 bottom) { - Graphics::Surface *surface = findImage(image)->getSurface(); - - // Clip the width to fit on the screen. Fixes some images. - if (left + surface->w > 608) - surface->w = 608 - left; - - for (uint16 i = 0; i < surface->h; i++) - memcpy(_mainScreen->getBasePtr(left, i + top), surface->getBasePtr(0, i), surface->w * surface->format.bytesPerPixel); - - _dirtyScreen = true; -} - -void RivenGraphics::drawPLST(uint16 x) { - Common::SeekableReadStream* plst = _vm->getResource(ID_PLST, _vm->getCurCard()); - uint16 recordCount = plst->readUint16BE(); - - for (uint16 i = 0; i < recordCount; i++) { - uint16 index = plst->readUint16BE(); - uint16 id = plst->readUint16BE(); - uint16 left = plst->readUint16BE(); - uint16 top = plst->readUint16BE(); - uint16 right = plst->readUint16BE(); - uint16 bottom = plst->readUint16BE(); - - // We are also checking here to make sure we haven't drawn the image yet on screen. - // This fixes problems with drawing PLST 1 twice and some other images twice. PLST - // 1 is sometimes not called by the scripts, so some cards don't appear if we don't - // draw PLST 1 each time. This "hack" is here to catch any PLST attempting to draw - // twice. There should never be a problem with doing it this way. - if (index == x && !(Common::find(_activatedPLSTs.begin(), _activatedPLSTs.end(), x) != _activatedPLSTs.end())) { - debug(0, "Drawing image %d", id); - copyImageToScreen(id, left, top, right, bottom); - _activatedPLSTs.push_back(x); - break; - } - } - - delete plst; -} - -void RivenGraphics::updateScreen(Common::Rect updateRect) { - if (_updatesEnabled) { - _vm->runUpdateScreenScript(); - - if (_dirtyScreen) { - _activatedPLSTs.clear(); - - // Copy to screen if there's no transition. Otherwise transition. ;) - if (_scheduledTransition < 0) - _vm->_system->copyRectToScreen((byte *)_mainScreen->getBasePtr(updateRect.left, updateRect.top), _mainScreen->pitch, updateRect.left, updateRect.top, updateRect.width(), updateRect.height()); - else - runScheduledTransition(); - - // Finally, update the screen. - _vm->_system->updateScreen(); - _dirtyScreen = false; - } - } -} - -void RivenGraphics::scheduleWaterEffect(uint16 sfxeID) { - Common::SeekableReadStream *sfxeStream = _vm->getResource(ID_SFXE, sfxeID); - - if (sfxeStream->readUint16BE() != 'SL') - error ("Unknown sfxe tag"); - - // Read in header info - SFXERecord sfxeRecord; - sfxeRecord.frameCount = sfxeStream->readUint16BE(); - uint32 offsetTablePosition = sfxeStream->readUint32BE(); - sfxeRecord.rect.left = sfxeStream->readUint16BE(); - sfxeRecord.rect.top = sfxeStream->readUint16BE(); - sfxeRecord.rect.right = sfxeStream->readUint16BE(); - sfxeRecord.rect.bottom = sfxeStream->readUint16BE(); - sfxeRecord.speed = sfxeStream->readUint16BE(); - // Skip the rest of the fields... - - // Read in offsets - sfxeStream->seek(offsetTablePosition); - uint32 *frameOffsets = new uint32[sfxeRecord.frameCount]; - for (uint16 i = 0; i < sfxeRecord.frameCount; i++) - frameOffsets[i] = sfxeStream->readUint32BE(); - sfxeStream->seek(frameOffsets[0]); - - // Read in the scripts - for (uint16 i = 0; i < sfxeRecord.frameCount; i++) - sfxeRecord.frameScripts.push_back(sfxeStream->readStream((i == sfxeRecord.frameCount - 1) ? sfxeStream->size() - frameOffsets[i] : frameOffsets[i + 1] - frameOffsets[i])); - - // Set it to the first frame - sfxeRecord.curFrame = 0; - sfxeRecord.lastFrameTime = 0; - - delete[] frameOffsets; - delete sfxeStream; - _waterEffects.push_back(sfxeRecord); -} - -void RivenGraphics::clearWaterEffects() { - _waterEffects.clear(); -} - -bool RivenGraphics::runScheduledWaterEffects() { - // Don't run the effect if it's disabled - if (_vm->_vars["waterenabled"] == 0) - return false; - - Graphics::Surface *screen = NULL; - - for (uint16 i = 0; i < _waterEffects.size(); i++) { - if (_vm->_system->getMillis() > _waterEffects[i].lastFrameTime + 1000 / _waterEffects[i].speed) { - // Lock the screen! - if (!screen) - screen = _vm->_system->lockScreen(); - - // Make sure the script is at the starting point - Common::SeekableReadStream *script = _waterEffects[i].frameScripts[_waterEffects[i].curFrame]; - if (script->pos() != 0) - script->seek(0); - - // Run script - uint16 curRow = 0; - for (uint16 op = script->readUint16BE(); op != 4; op = script->readUint16BE()) { - if (op == 1) { // Increment Row - curRow++; - } else if (op == 3) { // Copy Pixels - uint16 dstLeft = script->readUint16BE(); - uint16 srcLeft = script->readUint16BE(); - uint16 srcTop = script->readUint16BE(); - uint16 rowWidth = script->readUint16BE(); - memcpy ((byte *)screen->getBasePtr(dstLeft, curRow + _waterEffects[i].rect.top), (byte *)_mainScreen->getBasePtr(srcLeft, srcTop), rowWidth * _pixelFormat.bytesPerPixel); - } else if (op != 4) { // End of Script - error ("Unknown SFXE opcode %d", op); - } - } - - // Increment frame - _waterEffects[i].curFrame++; - if (_waterEffects[i].curFrame == _waterEffects[i].frameCount) - _waterEffects[i].curFrame = 0; - - // Set the new time - _waterEffects[i].lastFrameTime = _vm->_system->getMillis(); - } - } - - // Unlock the screen if it has been locked and return true to update the screen - if (screen) { - _vm->_system->unlockScreen(); - return true; - } - - return false; -} - -void RivenGraphics::scheduleTransition(uint16 id, Common::Rect rect) { - _scheduledTransition = id; - _transitionRect = rect; -} - -void RivenGraphics::runScheduledTransition() { - if (_scheduledTransition < 0) // No transition is scheduled - return; - - // TODO: There's a lot to be done here... - - // Note: Transitions 0-11 are actual transitions, but none are used in-game. - // There's no point in implementing them if they're not used. These extra - // transitions were found by hacking scripts. - - switch (_scheduledTransition) { - case 0: // Swipe Left - case 1: // Swipe Right - case 2: // Swipe Up - case 3: // Swipe Down - case 12: // Pan Left - case 13: // Pan Right - case 14: // Pan Up - case 15: // Pan Down - case 16: // Dissolve - case 17: // Dissolve (tspit CARD 155) - break; - default: - if (_scheduledTransition >= 4 && _scheduledTransition <= 11) - error("Found unused transition %d", _scheduledTransition); - else - error("Found unknown transition %d", _scheduledTransition); - } - - // For now, just copy the image to screen without doing any transition. - _vm->_system->copyRectToScreen((byte *)_mainScreen->pixels, _mainScreen->pitch, 0, 0, _mainScreen->w, _mainScreen->h); - _vm->_system->updateScreen(); - - _scheduledTransition = -1; // Clear scheduled transition -} - -void RivenGraphics::clearMainScreen() { - _mainScreen->fillRect(Common::Rect(0, 0, 608, 392), _pixelFormat.RGBToColor(0, 0, 0)); -} - -void RivenGraphics::fadeToBlack() { - // The transition speed is forced to best here - setTransitionSpeed(kRivenTransitionSpeedBest); - scheduleTransition(16); - clearMainScreen(); - runScheduledTransition(); -} - -void RivenGraphics::showInventory() { - // Don't redraw the inventory - if (_inventoryDrawn) - return; - - // Clear the inventory area - clearInventoryArea(); - - // Draw the demo's exit button - if (_vm->getFeatures() & GF_DEMO) { - // extras.mhk tBMP 101 contains "EXIT" instead of Atrus' journal in the demo! - // The demo's extras.mhk contains all the other inventory/marble/credits image - // but has hacked tBMP 101 with "EXIT". *sigh* - drawInventoryImage(101, g_demoExitRect); - } else { - // We don't want to show the inventory on setup screens or in other journals. - if (_vm->getCurStack() == aspit) - return; - - // There are three books and three vars. We have three different - // combinations. At the start you have just Atrus' journal. Later, - // you get Catherine's journal and the trap book. Near the end, - // you lose the trap book and have just the two journals. - - bool hasCathBook = _vm->_vars["acathbook"] != 0; - bool hasTrapBook = _vm->_vars["atrapbook"] != 0; - - if (!hasCathBook) { - drawInventoryImage(101, g_atrusJournalRect1); - } else if (!hasTrapBook) { - drawInventoryImage(101, g_atrusJournalRect2); - drawInventoryImage(102, g_cathJournalRect2); - } else { - drawInventoryImage(101, g_atrusJournalRect3); - drawInventoryImage(102, g_cathJournalRect3); - drawInventoryImage(100, g_trapBookRect3); - } - } - - _vm->_system->updateScreen(); - _inventoryDrawn = true; -} - -void RivenGraphics::hideInventory() { - // Don't hide the inventory twice - if (!_inventoryDrawn) - return; - - // Clear the area - clearInventoryArea(); - - _inventoryDrawn = false; -} - -void RivenGraphics::clearInventoryArea() { - // Clear the inventory area - static const Common::Rect inventoryRect = Common::Rect(0, 392, 608, 436); - - // Lock the screen - Graphics::Surface *screen = _vm->_system->lockScreen(); - - // Fill the inventory area with black - screen->fillRect(inventoryRect, _pixelFormat.RGBToColor(0, 0, 0)); - - _vm->_system->unlockScreen(); -} - -void RivenGraphics::drawInventoryImage(uint16 id, const Common::Rect *rect) { - MohawkSurface *mhkSurface = _bitmapDecoder->decodeImage(_vm->getExtrasResource(ID_TBMP, id)); - mhkSurface->convertToTrueColor(); - Graphics::Surface *surface = mhkSurface->getSurface(); - - _vm->_system->copyRectToScreen((byte *)surface->pixels, surface->pitch, rect->left, rect->top, surface->w, surface->h); - - delete mhkSurface; -} - -void RivenGraphics::drawRect(Common::Rect rect, bool active) { - // Useful with debugging. Shows where hotspots are on the screen and whether or not they're active. - Graphics::Surface *screen = _vm->_system->lockScreen(); - - if (active) - screen->frameRect(rect, _pixelFormat.RGBToColor(0, 255, 0)); - else - screen->frameRect(rect, _pixelFormat.RGBToColor(255, 0, 0)); - - _vm->_system->unlockScreen(); -} - -void RivenGraphics::drawImageRect(uint16 id, Common::Rect srcRect, Common::Rect dstRect) { - // Draw tBMP id from srcRect to dstRect - Graphics::Surface *surface = findImage(id)->getSurface(); - - assert(srcRect.width() == dstRect.width() && srcRect.height() == dstRect.height()); - - for (uint16 i = 0; i < srcRect.height(); i++) - memcpy(_mainScreen->getBasePtr(dstRect.left, i + dstRect.top), surface->getBasePtr(srcRect.left, i + srcRect.top), srcRect.width() * surface->format.bytesPerPixel); - - _dirtyScreen = true; -} - -void RivenGraphics::drawExtrasImage(uint16 id, Common::Rect dstRect) { - MohawkSurface *mhkSurface = _bitmapDecoder->decodeImage(_vm->getExtrasResource(ID_TBMP, id)); - mhkSurface->convertToTrueColor(); - Graphics::Surface *surface = mhkSurface->getSurface(); - - assert(dstRect.width() == surface->w); - - for (uint16 i = 0; i < surface->h; i++) - memcpy(_mainScreen->getBasePtr(dstRect.left, i + dstRect.top), surface->getBasePtr(0, i), surface->pitch); - - delete mhkSurface; - _dirtyScreen = true; -} - -void RivenGraphics::beginCredits() { - // Clear the old cache - clearCache(); - - // Now cache all the credits images - for (uint16 i = 302; i <= 320; i++) { - MohawkSurface *surface = _bitmapDecoder->decodeImage(_vm->getExtrasResource(ID_TBMP, i)); - surface->convertToTrueColor(); - addImageToCache(i, surface); - } - - // And clear our screen too - clearMainScreen(); -} - -void RivenGraphics::updateCredits() { - if ((_creditsImage == 303 || _creditsImage == 304) && _creditsPos == 0) - fadeToBlack(); - - if (_creditsImage < 304) { - // For the first two credit images, they are faded from black to the image and then out again - scheduleTransition(16); - - Graphics::Surface *frame = findImage(_creditsImage++)->getSurface(); - - for (int y = 0; y < frame->h; y++) - memcpy(_mainScreen->getBasePtr(124, y), frame->getBasePtr(0, y), frame->pitch); - - runScheduledTransition(); - } else { - // Otheriwse, we're scrolling - // Move the screen up one row - memmove(_mainScreen->pixels, _mainScreen->getBasePtr(0, 1), _mainScreen->pitch * (_mainScreen->h - 1)); - - // Only update as long as we're not before the last frame - // Otherwise, we're just moving up a row (which we already did) - if (_creditsImage <= 320) { - // Copy the next row to the bottom of the screen - Graphics::Surface *frame = findImage(_creditsImage)->getSurface(); - memcpy(_mainScreen->getBasePtr(124, _mainScreen->h - 1), frame->getBasePtr(0, _creditsPos), frame->pitch); - _creditsPos++; - - if (_creditsPos == _mainScreen->h) { - _creditsImage++; - _creditsPos = 0; - } - } - - // Now flush the new screen - _vm->_system->copyRectToScreen((byte *)_mainScreen->pixels, _mainScreen->pitch, 0, 0, _mainScreen->w, _mainScreen->h); - _vm->_system->updateScreen(); - } -} - -#endif // ENABLE_RIVEN - -LBGraphics::LBGraphics(MohawkEngine_LivingBooks *vm, uint16 width, uint16 height) : GraphicsManager(), _vm(vm) { - _bmpDecoder = _vm->isPreMohawk() ? new LivingBooksBitmap_v1() : new MohawkBitmap(); - - initGraphics(width, height, true); -} - -LBGraphics::~LBGraphics() { - delete _bmpDecoder; -} - -MohawkSurface *LBGraphics::decodeImage(uint16 id) { - if (_vm->isPreMohawk()) - return _bmpDecoder->decodeImage(_vm->wrapStreamEndian(ID_BMAP, id)); - - return _bmpDecoder->decodeImage(_vm->getResource(ID_TBMP, id)); -} - -void LBGraphics::copyOffsetAnimImageToScreen(uint16 image, int left, int top) { - MohawkSurface *mhkSurface = findImage(image); - - left -= mhkSurface->getOffsetX(); - top -= mhkSurface->getOffsetY(); - - GraphicsManager::copyAnimImageToScreen(image, left, top); -} - -bool LBGraphics::imageIsTransparentAt(uint16 image, bool useOffsets, int x, int y) { - MohawkSurface *mhkSurface = findImage(image); - - if (useOffsets) { - x += mhkSurface->getOffsetX(); - y += mhkSurface->getOffsetY(); - } - - if (x < 0 || y < 0) - return true; - - Graphics::Surface *surface = mhkSurface->getSurface(); - if (x >= surface->w || y >= surface->h) - return true; - - return *(byte *)surface->getBasePtr(x, y) == 0; -} - -void LBGraphics::setPalette(uint16 id) { - // Old Living Books games use the old CTBL-style palette format while newer - // games use the better tPAL format which can store partial palettes. - if (_vm->isPreMohawk()) { - Common::SeekableSubReadStreamEndian *ctblStream = _vm->wrapStreamEndian(ID_CTBL, id); - uint16 colorCount = ctblStream->readUint16(); - byte *palette = new byte[colorCount * 3]; - - for (uint16 i = 0; i < colorCount; i++) { - palette[i * 3 + 0] = ctblStream->readByte(); - palette[i * 3 + 1] = ctblStream->readByte(); - palette[i * 3 + 2] = ctblStream->readByte(); - ctblStream->readByte(); - } - - delete ctblStream; - - _vm->_system->getPaletteManager()->setPalette(palette, 0, colorCount); - delete[] palette; - } else { - GraphicsManager::setPalette(id); - } -} - -#ifdef ENABLE_CSTIME - -CSTimeGraphics::CSTimeGraphics(MohawkEngine_CSTime *vm) : GraphicsManager(), _vm(vm) { - _bmpDecoder = new MohawkBitmap(); - - initGraphics(640, 480, true); -} - -CSTimeGraphics::~CSTimeGraphics() { - delete _bmpDecoder; -} - -void CSTimeGraphics::drawRect(Common::Rect rect, byte color) { - rect.clip(Common::Rect(640, 480)); - - // Useful with debugging. Shows where hotspots are on the screen and whether or not they're active. - if (!rect.isValidRect() || rect.width() == 0 || rect.height() == 0) - return; - - Graphics::Surface *screen = _vm->_system->lockScreen(); - - screen->frameRect(rect, color); - - _vm->_system->unlockScreen(); -} - -MohawkSurface *CSTimeGraphics::decodeImage(uint16 id) { - return _bmpDecoder->decodeImage(_vm->getResource(ID_TBMP, id)); -} - -Common::Array CSTimeGraphics::decodeImages(uint16 id) { - return _bmpDecoder->decodeImages(_vm->getResource(ID_TBMH, id)); -} - -#endif - } // End of namespace Mohawk -- cgit v1.2.3