From 3359ea9c99eba7f7e630a2b8057ec4df55fed83c Mon Sep 17 00:00:00 2001 From: stevenhoefel Date: Mon, 9 Jan 2017 09:31:27 +1100 Subject: DIRECTOR: CASt members have Children in D4. --- engines/director/archive.cpp | 49 +++++++++++++++++++++++++++++++++++---- engines/director/archive.h | 16 +++++++++---- engines/director/cast.cpp | 20 ++++++++++++++-- engines/director/cast.h | 2 ++ engines/director/director.h | 1 + engines/director/resource.cpp | 2 +- engines/director/score.cpp | 53 ++++++++++++++++++++++++++++++++----------- engines/director/score.h | 3 ++- 8 files changed, 120 insertions(+), 26 deletions(-) diff --git a/engines/director/archive.cpp b/engines/director/archive.cpp index 5b1a26ffd4..398b287b90 100644 --- a/engines/director/archive.cpp +++ b/engines/director/archive.cpp @@ -100,6 +100,18 @@ Common::SeekableSubReadStreamEndian *Archive::getResource(uint32 tag, uint16 id) return new Common::SeekableSubReadStreamEndian(_stream, res.offset, res.offset + res.size, _isBigEndian, DisposeAfterUse::NO); } +Resource Archive::getResourceDetail(uint32 tag, uint16 id) { + if (!_types.contains(tag)) + error("Archive does not contain '%s' %04x", tag2str(tag), id); + + const ResourceMap &resMap = _types[tag]; + + if (!resMap.contains(id)) + error("Archive does not contain '%s' %04x", tag2str(tag), id); + + return resMap[id]; +} + uint32 Archive::getOffset(uint32 tag, uint16 id) const { if (!_types.contains(tag)) error("Archive does not contain '%s' %04x", tag2str(tag), id); @@ -365,6 +377,7 @@ bool RIFXArchive::openStream(Common::SeekableReadStream *stream, uint32 startOff subStream.readUint32(); // unknown Common::Array resources; + resources.reserve(2048); // Need to look for these two resources const Resource *keyRes = 0; @@ -395,6 +408,8 @@ bool RIFXArchive::openStream(Common::SeekableReadStream *stream, uint32 startOff keyRes = &resources[resources.size() - 1]; else if (tag == MKTAG('C', 'A', 'S', '*')) casRes = &resources[resources.size() - 1]; + else + _types[tag][i] = res; } // We need to have found the 'File' resource already @@ -409,6 +424,8 @@ bool RIFXArchive::openStream(Common::SeekableReadStream *stream, uint32 startOff return false; } + uint castTag = MKTAG('C', 'A', 'S', 't'); + // Parse the CAS*, if present if (casRes) { Common::SeekableSubReadStreamEndian casStream(stream, casRes->offset + 8, casRes->offset + 8 + casRes->size, _isBigEndian, DisposeAfterUse::NO); @@ -420,8 +437,10 @@ bool RIFXArchive::openStream(Common::SeekableReadStream *stream, uint32 startOff for (uint i = 0; i < casSize; i++) { uint32 index = casStream.readUint32(); - const Resource &res = resources[index]; - _types[MKTAG('C', 'A', 'S', 't')][i + 1] = res; + Resource &res = resources[index]; + res.index = index; + res.castId = i + 1; + _types[castTag][res.castId] = res; debugCN(2, kDebugLoading, "%d ", index); } @@ -444,10 +463,20 @@ bool RIFXArchive::openStream(Common::SeekableReadStream *stream, uint32 startOff debugC(2, kDebugLoading, "KEY*: index: %d id: %d resTag: %s", index, id, tag2str(resTag)); - const Resource &res = resources[index]; + Resource &res = resources[index]; debug(3, "Found RIFX resource: '%s' id: 0x%04x, %d @ 0x%08x (%d)", tag2str(resTag), id, res.size, res.offset, res.offset); _types[resTag][id] = res; - _types[resTag][1024 + i + 1] = res; + //_types[resTag][1024 + i + 1] = res; + + if (id < 1024) { + for (uint cast = 0; cast < _types[castTag].size(); cast++) { + if (_types[castTag][cast].index == id) { + res.index = index; + _types[castTag][cast].children.push_back(res); + break; + } + } + } } _stream = stream; @@ -471,5 +500,17 @@ Common::SeekableSubReadStreamEndian *RIFXArchive::getResource(uint32 tag, uint16 return new Common::SeekableSubReadStreamEndian(_stream, offset, offset + size, true, DisposeAfterUse::NO); } +Resource RIFXArchive::getResourceDetail(uint32 tag, uint16 id) { + if (!_types.contains(tag)) + error("Archive does not contain '%s' %04x", tag2str(tag), id); + + const ResourceMap &resMap = _types[tag]; + + if (!resMap.contains(id)) + error("Archive does not contain '%s' %04x", tag2str(tag), id); + + return resMap[id]; +} + } // End of namespace Director diff --git a/engines/director/archive.h b/engines/director/archive.h index 93f4ce7ee9..b77bace9ba 100644 --- a/engines/director/archive.h +++ b/engines/director/archive.h @@ -33,6 +33,15 @@ class MacResManager; namespace Director { // Completely ripped off of Mohawk's Archive code + +struct Resource { + uint32 index; + uint32 offset; + uint32 size; + uint32 castId; + Common::String name; + Common::Array children; +}; class Archive { public: @@ -50,6 +59,7 @@ public: bool hasResource(uint32 tag, uint16 id) const; bool hasResource(uint32 tag, const Common::String &resName) const; virtual Common::SeekableSubReadStreamEndian *getResource(uint32 tag, uint16 id); + virtual Resource getResourceDetail(uint32 tag, uint16 id); uint32 getOffset(uint32 tag, uint16 id) const; uint16 findResourceID(uint32 tag, const Common::String &resName) const; Common::String getName(uint32 tag, uint16 id) const; @@ -61,11 +71,6 @@ public: protected: Common::SeekableReadStream *_stream; - struct Resource { - uint32 offset; - uint32 size; - Common::String name; - }; typedef Common::HashMap ResourceMap; typedef Common::HashMap TypeMap; TypeMap _types; @@ -103,6 +108,7 @@ public: bool openStream(Common::SeekableReadStream *stream, uint32 startOffset = 0); Common::SeekableSubReadStreamEndian *getResource(uint32 tag, uint16 id); + Resource getResourceDetail(uint32 tag, uint16 id); }; } // End of namespace Director diff --git a/engines/director/cast.cpp b/engines/director/cast.cpp index 892ac48f8c..81637b9684 100644 --- a/engines/director/cast.cpp +++ b/engines/director/cast.cpp @@ -41,6 +41,9 @@ BitmapCast::BitmapCast(Common::ReadStreamEndian &stream, uint16 version) { unk2 = stream.readUint16(); } } else { + stream.readByte(); + stream.readByte(); + initialRect = Score::readRect(stream); boundingRect = Score::readRect(stream); regX = stream.readUint16(); @@ -59,8 +62,10 @@ BitmapCast::BitmapCast(Common::ReadStreamEndian &stream, uint16 version) { } TextCast::TextCast(Common::ReadStreamEndian &stream, uint16 version) { - if (version < 4) { - flags1 = stream.readByte(); + if (version < 5) { + if (version <= 3) + flags1 = stream.readByte(); + borderSize = static_cast(stream.readByte()); gutterSize = static_cast(stream.readByte()); boxShadow = static_cast(stream.readByte()); @@ -109,6 +114,9 @@ ShapeCast::ShapeCast(Common::ReadStreamEndian &stream, uint16 version) { lineThickness = stream.readByte(); lineDirection = stream.readByte(); } else { + stream.readByte(); + stream.readByte(); + initialRect = Score::readRect(stream); boundingRect = Score::readRect(stream); } @@ -119,8 +127,13 @@ ButtonCast::ButtonCast(Common::ReadStreamEndian &stream, uint16 version) : TextC if (version < 4) { buttonType = static_cast(stream.readUint16BE()); } else { + stream.readByte(); + stream.readByte(); + initialRect = Score::readRect(stream); boundingRect = Score::readRect(stream); + + buttonType = static_cast(stream.readUint16BE()); } modified = 0; } @@ -129,6 +142,9 @@ ScriptCast::ScriptCast(Common::ReadStreamEndian &stream, uint16 version) { if (version < 4) { error("Unhandled Script cast"); } else { + stream.readByte(); + stream.readByte(); + initialRect = Score::readRect(stream); boundingRect = Score::readRect(stream); diff --git a/engines/director/cast.h b/engines/director/cast.h index 69edf8ce89..a739ccc25d 100644 --- a/engines/director/cast.h +++ b/engines/director/cast.h @@ -25,6 +25,7 @@ #include "common/rect.h" #include "common/substream.h" +#include "director/archive.h" namespace Director { @@ -46,6 +47,7 @@ struct Cast { CastType type; Common::Rect initialRect; Common::Rect boundingRect; + Common::Array children; byte modified; }; diff --git a/engines/director/director.h b/engines/director/director.h index 7ec9608662..ead143758e 100644 --- a/engines/director/director.h +++ b/engines/director/director.h @@ -73,6 +73,7 @@ public: Common::Language getLanguage() const; Common::String getEXEName() const; DirectorSound *getSoundManager() const { return _soundManager; } + Graphics::MacWindowManager *getMacWindowManager() const { return _wm; } Archive *getMainArchive() const { return _mainArchive; } Lingo *getLingo() const { return _lingo; } Score *getCurrentScore() const { return _currentScore; } diff --git a/engines/director/resource.cpp b/engines/director/resource.cpp index 2f8ef3e432..711ce0474d 100644 --- a/engines/director/resource.cpp +++ b/engines/director/resource.cpp @@ -217,7 +217,7 @@ void DirectorEngine::loadSharedCastsFrom(Common::String filename) { Common::Array cast = shardcst->getResourceIDList(MKTAG('C','A','S','t')); if (cast.size() > 0) { for (Common::Array::iterator iterator = cast.begin(); iterator != cast.end(); ++iterator) - castScore->loadCastData(*shardcst->getResource(MKTAG('C','A','S','t'), *iterator), *iterator); + castScore->loadCastData(*shardcst->getResource(MKTAG('C','A','S','t'), *iterator), *iterator, NULL); } castScore->setSpriteCasts(); diff --git a/engines/director/score.cpp b/engines/director/score.cpp index 8a80e30765..b3aee97fd8 100644 --- a/engines/director/score.cpp +++ b/engines/director/score.cpp @@ -216,16 +216,19 @@ void Score::loadArchive() { Common::Array cast = _movieArchive->getResourceIDList(MKTAG('C','A','S','t')); if (cast.size() > 0) { - for (Common::Array::iterator iterator = cast.begin(); iterator != cast.end(); ++iterator) - loadCastData(*_movieArchive->getResource(MKTAG('C','A','S','t'), *iterator), *iterator); + for (Common::Array::iterator iterator = cast.begin(); iterator != cast.end(); ++iterator) { + Common::SeekableSubReadStreamEndian *stream = _movieArchive->getResource(MKTAG('C', 'A', 'S', 't'), *iterator); + Resource res = _movieArchive->getResourceDetail(MKTAG('C', 'A', 'S', 't'), *iterator); + loadCastData(*stream, *iterator, &res); + } } setSpriteCasts(); - Common::Array stxt = _movieArchive->getResourceIDList(MKTAG('S','T','X','T')); - if (stxt.size() > 0) { - loadScriptText(*_movieArchive->getResource(MKTAG('S','T','X','T'), *stxt.begin())); - } + //Common::Array stxt = _movieArchive->getResourceIDList(MKTAG('S','T','X','T')); + //if (stxt.size() > 0) { + // loadScriptText(*_movieArchive->getResource(MKTAG('S','T','X','T'), *stxt.begin())); + //} } Score::~Score() { @@ -397,7 +400,7 @@ void Score::setSpriteCasts() { } } -void Score::loadCastData(Common::SeekableSubReadStreamEndian &stream, uint16 id) { +void Score::loadCastData(Common::SeekableSubReadStreamEndian &stream, uint16 id, Resource *res) { // d4+ variant if (stream.size() == 0) return; @@ -415,7 +418,7 @@ void Score::loadCastData(Common::SeekableSubReadStreamEndian &stream, uint16 id) uint32 size1, size2, size3, castType; byte unk1 = 0, unk2 = 0, unk3 = 0; - if (_vm->getVersion() < 5) { + if (_vm->getVersion() < 4) { size1 = stream.readUint16(); size2 = stream.readUint32(); size3 = 0; @@ -423,6 +426,12 @@ void Score::loadCastData(Common::SeekableSubReadStreamEndian &stream, uint16 id) unk1 = stream.readByte(); unk2 = stream.readByte(); unk3 = stream.readByte(); + } else if (_vm->getVersion() < 5) { + size1 = stream.readUint16() + 2; + size2 = stream.readUint32(); + size3 = 0; + castType = stream.readByte(); + unk1 = stream.readByte(); } else { // FIXME: only the cast type and the strings are good castType = stream.readUint32(); @@ -436,7 +445,7 @@ void Score::loadCastData(Common::SeekableSubReadStreamEndian &stream, uint16 id) debugC(3, kDebugLoading, "CASt: id: %d type: %x size1: %d size2: %d (%x) size3: %d unk1: %d unk2: %d unk3: %d", id, castType, size1, size2, size2, size3, unk1, unk2, unk3); - byte *data = (byte *)calloc(size1, 1); // 16 is for bounding rects + byte *data = (byte *)calloc(size1 + 16, 1); // 16 is for bounding rects stream.read(data, size1 + 16); Common::MemoryReadStreamEndian castStream(data, size1 + 16, stream.isBE()); @@ -469,6 +478,9 @@ void Score::loadCastData(Common::SeekableSubReadStreamEndian &stream, uint16 id) _casts[id]->type = kCastButton; break; case kCastScript: + warning("CASt: Script"); + Common::hexdump(data, size1 + 16); + _casts[id] = new ScriptCast(castStream, _vm->getVersion()); _casts[id]->type = kCastScript; break; @@ -477,6 +489,11 @@ void Score::loadCastData(Common::SeekableSubReadStreamEndian &stream, uint16 id) break; } + if (res != NULL) { + for (uint child = 0; child < res->children.size(); child++) + _casts[id]->children.push_back(res->children[child]); + } + free(data); if (size2) { @@ -500,6 +517,11 @@ void Score::loadCastData(Common::SeekableSubReadStreamEndian &stream, uint16 id) ci->fileName = castStrings[3]; ci->type = castStrings[4]; + if (!ci->script.empty()) { + //the script type here could be wrong! + _lingo->addCode(ci->script.c_str(), _casts[id]->type == kCastScript ? kFrameScript : kSpriteScript, id); + } + _castsInfo[id] = ci; } @@ -802,7 +824,7 @@ Common::Array Score::loadStrings(Common::SeekableSubReadStreamEn byte *data = (byte *)malloc(entries[count - 1]); stream.read(data, entries[count - 1]); - for (uint i = 0; i < count - 1; i++) { + for (uint16 i = 0; i < count - 1; i++) { Common::String entryString; for (uint j = entries[i]; j < entries[i + 1]; j++) @@ -821,6 +843,9 @@ Common::Array Score::loadStrings(Common::SeekableSubReadStreamEn } void Score::loadFontMap(Common::SeekableSubReadStreamEndian &stream) { + if (stream.size() == 0) + return; + uint16 count = stream.readUint16(); uint32 offset = (count * 2) + 2; uint16 currentRawPosition = offset; @@ -908,9 +933,11 @@ void Score::update() { _currentFrame++; Common::SortedArray