aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorNicola Mettifogo2008-08-15 14:25:43 +0000
committerNicola Mettifogo2008-08-15 14:25:43 +0000
commit05a021fd952c4d35ab82f487753162f3ed3bbd43 (patch)
treecfa927ebecdf7d7a8f323f5bddfb71417cbdbbc4 /engines
parent4e0485197fcfb6e8807996e5bf179c0249a7369c (diff)
downloadscummvm-rg350-05a021fd952c4d35ab82f487753162f3ed3bbd43.tar.gz
scummvm-rg350-05a021fd952c4d35ab82f487753162f3ed3bbd43.tar.bz2
scummvm-rg350-05a021fd952c4d35ab82f487753162f3ed3bbd43.zip
Added routines to load and handle item masks: animation are now correctly hidden when they are behind any object. The masks of items that are not explicitly activated (even if visible) still are handled (e.g. the crown in the museum is not visible in the foreground).
svn-id: r33900
Diffstat (limited to 'engines')
-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;