diff options
| author | Colin Snover | 2016-11-06 15:05:58 -0600 | 
|---|---|---|
| committer | Colin Snover | 2016-11-20 12:31:44 -0600 | 
| commit | 22c2f39c0026a1ba00d7f28a93a0b4f9baa5fbfc (patch) | |
| tree | a326c75cb7a08b84d541260a54f914cd2fc7610a | |
| parent | 4814682d5ff72f0a986e878290394e3517b69da4 (diff) | |
| download | scummvm-rg350-22c2f39c0026a1ba00d7f28a93a0b4f9baa5fbfc.tar.gz scummvm-rg350-22c2f39c0026a1ba00d7f28a93a0b4f9baa5fbfc.tar.bz2 scummvm-rg350-22c2f39c0026a1ba00d7f28a93a0b4f9baa5fbfc.zip  | |
SCI32: Add recursion code to kListFirstTrue and kListAllTrue
This change ensures that these kernel calls operate in the same
manner that they did in SSCI.
| -rw-r--r-- | engines/sci/engine/klists.cpp | 57 | 
1 files changed, 41 insertions, 16 deletions
diff --git a/engines/sci/engine/klists.cpp b/engines/sci/engine/klists.cpp index 5cd9c3623d..16ce2363d7 100644 --- a/engines/sci/engine/klists.cpp +++ b/engines/sci/engine/klists.cpp @@ -547,7 +547,6 @@ reg_t kListEachElementDo(EngineState *s, int argc, reg_t *argv) {  	List *list = s->_segMan->lookupList(argv[0]);  	Node *curNode = s->_segMan->lookupNode(list->first); -	reg_t curObject;  	Selector slc = argv[1].toUint16();  	ObjVarRef address; @@ -564,7 +563,7 @@ reg_t kListEachElementDo(EngineState *s, int argc, reg_t *argv) {  		// needs to be able to adjust the location of the next node, which is  		// why it is stored on the list instead of on the stack  		list->nextNodes[list->numRecursions] = curNode->succ; -		curObject = curNode->value; +		reg_t curObject = curNode->value;  		// First, check if the target selector is a variable  		if (lookupSelector(s->_segMan, curObject, slc, &address, NULL) == kSelectorVariable) { @@ -595,37 +594,51 @@ reg_t kListFirstTrue(EngineState *s, int argc, reg_t *argv) {  	List *list = s->_segMan->lookupList(argv[0]);  	Node *curNode = s->_segMan->lookupNode(list->first); -	reg_t curObject;  	Selector slc = argv[1].toUint16();  	ObjVarRef address; -	s->r_acc = NULL_REG;	// reset the accumulator +	s->r_acc = NULL_REG; + +	++list->numRecursions; + +	if (list->numRecursions >= ARRAYSIZE(list->nextNodes)) { +		error("Too much recursion in kListFirstTrue"); +	}  	while (curNode) { -		reg_t nextNode = curNode->succ; -		curObject = curNode->value; +		// We get the next node here as the current node might be deleted by the +		// invoke. In the case that the next node is also deleted, kDeleteKey +		// needs to be able to adjust the location of the next node, which is +		// why it is stored on the list instead of on the stack +		list->nextNodes[list->numRecursions] = curNode->succ; +		reg_t curObject = curNode->value;  		// First, check if the target selector is a variable  		if (lookupSelector(s->_segMan, curObject, slc, &address, NULL) == kSelectorVariable) {  			// If it's a variable selector, check its value.  			// Example: script 64893 in Torin, MenuHandler::isHilited checks  			// all children for variable selector 0x03ba (bHilited). -			if (!readSelector(s->_segMan, curObject, slc).isNull()) -				return curObject; +			if (!readSelector(s->_segMan, curObject, slc).isNull()) { +				s->r_acc = curObject; +				break; +			}  		} else {  			invokeSelector(s, curObject, slc, argc, argv, argc - 2, argv + 2);  			// Check if the result is true -			if (!s->r_acc.isNull()) -				return curObject; +			if (!s->r_acc.isNull()) { +				s->r_acc = curObject; +				break; +			}  		} -		curNode = s->_segMan->lookupNode(nextNode); +		curNode = s->_segMan->lookupNode(list->nextNodes[list->numRecursions]);  	} -	// No selector returned true -	return NULL_REG; +	--list->numRecursions; + +	return s->r_acc;  }  reg_t kListAllTrue(EngineState *s, int argc, reg_t *argv) { @@ -637,10 +650,20 @@ reg_t kListAllTrue(EngineState *s, int argc, reg_t *argv) {  	ObjVarRef address; -	s->r_acc = make_reg(0, 1);	// reset the accumulator +	s->r_acc = TRUE_REG; + +	++list->numRecursions; + +	if (list->numRecursions >= ARRAYSIZE(list->nextNodes)) { +		error("Too much recursion in kListAllTrue"); +	}  	while (curNode) { -		reg_t nextNode = curNode->succ; +		// We get the next node here as the current node might be deleted by the +		// invoke. In the case that the next node is also deleted, kDeleteKey +		// needs to be able to adjust the location of the next node, which is +		// why it is stored on the list instead of on the stack +		list->nextNodes[list->numRecursions] = curNode->succ;  		curObject = curNode->value;  		// First, check if the target selector is a variable @@ -655,9 +678,11 @@ reg_t kListAllTrue(EngineState *s, int argc, reg_t *argv) {  		if (s->r_acc.isNull())  			break; -		curNode = s->_segMan->lookupNode(nextNode); +		curNode = s->_segMan->lookupNode(list->nextNodes[list->numRecursions]);  	} +	--list->numRecursions; +  	return s->r_acc;  }  | 
