aboutsummaryrefslogtreecommitdiff
path: root/engines/mohawk/graphics.cpp
diff options
context:
space:
mode:
authorMatthew Hoops2012-03-10 13:50:27 -0500
committerMatthew Hoops2012-03-10 13:55:08 -0500
commit5e52b0a5d46e4c5b230cba7464301484d27804f7 (patch)
treeb0c732e5b7c6e98e43e2a7b1e6a8c7a399f3055d /engines/mohawk/graphics.cpp
parentd142606f755203bf2e407729840898b0c8ca53d5 (diff)
downloadscummvm-rg350-5e52b0a5d46e4c5b230cba7464301484d27804f7.tar.gz
scummvm-rg350-5e52b0a5d46e4c5b230cba7464301484d27804f7.tar.bz2
scummvm-rg350-5e52b0a5d46e4c5b230cba7464301484d27804f7.zip
MOHAWK: Split the graphics classes into their own files
Diffstat (limited to 'engines/mohawk/graphics.cpp')
-rw-r--r--engines/mohawk/graphics.cpp1001
1 files changed, 1 insertions, 1000 deletions
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<int>(surface->h, dest.height());
-
- // Convert from bitmap coordinates to surface coordinates
- uint16 top = surface->h - (src.top + MIN<int>(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<int>(dest.right, 0, _vm->_system->getWidth());
- dest.bottom = CLIP<int>(dest.bottom, 0, _vm->_system->getHeight());
-
- uint16 width = MIN<int>(surface->w, dest.width());
- uint16 height = MIN<int>(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<int>(surface->h, dest.height());
-
- // Convert from bitmap coordinates to surface coordinates
- uint16 top = surface->h - (src.top + MIN<int>(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<int>(dest.right, 0, _vm->_system->getWidth());
- dest.bottom = CLIP<int>(dest.bottom, 0, _vm->_system->getHeight());
-
- uint16 width = MIN<int>(surface->w, dest.width());
- uint16 height = MIN<int>(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>((int16)r - saturation, 0, 255);
- g = CLIP<int16>((int16)g - saturation, 0, 255);
- b = CLIP<int16>((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<MohawkSurface *> CSTimeGraphics::decodeImages(uint16 id) {
- return _bmpDecoder->decodeImages(_vm->getResource(ID_TBMH, id));
-}
-
-#endif
-
} // End of namespace Mohawk