diff options
Diffstat (limited to 'engines/sci/engine/klists.cpp')
-rw-r--r-- | engines/sci/engine/klists.cpp | 68 |
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; |