aboutsummaryrefslogtreecommitdiff
path: root/engines/mohawk/graphics.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/mohawk/graphics.cpp')
-rw-r--r--engines/mohawk/graphics.cpp434
1 files changed, 182 insertions, 252 deletions
diff --git a/engines/mohawk/graphics.cpp b/engines/mohawk/graphics.cpp
index f472a9d721..65eebf7134 100644
--- a/engines/mohawk/graphics.cpp
+++ b/engines/mohawk/graphics.cpp
@@ -27,43 +27,94 @@
#include "mohawk/graphics.h"
#include "mohawk/myst.h"
#include "mohawk/riven.h"
-#include "mohawk/riven_cursors.h"
#include "engines/util.h"
-#include "graphics/cursorman.h"
#include "graphics/primitives.h"
#include "gui/message.h"
namespace Mohawk {
-Graphics::Surface *ImageData::getSurface() {
+MohawkSurface::MohawkSurface() : _surface(0), _palette(0) {
+ _offsetX = 0;
+ _offsetY = 0;
+}
+
+MohawkSurface::MohawkSurface(Graphics::Surface *surface, byte *palette, int offsetX, int offsetY) : _palette(palette), _offsetX(offsetX), _offsetY(offsetY) {
+ assert(surface);
+
+ _surface = surface;
+}
+
+MohawkSurface::~MohawkSurface() {
+ free(_palette);
+
+ if (_surface) {
+ _surface->free();
+ delete _surface;
+ }
+}
+
+void MohawkSurface::convertToTrueColor() {
+ assert(_surface);
+
+ if (_surface->bytesPerPixel > 1)
+ return;
+
+ assert(_palette);
+
Graphics::PixelFormat pixelFormat = g_system->getScreenFormat();
Graphics::Surface *surface = new Graphics::Surface();
surface->create(_surface->w, _surface->h, pixelFormat.bytesPerPixel);
- if (_surface->bytesPerPixel == 1) {
- assert(_palette);
-
- 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 * 4];
- byte g = _palette[palIndex * 4 + 1];
- byte b = _palette[palIndex * 4 + 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);
- }
+ 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 * 4];
+ byte g = _palette[palIndex * 4 + 1];
+ byte b = _palette[palIndex * 4 + 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);
}
- } else
- memcpy(surface->pixels, _surface->pixels, _surface->w * _surface->h * _surface->bytesPerPixel);
+ }
- return surface;
+ // Free everything and set the new surface as the converted surface
+ _surface->free();
+ delete _surface;
+ free(_palette);
+ _palette = 0;
+ _surface = surface;
+}
+
+GraphicsManager::GraphicsManager() {
+}
+
+GraphicsManager::~GraphicsManager() {
+ clearCache();
+}
+
+void GraphicsManager::clearCache() {
+ for (Common::HashMap<uint16, MohawkSurface*>::iterator it = _cache.begin(); it != _cache.end(); it++)
+ delete it->_value;
+
+ _cache.clear();
}
-MystGraphics::MystGraphics(MohawkEngine_Myst* vm) : _vm(vm) {
+MohawkSurface *GraphicsManager::findImage(uint16 id) {
+ if (!_cache.contains(id))
+ _cache[id] = decodeImage(id);
+
+ // TODO: Probably would be nice to limit the size of the cache
+ // Currently, this can't get large because it is freed on every
+ // card/stack change in Myst/Riven so I'm not worried about it.
+ // Doesn't mean this shouldn't be done in the future.
+
+ return _cache[id];
+}
+
+MystGraphics::MystGraphics(MohawkEngine_Myst* vm) : GraphicsManager(), _vm(vm) {
_bmpDecoder = new MystBitmap();
// The original version of Myst could run in 8bpp color too.
@@ -86,12 +137,21 @@ MystGraphics::MystGraphics(MohawkEngine_Myst* vm) : _vm(vm) {
}
_pictureFile.entries = NULL;
+
+ // Initialize our buffer
+ _mainScreen = new Graphics::Surface();
+ _mainScreen->create(_vm->_system->getWidth(), _vm->_system->getHeight(), _pixelFormat.bytesPerPixel);
+ _dirtyScreen = false;
}
MystGraphics::~MystGraphics() {
delete _bmpDecoder;
delete _jpegDecoder;
delete _pictDecoder;
+ delete[] _pictureFile.entries;
+
+ _mainScreen->free();
+ delete _mainScreen;
}
static const char* picFileNames[] = {
@@ -133,16 +193,8 @@ void MystGraphics::loadExternalPictureFile(uint16 stack) {
}
}
-void MystGraphics::copyImageSectionToScreen(uint16 image, Common::Rect src, Common::Rect dest) {
- // 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());
-
- Graphics::Surface *surface = NULL;
-
+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,
@@ -150,13 +202,14 @@ void MystGraphics::copyImageSectionToScreen(uint16 image, Common::Rect src, Comm
// 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 == image) {
+ if (_pictureFile.entries[i].id == id) {
if (_pictureFile.entries[i].type == 0) {
- Graphics::Surface *jpegSurface = _jpegDecoder->decodeImage(new Common::SeekableSubReadStream(&_pictureFile.picFile, _pictureFile.entries[i].offset, _pictureFile.entries[i].offset + _pictureFile.entries[i].size));
- surface->copyFrom(*jpegSurface);
- } else if (_pictureFile.entries[i].type == 1)
- surface = _pictDecoder->decodeImage(new Common::SeekableSubReadStream(&_pictureFile.picFile, _pictureFile.entries[i].offset, _pictureFile.entries[i].offset + _pictureFile.entries[i].size));
- else
+ Graphics::Surface *surface = new Graphics::Surface();
+ surface->copyFrom(*_jpegDecoder->decodeImage(new Common::SeekableSubReadStream(&_pictureFile.picFile, _pictureFile.entries[i].offset, _pictureFile.entries[i].offset + _pictureFile.entries[i].size)));
+ mhkSurface = new MohawkSurface(surface);
+ } 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;
}
@@ -167,14 +220,14 @@ void MystGraphics::copyImageSectionToScreen(uint16 image, Common::Rect src, Comm
// 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 (!surface) {
+ if (!mhkSurface) {
bool isPict = false;
Common::SeekableReadStream *dataStream = NULL;
- if (_vm->getFeatures() & GF_ME && _vm->hasResource(ID_PICT, image)) {
+ 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->getRawData(ID_PICT, image);
+ dataStream = _vm->getResource(ID_PICT, id);
// 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.
@@ -183,17 +236,30 @@ void MystGraphics::copyImageSectionToScreen(uint16 image, Common::Rect src, Comm
isPict = (dataStream->readUint32BE() == 0x001102FF);
dataStream->seek(0);
} else // No PICT, so the WDIB must exist. Let's go grab it.
- dataStream = _vm->getRawData(ID_WDIB, image);
+ dataStream = _vm->getResource(ID_WDIB, id);
if (isPict)
- surface = _pictDecoder->decodeImage(dataStream);
+ mhkSurface = new MohawkSurface(_pictDecoder->decodeImage(dataStream));
else {
- ImageData *imageData = _bmpDecoder->decodeImage(dataStream);
- surface = imageData->getSurface();
- delete imageData;
+ mhkSurface = _bmpDecoder->decodeImage(dataStream);
+ mhkSurface->convertToTrueColor();
}
}
+ assert(mhkSurface);
+ return mhkSurface;
+}
+
+void MystGraphics::copyImageSectionToScreen(uint16 image, Common::Rect src, Common::Rect dest) {
+ // 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());
+
+ Graphics::Surface *surface = findImage(image)->getSurface();
+
debug(3, "Image Blit:");
debug(3, "src.x: %d", src.left);
debug(3, "src.y: %d", src.top);
@@ -202,48 +268,30 @@ void MystGraphics::copyImageSectionToScreen(uint16 image, Common::Rect src, Comm
debug(3, "width: %d", src.width());
debug(3, "height: %d", src.height());
- if (surface) {
- uint16 width = MIN<int>(surface->w, dest.width());
- uint16 height = MIN<int>(surface->h, dest.height());
- _vm->_system->copyRectToScreen((byte *)surface->getBasePtr(src.left, src.top), surface->pitch, dest.left, dest.top, width, height);
- surface->free();
- delete surface;
- }
+ uint16 width = MIN<int>(surface->w, dest.width());
+ uint16 height = MIN<int>(surface->h, dest.height());
- // FIXME: Remove this and update only at certain points
- _vm->_system->updateScreen();
-}
+ // Convert from bitmap coordinates to surface coordinates
+ uint16 top = surface->h - src.top - height;
-void MystGraphics::copyImageToScreen(uint16 image, Common::Rect dest) {
- copyImageSectionToScreen(image, Common::Rect(0, 0, 544, 333), dest);
-}
+ for (uint16 i = 0; i < height; i++)
+ memcpy(_mainScreen->getBasePtr(dest.left, i + dest.top), surface->getBasePtr(src.left, top + i), width * surface->bytesPerPixel);
-void MystGraphics::showCursor(void) {
- CursorMan.showMouse(true);
- _vm->_needsUpdate = true;
+ // Mark the screen as dirty
+ _dirtyScreen = true;
}
-void MystGraphics::hideCursor(void) {
- CursorMan.showMouse(false);
- _vm->_needsUpdate = true;
+void MystGraphics::copyImageToScreen(uint16 image, Common::Rect dest) {
+ copyImageSectionToScreen(image, Common::Rect(0, 0, 544, 333), dest);
}
-void MystGraphics::changeCursor(uint16 cursor) {
- // Both Myst and Myst ME use the "MystBitmap" format for cursor images.
- ImageData *data = _bmpDecoder->decodeImage(_vm->getRawData(ID_WDIB, cursor));
- Common::SeekableReadStream *clrcStream = _vm->getRawData(ID_CLRC, cursor);
- uint16 hotspotX = clrcStream->readUint16LE();
- uint16 hotspotY = clrcStream->readUint16LE();
- delete clrcStream;
-
- // Myst ME stores some cursors as 24bpp images instead of 8bpp
- if (data->_surface->bytesPerPixel == 1) {
- CursorMan.replaceCursor((byte *)data->_surface->pixels, data->_surface->w, data->_surface->h, hotspotX, hotspotY, 0);
- CursorMan.replaceCursorPalette(data->_palette, 0, 256);
- } else
- CursorMan.replaceCursor((byte *)data->_surface->pixels, data->_surface->w, data->_surface->h, hotspotX, hotspotY, _pixelFormat.RGBToColor(255, 255, 255), 1, &_pixelFormat);
-
- _vm->_needsUpdate = true;
+void MystGraphics::updateScreen() {
+ if (_dirtyScreen) {
+ // Only copy the buffer to the screen if it's dirty
+ _vm->_system->copyRectToScreen((byte *)_mainScreen->pixels, _mainScreen->pitch, 0, 0, _mainScreen->w, _mainScreen->h);
+ _vm->_system->updateScreen();
+ _dirtyScreen = false;
+ }
}
void MystGraphics::drawRect(Common::Rect rect, bool active) {
@@ -261,7 +309,7 @@ void MystGraphics::drawRect(Common::Rect rect, bool active) {
_vm->_system->unlockScreen();
}
-RivenGraphics::RivenGraphics(MohawkEngine_Riven* vm) : _vm(vm) {
+RivenGraphics::RivenGraphics(MohawkEngine_Riven* vm) : GraphicsManager(), _vm(vm) {
_bitmapDecoder = new MohawkBitmap();
// Give me the best you've got!
@@ -288,11 +336,14 @@ RivenGraphics::~RivenGraphics() {
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) {
- // First, decode the image and get the high color surface
- ImageData *imageData = _bitmapDecoder->decodeImage(_vm->getRawData(ID_TBMP, image));
- Graphics::Surface *surface = imageData->getSurface();
- delete imageData;
+ Graphics::Surface *surface = findImage(image)->getSurface();
// Clip the width to fit on the screen. Fixes some images.
if (left + surface->w > 608)
@@ -301,14 +352,11 @@ void RivenGraphics::copyImageToScreen(uint16 image, uint32 left, uint32 top, uin
for (uint16 i = 0; i < surface->h; i++)
memcpy(_mainScreen->getBasePtr(left, i + top), surface->getBasePtr(0, i), surface->w * surface->bytesPerPixel);
- surface->free();
- delete surface;
-
_dirtyScreen = true;
}
void RivenGraphics::drawPLST(uint16 x) {
- Common::SeekableReadStream* plst = _vm->getRawData(ID_PLST, _vm->getCurCard());
+ Common::SeekableReadStream* plst = _vm->getResource(ID_PLST, _vm->getCurCard());
uint16 index, id, left, top, right, bottom;
uint16 recordCount = plst->readUint16BE();
@@ -357,7 +405,7 @@ void RivenGraphics::updateScreen() {
}
void RivenGraphics::scheduleWaterEffect(uint16 sfxeID) {
- Common::SeekableReadStream *sfxeStream = _vm->getRawData(ID_SFXE, sfxeID);
+ Common::SeekableReadStream *sfxeStream = _vm->getResource(ID_SFXE, sfxeID);
if (sfxeStream->readUint16BE() != 'SL')
error ("Unknown sfxe tag");
@@ -491,115 +539,6 @@ void RivenGraphics::runScheduledTransition() {
_scheduledTransition = -1; // Clear scheduled transition
}
-void RivenGraphics::changeCursor(uint16 num) {
- // All of Riven's cursors are hardcoded. See riven_cursors.h for these definitions.
-
- switch (num) {
- case 1002:
- // Zip Mode
- CursorMan.replaceCursor(s_zipModeCursor, 16, 16, 8, 8, 0);
- CursorMan.replaceCursorPalette(s_zipModeCursorPalette, 1, ARRAYSIZE(s_zipModeCursorPalette) / 4);
- break;
- case 2003:
- // Hand Over Object
- CursorMan.replaceCursor(s_objectHandCursor, 16, 16, 8, 8, 0);
- CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 4);
- break;
- case 2004:
- // Grabbing/Using Object
- CursorMan.replaceCursor(s_grabbingHandCursor, 13, 13, 6, 6, 0);
- CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 4);
- break;
- case 3000:
- // Standard Hand
- CursorMan.replaceCursor(s_standardHandCursor, 15, 16, 6, 0, 0);
- CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 4);
- break;
- case 3001:
- // Pointing Left
- CursorMan.replaceCursor(s_pointingLeftCursor, 15, 13, 0, 3, 0);
- CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 4);
- break;
- case 3002:
- // Pointing Right
- CursorMan.replaceCursor(s_pointingRightCursor, 15, 13, 14, 3, 0);
- CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 4);
- break;
- case 3003:
- // Pointing Down (Palm Up)
- CursorMan.replaceCursor(s_pointingDownCursorPalmUp, 13, 16, 3, 15, 0);
- CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 4);
- break;
- case 3004:
- // Pointing Up (Palm Up)
- CursorMan.replaceCursor(s_pointingUpCursorPalmUp, 13, 16, 3, 0, 0);
- CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 4);
- break;
- case 3005:
- // Pointing Left (Curved)
- CursorMan.replaceCursor(s_pointingLeftCursorBent, 15, 13, 0, 5, 0);
- CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 4);
- break;
- case 3006:
- // Pointing Right (Curved)
- CursorMan.replaceCursor(s_pointingRightCursorBent, 15, 13, 14, 5, 0);
- CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 4);
- break;
- case 3007:
- // Pointing Down (Palm Down)
- CursorMan.replaceCursor(s_pointingDownCursorPalmDown, 15, 16, 7, 15, 0);
- CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 4);
- break;
- case 4001:
- // Red Marble
- CursorMan.replaceCursor(s_redMarbleCursor, 12, 12, 5, 5, 0);
- CursorMan.replaceCursorPalette(s_redMarbleCursorPalette, 1, ARRAYSIZE(s_redMarbleCursorPalette) / 4);
- break;
- case 4002:
- // Orange Marble
- CursorMan.replaceCursor(s_orangeMarbleCursor, 12, 12, 5, 5, 0);
- CursorMan.replaceCursorPalette(s_orangeMarbleCursorPalette, 1, ARRAYSIZE(s_orangeMarbleCursorPalette) / 4);
- break;
- case 4003:
- // Yellow Marble
- CursorMan.replaceCursor(s_yellowMarbleCursor, 12, 12, 5, 5, 0);
- CursorMan.replaceCursorPalette(s_yellowMarbleCursorPalette, 1, ARRAYSIZE(s_yellowMarbleCursorPalette) / 4);
- break;
- case 4004:
- // Green Marble
- CursorMan.replaceCursor(s_greenMarbleCursor, 12, 12, 5, 5, 0);
- CursorMan.replaceCursorPalette(s_greenMarbleCursorPalette, 1, ARRAYSIZE(s_greenMarbleCursorPalette) / 4);
- break;
- case 4005:
- // Blue Marble
- CursorMan.replaceCursor(s_blueMarbleCursor, 12, 12, 5, 5, 0);
- CursorMan.replaceCursorPalette(s_blueMarbleCursorPalette, 1, ARRAYSIZE(s_blueMarbleCursorPalette) / 4);
- break;
- case 4006:
- // Violet Marble
- CursorMan.replaceCursor(s_violetMarbleCursor, 12, 12, 5, 5, 0);
- CursorMan.replaceCursorPalette(s_violetMarbleCursorPalette, 1, ARRAYSIZE(s_violetMarbleCursorPalette) / 4);
- break;
- case 5000:
- // Pellet
- CursorMan.replaceCursor(s_pelletCursor, 8, 8, 4, 4, 0);
- CursorMan.replaceCursorPalette(s_pelletCursorPalette, 1, ARRAYSIZE(s_pelletCursorPalette) / 4);
- break;
- case 9000:
- // Hide Cursor
- CursorMan.showMouse(false);
- break;
- default:
- error("Cursor %d does not exist!", num);
- }
-
- if (num != 9000) // Show Cursor
- CursorMan.showMouse(true);
-
- // Should help in cases where we need to hide the cursor immediately.
- _vm->_system->updateScreen();
-}
-
void RivenGraphics::showInventory() {
// Don't redraw the inventory
if (_inventoryDrawn)
@@ -668,14 +607,13 @@ void RivenGraphics::clearInventoryArea() {
}
void RivenGraphics::drawInventoryImage(uint16 id, const Common::Rect *rect) {
- ImageData *imageData = _bitmapDecoder->decodeImage(_vm->getExtrasResource(ID_TBMP, id));
- Graphics::Surface *surface = imageData->getSurface();
- delete imageData;
+ 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);
- surface->free();
- delete surface;
+ delete mhkSurface;
}
void RivenGraphics::drawRect(Common::Rect rect, bool active) {
@@ -692,100 +630,92 @@ void RivenGraphics::drawRect(Common::Rect rect, bool active) {
void RivenGraphics::drawImageRect(uint16 id, Common::Rect srcRect, Common::Rect dstRect) {
// Draw tBMP id from srcRect to dstRect
- ImageData *imageData = _bitmapDecoder->decodeImage(_vm->getRawData(ID_TBMP, id));
- Graphics::Surface *surface = imageData->getSurface();
- delete imageData;
+ 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->bytesPerPixel);
- surface->free();
- delete surface;
-
_dirtyScreen = true;
}
void RivenGraphics::drawExtrasImage(uint16 id, Common::Rect dstRect) {
- ImageData *imageData = _bitmapDecoder->decodeImage(_vm->getExtrasResource(ID_TBMP, id));
- Graphics::Surface *surface = imageData->getSurface();
- delete imageData;
+ 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);
- surface->free();
- delete surface;
-
+ delete mhkSurface;
_dirtyScreen = true;
}
-LBGraphics::LBGraphics(MohawkEngine_LivingBooks *vm) : _vm(vm) {
+LBGraphics::LBGraphics(MohawkEngine_LivingBooks *vm) : GraphicsManager(), _vm(vm) {
_bmpDecoder = (_vm->getGameType() == GType_LIVINGBOOKSV1) ? new OldMohawkBitmap() : new MohawkBitmap();
- _palette = new byte[256 * 4];
- memset(_palette, 0, 256 * 4);
}
LBGraphics::~LBGraphics() {
delete _bmpDecoder;
- delete[] _palette;
}
-void LBGraphics::copyImageToScreen(uint16 image, uint16 left, uint16 right) {
- if (_vm->getGameType() == GType_LIVINGBOOKSV1) {
- // Drawing images in the old format isn't supported (yet)
- ImageData *imageData = _bmpDecoder->decodeImage(_vm->wrapStreamEndian(ID_BMAP, image));
- delete imageData;
- } else {
- ImageData *imageData = _bmpDecoder->decodeImage(_vm->getRawData(ID_TBMP, image));
- imageData->_palette = _palette;
- Graphics::Surface *surface = imageData->getSurface();
- imageData->_palette = NULL; // Unset the palette so it doesn't get deleted
- delete imageData;
-
- uint16 width = MIN<int>(surface->w, 640);
- uint16 height = MIN<int>(surface->h, 480);
- _vm->_system->copyRectToScreen((byte *)surface->pixels, surface->pitch, left, right, width, height);
- surface->free();
- delete surface;
-
- // FIXME: Remove this and update only at certain points
- _vm->_system->updateScreen();
- }
+MohawkSurface *LBGraphics::decodeImage(uint16 id) {
+ if (_vm->getGameType() == GType_LIVINGBOOKSV1)
+ return _bmpDecoder->decodeImage(_vm->wrapStreamEndian(ID_BMAP, id));
+
+ return _bmpDecoder->decodeImage(_vm->getResource(ID_TBMP, id));
+}
+
+void LBGraphics::copyImageToScreen(uint16 image, uint16 left, uint16 top) {
+ Graphics::Surface *surface = findImage(image)->getSurface();
+
+ uint16 width = MIN<int>(surface->w, _vm->_system->getWidth());
+ uint16 height = MIN<int>(surface->h, _vm->_system->getHeight());
+ _vm->_system->copyRectToScreen((byte *)surface->pixels, surface->pitch, left, top, width, height);
+
+ // FIXME: Remove this and update only when necessary
+ _vm->_system->updateScreen();
}
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->getGameType() == GType_LIVINGBOOKSV1) {
Common::SeekableSubReadStreamEndian *ctblStream = _vm->wrapStreamEndian(ID_CTBL, id);
uint16 colorCount = ctblStream->readUint16();
+ byte *palette = new byte[colorCount * 4];
for (uint16 i = 0; i < colorCount; i++) {
- _palette[i * 4] = ctblStream->readByte();
- _palette[i * 4 + 1] = ctblStream->readByte();
- _palette[i * 4 + 2] = ctblStream->readByte();
- _palette[i * 4 + 3] = ctblStream->readByte();
+ palette[i * 4] = ctblStream->readByte();
+ palette[i * 4 + 1] = ctblStream->readByte();
+ palette[i * 4 + 2] = ctblStream->readByte();
+ palette[i * 4 + 3] = ctblStream->readByte();
}
delete ctblStream;
+
+ _vm->_system->setPalette(palette, 0, colorCount);
+ delete[] palette;
} else {
- Common::SeekableReadStream *tpalStream = _vm->getRawData(ID_TPAL, id);
+ Common::SeekableReadStream *tpalStream = _vm->getResource(ID_TPAL, id);
uint16 colorStart = tpalStream->readUint16BE();
uint16 colorCount = tpalStream->readUint16BE();
+ byte *palette = new byte[colorCount * 4];
- for (uint16 i = colorStart; i < colorStart + colorCount; i++) {
- _palette[i * 4] = tpalStream->readByte();
- _palette[i * 4 + 1] = tpalStream->readByte();
- _palette[i * 4 + 2] = tpalStream->readByte();
- _palette[i * 4 + 3] = tpalStream->readByte();
+ for (uint16 i = 0; i < colorCount; i++) {
+ palette[i * 4] = tpalStream->readByte();
+ palette[i * 4 + 1] = tpalStream->readByte();
+ palette[i * 4 + 2] = tpalStream->readByte();
+ palette[i * 4 + 3] = tpalStream->readByte();
}
delete tpalStream;
+
+ _vm->_system->setPalette(palette, colorStart, colorCount);
+ delete[] palette;
}
}