aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/engine/kscripts.cpp
diff options
context:
space:
mode:
authorMartin Kiewitz2010-09-03 18:14:59 +0000
committerMartin Kiewitz2010-09-03 18:14:59 +0000
commit87b78b1673037409604cdb4a1a5d6884af71bac1 (patch)
treeff386819ec9c9cf1575575d8e27096857b617867 /engines/sci/engine/kscripts.cpp
parentb7a2fd899e07c3ae47bf5c845aadba6991c33666 (diff)
downloadscummvm-rg350-87b78b1673037409604cdb4a1a5d6884af71bac1.tar.gz
scummvm-rg350-87b78b1673037409604cdb4a1a5d6884af71bac1.tar.bz2
scummvm-rg350-87b78b1673037409604cdb4a1a5d6884af71bac1.zip
SCI: kClone/kDisposeClone behaviour more accurate
now also checking -info- selector, if object is supposed to get freed. Fixes kq4 early hanging (in intro, when opening door, etc.) svn-id: r52508
Diffstat (limited to 'engines/sci/engine/kscripts.cpp')
-rw-r--r--engines/sci/engine/kscripts.cpp24
1 files changed, 17 insertions, 7 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;
}