aboutsummaryrefslogtreecommitdiff
path: root/engines/draci
diff options
context:
space:
mode:
authorRobert Špalek2009-11-22 09:13:05 +0000
committerRobert Špalek2009-11-22 09:13:05 +0000
commit2397efd73014b6a4303e724360986f14ed29addc (patch)
tree42fda9b5660ca9cfd2547bd8c67d6c4578ccaab3 /engines/draci
parentd81bb78053453b02e36b1aa7b2a972931ddbd549 (diff)
downloadscummvm-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.cpp65
-rw-r--r--engines/draci/walking.h4
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;