diff options
| -rw-r--r-- | engines/sci/engine/script.cpp | 30 | ||||
| -rw-r--r-- | engines/sci/engine/script.h | 6 | ||||
| -rw-r--r-- | engines/sci/engine/vm.cpp | 23 | 
3 files changed, 28 insertions, 31 deletions
diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index 897ceccad3..80aaedfece 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -385,7 +385,7 @@ void Script::setLockers(int lockers) {  	_lockers = lockers;  } -uint16 Script::validateExportFunc(int pubfunct, bool relocate) { +uint16 Script::validateExportFunc(int pubfunct, bool relocateSci3) {  	bool exportsAreWide = (g_sci->_features->detectLofsType() == SCI_VERSION_1_MIDDLE);  	if (_numExports <= pubfunct) { @@ -398,15 +398,15 @@ uint16 Script::validateExportFunc(int pubfunct, bool relocate) {  	uint16 offset; -	if (getSciVersion() != SCI_VERSION_3 || !relocate) { +	if (getSciVersion() != SCI_VERSION_3) {  		offset = READ_SCI11ENDIAN_UINT16(_exportTable + pubfunct);  	} else { -		offset = relocateOffsetSci3(pubfunct * 2 + 22); +		if (!relocateSci3) +			offset = READ_SCI11ENDIAN_UINT16(_exportTable + pubfunct) + getCodeBlockOffsetSci3(); +		else +			offset = relocateOffsetSci3(pubfunct * 2 + 22);  	} -	if (offset >= _bufSize) -		error("Invalid export function pointer"); -  	// Check if the offset found points to a second export table (e.g. script 912  	// in Camelot and script 306 in KQ4). Such offsets are usually small (i.e. < 10),  	// thus easily distinguished from actual code offsets. @@ -419,11 +419,23 @@ uint16 Script::validateExportFunc(int pubfunct, bool relocate) {  		if (secondExportTable) {  			secondExportTable += 3;	// skip header plus 2 bytes (secondExportTable is a uint16 pointer)  			offset = READ_SCI11ENDIAN_UINT16(secondExportTable + pubfunct); -			if (offset >= _bufSize) -				error("Invalid export function pointer");  		}  	} +	if (!offset) { +#ifdef ENABLE_SCI32 +		// WORKAROUNDS for invalid (empty) exports +		if (g_sci->getGameId() == GID_TORIN && _nr == 64036) { +		} else if (g_sci->getGameId() == GID_RAMA && _nr == 64908) { +		} else +#endif +			error("Request for invalid exported function 0x%x of script %d", pubfunct, _nr); +		return NULL; +	} + +	if (offset >= _bufSize) +		error("Invalid export function pointer"); +  	return offset;  } @@ -551,7 +563,7 @@ void Script::initializeClasses(SegManager *segMan) {  		if (getSciVersion() <= SCI_VERSION_1_LATE && !marker)  			break; -		if (getSciVersion() >= SCI_VERSION_1_1 && marker != 0x1234) +		if (getSciVersion() >= SCI_VERSION_1_1 && marker != SCRIPT_OBJECT_MAGIC_NUMBER)  			break;  		if (getSciVersion() <= SCI_VERSION_1_LATE) { diff --git a/engines/sci/engine/script.h b/engines/sci/engine/script.h index 0c99f13235..9747f072c5 100644 --- a/engines/sci/engine/script.h +++ b/engines/sci/engine/script.h @@ -197,11 +197,11 @@ public:  	 * Validate whether the specified public function is exported by  	 * the script in the specified segment.  	 * @param pubfunct		Index of the function to validate -	 * @param relocate              Decide whether to relocate this public function or not +	 * @param relocateSci3  Decide whether to relocate this SCI3 public function or not  	 * @return				NULL if the public function is invalid, its  	 * 						offset into the script's segment otherwise  	 */ -	uint16 validateExportFunc(int pubfunct, bool relocate); +	uint16 validateExportFunc(int pubfunct, bool relocateSci3);  	/**  	 * Marks the script as deleted. @@ -249,7 +249,7 @@ public:  	/**  	 * Gets an offset to the beginning of the code block in a SCI3 script  	 */ -	int getCodeBlockOffset() { return READ_SCI11ENDIAN_UINT32(_buf); } +	int getCodeBlockOffsetSci3() { return READ_SCI11ENDIAN_UINT32(_buf); }  private:  	/** diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 89f59eaa14..a42606a6a6 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -225,30 +225,15 @@ ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackP  		scr = s->_segMan->getScript(seg);  	} -	int temp = scr->validateExportFunc(pubfunct, false); - -	if (getSciVersion() == SCI_VERSION_3) -		temp += scr->getCodeBlockOffset(); - -	if (!temp) { -#ifdef ENABLE_SCI32 -		if (g_sci->getGameId() == GID_TORIN && script == 64036) { -			// Script 64036 in Torin's Passage is empty and contains an invalid -			// (empty) export -		} else if (g_sci->getGameId() == GID_RAMA && script == 64908) { -			// Script 64908 in the demo of RAMA contains an invalid (empty) -			// export -		} else -#endif -			error("Request for invalid exported function 0x%x of script %d", pubfunct, script); +	uint32 exportAddr = scr->validateExportFunc(pubfunct, false); +	if (!exportAddr)  		return NULL; -	} - +	  	// Check if a breakpoint is set on this method  	g_sci->checkExportBreakpoint(script, pubfunct);  	ExecStack xstack(calling_obj, calling_obj, sp, argc, argp, -						seg, make_reg(seg, temp), -1, pubfunct, -1, +						seg, make_reg(seg, exportAddr), -1, pubfunct, -1,  						s->_executionStack.size() - 1, EXEC_STACK_TYPE_CALL);  	s->_executionStack.push_back(xstack);  	return &(s->_executionStack.back());  | 
