aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJody Northup2009-08-21 09:37:51 +0000
committerJody Northup2009-08-21 09:37:51 +0000
commit3084919b32771d43d17fdd5d584505cd31d20b72 (patch)
tree3f42b5e0cb69f340ccd30fad96f6ee4e51e260cf
parentcba2897cc8f7b70d27fc75ca8b8d55cde4738e4a (diff)
parent89d7fea4e619cd44d5ce16eee1e46ad417e26c9c (diff)
downloadscummvm-rg350-3084919b32771d43d17fdd5d584505cd31d20b72.tar.gz
scummvm-rg350-3084919b32771d43d17fdd5d584505cd31d20b72.tar.bz2
scummvm-rg350-3084919b32771d43d17fdd5d584505cd31d20b72.zip
Merged RGB color API and support in from /scummvm/branches/gsoc2009-16bit/
svn-id: r43577
-rw-r--r--backends/platform/sdl/graphics.cpp212
-rw-r--r--backends/platform/sdl/sdl.cpp4
-rw-r--r--backends/platform/sdl/sdl.h27
-rw-r--r--common/error.h1
-rw-r--r--common/system.h68
-rwxr-xr-xconfigure2
-rw-r--r--dists/msvc8/ScummVM_Global.vsprops2
-rw-r--r--dists/msvc8/groovie.vcproj262
-rw-r--r--dists/msvc8/sci.vcproj2
-rw-r--r--dists/msvc8/scumm.vcproj2
-rw-r--r--dists/msvc8/scummvm.vcproj9
-rw-r--r--engines/cine/pal.h7
-rw-r--r--engines/engine.cpp29
-rw-r--r--engines/engine.h7
-rw-r--r--engines/sci/gfx/gfx_driver.cpp66
-rw-r--r--engines/sci/gfx/gfx_driver.h4
-rw-r--r--engines/sci/gfx/gfx_pixmap_scale.cpp5
-rw-r--r--engines/sci/gfx/gfx_resmgr.cpp6
-rw-r--r--engines/sci/gfx/gfx_system.h3
-rw-r--r--engines/sci/gfx/gfx_tools.cpp9
-rw-r--r--engines/sci/gfx/operations.cpp13
-rw-r--r--engines/sci/gfx/operations.h9
-rw-r--r--engines/sci/gfx/res_pic.cpp4
-rw-r--r--engines/sci/sci.cpp8
-rw-r--r--engines/scumm/actor.cpp7
-rw-r--r--engines/scumm/actor.h2
-rw-r--r--engines/scumm/akos.cpp81
-rw-r--r--engines/scumm/akos.h4
-rw-r--r--engines/scumm/base-costume.cpp2
-rw-r--r--engines/scumm/base-costume.h2
-rw-r--r--engines/scumm/charset.cpp4
-rw-r--r--engines/scumm/costume.cpp13
-rw-r--r--engines/scumm/costume.h6
-rw-r--r--engines/scumm/cursor.cpp44
-rw-r--r--engines/scumm/gfx.cpp220
-rw-r--r--engines/scumm/gfx.h12
-rw-r--r--engines/scumm/he/animation_he.cpp32
-rw-r--r--engines/scumm/he/animation_he.h1
-rw-r--r--engines/scumm/he/intern_he.h3
-rw-r--r--engines/scumm/he/palette_he.cpp196
-rw-r--r--engines/scumm/he/script_v100he.cpp44
-rw-r--r--engines/scumm/he/script_v60he.cpp2
-rw-r--r--engines/scumm/he/script_v72he.cpp17
-rw-r--r--engines/scumm/he/script_v80he.cpp8
-rw-r--r--engines/scumm/he/script_v90he.cpp40
-rw-r--r--engines/scumm/he/wiz_he.cpp884
-rw-r--r--engines/scumm/he/wiz_he.h38
-rw-r--r--engines/scumm/palette.cpp34
-rw-r--r--engines/scumm/resource.cpp6
-rw-r--r--engines/scumm/saveload.cpp2
-rw-r--r--engines/scumm/saveload.h2
-rw-r--r--engines/scumm/scumm.cpp33
-rw-r--r--engines/scumm/scumm.h11
-rw-r--r--graphics/cursorman.cpp29
-rw-r--r--graphics/cursorman.h36
-rw-r--r--graphics/pixelformat.h39
-rw-r--r--graphics/scaler.cpp9
-rw-r--r--gui/ThemeEngine.cpp6
-rw-r--r--gui/ThemeEngine.h3
59 files changed, 1912 insertions, 721 deletions
diff --git a/backends/platform/sdl/graphics.cpp b/backends/platform/sdl/graphics.cpp
index f3e4ce626b..3bfe8f5c98 100644
--- a/backends/platform/sdl/graphics.cpp
+++ b/backends/platform/sdl/graphics.cpp
@@ -26,6 +26,9 @@
#include "backends/platform/sdl/sdl.h"
#include "common/mutex.h"
#include "common/util.h"
+#ifdef ENABLE_RGB_COLOR
+#include "common/list.h"
+#endif
#include "graphics/font.h"
#include "graphics/fontman.h"
#include "graphics/scaler.h"
@@ -97,6 +100,9 @@ void OSystem_SDL::beginGFXTransaction(void) {
_transactionDetails.needUpdatescreen = false;
_transactionDetails.normal1xScaler = false;
+#ifdef ENABLE_RGB_COLOR
+ _transactionDetails.formatChanged = false;
+#endif
_oldVideoMode = _videoMode;
}
@@ -120,6 +126,13 @@ OSystem::TransactionError OSystem_SDL::endGFXTransaction(void) {
_videoMode.mode = _oldVideoMode.mode;
_videoMode.scaleFactor = _oldVideoMode.scaleFactor;
+#ifdef ENABLE_RGB_COLOR
+ } else if (_videoMode.format != _oldVideoMode.format) {
+ errors |= kTransactionFormatNotSupported;
+
+ _videoMode.format = _oldVideoMode.format;
+ _screenFormat = _videoMode.format;
+#endif
} else if (_videoMode.screenWidth != _oldVideoMode.screenWidth || _videoMode.screenHeight != _oldVideoMode.screenHeight) {
errors |= kTransactionSizeChangeFailed;
@@ -143,7 +156,11 @@ OSystem::TransactionError OSystem_SDL::endGFXTransaction(void) {
}
}
+#ifdef ENABLE_RGB_COLOR
+ if (_transactionDetails.sizeChanged || _transactionDetails.formatChanged) {
+#else
if (_transactionDetails.sizeChanged) {
+#endif
unloadGFXMode();
if (!loadGFXMode()) {
if (_oldVideoMode.setup) {
@@ -186,12 +203,94 @@ OSystem::TransactionError OSystem_SDL::endGFXTransaction(void) {
} else if (_transactionDetails.needUpdatescreen) {
setGraphicsModeIntern();
internUpdateScreen();
- }
+ }
_transactionMode = kTransactionNone;
return (TransactionError)errors;
}
+#ifdef ENABLE_RGB_COLOR
+const Graphics::PixelFormat RGBList[] = {
+#ifdef ENABLE_32BIT
+ // RGBA8888, ARGB8888, RGB888
+ Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0),
+ Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24),
+ Graphics::PixelFormat(3, 8, 8, 8, 0, 16, 8, 0, 0),
+#endif
+ // RGB565, XRGB1555, RGB555, RGBA4444, ARGB4444
+ Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0),
+ Graphics::PixelFormat(2, 5, 5, 5, 1, 10, 5, 0, 15),
+ Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0),
+ Graphics::PixelFormat(2, 4, 4, 4, 4, 12, 8, 4, 0),
+ Graphics::PixelFormat(2, 4, 4, 4, 4, 8, 4, 0, 12)
+};
+const Graphics::PixelFormat BGRList[] = {
+#ifdef ENABLE_32BIT
+ // ABGR8888, BGRA8888, BGR888
+ Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24),
+ Graphics::PixelFormat(4, 8, 8, 8, 8, 8, 16, 24, 0),
+ Graphics::PixelFormat(3, 8, 8, 8, 0, 0, 8, 16, 0),
+#endif
+ // BGR565, XBGR1555, BGR555, ABGR4444, BGRA4444
+ Graphics::PixelFormat(2, 5, 6, 5, 0, 0, 5, 11, 0),
+ Graphics::PixelFormat(2, 5, 5, 5, 1, 0, 5, 10, 15),
+ Graphics::PixelFormat(2, 5, 5, 5, 0, 0, 5, 10, 0),
+ Graphics::PixelFormat(2, 4, 4, 4, 4, 0, 4, 8, 12),
+ Graphics::PixelFormat(2, 4, 4, 4, 4, 4, 8, 12, 0)
+};
+
+// TODO: prioritize matching alpha masks
+Common::List<Graphics::PixelFormat> OSystem_SDL::getSupportedFormats() {
+ static Common::List<Graphics::PixelFormat> list;
+ static bool inited = false;
+
+ if (inited)
+ return list;
+
+ bool BGR = false;
+ int listLength = ARRAYSIZE(RGBList);
+
+ Graphics::PixelFormat format = Graphics::PixelFormat::createFormatCLUT8();
+ if (_hwscreen) {
+ // Get our currently set hardware format
+ format = Graphics::PixelFormat(_hwscreen->format->BytesPerPixel,
+ 8 - _hwscreen->format->Rloss, 8 - _hwscreen->format->Gloss,
+ 8 - _hwscreen->format->Bloss, 8 - _hwscreen->format->Aloss,
+ _hwscreen->format->Rshift, _hwscreen->format->Gshift,
+ _hwscreen->format->Bshift, _hwscreen->format->Ashift);
+
+ // Workaround to MacOSX SDL not providing an accurate Aloss value.
+ if (_hwscreen->format->Amask == 0)
+ format.aLoss = 8;
+
+ // Push it first, as the prefered format.
+ list.push_back(format);
+
+ if (format.bShift > format.rShift)
+ BGR = true;
+
+ // Mark that we don't need to do this any more.
+ inited = true;
+ }
+
+ for (int i = 0; i < listLength; i++) {
+ if (inited && (RGBList[i].bytesPerPixel > format.bytesPerPixel))
+ continue;
+ if (BGR) {
+ if (BGRList[i] != format)
+ list.push_back(BGRList[i]);
+ list.push_back(RGBList[i]);
+ } else {
+ if (RGBList[i] != format)
+ list.push_back(RGBList[i]);
+ list.push_back(BGRList[i]);
+ }
+ }
+ list.push_back(Graphics::PixelFormat::createFormatCLUT8());
+ return list;
+}
+#endif
+
bool OSystem_SDL::setGraphicsMode(int mode) {
Common::StackLock lock(_graphicsMutex);
@@ -340,9 +439,27 @@ int OSystem_SDL::getGraphicsMode() const {
return _videoMode.mode;
}
-void OSystem_SDL::initSize(uint w, uint h) {
+void OSystem_SDL::initSize(uint w, uint h, const Graphics::PixelFormat *format) {
assert(_transactionMode == kTransactionActive);
+#ifdef ENABLE_RGB_COLOR
+ //avoid redundant format changes
+ Graphics::PixelFormat newFormat;
+ if (!format)
+ newFormat = Graphics::PixelFormat::createFormatCLUT8();
+ else
+ newFormat = *format;
+
+ assert(newFormat.bytesPerPixel > 0);
+
+ if (newFormat != _videoMode.format)
+ {
+ _videoMode.format = newFormat;
+ _transactionDetails.formatChanged = true;
+ _screenFormat = newFormat;
+ }
+#endif
+
// Avoid redundant res changes
if ((int)w == _videoMode.screenWidth && (int)h == _videoMode.screenHeight)
return;
@@ -426,9 +543,21 @@ bool OSystem_SDL::loadGFXMode() {
//
// Create the surface that contains the 8 bit game data
//
+#ifdef ENABLE_RGB_COLOR
+ _screen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.screenWidth, _videoMode.screenHeight,
+ _screenFormat.bytesPerPixel << 3,
+ ((1 << _screenFormat.rBits()) - 1) << _screenFormat.rShift ,
+ ((1 << _screenFormat.gBits()) - 1) << _screenFormat.gShift ,
+ ((1 << _screenFormat.bBits()) - 1) << _screenFormat.bShift ,
+ ((1 << _screenFormat.aBits()) - 1) << _screenFormat.aShift );
+ if (_screen == NULL)
+ error("allocating _screen failed");
+
+#else
_screen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.screenWidth, _videoMode.screenHeight, 8, 0, 0, 0, 0);
if (_screen == NULL)
error("allocating _screen failed");
+#endif
//
// Create the surface that contains the scaled graphics in 16 bit mode
@@ -571,8 +700,8 @@ bool OSystem_SDL::hotswapGFXMode() {
// Keep around the old _screen & _overlayscreen so we can restore the screen data
// after the mode switch.
SDL_Surface *old_screen = _screen;
- SDL_Surface *old_overlayscreen = _overlayscreen;
_screen = NULL;
+ SDL_Surface *old_overlayscreen = _overlayscreen;
_overlayscreen = NULL;
// Release the HW screen surface
@@ -878,8 +1007,19 @@ void OSystem_SDL::copyRectToScreen(const byte *src, int pitch, int x, int y, int
if (SDL_LockSurface(_screen) == -1)
error("SDL_LockSurface failed: %s", SDL_GetError());
+#ifdef ENABLE_RGB_COLOR
+ byte *dst = (byte *)_screen->pixels + y * _videoMode.screenWidth * _screenFormat.bytesPerPixel + x * _screenFormat.bytesPerPixel;
+ if (_videoMode.screenWidth == w && pitch == w * _screenFormat.bytesPerPixel) {
+ memcpy(dst, src, h*w*_screenFormat.bytesPerPixel);
+ } else {
+ do {
+ memcpy(dst, src, w * _screenFormat.bytesPerPixel);
+ src += pitch;
+ dst += _videoMode.screenWidth * _screenFormat.bytesPerPixel;
+ } while (--h);
+ }
+#else
byte *dst = (byte *)_screen->pixels + y * _videoMode.screenWidth + x;
-
if (_videoMode.screenWidth == pitch && pitch == w) {
memcpy(dst, src, h*w);
} else {
@@ -889,6 +1029,7 @@ void OSystem_SDL::copyRectToScreen(const byte *src, int pitch, int x, int y, int
dst += _videoMode.screenWidth;
} while (--h);
}
+#endif
// Unlock the screen surface
SDL_UnlockSurface(_screen);
@@ -912,7 +1053,11 @@ Graphics::Surface *OSystem_SDL::lockScreen() {
_framebuffer.w = _screen->w;
_framebuffer.h = _screen->h;
_framebuffer.pitch = _screen->pitch;
+#ifdef ENABLE_RGB_COLOR
+ _framebuffer.bytesPerPixel = _screenFormat.bytesPerPixel;
+#else
_framebuffer.bytesPerPixel = 1;
+#endif
return &_framebuffer;
}
@@ -1096,6 +1241,11 @@ int16 OSystem_SDL::getWidth() {
void OSystem_SDL::setPalette(const byte *colors, uint start, uint num) {
assert(colors);
+#ifdef ENABLE_RGB_COLOR
+ if (_screenFormat.bytesPerPixel > 1)
+ return; //not using a paletted pixel format
+#endif
+
// Setting the palette before _screen is created is allowed - for now -
// since we don't actually set the palette until the screen is updated.
// But it could indicate a programming error, so let's warn about it.
@@ -1149,10 +1299,10 @@ void OSystem_SDL::setCursorPalette(const byte *colors, uint start, uint num) {
}
_cursorPaletteDisabled = false;
-
blitCursor();
}
+
void OSystem_SDL::setShakePos(int shake_pos) {
assert (_transactionMode == kTransactionNone);
@@ -1357,7 +1507,17 @@ void OSystem_SDL::warpMouse(int x, int y) {
}
}
-void OSystem_SDL::setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, byte keycolor, int cursorTargetScale) {
+void OSystem_SDL::setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format) {
+#ifdef ENABLE_RGB_COLOR
+ if (!format)
+ _cursorFormat = Graphics::PixelFormat::createFormatCLUT8();
+ else if (format->bytesPerPixel <= _screenFormat.bytesPerPixel)
+ _cursorFormat = *format;
+ keycolor &= (1 << (_cursorFormat.bytesPerPixel << 3)) - 1;
+#else
+ keycolor &= 0xFF;
+#endif
+
if (w == 0 || h == 0)
return;
@@ -1391,16 +1551,26 @@ void OSystem_SDL::setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x,
}
free(_mouseData);
-
+#ifdef ENABLE_RGB_COLOR
+ _mouseData = (byte *)malloc(w * h * _cursorFormat.bytesPerPixel);
+ memcpy(_mouseData, buf, w * h * _cursorFormat.bytesPerPixel);
+#else
_mouseData = (byte *)malloc(w * h);
memcpy(_mouseData, buf, w * h);
+#endif
+
blitCursor();
}
void OSystem_SDL::blitCursor() {
byte *dstPtr;
const byte *srcPtr = _mouseData;
+#ifdef ENABLE_RGB_COLOR
+ uint32 color;
+ uint32 colormask = (1 << (_cursorFormat.bytesPerPixel << 3)) - 1;
+#else
byte color;
+#endif
int w, h, i, j;
if (!_mouseOrigSurface || !_mouseData)
@@ -1434,13 +1604,29 @@ void OSystem_SDL::blitCursor() {
for (i = 0; i < h; i++) {
for (j = 0; j < w; j++) {
- color = *srcPtr;
- if (color != _mouseKeyColor) { // transparent, don't draw
- *(uint16 *)dstPtr = SDL_MapRGB(_mouseOrigSurface->format,
- palette[color].r, palette[color].g, palette[color].b);
+#ifdef ENABLE_RGB_COLOR
+ if (_cursorFormat.bytesPerPixel > 1) {
+ color = (*(uint32 *) srcPtr) & colormask;
+ if (color != _mouseKeyColor) { // transparent, don't draw
+ uint8 r,g,b;
+ _cursorFormat.colorToRGB(color,r,g,b);
+ *(uint16 *)dstPtr = SDL_MapRGB(_mouseOrigSurface->format,
+ r, g, b);
+ }
+ dstPtr += 2;
+ srcPtr += _cursorFormat.bytesPerPixel;
+ } else {
+#endif
+ color = *srcPtr;
+ if (color != _mouseKeyColor) { // transparent, don't draw
+ *(uint16 *)dstPtr = SDL_MapRGB(_mouseOrigSurface->format,
+ palette[color].r, palette[color].g, palette[color].b);
+ }
+ dstPtr += 2;
+ srcPtr++;
+#ifdef ENABLE_RGB_COLOR
}
- dstPtr += 2;
- srcPtr++;
+#endif
}
dstPtr += _mouseOrigSurface->pitch - w * 2;
}
diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp
index 7b3cf4eaa1..b6b46af9d7 100644
--- a/backends/platform/sdl/sdl.cpp
+++ b/backends/platform/sdl/sdl.cpp
@@ -222,6 +222,10 @@ OSystem_SDL::OSystem_SDL()
_osdSurface(0), _osdAlpha(SDL_ALPHA_TRANSPARENT), _osdFadeStartTime(0),
#endif
_hwscreen(0), _screen(0), _tmpscreen(0),
+#ifdef ENABLE_RGB_COLOR
+ _screenFormat(Graphics::PixelFormat::createFormatCLUT8()),
+ _cursorFormat(Graphics::PixelFormat::createFormatCLUT8()),
+#endif
_overlayVisible(false),
_overlayscreen(0), _tmpscreen2(0),
_samplesPerSec(0),
diff --git a/backends/platform/sdl/sdl.h b/backends/platform/sdl/sdl.h
index 2a5fda30bd..09213ad417 100644
--- a/backends/platform/sdl/sdl.h
+++ b/backends/platform/sdl/sdl.h
@@ -93,9 +93,17 @@ public:
void beginGFXTransaction(void);
TransactionError endGFXTransaction(void);
- // Set the size of the video bitmap.
- // Typically, 320x200
- virtual void initSize(uint w, uint h); // overloaded by CE backend
+#ifdef ENABLE_RGB_COLOR
+ // Game screen
+ virtual Graphics::PixelFormat getScreenFormat() const { return _screenFormat; }
+
+ // Highest supported
+ virtual Common::List<Graphics::PixelFormat> getSupportedFormats();
+#endif
+
+ // Set the size and format of the video bitmap.
+ // Typically, 320x200 CLUT8
+ virtual void initSize(uint w, uint h, const Graphics::PixelFormat *format); // overloaded by CE backend
virtual int getScreenChangeID() const { return _screenChangeCount; }
@@ -124,7 +132,7 @@ public:
virtual void warpMouse(int x, int y); // overloaded by CE backend (FIXME)
// Set the bitmap that's used when drawing the cursor.
- virtual void setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, byte keycolor, int cursorTargetScale); // overloaded by CE backend (FIXME)
+ virtual void setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format); // overloaded by CE backend (FIXME)
// Set colors of cursor palette
void setCursorPalette(const byte *colors, uint start, uint num);
@@ -186,6 +194,7 @@ public:
// Overlay
virtual Graphics::PixelFormat getOverlayFormat() const { return _overlayFormat; }
+
virtual void showOverlay();
virtual void hideOverlay();
virtual void clearOverlay();
@@ -239,6 +248,10 @@ protected:
// unseen game screen
SDL_Surface *_screen;
+#ifdef ENABLE_RGB_COLOR
+ Graphics::PixelFormat _screenFormat;
+ Graphics::PixelFormat _cursorFormat;
+#endif
// temporary screen (for scalers)
SDL_Surface *_tmpscreen;
@@ -272,6 +285,9 @@ protected:
bool needHotswap;
bool needUpdatescreen;
bool normal1xScaler;
+#ifdef ENABLE_RGB_COLOR
+ bool formatChanged;
+#endif
};
TransactionDetails _transactionDetails;
@@ -288,6 +304,9 @@ protected:
int screenWidth, screenHeight;
int overlayWidth, overlayHeight;
int hardwareWidth, hardwareHeight;
+#ifdef ENABLE_RGB_COLOR
+ Graphics::PixelFormat format;
+#endif
};
VideoState _videoMode, _oldVideoMode;
diff --git a/common/error.h b/common/error.h
index 23305a5c2e..d91ce2971a 100644
--- a/common/error.h
+++ b/common/error.h
@@ -48,6 +48,7 @@ enum Error {
kInvalidPathError, //!< Engine initialization: Invalid game path was passed
kNoGameDataFoundError, //!< Engine initialization: No game data was found in the specified location
kUnsupportedGameidError, //!< Engine initialization: Gameid not supported by this (Meta)Engine
+ kUnsupportedColorMode, //!< Engine initialization: Engine does not support backend's color mode
kReadPermissionDenied, //!< Unable to read data due to missing read permission
diff --git a/common/system.h b/common/system.h
index 5c91296ab1..0f265ea2be 100644
--- a/common/system.h
+++ b/common/system.h
@@ -31,6 +31,9 @@
#include "common/rect.h"
#include "graphics/pixelformat.h"
+#ifdef ENABLE_RGB_COLOR
+#include "graphics/conversion.h"
+#endif
namespace Audio {
class Mixer;
@@ -347,8 +350,52 @@ public:
*/
virtual int getGraphicsMode() const = 0;
+#ifdef ENABLE_RGB_COLOR
+ /**
+ * Determine the pixel format currently in use for screen rendering.
+ * @return the active screen pixel format.
+ * @see Graphics::PixelFormat
+ */
+ virtual Graphics::PixelFormat getScreenFormat() const = 0;
+
/**
- * Set the size of the virtual screen. Typical sizes include:
+ * Returns a list of all pixel formats supported by the backend.
+ * The first item in the list must be directly supported by hardware,
+ * and provide the largest color space of those formats with direct
+ * hardware support. It is also strongly recommended that remaining
+ * formats should be placed in order of descending preference for the
+ * backend to use.
+ *
+ * EG: a backend that supports 32-bit ABGR and 16-bit 555 BGR in hardware
+ * and provides conversion from equivalent RGB(A) modes should order its list
+ * 1) Graphics::PixelFormat(4, 0, 0, 0, 0, 0, 8, 16, 24)
+ * 2) Graphics::PixelFormat(2, 3, 3, 3, 8, 0, 5, 10, 0)
+ * 3) Graphics::PixelFormat(4, 0, 0, 0, 0, 24, 16, 8, 0)
+ * 4) Graphics::PixelFormat(2, 3, 3, 3, 8, 10, 5, 0, 0)
+ * 5) Graphics::PixelFormat::createFormatCLUT8()
+ *
+ * @see Graphics::PixelFormat
+ *
+ * @note Backends supporting RGB color should accept game data in RGB color
+ * order, even if hardware uses BGR or some other color order.
+ *
+ * @see convertScreenRect
+ */
+ virtual Common::List<Graphics::PixelFormat> getSupportedFormats() = 0;
+#else
+ inline Graphics::PixelFormat getScreenFormat() const {
+ return Graphics::PixelFormat::createFormatCLUT8();
+ };
+
+ inline Common::List<Graphics::PixelFormat> getSupportedFormats() const {
+ Common::List<Graphics::PixelFormat> list;
+ list.push_back(Graphics::PixelFormat::createFormatCLUT8());
+ return list;
+ };
+#endif
+
+ /**
+ * Set the size and color format of the virtual screen. Typical sizes include:
* - 320x200 (e.g. for most SCUMM games, and Simon)
* - 320x240 (e.g. for FM-TOWN SCUMM games)
* - 640x480 (e.g. for Curse of Monkey Island)
@@ -359,10 +406,21 @@ public:
* GraphicsMode); stretch the data to perform aspect ratio correction;
* or shrink it to fit on small screens (in cell phones).
*
+ * Typical formats include:
+ * CLUT8 (e.g. 256 color, for most games)
+ * RGB555 (e.g. 16-bit color, for later SCUMM HE games)
+ * RGB565 (e.g. 16-bit color, for Urban Runner)
+ *
+ * This is the pixel format for which the client code generates data;
+ * this is not necessarily equal to the hardware pixel format. For example,
+ * a backend may perform color lookup of 8-bit graphics before pushing
+ * a screen to hardware, or correct the ARGB color order via convertScreenRect.
+ *
* @param width the new virtual screen width
* @param height the new virtual screen height
+ * @param format the new virtual screen pixel format
*/
- virtual void initSize(uint width, uint height) = 0;
+ virtual void initSize(uint width, uint height, const Graphics::PixelFormat *format = NULL) = 0;
/**
* Return an int value which is changed whenever any screen
@@ -411,7 +469,8 @@ public:
kTransactionAspectRatioFailed = (1 << 0), /**< Failed switching aspect ratio correction mode */
kTransactionFullscreenFailed = (1 << 1), /**< Failed switching fullscreen mode */
kTransactionModeSwitchFailed = (1 << 2), /**< Failed switching the GFX graphics mode (setGraphicsMode) */
- kTransactionSizeChangeFailed = (1 << 3) /**< Failed switching the screen dimensions (initSize) */
+ kTransactionSizeChangeFailed = (1 << 3), /**< Failed switching the screen dimensions (initSize) */
+ kTransactionFormatNotSupported = (1 << 4) /**< Failed setting the color format */
};
/**
@@ -705,8 +764,9 @@ public:
* @param hotspotY vertical offset from the top side to the hotspot
* @param keycolor transparency color index
* @param cursorTargetScale scale factor which cursor is designed for
+ * @param format pointer to the pixel format which cursor graphic uses
*/
- virtual void setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, byte keycolor = 255, int cursorTargetScale = 1) = 0;
+ virtual void setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor = 0xFFFFFFFF, int cursorTargetScale = 1, const Graphics::PixelFormat *format = NULL) = 0;
/**
* Replace the specified range of cursor the palette with new colors.
diff --git a/configure b/configure
index b939838505..9ef794eed2 100755
--- a/configure
+++ b/configure
@@ -110,7 +110,7 @@ _alsa=auto
_zlib=auto
_mpeg2=no
_fluidsynth=auto
-_readline=auto
+_16bit=yes_readline=auto
# Default option behaviour yes/no
_text_console=no
_mt32emu=yes
diff --git a/dists/msvc8/ScummVM_Global.vsprops b/dists/msvc8/ScummVM_Global.vsprops
index afcfab102b..4da6748645 100644
--- a/dists/msvc8/ScummVM_Global.vsprops
+++ b/dists/msvc8/ScummVM_Global.vsprops
@@ -10,7 +10,7 @@
Name="VCCLCompilerTool"
DisableSpecificWarnings="4068;4100;4103;4121;4127;4189;4201;4221;4244;4250;4310;4351;4355;4510;4511;4512;4610;4701;4702;4706;4800;4996"
AdditionalIncludeDirectories="../..;../../engines"
- PreprocessorDefinitions="USE_NASM;USE_ZLIB;USE_MAD;USE_VORBIS;USE_MPEG2;USE_MT32EMU;ENABLE_AGI;ENABLE_AGOS;ENABLE_AGOS2;ENABLE_CINE;ENABLE_CRUISE;ENABLE_DRASCULA;ENABLE_GOB;ENABLE_IGOR;ENABLE_KYRA;ENABLE_LOL;ENABLE_LURE;ENABLE_M4;ENABLE_MADE;ENABLE_PARALLACTION;ENABLE_QUEEN;ENABLE_SAGA;ENABLE_IHNM;ENABLE_SAGA2;ENABLE_SCI;ENABLE_SCUMM;ENABLE_SKY;ENABLE_SWORD1;ENABLE_SWORD2;ENABLE_TOUCHE;ENABLE_SCUMM_7_8;ENABLE_HE;ENABLE_TINSEL;ENABLE_TUCKER;ENABLE_GROOVIE"
+ PreprocessorDefinitions="USE_NASM;USE_ZLIB;USE_MAD;USE_VORBIS;USE_MPEG2;USE_MT32EMU;ENABLE_AGI;ENABLE_AGOS;ENABLE_AGOS2;ENABLE_CINE;ENABLE_CRUISE;ENABLE_DRASCULA;ENABLE_GOB;ENABLE_IGOR;ENABLE_KYRA;ENABLE_LOL;ENABLE_LURE;ENABLE_M4;ENABLE_MADE;ENABLE_PARALLACTION;ENABLE_QUEEN;ENABLE_SAGA;ENABLE_IHNM;ENABLE_SAGA2;ENABLE_SCI;ENABLE_SCUMM;ENABLE_SKY;ENABLE_SWORD1;ENABLE_SWORD2;ENABLE_TOUCHE;ENABLE_SCUMM_7_8;ENABLE_HE;ENABLE_TINSEL;ENABLE_TUCKER;ENABLE_GROOVIE;;ENABLE_RGB_COLOR"
ExceptionHandling="0"
RuntimeTypeInfo="false"
WarningLevel="4"
diff --git a/dists/msvc8/groovie.vcproj b/dists/msvc8/groovie.vcproj
index 5404803ae9..cc8f060b06 100644
--- a/dists/msvc8/groovie.vcproj
+++ b/dists/msvc8/groovie.vcproj
@@ -1,48 +1,244 @@
<?xml version="1.0" encoding="windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
- Version="8,00"
+ Version="8.00"
Name="groovie"
ProjectGUID="{2C1EA540-0B09-11DD-BD00-000000000000}"
RootNamespace="groovie"
Keyword="Win32Proj"
>
<Platforms>
- <Platform Name="Win32" />
+ <Platform
+ Name="Win32"
+ />
</Platforms>
+ <ToolFiles>
+ </ToolFiles>
<Configurations>
- <Configuration Name="Debug|Win32" ConfigurationType="4" InheritedPropertySheets=".\ScummVM_Debug.vsprops" />
- <Configuration Name="Release|Win32" ConfigurationType="4" InheritedPropertySheets=".\ScummVM_Release.vsprops" />
+ <Configuration
+ Name="Debug|Win32"
+ ConfigurationType="4"
+ InheritedPropertySheets=".\ScummVM_Debug.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="GROOVIE_EXPERIMENTAL"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ ConfigurationType="4"
+ InheritedPropertySheets=".\ScummVM_Release.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
</Configurations>
+ <References>
+ </References>
<Files>
- <File RelativePath="..\..\engines\groovie\cell.cpp" />
- <File RelativePath="..\..\engines\groovie\cell.h" />
- <File RelativePath="..\..\engines\groovie\cursor.cpp" />
- <File RelativePath="..\..\engines\groovie\cursor.h" />
- <File RelativePath="..\..\engines\groovie\debug.cpp" />
- <File RelativePath="..\..\engines\groovie\debug.h" />
- <File RelativePath="..\..\engines\groovie\detection.cpp" />
- <File RelativePath="..\..\engines\groovie\font.cpp" />
- <File RelativePath="..\..\engines\groovie\font.h" />
- <File RelativePath="..\..\engines\groovie\graphics.cpp" />
- <File RelativePath="..\..\engines\groovie\graphics.h" />
- <File RelativePath="..\..\engines\groovie\groovie.cpp" />
- <File RelativePath="..\..\engines\groovie\groovie.h" />
- <File RelativePath="..\..\engines\groovie\lzss.cpp" />
- <File RelativePath="..\..\engines\groovie\lzss.h" />
- <File RelativePath="..\..\engines\groovie\music.cpp" />
- <File RelativePath="..\..\engines\groovie\music.h" />
- <File RelativePath="..\..\engines\groovie\player.cpp" />
- <File RelativePath="..\..\engines\groovie\player.h" />
- <File RelativePath="..\..\engines\groovie\resource.cpp" />
- <File RelativePath="..\..\engines\groovie\resource.h" />
- <File RelativePath="..\..\engines\groovie\roq.cpp" />
- <File RelativePath="..\..\engines\groovie\roq.h" />
- <File RelativePath="..\..\engines\groovie\saveload.cpp" />
- <File RelativePath="..\..\engines\groovie\saveload.h" />
- <File RelativePath="..\..\engines\groovie\script.cpp" />
- <File RelativePath="..\..\engines\groovie\script.h" />
- <File RelativePath="..\..\engines\groovie\vdx.cpp" />
- <File RelativePath="..\..\engines\groovie\vdx.h" />
+ <File
+ RelativePath="..\..\engines\groovie\cell.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\engines\groovie\cell.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\engines\groovie\cursor.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\engines\groovie\cursor.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\engines\groovie\debug.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\engines\groovie\debug.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\engines\groovie\detection.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\engines\groovie\font.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\engines\groovie\font.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\engines\groovie\graphics.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\engines\groovie\graphics.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\engines\groovie\groovie.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\engines\groovie\groovie.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\engines\groovie\lzss.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\engines\groovie\lzss.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\engines\groovie\music.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\engines\groovie\music.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\engines\groovie\player.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\engines\groovie\player.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\engines\groovie\resource.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\engines\groovie\resource.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\engines\groovie\roq.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\engines\groovie\roq.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\engines\groovie\saveload.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\engines\groovie\saveload.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\engines\groovie\script.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\engines\groovie\script.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\engines\groovie\vdx.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\engines\groovie\vdx.h"
+ >
+ </File>
</Files>
+ <Globals>
+ </Globals>
</VisualStudioProject>
diff --git a/dists/msvc8/sci.vcproj b/dists/msvc8/sci.vcproj
index 4a9862d7f6..eab736cd4c 100644
--- a/dists/msvc8/sci.vcproj
+++ b/dists/msvc8/sci.vcproj
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
- Version="8,00"
+ Version="8.00"
Name="sci"
ProjectGUID="{53F17B2B-0412-4EC3-A999-ED0537BB5223}"
RootNamespace="sci"
diff --git a/dists/msvc8/scumm.vcproj b/dists/msvc8/scumm.vcproj
index e71317ac16..e99fdae790 100644
--- a/dists/msvc8/scumm.vcproj
+++ b/dists/msvc8/scumm.vcproj
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
- Version="8,00"
+ Version="8.00"
Name="scumm"
ProjectGUID="{B6AFD548-63D2-40CD-A652-E87095AFCBAF}"
RootNamespace="scumm"
diff --git a/dists/msvc8/scummvm.vcproj b/dists/msvc8/scummvm.vcproj
index 27e37add0b..fd02ba0023 100644
--- a/dists/msvc8/scummvm.vcproj
+++ b/dists/msvc8/scummvm.vcproj
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
- Version="8,00"
+ Version="8.00"
Name="scummvm"
ProjectGUID="{8434CB15-D08F-427D-9E6D-581AE5B28440}"
RootNamespace="scummvm"
@@ -47,6 +47,9 @@
<File RelativePath="..\..\common\debug.h" />
<File RelativePath="..\..\common\endian.h" />
<File RelativePath="..\..\common\error.h" />
+ <File RelativePath="..\..\common\EventDispatcher.cpp" />
+ <File RelativePath="..\..\common\EventRecorder.cpp" />
+ <File RelativePath="..\..\common\EventRecorder.h" />
<File RelativePath="..\..\common\events.h" />
<File RelativePath="..\..\common\file.cpp" />
<File RelativePath="..\..\common\file.h" />
@@ -347,6 +350,8 @@
</Filter>
<Filter Name="graphics">
<File RelativePath="..\..\graphics\colormasks.h" />
+ <File RelativePath="..\..\graphics\conversion.cpp" />
+ <File RelativePath="..\..\graphics\conversion.h" />
<File RelativePath="..\..\graphics\cursorman.cpp" />
<File RelativePath="..\..\graphics\cursorman.h" />
<File RelativePath="..\..\graphics\dither.cpp" />
@@ -357,6 +362,8 @@
<File RelativePath="..\..\graphics\fontman.h" />
<File RelativePath="..\..\graphics\iff.cpp" />
<File RelativePath="..\..\graphics\iff.h" />
+ <File RelativePath="..\..\graphics\jpeg.cpp" />
+ <File RelativePath="..\..\graphics\jpeg.h" />
<File RelativePath="..\..\graphics\imagedec.cpp" />
<File RelativePath="..\..\graphics\imagedec.h" />
<File RelativePath="..\..\graphics\pixelformat.h" />
diff --git a/engines/cine/pal.h b/engines/cine/pal.h
index 4764d5a474..26513eb5a1 100644
--- a/engines/cine/pal.h
+++ b/engines/cine/pal.h
@@ -36,7 +36,8 @@ namespace Cine {
#define kLowPalNumBytes ((kLowPalNumColors) * (kLowPalBytesPerColor))
/*! \brief Low resolution (9-bit) color format used in Cine's 16-color modes. */
-static const Graphics::PixelFormat kLowPalFormat = {kLowPalBytesPerColor, 5, 5, 5, 8, 8, 4, 0, 0};
+ static const Graphics::PixelFormat kLowPalFormat(kLowPalBytesPerColor, 5, 5, 5, 8, 8, 4, 0, 0);
+
// Constants related to kHighPalFormat
#define kHighPalBytesPerColor 3
@@ -44,10 +45,10 @@ static const Graphics::PixelFormat kLowPalFormat = {kLowPalBytesPerColor, 5, 5,
#define kHighPalNumBytes ((kHighPalNumColors) * (kHighPalBytesPerColor))
/*! \brief High resolution (24-bit) color format used in Cine's 256-color modes. */
-static const Graphics::PixelFormat kHighPalFormat = {kHighPalBytesPerColor, 0, 0, 0, 8, 0, 8, 16, 0};
+static const Graphics::PixelFormat kHighPalFormat(kHighPalBytesPerColor, 0, 0, 0, 8, 0, 8, 16, 0);
/*! \brief The color format used by OSystem's setPalette-function. */
-static const Graphics::PixelFormat kSystemPalFormat = {4, 0, 0, 0, 8, 0, 8, 16, 0};
+static const Graphics::PixelFormat kSystemPalFormat(4, 0, 0, 0, 8, 0, 8, 16, 0);
/*! \brief Endian types. Used at least by Palette class's load and save functions.
* TODO: Move somewhere more general as this is definitely not Cine-engine specific
diff --git a/engines/engine.cpp b/engines/engine.cpp
index 0847e27246..eb46add82f 100644
--- a/engines/engine.cpp
+++ b/engines/engine.cpp
@@ -125,11 +125,21 @@ void initCommonGFX(bool defaultTo1XScaler) {
g_system->setFeatureState(OSystem::kFeatureFullscreenMode, ConfMan.getBool("fullscreen"));
}
-void initGraphics(int width, int height, bool defaultTo1xScaler) {
+void initGraphics(int width, int height, bool defaultTo1xScaler, const Graphics::PixelFormat *format) {
+
g_system->beginGFXTransaction();
initCommonGFX(defaultTo1xScaler);
+#ifdef ENABLE_RGB_COLOR
+ if (format)
+ g_system->initSize(width, height, format);
+ else {
+ Graphics::PixelFormat Format = g_system->getSupportedFormats().front();
+ g_system->initSize(width, height, &Format);
+ }
+#else
g_system->initSize(width, height);
+#endif
OSystem::TransactionError gfxError = g_system->endGFXTransaction();
@@ -150,6 +160,15 @@ void initGraphics(int width, int height, bool defaultTo1xScaler) {
}
// Just show warnings then these occur:
+#ifdef ENABLE_RGB_COLOR
+ if (gfxError & OSystem::kTransactionFormatNotSupported) {
+ Common::String message = "Could not initialize color format.";
+
+ GUI::MessageDialog dialog(message);
+ dialog.runModal();
+ }
+#endif
+
if (gfxError & OSystem::kTransactionModeSwitchFailed) {
Common::String message = "Could not switch to video mode: '";
message += ConfMan.get("gfx_mode");
@@ -169,6 +188,14 @@ void initGraphics(int width, int height, bool defaultTo1xScaler) {
dialog.runModal();
}
}
+void initGraphics(int width, int height, bool defaultTo1xScaler, const Common::List<Graphics::PixelFormat> &formatList) {
+ Graphics::PixelFormat format = Graphics::findCompatibleFormat(g_system->getSupportedFormats(),formatList);
+ initGraphics(width,height,defaultTo1xScaler,&format);
+}
+void initGraphics(int width, int height, bool defaultTo1xScaler) {
+ Graphics::PixelFormat format = Graphics::PixelFormat::createFormatCLUT8();
+ initGraphics(width,height,defaultTo1xScaler,&format);
+}
void GUIErrorMessage(const Common::String msg) {
g_system->setWindowCaption("Error");
diff --git a/engines/engine.h b/engines/engine.h
index ff3ce6c326..cd39c0065d 100644
--- a/engines/engine.h
+++ b/engines/engine.h
@@ -29,6 +29,7 @@
#include "common/error.h"
#include "common/fs.h"
#include "common/str.h"
+#include "graphics/pixelformat.h"
class OSystem;
@@ -58,8 +59,14 @@ void initCommonGFX(bool defaultTo1XScaler);
*
* Errors out when backend is not able to switch to the specified
* mode.
+ *
+ * Defaults to 256 color paletted mode if no graphics format is provided.
+ * Uses the backend's preferred format if graphics format pointer is NULL.
+ * Finds the best compatible format if a list of graphics formats is provided.
*/
void initGraphics(int width, int height, bool defaultTo1xScaler);
+void initGraphics(int width, int height, bool defaultTo1xScaler, const Graphics::PixelFormat *format);
+void initGraphics(int width, int height, bool defaultTo1xScaler, const Common::List<Graphics::PixelFormat> &formatList);
/**
* Initializes graphics and shows error message.
diff --git a/engines/sci/gfx/gfx_driver.cpp b/engines/sci/gfx/gfx_driver.cpp
index 0b1387074c..b71152822c 100644
--- a/engines/sci/gfx/gfx_driver.cpp
+++ b/engines/sci/gfx/gfx_driver.cpp
@@ -27,18 +27,19 @@
#include "common/system.h"
#include "graphics/cursorman.h"
#include "graphics/primitives.h"
+#include "graphics/surface.h"
#include "sci/sci.h"
#include "sci/gfx/gfx_driver.h"
#include "sci/gfx/gfx_tools.h"
+
namespace Sci {
-GfxDriver::GfxDriver(int xfact, int yfact, int bytespp) {
+GfxDriver::GfxDriver(int xfact, int yfact, Graphics::PixelFormat format) {
int i;
- Graphics::PixelFormat format = { bytespp, 0, 0, 0, 0, 0, 0, 0, 0 };
- _mode = gfx_new_mode(xfact, yfact, format, new Palette(256), 0);
+ _mode = gfx_new_mode(xfact, yfact, format, format.bytesPerPixel == 1 ? new Palette(256) : 0, 0);
_mode->xsize = xfact * 320;
_mode->ysize = yfact * 200;
@@ -51,14 +52,15 @@ GfxDriver::GfxDriver(int xfact, int yfact, int bytespp) {
// create the visual buffers
for (i = 0; i < 2; i++) {
_visual[i] = NULL;
- _visual[i] = new byte[_mode->xsize * _mode->ysize];
+ _visual[i] = new byte[_mode->xsize * _mode->ysize * _mode->bytespp];
if (!_visual[i]) {
error("Out of memory: Could not allocate visual buffers! (%dx%d)\n", _mode->xsize, _mode->ysize);
}
- memset(_visual[i], 0, _mode->xsize * _mode->ysize);
+ memset(_visual[i], 0, _mode->xsize * _mode->ysize * _mode->bytespp);
}
- _mode->palette->name = "global";
+ if (_mode->palette)
+ _mode->palette->name = "global";
}
GfxDriver::~GfxDriver() {
@@ -77,10 +79,12 @@ GfxDriver::~GfxDriver() {
// Drawing operations
+template<int COPY_BYTES, typename SIZETYPE, int EXTRA_BYTE_OFFSET>
static void drawProc(int x, int y, int c, void *data) {
GfxDriver *drv = (GfxDriver *)data;
byte *p = drv->getVisual0();
- p[y * 320* drv->getMode()->xfact + x] = c;
+ SIZETYPE col = c << (EXTRA_BYTE_OFFSET * 8);
+ memcpy(p + (y * 320* drv->getMode()->xfact + x) * COPY_BYTES, &col, COPY_BYTES);
}
int GfxDriver::drawLine(Common::Point start, Common::Point end, gfx_color_t color,
@@ -91,6 +95,28 @@ int GfxDriver::drawLine(Common::Point start, Common::Point end, gfx_color_t colo
int xsize = _mode->xsize;
int ysize = _mode->ysize;
+ void (*modeDrawProc)(int,int,int,void*);
+ switch (_mode->bytespp) {
+ case 1:
+ modeDrawProc = drawProc<1, uint8, 0>;
+ break;
+ case 2:
+ modeDrawProc = drawProc<2, uint16, 0>;
+ break;
+ case 3:
+#ifdef SCUMM_BIG_ENDIAN
+ modeDrawProc = drawProc<3, uint32, 1>;
+#else
+ modeDrawProc = drawProc<3, uint32, 0>;
+#endif
+ break;
+ case 4:
+ modeDrawProc = drawProc<4, uint32, 0>;
+ break;
+ default:
+ error("Invalid mode->bytespp=%d", _mode->bytespp);
+ }
+
if (color.mask & GFX_MASK_VISUAL) {
Common::Point nstart, nend;
@@ -102,7 +128,7 @@ int GfxDriver::drawLine(Common::Point start, Common::Point end, gfx_color_t colo
nend.x = CLIP<int16>(end.x + xc, 0, xsize - 1);
nend.y = CLIP<int16>(end.y + yc, 0, ysize - 1);
- Graphics::drawLine(nstart.x, nstart.y, nend.x, nend.y, scolor, drawProc, this);
+ Graphics::drawLine(nstart.x, nstart.y, nend.x, nend.y, scolor, modeDrawProc, this);
if (color.mask & GFX_MASK_PRIORITY) {
gfx_draw_line_pixmap_i(_priority[0], nstart, nend, color.priority);
@@ -118,7 +144,8 @@ int GfxDriver::drawFilledRect(rect_t rect, gfx_color_t color1, gfx_color_t color
gfx_rectangle_fill_t shade_mode) {
if (color1.mask & GFX_MASK_VISUAL) {
for (int i = rect.y; i < rect.y + rect.height; i++) {
- memset(_visual[0] + i * _mode->xsize + rect.x, color1.visual.parent_index, rect.width);
+ memset(_visual[0] + (i * _mode->xsize + rect.x) * _mode->bytespp,
+ color1.visual.parent_index, rect.width * _mode->bytespp);
}
}
@@ -138,8 +165,10 @@ int GfxDriver::drawPixmap(gfx_pixmap_t *pxm, int priority, rect_t src, rect_t de
return GFX_ERROR;
}
- gfx_crossblit_pixmap(_mode, pxm, priority, src, dest, _visual[bufnr], _mode->xsize,
- _priority[bufnr]->index_data, _priority[bufnr]->index_width, 1, 0);
+ gfx_crossblit_pixmap(_mode, pxm, priority, src, dest, _visual[bufnr],
+ _mode->xsize * _mode->bytespp,
+ _priority[bufnr]->index_data,
+ _priority[bufnr]->index_width, 1, 0);
return GFX_OK;
}
@@ -161,7 +190,9 @@ int GfxDriver::grabPixmap(rect_t src, gfx_pixmap_t *pxm, gfx_map_mask_t map) {
pxm->width = src.width;
pxm->height = src.height;
for (int i = 0; i < src.height; i++) {
- memcpy(pxm->data + i * src.width, _visual[0] + (i + src.y) * _mode->xsize + src.x, src.width);
+ memcpy(pxm->data + i * src.width * _mode->bytespp,
+ _visual[0] + _mode->bytespp * ((i + src.y) * _mode->xsize + src.x),
+ src.width * _mode->bytespp);
}
break;
@@ -193,17 +224,18 @@ int GfxDriver::update(rect_t src, Common::Point dest, gfx_buffer_t buffer) {
switch (buffer) {
case GFX_BUFFER_BACK:
for (int i = 0; i < src.height; i++) {
- memcpy(_visual[0] + (dest.y + i) * _mode->xsize + dest.x,
- _visual[1] + (src.y + i) * _mode->xsize + src.x, src.width);
+ memcpy(_visual[0] + _mode->bytespp * ( (dest.y + i) * _mode->xsize + dest.x),
+ _visual[1] + _mode->bytespp * ( (src.y + i) * _mode->xsize + src.x), src.width * _mode->bytespp );
}
if ((src.x == dest.x) && (src.y == dest.y))
gfx_copy_pixmap_box_i(_priority[0], _priority[1], src);
break;
- case GFX_BUFFER_FRONT:
- g_system->copyRectToScreen(_visual[0] + src.x + src.y * _mode->xsize, _mode->xsize, dest.x, dest.y, src.width, src.height);
+ case GFX_BUFFER_FRONT: {
+ g_system->copyRectToScreen(_visual[0] + _mode->bytespp * (src.x + src.y * _mode->xsize), _mode->xsize * _mode->bytespp, dest.x, dest.y, src.width, src.height);
g_system->updateScreen();
break;
+ }
default:
error("Invalid buffer %d in update", buffer);
return GFX_ERROR;
@@ -213,7 +245,7 @@ int GfxDriver::update(rect_t src, Common::Point dest, gfx_buffer_t buffer) {
}
int GfxDriver::setStaticBuffer(gfx_pixmap_t *pic, gfx_pixmap_t *priority) {
- memcpy(_visual[1], pic->data, _mode->xsize * _mode->ysize);
+ memcpy(_visual[1], pic->data, _mode->xsize * _mode->ysize * _mode->bytespp);
gfx_copy_pixmap_box_i(_priority[1], priority, gfx_rect(0, 0, _mode->xsize, _mode->ysize));
return GFX_OK;
diff --git a/engines/sci/gfx/gfx_driver.h b/engines/sci/gfx/gfx_driver.h
index f7cbd0b6c2..cc8a5208d4 100644
--- a/engines/sci/gfx/gfx_driver.h
+++ b/engines/sci/gfx/gfx_driver.h
@@ -29,6 +29,8 @@
#include "sci/gfx/gfx_system.h"
#include "sci/uinput.h"
+#include "graphics/pixelformat.h"
+
namespace Sci {
enum gfx_buffer_t {
@@ -85,7 +87,7 @@ public:
* not be set, or GFX_FATAL if the graphics target
* is unuseable.
*/
- GfxDriver(int xfact, int yfact, int bytespp);
+ GfxDriver(int xfact, int yfact, Graphics::PixelFormat mode);
/**
* Uninitializes the current graphics mode.
diff --git a/engines/sci/gfx/gfx_pixmap_scale.cpp b/engines/sci/gfx/gfx_pixmap_scale.cpp
index 034efafe8d..41e6102cbd 100644
--- a/engines/sci/gfx/gfx_pixmap_scale.cpp
+++ b/engines/sci/gfx/gfx_pixmap_scale.cpp
@@ -70,14 +70,11 @@ void _gfx_xlate_pixmap_unfiltered(gfx_mode_t *mode, gfx_pixmap_t *pxm, int scale
// Calculate all colors
for (i = 0; i < pxm->colors_nr(); i++) {
int col;
-
const PaletteEntry& color = pxm->palette->getColor(i);
if (mode->palette)
col = color.parent_index;
else {
- col = mode->red_mask & ((EXTEND_COLOR(color.r)) >> mode->red_shift);
- col |= mode->green_mask & ((EXTEND_COLOR(color.g)) >> mode->green_shift);
- col |= mode->blue_mask & ((EXTEND_COLOR(color.b)) >> mode->blue_shift);
+ col = mode->format.ARGBToColor(0, color.r, color.g, color.b);
col |= alpha_ormask;
}
result_colors[i] = col;
diff --git a/engines/sci/gfx/gfx_resmgr.cpp b/engines/sci/gfx/gfx_resmgr.cpp
index 326cd2dfcf..8ce7a50ed5 100644
--- a/engines/sci/gfx/gfx_resmgr.cpp
+++ b/engines/sci/gfx/gfx_resmgr.cpp
@@ -269,7 +269,8 @@ void GfxResManager::setStaticPalette(Palette *newPalette)
_staticPalette = newPalette;
_staticPalette->name = "static palette";
- _staticPalette->mergeInto(_driver->getMode()->palette);
+ if (_driver->getMode()->palette)
+ _staticPalette->mergeInto(_driver->getMode()->palette);
}
#if 0
@@ -320,7 +321,8 @@ gfx_mode_t mode_1x1_color_index = { /* Fake 1x1 mode */
/* palette */ NULL,
/* color masks */ 0, 0, 0, 0,
- /* color shifts */ 0, 0, 0, 0
+ /* color shifts */ 0, 0, 0, 0,
+ Graphics::PixelFormat()
};
gfxr_pic_t *GfxResManager::getPic(int num, int maps, int flags, int default_palette, bool scaled) {
diff --git a/engines/sci/gfx/gfx_system.h b/engines/sci/gfx/gfx_system.h
index 20c92efa2d..0f5292aedf 100644
--- a/engines/sci/gfx/gfx_system.h
+++ b/engines/sci/gfx/gfx_system.h
@@ -30,6 +30,7 @@
#include "common/rect.h"
#include "sci/tools.h"
#include "sci/gfx/palette.h"
+#include "graphics/pixelformat.h"
namespace Sci {
@@ -74,8 +75,10 @@ struct gfx_mode_t {
*/
Palette *palette;
+ // TODO: remove those
uint32 red_mask, green_mask, blue_mask, alpha_mask;
short red_shift, green_shift, blue_shift, alpha_shift;
+ Graphics::PixelFormat format;
};
diff --git a/engines/sci/gfx/gfx_tools.cpp b/engines/sci/gfx/gfx_tools.cpp
index e3d35ecb14..9e81ec1a8a 100644
--- a/engines/sci/gfx/gfx_tools.cpp
+++ b/engines/sci/gfx/gfx_tools.cpp
@@ -49,6 +49,7 @@ gfx_mode_t *gfx_new_mode(int xfact, int yfact, const Graphics::PixelFormat &form
mode->xfact = xfact;
mode->yfact = yfact;
mode->bytespp = format.bytesPerPixel;
+ mode->format = format;
// FIXME: I am not sure whether the following assignments are quite right.
// The only code using these are the built-in scalers of the SCI engine.
@@ -60,10 +61,10 @@ gfx_mode_t *gfx_new_mode(int xfact, int yfact, const Graphics::PixelFormat &form
mode->green_mask = format.ARGBToColor(0, 0, 0xFF, 0);
mode->blue_mask = format.ARGBToColor(0, 0, 0, 0xFF);
mode->alpha_mask = format.ARGBToColor(0xFF, 0, 0, 0);
- mode->red_shift = format.rLoss;
- mode->green_shift = format.gLoss;
- mode->blue_shift = format.bLoss;
- mode->alpha_shift = format.aLoss;
+ mode->red_shift = format.rShift;
+ mode->green_shift = format.gShift;
+ mode->blue_shift = format.bShift;
+ mode->alpha_shift = format.aShift;
} else {
mode->red_mask = mode->green_mask = mode->blue_mask = 0;
mode->alpha_mask = 0;
diff --git a/engines/sci/gfx/operations.cpp b/engines/sci/gfx/operations.cpp
index 94bb6e0443..b3a1be68d1 100644
--- a/engines/sci/gfx/operations.cpp
+++ b/engines/sci/gfx/operations.cpp
@@ -404,8 +404,9 @@ static void init_aux_pixmap(gfx_pixmap_t **pixmap) {
(*pixmap)->palette = new Palette(default_colors, DEFAULT_COLORS_NR);
}
-int gfxop_init(int version, GfxState *state, gfx_options_t *options, ResourceManager *resManager,
- int xfact, int yfact, gfx_color_mode_t bpp) {
+int gfxop_init(int version, GfxState *state,
+ gfx_options_t *options, ResourceManager *resManager,
+ Graphics::PixelFormat mode, int xfact, int yfact) {
//int color_depth = bpp ? bpp : 1;
//int initialized = 0;
@@ -421,7 +422,7 @@ int gfxop_init(int version, GfxState *state, gfx_options_t *options, ResourceMan
state->pic_port_bounds = gfx_rect(0, 10, 320, 190);
state->_dirtyRects.clear();
- state->driver = new GfxDriver(xfact, yfact, bpp);
+ state->driver = new GfxDriver(xfact, yfact, mode);
state->gfxResMan = new GfxResManager(state->options, state->driver, resManager);
@@ -1131,8 +1132,10 @@ static int _gfxop_set_pointer(GfxState *state, gfx_pixmap_t *pxm, Common::Point
// may change when a new PIC is loaded. The cursor has to be regenerated
// from this pxm at that point. (An alternative might be to ensure the
// cursor only uses colours in the static part of the palette?)
- if (pxm && pxm->palette)
+ if (pxm && state->driver->getMode()->palette) {
+ assert(pxm->palette);
pxm->palette->mergeInto(state->driver->getMode()->palette);
+ }
state->driver->setPointer(pxm, hotspot);
return GFX_OK;
@@ -1736,7 +1739,7 @@ int gfxop_new_pic(GfxState *state, int nr, int flags, int default_palette) {
if (state->driver->getMode()->xfact == 1 && state->driver->getMode()->yfact == 1) {
state->pic_unscaled = state->pic;
} else {
- state->pic = state->gfxResMan->getPic(nr, GFX_MASK_VISUAL, flags, default_palette, false);
+ state->pic_unscaled = state->gfxResMan->getPic(nr, GFX_MASK_VISUAL, flags, default_palette, false);
}
if (!state->pic || !state->pic_unscaled) {
diff --git a/engines/sci/gfx/operations.h b/engines/sci/gfx/operations.h
index b9a16d4a27..ec0a810224 100644
--- a/engines/sci/gfx/operations.h
+++ b/engines/sci/gfx/operations.h
@@ -138,17 +138,16 @@ struct GfxState {
* @param[in] state The state to initialize
* @param[in] xfact Horizontal scale factor
* @param[in] yfact Vertical scale factors
- * @param[in] bpp Bytes per pixel to initialize with, or 0
- * (GFX_COLOR_MODE_AUTO) to auto-detect
+ * @param[in] mode Graphics mode to use
* @param[in] options Rendering options
* @param[in] resManager Resource manager to use
* @return GFX_OK on success, GFX_ERROR if that particular mode
* is unavailable, or GFX_FATAL if the graphics driver
* is unable to provide any useful graphics support
*/
-int gfxop_init(int version, GfxState *state, gfx_options_t *options,
- ResourceManager *resManager, int xfact = 1, int yfact = 1,
- gfx_color_mode_t bpp = GFX_COLOR_MODE_INDEX);
+int gfxop_init(int version, GfxState *state,
+ gfx_options_t *options, ResourceManager *resManager,
+ Graphics::PixelFormat mode, int xfact = 1, int yfact = 1);
/**
* Deinitializes a currently active driver.
diff --git a/engines/sci/gfx/res_pic.cpp b/engines/sci/gfx/res_pic.cpp
index 2534c7faf9..09b98d12aa 100644
--- a/engines/sci/gfx/res_pic.cpp
+++ b/engines/sci/gfx/res_pic.cpp
@@ -1552,7 +1552,7 @@ void gfxr_draw_pic01(gfxr_pic_t *pic, int flags, int default_palette, int size,
view->index_height = CLIP<int>(view->index_height, 0, portBounds.height());
// Set up mode structure for resizing the view
- Graphics::PixelFormat format = { 1, 0, 0, 0, 0, 0, 0, 0, 0 }; // 1byte/p, which handles masks and the rest for us
+ Graphics::PixelFormat format(1, 0, 0, 0, 0, 0, 0, 0, 0); // 1byte/p, which handles masks and the rest for us
gfx_mode_t *mode = gfx_new_mode(pic->visual_map->index_width / 320,
pic->visual_map->index_height / 200, format, view->palette, 0);
@@ -1658,7 +1658,7 @@ void gfxr_draw_pic11(gfxr_pic_t *pic, int flags, int default_palette, int size,
view->palette = pic->visual_map->palette->getref();
// Set up mode structure for resizing the view
- Graphics::PixelFormat format = { 1, 0, 0, 0, 0, 0, 0, 0, 0 }; // 1 byte/p, which handles masks and the rest for us
+ Graphics::PixelFormat format(1, 0, 0, 0, 0, 0, 0, 0, 0); // 1 byte/p, which handles masks and the rest for us
gfx_mode_t *mode = gfx_new_mode(pic->visual_map->index_width / 320, pic->visual_map->index_height / 200, format, view->palette, 0);
gfx_xlate_pixmap(view, mode, GFX_XLATE_FILTER_NONE);
diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp
index 53e3e7ab9c..596895d1cb 100644
--- a/engines/sci/sci.cpp
+++ b/engines/sci/sci.cpp
@@ -111,7 +111,13 @@ SciEngine::~SciEngine() {
}
Common::Error SciEngine::run() {
+ Graphics::PixelFormat gfxmode;
+#ifdef ENABLE_RGB_COLOR
+ initGraphics(320, 200, false, NULL);
+#else
initGraphics(320, 200, false);
+#endif
+ gfxmode = _system->getScreenFormat();
// Create debugger console. It requires GFX to be initialized
_console = new Console(this);
@@ -190,7 +196,7 @@ Common::Error SciEngine::run() {
// Default config ends
#endif
- if (gfxop_init(_resmgr->sciVersion(), &gfx_state, &gfx_options, _resmgr)) {
+ if (gfxop_init(_resmgr->sciVersion(), &gfx_state, &gfx_options, _resmgr, gfxmode, 1, 1)) {
warning("Graphics initialization failed. Aborting...");
return Common::kUnknownError;
}
diff --git a/engines/scumm/actor.cpp b/engines/scumm/actor.cpp
index 3033904357..9dab776b67 100644
--- a/engines/scumm/actor.cpp
+++ b/engines/scumm/actor.cpp
@@ -2451,7 +2451,7 @@ void ScummEngine_v71he::postProcessAuxQueue() {
uint8 *dst2 = pvs->getBackPixels(0, pvs->topline);
switch (comp) {
case 1:
- Wiz::copyAuxImage(dst1, dst2, axfd + 10, pvs->w, pvs->h, x, y, w, h);
+ Wiz::copyAuxImage(dst1, dst2, axfd + 10, pvs->pitch, pvs->h, x, y, w, h, _bitDepth);
break;
default:
error("unimplemented compression type %d", comp);
@@ -2551,9 +2551,10 @@ void Actor::saveLoadWithSerializer(Serializer *ser) {
MKLINE(Actor, _flip, sleByte, VER(32)),
MKLINE(Actor, _heSkipLimbs, sleByte, VER(32)),
- // Actor palette grew from 64 to 256 bytes
+ // Actor palette grew from 64 to 256 bytes and switched to uint16 in HE games
MKARRAY_OLD(Actor, _palette[0], sleByte, 64, VER(8), VER(9)),
- MKARRAY(Actor, _palette[0], sleByte, 256, VER(10)),
+ MKARRAY_OLD(Actor, _palette[0], sleByte, 256, VER(10), VER(79)),
+ MKARRAY(Actor, _palette[0], sleUint16, 256, VER(80)),
MK_OBSOLETE(Actor, _mask, sleByte, VER(8), VER(9)),
MKLINE(Actor, _shadowMode, sleByte, VER(8)),
diff --git a/engines/scumm/actor.h b/engines/scumm/actor.h
index 3f67d42a50..c3edd24a39 100644
--- a/engines/scumm/actor.h
+++ b/engines/scumm/actor.h
@@ -157,7 +157,7 @@ protected:
};
- byte _palette[256];
+ uint16 _palette[256];
int _elevation;
uint16 _facing;
uint16 _targetFacing;
diff --git a/engines/scumm/akos.cpp b/engines/scumm/akos.cpp
index ab7db2c4a7..f4bb8a2c8b 100644
--- a/engines/scumm/akos.cpp
+++ b/engines/scumm/akos.cpp
@@ -289,7 +289,7 @@ void AkosCostumeLoader::costumeDecodeData(Actor *a, int frame, uint usemask) {
} while ((uint16)mask);
}
-void AkosRenderer::setPalette(byte *new_palette) {
+void AkosRenderer::setPalette(uint16 *new_palette) {
uint size, i;
size = _vm->getResourceDataSize(akpl);
@@ -299,22 +299,23 @@ void AkosRenderer::setPalette(byte *new_palette) {
if (size > 256)
error("akos_setPalette: %d is too many colors", size);
- if (_vm->_game.heversion >= 99 && _paletteNum) {
- for (i = 0; i < size; i++)
- _palette[i] = (byte)_vm->_hePalettes[_paletteNum * 1024 + 768 + akpl[i]];
- } else if ((_vm->_game.features & GF_16BIT_COLOR) && rgbs) {
- for (i = 0; i < size; i++) {
- if (new_palette[i] == 0xFF) {
- uint8 col = akpl[i];
- uint8 r = rgbs[col * 3 + 0];
- uint8 g = rgbs[col * 3 + 1];
- uint8 b = rgbs[col * 3 + 2];
-
- _palette[i] = _vm->remapPaletteColor(r, g, b, -1);
- } else {
- _palette[i] = new_palette[i];
+ if (_vm->_game.features & GF_16BIT_COLOR) {
+ if (_paletteNum) {
+ for (i = 0; i < size; i++)
+ _palette[i] = READ_LE_UINT16(_vm->_hePalettes + _paletteNum * _vm->_hePaletteSlot + 768 + akpl[i] * 2);
+ } else if (rgbs) {
+ for (i = 0; i < size; i++) {
+ if (new_palette[i] == 0xFF) {
+ uint8 col = akpl[i];
+ _palette[i] = _vm->get16BitColor(rgbs[col * 3 + 0], rgbs[col * 3 + 1], rgbs[col * 3 + 2]);
+ } else {
+ _palette[i] = new_palette[i];
+ }
}
}
+ } else if (_vm->_game.heversion >= 99 && _paletteNum) {
+ for (i = 0; i < size; i++)
+ _palette[i] = (byte)_vm->_hePalettes[_paletteNum * _vm->_hePaletteSlot + 768 + akpl[i]];
} else {
for (i = 0; i < size; i++) {
_palette[i] = new_palette[i] != 0xFF ? new_palette[i] : akpl[i];
@@ -545,7 +546,7 @@ void AkosRenderer::codec1_genericDecode(Codec1 &v1) {
byte *dst;
byte len, maskbit;
int y;
- uint color, height, pcolor;
+ uint16 color, height, pcolor;
const byte *scaleytab;
bool masked;
bool skip_column = false;
@@ -589,7 +590,11 @@ void AkosRenderer::codec1_genericDecode(Codec1 &v1) {
} else if (_shadow_mode == 2) {
error("codec1_spec2"); // TODO
} else if (_shadow_mode == 3) {
- if (_vm->_game.heversion >= 90) {
+ if (_vm->_game.features & GF_16BIT_COLOR) {
+ uint16 srcColor = (pcolor >> 1) & 0x7DEF;
+ uint16 dstColor = (READ_UINT16(dst) >> 1) & 0x7DEF;
+ pcolor = srcColor + dstColor;
+ } else if (_vm->_game.heversion >= 90) {
pcolor = (pcolor << 8) + *dst;
pcolor = xmap[pcolor];
} else if (pcolor < 8) {
@@ -597,7 +602,11 @@ void AkosRenderer::codec1_genericDecode(Codec1 &v1) {
pcolor = _shadow_table[pcolor];
}
}
- *dst = pcolor;
+ if (_vm->_bitDepth == 2) {
+ WRITE_UINT16(dst, pcolor);
+ } else {
+ *dst = pcolor;
+ }
}
}
dst += _out.pitch;
@@ -617,7 +626,7 @@ void AkosRenderer::codec1_genericDecode(Codec1 &v1) {
if (v1.x < 0 || v1.x >= v1.boundsRect.right)
return;
maskbit = revBitMask(v1.x & 7);
- v1.destptr += v1.scaleXstep;
+ v1.destptr += v1.scaleXstep * _vm->_bitDepth;
skip_column = false;
} else
skip_column = true;
@@ -987,7 +996,7 @@ byte AkosRenderer::codec1(int xmoveCur, int ymoveCur) {
if (_draw_bottom < rect.bottom)
_draw_bottom = rect.bottom;
- v1.destptr = (byte *)_out.pixels + v1.y * _out.pitch + v1.x;
+ v1.destptr = (byte *)_out.pixels + v1.y * _out.pitch + v1.x * _vm->_bitDepth;
codec1_genericDecode(v1);
@@ -1056,7 +1065,12 @@ byte AkosRenderer::codec5(int xmoveCur, int ymoveCur) {
bdd.shadowMode = _shadow_mode;
bdd.shadowPalette = _vm->_shadowPalette;
- bdd.actorPalette = _useBompPalette ? _palette : 0;
+ bdd.actorPalette = 0;
+ if (_useBompPalette) {
+ for (uint i = 0; i < 256; i++)
+ bdd.actorPalette[i] = _palette[i];
+ }
+
bdd.mirror = !_mirror;
drawBomp(bdd);
@@ -1176,6 +1190,8 @@ void AkosRenderer::akos16Decompress(byte *dest, int32 pitch, const byte *src, in
}
byte AkosRenderer::codec16(int xmoveCur, int ymoveCur) {
+ assert(_vm->_bitDepth == 1);
+
Common::Rect clip;
int32 minx, miny, maxw, maxh;
int32 skip_x, skip_y, cur_x, cur_y;
@@ -1278,7 +1294,7 @@ byte AkosRenderer::codec16(int xmoveCur, int ymoveCur) {
int32 numskip_before = skip_x + (skip_y * _width);
int32 numskip_after = _width - cur_x;
- byte *dst = (byte *)_out.pixels + width_unk + height_unk * _out.pitch;
+ byte *dst = (byte *)_out.pixels + height_unk * _out.pitch + width_unk * _vm->_bitDepth;
akos16Decompress(dst, _out.pitch, _srcptr, cur_x, out_height, dir, numskip_before, numskip_after, transparency, clip.left, clip.top, _zbuf);
return 0;
@@ -1335,18 +1351,27 @@ byte AkosRenderer::codec32(int xmoveCur, int ymoveCur) {
_draw_bottom = dst.bottom;
const uint8 *palPtr = NULL;
- if (_vm->_game.heversion >= 99) {
- palPtr = _vm->_hePalettes + 1792;
+ if (_vm->_game.features & GF_16BIT_COLOR) {
+ palPtr = _vm->_hePalettes + _vm->_hePaletteSlot + 768;
+ if (_paletteNum) {
+ palPtr = _vm->_hePalettes + _paletteNum * _vm->_hePaletteSlot + 768;
+ } else if (rgbs) {
+ for (uint i = 0; i < 256; i++)
+ WRITE_LE_UINT16(_palette + i, _vm->get16BitColor(rgbs[i * 3 + 0], rgbs[i * 3 + 1], rgbs[i * 3 + 2]));
+ palPtr = (uint8 *)_palette;
+ }
+ } else if (_vm->_game.heversion >= 99) {
+ palPtr = _vm->_hePalettes + _vm->_hePaletteSlot + 768;
}
- byte *dstPtr = (byte *)_out.pixels + dst.left + dst.top * _out.pitch;
+ byte *dstPtr = (byte *)_out.pixels + dst.top * _out.pitch + dst.left * _vm->_bitDepth;
if (_shadow_mode == 3) {
- Wiz::decompressWizImage<kWizXMap>(dstPtr, _out.pitch, _srcptr, src, 0, palPtr, xmap);
+ Wiz::decompressWizImage<kWizXMap>(dstPtr, _out.pitch, kDstScreen, _srcptr, src, 0, palPtr, xmap, _vm->_bitDepth);
} else {
if (palPtr != NULL) {
- Wiz::decompressWizImage<kWizRMap>(dstPtr, _out.pitch, _srcptr, src, 0, palPtr);
+ Wiz::decompressWizImage<kWizRMap>(dstPtr, _out.pitch, kDstScreen, _srcptr, src, 0, palPtr, NULL, _vm->_bitDepth);
} else {
- Wiz::decompressWizImage<kWizCopy>(dstPtr, _out.pitch, _srcptr, src, 0);
+ Wiz::decompressWizImage<kWizCopy>(dstPtr, _out.pitch, kDstScreen, _srcptr, src, 0, NULL, NULL, _vm->_bitDepth);
}
}
#endif
diff --git a/engines/scumm/akos.h b/engines/scumm/akos.h
index be532b804d..9f4f09d4dc 100644
--- a/engines/scumm/akos.h
+++ b/engines/scumm/akos.h
@@ -60,7 +60,7 @@ protected:
uint16 _codec;
// actor _palette
- byte _palette[256];
+ uint16 _palette[256];
bool _useBompPalette;
// pointer to various parts of the costume resource
@@ -107,7 +107,7 @@ public:
int16 _actorHitX, _actorHitY;
bool _actorHitResult;
- void setPalette(byte *_palette);
+ void setPalette(uint16 *_palette);
void setFacing(const Actor *a);
void setCostume(int costume, int shadow);
diff --git a/engines/scumm/base-costume.cpp b/engines/scumm/base-costume.cpp
index 795abb8685..ef706afaac 100644
--- a/engines/scumm/base-costume.cpp
+++ b/engines/scumm/base-costume.cpp
@@ -40,7 +40,7 @@ byte BaseCostumeRenderer::drawCostume(const VirtScreen &vs, int numStrips, const
_out.pixels = vs.getPixels(0, 0);
_actorX += _vm->_virtscr[kMainVirtScreen].xstart & 7;
- _out.w = _out.pitch;
+ _out.w = _out.pitch / _vm->_bitDepth;
_out.pixels = (byte *)_out.pixels - (_vm->_virtscr[kMainVirtScreen].xstart & 7);
_numStrips = numStrips;
diff --git a/engines/scumm/base-costume.h b/engines/scumm/base-costume.h
index 59ca3ded1f..d41d795e34 100644
--- a/engines/scumm/base-costume.h
+++ b/engines/scumm/base-costume.h
@@ -145,7 +145,7 @@ public:
}
virtual ~BaseCostumeRenderer() {}
- virtual void setPalette(byte *palette) = 0;
+ virtual void setPalette(uint16 *palette) = 0;
virtual void setFacing(const Actor *a) = 0;
virtual void setCostume(int costume, int shadow) = 0;
diff --git a/engines/scumm/charset.cpp b/engines/scumm/charset.cpp
index 193fc434e4..d6dfa4c5bb 100644
--- a/engines/scumm/charset.cpp
+++ b/engines/scumm/charset.cpp
@@ -819,9 +819,9 @@ void CharsetRendererClassic::printCharIntern(bool is2byte, const byte *charPtr,
byte imagePalette[256];
memset(imagePalette, 0, sizeof(imagePalette));
memcpy(imagePalette, _vm->_charsetColorMap, 4);
- Wiz::copyWizImage(dstPtr, charPtr, vs->w, vs->h, _left, _top, origWidth, origHeight, &rScreen, 0, imagePalette);
+ Wiz::copyWizImage(dstPtr, charPtr, vs->pitch, kDstScreen, vs->w, vs->h, _left, _top, origWidth, origHeight, &rScreen, 0, imagePalette, NULL, _vm->_bitDepth);
} else {
- Wiz::copyWizImage(dstPtr, charPtr, vs->w, vs->h, _left, _top, origWidth, origHeight, &rScreen);
+ Wiz::copyWizImage(dstPtr, charPtr, vs->pitch, kDstScreen, vs->w, vs->h, _left, _top, origWidth, origHeight, &rScreen, 0, NULL, NULL, _vm->_bitDepth);
}
if (_blitAlso && vs->hasTwoBuffers) {
diff --git a/engines/scumm/costume.cpp b/engines/scumm/costume.cpp
index 57b793d579..6923c27b38 100644
--- a/engines/scumm/costume.cpp
+++ b/engines/scumm/costume.cpp
@@ -791,7 +791,7 @@ byte ClassicCostumeRenderer::drawLimb(const Actor *a, int limb) {
}
-void NESCostumeRenderer::setPalette(byte *palette) {
+void NESCostumeRenderer::setPalette(uint16 *palette) {
// TODO
}
@@ -874,17 +874,20 @@ void ClassicCostumeLoader::costumeDecodeData(Actor *a, int frame, uint usemask)
} while (mask&0xFFFF);
}
-void ClassicCostumeRenderer::setPalette(byte *palette) {
+void ClassicCostumeRenderer::setPalette(uint16 *palette) {
int i;
byte color;
if (_loaded._format == 0x57) {
- memcpy(_palette, palette, 13);
+ for (i = 0; i < 13; i++)
+ _palette[i] = palette[i];
} else if (_vm->_game.features & GF_OLD_BUNDLE) {
if (_vm->getCurrentLights() & LIGHTMODE_actor_use_colors) {
- memcpy(_palette, palette, 16);
+ for (i = 0; i < 16; i++)
+ _palette[i] = palette[i];
} else {
- memset(_palette, 8, 16);
+ for (i = 0; i < 16; i++)
+ _palette[i] = 8;
_palette[12] = 0;
}
_palette[_loaded._palette[0]] = _palette[0];
diff --git a/engines/scumm/costume.h b/engines/scumm/costume.h
index 8e1910abcf..929eb8c451 100644
--- a/engines/scumm/costume.h
+++ b/engines/scumm/costume.h
@@ -98,7 +98,7 @@ protected:
public:
ClassicCostumeRenderer(ScummEngine *vm) : BaseCostumeRenderer(vm), _loaded(vm) {}
- void setPalette(byte *palette);
+ void setPalette(uint16 *palette);
void setFacing(const Actor *a);
void setCostume(int costume, int shadow);
@@ -120,7 +120,7 @@ protected:
public:
NESCostumeRenderer(ScummEngine *vm) : BaseCostumeRenderer(vm), _loaded(vm) {}
- void setPalette(byte *palette);
+ void setPalette(uint16 *palette);
void setFacing(const Actor *a);
void setCostume(int costume, int shadow);
@@ -135,7 +135,7 @@ protected:
public:
C64CostumeRenderer(ScummEngine *vm) : BaseCostumeRenderer(vm), _loaded(vm) {}
- void setPalette(byte *palette) {}
+ void setPalette(uint16 *palette) {}
void setFacing(const Actor *a) {}
void setCostume(int costume, int shadow);
diff --git a/engines/scumm/cursor.cpp b/engines/scumm/cursor.cpp
index 64829114ca..66ac68bd95 100644
--- a/engines/scumm/cursor.cpp
+++ b/engines/scumm/cursor.cpp
@@ -111,11 +111,20 @@ void ScummEngine_v6::setCursorTransparency(int a) {
}
void ScummEngine::updateCursor() {
- const int transColor = (_game.heversion >= 80) ? 5 : 255;
+ int transColor = (_game.heversion >= 80) ? 5 : 255;
+#ifdef ENABLE_RGB_COLOR
+ Graphics::PixelFormat format = _system->getScreenFormat();
+ CursorMan.replaceCursor(_grabbedCursor, _cursor.width, _cursor.height,
+ _cursor.hotspotX, _cursor.hotspotY,
+ (_game.platform == Common::kPlatformNES ? _grabbedCursor[63] : transColor),
+ (_game.heversion == 70 ? 2 : 1),
+ &format);
+#else
CursorMan.replaceCursor(_grabbedCursor, _cursor.width, _cursor.height,
_cursor.hotspotX, _cursor.hotspotY,
(_game.platform == Common::kPlatformNES ? _grabbedCursor[63] : transColor),
(_game.heversion == 70 ? 2 : 1));
+#endif
}
void ScummEngine_v6::grabCursor(int x, int y, int w, int h) {
@@ -138,7 +147,7 @@ void ScummEngine::setCursorFromBuffer(const byte *ptr, int width, int height, in
uint size;
byte *dst;
- size = width * height;
+ size = width * height * _bitDepth;
if (size > sizeof(_grabbedCursor))
error("grabCursor: grabbed cursor too big");
@@ -148,8 +157,8 @@ void ScummEngine::setCursorFromBuffer(const byte *ptr, int width, int height, in
dst = _grabbedCursor;
for (; height; height--) {
- memcpy(dst, ptr, width);
- dst += width;
+ memcpy(dst, ptr, width * _bitDepth);
+ dst += width * _bitDepth;
ptr += pitch;
}
@@ -166,8 +175,13 @@ void ScummEngine_v70he::setDefaultCursor() {
static const byte palette[] = {0, 0, 0, 0,
0xff, 0xff, 0xff, 0,
0, 0, 0, 0};
-
- memset(_grabbedCursor, 5, sizeof(_grabbedCursor));
+
+ if (_bitDepth == 2) {
+ for (i = 0; i < 1024; i++)
+ WRITE_UINT16(_grabbedCursor + i * 2, 5);
+ } else {
+ memset(_grabbedCursor, 5, sizeof(_grabbedCursor));
+ }
_cursor.hotspotX = _cursor.hotspotY = 2;
src = default_he_cursor;
@@ -180,10 +194,16 @@ void ScummEngine_v70he::setDefaultCursor() {
for (j = 0; j < 32; j++) {
switch ((p & (0x3 << 14)) >> 14) {
case 1:
- _grabbedCursor[32 * i + j] = 0xfe;
+ if (_bitDepth == 2)
+ WRITE_UINT16(_grabbedCursor + 64 * i + j * 2, get16BitColor(palette[4], palette[5], palette[6]));
+ else
+ _grabbedCursor[32 * i + j] = 0xfe;
break;
case 2:
- _grabbedCursor[32 * i + j] = 0xfd;
+ if (_bitDepth == 2)
+ WRITE_UINT16(_grabbedCursor + 64 * i + j * 2, get16BitColor(palette[0], palette[1], palette[2]));
+ else
+ _grabbedCursor[32 * i + j] = 0xfd;
break;
default:
break;
@@ -195,9 +215,11 @@ void ScummEngine_v70he::setDefaultCursor() {
}
}
- // Since white color position is not guaranteed
- // we setup our own palette if supported by backend
- CursorMan.replaceCursorPalette(palette, 0xfd, 3);
+ if (_bitDepth == 1) {
+ // Since white color position is not guaranteed
+ // we setup our own palette if supported by backend
+ CursorMan.replaceCursorPalette(palette, 0xfd, 3);
+ }
updateCursor();
}
diff --git a/engines/scumm/gfx.cpp b/engines/scumm/gfx.cpp
index fa5d2011b0..1802d0d39c 100644
--- a/engines/scumm/gfx.cpp
+++ b/engines/scumm/gfx.cpp
@@ -43,12 +43,12 @@ extern "C" void asmCopy8Col(byte* dst, int dstPitch, const byte* src, int height
namespace Scumm {
-static void blit(byte *dst, int dstPitch, const byte *src, int srcPitch, int w, int h);
-static void fill(byte *dst, int dstPitch, byte color, int w, int h);
+static void blit(byte *dst, int dstPitch, const byte *src, int srcPitch, int w, int h, uint8 bitDepth);
+static void fill(byte *dst, int dstPitch, uint16 color, int w, int h, uint8 bitDepth);
#ifndef USE_ARM_GFX_ASM
-static void copy8Col(byte *dst, int dstPitch, const byte *src, int height);
+static void copy8Col(byte *dst, int dstPitch, const byte *src, int height, uint8 bitDepth);
#endif
-static void clear8Col(byte *dst, int dstPitch, int height);
+static void clear8Col(byte *dst, int dstPitch, int height, uint8 bitDepth);
static void ditherHerc(byte *src, byte *hercbuf, int srcPitch, int *x, int *y, int *width, int *height);
static void scale2x(byte *dst, int dstPitch, const byte *src, int srcPitch, int w, int h);
@@ -231,6 +231,9 @@ GdiV2::~GdiV2() {
free(_roomStrips);
}
+Gdi16Bit::Gdi16Bit(ScummEngine *vm) : Gdi(vm) {
+}
+
void Gdi::init() {
_numStrips = _vm->_screenWidth / 8;
@@ -341,8 +344,8 @@ void ScummEngine::initVirtScreen(VirtScreenNumber slot, int top, int width, int
vs->hasTwoBuffers = twobufs;
vs->xstart = 0;
vs->backBuf = NULL;
- vs->bytesPerPixel = 1;
- vs->pitch = width;
+ vs->bytesPerPixel = (_game.features & GF_16BIT_COLOR) ? 2 : 1;
+ vs->pitch = width * vs->bytesPerPixel;
if (_game.version >= 7) {
// Increase the pitch by one; needed to accomodate the extra screen
@@ -586,7 +589,7 @@ void ScummEngine::drawStripToScreen(VirtScreen *vs, int x, int width, int top, i
vsPitch = _screenWidth * m - width * m;
} else {
- vsPitch = vs->pitch - width;
+ vsPitch = vs->pitch - width * vs->bytesPerPixel;
}
@@ -612,36 +615,49 @@ void ScummEngine::drawStripToScreen(VirtScreen *vs, int x, int width, int top, i
#else
// We blit four pixels at a time, for improved performance.
const uint32 *src32 = (const uint32 *)src;
- const uint32 *text32 = (const uint32 *)text;
uint32 *dst32 = (uint32 *)_compositeBuf;
vsPitch >>= 2;
- const int textPitch = (_textSurface.pitch - width * m) >> 2;
- for (int h = height * m; h > 0; --h) {
- for (int w = width*m; w > 0; w-=4) {
- uint32 temp = *text32++;
-
- // Generate a byte mask for those text pixels (bytes) with
- // value CHARSET_MASK_TRANSPARENCY. In the end, each byte
- // in mask will be either equal to 0x00 or 0xFF.
- // Doing it this way avoids branches and bytewise operations,
- // at the cost of readability ;).
- uint32 mask = temp ^ CHARSET_MASK_TRANSPARENCY_32;
- mask = (((mask & 0x7f7f7f7f) + 0x7f7f7f7f) | mask) & 0x80808080;
- mask = ((mask >> 7) + 0x7f7f7f7f) ^ 0x80808080;
-
- // The following line is equivalent to this code:
- // *dst32++ = (*src32++ & mask) | (temp & ~mask);
- // However, some compilers can generate somewhat better
- // machine code for this equivalent statement:
- *dst32++ = ((temp ^ *src32++) & mask) ^ temp;
+
+ if (_bitDepth == 2) {
+ // Sprites always seem to be used for subtitles in 16Bit color HE games, and not
+ // the charset renderer, so charset masking isn't required.
+ for (int h = height * m; h > 0; --h) {
+ for (int w = width * m; w > 0; w -= 4) {
+ *dst32++ = *src32++;
+ *dst32++ = *src32++;
+ }
+ src32 += vsPitch;
+ }
+ } else {
+ const uint32 *text32 = (const uint32 *)text;
+ const int textPitch = (_textSurface.pitch - width * m) >> 2;
+ for (int h = height * m; h > 0; --h) {
+ for (int w = width * m; w > 0; w -= 4) {
+ uint32 temp = *text32++;
+
+ // Generate a byte mask for those text pixels (bytes) with
+ // value CHARSET_MASK_TRANSPARENCY. In the end, each byte
+ // in mask will be either equal to 0x00 or 0xFF.
+ // Doing it this way avoids branches and bytewise operations,
+ // at the cost of readability ;).
+ uint32 mask = temp ^ CHARSET_MASK_TRANSPARENCY_32;
+ mask = (((mask & 0x7f7f7f7f) + 0x7f7f7f7f) | mask) & 0x80808080;
+ mask = ((mask >> 7) + 0x7f7f7f7f) ^ 0x80808080;
+
+ // The following line is equivalent to this code:
+ // *dst32++ = (*src32++ & mask) | (temp & ~mask);
+ // However, some compilers can generate somewhat better
+ // machine code for this equivalent statement:
+ *dst32++ = ((temp ^ *src32++) & mask) ^ temp;
+ }
+ src32 += vsPitch;
+ text32 += textPitch;
}
- src32 += vsPitch;
- text32 += textPitch;
}
#endif
src = _compositeBuf;
- pitch = width;
+ pitch = width * vs->bytesPerPixel;
if (_renderMode == Common::kRenderHercA || _renderMode == Common::kRenderHercG) {
ditherHerc(_compositeBuf, _herculesBuf, width, &x, &y, &width, &height);
@@ -986,13 +1002,13 @@ void ScummEngine::restoreBackground(Common::Rect rect, byte backColor) {
return;
if (vs->hasTwoBuffers && _currentRoom != 0 && isLightOn()) {
- blit(screenBuf, vs->pitch, vs->getBackPixels(rect.left, rect.top), vs->pitch, width, height);
+ blit(screenBuf, vs->pitch, vs->getBackPixels(rect.left, rect.top), vs->pitch, width, height, vs->bytesPerPixel);
if (vs->number == kMainVirtScreen && _charset->_hasMask) {
byte *mask = (byte *)_textSurface.getBasePtr(rect.left, rect.top - _screenTop);
- fill(mask, _textSurface.pitch, CHARSET_MASK_TRANSPARENCY, width, height);
+ fill(mask, _textSurface.pitch, CHARSET_MASK_TRANSPARENCY, width, height, _textSurface.bytesPerPixel);
}
} else {
- fill(screenBuf, vs->pitch, backColor, width, height);
+ fill(screenBuf, vs->pitch, backColor, width, height, vs->bytesPerPixel);
}
}
@@ -1021,7 +1037,7 @@ void ScummEngine::restoreCharsetBg() {
if (vs->number != kMainVirtScreen) {
// Restore from back buffer
const byte *backBuf = vs->getBackPixels(0, 0);
- blit(screenBuf, vs->pitch, backBuf, vs->pitch, vs->w, vs->h);
+ blit(screenBuf, vs->pitch, backBuf, vs->pitch, vs->w, vs->h, vs->bytesPerPixel);
}
} else {
// Clear area
@@ -1057,34 +1073,42 @@ byte *Gdi::getMaskBuffer(int x, int y, int z) {
#pragma mark --- Misc ---
#pragma mark -
-static void blit(byte *dst, int dstPitch, const byte *src, int srcPitch, int w, int h) {
+static void blit(byte *dst, int dstPitch, const byte *src, int srcPitch, int w, int h, uint8 bitDepth) {
assert(w > 0);
assert(h > 0);
assert(src != NULL);
assert(dst != NULL);
- if (w == srcPitch && w == dstPitch) {
- memcpy(dst, src, w*h);
+ if ((w * bitDepth == srcPitch) && (w * bitDepth == dstPitch)) {
+ memcpy(dst, src, w * h * bitDepth);
} else {
do {
- memcpy(dst, src, w);
+ memcpy(dst, src, w * bitDepth);
dst += dstPitch;
src += srcPitch;
} while (--h);
}
}
-static void fill(byte *dst, int dstPitch, byte color, int w, int h) {
+static void fill(byte *dst, int dstPitch, uint16 color, int w, int h, uint8 bitDepth) {
assert(h > 0);
assert(dst != NULL);
- if (w == dstPitch) {
- memset(dst, color, w*h);
- } else {
+ if (bitDepth == 2) {
do {
- memset(dst, color, w);
+ for (int i = 0; i < w; i++)
+ WRITE_UINT16(dst + i * 2, color);
dst += dstPitch;
} while (--h);
+ } else {
+ if (w == dstPitch) {
+ memset(dst, color, w * h);
+ } else {
+ do {
+ memset(dst, color, w);
+ dst += dstPitch;
+ } while (--h);
+ }
}
}
@@ -1094,14 +1118,18 @@ static void fill(byte *dst, int dstPitch, byte color, int w, int h) {
#else
-static void copy8Col(byte *dst, int dstPitch, const byte *src, int height) {
+static void copy8Col(byte *dst, int dstPitch, const byte *src, int height, uint8 bitDepth) {
do {
#if defined(SCUMM_NEED_ALIGNMENT)
- memcpy(dst, src, 8);
+ memcpy(dst, src, 8 * bitDepth);
#else
((uint32 *)dst)[0] = ((const uint32 *)src)[0];
((uint32 *)dst)[1] = ((const uint32 *)src)[1];
+ if (bitDepth == 2) {
+ ((uint32 *)dst)[2] = ((const uint32 *)src)[2];
+ ((uint32 *)dst)[3] = ((const uint32 *)src)[3];
+ }
#endif
dst += dstPitch;
src += dstPitch;
@@ -1110,13 +1138,17 @@ static void copy8Col(byte *dst, int dstPitch, const byte *src, int height) {
#endif /* USE_ARM_GFX_ASM */
-static void clear8Col(byte *dst, int dstPitch, int height) {
+static void clear8Col(byte *dst, int dstPitch, int height, uint8 bitDepth) {
do {
#if defined(SCUMM_NEED_ALIGNMENT)
- memset(dst, 0, 8);
+ memset(dst, 0, 8 * bitDepth);
#else
((uint32 *)dst)[0] = 0;
((uint32 *)dst)[1] = 0;
+ if (bitDepth == 2) {
+ ((uint32 *)dst)[2] = 0;
+ ((uint32 *)dst)[3] = 0;
+ }
#endif
dst += dstPitch;
} while (--height);
@@ -1181,41 +1213,41 @@ void ScummEngine::drawBox(int x, int y, int x2, int y2, int color) {
if (color == -1) {
if (vs->number != kMainVirtScreen)
error("can only copy bg to main window");
- blit(backbuff, vs->pitch, bgbuff, vs->pitch, width, height);
+ blit(backbuff, vs->pitch, bgbuff, vs->pitch, width, height, vs->bytesPerPixel);
if (_charset->_hasMask) {
byte *mask = (byte *)_textSurface.getBasePtr(x * _textSurfaceMultiplier, (y - _screenTop) * _textSurfaceMultiplier);
- fill(mask, _textSurface.pitch, CHARSET_MASK_TRANSPARENCY, width * _textSurfaceMultiplier, height * _textSurfaceMultiplier);
+ fill(mask, _textSurface.pitch, CHARSET_MASK_TRANSPARENCY, width * _textSurfaceMultiplier, height * _textSurfaceMultiplier, _textSurface.bytesPerPixel);
}
} else if (_game.heversion >= 72) {
// Flags are used for different methods in HE games
uint32 flags = color;
if ((flags & 0x2000) || (flags & 0x4000000)) {
- blit(backbuff, vs->pitch, bgbuff, vs->pitch, width, height);
+ blit(backbuff, vs->pitch, bgbuff, vs->pitch, width, height, vs->bytesPerPixel);
} else if ((flags & 0x4000) || (flags & 0x2000000)) {
- blit(bgbuff, vs->pitch, backbuff, vs->pitch, width, height);
+ blit(bgbuff, vs->pitch, backbuff, vs->pitch, width, height, vs->bytesPerPixel);
} else if ((flags & 0x8000) || (flags & 0x1000000)) {
flags &= (flags & 0x1000000) ? 0xFFFFFF : 0x7FFF;
- fill(backbuff, vs->pitch, flags, width, height);
- fill(bgbuff, vs->pitch, flags, width, height);
+ fill(backbuff, vs->pitch, flags, width, height, vs->bytesPerPixel);
+ fill(bgbuff, vs->pitch, flags, width, height, vs->bytesPerPixel);
} else {
- fill(backbuff, vs->pitch, flags, width, height);
+ fill(backbuff, vs->pitch, flags, width, height, vs->bytesPerPixel);
}
} else if (_game.heversion >= 60) {
// Flags are used for different methods in HE games
uint16 flags = color;
if (flags & 0x2000) {
- blit(backbuff, vs->pitch, bgbuff, vs->pitch, width, height);
+ blit(backbuff, vs->pitch, bgbuff, vs->pitch, width, height, vs->bytesPerPixel);
} else if (flags & 0x4000) {
- blit(bgbuff, vs->pitch, backbuff, vs->pitch, width, height);
+ blit(bgbuff, vs->pitch, backbuff, vs->pitch, width, height, vs->bytesPerPixel);
} else if (flags & 0x8000) {
flags &= 0x7FFF;
- fill(backbuff, vs->pitch, flags, width, height);
- fill(bgbuff, vs->pitch, flags, width, height);
+ fill(backbuff, vs->pitch, flags, width, height, vs->bytesPerPixel);
+ fill(bgbuff, vs->pitch, flags, width, height, vs->bytesPerPixel);
} else {
- fill(backbuff, vs->pitch, flags, width, height);
+ fill(backbuff, vs->pitch, flags, width, height, vs->bytesPerPixel);
}
} else {
- fill(backbuff, vs->pitch, color, width, height);
+ fill(backbuff, vs->pitch, color, width, height, vs->bytesPerPixel);
}
}
@@ -1253,7 +1285,7 @@ void ScummEngine_v5::drawFlashlight() {
_flashlight.y, _flashlight.y + _flashlight.h, USAGE_BIT_DIRTY);
if (_flashlight.buffer) {
- fill(_flashlight.buffer, vs->pitch, 0, _flashlight.w, _flashlight.h);
+ fill(_flashlight.buffer, vs->pitch, 0, _flashlight.w, _flashlight.h, vs->bytesPerPixel);
}
_flashlight.isDrawn = false;
}
@@ -1300,7 +1332,7 @@ void ScummEngine_v5::drawFlashlight() {
_flashlight.buffer = vs->getPixels(_flashlight.x, _flashlight.y);
bgbak = vs->getBackPixels(_flashlight.x, _flashlight.y);
- blit(_flashlight.buffer, vs->pitch, bgbak, vs->pitch, _flashlight.w, _flashlight.h);
+ blit(_flashlight.buffer, vs->pitch, bgbak, vs->pitch, _flashlight.w, _flashlight.h, vs->bytesPerPixel);
// Round the corners. To do so, we simply hard-code a set of nicely
// rounded corners.
@@ -1609,7 +1641,7 @@ void Gdi::drawBitmap(const byte *ptr, VirtScreen *vs, int x, const int y, const
warning("Gdi::drawBitmap, strip drawn to %d below window bottom %d", y + height, vs->h);
}
- _vertStripNextInc = height * vs->pitch - 1;
+ _vertStripNextInc = height * vs->pitch - 1 * vs->bytesPerPixel;
_objectMode = (flag & dbObjectMode) == dbObjectMode;
prepareDrawBitmap(ptr, vs, x, y, width, height, stripnr, numstrip);
@@ -1642,9 +1674,9 @@ void Gdi::drawBitmap(const byte *ptr, VirtScreen *vs, int x, const int y, const
// In the case of a double buffered virtual screen, we draw to
// the backbuffer, otherwise to the primary surface memory.
if (vs->hasTwoBuffers)
- dstPtr = vs->backBuf + y * vs->pitch + x * 8;
+ dstPtr = vs->backBuf + y * vs->pitch + (x * 8 * vs->bytesPerPixel);
else
- dstPtr = (byte *)vs->pixels + y * vs->pitch + x * 8;
+ dstPtr = (byte *)vs->pixels + y * vs->pitch + (x * 8 * vs->bytesPerPixel);
transpStrip = drawStrip(dstPtr, vs, x, y, width, height, stripnr, smap_ptr);
@@ -1653,11 +1685,11 @@ void Gdi::drawBitmap(const byte *ptr, VirtScreen *vs, int x, const int y, const
transpStrip = true;
if (vs->hasTwoBuffers) {
- byte *frontBuf = (byte *)vs->pixels + y * vs->pitch + x * 8;
+ byte *frontBuf = (byte *)vs->pixels + y * vs->pitch + (x * 8 * vs->bytesPerPixel);
if (lightsOn)
- copy8Col(frontBuf, vs->pitch, dstPtr, height);
+ copy8Col(frontBuf, vs->pitch, dstPtr, height, vs->bytesPerPixel);
else
- clear8Col(frontBuf, vs->pitch, height);
+ clear8Col(frontBuf, vs->pitch, height, vs->bytesPerPixel);
}
decodeMask(x, y, width, height, stripnr, numzbuf, zplane_list, transpStrip, flag, tmsk_ptr);
@@ -1885,7 +1917,7 @@ void Gdi::drawBMAPBg(const byte *ptr, VirtScreen *vs) {
drawStripHE(dst, vs->pitch, bmap_ptr, vs->w, vs->h, true);
break;
case 150:
- fill(dst, vs->pitch, *bmap_ptr, vs->w, vs->h);
+ fill(dst, vs->pitch, *bmap_ptr, vs->w, vs->h, vs->bytesPerPixel);
break;
default:
// Alternative russian freddi3 uses badly formatted bitmaps
@@ -1941,12 +1973,12 @@ void Gdi::drawBMAPObject(const byte *ptr, VirtScreen *vs, int obj, int x, int y,
assert(bmap_ptr);
byte code = *bmap_ptr++;
- int scrX = _vm->_screenStartStrip * 8;
+ int scrX = _vm->_screenStartStrip * 8 * _vm->_bitDepth;
if (code == 8 || code == 9) {
Common::Rect rScreen(0, 0, vs->w, vs->h);
byte *dst = (byte *)_vm->_virtscr[kMainVirtScreen].backBuf + scrX;
- Wiz::copyWizImage(dst, bmap_ptr, vs->w, vs->h, x - scrX, y, w, h, &rScreen);
+ Wiz::copyWizImage(dst, bmap_ptr, vs->pitch, kDstScreen, vs->w, vs->h, x - scrX, y, w, h, &rScreen, 0, 0, 0, _vm->_bitDepth);
}
Common::Rect rect1(x, y, x + w, y + h);
@@ -1996,7 +2028,7 @@ void ScummEngine_v70he::restoreBackgroundHE(Common::Rect rect, int dirtybit) {
assert(rw <= _screenWidth && rw > 0);
assert(rh <= _screenHeight && rh > 0);
- blit(dst, _virtscr[kMainVirtScreen].pitch, src, _virtscr[kMainVirtScreen].pitch, rw, rh);
+ blit(dst, _virtscr[kMainVirtScreen].pitch, src, _virtscr[kMainVirtScreen].pitch, rw, rh, vs->bytesPerPixel);
markRectAsDirty(kMainVirtScreen, rect, dirtybit);
}
#endif
@@ -2026,15 +2058,15 @@ void Gdi::resetBackground(int top, int bottom, int strip) {
if (bottom > vs->bdirty[strip])
vs->bdirty[strip] = bottom;
- bgbak_ptr = (byte *)vs->backBuf + top * vs->pitch + (strip + vs->xstart/8) * 8;
- backbuff_ptr = (byte *)vs->pixels + top * vs->pitch + (strip + vs->xstart/8) * 8;
+ bgbak_ptr = (byte *)vs->backBuf + top * vs->pitch + (strip + vs->xstart/8) * 8 * vs->bytesPerPixel;
+ backbuff_ptr = (byte *)vs->pixels + top * vs->pitch + (strip + vs->xstart/8) * 8 * vs->bytesPerPixel;
numLinesToProcess = bottom - top;
if (numLinesToProcess) {
if (_vm->isLightOn()) {
- copy8Col(backbuff_ptr, vs->pitch, bgbak_ptr, numLinesToProcess);
+ copy8Col(backbuff_ptr, vs->pitch, bgbak_ptr, numLinesToProcess, vs->bytesPerPixel);
} else {
- clear8Col(backbuff_ptr, vs->pitch, numLinesToProcess);
+ clear8Col(backbuff_ptr, vs->pitch, numLinesToProcess, vs->bytesPerPixel);
}
}
}
@@ -2785,12 +2817,12 @@ void Gdi::drawStripHE(byte *dst, int dstPitch, const byte *src, int width, int h
int x = width;
while (1) {
if (!transpCheck || color != _transparentColor)
- *dst = _roomPalette[color];
- dst++;
+ writeRoomColor(dst, color);
+ dst += _vm->_bitDepth;
--x;
if (x == 0) {
x = width;
- dst += dstPitch - width;
+ dst += dstPitch - width * _vm->_bitDepth;
--height;
if (height == 0)
return;
@@ -2874,8 +2906,8 @@ void Gdi::drawStripComplex(byte *dst, int dstPitch, const byte *src, int height,
do {
FILL_BITS;
if (!transpCheck || color != _transparentColor)
- *dst = _roomPalette[color] + _paletteMod;
- dst++;
+ writeRoomColor(dst, color);
+ dst += _vm->_bitDepth;
againPos:
if (!READ_BIT) {
@@ -2896,13 +2928,13 @@ void Gdi::drawStripComplex(byte *dst, int dstPitch, const byte *src, int height,
do {
if (!--x) {
x = 8;
- dst += dstPitch - 8;
+ dst += dstPitch - 8 * _vm->_bitDepth;
if (!--height)
return;
}
if (!transpCheck || color != _transparentColor)
- *dst = _roomPalette[color] + _paletteMod;
- dst++;
+ writeRoomColor(dst, color);
+ dst += _vm->_bitDepth;
} while (--reps);
bits >>= 8;
bits |= (*src++) << (cl - 8);
@@ -2910,7 +2942,7 @@ void Gdi::drawStripComplex(byte *dst, int dstPitch, const byte *src, int height,
}
}
} while (--x);
- dst += dstPitch - 8;
+ dst += dstPitch - 8 * _vm->_bitDepth;
} while (--height);
}
@@ -2926,8 +2958,8 @@ void Gdi::drawStripBasicH(byte *dst, int dstPitch, const byte *src, int height,
do {
FILL_BITS;
if (!transpCheck || color != _transparentColor)
- *dst = _roomPalette[color] + _paletteMod;
- dst++;
+ writeRoomColor(dst, color);
+ dst += _vm->_bitDepth;
if (!READ_BIT) {
} else if (!READ_BIT) {
FILL_BITS;
@@ -2942,7 +2974,7 @@ void Gdi::drawStripBasicH(byte *dst, int dstPitch, const byte *src, int height,
color += inc;
}
} while (--x);
- dst += dstPitch - 8;
+ dst += dstPitch - 8 * _vm->_bitDepth;
} while (--height);
}
@@ -2959,7 +2991,7 @@ void Gdi::drawStripBasicV(byte *dst, int dstPitch, const byte *src, int height,
do {
FILL_BITS;
if (!transpCheck || color != _transparentColor)
- *dst = _roomPalette[color] + _paletteMod;
+ writeRoomColor(dst, color);
dst += dstPitch;
if (!READ_BIT) {
} else if (!READ_BIT) {
@@ -3027,7 +3059,7 @@ void Gdi::drawStripRaw(byte *dst, int dstPitch, const byte *src, int height, con
for (x = 0; x < 8; x ++) {
byte color = *src++;
if (!transpCheck || color != _transparentColor)
- dst[x] = _roomPalette[color] + _paletteMod;
+ writeRoomColor(dst + x * _vm->_bitDepth, color);
}
dst += dstPitch;
} while (--height);
@@ -3150,6 +3182,14 @@ void Gdi::unkDecode11(byte *dst, int dstPitch, const byte *src, int height) cons
#undef NEXT_ROW
#undef READ_BIT_256
+void Gdi16Bit::writeRoomColor(byte *dst, byte color) const {
+ WRITE_UINT16(dst, READ_LE_UINT16(_vm->_hePalettes + 2048 + color * 2));
+}
+
+void Gdi::writeRoomColor(byte *dst, byte color) const {
+ *dst = _roomPalette[color] + _paletteMod;
+}
+
#pragma mark -
#pragma mark --- Transition effects ---
diff --git a/engines/scumm/gfx.h b/engines/scumm/gfx.h
index e4c1054450..0910d9bc59 100644
--- a/engines/scumm/gfx.h
+++ b/engines/scumm/gfx.h
@@ -155,11 +155,11 @@ struct VirtScreen : Graphics::Surface {
}
byte *getPixels(int x, int y) const {
- return (byte *)pixels + xstart + y * pitch + x;
+ return (byte *)pixels + y * pitch + (xstart + x) * bytesPerPixel;
}
byte *getBackPixels(int x, int y) const {
- return (byte *)backBuf + xstart + y * pitch + x;
+ return (byte *)backBuf + y * pitch + (xstart + x) * bytesPerPixel;
}
};
@@ -215,6 +215,7 @@ protected:
void drawStrip3DO(byte *dst, int dstPitch, const byte *src, int height, const bool transpCheck) const;
void drawStripHE(byte *dst, int dstPitch, const byte *src, int width, int height, const bool transpCheck) const;
+ virtual void writeRoomColor(byte *dst, byte color) const;
/* Mask decompressors */
void decompressTMSK(byte *dst, const byte *tmsk, const byte *src, int height) const;
@@ -361,6 +362,13 @@ public:
virtual void roomChanged(byte *roomptr);
};
+class Gdi16Bit : public Gdi {
+protected:
+ virtual void writeRoomColor(byte *dst, byte color) const;
+public:
+ Gdi16Bit(ScummEngine *vm);
+};
+
} // End of namespace Scumm
#endif
diff --git a/engines/scumm/he/animation_he.cpp b/engines/scumm/he/animation_he.cpp
index 2ca17161db..47b25c57d1 100644
--- a/engines/scumm/he/animation_he.cpp
+++ b/engines/scumm/he/animation_he.cpp
@@ -66,6 +66,32 @@ int MoviePlayer::load(const char *filename, int flags, int image) {
return 0;
}
+void MoviePlayer::copyFrameToBuffer(byte *dst, uint x, uint y, uint pitch) {
+ uint h = getHeight();
+ uint w = getWidth();
+
+ byte *src = _videoFrameBuffer;
+
+ if (_vm->_game.features & GF_16BIT_COLOR) {
+ dst += y * pitch + x * 2;
+ do {
+ for (uint i = 0; i < w; i++) {
+ uint16 col = READ_LE_UINT16(_vm->_hePalettes + _vm->_hePaletteSlot + 768 + src[i] * 2);
+ WRITE_UINT16(dst + i * 2, col);
+ }
+ dst += pitch;
+ src += w;
+ } while (--h);
+ } else {
+ dst += y * pitch + x;
+ do {
+ memcpy(dst, src, w);
+ dst += pitch;
+ src += w;
+ } while (--h);
+ }
+}
+
void MoviePlayer::handleNextFrame() {
if (!isVideoLoaded()) {
return;
@@ -80,14 +106,14 @@ void MoviePlayer::handleNextFrame() {
assert(dstPtr);
uint8 *dst = _vm->findWrappedBlock(MKID_BE('WIZD'), dstPtr, 0, 0);
assert(dst);
- copyFrameToBuffer(dst, 0, 0, _vm->_screenWidth);
+ copyFrameToBuffer(dst, 0, 0, _vm->_screenWidth * _vm->_bitDepth);
} else if (_flags & 1) {
- copyFrameToBuffer(pvs->getBackPixels(0, 0), 0, 0, _vm->_screenWidth);
+ copyFrameToBuffer(pvs->getBackPixels(0, 0), 0, 0, pvs->pitch);
Common::Rect imageRect(getWidth(), getHeight());
_vm->restoreBackgroundHE(imageRect);
} else {
- copyFrameToBuffer(pvs->getPixels(0, 0), 0, 0, _vm->_screenWidth);
+ copyFrameToBuffer(pvs->getPixels(0, 0), 0, 0, pvs->pitch);
Common::Rect imageRect(getWidth(), getHeight());
_vm->markRectAsDirty(kMainVirtScreen, imageRect);
diff --git a/engines/scumm/he/animation_he.h b/engines/scumm/he/animation_he.h
index cf5d054ead..0adba35d53 100644
--- a/engines/scumm/he/animation_he.h
+++ b/engines/scumm/he/animation_he.h
@@ -54,6 +54,7 @@ public:
int getImageNum();
int load(const char *filename, int flags, int image = 0);
+ void copyFrameToBuffer(byte *dst, uint x, uint y, uint pitch);
void handleNextFrame();
protected:
diff --git a/engines/scumm/he/intern_he.h b/engines/scumm/he/intern_he.h
index 9e905b0e79..2f7f539ee3 100644
--- a/engines/scumm/he/intern_he.h
+++ b/engines/scumm/he/intern_he.h
@@ -458,6 +458,7 @@ protected:
uint8 *getHEPaletteIndex(int palSlot);
int getHEPaletteColor(int palSlot, int color);
int getHEPaletteSimilarColor(int palSlot, int red, int green, int start, int end);
+ int getHEPalette16BitColorComponent(int component, int type);
int getHEPaletteColorComponent(int palSlot, int color, int component);
void setHEPaletteColor(int palSlot, uint8 color, uint8 r, uint8 g, uint8 b);
void setHEPaletteFromPtr(int palSlot, const uint8 *palData);
@@ -466,7 +467,7 @@ protected:
void setHEPaletteFromRoom(int palSlot, int resId, int state);
void restoreHEPalette(int palSlot);
void copyHEPalette(int dstPalSlot, int srcPalSlot);
- void copyHEPaletteColor(int palSlot, uint8 dstColor, uint8 srcColor);
+ void copyHEPaletteColor(int palSlot, uint8 dstColor, uint16 srcColor);
protected:
/* HE version 90 script opcodes */
diff --git a/engines/scumm/he/palette_he.cpp b/engines/scumm/he/palette_he.cpp
index 7fe04f223e..ff29f9ecd0 100644
--- a/engines/scumm/he/palette_he.cpp
+++ b/engines/scumm/he/palette_he.cpp
@@ -40,7 +40,7 @@ void ScummEngine_v71he::remapHEPalette(const uint8 *src, uint8 *dst) {
src += 30;
if (_game.heversion >= 99) {
- palPtr = _hePalettes + 1024 + 30;
+ palPtr = _hePalettes + _hePaletteSlot + 30;
} else {
palPtr = _currentPalette + 30;
}
@@ -75,9 +75,9 @@ void ScummEngine_v71he::remapHEPalette(const uint8 *src, uint8 *dst) {
uint8 *ScummEngine_v90he::getHEPaletteIndex(int palSlot) {
if (palSlot) {
assert(palSlot >= 1 && palSlot <= _numPalettes);
- return _hePalettes + palSlot * 1024;
+ return _hePalettes + palSlot * _hePaletteSlot;
} else {
- return _hePalettes + 1024;
+ return _hePalettes + _hePaletteSlot;
}
}
@@ -86,7 +86,7 @@ int ScummEngine_v90he::getHEPaletteSimilarColor(int palSlot, int red, int green,
assertRange(0, start, 255, "start palette slot");
assertRange(0, end, 255, "pend alette slot");
- uint8 *pal = _hePalettes + palSlot * 1024 + start * 3;
+ uint8 *pal = _hePalettes + palSlot * _hePaletteSlot + start * 3;
int bestsum = 0x7FFFFFFF;
int bestitem = start;
@@ -107,39 +107,83 @@ int ScummEngine_v90he::getHEPaletteSimilarColor(int palSlot, int red, int green,
return bestitem;
}
+int ScummEngine_v90he::getHEPalette16BitColorComponent(int component, int type) {
+ uint16 col;
+ if (type == 2) {
+ col = (((component & 0xFFFF) >> 0) & 0x1F) << 3;;
+ } else if (type == 1) {
+ col = (((component & 0xFFFF) >> 5) & 0x1F) << 3;
+ } else {
+ col = (((component & 0xFFFF) >> 10) & 0x1F) << 3;
+ }
+ return col;
+}
+
int ScummEngine_v90he::getHEPaletteColorComponent(int palSlot, int color, int component) {
assertRange(1, palSlot, _numPalettes, "palette");
assertRange(0, color, 255, "palette slot");
- return _hePalettes[palSlot * 1024 + color * 3 + component % 3];
+ return _hePalettes[palSlot * _hePaletteSlot + color * 3 + component % 3];
}
int ScummEngine_v90he::getHEPaletteColor(int palSlot, int color) {
assertRange(1, palSlot, _numPalettes, "palette");
assertRange(0, color, 255, "palette slot");
- return _hePalettes[palSlot * 1024 + 768 + color];
+ if (_game.features & GF_16BIT_COLOR)
+ return READ_LE_UINT16(_hePalettes + palSlot * _hePaletteSlot + 768 + color * 2);
+ else
+ return _hePalettes[palSlot * _hePaletteSlot + 768 + color];
}
void ScummEngine_v90he::setHEPaletteColor(int palSlot, uint8 color, uint8 r, uint8 g, uint8 b) {
debug(7, "setHEPaletteColor(%d, %d, %d, %d, %d)", palSlot, color, r, g, b);
assertRange(1, palSlot, _numPalettes, "palette");
- uint8 *p = _hePalettes + palSlot * 1024 + color * 3;
+
+ uint8 *p = _hePalettes + palSlot * _hePaletteSlot + color * 3;
*(p + 0) = r;
*(p + 1) = g;
*(p + 2) = b;
- _hePalettes[palSlot * 1024 + 768 + color] = color;
+ if (_game.features & GF_16BIT_COLOR) {
+ WRITE_LE_UINT16(_hePalettes + palSlot * _hePaletteSlot + 768 + color * 2, get16BitColor(r, g, b));
+ } else {
+ _hePalettes[palSlot * _hePaletteSlot + 768 + color] = color;
+ }
}
void ScummEngine_v90he::setHEPaletteFromPtr(int palSlot, const uint8 *palData) {
assertRange(1, palSlot, _numPalettes, "palette");
- uint8 *pc = _hePalettes + palSlot * 1024;
+
+ uint8 *pc = _hePalettes + palSlot * _hePaletteSlot;
uint8 *pi = pc + 768;
- for (int i = 0; i < 256; ++i) {
- *pc++ = *palData++;
- *pc++ = *palData++;
- *pc++ = *palData++;
- *pi++ = i;
+ if (_game.features & GF_16BIT_COLOR) {
+ for (int i = 0; i < 256; ++i) {
+ uint8 r = *pc++ = *palData++;
+ uint8 g = *pc++ = *palData++;
+ uint8 b = *pc++ = *palData++;
+ WRITE_LE_UINT16(pi, get16BitColor(r, g, b)); pi += 2;
+ }
+ } else {
+ for (int i = 0; i < 256; ++i) {
+ *pc++ = *palData++;
+ *pc++ = *palData++;
+ *pc++ = *palData++;
+ *pi++ = i;
+ }
+ }
+
+ int i;
+ uint8 *palPtr = _hePalettes + palSlot * _hePaletteSlot + 768;
+ if (_game.features & GF_16BIT_COLOR) {
+ for (i = 0; i < 10; ++i)
+ WRITE_LE_UINT16(palPtr + i * 2, i);
+ for (i = 246; i < 256; ++i)
+ WRITE_LE_UINT16(palPtr + i * 2, i);
+ } else {
+ for (i = 0; i < 10; ++i)
+ *(palPtr + i) = i;
+ for (i = 246; i < 256; ++i)
+ *(palPtr + i) = i;
}
}
@@ -178,8 +222,9 @@ void ScummEngine_v90he::setHEPaletteFromRoom(int palSlot, int resId, int state)
void ScummEngine_v90he::restoreHEPalette(int palSlot) {
debug(7, "restoreHEPalette(%d)", palSlot);
assertRange(1, palSlot, _numPalettes, "palette");
+
if (palSlot != 1) {
- memcpy(_hePalettes + palSlot * 1024, _hePalettes + 1024, 1024);
+ memcpy(_hePalettes + palSlot * _hePaletteSlot, _hePalettes + _hePaletteSlot, _hePaletteSlot);
}
}
@@ -187,18 +232,27 @@ void ScummEngine_v90he::copyHEPalette(int dstPalSlot, int srcPalSlot) {
debug(7, "copyHEPalette(%d, %d)", dstPalSlot, srcPalSlot);
assert(dstPalSlot >= 1 && dstPalSlot <= _numPalettes);
assert(srcPalSlot >= 1 && srcPalSlot <= _numPalettes);
+
if (dstPalSlot != srcPalSlot) {
- memcpy(_hePalettes + dstPalSlot * 1024, _hePalettes + srcPalSlot * 1024, 1024);
+ memcpy(_hePalettes + dstPalSlot * _hePaletteSlot, _hePalettes + srcPalSlot * _hePaletteSlot, _hePaletteSlot);
}
}
-void ScummEngine_v90he::copyHEPaletteColor(int palSlot, uint8 dstColor, uint8 srcColor) {
+void ScummEngine_v90he::copyHEPaletteColor(int palSlot, uint8 dstColor, uint16 srcColor) {
debug(7, "copyHEPaletteColor(%d, %d, %d)", palSlot, dstColor, srcColor);
assertRange(1, palSlot, _numPalettes, "palette");
- uint8 *dstPal = _hePalettes + palSlot * 1024 + dstColor * 3;
- uint8 *srcPal = _hePalettes + 1024 + srcColor * 3;
- memcpy(dstPal, srcPal, 3);
- _hePalettes[palSlot * 1024 + 768 + dstColor] = srcColor;
+
+ uint8 *dstPal = _hePalettes + palSlot * _hePaletteSlot + dstColor * 3;
+ uint8 *srcPal = _hePalettes + _hePaletteSlot + srcColor * 3;
+ if (_game.features & GF_16BIT_COLOR) {
+ dstPal[0] = (srcColor >> 10) << 3;
+ dstPal[1] = (srcColor >> 5) << 3;
+ dstPal[2] = (srcColor >> 0) << 3;
+ WRITE_LE_UINT16(_hePalettes + palSlot * _hePaletteSlot + 768 + dstColor * 2, srcColor);
+ } else {
+ memcpy(dstPal, srcPal, 3);
+ _hePalettes[palSlot * _hePaletteSlot + 768 + dstColor] = srcColor;
+ }
}
void ScummEngine_v99he::setPaletteFromPtr(const byte *ptr, int numcolor) {
@@ -211,7 +265,7 @@ void ScummEngine_v99he::setPaletteFromPtr(const byte *ptr, int numcolor) {
assertRange(0, numcolor, 256, "setPaletteFromPtr: numcolor");
- dest = _hePalettes + 1024;
+ dest = _hePalettes + _hePaletteSlot;
for (i = 0; i < numcolor; i++) {
r = *ptr++;
@@ -222,48 +276,63 @@ void ScummEngine_v99he::setPaletteFromPtr(const byte *ptr, int numcolor) {
*dest++ = r;
*dest++ = g;
*dest++ = b;
- _hePalettes[1792 + i] = i;
+
+ if (_game.features & GF_16BIT_COLOR) {
+ WRITE_LE_UINT16(_hePalettes + 2048 + i * 2, get16BitColor(r, g, b));
+ } else {
+ _hePalettes[1792 + i] = i;
+ }
} else {
dest += 3;
}
}
- memcpy(_hePalettes, _hePalettes + 1024, 768);
-
- for (i = 0; i < 10; ++i)
- _hePalettes[1792 + i] = i;
- for (i = 246; i < 256; ++i)
- _hePalettes[1792 + i] = i;
+ memcpy(_hePalettes, _hePalettes + _hePaletteSlot, 768);
+ if (_game.features & GF_16BIT_COLOR) {
+ for (i = 0; i < 10; ++i)
+ WRITE_LE_UINT16(_hePalettes + 2048 + i * 2, i);
+ for (i = 246; i < 256; ++i)
+ WRITE_LE_UINT16(_hePalettes + 2048 + i * 2, i);
+ } else {
+ for (i = 0; i < 10; ++i)
+ _hePalettes[1792 + i] = i;
+ for (i = 246; i < 256; ++i)
+ _hePalettes[1792 + i] = i;
+ }
setDirtyColors(0, numcolor - 1);
}
void ScummEngine_v99he::darkenPalette(int redScale, int greenScale, int blueScale, int startColor, int endColor) {
uint8 *src, *dst;
- int color, j;
+ int j, r, g, b;
src = _hePalettes + startColor * 3;
- dst = _hePalettes + 1024 + startColor * 3;
+ dst = _hePalettes + _hePaletteSlot + startColor * 3;
for (j = startColor; j <= endColor; j++) {
- color = *src++;
- color = color * redScale / 0xFF;
- if (color > 255)
- color = 255;
- *dst++ = color;
-
- color = *src++;
- color = color * greenScale / 0xFF;
- if (color > 255)
- color = 255;
- *dst++ = color;
-
- color = *src++;
- color = color * blueScale / 0xFF;
- if (color > 255)
- color = 255;
- *dst++ = color;
-
- _hePalettes[1792 + j] = j;
+ r = *src++;
+ r = r * redScale / 0xFF;
+ if (r > 255)
+ r = 255;
+ *dst++ = r;
+
+ g = *src++;
+ g = g * greenScale / 0xFF;
+ if (g > 255)
+ g = 255;
+ *dst++ = g;
+
+ b = *src++;
+ b = b * blueScale / 0xFF;
+ if (b > 255)
+ b = 255;
+ *dst++ = b;
+
+ if (_game.features & GF_16BIT_COLOR) {
+ WRITE_LE_UINT16(_hePalettes + 2048 + j * 2, get16BitColor(r, g, b));
+ } else {
+ _hePalettes[1792 + j] = j;
+ }
setDirtyColors(j, endColor);
}
}
@@ -274,26 +343,39 @@ void ScummEngine_v99he::copyPalColor(int dst, int src) {
if ((uint) dst >= 256 || (uint) src >= 256)
error("copyPalColor: invalid values, %d, %d", dst, src);
- dp = &_hePalettes[1024 + dst * 3];
- sp = &_hePalettes[1024 + src * 3];
+ dp = &_hePalettes[_hePaletteSlot + dst * 3];
+ sp = &_hePalettes[_hePaletteSlot + src * 3];
dp[0] = sp[0];
dp[1] = sp[1];
dp[2] = sp[2];
- _hePalettes[1792 + dst] = dst;
+
+ if (_game.features & GF_16BIT_COLOR) {
+ WRITE_LE_UINT16(_hePalettes + 2048 + dst * 2, get16BitColor(sp[0], sp[1], sp[2]));
+ } else {
+ _hePalettes[1792 + dst] = dst;
+ }
setDirtyColors(dst, dst);
}
void ScummEngine_v99he::setPalColor(int idx, int r, int g, int b) {
- _hePalettes[1024 + idx * 3 + 0] = r;
- _hePalettes[1024 + idx * 3 + 1] = g;
- _hePalettes[1024 + idx * 3 + 2] = b;
- _hePalettes[1792 + idx] = idx;
+ _hePalettes[_hePaletteSlot + idx * 3 + 0] = r;
+ _hePalettes[_hePaletteSlot + idx * 3 + 1] = g;
+ _hePalettes[_hePaletteSlot + idx * 3 + 2] = b;
+
+ if (_game.features & GF_16BIT_COLOR) {
+ WRITE_LE_UINT16(_hePalettes + 2048 + idx * 2, get16BitColor(r, g, b));
+ } else {
+ _hePalettes[1792 + idx] = idx;
+ }
setDirtyColors(idx, idx);
}
void ScummEngine_v99he::updatePalette() {
+ if (_game.features & GF_16BIT_COLOR)
+ return;
+
if (_palDirtyMax == -1)
return;
diff --git a/engines/scumm/he/script_v100he.cpp b/engines/scumm/he/script_v100he.cpp
index 44a38401ce..49e490a8ec 100644
--- a/engines/scumm/he/script_v100he.cpp
+++ b/engines/scumm/he/script_v100he.cpp
@@ -1576,7 +1576,10 @@ void ScummEngine_v100he::o100_roomOps() {
case 130:
a = pop();
b = pop();
- copyPalColor(a, b);
+ if (_game.features & GF_16BIT_COLOR)
+ copyHEPaletteColor(1, a, b);
+ else
+ copyPalColor(a, b);
break;
case 131: // SO_ROOM_FADE
@@ -2153,8 +2156,9 @@ void ScummEngine_v100he::o100_systemOps() {
}
void ScummEngine_v100he::o100_cursorCommand() {
- int a, i;
+ int a, b, i;
int args[16];
+
byte subOp = fetchScriptByte();
switch (subOp) {
@@ -2169,12 +2173,12 @@ void ScummEngine_v100he::o100_cursorCommand() {
case 0x80:
case 0x81:
a = pop();
- _wiz->loadWizCursor(a);
+ _wiz->loadWizCursor(a, 0);
break;
case 0x82:
- pop();
+ b = pop();
a = pop();
- _wiz->loadWizCursor(a);
+ _wiz->loadWizCursor(a, b);
break;
case 0x86: // SO_CURSOR_ON Turn cursor on
_cursor.state = 1;
@@ -2577,7 +2581,8 @@ void ScummEngine_v100he::o100_getWizData() {
}
void ScummEngine_v100he::o100_getPaletteData() {
- int b, c, d, e;
+ int c, d, e;
+ int r, g, b;
int palSlot, color;
byte subOp = fetchScriptByte();
@@ -2586,7 +2591,10 @@ void ScummEngine_v100he::o100_getPaletteData() {
case 13:
c = pop();
b = pop();
- push(getHEPaletteColorComponent(1, b, c));
+ if (_game.features & GF_16BIT_COLOR)
+ push(getHEPalette16BitColorComponent(b, c));
+ else
+ push(getHEPaletteColorComponent(1, b, c));
break;
case 20:
color = pop();
@@ -2597,20 +2605,26 @@ void ScummEngine_v100he::o100_getPaletteData() {
e = pop();
d = pop();
palSlot = pop();
- pop();
- c = pop();
b = pop();
- push(getHEPaletteSimilarColor(palSlot, b, c, d, e));
+ g = pop();
+ r = pop();
+ push(getHEPaletteSimilarColor(palSlot, r, g, d, e));
break;
case 53:
- pop();
- c = pop();
- c = MAX(0, c);
- c = MIN(c, 255);
b = pop();
b = MAX(0, b);
b = MIN(b, 255);
- push(getHEPaletteSimilarColor(1, b, c, 10, 245));
+ g = pop();
+ g = MAX(0, g);
+ g = MIN(g, 255);
+ r = pop();
+ r = MAX(0, r);
+ r = MIN(r, 255);
+ if (_game.features & GF_16BIT_COLOR) {
+ push(get16BitColor(r, g, b));
+ } else {
+ push(getHEPaletteSimilarColor(1, r, g, 10, 245));
+ }
break;
case 73:
c = pop();
diff --git a/engines/scumm/he/script_v60he.cpp b/engines/scumm/he/script_v60he.cpp
index 7c109b1dcd..92848ce981 100644
--- a/engines/scumm/he/script_v60he.cpp
+++ b/engines/scumm/he/script_v60he.cpp
@@ -122,6 +122,8 @@ int ScummEngine_v60he::convertFilePath(byte *dst, int dstSize) {
} else if (dst[0] == '.' && dst[1] == '/') { // Game Data Path
// The default game data path is set to './' by ScummVM
r = 2;
+ } else if (dst[2] == 'b' && dst[5] == 'k') { // Backyard Basketball INI
+ r = 13;
} else if (dst[0] == '*' && dst[1] == '/') { // Save Game Path (HE72 - HE100)
// The default save game path is set to '*/' by ScummVM
r = 2;
diff --git a/engines/scumm/he/script_v72he.cpp b/engines/scumm/he/script_v72he.cpp
index 1d73f0da76..0c2c01d419 100644
--- a/engines/scumm/he/script_v72he.cpp
+++ b/engines/scumm/he/script_v72he.cpp
@@ -1484,6 +1484,7 @@ void ScummEngine_v72he::o72_readFile() {
fetchScriptByte();
size = pop();
slot = pop();
+ assert(_hInFileTable[slot]);
val = readFileToArray(slot, size);
push(val);
break;
@@ -1573,7 +1574,7 @@ void ScummEngine_v72he::o72_rename() {
}
void ScummEngine_v72he::o72_getPixel() {
- byte area;
+ uint16 area;
int y = pop();
int x = pop();
@@ -1588,11 +1589,17 @@ void ScummEngine_v72he::o72_getPixel() {
switch (subOp) {
case 9: // HE 100
case 218:
- area = *vs->getBackPixels(x, y - vs->topline);
+ if (_game.features & GF_16BIT_COLOR)
+ area = READ_UINT16(vs->getBackPixels(x, y - vs->topline));
+ else
+ area = *vs->getBackPixels(x, y - vs->topline);
break;
case 8: // HE 100
case 219:
- area = *vs->getPixels(x, y - vs->topline);
+ if (_game.features & GF_16BIT_COLOR)
+ area = READ_UINT16(vs->getPixels(x, y - vs->topline));
+ else
+ area = *vs->getPixels(x, y - vs->topline);
break;
default:
error("o72_getPixel: default case %d", subOp);
@@ -1805,9 +1812,7 @@ void ScummEngine_v72he::o72_readINI() {
switch (subOp) {
case 43: // HE 100
case 6: // number
- if (!strcmp((char *)option, "NoFontsInstalled")) {
- push(1);
- } else if (!strcmp((char *)option, "NoPrinting")) {
+ if (!strcmp((char *)option, "NoPrinting")) {
push(1);
} else if (!strcmp((char *)option, "TextOn")) {
push(ConfMan.getBool("subtitles"));
diff --git a/engines/scumm/he/script_v80he.cpp b/engines/scumm/he/script_v80he.cpp
index 5b10944899..dd44180fa0 100644
--- a/engines/scumm/he/script_v80he.cpp
+++ b/engines/scumm/he/script_v80he.cpp
@@ -243,7 +243,7 @@ void ScummEngine_v80he::o80_writeConfigFile() {
}
void ScummEngine_v80he::o80_cursorCommand() {
- int a, i;
+ int a, b, i;
int args[16];
byte subOp = fetchScriptByte();
@@ -252,12 +252,12 @@ void ScummEngine_v80he::o80_cursorCommand() {
case 0x13:
case 0x14:
a = pop();
- _wiz->loadWizCursor(a);
+ _wiz->loadWizCursor(a, 0);
break;
case 0x3C:
- pop();
+ b = pop();
a = pop();
- _wiz->loadWizCursor(a);
+ _wiz->loadWizCursor(a, b);
break;
case 0x90: // SO_CURSOR_ON Turn cursor on
_cursor.state = 1;
diff --git a/engines/scumm/he/script_v90he.cpp b/engines/scumm/he/script_v90he.cpp
index be20a229f0..e302af1144 100644
--- a/engines/scumm/he/script_v90he.cpp
+++ b/engines/scumm/he/script_v90he.cpp
@@ -1255,7 +1255,7 @@ void ScummEngine_v90he::o90_setSpriteGroupInfo() {
void ScummEngine_v90he::o90_getWizData() {
byte filename[4096];
- int state, resId;
+ int resId, state, type;
int32 w, h;
int32 x, y;
@@ -1319,9 +1319,10 @@ void ScummEngine_v90he::o90_getWizData() {
push(computeWizHistogram(resId, state, x, y, w, h));
break;
case 139:
- pop();
- pop();
- push(0);
+ type = pop();
+ state = pop();
+ resId = pop();
+ push(_wiz->getWizImageData(resId, state, type));
break;
case 141:
pop();
@@ -2101,7 +2102,8 @@ void ScummEngine_v90he::o90_getObjectData() {
}
void ScummEngine_v90he::o90_getPaletteData() {
- int b, c, d, e;
+ int c, d, e;
+ int r, g, b;
int palSlot, color;
byte subOp = fetchScriptByte();
@@ -2111,10 +2113,10 @@ void ScummEngine_v90he::o90_getPaletteData() {
e = pop();
d = pop();
palSlot = pop();
- pop();
- c = pop();
b = pop();
- push(getHEPaletteSimilarColor(palSlot, b, c, d, e));
+ g = pop();
+ r = pop();
+ push(getHEPaletteSimilarColor(palSlot, r, g, d, e));
break;
case 52:
c = pop();
@@ -2130,17 +2132,27 @@ void ScummEngine_v90he::o90_getPaletteData() {
case 132:
c = pop();
b = pop();
- push(getHEPaletteColorComponent(1, b, c));
+ if (_game.features & GF_16BIT_COLOR)
+ push(getHEPalette16BitColorComponent(b, c));
+ else
+ push(getHEPaletteColorComponent(1, b, c));
break;
case 217:
- pop();
- c = pop();
- c = MAX(0, c);
- c = MIN(c, 255);
b = pop();
b = MAX(0, b);
b = MIN(b, 255);
- push(getHEPaletteSimilarColor(1, b, c, 10, 245));
+ g = pop();
+ g = MAX(0, g);
+ g = MIN(g, 255);
+ r = pop();
+ r = MAX(0, r);
+ r = MIN(r, 255);
+
+ if (_game.features & GF_16BIT_COLOR) {
+ push(get16BitColor(r, g, b));
+ } else {
+ push(getHEPaletteSimilarColor(1, r, g, 10, 245));
+ }
break;
default:
error("o90_getPaletteData: Unknown case %d", subOp);
diff --git a/engines/scumm/he/wiz_he.cpp b/engines/scumm/he/wiz_he.cpp
index 549877090c..b00294cb96 100644
--- a/engines/scumm/he/wiz_he.cpp
+++ b/engines/scumm/he/wiz_he.cpp
@@ -254,7 +254,9 @@ bool Wiz::polygonContains(const WizPolygon &pol, int x, int y) {
return r;
}
-void Wiz::copyAuxImage(uint8 *dst1, uint8 *dst2, const uint8 *src, int dstw, int dsth, int srcx, int srcy, int srcw, int srch) {
+void Wiz::copyAuxImage(uint8 *dst1, uint8 *dst2, const uint8 *src, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, uint8 bitDepth) {
+ assert(bitDepth == 1);
+
Common::Rect dstRect(srcx, srcy, srcx + srcw, srcy + srch);
dstRect.clip(dstw, dsth);
@@ -263,8 +265,8 @@ void Wiz::copyAuxImage(uint8 *dst1, uint8 *dst2, const uint8 *src, int dstw, int
if (rh <= 0 || rw <= 0)
return;
- uint8 *dst1Ptr = dst1 + dstRect.left + dstRect.top * dstw;
- uint8 *dst2Ptr = dst2 + dstRect.left + dstRect.top * dstw;
+ uint8 *dst1Ptr = dst1 + dstRect.top * dstw + dstRect.left;
+ uint8 *dst2Ptr = dst2 + dstRect.top * dstw + dstRect.left;
const uint8 *dataPtr = src;
while (rh--) {
@@ -353,12 +355,24 @@ static bool calcClipRects(int dst_w, int dst_h, int src_x, int src_y, int src_w,
return srcRect.isValidRect() && dstRect.isValidRect();
}
-void Wiz::copy16BitWizImage(uint8 *dst, const uint8 *src, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int flags, const uint8 *palPtr, const uint8 *xmapPtr) {
- // TODO: Compressed 16 bits in 555 format
+void Wiz::writeColor(uint8 *dstPtr, int dstType, uint16 color) {
+ switch (dstType) {
+ case kDstScreen:
+ WRITE_UINT16(dstPtr, color);
+ break;
+ case kDstMemory:
+ case kDstResource:
+ WRITE_LE_UINT16(dstPtr, color);
+ break;
+ default:
+ error("writeColor: Unknown dstType %d", dstType);
+ }
+}
+void Wiz::copy16BitWizImage(uint8 *dst, const uint8 *src, int dstPitch, int dstType, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int flags, const uint8 *xmapPtr) {
Common::Rect r1, r2;
if (calcClipRects(dstw, dsth, srcx, srcy, srcw, srch, rect, r1, r2)) {
- dst += r2.top * dstw + r2.left;
+ dst += r2.top * dstPitch + r2.left * 2;
if (flags & kWIFFlipY) {
const int dy = (srcy < 0) ? srcy : (srch - r1.height());
r1.translate(0, dy);
@@ -368,17 +382,17 @@ void Wiz::copy16BitWizImage(uint8 *dst, const uint8 *src, int dstw, int dsth, in
r1.translate(dx, 0);
}
if (xmapPtr) {
- decompress16BitWizImage<kWizXMap>(dst, dstw, src, r1, flags, palPtr, xmapPtr);
+ decompress16BitWizImage<kWizXMap>(dst, dstPitch, dstType, src, r1, flags, xmapPtr);
} else {
- decompress16BitWizImage<kWizCopy>(dst, dstw, src, r1, flags);
+ decompress16BitWizImage<kWizCopy>(dst, dstPitch, dstType, src, r1, flags);
}
}
}
-void Wiz::copyWizImage(uint8 *dst, const uint8 *src, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int flags, const uint8 *palPtr, const uint8 *xmapPtr) {
+void Wiz::copyWizImage(uint8 *dst, const uint8 *src, int dstPitch, int dstType, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int flags, const uint8 *palPtr, const uint8 *xmapPtr, uint8 bitDepth) {
Common::Rect r1, r2;
if (calcClipRects(dstw, dsth, srcx, srcy, srcw, srch, rect, r1, r2)) {
- dst += r2.left + r2.top * dstw;
+ dst += r2.top * dstPitch + r2.left * bitDepth;
if (flags & kWIFFlipY) {
const int dy = (srcy < 0) ? srcy : (srch - r1.height());
r1.translate(0, dy);
@@ -388,11 +402,11 @@ void Wiz::copyWizImage(uint8 *dst, const uint8 *src, int dstw, int dsth, int src
r1.translate(dx, 0);
}
if (xmapPtr) {
- decompressWizImage<kWizXMap>(dst, dstw, src, r1, flags, palPtr, xmapPtr);
+ decompressWizImage<kWizXMap>(dst, dstPitch, dstType, src, r1, flags, palPtr, xmapPtr, bitDepth);
} else if (palPtr) {
- decompressWizImage<kWizRMap>(dst, dstw, src, r1, flags, palPtr);
+ decompressWizImage<kWizRMap>(dst, dstPitch, dstType, src, r1, flags, palPtr, NULL, bitDepth);
} else {
- decompressWizImage<kWizCopy>(dst, dstw, src, r1, flags);
+ decompressWizImage<kWizCopy>(dst, dstPitch, dstType, src, r1, flags, NULL, NULL, bitDepth);
}
}
}
@@ -431,13 +445,100 @@ static void decodeWizMask(uint8 *&dst, uint8 &mask, int w, int maskType) {
}
}
-void Wiz::copyWizImageWithMask(uint8 *dst, const uint8 *src, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int maskT, int maskP) {
+void Wiz::copyMaskWizImage(uint8 *dst, const uint8 *src, const uint8 *mask, int dstPitch, int dstType, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int flags, const uint8 *palPtr) {
Common::Rect srcRect, dstRect;
if (!calcClipRects(dstw, dsth, srcx, srcy, srcw, srch, rect, srcRect, dstRect)) {
return;
}
- dstw = dstw / 8;
- dst += dstRect.top * dstw + dstRect.left / 8;
+ dst += dstRect.top * dstPitch + dstRect.left * 2;
+ if (flags & kWIFFlipY) {
+ const int dy = (srcy < 0) ? srcy : (srch - srcRect.height());
+ srcRect.translate(0, dy);
+ }
+ if (flags & kWIFFlipX) {
+ const int dx = (srcx < 0) ? srcx : (srcw - srcRect.width());
+ srcRect.translate(dx, 0);
+ }
+
+ const uint8 *dataPtr, *dataPtrNext;
+ const uint8 *maskPtr, *maskPtrNext;
+ uint8 code, *dstPtr, *dstPtrNext;
+ int h, w, dstInc;
+
+ dataPtr = src;
+ dstPtr = dst;
+ maskPtr = mask;
+
+ // Skip over the first 'srcRect->top' lines in the data
+ dataPtr += dstRect.top * dstPitch + dstRect.left * 2;
+
+ h = dstRect.height();
+ w = dstRect.width();
+ if (h <= 0 || w <= 0)
+ return;
+
+ dstInc = 2;
+ if (flags & kWIFFlipX) {
+ dstPtr += (w - 1) * 2;
+ dstInc = -2;
+ }
+
+ while (h--) {
+ w = dstRect.width();
+ uint16 lineSize = READ_LE_UINT16(maskPtr); maskPtr += 2;
+ dataPtrNext = dataPtr + dstPitch;
+ dstPtrNext = dstPtr + dstPitch;
+ maskPtrNext = maskPtr + lineSize;
+ if (lineSize != 0) {
+ while (w > 0) {
+ code = *maskPtr++;
+ if (code & 1) {
+ code >>= 1;
+ dataPtr += dstInc * code;
+ dstPtr += dstInc * code;
+ w -= code;
+ } else if (code & 2) {
+ code = (code >> 2) + 1;
+ w -= code;
+ if (w < 0) {
+ code += w;
+ }
+ while (code--) {
+ if (*maskPtr != 5)
+ write16BitColor<kWizCopy>(dstPtr, dataPtr, dstType, palPtr);
+ dataPtr += 2;
+ dstPtr += dstInc;
+ }
+ maskPtr++;
+ } else {
+ code = (code >> 2) + 1;
+ w -= code;
+ if (w < 0) {
+ code += w;
+ }
+ while (code--) {
+ if (*maskPtr != 5)
+ write16BitColor<kWizCopy>(dstPtr, dataPtr, dstType, palPtr);
+ dataPtr += 2;
+ dstPtr += dstInc;
+ maskPtr++;
+ }
+ }
+ }
+ }
+ dataPtr = dataPtrNext;
+ dstPtr = dstPtrNext;
+ maskPtr = maskPtrNext;
+ }
+}
+
+void Wiz::copyWizImageWithMask(uint8 *dst, const uint8 *src, int dstPitch, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int maskT, int maskP) {
+ Common::Rect srcRect, dstRect;
+ if (!calcClipRects(dstw, dsth, srcx, srcy, srcw, srch, rect, srcRect, dstRect)) {
+ return;
+ }
+ dstPitch /= 8;
+ dst += dstRect.top * dstPitch + dstRect.left / 8;
const uint8 *dataPtr, *dataPtrNext;
uint8 code, mask, *dstPtr, *dstPtrNext;
@@ -462,7 +563,7 @@ void Wiz::copyWizImageWithMask(uint8 *dst, const uint8 *src, int dstw, int dsth,
w = srcRect.width();
mask = revBitMask(dstRect.left & 7);
off = READ_LE_UINT16(dataPtr); dataPtr += 2;
- dstPtrNext = dstPtr + dstw;
+ dstPtrNext = dstPtr + dstPitch;
dataPtrNext = dataPtr + off;
if (off != 0) {
while (w > 0) {
@@ -520,7 +621,7 @@ void Wiz::copyWizImageWithMask(uint8 *dst, const uint8 *src, int dstw, int dsth,
}
}
-void Wiz::copyRawWizImage(uint8 *dst, const uint8 *src, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int flags, const uint8 *palPtr, int transColor) {
+void Wiz::copyRawWizImage(uint8 *dst, const uint8 *src, int dstPitch, int dstType, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int flags, const uint8 *palPtr, int transColor, uint8 bitDepth) {
Common::Rect r1, r2;
if (calcClipRects(dstw, dsth, srcx, srcy, srcw, srch, rect, r1, r2)) {
if (flags & kWIFFlipX) {
@@ -537,19 +638,17 @@ void Wiz::copyRawWizImage(uint8 *dst, const uint8 *src, int dstw, int dsth, int
}
int h = r1.height();
int w = r1.width();
- src += r1.left + r1.top * srcw;
- dst += r2.left + r2.top * dstw;
+ src += r1.top * srcw + r1.left;
+ dst += r2.top * dstPitch + r2.left * bitDepth;
if (palPtr) {
- decompressRawWizImage<kWizRMap>(dst, dstw, src, srcw, w, h, transColor, palPtr);
+ decompressRawWizImage<kWizRMap>(dst, dstPitch, dstType, src, srcw, w, h, transColor, palPtr, bitDepth);
} else {
- decompressRawWizImage<kWizCopy>(dst, dstw, src, srcw, w, h, transColor);
+ decompressRawWizImage<kWizCopy>(dst, dstPitch, dstType, src, srcw, w, h, transColor, NULL, bitDepth);
}
}
}
-void Wiz::copyRaw16BitWizImage(uint8 *dst, const uint8 *src, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int flags, const uint8 *palPtr, int transColor) {
- // TODO: RAW 16 bits in 555 format
-
+void Wiz::copyRaw16BitWizImage(uint8 *dst, const uint8 *src, int dstPitch, int dstType, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int flags, int transColor) {
Common::Rect r1, r2;
if (calcClipRects(dstw, dsth, srcx, srcy, srcw, srch, rect, r1, r2)) {
if (flags & kWIFFlipX) {
@@ -567,37 +666,44 @@ void Wiz::copyRaw16BitWizImage(uint8 *dst, const uint8 *src, int dstw, int dsth,
int h = r1.height();
int w = r1.width();
src += (r1.top * srcw + r1.left) * 2;
- dst += r2.top * dstw + r2.left;
+ dst += r2.top * dstPitch + r2.left * 2;
while (h--) {
- for (int i = 0; i < w; ++i) {
+ for (int i = 0; i < w; ++ i) {
uint16 col = READ_LE_UINT16(src + 2 * i);
- uint8 r = ((col >> 10) & 0x1F) << 3;
- uint8 g = ((col >> 5) & 0x1F) << 3;
- uint8 b = ((col >> 0) & 0x1F) << 3;
- uint8 color = _vm->convert16BitColor(col, r, g, b);
-
if (transColor == -1 || transColor != col) {
- dst[i] = color;
+ writeColor(dst + i * 2, dstType, col);
}
}
src += srcw * 2;
- dst += dstw;
+ dst += dstPitch;
}
}
}
template <int type>
-void Wiz::decompress16BitWizImage(uint8 *dst, int dstPitch, const uint8 *src, const Common::Rect &srcRect, int flags, const uint8 *palPtr, const uint8 *xmapPtr) {
+void Wiz::write16BitColor(uint8 *dstPtr, const uint8 *dataPtr, int dstType, const uint8 *xmapPtr) {
+ uint16 col = READ_LE_UINT16(dataPtr);
+ if (type == kWizXMap) {
+ uint16 srcColor = (col >> 1) & 0x7DEF;
+ uint16 dstColor = (READ_UINT16(dstPtr) >> 1) & 0x7DEF;
+ uint16 newColor = srcColor + dstColor;
+ writeColor(dstPtr, dstType, newColor);
+ }
+ if (type == kWizCopy) {
+ writeColor(dstPtr, dstType, col);
+ }
+}
+
+template <int type>
+void Wiz::decompress16BitWizImage(uint8 *dst, int dstPitch, int dstType, const uint8 *src, const Common::Rect &srcRect, int flags, const uint8 *xmapPtr) {
const uint8 *dataPtr, *dataPtrNext;
- uint8 code, *dstPtr, *dstPtrNext;
+ uint8 code;
+ uint8 *dstPtr, *dstPtrNext;
int h, w, xoff, dstInc;
if (type == kWizXMap) {
assert(xmapPtr != 0);
}
- if (type == kWizRMap) {
- assert(palPtr != 0);
- }
dstPtr = dst;
dataPtr = src;
@@ -616,10 +722,10 @@ void Wiz::decompress16BitWizImage(uint8 *dst, int dstPitch, const uint8 *src, co
dstPtr += (h - 1) * dstPitch;
dstPitch = -dstPitch;
}
- dstInc = 1;
+ dstInc = 2;
if (flags & kWIFFlipX) {
- dstPtr += w - 1;
- dstInc = -1;
+ dstPtr += (w - 1) * 2;
+ dstInc = -2;
}
while (h--) {
@@ -658,21 +764,10 @@ void Wiz::decompress16BitWizImage(uint8 *dst, int dstPitch, const uint8 *src, co
code += w;
}
while (code--) {
- uint16 col = READ_LE_UINT16(dataPtr);
- uint8 r = ((col >> 10) & 0x1F) << 3;
- uint8 g = ((col >> 5) & 0x1F) << 3;
- uint8 b = ((col >> 0) & 0x1F) << 3;
- col = _vm->convert16BitColor(col, r, g, b);
-
- if (type == kWizXMap) {
- *dstPtr = xmapPtr[col * 256 + *dstPtr];
- }
- if (type == kWizCopy) {
- *dstPtr = col;
- }
+ write16BitColor<type>(dstPtr, dataPtr, dstType, xmapPtr);
dstPtr += dstInc;
}
- dataPtr+= 2;
+ dataPtr += 2;
} else {
code = (code >> 2) + 1;
if (xoff > 0) {
@@ -689,18 +784,7 @@ void Wiz::decompress16BitWizImage(uint8 *dst, int dstPitch, const uint8 *src, co
code += w;
}
while (code--) {
- uint16 col = READ_LE_UINT16(dataPtr);
- uint8 r = ((col >> 10) & 0x1F) << 3;
- uint8 g = ((col >> 5) & 0x1F) << 3;
- uint8 b = ((col >> 0) & 0x1F) << 3;
- col = _vm->convert16BitColor(col, r, g, b);
-
- if (type == kWizXMap) {
- *dstPtr = xmapPtr[col * 256 + *dstPtr];
- }
- if (type == kWizCopy) {
- *dstPtr = col;
- }
+ write16BitColor<type>(dstPtr, dataPtr, dstType, xmapPtr);
dataPtr += 2;
dstPtr += dstInc;
}
@@ -713,7 +797,36 @@ void Wiz::decompress16BitWizImage(uint8 *dst, int dstPitch, const uint8 *src, co
}
template <int type>
-void Wiz::decompressWizImage(uint8 *dst, int dstPitch, const uint8 *src, const Common::Rect &srcRect, int flags, const uint8 *palPtr, const uint8 *xmapPtr) {
+void Wiz::write8BitColor(uint8 *dstPtr, const uint8 *dataPtr, int dstType, const uint8 *palPtr, const uint8 *xmapPtr, uint8 bitDepth) {
+ if (bitDepth == 2) {
+ if (type == kWizXMap) {
+ uint16 color = READ_LE_UINT16(palPtr + *dataPtr * 2);
+ uint16 srcColor = (color >> 1) & 0x7DEF;
+ uint16 dstColor = (READ_UINT16(dstPtr) >> 1) & 0x7DEF;
+ uint16 newColor = srcColor + dstColor;
+ writeColor(dstPtr, dstType, newColor);
+ }
+ if (type == kWizRMap) {
+ writeColor(dstPtr, dstType, READ_LE_UINT16(palPtr + *dataPtr * 2));
+ }
+ if (type == kWizCopy) {
+ writeColor(dstPtr, dstType, *dataPtr);
+ }
+ } else {
+ if (type == kWizXMap) {
+ *dstPtr = xmapPtr[*dataPtr * 256 + *dstPtr];
+ }
+ if (type == kWizRMap) {
+ *dstPtr = palPtr[*dataPtr];
+ }
+ if (type == kWizCopy) {
+ *dstPtr = *dataPtr;
+ }
+ }
+}
+
+template <int type>
+void Wiz::decompressWizImage(uint8 *dst, int dstPitch, int dstType, const uint8 *src, const Common::Rect &srcRect, int flags, const uint8 *palPtr, const uint8 *xmapPtr, uint8 bitDepth) {
const uint8 *dataPtr, *dataPtrNext;
uint8 code, *dstPtr, *dstPtrNext;
int h, w, xoff, dstInc;
@@ -742,10 +855,10 @@ void Wiz::decompressWizImage(uint8 *dst, int dstPitch, const uint8 *src, const C
dstPtr += (h - 1) * dstPitch;
dstPitch = -dstPitch;
}
- dstInc = 1;
+ dstInc = bitDepth;
if (flags & kWIFFlipX) {
- dstPtr += w - 1;
- dstInc = -1;
+ dstPtr += (w - 1) * bitDepth;
+ dstInc = -bitDepth;
}
while (h--) {
@@ -784,15 +897,7 @@ void Wiz::decompressWizImage(uint8 *dst, int dstPitch, const uint8 *src, const C
code += w;
}
while (code--) {
- if (type == kWizXMap) {
- *dstPtr = xmapPtr[*dataPtr * 256 + *dstPtr];
- }
- if (type == kWizRMap) {
- *dstPtr = palPtr[*dataPtr];
- }
- if (type == kWizCopy) {
- *dstPtr = *dataPtr;
- }
+ write8BitColor<type>(dstPtr, dataPtr, dstType, palPtr, xmapPtr, bitDepth);
dstPtr += dstInc;
}
dataPtr++;
@@ -812,15 +917,8 @@ void Wiz::decompressWizImage(uint8 *dst, int dstPitch, const uint8 *src, const C
code += w;
}
while (code--) {
- if (type == kWizXMap) {
- *dstPtr = xmapPtr[*dataPtr++ * 256 + *dstPtr];
- }
- if (type == kWizRMap) {
- *dstPtr = palPtr[*dataPtr++];
- }
- if (type == kWizCopy) {
- *dstPtr = *dataPtr++;
- }
+ write8BitColor<type>(dstPtr, dataPtr, dstType, palPtr, xmapPtr, bitDepth);
+ dataPtr++;
dstPtr += dstInc;
}
}
@@ -832,12 +930,12 @@ void Wiz::decompressWizImage(uint8 *dst, int dstPitch, const uint8 *src, const C
}
// NOTE: These templates are used outside this file. We don't want the compiler to optimize them away, so we need to explicitely instantiate them.
-template void Wiz::decompressWizImage<kWizXMap>(uint8 *dst, int dstPitch, const uint8 *src, const Common::Rect &srcRect, int flags, const uint8 *palPtr, const uint8 *xmapPtr);
-template void Wiz::decompressWizImage<kWizRMap>(uint8 *dst, int dstPitch, const uint8 *src, const Common::Rect &srcRect, int flags, const uint8 *palPtr, const uint8 *xmapPtr);
-template void Wiz::decompressWizImage<kWizCopy>(uint8 *dst, int dstPitch, const uint8 *src, const Common::Rect &srcRect, int flags, const uint8 *palPtr, const uint8 *xmapPtr);
+template void Wiz::decompressWizImage<kWizXMap>(uint8 *dst, int dstPitch, int dstType, const uint8 *src, const Common::Rect &srcRect, int flags, const uint8 *palPtr, const uint8 *xmapPtr, uint8 bitDepth);
+template void Wiz::decompressWizImage<kWizRMap>(uint8 *dst, int dstPitch, int dstType, const uint8 *src, const Common::Rect &srcRect, int flags, const uint8 *palPtr, const uint8 *xmapPtr, uint8 bitDepth);
+template void Wiz::decompressWizImage<kWizCopy>(uint8 *dst, int dstPitch, int dstType, const uint8 *src, const Common::Rect &srcRect, int flags, const uint8 *palPtr, const uint8 *xmapPtr, uint8 bitDepth);
template <int type>
-void Wiz::decompressRawWizImage(uint8 *dst, int dstPitch, const uint8 *src, int srcPitch, int w, int h, int transColor, const uint8 *palPtr) {
+void Wiz::decompressRawWizImage(uint8 *dst, int dstPitch, int dstType, const uint8 *src, int srcPitch, int w, int h, int transColor, const uint8 *palPtr, uint8 bitDepth) {
if (type == kWizRMap) {
assert(palPtr != 0);
}
@@ -850,10 +948,18 @@ void Wiz::decompressRawWizImage(uint8 *dst, int dstPitch, const uint8 *src, int
uint8 col = src[i];
if (transColor == -1 || transColor != col) {
if (type == kWizRMap) {
- dst[i] = palPtr[col];
+ if (bitDepth == 2) {
+ writeColor(dst + i * 2, dstType, READ_LE_UINT16(palPtr + col * 2));
+ } else {
+ dst[i] = palPtr[col];
+ }
}
if (type == kWizCopy) {
- dst[i] = col;
+ if (bitDepth == 2) {
+ writeColor(dst + i * 2, dstType, col);
+ } else {
+ dst[i] = col;
+ }
}
}
}
@@ -943,7 +1049,7 @@ uint16 Wiz::getWizPixelColor(const uint8 *data, int x, int y, int w, int h, uint
}
if (bitDepth == 2)
- return (READ_LE_UINT16(data) & 1) ? color : READ_LE_UINT16(data + 1);
+ return (READ_LE_UINT16(data) & 1) ? color : READ_LE_UINT16(data + 2);
else
return (data[0] & 1) ? color : data[1];
@@ -954,7 +1060,7 @@ uint16 Wiz::getRawWizPixelColor(const uint8 *data, int x, int y, int w, int h, u
return color;
}
if (bitDepth == 2)
- return READ_LE_UINT16(data + y * w + x * 2);
+ return READ_LE_UINT16(data + (y * w + x) * 2);
else
return data[y * w + x];
}
@@ -1043,6 +1149,23 @@ void Wiz::computeRawWizHistogram(uint32 *histogram, const uint8 *data, int srcPi
}
}
+static int wizPackType2(uint8 *dst, const uint8 *src, int srcPitch, const Common::Rect& rCapt) {
+ debug(9, "wizPackType2([%d,%d,%d,%d])", rCapt.left, rCapt.top, rCapt.right, rCapt.bottom);
+ int w = rCapt.width();
+ int h = rCapt.height();
+ int size = w * h * 2;
+ if (dst) {
+ src += rCapt.top * srcPitch + rCapt.left * 2;
+ while (h--) {
+ for (int i = 0; i < w; i++)
+ WRITE_LE_UINT16(dst + i * 2, READ_UINT16(src + i * 2));
+ dst += w * 2;
+ src += srcPitch;
+ }
+ }
+ return size;
+}
+
static int wizPackType1(uint8 *dst, const uint8 *src, int srcPitch, const Common::Rect& rCapt, uint8 transColor) {
debug(9, "wizPackType1(%d, [%d,%d,%d,%d])", transColor, rCapt.left, rCapt.top, rCapt.right, rCapt.bottom);
src += rCapt.top * srcPitch + rCapt.left;
@@ -1179,7 +1302,6 @@ static int wizPackType0(uint8 *dst, const uint8 *src, int srcPitch, const Common
}
void Wiz::captureWizImage(int resNum, const Common::Rect& r, bool backBuffer, int compType) {
- debug(5, "ScummEngine_v72he::captureWizImage(%d, %d, [%d,%d,%d,%d])", resNum, compType, r.left, r.top, r.right, r.bottom);
uint8 *src = NULL;
VirtScreen *pvs = &_vm->_virtscr[kMainVirtScreen];
if (backBuffer) {
@@ -1187,12 +1309,17 @@ void Wiz::captureWizImage(int resNum, const Common::Rect& r, bool backBuffer, in
} else {
src = pvs->getPixels(0, 0);
}
- Common::Rect rCapt(pvs->w, pvs->h);
+ captureImage(src, pvs->pitch, pvs->w, pvs->h, resNum, r, compType);
+}
+
+void Wiz::captureImage(uint8 *src, int srcPitch, int srcw, int srch, int resNum, const Common::Rect& r, int compType) {
+ debug(0, "captureImage(%d, %d, [%d,%d,%d,%d])", resNum, compType, r.left, r.top, r.right, r.bottom);
+ Common::Rect rCapt(srcw, srch);
if (rCapt.intersects(r)) {
rCapt.clip(r);
const uint8 *palPtr;
if (_vm->_game.heversion >= 99) {
- palPtr = _vm->_hePalettes + 1024;
+ palPtr = _vm->_hePalettes + _vm->_hePaletteSlot;
} else {
palPtr = _vm->_currentPalette;
}
@@ -1201,15 +1328,21 @@ void Wiz::captureWizImage(int resNum, const Common::Rect& r, bool backBuffer, in
int h = rCapt.height();
int transColor = (_vm->VAR_WIZ_TCOLOR != 0xFF) ? _vm->VAR(_vm->VAR_WIZ_TCOLOR) : 5;
+ if (_vm->_game.features & GF_16BIT_COLOR)
+ compType = 2;
+
// compute compressed size
int dataSize = 0;
int headerSize = palPtr ? 1080 : 36;
switch (compType) {
case 0:
- dataSize = wizPackType0(0, src, pvs->pitch, rCapt);
+ dataSize = wizPackType0(0, src, srcPitch, rCapt);
break;
case 1:
- dataSize = wizPackType1(0, src, pvs->pitch, rCapt, transColor);
+ dataSize = wizPackType1(0, src, srcPitch, rCapt, transColor);
+ break;
+ case 2:
+ dataSize = wizPackType2(0, src, srcPitch, rCapt);
break;
default:
error("unhandled compression type %d", compType);
@@ -1249,10 +1382,13 @@ void Wiz::captureWizImage(int resNum, const Common::Rect& r, bool backBuffer, in
// write compressed data
switch (compType) {
case 0:
- wizPackType0(wizImg + headerSize, src, pvs->pitch, rCapt);
+ wizPackType0(wizImg + headerSize, src, srcPitch, rCapt);
break;
case 1:
- wizPackType1(wizImg + headerSize, src, pvs->pitch, rCapt, transColor);
+ wizPackType1(wizImg + headerSize, src, srcPitch, rCapt, transColor);
+ break;
+ case 2:
+ wizPackType2(wizImg + headerSize, src, srcPitch, rCapt);
break;
default:
break;
@@ -1279,24 +1415,15 @@ void Wiz::displayWizImage(WizImage *pwi) {
drawWizPolygon(pwi->resNum, pwi->state, pwi->x1, pwi->flags, 0, 0, 0);
} else {
const Common::Rect *r = NULL;
- drawWizImage(pwi->resNum, pwi->state, pwi->x1, pwi->y1, 0, 0, 0, r, pwi->flags, 0, 0);
+ drawWizImage(pwi->resNum, pwi->state, 0, 0, pwi->x1, pwi->y1, 0, 0, 0, r, pwi->flags, 0, _vm->getHEPaletteSlot(0));
}
}
-uint8 *Wiz::drawWizImage(int resNum, int state, int x1, int y1, int zorder, int shadow, int field_390, const Common::Rect *clipBox, int flags, int dstResNum, int palette) {
- debug(3, "drawWizImage(resNum %d, x1 %d y1 %d flags 0x%X zorder %d shadow %d field_390 %d dstResNum %d palette %d)", resNum, x1, y1, flags, zorder, shadow, field_390, dstResNum, palette);
+uint8 *Wiz::drawWizImage(int resNum, int state, int maskNum, int maskState, int x1, int y1, int zorder, int shadow, int field_390, const Common::Rect *clipBox, int flags, int dstResNum, const uint8 *palPtr) {
+ debug(3, "drawWizImage(resNum %d, state %d maskNum %d maskState %d x1 %d y1 %d flags 0x%X zorder %d shadow %d field_390 %d dstResNum %d)", resNum, state, maskNum, maskState, x1, y1, flags, zorder, shadow, field_390, dstResNum);
uint8 *dataPtr;
uint8 *dst = NULL;
- const uint8 *palPtr = NULL;
- if (_vm->_game.heversion >= 99) {
- if (palette) {
- palPtr = _vm->_hePalettes + palette * 1024 + 768;
- } else {
- palPtr = _vm->_hePalettes + 1792;
- }
- }
-
const uint8 *xmapPtr = NULL;
if (shadow) {
dataPtr = _vm->getResourceAddress(rtImage, shadow);
@@ -1318,6 +1445,21 @@ uint8 *Wiz::drawWizImage(int resNum, int state, int x1, int y1, int zorder, int
uint8 *wizd = _vm->findWrappedBlock(MKID_BE('WIZD'), dataPtr, state, 0);
assert(wizd);
+ uint8 *mask = NULL;
+ if (maskNum) {
+ uint8 *maskPtr = _vm->getResourceAddress(rtImage, maskNum);
+ assert(maskPtr);
+
+ wizh = _vm->findWrappedBlock(MKID_BE('WIZH'), maskPtr, maskState, 0);
+ assert(wizh);
+ assert(comp == 2 && READ_LE_UINT32(wizh + 0x0) == 1);
+ width = READ_LE_UINT32(wizh + 0x4);
+ height = READ_LE_UINT32(wizh + 0x8);
+
+ mask = _vm->findWrappedBlock(MKID_BE('WIZD'), maskPtr, maskState, 0);
+ assert(mask);
+ }
+
if (flags & kWIFHasPalette) {
uint8 *pal = _vm->findWrappedBlock(MKID_BE('RGBS'), dataPtr, state, 0);
assert(pal);
@@ -1339,13 +1481,25 @@ uint8 *Wiz::drawWizImage(int resNum, int state, int x1, int y1, int zorder, int
error("WizImage printing is unimplemented");
}
- int32 cw, ch;
+ int32 dstPitch, dstType, cw, ch;
if (flags & kWIFBlitToMemBuffer) {
- dst = (uint8 *)malloc(width * height);
+ dst = (uint8 *)malloc(width * height * _vm->_bitDepth);
int transColor = (_vm->VAR_WIZ_TCOLOR != 0xFF) ? (_vm->VAR(_vm->VAR_WIZ_TCOLOR)) : 5;
- memset(dst, transColor, width * height);
+
+ if (_vm->_bitDepth == 2) {
+ uint8 *tmpPtr = dst;
+ for (uint i = 0; i < height; i++) {
+ for (uint j = 0; j < width; j++)
+ WRITE_LE_UINT16(tmpPtr + j * 2, transColor);
+ tmpPtr += width * 2;
+ }
+ } else {
+ memset(dst, transColor, width * height);
+ }
cw = width;
ch = height;
+ dstPitch = cw * _vm->_bitDepth;
+ dstType = kDstMemory;
} else {
if (dstResNum) {
uint8 *dstPtr = _vm->getResourceAddress(rtImage, dstResNum);
@@ -1353,6 +1507,8 @@ uint8 *Wiz::drawWizImage(int resNum, int state, int x1, int y1, int zorder, int
dst = _vm->findWrappedBlock(MKID_BE('WIZD'), dstPtr, 0, 0);
assert(dst);
getWizImageDim(dstResNum, 0, cw, ch);
+ dstPitch = cw * _vm->_bitDepth;
+ dstType = kDstResource;
} else {
VirtScreen *pvs = &_vm->_virtscr[kMainVirtScreen];
if (flags & kWIFMarkBufferDirty) {
@@ -1362,6 +1518,8 @@ uint8 *Wiz::drawWizImage(int resNum, int state, int x1, int y1, int zorder, int
}
cw = pvs->w;
ch = pvs->h;
+ dstPitch = pvs->pitch;
+ dstType = kDstScreen;
}
}
@@ -1381,7 +1539,7 @@ uint8 *Wiz::drawWizImage(int resNum, int state, int x1, int y1, int zorder, int
}
}
- if (flags & kWIFRemapPalette) {
+ if (flags & kWIFRemapPalette && _vm->_bitDepth == 1) {
palPtr = rmap + 4;
}
@@ -1393,28 +1551,33 @@ uint8 *Wiz::drawWizImage(int resNum, int state, int x1, int y1, int zorder, int
switch (comp) {
case 0:
- copyRawWizImage(dst, wizd, cw, ch, x1, y1, width, height, &rScreen, flags, palPtr, transColor);
+ copyRawWizImage(dst, wizd, dstPitch, dstType, cw, ch, x1, y1, width, height, &rScreen, flags, palPtr, transColor, _vm->_bitDepth);
break;
case 1:
if (flags & 0x80) {
dst = _vm->getMaskBuffer(0, 0, 1);
- copyWizImageWithMask(dst, wizd, cw, ch, x1, y1, width, height, &rScreen, 0, 2);
+ dstPitch /= _vm->_bitDepth;
+ copyWizImageWithMask(dst, wizd, dstPitch, cw, ch, x1, y1, width, height, &rScreen, 0, 2);
} else if (flags & 0x100) {
dst = _vm->getMaskBuffer(0, 0, 1);
- copyWizImageWithMask(dst, wizd, cw, ch, x1, y1, width, height, &rScreen, 0, 1);
+ dstPitch /= _vm->_bitDepth;
+ copyWizImageWithMask(dst, wizd, dstPitch, cw, ch, x1, y1, width, height, &rScreen, 0, 1);
} else {
- copyWizImage(dst, wizd, cw, ch, x1, y1, width, height, &rScreen, flags, palPtr, xmapPtr);
+ copyWizImage(dst, wizd, dstPitch, dstType, cw, ch, x1, y1, width, height, &rScreen, flags, palPtr, xmapPtr, _vm->_bitDepth);
}
break;
case 2:
- copyRaw16BitWizImage(dst, wizd, cw, ch, x1, y1, width, height, &rScreen, flags, palPtr, transColor);
+ if (maskNum) {
+ copyMaskWizImage(dst, wizd, mask, dstPitch, dstType, cw, ch, x1, y1, width, height, &rScreen, flags, palPtr);
+ } else {
+ copyRaw16BitWizImage(dst, wizd, dstPitch, dstType, cw, ch, x1, y1, width, height, &rScreen, flags, transColor);
+ }
break;
case 4:
// TODO: Unknown image type
break;
case 5:
- // TODO: 16bit color compressed image
- copy16BitWizImage(dst, wizd, cw, ch, x1, y1, width, height, &rScreen, flags, palPtr, xmapPtr);
+ copy16BitWizImage(dst, wizd, dstPitch, dstType, cw, ch, x1, y1, width, height, &rScreen, flags, xmapPtr);
break;
default:
error("drawWizImage: Unhandled wiz compression type %d", comp);
@@ -1517,6 +1680,74 @@ struct PolygonDrawData {
}
};
+void Wiz::captureWizPolygon(int resNum, int maskNum, int maskState, int id1, int id2, int compType) {
+ debug(0, "captureWizPolygon: resNum %d, maskNum %d maskState %d, id1 %d id2 %d compType %d", resNum, maskNum, maskState, id1, id2, compType);
+
+ int i, j;
+ WizPolygon *wp;
+
+ wp = NULL;
+ for (i = 0; i < ARRAYSIZE(_polygons); ++i) {
+ if (_polygons[i].id == id1) {
+ wp = &_polygons[i];
+ break;
+ }
+ }
+ if (!wp) {
+ error("Polygon1 %d is not defined", id1);
+ }
+ if (wp->numVerts != 5) {
+ error("Invalid point count %d for Polygon1 %d", wp->numVerts, id1);
+ }
+
+ wp = NULL;
+ for (i = 0; i < ARRAYSIZE(_polygons); ++i) {
+ if (_polygons[i].id == id2) {
+ wp = &_polygons[i];
+ break;
+ }
+ }
+ if (!wp) {
+ error("Polygon2 %d is not defined", id2);
+ }
+ if (wp->numVerts != 5) {
+ error("Invalid point count %d for Polygon2 %d", wp->numVerts, id2);
+ }
+
+ int32 dstw, dsth, dstpitch;
+ int32 srcw, srch;
+ uint8 *imageBuffer;
+
+ assert(maskNum);
+ const Common::Rect *r = NULL;
+ const uint8 *src = drawWizImage(maskNum, maskState, 0, 0, 0, 0, 0, 0, 0, r, kWIFBlitToMemBuffer, 0, 0);
+ getWizImageDim(maskNum, maskState, srcw, srch);
+
+ dstw = wp->bound.width();
+ dsth = wp->bound.height();
+ dstpitch = dstw * _vm->_bitDepth;
+ imageBuffer = (uint8 *)malloc(dstw * dsth * _vm->_bitDepth);
+ assert(imageBuffer);
+
+ const uint16 transColor = (_vm->VAR_WIZ_TCOLOR != 0xFF) ? _vm->VAR(_vm->VAR_WIZ_TCOLOR) : 5;
+ if (_vm->_bitDepth == 2) {
+ uint8 *tmpPtr = imageBuffer;
+ for (i = 0; i < dsth; i++) {
+ for (j = 0; j < dstw; j++)
+ WRITE_LE_UINT16(tmpPtr + j * 2, transColor);
+ tmpPtr += dstpitch;
+ }
+ } else {
+ memset(imageBuffer, transColor, dstw * dsth);
+ }
+
+ Common::Rect bound;
+ drawWizPolygonImage(imageBuffer, src, NULL, dstpitch, kDstMemory, dstw, dsth, srcw, srch, bound, wp->vert, _vm->_bitDepth);
+
+ captureImage(imageBuffer, dstpitch, dstw, dsth, resNum, wp->bound, compType);
+ free(imageBuffer);
+}
+
void Wiz::drawWizComplexPolygon(int resNum, int state, int po_x, int po_y, int shadow, int angle, int scale, const Common::Rect *r, int flags, int dstResNum, int palette) {
Common::Point pts[4];
@@ -1544,11 +1775,10 @@ void Wiz::drawWizPolygon(int resNum, int state, int id, int flags, int shadow, i
}
void Wiz::drawWizPolygonTransform(int resNum, int state, Common::Point *wp, int flags, int shadow, int dstResNum, int palette) {
- debug(3, "drawWizPolygonTransform(resNum %d, flags 0x%X, shadow %d dstResNum %d palette %d)", resNum, flags, shadow, dstResNum, palette);
+ debug(0, "drawWizPolygonTransform(resNum %d, flags 0x%X, shadow %d dstResNum %d palette %d)", resNum, flags, shadow, dstResNum, palette);
const Common::Rect *r = NULL;
uint8 *srcWizBuf = NULL;
bool freeBuffer = true;
- int i;
if (_vm->_game.heversion >= 99) {
if (getWizImageData(resNum, state, 0) != 0 || (flags & (kWIFRemapPalette | kWIFFlipX | kWIFFlipY)) || palette != 0) {
@@ -1557,8 +1787,10 @@ void Wiz::drawWizPolygonTransform(int resNum, int state, Common::Point *wp, int
if (flags & 0x800000) {
debug(0, "drawWizPolygonTransform() unhandled flag 0x800000");
}
- srcWizBuf = drawWizImage(resNum, state, 0, 0, 0, shadow, 0, r, flags, 0, palette);
+
+ srcWizBuf = drawWizImage(resNum, state, 0, 0, 0, 0, 0, shadow, 0, r, flags, 0, _vm->getHEPaletteSlot(palette));
} else {
+ assert(_vm->_bitDepth == 1);
uint8 *dataPtr = _vm->getResourceAddress(rtImage, resNum);
assert(dataPtr);
srcWizBuf = _vm->findWrappedBlock(MKID_BE('WIZD'), dataPtr, state, 0);
@@ -1567,7 +1799,7 @@ void Wiz::drawWizPolygonTransform(int resNum, int state, Common::Point *wp, int
}
} else {
if (getWizImageData(resNum, state, 0) != 0) {
- srcWizBuf = drawWizImage(resNum, state, 0, 0, 0, shadow, 0, r, kWIFBlitToMemBuffer, 0, palette);
+ srcWizBuf = drawWizImage(resNum, state, 0, 0, 0, 0, 0, shadow, 0, r, kWIFBlitToMemBuffer, 0, _vm->getHEPaletteSlot(palette));
} else {
uint8 *dataPtr = _vm->getResourceAddress(rtImage, resNum);
assert(dataPtr);
@@ -1577,146 +1809,163 @@ void Wiz::drawWizPolygonTransform(int resNum, int state, Common::Point *wp, int
}
}
- if (srcWizBuf) {
- uint8 *dst;
- int32 dstw, dsth, dstpitch, wizW, wizH;
- VirtScreen *pvs = &_vm->_virtscr[kMainVirtScreen];
- int transColor = (_vm->VAR_WIZ_TCOLOR != 0xFF) ? _vm->VAR(_vm->VAR_WIZ_TCOLOR) : 5;
+ assert(srcWizBuf);
- if (dstResNum) {
- uint8 *dstPtr = _vm->getResourceAddress(rtImage, dstResNum);
- assert(dstPtr);
- dst = _vm->findWrappedBlock(MKID_BE('WIZD'), dstPtr, 0, 0);
- assert(dst);
- getWizImageDim(dstResNum, 0, dstw, dsth);
- dstpitch = dstw;
+ uint8 *dst;
+ int32 dstw, dsth, dstpitch, dstType, wizW, wizH;
+ VirtScreen *pvs = &_vm->_virtscr[kMainVirtScreen];
+
+ if (dstResNum) {
+ uint8 *dstPtr = _vm->getResourceAddress(rtImage, dstResNum);
+ assert(dstPtr);
+ dst = _vm->findWrappedBlock(MKID_BE('WIZD'), dstPtr, 0, 0);
+ assert(dst);
+ getWizImageDim(dstResNum, 0, dstw, dsth);
+ dstpitch = dstw * _vm->_bitDepth;
+ dstType = kDstResource;
+ } else {
+ if (flags & kWIFMarkBufferDirty) {
+ dst = pvs->getPixels(0, 0);
} else {
- if (flags & kWIFMarkBufferDirty) {
- dst = pvs->getPixels(0, 0);
- } else {
- dst = pvs->getBackPixels(0, 0);
+ dst = pvs->getBackPixels(0, 0);
+ }
+ dstw = pvs->w;
+ dsth = pvs->h;
+ dstpitch = pvs->pitch;
+ dstType = kDstScreen;
+ }
+
+ Common::Rect bound;
+ getWizImageDim(resNum, state, wizW, wizH);
+ drawWizPolygonImage(dst, srcWizBuf, 0, dstpitch, dstType, dstw, dsth, wizW, wizH, bound, wp, _vm->_bitDepth);
+
+ if (flags & kWIFMarkBufferDirty) {
+ _vm->markRectAsDirty(kMainVirtScreen, bound);
+ } else {
+ _vm->restoreBackgroundHE(bound);
+ }
+
+ if (freeBuffer)
+ free(srcWizBuf);
+}
+
+void Wiz::drawWizPolygonImage(uint8 *dst, const uint8 *src, const uint8 *mask, int dstpitch, int dstType, int dstw, int dsth, int wizW, int wizH, Common::Rect &bound, Common::Point *wp, uint8 bitDepth) {
+ int i, transColor = (_vm->VAR_WIZ_TCOLOR != 0xFF) ? _vm->VAR(_vm->VAR_WIZ_TCOLOR) : 5;
+
+ Common::Point bbox[4];
+ bbox[0].x = 0;
+ bbox[0].y = 0;
+ bbox[1].x = wizW - 1;
+ bbox[1].y = 0;
+ bbox[2].x = wizW - 1;
+ bbox[2].y = wizH - 1;
+ bbox[3].x = 0;
+ bbox[3].y = wizH - 1;
+
+ int16 xmin_p, xmax_p, ymin_p, ymax_p;
+ xmin_p = ymin_p = (int16)0x7FFF;
+ xmax_p = ymax_p = (int16)0x8000;
+
+ for (i = 0; i < 4; ++i) {
+ xmin_p = MIN(wp[i].x, xmin_p);
+ xmax_p = MAX(wp[i].x, xmax_p);
+ ymin_p = MIN(wp[i].y, ymin_p);
+ ymax_p = MAX(wp[i].y, ymax_p);
+ }
+
+ int16 xmin_b, xmax_b, ymin_b, ymax_b;
+ xmin_b = ymin_b = (int16)0x7FFF;
+ xmax_b = ymax_b = (int16)0x8000;
+
+ for (i = 0; i < 4; ++i) {
+ xmin_b = MIN(bbox[i].x, xmin_b);
+ xmax_b = MAX(bbox[i].x, xmax_b);
+ ymin_b = MIN(bbox[i].y, ymin_b);
+ ymax_b = MAX(bbox[i].y, ymax_b);
+ }
+
+ PolygonDrawData pdd(ymax_p - ymin_p + 1);
+ pdd.mat[0].x = xmin_p;
+ pdd.mat[0].y = ymin_p;
+ pdd.mat[1].x = xmax_p;
+ pdd.mat[1].y = ymax_p;
+ pdd.mat[2].x = xmin_b;
+ pdd.mat[2].y = ymin_b;
+ pdd.mat[3].x = xmax_b;
+ pdd.mat[3].y = ymax_b;
+
+ // precompute the transformation which remaps 'bbox' pixels to 'wp'
+ for (i = 0; i < 3; ++i) {
+ pdd.transform(&wp[i], &wp[i + 1], &bbox[i], &bbox[i + 1]);
+ }
+ pdd.transform(&wp[3], &wp[0], &bbox[3], &bbox[0]);
+
+ pdd.rAreasNum = 0;
+ PolygonDrawData::ResultArea *pra = &pdd.ra[0];
+ int32 yoff = pdd.mat[0].y * dstpitch;
+ int16 y_start = pdd.mat[0].y;
+ for (i = 0; i < pdd.pAreasNum; ++i) {
+ PolygonDrawData::PolygonArea *ppa = &pdd.pa[i];
+ if (y_start >= 0 && y_start < dsth) {
+ int16 x1 = ppa->xmin;
+ if (x1 < 0) {
+ x1 = 0;
}
- dstw = pvs->w;
- dsth = pvs->h;
- dstpitch = pvs->pitch;
- }
-
- getWizImageDim(resNum, state, wizW, wizH);
-
- Common::Point bbox[4];
- bbox[0].x = 0;
- bbox[0].y = 0;
- bbox[1].x = wizW - 1;
- bbox[1].y = 0;
- bbox[2].x = wizW - 1;
- bbox[2].y = wizH - 1;
- bbox[3].x = 0;
- bbox[3].y = wizH - 1;
-
- int16 xmin_p, xmax_p, ymin_p, ymax_p;
- xmin_p = ymin_p = (int16)0x7FFF;
- xmax_p = ymax_p = (int16)0x8000;
-
- for (i = 0; i < 4; ++i) {
- xmin_p = MIN(wp[i].x, xmin_p);
- xmax_p = MAX(wp[i].x, xmax_p);
- ymin_p = MIN(wp[i].y, ymin_p);
- ymax_p = MAX(wp[i].y, ymax_p);
- }
-
- int16 xmin_b, xmax_b, ymin_b, ymax_b;
- xmin_b = ymin_b = (int16)0x7FFF;
- xmax_b = ymax_b = (int16)0x8000;
-
- for (i = 0; i < 4; ++i) {
- xmin_b = MIN(bbox[i].x, xmin_b);
- xmax_b = MAX(bbox[i].x, xmax_b);
- ymin_b = MIN(bbox[i].y, ymin_b);
- ymax_b = MAX(bbox[i].y, ymax_b);
- }
-
- PolygonDrawData pdd(ymax_p - ymin_p + 1);
- pdd.mat[0].x = xmin_p;
- pdd.mat[0].y = ymin_p;
- pdd.mat[1].x = xmax_p;
- pdd.mat[1].y = ymax_p;
- pdd.mat[2].x = xmin_b;
- pdd.mat[2].y = ymin_b;
- pdd.mat[3].x = xmax_b;
- pdd.mat[3].y = ymax_b;
-
- // precompute the transformation which remaps 'bbox' pixels to 'wp'
- for (i = 0; i < 3; ++i) {
- pdd.transform(&wp[i], &wp[i + 1], &bbox[i], &bbox[i + 1]);
- }
- pdd.transform(&wp[3], &wp[0], &bbox[3], &bbox[0]);
-
- pdd.rAreasNum = 0;
- PolygonDrawData::ResultArea *pra = &pdd.ra[0];
- int32 yoff = pdd.mat[0].y * dstpitch;
- int16 y_start = pdd.mat[0].y;
- for (i = 0; i < pdd.pAreasNum; ++i) {
- PolygonDrawData::PolygonArea *ppa = &pdd.pa[i];
- if (y_start >= 0 && y_start < dsth) {
- int16 x1 = ppa->xmin;
- if (x1 < 0) {
- x1 = 0;
- }
- int16 x2 = ppa->xmax;
- if (x2 >= dstw) {
- x2 = dstw - 1;
- }
- int16 w = x2 - x1 + 1;
- if (w > 0) {
- int16 width = ppa->xmax - ppa->xmin + 1;
- pra->x_step = ((ppa->x2 - ppa->x1) << 16) / width;
- pra->y_step = ((ppa->y2 - ppa->y1) << 16) / width;
- pra->dst_offs = yoff + x1;
- pra->w = w;
- pra->x_s = ppa->x1 << 16;
- pra->y_s = ppa->y1 << 16;
- int16 tmp = x1 - ppa->xmin;
- if (tmp != 0) {
- pra->x_s += pra->x_step * tmp;
- pra->y_s += pra->y_step * tmp;
- }
- ++pra;
- ++pdd.rAreasNum;
- }
+ int16 x2 = ppa->xmax;
+ if (x2 >= dstw) {
+ x2 = dstw - 1;
}
- ++ppa;
- yoff += dstpitch;
- ++y_start;
- }
-
- pra = &pdd.ra[0];
- for (i = 0; i < pdd.rAreasNum; ++i, ++pra) {
- uint8 *dstPtr = dst + pra->dst_offs;
- int32 w = pra->w;
- int32 x_acc = pra->x_s;
- int32 y_acc = pra->y_s;
- while (--w) {
- int32 src_offs = (y_acc >> 16) * wizW + (x_acc >> 16);
- assert(src_offs < wizW * wizH);
- x_acc += pra->x_step;
- y_acc += pra->y_step;
- if (transColor == -1 || transColor != srcWizBuf[src_offs]) {
- *dstPtr = srcWizBuf[src_offs];
+ int16 w = x2 - x1 + 1;
+ if (w > 0) {
+ int16 width = ppa->xmax - ppa->xmin + 1;
+ pra->x_step = ((ppa->x2 - ppa->x1) << 16) / width;
+ pra->y_step = ((ppa->y2 - ppa->y1) << 16) / width;
+ pra->dst_offs = yoff + x1 * _vm->_bitDepth;
+ pra->w = w;
+ pra->x_s = ppa->x1 << 16;
+ pra->y_s = ppa->y1 << 16;
+ int16 tmp = x1 - ppa->xmin;
+ if (tmp != 0) {
+ pra->x_s += pra->x_step * tmp;
+ pra->y_s += pra->y_step * tmp;
}
- dstPtr++;
+ ++pra;
+ ++pdd.rAreasNum;
}
}
-
- Common::Rect bound(xmin_p, ymin_p, xmax_p + 1, ymax_p + 1);
- if (flags & kWIFMarkBufferDirty) {
- _vm->markRectAsDirty(kMainVirtScreen, bound);
- } else {
- _vm->restoreBackgroundHE(bound);
+ ++ppa;
+ yoff += dstpitch;
+ ++y_start;
+ }
+
+ pra = &pdd.ra[0];
+ for (i = 0; i < pdd.rAreasNum; ++i, ++pra) {
+ uint8 *dstPtr = dst + pra->dst_offs;
+ int32 w = pra->w;
+ int32 x_acc = pra->x_s;
+ int32 y_acc = pra->y_s;
+ while (--w) {
+ int32 src_offs = (y_acc >> 16) * wizW + (x_acc >> 16);
+ assert(src_offs < wizW * wizH);
+ x_acc += pra->x_step;
+ y_acc += pra->y_step;
+ if (bitDepth == 2) {
+ if (transColor == -1 || transColor != READ_LE_UINT16(src + src_offs * 2)) {
+ //if (transColor == -1 || READ_LE_UINT16(dstPtr) != transColor)
+ writeColor(dstPtr, dstType, READ_LE_UINT16(src + src_offs * 2));
+ }
+ } else {
+ if (transColor == -1 || transColor != src[src_offs])
+ *dstPtr = src[src_offs];
+ }
+ dstPtr += bitDepth;
}
-
- if (freeBuffer)
- free(srcWizBuf);
}
+
+ bound.left = xmin_p;
+ bound.top = ymin_p;
+ bound.right = xmax_p + 1;
+ bound.bottom = ymax_p + 1;
}
void Wiz::flushWizBuffer() {
@@ -1726,13 +1975,13 @@ void Wiz::flushWizBuffer() {
drawWizPolygon(pwi->resNum, pwi->state, pwi->x1, pwi->flags, pwi->shadow, 0, pwi->palette);
} else {
const Common::Rect *r = NULL;
- drawWizImage(pwi->resNum, pwi->state, pwi->x1, pwi->y1, pwi->zorder, pwi->shadow, pwi->field_390, r, pwi->flags, 0, pwi->palette);
+ drawWizImage(pwi->resNum, pwi->state, 0, 0, pwi->x1, pwi->y1, pwi->zorder, pwi->shadow, pwi->field_390, r, pwi->flags, 0, _vm->getHEPaletteSlot(pwi->palette));
}
}
_imagesNum = 0;
}
-void Wiz::loadWizCursor(int resId) {
+void Wiz::loadWizCursor(int resId, int palette) {
int32 x, y;
getWizImageSpot(resId, 0, x, y);
if (x < 0) {
@@ -1747,11 +1996,12 @@ void Wiz::loadWizCursor(int resId) {
}
const Common::Rect *r = NULL;
- uint8 *cursor = drawWizImage(resId, 0, 0, 0, 0, 0, 0, r, kWIFBlitToMemBuffer, 0, 0);
+ uint8 *cursor = drawWizImage(resId, 0, 0, 0, 0, 0, 0, 0, 0, r, kWIFBlitToMemBuffer, 0, _vm->getHEPaletteSlot(palette));
+
int32 cw, ch;
getWizImageDim(resId, 0, cw, ch);
_vm->setCursorHotspot(x, y);
- _vm->setCursorFromBuffer(cursor, cw, ch, cw);
+ _vm->setCursorFromBuffer(cursor, cw, ch, cw * _vm->_bitDepth);
// Since we set up cursor palette for default cursor, disable it now
CursorMan.disableCursorPalette(true);
@@ -1763,7 +2013,7 @@ void Wiz::displayWizComplexImage(const WizParameters *params) {
int sourceImage = 0;
if (params->processFlags & kWPFMaskImg) {
sourceImage = params->sourceImage;
- debug(0, "displayWizComplexImage() unhandled flag kWPFMaskImg");
+ debug(0, "displayWizComplexImage() flag kWPFMaskImg");
}
int palette = 0;
if (params->processFlags & kWPFPaletteNum) {
@@ -1831,15 +2081,14 @@ void Wiz::displayWizComplexImage(const WizParameters *params) {
++_imagesNum;
} else {
if (sourceImage != 0) {
- // TODO: Add support for kWPFMaskImg
- drawWizImage(params->sourceImage, state, po_x, po_y, params->img.zorder, shadow, field_390, r, flags, dstResNum, palette);
+ drawWizImage(params->sourceImage, 0, params->img.resNum, state, po_x, po_y, params->img.zorder, shadow, field_390, r, flags, dstResNum, _vm->getHEPaletteSlot(palette));
} else if (params->processFlags & (kWPFScaled | kWPFRotate)) {
drawWizComplexPolygon(params->img.resNum, state, po_x, po_y, shadow, rotationAngle, scale, r, flags, dstResNum, palette);
} else {
if (flags & kWIFIsPolygon) {
drawWizPolygon(params->img.resNum, state, po_x, flags, shadow, dstResNum, palette);
} else {
- drawWizImage(params->img.resNum, state, po_x, po_y, params->img.zorder, shadow, field_390, r, flags, dstResNum, palette);
+ drawWizImage(params->img.resNum, state, 0, 0, po_x, po_y, params->img.zorder, shadow, field_390, r, flags, dstResNum, _vm->getHEPaletteSlot(palette));
}
}
}
@@ -1847,6 +2096,8 @@ void Wiz::displayWizComplexImage(const WizParameters *params) {
void Wiz::createWizEmptyImage(int resNum, int img_x, int img_y, int img_w, int img_h) {
const uint16 flags = 0xB;
+ const uint8 compType = (_vm->_game.features & GF_16BIT_COLOR) ? 2 : 0;
+ const uint8 bitDepth = (_vm->_game.features & GF_16BIT_COLOR) ? 2 : 1;
int res_size = 0x1C;
if (flags & 1) {
res_size += 0x308;
@@ -1857,11 +2108,11 @@ void Wiz::createWizEmptyImage(int resNum, int img_x, int img_y, int img_w, int i
if (flags & 8) {
res_size += 0x10C;
}
- res_size += 8 + img_w * img_h;
+ res_size += 8 + img_w * img_h * bitDepth;
const uint8 *palPtr;
if (_vm->_game.heversion >= 99) {
- palPtr = _vm->_hePalettes + 1024;
+ palPtr = _vm->_hePalettes + _vm->_hePaletteSlot;
} else {
palPtr = _vm->_currentPalette;
}
@@ -1874,7 +2125,7 @@ void Wiz::createWizEmptyImage(int resNum, int img_x, int img_y, int img_w, int i
WRITE_BE_UINT32(res_data, res_size); res_data += 4;
WRITE_BE_UINT32(res_data, 'WIZH'); res_data += 4;
WRITE_BE_UINT32(res_data, 0x14); res_data += 4;
- WRITE_LE_UINT32(res_data, 0); res_data += 4;
+ WRITE_LE_UINT32(res_data, compType); res_data += 4;
WRITE_LE_UINT32(res_data, img_w); res_data += 4;
WRITE_LE_UINT32(res_data, img_h); res_data += 4;
if (flags & 1) {
@@ -1897,7 +2148,7 @@ void Wiz::createWizEmptyImage(int resNum, int img_x, int img_y, int img_w, int i
}
}
WRITE_BE_UINT32(res_data, 'WIZD'); res_data += 4;
- WRITE_BE_UINT32(res_data, 8 + img_w * img_h); res_data += 4;
+ WRITE_BE_UINT32(res_data, 8 + img_w * img_h * bitDepth); res_data += 4;
}
_vm->_res->setModified(rtImage, resNum);
}
@@ -1914,7 +2165,8 @@ void Wiz::fillWizRect(const WizParameters *params) {
int c = READ_LE_UINT32(wizh + 0x0);
int w = READ_LE_UINT32(wizh + 0x4);
int h = READ_LE_UINT32(wizh + 0x8);
- assert(c == 0);
+ assert(c == 0 || c == 2);
+ uint8 bitDepth = (c == 2) ? 2 : 1;
Common::Rect areaRect, imageRect(w, h);
if (params->processFlags & kWPFClipBox) {
if (!imageRect.intersects(params->box)) {
@@ -1937,10 +2189,15 @@ void Wiz::fillWizRect(const WizParameters *params) {
assert(wizd);
int dx = areaRect.width();
int dy = areaRect.height();
- wizd += areaRect.top * w + areaRect.left;
+ wizd += (areaRect.top * w + areaRect.left) * bitDepth;
while (dy--) {
- memset(wizd, color, dx);
- wizd += w;
+ if (bitDepth == 2) {
+ for (int i = 0; i < dx; i++)
+ WRITE_LE_UINT16(wizd + i * 2, color);
+ } else {
+ memset(wizd, color, dx);
+ }
+ wizd += w * bitDepth;
}
}
}
@@ -1950,14 +2207,19 @@ void Wiz::fillWizRect(const WizParameters *params) {
struct drawProcP {
Common::Rect *imageRect;
uint8 *wizd;
- int width;
+ int pitch;
+ int depth;
};
static void drawProc(int x, int y, int c, void *data) {
drawProcP *param = (drawProcP *)data;
if (param->imageRect->contains(x, y)) {
- *(param->wizd + y * param->width + x) = c;
+ uint32 offs = y * param->pitch + x * param->depth;
+ if (param->depth == 2)
+ WRITE_LE_UINT16(param->wizd + offs, c);
+ else
+ *(param->wizd + offs) = c;
}
}
@@ -1974,7 +2236,8 @@ void Wiz::fillWizLine(const WizParameters *params) {
int c = READ_LE_UINT32(wizh + 0x0);
int w = READ_LE_UINT32(wizh + 0x4);
int h = READ_LE_UINT32(wizh + 0x8);
- assert(c == 0);
+ assert(c == 0 || c == 2);
+ uint8 bitDepth = (c == 2) ? 2 : 1;
Common::Rect imageRect(w, h);
if (params->processFlags & kWPFClipBox) {
if (!imageRect.intersects(params->box)) {
@@ -1997,13 +2260,13 @@ void Wiz::fillWizLine(const WizParameters *params) {
lineP.imageRect = &imageRect;
lineP.wizd = wizd;
- lineP.width = w;
+ lineP.pitch = w * bitDepth;
+ lineP.depth = bitDepth;
if (params->processFlags & kWPFParams) {
assert (params->params2 == 1); // Catch untested usage
Graphics::drawThickLine(x1, y1, x2, y2, params->params1, color, drawProc, &lineP);
} else {
-
Graphics::drawLine(x1, y1, x2, y2, color, drawProc, &lineP);
}
}
@@ -2065,7 +2328,7 @@ void Wiz::remapWizImagePal(const WizParameters *params) {
}
void Wiz::processWizImage(const WizParameters *params) {
- byte filename[260];
+ byte buffer[260];
debug(3, "processWizImage: processMode %d", params->processMode);
switch (params->processMode) {
@@ -2080,18 +2343,28 @@ void Wiz::processWizImage(const WizParameters *params) {
break;
case 3:
if (params->processFlags & kWPFUseFile) {
- Common::File f;
+ Common::SeekableReadStream *f = NULL;
+ memcpy(buffer, params->filename, 260);
+ const char *filename = (char *)buffer + _vm->convertFilePath(buffer, sizeof(buffer));
- memcpy(filename, params->filename, 260);
- _vm->convertFilePath(filename, sizeof(filename));
+ if (!_vm->_saveFileMan->listSavefiles(filename).empty()) {
+ f = _vm->_saveFileMan->openForLoading(filename);
+ } else {
+ Common::File *nf = new Common::File();
+ nf->open(filename);
+ if (!nf->isOpen())
+ delete nf;
+ else
+ f = nf;
+ }
- if (f.open((const char *)filename)) {
- uint32 id = f.readUint32BE();
+ if (f) {
+ uint32 id = f->readUint32BE();
if (id == MKID_BE('AWIZ') || id == MKID_BE('MULT')) {
- uint32 size = f.readUint32BE();
- f.seek(0, SEEK_SET);
+ uint32 size = f->readUint32BE();
+ f->seek(0, SEEK_SET);
byte *p = _vm->_res->createResource(rtImage, params->img.resNum, size);
- if (f.read(p, size) != size) {
+ if (f->read(p, size) != size) {
_vm->_res->nukeResource(rtImage, params->img.resNum);
error("i/o error when reading '%s'", filename);
_vm->VAR(_vm->VAR_GAME_LOADED) = -2;
@@ -2105,7 +2378,7 @@ void Wiz::processWizImage(const WizParameters *params) {
_vm->VAR(_vm->VAR_GAME_LOADED) = -1;
_vm->VAR(119) = -1;
}
- f.close();
+ delete f;
} else {
_vm->VAR(_vm->VAR_GAME_LOADED) = -3;
_vm->VAR(119) = -3;
@@ -2115,7 +2388,9 @@ void Wiz::processWizImage(const WizParameters *params) {
break;
case 4:
if (params->processFlags & kWPFUseFile) {
- Common::DumpFile f;
+ Common::OutSaveFile *f;
+ memcpy(buffer, params->filename, 260);
+ const char *filename = (char *)buffer + _vm->convertFilePath(buffer, sizeof(buffer));
switch (params->fileWriteMode) {
case 2:
@@ -2125,22 +2400,20 @@ void Wiz::processWizImage(const WizParameters *params) {
// TODO Write image to file
break;
case 0:
- memcpy(filename, params->filename, 260);
- _vm->convertFilePath(filename, sizeof(filename));
-
- if (!f.open((const char *)filename)) {
+ if (!(f = _vm->_saveFileMan->openForSaving(filename))) {
debug(0, "Unable to open for write '%s'", filename);
_vm->VAR(119) = -3;
} else {
byte *p = _vm->getResourceAddress(rtImage, params->img.resNum);
uint32 size = READ_BE_UINT32(p + 4);
- if (f.write(p, size) != size) {
- error("i/o error when writing '%s'", params->filename);
+ if (f->write(p, size) != size) {
+ error("i/o error when writing '%s'", filename);
_vm->VAR(119) = -2;
} else {
_vm->VAR(119) = 0;
}
- f.close();
+ f->finalize();
+ delete f;
}
break;
default:
@@ -2153,9 +2426,7 @@ void Wiz::processWizImage(const WizParameters *params) {
break;
// HE 99+
case 7:
- // Used in PuttsFunShop/SamsFunShop/soccer2004
- // TODO: Capture polygon
- _vm->_res->setModified(rtImage, params->img.resNum);
+ captureWizPolygon(params->img.resNum, params->sourceImage, (params->processFlags & kWPFNewState) ? params->img.state : 0, params->polygonId1, params->polygonId2, params->compType);
break;
case 8: {
int img_w = 640;
@@ -2172,6 +2443,9 @@ void Wiz::processWizImage(const WizParameters *params) {
img_x = params->img.x1;
img_y = params->img.y1;
}
+ if (params->processFlags & kWPFParams) {
+ debug(0, "Compression %d Color Depth %d", params->params1, params->params2);
+ }
createWizEmptyImage(params->img.resNum, img_x, img_y, img_w, img_h);
}
break;
@@ -2309,7 +2583,7 @@ int Wiz::isWizPixelNonTransparent(int resNum, int state, int x, int y, int flags
ret = isWizPixelNonTransparent(wizd, x, y, w, h, 1);
break;
case 2:
- ret = getRawWizPixelColor(wizd, x, y, w, h, 2, _vm->VAR(_vm->VAR_WIZ_TCOLOR)) != _vm->VAR(_vm->VAR_WIZ_TCOLOR) ? 1 : 0;
+ ret = getRawWizPixelColor(wizd, x, y, w, h, 2, _vm->VAR(_vm->VAR_WIZ_TCOLOR)) != _vm->VAR(_vm->VAR_WIZ_TCOLOR) ? 1 : 0;
break;
case 4:
// TODO: Unknown image type
diff --git a/engines/scumm/he/wiz_he.h b/engines/scumm/he/wiz_he.h
index fe63457ead..d8f984f710 100644
--- a/engines/scumm/he/wiz_he.h
+++ b/engines/scumm/he/wiz_he.h
@@ -142,6 +142,12 @@ enum {
kWizCopy
};
+enum DstSurface {
+ kDstScreen = 0,
+ kDstMemory = 1,
+ kDstResource = 2
+};
+
class ScummEngine_v71he;
class Wiz {
@@ -188,27 +194,37 @@ public:
void flushWizBuffer();
void getWizImageSpot(int resId, int state, int32 &x, int32 &y);
- void loadWizCursor(int resId);
+ void loadWizCursor(int resId, int palette);
void captureWizImage(int resNum, const Common::Rect& r, bool frontBuffer, int compType);
+ void captureImage(uint8 *src, int srcPitch, int srcw, int srch, int resNum, const Common::Rect& r, int compType);
+ void captureWizPolygon(int resNum, int maskNum, int maskState, int id1, int id2, int compType);
void displayWizComplexImage(const WizParameters *params);
void displayWizImage(WizImage *pwi);
void processWizImage(const WizParameters *params);
- uint8 *drawWizImage(int resNum, int state, int x1, int y1, int zorder, int shadow, int field_390, const Common::Rect *clipBox, int flags, int dstResNum, int palette);
+ uint8 *drawWizImage(int resNum, int state, int maskNum, int maskState, int x1, int y1, int zorder, int shadow, int field_390, const Common::Rect *clipBox, int flags, int dstResNum, const uint8 *palPtr);
void drawWizPolygon(int resNum, int state, int id, int flags, int shadow, int dstResNum, int palette);
void drawWizComplexPolygon(int resNum, int state, int po_x, int po_y, int shadow, int angle, int zoom, const Common::Rect *r, int flags, int dstResNum, int palette);
void drawWizPolygonTransform(int resNum, int state, Common::Point *wp, int flags, int shadow, int dstResNum, int palette);
+ void drawWizPolygonImage(uint8 *dst, const uint8 *src, const uint8 *mask, int dstpitch, int dstType, int dstw, int dsth, int wizW, int wizH, Common::Rect &bound, Common::Point *wp, uint8 bitDepth);
+
+ static void copyMaskWizImage(uint8 *dst, const uint8 *src, const uint8 *mask, int dstPitch, int dstType, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int flags, const uint8 *palPtr);
+
+ static void copyAuxImage(uint8 *dst1, uint8 *dst2, const uint8 *src, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, uint8 bitdepth);
+ static void copyWizImageWithMask(uint8 *dst, const uint8 *src, int dstPitch, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int maskT, int maskP);
+ static void copyWizImage(uint8 *dst, const uint8 *src, int dstPitch, int dstType, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int flags, const uint8 *palPtr, const uint8 *xmapPtr, uint8 bitdepth);
+ static void copyRawWizImage(uint8 *dst, const uint8 *src, int dstPitch, int dstType, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int flags, const uint8 *palPtr, int transColor, uint8 bitdepth);
+ static void copy16BitWizImage(uint8 *dst, const uint8 *src, int dstPitch, int dstType, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int flags, const uint8 *xmapPtr);
+ static void copyRaw16BitWizImage(uint8 *dst, const uint8 *src, int dstPitch, int dstType, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int flags, int transColor);
+ template<int type> static void decompress16BitWizImage(uint8 *dst, int dstPitch, int dstType, const uint8 *src, const Common::Rect &srcRect, int flags, const uint8 *xmapPtr = NULL);
+ template<int type> static void decompressWizImage(uint8 *dst, int dstPitch, int dstType, const uint8 *src, const Common::Rect &srcRect, int flags, const uint8 *palPtr, const uint8 *xmapPtr, uint8 bitdepth);
+ template<int type> static void decompressRawWizImage(uint8 *dst, int dstPitch, int dstType, const uint8 *src, int srcPitch, int w, int h, int transColor, const uint8 *palPtr, uint8 bitdepth);
+
+ template<int type> static void write16BitColor(uint8 *dst, const uint8 *src, int dstType, const uint8 *xmapPtr);
+ template<int type> static void write8BitColor(uint8 *dst, const uint8 *src, int dstType, const uint8 *palPtr, const uint8 *xmapPtr, uint8 bitDepth);
+ static void writeColor(uint8 *dstPtr, int dstType, uint16 color);
- static void copyAuxImage(uint8 *dst1, uint8 *dst2, const uint8 *src, int dstw, int dsth, int srcx, int srcy, int srcw, int srch);
- static void copyWizImage(uint8 *dst, const uint8 *src, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int flags = 0, const uint8 *palPtr = NULL, const uint8 *xmapPtr = NULL);
- static void copyWizImageWithMask(uint8 *dst, const uint8 *src, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int maskT, int maskP);
- void copy16BitWizImage(uint8 *dst, const uint8 *src, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int flags = 0, const uint8 *palPtr = NULL, const uint8 *xmapPtr = NULL);
- static void copyRawWizImage(uint8 *dst, const uint8 *src, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int flags, const uint8 *palPtr, int transColor);
- void copyRaw16BitWizImage(uint8 *dst, const uint8 *src, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int flags, const uint8 *palPtr, int transColor);
- template<int type> static void decompressWizImage(uint8 *dst, int dstPitch, const uint8 *src, const Common::Rect &srcRect, int flags, const uint8 *palPtr = NULL, const uint8 *xmapPtr = NULL);
- template<int type> void decompress16BitWizImage(uint8 *dst, int dstPitch, const uint8 *src, const Common::Rect &srcRect, int flags, const uint8 *palPtr = NULL, const uint8 *xmapPtr = NULL);
- template<int type> static void decompressRawWizImage(uint8 *dst, int dstPitch, const uint8 *src, int srcPitch, int w, int h, int transColor, const uint8 *palPtr = NULL);
int isWizPixelNonTransparent(const uint8 *data, int x, int y, int w, int h, uint8 bitdepth);
uint16 getWizPixelColor(const uint8 *data, int x, int y, int w, int h, uint8 bitDepth, uint16 color);
uint16 getRawWizPixelColor(const uint8 *data, int x, int y, int w, int h, uint8 bitDepth, uint16 color);
diff --git a/engines/scumm/palette.cpp b/engines/scumm/palette.cpp
index c356e7a06c..a596cc5b1a 100644
--- a/engines/scumm/palette.cpp
+++ b/engines/scumm/palette.cpp
@@ -33,6 +33,27 @@
namespace Scumm {
+uint8 *ScummEngine::getHEPaletteSlot(uint16 palSlot) {
+ assertRange(0, palSlot, _numPalettes, "palette");
+
+ if (_game.heversion >= 99) {
+ if (palSlot)
+ return _hePalettes + palSlot * _hePaletteSlot + 768;
+ else
+ return _hePalettes + _hePaletteSlot + 768;
+ }
+
+ return NULL;
+}
+
+uint16 ScummEngine::get16BitColor(uint8 r, uint8 g, uint8 b) {
+ uint16 ar = (r >> 3) << 10;
+ uint16 ag = (g >> 3) << 5;
+ uint16 ab = (b >> 3) << 0;
+ uint16 col = ar | ag | ab;
+ return col;
+}
+
void ScummEngine::resetPalette() {
if (_game.version <= 1) {
if (_game.platform == Common::kPlatformApple2GS) {
@@ -310,9 +331,6 @@ void ScummEngine::setDirtyColors(int min, int max) {
_palDirtyMin = min;
if (_palDirtyMax < max)
_palDirtyMax = max;
-
- if (_hePaletteCache)
- memset(_hePaletteCache, -1, 65536);
}
void ScummEngine::initCycl(const byte *ptr) {
@@ -799,16 +817,6 @@ void ScummEngine_v8::desaturatePalette(int hueScale, int satScale, int lightScal
#endif
-int ScummEngine::convert16BitColor(uint16 color, uint8 r, uint8 g, uint8 b) {
- // HACK: Find the closest matching color, and store in
- // cache for faster access.
- if (_hePaletteCache[color] == -1) {
- _hePaletteCache[color] = remapPaletteColor(r, g, b, -1);
- }
-
- return _hePaletteCache[color];
-}
-
int ScummEngine::remapPaletteColor(int r, int g, int b, int threshold) {
byte *pal;
int ar, ag, ab, i;
diff --git a/engines/scumm/resource.cpp b/engines/scumm/resource.cpp
index 67baff97b3..d3faa15c10 100644
--- a/engines/scumm/resource.cpp
+++ b/engines/scumm/resource.cpp
@@ -919,7 +919,11 @@ bool ScummEngine::isResourceInUse(int type, int i) const {
case rtCostume:
return isCostumeInUse(i);
case rtSound:
- return _sound->isSoundInUse(i);
+ // Sound resource 1 is used for queued speech
+ if (_game.heversion >= 60 && i == 1)
+ return true;
+ else
+ return _sound->isSoundInUse(i);
case rtCharset:
return _charset->getCurID() == i;
case rtImage:
diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp
index aa4dce470e..7bf61a8762 100644
--- a/engines/scumm/saveload.cpp
+++ b/engines/scumm/saveload.cpp
@@ -1553,7 +1553,7 @@ void ScummEngine_v90he::saveOrLoad(Serializer *s) {
void ScummEngine_v99he::saveOrLoad(Serializer *s) {
ScummEngine_v90he::saveOrLoad(s);
- s->saveLoadArrayOf(_hePalettes, (_numPalettes + 1) * 1024, sizeof(_hePalettes[0]), sleUint8);
+ s->saveLoadArrayOf(_hePalettes, (_numPalettes + 1) * _hePaletteSlot, sizeof(_hePalettes[0]), sleUint8);
}
void ScummEngine_v100he::saveOrLoad(Serializer *s) {
diff --git a/engines/scumm/saveload.h b/engines/scumm/saveload.h
index 4f6adc5570..fafb6b383f 100644
--- a/engines/scumm/saveload.h
+++ b/engines/scumm/saveload.h
@@ -50,7 +50,7 @@ namespace Scumm {
* only saves/loads those which are valid for the version of the savegame
* which is being loaded/saved currently.
*/
-#define CURRENT_VER 79
+#define CURRENT_VER 80
/**
* An auxillary macro, used to specify savegame versions. We use this instead
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index 8c5731d539..1beda85456 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -110,7 +110,9 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr)
_currentScript(0xFF), // Let debug() work on init stage
_messageDialog(0), _pauseDialog(0), _scummMenuDialog(0), _versionDialog(0) {
- if (_game.platform == Common::kPlatformNES) {
+ if (_game.features & GF_16BIT_COLOR) {
+ _gdi = new Gdi16Bit(this);
+ } else if (_game.platform == Common::kPlatformNES) {
_gdi = new GdiNES(this);
} else if (_game.version <= 1) {
_gdi = new GdiV1(this);
@@ -251,6 +253,7 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr)
_switchRoomEffect2 = 0;
_switchRoomEffect = 0;
+ _bitDepth = 0;
_doEffect = false;
_snapScroll = false;
_currentLights = 0;
@@ -267,8 +270,8 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr)
_palManipPalette = NULL;
_palManipIntermediatePal = NULL;
memset(gfxUsageBits, 0, sizeof(gfxUsageBits));
- _hePaletteCache = NULL;
_hePalettes = NULL;
+ _hePaletteSlot = 0;
_shadowPalette = NULL;
_shadowPaletteSize = 0;
memset(_currentPalette, 0, sizeof(_currentPalette));
@@ -523,9 +526,11 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr)
_screenHeight = 200;
}
+ _bitDepth = (_game.features & GF_16BIT_COLOR) ? 2 : 1;
+
// Allocate gfx compositing buffer (not needed for V7/V8 games).
if (_game.version < 7)
- _compositeBuf = (byte *)malloc(_screenWidth * _screenHeight);
+ _compositeBuf = (byte *)malloc(_screenWidth * _screenHeight * _bitDepth);
else
_compositeBuf = 0;
@@ -830,7 +835,6 @@ ScummEngine_v90he::~ScummEngine_v90he() {
delete _logicHE;
}
if (_game.heversion >= 99) {
- free(_hePaletteCache);
free(_hePalettes);
}
}
@@ -1095,6 +1099,15 @@ Common::Error ScummEngine::init() {
// CJK FT and DIG use usual NUT fonts, not FM-TOWNS ROM, so
// there is no text surface for them. This takes that into account
(_screenWidth * _textSurfaceMultiplier > 320));
+ } else if (_game.features & GF_16BIT_COLOR) {
+#ifdef ENABLE_RGB_COLOR
+ Graphics::PixelFormat format = Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0);
+ initGraphics(_screenWidth, _screenHeight, _screenWidth > 320, &format);
+ if (format != _system->getScreenFormat())
+ return Common::kUnsupportedColorMode;
+#else
+ error("16bit color support is required for this game");
+#endif
} else {
initGraphics(_screenWidth, _screenHeight, _screenWidth > 320);
}
@@ -1198,7 +1211,7 @@ void ScummEngine::setupScumm() {
int maxHeapThreshold = -1;
if (_game.features & GF_16BIT_COLOR) {
- // 16Bit color games require double the memory, due to increased resource sizes.
+ // 16bit color games require double the memory, due to increased resource sizes.
maxHeapThreshold = 12 * 1024 * 1024;
} else if (_game.features & GF_NEW_COSTUMES) {
// Since the new costumes are very big, we increase the heap limit, to avoid having
@@ -1220,7 +1233,7 @@ void ScummEngine::setupScumm() {
}
free(_compositeBuf);
- _compositeBuf = (byte *)malloc(_screenWidth * _textSurfaceMultiplier * _screenHeight * _textSurfaceMultiplier);
+ _compositeBuf = (byte *)malloc(_screenWidth * _textSurfaceMultiplier * _screenHeight * _textSurfaceMultiplier * _bitDepth);
}
#ifdef ENABLE_SCUMM_7_8
@@ -1562,11 +1575,9 @@ void ScummEngine_v99he::resetScumm() {
ScummEngine_v90he::resetScumm();
- _hePaletteCache = (int16 *)malloc(65536);
- memset(_hePaletteCache, -1, 65536);
-
- _hePalettes = (uint8 *)malloc((_numPalettes + 1) * 1024);
- memset(_hePalettes, 0, (_numPalettes + 1) * 1024);
+ _hePaletteSlot = (_game.features & GF_16BIT_COLOR) ? 1280 : 1024;
+ _hePalettes = (uint8 *)malloc((_numPalettes + 1) * _hePaletteSlot);
+ memset(_hePalettes, 0, (_numPalettes + 1) * _hePaletteSlot);
// Array 129 is set to base name
len = strlen(_filenamePattern.pattern);
diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h
index f2eb331a14..7d2bf3336a 100644
--- a/engines/scumm/scumm.h
+++ b/engines/scumm/scumm.h
@@ -963,6 +963,7 @@ public:
int _screenTop;
Common::RenderMode _renderMode;
+ uint8 _bitDepth;
protected:
ColorCycle _colorCycle[16]; // Palette cycles
@@ -982,7 +983,10 @@ protected:
byte animate, animateIndex;
int8 state;
} _cursor;
- byte _grabbedCursor[8192];
+
+ // HACK Double the array size to handle 16-bit images.
+ // this should be dynamically allocated based on game depth instead.
+ byte _grabbedCursor[16384];
byte _currentCursor;
byte _newEffect, _switchRoomEffect2, _switchRoomEffect;
@@ -1048,7 +1052,8 @@ protected:
virtual void palManipulateInit(int resID, int start, int end, int time);
void palManipulate();
public:
- int convert16BitColor(uint16 color, uint8 r, uint8 g, uint8 b);
+ uint8 *getHEPaletteSlot(uint16 palSlot);
+ uint16 get16BitColor(uint8 r, uint8 g, uint8 b);
int remapPaletteColor(int r, int g, int b, int threshold); // Used by Actor::remapActorPalette
protected:
void moveMemInPalRes(int start, int end, byte direction);
@@ -1124,7 +1129,7 @@ public:
// HE specific
byte _HEV7ActorPalette[256];
uint8 *_hePalettes;
- int16 *_hePaletteCache;
+ uint16 _hePaletteSlot;
protected:
int _shadowPaletteSize;
diff --git a/graphics/cursorman.cpp b/graphics/cursorman.cpp
index 2e71b548bc..b77aac37cf 100644
--- a/graphics/cursorman.cpp
+++ b/graphics/cursorman.cpp
@@ -57,14 +57,14 @@ bool CursorManager::showMouse(bool visible) {
return g_system->showMouse(visible);
}
-void CursorManager::pushCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, byte keycolor, int targetScale) {
- Cursor *cur = new Cursor(buf, w, h, hotspotX, hotspotY, keycolor, targetScale);
+void CursorManager::pushCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int targetScale, const Graphics::PixelFormat *format) {
+ Cursor *cur = new Cursor(buf, w, h, hotspotX, hotspotY, keycolor, targetScale, format);
cur->_visible = isVisible();
_cursorStack.push(cur);
if (buf) {
- g_system->setMouseCursor(cur->_data, w, h, hotspotX, hotspotY, keycolor, targetScale);
+ g_system->setMouseCursor(cur->_data, w, h, hotspotX, hotspotY, keycolor, targetScale, format);
}
}
@@ -77,7 +77,7 @@ void CursorManager::popCursor() {
if (!_cursorStack.empty()) {
cur = _cursorStack.top();
- g_system->setMouseCursor(cur->_data, cur->_width, cur->_height, cur->_hotspotX, cur->_hotspotY, cur->_keycolor, cur->_targetScale);
+ g_system->setMouseCursor(cur->_data, cur->_width, cur->_height, cur->_hotspotX, cur->_hotspotY, cur->_keycolor, cur->_targetScale, &cur->_format);
}
g_system->showMouse(isVisible());
@@ -100,15 +100,24 @@ void CursorManager::popAllCursors() {
g_system->showMouse(isVisible());
}
+void CursorManager::replaceCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int targetScale, const Graphics::PixelFormat *format) {
-void CursorManager::replaceCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, byte keycolor, int targetScale) {
if (_cursorStack.empty()) {
- pushCursor(buf, w, h, hotspotX, hotspotY, keycolor, targetScale);
+ pushCursor(buf, w, h, hotspotX, hotspotY, keycolor, targetScale, format);
return;
}
Cursor *cur = _cursorStack.top();
+
+#ifdef ENABLE_RGB_COLOR
+ uint size;
+ if (!format)
+ size = w * h;
+ else
+ size = w * h * format->bytesPerPixel;
+#else
uint size = w * h;
+#endif
if (cur->_size < size) {
delete[] cur->_data;
@@ -125,8 +134,14 @@ void CursorManager::replaceCursor(const byte *buf, uint w, uint h, int hotspotX,
cur->_hotspotY = hotspotY;
cur->_keycolor = keycolor;
cur->_targetScale = targetScale;
+#ifdef ENABLE_RGB_COLOR
+ if (format)
+ cur->_format = *format;
+ else
+ cur->_format = Graphics::PixelFormat::createFormatCLUT8();
+#endif
- g_system->setMouseCursor(cur->_data, w, h, hotspotX, hotspotY, keycolor, targetScale);
+ g_system->setMouseCursor(cur->_data, w, h, hotspotX, hotspotY, keycolor, targetScale, format);
}
bool CursorManager::supportsCursorPalettes() {
diff --git a/graphics/cursorman.h b/graphics/cursorman.h
index f019e37b04..ae7008f54c 100644
--- a/graphics/cursorman.h
+++ b/graphics/cursorman.h
@@ -28,6 +28,10 @@
#include "common/scummsys.h"
#include "common/stack.h"
#include "common/singleton.h"
+#include "graphics/pixelformat.h"
+#ifdef ENABLE_RGB_COLOR
+#include "common/system.h"
+#endif
namespace Graphics {
@@ -59,18 +63,19 @@ public:
* safely freed afterwards.
*
* @param buf the new cursor data
- * @param w the width
- * @param h the height
+ * @param w the width
+ * @param h the height
* @param hotspotX the hotspot X coordinate
* @param hotspotY the hotspot Y coordinate
* @param keycolor the index for the transparent color
* @param targetScale the scale for which the cursor is designed
- *
+ * @param format a pointer to the pixel format which the cursor graphic uses,
+ * CLUT8 will be used if this is NULL or not specified.
* @note It is ok for the buffer to be a NULL pointer. It is sometimes
* useful to push a "dummy" cursor and modify it later. The
* cursor will be added to the stack, but not to the backend.
*/
- void pushCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, byte keycolor = 255, int targetScale = 1);
+ void pushCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor = 0xFFFFFFFF, int targetScale = 1, const Graphics::PixelFormat *format = NULL);
/**
* Pop a cursor from the stack, and restore the previous one to the
@@ -90,8 +95,10 @@ public:
* @param hotspotY the hotspot Y coordinate
* @param keycolor the index for the transparent color
* @param targetScale the scale for which the cursor is designed
+ * @param format a pointer to the pixel format which the cursor graphic uses,
+ * CLUT8 will be used if this is NULL or not specified.
*/
- void replaceCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, byte keycolor = 255, int targetScale = 1);
+ void replaceCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor = 0xFFFFFFFF, int targetScale = 1, const Graphics::PixelFormat *format = NULL);
/**
* Pop all of the cursors and cursor palettes from their respective stacks.
@@ -166,13 +173,24 @@ private:
uint _height;
int _hotspotX;
int _hotspotY;
- byte _keycolor;
+ uint32 _keycolor;
+ Graphics::PixelFormat _format;
byte _targetScale;
uint _size;
-
- Cursor(const byte *data, uint w, uint h, int hotspotX, int hotspotY, byte keycolor = 255, int targetScale = 1) {
+ Cursor(const byte *data, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor = 0xFFFFFFFF, int targetScale = 1, const Graphics::PixelFormat *format = NULL) {
+#ifdef ENABLE_RGB_COLOR
+ if (!format)
+ _format = Graphics::PixelFormat::createFormatCLUT8();
+ else
+ _format = *format;
+ _size = w * h * _format.bytesPerPixel;
+ _keycolor &= ((1 << (_format.bytesPerPixel << 3)) - 1);
+#else
+ _format = Graphics::PixelFormat::createFormatCLUT8();
_size = w * h;
+ _keycolor &= 0xFF;
+#endif
_data = new byte[_size];
if (data && _data)
memcpy(_data, data, _size);
@@ -180,7 +198,6 @@ private:
_height = h;
_hotspotX = hotspotX;
_hotspotY = hotspotY;
- _keycolor = keycolor;
_targetScale = targetScale;
}
@@ -216,7 +233,6 @@ private:
delete[] _data;
}
};
-
Common::Stack<Cursor *> _cursorStack;
Common::Stack<Palette *> _cursorPaletteStack;
};
diff --git a/graphics/pixelformat.h b/graphics/pixelformat.h
index f59650e5cc..d16de51ea7 100644
--- a/graphics/pixelformat.h
+++ b/graphics/pixelformat.h
@@ -27,6 +27,7 @@
#define GRAPHICS_PIXELFORMAT_H
#include "common/scummsys.h"
+#include "common/list.h"
namespace Graphics {
@@ -50,6 +51,24 @@ struct PixelFormat {
byte rLoss, gLoss, bLoss, aLoss; /**< Precision loss of each color component. */
byte rShift, gShift, bShift, aShift; /**< Binary left shift of each color component in the pixel value. */
+ inline PixelFormat() {
+ bytesPerPixel =
+ rLoss = gLoss = bLoss = aLoss =
+ rShift = gShift = bShift = aShift = 0;
+ }
+
+ inline PixelFormat(byte BytesPerPixel,
+ byte RBits, byte GBits, byte BBits, byte ABits,
+ byte RShift, byte GShift, byte BShift, byte AShift) {
+ bytesPerPixel = BytesPerPixel;
+ rLoss = 8 - RBits, gLoss = 8 - GBits, bLoss = 8 - BBits, aLoss = 8 - ABits;
+ rShift = RShift, gShift = GShift, bShift = BShift, aShift = AShift;
+ }
+
+ static inline PixelFormat createFormatCLUT8() {
+ return PixelFormat(1, 0, 0, 0, 0, 0, 0, 0, 0);
+ }
+
inline bool operator==(const PixelFormat &fmt) const {
// TODO: If aLoss==8, then the value of aShift is irrelevant, and should be ignored.
return 0 == memcmp(this, &fmt, sizeof(PixelFormat));
@@ -129,6 +148,26 @@ struct PixelFormat {
}
};
+/**
+ * Determines the first matching format between two lists.
+ *
+ * @param backend The higher priority list, meant to be a list of formats supported by the backend
+ * @param frontend The lower priority list, meant to be a list of formats supported by the engine
+ * @return The first item on the backend list that also occurs on the frontend list
+ * or PixelFormat::createFormatCLUT8() if no matching formats were found.
+ */
+inline PixelFormat findCompatibleFormat(Common::List<PixelFormat> backend, Common::List<PixelFormat> frontend) {
+#ifdef ENABLE_RGB_COLOR
+ for (Common::List<PixelFormat>::iterator i = backend.begin(); i != backend.end(); ++i) {
+ for (Common::List<PixelFormat>::iterator j = frontend.begin(); j != frontend.end(); ++j) {
+ if (*i == *j)
+ return *i;
+ }
+ }
+#endif
+ return PixelFormat::createFormatCLUT8();
+}
+
} // end of namespace Graphics
#endif
diff --git a/graphics/scaler.cpp b/graphics/scaler.cpp
index a3aaaa121d..8c677cc083 100644
--- a/graphics/scaler.cpp
+++ b/graphics/scaler.cpp
@@ -30,18 +30,17 @@
int gBitFormat = 565;
-static const Graphics::PixelFormat gPixelFormat555 = {
+static const Graphics::PixelFormat gPixelFormat555(
2,
3, 3, 3, 8,
10, 5, 0, 0
- };
+ );
-static const Graphics::PixelFormat gPixelFormat565 = {
+static const Graphics::PixelFormat gPixelFormat565(
2,
3, 2, 3, 8,
11, 5, 0, 0
- };
-
+ );
#ifndef DISABLE_HQ_SCALERS
diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp
index 1d9062f323..417a1f714c 100644
--- a/gui/ThemeEngine.cpp
+++ b/gui/ThemeEngine.cpp
@@ -1234,6 +1234,12 @@ bool ThemeEngine::createCursor(const Common::String &filename, int hotspotX, int
if (!cursor)
return false;
+#ifdef ENABLE_RGB_COLOR
+ _cursorFormat.bytesPerPixel = 1;
+ _cursorFormat.rLoss = _cursorFormat.gLoss = _cursorFormat.bLoss = _cursorFormat.aLoss = 8;
+ _cursorFormat.rShift = _cursorFormat.gShift = _cursorFormat.bShift = _cursorFormat.aShift = 0;
+#endif
+
// Set up the cursor parameters
_cursorHotspotX = hotspotX;
_cursorHotspotY = hotspotY;
diff --git a/gui/ThemeEngine.h b/gui/ThemeEngine.h
index dfa27c2c88..43e227d5fb 100644
--- a/gui/ThemeEngine.h
+++ b/gui/ThemeEngine.h
@@ -612,6 +612,9 @@ protected:
ImagesMap _bitmaps;
Graphics::PixelFormat _overlayFormat;
+#ifdef ENABLE_RGB_COLOR
+ Graphics::PixelFormat _cursorFormat;
+#endif
/** List of all the dirty screens that must be blitted to the overlay. */
Common::List<Common::Rect> _dirtyScreen;