aboutsummaryrefslogtreecommitdiff
path: root/engines/sci
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sci')
-rw-r--r--engines/sci/detection.cpp99
-rw-r--r--engines/sci/exereader.cpp92
-rw-r--r--engines/sci/exereader.h13
-rw-r--r--engines/sci/sci.cpp26
-rw-r--r--engines/sci/sci.h6
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