Exemple #1
0
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;
		}
	}
}
Exemple #2
0
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;
		}
	}
}