示例#1
0
文件: animate.cpp 项目: Cruel/scummvm
// SCI1 Early:
// KQ5 - no fastcast, LSL1 (demo) - no fastcast, Mixed Up Fairy Tales - *has fastcast*, XMas Card 1990 - no fastcast,
// SQ4Floppy - no fastcast, Mixed Up Mother Goose - no fastcast
//
// SCI1 Middle:
// LSL5 demo - no fastfast, Conquest of the Longbow demo - no fastcast, LSL1 - no fastcast,
// Astro Chicken II - no fastcast
//
// SCI1 Late:
// Castle of Dr. Brain demo - has fastcast, Castle of Dr. Brain - has fastcast,
// Conquests of the Longbow - has fastcast, Space Quest 1 EGA - has fastcast,
// King's Quest 5 multilingual - *NO* fastcast, Police Quest 3 demo - *NO* fastcast,
// LSL5 multilingual - has fastcast, Police Quest 3 - has fastcast,
// EcoQuest 1 - has fastcast, Mixed Up Fairy Tales demo - has fastcast,
// Space Quest 4 multilingual - *NO* fastcast
//
// SCI1.1
// Quest for Glory 3 demo - has fastcast, Police Quest 1 - hast fastcast, Quest for Glory 1 - has fastcast
// Laura Bow 2 Floppy - has fastcast, Mixed Up Mother Goose - has fastcast, Quest for Glory 3 - has fastcast
// Island of Dr. Brain - has fastcast, King's Quest 6 - has fastcast, Space Quest 5 - has fastcast
// Hoyle 4 - has fastcast, Laura Bow 2 CD - has fastcast, Freddy Pharkas CD - has fastcast
bool GfxAnimate::detectFastCast() {
	SegManager *segMan = _s->_segMan;
	const reg_t gameVMObject = g_sci->getGameObject();
	reg_t gameSuperVMObject = segMan->getObject(gameVMObject)->getSuperClassSelector();
	uint32 magicDWord = 0; // platform-specific BE/LE for performance
	int    magicDWordOffset = 0;

	if (gameSuperVMObject.isNull()) {
		gameSuperVMObject = gameVMObject; // Just in case. According to sci.cpp this may happen in KQ5CD, when loading saved games before r54510
	}

	Script *objectScript = segMan->getScript(gameSuperVMObject.getSegment());
	byte *scriptData = const_cast<byte *>(objectScript->getBuf(0));
	uint32 scriptSize = objectScript->getBufSize();

	_scriptPatcher->calculateMagicDWordAndVerify("fast cast detection", fastCastSignature, true, magicDWord, magicDWordOffset);

	// Signature is found for multilingual King's Quest 5 too, but it looks as if the fast cast global is never set
	// within that game. Which means even though we detect it as having the capability, it's never actually used.
	// The original multilingual KQ5 interpreter did have this feature disabled.
	// Sierra probably used latest system scripts and that's why we detect it.
	if (_scriptPatcher->findSignature(magicDWord, magicDWordOffset, fastCastSignature, "fast cast detection", scriptData, scriptSize) >= 0) {
		// Signature found, game seems to use fast cast for kAnimate
		return true;
	}
	return false;
}
示例#2
0
void SciEngine::patchGameSaveRestore() {
	SegManager *segMan = _gamestate->_segMan;
	const Object *gameObject = segMan->getObject(_gameObjectAddress);
	const uint16 gameMethodCount = gameObject->getMethodCount();
	const Object *gameSuperObject = segMan->getObject(_gameSuperClassAddress);
	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 on SCI32
	if (getSciVersion() >= SCI_VERSION_2)
		return;

	switch (_gameId) {
	case GID_MOTHERGOOSE256: // mother goose saves/restores directly and has no save/restore dialogs
	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_HOYLE1: // gets confused, although the game doesnt support saving/restoring at all
	case GID_HOYLE2: // gets confused, see hoyle1
		return;
	default:
		break;
	}

	if (ConfMan.getBool("sci_originalsaveload"))
		return;

	for (uint16 kernelNr = 0; kernelNr < kernelCount; kernelNr++) {
		Common::String kernelName = _kernel->getKernelName(kernelNr);
		if (kernelName == "RestoreGame")
			kernelIdRestore = kernelNr;
		if (kernelName == "SaveGame")
			kernelIdSave = kernelNr;
	}

	// Search for gameobject-superclass ::restore
	for (uint16 methodNr = 0; methodNr < gameSuperMethodCount; 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);
		}
	}

	// Search for gameobject ::save, if there is one patch that one instead
	for (uint16 methodNr = 0; methodNr < gameMethodCount; 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);
			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<byte *>(scriptRestorePtr);
		memcpy(patchPtr, patchGameRestoreSave, sizeof(patchGameRestoreSave));
		patchPtr[8] = kernelIdRestore;
	}
	if (scriptSavePtr) {
		// Now patch in our code
		byte *patchPtr = const_cast<byte *>(scriptSavePtr);
		memcpy(patchPtr, patchGameRestoreSave, sizeof(patchGameRestoreSave));
		patchPtr[8] = kernelIdSave;
	}
}