diff options
author | Robert Špalek | 2009-11-22 09:13:05 +0000 |
---|---|---|
committer | Robert Špalek | 2009-11-22 09:13:05 +0000 |
commit | 2397efd73014b6a4303e724360986f14ed29addc (patch) | |
tree | 42fda9b5660ca9cfd2547bd8c67d6c4578ccaab3 /engines/draci | |
parent | d81bb78053453b02e36b1aa7b2a972931ddbd549 (diff) | |
download | scummvm-rg350-2397efd73014b6a4303e724360986f14ed29addc.tar.gz scummvm-rg350-2397efd73014b6a4303e724360986f14ed29addc.tar.bz2 scummvm-rg350-2397efd73014b6a4303e724360986f14ed29addc.zip |
Fix SIGSEGV by an absolutely brutally horrible hack
I have thoroughly documented why this hack is needed and added ideas how to
fix it properly.
svn-id: r46068
Diffstat (limited to 'engines/draci')
-rw-r--r-- | engines/draci/game.cpp | 65 | ||||
-rw-r--r-- | engines/draci/walking.h | 4 |
2 files changed, 66 insertions, 3 deletions
diff --git a/engines/draci/game.cpp b/engines/draci/game.cpp index b04de1a000..0d437f2475 100644 --- a/engines/draci/game.cpp +++ b/engines/draci/game.cpp @@ -1155,12 +1155,73 @@ void Game::loadOverlays() { } void Game::deleteObjectAnimations() { - for (uint i = 0; i < _info._numObjects; ++i) { + for (uint i = 1; i < _info._numObjects; ++i) { GameObject *obj = &_objects[i]; - if (i != 0 && (obj->_location == getPreviousRoomNum())) { + if (obj->_location == getPreviousRoomNum()) { obj->deleteAnims(); } } + + // WORKAROUND + // + // An absolutely horrible hack follows. The current memory management + // is completely broken and it needs to be seriously hacked to work at + // all. The problem is caching sound samples in BArchive and clearing + // all caches when entering a new location. The animation sequences + // store pointers to samples owned by the BArchive cache, which gets + // invalidated during the location change. If an animation sequence + // survives location change and refers to any sound sample, we get + // SIGSEGV when next played, because this sound sample will have been + // deallocated by the cache although still referred to by the animation. + // + // Caveat: when I tried to perform a deep copy and make the animation + // object own the sound samples and deallocate them when the animation + // has been deleted, I get an almost immediate SIGSEGV in runWrapper() + // on many objects, because often an animation graphically ends and is + // stopped, but the last sound sample still plays for a short while + // afterwards. If the sound sample is cached, it's OK, but if it's + // deallocated with releaseAnims==true, we get SIGSEGV in the sound + // mixer. This problem doesn't occur when changing locations, because + // there we first explicitly stop all playing sounds. + // + // The loop above deallocates all animations corresponding to non-hero + // objects. Hero is special, because the first ~20 animations are + // standard and loaded for the whole game (standing, walking, etc.). + // They are loaded by the GPL2 init routine for object hero. Luckily + // the animations don't refer to any sound samples. The remaining + // animations thus must be deallocated manually, otherwise they won't + // be re-loaded next time assuming that they are already correctly + // loaded. + // + // mini-TODO: integrate this deletion into deleteAnim() an optional + // parameter with starting index for deletion. + // + // Why this only occurs for sound samples and not sprites? This bug is + // concealed by a complete coincidence, that all sprites are stored + // column-wise and our class Sprite detects this and creates a local + // copy. If this wasn't the case, each animation (not just with sound + // samples) would fail and preserving the ~20 hero animations wouldn't + // work either. + // + // TODO: maybe simply deallocate everything except for those ~20 hero + // animations instead of listing what to deallocate. maybe simply + // deallocate everything; reloading isn't that expensive. + // + // TODO: completely rewrite the resource management. maybe implement + // usage counters? maybe completely ignore the GPL2 hints and manage + // memory completely on my own? + // + // URGENT TODO: if a game item is in the hero's hands when changing + // locations, its animations survive and we get assert in + // AnimationManager::load(). + GameObject *dragon = &_objects[kDragonObject]; + for (uint i = dragon->_anim.size() - 1; i >= kFirstTemporaryAnimation; --i) { + dragon->_anim.back()->del(); + dragon->_anim.pop_back(); + } + if (dragon->_playingAnim >= kFirstTemporaryAnimation) { + dragon->_playingAnim = 0; + } } bool Game::enterNewRoom() { diff --git a/engines/draci/walking.h b/engines/draci/walking.h index e21ed710b8..55b39792f1 100644 --- a/engines/draci/walking.h +++ b/engines/draci/walking.h @@ -96,7 +96,9 @@ enum Movement { kMoveLeftRight, kMoveRightLeft, kMoveUpStopLeft, kMoveUpStopRight, kLastTurning = kMoveUpStopRight, - kSpeakRight, kSpeakLeft, kStopRight, kStopLeft + kSpeakRight, kSpeakLeft, kStopRight, kStopLeft, + + kFirstTemporaryAnimation }; class DraciEngine; |