aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/engine/kscripts.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sci/engine/kscripts.cpp')
-rw-r--r--engines/sci/engine/kscripts.cpp13
1 files changed, 13 insertions, 0 deletions
diff --git a/engines/sci/engine/kscripts.cpp b/engines/sci/engine/kscripts.cpp
index d99302b3d4..7cc677cd3a 100644
--- a/engines/sci/engine/kscripts.cpp
+++ b/engines/sci/engine/kscripts.cpp
@@ -145,6 +145,7 @@ reg_t kResCheck(EngineState *s, int argc, reg_t *argv) {
reg_t kClone(EngineState *s, int argc, reg_t *argv) {
reg_t parent_addr = argv[0];
const Object *parent_obj = s->_segMan->getObject(parent_addr);
+ const bool parentIsClone = parent_obj->isClone();
reg_t clone_addr;
Clone *clone_obj; // same as Object*
@@ -162,6 +163,18 @@ reg_t kClone(EngineState *s, int argc, reg_t *argv) {
return NULL_REG;
}
+ // In case the parent object is a clone itself we need to refresh our
+ // pointer to it here. This is because calling allocateClone might
+ // invalidate all pointers, references and iterators to data in the clones
+ // segment.
+ //
+ // The reason why it might invalidate those is, that the segement code
+ // (Table) uses Common::Array for internal storage. Common::Array now
+ // might invalidate references to its contained data, when it has to
+ // extend the internal storage size.
+ if (parentIsClone)
+ parent_obj = s->_segMan->getObject(parent_addr);
+
*clone_obj = *parent_obj;
// Mark as clone