From 4d3392343675faec3b2427a7cd2d19ddce69884b Mon Sep 17 00:00:00 2001 From: md5 Date: Mon, 28 Feb 2011 00:15:47 +0200 Subject: SCI: Cleanup of the save/load dialog patching code and the lofs type detection code --- engines/sci/engine/features.cpp | 20 ++++------ engines/sci/sci.cpp | 81 ++++++++++++++--------------------------- engines/sci/sci.h | 2 - 3 files changed, 35 insertions(+), 68 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/features.cpp b/engines/sci/engine/features.cpp index 206624f87e..964097f57d 100644 --- a/engines/sci/engine/features.cpp +++ b/engines/sci/engine/features.cpp @@ -285,20 +285,16 @@ SciVersion GameFeatures::detectLofsType() { } // Find a function of the "Game" object (which is the game super class) which invokes lofsa/lofss - reg_t gameSuperClass = g_sci->getGameSuperClassAddress(); + const Object *gameObject = _segMan->getObject(g_sci->getGameObject()); + const Object *gameSuperObject = _segMan->getObject(gameObject->getSuperClassSelector()); bool found = false; - if (!gameSuperClass.isNull()) { - Common::String gameSuperClassName = _segMan->getObjectName(gameSuperClass); - const Object *gameSuperObject = _segMan->getObject(gameSuperClass); + if (gameSuperObject) { + Common::String gameSuperClassName = _segMan->getObjectName(gameObject->getSuperClassSelector()); - if (gameSuperObject) { - for (uint m = 0; m < gameSuperObject->getMethodCount(); m++) { - found = autoDetectLofsType(gameSuperClassName, m); - if (found) - break; - } - } else { - warning("detectLofsType(): Could not get superclass object"); + for (uint m = 0; m < gameSuperObject->getMethodCount(); m++) { + found = autoDetectLofsType(gameSuperClassName, m); + if (found) + break; } } else { warning("detectLofsType(): Could not find superclass of game object"); diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index b460b06662..4155fd2a1f 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -213,7 +213,6 @@ Common::Error SciEngine::run() { // Add the after market GM patches for the specified game, if they exist _resMan->addNewGMPatch(_gameId); _gameObjectAddress = _resMan->findGameObject(); - _gameSuperClassAddress = NULL_REG; SegManager *segMan = new SegManager(_resMan); @@ -250,7 +249,6 @@ Common::Error SciEngine::run() { warning("Could not get game object, aborting..."); return Common::kUnknownError; } - _gameSuperClassAddress = gameObject->getSuperClassSelector(); script_adjust_opcode_formats(); @@ -441,19 +439,24 @@ static byte patchGameRestoreSaveSci2[] = { 0x48, // ret }; +static void patchGameSaveRestoreCode(SegManager *segMan, reg_t methodAddress, byte id) { + Script *script = segMan->getScript(methodAddress.segment); + byte *patchPtr = const_cast(script->getBuf(methodAddress.offset)); + if (getSciVersion() <= SCI_VERSION_1_1) + memcpy(patchPtr, patchGameRestoreSave, sizeof(patchGameRestoreSave)); + else if (getSciVersion() == SCI_VERSION_2) + memcpy(patchPtr, patchGameRestoreSaveSci2, sizeof(patchGameRestoreSaveSci2)); + // TODO: SCI21/SCI3 + patchPtr[8] = id; +} + void SciEngine::patchGameSaveRestore() { SegManager *segMan = _gamestate->_segMan; const Object *gameObject = segMan->getObject(_gameObjectAddress); - const uint16 gameMethodCount = gameObject->getMethodCount(); - const Object *gameSuperObject = segMan->getObject(_gameSuperClassAddress); + const Object *gameSuperObject = segMan->getObject(gameObject->getSuperClassSelector()); if (!gameSuperObject) gameSuperObject = gameObject; // happens in KQ5CD, when loading saved games before r54510 - const uint16 gameSuperMethodCount = gameSuperObject->getMethodCount(); - reg_t methodAddress; - const uint16 kernelCount = _kernel->getKernelNamesSize(); - const byte *scriptRestorePtr = NULL; byte kernelIdRestore = 0; - const byte *scriptSavePtr = NULL; byte kernelIdSave = 0; // This feature is currently not supported in SCI21 or SCI3 @@ -473,7 +476,8 @@ void SciEngine::patchGameSaveRestore() { if (ConfMan.getBool("sci_originalsaveload")) return; - for (uint16 kernelNr = 0; kernelNr < kernelCount; kernelNr++) { + uint16 kernelNamesSize = _kernel->getKernelNamesSize(); + for (uint16 kernelNr = 0; kernelNr < kernelNamesSize; kernelNr++) { Common::String kernelName = _kernel->getKernelName(kernelNr); if (kernelName == "RestoreGame") kernelIdRestore = kernelNr; @@ -481,61 +485,30 @@ void SciEngine::patchGameSaveRestore() { kernelIdSave = kernelNr; } - // Search for gameobject-superclass ::restore - for (uint16 methodNr = 0; methodNr < gameSuperMethodCount; methodNr++) { + // Search for gameobject superclass ::restore + uint16 gameSuperObjectMethodCount = gameSuperObject->getMethodCount(); + for (uint16 methodNr = 0; methodNr < gameSuperObjectMethodCount; methodNr++) { uint16 selectorId = gameSuperObject->getFuncSelector(methodNr); Common::String methodName = _kernel->getSelectorName(selectorId); - if (methodName == "restore") { - methodAddress = gameSuperObject->getFunction(methodNr); - Script *script = segMan->getScript(methodAddress.segment); - scriptRestorePtr = script->getBuf(methodAddress.offset); - } - if (methodName == "save") { - methodAddress = gameSuperObject->getFunction(methodNr); - Script *script = segMan->getScript(methodAddress.segment); - scriptSavePtr = script->getBuf(methodAddress.offset); + if (methodName == "restore") + patchGameSaveRestoreCode(segMan, gameSuperObject->getFunction(methodNr), kernelIdRestore); + else if (methodName == "save") { + if (_gameId != GID_FAIRYTALES) // Fairy Tales saves automatically without a dialog + patchGameSaveRestoreCode(segMan, gameSuperObject->getFunction(methodNr), kernelIdSave); } } - // Search for gameobject ::save, if there is one patch that one instead - for (uint16 methodNr = 0; methodNr < gameMethodCount; methodNr++) { + // Search for gameobject ::save, if there is one patch that one too + uint16 gameObjectMethodCount = gameObject->getMethodCount(); + for (uint16 methodNr = 0; methodNr < gameObjectMethodCount; methodNr++) { uint16 selectorId = gameObject->getFuncSelector(methodNr); Common::String methodName = _kernel->getSelectorName(selectorId); if (methodName == "save") { - methodAddress = gameObject->getFunction(methodNr); - Script *script = segMan->getScript(methodAddress.segment); - scriptSavePtr = script->getBuf(methodAddress.offset); + if (_gameId != GID_FAIRYTALES) // Fairy Tales saves automatically without a dialog + patchGameSaveRestoreCode(segMan, gameObject->getFunction(methodNr), kernelIdSave); break; } } - - switch (_gameId) { - case GID_FAIRYTALES: // fairy tales automatically saves w/o dialog - scriptSavePtr = NULL; - default: - break; - } - - if (scriptRestorePtr) { - // Now patch in our code - byte *patchPtr = const_cast(scriptRestorePtr); - if (getSciVersion() <= SCI_VERSION_1_1) - memcpy(patchPtr, patchGameRestoreSave, sizeof(patchGameRestoreSave)); - else if (getSciVersion() == SCI_VERSION_2) - memcpy(patchPtr, patchGameRestoreSaveSci2, sizeof(patchGameRestoreSaveSci2)); - // TODO: SCI21/SCI3 - patchPtr[8] = kernelIdRestore; - } - if (scriptSavePtr) { - // Now patch in our code - byte *patchPtr = const_cast(scriptSavePtr); - if (getSciVersion() <= SCI_VERSION_1_1) - memcpy(patchPtr, patchGameRestoreSave, sizeof(patchGameRestoreSave)); - else if (getSciVersion() == SCI_VERSION_2) - memcpy(patchPtr, patchGameRestoreSaveSci2, sizeof(patchGameRestoreSaveSci2)); - // TODO: SCI21/SCI3 - patchPtr[8] = kernelIdSave; - } } bool SciEngine::initGame() { diff --git a/engines/sci/sci.h b/engines/sci/sci.h index 72fbe0c71f..aea5712ace 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -246,7 +246,6 @@ public: inline Vocabulary *getVocabulary() const { return _vocabulary; } inline EventManager *getEventManager() const { return _eventMan; } inline reg_t getGameObject() const { return _gameObjectAddress; } - inline reg_t getGameSuperClassAddress() const { return _gameSuperClassAddress; } Common::RandomSource &getRNG() { return _rng; } @@ -375,7 +374,6 @@ private: int16 _vocabularyLanguage; EventManager *_eventMan; reg_t _gameObjectAddress; /**< Pointer to the game object */ - reg_t _gameSuperClassAddress; // Address of the super class of the game object Console *_console; Common::RandomSource _rng; Common::MacResManager _macExecutable; -- cgit v1.2.3