From e242814990862998c2af9289f88f0cbc8060fb13 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 13 Sep 2010 13:17:55 +0000 Subject: SCI: Proper fix for bug #3038837 - "HOYLE3: EGA/VGA Crashes" and some cleanup System scripts (i.e. 0 and 900-999) are now protected and never destroyed during a game svn-id: r52702 --- engines/sci/engine/script.cpp | 26 +++++++------------------- engines/sci/engine/script.h | 23 +++++++++++++++-------- engines/sci/engine/seg_manager.cpp | 15 +++++++-------- 3 files changed, 29 insertions(+), 35 deletions(-) (limited to 'engines/sci/engine') diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index 81094c6f59..da9ab5106d 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -310,25 +310,6 @@ void Script::incrementLockers() { void Script::decrementLockers() { if (_lockers > 0) _lockers--; - - // WORKAROUND for bug #3038837: HOYLE3: EGA/VGA Crashes - // This is caused by script 0 lockers reaching zero. Since - // this should never happen, I'm confident in making this a - // non-specific fix. We can't just reset lockers to 1, because - // the objects associated with the script are already marked - // to be deleted at this point, thus we need to reload the - // script itself. If we don't, the game will surely error - // out later on, because of objects associated with this - // script which are incorrectly marked to be deleted. For - // example, in Hoyle 3, if you exit Checkers and reenter - // checkers, the game will crash when selecting a player. - // - // TODO: Figure out why this happens, and fix it properly! - if (_nr == 0 && _lockers == 0) { - init(0, g_sci->getResMan()); - load(g_sci->getResMan()); - } - } int Script::getLockers() const { @@ -577,6 +558,13 @@ void Script::initialiseObjectsSci11(SegManager *segMan, SegmentId segmentId) { relocate(make_reg(segmentId, READ_SCI11ENDIAN_UINT16(_heapStart))); } +void Script::initialiseObjects(SegManager *segMan, SegmentId segmentId) { + if (getSciVersion() >= SCI_VERSION_1_1) + initialiseObjectsSci11(segMan, segmentId); + else + initialiseObjectsSci0(segMan, segmentId); +} + reg_t Script::findCanonicAddress(SegManager *segMan, reg_t addr) const { addr.offset = 0; return addr; diff --git a/engines/sci/engine/script.h b/engines/sci/engine/script.h index c60cc4b19f..e316fc0c8d 100644 --- a/engines/sci/engine/script.h +++ b/engines/sci/engine/script.h @@ -159,14 +159,7 @@ public: * @param segMan A reference to the segment manager * @param segmentId The script's segment id */ - void initialiseObjectsSci0(SegManager *segMan, SegmentId segmentId); - - /** - * Initializes the script's objects (SCI1.1+) - * @param segMan A reference to the segment manager - * @param segmentId The script's segment id - */ - void initialiseObjectsSci11(SegManager *segMan, SegmentId segmentId); + void initialiseObjects(SegManager *segMan, SegmentId segmentId); // script lock operations @@ -260,6 +253,20 @@ private: void relocate(reg_t block); bool relocateLocal(SegmentId segment, int location); + + /** + * Initializes the script's objects (SCI0) + * @param segMan A reference to the segment manager + * @param segmentId The script's segment id + */ + void initialiseObjectsSci0(SegManager *segMan, SegmentId segmentId); + + /** + * Initializes the script's objects (SCI1.1+) + * @param segMan A reference to the segment manager + * @param segmentId The script's segment id + */ + void initialiseObjectsSci11(SegManager *segMan, SegmentId segmentId); }; } // End of namespace Sci diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index 7fdd2d25ac..43e572d071 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -1004,12 +1004,7 @@ int SegManager::instantiateScript(int scriptNum) { scr->load(_resMan); scr->initialiseLocals(this); scr->initialiseClasses(this); - - if (getSciVersion() >= SCI_VERSION_1_1) { - scr->initialiseObjectsSci11(this, segmentId); - } else { - scr->initialiseObjectsSci0(this, segmentId); - } + scr->initialiseObjects(this, segmentId); return segmentId; } @@ -1074,8 +1069,12 @@ void SegManager::uninstantiateScriptSci0(int script_nr) { if (superclass_script == script_nr) { if (scr->getLockers()) scr->decrementLockers(); // Decrease lockers if this is us ourselves - } else - uninstantiateScript(superclass_script); + } else { + // Uninstantiate superclass, but never uninstantiate + // system scripts, i.e. script 0 and scripts 900-999 - bug #3038837 + if (superclass_script != 0 && superclass_script < 900) + uninstantiateScript(superclass_script); + } // Recurse to assure that the superclass lockers number gets decreased } -- cgit v1.2.3