diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 540b7c84d84..f73932bcb1f 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -421,10 +421,9 @@ const char *selector_name(EngineState *s, int selector) { bool Console::cmdGetVersion(int argc, const char **argv) { const char *viewTypeDesc[] = { "Unknown", "EGA", "VGA", "VGA SCI1.1", "Amiga" }; - EngineState *s = _engine->_gamestate; bool hasVocab997 = g_sci->getResMan()->testResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SELECTORS)) ? true : false; - DebugPrintf("Game ID: %s\n", s->_gameId.c_str()); + DebugPrintf("Game ID: %s\n", _engine->getGameID()); DebugPrintf("Emulated interpreter version: %s\n", getSciVersionDesc(getSciVersion())); DebugPrintf("\n"); DebugPrintf("Detected features:\n"); diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp index beea025aeac..fc81a4671db 100644 --- a/engines/sci/detection.cpp +++ b/engines/sci/detection.cpp @@ -120,6 +120,140 @@ 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 + { "fp", "freddypharkas", SCI_VERSION_NONE }, + { "emc", "funseeker", SCI_VERSION_NONE }, + { "gk", "gk1", SCI_VERSION_NONE }, + { "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 }, + { "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 }, + { "pq1", "pq1sci", SCI_VERSION_NONE }, + { "pq", "pq2", SCI_VERSION_NONE }, + // pq3 is the same + // pq4 is the same + { "tales", "fairytales", SCI_VERSION_NONE }, + { "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 }, + { "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 + // torin is the same + + // TODO: SCI2.1, 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 *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"; + } + + 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" /** @@ -205,42 +339,6 @@ Common::Language charToScummVMLanguage(const char c) { } } -#define READ_UINT16(ptr) (!resMan->isSci11Mac() ? READ_LE_UINT16(ptr) : READ_BE_UINT16(ptr)) - -// Finds the internal ID of the current game from script 0 -Common::String getSierraGameId(ResourceManager *resMan) { - Resource *script = resMan->findResource(ResourceId(kResourceTypeScript, 0), false); - // In SCI0-SCI1, the heap is embedded in the script. In SCI1.1+, it's separated - Resource *heap = 0; - byte *seeker = 0; - - // Seek to the name selector of the first export - if (getSciVersion() < SCI_VERSION_1_1) { - const int nameSelector = 3; - int extraSci0EarlyBytes = (getSciVersion() == SCI_VERSION_0_EARLY) ? 2 : 0; - byte *exportPtr = script->data + extraSci0EarlyBytes + 4 + 2; - seeker = script->data + READ_UINT16(script->data + READ_UINT16(exportPtr) + nameSelector * 2); - } else { - const int nameSelector = 5 + 3; - heap = resMan->findResource(ResourceId(kResourceTypeHeap, 0), false); - byte *exportPtr = script->data + 4 + 2 + 2; - seeker = heap->data + READ_UINT16(heap->data + READ_UINT16(exportPtr) + nameSelector * 2); - } - - char sierraId[20]; - int i = 0; - byte curChar = 0; - - do { - curChar = *(seeker + i); - sierraId[i++] = curChar; - } while (curChar != 0); - - return sierraId; -} - -#undef READ_UINT16 - const ADGameDescription *SciMetaEngine::fallbackDetect(const Common::FSList &fslist) const { bool foundResMap = false; bool foundRes000 = false; @@ -352,7 +450,7 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const Common::FSList &fsl s_fallbackDesc.platform = Common::kPlatformAmiga; // Determine the game id - Common::String gameId = convertSierraGameId(getSierraGameId(resMan).c_str(), &s_fallbackDesc.flags, resMan); + Common::String gameId = convertSierraGameId(resMan->findSierraGameId(), &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; diff --git a/engines/sci/engine/game.cpp b/engines/sci/engine/game.cpp index 4ac2a22531f..d7fdd9be6e0 100644 --- a/engines/sci/engine/game.cpp +++ b/engines/sci/engine/game.cpp @@ -41,141 +41,6 @@ namespace Sci { -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 - { "fp", "freddypharkas", SCI_VERSION_NONE }, - { "emc", "funseeker", SCI_VERSION_NONE }, - { "gk", "gk1", SCI_VERSION_NONE }, - { "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 }, - { "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 }, - { "pq1", "pq1sci", SCI_VERSION_NONE }, - { "pq", "pq2", SCI_VERSION_NONE }, - // pq3 is the same - // pq4 is the same - { "tales", "fairytales", SCI_VERSION_NONE }, - { "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 }, - { "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 - // torin is the same - - // TODO: SCI2.1, SCI3 IDs - - { "", "", SCI_VERSION_NONE } -}; - -Common::String convertSierraGameId(const char *gameId, uint32 *gameFlags, ResourceManager *resMan) { - // Convert the id to lower case, so that we match all upper/lower case variants. - Common::String sierraId = gameId; - 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 *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"; - } - - 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; -} - #ifdef USE_OLD_MUSIC_FUNCTIONS int game_init_sound(EngineState *s, int sound_flags, SciVersion soundVersion) { if (getSciVersion() > SCI_VERSION_0_LATE) @@ -265,10 +130,6 @@ int game_init(EngineState *s) { // script_dissect(0, s->_selectorNames); // The first entry in the export table of script 0 points to the game object s->_gameObj = s->_segMan->lookupScriptExport(0, 0); - uint32 gameFlags = 0; // unused - s->_gameId = convertSierraGameId(s->_segMan->getObjectName(s->_gameObj), &gameFlags, g_sci->getResMan()); - - debug(2, " \"%s\" at %04x:%04x", s->_gameId.c_str(), PRINT_REG(s->_gameObj)); #ifdef USE_OLD_MUSIC_FUNCTIONS if (s->sfx_init_flags & SFX_STATE_FLAG_NOSOUND) diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index d587790b6c4..abc7efd7438 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -525,7 +525,7 @@ reg_t kBaseSetter(EngineState *s, int argc, reg_t *argv) { // WORKAROUND for a problem in LSL1VGA. This allows the casino door to be opened, // till the actual problem is found - if (s->_gameId == "lsl1sci" && s->currentRoomNumber() == 300) { + if (!strcmp(g_sci->getGameID(), "lsl1sci") && s->currentRoomNumber() == 300) { int top = GET_SEL32V(s->_segMan, object, SELECTOR(brTop)); PUT_SEL32V(s->_segMan, object, SELECTOR(brTop), top + 2); } @@ -799,7 +799,7 @@ void _k_GenericDrawControl(EngineState *s, reg_t controlObject, bool hilite) { // ALL other games use a hardcoded -1 (madness!) // We are detecting jones/talkie as "jones" as well, but the sierra interpreter of talkie doesnt have this // "hack". Hopefully it wont cause regressions (the code causes regressions if used against kq5/floppy) - if (s->_gameId == "jones") + if (!strcmp(g_sci->getGameID(), "jones")) priority = GET_SEL32V(s->_segMan, controlObject, SELECTOR(priority)); else priority = -1; @@ -983,7 +983,7 @@ reg_t kDrawCel(EngineState *s, int argc, reg_t *argv) { bool hiresMode = (argc > 7) ? true : false; reg_t upscaledHiresHandle = (argc > 7) ? argv[7] : NULL_REG; - if ((s->_gameId == "freddypharkas") || (s->_gameId == "freddypharkas-demo")) { + if (!strcmp(g_sci->getGameID(), "freddypharkas") || !strcmp(g_sci->getGameID(), "freddypharkas-demo")) { // WORKAROUND // Script 24 contains code that draws the game menu on screen. It uses a temp variable for setting priority that // is not set. in Sierra sci this happens to be 8250h. In our sci temporary variables are initialized thus we would @@ -994,7 +994,7 @@ reg_t kDrawCel(EngineState *s, int argc, reg_t *argv) { priority = 15; } - if (s->_gameId == "laurabow2") { + if (!strcmp(g_sci->getGameID(), "laurabow2")) { // WORKAROUND // see the one above if ((viewId == 995) && (priority == 0)) diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp index 450dca37709..74368b8c714 100644 --- a/engines/sci/engine/kmisc.cpp +++ b/engines/sci/engine/kmisc.cpp @@ -62,9 +62,9 @@ reg_t kGameIsRestarting(EngineState *s, int argc, reg_t *argv) { // LSL3 calculates a machinespeed variable during game startup (right after the filthy questions) // This one would go through w/o throttling resulting in having to do 1000 pushups or something // Another way of handling this would be delaying incrementing of "machineSpeed" selector - if (s->_gameId == "lsl3" && s->currentRoomNumber() == 290) + if (!strcmp(g_sci->getGameID(), "lsl3") && s->currentRoomNumber() == 290) s->_throttleTrigger = true; - if (s->_gameId == "iceman" && s->currentRoomNumber() == 27) { + if (!strcmp(g_sci->getGameID(), "iceman") && s->currentRoomNumber() == 27) { s->_throttleTrigger = true; neededSleep = 60; } diff --git a/engines/sci/engine/kmovement.cpp b/engines/sci/engine/kmovement.cpp index fcaf0d7ea01..5acda3a3254 100644 --- a/engines/sci/engine/kmovement.cpp +++ b/engines/sci/engine/kmovement.cpp @@ -334,7 +334,7 @@ reg_t kDoBresen(EngineState *s, int argc, reg_t *argv) { } // FIXME: find out why iceman needs this and we ask for version > SCI01 - if ((getSciVersion() > SCI_VERSION_01) || (s->_gameId == "iceman")) + if ((getSciVersion() > SCI_VERSION_01) || !strcmp(g_sci->getGameID(), "iceman")) if (completed) invoke_selector(INV_SEL(s, mover, moveDone, kStopOnInvalidSelector), 0); diff --git a/engines/sci/engine/kpathing.cpp b/engines/sci/engine/kpathing.cpp index 25d967c247e..1152addeba1 100644 --- a/engines/sci/engine/kpathing.cpp +++ b/engines/sci/engine/kpathing.cpp @@ -1056,7 +1056,7 @@ static Polygon *convert_polygon(EngineState *s, reg_t polygon) { // WORKAROUND: broken polygon in lsl1sci, room 350, after opening elevator // Polygon has 17 points but size is set to 19 - if ((size == 19) && (s->_gameId == "lsl1sci")) { + if ((size == 19) && !strcmp(g_sci->getGameID(), "lsl1sci")) { if ((s->currentRoomNumber() == 350) && (read_point(segMan, points, 18) == Common::Point(108, 137))) { debug(1, "Applying fix for broken polygon in lsl1sci, room 350"); @@ -1174,7 +1174,7 @@ static PathfindingState *convert_polygon_set(EngineState *s, reg_t poly_list, Co // WORKAROUND LSL5 room 660. Priority glitch due to us choosing a different path // than SSCI. Happens when Patti walks to the control room. - if ((s->_gameId == "lsl5") && (s->currentRoomNumber() == 660) && (Common::Point(67, 131) == *new_start) && (Common::Point(229, 101) == *new_end)) { + if (!strcmp(g_sci->getGameID(), "lsl5") && (s->currentRoomNumber() == 660) && (Common::Point(67, 131) == *new_start) && (Common::Point(229, 101) == *new_end)) { debug(1, "[avoidpath] Applying fix for priority problem in LSL5, room 660"); pf_s->_prependPoint = new_start; new_start = new Common::Point(77, 107); diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index fef2b9a19e1..2532d174a1f 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -997,7 +997,6 @@ void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { retval->_voc->parser_base = make_reg(s->sys_strings_segment, SYS_STRING_PARSER_BASE); retval->successor = NULL; - retval->_gameId = s->_gameId; #ifdef USE_OLD_MUSIC_FUNCTIONS retval->_sound._it = NULL; diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h index c4b995806f9..ad2b0f70585 100644 --- a/engines/sci/engine/state.h +++ b/engines/sci/engine/state.h @@ -105,8 +105,6 @@ public: SegManager *_segMan; /**< The segment manager */ Vocabulary *_voc; - Common::String _gameId; /**< Designation of the primary object (which inherits from Game) */ - /* Non-VM information */ SciEvent *_event; // Event handling diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index e2ee2e19717..bf447419e8a 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -1732,7 +1732,7 @@ static EngineState *_game_run(EngineState *&s) { int game_run(EngineState **_s) { EngineState *s = *_s; - debugC(2, kDebugLevelVM, "Calling %s::play()", s->_gameId.c_str()); + debugC(2, kDebugLevelVM, "Calling %s::play()", g_sci->getGameID()); _init_stack_base_with_selector(s, g_sci->getKernel()->_selectorCache.play); // Call the play selector // Now: Register the first element on the execution stack- diff --git a/engines/sci/graphics/gui.cpp b/engines/sci/graphics/gui.cpp index 46f7fcd6890..29ab64ddb27 100644 --- a/engines/sci/graphics/gui.cpp +++ b/engines/sci/graphics/gui.cpp @@ -92,7 +92,7 @@ void SciGui::resetEngineState(EngineState *s) { } void SciGui::init(bool usesOldGfxFunctions) { - _ports->init(usesOldGfxFunctions, this, _paint16, _text16, _s->_gameId); + _ports->init(usesOldGfxFunctions, this, _paint16, _text16); _paint16->init(_animate, _text16); } diff --git a/engines/sci/graphics/ports.cpp b/engines/sci/graphics/ports.cpp index ab3291dd79d..cdb6fe4ae11 100644 --- a/engines/sci/graphics/ports.cpp +++ b/engines/sci/graphics/ports.cpp @@ -54,7 +54,7 @@ GfxPorts::~GfxPorts() { delete _menuPort; } -void GfxPorts::init(bool usesOldGfxFunctions, SciGui *gui, GfxPaint16 *paint16, GfxText16 *text16, Common::String gameId) { +void GfxPorts::init(bool usesOldGfxFunctions, SciGui *gui, GfxPaint16 *paint16, GfxText16 *text16) { int16 offTop = 10; _usesOldGfxFunctions = usesOldGfxFunctions; @@ -88,6 +88,7 @@ void GfxPorts::init(bool usesOldGfxFunctions, SciGui *gui, GfxPaint16 *paint16, // Jones, Slater and Hoyle 3 were called with parameter -Nw 0 0 200 320. // Mother Goose (SCI1) uses -Nw 0 0 159 262. The game will later use SetPort so we don't need to set the other fields. // This actually meant not skipping the first 10 pixellines in windowMgrPort + Common::String gameId = g_sci->getGameID(); if (gameId == "jones" || gameId == "slater" || gameId == "hoyle3" || (gameId == "mothergoose" && getSciVersion() == SCI_VERSION_1_EARLY)) offTop = 0; diff --git a/engines/sci/graphics/ports.h b/engines/sci/graphics/ports.h index 0876d9e4424..c8ce6b34703 100644 --- a/engines/sci/graphics/ports.h +++ b/engines/sci/graphics/ports.h @@ -45,7 +45,7 @@ public: GfxPorts(SegManager *segMan, GfxScreen *screen); ~GfxPorts(); - void init(bool usesOldGfxFunctions, SciGui *gui, GfxPaint16 *paint16, GfxText16 *text16, Common::String gameId); + void init(bool usesOldGfxFunctions, SciGui *gui, GfxPaint16 *paint16, GfxText16 *text16); void kernelSetActive(uint16 portId); Common::Rect kernelGetPicWindow(int16 &picTop, int16 &picLeft); diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 4888dbd4cb1..aa3b8019de0 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -2329,6 +2329,41 @@ bool ResourceManager::hasSci1Voc900() { return offset == res->size; } +#define READ_UINT16(ptr) (!isSci11Mac() ? READ_LE_UINT16(ptr) : READ_BE_UINT16(ptr)) + +Common::String ResourceManager::findSierraGameId() { + Resource *script = findResource(ResourceId(kResourceTypeScript, 0), false); + // In SCI0-SCI1, the heap is embedded in the script. In SCI1.1+, it's separated + Resource *heap = 0; + byte *seeker = 0; + + // Seek to the name selector of the first export + if (getSciVersion() < SCI_VERSION_1_1) { + const int nameSelector = 3; + int extraSci0EarlyBytes = (getSciVersion() == SCI_VERSION_0_EARLY) ? 2 : 0; + byte *exportPtr = script->data + extraSci0EarlyBytes + 4 + 2; + seeker = script->data + READ_UINT16(script->data + READ_UINT16(exportPtr) + nameSelector * 2); + } else { + const int nameSelector = 5 + 3; + heap = findResource(ResourceId(kResourceTypeHeap, 0), false); + byte *exportPtr = script->data + 4 + 2 + 2; + seeker = heap->data + READ_UINT16(heap->data + READ_UINT16(exportPtr) + nameSelector * 2); + } + + char sierraId[20]; + int i = 0; + byte curChar = 0; + + do { + curChar = *(seeker + i); + sierraId[i++] = curChar; + } while (curChar != 0); + + return sierraId; +} + +#undef READ_UINT16 + SoundResource::SoundResource(uint32 resNumber, ResourceManager *resMan, SciVersion soundVersion) : _resMan(resMan), _soundVersion(soundVersion) { Resource *resource = _resMan->findResource(ResourceId(kResourceTypeSound, resNumber), true); int trackNr, channelNr; diff --git a/engines/sci/resource.h b/engines/sci/resource.h index 48b5f095b18..befda072e08 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -273,6 +273,11 @@ public: // Detects, if standard font of current game includes extended characters (>0x80) bool detectFontExtended(); + /** + * Finds the internal Sierra ID of the current game from script 0 + */ + Common::String findSierraGameId(); + protected: // Maximum number of bytes to allow being allocated for resources // Note: maxMemory will not be interpreted as a hard limit, only as a restriction diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 4862d0579ac..bb5124b88bf 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -222,7 +222,7 @@ Common::Error SciEngine::run() { } // Add the after market GM patches for the specified game, if they exist - _resMan->addNewGMPatch(_gamestate->_gameId); + _resMan->addNewGMPatch(getGameID()); script_adjust_opcode_formats(_gamestate); _kernel->loadKernelNames(getGameID());