aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorMartin Kiewitz2010-08-03 19:43:16 +0000
committerMartin Kiewitz2010-08-03 19:43:16 +0000
commit2e11c1cf9642de2db81ea0a25541872c20f28b8e (patch)
tree4f36bcedc25fadfec20056b9da21d35415cb7479 /engines
parentfcede4680a03e4f7a389a43f71d1484794e8dead (diff)
downloadscummvm-rg350-2e11c1cf9642de2db81ea0a25541872c20f28b8e.tar.gz
scummvm-rg350-2e11c1cf9642de2db81ea0a25541872c20f28b8e.tar.bz2
scummvm-rg350-2e11c1cf9642de2db81ea0a25541872c20f28b8e.zip
SCI: reset ports when restoring
fixes qfg3/fairy tales restoring (bug #3035626) also fixes ScummVM menu restoring while a window is shown (e.g. sq5) svn-id: r51712
Diffstat (limited to 'engines')
-rw-r--r--engines/sci/engine/savegame.cpp2
-rw-r--r--engines/sci/graphics/ports.cpp52
-rw-r--r--engines/sci/graphics/ports.h6
3 files changed, 49 insertions, 11 deletions
diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp
index f434e5326b..fb23b79c34 100644
--- a/engines/sci/engine/savegame.cpp
+++ b/engines/sci/engine/savegame.cpp
@@ -760,6 +760,8 @@ void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) {
s->gameStartTime = g_system->getMillis();
s->_screenUpdateTime = g_system->getMillis();
+ g_sci->_gfxPorts->reset();
+
g_sci->_soundCmd->reconstructPlayList(meta.savegame_version);
// Message state:
diff --git a/engines/sci/graphics/ports.cpp b/engines/sci/graphics/ports.cpp
index 2137de39de..afbe0e676c 100644
--- a/engines/sci/graphics/ports.cpp
+++ b/engines/sci/graphics/ports.cpp
@@ -50,7 +50,10 @@ GfxPorts::GfxPorts(SegManager *segMan, GfxScreen *screen)
}
GfxPorts::~GfxPorts() {
- // TODO: Clear _windowList and delete all stuff in it?
+ // reset frees all windows but _picWind
+ reset();
+ freeWindow(_picWind);
+ delete _wmgrPort;
delete _menuPort;
}
@@ -135,7 +138,7 @@ void GfxPorts::init(bool usesOldGfxFunctions, GfxPaint16 *paint16, GfxText16 *te
_wmgrPort->curLeft = 0;
_windowList.push_front(_wmgrPort);
- _picWind = newWindow(Common::Rect(0, offTop, _screen->getWidth(), _screen->getHeight()), 0, 0, SCI_WINDOWMGR_STYLE_TRANSPARENT | SCI_WINDOWMGR_STYLE_NOFRAME, 0, true);
+ _picWind = addWindow(Common::Rect(0, offTop, _screen->getWidth(), _screen->getHeight()), 0, 0, SCI_WINDOWMGR_STYLE_TRANSPARENT | SCI_WINDOWMGR_STYLE_NOFRAME, 0, true);
// For SCI0 games till kq4 (.502 - not including) we set _picWind top to offTop instead
// Because of the menu/status bar
if (g_sci->_features->usesOldGfxFunctions())
@@ -144,6 +147,30 @@ void GfxPorts::init(bool usesOldGfxFunctions, GfxPaint16 *paint16, GfxText16 *te
kernelInitPriorityBands();
}
+// Removes any windows from windowList
+// is used when restoring/restarting the game
+// Sierra SCI actually saved the whole windowList, it seems we don't need to do this at all
+// but in some games there are still windows active when restoring. Leaving those windows open
+// would create all sorts of issues, that's why we remove them
+void GfxPorts::reset() {
+ PortList::iterator it = _windowList.begin();
+ const PortList::iterator end = _windowList.end();
+
+ setPort(_picWind);
+
+ while (it != end) {
+ Port *pPort = *it;
+ if (pPort->id > 2) {
+ // found a window beyond _picWind
+ freeWindow((Window *)pPort);
+ }
+ it++;
+ }
+ _windowList.clear();
+ _windowList.push_front(_wmgrPort);
+ _windowList.push_back(_picWind);
+}
+
void GfxPorts::kernelSetActive(uint16 portId) {
switch (portId) {
case 0:
@@ -179,9 +206,9 @@ reg_t GfxPorts::kernelNewWindow(Common::Rect dims, Common::Rect restoreRect, uin
Window *wnd = NULL;
if (restoreRect.bottom != 0 && restoreRect.right != 0)
- wnd = newWindow(dims, &restoreRect, title, style, priority, false);
+ wnd = addWindow(dims, &restoreRect, title, style, priority, false);
else
- wnd = newWindow(dims, NULL, title, style, priority, false);
+ wnd = addWindow(dims, NULL, title, style, priority, false);
wnd->penClr = colorPen;
wnd->backClr = colorBack;
drawWindow(wnd);
@@ -191,7 +218,7 @@ reg_t GfxPorts::kernelNewWindow(Common::Rect dims, Common::Rect restoreRect, uin
void GfxPorts::kernelDisposeWindow(uint16 windowId, bool reanimate) {
Window *wnd = (Window *)getPortById(windowId);
- disposeWindow(wnd, reanimate);
+ removeWindow(wnd, reanimate);
}
int16 GfxPorts::isFrontWindow(Window *pWnd) {
@@ -228,7 +255,7 @@ void GfxPorts::endUpdate(Window *wnd) {
setPort(oldPort);
}
-Window *GfxPorts::newWindow(const Common::Rect &dims, const Common::Rect *restoreRect, const char *title, uint16 style, int16 priority, bool draw) {
+Window *GfxPorts::addWindow(const Common::Rect &dims, const Common::Rect *restoreRect, const char *title, uint16 style, int16 priority, bool draw) {
// Find an unused window/port id
uint id = 1;
while (id < _windowsById.size() && _windowsById[id]) {
@@ -378,7 +405,7 @@ void GfxPorts::drawWindow(Window *pWnd) {
setPort(oldport);
}
-void GfxPorts::disposeWindow(Window *pWnd, bool reanimate) {
+void GfxPorts::removeWindow(Window *pWnd, bool reanimate) {
setPort(_wmgrPort);
_paint16->bitsRestore(pWnd->hSaved1);
_paint16->bitsRestore(pWnd->hSaved2);
@@ -392,6 +419,15 @@ void GfxPorts::disposeWindow(Window *pWnd, bool reanimate) {
delete pWnd;
}
+void GfxPorts::freeWindow(Window *pWnd) {
+ if (!pWnd->hSaved1.isNull())
+ _segMan->freeHunkEntry(pWnd->hSaved1);
+ if (!pWnd->hSaved2.isNull())
+ _segMan->freeHunkEntry(pWnd->hSaved1);
+ _windowsById[pWnd->id] = 0;
+ delete pWnd;
+}
+
void GfxPorts::updateWindow(Window *wnd) {
reg_t handle;
@@ -413,8 +449,6 @@ Port *GfxPorts::getPortById(uint16 id) {
return _windowsById[id];
}
-
-
Port *GfxPorts::setPort(Port *newPort) {
Port *oldPort = _curPort;
_curPort = newPort;
diff --git a/engines/sci/graphics/ports.h b/engines/sci/graphics/ports.h
index d10bc6772f..f7f0721eb7 100644
--- a/engines/sci/graphics/ports.h
+++ b/engines/sci/graphics/ports.h
@@ -46,6 +46,7 @@ public:
~GfxPorts();
void init(bool usesOldGfxFunctions, GfxPaint16 *paint16, GfxText16 *text16);
+ void reset();
void kernelSetActive(uint16 portId);
Common::Rect kernelGetPicWindow(int16 &picTop, int16 &picLeft);
@@ -57,9 +58,10 @@ public:
int16 isFrontWindow(Window *wnd);
void beginUpdate(Window *wnd);
void endUpdate(Window *wnd);
- Window *newWindow(const Common::Rect &dims, const Common::Rect *restoreRect, const char *title, uint16 style, int16 priority, bool draw);
+ Window *addWindow(const Common::Rect &dims, const Common::Rect *restoreRect, const char *title, uint16 style, int16 priority, bool draw);
void drawWindow(Window *wnd);
- void disposeWindow(Window *pWnd, bool reanimate);
+ void removeWindow(Window *pWnd, bool reanimate);
+ void freeWindow(Window *pWnd);
void updateWindow(Window *wnd);
Port *getPortById(uint16 id);