aboutsummaryrefslogtreecommitdiff
path: root/engines/wintermute
diff options
context:
space:
mode:
Diffstat (limited to 'engines/wintermute')
-rw-r--r--engines/wintermute/ad/ad_region.cpp2
-rw-r--r--engines/wintermute/ad/ad_rot_level.cpp2
-rw-r--r--engines/wintermute/ad/ad_scale_level.cpp2
-rw-r--r--engines/wintermute/ad/ad_waypoint_group.cpp2
-rw-r--r--engines/wintermute/base/base_game.cpp4
-rw-r--r--engines/wintermute/base/base_object.cpp20
-rw-r--r--engines/wintermute/base/base_persistence_manager.cpp69
-rw-r--r--engines/wintermute/base/base_persistence_manager.h4
-rw-r--r--engines/wintermute/base/base_region.cpp2
-rw-r--r--engines/wintermute/base/font/base_font_truetype.cpp6
-rw-r--r--engines/wintermute/base/gfx/base_renderer.h2
-rw-r--r--engines/wintermute/base/gfx/osystem/base_render_osystem.cpp43
-rw-r--r--engines/wintermute/base/gfx/osystem/base_render_osystem.h39
-rw-r--r--engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp90
-rw-r--r--engines/wintermute/base/gfx/osystem/base_surface_osystem.h4
-rw-r--r--engines/wintermute/base/gfx/osystem/render_ticket.cpp17
-rw-r--r--engines/wintermute/base/gfx/osystem/render_ticket.h13
-rw-r--r--engines/wintermute/base/particles/part_emitter.cpp20
-rw-r--r--engines/wintermute/base/particles/part_particle.cpp10
-rw-r--r--engines/wintermute/base/scriptables/script_engine.cpp9
-rw-r--r--engines/wintermute/base/scriptables/script_value.cpp11
-rw-r--r--engines/wintermute/dcgf.h2
-rw-r--r--engines/wintermute/detection_tables.h86
-rw-r--r--engines/wintermute/graphics/transparent_surface.cpp173
-rw-r--r--engines/wintermute/graphics/transparent_surface.h13
-rw-r--r--engines/wintermute/utils/string_util.cpp23
-rw-r--r--engines/wintermute/video/video_theora_player.cpp2
-rw-r--r--engines/wintermute/wintermute.cpp2
28 files changed, 424 insertions, 248 deletions
diff --git a/engines/wintermute/ad/ad_region.cpp b/engines/wintermute/ad/ad_region.cpp
index 444ada2433..bc9ac903c6 100644
--- a/engines/wintermute/ad/ad_region.cpp
+++ b/engines/wintermute/ad/ad_region.cpp
@@ -404,7 +404,7 @@ bool AdRegion::persist(BasePersistenceManager *persistMgr) {
persistMgr->transfer(TMEMBER(_alpha));
persistMgr->transfer(TMEMBER(_blocked));
persistMgr->transfer(TMEMBER(_decoration));
- persistMgr->transfer(TMEMBER(_zoom));
+ persistMgr->transferFloat(TMEMBER(_zoom));
return STATUS_OK;
}
diff --git a/engines/wintermute/ad/ad_rot_level.cpp b/engines/wintermute/ad/ad_rot_level.cpp
index b11fad96d7..d925b0d57a 100644
--- a/engines/wintermute/ad/ad_rot_level.cpp
+++ b/engines/wintermute/ad/ad_rot_level.cpp
@@ -153,7 +153,7 @@ bool AdRotLevel::persist(BasePersistenceManager *persistMgr) {
BaseObject::persist(persistMgr);
- persistMgr->transfer(TMEMBER(_rotation));
+ persistMgr->transferFloat(TMEMBER(_rotation));
return STATUS_OK;
}
diff --git a/engines/wintermute/ad/ad_scale_level.cpp b/engines/wintermute/ad/ad_scale_level.cpp
index 9cf7bfa600..59e6d57787 100644
--- a/engines/wintermute/ad/ad_scale_level.cpp
+++ b/engines/wintermute/ad/ad_scale_level.cpp
@@ -154,7 +154,7 @@ bool AdScaleLevel::persist(BasePersistenceManager *persistMgr) {
BaseObject::persist(persistMgr);
- persistMgr->transfer(TMEMBER(_scale));
+ persistMgr->transferFloat(TMEMBER(_scale));
return STATUS_OK;
}
diff --git a/engines/wintermute/ad/ad_waypoint_group.cpp b/engines/wintermute/ad/ad_waypoint_group.cpp
index cb754516b3..cc7982cb9d 100644
--- a/engines/wintermute/ad/ad_waypoint_group.cpp
+++ b/engines/wintermute/ad/ad_waypoint_group.cpp
@@ -196,7 +196,7 @@ bool AdWaypointGroup::persist(BasePersistenceManager *persistMgr) {
persistMgr->transfer(TMEMBER(_active));
persistMgr->transfer(TMEMBER(_editorSelectedPoint));
- persistMgr->transfer(TMEMBER(_lastMimicScale));
+ persistMgr->transferFloat(TMEMBER(_lastMimicScale));
persistMgr->transfer(TMEMBER(_lastMimicX));
persistMgr->transfer(TMEMBER(_lastMimicY));
_points.persist(persistMgr);
diff --git a/engines/wintermute/base/base_game.cpp b/engines/wintermute/base/base_game.cpp
index 5b88dab90e..b2c05d271d 100644
--- a/engines/wintermute/base/base_game.cpp
+++ b/engines/wintermute/base/base_game.cpp
@@ -3068,8 +3068,8 @@ bool BaseGame::persist(BasePersistenceManager *persistMgr) {
persistMgr->transfer(TMEMBER(_offsetX));
persistMgr->transfer(TMEMBER(_offsetY));
- persistMgr->transfer(TMEMBER(_offsetPercentX));
- persistMgr->transfer(TMEMBER(_offsetPercentY));
+ persistMgr->transferFloat(TMEMBER(_offsetPercentX));
+ persistMgr->transferFloat(TMEMBER(_offsetPercentY));
persistMgr->transfer(TMEMBER(_origInteractive));
persistMgr->transfer(TMEMBER_INT(_origState));
diff --git a/engines/wintermute/base/base_object.cpp b/engines/wintermute/base/base_object.cpp
index 9d5548be0f..ea754f8f23 100644
--- a/engines/wintermute/base/base_object.cpp
+++ b/engines/wintermute/base/base_object.cpp
@@ -968,9 +968,9 @@ bool BaseObject::persist(BasePersistenceManager *persistMgr) {
persistMgr->transfer(TMEMBER(_movable));
persistMgr->transfer(TMEMBER(_posX));
persistMgr->transfer(TMEMBER(_posY));
- persistMgr->transfer(TMEMBER(_relativeScale));
+ persistMgr->transferFloat(TMEMBER(_relativeScale));
persistMgr->transfer(TMEMBER(_rotatable));
- persistMgr->transfer(TMEMBER(_scale));
+ persistMgr->transferFloat(TMEMBER(_scale));
persistMgr->transferPtr(TMEMBER_PTR(_sFX));
persistMgr->transfer(TMEMBER(_sFXStart));
persistMgr->transfer(TMEMBER(_sFXVolume));
@@ -982,21 +982,21 @@ bool BaseObject::persist(BasePersistenceManager *persistMgr) {
persistMgr->transfer(TMEMBER(_soundEvent));
persistMgr->transfer(TMEMBER(_zoomable));
- persistMgr->transfer(TMEMBER(_scaleX));
- persistMgr->transfer(TMEMBER(_scaleY));
+ persistMgr->transferFloat(TMEMBER(_scaleX));
+ persistMgr->transferFloat(TMEMBER(_scaleY));
- persistMgr->transfer(TMEMBER(_rotate));
+ persistMgr->transferFloat(TMEMBER(_rotate));
persistMgr->transfer(TMEMBER(_rotateValid));
- persistMgr->transfer(TMEMBER(_relativeRotate));
+ persistMgr->transferFloat(TMEMBER(_relativeRotate));
persistMgr->transfer(TMEMBER(_saveState));
persistMgr->transfer(TMEMBER(_nonIntMouseEvents));
persistMgr->transfer(TMEMBER_INT(_sFXType));
- persistMgr->transfer(TMEMBER(_sFXParam1));
- persistMgr->transfer(TMEMBER(_sFXParam2));
- persistMgr->transfer(TMEMBER(_sFXParam3));
- persistMgr->transfer(TMEMBER(_sFXParam4));
+ persistMgr->transferFloat(TMEMBER(_sFXParam1));
+ persistMgr->transferFloat(TMEMBER(_sFXParam2));
+ persistMgr->transferFloat(TMEMBER(_sFXParam3));
+ persistMgr->transferFloat(TMEMBER(_sFXParam4));
persistMgr->transfer(TMEMBER_INT(_blendMode));
diff --git a/engines/wintermute/base/base_persistence_manager.cpp b/engines/wintermute/base/base_persistence_manager.cpp
index 6f0f7e289f..e5542d96b7 100644
--- a/engines/wintermute/base/base_persistence_manager.cpp
+++ b/engines/wintermute/base/base_persistence_manager.cpp
@@ -465,44 +465,53 @@ uint32 BasePersistenceManager::getDWORD() {
//////////////////////////////////////////////////////////////////////////
-void BasePersistenceManager::putString(const Common::String &val) {
- if (!val.size()) {
- putString("(null)");
- } else {
- _saveStream->writeUint32LE(val.size());
- _saveStream->writeString(val);
+void BasePersistenceManager::putString(const char *val) {
+ if (!val) {
+ _saveStream->writeUint32LE(0);
+ return;
}
-}
-
-Common::String BasePersistenceManager::getStringObj() {
- uint32 len = _loadStream->readUint32LE();
- char *ret = new char[len + 1];
- _loadStream->read(ret, len);
- ret[len] = '\0';
- Common::String retString = ret;
- delete[] ret;
+ uint32 len = strlen(val);
- if (retString == "(null)") {
- retString = "";
- }
+ _saveStream->writeUint32LE(len + 1);
+ _saveStream->write(val, len);
+}
- return retString;
+Common::String BasePersistenceManager::getStringObj() {
+ return getString();
}
//////////////////////////////////////////////////////////////////////////
char *BasePersistenceManager::getString() {
uint32 len = _loadStream->readUint32LE();
- char *ret = new char[len + 1];
- _loadStream->read(ret, len);
- ret[len] = '\0';
- if (!strcmp(ret, "(null)")) {
- delete[] ret;
- return nullptr;
+ if (checkVersion(1,2,2)) {
+ // Version 1.2.2 and above: len == strlen() + 1, NULL has len == 0
+
+ if (len == 0)
+ return nullptr;
+
+ char *ret = new char[len];
+ _loadStream->read(ret, len - 1);
+ ret[len - 1] = '\0';
+
+ return ret;
+
} else {
+
+ // Version 1.2.1 and older: NULL strings are represented as "(null)"
+ char *ret = new char[len + 1];
+ _loadStream->read(ret, len);
+ ret[len] = '\0';
+
+ if (!strcmp(ret, "(null)")) {
+ delete[] ret;
+ return nullptr;
+ }
+
return ret;
}
+
}
bool BasePersistenceManager::putTimeDate(const TimeDate &t) {
@@ -536,8 +545,7 @@ void BasePersistenceManager::putFloat(float val) {
int exponent = 0;
float significand = frexp(val, &exponent);
Common::String str = Common::String::format("FS%f", significand);
- _saveStream->writeUint32LE(str.size());
- _saveStream->writeString(str);
+ putString(str.c_str());
_saveStream->writeSint32LE(exponent);
}
@@ -559,8 +567,7 @@ void BasePersistenceManager::putDouble(double val) {
int exponent = 0;
double significand = frexp(val, &exponent);
Common::String str = Common::String::format("DS%f", significand);
- _saveStream->writeUint32LE(str.size());
- _saveStream->writeString(str);
+ putString(str.c_str());
_saveStream->writeSint32LE(exponent);
}
@@ -637,7 +644,7 @@ bool BasePersistenceManager::transfer(const char *name, uint32 *val) {
//////////////////////////////////////////////////////////////////////////
// float
-bool BasePersistenceManager::transfer(const char *name, float *val) {
+bool BasePersistenceManager::transferFloat(const char *name, float *val) {
if (_saving) {
putFloat(*val);
if (_saveStream->err()) {
@@ -711,7 +718,7 @@ bool BasePersistenceManager::transfer(const char *name, const char **val) {
// Common::String
bool BasePersistenceManager::transfer(const char *name, Common::String *val) {
if (_saving) {
- putString(*val);
+ putString(val->c_str());
return STATUS_OK;
} else {
char *str = getString();
diff --git a/engines/wintermute/base/base_persistence_manager.h b/engines/wintermute/base/base_persistence_manager.h
index 6949bfe278..3c0587b362 100644
--- a/engines/wintermute/base/base_persistence_manager.h
+++ b/engines/wintermute/base/base_persistence_manager.h
@@ -52,7 +52,7 @@ public:
void putDWORD(uint32 val);
char *getString();
Common::String getStringObj();
- void putString(const Common::String &val);
+ void putString(const char *val);
float getFloat();
void putFloat(float val);
double getDouble();
@@ -76,7 +76,7 @@ public:
bool transferPtr(const char *name, void *val);
bool transfer(const char *name, int32 *val);
bool transfer(const char *name, uint32 *val);
- bool transfer(const char *name, float *val);
+ bool transferFloat(const char *name, float *val);
bool transfer(const char *name, double *val);
bool transfer(const char *name, bool *val);
bool transfer(const char *name, byte *val);
diff --git a/engines/wintermute/base/base_region.cpp b/engines/wintermute/base/base_region.cpp
index 61e9deefb3..36036a1f18 100644
--- a/engines/wintermute/base/base_region.cpp
+++ b/engines/wintermute/base/base_region.cpp
@@ -432,7 +432,7 @@ bool BaseRegion::persist(BasePersistenceManager *persistMgr) {
persistMgr->transfer(TMEMBER(_active));
persistMgr->transfer(TMEMBER(_editorSelectedPoint));
- persistMgr->transfer(TMEMBER(_lastMimicScale));
+ persistMgr->transferFloat(TMEMBER(_lastMimicScale));
persistMgr->transfer(TMEMBER(_lastMimicX));
persistMgr->transfer(TMEMBER(_lastMimicY));
_points.persist(persistMgr);
diff --git a/engines/wintermute/base/font/base_font_truetype.cpp b/engines/wintermute/base/font/base_font_truetype.cpp
index 3059a69047..b6f372f377 100644
--- a/engines/wintermute/base/font/base_font_truetype.cpp
+++ b/engines/wintermute/base/font/base_font_truetype.cpp
@@ -272,7 +272,7 @@ BaseSurface *BaseFontTT::renderTextToTexture(const WideString &text, int width,
// void drawString(Surface *dst, const Common::String &str, int x, int y, int w, uint32 color, TextAlign align = kTextAlignLeft, int deltax = 0, bool useEllipsis = true) const;
Graphics::Surface *surface = new Graphics::Surface();
if (_deletableFont) { // We actually have a TTF
- surface->create((uint16)width, (uint16)(_lineHeight * lines.size()), Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24));
+ surface->create((uint16)width, (uint16)(_lineHeight * lines.size()), _gameRef->_renderer->getPixelFormat());
} else { // We are using a fallback, they can't do 32bpp
surface->create((uint16)width, (uint16)(_lineHeight * lines.size()), Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0));
}
@@ -285,7 +285,7 @@ BaseSurface *BaseFontTT::renderTextToTexture(const WideString &text, int width,
}
BaseSurface *retSurface = _gameRef->_renderer->createSurface();
- Graphics::Surface *convertedSurface = surface->convertTo(Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24));
+ Graphics::Surface *convertedSurface = surface->convertTo(_gameRef->_renderer->getPixelFormat());
retSurface->putSurface(*convertedSurface, true);
convertedSurface->free();
surface->free();
@@ -559,7 +559,7 @@ bool BaseFontTT::initFont() {
}
if (file) {
- _deletableFont = Graphics::loadTTFFont(*file, 96, _fontHeight); // Use the same dpi as WME (96 vs 72).
+ _deletableFont = Graphics::loadTTFFont(*file, _fontHeight, 96); // Use the same dpi as WME (96 vs 72).
_font = _deletableFont;
BaseFileManager::getEngineInstance()->closeFile(file);
file = nullptr;
diff --git a/engines/wintermute/base/gfx/base_renderer.h b/engines/wintermute/base/gfx/base_renderer.h
index 31dc2a022d..b6615bc8fc 100644
--- a/engines/wintermute/base/gfx/base_renderer.h
+++ b/engines/wintermute/base/gfx/base_renderer.h
@@ -84,7 +84,7 @@ public:
* @param a the alpha component to fade too.
* @param rect the portion of the screen to fade (if nullptr, the entire screen will be faded).
*/
- virtual void fadeToColor(byte r, byte g, byte b, byte a, Common::Rect *rect = nullptr) = 0;
+ virtual void fadeToColor(byte r, byte g, byte b, byte a) = 0;
virtual bool drawLine(int x1, int y1, int x2, int y2, uint32 color); // Unused outside indicator-display
virtual bool drawRect(int x1, int y1, int x2, int y2, uint32 color, int width = 1); // Unused outside indicator-display
diff --git a/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp b/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp
index b16cf60752..e4c19fde8b 100644
--- a/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp
+++ b/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp
@@ -84,7 +84,6 @@ BaseRenderOSystem::~BaseRenderOSystem() {
delete _renderSurface;
_blankSurface->free();
delete _blankSurface;
- TransparentSurface::destroyLookup();
}
//////////////////////////////////////////////////////////////////////////
@@ -127,7 +126,7 @@ bool BaseRenderOSystem::initRenderer(int width, int height, bool windowed) {
_windowed = !ConfMan.getBool("fullscreen");
- Graphics::PixelFormat format(4, 8, 8, 8, 8, 16, 8, 0, 24);
+ Graphics::PixelFormat format(4, 8, 8, 8, 8, 24, 16, 8, 0);
g_system->beginGFXTransaction();
g_system->initSize(_width, _height, &format);
OSystem::TransactionError gfxError = g_system->endGFXTransaction();
@@ -244,22 +243,16 @@ void BaseRenderOSystem::fade(uint16 alpha) {
}
//////////////////////////////////////////////////////////////////////////
-void BaseRenderOSystem::fadeToColor(byte r, byte g, byte b, byte a, Common::Rect *rect) {
+void BaseRenderOSystem::fadeToColor(byte r, byte g, byte b, byte a) {
Common::Rect fillRect;
- if (rect) {
- fillRect.left = rect->left;
- fillRect.top = rect->top;
- fillRect.setWidth(rect->width());
- fillRect.setHeight(rect->height());
- } else {
- Rect32 rc;
- _gameRef->getCurrentViewportRect(&rc);
- fillRect.left = (int16)rc.left;
- fillRect.top = (int16)rc.top;
- fillRect.setWidth((int16)(rc.right - rc.left));
- fillRect.setHeight((int16)(rc.bottom - rc.top));
- }
+ Rect32 rc;
+ _gameRef->getCurrentViewportRect(&rc);
+ fillRect.left = (int16)rc.left;
+ fillRect.top = (int16)rc.top;
+ fillRect.setWidth((int16)(rc.right - rc.left));
+ fillRect.setHeight((int16)(rc.bottom - rc.top));
+
modTargetRect(&fillRect);
//TODO: This is only here until I'm sure about the final pixelformat
@@ -613,8 +606,8 @@ bool BaseRenderOSystem::setViewport(int left, int top, int right, int bottom) {
// TODO: Hopefully this is the same logic that ScummVM uses.
rect.left = (int16)(left + _borderLeft);
rect.top = (int16)(top + _borderTop);
- rect.right = (int16)((right - left) * _ratioX);
- rect.bottom = (int16)((bottom - top) * _ratioY);
+ rect.setWidth((int16)((right - left) * _ratioX));
+ rect.setHeight((int16)((bottom - top) * _ratioY));
_renderRect = rect;
return STATUS_OK;
@@ -631,15 +624,13 @@ Rect32 BaseRenderOSystem::getViewPort() {
//////////////////////////////////////////////////////////////////////////
void BaseRenderOSystem::modTargetRect(Common::Rect *rect) {
- // FIXME: This is wrong in quite a few ways right now, and ends up
- // breaking the notebook in Dirty Split, so we disable the correction
- // for now, this will need fixing when a game with odd aspect-ratios
- // show up.
return;
- rect->left = (int16)MathUtil::round(rect->left * _ratioX + _borderLeft - _renderRect.left);
- rect->top = (int16)MathUtil::round(rect->top * _ratioY + _borderTop - _renderRect.top);
- rect->setWidth((int16)MathUtil::roundUp(rect->width() * _ratioX));
- rect->setHeight((int16)MathUtil::roundUp(rect->height() * _ratioY));
+ int newWidth = (int16)MathUtil::roundUp(rect->width() * _ratioX);
+ int newHeight = (int16)MathUtil::roundUp(rect->height() * _ratioY);
+ rect->left = (int16)MathUtil::round(rect->left * _ratioX + _borderLeft);
+ rect->top = (int16)MathUtil::round(rect->top * _ratioY + _borderTop);
+ rect->setWidth(newWidth);
+ rect->setHeight(newHeight);
}
//////////////////////////////////////////////////////////////////////////
diff --git a/engines/wintermute/base/gfx/osystem/base_render_osystem.h b/engines/wintermute/base/gfx/osystem/base_render_osystem.h
index bf2914b430..306563af3b 100644
--- a/engines/wintermute/base/gfx/osystem/base_render_osystem.h
+++ b/engines/wintermute/base/gfx/osystem/base_render_osystem.h
@@ -38,6 +38,25 @@
namespace Wintermute {
class BaseSurfaceOSystem;
class RenderTicket;
+/**
+ * A 2D-renderer implementation for WME.
+ * This renderer makes use of a "ticket"-system, where all draw-calls
+ * are stored as tickets until flip() is called, and compared against the tickets
+ * from last frame, to determine which calls were the same as last round
+ * (i.e. in the exact same order, with the exact same arguments), and thus
+ * figure out which parts of the screen need to be redrawn.
+ *
+ * Important concepts to handle here, is the ordered number of any ticket
+ * which is called the "drawNum", every frame this starts from scratch, and
+ * then the incoming tickets created from the draw-calls are checked to see whether
+ * they came before, on, or after the drawNum they had last frame. Everything else
+ * being equal, this information is then used to check whether the draw order changed,
+ * which will then create a need for redrawing, as we draw with an alpha-channel here.
+ *
+ * There is also a draw path that draws without tickets, for debugging purposes,
+ * as well as to accomodate situations with large enough amounts of draw calls,
+ * that there will be too much overhead involved with comparing the generated tickets.
+ */
class BaseRenderOSystem : public BaseRenderer {
public:
BaseRenderOSystem(BaseGame *inGame);
@@ -51,7 +70,7 @@ public:
bool fill(byte r, byte g, byte b, Common::Rect *rect = nullptr) override;
Graphics::PixelFormat getPixelFormat() const override;
void fade(uint16 alpha) override;
- void fadeToColor(byte r, byte g, byte b, byte a, Common::Rect *rect = nullptr) override;
+ void fadeToColor(byte r, byte g, byte b, byte a) override;
bool drawLine(int x1, int y1, int x2, int y2, uint32 color) override;
@@ -59,6 +78,11 @@ public:
void invalidateTicket(RenderTicket *renderTicket);
void invalidateTicketsFromSurface(BaseSurfaceOSystem *surf);
+ /**
+ * Insert a ticket into the queue, adding a dirty rect if it's
+ * new, or out-of-order from last draw from the ticket.
+ * param renderTicket the ticket to be added.
+ */
void drawFromTicket(RenderTicket *renderTicket);
bool setViewport(int left, int top, int right, int bottom) override;
@@ -79,11 +103,18 @@ public:
virtual bool startSpriteBatch() override;
virtual bool endSpriteBatch() override;
void endSaveLoad();
- void drawSurface(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, TransformStruct &transform);
+ void drawSurface(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, TransformStruct &transform);
void repeatLastDraw(int offsetX, int offsetY, int numTimesX, int numTimesY);
BaseSurface *createSurface() override;
private:
- void addDirtyRect(const Common::Rect &rect) ;
+ /**
+ * Mark a specified rect of the screen as dirty.
+ * @param rect the region to be marked as dirty
+ */
+ void addDirtyRect(const Common::Rect &rect);
+ /**
+ * Traverse the tickets that are dirty, and draw them
+ */
void drawTickets();
// Non-dirty-rects:
void drawFromSurface(RenderTicket *ticket);
@@ -96,7 +127,7 @@ private:
RenderTicket *_previousTicket;
bool _needsFlip;
- uint32 _drawNum;
+ uint32 _drawNum; ///< The global number of the current draw-operation.
Common::Rect _renderRect;
Graphics::Surface *_renderSurface;
Graphics::Surface *_blankSurface;
diff --git a/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp b/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp
index d4c5905c4b..14767aa067 100644
--- a/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp
+++ b/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp
@@ -48,7 +48,7 @@ namespace Wintermute {
BaseSurfaceOSystem::BaseSurfaceOSystem(BaseGame *inGame) : BaseSurface(inGame) {
_surface = new Graphics::Surface();
_alphaMask = nullptr;
- _hasAlpha = true;
+ _alphaType = TransparentSurface::ALPHA_FULL;
_lockPixels = nullptr;
_lockPitch = 0;
_loaded = false;
@@ -71,22 +71,37 @@ BaseSurfaceOSystem::~BaseSurfaceOSystem() {
renderer->invalidateTicketsFromSurface(this);
}
-bool hasTransparency(Graphics::Surface *surf) {
+TransparentSurface::AlphaType hasTransparencyType(const Graphics::Surface *surf) {
if (surf->format.bytesPerPixel != 4) {
- warning("hasTransparency:: non 32 bpp surface passed as argument");
- return false;
+ warning("hasTransparencyType:: non 32 bpp surface passed as argument");
+ return TransparentSurface::ALPHA_OPAQUE;
}
uint8 r, g, b, a;
+ bool seenAlpha = false;
+ bool seenFullAlpha = false;
for (int i = 0; i < surf->h; i++) {
+ if (seenFullAlpha) {
+ break;
+ }
for (int j = 0; j < surf->w; j++) {
- uint32 pix = *(uint32 *)surf->getBasePtr(j, i);
+ uint32 pix = *(const uint32 *)surf->getBasePtr(j, i);
surf->format.colorToARGB(pix, a, r, g, b);
if (a != 255) {
- return true;
+ seenAlpha = true;
+ if (a != 0) {
+ seenFullAlpha = true;
+ break;
+ }
}
}
}
- return false;
+ if (seenFullAlpha) {
+ return TransparentSurface::ALPHA_FULL;
+ } else if (seenAlpha) {
+ return TransparentSurface::ALPHA_BINARY;
+ } else {
+ return TransparentSurface::ALPHA_OPAQUE;
+ }
}
//////////////////////////////////////////////////////////////////////////
@@ -128,39 +143,36 @@ bool BaseSurfaceOSystem::finishLoad() {
_width = image->getSurface()->w;
_height = image->getSurface()->h;
- bool isSaveGameGrayscale = scumm_strnicmp(_filename.c_str(), "savegame:", 9) == 0 && (_filename.c_str()[_filename.size() - 1] == 'g' || _filename.c_str()[_filename.size() - 1] == 'G');
+ bool isSaveGameGrayscale = _filename.matchString("savegame:*g", true);
if (isSaveGameGrayscale) {
warning("grayscaleConversion not yet implemented");
// FIBITMAP *newImg = FreeImage_ConvertToGreyscale(img); TODO
}
- // no alpha, set color key
- /* if (surface->format.bytesPerPixel != 4)
- SDL_SetColorKey(surf, SDL_TRUE, SDL_MapRGB(surf->format, ck_red, ck_green, ck_blue));*/
-
- // convert 32-bit BMPs to 24-bit or they appear totally transparent (does any app actually write alpha in BMP properly?)
- // Well, actually, we don't convert via 24-bit as the color-key application overwrites the Alpha-channel anyhow.
_surface->free();
delete _surface;
bool needsColorKey = false;
bool replaceAlpha = true;
- if (_filename.hasSuffix(".bmp") && image->getSurface()->format.bytesPerPixel == 4) {
- _surface = image->getSurface()->convertTo(g_system->getScreenFormat(), image->getPalette());
- needsColorKey = true;
- replaceAlpha = false;
- } else if (image->getSurface()->format.bytesPerPixel == 1 && image->getPalette()) {
+ if (image->getSurface()->format.bytesPerPixel == 1) {
+ if (!image->getPalette()) {
+ error("Missing palette while loading 8bit image %s", _filename.c_str());
+ }
_surface = image->getSurface()->convertTo(g_system->getScreenFormat(), image->getPalette());
needsColorKey = true;
- } else if (image->getSurface()->format.bytesPerPixel >= 3 && image->getSurface()->format != g_system->getScreenFormat()) {
- _surface = image->getSurface()->convertTo(g_system->getScreenFormat());
- if (image->getSurface()->format.bytesPerPixel == 3) {
- needsColorKey = true;
- }
} else {
- _surface = new Graphics::Surface();
- _surface->copyFrom(*image->getSurface());
- if (_surface->format.aBits() == 0) {
+ if (image->getSurface()->format != g_system->getScreenFormat()) {
+ _surface = image->getSurface()->convertTo(g_system->getScreenFormat());
+ } else {
+ _surface = new Graphics::Surface();
+ _surface->copyFrom(*image->getSurface());
+ }
+
+ if (_filename.hasSuffix(".bmp") && image->getSurface()->format.bytesPerPixel == 4) {
+ // 32 bpp BMPs have nothing useful in their alpha-channel -> color-key
+ needsColorKey = true;
+ replaceAlpha = false;
+ } else if (image->getSurface()->format.aBits() == 0) {
needsColorKey = true;
}
}
@@ -170,7 +182,7 @@ bool BaseSurfaceOSystem::finishLoad() {
trans.applyColorKey(_ckRed, _ckGreen, _ckBlue, replaceAlpha);
}
- _hasAlpha = hasTransparency(_surface);
+ _alphaType = hasTransparencyType(_surface);
_valid = true;
_gameRef->addMem(_width * _height * 4);
@@ -409,8 +421,6 @@ bool BaseSurfaceOSystem::drawSprite(int x, int y, Rect32 *rect, Rect32 *newRect,
if (newRect) {
position.top = y;
position.left = x;
- position.right = x + newRect->width();
- position.bottom = y + newRect->height();
position.setWidth(newRect->width());
position.setHeight(newRect->height());
} else {
@@ -422,17 +432,11 @@ bool BaseSurfaceOSystem::drawSprite(int x, int y, Rect32 *rect, Rect32 *newRect,
// TODO: This actually requires us to have the SAME source-offsets every time,
// But no checking is in place for that yet.
- // TODO: Optimize by not doing alpha-blits if we lack or disable alpha
-
- bool hasAlpha = false;
-
- if (_hasAlpha && !transform._alphaDisable) {
- hasAlpha = true;
- }
-
- if (transform._alphaDisable) {
- warning("BaseSurfaceOSystem::drawSprite - AlphaDisable ignored");
+ // Optimize by not doing alpha-blits if we lack alpha
+ if (_alphaType == TransparentSurface::ALPHA_OPAQUE && !transform._alphaDisable) {
+ transform._alphaDisable = true;
}
+
renderer->drawSurface(this, _surface, &srcRect, &position, transform);
return STATUS_OK;
}
@@ -447,7 +451,11 @@ bool BaseSurfaceOSystem::putSurface(const Graphics::Surface &surface, bool hasAl
_loaded = true;
_surface->free();
_surface->copyFrom(surface);
- _hasAlpha = hasAlpha;
+ if (hasAlpha) {
+ _alphaType = TransparentSurface::ALPHA_FULL;
+ } else {
+ _alphaType = TransparentSurface::ALPHA_OPAQUE;
+ }
BaseRenderOSystem *renderer = static_cast<BaseRenderOSystem *>(_gameRef->_renderer);
renderer->invalidateTicketsFromSurface(this);
diff --git a/engines/wintermute/base/gfx/osystem/base_surface_osystem.h b/engines/wintermute/base/gfx/osystem/base_surface_osystem.h
index da86833517..6cf19d00fb 100644
--- a/engines/wintermute/base/gfx/osystem/base_surface_osystem.h
+++ b/engines/wintermute/base/gfx/osystem/base_surface_osystem.h
@@ -30,6 +30,7 @@
#define WINTERMUTE_BASE_SURFACESDL_H
#include "graphics/surface.h"
+#include "engines/wintermute/graphics/transparent_surface.h"
#include "engines/wintermute/base/gfx/base_surface.h"
#include "common/list.h"
@@ -81,6 +82,7 @@ public:
return _height;
}
+ TransparentSurface::AlphaType getAlphaType() const { return _alphaType; }
private:
Graphics::Surface *_surface;
bool _loaded;
@@ -90,7 +92,7 @@ private:
uint32 getPixelAt(Graphics::Surface *surface, int x, int y);
uint32 _rotation;
- bool _hasAlpha;
+ TransparentSurface::AlphaType _alphaType;
void *_lockPixels;
int _lockPitch;
byte *_alphaMask;
diff --git a/engines/wintermute/base/gfx/osystem/render_ticket.cpp b/engines/wintermute/base/gfx/osystem/render_ticket.cpp
index 98739e0778..b1720c1b0b 100644
--- a/engines/wintermute/base/gfx/osystem/render_ticket.cpp
+++ b/engines/wintermute/base/gfx/osystem/render_ticket.cpp
@@ -28,6 +28,7 @@
#include "engines/wintermute/base/gfx/osystem/render_ticket.h"
+#include "engines/wintermute/base/gfx/osystem/base_surface_osystem.h"
#include "engines/wintermute/graphics/transform_tools.h"
#include "common/textconsole.h"
@@ -104,7 +105,13 @@ void RenderTicket::drawToSurface(Graphics::Surface *_targetSurface) const {
clipRect.setWidth(getSurface()->w);
clipRect.setHeight(getSurface()->h);
- src._enableAlphaBlit = !_transform._alphaDisable;
+ if (_owner) {
+ if (_transform._alphaDisable) {
+ src._alphaMode = TransparentSurface::ALPHA_OPAQUE;
+ } else {
+ src._alphaMode = _owner->getAlphaType();
+ }
+ }
src.blit(*_targetSurface, _dstRect.left, _dstRect.top, _transform._flip, &clipRect, _transform._rgbaMod, clipRect.width(), clipRect.height());
}
@@ -118,7 +125,13 @@ void RenderTicket::drawToSurface(Graphics::Surface *_targetSurface, Common::Rect
clipRect->setHeight(getSurface()->h);
}
- src._enableAlphaBlit = !_transform._alphaDisable;
+ if (_owner) {
+ if (_transform._alphaDisable) {
+ src._alphaMode = TransparentSurface::ALPHA_OPAQUE;
+ } else {
+ src._alphaMode = _owner->getAlphaType();
+ }
+ }
src.blit(*_targetSurface, dstRect->left, dstRect->top, _transform._flip, clipRect, _transform._rgbaMod, clipRect->width(), clipRect->height());
if (doDelete) {
delete clipRect;
diff --git a/engines/wintermute/base/gfx/osystem/render_ticket.h b/engines/wintermute/base/gfx/osystem/render_ticket.h
index b1313e932d..875102d01c 100644
--- a/engines/wintermute/base/gfx/osystem/render_ticket.h
+++ b/engines/wintermute/base/gfx/osystem/render_ticket.h
@@ -36,6 +36,19 @@
namespace Wintermute {
class BaseSurfaceOSystem;
+/**
+ * A single RenderTicket.
+ * A render ticket is a collection of the data and draw specifications made
+ * for a single draw-call in the OSystem-backend for WME. The ticket additionally
+ * holds the order in which this call was made, so that it can be detected if
+ * the same call is done in the following frame. Thus allowing us to potentially
+ * skip drawing the same region again, unless anything has changed. Since a surface
+ * can have a potentially large amount of draw-calls made to it, at varying rotation,
+ * zoom, and crop-levels we also need to hold a copy of the necessary data.
+ * (Video-surfaces may even change their data). The promise that is made when a ticket
+ * is created is that what the state was of the surface at THAT point, is what will end
+ * up on screen at flip() time.
+ */
class RenderTicket {
public:
RenderTicket(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRest, TransformStruct transform);
diff --git a/engines/wintermute/base/particles/part_emitter.cpp b/engines/wintermute/base/particles/part_emitter.cpp
index 5c21988141..aaffa0965a 100644
--- a/engines/wintermute/base/particles/part_emitter.cpp
+++ b/engines/wintermute/base/particles/part_emitter.cpp
@@ -1163,12 +1163,12 @@ bool PartEmitter::persist(BasePersistenceManager *persistMgr) {
persistMgr->transfer(TMEMBER(_angle1));
persistMgr->transfer(TMEMBER(_angle2));
- persistMgr->transfer(TMEMBER(_velocity1));
- persistMgr->transfer(TMEMBER(_velocity2));
+ persistMgr->transferFloat(TMEMBER(_velocity1));
+ persistMgr->transferFloat(TMEMBER(_velocity2));
persistMgr->transfer(TMEMBER(_velocityZBased));
- persistMgr->transfer(TMEMBER(_scale1));
- persistMgr->transfer(TMEMBER(_scale2));
+ persistMgr->transferFloat(TMEMBER(_scale1));
+ persistMgr->transferFloat(TMEMBER(_scale2));
persistMgr->transfer(TMEMBER(_scaleZBased));
persistMgr->transfer(TMEMBER(_maxParticles));
@@ -1196,14 +1196,14 @@ bool PartEmitter::persist(BasePersistenceManager *persistMgr) {
persistMgr->transfer(TMEMBER(_alpha2));
persistMgr->transfer(TMEMBER(_alphaTimeBased));
- persistMgr->transfer(TMEMBER(_angVelocity1));
- persistMgr->transfer(TMEMBER(_angVelocity2));
+ persistMgr->transferFloat(TMEMBER(_angVelocity1));
+ persistMgr->transferFloat(TMEMBER(_angVelocity2));
- persistMgr->transfer(TMEMBER(_rotation1));
- persistMgr->transfer(TMEMBER(_rotation2));
+ persistMgr->transferFloat(TMEMBER(_rotation1));
+ persistMgr->transferFloat(TMEMBER(_rotation2));
- persistMgr->transfer(TMEMBER(_growthRate1));
- persistMgr->transfer(TMEMBER(_growthRate2));
+ persistMgr->transferFloat(TMEMBER(_growthRate1));
+ persistMgr->transferFloat(TMEMBER(_growthRate2));
persistMgr->transfer(TMEMBER(_exponentialGrowth));
persistMgr->transfer(TMEMBER(_useRegion));
diff --git a/engines/wintermute/base/particles/part_particle.cpp b/engines/wintermute/base/particles/part_particle.cpp
index 2ae867fd42..86cacacb5c 100644
--- a/engines/wintermute/base/particles/part_particle.cpp
+++ b/engines/wintermute/base/particles/part_particle.cpp
@@ -234,9 +234,9 @@ bool PartParticle::persist(BasePersistenceManager *persistMgr) {
persistMgr->transfer(TMEMBER(_alpha2));
persistMgr->transfer(TMEMBER(_border));
persistMgr->transfer(TMEMBER(_pos));
- persistMgr->transfer(TMEMBER(_posZ));
+ persistMgr->transferFloat(TMEMBER(_posZ));
persistMgr->transfer(TMEMBER(_velocity));
- persistMgr->transfer(TMEMBER(_scale));
+ persistMgr->transferFloat(TMEMBER(_scale));
persistMgr->transfer(TMEMBER(_creationTime));
persistMgr->transfer(TMEMBER(_lifeTime));
persistMgr->transfer(TMEMBER(_isDead));
@@ -244,9 +244,9 @@ bool PartParticle::persist(BasePersistenceManager *persistMgr) {
persistMgr->transfer(TMEMBER(_fadeStart));
persistMgr->transfer(TMEMBER(_fadeTime));
persistMgr->transfer(TMEMBER(_currentAlpha));
- persistMgr->transfer(TMEMBER(_angVelocity));
- persistMgr->transfer(TMEMBER(_rotation));
- persistMgr->transfer(TMEMBER(_growthRate));
+ persistMgr->transferFloat(TMEMBER(_angVelocity));
+ persistMgr->transferFloat(TMEMBER(_rotation));
+ persistMgr->transferFloat(TMEMBER(_growthRate));
persistMgr->transfer(TMEMBER(_exponentialGrowth));
persistMgr->transfer(TMEMBER(_fadeStartAlpha));
diff --git a/engines/wintermute/base/scriptables/script_engine.cpp b/engines/wintermute/base/scriptables/script_engine.cpp
index dd24457d6c..bb819b23e4 100644
--- a/engines/wintermute/base/scriptables/script_engine.cpp
+++ b/engines/wintermute/base/scriptables/script_engine.cpp
@@ -362,6 +362,8 @@ bool ScEngine::tick() {
//////////////////////////////////////////////////////////////////////////
bool ScEngine::tickUnbreakable() {
+ ScScript *oldScript = _currentScript;
+
// execute unbreakable scripts
for (uint32 i = 0; i < _scripts.size(); i++) {
if (!_scripts[i]->_unbreakable) {
@@ -373,9 +375,12 @@ bool ScEngine::tickUnbreakable() {
_scripts[i]->executeInstruction();
}
_scripts[i]->finish();
- _currentScript = nullptr;
+ _currentScript = oldScript;
}
- removeFinishedScripts();
+
+ // NB: Don't remove finished scripts here since we could be recursively
+ // executing scripts. Doing so could invalidate the outer iteration in
+ // ::tick() over _scripts.
return STATUS_OK;
}
diff --git a/engines/wintermute/base/scriptables/script_value.cpp b/engines/wintermute/base/scriptables/script_value.cpp
index 3532e127d0..31ec457df1 100644
--- a/engines/wintermute/base/scriptables/script_value.cpp
+++ b/engines/wintermute/base/scriptables/script_value.cpp
@@ -827,6 +827,17 @@ bool ScValue::persist(BasePersistenceManager *persistMgr) {
persistMgr->transferPtr(TMEMBER_PTR(_valRef));
persistMgr->transfer(TMEMBER(_valString));
+ if (!persistMgr->getIsSaving() && !persistMgr->checkVersion(1,2,2)) {
+ // Savegames prior to 1.2.2 stored empty strings as NULL.
+ // We disambiguate those by turning NULL strings into empty
+ // strings if _type is VAL_STRING instead of VAL_NULL.
+
+ if (_type == VAL_STRING && !_valString) {
+ _valString = new char[1];
+ _valString[0] = '\0';
+ }
+ }
+
/* // TODO: Convert to Debug-statements.
FILE* f = fopen("c:\\val.log", "a+");
switch(_type)
diff --git a/engines/wintermute/dcgf.h b/engines/wintermute/dcgf.h
index fe92194443..3db443965e 100644
--- a/engines/wintermute/dcgf.h
+++ b/engines/wintermute/dcgf.h
@@ -33,7 +33,7 @@
//////////////////////////////////////////////////////////////////////////
#define DCGF_VER_MAJOR 1
#define DCGF_VER_MINOR 2
-#define DCGF_VER_BUILD 1
+#define DCGF_VER_BUILD 2
#define DCGF_VER_SUFFIX "ScummVM"
#define DCGF_VER_BETA true
diff --git a/engines/wintermute/detection_tables.h b/engines/wintermute/detection_tables.h
index 702c0b28ba..63f5078c12 100644
--- a/engines/wintermute/detection_tables.h
+++ b/engines/wintermute/detection_tables.h
@@ -40,16 +40,20 @@ static const PlainGameDescriptor wintermuteGames[] = {
{"dreaming", "Des Reves Elastiques Avec Mille Insectes Nommes Georges"},
{"dirtysplit", "Dirty Split"},
{"dreamscape", "Dreamscape"},
+ {"escapemansion", "Escape from the Mansion"},
{"ghostsheet", "Ghost in the Sheet"},
{"hamlet", "Hamlet or the last game without MMORPS features, shaders and product placement"},
{"jamesperis", "James Peris: No License Nor Control"},
+ {"looky", "Looky"},
{"julia", "J.U.L.I.A."},
{"mirage", "Mirage"},
{"pigeons", "Pigeons in the Park"},
{"reversion1", "Reversion: The Escape"},
{"reversion2", "Reversion: The Meeting"},
{"rosemary", "Rosemary"},
+ {"shaban", "Shaban"},
{"shinestar", "The Shine of a Star"},
+ {"spacemadness", "Space Madness"},
{"thebox", "The Box"},
{"tib", "Fairy Tales About Toshechka and Boshechka"},
{"tradestory", "The Trader of Stories"},
@@ -284,6 +288,26 @@ static const ADGameDescription gameDescriptions[] = {
ADGF_UNSTABLE,
GUIO0()
},
+ // Escape from the Mansion
+ {
+ "escapemansion",
+ "Beta 1",
+ AD_ENTRY1s("data.dcp", "d8e348b2312cc36a929cad75f12e0b3a", 21452380),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE,
+ GUIO0()
+ },
+ // Escape from the Mansion
+ {
+ "escapemansion",
+ "Beta 2",
+ AD_ENTRY1s("data.dcp", "ded5fa6c5f2afdaf2cafb53e52cd3dd8", 21455763),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE,
+ GUIO0()
+ },
// Ghosts in the Sheet
{
"ghostsheet",
@@ -379,6 +403,48 @@ static const ADGameDescription gameDescriptions[] = {
ADGF_DEMO,
GUIO0()
},
+ // Looky Demo (English)
+ {
+ "looky",
+ "Demo",
+ {
+ {"english.dcp", 0, "1388e1dd320f4d553dea3b0316812f9d", 1358442},
+ {"data.dcp", 0, "7074bcd7bc7ad7eb04c271aafb964c32", 13815660},
+ AD_LISTEND
+ },
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE,
+ GUIO0()
+ },
+ // Looky Demo (German)
+ {
+ "looky",
+ "Demo",
+ {
+ {"german.dcp", 0, "606c048426dfbe94442b59fd34a5c76e", 14339496},
+ {"data.dcp", 0, "7074bcd7bc7ad7eb04c271aafb964c32", 13815660},
+ AD_LISTEND
+ },
+ Common::DE_DEU,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE,
+ GUIO0()
+ },
+ // Looky (German)
+ {
+ "looky",
+ "",
+ {
+ {"german.dcp", 0, "bf4c2b8c26342342441a6d64934ab832", 107027865},
+ {"data.dcp", 0, "50de0beaa5ad621aa9f020df901d1e74", 1342214},
+ AD_LISTEND
+ },
+ Common::DE_DEU,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE,
+ GUIO0()
+ },
// Mirage
{
"mirage",
@@ -625,6 +691,16 @@ static const ADGameDescription gameDescriptions[] = {
ADGF_UNSTABLE,
GUIO0()
},
+ // Shaban
+ {
+ "shaban",
+ "",
+ AD_ENTRY1s("data.dcp", "35f702ca9baabc5c620e0be230195c8a", 755388466),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE,
+ GUIO0()
+ },
// The Shine of a Star
{
"shinestar",
@@ -635,6 +711,16 @@ static const ADGameDescription gameDescriptions[] = {
ADGF_UNSTABLE,
GUIO0()
},
+ // Space Madness
+ {
+ "spacemadness",
+ "1.0.2",
+ AD_ENTRY1s("data.dcp", "b9b83135dc7a9e1b4b5f50195dbeb630", 39546622),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE,
+ GUIO0()
+ },
// The Box
{
"thebox",
diff --git a/engines/wintermute/graphics/transparent_surface.cpp b/engines/wintermute/graphics/transparent_surface.cpp
index df6286e37a..cd200354f7 100644
--- a/engines/wintermute/graphics/transparent_surface.cpp
+++ b/engines/wintermute/graphics/transparent_surface.cpp
@@ -140,16 +140,9 @@ void TransparentSurface::copyPixelNearestNeighbor(float projX, float projY, int
}
#endif
-byte *TransparentSurface::_lookup = nullptr;
+TransparentSurface::TransparentSurface() : Surface(), _alphaMode(ALPHA_FULL) {}
-void TransparentSurface::destroyLookup() {
- delete[] _lookup;
- _lookup = nullptr;
-}
-
-TransparentSurface::TransparentSurface() : Surface(), _enableAlphaBlit(true) {}
-
-TransparentSurface::TransparentSurface(const Surface &surf, bool copyData) : Surface(), _enableAlphaBlit(true) {
+TransparentSurface::TransparentSurface(const Surface &surf, bool copyData) : Surface(), _alphaMode(ALPHA_FULL) {
if (copyData) {
copyFrom(surf);
} else {
@@ -168,9 +161,9 @@ void doBlitOpaque(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pit
byte *in, *out;
#ifdef SCUMM_LITTLE_ENDIAN
- const int aIndex = 3;
-#else
const int aIndex = 0;
+#else
+ const int aIndex = 3;
#endif
for (uint32 i = 0; i < height; i++) {
@@ -186,42 +179,60 @@ void doBlitOpaque(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pit
}
}
-void TransparentSurface::generateLookup() {
- _lookup = new byte[256 * 256];
- for (int i = 0; i < 256; i++) {
- for (int j = 0; j < 256; j++) {
- _lookup[(i << 8) + j] = (i * j) >> 8;
+void doBlitBinary(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep) {
+ byte *in, *out;
+
+#ifdef SCUMM_LITTLE_ENDIAN
+ const int aIndex = 0;
+#else
+ const int aIndex = 3;
+#endif
+ const int aShift = 0;//img->format.aShift;
+
+ for (uint32 i = 0; i < height; i++) {
+ out = outo;
+ in = ino;
+ for (uint32 j = 0; j < width; j++) {
+ uint32 pix = *(uint32 *)in;
+ int a = (pix >> aShift) & 0xff;
+ in += inStep;
+
+ if (a == 0) { // Full transparency
+ out += 4;
+ } else { // Full opacity (Any value not exactly 0 is Opaque here)
+ *(uint32 *)out = pix;
+ out[aIndex] = 0xFF;
+ out += 4;
+ }
}
+ outo += pitch;
+ ino += inoStep;
}
}
-void TransparentSurface::doBlitAlpha(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep) {
+void doBlitAlpha(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep) {
byte *in, *out;
- if (!_lookup) {
- generateLookup();
- }
-
#ifdef SCUMM_LITTLE_ENDIAN
- const int aIndex = 3;
- const int bIndex = 0;
- const int gIndex = 1;
- const int rIndex = 2;
-#else
const int aIndex = 0;
- const int bIndex = 3;
+ const int bIndex = 1;
const int gIndex = 2;
- const int rIndex = 1;
+ const int rIndex = 3;
+#else
+ const int aIndex = 3;
+ const int bIndex = 2;
+ const int gIndex = 1;
+ const int rIndex = 0;
#endif
- const int bShift = 0;//img->format.bShift;
- const int gShift = 8;//img->format.gShift;
- const int rShift = 16;//img->format.rShift;
- const int aShift = 24;//img->format.aShift;
+ const int bShift = 8;//img->format.bShift;
+ const int gShift = 16;//img->format.gShift;
+ const int rShift = 24;//img->format.rShift;
+ const int aShift = 0;//img->format.aShift;
- const int bShiftTarget = 0;//target.format.bShift;
- const int gShiftTarget = 8;//target.format.gShift;
- const int rShiftTarget = 16;//target.format.rShift;
+ const int bShiftTarget = 8;//target.format.bShift;
+ const int gShiftTarget = 16;//target.format.gShift;
+ const int rShiftTarget = 24;//target.format.rShift;
for (uint32 i = 0; i < height; i++) {
out = outo;
@@ -255,13 +266,9 @@ void TransparentSurface::doBlitAlpha(byte *ino, byte *outo, uint32 width, uint32
default: // alpha blending
outa = 255;
-
- outb = _lookup[(((oPix >> bShiftTarget) & 0xff)) + ((255 - a) << 8)];
- outg = _lookup[(((oPix >> gShiftTarget) & 0xff)) + ((255 - a) << 8)];
- outr = _lookup[(((oPix >> rShiftTarget) & 0xff)) + ((255 - a) << 8)];
- outb += _lookup[b + (a << 8)];
- outg += _lookup[g + (a << 8)];
- outr += _lookup[r + (a << 8)];
+ outb = ((b * a) + ((oPix >> bShiftTarget) & 0xff) * (255-a)) >> 8;
+ outg = ((g * a) + ((oPix >> gShiftTarget) & 0xff) * (255-a)) >> 8;
+ outr = ((r * a) + ((oPix >> rShiftTarget) & 0xff) * (255-a)) >> 8;
out[aIndex] = outa;
out[bIndex] = outb;
@@ -292,14 +299,6 @@ Common::Rect TransparentSurface::blit(Graphics::Surface &target, int posX, int p
int cg = (color >> 8) & 0xff;
int cb = (color >> 0) & 0xff;
- // Compensate for transparency. Since we're coming
- // down to 255 alpha, we just compensate for the colors here
- if (ca != 255) {
- cr = cr * ca >> 8;
- cg = cg * ca >> 8;
- cb = cb * ca >> 8;
- }
-
// Create an encapsulating surface for the data
TransparentSurface srcImage(*this, false);
// TODO: Is the data really in the screen format?
@@ -309,7 +308,19 @@ Common::Rect TransparentSurface::blit(Graphics::Surface &target, int posX, int p
}
if (pPartRect) {
- srcImage.pixels = getBasePtr(pPartRect->left, pPartRect->top);
+
+ int xOffset = pPartRect->left;
+ int yOffset = pPartRect->top;
+
+ if (flipping & FLIP_V) {
+ yOffset = srcImage.h - pPartRect->bottom;
+ }
+
+ if (flipping & FLIP_H) {
+ xOffset = srcImage.w - pPartRect->right;
+ }
+
+ srcImage.pixels = getBasePtr(xOffset, yOffset);
srcImage.w = pPartRect->width();
srcImage.h = pPartRect->height();
@@ -379,29 +390,32 @@ Common::Rect TransparentSurface::blit(Graphics::Surface &target, int posX, int p
byte *in, *out;
#ifdef SCUMM_LITTLE_ENDIAN
- const int aIndex = 3;
- const int bIndex = 0;
- const int gIndex = 1;
- const int rIndex = 2;
-#else
const int aIndex = 0;
- const int bIndex = 3;
+ const int bIndex = 1;
const int gIndex = 2;
- const int rIndex = 1;
+ const int rIndex = 3;
+#else
+ const int aIndex = 3;
+ const int bIndex = 2;
+ const int gIndex = 1;
+ const int rIndex = 0;
#endif
- const int bShift = 0;//img->format.bShift;
- const int gShift = 8;//img->format.gShift;
- const int rShift = 16;//img->format.rShift;
- const int aShift = 24;//img->format.aShift;
- const int bShiftTarget = 0;//target.format.bShift;
- const int gShiftTarget = 8;//target.format.gShift;
- const int rShiftTarget = 16;//target.format.rShift;
+ const int bShift = 8;//img->format.bShift;
+ const int gShift = 16;//img->format.gShift;
+ const int rShift = 24;//img->format.rShift;
+ const int aShift = 0;//img->format.aShift;
+
+ const int bShiftTarget = 8;//target.format.bShift;
+ const int gShiftTarget = 16;//target.format.gShift;
+ const int rShiftTarget = 24;//target.format.rShift;
if (ca == 255 && cb == 255 && cg == 255 && cr == 255) {
- if (_enableAlphaBlit) {
+ if (_alphaMode == ALPHA_FULL) {
doBlitAlpha(ino, outo, img->w, img->h, target.pitch, inStep, inoStep);
- } else {
+ } else if (_alphaMode == ALPHA_BINARY) {
+ doBlitBinary(ino, outo, img->w, img->h, target.pitch, inStep, inoStep);
+ } else if (_alphaMode == ALPHA_OPAQUE) {
doBlitOpaque(ino, outo, img->w, img->h, target.pitch, inStep, inoStep);
}
} else {
@@ -421,7 +435,6 @@ Common::Rect TransparentSurface::blit(Graphics::Surface &target, int posX, int p
if (ca != 255) {
a = a * ca >> 8;
}
-
switch (a) {
case 0: // Full transparency
out += 4;
@@ -451,27 +464,27 @@ Common::Rect TransparentSurface::blit(Graphics::Surface &target, int posX, int p
default: // alpha blending
outa = 255;
- outb = (o_pix >> bShiftTarget) & 0xff;
- outg = (o_pix >> gShiftTarget) & 0xff;
- outr = (o_pix >> rShiftTarget) & 0xff;
+ outb = ((o_pix >> bShiftTarget) & 0xff) * (255 - a);
+ outg = ((o_pix >> gShiftTarget) & 0xff) * (255 - a);
+ outr = ((o_pix >> rShiftTarget) & 0xff) * (255 - a);
if (cb == 0)
- outb = 0;
+ outb = outb >> 8;
else if (cb != 255)
- outb += ((b - outb) * a * cb) >> 16;
+ outb = ((outb<<8) + b * a * cb) >> 16;
else
- outb += ((b - outb) * a) >> 8;
+ outb = (outb + b * a) >> 8;
if (cg == 0)
- outg = 0;
+ outg = outg >> 8;
else if (cg != 255)
- outg += ((g - outg) * a * cg) >> 16;
+ outg = ((outg<<8) + g * a * cg) >> 16;
else
- outg += ((g - outg) * a) >> 8;
+ outg = (outg + g * a) >> 8;
if (cr == 0)
- outr = 0;
+ outr = outr >> 8;
else if (cr != 255)
- outr += ((r - outr) * a * cr) >> 16;
+ outr = ((outr<<8) + r * a * cr) >> 16;
else
- outr += ((r - outr) * a) >> 8;
+ outr = (outr + r * a) >> 8;
out[aIndex] = outa;
out[bIndex] = outb;
out[gIndex] = outg;
diff --git a/engines/wintermute/graphics/transparent_surface.h b/engines/wintermute/graphics/transparent_surface.h
index 9d06f3e006..598aaa55d7 100644
--- a/engines/wintermute/graphics/transparent_surface.h
+++ b/engines/wintermute/graphics/transparent_surface.h
@@ -75,7 +75,13 @@ struct TransparentSurface : public Graphics::Surface {
FLIP_VH = FLIP_H | FLIP_V
};
- bool _enableAlphaBlit;
+ enum AlphaType {
+ ALPHA_OPAQUE = 0,
+ ALPHA_BINARY = 1,
+ ALPHA_FULL = 2
+ };
+
+ AlphaType _alphaMode;
/**
@brief renders the surface to another surface
@@ -114,11 +120,6 @@ struct TransparentSurface : public Graphics::Surface {
TransparentSurface *scale(uint16 newWidth, uint16 newHeight) const;
TransparentSurface *rotoscale(const TransformStruct &transform) const;
- static byte *_lookup;
- static void destroyLookup();
-private:
- static void doBlitAlpha(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep);
- static void generateLookup();
};
/**
diff --git a/engines/wintermute/utils/string_util.cpp b/engines/wintermute/utils/string_util.cpp
index 23abb5d579..e8e078aba8 100644
--- a/engines/wintermute/utils/string_util.cpp
+++ b/engines/wintermute/utils/string_util.cpp
@@ -146,26 +146,21 @@ Utf8String StringUtil::wideToUtf8(const WideString &WideStr) {
return "";
}
-// Currently this only does Ansi->ISO 8859, and only for carets.
-char simpleAnsiToWide(const AnsiString &str, uint32 &offset) {
- byte c = str[offset];
-
- if (c == 146) {
- offset++;
- return 39; // Replace right-quote with apostrophe
- } else {
- offset++;
- return c;
- }
-}
-
//////////////////////////////////////////////////////////////////////////
WideString StringUtil::ansiToWide(const AnsiString &str) {
// TODO: This function gets called a lot, so warnings like these drown out the usefull information
Common::String converted = "";
uint32 index = 0;
while (index != str.size()) {
- converted += simpleAnsiToWide(str, index);
+ byte c = str[index];
+ if (c == 146) {
+ converted += (char)39; // Replace right-quote with apostrophe
+ } else if (c == 133) {
+ converted += Common::String("..."); // Replace ...-symbol with ...
+ } else {
+ converted += c;
+ }
+ index++;
}
// using default os locale!
diff --git a/engines/wintermute/video/video_theora_player.cpp b/engines/wintermute/video/video_theora_player.cpp
index ef4d6b4dd9..f3317684b5 100644
--- a/engines/wintermute/video/video_theora_player.cpp
+++ b/engines/wintermute/video/video_theora_player.cpp
@@ -498,7 +498,7 @@ bool VideoTheoraPlayer::persist(BasePersistenceManager *persistMgr) {
persistMgr->transfer(TMEMBER(_alphaFilename));
persistMgr->transfer(TMEMBER(_posX));
persistMgr->transfer(TMEMBER(_posY));
- persistMgr->transfer(TMEMBER(_playZoom));
+ persistMgr->transferFloat(TMEMBER(_playZoom));
persistMgr->transfer(TMEMBER_INT(_playbackType));
persistMgr->transfer(TMEMBER(_looping));
persistMgr->transfer(TMEMBER(_volume));
diff --git a/engines/wintermute/wintermute.cpp b/engines/wintermute/wintermute.cpp
index a878944661..0a6be4caf8 100644
--- a/engines/wintermute/wintermute.cpp
+++ b/engines/wintermute/wintermute.cpp
@@ -105,7 +105,7 @@ bool WintermuteEngine::hasFeature(EngineFeature f) const {
Common::Error WintermuteEngine::run() {
// Initialize graphics using following:
- Graphics::PixelFormat format(4, 8, 8, 8, 8, 16, 8, 0, 24);
+ Graphics::PixelFormat format(4, 8, 8, 8, 8, 24, 16, 8, 0);
initGraphics(800, 600, true, &format);
if (g_system->getScreenFormat() != format) {
error("Wintermute currently REQUIRES 32bpp");