diff options
-rw-r--r-- | engines/sci/engine/kernel.cpp | 4 | ||||
-rw-r--r-- | engines/sci/engine/kernel.h | 3 | ||||
-rw-r--r-- | engines/sci/engine/kernel32.cpp | 51 |
3 files changed, 56 insertions, 2 deletions
diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index d6c92c8e1a..6c635ae509 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -351,7 +351,9 @@ SciKernelFunction kfunct_mappers[] = { DEFUN("UpdatePlane", kUpdatePlane, "o"), DEFUN("RepaintPlane", kRepaintPlane, "o"), DEFUN("FrameOut", kFrameOut, ""), - DEFUN("ListEachElementDo", kListEachElementDo, ".*"), + DEFUN("ListEachElementDo", kListEachElementDo, "li.*"), + DEFUN("ListFirstTrue", kListFirstTrue, "li.*"), + //DEFUN("ListAllTrue", kListAllTrue, "li.*"), DEFUN("ListIndexOf", kListIndexOf, "lo"), DEFUN("OnMe", kOnMe, "iio.*"), diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index b7bd52eac2..b7a588dfd6 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -408,6 +408,9 @@ reg_t kRepaintPlane(EngineState *s, int argc, reg_t *argv); reg_t kFrameOut(EngineState *s, int argc, reg_t *argv); reg_t kListIndexOf(EngineState *s, int argc, reg_t *argv); reg_t kListEachElementDo(EngineState *s, int argc, reg_t *argv); +reg_t kListFirstTrue(EngineState *s, int argc, reg_t *argv); +// TODO: What is this supposed to return? +//reg_t kListAllTrue(EngineState *s, int argc, reg_t *argv); reg_t kOnMe(EngineState *s, int argc, reg_t *argv); // SCI2.1 Kernel Functions diff --git a/engines/sci/engine/kernel32.cpp b/engines/sci/engine/kernel32.cpp index 2598c70bb2..db6a91335b 100644 --- a/engines/sci/engine/kernel32.cpp +++ b/engines/sci/engine/kernel32.cpp @@ -764,7 +764,7 @@ reg_t kListEachElementDo(EngineState *s, int argc, reg_t *argv) { // First, check if the target selector is a variable if (lookup_selector(s->_segMan, curObject, slc, &address, NULL) == kSelectorVariable) { - // This can only happen with 3 params (list, target object, variable) + // This can only happen with 3 params (list, target selector, variable) if (argc != 3) { warning("kListEachElementDo: Attempted to modify a variable selector with %d params", argc); } else { @@ -796,6 +796,55 @@ reg_t kListEachElementDo(EngineState *s, int argc, reg_t *argv) { return s->r_acc; } +reg_t kListFirstTrue(EngineState *s, int argc, reg_t *argv) { + List *list = s->_segMan->lookupList(argv[0]); + + reg_t curAddress = list->first; + Node *curNode = s->_segMan->lookupNode(curAddress); + reg_t curObject; + Selector slc = argv[1].toUint16(); + + ObjVarRef address; + + s->r_acc = NULL_REG; // reset the accumulator + + while (curNode) { + curObject = curNode->value; + + // First, check if the target selector is a variable + if (lookup_selector(s->_segMan, curObject, slc, &address, NULL) == kSelectorVariable) { + // Can this happen with variable selectors? + warning("kListFirstTrue: Attempted to access a variable selector"); + } else { + // FIXME: Yes, this is an ugly hack... + if (argc == 2) { + invoke_selector(s, curObject, slc, kContinueOnInvalidSelector, argv, argc, 0); + } else if (argc == 3) { + invoke_selector(s, curObject, slc, kContinueOnInvalidSelector, argv, argc, 1, argv[2]); + } else if (argc == 4) { + invoke_selector(s, curObject, slc, kContinueOnInvalidSelector, argv, argc, 2, argv[2], argv[3]); + } else if (argc == 5) { + invoke_selector(s, curObject, slc, kContinueOnInvalidSelector, argv, argc, 3, argv[2], argv[3], argv[4]); + } else { + warning("kListFirstTrue: called with %d params", argc); + } + + // Check if the result is true + if (s->r_acc != NULL_REG) + return curObject; + } + + // Lookup node again, since the nodetable it was in may have been reallocated + curNode = s->_segMan->lookupNode(curAddress); + + curAddress = curNode->succ; + curNode = s->_segMan->lookupNode(curAddress); + } + + // No selector returned true + return NULL_REG; +} + reg_t kOnMe(EngineState *s, int argc, reg_t *argv) { // Tests if the cursor is on the passed object |