diff options
-rw-r--r-- | engines/parallaction/disk.h | 2 | ||||
-rw-r--r-- | engines/parallaction/disk_br.cpp | 23 | ||||
-rw-r--r-- | engines/parallaction/exec_ns.cpp | 7 | ||||
-rw-r--r-- | engines/parallaction/graphics.h | 30 | ||||
-rw-r--r-- | engines/parallaction/objects.h | 3 | ||||
-rw-r--r-- | engines/parallaction/parser.h | 4 | ||||
-rw-r--r-- | engines/parallaction/parser_br.cpp | 64 |
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; |