aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/parallaction/callables_ns.cpp20
-rw-r--r--engines/parallaction/disk_br.cpp5
-rw-r--r--engines/parallaction/disk_ns.cpp21
-rw-r--r--engines/parallaction/gfxbase.cpp25
-rw-r--r--engines/parallaction/graphics.cpp210
-rw-r--r--engines/parallaction/graphics.h269
-rw-r--r--engines/parallaction/parallaction.cpp4
-rw-r--r--engines/parallaction/parser_br.cpp7
-rw-r--r--engines/parallaction/walk.cpp21
9 files changed, 337 insertions, 245 deletions
diff --git a/engines/parallaction/callables_ns.cpp b/engines/parallaction/callables_ns.cpp
index b45a30c317..d40f028941 100644
--- a/engines/parallaction/callables_ns.cpp
+++ b/engines/parallaction/callables_ns.cpp
@@ -288,7 +288,10 @@ void Parallaction_ns::_c_onMouse(void *parm) {
void Parallaction_ns::_c_setMask(void *parm) {
- memset(_gfx->_backgroundInfo->mask.data + 3600, 0, 3600);
+ if (!_gfx->_backgroundInfo->hasMask())
+ return;
+
+ memset(_gfx->_backgroundInfo->_mask->data + 3600, 0, 3600);
_gfx->_backgroundInfo->layers[1] = 500;
return;
@@ -446,10 +449,13 @@ void Parallaction_ns::_c_moveSheet(void *parm) {
void zeroMask(int x, int y, int color, void *data) {
//_vm->_gfx->zeroMaskValue(x, y, color);
- BackgroundInfo* info = (BackgroundInfo*)data;
+ if (!_vm->_gfx->_backgroundInfo->hasMask())
+ return;
+
+// BackgroundInfo* info = (BackgroundInfo*)data;
- uint16 _ax = x + y * info->width;
- info->mask.data[_ax >> 2] &= ~(3 << ((_ax & 3) << 1));
+ uint16 _ax = x + y * _vm->_gfx->_backgroundInfo->_mask->w;
+ _vm->_gfx->_backgroundInfo->_mask->data[_ax >> 2] &= ~(3 << ((_ax & 3) << 1));
}
@@ -498,11 +504,11 @@ void Parallaction_ns::_c_shade(void *parm) {
_rightHandAnim->getY()
);
- uint16 _di = r.left/4 + r.top * _gfx->_backgroundInfo->mask.internalWidth;
+ uint16 _di = r.left/4 + r.top * _vm->_gfx->_backgroundInfo->_mask->internalWidth;
for (uint16 _si = r.top; _si < r.bottom; _si++) {
- memset(_gfx->_backgroundInfo->mask.data + _di, 0, r.width()/4+1);
- _di += _gfx->_backgroundInfo->mask.internalWidth;
+ memset(_vm->_gfx->_backgroundInfo->_mask->data + _di, 0, r.width()/4+1);
+ _di += _vm->_gfx->_backgroundInfo->_mask->internalWidth;
}
return;
diff --git a/engines/parallaction/disk_br.cpp b/engines/parallaction/disk_br.cpp
index 45ef34e046..5f2ddcd1b7 100644
--- a/engines/parallaction/disk_br.cpp
+++ b/engines/parallaction/disk_br.cpp
@@ -339,8 +339,9 @@ void DosDisk_br::loadScenery(BackgroundInfo& info, const char *name, const char
}
if (mask) {
- info.mask.create(info.width, info.height);
- loadMask(mask, info.mask);
+ info._mask = new MaskBuffer;
+ info._mask->create(info.width, info.height);
+ loadMask(mask, *info._mask);
}
if (path) {
diff --git a/engines/parallaction/disk_ns.cpp b/engines/parallaction/disk_ns.cpp
index eedfaf92b7..c24eaf7007 100644
--- a/engines/parallaction/disk_ns.cpp
+++ b/engines/parallaction/disk_ns.cpp
@@ -457,12 +457,13 @@ void DosDisk_ns::loadBackground(BackgroundInfo& info, const char *filename) {
parseBackground(info, *stream);
info.bg.create(info.width, info.height, 1);
- info.mask.create(info.width, info.height);
- info.mask.bigEndian = true;
+ info._mask = new MaskBuffer;
+ info._mask->create(info.width, info.height);
+ info._mask->bigEndian = true;
info.path.create(info.width, info.height);
Graphics::PackBitsReadStream pbstream(*stream);
- unpackBackground(&pbstream, (byte*)info.bg.pixels, info.mask.data, info.path.data);
+ unpackBackground(&pbstream, (byte*)info.bg.pixels, info._mask->data, info.path.data);
delete stream;
}
@@ -480,9 +481,10 @@ void DosDisk_ns::loadMaskAndPath(BackgroundInfo& info, const char *name) {
parseDepths(info, *stream);
info.path.create(info.width, info.height);
stream->read(info.path.data, info.path.size);
- info.mask.create(info.width, info.height);
- info.mask.bigEndian = true;
- stream->read(info.mask.data, info.mask.size);
+ info._mask = new MaskBuffer;
+ info._mask->create(info.width, info.height);
+ info._mask->bigEndian = true;
+ stream->read(info._mask->data, info._mask->size);
delete stream;
}
@@ -1049,9 +1051,10 @@ void AmigaDisk_ns::loadMask(BackgroundInfo& info, const char *name) {
s->seek(0x126, SEEK_SET); // HACK: skipping IFF/ILBM header should be done by analysis, not magic
Graphics::PackBitsReadStream stream(*s);
- info.mask.create(info.width, info.height);
- stream.read(info.mask.data, info.mask.size);
- buildMask(info.mask.data);
+ info._mask = new MaskBuffer;
+ info._mask->create(info.width, info.height);
+ stream.read(info._mask->data, info._mask->size);
+ buildMask(info._mask->data);
delete s;
diff --git a/engines/parallaction/gfxbase.cpp b/engines/parallaction/gfxbase.cpp
index 2e7794a1f1..a585caa713 100644
--- a/engines/parallaction/gfxbase.cpp
+++ b/engines/parallaction/gfxbase.cpp
@@ -46,7 +46,6 @@ GfxObj::GfxObj(uint objType, Frames *frames, const char* name) :
GfxObj::~GfxObj() {
delete _frames;
free(_name);
- _mask.free();
}
void GfxObj::release() {
@@ -157,12 +156,15 @@ void Gfx::freeCharacterObjects() {
clearGfxObjects(kGfxObjCharacter);
}
-
void Gfx::loadGfxObjMask(const char *name, GfxObj *obj) {
Common::Rect rect;
obj->getRect(0, rect);
- obj->_mask.create(rect.width(), rect.height());
- _vm->_disk->loadMask(name, obj->_mask);
+
+ MaskBuffer *buf = new MaskBuffer;
+ buf->create(rect.width(), rect.height());
+ _vm->_disk->loadMask(name, *buf);
+
+ obj->_maskId = _backgroundInfo->addMaskPatch(buf);
obj->_hasMask = true;
}
@@ -177,12 +179,9 @@ void Gfx::showGfxObj(GfxObj* obj, bool visible) {
obj->clearFlags(kGfxObjVisible);
}
- if (obj->_hasMask && _backgroundInfo->hasMask) {
- if (visible) {
- _backgroundInfo->mask.bltOr(obj->x, obj->y, obj->_mask, 0, 0, obj->_mask.w, obj->_mask.h);
- } else {
- _backgroundInfo->mask.bltCopy(obj->x, obj->y, _backgroundInfo->maskBackup, obj->x, obj->y, obj->_mask.w, obj->_mask.h);
- }
+ //TODO: move handling of mask existence inside MaskManager
+ if (obj->_hasMask) {
+ _backgroundInfo->toggleMaskPatch(obj->_maskId, obj->x, obj->y, visible);
}
}
@@ -334,7 +333,7 @@ void Gfx::bltMaskScale(const Common::Rect& r, byte *data, Graphics::Surface *sur
}
if (*s != transparentColor) {
- byte v = _backgroundInfo->mask.getValue(dp.x + col, dp.y + line);
+ byte v = _backgroundInfo->_mask->getValue(dp.x + col, dp.y + line);
if (z >= v) *d2 = *s;
}
@@ -351,7 +350,7 @@ void Gfx::bltMaskScale(const Common::Rect& r, byte *data, Graphics::Surface *sur
}
void Gfx::bltMaskNoScale(const Common::Rect& r, byte *data, Graphics::Surface *surf, uint16 z, byte transparentColor) {
- if (!_backgroundInfo->mask.data || (z == LAYER_FOREGROUND)) {
+ if (!_backgroundInfo->hasMask() || (z == LAYER_FOREGROUND)) {
// use optimized path
bltNoMaskNoScale(r, data, surf, transparentColor);
return;
@@ -380,7 +379,7 @@ void Gfx::bltMaskNoScale(const Common::Rect& r, byte *data, Graphics::Surface *s
for (uint16 j = 0; j < q.width(); j++) {
if (*s != transparentColor) {
- byte v = _backgroundInfo->mask.getValue(dp.x + j, dp.y + i);
+ byte v = _backgroundInfo->_mask->getValue(dp.x + j, dp.y + i);
if (z >= v) *d = *s;
}
diff --git a/engines/parallaction/graphics.cpp b/engines/parallaction/graphics.cpp
index d3ca4934d0..1a233bb990 100644
--- a/engines/parallaction/graphics.cpp
+++ b/engines/parallaction/graphics.cpp
@@ -464,7 +464,7 @@ void Gfx::patchBackground(Graphics::Surface &surf, int16 x, int16 y, bool mask)
Common::Rect r(surf.w, surf.h);
r.moveTo(x, y);
- uint16 z = (mask) ? _backgroundInfo->getLayer(y) : LAYER_FOREGROUND;
+ uint16 z = (mask) ? _backgroundInfo->getMaskLayer(y) : LAYER_FOREGROUND;
blt(r, (byte*)surf.pixels, &_backgroundInfo->bg, z, 100, 0);
}
@@ -687,7 +687,7 @@ void Gfx::grabBackground(const Common::Rect& r, Graphics::Surface &dst) {
Gfx::Gfx(Parallaction* vm) :
- _vm(vm), _disk(vm->_disk), _scrollPos(0), _minScroll(0), _maxScroll(0) {
+ _vm(vm), _disk(vm->_disk), _backgroundInfo(0), _scrollPos(0), _minScroll(0), _maxScroll(0) {
_gameType = _vm->getGameType();
_doubleBuffering = _gameType != GType_Nippon;
@@ -778,6 +778,11 @@ void Gfx::freeDialogueObjects() {
}
void Gfx::setBackground(uint type, BackgroundInfo *info) {
+ if (!info) {
+ warning("Gfx::setBackground() called with an null BackgroundInfo");
+ return;
+ }
+
delete _backgroundInfo;
_backgroundInfo = info;
@@ -801,9 +806,7 @@ void Gfx::setBackground(uint type, BackgroundInfo *info) {
setPalette(_backgroundInfo->palette);
}
- if (_backgroundInfo->hasMask) {
- _backgroundInfo->maskBackup.clone(_backgroundInfo->mask);
- }
+ _backgroundInfo->finalizeMask();
if (_gameType == GType_BRA) {
int width = CLIP(info->width, (int)_vm->_screenWidth, info->width);
@@ -818,4 +821,201 @@ void Gfx::setBackground(uint type, BackgroundInfo *info) {
_maxScroll = MAX<int>(0, _backgroundInfo->width - _vm->_screenWidth);
}
+
+BackgroundInfo::BackgroundInfo() : x(0), y(0), width(0), height(0), _mask(0) {
+ layers[0] = layers[1] = layers[2] = layers[3] = 0;
+ memset(ranges, 0, sizeof(ranges));
+}
+
+BackgroundInfo::~BackgroundInfo() {
+ bg.free();
+ clearMaskData();
+ path.free();
+}
+
+bool BackgroundInfo::hasMask() {
+ return _mask != 0;
+}
+
+void BackgroundInfo::clearMaskData() {
+ // free mask data
+ MaskPatchMap::iterator it = _maskPatches.begin();
+ for ( ; it != _maskPatches.end(); it++) {
+ delete (*it)._value;
+ }
+ _maskPatches.clear();
+ delete _mask;
+ _mask = 0;
+ _maskBackup.free();
+}
+
+void BackgroundInfo::finalizeMask() {
+ if (_mask) {
+ _maskBackup.clone(*_mask);
+ } else {
+ clearMaskData();
+ }
+}
+
+int BackgroundInfo::addMaskPatch(MaskBuffer *patch) {
+ int id = _maskPatches.size();
+ _maskPatches.setVal(id, patch);
+ return id;
+}
+
+void BackgroundInfo::toggleMaskPatch(int id, int x, int y, bool apply) {
+ if (!hasMask()) {
+ return;
+ }
+ if (!_maskPatches.contains(id)) {
+ return;
+ }
+ MaskBuffer *patch = _maskPatches.getVal(id);
+ if (apply) {
+ _mask->bltOr(x, y, *patch, 0, 0, patch->w, patch->h);
+ } else {
+ _mask->bltCopy(x, y, _maskBackup, x, y, patch->w, patch->h);
+ }
+}
+
+uint16 BackgroundInfo::getMaskLayer(uint16 z) const {
+ for (uint16 i = 0; i < 3; i++) {
+ if (layers[i+1] > z) return i;
+ }
+ return LAYER_FOREGROUND;
+}
+
+void BackgroundInfo::setPaletteRange(int index, const PaletteFxRange& range) {
+ assert(index < 6);
+ memcpy(&ranges[index], &range, sizeof(PaletteFxRange));
+}
+
+MaskBuffer::MaskBuffer() : w(0), internalWidth(0), h(0), size(0), data(0), bigEndian(true) {
+}
+
+MaskBuffer::~MaskBuffer() {
+ free();
+}
+
+byte* MaskBuffer::getPtr(uint16 x, uint16 y) const {
+ return data + (x >> 2) + y * internalWidth;
+}
+
+void MaskBuffer::clone(const MaskBuffer &buf) {
+ if (!buf.data)
+ return;
+
+ create(buf.w, buf.h);
+ bigEndian = buf.bigEndian;
+ memcpy(data, buf.data, size);
+}
+
+void MaskBuffer::create(uint16 width, uint16 height) {
+ free();
+
+ w = width;
+ internalWidth = w >> 2;
+ h = height;
+ size = (internalWidth * h);
+ data = (byte*)calloc(size, 1);
+}
+
+void MaskBuffer::free() {
+ ::free(data);
+ data = 0;
+ w = 0;
+ h = 0;
+ internalWidth = 0;
+ size = 0;
+}
+
+byte MaskBuffer::getValue(uint16 x, uint16 y) const {
+ byte m = data[(x >> 2) + y * internalWidth];
+ uint n;
+ if (bigEndian) {
+ n = (x & 3) << 1;
+ } else {
+ n = (3 - (x & 3)) << 1;
+ }
+ return (m >> n) & 3;
+}
+
+void MaskBuffer::bltOr(uint16 dx, uint16 dy, const MaskBuffer &src, uint16 sx, uint16 sy, uint width, uint height) {
+ assert((width <= w) && (width <= src.w) && (height <= h) && (height <= src.h));
+
+ byte *s = src.getPtr(sx, sy);
+ byte *d = getPtr(dx, dy);
+
+ // this code assumes buffers are aligned on 4-pixels boundaries, as the original does
+ uint16 linewidth = width >> 2;
+ for (uint16 i = 0; i < height; i++) {
+ for (uint16 j = 0; j < linewidth; j++) {
+ *d++ |= *s++;
+ }
+ d += internalWidth - linewidth;
+ s += src.internalWidth - linewidth;
+ }
+}
+
+void MaskBuffer::bltCopy(uint16 dx, uint16 dy, const MaskBuffer &src, uint16 sx, uint16 sy, uint width, uint height) {
+ assert((width <= w) && (width <= src.w) && (height <= h) && (height <= src.h));
+
+ byte *s = src.getPtr(sx, sy);
+ byte *d = getPtr(dx, dy);
+
+ // this code assumes buffers are aligned on 4-pixels boundaries, as the original does
+ for (uint16 i = 0; i < height; i++) {
+ memcpy(d, s, (width >> 2));
+ d += internalWidth;
+ s += src.internalWidth;
+ }
+}
+
+
+
+PathBuffer::PathBuffer() : w(0), internalWidth(0), h(0), size(0), data(0) {
+}
+
+PathBuffer::~PathBuffer() {
+ free();
+}
+
+void PathBuffer::create(uint16 width, uint16 height) {
+ free();
+
+ w = width;
+ internalWidth = w >> 3;
+ h = height;
+ size = (internalWidth * h);
+ data = (byte*)calloc(size, 1);
+}
+
+void PathBuffer::free() {
+ ::free(data);
+ data = 0;
+ w = 0;
+ h = 0;
+ internalWidth = 0;
+ size = 0;
+}
+
+byte PathBuffer::getValue(uint16 x, uint16 y) const {
+ byte m = data[(x >> 3) + y * internalWidth];
+ uint bit = 0;
+ switch (_vm->getGameType()) {
+ case GType_Nippon:
+ bit = (_vm->getPlatform() == Common::kPlatformPC) ? (x & 7) : (7 - (x & 7));
+ break;
+
+ case GType_BRA:
+ // Amiga and PC versions pack the path bits the same way in BRA
+ bit = 7 - (x & 7);
+ break;
+
+ default:
+ error("path mask not yet implemented for this game type");
+ }
+ return ((1 << bit) & m) >> bit;
+}
+
} // namespace Parallaction
diff --git a/engines/parallaction/graphics.h b/engines/parallaction/graphics.h
index f409ab7745..db80586a70 100644
--- a/engines/parallaction/graphics.h
+++ b/engines/parallaction/graphics.h
@@ -28,6 +28,7 @@
#include "common/list.h"
#include "common/rect.h"
+#include "common/hashmap.h"
#include "common/hash-str.h"
#include "common/stream.h"
@@ -124,97 +125,85 @@ public:
};
-
-
-struct MaskBuffer {
- // handles a 2-bit depth buffer used for z-buffering
-
- uint16 w;
- uint16 internalWidth;
- uint16 h;
- uint size;
- byte *data;
- bool bigEndian;
+struct Cnv : public Frames {
+ uint16 _count; // # of frames
+ uint16 _width; //
+ uint16 _height; //
+ byte** field_8; // unused
+ byte* _data;
+ bool _freeData;
public:
- MaskBuffer() : w(0), internalWidth(0), h(0), size(0), data(0), bigEndian(true) {
+ Cnv() {
+ _width = _height = _count = 0;
+ _data = NULL;
}
- void clone(const MaskBuffer &buf) {
- if (!buf.data)
- return;
+ Cnv(uint16 numFrames, uint16 width, uint16 height, byte* data, bool freeData = false)
+ : _count(numFrames), _width(width), _height(height), _data(data), _freeData(freeData) {
- create(buf.w, buf.h);
- bigEndian = buf.bigEndian;
- memcpy(data, buf.data, size);
}
- void create(uint16 width, uint16 height) {
- free();
-
- w = width;
- internalWidth = w >> 2;
- h = height;
- size = (internalWidth * h);
- data = (byte*)calloc(size, 1);
+ ~Cnv() {
+ if (_freeData)
+ delete []_data;
}
- void free() {
- ::free(data);
- data = 0;
- w = 0;
- h = 0;
- internalWidth = 0;
- size = 0;
+ byte* getFramePtr(uint16 index) {
+ if (index >= _count)
+ return NULL;
+ return &_data[index * _width * _height];
}
- inline byte getValue(uint16 x, uint16 y) {
- byte m = data[(x >> 2) + y * internalWidth];
- uint n;
- if (bigEndian) {
- n = (x & 3) << 1;
- } else {
- n = (3 - (x & 3)) << 1;
- }
- return (m >> n) & 3;
+ uint16 getNum() {
+ return _count;
}
- inline byte* getPtr(uint16 x, uint16 y) const {
- return data + (x >> 2) + y * internalWidth;
+ byte *getData(uint16 index) {
+ return getFramePtr(index);
}
- void bltOr(uint16 dx, uint16 dy, const MaskBuffer &src, uint16 sx, uint16 sy, uint width, uint height) {
- assert((width <= w) && (width <= src.w) && (height <= h) && (height <= src.h));
-
- byte *s = src.getPtr(sx, sy);
- byte *d = getPtr(dx, dy);
-
- // this code assumes buffers are aligned on 4-pixels boundaries, as the original does
- uint16 linewidth = width >> 2;
- for (uint16 i = 0; i < height; i++) {
- for (uint16 j = 0; j < linewidth; j++) {
- *d++ |= *s++;
- }
- d += internalWidth - linewidth;
- s += src.internalWidth - linewidth;
- }
+ void getRect(uint16 index, Common::Rect &r) {
+ r.left = 0;
+ r.top = 0;
+ r.setWidth(_width);
+ r.setHeight(_height);
+ }
+ uint getRawSize(uint16 index) {
+ assert(index < _count);
+ return getSize(index);
+ }
+ uint getSize(uint16 index) {
+ assert(index < _count);
+ return _width * _height;
}
- void bltCopy(uint16 dx, uint16 dy, const MaskBuffer &src, uint16 sx, uint16 sy, uint width, uint height) {
- assert((width <= w) && (width <= src.w) && (height <= h) && (height <= src.h));
+};
- byte *s = src.getPtr(sx, sy);
- byte *d = getPtr(dx, dy);
- // this code assumes buffers are aligned on 4-pixels boundaries, as the original does
- for (uint16 i = 0; i < height; i++) {
- memcpy(d, s, (width >> 2));
- d += internalWidth;
- s += src.internalWidth;
- }
- }
+struct MaskBuffer {
+ // handles a 2-bit depth buffer used for z-buffering
+ uint16 w;
+ uint16 internalWidth;
+ uint16 h;
+ uint size;
+ byte *data;
+ bool bigEndian;
+
+ byte* getPtr(uint16 x, uint16 y) const;
+
+public:
+ MaskBuffer();
+ ~MaskBuffer();
+ void clone(const MaskBuffer &buf);
+ void create(uint16 width, uint16 height);
+ void free();
+
+ byte getValue(uint16 x, uint16 y) const;
+ void bltOr(uint16 dx, uint16 dy, const MaskBuffer &src, uint16 sx, uint16 sy, uint width, uint height);
+ void bltCopy(uint16 dx, uint16 dy, const MaskBuffer &src, uint16 sx, uint16 sy, uint width, uint height);
};
@@ -228,29 +217,12 @@ struct PathBuffer {
byte *data;
public:
- PathBuffer() : w(0), internalWidth(0), h(0), size(0), data(0) {
- }
-
- void create(uint16 width, uint16 height) {
- free();
-
- w = width;
- internalWidth = w >> 3;
- h = height;
- size = (internalWidth * h);
- data = (byte*)calloc(size, 1);
- }
-
- void free() {
- ::free(data);
- data = 0;
- w = 0;
- h = 0;
- internalWidth = 0;
- size = 0;
- }
+ PathBuffer();
+ ~PathBuffer();
- inline byte getValue(uint16 x, uint16 y);
+ void create(uint16 width, uint16 height);
+ void free();
+ byte getValue(uint16 x, uint16 y) const;
};
@@ -279,62 +251,6 @@ public:
};
-struct Cnv : public Frames {
- uint16 _count; // # of frames
- uint16 _width; //
- uint16 _height; //
- byte** field_8; // unused
- byte* _data;
- bool _freeData;
-
-public:
- Cnv() {
- _width = _height = _count = 0;
- _data = NULL;
- }
-
- Cnv(uint16 numFrames, uint16 width, uint16 height, byte* data, bool freeData = false)
- : _count(numFrames), _width(width), _height(height), _data(data), _freeData(freeData) {
-
- }
-
- ~Cnv() {
- if (_freeData)
- delete []_data;
- }
-
- byte* getFramePtr(uint16 index) {
- if (index >= _count)
- return NULL;
- return &_data[index * _width * _height];
- }
-
- uint16 getNum() {
- return _count;
- }
-
- byte *getData(uint16 index) {
- return getFramePtr(index);
- }
-
- void getRect(uint16 index, Common::Rect &r) {
- r.left = 0;
- r.top = 0;
- r.setWidth(_width);
- r.setHeight(_height);
- }
- uint getRawSize(uint16 index) {
- assert(index < _count);
- return getSize(index);
- }
- uint getSize(uint16 index) {
- assert(index < _count);
- return _width * _height;
- }
-
-};
-
-
#define CENTER_LABEL_HORIZONTAL -1
#define CENTER_LABEL_VERTICAL -1
@@ -387,7 +303,7 @@ public:
uint transparentKey;
uint scale;
- MaskBuffer _mask;
+ int _maskId;
bool _hasMask;
@@ -420,13 +336,20 @@ public:
being the most common options.
*/
struct BackgroundInfo {
+protected:
+ typedef Common::HashMap<int, MaskBuffer*> MaskPatchMap;
+ MaskPatchMap _maskPatches;
+ MaskBuffer _maskBackup;
+
+ void clearMaskData();
+
+public:
int x, y; // used to display bitmaps smaller than the screen
int width;
int height;
Graphics::Surface bg;
- MaskBuffer mask;
- MaskBuffer maskBackup;
+ MaskBuffer *_mask;
PathBuffer path;
Palette palette;
@@ -434,39 +357,28 @@ struct BackgroundInfo {
int layers[4];
PaletteFxRange ranges[6];
- bool hasMask;
- BackgroundInfo() : x(0), y(0), width(0), height(0), hasMask(false) {
- layers[0] = layers[1] = layers[2] = layers[3] = 0;
- memset(ranges, 0, sizeof(ranges));
- }
+ BackgroundInfo();
+ ~BackgroundInfo();
- void setPaletteRange(int index, const PaletteFxRange& range) {
- assert(index < 6);
- memcpy(&ranges[index], &range, sizeof(PaletteFxRange));
- }
+ void setPaletteRange(int index, const PaletteFxRange& range);
- uint16 getLayer(uint16 z) {
- for (uint16 i = 0; i < 3; i++) {
- if (layers[i+1] > z) return i;
- }
- return LAYER_FOREGROUND;
- }
-
- ~BackgroundInfo() {
- bg.free();
- mask.free();
- maskBackup.free();
- path.free();
- x = 0;
- y = 0;
- width = 0;
- height = 0;
- }
+ // mask management
+ bool hasMask();
+ int addMaskPatch(MaskBuffer *patch);
+ void toggleMaskPatch(int id, int x, int y, bool apply);
+ uint16 getMaskLayer(uint16 z) const;
+ void finalizeMask();
+ // path management
+ bool hasPath();
+ int addPathPatch(PathBuffer *patch);
+ void togglePathPatch(int id, int x, int y, bool apply);
};
+
+
enum {
kBackgroundLocation = 1,
kBackgroundSlide = 2
@@ -611,9 +523,6 @@ protected:
void bltMaskScale(const Common::Rect& r, byte *data, Graphics::Surface *surf, uint16 z, uint scale, byte transparentColor);
void bltMaskNoScale(const Common::Rect& r, byte *data, Graphics::Surface *surf, uint16 z, byte transparentColor);
void bltNoMaskNoScale(const Common::Rect& r, byte *data, Graphics::Surface *surf, byte transparentColor);
-
-public:
-
};
diff --git a/engines/parallaction/parallaction.cpp b/engines/parallaction/parallaction.cpp
index e1f26874e8..426cb7afde 100644
--- a/engines/parallaction/parallaction.cpp
+++ b/engines/parallaction/parallaction.cpp
@@ -456,12 +456,12 @@ void Parallaction::drawAnimations() {
} else {
if (getGameType() == GType_Nippon) {
// Layer in NS depends on where the animation is on the screen, for each animation.
- layer = _gfx->_backgroundInfo->getLayer(anim->getBottom());
+ layer = _gfx->_backgroundInfo->getMaskLayer(anim->getBottom());
} else {
// Layer in BRA is calculated from Z value. For characters it is the same as NS,
// but other animations can have Z set from scripts independently from their
// position on the screen.
- layer = _gfx->_backgroundInfo->getLayer(anim->getZ());
+ layer = _gfx->_backgroundInfo->getMaskLayer(anim->getZ());
}
}
diff --git a/engines/parallaction/parser_br.cpp b/engines/parallaction/parser_br.cpp
index b48db587db..3b5efd2c3f 100644
--- a/engines/parallaction/parser_br.cpp
+++ b/engines/parallaction/parser_br.cpp
@@ -472,7 +472,6 @@ DECLARE_LOCATION_PARSER(mask) {
ctxt.info->layers[3] = atoi(_tokens[4]);
_vm->_disk->loadScenery(*ctxt.info, 0, _tokens[1], 0);
- ctxt.info->hasMask = true;
}
@@ -789,11 +788,7 @@ void LocationParser_br::parseGetData(ZonePtr z) {
}
if (!scumm_stricmp(_tokens[0], "mask")) {
- if (ctxt.info->hasMask) {
- _vm->_gfx->loadGfxObjMask(_tokens[1], data->gfxobj);
- } else {
- warning("Mask for zone '%s' ignored, since background doesn't have one", z->_name);
- }
+ _vm->_gfx->loadGfxObjMask(_tokens[1], data->gfxobj);
}
if (!scumm_stricmp(_tokens[0], "path")) {
diff --git a/engines/parallaction/walk.cpp b/engines/parallaction/walk.cpp
index acd5daa8d5..5a646caa9f 100644
--- a/engines/parallaction/walk.cpp
+++ b/engines/parallaction/walk.cpp
@@ -27,29 +27,8 @@
namespace Parallaction {
-
-
#define IS_PATH_CLEAR(x,y) _vm->_gfx->_backgroundInfo->path.getValue((x), (y))
-inline byte PathBuffer::getValue(uint16 x, uint16 y) {
- byte m = data[(x >> 3) + y * internalWidth];
- uint bit = 0;
- switch (_vm->getGameType()) {
- case GType_Nippon:
- bit = (_vm->getPlatform() == Common::kPlatformPC) ? (x & 7) : (7 - (x & 7));
- break;
-
- case GType_BRA:
- // Amiga and PC versions pack the path bits the same way in BRA
- bit = 7 - (x & 7);
- break;
-
- default:
- error("path mask not yet implemented for this game type");
- }
- return ((1 << bit) & m) >> bit;
-}
-
// adjusts position towards nearest walkable point
//
void PathBuilder_NS::correctPathPoint(Common::Point &to) {