aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/engine/klists.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sci/engine/klists.cpp')
-rw-r--r--engines/sci/engine/klists.cpp198
1 files changed, 198 insertions, 0 deletions
diff --git a/engines/sci/engine/klists.cpp b/engines/sci/engine/klists.cpp
index 523f8ed3c6..f19cc88dac 100644
--- a/engines/sci/engine/klists.cpp
+++ b/engines/sci/engine/klists.cpp
@@ -436,4 +436,202 @@ reg_t kSort(EngineState *s, int argc, reg_t *argv) {
return s->r_acc;
}
+// SCI32 list functions
+#ifdef ENABLE_SCI32
+
+reg_t kListAt(EngineState *s, int argc, reg_t *argv) {
+ if (argc != 2) {
+ warning("kListAt called with %d parameters", argc);
+ return NULL_REG;
+ }
+
+ List *list = s->_segMan->lookupList(argv[0]);
+ reg_t curAddress = list->first;
+ Node *curNode = s->_segMan->lookupNode(curAddress);
+ reg_t curObject = curNode->value;
+ int16 listIndex = argv[1].toUint16();
+ int curIndex = 0;
+
+ while (curIndex != listIndex) {
+ if (curNode->succ.isNull()) { // end of the list?
+ return NULL_REG;
+ }
+
+ curAddress = curNode->succ;
+ curNode = s->_segMan->lookupNode(curAddress);
+ curObject = curNode->value;
+
+ curIndex++;
+ }
+
+ return curObject;
+}
+
+reg_t kListIndexOf(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;
+ uint16 curIndex = 0;
+
+ while (curNode) {
+ curObject = curNode->value;
+ if (curObject == argv[1])
+ return make_reg(0, curIndex);
+
+ curAddress = curNode->succ;
+ curNode = s->_segMan->lookupNode(curAddress);
+ curIndex++;
+ }
+
+ return SIGNAL_REG;
+}
+
+reg_t kListEachElementDo(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;
+
+ while (curNode) {
+ curObject = curNode->value;
+
+ // 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 selector, variable)
+ if (argc != 3) {
+ warning("kListEachElementDo: Attempted to modify a variable selector with %d params", argc);
+ } else {
+ write_selector(s->_segMan, curObject, slc, argv[2]);
+ }
+ } 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("kListEachElementDo: called with %d params", argc);
+ }
+ }
+
+ // 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);
+ }
+
+
+ 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.isNull())
+ 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 kListAllTrue(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 = make_reg(0, 1); // 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("kListAllTrue: 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("kListAllTrue: called with %d params", argc);
+ }
+
+ // Check if the result isn't true
+ if (s->r_acc.isNull())
+ break;
+ }
+
+ // 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);
+ }
+
+ return s->r_acc;
+}
+
+#endif
+
} // End of namespace Sci