diff options
| -rw-r--r-- | engines/sci/engine/vm.cpp | 72 | ||||
| -rw-r--r-- | engines/sci/engine/vm.h | 1 | 
2 files changed, 47 insertions, 26 deletions
| diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 70c4f3d996..d1fcbbd1f9 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -72,7 +72,7 @@ const reg_t SIGNAL_REG = {0, SIGNAL_OFFSET};   * @return 					A pointer to the new exec stack TOS entry   */  static ExecStack *add_exec_stack_entry(Common::List<ExecStack> &execStack, reg_t pc, StackPtr sp, -		reg_t objp, int argc, StackPtr argp, Selector selector, int exportId, +		reg_t objp, int argc, StackPtr argp, Selector selector, int exportId, int localCallOffset,  		reg_t sendp, int origin, SegmentId local_segment); @@ -188,19 +188,22 @@ struct UninitializedReadWorkaround {  	int scriptNr;  	const char *objectName;  	const char *methodName; +	int localCallOffset;  	int index;  	uint16 newValue;  };  static const UninitializedReadWorkaround uninitializedReadWorkarounds[] = { -	{ GID_LAURABOW2,      24,              "gcWin", "open",         5, 0xf }, // is used as priority for game menu -	{ GID_FREDDYPHARKAS,  24,              "gcWin", "open",         5, 0xf }, // is used as priority for game menu -	{ GID_FREDDYPHARKAS,  31,            "quitWin", "open",         5, 0xf }, // is used as priority for game menu -	{ GID_LSL1,          720,              "rm720", "init",         0,   0 }, // age check room -	{ GID_ISLANDBRAIN,   140,              "piece", "init",         3,   1 }, // some initialization variable. bnt is done on it, and it should be non-0 -	{ GID_SQ1,           703,                   "", "export 1",     0,   0 }, // sub that's called from several objects -	{ GID_SQ4,           928,           "Narrator", "startText", 1000,   1 }, // sq4cd: method returns this to the caller -	{ (SciGameId)0,       -1,                 NULL, NULL,           0,   0 } +	{ GID_LAURABOW2,      24,              "gcWin", "open",           -1,    5, 0xf }, // is used as priority for game menu +	{ GID_FREDDYPHARKAS,  24,              "gcWin", "open",           -1,    5, 0xf }, // is used as priority for game menu +	{ GID_FREDDYPHARKAS,  31,            "quitWin", "open",           -1,    5, 0xf }, // is used as priority for game menu +	{ GID_LSL1,          720,              "rm720", "init",           -1,    0,   0 }, // age check room +	{ GID_ISLANDBRAIN,   140,              "piece", "init",           -1,    3,   1 }, // some initialization variable. bnt is done on it, and it should be non-0 +	{ GID_SQ1,           703,                   "", "export 1",       -1,    0,   0 }, // sub that's called from several objects +	{ GID_SQ1,           703,         "firePulsar", "changeState", 0x18a,    0,   0 }, // export 1, but called locally +	{ GID_SQ1,           703,                   "", "export 1",       -1,    0,   0 }, // export 1 sub, but called locally +	{ GID_SQ4,           928,           "Narrator", "startText",      -1, 1000,   1 }, // sq4cd: method returns this to the caller +	{ (SciGameId)0,       -1,                 NULL, NULL,             -1,    0,   0 }  };  static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, int index, int line, reg_t default_value) { @@ -209,20 +212,34 @@ static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, i  			// Uninitialized read on a temp  			//  We need to find correct replacements for each situation manually  			EngineState *state = g_sci->getEngineState(); -			ExecStack *call = state->xs; -			Script *local_script = state->_segMan->getScriptIfLoaded(call->local_segment); +			ExecStack *lastCall = state->xs; +			Script *local_script = state->_segMan->getScriptIfLoaded(lastCall->local_segment);  			int curScriptNr = local_script->_nr; -			Common::String curObjectName = state->_segMan->getObjectName(call->sendp); +			if (lastCall->localCallOffset != -1) { +				// if lastcall was actually a local call search back for a real call +				Common::List<ExecStack>::iterator callIterator = state->_executionStack.end();
 +				while (callIterator != state->_executionStack.begin()) {
 +					callIterator--;
 +					ExecStack loopCall = *callIterator;
 +					if ((loopCall.selector != -1) || (loopCall.exportId != -1)) {
 +						lastCall->selector = loopCall.selector;
 +						lastCall->exportId = loopCall.exportId;
 +						break;
 +					}
 +				}
 +			}
 + +			Common::String curObjectName = state->_segMan->getObjectName(lastCall->sendp);  			Common::String curMethodName;  			const SciGameId gameId = g_sci->getGameId(); -			if (call->type == EXEC_STACK_TYPE_CALL) { -				if (call->selector != -1) { -					curMethodName = g_sci->getKernel()->getSelectorName(call->selector); -				} else if (call->exportId != -1) { +			if (lastCall->type == EXEC_STACK_TYPE_CALL) { +				if (lastCall->selector != -1) { +					curMethodName = g_sci->getKernel()->getSelectorName(lastCall->selector); +				} else if (lastCall->exportId != -1) {  					curObjectName = ""; -					curMethodName = curMethodName.printf("export %d", call->exportId); +					curMethodName = curMethodName.printf("export %d", lastCall->exportId);  				}  			} @@ -230,14 +247,14 @@ static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, i  			const UninitializedReadWorkaround *workaround = uninitializedReadWorkarounds;  			while (workaround->objectName) {  				if (workaround->gameId == gameId && workaround->scriptNr == curScriptNr && workaround->objectName == curObjectName -						&& workaround->methodName == curMethodName && workaround->index == index) { +						&& workaround->methodName == curMethodName && workaround->localCallOffset == lastCall->localCallOffset && workaround->index == index) {  					// Workaround found  					r[index] = make_reg(0, workaround->newValue);  					return r[index];  				}  				workaround++;  			} -			error("Uninitialized read for temp %d from method %s::%s (script %d)", index, curObjectName.c_str(), curMethodName.c_str(), curScriptNr); +			error("Uninitialized read for temp %d from method %s::%s (script %d, localCall %lx)", index, curObjectName.c_str(), curMethodName.c_str(), curScriptNr, lastCall->localCallOffset);  		}  		return r[index];  	} else @@ -345,7 +362,7 @@ ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackP  		}  	} -	return add_exec_stack_entry(s->_executionStack, make_reg(seg, temp), sp, calling_obj, argc, argp, -1, pubfunct, calling_obj, s->_executionStack.size()-1, seg); +	return add_exec_stack_entry(s->_executionStack, make_reg(seg, temp), sp, calling_obj, argc, argp, -1, pubfunct, -1, calling_obj, s->_executionStack.size()-1, seg);  } @@ -543,7 +560,7 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt  		else  			add_exec_stack_entry(s->_executionStack, call.address.func, call.sp, work_obj,  			                         call.argc, call.argp, -			                         call.selector, -1, send_obj, origin, SCI_XS_CALLEE_LOCALS); +			                         call.selector, -1, -1, send_obj, origin, SCI_XS_CALLEE_LOCALS);  	}  	_exec_varselectors(s); @@ -552,7 +569,7 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt  }  static ExecStack *add_exec_stack_varselector(Common::List<ExecStack> &execStack, reg_t objp, int argc, StackPtr argp, Selector selector, const ObjVarRef& address, int origin) { -	ExecStack *xstack = add_exec_stack_entry(execStack, NULL_REG, 0, objp, argc, argp, selector, -1, objp, origin, SCI_XS_CALLEE_LOCALS); +	ExecStack *xstack = add_exec_stack_entry(execStack, NULL_REG, 0, objp, argc, argp, selector, -1, -1, objp, origin, SCI_XS_CALLEE_LOCALS);  	// Store selector address in sp  	xstack->addr.varp = address; @@ -562,7 +579,7 @@ static ExecStack *add_exec_stack_varselector(Common::List<ExecStack> &execStack,  }  static ExecStack *add_exec_stack_entry(Common::List<ExecStack> &execStack, reg_t pc, StackPtr sp, reg_t objp, int argc, -								   StackPtr argp, Selector selector, int exportId, reg_t sendp, int origin, SegmentId _localsSegment) { +								   StackPtr argp, Selector selector, int exportId, int localCallOffset, reg_t sendp, int origin, SegmentId _localsSegment) {  	// Returns new TOS element for the execution stack  	// _localsSegment may be -1 if derived from the called object @@ -588,6 +605,7 @@ static ExecStack *add_exec_stack_entry(Common::List<ExecStack> &execStack, reg_t  	// Additional debug information  	xstack.selector = selector;  	xstack.exportId = exportId; +	xstack.localCallOffset = localCallOffset;  	xstack.origin = origin;  	xstack.type = EXEC_STACK_TYPE_CALL; // Normal call @@ -642,7 +660,7 @@ static void callKernelFunc(EngineState *s, int kernelFuncNum, int argc) {  		// This is useful in debugger backtraces if this  		// kernel function calls a script itself.  		ExecStack *xstack; -		xstack = add_exec_stack_entry(s->_executionStack, NULL_REG, NULL, NULL_REG, argc, argv - 1, 0, -1, NULL_REG, +		xstack = add_exec_stack_entry(s->_executionStack, NULL_REG, NULL, NULL_REG, argc, argv - 1, 0, -1, -1, NULL_REG,  				  s->_executionStack.size()-1, SCI_XS_CALLEE_LOCALS);  		xstack->selector = kernelFuncNum;  		xstack->type = EXEC_STACK_TYPE_KERNEL; @@ -1199,11 +1217,13 @@ void run_vm(EngineState *s, bool restoring) {  			StackPtr call_base = s->xs->sp - argc;  			s->xs->sp[1].offset += s->restAdjust; +			uint16 localCallOffset = s->xs->addr.pc.offset + opparams[0]; +  			xs_new = add_exec_stack_entry(s->_executionStack, make_reg(s->xs->addr.pc.segment, -											s->xs->addr.pc.offset + opparams[0]), +											localCallOffset),  											s->xs->sp, s->xs->objp,  											(validate_arithmetic(*call_base)) + s->restAdjust, -											call_base, NULL_SELECTOR, -1, s->xs->objp, +											call_base, NULL_SELECTOR, -1, localCallOffset, s->xs->objp,  											s->_executionStack.size()-1, s->xs->local_segment);  			s->restAdjust = 0; // Used up the &rest adjustment  			s->xs->sp = call_base; diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h index ed3d5483b6..d747ddd113 100644 --- a/engines/sci/engine/vm.h +++ b/engines/sci/engine/vm.h @@ -104,6 +104,7 @@ struct ExecStack {  	Selector selector;      // The selector which was used to call or -1 if not applicable  	int exportId;           // The exportId which was called or -1 if not applicable +	int localCallOffset;    // Local call offset or -1 if not applicable  	int origin;             // The stack frame position the call was made from, or -1 if it was the initial call  	ExecStackType type; | 
