aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorMatthew Hoops2012-11-15 10:54:03 -0500
committerEugene Sandulenko2016-08-03 23:40:36 +0200
commit4a334980e1121d310948fbd497298d24d07011ac (patch)
tree4270156d8389385b4b9d90e230e59b0b7c516e1b /engines
parent387833ace4c176a5a47acae8e6e6a9764b08f235 (diff)
downloadscummvm-rg350-4a334980e1121d310948fbd497298d24d07011ac.tar.gz
scummvm-rg350-4a334980e1121d310948fbd497298d24d07011ac.tar.bz2
scummvm-rg350-4a334980e1121d310948fbd497298d24d07011ac.zip
DIRECTOR: Add some simple Windows version fallback detection
Diffstat (limited to 'engines')
-rw-r--r--engines/director/detection.cpp126
1 files changed, 126 insertions, 0 deletions
diff --git a/engines/director/detection.cpp b/engines/director/detection.cpp
index 3e3d6ca117..63d6b4e685 100644
--- a/engines/director/detection.cpp
+++ b/engines/director/detection.cpp
@@ -91,6 +91,7 @@ public:
return "Macromedia Director (C) Macromedia";
}
+ const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const;
virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
};
@@ -103,6 +104,131 @@ bool DirectorMetaEngine::createInstance(OSystem *syst, Engine **engine, const AD
return (gd != 0);
}
+static Director::DirectorGameDescription s_fallbackDesc = {
+ {
+ "director",
+ "",
+ AD_ENTRY1(0, 0),
+ Common::UNK_LANG,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO0()
+ },
+ Director::GID_GENERIC,
+ 0
+};
+
+static char s_fallbackFileNameBuffer[51];
+
+const ADGameDescription *DirectorMetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const {
+ // TODO: Handle Mac fallback
+
+ // reset fallback description
+ Director::DirectorGameDescription *desc = &s_fallbackDesc;
+ desc->desc.gameid = "director";
+ desc->desc.extra = "";
+ desc->desc.language = Common::UNK_LANG;
+ desc->desc.flags = ADGF_NO_FLAGS;
+ desc->desc.platform = Common::kPlatformWindows;
+ desc->desc.guioptions = GUIO0();
+ desc->desc.filesDescriptions[0].fileName = 0;
+ desc->version = 0;
+ desc->gameID = Director::GID_GENERIC;
+
+ for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
+ if (file->isDirectory())
+ continue;
+
+ Common::String fileName = file->getName();
+ fileName.toLowercase();
+ if (!fileName.hasSuffix(".exe"))
+ continue;
+
+ SearchMan.clear();
+ SearchMan.addDirectory(file->getParent().getName(), file->getParent());
+
+ Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(file->getName());
+
+ if (!stream)
+ continue;
+
+ stream->seek(-4, SEEK_END);
+
+ uint32 offset = stream->readUint32LE();
+
+ if (stream->eos() || offset == 0 || offset >= (uint32)(stream->size() - 4)) {
+ delete stream;
+ continue;
+ }
+
+ stream->seek(offset);
+
+ uint32 tag = stream->readUint32LE();
+
+ switch (tag) {
+ case MKTAG('3', '9', 'J', 'P'):
+ desc->version = 4;
+ break;
+ case MKTAG('P', 'J', '9', '5'):
+ desc->version = 5;
+ break;
+ case MKTAG('P', 'J', '0', '0'):
+ desc->version = 7;
+ break;
+ default:
+ // Prior to version 4, there was no tag here. So we'll use a bit of a
+ // heuristic to detect. The first field is the entry count, of which
+ // there should only be one.
+ if ((tag & 0xFFFF) != 1) {
+ delete stream;
+ continue;
+ }
+
+ stream->skip(3);
+
+ uint32 mmmSize = stream->readUint32LE();
+
+ if (stream->eos() || mmmSize == 0) {
+ delete stream;
+ continue;
+ }
+
+ byte fileNameSize = stream->readByte();
+
+ if (stream->eos()) {
+ delete stream;
+ continue;
+ }
+
+ stream->skip(fileNameSize);
+ byte directoryNameSize = stream->readByte();
+
+ if (stream->eos()) {
+ delete stream;
+ continue;
+ }
+
+ stream->skip(directoryNameSize);
+
+ if ((uint32)stream->pos() != offset) {
+ delete stream;
+ continue;
+ }
+
+ // Assume v3 at this point (for now at least)
+ desc->version = 3;
+ }
+
+ strncpy(s_fallbackFileNameBuffer, fileName.c_str(), 50);
+ s_fallbackFileNameBuffer[50] = '\0';
+ desc->desc.filesDescriptions[0].fileName = s_fallbackFileNameBuffer;
+
+ return (ADGameDescription *)desc;
+ }
+
+ return 0;
+}
+
#if PLUGIN_ENABLED_DYNAMIC(DIRECTOR)
REGISTER_PLUGIN_DYNAMIC(DIRECTOR, PLUGIN_TYPE_ENGINE, DirectorMetaEngine);
#else