diff options
Diffstat (limited to 'engines/dreamweb/saveload.cpp')
-rw-r--r-- | engines/dreamweb/saveload.cpp | 63 |
1 files changed, 62 insertions, 1 deletions
diff --git a/engines/dreamweb/saveload.cpp b/engines/dreamweb/saveload.cpp index ea9cdc0249..8a0791d19b 100644 --- a/engines/dreamweb/saveload.cpp +++ b/engines/dreamweb/saveload.cpp @@ -156,8 +156,16 @@ void DreamWebEngine::doLoad(int savegameId) { } else { if (savegameId == -1) { - // Open dialog to get savegameId + // Wait till both mouse buttons are up. We should wait till the user + // releases the mouse button, otherwise the follow-up mouseup event + // will trigger a load of the save slot under the mouse cursor. Fixes + // bug #3582582. + while (_oldMouseState > 0) { + readMouse(); + g_system->delayMillis(10); + } + // Open dialog to get savegameId GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Restore game:"), _("Restore"), false); savegameId = dialog->runModalWithCurrentTarget(); delete dialog; @@ -241,6 +249,15 @@ void DreamWebEngine::saveGame() { } return; } else { + // Wait till both mouse buttons are up. We should wait till the user + // releases the mouse button, otherwise the follow-up mouseup event + // will trigger a save into the save slot under the mouse cursor. Fixes + // bug #3582582. + while (_oldMouseState > 0) { + readMouse(); + g_system->delayMillis(10); + } + GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true); int savegameId = dialog->runModalWithCurrentTarget(); Common::String game_description = dialog->getResultString(); @@ -557,6 +574,14 @@ void DreamWebEngine::savePosition(unsigned int slot, const char *descbuf) { delete outSaveFile; } + +// Utility struct for a savegame sanity check in loadPosition +struct FrameExtent { + uint16 start; + uint16 length; + bool operator<(const struct FrameExtent& other) const { return start<other.start; } +}; + void DreamWebEngine::loadPosition(unsigned int slot) { _timeCount = 0; clearChanges(); @@ -636,6 +661,42 @@ void DreamWebEngine::loadPosition(unsigned int slot) { } delete inSaveFile; + + + // Do a sanity check on exFrames data to detect exFrames corruption + // caused by a (now fixed) bug in emergencyPurge. See bug #3591088. + // Gather the location of frame data of all used ex object frames. + Common::List<FrameExtent> flist; + for (unsigned int i = 0; i < kNumexobjects; ++i) { + if (_exData[i].mapad[0] != 0xff) { + FrameExtent fe; + Frame *frame = &_exFrames._frames[3*i+0]; + fe.start = frame->ptr(); + fe.length = frame->width * frame->height; + flist.push_back(fe); + + frame = &_exFrames._frames[3*i+1]; + fe.start = frame->ptr(); + fe.length = frame->width * frame->height; + flist.push_back(fe); + } + } + // ...and check if the frames overlap. + Common::sort(flist.begin(), flist.end(), Common::Less<FrameExtent>()); + Common::List<FrameExtent>::const_iterator iter; + uint16 curEnd = 0; + for (iter = flist.begin(); iter != flist.end(); ++iter) { + if (iter->start < curEnd) + error("exFrames data corruption in savegame"); + curEnd = iter->start + iter->length; + } + if (curEnd > _vars._exFramePos) { + if (curEnd > kExframeslen) + error("exFrames data corruption in savegame"); + warning("Fixing up exFramePos"); + _vars._exFramePos = curEnd; + } + // (end of sanity check) } // Count number of save files, and load their descriptions into _saveNames |