aboutsummaryrefslogtreecommitdiff
path: root/engines/mohawk
diff options
context:
space:
mode:
Diffstat (limited to 'engines/mohawk')
-rw-r--r--engines/mohawk/bitmap.cpp101
-rw-r--r--engines/mohawk/bitmap.h24
-rw-r--r--engines/mohawk/console.cpp2
-rw-r--r--engines/mohawk/cstime.h2
-rw-r--r--engines/mohawk/cstime_graphics.cpp64
-rw-r--r--engines/mohawk/cstime_graphics.h51
-rw-r--r--engines/mohawk/detection_tables.h84
-rw-r--r--engines/mohawk/graphics.cpp1022
-rw-r--r--engines/mohawk/graphics.h199
-rw-r--r--engines/mohawk/installer_archive.cpp6
-rw-r--r--engines/mohawk/installer_archive.h6
-rw-r--r--engines/mohawk/livingbooks.cpp3
-rw-r--r--engines/mohawk/livingbooks.h2
-rw-r--r--engines/mohawk/livingbooks_code.cpp8
-rw-r--r--engines/mohawk/livingbooks_graphics.cpp102
-rw-r--r--engines/mohawk/livingbooks_graphics.h52
-rw-r--r--engines/mohawk/module.mk4
-rw-r--r--engines/mohawk/myst.cpp2
-rw-r--r--engines/mohawk/myst.h2
-rw-r--r--engines/mohawk/myst_areas.cpp4
-rw-r--r--engines/mohawk/myst_areas.h8
-rw-r--r--engines/mohawk/myst_graphics.cpp494
-rw-r--r--engines/mohawk/myst_graphics.h95
-rw-r--r--engines/mohawk/myst_scripts.cpp6
-rw-r--r--engines/mohawk/myst_scripts.h2
-rw-r--r--engines/mohawk/myst_stacks/channelwood.cpp2
-rw-r--r--engines/mohawk/myst_stacks/credits.cpp2
-rw-r--r--engines/mohawk/myst_stacks/demo.cpp2
-rw-r--r--engines/mohawk/myst_stacks/intro.cpp2
-rw-r--r--engines/mohawk/myst_stacks/mechanical.cpp2
-rw-r--r--engines/mohawk/myst_stacks/myst.cpp10
-rw-r--r--engines/mohawk/myst_stacks/preview.cpp2
-rw-r--r--engines/mohawk/myst_stacks/slides.cpp2
-rw-r--r--engines/mohawk/myst_stacks/stoneship.cpp2
-rw-r--r--engines/mohawk/riven.cpp8
-rw-r--r--engines/mohawk/riven.h4
-rw-r--r--engines/mohawk/riven_external.cpp2
-rw-r--r--engines/mohawk/riven_external.h2
-rw-r--r--engines/mohawk/riven_graphics.cpp445
-rw-r--r--engines/mohawk/riven_graphics.h110
-rw-r--r--engines/mohawk/riven_saveload.cpp18
-rw-r--r--engines/mohawk/riven_saveload.h4
-rw-r--r--engines/mohawk/riven_scripts.cpp2
-rw-r--r--engines/mohawk/riven_scripts.h5
-rw-r--r--engines/mohawk/riven_vars.cpp1
-rw-r--r--engines/mohawk/video.cpp22
46 files changed, 1599 insertions, 1395 deletions
diff --git a/engines/mohawk/bitmap.cpp b/engines/mohawk/bitmap.cpp
index 4edde31236..952b6daec2 100644
--- a/engines/mohawk/bitmap.cpp
+++ b/engines/mohawk/bitmap.cpp
@@ -29,6 +29,7 @@
#include "common/substream.h"
#include "common/system.h"
#include "common/textconsole.h"
+#include "graphics/decoders/bmp.h"
namespace Mohawk {
@@ -631,97 +632,37 @@ void MohawkBitmap::drawRLE8(Graphics::Surface *surface, bool isLE) {
MohawkSurface *MystBitmap::decodeImage(Common::SeekableReadStream* stream) {
uint32 uncompressedSize = stream->readUint32LE();
- Common::SeekableReadStream* bmpStream = decompressLZ(stream, uncompressedSize);
+ Common::SeekableReadStream *bmpStream = decompressLZ(stream, uncompressedSize);
delete stream;
- _header.type = bmpStream->readUint16BE();
+ Graphics::BitmapDecoder bitmapDecoder;
+ if (!bitmapDecoder.loadStream(*bmpStream))
+ error("Could not decode Myst bitmap");
- if (_header.type != 'BM')
- error("BMP header not detected");
+ const Graphics::Surface *bmpSurface = bitmapDecoder.getSurface();
+ Graphics::Surface *newSurface = 0;
- _header.size = bmpStream->readUint32LE();
- assert (_header.size > 0);
- _header.res1 = bmpStream->readUint16LE();
- _header.res2 = bmpStream->readUint16LE();
- _header.imageOffset = bmpStream->readUint32LE();
-
- _info.size = bmpStream->readUint32LE();
-
- if (_info.size != 40)
- error("Only Windows v3 BMP's are supported");
-
- _info.width = bmpStream->readUint32LE();
- _info.height = bmpStream->readUint32LE();
- _info.planes = bmpStream->readUint16LE();
- _info.bitsPerPixel = bmpStream->readUint16LE();
- _info.compression = bmpStream->readUint32LE();
- _info.imageSize = bmpStream->readUint32LE();
- _info.pixelsPerMeterX = bmpStream->readUint32LE();
- _info.pixelsPerMeterY = bmpStream->readUint32LE();
- _info.colorsUsed = bmpStream->readUint32LE();
- _info.colorsImportant = bmpStream->readUint32LE();
-
- if (_info.compression != 0)
- error("Unhandled BMP compression %d", _info.compression);
-
- if (_info.colorsUsed == 0)
- _info.colorsUsed = 256;
-
- if (_info.bitsPerPixel != 8 && _info.bitsPerPixel != 24)
- error("%dbpp Bitmaps not supported", _info.bitsPerPixel);
-
- byte *palData = NULL;
-
- if (_info.bitsPerPixel == 8) {
- palData = (byte *)malloc(256 * 3);
- for (uint16 i = 0; i < _info.colorsUsed; i++) {
- palData[i * 3 + 2] = bmpStream->readByte();
- palData[i * 3 + 1] = bmpStream->readByte();
- palData[i * 3 + 0] = bmpStream->readByte();
- bmpStream->readByte();
- }
- }
-
- bmpStream->seek(_header.imageOffset);
-
- Graphics::Surface *surface = createSurface(_info.width, _info.height);
- int srcPitch = _info.width * (_info.bitsPerPixel >> 3);
- const int extraDataLength = (srcPitch % 4) ? 4 - (srcPitch % 4) : 0;
-
- if (_info.bitsPerPixel == 8) {
- byte *dst = (byte *)surface->pixels;
-
- for (uint32 i = 0; i < _info.height; i++) {
- bmpStream->read(dst + (_info.height - i - 1) * _info.width, _info.width);
- bmpStream->skip(extraDataLength);
- }
+ if (bmpSurface->format.bytesPerPixel == 1) {
+ _bitsPerPixel = 8;
+ newSurface = new Graphics::Surface();
+ newSurface->copyFrom(*bmpSurface);
} else {
- Graphics::PixelFormat pixelFormat = g_system->getScreenFormat();
-
- byte *dst = (byte *)surface->pixels + (surface->h - 1) * surface->pitch;
-
- for (uint32 i = 0; i < _info.height; i++) {
- for (uint32 j = 0; j < _info.width; j++) {
- byte b = bmpStream->readByte();
- byte g = bmpStream->readByte();
- byte r = bmpStream->readByte();
+ _bitsPerPixel = 24;
+ newSurface = bmpSurface->convertTo(g_system->getScreenFormat());
+ }
- if (pixelFormat.bytesPerPixel == 2)
- *((uint16 *)dst) = pixelFormat.RGBToColor(r, g, b);
- else
- *((uint32 *)dst) = pixelFormat.RGBToColor(r, g, b);
+ // Copy the palette to one of our own
+ const byte *palette = bitmapDecoder.getPalette();
+ byte *newPal = 0;
- dst += pixelFormat.bytesPerPixel;
- }
-
- bmpStream->skip(extraDataLength);
- dst -= surface->pitch * 2;
- }
+ if (palette) {
+ newPal = (byte *)malloc(256 * 3);
+ memcpy(newPal, palette, 256 * 3);
}
delete bmpStream;
- return new MohawkSurface(surface, palData);
+ return new MohawkSurface(newSurface, newPal);
}
#endif
diff --git a/engines/mohawk/bitmap.h b/engines/mohawk/bitmap.h
index 74218882e8..73c117b5c7 100644
--- a/engines/mohawk/bitmap.h
+++ b/engines/mohawk/bitmap.h
@@ -154,30 +154,10 @@ public:
MohawkSurface *decodeImage(Common::SeekableReadStream *stream);
protected:
- byte getBitsPerPixel() { return _info.bitsPerPixel; }
+ byte getBitsPerPixel() { return _bitsPerPixel; }
private:
- struct BitmapHeader {
- uint16 type;
- uint32 size;
- uint16 res1;
- uint16 res2;
- uint32 imageOffset;
- } _header;
-
- struct InfoHeader {
- uint32 size;
- uint32 width;
- uint32 height;
- uint16 planes;
- uint16 bitsPerPixel;
- uint32 compression;
- uint32 imageSize;
- uint32 pixelsPerMeterX;
- uint32 pixelsPerMeterY;
- uint32 colorsUsed;
- uint32 colorsImportant;
- } _info;
+ uint16 _bitsPerPixel;
};
#endif
diff --git a/engines/mohawk/console.cpp b/engines/mohawk/console.cpp
index 0234c86c7e..a7a650d8ed 100644
--- a/engines/mohawk/console.cpp
+++ b/engines/mohawk/console.cpp
@@ -21,7 +21,6 @@
*/
#include "mohawk/console.h"
-#include "mohawk/graphics.h"
#include "mohawk/livingbooks.h"
#include "mohawk/sound.h"
#include "mohawk/video.h"
@@ -36,6 +35,7 @@
#ifdef ENABLE_MYST
#include "mohawk/myst.h"
#include "mohawk/myst_areas.h"
+#include "mohawk/myst_graphics.h"
#include "mohawk/myst_scripts.h"
#endif
diff --git a/engines/mohawk/cstime.h b/engines/mohawk/cstime.h
index 0bc236f930..db06b9791e 100644
--- a/engines/mohawk/cstime.h
+++ b/engines/mohawk/cstime.h
@@ -25,7 +25,7 @@
#include "mohawk/mohawk.h"
#include "mohawk/console.h"
-#include "mohawk/graphics.h"
+#include "mohawk/cstime_graphics.h"
#include "common/random.h"
#include "common/list.h"
diff --git a/engines/mohawk/cstime_graphics.cpp b/engines/mohawk/cstime_graphics.cpp
new file mode 100644
index 0000000000..3a1452e67c
--- /dev/null
+++ b/engines/mohawk/cstime_graphics.cpp
@@ -0,0 +1,64 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "mohawk/cstime.h"
+#include "mohawk/cstime_graphics.h"
+#include "mohawk/resource.h"
+
+#include "common/system.h"
+#include "engines/util.h"
+
+namespace Mohawk {
+
+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));
+}
+
+} // End of namespace Mohawk
diff --git a/engines/mohawk/cstime_graphics.h b/engines/mohawk/cstime_graphics.h
new file mode 100644
index 0000000000..5f034f47f4
--- /dev/null
+++ b/engines/mohawk/cstime_graphics.h
@@ -0,0 +1,51 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef MOHAWK_CSTIME_GRAPHICS_H
+#define MOHAWK_CSTIME_GRAPHICS_H
+
+#include "mohawk/graphics.h"
+
+namespace Mohawk {
+
+class MohawkEngine_CSTime;
+
+class CSTimeGraphics : public GraphicsManager {
+public:
+ CSTimeGraphics(MohawkEngine_CSTime *vm);
+ ~CSTimeGraphics();
+
+ void drawRect(Common::Rect rect, byte color);
+
+protected:
+ MohawkSurface *decodeImage(uint16 id);
+ Common::Array<MohawkSurface *> decodeImages(uint16 id);
+ MohawkEngine *getVM() { return (MohawkEngine *)_vm; }
+
+private:
+ MohawkBitmap *_bmpDecoder;
+ MohawkEngine_CSTime *_vm;
+};
+
+} // End of namespace Mohawk
+
+#endif
diff --git a/engines/mohawk/detection_tables.h b/engines/mohawk/detection_tables.h
index 998c2ef56d..5acc1bb179 100644
--- a/engines/mohawk/detection_tables.h
+++ b/engines/mohawk/detection_tables.h
@@ -376,7 +376,7 @@ static const MohawkGameDescription gameDescriptions[] = {
Common::EN_ANY,
Common::kPlatformWindows,
ADGF_DEMO | ADGF_UNSTABLE,
- GUIO1(GUIO_NOASPECT)
+ GUIO2(GUIO_NOASPECT, GUIO_NOLAUNCHLOAD)
},
GType_RIVEN,
GF_DEMO,
@@ -1011,6 +1011,22 @@ static const MohawkGameDescription gameDescriptions[] = {
0,
},
+ // Tortoise and the Hare Hebrew variant - From georgeqgreg on bug #3441928
+ {
+ {
+ "tortoise",
+ "",
+ AD_ENTRY1("TORTB.LB", "23135777370cf1ff00aa7247e93642d3"),
+ Common::HE_ISR,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NOASPECT)
+ },
+ GType_LIVINGBOOKSV2,
+ 0,
+ 0,
+ },
+
// From afholman in bug#3309308
{
{
@@ -1293,6 +1309,23 @@ static const MohawkGameDescription gameDescriptions[] = {
0
},
+ // Just Grandma and Me 2.0 Macintosh
+ // From aluff in bug #3461368
+ {
+ {
+ "grandma",
+ "v2.0",
+ AD_ENTRY1("BookOutline", "99fe5c8ace79f0542e6390bc3b58f25a"),
+ Common::EN_ANY,
+ Common::kPlatformMacintosh,
+ ADGF_UNSTABLE,
+ GUIO1(GUIO_NOASPECT)
+ },
+ GType_LIVINGBOOKSV3,
+ 0,
+ 0
+ },
+
// Just Grandma and Me 1.0
// From scoriae
{
@@ -1782,6 +1815,23 @@ static const MohawkGameDescription gameDescriptions[] = {
0
},
+ // Arthur Birthday (English) Version 2.0 Macintosh
+ // From aluff in bug #3461368
+ {
+ {
+ "arthurbday",
+ "",
+ AD_ENTRY1("BookOutline", "8e4fddb5b761c8cf2a3b448dd38422be"),
+ Common::EN_ANY,
+ Common::kPlatformMacintosh,
+ ADGF_UNSTABLE,
+ GUIO1(GUIO_NOASPECT)
+ },
+ GType_LIVINGBOOKSV3,
+ 0,
+ 0
+ },
+
{
{
"arthurbday",
@@ -1970,6 +2020,22 @@ static const MohawkGameDescription gameDescriptions[] = {
"MONSTER.EXE"
},
+ // From GeorgeQGreg
+ {
+ {
+ "lilmonster",
+ "Demo",
+ AD_ENTRY1("MONSTER.512", "f603f04c1824d1034ec0366416a059c9"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_DEMO,
+ GUIO1(GUIO_NOASPECT)
+ },
+ GType_LIVINGBOOKSV1,
+ GF_DEMO,
+ "MONSTER.EXE"
+ },
+
{
{
"catinthehat",
@@ -2235,6 +2301,22 @@ static const MohawkGameDescription gameDescriptions[] = {
0
},
+ // From aluff in bug #3461368
+ {
+ {
+ "beardark",
+ "",
+ AD_ENTRY1("BookOutline", "b56746b3b2c062c8588bfb6b28e137c1"),
+ Common::EN_ANY,
+ Common::kPlatformMacintosh,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NOASPECT)
+ },
+ GType_LIVINGBOOKSV3,
+ 0,
+ 0
+ },
+
{
{
"arthurcomp",
diff --git a/engines/mohawk/graphics.cpp b/engines/mohawk/graphics.cpp
index dcb0c7940d..0f9a62c891 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 {
@@ -75,22 +58,7 @@ void MohawkSurface::convertToTrueColor() {
assert(_palette);
- Graphics::PixelFormat pixelFormat = g_system->getScreenFormat();
- Graphics::Surface *surface = new Graphics::Surface();
- surface->create(_surface->w, _surface->h, pixelFormat);
-
- for (uint16 i = 0; i < _surface->h; i++) {
- for (uint16 j = 0; j < _surface->w; j++) {
- byte palIndex = *((byte *)_surface->pixels + i * _surface->pitch + j);
- byte r = _palette[palIndex * 3 + 0];
- byte g = _palette[palIndex * 3 + 1];
- byte b = _palette[palIndex * 3 + 2];
- if (pixelFormat.bytesPerPixel == 2)
- *((uint16 *)surface->getBasePtr(j, i)) = pixelFormat.RGBToColor(r, g, b);
- else
- *((uint32 *)surface->getBasePtr(j, i)) = pixelFormat.RGBToColor(r, g, b);
- }
- }
+ Graphics::Surface *surface = _surface->convertTo(g_system->getScreenFormat(), _palette);
// Free everything and set the new surface as the converted surface
_surface->free();
@@ -108,9 +76,9 @@ GraphicsManager::~GraphicsManager() {
}
void GraphicsManager::clearCache() {
- for (Common::HashMap<uint16, MohawkSurface*>::iterator it = _cache.begin(); it != _cache.end(); it++)
+ for (Common::HashMap<uint16, MohawkSurface *>::iterator it = _cache.begin(); it != _cache.end(); it++)
delete it->_value;
- for (Common::HashMap<uint16, Common::Array<MohawkSurface*> >::iterator it = _subImageCache.begin(); it != _subImageCache.end(); it++) {
+ for (Common::HashMap<uint16, Common::Array<MohawkSurface *> >::iterator it = _subImageCache.begin(); it != _subImageCache.end(); it++) {
Common::Array<MohawkSurface *> &array = it->_value;
for (uint i = 0; i < array.size(); i++)
delete array[i];
@@ -262,986 +230,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
diff --git a/engines/mohawk/graphics.h b/engines/mohawk/graphics.h
index 463608a2aa..51d25db5d9 100644
--- a/engines/mohawk/graphics.h
+++ b/engines/mohawk/graphics.h
@@ -25,12 +25,11 @@
#include "mohawk/bitmap.h"
-#include "common/file.h"
#include "common/hashmap.h"
-#include "graphics/pict.h"
+#include "common/rect.h"
namespace Graphics {
-class JPEG;
+struct Surface;
}
namespace Mohawk {
@@ -99,200 +98,10 @@ protected:
private:
// An image cache that stores images until clearCache() is called
- Common::HashMap<uint16, MohawkSurface*> _cache;
- Common::HashMap<uint16, Common::Array<MohawkSurface*> > _subImageCache;
+ Common::HashMap<uint16, MohawkSurface *> _cache;
+ Common::HashMap<uint16, Common::Array<MohawkSurface *> > _subImageCache;
};
-#ifdef ENABLE_MYST
-
-class MystBitmap;
-class MohawkEngine_Myst;
-
-enum RectState {
- kRectEnabled,
- kRectDisabled,
- kRectUnreachable
-};
-
-class MystGraphics : public GraphicsManager {
-public:
- MystGraphics(MohawkEngine_Myst*);
- ~MystGraphics();
-
- void loadExternalPictureFile(uint16 stack);
- void copyImageSectionToScreen(uint16 image, Common::Rect src, Common::Rect dest);
- void copyImageSectionToBackBuffer(uint16 image, Common::Rect src, Common::Rect dest);
- void copyImageToScreen(uint16 image, Common::Rect dest);
- void copyImageToBackBuffer(uint16 image, Common::Rect dest);
- void copyBackBufferToScreen(Common::Rect r);
- void runTransition(uint16 type, Common::Rect rect, uint16 steps, uint16 delay);
- void drawRect(Common::Rect rect, RectState state);
- void drawLine(const Common::Point &p1, const Common::Point &p2, uint32 color);
- void enableDrawingTimeSimulation(bool enable);
- void fadeToBlack();
- void fadeFromBlack();
-
-protected:
- MohawkSurface *decodeImage(uint16 id);
- MohawkEngine *getVM() { return (MohawkEngine *)_vm; }
- void simulatePreviousDrawDelay(const Common::Rect &dest);
- void copyBackBufferToScreenWithSaturation(int16 saturation);
-
-private:
- MohawkEngine_Myst *_vm;
- MystBitmap *_bmpDecoder;
- Graphics::PictDecoder *_pictDecoder;
- Graphics::JPEG *_jpegDecoder;
-
- struct PictureFile {
- uint32 pictureCount;
- struct PictureEntry {
- uint32 offset;
- uint32 size;
- uint16 id;
- uint16 type;
- uint16 width;
- uint16 height;
- } *entries;
-
- Common::File picFile;
- } _pictureFile;
-
- Graphics::Surface *_backBuffer;
- Graphics::PixelFormat _pixelFormat;
- Common::Rect _viewport;
-
- int _enableDrawingTimeSimulation;
- uint32 _nextAllowedDrawTime;
- static const uint _constantDrawDelay = 10; // ms
- static const uint _proportionalDrawDelay = 500; // pixels per ms
-};
-
-#endif // ENABLE_MYST
-
-#ifdef ENABLE_RIVEN
-
-class MohawkEngine_Riven;
-
-class RivenGraphics : public GraphicsManager {
-public:
- RivenGraphics(MohawkEngine_Riven *vm);
- ~RivenGraphics();
-
- void copyImageToScreen(uint16, uint32, uint32, uint32, uint32);
- void updateScreen(Common::Rect updateRect = Common::Rect(0, 0, 608, 392));
- bool _updatesEnabled;
- Common::Array<uint16> _activatedPLSTs;
- void drawPLST(uint16 x);
- void drawRect(Common::Rect rect, bool active);
- void drawImageRect(uint16 id, Common::Rect srcRect, Common::Rect dstRect);
- void drawExtrasImage(uint16 id, Common::Rect dstRect);
-
- // Water Effect
- void scheduleWaterEffect(uint16);
- void clearWaterEffects();
- bool runScheduledWaterEffects();
-
- // Transitions
- void scheduleTransition(uint16 id, Common::Rect rect = Common::Rect(0, 0, 608, 392));
- void runScheduledTransition();
- void fadeToBlack();
- void setTransitionSpeed(uint32 speed) { _transitionSpeed = speed; }
-
- // Inventory
- void showInventory();
- void hideInventory();
-
- // Credits
- void beginCredits();
- void updateCredits();
- uint getCurCreditsImage() { return _creditsImage; }
-
-protected:
- MohawkSurface *decodeImage(uint16 id);
- MohawkEngine *getVM() { return (MohawkEngine *)_vm; }
-
-private:
- MohawkEngine_Riven *_vm;
- MohawkBitmap *_bitmapDecoder;
-
- // Water Effects
- struct SFXERecord {
- // Record values
- uint16 frameCount;
- Common::Rect rect;
- uint16 speed;
- Common::Array<Common::SeekableReadStream*> frameScripts;
-
- // Cur frame
- uint16 curFrame;
- uint32 lastFrameTime;
- };
- Common::Array<SFXERecord> _waterEffects;
-
- // Transitions
- int16 _scheduledTransition;
- Common::Rect _transitionRect;
- uint32 _transitionSpeed;
-
- // Inventory
- void clearInventoryArea();
- void drawInventoryImage(uint16 id, const Common::Rect *rect);
- bool _inventoryDrawn;
-
- // Screen Related
- Graphics::Surface *_mainScreen;
- bool _dirtyScreen;
- Graphics::PixelFormat _pixelFormat;
- void clearMainScreen();
-
- // Credits
- uint _creditsImage, _creditsPos;
-};
-
-#endif // ENABLE_RIVEN
-
-class LBGraphics : public GraphicsManager {
-public:
- LBGraphics(MohawkEngine_LivingBooks *vm, uint16 width, uint16 height);
- ~LBGraphics();
-
- void setPalette(uint16 id);
- void copyOffsetAnimImageToScreen(uint16 image, int left = 0, int top = 0);
- bool imageIsTransparentAt(uint16 image, bool useOffsets, int x, int y);
-
-protected:
- MohawkSurface *decodeImage(uint16 id);
- MohawkEngine *getVM() { return (MohawkEngine *)_vm; }
-
-private:
- MohawkBitmap *_bmpDecoder;
- MohawkEngine_LivingBooks *_vm;
-};
-
-#ifdef ENABLE_CSTIME
-
-class MohawkEngine_CSTime;
-
-class CSTimeGraphics : public GraphicsManager {
-public:
- CSTimeGraphics(MohawkEngine_CSTime *vm);
- ~CSTimeGraphics();
-
- void drawRect(Common::Rect rect, byte color);
-
-protected:
- MohawkSurface *decodeImage(uint16 id);
- Common::Array<MohawkSurface *> decodeImages(uint16 id);
- MohawkEngine *getVM() { return (MohawkEngine *)_vm; }
-
-private:
- MohawkBitmap *_bmpDecoder;
- MohawkEngine_CSTime *_vm;
-};
-
-#endif
-
} // End of namespace Mohawk
#endif
diff --git a/engines/mohawk/installer_archive.cpp b/engines/mohawk/installer_archive.cpp
index 83796158a6..636b7ae476 100644
--- a/engines/mohawk/installer_archive.cpp
+++ b/engines/mohawk/installer_archive.cpp
@@ -107,18 +107,18 @@ void InstallerArchive::close() {
_map.clear();
}
-bool InstallerArchive::hasFile(const Common::String &name) {
+bool InstallerArchive::hasFile(const Common::String &name) const {
return _map.contains(name);
}
-int InstallerArchive::listMembers(Common::ArchiveMemberList &list) {
+int InstallerArchive::listMembers(Common::ArchiveMemberList &list) const {
for (FileMap::const_iterator it = _map.begin(); it != _map.end(); it++)
list.push_back(getMember(it->_key));
return _map.size();
}
-Common::ArchiveMemberPtr InstallerArchive::getMember(const Common::String &name) {
+const Common::ArchiveMemberPtr InstallerArchive::getMember(const Common::String &name) const {
return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, this));
}
diff --git a/engines/mohawk/installer_archive.h b/engines/mohawk/installer_archive.h
index 27877d69f9..89d2d85f8d 100644
--- a/engines/mohawk/installer_archive.h
+++ b/engines/mohawk/installer_archive.h
@@ -43,9 +43,9 @@ public:
bool isOpen() const { return _stream != 0; }
// Common::Archive API implementation
- bool hasFile(const Common::String &name);
- int listMembers(Common::ArchiveMemberList &list);
- Common::ArchiveMemberPtr getMember(const Common::String &name);
+ bool hasFile(const Common::String &name) const;
+ int listMembers(Common::ArchiveMemberList &list) const;
+ const Common::ArchiveMemberPtr getMember(const Common::String &name) const;
Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const;
private:
diff --git a/engines/mohawk/livingbooks.cpp b/engines/mohawk/livingbooks.cpp
index 08f3b86c7c..708478a6d8 100644
--- a/engines/mohawk/livingbooks.cpp
+++ b/engines/mohawk/livingbooks.cpp
@@ -388,10 +388,13 @@ bool MohawkEngine_LivingBooks::loadPage(LBMode mode, uint page, uint subpage) {
}
// TODO: fading between pages
+#if 0
bool fade = false;
if (leftover.contains("fade")) {
fade = true;
}
+#endif
+
if (leftover.contains("read")) {
_readOnly = true;
}
diff --git a/engines/mohawk/livingbooks.h b/engines/mohawk/livingbooks.h
index 23ab0acfb1..91d6a8cd30 100644
--- a/engines/mohawk/livingbooks.h
+++ b/engines/mohawk/livingbooks.h
@@ -25,7 +25,7 @@
#include "mohawk/mohawk.h"
#include "mohawk/console.h"
-#include "mohawk/graphics.h"
+#include "mohawk/livingbooks_graphics.h"
#include "mohawk/sound.h"
#include "common/config-file.h"
diff --git a/engines/mohawk/livingbooks_code.cpp b/engines/mohawk/livingbooks_code.cpp
index 41acea19c4..bb8f7a0d05 100644
--- a/engines/mohawk/livingbooks_code.cpp
+++ b/engines/mohawk/livingbooks_code.cpp
@@ -1766,7 +1766,7 @@ uint LBCode::parseCode(const Common::String &source) {
{
Common::String tempString;
while (pos < source.size()) {
- if (!isalpha(source[pos]) && !isdigit(source[pos]))
+ if (!Common::isAlpha(source[pos]) && !Common::isDigit(source[pos]))
break;
tempString += source[pos++];
}
@@ -1777,7 +1777,7 @@ uint LBCode::parseCode(const Common::String &source) {
}
break;
default:
- if (isdigit(token)) {
+ if (Common::isDigit(token)) {
const char *in = source.c_str() + pos - 1;
// FIXME: handle floats?
char *endptr;
@@ -1792,11 +1792,11 @@ uint LBCode::parseCode(const Common::String &source) {
WRITE_BE_UINT16(tmp, (int16)intValue);
code.push_back(tmp[0]);
code.push_back(tmp[1]);
- } else if (isalpha(token)) {
+ } else if (Common::isAlpha(token)) {
Common::String tempString;
tempString += token;
while (pos < source.size()) {
- if (!isalpha(source[pos]) && !isdigit(source[pos]))
+ if (!Common::isAlpha(source[pos]) && !Common::isDigit(source[pos]))
break;
tempString += source[pos++];
}
diff --git a/engines/mohawk/livingbooks_graphics.cpp b/engines/mohawk/livingbooks_graphics.cpp
new file mode 100644
index 0000000000..fb764fa15b
--- /dev/null
+++ b/engines/mohawk/livingbooks_graphics.cpp
@@ -0,0 +1,102 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "mohawk/resource.h"
+#include "mohawk/livingbooks.h"
+#include "mohawk/livingbooks_graphics.h"
+
+#include "common/substream.h"
+#include "common/system.h"
+#include "engines/util.h"
+#include "graphics/palette.h"
+
+namespace Mohawk {
+
+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);
+ }
+}
+
+} // End of namespace Mohawk
diff --git a/engines/mohawk/livingbooks_graphics.h b/engines/mohawk/livingbooks_graphics.h
new file mode 100644
index 0000000000..3e2609750a
--- /dev/null
+++ b/engines/mohawk/livingbooks_graphics.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef MOHAWK_LIVINGBOOKS_GRAPHICS_H
+#define MOHAWK_LIVINGBOOKS_GRAPHICS_H
+
+#include "mohawk/graphics.h"
+
+namespace Mohawk {
+
+class MohawkEngine_LivingBooks;
+
+class LBGraphics : public GraphicsManager {
+public:
+ LBGraphics(MohawkEngine_LivingBooks *vm, uint16 width, uint16 height);
+ ~LBGraphics();
+
+ void setPalette(uint16 id);
+ void copyOffsetAnimImageToScreen(uint16 image, int left = 0, int top = 0);
+ bool imageIsTransparentAt(uint16 image, bool useOffsets, int x, int y);
+
+protected:
+ MohawkSurface *decodeImage(uint16 id);
+ MohawkEngine *getVM() { return (MohawkEngine *)_vm; }
+
+private:
+ MohawkBitmap *_bmpDecoder;
+ MohawkEngine_LivingBooks *_vm;
+};
+
+} // End of namespace Mohawk
+
+#endif
diff --git a/engines/mohawk/module.mk b/engines/mohawk/module.mk
index 882f3966b2..83e541e3e4 100644
--- a/engines/mohawk/module.mk
+++ b/engines/mohawk/module.mk
@@ -10,6 +10,7 @@ MODULE_OBJS = \
installer_archive.o \
livingbooks.o \
livingbooks_code.o \
+ livingbooks_graphics.o \
livingbooks_lbx.o \
mohawk.o \
resource.o \
@@ -22,6 +23,7 @@ MODULE_OBJS += \
cstime.o \
cstime_cases.o \
cstime_game.o \
+ cstime_graphics.o \
cstime_ui.o \
cstime_view.o
endif
@@ -30,6 +32,7 @@ ifdef ENABLE_MYST
MODULE_OBJS += \
myst.o \
myst_areas.o \
+ myst_graphics.o \
myst_scripts.o \
myst_state.o \
resource_cache.o \
@@ -51,6 +54,7 @@ ifdef ENABLE_RIVEN
MODULE_OBJS += \
riven.o \
riven_external.o \
+ riven_graphics.o \
riven_saveload.o \
riven_scripts.o \
riven_vars.o
diff --git a/engines/mohawk/myst.cpp b/engines/mohawk/myst.cpp
index eeb4594f3c..c22b30ad4d 100644
--- a/engines/mohawk/myst.cpp
+++ b/engines/mohawk/myst.cpp
@@ -27,9 +27,9 @@
#include "common/textconsole.h"
#include "mohawk/cursors.h"
-#include "mohawk/graphics.h"
#include "mohawk/myst.h"
#include "mohawk/myst_areas.h"
+#include "mohawk/myst_graphics.h"
#include "mohawk/myst_scripts.h"
#include "mohawk/myst_state.h"
#include "mohawk/dialogs.h"
diff --git a/engines/mohawk/myst.h b/engines/mohawk/myst.h
index 02f0a46e3f..30770f7ec9 100644
--- a/engines/mohawk/myst.h
+++ b/engines/mohawk/myst.h
@@ -173,7 +173,7 @@ public:
MystGraphics *_gfx;
MystGameState *_gameState;
MystScriptParser *_scriptParser;
- Common::Array<MystResource*> _resources;
+ Common::Array<MystResource *> _resources;
MystResource *_dragResource;
Common::RandomSource *_rnd;
diff --git a/engines/mohawk/myst_areas.cpp b/engines/mohawk/myst_areas.cpp
index 294fcea2f1..a54b67bef4 100644
--- a/engines/mohawk/myst_areas.cpp
+++ b/engines/mohawk/myst_areas.cpp
@@ -20,8 +20,8 @@
*
*/
-#include "mohawk/graphics.h"
#include "mohawk/myst_areas.h"
+#include "mohawk/myst_graphics.h"
#include "mohawk/myst_scripts.h"
#include "mohawk/sound.h"
#include "mohawk/video.h"
@@ -134,7 +134,7 @@ const Common::String MystResourceType5::describe() {
desc += " ops:";
for (uint i = 0; i < _script->size(); i++)
- desc += " " + _vm->_scriptParser->getOpcodeDesc(_script->operator[](i).opcode);
+ desc += " " + _vm->_scriptParser->getOpcodeDesc((*_script)[i].opcode);
}
return desc;
diff --git a/engines/mohawk/myst_areas.h b/engines/mohawk/myst_areas.h
index 136356ea4f..62af5ec4cf 100644
--- a/engines/mohawk/myst_areas.h
+++ b/engines/mohawk/myst_areas.h
@@ -20,11 +20,13 @@
*
*/
+#ifndef MYST_AREAS_H
+#define MYST_AREAS_H
+
#include "mohawk/myst.h"
#include "mohawk/video.h"
-#ifndef MYST_AREAS_H
-#define MYST_AREAS_H
+#include "common/rect.h"
namespace Mohawk {
@@ -137,7 +139,7 @@ public:
protected:
uint16 _var7;
uint16 _numSubResources;
- Common::Array<MystResource*> _subResources;
+ Common::Array<MystResource *> _subResources;
};
class MystResourceType8 : public MystResourceType7 {
diff --git a/engines/mohawk/myst_graphics.cpp b/engines/mohawk/myst_graphics.cpp
new file mode 100644
index 0000000000..484e49d529
--- /dev/null
+++ b/engines/mohawk/myst_graphics.cpp
@@ -0,0 +1,494 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "mohawk/myst.h"
+#include "mohawk/myst_graphics.h"
+#include "mohawk/resource.h"
+
+#include "common/substream.h"
+#include "common/system.h"
+#include "common/textconsole.h"
+#include "engines/util.h"
+#include "graphics/decoders/jpeg.h"
+#include "graphics/decoders/pict.h"
+
+namespace Mohawk {
+
+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");
+
+ _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[] _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) {
+ Graphics::JPEGDecoder jpeg;
+ Common::SeekableSubReadStream subStream(&_pictureFile.picFile, _pictureFile.entries[i].offset, _pictureFile.entries[i].offset + _pictureFile.entries[i].size);
+
+ if (!jpeg.loadStream(subStream))
+ error("Could not decode Myst ME Mac JPEG");
+
+ mhkSurface = new MohawkSurface(jpeg.getSurface()->convertTo(_pixelFormat));
+ } else if (_pictureFile.entries[i].type == 1) {
+ Graphics::PICTDecoder pict;
+ Common::SeekableSubReadStream subStream(&_pictureFile.picFile, _pictureFile.entries[i].offset, _pictureFile.entries[i].offset + _pictureFile.entries[i].size);
+
+ if (!pict.loadStream(subStream))
+ error("Could not decode Myst ME Mac PICT");
+
+ mhkSurface = new MohawkSurface(pict.getSurface()->convertTo(_pixelFormat));
+ } 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) {
+ Graphics::PICTDecoder pict;
+
+ if (!pict.loadStream(*dataStream))
+ error("Could not decode Myst ME PICT");
+
+ mhkSurface = new MohawkSurface(pict.getSurface()->convertTo(_pixelFormat));
+ } 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);
+ }
+}
+
+} // End of namespace Mohawk
diff --git a/engines/mohawk/myst_graphics.h b/engines/mohawk/myst_graphics.h
new file mode 100644
index 0000000000..20fd46c5b9
--- /dev/null
+++ b/engines/mohawk/myst_graphics.h
@@ -0,0 +1,95 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef MOHAWK_MYST_GRAPHICS_H
+#define MOHAWK_MYST_GRAPHICS_H
+
+#include "mohawk/graphics.h"
+
+#include "common/file.h"
+
+namespace Mohawk {
+
+class MystBitmap;
+class MohawkEngine_Myst;
+
+enum RectState {
+ kRectEnabled,
+ kRectDisabled,
+ kRectUnreachable
+};
+
+class MystGraphics : public GraphicsManager {
+public:
+ MystGraphics(MohawkEngine_Myst*);
+ ~MystGraphics();
+
+ void loadExternalPictureFile(uint16 stack);
+ void copyImageSectionToScreen(uint16 image, Common::Rect src, Common::Rect dest);
+ void copyImageSectionToBackBuffer(uint16 image, Common::Rect src, Common::Rect dest);
+ void copyImageToScreen(uint16 image, Common::Rect dest);
+ void copyImageToBackBuffer(uint16 image, Common::Rect dest);
+ void copyBackBufferToScreen(Common::Rect r);
+ void runTransition(uint16 type, Common::Rect rect, uint16 steps, uint16 delay);
+ void drawRect(Common::Rect rect, RectState state);
+ void drawLine(const Common::Point &p1, const Common::Point &p2, uint32 color);
+ void enableDrawingTimeSimulation(bool enable);
+ void fadeToBlack();
+ void fadeFromBlack();
+
+protected:
+ MohawkSurface *decodeImage(uint16 id);
+ MohawkEngine *getVM() { return (MohawkEngine *)_vm; }
+ void simulatePreviousDrawDelay(const Common::Rect &dest);
+ void copyBackBufferToScreenWithSaturation(int16 saturation);
+
+private:
+ MohawkEngine_Myst *_vm;
+ MystBitmap *_bmpDecoder;
+
+ struct PictureFile {
+ uint32 pictureCount;
+ struct PictureEntry {
+ uint32 offset;
+ uint32 size;
+ uint16 id;
+ uint16 type;
+ uint16 width;
+ uint16 height;
+ } *entries;
+
+ Common::File picFile;
+ } _pictureFile;
+
+ Graphics::Surface *_backBuffer;
+ Graphics::PixelFormat _pixelFormat;
+ Common::Rect _viewport;
+
+ int _enableDrawingTimeSimulation;
+ uint32 _nextAllowedDrawTime;
+ static const uint _constantDrawDelay = 10; // ms
+ static const uint _proportionalDrawDelay = 500; // pixels per ms
+};
+
+} // End of namespace Mohawk
+
+#endif
diff --git a/engines/mohawk/myst_scripts.cpp b/engines/mohawk/myst_scripts.cpp
index ca8e985491..107a8b03e9 100644
--- a/engines/mohawk/myst_scripts.cpp
+++ b/engines/mohawk/myst_scripts.cpp
@@ -22,8 +22,8 @@
#include "mohawk/cursors.h"
#include "mohawk/myst.h"
-#include "mohawk/graphics.h"
#include "mohawk/myst_areas.h"
+#include "mohawk/myst_graphics.h"
#include "mohawk/myst_scripts.h"
#include "mohawk/sound.h"
#include "mohawk/video.h"
@@ -161,7 +161,7 @@ void MystScriptParser::runScript(MystScript script, MystResource *invokingResour
_vm->_gfx->enableDrawingTimeSimulation(true);
for (uint16 i = 0; i < script->size(); i++) {
- MystScriptEntry &entry = script->operator[](i);
+ MystScriptEntry &entry = (*script)[i];
debugC(kDebugScript, "\tOpcode %d: %d", i, entry.opcode);
if (entry.type == kMystScriptNormal)
@@ -207,7 +207,7 @@ MystScript MystScriptParser::readScript(Common::SeekableReadStream *stream, Myst
script->resize(opcodeCount);
for (uint16 i = 0; i < opcodeCount; i++) {
- MystScriptEntry &entry = script->operator[](i);
+ MystScriptEntry &entry = (*script)[i];
entry.type = type;
// Resource ID only exists in INIT and EXIT scripts
diff --git a/engines/mohawk/myst_scripts.h b/engines/mohawk/myst_scripts.h
index 18f5b27a6d..ccb76e0dc8 100644
--- a/engines/mohawk/myst_scripts.h
+++ b/engines/mohawk/myst_scripts.h
@@ -143,7 +143,7 @@ protected:
const char *desc;
};
- Common::Array<MystOpcode*> _opcodes;
+ Common::Array<MystOpcode *> _opcodes;
MystResource *_invokingResource;
diff --git a/engines/mohawk/myst_stacks/channelwood.cpp b/engines/mohawk/myst_stacks/channelwood.cpp
index 9ca47cc92a..069281f5dc 100644
--- a/engines/mohawk/myst_stacks/channelwood.cpp
+++ b/engines/mohawk/myst_stacks/channelwood.cpp
@@ -22,8 +22,8 @@
#include "mohawk/cursors.h"
#include "mohawk/myst.h"
-#include "mohawk/graphics.h"
#include "mohawk/myst_areas.h"
+#include "mohawk/myst_graphics.h"
#include "mohawk/myst_state.h"
#include "mohawk/sound.h"
#include "mohawk/video.h"
diff --git a/engines/mohawk/myst_stacks/credits.cpp b/engines/mohawk/myst_stacks/credits.cpp
index ad593e3542..192e55d5e3 100644
--- a/engines/mohawk/myst_stacks/credits.cpp
+++ b/engines/mohawk/myst_stacks/credits.cpp
@@ -21,8 +21,8 @@
*/
#include "mohawk/myst.h"
-#include "mohawk/graphics.h"
#include "mohawk/myst_areas.h"
+#include "mohawk/myst_graphics.h"
#include "mohawk/sound.h"
#include "mohawk/video.h"
#include "mohawk/myst_stacks/credits.h"
diff --git a/engines/mohawk/myst_stacks/demo.cpp b/engines/mohawk/myst_stacks/demo.cpp
index fbad7dc384..29a12571fd 100644
--- a/engines/mohawk/myst_stacks/demo.cpp
+++ b/engines/mohawk/myst_stacks/demo.cpp
@@ -21,8 +21,8 @@
*/
#include "mohawk/cursors.h"
-#include "mohawk/graphics.h"
#include "mohawk/myst.h"
+#include "mohawk/myst_graphics.h"
#include "mohawk/myst_stacks/demo.h"
#include "common/system.h"
diff --git a/engines/mohawk/myst_stacks/intro.cpp b/engines/mohawk/myst_stacks/intro.cpp
index 7d3179fa24..0af386f51f 100644
--- a/engines/mohawk/myst_stacks/intro.cpp
+++ b/engines/mohawk/myst_stacks/intro.cpp
@@ -21,8 +21,8 @@
*/
#include "mohawk/myst.h"
-#include "mohawk/graphics.h"
#include "mohawk/myst_areas.h"
+#include "mohawk/myst_graphics.h"
#include "mohawk/myst_state.h"
#include "mohawk/sound.h"
#include "mohawk/video.h"
diff --git a/engines/mohawk/myst_stacks/mechanical.cpp b/engines/mohawk/myst_stacks/mechanical.cpp
index 12d9dc7e2f..79de03308c 100644
--- a/engines/mohawk/myst_stacks/mechanical.cpp
+++ b/engines/mohawk/myst_stacks/mechanical.cpp
@@ -22,8 +22,8 @@
#include "mohawk/cursors.h"
#include "mohawk/myst.h"
-#include "mohawk/graphics.h"
#include "mohawk/myst_areas.h"
+#include "mohawk/myst_graphics.h"
#include "mohawk/myst_state.h"
#include "mohawk/sound.h"
#include "mohawk/video.h"
diff --git a/engines/mohawk/myst_stacks/myst.cpp b/engines/mohawk/myst_stacks/myst.cpp
index b6c0a3212f..c1ddc74c82 100644
--- a/engines/mohawk/myst_stacks/myst.cpp
+++ b/engines/mohawk/myst_stacks/myst.cpp
@@ -22,8 +22,8 @@
#include "mohawk/cursors.h"
#include "mohawk/myst.h"
-#include "mohawk/graphics.h"
#include "mohawk/myst_areas.h"
+#include "mohawk/myst_graphics.h"
#include "mohawk/myst_state.h"
#include "mohawk/sound.h"
#include "mohawk/video.h"
@@ -2978,15 +2978,17 @@ void Myst::clockReset() {
}
void Myst::clockResetWeight() {
- // Set video bounds, weight going up
+ _clockWeightVideo = _vm->_video->playMovie(_vm->wrapMovieFilename("cl1wlfch", kMystStack) , 124, 0);
+
if (!(_vm->getFeatures() & GF_ME)) {
- _clockWeightVideo = _vm->_video->playMovie(_vm->wrapMovieFilename("cl1wlfch", kMystStack) , 124, 0);
+ // Set video bounds, weight going up
_vm->_video->setVideoBounds(_clockWeightVideo,
Audio::Timestamp(0, 2214 * 2 - _clockWeightPosition, 600),
Audio::Timestamp(0, 2214 * 2, 600));
} else {
- //FIXME: Needs QT backwards playing
+ //FIXME: Needs QT backwards playing, for now just display the weight up
warning("Weight going back up not implemented");
+ _vm->_video->drawVideoFrame(_clockWeightVideo, Audio::Timestamp(0, 0, 600));
}
// Reset position
diff --git a/engines/mohawk/myst_stacks/preview.cpp b/engines/mohawk/myst_stacks/preview.cpp
index 31e22bb8c5..0b8dcf897a 100644
--- a/engines/mohawk/myst_stacks/preview.cpp
+++ b/engines/mohawk/myst_stacks/preview.cpp
@@ -22,8 +22,8 @@
#include "mohawk/cursors.h"
#include "mohawk/myst.h"
-#include "mohawk/graphics.h"
#include "mohawk/myst_areas.h"
+#include "mohawk/myst_graphics.h"
#include "mohawk/sound.h"
#include "mohawk/video.h"
#include "mohawk/myst_stacks/preview.h"
diff --git a/engines/mohawk/myst_stacks/slides.cpp b/engines/mohawk/myst_stacks/slides.cpp
index 794793e49c..c0bb400db1 100644
--- a/engines/mohawk/myst_stacks/slides.cpp
+++ b/engines/mohawk/myst_stacks/slides.cpp
@@ -22,8 +22,8 @@
#include "mohawk/cursors.h"
#include "mohawk/myst.h"
-#include "mohawk/graphics.h"
#include "mohawk/myst_areas.h"
+#include "mohawk/myst_graphics.h"
#include "mohawk/sound.h"
#include "mohawk/video.h"
#include "mohawk/myst_stacks/slides.h"
diff --git a/engines/mohawk/myst_stacks/stoneship.cpp b/engines/mohawk/myst_stacks/stoneship.cpp
index 6d54d0c586..ef228e62f3 100644
--- a/engines/mohawk/myst_stacks/stoneship.cpp
+++ b/engines/mohawk/myst_stacks/stoneship.cpp
@@ -22,8 +22,8 @@
#include "mohawk/cursors.h"
#include "mohawk/myst.h"
-#include "mohawk/graphics.h"
#include "mohawk/myst_areas.h"
+#include "mohawk/myst_graphics.h"
#include "mohawk/myst_state.h"
#include "mohawk/sound.h"
#include "mohawk/video.h"
diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp
index 3e2fa4f979..95a8313536 100644
--- a/engines/mohawk/riven.cpp
+++ b/engines/mohawk/riven.cpp
@@ -27,11 +27,11 @@
#include "common/system.h"
#include "mohawk/cursors.h"
-#include "mohawk/graphics.h"
#include "mohawk/installer_archive.h"
#include "mohawk/resource.h"
#include "mohawk/riven.h"
#include "mohawk/riven_external.h"
+#include "mohawk/riven_graphics.h"
#include "mohawk/riven_saveload.h"
#include "mohawk/dialogs.h"
#include "mohawk/sound.h"
@@ -171,7 +171,7 @@ Common::Error MohawkEngine_Riven::run() {
error ("Could not find saved game");
// Attempt to load the game. On failure, just send us to the main menu.
- if (!_saveLoad->loadGame(savedGamesList[gameToLoad])) {
+ if (_saveLoad->loadGame(savedGamesList[gameToLoad]).getCode() != Common::kNoError) {
changeToStack(aspit);
changeToCard(1);
}
@@ -729,7 +729,7 @@ void MohawkEngine_Riven::runLoadDialog() {
}
Common::Error MohawkEngine_Riven::loadGameState(int slot) {
- return _saveLoad->loadGame(_saveLoad->generateSaveGameList()[slot]) ? Common::kNoError : Common::kUnknownError;
+ return _saveLoad->loadGame(_saveLoad->generateSaveGameList()[slot]);
}
Common::Error MohawkEngine_Riven::saveGameState(int slot, const Common::String &desc) {
@@ -738,7 +738,7 @@ Common::Error MohawkEngine_Riven::saveGameState(int slot, const Common::String &
if ((uint)slot < saveList.size())
_saveLoad->deleteSave(saveList[slot]);
- return _saveLoad->saveGame(Common::String(desc)) ? Common::kNoError : Common::kUnknownError;
+ return _saveLoad->saveGame(desc);
}
Common::String MohawkEngine_Riven::getStackName(uint16 stack) const {
diff --git a/engines/mohawk/riven.h b/engines/mohawk/riven.h
index e99a9f78fc..961d85d61a 100644
--- a/engines/mohawk/riven.h
+++ b/engines/mohawk/riven.h
@@ -130,8 +130,8 @@ public:
GUI::Debugger *getDebugger();
- bool canLoadGameStateCurrently() { return true; }
- bool canSaveGameStateCurrently() { return true; }
+ bool canLoadGameStateCurrently() { return !(getFeatures() & GF_DEMO); }
+ bool canSaveGameStateCurrently() { return !(getFeatures() & GF_DEMO); }
Common::Error loadGameState(int slot);
Common::Error saveGameState(int slot, const Common::String &desc);
bool hasFeature(EngineFeature f) const;
diff --git a/engines/mohawk/riven_external.cpp b/engines/mohawk/riven_external.cpp
index 9e1365f8da..8dfc74ebf0 100644
--- a/engines/mohawk/riven_external.cpp
+++ b/engines/mohawk/riven_external.cpp
@@ -21,9 +21,9 @@
*/
#include "mohawk/cursors.h"
-#include "mohawk/graphics.h"
#include "mohawk/riven.h"
#include "mohawk/riven_external.h"
+#include "mohawk/riven_graphics.h"
#include "mohawk/sound.h"
#include "mohawk/video.h"
diff --git a/engines/mohawk/riven_external.h b/engines/mohawk/riven_external.h
index 5f5d0cb0b2..9f076325a2 100644
--- a/engines/mohawk/riven_external.h
+++ b/engines/mohawk/riven_external.h
@@ -53,7 +53,7 @@ private:
ExternalCmd proc;
};
- Common::Array<RivenExternalCmd*> _externalCommands;
+ Common::Array<RivenExternalCmd *> _externalCommands;
void setupCommands();
// Supplementary Functions
diff --git a/engines/mohawk/riven_graphics.cpp b/engines/mohawk/riven_graphics.cpp
new file mode 100644
index 0000000000..9415e51412
--- /dev/null
+++ b/engines/mohawk/riven_graphics.cpp
@@ -0,0 +1,445 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "mohawk/resource.h"
+#include "mohawk/riven.h"
+#include "mohawk/riven_graphics.h"
+
+#include "common/system.h"
+#include "engines/util.h"
+
+namespace Mohawk {
+
+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();
+ }
+}
+
+} // End of namespace Mohawk
diff --git a/engines/mohawk/riven_graphics.h b/engines/mohawk/riven_graphics.h
new file mode 100644
index 0000000000..48dda28afd
--- /dev/null
+++ b/engines/mohawk/riven_graphics.h
@@ -0,0 +1,110 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef MOHAWK_RIVEN_GRAPHICS_H
+#define MOHAWK_RIVEN_GRAPHICS_H
+
+#include "mohawk/graphics.h"
+
+namespace Mohawk {
+
+class MohawkEngine_Riven;
+
+class RivenGraphics : public GraphicsManager {
+public:
+ RivenGraphics(MohawkEngine_Riven *vm);
+ ~RivenGraphics();
+
+ void copyImageToScreen(uint16, uint32, uint32, uint32, uint32);
+ void updateScreen(Common::Rect updateRect = Common::Rect(0, 0, 608, 392));
+ bool _updatesEnabled;
+ Common::Array<uint16> _activatedPLSTs;
+ void drawPLST(uint16 x);
+ void drawRect(Common::Rect rect, bool active);
+ void drawImageRect(uint16 id, Common::Rect srcRect, Common::Rect dstRect);
+ void drawExtrasImage(uint16 id, Common::Rect dstRect);
+
+ // Water Effect
+ void scheduleWaterEffect(uint16);
+ void clearWaterEffects();
+ bool runScheduledWaterEffects();
+
+ // Transitions
+ void scheduleTransition(uint16 id, Common::Rect rect = Common::Rect(0, 0, 608, 392));
+ void runScheduledTransition();
+ void fadeToBlack();
+ void setTransitionSpeed(uint32 speed) { _transitionSpeed = speed; }
+
+ // Inventory
+ void showInventory();
+ void hideInventory();
+
+ // Credits
+ void beginCredits();
+ void updateCredits();
+ uint getCurCreditsImage() { return _creditsImage; }
+
+protected:
+ MohawkSurface *decodeImage(uint16 id);
+ MohawkEngine *getVM() { return (MohawkEngine *)_vm; }
+
+private:
+ MohawkEngine_Riven *_vm;
+ MohawkBitmap *_bitmapDecoder;
+
+ // Water Effects
+ struct SFXERecord {
+ // Record values
+ uint16 frameCount;
+ Common::Rect rect;
+ uint16 speed;
+ Common::Array<Common::SeekableReadStream *> frameScripts;
+
+ // Cur frame
+ uint16 curFrame;
+ uint32 lastFrameTime;
+ };
+ Common::Array<SFXERecord> _waterEffects;
+
+ // Transitions
+ int16 _scheduledTransition;
+ Common::Rect _transitionRect;
+ uint32 _transitionSpeed;
+
+ // Inventory
+ void clearInventoryArea();
+ void drawInventoryImage(uint16 id, const Common::Rect *rect);
+ bool _inventoryDrawn;
+
+ // Screen Related
+ Graphics::Surface *_mainScreen;
+ bool _dirtyScreen;
+ Graphics::PixelFormat _pixelFormat;
+ void clearMainScreen();
+
+ // Credits
+ uint _creditsImage, _creditsPos;
+};
+
+} // End of namespace Mohawk
+
+#endif
diff --git a/engines/mohawk/riven_saveload.cpp b/engines/mohawk/riven_saveload.cpp
index 18c13ec12b..f5bf7782d4 100644
--- a/engines/mohawk/riven_saveload.cpp
+++ b/engines/mohawk/riven_saveload.cpp
@@ -88,13 +88,13 @@ static uint16 mapNewStackIDToOld(uint16 newID) {
return 0;
}
-bool RivenSaveLoad::loadGame(Common::String filename) {
+Common::Error RivenSaveLoad::loadGame(Common::String filename) {
if (_vm->getFeatures() & GF_DEMO) // Don't load games in the demo
- return false;
+ return Common::kNoError;
Common::InSaveFile *loadFile = _saveFileMan->openForLoading(filename);
if (!loadFile)
- return false;
+ return Common::kReadingFailed;
debug(0, "Loading game from \'%s\'", filename.c_str());
@@ -103,7 +103,7 @@ bool RivenSaveLoad::loadGame(Common::String filename) {
if (!mhk->openStream(loadFile)) {
warning("Save file is not a Mohawk archive");
delete mhk;
- return false;
+ return Common::Error(Common::kUnknownError, "Invalid save file");
}
// First, let's make sure we're using a saved game file from this version of Riven by checking the VERS resource
@@ -114,7 +114,7 @@ bool RivenSaveLoad::loadGame(Common::String filename) {
|| (saveGameVersion == kDVDSaveGameVersion && !(_vm->getFeatures() & GF_DVD))) {
warning("Incompatible saved game versions. No support for this yet");
delete mhk;
- return false;
+ return Common::Error(Common::kUnknownError, "Incompatible save version");
}
// Now, we'll read in the variable values.
@@ -206,7 +206,7 @@ bool RivenSaveLoad::loadGame(Common::String filename) {
delete zips;
delete mhk;
- return true;
+ return Common::kNoError;
}
Common::MemoryWriteStreamDynamic *RivenSaveLoad::genVERSSection() {
@@ -273,7 +273,7 @@ Common::MemoryWriteStreamDynamic *RivenSaveLoad::genZIPSSection() {
return stream;
}
-bool RivenSaveLoad::saveGame(Common::String filename) {
+Common::Error RivenSaveLoad::saveGame(Common::String filename) {
// NOTE: This code is designed to only output a Mohawk archive
// for a Riven saved game. It's hardcoded to do this because
// (as of right now) this is the only place in the engine
@@ -295,7 +295,7 @@ bool RivenSaveLoad::saveGame(Common::String filename) {
Common::OutSaveFile *saveFile = _saveFileMan->openForSaving(filename);
if (!saveFile)
- return false;
+ return Common::kWritingFailed;
debug (0, "Saving game to \'%s\'", filename.c_str());
@@ -418,7 +418,7 @@ bool RivenSaveLoad::saveGame(Common::String filename) {
delete varsSection;
delete zipsSection;
- return true;
+ return Common::kNoError;
}
void RivenSaveLoad::deleteSave(Common::String saveName) {
diff --git a/engines/mohawk/riven_saveload.h b/engines/mohawk/riven_saveload.h
index c1b3fc639e..37b73c26c6 100644
--- a/engines/mohawk/riven_saveload.h
+++ b/engines/mohawk/riven_saveload.h
@@ -42,8 +42,8 @@ public:
~RivenSaveLoad();
Common::StringArray generateSaveGameList();
- bool loadGame(Common::String);
- bool saveGame(Common::String);
+ Common::Error loadGame(Common::String);
+ Common::Error saveGame(Common::String);
void deleteSave(Common::String);
private:
diff --git a/engines/mohawk/riven_scripts.cpp b/engines/mohawk/riven_scripts.cpp
index 6e3e9a34dc..352a018990 100644
--- a/engines/mohawk/riven_scripts.cpp
+++ b/engines/mohawk/riven_scripts.cpp
@@ -21,9 +21,9 @@
*/
#include "mohawk/cursors.h"
-#include "mohawk/graphics.h"
#include "mohawk/riven.h"
#include "mohawk/riven_external.h"
+#include "mohawk/riven_graphics.h"
#include "mohawk/riven_scripts.h"
#include "mohawk/sound.h"
#include "mohawk/video.h"
diff --git a/engines/mohawk/riven_scripts.h b/engines/mohawk/riven_scripts.h
index 2932ba5939..6df4a2e523 100644
--- a/engines/mohawk/riven_scripts.h
+++ b/engines/mohawk/riven_scripts.h
@@ -27,8 +27,6 @@
#include "common/ptr.h"
#include "common/textconsole.h"
-class MohawkEngine_Riven;
-
#define DECLARE_OPCODE(x) void x(uint16 op, uint16 argc, uint16 *argv)
namespace Mohawk {
@@ -50,6 +48,7 @@ enum {
kStoredOpcodeScript // This is ScummVM-only to denote the script from a storeMovieOpcode() call
};
+class MohawkEngine_Riven;
class RivenScript;
class RivenScript {
@@ -125,7 +124,7 @@ private:
DECLARE_OPCODE(activateMLST);
};
-typedef Common::Array<RivenScript*> RivenScriptList;
+typedef Common::Array<RivenScript *> RivenScriptList;
class RivenScriptManager {
public:
diff --git a/engines/mohawk/riven_vars.cpp b/engines/mohawk/riven_vars.cpp
index ba5c343e07..8ddb76eec9 100644
--- a/engines/mohawk/riven_vars.cpp
+++ b/engines/mohawk/riven_vars.cpp
@@ -305,6 +305,7 @@ void MohawkEngine_Riven::initVars() {
_vars["gnmagcar"] = 1;
_vars["omusicplayer"] = 1;
_vars["transitionmode"] = kRivenTransitionSpeedFastest;
+ _vars["tdomeelev"] = 1;
// Randomize the telescope combination
uint32 &teleCombo = _vars["tcorrectorder"];
diff --git a/engines/mohawk/video.cpp b/engines/mohawk/video.cpp
index 7958906897..80fa4bf9a0 100644
--- a/engines/mohawk/video.cpp
+++ b/engines/mohawk/video.cpp
@@ -235,25 +235,7 @@ bool VideoManager::updateMovies() {
if (_videoStreams[i]->hasDirtyPalette())
_videoStreams[i]->setSystemPalette();
} else {
- convertedFrame = new Graphics::Surface();
- const byte *palette = _videoStreams[i]->getPalette();
- assert(palette);
-
- convertedFrame->create(frame->w, frame->h, pixelFormat);
-
- for (uint16 j = 0; j < frame->h; j++) {
- for (uint16 k = 0; k < frame->w; k++) {
- byte palIndex = *((const byte *)frame->getBasePtr(k, j));
- byte r = palette[palIndex * 3];
- byte g = palette[palIndex * 3 + 1];
- byte b = palette[palIndex * 3 + 2];
- if (pixelFormat.bytesPerPixel == 2)
- *((uint16 *)convertedFrame->getBasePtr(k, j)) = pixelFormat.RGBToColor(r, g, b);
- else
- *((uint32 *)convertedFrame->getBasePtr(k, j)) = pixelFormat.RGBToColor(r, g, b);
- }
- }
-
+ convertedFrame = frame->convertTo(pixelFormat, _videoStreams[i]->getPalette());
frame = convertedFrame;
}
}
@@ -261,7 +243,7 @@ bool VideoManager::updateMovies() {
// Clip the width/height to make sure we stay on the screen (Myst does this a few times)
uint16 width = MIN<int32>(_videoStreams[i]->getWidth(), _vm->_system->getWidth() - _videoStreams[i].x);
uint16 height = MIN<int32>(_videoStreams[i]->getHeight(), _vm->_system->getHeight() - _videoStreams[i].y);
- _vm->_system->copyRectToScreen((byte*)frame->pixels, frame->pitch, _videoStreams[i].x, _videoStreams[i].y, width, height);
+ _vm->_system->copyRectToScreen((byte *)frame->pixels, frame->pitch, _videoStreams[i].x, _videoStreams[i].y, width, height);
// We've drawn something to the screen, make sure we update it
updateScreen = true;