diff options
Diffstat (limited to 'engines/sci')
-rw-r--r-- | engines/sci/detection.cpp | 99 | ||||
-rw-r--r-- | engines/sci/exereader.cpp | 92 | ||||
-rw-r--r-- | engines/sci/exereader.h | 13 | ||||
-rw-r--r-- | engines/sci/sci.cpp | 26 | ||||
-rw-r--r-- | engines/sci/sci.h | 6 |
5 files changed, 148 insertions, 88 deletions
diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp index 061532cb5a..75b601bcc1 100644 --- a/engines/sci/detection.cpp +++ b/engines/sci/detection.cpp @@ -30,6 +30,8 @@ #include "sci/exereader.h" #include "sci/include/versions.h" +namespace Sci { + // Titles of the games static const PlainGameDescriptor SciGameTitles[] = { {"sci", "Unknown SCI Game"}, @@ -90,26 +92,6 @@ static const PlainGameDescriptor SciGameTitles[] = { {0, 0} }; -const char* SciEngine::getGameID() const { - return _gameDescription->desc.gameid; -} - -Common::Platform SciEngine::getPlatform() const { - return _gameDescription->desc.platform; -} - -Common::Language SciEngine::getLanguage() const { - return _gameDescription->desc.language; -} - -uint32 SciEngine::getFlags() const { - return _gameDescription->desc.flags; -} - -int SciEngine::getVersion() const { - return _gameDescription->version; -} - /* // Missing - from FreeSCI { 0x980CEAD3, SCI_VERSION(0, 000, 629), "Demo Quest" }, @@ -154,7 +136,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {}, SCI_VERSION(1, 000, 510) }, - + // Castle of Dr. Brain - English DOS Demo {{"castlebrain", "Demo", { {"resource.map", 0, "467bb5e3224bb54640c3280032aebff5", 633}, @@ -332,7 +314,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { SCI_VERSION(0, 000, 000) // FIXME: add version here }, #endif - + // Freddy Pharkas - English DOS CD Demo {{"freddypharkas", "CD Demo", { {"resource.map", 0, "a62a7eae85dd1e6b07f39662b278437e", 1918}, @@ -1681,7 +1663,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {}, SCI_VERSION(2, 100, 2) }, - + // Torin's Passage - Spanish Windows {{"torin", "", { {"resmap.000", 0, "bb3b0b22ff08df54fbe2d06263409be6", 9799}, @@ -1690,7 +1672,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {}, SCI_VERSION(2, 100, 2) }, - + // Torin's Passage - French Windows {{"torin", "", { {"resmap.000", 0, "bb3b0b22ff08df54fbe2d06263409be6", 9799}, @@ -1699,7 +1681,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {}, SCI_VERSION(2, 100, 2) }, - + // Torin's Passage - German Windows {{"torin", "", { {"resmap.000", 0, "bb3b0b22ff08df54fbe2d06263409be6", 9799}, @@ -1708,7 +1690,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {}, SCI_VERSION(2, 100, 2) }, - + // Torin's Passage - Italian Windows CD (from glorifindel) {{"torin", "", { {"resmap.000", 0, "bb3b0b22ff08df54fbe2d06263409be6", 9799}, @@ -1776,20 +1758,22 @@ public: const ADGameDescription *SciMetaEngine::fallbackDetect(const Common::FSList &fslist) const { - int exeVersion = 0; bool foundResMap = false; bool foundRes000 = false; - bool foundExe = false; + Common::Platform exePlatform = Common::kPlatformUnknown; + Common::String exeVersionString; // First grab all filenames for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) { - if (file->isDirectory()) continue; + if (file->isDirectory()) + continue; + Common::String filename = file->getName(); filename.toLowercase(); - + if (filename.contains("resource.map") || filename.contains("resmap.000")) foundResMap = true; - + if (filename.contains("resource.000") || filename.contains("resource.001") || filename.contains("ressci.000") || filename.contains("ressci.001")) foundRes000 = true; @@ -1798,47 +1782,56 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const Common::FSList &fsl if (filename.contains("scidhuv") || filename.contains("sciv") || filename.contains("sierra") || filename.contains("sciw") || filename.contains("prog")) { - - if (foundExe) // We already found a valid exe, no need to check this one. + + // We already found a valid exe, no need to check this one. + if (exeVersionString.size()) continue; - + // Is it really an executable file? Common::SeekableReadStream *fileStream = file->createReadStream(); - bool isExe = isGameExe(fileStream); + exePlatform = getGameExePlatform(fileStream); + + // It's a valid exe, read the interpreter version string + if (exePlatform != Common::kPlatformUnknown) + exeVersionString = readSciVersionFromExe(fileStream); - if (isExe && readSciVersionFromExe(fileStream, &exeVersion)) // All ok, we got the version from the executable successfully - foundExe = true; - delete fileStream; } - } - - if (!foundExe) + + if (exePlatform == Common::kPlatformUnknown) return 0; // If these files aren't found, it can't be SCI if (!foundResMap && !foundRes000) return 0; - + // Set some defaults g_fallbackDesc.desc.gameid = "sci"; g_fallbackDesc.desc.extra = ""; g_fallbackDesc.desc.language = Common::UNK_LANG; - g_fallbackDesc.desc.platform = Common::kPlatformPC; + g_fallbackDesc.desc.platform = exePlatform; g_fallbackDesc.desc.flags = ADGF_NO_FLAGS; - g_fallbackDesc.version = exeVersion; + g_fallbackDesc.version = SCI_VERSION(0, 0, 0); printf("If this is *NOT* a fan-modified version (in particular, not a fan-made\n"); printf("translation), please, report the data above, including the following\n"); printf("version number, from the game's executable:\n"); - printf("Interpreter version: %d.%03d.%03d (by executable scan)\n", - SCI_VERSION_MAJOR(exeVersion), - SCI_VERSION_MINOR(exeVersion), - SCI_VERSION_PATCHLEVEL(exeVersion)); - - return (const ADGameDescription *)&g_fallbackDesc; + // Try to parse the executable version + if (getSciVersionFromString(exeVersionString, &g_fallbackDesc.version)) { + printf("Interpreter version: %d.%03d.%03d (got %s by executable scan)\n", + SCI_VERSION_MAJOR(g_fallbackDesc.version), + SCI_VERSION_MINOR(g_fallbackDesc.version), + SCI_VERSION_PATCHLEVEL(g_fallbackDesc.version), + exeVersionString.c_str()); + + return (const ADGameDescription *)&g_fallbackDesc; + } else { + printf("Couldn't parse the interpreter version: %s (by executable scan)\n", + exeVersionString.c_str()); + return NULL; + } } bool SciMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const { @@ -1849,8 +1842,10 @@ bool SciMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameD return true; } +} // End of namespace Sci + #if PLUGIN_ENABLED_DYNAMIC(SCI) - REGISTER_PLUGIN_DYNAMIC(SCI, PLUGIN_TYPE_ENGINE, SciMetaEngine); + REGISTER_PLUGIN_DYNAMIC(SCI, PLUGIN_TYPE_ENGINE, Sci::SciMetaEngine); #else - REGISTER_PLUGIN_STATIC(SCI, PLUGIN_TYPE_ENGINE, SciMetaEngine); + REGISTER_PLUGIN_STATIC(SCI, PLUGIN_TYPE_ENGINE, Sci::SciMetaEngine); #endif diff --git a/engines/sci/exereader.cpp b/engines/sci/exereader.cpp index 21e55760e1..edb2bc0589 100644 --- a/engines/sci/exereader.cpp +++ b/engines/sci/exereader.cpp @@ -24,21 +24,20 @@ */ #include "common/endian.h" -#include "common/util.h" #include "sci/exereader.h" #include "sci/include/versions.h" -//namespace Sci { +namespace Sci { int _bitCount; uint16 _bits; -bool isGameExe(Common::SeekableReadStream *exeStream) { +Common::Platform getGameExePlatform(Common::SeekableReadStream *exeStream) { byte magic[4]; // Make sure that the executable is at least 4KB big if (exeStream->size() < 4096) - return false; + return Common::kPlatformUnknown; // Read exe header exeStream->read(magic, 4); @@ -48,18 +47,18 @@ bool isGameExe(Common::SeekableReadStream *exeStream) { // Information obtained from http://magicdb.org/magic.db // Check if it's a DOS executable if (magic[0] == 'M' && magic[1] == 'Z') { - return true; + return Common::kPlatformPC; } // Check if it's an Amiga executable if ((magic[2] == 0x03 && magic[3] == 0xF3) || (magic[0] == 0x7F && magic[1] == 'E' && magic[2] == 'L' && magic[3] == 'F')) { - return true; + return Common::kPlatformAmiga; } // Check if it's an Atari executable if ((magic[0] == 0x60 && magic[1] == 0x1A)) - return true; + return Common::kPlatformAtariST; // Check if it's a Mac exe @@ -67,7 +66,7 @@ bool isGameExe(Common::SeekableReadStream *exeStream) { int32 offset = (int32)READ_BE_UINT32(magic); offset += 28; if (exeStream->size() <= offset) - return false; + return Common::kPlatformUnknown; // Skip number of types in map exeStream->skip(2); @@ -77,23 +76,23 @@ bool isGameExe(Common::SeekableReadStream *exeStream) { while (!exeStream->eos()) { exeStream->skip(4); if (exeStream->eos()) - return false; + return Common::kPlatformUnknown; exeStream->read(magic, 4); if (exeStream->eos()) - return false; + return Common::kPlatformUnknown; if (!memcmp(magic, "CODE", 4)) { - return true; + return Common::kPlatformMacintosh; } // Skip to the next list entry exeStream->skip(4); if (exeStream->eos()) - return false; + return Common::kPlatformUnknown; } // If we've reached here, the file type is unknown - return false; + return Common::kPlatformUnknown; } bool isLZEXECompressed(Common::SeekableReadStream *exeStream) { @@ -172,10 +171,10 @@ uint getBit(Common::SeekableReadStream *input) { return bit; } -bool readSciVersionFromExe(Common::SeekableReadStream *exeStream, int *version) { +Common::String readSciVersionFromExe(Common::SeekableReadStream *exeStream) { int len = exeStream->size(); unsigned char *buffer = NULL; - char result_string[10]; /* string-encoded result, copied from buf */ + // Read the executable bool isLZEXE = isLZEXECompressed(exeStream); @@ -186,6 +185,7 @@ bool readSciVersionFromExe(Common::SeekableReadStream *exeStream, int *version) exeStream->read(buffer, exeStream->size()); } else { buffer = new unsigned char[exeStream->size() * 3]; + _bitCount = 0; // Skip LZEXE header exeStream->seek(32, SEEK_SET); @@ -198,7 +198,7 @@ bool readSciVersionFromExe(Common::SeekableReadStream *exeStream, int *version) if (exeStream->ioFailed()) { warning("Error reading from input file"); delete[] buffer; - return false; + return NULL; } if (getBit(exeStream)) { @@ -257,9 +257,14 @@ bool readSciVersionFromExe(Common::SeekableReadStream *exeStream, int *version) int accept; unsigned char *buf = buffer; + // String-encoded result, copied from buffer + char currentString[10]; + Common::String resultString; + for (int i = 0; i < len; i++) { unsigned char ch = *buf++; - accept = 0; // By default, we don't like this character + // By default, we don't like this character + accept = 0; if (isalnum(ch)) { accept = (state != 1 @@ -269,24 +274,63 @@ bool readSciVersionFromExe(Common::SeekableReadStream *exeStream, int *version) accept = (state == 1 || state == 5); } else if (state == 9) { - result_string[9] = 0; /* terminate string */ + // Terminate string + currentString[9] = 0; - if (!version_parse(result_string, version)) { + // Return the current string if it's parseable + int version; + if (getSciVersionFromString(currentString, &version)) { delete[] buffer; - return true; // success + return currentString; } - // Continue searching + // Save the found string and continue searching + resultString = currentString; } if (accept) - result_string[state++] = ch; + currentString[state++] = ch; else state = 0; } delete[] buffer; - return false; // failure + return resultString; +} + +bool getSciVersionFromString(Common::String versionString, int *version) { + // Map non-numeric versions to their numeric counterparts + Common::String mappedVersion = versionString; + if (versionString.hasPrefix("S.old.")) { + // SCI 01 + mappedVersion = "0.001."; + mappedVersion += versionString.c_str() + 6; + } else if (versionString.hasPrefix("1.ECO.") + || versionString.hasPrefix("1.SQ1.") + || versionString.hasPrefix("1.SQ4.") + || versionString.hasPrefix("1.LS5.") + || versionString.hasPrefix("1.pq3.") + || versionString.hasPrefix("FAIRY.")) { + // SCI 1.0 + mappedVersion = "1.000."; + mappedVersion += versionString.c_str() + 6; + } else if (versionString.hasPrefix("T.A00.")) { + mappedVersion = "1.000.510"; + } else if (versionString.hasPrefix("L.rry.") + || versionString.hasPrefix("l.cfs.")) { + // SCI 1.1 + mappedVersion = "1.001."; + mappedVersion += versionString.c_str() + 6; + } else if (versionString == "x.yyy.yyy") { + // How to map it? + } + + // Parse to a version number + if (!version_parse(mappedVersion.c_str(), version)) { + return true; + } else { + return false; + } } -//} // End of namespace Sci +} // End of namespace Sci diff --git a/engines/sci/exereader.h b/engines/sci/exereader.h index 32f070a59a..1100dc7244 100644 --- a/engines/sci/exereader.h +++ b/engines/sci/exereader.h @@ -26,14 +26,15 @@ #ifndef EXEREADER_H #define EXEREADER_H -#include "common/file.h" -#include "common/str.h" +#include "common/stream.h" +#include "common/util.h" -//namespace Sci { +namespace Sci { -bool isGameExe(Common::SeekableReadStream *exeStream); -bool readSciVersionFromExe(Common::SeekableReadStream *exeStream, int *version); +Common::Platform getGameExePlatform(Common::SeekableReadStream *exeStream); +Common::String readSciVersionFromExe(Common::SeekableReadStream *exeStream); +bool getSciVersionFromString(Common::String versionString, int *version); -//} // End of namespace Sci +} // End of namespace Sci #endif // SCI_H diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index dda8d54bc4..b4336e9b4f 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -31,10 +31,10 @@ #include "sci/sci.h" #include "sci/include/engine.h" -//namespace Sci { - extern gfx_driver_t gfx_driver_scummvm; +namespace Sci { + int c_quit(state_t *s) { script_abort_flag = 1; /* Terminate VM */ @@ -309,4 +309,24 @@ Common::Error SciEngine::go() { return Common::kNoError; } -//} // End of namespace Sci +const char* SciEngine::getGameID() const { + return _gameDescription->desc.gameid; +} + +int SciEngine::getVersion() const { + return _gameDescription->version; +} + +Common::Language SciEngine::getLanguage() const { + return _gameDescription->desc.language; +} + +Common::Platform SciEngine::getPlatform() const { + return _gameDescription->desc.platform; +} + +uint32 SciEngine::getFlags() const { + return _gameDescription->desc.flags; +} + +} // End of namespace Sci diff --git a/engines/sci/sci.h b/engines/sci/sci.h index 575fa5eadd..b5951ca398 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -29,7 +29,7 @@ #include "engines/engine.h" #include "gui/debugger.h" -//namespace Sci { +namespace Sci { // our engine debug levels enum { @@ -62,7 +62,6 @@ public: virtual Common::Error init(void); virtual Common::Error go(void); - const SciGameDescription *_gameDescription; const char* getGameID() const; int getVersion() const; Common::Language getLanguage() const; @@ -70,6 +69,7 @@ public: uint32 getFlags() const; private: + const SciGameDescription *_gameDescription; //Console *_console; }; @@ -82,6 +82,6 @@ class Console : public GUI::Debugger { }; */ -//} // End of namespace Sci +} // End of namespace Sci #endif // SCI_H |