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.cpp210
1 files changed, 146 insertions, 64 deletions
diff --git a/engines/sci/engine/klists.cpp b/engines/sci/engine/klists.cpp
index 0701883a9b..93e95099f5 100644
--- a/engines/sci/engine/klists.cpp
+++ b/engines/sci/engine/klists.cpp
@@ -34,10 +34,15 @@ static bool isSaneNodePointer(SegManager *segMan, reg_t addr) {
reg_t prev = addr;
do {
- Node *node = segMan->lookupNode(addr);
+ Node *node = segMan->lookupNode(addr, false);
if (!node) {
- error("isSaneNodePointer: Node at %04x:%04x wasn't found", PRINT_REG(addr));
+ if ((g_sci->getGameId() == GID_ICEMAN) && (g_sci->getEngineState()->currentRoomNumber() == 40)) {
+ // ICEMAN: when plotting course, unDrawLast is called by startPlot::changeState
+ // there is no previous entry so we get 0 in here
+ } else {
+ error("isSaneNodePointer: Node at %04x:%04x wasn't found", PRINT_REG(addr));
+ }
return false;
}
@@ -70,8 +75,8 @@ static void checkListPointer(SegManager *segMan, reg_t addr) {
// Empty list is fine
} else if (!list->first.isNull() && !list->last.isNull()) {
// Normal list
- Node *node_a = segMan->lookupNode(list->first);
- Node *node_z = segMan->lookupNode(list->last);
+ Node *node_a = segMan->lookupNode(list->first, false);
+ Node *node_z = segMan->lookupNode(list->last, false);
if (!node_a) {
error("checkListPointer (list %04x:%04x): missing first node", PRINT_REG(addr));
@@ -251,6 +256,19 @@ reg_t kNodeValue(EngineState *s, int argc, reg_t *argv) {
reg_t kAddToFront(EngineState *s, int argc, reg_t *argv) {
addToFront(s, argv[0], argv[1]);
+
+ if (argc == 3)
+ s->_segMan->lookupNode(argv[1])->key = argv[2];
+
+ return s->r_acc;
+}
+
+reg_t kAddToEnd(EngineState *s, int argc, reg_t *argv) {
+ addToEnd(s, argv[0], argv[1]);
+
+ if (argc == 3)
+ s->_segMan->lookupNode(argv[1])->key = argv[2];
+
return s->r_acc;
}
@@ -294,11 +312,6 @@ reg_t kAddAfter(EngineState *s, int argc, reg_t *argv) {
return s->r_acc;
}
-reg_t kAddToEnd(EngineState *s, int argc, reg_t *argv) {
- addToEnd(s, argv[0], argv[1]);
- return s->r_acc;
-}
-
reg_t kFindKey(EngineState *s, int argc, reg_t *argv) {
reg_t node_pos;
reg_t key = argv[1];
@@ -580,65 +593,134 @@ reg_t kListAllTrue(EngineState *s, int argc, reg_t *argv) {
return s->r_acc;
}
-// In SCI2.1, all the list functions were merged in one
reg_t kList(EngineState *s, int argc, reg_t *argv) {
+ if (!s)
+ return make_reg(0, getSciVersion());
+ error("not supposed to call this");
+}
+
+reg_t kAddBefore(EngineState *s, int argc, reg_t *argv) {
+ error("Unimplemented function kAddBefore called");
+ return s->r_acc;
+}
+
+reg_t kMoveToFront(EngineState *s, int argc, reg_t *argv) {
+ error("Unimplemented function kMoveToFront called");
+ return s->r_acc;
+}
+
+reg_t kMoveToEnd(EngineState *s, int argc, reg_t *argv) {
+ error("Unimplemented function kMoveToEnd called");
+ return s->r_acc;
+}
+
+reg_t kArray(EngineState *s, int argc, reg_t *argv) {
switch (argv[0].toUint16()) {
- case 0:
- return kNewList(s, argc - 1, argv + 1);
- case 1:
- return kDisposeList(s, argc - 1, argv + 1);
- case 2:
- return kNewNode(s, argc - 1, argv + 1);
- case 3:
- return kFirstNode(s, argc - 1, argv + 1);
- case 4:
- return kLastNode(s, argc - 1, argv + 1);
- case 5:
- return kEmptyList(s, argc - 1, argv + 1);
- case 6:
- return kNextNode(s, argc - 1, argv + 1);
- case 7:
- return kPrevNode(s, argc - 1, argv + 1);
- case 8:
- return kNodeValue(s, argc - 1, argv + 1);
- case 9:
- return kAddAfter(s, argc - 1, argv + 1);
- case 10:
- return kAddToFront(s, argc - 1, argv + 1);
- case 11:
- return kAddToEnd(s, argc - 1, argv + 1);
- case 12:
- error("kList: unimplemented subfunction kAddBefore");
- //return kAddBefore(s, argc - 1, argv + 1);
- return NULL_REG;
- case 13:
- error("kList: unimplemented subfunction kMoveToFront");
- //return kMoveToFront(s, argc - 1, argv + 1);
- return NULL_REG;
- case 14:
- error("kList: unimplemented subfunction kMoveToEnd");
- //return kMoveToEnd(s, argc - 1, argv + 1);
- return NULL_REG;
- case 15:
- return kFindKey(s, argc - 1, argv + 1);
- case 16:
- return kDeleteKey(s, argc - 1, argv + 1);
- case 17:
- return kListAt(s, argc - 1, argv + 1);
- case 18:
- return kListIndexOf(s, argc - 1, argv + 1);
- case 19:
- return kListEachElementDo(s, argc - 1, argv + 1);
- case 20:
- return kListFirstTrue(s, argc - 1, argv + 1);
- case 21:
- return kListAllTrue(s, argc - 1, argv + 1);
- case 22:
- return kSort(s, argc - 1, argv + 1);
+ case 0: { // New
+ reg_t arrayHandle;
+ SciArray<reg_t> *array = s->_segMan->allocateArray(&arrayHandle);
+ array->setType(argv[2].toUint16());
+ array->setSize(argv[1].toUint16());
+ return arrayHandle;
+ }
+ case 1: { // Size
+ SciArray<reg_t> *array = s->_segMan->lookupArray(argv[1]);
+ return make_reg(0, array->getSize());
+ }
+ case 2: { // At (return value at an index)
+ SciArray<reg_t> *array = s->_segMan->lookupArray(argv[1]);
+ return array->getValue(argv[2].toUint16());
+ }
+ case 3: { // Atput (put value at an index)
+ SciArray<reg_t> *array = s->_segMan->lookupArray(argv[1]);
+
+ uint32 index = argv[2].toUint16();
+ uint32 count = argc - 3;
+
+ if (index + count > 65535)
+ break;
+
+ if (array->getSize() < index + count)
+ array->setSize(index + count);
+
+ for (uint16 i = 0; i < count; i++)
+ array->setValue(i + index, argv[i + 3]);
+
+ return argv[1]; // We also have to return the handle
+ }
+ case 4: // Free
+ // Freeing of arrays is handled by the garbage collector
+ return s->r_acc;
+ case 5: { // Fill
+ SciArray<reg_t> *array = s->_segMan->lookupArray(argv[1]);
+ uint16 index = argv[2].toUint16();
+
+ // A count of -1 means fill the rest of the array
+ uint16 count = argv[3].toSint16() == -1 ? array->getSize() - index : argv[3].toUint16();
+ uint16 arraySize = array->getSize();
+
+ if (arraySize < index + count)
+ array->setSize(index + count);
+
+ for (uint16 i = 0; i < count; i++)
+ array->setValue(i + index, argv[4]);
+
+ return argv[1];
+ }
+ case 6: { // Cpy
+ if (s->_segMan->getSegmentObj(argv[1].segment)->getType() != SEG_TYPE_ARRAY ||
+ s->_segMan->getSegmentObj(argv[3].segment)->getType() != SEG_TYPE_ARRAY) {
+ // Happens in the RAMA demo
+ warning("kArray(Cpy): Request to copy a segment which isn't an array, ignoring");
+ return NULL_REG;
+ }
+
+ SciArray<reg_t> *array1 = s->_segMan->lookupArray(argv[1]);
+ SciArray<reg_t> *array2 = s->_segMan->lookupArray(argv[3]);
+ uint32 index1 = argv[2].toUint16();
+ uint32 index2 = argv[4].toUint16();
+
+ // The original engine ignores bad copies too
+ if (index2 > array2->getSize())
+ break;
+
+ // A count of -1 means fill the rest of the array
+ uint32 count = argv[5].toSint16() == -1 ? array2->getSize() - index2 : argv[5].toUint16();
+
+ if (array1->getSize() < index1 + count)
+ array1->setSize(index1 + count);
+
+ for (uint16 i = 0; i < count; i++)
+ array1->setValue(i + index1, array2->getValue(i + index2));
+
+ return argv[1];
+ }
+ case 7: // Cmp
+ // Not implemented in SSCI
+ return s->r_acc;
+ case 8: { // Dup
+ SciArray<reg_t> *array = s->_segMan->lookupArray(argv[1]);
+ reg_t arrayHandle;
+ SciArray<reg_t> *dupArray = s->_segMan->allocateArray(&arrayHandle);
+
+ dupArray->setType(array->getType());
+ dupArray->setSize(array->getSize());
+
+ for (uint32 i = 0; i < array->getSize(); i++)
+ dupArray->setValue(i, array->getValue(i));
+
+ return arrayHandle;
+ }
+ case 9: // Getdata
+ if (!s->_segMan->isHeapObject(argv[1]))
+ return argv[1];
+
+ return readSelector(s->_segMan, argv[1], SELECTOR(data));
default:
- error("kList: Unhandled case %d", argv[0].toUint16());
- return NULL_REG;
+ error("Unknown kArray subop %d", argv[0].toUint16());
}
+
+ return NULL_REG;
}
#endif