diff options
-rw-r--r-- | engines/sci/detection.cpp | 40 | ||||
-rw-r--r-- | engines/sci/exereader.cpp | 172 | ||||
-rw-r--r-- | engines/sci/exereader.h | 1 |
3 files changed, 26 insertions, 187 deletions
diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp index 177fc2fbd1..55ea8ee00a 100644 --- a/engines/sci/detection.cpp +++ b/engines/sci/detection.cpp @@ -260,7 +260,6 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const Common::FSList &fsl bool foundResMap = false; bool foundRes000 = 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) { @@ -293,22 +292,15 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const Common::FSList &fsl // Check if it's a known executable name // Note: "sier" matches "sier.exe", "sierra.exe", "sierw.exe" and "sierw5.exe" + // TODO: Try to remove this code, and base platform detection on game resources + // instead of the executable itself if (filename.contains("scidhuv") || filename.contains("sciduv") || filename.contains("sciv") || filename.contains("sciw") || filename.contains("prog") || filename.contains("sier")) { - // We already found a valid exe, no need to check this one. - if (!exeVersionString.empty()) - continue; - // Is it really an executable file? Common::SeekableReadStream *fileStream = file->createReadStream(); exePlatform = getGameExePlatform(fileStream); - - // It's a valid exe, read the interpreter version string - if (exePlatform != Common::kPlatformUnknown) - exeVersionString = readSciVersionFromExe(fileStream, exePlatform); - delete fileStream; } } @@ -319,19 +311,40 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const Common::FSList &fsl return 0; } + ResourceManager *resMgr = new ResourceManager(fslist); + SciVersion version = resMgr->sciVersion(); + SegManager *segManager = new SegManager(resMgr, version); + // Set some defaults s_fallbackDesc.desc.extra = ""; s_fallbackDesc.desc.language = Common::UNK_LANG; + if (exePlatform == Common::kPlatformUnknown) { + // Try to determine the platform from game resources + ViewType gameViews = resMgr->getViewType(); + if (gameViews == kViewEga || gameViews == kViewVga || + gameViews == kViewVga11) { + // Must be PC or Mac, set to PC for now + // TODO: Is there a reliable way to determine the game + // platform from the resources? So far, I've noticed + // that Mac versions have a different signature for + // kGetEvent and kNewWindow. I'm unsure about Atari ST + // versions. Could we base detection on this? + exePlatform = Common::kPlatformPC; + } else if (gameViews == kViewAmiga) { + exePlatform = Common::kPlatformAmiga; + } + // TODO: detection for Mac and Atari ST + } + s_fallbackDesc.desc.platform = exePlatform; s_fallbackDesc.desc.flags = ADGF_NO_FLAGS; // Determine the game id - ResourceManager *resMgr = new ResourceManager(fslist); - SciVersion version = resMgr->sciVersion(); - SegManager *segManager = new SegManager(resMgr, version); if (!script_instantiate(resMgr, segManager, version, 0)) { warning("fallbackDetect(): Could not instantiate script 0"); SearchMan.remove("SCI_detection"); + delete segManager; + delete resMgr; return 0; } reg_t game_obj = script_lookup_export(segManager, 0, 0); @@ -345,7 +358,6 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const Common::FSList &fsl 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("Version: %s\n\n", exeVersionString.empty() ? "not found" : exeVersionString.c_str()); SearchMan.remove("SCI_detection"); diff --git a/engines/sci/exereader.cpp b/engines/sci/exereader.cpp index ce6bf184fb..fbeda66b45 100644 --- a/engines/sci/exereader.cpp +++ b/engines/sci/exereader.cpp @@ -96,62 +96,6 @@ Common::Platform getGameExePlatform(Common::SeekableReadStream *exeStream) { return Common::kPlatformUnknown; } -bool isLZEXECompressed(Common::SeekableReadStream *exeStream) { - uint32 filepos = 0; - - exeStream->seek(0, SEEK_SET); - - // First 2 bytes should be "MZ" (0x5A4D) - if (exeStream->readUint16LE() != 0x5A4D) // at pos 0, +2 - return false; - - exeStream->skip(6); - - // Header size should be 2 - filepos = exeStream->readUint16LE(); - if (filepos != 2) // at pos 8, +2 - return false; - - exeStream->skip(12); - - // Calculate code segment offset in exe file - filepos += exeStream->readUint16LE(); // at pos 22, +2 - filepos <<= 4; - - // First relocation item offset should be 0x1c - if (exeStream->readUint16LE() != 0x1c) // at pos 24, +2 - return false; - - // Number of overlays should be 0 - if (exeStream->readUint16LE() != 0) // at pos 26, +2 - return false; - - // Look for LZEXE signature - byte magic[4]; - exeStream->read(magic, 4); - - if (memcmp(magic, "LZ09", 4) && memcmp(magic, "LZ91", 4)) - return false; - - // Seek to offset 8 of info table at start of code segment - exeStream->seek(filepos + 8, SEEK_SET); - if (exeStream->err()) - return false; - - // Read size of compressed data in paragraphs - uint16 size = exeStream->readUint16LE(); - - // Move file pointer to start of compressed data - filepos -= size << 4; - exeStream->seek(filepos, SEEK_SET); - if (exeStream->err()) - return false; - - // All conditions met, this is an LZEXE packed file - // We are currently at the start of the compressed file data - return true; -} - uint getBit(Common::SeekableReadStream *input) { uint bit = _bits & 1; _bitCount--; @@ -172,120 +116,4 @@ uint getBit(Common::SeekableReadStream *input) { return bit; } -Common::String readSciVersionFromExe(Common::SeekableReadStream *exeStream, Common::Platform platform) { - int len = exeStream->size(); - unsigned char *buffer = NULL; - - // Read the executable - bool isLZEXE = isLZEXECompressed(exeStream); - - if (!isLZEXE) { - buffer = new unsigned char[exeStream->size()]; - - exeStream->seek(0, SEEK_SET); - exeStream->read(buffer, exeStream->size()); - } else { - buffer = new unsigned char[exeStream->size() * 3]; - _bitCount = 0; - - // Skip LZEXE header - exeStream->seek(32, SEEK_SET); - - int pos = 0; - int repeat; - short offset; - - while (1) { - if (exeStream->ioFailed()) { - warning("Error reading from input file"); - delete[] buffer; - return NULL; - } - - if (getBit(exeStream)) { - buffer[pos++] = exeStream->readByte(); - } else { - if (getBit(exeStream)) { - byte tmp[2]; - exeStream->read(tmp, 2); - repeat = (tmp[1] & 0x07); - offset = ((tmp[1] & ~0x07) << 5) | tmp[0] | 0xE000; - - if (repeat == 0) { - repeat = exeStream->readByte(); - - if (repeat == 0) { - len = pos; - break; - } - else if (repeat == 1) - continue; - else - repeat++; - } else - repeat += 2; - } else { - repeat = getBit(exeStream) << 1; - repeat += getBit(exeStream) + 2; - offset = exeStream->readByte() | 0xFF00; - } - - while (repeat > 0) { - buffer[pos] = buffer[pos + offset]; - pos++; - repeat--; - } - } - } - } - - // Find SCI version number - - int state = 0; - /* 'state' encodes how far we have matched the version pattern - ** "n.nnn.nnn" - ** - ** n.nnn.nnn - ** 0123456789 - ** - ** Since we cannot be certain that the pattern does not begin with an - ** alphanumeric character, some states are ambiguous. - ** The pattern is expected to be terminated with a non-alphanumeric - ** character. - */ - - - int accept; - unsigned char *buf = buffer; - - // String-encoded result, copied from buffer - char currentString[10]; - - for (int i = 0; i < len; i++) { - unsigned char ch = *buf++; - // By default, we don't like this character - accept = 0; - - if (isalnum(ch)) { - accept = (state != 1 && state != 5 && state != 9); - } else if (ch == '.') { - accept = (state == 1 || state == 5); - } else if (state == 9) { - // Terminate string - currentString[9] = 0; - - // Return the current string - return currentString; - } - - if (accept) - currentString[state++] = ch; - else - state = 0; - } - - delete[] buffer; - return "unknown"; -} - } // End of namespace Sci diff --git a/engines/sci/exereader.h b/engines/sci/exereader.h index e30d3d90c4..e114c0a3a4 100644 --- a/engines/sci/exereader.h +++ b/engines/sci/exereader.h @@ -32,7 +32,6 @@ namespace Sci { Common::Platform getGameExePlatform(Common::SeekableReadStream *exeStream); -Common::String readSciVersionFromExe(Common::SeekableReadStream *exeStream, Common::Platform platform); } // End of namespace Sci |