void SciEngine::patchGameSaveRestore() { SegManager *segMan = _gamestate->_segMan; const Object *gameObject = segMan->getObject(_gameObjectAddress); const Object *gameSuperObject = segMan->getObject(gameObject->getSuperClassSelector()); if (!gameSuperObject) gameSuperObject = gameObject; // happens in KQ5CD, when loading saved games before r54510 byte kernelIdRestore = 0; byte kernelIdSave = 0; switch (_gameId) { case GID_HOYLE1: // gets confused, although the game doesn't support saving/restoring at all case GID_HOYLE2: // gets confused, see hoyle1 case GID_JONES: // gets confused, when we patch us in, the game is only able to save to 1 slot, so hooking is not required case GID_KQ7: // has custom save/load code case GID_MOTHERGOOSE: // mother goose EGA saves/restores directly and has no save/restore dialogs case GID_MOTHERGOOSE256: // mother goose saves/restores directly and has no save/restore dialogs case GID_MOTHERGOOSEHIRES: // has custom save/load code case GID_PHANTASMAGORIA: // has custom save/load code case GID_PQSWAT: // has custom save/load code case GID_SHIVERS: // has custom save/load code return; default: break; } if (ConfMan.getBool("originalsaveload")) return; uint16 kernelNamesSize = _kernel->getKernelNamesSize(); for (uint16 kernelNr = 0; kernelNr < kernelNamesSize; kernelNr++) { Common::String kernelName = _kernel->getKernelName(kernelNr); if (kernelName == "RestoreGame") kernelIdRestore = kernelNr; if (kernelName == "SaveGame") kernelIdSave = kernelNr; if (kernelName == "Save") kernelIdSave = kernelIdRestore = kernelNr; } // 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") { #ifdef ENABLE_SCI32 if (getSciVersion() >= SCI_VERSION_2) { patchGameSaveRestoreCodeSci2(segMan, gameSuperObject->getFunction(methodNr), kernelIdRestore, true); } else #endif patchGameSaveRestoreCode(segMan, gameSuperObject->getFunction(methodNr), kernelIdRestore); } else if (methodName == "save") { if (_gameId != GID_FAIRYTALES) { // Fairy Tales saves automatically without a dialog #ifdef ENABLE_SCI32 if (getSciVersion() >= SCI_VERSION_2) { patchGameSaveRestoreCodeSci2(segMan, gameSuperObject->getFunction(methodNr), kernelIdSave, false); } else #endif patchGameSaveRestoreCode(segMan, gameSuperObject->getFunction(methodNr), kernelIdSave); } } } const Object *patchObjectSave = nullptr; if (getSciVersion() < SCI_VERSION_2) { // Patch gameobject ::save for now for SCI0 - SCI1.1 // TODO: It seems this was never adjusted to superclass, but adjusting it now may cause // issues with some game. Needs to get checked and then possibly changed. patchObjectSave = gameObject; } else { // Patch superclass ::save for SCI32 patchObjectSave = gameSuperObject; } // Search for gameobject ::save, if there is one patch that one too uint16 patchObjectMethodCount = patchObjectSave->getMethodCount(); for (uint16 methodNr = 0; methodNr < patchObjectMethodCount; methodNr++) { uint16 selectorId = patchObjectSave->getFuncSelector(methodNr); Common::String methodName = _kernel->getSelectorName(selectorId); if (methodName == "save") { if (_gameId != GID_FAIRYTALES) { // Fairy Tales saves automatically without a dialog #ifdef ENABLE_SCI32 if (getSciVersion() >= SCI_VERSION_2) { patchGameSaveRestoreCodeSci2(segMan, gameSuperObject->getFunction(methodNr), kernelIdSave, false); } else #endif patchGameSaveRestoreCode(segMan, patchObjectSave->getFunction(methodNr), kernelIdSave); } break; } } }
void SciEngine::patchGameSaveRestore() { SegManager *segMan = _gamestate->_segMan; const Object *gameObject = segMan->getObject(_gameObjectAddress); const Object *gameSuperObject = segMan->getObject(gameObject->getSuperClassSelector()); if (!gameSuperObject) gameSuperObject = gameObject; // happens in KQ5CD, when loading saved games before r54510 byte kernelIdRestore = 0; byte kernelIdSave = 0; switch (_gameId) { case GID_HOYLE1: // gets confused, although the game doesnt support saving/restoring at all case GID_HOYLE2: // gets confused, see hoyle1 case GID_JONES: // gets confused, when we patch us in, the game is only able to save to 1 slot, so hooking is not required case GID_MOTHERGOOSE256: // mother goose saves/restores directly and has no save/restore dialogs case GID_PHANTASMAGORIA: // has custom save/load code case GID_SHIVERS: // has custom save/load code return; default: break; } if (ConfMan.getBool("originalsaveload")) return; uint16 kernelNamesSize = _kernel->getKernelNamesSize(); for (uint16 kernelNr = 0; kernelNr < kernelNamesSize; kernelNr++) { Common::String kernelName = _kernel->getKernelName(kernelNr); if (kernelName == "RestoreGame") kernelIdRestore = kernelNr; if (kernelName == "SaveGame") kernelIdSave = kernelNr; if (kernelName == "Save") kernelIdSave = kernelIdRestore = kernelNr; } // 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") { if (kernelIdSave != kernelIdRestore) patchGameSaveRestoreCode(segMan, gameSuperObject->getFunction(methodNr), kernelIdRestore); else patchGameSaveRestoreCodeSci21(segMan, gameSuperObject->getFunction(methodNr), kernelIdRestore, true); } else if (methodName == "save") { if (_gameId != GID_FAIRYTALES) { // Fairy Tales saves automatically without a dialog if (kernelIdSave != kernelIdRestore) patchGameSaveRestoreCode(segMan, gameSuperObject->getFunction(methodNr), kernelIdSave); else patchGameSaveRestoreCodeSci21(segMan, gameSuperObject->getFunction(methodNr), kernelIdSave, false); } } } // 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") { if (_gameId != GID_FAIRYTALES) { // Fairy Tales saves automatically without a dialog if (kernelIdSave != kernelIdRestore) patchGameSaveRestoreCode(segMan, gameObject->getFunction(methodNr), kernelIdSave); else patchGameSaveRestoreCodeSci21(segMan, gameObject->getFunction(methodNr), kernelIdSave, false); } break; } } }