diff options
| author | Martin Kiewitz | 2010-09-03 18:14:59 +0000 |
|---|---|---|
| committer | Martin Kiewitz | 2010-09-03 18:14:59 +0000 |
| commit | 87b78b1673037409604cdb4a1a5d6884af71bac1 (patch) | |
| tree | ff386819ec9c9cf1575575d8e27096857b617867 /engines/sci/engine/kscripts.cpp | |
| parent | b7a2fd899e07c3ae47bf5c845aadba6991c33666 (diff) | |
| download | scummvm-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.cpp | 24 |
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; } |
