[Scummvm-git-logs] scummvm master -> f6dda6b7fbbba28d8aa1d396f9812471ed0e059d

sev- sev at scummvm.org
Wed Oct 26 10:48:44 CEST 2016


This automated email contains information about 3 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
df2bd1a94c DIRECTOR: Skipping useless movie scanning.
814db5fd38 DIRECTOR: Renamed resource/archive files to better reflect reality
f6dda6b7fb DIRECTOR: Skip header in VWLB resource for D4+


Commit: df2bd1a94c17b4cf4e6981b85d80d23172d31ba0
    https://github.com/scummvm/scummvm/commit/df2bd1a94c17b4cf4e6981b85d80d23172d31ba0
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2016-10-26T10:48:37+02:00

Commit Message:
DIRECTOR: Skipping useless movie scanning.

We can easily rely on the FS path resolving.

Changed paths:
    engines/director/archive.cpp
    engines/director/director.cpp



diff --git a/engines/director/archive.cpp b/engines/director/archive.cpp
index 1af63a8..9976c25 100644
--- a/engines/director/archive.cpp
+++ b/engines/director/archive.cpp
@@ -194,7 +194,11 @@ void DirectorEngine::loadSharedCastsFrom(Common::String filename) {
 
 	debugC(1, kDebugLoading, "Loading Shared cast '%s'", filename.c_str());
 
-	shardcst->openFile(filename);
+	if (!shardcst->openFile(filename)) {
+		warning("No shared cast %s", filename.c_str());
+
+		return;
+	}
 
 	_sharedDIB = new Common::HashMap<int, Common::SeekableSubReadStreamEndian *>;
 	_sharedSTXT = new Common::HashMap<int, Common::SeekableSubReadStreamEndian *>;
diff --git a/engines/director/director.cpp b/engines/director/director.cpp
index 8c5e456..034c7c4 100644
--- a/engines/director/director.cpp
+++ b/engines/director/director.cpp
@@ -120,10 +120,13 @@ Common::Error DirectorEngine::run() {
 
 	//testFont();
 
-	_movies = scanMovies(ConfMan.get("path"));
+	if (getPlatform() == Common::kPlatformWindows)
+		_sharedCastFile = "SHARDCST.MMM";
+	else
+		_sharedCastFile = "Shared Cast*";
+
+	loadSharedCastsFrom(_sharedCastFile);
 
-	if (!_sharedCastFile.empty())
-		loadSharedCastsFrom(_sharedCastFile);
 	loadMainArchive();
 
 	_currentScore = new Score(this, _mainArchive);


Commit: 814db5fd38ae87a23674f07461ca35358bd77eb5
    https://github.com/scummvm/scummvm/commit/814db5fd38ae87a23674f07461ca35358bd77eb5
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2016-10-26T10:48:37+02:00

Commit Message:
DIRECTOR: Renamed resource/archive files to better reflect reality

Changed paths:
  A engines/director/archive.h
  R engines/director/resource.h
    engines/director/archive.cpp
    engines/director/director.cpp
    engines/director/frame.cpp
    engines/director/resource.cpp
    engines/director/score.cpp



diff --git a/engines/director/archive.cpp b/engines/director/archive.cpp
index 9976c25..8297645 100644
--- a/engines/director/archive.cpp
+++ b/engines/director/archive.cpp
@@ -20,233 +20,430 @@
  *
  */
 
-#include "common/macresman.h"
+#include "director/archive.h"
 
-#include "director/director.h"
-#include "director/resource.h"
-#include "director/lingo/lingo.h"
+#include "common/debug.h"
+#include "common/macresman.h"
 
 namespace Director {
 
-Archive *DirectorEngine::createArchive() {
-	if (getPlatform() == Common::kPlatformMacintosh) {
-		if (getVersion() < 4)
-			return new MacArchive();
-		else
-			return new RIFXArchive();
-	} else {
-		return new RIFFArchive();
-	}
+// Base Archive code
+
+Archive::Archive() {
+	_stream = 0;
+	_isBigEndian = true;
 }
 
-void DirectorEngine::loadMainArchive() {
-	if (getPlatform() == Common::kPlatformWindows)
-		loadEXE();
-	else
-		loadMac();
-}
-
-void DirectorEngine::cleanupMainArchive() {
-	delete _mainArchive;
-	delete _macBinary;
-}
-
-void DirectorEngine::loadEXE() {
-	Common::SeekableReadStream *exeStream = SearchMan.createReadStreamForMember(getEXEName());
-	if (!exeStream)
-		error("Failed to open EXE '%s'", getEXEName().c_str());
-
-	_lingo->processEvent(kEventStart, 0);
-
-	exeStream->seek(-4, SEEK_END);
-	exeStream->seek(exeStream->readUint32LE());
-
-	switch (getVersion()) {
-	case 3:
-		loadEXEv3(exeStream);
-		break;
-	case 4:
-		loadEXEv4(exeStream);
-		break;
-	case 5:
-		loadEXEv5(exeStream);
-		break;
-	case 7:
-		loadEXEv7(exeStream);
-		break;
-	default:
-		error("Unhandled Windows EXE version %d", getVersion());
+Archive::~Archive() {
+	close();
+}
+
+bool Archive::openFile(const Common::String &fileName) {
+	Common::File *file = new Common::File();
+
+	if (!file->open(fileName)) {
+		delete file;
+		return false;
+	}
+
+	if (!openStream(file)) {
+		close();
+		return false;
 	}
+
+	_fileName = fileName;
+
+	return true;
 }
 
-void DirectorEngine::loadEXEv3(Common::SeekableReadStream *stream) {
-	uint16 entryCount = stream->readUint16LE();
-	if (entryCount != 1)
-		error("Unhandled multiple entry v3 EXE");
+void Archive::close() {
+	_types.clear();
 
-	stream->skip(5); // unknown
+	if (_stream)
+		delete _stream;
 
-	stream->readUint32LE(); // Main MMM size
-	Common::String mmmFileName = readPascalString(*stream);
-	Common::String directoryName = readPascalString(*stream);
+	_stream = 0;
+}
 
-	debugC(1, kDebugLoading, "Main MMM: '%s'", mmmFileName.c_str());
-	debugC(1, kDebugLoading, "Directory Name: '%s'", directoryName.c_str());
+bool Archive::hasResource(uint32 tag, uint16 id) const {
+	if (!_types.contains(tag))
+		return false;
 
-	_mainArchive = new RIFFArchive();
+	return _types[tag].contains(id);
+}
+
+bool Archive::hasResource(uint32 tag, const Common::String &resName) const {
+	if (!_types.contains(tag) || resName.empty())
+		return false;
+
+	const ResourceMap &resMap = _types[tag];
+
+	for (ResourceMap::const_iterator it = resMap.begin(); it != resMap.end(); it++)
+		if (it->_value.name.matchString(resName))
+			return true;
+
+	return false;
+}
 
-	if (!_mainArchive->openFile(mmmFileName))
-		error("Could not open '%s'", mmmFileName.c_str());
+Common::SeekableSubReadStreamEndian *Archive::getResource(uint32 tag, uint16 id) {
+	if (!_types.contains(tag))
+		error("Archive does not contain '%s' %04x", tag2str(tag), id);
 
-	delete stream;
+	const ResourceMap &resMap = _types[tag];
+
+	if (!resMap.contains(id))
+		error("Archive does not contain '%s' %04x", tag2str(tag), id);
+
+	const Resource &res = resMap[id];
+
+	return new Common::SeekableSubReadStreamEndian(_stream, res.offset, res.offset + res.size, _isBigEndian, DisposeAfterUse::NO);
 }
 
-void DirectorEngine::loadEXEv4(Common::SeekableReadStream *stream) {
-	if (stream->readUint32BE() != MKTAG('P', 'J', '9', '3'))
-		error("Invalid projector tag found in v4 EXE");
+uint32 Archive::getOffset(uint32 tag, uint16 id) const {
+	if (!_types.contains(tag))
+		error("Archive does not contain '%s' %04x", tag2str(tag), id);
 
-	uint32 rifxOffset = stream->readUint32LE();
-	/* uint32 fontMapOffset = */ stream->readUint32LE();
-	/* uint32 resourceForkOffset1 = */ stream->readUint32LE();
-	/* uint32 resourceForkOffset2 = */ stream->readUint32LE();
-	stream->readUint32LE(); // graphics DLL offset
-	stream->readUint32LE(); // sound DLL offset
-	/* uint32 rifxOffsetAlt = */ stream->readUint32LE(); // equivalent to rifxOffset
+	const ResourceMap &resMap = _types[tag];
 
-	loadEXERIFX(stream, rifxOffset);
+	if (!resMap.contains(id))
+		error("Archive does not contain '%s' %04x", tag2str(tag), id);
+
+	return resMap[id].offset;
 }
 
-void DirectorEngine::loadEXEv5(Common::SeekableReadStream *stream) {
-	if (stream->readUint32LE() != MKTAG('P', 'J', '9', '5'))
-		error("Invalid projector tag found in v5 EXE");
+uint16 Archive::findResourceID(uint32 tag, const Common::String &resName) const {
+	if (!_types.contains(tag) || resName.empty())
+		return 0xFFFF;
+
+	const ResourceMap &resMap = _types[tag];
+
+	for (ResourceMap::const_iterator it = resMap.begin(); it != resMap.end(); it++)
+		if (it->_value.name.matchString(resName))
+			return it->_key;
 
-	uint32 rifxOffset = stream->readUint32LE();
-	stream->readUint32LE(); // unknown
-	stream->readUint32LE(); // unknown
-	stream->readUint32LE(); // unknown
-	/* uint16 screenWidth = */ stream->readUint16LE();
-	/* uint16 screenHeight = */ stream->readUint16LE();
-	stream->readUint32LE(); // unknown
-	stream->readUint32LE(); // unknown
-	/* uint32 fontMapOffset = */ stream->readUint32LE();
+	return 0xFFFF;
+}
+
+Common::String Archive::getName(uint32 tag, uint16 id) const {
+	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].name;
+}
+
+Common::Array<uint32> Archive::getResourceTypeList() const {
+	Common::Array<uint32> typeList;
+
+	for (TypeMap::const_iterator it = _types.begin(); it != _types.end(); it++)
+		typeList.push_back(it->_key);
+
+	return typeList;
+}
+
+Common::Array<uint16> Archive::getResourceIDList(uint32 type) const {
+	Common::Array<uint16> idList;
+
+	if (!_types.contains(type))
+		return idList;
+
+	const ResourceMap &resMap = _types[type];
+
+	for (ResourceMap::const_iterator it = resMap.begin(); it != resMap.end(); it++)
+		idList.push_back(it->_key);
+
+	return idList;
+}
+
+uint32 Archive::convertTagToUppercase(uint32 tag) {
+	uint32 newTag = toupper(tag >> 24) << 24;
+	newTag |= toupper((tag >> 16) & 0xFF) << 16;
+	newTag |= toupper((tag >> 8) & 0xFF) << 8;
+
+	return newTag | toupper(tag & 0xFF);
+}
+
+// Mac Archive code
+
+MacArchive::MacArchive() : Archive(), _resFork(0) {
+}
+
+MacArchive::~MacArchive() {
+	delete _resFork;
+}
 
-	loadEXERIFX(stream, rifxOffset);
+void MacArchive::close() {
+	Archive::close();
+	delete _resFork;
+	_resFork = 0;
 }
 
-void DirectorEngine::loadEXEv7(Common::SeekableReadStream *stream) {
-	if (stream->readUint32LE() != MKTAG('P', 'J', '0', '0'))
-		error("Invalid projector tag found in v7 EXE");
+bool MacArchive::openFile(const Common::String &fileName) {
+	close();
 
-	uint32 rifxOffset = stream->readUint32LE();
-	stream->readUint32LE(); // unknown
-	stream->readUint32LE(); // unknown
-	stream->readUint32LE(); // unknown
-	stream->readUint32LE(); // unknown
-	stream->readUint32LE(); // some DLL offset
+	_resFork = new Common::MacResManager();
 
-	loadEXERIFX(stream, rifxOffset);
+	if (!_resFork->open(fileName) || !_resFork->hasResFork()) {
+		close();
+		return false;
+	}
+
+	_fileName = _resFork->getBaseFileName();
+	if (_fileName.hasSuffix(".bin")) {
+		for (int i = 0; i < 4; i++)
+			_fileName.deleteLastChar();
+	}
+
+	Common::MacResTagArray tagArray = _resFork->getResTagArray();
+
+	for (uint32 i = 0; i < tagArray.size(); i++) {
+		ResourceMap &resMap = _types[tagArray[i]];
+		Common::MacResIDArray idArray = _resFork->getResIDArray(tagArray[i]);
+
+		for (uint32 j = 0; j < idArray.size(); j++) {
+			Resource &res = resMap[idArray[j]];
+
+			res.offset = res.size = 0; // unused
+			res.name = _resFork->getResName(tagArray[i], idArray[j]);
+			debug(3, "Found MacArchive resource '%s' %d: %s", tag2str(tagArray[i]), idArray[j], res.name.c_str());
+		}
+	}
+
+	return true;
 }
 
-void DirectorEngine::loadEXERIFX(Common::SeekableReadStream *stream, uint32 offset) {
-	_mainArchive = new RIFXArchive();
+bool MacArchive::openStream(Common::SeekableReadStream *stream, uint32 startOffset) {
+	// TODO: Add support for this (v4 Windows games)
+	return false;
+}
 
-	if (!_mainArchive->openStream(stream, offset))
-		error("Failed to load RIFX from EXE");
+Common::SeekableSubReadStreamEndian *MacArchive::getResource(uint32 tag, uint16 id) {
+	assert(_resFork);
+	Common::SeekableReadStream *stream = _resFork->getResource(tag, id);
+	return new Common::SeekableSubReadStreamEndian(stream, 0, stream->size(), true, DisposeAfterUse::NO);
 }
 
-void DirectorEngine::loadMac() {
-	if (getVersion() < 4) {
-		// The data is part of the resource fork of the executable
-		_mainArchive = new MacArchive();
+// RIFF Archive code
+
+bool RIFFArchive::openStream(Common::SeekableReadStream *stream, uint32 startOffset) {
+	close();
+
+	stream->seek(startOffset);
 
-		if (!_mainArchive->openFile(getEXEName()))
-			error("Failed to open Mac binary '%s'", getEXEName().c_str());
-	} else {
-		// The RIFX is located in the data fork of the executable
-		_macBinary = new Common::MacResManager();
+	if (convertTagToUppercase(stream->readUint32BE()) != MKTAG('R', 'I', 'F', 'F'))
+		return false;
 
-		if (!_macBinary->open(getEXEName()) || !_macBinary->hasDataFork())
-			error("Failed to open Mac binary '%s'", getEXEName().c_str());
+	stream->readUint32LE(); // size
 
-		Common::SeekableReadStream *dataFork = _macBinary->getDataFork();
-		_mainArchive = new RIFXArchive();
+	if (convertTagToUppercase(stream->readUint32BE()) != MKTAG('R', 'M', 'M', 'P'))
+		return false;
 
-		// First we need to detect PPC vs. 68k
+	if (convertTagToUppercase(stream->readUint32BE()) != MKTAG('C', 'F', 'T', 'C'))
+		return false;
 
-		uint32 tag = dataFork->readUint32BE();
-		uint32 startOffset;
+	uint32 cftcSize = stream->readUint32LE();
+	uint32 startPos = stream->pos();
+	stream->readUint32LE(); // unknown (always 0?)
 
-		if (SWAP_BYTES_32(tag) == MKTAG('P', 'J', '9', '3') || tag == MKTAG('P', 'J', '9', '5') || tag == MKTAG('P', 'J', '0', '0')) {
-			// PPC: The RIFX shares the data fork with the binary
-			startOffset = dataFork->readUint32BE();
-		} else {
-			// 68k: The RIFX is the only thing in the data fork
-			startOffset = 0;
+	while ((uint32)stream->pos() < startPos + cftcSize) {
+		uint32 tag = convertTagToUppercase(stream->readUint32BE());
+
+		uint32 size = stream->readUint32LE();
+		uint32 id = stream->readUint32LE();
+		uint32 offset = stream->readUint32LE();
+
+		if (tag == 0)
+			break;
+
+		uint16 startResPos = stream->pos();
+		stream->seek(offset + 12);
+
+		Common::String name = "";
+		byte nameSize = stream->readByte();
+
+		if (nameSize) {
+			for (uint8 i = 0; i < nameSize; i++) {
+				name += stream->readByte();
+			}
 		}
 
-		if (!_mainArchive->openStream(dataFork, startOffset))
-			error("Failed to load RIFX from Mac binary");
+		stream->seek(startResPos);
+
+		debug(3, "Found RIFF resource '%s' %d: %d @ 0x%08x", tag2str(tag), id, size, offset);
+
+		ResourceMap &resMap = _types[tag];
+		Resource &res = resMap[id];
+		res.offset = offset;
+		res.size = size;
+		res.name = name;
 	}
+
+	_stream = stream;
+	return true;
 }
 
-void DirectorEngine::loadSharedCastsFrom(Common::String filename) {
-	Archive *shardcst = createArchive();
+Common::SeekableSubReadStreamEndian *RIFFArchive::getResource(uint32 tag, uint16 id) {
+	if (!_types.contains(tag))
+		error("Archive does not contain '%s' %04x", tag2str(tag), id);
+
+	const ResourceMap &resMap = _types[tag];
 
-	debugC(1, kDebugLoading, "Loading Shared cast '%s'", filename.c_str());
+	if (!resMap.contains(id))
+		error("Archive does not contain '%s' %04x", tag2str(tag), id);
 
-	if (!shardcst->openFile(filename)) {
-		warning("No shared cast %s", filename.c_str());
+	const Resource &res = resMap[id];
 
-		return;
+	// Adjust to skip the resource header
+	uint32 offset = res.offset + 12;
+	uint32 size = res.size - 4;
+	// Skip the Pascal string
+	_stream->seek(offset);
+	byte stringSize = _stream->readByte(); // 1 for this byte
+
+	offset += stringSize + 1;
+	size -= stringSize + 1;
+
+	// Align to nearest word boundary
+	if (offset & 1) {
+		offset++;
+		size--;
 	}
 
-	_sharedDIB = new Common::HashMap<int, Common::SeekableSubReadStreamEndian *>;
-	_sharedSTXT = new Common::HashMap<int, Common::SeekableSubReadStreamEndian *>;
-	_sharedSound = new Common::HashMap<int, Common::SeekableSubReadStreamEndian *>;
-	_sharedBMP = new Common::HashMap<int, Common::SeekableSubReadStreamEndian *>;
+	return new Common::SeekableSubReadStreamEndian(_stream, offset, offset + size, true, DisposeAfterUse::NO);
+}
 
-	Score *castScore = new Score(this, shardcst);
+// RIFX Archive code
 
-	castScore->loadConfig(*shardcst->getResource(MKTAG('V','W','C','F'), 1024));
-	castScore->loadCastData(*shardcst->getResource(MKTAG('V','W','C','R'), 1024));
+bool RIFXArchive::openStream(Common::SeekableReadStream *stream, uint32 startOffset) {
+	close();
 
-	_sharedCasts = &castScore->_casts;
+	stream->seek(startOffset);
 
-	Common::Array<uint16> dib = shardcst->getResourceIDList(MKTAG('D','I','B',' '));
-	if (dib.size() != 0) {
-		debugC(3, kDebugLoading, "Loading %d DIBs", dib.size());
+	uint32 headerTag = stream->readUint32BE();
 
-		for (Common::Array<uint16>::iterator iterator = dib.begin(); iterator != dib.end(); ++iterator) {
-			debugC(3, kDebugLoading, "Shared DIB %d", *iterator);
-			_sharedDIB->setVal(*iterator, shardcst->getResource(MKTAG('D','I','B',' '), *iterator));
-		}
+	if (headerTag == MKTAG('R', 'I', 'F', 'X'))
+		_isBigEndian = true;
+	else if (SWAP_BYTES_32(headerTag) == MKTAG('R', 'I', 'F', 'X'))
+		_isBigEndian = false;
+	else
+		return false;
+
+	Common::SeekableSubReadStreamEndian subStream(stream, startOffset + 4, stream->size(), _isBigEndian, DisposeAfterUse::NO);
+
+	subStream.readUint32(); // size
+
+	uint32 rifxType = subStream.readUint32();
+
+	if (rifxType != MKTAG('M', 'V', '9', '3') && rifxType != MKTAG('A', 'P', 'P', 'L'))
+		return false;
+
+	if (subStream.readUint32() != MKTAG('i', 'm', 'a', 'p'))
+		return false;
+
+	subStream.readUint32(); // imap length
+	subStream.readUint32(); // unknown
+	uint32 mmapOffset = subStream.readUint32() - startOffset - 4;
+
+	subStream.seek(mmapOffset);
+
+	if (subStream.readUint32() != MKTAG('m', 'm', 'a', 'p'))
+		return false;
+
+	subStream.readUint32(); // mmap length
+	subStream.readUint16(); // unknown
+	subStream.readUint16(); // unknown
+	subStream.readUint32(); // resCount + empty entries
+	uint32 resCount = subStream.readUint32();
+	subStream.skip(8); // all 0xFF
+	subStream.readUint32(); // unknown
+
+	Common::Array<Resource> resources;
+
+	// Need to look for these two resources
+	const Resource *keyRes = 0;
+	const Resource *casRes = 0;
+
+	for (uint32 i = 0; i < resCount; i++) {
+		uint32 tag = subStream.readUint32();
+		uint32 size = subStream.readUint32();
+		uint32 offset = subStream.readUint32();
+		/*uint16 flags = */ subStream.readUint16();
+		/*uint16 unk1 = */ subStream.readUint16();
+		/*uint32 unk2 = */ subStream.readUint32();
+
+		debug(3, "Found RIFX resource index %d: '%s', %d @ 0x%08x", i, tag2str(tag), size, offset);
+
+		Resource res;
+		res.offset = offset;
+		res.size = size;
+		resources.push_back(res);
+
+		// APPL is a special case; it has an embedded "normal" archive
+		if (rifxType == MKTAG('A', 'P', 'P', 'L') && tag == MKTAG('F', 'i', 'l', 'e'))
+			return openStream(stream, offset);
+
+		// Looking for two types here
+		if (tag == MKTAG('K', 'E', 'Y', '*'))
+			keyRes = &resources[resources.size() - 1];
+		else if (tag == MKTAG('C', 'A', 'S', '*'))
+			casRes = &resources[resources.size() - 1];
 	}
 
-	Common::Array<uint16> stxt = shardcst->getResourceIDList(MKTAG('S','T','X','T'));
-	if (stxt.size() != 0) {
-		debugC(3, kDebugLoading, "Loading %d STXTs", stxt.size());
+	// We need to have found the 'File' resource already
+	if (rifxType == MKTAG('A', 'P', 'P', 'L')) {
+		warning("No 'File' resource present in APPL archive");
+		return false;
+	}
 
-		for (Common::Array<uint16>::iterator iterator = stxt.begin(); iterator != stxt.end(); ++iterator) {
-			debugC(3, kDebugLoading, "Shared STXT %d", *iterator);
-			_sharedSTXT->setVal(*iterator, shardcst->getResource(MKTAG('S','T','X','T'), *iterator));
-		}
+	// A KEY* must be present
+	if (!keyRes) {
+		warning("No 'KEY*' resource present");
+		return false;
 	}
 
-	Common::Array<uint16> bmp = shardcst->getResourceIDList(MKTAG('B','I','T','D'));
-	if (bmp.size() != 0) {
-		debugC(3, kDebugLoading, "Loading %d BITDs", bmp.size());
-		for (Common::Array<uint16>::iterator iterator = bmp.begin(); iterator != bmp.end(); ++iterator) {
-			_sharedBMP->setVal(*iterator, shardcst->getResource(MKTAG('B','I','T','D'), *iterator));
-		}
+	// Parse the CAS*, if present
+	Common::Array<uint32> casEntries;
+	if (casRes) {
+		Common::SeekableSubReadStreamEndian casStream(stream, casRes->offset + 8, casRes->offset + 8 + casRes->size, _isBigEndian, DisposeAfterUse::NO);
+		casEntries.resize(casRes->size / 4);
+
+		for (uint32 i = 0; i < casEntries.size(); i++)
+			casEntries[i] = casStream.readUint32();
 	}
 
-	Common::Array<uint16> sound = shardcst->getResourceIDList(MKTAG('S','N','D',' '));
-	if (stxt.size() != 0) {
-		debugC(3, kDebugLoading, "Loading %d SNDs", sound.size());
-		for (Common::Array<uint16>::iterator iterator = sound.begin(); iterator != sound.end(); ++iterator) {
-			_sharedSound->setVal(*iterator, shardcst->getResource(MKTAG('S','N','D',' '), *iterator));
+	// Parse the KEY*
+	Common::SeekableSubReadStreamEndian keyStream(stream, keyRes->offset + 8, keyRes->offset + 8 + keyRes->size, _isBigEndian, DisposeAfterUse::NO);
+	/*uint16 unk1 = */ keyStream.readUint16();
+	/*uint16 unk2 = */ keyStream.readUint16();
+	/*uint32 unk3 = */ keyStream.readUint32();
+	uint32 keyCount = keyStream.readUint32();
+
+	for (uint32 i = 0; i < keyCount; i++) {
+		uint32 index = keyStream.readUint32();
+		uint32 id = keyStream.readUint32();
+		uint32 resTag = keyStream.readUint32();
+
+		// Handle CAS*/CASt nonsense
+		if (resTag == MKTAG('C', 'A', 'S', 't')) {
+			for (uint32 j = 0; j < casEntries.size(); j++) {
+				if (casEntries[j] == index) {
+					id += j + 1;
+					break;
+				}
+			}
 		}
+
+		const Resource &res = resources[index];
+		debug(3, "Found RIFX resource: '%s' 0x%04x, %d @ 0x%08x", tag2str(resTag), id, res.size, res.offset);
+		_types[resTag][id] = res;
 	}
+
+	_stream = stream;
+	return true;
 }
 
 } // End of namespace Director
diff --git a/engines/director/archive.h b/engines/director/archive.h
new file mode 100644
index 0000000..54d7086
--- /dev/null
+++ b/engines/director/archive.h
@@ -0,0 +1,109 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef DIRECTOR_ARCHIVE_H
+#define DIRECTOR_ARCHIVE_H
+
+#include "common/file.h"
+#include "common/substream.h"
+
+namespace Common {
+class MacResManager;
+}
+
+namespace Director {
+
+// Completely ripped off of Mohawk's Archive code
+
+class Archive {
+public:
+	Archive();
+	virtual ~Archive();
+
+	virtual bool openFile(const Common::String &fileName);
+	virtual bool openStream(Common::SeekableReadStream *stream, uint32 offset = 0) = 0;
+	virtual void close();
+
+	Common::String getFileName() const { return _fileName; }
+
+	bool isOpen() const { return _stream != 0; }
+
+	bool hasResource(uint32 tag, uint16 id) const;
+	bool hasResource(uint32 tag, const Common::String &resName) const;
+	virtual Common::SeekableSubReadStreamEndian *getResource(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;
+
+	Common::Array<uint32> getResourceTypeList() const;
+	Common::Array<uint16> getResourceIDList(uint32 type) const;
+	bool _isBigEndian;
+	static uint32 convertTagToUppercase(uint32 tag);
+
+protected:
+	Common::SeekableReadStream *_stream;
+	struct Resource {
+		uint32 offset;
+		uint32 size;
+		Common::String name;
+	};
+	typedef Common::HashMap<uint16, Resource> ResourceMap;
+	typedef Common::HashMap<uint32, ResourceMap> TypeMap;
+	TypeMap _types;
+
+	Common::String _fileName;
+};
+
+class MacArchive : public Archive {
+public:
+	MacArchive();
+	~MacArchive();
+
+	void close();
+	bool openFile(const Common::String &fileName);
+	bool openStream(Common::SeekableReadStream *stream, uint32 startOffset = 0);
+	Common::SeekableSubReadStreamEndian *getResource(uint32 tag, uint16 id);
+
+private:
+	Common::MacResManager *_resFork;
+};
+
+class RIFFArchive : public Archive {
+public:
+	RIFFArchive() : Archive() {}
+	~RIFFArchive() {}
+
+	bool openStream(Common::SeekableReadStream *stream, uint32 startOffset = 0);
+	Common::SeekableSubReadStreamEndian *getResource(uint32 tag, uint16 id);
+};
+
+class RIFXArchive : public Archive {
+public:
+	RIFXArchive() : Archive(){ _isBigEndian = true; }
+	~RIFXArchive() {}
+
+	bool openStream(Common::SeekableReadStream *stream, uint32 startOffset = 0);
+};
+
+} // End of namespace Director
+
+#endif
diff --git a/engines/director/director.cpp b/engines/director/director.cpp
index 034c7c4..32358e4 100644
--- a/engines/director/director.cpp
+++ b/engines/director/director.cpp
@@ -27,7 +27,7 @@
 #include "graphics/macgui/macwindowmanager.h"
 
 #include "director/director.h"
-#include "director/resource.h"
+#include "director/archive.h"
 #include "director/sound.h"
 #include "director/lingo/lingo.h"
 
diff --git a/engines/director/frame.cpp b/engines/director/frame.cpp
index 0ce7f2b..c00d8bd 100644
--- a/engines/director/frame.cpp
+++ b/engines/director/frame.cpp
@@ -29,7 +29,7 @@
 #include "director/director.h"
 #include "director/frame.h"
 #include "director/images.h"
-#include "director/resource.h"
+#include "director/archive.h"
 #include "director/score.h"
 #include "director/sprite.h"
 
diff --git a/engines/director/resource.cpp b/engines/director/resource.cpp
index 8efec14..a704918 100644
--- a/engines/director/resource.cpp
+++ b/engines/director/resource.cpp
@@ -20,430 +20,233 @@
  *
  */
 
-#include "director/resource.h"
-
-#include "common/debug.h"
 #include "common/macresman.h"
 
-namespace Director {
-
-// Base Archive code
-
-Archive::Archive() {
-	_stream = 0;
-	_isBigEndian = true;
-}
-
-Archive::~Archive() {
-	close();
-}
+#include "director/director.h"
+#include "director/archive.h"
+#include "director/lingo/lingo.h"
 
-bool Archive::openFile(const Common::String &fileName) {
-	Common::File *file = new Common::File();
-
-	if (!file->open(fileName)) {
-		delete file;
-		return false;
-	}
+namespace Director {
 
-	if (!openStream(file)) {
-		close();
-		return false;
+Archive *DirectorEngine::createArchive() {
+	if (getPlatform() == Common::kPlatformMacintosh) {
+		if (getVersion() < 4)
+			return new MacArchive();
+		else
+			return new RIFXArchive();
+	} else {
+		return new RIFFArchive();
 	}
-
-	_fileName = fileName;
-
-	return true;
 }
 
-void Archive::close() {
-	_types.clear();
-
-	if (_stream)
-		delete _stream;
-
-	_stream = 0;
-}
-
-bool Archive::hasResource(uint32 tag, uint16 id) const {
-	if (!_types.contains(tag))
-		return false;
-
-	return _types[tag].contains(id);
-}
-
-bool Archive::hasResource(uint32 tag, const Common::String &resName) const {
-	if (!_types.contains(tag) || resName.empty())
-		return false;
-
-	const ResourceMap &resMap = _types[tag];
-
-	for (ResourceMap::const_iterator it = resMap.begin(); it != resMap.end(); it++)
-		if (it->_value.name.matchString(resName))
-			return true;
-
-	return false;
-}
-
-Common::SeekableSubReadStreamEndian *Archive::getResource(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);
-
-	const Resource &res = resMap[id];
-
-	return new Common::SeekableSubReadStreamEndian(_stream, res.offset, res.offset + res.size, _isBigEndian, DisposeAfterUse::NO);
-}
-
-uint32 Archive::getOffset(uint32 tag, uint16 id) const {
-	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].offset;
-}
-
-uint16 Archive::findResourceID(uint32 tag, const Common::String &resName) const {
-	if (!_types.contains(tag) || resName.empty())
-		return 0xFFFF;
-
-	const ResourceMap &resMap = _types[tag];
-
-	for (ResourceMap::const_iterator it = resMap.begin(); it != resMap.end(); it++)
-		if (it->_value.name.matchString(resName))
-			return it->_key;
-
-	return 0xFFFF;
+void DirectorEngine::loadMainArchive() {
+	if (getPlatform() == Common::kPlatformWindows)
+		loadEXE();
+	else
+		loadMac();
+}
+
+void DirectorEngine::cleanupMainArchive() {
+	delete _mainArchive;
+	delete _macBinary;
+}
+
+void DirectorEngine::loadEXE() {
+	Common::SeekableReadStream *exeStream = SearchMan.createReadStreamForMember(getEXEName());
+	if (!exeStream)
+		error("Failed to open EXE '%s'", getEXEName().c_str());
+
+	_lingo->processEvent(kEventStart, 0);
+
+	exeStream->seek(-4, SEEK_END);
+	exeStream->seek(exeStream->readUint32LE());
+
+	switch (getVersion()) {
+	case 3:
+		loadEXEv3(exeStream);
+		break;
+	case 4:
+		loadEXEv4(exeStream);
+		break;
+	case 5:
+		loadEXEv5(exeStream);
+		break;
+	case 7:
+		loadEXEv7(exeStream);
+		break;
+	default:
+		error("Unhandled Windows EXE version %d", getVersion());
+	}
 }
 
-Common::String Archive::getName(uint32 tag, uint16 id) const {
-	if (!_types.contains(tag))
-		error("Archive does not contain '%s' %04x", tag2str(tag), id);
+void DirectorEngine::loadEXEv3(Common::SeekableReadStream *stream) {
+	uint16 entryCount = stream->readUint16LE();
+	if (entryCount != 1)
+		error("Unhandled multiple entry v3 EXE");
 
-	const ResourceMap &resMap = _types[tag];
+	stream->skip(5); // unknown
 
-	if (!resMap.contains(id))
-		error("Archive does not contain '%s' %04x", tag2str(tag), id);
+	stream->readUint32LE(); // Main MMM size
+	Common::String mmmFileName = readPascalString(*stream);
+	Common::String directoryName = readPascalString(*stream);
 
-	return resMap[id].name;
-}
+	debugC(1, kDebugLoading, "Main MMM: '%s'", mmmFileName.c_str());
+	debugC(1, kDebugLoading, "Directory Name: '%s'", directoryName.c_str());
 
-Common::Array<uint32> Archive::getResourceTypeList() const {
-	Common::Array<uint32> typeList;
+	_mainArchive = new RIFFArchive();
 
-	for (TypeMap::const_iterator it = _types.begin(); it != _types.end(); it++)
-		typeList.push_back(it->_key);
+	if (!_mainArchive->openFile(mmmFileName))
+		error("Could not open '%s'", mmmFileName.c_str());
 
-	return typeList;
+	delete stream;
 }
 
-Common::Array<uint16> Archive::getResourceIDList(uint32 type) const {
-	Common::Array<uint16> idList;
-
-	if (!_types.contains(type))
-		return idList;
-
-	const ResourceMap &resMap = _types[type];
+void DirectorEngine::loadEXEv4(Common::SeekableReadStream *stream) {
+	if (stream->readUint32BE() != MKTAG('P', 'J', '9', '3'))
+		error("Invalid projector tag found in v4 EXE");
 
-	for (ResourceMap::const_iterator it = resMap.begin(); it != resMap.end(); it++)
-		idList.push_back(it->_key);
+	uint32 rifxOffset = stream->readUint32LE();
+	/* uint32 fontMapOffset = */ stream->readUint32LE();
+	/* uint32 resourceForkOffset1 = */ stream->readUint32LE();
+	/* uint32 resourceForkOffset2 = */ stream->readUint32LE();
+	stream->readUint32LE(); // graphics DLL offset
+	stream->readUint32LE(); // sound DLL offset
+	/* uint32 rifxOffsetAlt = */ stream->readUint32LE(); // equivalent to rifxOffset
 
-	return idList;
+	loadEXERIFX(stream, rifxOffset);
 }
 
-uint32 Archive::convertTagToUppercase(uint32 tag) {
-	uint32 newTag = toupper(tag >> 24) << 24;
-	newTag |= toupper((tag >> 16) & 0xFF) << 16;
-	newTag |= toupper((tag >> 8) & 0xFF) << 8;
+void DirectorEngine::loadEXEv5(Common::SeekableReadStream *stream) {
+	if (stream->readUint32LE() != MKTAG('P', 'J', '9', '5'))
+		error("Invalid projector tag found in v5 EXE");
 
-	return newTag | toupper(tag & 0xFF);
-}
-
-// Mac Archive code
-
-MacArchive::MacArchive() : Archive(), _resFork(0) {
-}
-
-MacArchive::~MacArchive() {
-	delete _resFork;
-}
+	uint32 rifxOffset = stream->readUint32LE();
+	stream->readUint32LE(); // unknown
+	stream->readUint32LE(); // unknown
+	stream->readUint32LE(); // unknown
+	/* uint16 screenWidth = */ stream->readUint16LE();
+	/* uint16 screenHeight = */ stream->readUint16LE();
+	stream->readUint32LE(); // unknown
+	stream->readUint32LE(); // unknown
+	/* uint32 fontMapOffset = */ stream->readUint32LE();
 
-void MacArchive::close() {
-	Archive::close();
-	delete _resFork;
-	_resFork = 0;
+	loadEXERIFX(stream, rifxOffset);
 }
 
-bool MacArchive::openFile(const Common::String &fileName) {
-	close();
+void DirectorEngine::loadEXEv7(Common::SeekableReadStream *stream) {
+	if (stream->readUint32LE() != MKTAG('P', 'J', '0', '0'))
+		error("Invalid projector tag found in v7 EXE");
 
-	_resFork = new Common::MacResManager();
+	uint32 rifxOffset = stream->readUint32LE();
+	stream->readUint32LE(); // unknown
+	stream->readUint32LE(); // unknown
+	stream->readUint32LE(); // unknown
+	stream->readUint32LE(); // unknown
+	stream->readUint32LE(); // some DLL offset
 
-	if (!_resFork->open(fileName) || !_resFork->hasResFork()) {
-		close();
-		return false;
-	}
-
-	_fileName = _resFork->getBaseFileName();
-	if (_fileName.hasSuffix(".bin")) {
-		for (int i = 0; i < 4; i++)
-			_fileName.deleteLastChar();
-	}
-
-	Common::MacResTagArray tagArray = _resFork->getResTagArray();
-
-	for (uint32 i = 0; i < tagArray.size(); i++) {
-		ResourceMap &resMap = _types[tagArray[i]];
-		Common::MacResIDArray idArray = _resFork->getResIDArray(tagArray[i]);
-
-		for (uint32 j = 0; j < idArray.size(); j++) {
-			Resource &res = resMap[idArray[j]];
-
-			res.offset = res.size = 0; // unused
-			res.name = _resFork->getResName(tagArray[i], idArray[j]);
-			debug(3, "Found MacArchive resource '%s' %d: %s", tag2str(tagArray[i]), idArray[j], res.name.c_str());
-		}
-	}
-
-	return true;
+	loadEXERIFX(stream, rifxOffset);
 }
 
-bool MacArchive::openStream(Common::SeekableReadStream *stream, uint32 startOffset) {
-	// TODO: Add support for this (v4 Windows games)
-	return false;
-}
+void DirectorEngine::loadEXERIFX(Common::SeekableReadStream *stream, uint32 offset) {
+	_mainArchive = new RIFXArchive();
 
-Common::SeekableSubReadStreamEndian *MacArchive::getResource(uint32 tag, uint16 id) {
-	assert(_resFork);
-	Common::SeekableReadStream *stream = _resFork->getResource(tag, id);
-	return new Common::SeekableSubReadStreamEndian(stream, 0, stream->size(), true, DisposeAfterUse::NO);
+	if (!_mainArchive->openStream(stream, offset))
+		error("Failed to load RIFX from EXE");
 }
 
-// RIFF Archive code
-
-bool RIFFArchive::openStream(Common::SeekableReadStream *stream, uint32 startOffset) {
-	close();
-
-	stream->seek(startOffset);
+void DirectorEngine::loadMac() {
+	if (getVersion() < 4) {
+		// The data is part of the resource fork of the executable
+		_mainArchive = new MacArchive();
 
-	if (convertTagToUppercase(stream->readUint32BE()) != MKTAG('R', 'I', 'F', 'F'))
-		return false;
+		if (!_mainArchive->openFile(getEXEName()))
+			error("Failed to open Mac binary '%s'", getEXEName().c_str());
+	} else {
+		// The RIFX is located in the data fork of the executable
+		_macBinary = new Common::MacResManager();
 
-	stream->readUint32LE(); // size
+		if (!_macBinary->open(getEXEName()) || !_macBinary->hasDataFork())
+			error("Failed to open Mac binary '%s'", getEXEName().c_str());
 
-	if (convertTagToUppercase(stream->readUint32BE()) != MKTAG('R', 'M', 'M', 'P'))
-		return false;
+		Common::SeekableReadStream *dataFork = _macBinary->getDataFork();
+		_mainArchive = new RIFXArchive();
 
-	if (convertTagToUppercase(stream->readUint32BE()) != MKTAG('C', 'F', 'T', 'C'))
-		return false;
+		// First we need to detect PPC vs. 68k
 
-	uint32 cftcSize = stream->readUint32LE();
-	uint32 startPos = stream->pos();
-	stream->readUint32LE(); // unknown (always 0?)
+		uint32 tag = dataFork->readUint32BE();
+		uint32 startOffset;
 
-	while ((uint32)stream->pos() < startPos + cftcSize) {
-		uint32 tag = convertTagToUppercase(stream->readUint32BE());
-
-		uint32 size = stream->readUint32LE();
-		uint32 id = stream->readUint32LE();
-		uint32 offset = stream->readUint32LE();
-
-		if (tag == 0)
-			break;
-
-		uint16 startResPos = stream->pos();
-		stream->seek(offset + 12);
-
-		Common::String name = "";
-		byte nameSize = stream->readByte();
-
-		if (nameSize) {
-			for (uint8 i = 0; i < nameSize; i++) {
-				name += stream->readByte();
-			}
+		if (SWAP_BYTES_32(tag) == MKTAG('P', 'J', '9', '3') || tag == MKTAG('P', 'J', '9', '5') || tag == MKTAG('P', 'J', '0', '0')) {
+			// PPC: The RIFX shares the data fork with the binary
+			startOffset = dataFork->readUint32BE();
+		} else {
+			// 68k: The RIFX is the only thing in the data fork
+			startOffset = 0;
 		}
 
-		stream->seek(startResPos);
-
-		debug(3, "Found RIFF resource '%s' %d: %d @ 0x%08x", tag2str(tag), id, size, offset);
-
-		ResourceMap &resMap = _types[tag];
-		Resource &res = resMap[id];
-		res.offset = offset;
-		res.size = size;
-		res.name = name;
+		if (!_mainArchive->openStream(dataFork, startOffset))
+			error("Failed to load RIFX from Mac binary");
 	}
-
-	_stream = stream;
-	return true;
 }
 
-Common::SeekableSubReadStreamEndian *RIFFArchive::getResource(uint32 tag, uint16 id) {
-	if (!_types.contains(tag))
-		error("Archive does not contain '%s' %04x", tag2str(tag), id);
-
-	const ResourceMap &resMap = _types[tag];
+void DirectorEngine::loadSharedCastsFrom(Common::String filename) {
+	Archive *shardcst = createArchive();
 
-	if (!resMap.contains(id))
-		error("Archive does not contain '%s' %04x", tag2str(tag), id);
+	debugC(1, kDebugLoading, "Loading Shared cast '%s'", filename.c_str());
 
-	const Resource &res = resMap[id];
+	if (!shardcst->openFile(filename)) {
+		warning("No shared cast %s", filename.c_str());
 
-	// Adjust to skip the resource header
-	uint32 offset = res.offset + 12;
-	uint32 size = res.size - 4;
-	// Skip the Pascal string
-	_stream->seek(offset);
-	byte stringSize = _stream->readByte(); // 1 for this byte
-
-	offset += stringSize + 1;
-	size -= stringSize + 1;
-
-	// Align to nearest word boundary
-	if (offset & 1) {
-		offset++;
-		size--;
+		return;
 	}
 
-	return new Common::SeekableSubReadStreamEndian(_stream, offset, offset + size, true, DisposeAfterUse::NO);
-}
+	_sharedDIB = new Common::HashMap<int, Common::SeekableSubReadStreamEndian *>;
+	_sharedSTXT = new Common::HashMap<int, Common::SeekableSubReadStreamEndian *>;
+	_sharedSound = new Common::HashMap<int, Common::SeekableSubReadStreamEndian *>;
+	_sharedBMP = new Common::HashMap<int, Common::SeekableSubReadStreamEndian *>;
 
-// RIFX Archive code
+	Score *castScore = new Score(this, shardcst);
 
-bool RIFXArchive::openStream(Common::SeekableReadStream *stream, uint32 startOffset) {
-	close();
+	castScore->loadConfig(*shardcst->getResource(MKTAG('V','W','C','F'), 1024));
+	castScore->loadCastData(*shardcst->getResource(MKTAG('V','W','C','R'), 1024));
 
-	stream->seek(startOffset);
+	_sharedCasts = &castScore->_casts;
 
-	uint32 headerTag = stream->readUint32BE();
+	Common::Array<uint16> dib = shardcst->getResourceIDList(MKTAG('D','I','B',' '));
+	if (dib.size() != 0) {
+		debugC(3, kDebugLoading, "Loading %d DIBs", dib.size());
 
-	if (headerTag == MKTAG('R', 'I', 'F', 'X'))
-		_isBigEndian = true;
-	else if (SWAP_BYTES_32(headerTag) == MKTAG('R', 'I', 'F', 'X'))
-		_isBigEndian = false;
-	else
-		return false;
-
-	Common::SeekableSubReadStreamEndian subStream(stream, startOffset + 4, stream->size(), _isBigEndian, DisposeAfterUse::NO);
-
-	subStream.readUint32(); // size
-
-	uint32 rifxType = subStream.readUint32();
-
-	if (rifxType != MKTAG('M', 'V', '9', '3') && rifxType != MKTAG('A', 'P', 'P', 'L'))
-		return false;
-
-	if (subStream.readUint32() != MKTAG('i', 'm', 'a', 'p'))
-		return false;
-
-	subStream.readUint32(); // imap length
-	subStream.readUint32(); // unknown
-	uint32 mmapOffset = subStream.readUint32() - startOffset - 4;
-
-	subStream.seek(mmapOffset);
-
-	if (subStream.readUint32() != MKTAG('m', 'm', 'a', 'p'))
-		return false;
-
-	subStream.readUint32(); // mmap length
-	subStream.readUint16(); // unknown
-	subStream.readUint16(); // unknown
-	subStream.readUint32(); // resCount + empty entries
-	uint32 resCount = subStream.readUint32();
-	subStream.skip(8); // all 0xFF
-	subStream.readUint32(); // unknown
-
-	Common::Array<Resource> resources;
-
-	// Need to look for these two resources
-	const Resource *keyRes = 0;
-	const Resource *casRes = 0;
-
-	for (uint32 i = 0; i < resCount; i++) {
-		uint32 tag = subStream.readUint32();
-		uint32 size = subStream.readUint32();
-		uint32 offset = subStream.readUint32();
-		/*uint16 flags = */ subStream.readUint16();
-		/*uint16 unk1 = */ subStream.readUint16();
-		/*uint32 unk2 = */ subStream.readUint32();
-
-		debug(3, "Found RIFX resource index %d: '%s', %d @ 0x%08x", i, tag2str(tag), size, offset);
-
-		Resource res;
-		res.offset = offset;
-		res.size = size;
-		resources.push_back(res);
-
-		// APPL is a special case; it has an embedded "normal" archive
-		if (rifxType == MKTAG('A', 'P', 'P', 'L') && tag == MKTAG('F', 'i', 'l', 'e'))
-			return openStream(stream, offset);
-
-		// Looking for two types here
-		if (tag == MKTAG('K', 'E', 'Y', '*'))
-			keyRes = &resources[resources.size() - 1];
-		else if (tag == MKTAG('C', 'A', 'S', '*'))
-			casRes = &resources[resources.size() - 1];
+		for (Common::Array<uint16>::iterator iterator = dib.begin(); iterator != dib.end(); ++iterator) {
+			debugC(3, kDebugLoading, "Shared DIB %d", *iterator);
+			_sharedDIB->setVal(*iterator, shardcst->getResource(MKTAG('D','I','B',' '), *iterator));
+		}
 	}
 
-	// We need to have found the 'File' resource already
-	if (rifxType == MKTAG('A', 'P', 'P', 'L')) {
-		warning("No 'File' resource present in APPL archive");
-		return false;
-	}
+	Common::Array<uint16> stxt = shardcst->getResourceIDList(MKTAG('S','T','X','T'));
+	if (stxt.size() != 0) {
+		debugC(3, kDebugLoading, "Loading %d STXTs", stxt.size());
 
-	// A KEY* must be present
-	if (!keyRes) {
-		warning("No 'KEY*' resource present");
-		return false;
+		for (Common::Array<uint16>::iterator iterator = stxt.begin(); iterator != stxt.end(); ++iterator) {
+			debugC(3, kDebugLoading, "Shared STXT %d", *iterator);
+			_sharedSTXT->setVal(*iterator, shardcst->getResource(MKTAG('S','T','X','T'), *iterator));
+		}
 	}
 
-	// Parse the CAS*, if present
-	Common::Array<uint32> casEntries;
-	if (casRes) {
-		Common::SeekableSubReadStreamEndian casStream(stream, casRes->offset + 8, casRes->offset + 8 + casRes->size, _isBigEndian, DisposeAfterUse::NO);
-		casEntries.resize(casRes->size / 4);
-
-		for (uint32 i = 0; i < casEntries.size(); i++)
-			casEntries[i] = casStream.readUint32();
+	Common::Array<uint16> bmp = shardcst->getResourceIDList(MKTAG('B','I','T','D'));
+	if (bmp.size() != 0) {
+		debugC(3, kDebugLoading, "Loading %d BITDs", bmp.size());
+		for (Common::Array<uint16>::iterator iterator = bmp.begin(); iterator != bmp.end(); ++iterator) {
+			_sharedBMP->setVal(*iterator, shardcst->getResource(MKTAG('B','I','T','D'), *iterator));
+		}
 	}
 
-	// Parse the KEY*
-	Common::SeekableSubReadStreamEndian keyStream(stream, keyRes->offset + 8, keyRes->offset + 8 + keyRes->size, _isBigEndian, DisposeAfterUse::NO);
-	/*uint16 unk1 = */ keyStream.readUint16();
-	/*uint16 unk2 = */ keyStream.readUint16();
-	/*uint32 unk3 = */ keyStream.readUint32();
-	uint32 keyCount = keyStream.readUint32();
-
-	for (uint32 i = 0; i < keyCount; i++) {
-		uint32 index = keyStream.readUint32();
-		uint32 id = keyStream.readUint32();
-		uint32 resTag = keyStream.readUint32();
-
-		// Handle CAS*/CASt nonsense
-		if (resTag == MKTAG('C', 'A', 'S', 't')) {
-			for (uint32 j = 0; j < casEntries.size(); j++) {
-				if (casEntries[j] == index) {
-					id += j + 1;
-					break;
-				}
-			}
+	Common::Array<uint16> sound = shardcst->getResourceIDList(MKTAG('S','N','D',' '));
+	if (stxt.size() != 0) {
+		debugC(3, kDebugLoading, "Loading %d SNDs", sound.size());
+		for (Common::Array<uint16>::iterator iterator = sound.begin(); iterator != sound.end(); ++iterator) {
+			_sharedSound->setVal(*iterator, shardcst->getResource(MKTAG('S','N','D',' '), *iterator));
 		}
-
-		const Resource &res = resources[index];
-		debug(3, "Found RIFX resource: '%s' 0x%04x, %d @ 0x%08x", tag2str(resTag), id, res.size, res.offset);
-		_types[resTag][id] = res;
 	}
-
-	_stream = stream;
-	return true;
 }
 
 } // End of namespace Director
diff --git a/engines/director/resource.h b/engines/director/resource.h
deleted file mode 100644
index 1265908..0000000
--- a/engines/director/resource.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef DIRECTOR_RESOURCE_H
-#define DIRECTOR_RESOURCE_H
-
-#include "common/file.h"
-#include "common/substream.h"
-
-namespace Common {
-class MacResManager;
-}
-
-namespace Director {
-
-// Completely ripped off of Mohawk's Archive code
-
-class Archive {
-public:
-	Archive();
-	virtual ~Archive();
-
-	virtual bool openFile(const Common::String &fileName);
-	virtual bool openStream(Common::SeekableReadStream *stream, uint32 offset = 0) = 0;
-	virtual void close();
-
-	Common::String getFileName() const { return _fileName; }
-
-	bool isOpen() const { return _stream != 0; }
-
-	bool hasResource(uint32 tag, uint16 id) const;
-	bool hasResource(uint32 tag, const Common::String &resName) const;
-	virtual Common::SeekableSubReadStreamEndian *getResource(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;
-
-	Common::Array<uint32> getResourceTypeList() const;
-	Common::Array<uint16> getResourceIDList(uint32 type) const;
-	bool _isBigEndian;
-	static uint32 convertTagToUppercase(uint32 tag);
-
-protected:
-	Common::SeekableReadStream *_stream;
-	struct Resource {
-		uint32 offset;
-		uint32 size;
-		Common::String name;
-	};
-	typedef Common::HashMap<uint16, Resource> ResourceMap;
-	typedef Common::HashMap<uint32, ResourceMap> TypeMap;
-	TypeMap _types;
-
-	Common::String _fileName;
-};
-
-class MacArchive : public Archive {
-public:
-	MacArchive();
-	~MacArchive();
-
-	void close();
-	bool openFile(const Common::String &fileName);
-	bool openStream(Common::SeekableReadStream *stream, uint32 startOffset = 0);
-	Common::SeekableSubReadStreamEndian *getResource(uint32 tag, uint16 id);
-
-private:
-	Common::MacResManager *_resFork;
-};
-
-class RIFFArchive : public Archive {
-public:
-	RIFFArchive() : Archive() {}
-	~RIFFArchive() {}
-
-	bool openStream(Common::SeekableReadStream *stream, uint32 startOffset = 0);
-	Common::SeekableSubReadStreamEndian *getResource(uint32 tag, uint16 id);
-};
-
-class RIFXArchive : public Archive {
-public:
-	RIFXArchive() : Archive(){ _isBigEndian = true; }
-	~RIFXArchive() {}
-
-	bool openStream(Common::SeekableReadStream *stream, uint32 startOffset = 0);
-};
-
-} // End of namespace Director
-
-#endif
diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index 5c594c2..7b03ca1 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -32,7 +32,7 @@
 
 #include "director/score.h"
 #include "director/frame.h"
-#include "director/resource.h"
+#include "director/archive.h"
 #include "director/sound.h"
 #include "director/sprite.h"
 #include "director/lingo/lingo.h"


Commit: f6dda6b7fbbba28d8aa1d396f9812471ed0e059d
    https://github.com/scummvm/scummvm/commit/f6dda6b7fbbba28d8aa1d396f9812471ed0e059d
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2016-10-26T10:48:37+02:00

Commit Message:
DIRECTOR: Skip header in VWLB resource for D4+

For some reason the pointer in D4 movies points to the header
instead of data. Perhaps there is a flag which indicates that.
In the meanwhile, adding a hack to skip it so we could proceed
with development.

Changed paths:
    engines/director/score.cpp



diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index 7b03ca1..1345f4b 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -365,6 +365,11 @@ void Score::loadCastData(Common::SeekableSubReadStreamEndian &stream) {
 }
 
 void Score::loadLabels(Common::SeekableSubReadStreamEndian &stream) {
+	if (_vm->getVersion() >= 4) { // HACK: Skip the header. Why it is there?
+		stream.readUint32LE();
+		stream.readUint32LE();
+	}
+
 	_labels = new Common::SortedArray<Label *>(compareLabels);
 	uint16 count = stream.readUint16() + 1;
 	uint16 offset = count * 4 + 2;





More information about the Scummvm-git-logs mailing list