diff options
Diffstat (limited to 'engines/sci/engine/game.cpp')
-rw-r--r-- | engines/sci/engine/game.cpp | 173 |
1 files changed, 162 insertions, 11 deletions
diff --git a/engines/sci/engine/game.cpp b/engines/sci/engine/game.cpp index bc10099e52..4ac2a22531 100644 --- a/engines/sci/engine/game.cpp +++ b/engines/sci/engine/game.cpp @@ -41,6 +41,141 @@ 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<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"; + } + + 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) @@ -67,7 +202,13 @@ int script_init_engine(EngineState *s) { s->script_000 = s->_segMan->getScript(script_000_segment); - s->_segMan->initSysStrings(); + s->sys_strings = s->_segMan->allocateSysStrings(&s->sys_strings_segment); + + // Allocate static buffer for savegame and CWD directories + SystemString *str = &s->sys_strings->_strings[SYS_STRING_SAVEDIR]; + str->_name = "savedir"; + str->_maxSize = MAX_SAVE_DIR_SIZE; + str->_value = (char *)calloc(MAX_SAVE_DIR_SIZE, sizeof(char)); s->r_acc = s->r_prev = NULL_REG; s->restAdjust = 0; @@ -99,26 +240,35 @@ int game_init(EngineState *s) { return 1; } - // Reset parser - Vocabulary *voc = g_sci->getVocabulary(); - if (voc) { - voc->parserIsValid = false; // Invalidate parser - voc->parser_event = NULL_REG; // Invalidate parser event - voc->parser_base = make_reg(s->_segMan->getSysStringsSegment(), SYS_STRING_PARSER_BASE); + if (s->_voc) { + s->_voc->parserIsValid = false; // Invalidate parser + s->_voc->parser_event = NULL_REG; // Invalidate parser event + s->_voc->parser_base = make_reg(s->sys_strings_segment, SYS_STRING_PARSER_BASE); } // Initialize menu TODO: Actually this should be another init() if (g_sci->_gfxMenu) g_sci->_gfxMenu->reset(); - s->restoring = false; + s->successor = NULL; // No successor + + SystemString *str = &s->sys_strings->_strings[SYS_STRING_PARSER_BASE]; + str->_name = "parser-base"; + str->_maxSize = MAX_PARSER_BASE; + str->_value = (char *)calloc(MAX_PARSER_BASE, sizeof(char)); s->game_start_time = g_system->getMillis(); s->last_wait_time = s->game_start_time; srand(g_system->getMillis()); // Initialize random number generator - s->_gameObj = g_sci->getResMan()->findGameObject(); +// 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) @@ -134,8 +284,9 @@ int game_init(EngineState *s) { } int game_exit(EngineState *s) { - if (!s->restoring) { - s->_executionStack.clear(); + s->_executionStack.clear(); + + if (!s->successor) { #ifdef USE_OLD_MUSIC_FUNCTIONS s->_sound.sfx_exit(); // Reinit because some other code depends on having a valid state |