diff options
Diffstat (limited to 'engines/sci/engine')
-rw-r--r-- | engines/sci/engine/kscripts.cpp | 24 | ||||
-rw-r--r-- | engines/sci/engine/selector.cpp | 2 | ||||
-rw-r--r-- | engines/sci/engine/selector.h | 1 | ||||
-rw-r--r-- | engines/sci/engine/static_selectors.cpp | 2 |
4 files changed, 21 insertions, 8 deletions
diff --git a/engines/sci/engine/kscripts.cpp b/engines/sci/engine/kscripts.cpp index a5501c160f..d99302b3d4 100644 --- a/engines/sci/engine/kscripts.cpp +++ b/engines/sci/engine/kscripts.cpp @@ -172,27 +172,37 @@ reg_t kClone(EngineState *s, int argc, reg_t *argv) { s->_segMan->getScript(parent_obj->getPos().segment)->incrementLockers(); s->_segMan->getScript(clone_obj->getPos().segment)->incrementLockers(); + // Mark as clone for scripts as well + uint16 infoSelector = readSelectorValue(s->_segMan, clone_addr, SELECTOR(_info_)); + writeSelectorValue(s->_segMan, clone_addr, SELECTOR(_info_), (infoSelector & 0x7fff) | 1); + return clone_addr; } extern void _k_view_list_mark_free(EngineState *s, reg_t off); reg_t kDisposeClone(EngineState *s, int argc, reg_t *argv) { - reg_t victim_addr = argv[0]; - Clone *victim_obj = s->_segMan->getObject(victim_addr); + reg_t obj = argv[0]; + Clone *object = s->_segMan->getObject(obj); - if (!victim_obj) { + if (!object) { error("Attempt to dispose non-class/object at %04x:%04x", - PRINT_REG(victim_addr)); + PRINT_REG(obj)); return s->r_acc; } - if (!victim_obj->isClone()) { - // SCI silently ignores this behaviour; some games actually depend on it + if (!object->isClone()) { + // SCI silently ignores non-clones; some games actually depend on it return s->r_acc; } - victim_obj->markAsFreed(); + // SCI uses this technique to find out, if it's a clone and if it's supposed to get freed + // At least kq4early relies on this behaviour. The scripts clone "Sound", then set bit 1 manually + // and call kDisposeClone later. In that case we may not free it, otherwise we will run into issues + // later, because kIsObject would then return false and Sound object wouldn't get checked. + uint16 infoSelector = readSelectorValue(s->_segMan, obj, SELECTOR(_info_)); + if ((infoSelector & 3) == 1) + object->markAsFreed(); return s->r_acc; } diff --git a/engines/sci/engine/selector.cpp b/engines/sci/engine/selector.cpp index 436a4b98ff..b31f52aa13 100644 --- a/engines/sci/engine/selector.cpp +++ b/engines/sci/engine/selector.cpp @@ -50,7 +50,7 @@ namespace Sci { void Kernel::mapSelectors() { // species // superClass - // -info- + FIND_SELECTOR2(_info_, "-info-"); FIND_SELECTOR(y); FIND_SELECTOR(x); FIND_SELECTOR(view); diff --git a/engines/sci/engine/selector.h b/engines/sci/engine/selector.h index 63ec11fab1..98157c3eaf 100644 --- a/engines/sci/engine/selector.h +++ b/engines/sci/engine/selector.h @@ -40,6 +40,7 @@ struct SelectorCache { } // Statically defined selectors, (almost the) same in all SCI versions + Selector _info_; Selector y; Selector x; Selector view, loop, cel; ///< Description of a specific image diff --git a/engines/sci/engine/static_selectors.cpp b/engines/sci/engine/static_selectors.cpp index de7adb68c4..8ba10c5569 100644 --- a/engines/sci/engine/static_selectors.cpp +++ b/engines/sci/engine/static_selectors.cpp @@ -98,6 +98,7 @@ static const char * const sci2Selectors[] = { #endif static const SelectorRemap sciSelectorRemap[] = { + { SCI_VERSION_0_EARLY, SCI_VERSION_1_LATE, "-info-", 2 }, { SCI_VERSION_0_EARLY, SCI_VERSION_0_LATE, "moveDone", 170 }, { SCI_VERSION_0_EARLY, SCI_VERSION_0_LATE, "points", 316 }, { SCI_VERSION_0_EARLY, SCI_VERSION_0_LATE, "flags", 368 }, @@ -106,6 +107,7 @@ static const SelectorRemap sciSelectorRemap[] = { { SCI_VERSION_1_EARLY, SCI_VERSION_1_LATE, "topString", 101 }, { SCI_VERSION_1_EARLY, SCI_VERSION_1_LATE, "flags", 102 }, // SCI1.1 + { SCI_VERSION_1_1, SCI_VERSION_2_1, "-info-",4103 }, { SCI_VERSION_1_1, SCI_VERSION_1_1, "nodePtr", 41 }, { SCI_VERSION_1_1, SCI_VERSION_1_1, "cantBeHere", 54 }, { SCI_VERSION_1_1, SCI_VERSION_1_1, "topString", 98 }, |