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.cpp68
1 files changed, 60 insertions, 8 deletions
diff --git a/engines/sci/engine/klists.cpp b/engines/sci/engine/klists.cpp
index 2188087b8c..329e5cd531 100644
--- a/engines/sci/engine/klists.cpp
+++ b/engines/sci/engine/klists.cpp
@@ -23,6 +23,7 @@
*
*/
+#include "sci/engine/features.h"
#include "sci/engine/state.h"
#include "sci/engine/selector.h"
#include "sci/engine/kernel.h"
@@ -618,7 +619,29 @@ reg_t kMoveToEnd(EngineState *s, int argc, reg_t *argv) {
}
reg_t kArray(EngineState *s, int argc, reg_t *argv) {
- switch (argv[0].toUint16()) {
+ uint16 op = argv[0].toUint16();
+
+ // Use kString when accessing strings
+ // This is possible, as strings inherit from arrays
+ // and in this case (type 3) arrays are of type char *.
+ // kString is almost exactly the same as kArray, so
+ // this call is possible
+ // TODO: we need to either merge SCI2 strings and
+ // arrays together, and in the future merge them with
+ // the SCI1 strings and arrays in the segment manager
+ if (op == 0) {
+ // New, check if the target type is 3 (string)
+ if (argv[2].toUint16() == 3)
+ return kString(s, argc, argv);
+ } else {
+ if (s->_segMan->getSegmentType(argv[1].segment) == SEG_TYPE_STRING ||
+ s->_segMan->getSegmentType(argv[1].segment) == SEG_TYPE_SYS_STRINGS ||
+ s->_segMan->getSegmentType(argv[1].segment) == SEG_TYPE_SCRIPT) {
+ return kString(s, argc, argv);
+ }
+ }
+
+ switch (op) {
case 0: { // New
reg_t arrayHandle;
SciArray<reg_t> *array = s->_segMan->allocateArray(&arrayHandle);
@@ -671,13 +694,10 @@ reg_t kArray(EngineState *s, int argc, reg_t *argv) {
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");
+ if (argv[1].isNull() || argv[3].isNull()) {
+ warning("kArray(Cpy): Request to copy from or to a null pointer");
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();
@@ -700,11 +720,43 @@ reg_t kArray(EngineState *s, int argc, reg_t *argv) {
}
case 7: // Cmp
// Not implemented in SSCI
+ warning("kArray(Cmp) called");
return s->r_acc;
case 8: { // Dup
- SciArray<reg_t> *array = s->_segMan->lookupArray(argv[1]);
+ if (argv[1].isNull()) {
+ warning("kArray(Dup): Request to duplicate a null pointer");
+#if 0
+ // Allocate an array anyway
+ reg_t arrayHandle;
+ SciArray<reg_t> *dupArray = s->_segMan->allocateArray(&arrayHandle);
+ dupArray->setType(3);
+ dupArray->setSize(0);
+ return arrayHandle;
+#endif
+ return NULL_REG;
+ }
+ SegmentType sourceType = s->_segMan->getSegmentObj(argv[1].segment)->getType();
+ if (sourceType == SEG_TYPE_SCRIPT) {
+ // A technique used in later SCI2.1 and SCI3 games: the contents of a script
+ // are loaded in an array (well, actually a string).
+ Script *scr = s->_segMan->getScript(argv[1].segment);
+ reg_t stringHandle;
+
+ SciString *dupString = s->_segMan->allocateString(&stringHandle);
+ dupString->setSize(scr->getBufSize());
+ dupString->fromString(Common::String((const char *)scr->getBuf()));
+
+ return stringHandle;
+ } else if (sourceType != SEG_TYPE_ARRAY && sourceType != SEG_TYPE_SCRIPT) {
+ error("kArray(Dup): Request to duplicate a segment which isn't an array or a script");
+ }
+
reg_t arrayHandle;
SciArray<reg_t> *dupArray = s->_segMan->allocateArray(&arrayHandle);
+ // This must occur after allocateArray, as inserting a new object
+ // in the heap object list might invalidate this pointer. Also refer
+ // to the same issue in kClone()
+ SciArray<reg_t> *array = s->_segMan->lookupArray(argv[1]);
dupArray->setType(array->getType());
dupArray->setSize(array->getSize());
@@ -720,7 +772,7 @@ reg_t kArray(EngineState *s, int argc, reg_t *argv) {
return readSelector(s->_segMan, argv[1], SELECTOR(data));
default:
- error("Unknown kArray subop %d", argv[0].toUint16());
+ error("Unknown kArray subop %d", op);
}
return NULL_REG;