diff options
| author | md5 | 2011-03-04 00:20:28 +0200 | 
|---|---|---|
| committer | md5 | 2011-03-04 00:25:23 +0200 | 
| commit | 1bdc6db980ffb72c4466d3b1a37f631f78ef59b9 (patch) | |
| tree | 93900c73fde9883c8f6d36392fdf9d834fb253f8 /engines/sci/sci.cpp | |
| parent | 9cc12cfc97028e71ebaede1db67a076e408edaeb (diff) | |
| download | scummvm-rg350-1bdc6db980ffb72c4466d3b1a37f631f78ef59b9.tar.gz scummvm-rg350-1bdc6db980ffb72c4466d3b1a37f631f78ef59b9.tar.bz2 scummvm-rg350-1bdc6db980ffb72c4466d3b1a37f631f78ef59b9.zip | |
SCI21: Now replacing save/restore dialogs in SCI2.1 and newer games
Diffstat (limited to 'engines/sci/sci.cpp')
| -rw-r--r-- | engines/sci/sci.cpp | 57 | 
1 files changed, 42 insertions, 15 deletions
| diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 657a7b9ee2..de33a59647 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -265,8 +265,6 @@ Common::Error SciEngine::run() {  	// Initialize all graphics related subsystems  	initGraphics(); -	debug("Emulating SCI version %s\n", getSciVersionDesc(getSciVersion())); -  	// Patch in our save/restore code, so that dialogs are replaced  	patchGameSaveRestore();  	setLauncherLanguage(); @@ -425,7 +423,7 @@ static byte patchGameRestoreSave[] = {  	0x76,              // push0  	0x38, 0xff, 0xff,  // pushi -1  	0x76,              // push0 -	0x43, 0xff, 0x06,  // callk kRestoreGame/kSaveGame (will get fixed directly) +	0x43, 0xff, 0x06,  // callk kRestoreGame/kSaveGame (will get changed afterwards)  	0x48,              // ret  }; @@ -435,7 +433,18 @@ static byte patchGameRestoreSaveSci2[] = {  	0x76,              // push0  	0x38, 0xff, 0xff,  // pushi -1  	0x76,              // push0 -	0x43, 0xff, 0x06, 0x00, // callk kRestoreGame/kSaveGame (will get fixed directly) +	0x43, 0xff, 0x06, 0x00, // callk kRestoreGame/kSaveGame (will get changed afterwards) +	0x48,              // ret +}; + +// SCI21 version: Same as above, but the second parameter to callk is a word +static byte patchGameRestoreSaveSci21[] = { +	0x39, 0x04,        // pushi 04 +	0x76,              // push0	// 0: save, 1: restore (will get changed afterwards) +	0x76,              // push0 +	0x38, 0xff, 0xff,  // pushi -1 +	0x76,              // push0 +	0x43, 0xff, 0x08, 0x00, // callk kSave (will get changed afterwards)  	0x48,              // ret  }; @@ -449,6 +458,15 @@ static void patchGameSaveRestoreCode(SegManager *segMan, reg_t methodAddress, by  	patchPtr[8] = id;  } +static void patchGameSaveRestoreCodeSci21(SegManager *segMan, reg_t methodAddress, byte id, bool doRestore) { +	Script *script = segMan->getScript(methodAddress.segment); +	byte *patchPtr = const_cast<byte *>(script->getBuf(methodAddress.offset)); +	memcpy(patchPtr, patchGameRestoreSaveSci21, sizeof(patchGameRestoreSaveSci21)); +	if (doRestore) +		patchPtr[2] = 0x78;	// push1 +	patchPtr[9] = id; +} +  void SciEngine::patchGameSaveRestore() {  	SegManager *segMan = _gamestate->_segMan;  	const Object *gameObject = segMan->getObject(_gameObjectAddress); @@ -478,23 +496,28 @@ void SciEngine::patchGameSaveRestore() {  			kernelIdRestore = kernelNr;  		if (kernelName == "SaveGame")  			kernelIdSave = kernelNr; +		if (kernelName == "Save") +			kernelIdSave = kernelIdRestore = kernelNr;  	} -	// TODO: This feature does not yet work with the SCI2.1 middle and newer -	// kernel functions (i.e. kSave) -	if (!kernelIdRestore || !kernelIdSave) -		return; -  	// 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") -			patchGameSaveRestoreCode(segMan, gameSuperObject->getFunction(methodNr), kernelIdRestore); +		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 -				patchGameSaveRestoreCode(segMan, gameSuperObject->getFunction(methodNr), kernelIdSave); +			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); +			}  		}  	} @@ -504,8 +527,12 @@ void SciEngine::patchGameSaveRestore() {  		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 -				patchGameSaveRestoreCode(segMan, gameObject->getFunction(methodNr), kernelIdSave); +			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;  		}  	} | 
