aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/parallaction/disk.h2
-rw-r--r--engines/parallaction/disk_br.cpp23
-rw-r--r--engines/parallaction/exec_ns.cpp7
-rw-r--r--engines/parallaction/graphics.h30
-rw-r--r--engines/parallaction/objects.h3
-rw-r--r--engines/parallaction/parser.h4
-rw-r--r--engines/parallaction/parser_br.cpp64
7 files changed, 118 insertions, 15 deletions
diff --git a/engines/parallaction/disk.h b/engines/parallaction/disk.h
index 341229a649..2923f239d4 100644
--- a/engines/parallaction/disk.h
+++ b/engines/parallaction/disk.h
@@ -69,6 +69,7 @@ public:
virtual Table* loadTable(const char* name) = 0;
virtual Common::SeekableReadStream* loadMusic(const char* name) = 0;
virtual Common::ReadStream* loadSound(const char* name) = 0;
+ virtual void loadMask(const char *name, MaskBuffer &buffer) { }
};
@@ -248,6 +249,7 @@ public:
Table* loadTable(const char* name);
Common::SeekableReadStream* loadMusic(const char* name);
Common::ReadStream* loadSound(const char* name);
+ void loadMask(const char *name, MaskBuffer &buffer);
};
class DosDemo_br : public DosDisk_br {
diff --git a/engines/parallaction/disk_br.cpp b/engines/parallaction/disk_br.cpp
index 11f67a2d58..f52567bea2 100644
--- a/engines/parallaction/disk_br.cpp
+++ b/engines/parallaction/disk_br.cpp
@@ -357,6 +357,29 @@ void DosDisk_br::loadSlide(BackgroundInfo& info, const char *name) {
return;
}
+void DosDisk_br::loadMask(const char *name, MaskBuffer &buffer) {
+ if (!name) {
+ return;
+ }
+
+ Common::String filepath;
+ FilesystemNode node;
+ Common::File stream;
+
+ filepath = Common::String(name) + ".msk";
+ node = _mskDir.getChild(filepath);
+ if (!node.exists()) {
+ errorFileNotFound(_mskDir, filepath);
+ }
+ stream.open(node);
+
+ // NOTE: info.width and info.height are only valid if the background graphics
+ // have already been loaded
+ buffer.bigEndian = false;
+ stream.read(buffer.data, buffer.size);
+ stream.close();
+}
+
void DosDisk_br::loadScenery(BackgroundInfo& info, const char *name, const char *mask, const char* path) {
debugC(5, kDebugDisk, "DosDisk_br::loadScenery");
diff --git a/engines/parallaction/exec_ns.cpp b/engines/parallaction/exec_ns.cpp
index bf0423bbd1..6ccec4ed17 100644
--- a/engines/parallaction/exec_ns.cpp
+++ b/engines/parallaction/exec_ns.cpp
@@ -261,8 +261,13 @@ void Parallaction::showZone(ZonePtr z, bool visible) {
if ((z->_type & 0xFFFF) == kZoneGet) {
_gfx->showGfxObj(z->u.get->gfxobj, visible);
- }
+ GetData *data = z->u.get;
+ if (data->hasMask && _gfx->_backgroundInfo->hasMask) {
+ int frame = visible ? 0 : 1;
+ _gfx->_backgroundInfo->mask.blt(data->gfxobj->x, data->gfxobj->y, data->_mask[frame], 0, 0, data->_mask->w, data->_mask->h);
+ }
+ }
}
DECLARE_COMMAND_OPCODE(on) {
diff --git a/engines/parallaction/graphics.h b/engines/parallaction/graphics.h
index 23b4569c6a..0b5cdb02f2 100644
--- a/engines/parallaction/graphics.h
+++ b/engines/parallaction/graphics.h
@@ -209,6 +209,32 @@ public:
return (m >> n) & 3;
}
+ inline byte* getPtr(uint16 x, uint16 y) const {
+ return data + (x >> 2) + y * internalWidth;
+ }
+
+ void blt(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);
+
+ uint diffs = 0;
+
+ // 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++) {
+ if (*s) diffs++;
+ *d++ |= *s++;
+ }
+ d += internalWidth - linewidth;
+ s += src.internalWidth - linewidth;
+ }
+
+ printf("MaskBuffer::blt() diffs = %i\n", diffs);
+ }
+
};
@@ -419,7 +445,9 @@ struct BackgroundInfo {
int layers[4];
PaletteFxRange ranges[6];
- BackgroundInfo() : x(0), y(0), width(0), height(0) {
+ 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));
}
diff --git a/engines/parallaction/objects.h b/engines/parallaction/objects.h
index d06eaf1a03..f66e602f68 100644
--- a/engines/parallaction/objects.h
+++ b/engines/parallaction/objects.h
@@ -198,11 +198,14 @@ struct GetData { // size = 24
byte *_backup;
uint16 field_14; // unused
uint16 field_16; // unused
+ MaskBuffer _mask[2];
+ bool hasMask;
GetData() {
_icon = 0;
_backup = NULL;
gfxobj = NULL;
+ hasMask = false;
}
};
struct SpeakData { // size = 36
diff --git a/engines/parallaction/parser.h b/engines/parallaction/parser.h
index 5a01282e37..e622bfd81f 100644
--- a/engines/parallaction/parser.h
+++ b/engines/parallaction/parser.h
@@ -131,9 +131,6 @@ protected:
// BRA specific
int numZones;
BackgroundInfo *info;
- char *bgName;
- char *maskName;
- char *pathName;
char *characterName;
} ctxt;
@@ -306,6 +303,7 @@ protected:
virtual void parseZoneTypeBlock(ZonePtr z);
void parsePathData(ZonePtr z);
+ void parseGetData(ZonePtr z);
public:
LocationParser_br(Parallaction_br *vm) : LocationParser_ns((Parallaction_ns*)vm), _vm(vm) {
diff --git a/engines/parallaction/parser_br.cpp b/engines/parallaction/parser_br.cpp
index b9df3a2aa2..2a8064264d 100644
--- a/engines/parallaction/parser_br.cpp
+++ b/engines/parallaction/parser_br.cpp
@@ -316,7 +316,6 @@ DECLARE_LOCATION_PARSER(location) {
debugC(7, kDebugParser, "LOCATION_PARSER(location) ");
strcpy(_vm->_location._name, _tokens[1]);
- ctxt.bgName = strdup(_tokens[1]);
bool flip = false;
int nextToken;
@@ -340,6 +339,8 @@ DECLARE_LOCATION_PARSER(location) {
if (_tokens[nextToken][0] != '\0') {
_vm->_char._ani->setF(atoi(_tokens[nextToken]));
}
+
+ _vm->_disk->loadScenery(*ctxt.info, _tokens[1], 0, 0);
}
@@ -465,18 +466,20 @@ DECLARE_LOCATION_PARSER(null) {
DECLARE_LOCATION_PARSER(mask) {
debugC(7, kDebugParser, "LOCATION_PARSER(mask) ");
- ctxt.maskName = strdup(_tokens[1]);
ctxt.info->layers[0] = 0;
ctxt.info->layers[1] = atoi(_tokens[2]);
ctxt.info->layers[2] = atoi(_tokens[3]);
ctxt.info->layers[3] = atoi(_tokens[4]);
+
+ _vm->_disk->loadScenery(*ctxt.info, 0, _tokens[1], 0);
+ ctxt.info->hasMask = true;
}
DECLARE_LOCATION_PARSER(path) {
debugC(7, kDebugParser, "LOCATION_PARSER(path) ");
- ctxt.pathName = strdup(_tokens[1]);
+ _vm->_disk->loadScenery(*ctxt.info, 0, 0, _tokens[1]);
}
@@ -768,6 +771,54 @@ void LocationParser_br::parsePathData(ZonePtr z) {
z->u.path = data;
}
+void LocationParser_br::parseGetData(ZonePtr z) {
+
+ GetData *data = new GetData;
+
+ do {
+
+ if (!scumm_stricmp(_tokens[0], "file")) {
+
+ GfxObj *obj = _vm->_gfx->loadGet(_tokens[1]);
+ obj->frame = 0;
+ obj->x = z->getX();
+ obj->y = z->getY();
+ data->gfxobj = obj;
+ }
+
+ if (!scumm_stricmp(_tokens[0], "mask")) {
+ if (ctxt.info->hasMask) {
+ Common::Rect rect;
+ data->gfxobj->getRect(0, rect);
+ data->_mask[0].create(rect.width(), rect.height());
+ _vm->_disk->loadMask(_tokens[1], data->_mask[0]);
+ data->_mask[1].create(rect.width(), rect.height());
+ data->_mask[1].blt(0, 0, ctxt.info->mask, data->gfxobj->x, data->gfxobj->y, data->_mask->w, data->_mask->h);
+ data->hasMask = true;
+ } else {
+ warning("Mask for zone '%s' ignored, since background doesn't have one", z->_name);
+ }
+ }
+
+ if (!scumm_stricmp(_tokens[0], "path")) {
+
+ }
+
+ if (!scumm_stricmp(_tokens[0], "icon")) {
+ data->_icon = 4 + _vm->_objectsNames->lookup(_tokens[1]);
+ }
+
+ _script->readLineToken(true);
+ } while (scumm_stricmp(_tokens[0], "endzone"));
+
+ z->u.get = data;
+
+ // FIXME: right now showZone doesn't work properly when called during location
+ // parsing. In fact, the main backgroundInfo is not properly set yet.
+ bool visible = (z->_flags & kFlagsRemove) == 0;
+ _vm->showZone(z, visible);
+}
+
void LocationParser_br::parseZoneTypeBlock(ZonePtr z) {
debugC(7, kDebugParser, "parseZoneTypeBlock(name: %s, type: %x)", z->_name, z->_type);
@@ -1192,15 +1243,11 @@ void LocationParser_br::parse(Script *script) {
Script *script2 = new Script(getStream(list), true);
ctxt.numZones = 0;
- ctxt.bgName = 0;
- ctxt.maskName = 0;
- ctxt.pathName = 0;
ctxt.characterName = 0;
ctxt.info = new BackgroundInfo;
LocationParser_ns::parse(script2);
- _vm->_disk->loadScenery(*ctxt.info, ctxt.bgName, ctxt.maskName, ctxt.pathName);
_vm->_gfx->setBackground(kBackgroundLocation, ctxt.info);
_vm->_pathBuffer = &ctxt.info->path;
@@ -1209,9 +1256,6 @@ void LocationParser_br::parse(Script *script) {
_vm->changeCharacter(ctxt.characterName);
}
- free(ctxt.bgName);
- free(ctxt.maskName);
- free(ctxt.pathName);
free(ctxt.characterName);
delete script2;