diff options
Diffstat (limited to 'engines/sci/detection.cpp')
-rw-r--r-- | engines/sci/detection.cpp | 207 |
1 files changed, 47 insertions, 160 deletions
diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp index aba2b0b74e..2a83c8e32a 100644 --- a/engines/sci/detection.cpp +++ b/engines/sci/detection.cpp @@ -120,154 +120,6 @@ static const PlainGameDescriptor SciGameTitles[] = { {0, 0} }; -struct OldNewIdTableEntry { - const char *oldId; - const char *newId; - SciVersion version; -}; - -static const OldNewIdTableEntry s_oldNewTable[] = { - { "arthur", "camelot", SCI_VERSION_NONE }, - { "brain", "castlebrain", SCI_VERSION_1_MIDDLE }, // Amiga - { "brain", "castlebrain", SCI_VERSION_1_LATE }, - { "demo", "christmas1988", SCI_VERSION_NONE }, - { "card", "christmas1990", SCI_VERSION_1_EARLY, }, - { "card", "christmas1992", SCI_VERSION_1_1 }, - { "RH Budget", "cnick-longbow", SCI_VERSION_NONE }, - // iceman is the same - { "icedemo", "iceman", SCI_VERSION_NONE }, - // longbow is the same - { "eco", "ecoquest", SCI_VERSION_NONE }, - { "eco2", "ecoquest2", SCI_VERSION_NONE }, // EcoQuest 2 demo - { "rain", "ecoquest2", SCI_VERSION_NONE }, // EcoQuest 2 full - { "tales", "fairytales", SCI_VERSION_NONE }, - { "fp", "freddypharkas", SCI_VERSION_NONE }, - { "emc", "funseeker", SCI_VERSION_NONE }, - { "gk", "gk1", SCI_VERSION_NONE }, - // gk2 is the same - { "hoyledemo", "hoyle1", SCI_VERSION_NONE }, - { "cardgames", "hoyle1", SCI_VERSION_NONE }, - { "solitare", "hoyle2", SCI_VERSION_NONE }, - // hoyle3 is the same - // hoyle4 is the same - { "brain", "islandbrain", SCI_VERSION_1_1 }, - { "demo000", "kq1sci", SCI_VERSION_NONE }, - { "kq1", "kq1sci", SCI_VERSION_NONE }, - { "kq4", "kq4sci", SCI_VERSION_NONE }, - // kq5 is the same - // kq6 is the same - // kq7 is the same - { "mm1", "laurabow", SCI_VERSION_NONE }, - { "cb1", "laurabow", SCI_VERSION_NONE }, - { "lb2", "laurabow2", SCI_VERSION_NONE }, - { "rh", "longbow", SCI_VERSION_NONE }, - { "ll1", "lsl1sci", SCI_VERSION_NONE }, - { "lsl1", "lsl1sci", SCI_VERSION_NONE }, - // lsl2 is the same - { "lsl3", "lsl3", SCI_VERSION_NONE }, - { "ll5", "lsl5", SCI_VERSION_NONE }, - // lsl5 is the same - // lsl6 is the same - { "mg", "mothergoose", SCI_VERSION_NONE }, - { "twisty", "pepper", SCI_VERSION_NONE }, - { "scary", "phantasmagoria", SCI_VERSION_NONE }, - // TODO: distinguish the full version of Phantasmagoria from the demo - { "pq1", "pq1sci", SCI_VERSION_NONE }, - { "pq", "pq2", SCI_VERSION_NONE }, - // pq3 is the same - // pq4 is the same - { "hq", "qfg1", SCI_VERSION_NONE }, // QFG1 SCI0/EGA - { "glory", "qfg1", SCI_VERSION_0_LATE }, // QFG1 SCI0/EGA - { "trial", "qfg2", SCI_VERSION_NONE }, - { "hq2demo", "qfg2", SCI_VERSION_NONE }, - // rama is the same - // TODO: distinguish the full version of rama from the demo - { "thegame", "slater", SCI_VERSION_NONE }, - { "sq1demo", "sq1sci", SCI_VERSION_NONE }, - { "sq1", "sq1sci", SCI_VERSION_NONE }, - // sq3 is the same - // sq4 is the same - // sq5 is the same - // sq6 is the same - // TODO: distinguish the full version of SQ6 from the demo - // torin is the same - - - // TODO: SCI3 IDs - - { "", "", SCI_VERSION_NONE } -}; - -Common::String convertSierraGameId(Common::String sierraId, uint32 *gameFlags, ResourceManager *resMan) { - // Convert the id to lower case, so that we match all upper/lower case variants. - sierraId.toLowercase(); - - // If the game has less than the expected scripts, it's a demo - uint32 demoThreshold = 100; - // ...but there are some exceptions - if (sierraId == "brain" || sierraId == "lsl1" || - sierraId == "mg" || sierraId == "pq" || - sierraId == "jones" || - sierraId == "cardgames" || sierraId == "solitare" || - sierraId == "hoyle3" || sierraId == "hoyle4") - demoThreshold = 40; - if (sierraId == "fp" || sierraId == "gk" || sierraId == "pq4") - demoThreshold = 150; - - Common::List<ResourceId> *resources = resMan->listResources(kResourceTypeScript, -1); - if (resources->size() < demoThreshold) { - *gameFlags |= ADGF_DEMO; - - // Crazy Nick's Picks - if (sierraId == "lsl1" && resources->size() == 34) - return "cnick-lsl"; - if (sierraId == "sq4" && resources->size() == 34) - return "cnick-sq"; - - // TODO: cnick-kq, cnick-laurabow and cnick-longbow (their resources can't be read) - - // Handle Astrochicken 1 (SQ3) and 2 (SQ4) - if (sierraId == "sq3" && resources->size() == 20) - return "astrochicken"; - if (sierraId == "sq4") - return "msastrochicken"; - } - - if (sierraId == "torin" && resources->size() == 226) // Torin's Passage demo - *gameFlags |= ADGF_DEMO; - - for (const OldNewIdTableEntry *cur = s_oldNewTable; cur->oldId[0]; ++cur) { - if (sierraId == cur->oldId) { - // Distinguish same IDs from the SCI version - if (cur->version != SCI_VERSION_NONE && cur->version != getSciVersion()) - continue; - - return cur->newId; - } - } - - if (sierraId == "glory") { - // This could either be qfg1 VGA, qfg3 or qfg4 demo (all SCI1.1), - // or qfg4 full (SCI2) - // qfg1 VGA doesn't have view 1 - if (!resMan->testResource(ResourceId(kResourceTypeView, 1))) - return "qfg1"; - - // qfg4 full is SCI2 - if (getSciVersion() == SCI_VERSION_2) - return "qfg4"; - - // qfg4 demo has less than 50 scripts - if (resources->size() < 50) - return "qfg4"; - - // Otherwise it's qfg3 - return "qfg3"; - } - - return sierraId; -} - #include "sci/detection_tables.h" /** @@ -353,6 +205,50 @@ Common::Language charToScummVMLanguage(const char c) { } } +#define READ_UINT16(buf) (!resMan->isSci11Mac() ? READ_LE_UINT16(buf) : READ_BE_UINT16(buf)) + +// Finds the internal ID of the current game from script 0 +Common::String getSierraGameId(ResourceManager *resMan) { + Resource *script = resMan->findResource(ResourceId(kResourceTypeScript, 0), false); + Script *script000 = new Script(); + script000->init(0, resMan); + script000->mcpyInOut(0, script->data, script->size); + uint16 curOffset = (getSciVersion() == SCI_VERSION_0_EARLY) ? 2 : 0; + uint16 objLength = 0; + int objType = 0; + int16 exportsOffset = 0; + Common::String sierraId; + + // Now find the export table of the script + do { + objType = READ_UINT16(script000->_buf + curOffset); + if (!objType) + break; + + objLength = READ_UINT16(script000->_buf + curOffset + 2); + curOffset += 4; // skip header + + if (objType == SCI_OBJ_EXPORTS) { + exportsOffset = READ_UINT16(script000->_buf + curOffset + 2); + break; + } + curOffset += objLength - 4; + } while (objType != 0 && curOffset < script->size - 2); + + // The game object is the first export. Script 0 is always at segment 1 + reg_t gameObj = make_reg(1, exportsOffset); + + // TODO: stop using the segment manager and read the object name here + SegManager *segMan = new SegManager(resMan); + script_instantiate(resMan, segMan, 0); + sierraId = segMan->getObjectName(gameObj); + delete segMan; + + delete script000; + + return sierraId; +} + const ADGameDescription *SciMetaEngine::fallbackDetect(const Common::FSList &fslist) const { bool foundResMap = false; bool foundRes000 = false; @@ -464,16 +360,7 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const Common::FSList &fsl s_fallbackDesc.platform = Common::kPlatformAmiga; // Determine the game id - Common::String sierraGameId = resMan->findSierraGameId(); - - // If we don't have a game id, the game is not SCI - if (sierraGameId.empty()) { - SearchMan.remove("SCI_detection"); - delete resMan; - return 0; - } - - Common::String gameId = convertSierraGameId(sierraGameId, &s_fallbackDesc.flags, resMan); + Common::String gameId = convertSierraGameId(getSierraGameId(resMan).c_str(), &s_fallbackDesc.flags, resMan); strncpy(s_fallbackGameIdBuf, gameId.c_str(), sizeof(s_fallbackGameIdBuf) - 1); s_fallbackGameIdBuf[sizeof(s_fallbackGameIdBuf) - 1] = 0; // Make sure string is NULL terminated s_fallbackDesc.gameid = s_fallbackGameIdBuf; @@ -548,8 +435,8 @@ bool SciMetaEngine::hasFeature(MetaEngineFeature f) const { bool SciEngine::hasFeature(EngineFeature f) const { return //(f == kSupportsRTL) || - (f == kSupportsLoadingDuringRuntime) || - (f == kSupportsSavingDuringRuntime); + (f == kSupportsLoadingDuringRuntime); + //(f == kSupportsSavingDuringRuntime); } SaveStateList SciMetaEngine::listSaves(const char *target) const { |