From acb172251aa7401f43308ebcac9f30bef3aa40f5 Mon Sep 17 00:00:00 2001 From: Adrian Astley Date: Fri, 19 Dec 2014 11:14:10 -0600 Subject: ZVISION: Large scale variable, function, and class renaming to improve code clarity --- engines/zvision/core/events.cpp | 8 +- engines/zvision/graphics/render_manager.cpp | 348 +++++++++++++++------------- engines/zvision/graphics/render_manager.h | 102 ++++---- engines/zvision/zvision.cpp | 48 ++-- engines/zvision/zvision.h | 6 +- 5 files changed, 266 insertions(+), 246 deletions(-) (limited to 'engines') diff --git a/engines/zvision/core/events.cpp b/engines/zvision/core/events.cpp index c66e61a61a..fe357c263b 100644 --- a/engines/zvision/core/events.cpp +++ b/engines/zvision/core/events.cpp @@ -194,7 +194,7 @@ void ZVision::processEvents() { case Common::KEYCODE_LEFT: case Common::KEYCODE_RIGHT: if (_renderManager->getRenderTable()->getRenderState() == RenderTable::PANORAMA) - _kbdVelocity = (_event.kbd.keycode == Common::KEYCODE_LEFT ? + _keyboardVelocity = (_event.kbd.keycode == Common::KEYCODE_LEFT ? -_scriptManager->getStateValue(StateKey_KbdRotateSpeed) : _scriptManager->getStateValue(StateKey_KbdRotateSpeed)) * 2; break; @@ -202,7 +202,7 @@ void ZVision::processEvents() { case Common::KEYCODE_UP: case Common::KEYCODE_DOWN: if (_renderManager->getRenderTable()->getRenderState() == RenderTable::TILT) - _kbdVelocity = (_event.kbd.keycode == Common::KEYCODE_UP ? + _keyboardVelocity = (_event.kbd.keycode == Common::KEYCODE_UP ? -_scriptManager->getStateValue(StateKey_KbdRotateSpeed) : _scriptManager->getStateValue(StateKey_KbdRotateSpeed)) * 2; break; @@ -226,12 +226,12 @@ void ZVision::processEvents() { case Common::KEYCODE_LEFT: case Common::KEYCODE_RIGHT: if (_renderManager->getRenderTable()->getRenderState() == RenderTable::PANORAMA) - _kbdVelocity = 0; + _keyboardVelocity = 0; break; case Common::KEYCODE_UP: case Common::KEYCODE_DOWN: if (_renderManager->getRenderTable()->getRenderState() == RenderTable::TILT) - _kbdVelocity = 0; + _keyboardVelocity = 0; break; default: break; diff --git a/engines/zvision/graphics/render_manager.cpp b/engines/zvision/graphics/render_manager.cpp index e2ad13a330..b9305f5dcc 100644 --- a/engines/zvision/graphics/render_manager.cpp +++ b/engines/zvision/graphics/render_manager.cpp @@ -42,68 +42,73 @@ namespace ZVision { RenderManager::RenderManager(ZVision *engine, uint32 windowWidth, uint32 windowHeight, const Common::Rect workingWindow, const Graphics::PixelFormat pixelFormat) : _engine(engine), _system(engine->_system), - _wrkWidth(workingWindow.width()), - _wrkHeight(workingWindow.height()), - _screenCenterX(_wrkWidth / 2), - _screenCenterY(_wrkHeight / 2), + _workingWidth(workingWindow.width()), + _workingHeight(workingWindow.height()), + _screenCenterX(_workingWidth / 2), + _screenCenterY(_workingHeight / 2), _workingWindow(workingWindow), _pixelFormat(pixelFormat), - _bkgWidth(0), - _bkgHeight(0), - _bkgOff(0), - _renderTable(_wrkWidth, _wrkHeight) { + _backgroundWidth(0), + _backgroundHeight(0), + _backgroundOffset(0), + _renderTable(_workingWidth, _workingHeight) { - _wrkWnd.create(_wrkWidth, _wrkHeight, _pixelFormat); - _effectWnd.create(_wrkWidth, _wrkHeight, _pixelFormat); - _outWnd.create(_wrkWidth, _wrkHeight, _pixelFormat); - _menuWnd.create(windowWidth, workingWindow.top, _pixelFormat); - _subWnd.create(windowWidth, windowHeight - workingWindow.bottom, _pixelFormat); + _backgroundSurface.create(_workingWidth, _workingHeight, _pixelFormat); + _effectSurface.create(_workingWidth, _workingHeight, _pixelFormat); + _warpedSceneSurface.create(_workingWidth, _workingHeight, _pixelFormat); + _menuSurface.create(windowWidth, workingWindow.top, _pixelFormat); + _subtitleSurface.create(windowWidth, windowHeight - workingWindow.bottom, _pixelFormat); - _menuWndRect = Common::Rect(0, 0, windowWidth, workingWindow.top); - _subWndRect = Common::Rect(0, workingWindow.bottom, windowWidth, windowHeight); + _menuArea = Common::Rect(0, 0, windowWidth, workingWindow.top); + _subtitleArea = Common::Rect(0, workingWindow.bottom, windowWidth, windowHeight); _subid = 0; } RenderManager::~RenderManager() { - _curBkg.free(); - _wrkWnd.free(); - _effectWnd.free(); - _outWnd.free(); - _menuWnd.free(); - _subWnd.free(); + _currentBackgroundImage.free(); + _backgroundSurface.free(); + _effectSurface.free(); + _warpedSceneSurface.free(); + _menuSurface.free(); + _subtitleSurface.free(); } -void RenderManager::renderBackbufferToScreen() { - Graphics::Surface *out = &_outWnd; - Graphics::Surface *in = &_wrkWnd; +void RenderManager::renderSceneToScreen() { + Graphics::Surface *out = &_warpedSceneSurface; + Graphics::Surface *in = &_backgroundSurface; Common::Rect outWndDirtyRect; + // If we have graphical effects, we apply them using a temporary buffer if (!_effects.empty()) { bool copied = false; - Common::Rect windRect(_wrkWidth, _wrkHeight); - for (effectsList::iterator it = _effects.begin(); it != _effects.end(); it++) { + Common::Rect windowRect(_workingWidth, _workingHeight); + + for (EffectsList::iterator it = _effects.begin(); it != _effects.end(); it++) { Common::Rect rect = (*it)->getRegion(); - Common::Rect scrPlace = rect; - if ((*it)->isPort()) - scrPlace = bkgRectToScreen(scrPlace); - if (windRect.intersects(scrPlace)) { + Common::Rect screenSpaceLocation = rect; + + if ((*it)->isPort()) { + screenSpaceLocation = transformBackgroundSpaceRectToScreenSpace(screenSpaceLocation); + } + + if (windowRect.intersects(screenSpaceLocation)) { if (!copied) { copied = true; - _effectWnd.copyFrom(_wrkWnd); - in = &_effectWnd; + _effectSurface.copyFrom(_backgroundSurface); + in = &_effectSurface; } const Graphics::Surface *post; if ((*it)->isPort()) - post = (*it)->draw(_curBkg.getSubArea(rect)); + post = (*it)->draw(_currentBackgroundImage.getSubArea(rect)); else - post = (*it)->draw(_effectWnd.getSubArea(rect)); - blitSurfaceToSurface(*post, _effectWnd, scrPlace.left, scrPlace.top); - scrPlace.clip(windRect); - if (_wrkWndDirtyRect .isEmpty()) { - _wrkWndDirtyRect = scrPlace; + post = (*it)->draw(_effectSurface.getSubArea(rect)); + blitSurfaceToSurface(*post, _effectSurface, screenSpaceLocation.left, screenSpaceLocation.top); + screenSpaceLocation.clip(windowRect); + if (_backgroundSurfaceDirtyRect .isEmpty()) { + _backgroundSurfaceDirtyRect = screenSpaceLocation; } else { - _wrkWndDirtyRect.extend(scrPlace); + _backgroundSurfaceDirtyRect.extend(screenSpaceLocation); } } } @@ -111,14 +116,14 @@ void RenderManager::renderBackbufferToScreen() { RenderTable::RenderState state = _renderTable.getRenderState(); if (state == RenderTable::PANORAMA || state == RenderTable::TILT) { - if (!_wrkWndDirtyRect.isEmpty()) { - _renderTable.mutateImage(&_outWnd, in); - out = &_outWnd; - outWndDirtyRect = Common::Rect(_wrkWidth, _wrkHeight); + if (!_backgroundSurfaceDirtyRect.isEmpty()) { + _renderTable.mutateImage(&_warpedSceneSurface, in); + out = &_warpedSceneSurface; + outWndDirtyRect = Common::Rect(_workingWidth, _workingHeight); } } else { out = in; - outWndDirtyRect = _wrkWndDirtyRect; + outWndDirtyRect = _backgroundSurfaceDirtyRect; } if (!outWndDirtyRect.isEmpty()) { @@ -354,20 +359,20 @@ const Common::Point RenderManager::screenSpaceToImageSpace(const Common::Point & } if (state == RenderTable::PANORAMA) { - newPoint += (Common::Point(_bkgOff - _screenCenterX, 0)); + newPoint += (Common::Point(_backgroundOffset - _screenCenterX, 0)); } else if (state == RenderTable::TILT) { - newPoint += (Common::Point(0, _bkgOff - _screenCenterY)); + newPoint += (Common::Point(0, _backgroundOffset - _screenCenterY)); } - if (_bkgWidth) - newPoint.x %= _bkgWidth; - if (_bkgHeight) - newPoint.y %= _bkgHeight; + if (_backgroundWidth) + newPoint.x %= _backgroundWidth; + if (_backgroundHeight) + newPoint.y %= _backgroundHeight; if (newPoint.x < 0) - newPoint.x += _bkgWidth; + newPoint.x += _backgroundWidth; if (newPoint.y < 0) - newPoint.y += _bkgHeight; + newPoint.y += _backgroundHeight; return newPoint; } else { @@ -380,18 +385,18 @@ RenderTable *RenderManager::getRenderTable() { } void RenderManager::setBackgroundImage(const Common::String &fileName) { - readImageToSurface(fileName, _curBkg); - _bkgWidth = _curBkg.w; - _bkgHeight = _curBkg.h; - _bkgDirtyRect = Common::Rect(_bkgWidth, _bkgHeight); + readImageToSurface(fileName, _currentBackgroundImage); + _backgroundWidth = _currentBackgroundImage.w; + _backgroundHeight = _currentBackgroundImage.h; + _backgroundDirtyRect = Common::Rect(_backgroundWidth, _backgroundHeight); } void RenderManager::setBackgroundPosition(int offset) { RenderTable::RenderState state = _renderTable.getRenderState(); if (state == RenderTable::TILT || state == RenderTable::PANORAMA) - if (_bkgOff != offset) - _bkgDirtyRect = Common::Rect(_bkgWidth, _bkgHeight); - _bkgOff = offset; + if (_backgroundOffset != offset) + _backgroundDirtyRect = Common::Rect(_backgroundWidth, _backgroundHeight); + _backgroundOffset = offset; _engine->getScriptManager()->setStateValue(StateKey_ViewPos, offset); } @@ -400,9 +405,9 @@ uint32 RenderManager::getCurrentBackgroundOffset() { RenderTable::RenderState state = _renderTable.getRenderState(); if (state == RenderTable::PANORAMA) { - return _bkgOff; + return _backgroundOffset; } else if (state == RenderTable::TILT) { - return _bkgOff; + return _backgroundOffset; } else { return 0; } @@ -588,24 +593,24 @@ void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, Graphics: void RenderManager::blitSurfaceToBkg(const Graphics::Surface &src, int x, int y) { Common::Rect empt; - blitSurfaceToSurface(src, empt, _curBkg, x, y); + blitSurfaceToSurface(src, empt, _currentBackgroundImage, x, y); Common::Rect dirty(src.w, src.h); dirty.translate(x, y); - if (_bkgDirtyRect.isEmpty()) - _bkgDirtyRect = dirty; + if (_backgroundDirtyRect.isEmpty()) + _backgroundDirtyRect = dirty; else - _bkgDirtyRect.extend(dirty); + _backgroundDirtyRect.extend(dirty); } void RenderManager::blitSurfaceToBkg(const Graphics::Surface &src, int x, int y, uint32 colorkey) { Common::Rect empt; - blitSurfaceToSurface(src, empt, _curBkg, x, y, colorkey); + blitSurfaceToSurface(src, empt, _currentBackgroundImage, x, y, colorkey); Common::Rect dirty(src.w, src.h); dirty.translate(x, y); - if (_bkgDirtyRect.isEmpty()) - _bkgDirtyRect = dirty; + if (_backgroundDirtyRect.isEmpty()) + _backgroundDirtyRect = dirty; else - _bkgDirtyRect.extend(dirty); + _backgroundDirtyRect.extend(dirty); } void RenderManager::blitSurfaceToBkgScaled(const Graphics::Surface &src, const Common::Rect &_dstRect) { @@ -636,37 +641,37 @@ void RenderManager::blitSurfaceToBkgScaled(const Graphics::Surface &src, const C void RenderManager::blitSurfaceToMenu(const Graphics::Surface &src, int x, int y) { Common::Rect empt; - blitSurfaceToSurface(src, empt, _menuWnd, x, y); + blitSurfaceToSurface(src, empt, _menuSurface, x, y); Common::Rect dirty(src.w, src.h); dirty.translate(x, y); - if (_menuWndDirtyRect.isEmpty()) - _menuWndDirtyRect = dirty; + if (_menuSurfaceDirtyRect.isEmpty()) + _menuSurfaceDirtyRect = dirty; else - _menuWndDirtyRect.extend(dirty); + _menuSurfaceDirtyRect.extend(dirty); } void RenderManager::blitSurfaceToMenu(const Graphics::Surface &src, int x, int y, uint32 colorkey) { Common::Rect empt; - blitSurfaceToSurface(src, empt, _menuWnd, x, y, colorkey); + blitSurfaceToSurface(src, empt, _menuSurface, x, y, colorkey); Common::Rect dirty(src.w, src.h); dirty.translate(x, y); - if (_menuWndDirtyRect.isEmpty()) - _menuWndDirtyRect = dirty; + if (_menuSurfaceDirtyRect.isEmpty()) + _menuSurfaceDirtyRect = dirty; else - _menuWndDirtyRect.extend(dirty); + _menuSurfaceDirtyRect.extend(dirty); } Graphics::Surface *RenderManager::getBkgRect(Common::Rect &rect) { Common::Rect dst = rect; - dst.clip(_bkgWidth, _bkgHeight); + dst.clip(_backgroundWidth, _backgroundHeight); if (dst.isEmpty() || !dst.isValidRect()) return NULL; Graphics::Surface *srf = new Graphics::Surface; - srf->create(dst.width(), dst.height(), _curBkg.format); + srf->create(dst.width(), dst.height(), _currentBackgroundImage.format); - srf->copyRectToSurface(_curBkg, 0, 0, Common::Rect(dst)); + srf->copyRectToSurface(_currentBackgroundImage, 0, 0, Common::Rect(dst)); return srf; } @@ -693,101 +698,110 @@ Graphics::Surface *RenderManager::loadImage(const char *file, bool transposed) { return loadImage(str, transposed); } -void RenderManager::prepareBkg() { - _bkgDirtyRect.clip(_bkgWidth, _bkgHeight); +void RenderManager::prepareBackground() { + _backgroundDirtyRect.clip(_backgroundWidth, _backgroundHeight); RenderTable::RenderState state = _renderTable.getRenderState(); if (state == RenderTable::PANORAMA) { - Common::Rect viewPort(_wrkWidth, _wrkHeight); - viewPort.translate(-(_screenCenterX - _bkgOff), 0); - Common::Rect drawRect = _bkgDirtyRect; + // Calculate the visible portion of the background + Common::Rect viewPort(_workingWidth, _workingHeight); + viewPort.translate(-(_screenCenterX - _backgroundOffset), 0); + Common::Rect drawRect = _backgroundDirtyRect; drawRect.clip(viewPort); - if (!drawRect.isEmpty()) - blitSurfaceToSurface(_curBkg, drawRect, _wrkWnd, _screenCenterX - _bkgOff + drawRect.left, drawRect.top); + // Render the visible portion + if (!drawRect.isEmpty()) { + blitSurfaceToSurface(_currentBackgroundImage, drawRect, _backgroundSurface, _screenCenterX - _backgroundOffset + drawRect.left, drawRect.top); + } - _wrkWndDirtyRect = _bkgDirtyRect; - _wrkWndDirtyRect.translate(_screenCenterX - _bkgOff, 0); + // Mark the dirty portion of the surface + _backgroundSurfaceDirtyRect = _backgroundDirtyRect; + _backgroundSurfaceDirtyRect.translate(_screenCenterX - _backgroundOffset, 0); - if (_bkgOff < _screenCenterX) { - viewPort.moveTo(-(_screenCenterX - (_bkgOff + _bkgWidth)), 0); - drawRect = _bkgDirtyRect; + // Panorama mode allows the user to spin in circles. Therefore, we need to render + // the portion of the image that wrapped to the other side of the screen + if (_backgroundOffset < _screenCenterX) { + viewPort.moveTo(-(_screenCenterX - (_backgroundOffset + _backgroundWidth)), 0); + drawRect = _backgroundDirtyRect; drawRect.clip(viewPort); if (!drawRect.isEmpty()) - blitSurfaceToSurface(_curBkg, drawRect, _wrkWnd, _screenCenterX - (_bkgOff + _bkgWidth) + drawRect.left, drawRect.top); + blitSurfaceToSurface(_currentBackgroundImage, drawRect, _backgroundSurface, _screenCenterX - (_backgroundOffset + _backgroundWidth) + drawRect.left, drawRect.top); - Common::Rect tmp = _bkgDirtyRect; - tmp.translate(_screenCenterX - (_bkgOff + _bkgWidth), 0); + Common::Rect tmp = _backgroundDirtyRect; + tmp.translate(_screenCenterX - (_backgroundOffset + _backgroundWidth), 0); if (!tmp.isEmpty()) - _wrkWndDirtyRect.extend(tmp); + _backgroundSurfaceDirtyRect.extend(tmp); - } else if (_bkgWidth - _bkgOff < _screenCenterX) { - viewPort.moveTo(-(_screenCenterX + _bkgWidth - _bkgOff), 0); - drawRect = _bkgDirtyRect; + } else if (_backgroundWidth - _backgroundOffset < _screenCenterX) { + viewPort.moveTo(-(_screenCenterX + _backgroundWidth - _backgroundOffset), 0); + drawRect = _backgroundDirtyRect; drawRect.clip(viewPort); if (!drawRect.isEmpty()) - blitSurfaceToSurface(_curBkg, drawRect, _wrkWnd, _screenCenterX + _bkgWidth - _bkgOff + drawRect.left, drawRect.top); + blitSurfaceToSurface(_currentBackgroundImage, drawRect, _backgroundSurface, _screenCenterX + _backgroundWidth - _backgroundOffset + drawRect.left, drawRect.top); - Common::Rect tmp = _bkgDirtyRect; - tmp.translate(_screenCenterX + _bkgWidth - _bkgOff, 0); + Common::Rect tmp = _backgroundDirtyRect; + tmp.translate(_screenCenterX + _backgroundWidth - _backgroundOffset, 0); if (!tmp.isEmpty()) - _wrkWndDirtyRect.extend(tmp); + _backgroundSurfaceDirtyRect.extend(tmp); } } else if (state == RenderTable::TILT) { - Common::Rect viewPort(_wrkWidth, _wrkHeight); - viewPort.translate(0, -(_screenCenterY - _bkgOff)); - Common::Rect drawRect = _bkgDirtyRect; + // Tilt doesn't allow wrapping, so we just do a simple clip + Common::Rect viewPort(_workingWidth, _workingHeight); + viewPort.translate(0, -(_screenCenterY - _backgroundOffset)); + Common::Rect drawRect = _backgroundDirtyRect; drawRect.clip(viewPort); if (!drawRect.isEmpty()) - blitSurfaceToSurface(_curBkg, drawRect, _wrkWnd, drawRect.left, _screenCenterY - _bkgOff + drawRect.top); + blitSurfaceToSurface(_currentBackgroundImage, drawRect, _backgroundSurface, drawRect.left, _screenCenterY - _backgroundOffset + drawRect.top); - _wrkWndDirtyRect = _bkgDirtyRect; - _wrkWndDirtyRect.translate(0, _screenCenterY - _bkgOff); + // Mark the dirty portion of the surface + _backgroundSurfaceDirtyRect = _backgroundDirtyRect; + _backgroundSurfaceDirtyRect.translate(0, _screenCenterY - _backgroundOffset); } else { - if (!_bkgDirtyRect.isEmpty()) - blitSurfaceToSurface(_curBkg, _bkgDirtyRect, _wrkWnd, _bkgDirtyRect.left, _bkgDirtyRect.top); - _wrkWndDirtyRect = _bkgDirtyRect; + if (!_backgroundDirtyRect.isEmpty()) + blitSurfaceToSurface(_currentBackgroundImage, _backgroundDirtyRect, _backgroundSurface, _backgroundDirtyRect.left, _backgroundDirtyRect.top); + _backgroundSurfaceDirtyRect = _backgroundDirtyRect; } - _bkgDirtyRect = Common::Rect(); + // Clear the dirty rect since everything is clean now + _backgroundDirtyRect = Common::Rect(); - _wrkWndDirtyRect.clip(_wrkWidth, _wrkHeight); + _backgroundSurfaceDirtyRect.clip(_workingWidth, _workingHeight); } void RenderManager::clearMenuSurface() { - _menuWndDirtyRect = Common::Rect(0, 0, _menuWnd.w, _menuWnd.h); - _menuWnd.fillRect(_menuWndDirtyRect, 0); + _menuSurfaceDirtyRect = Common::Rect(0, 0, _menuSurface.w, _menuSurface.h); + _menuSurface.fillRect(_menuSurfaceDirtyRect, 0); } void RenderManager::clearMenuSurface(const Common::Rect &r) { - if (_menuWndDirtyRect.isEmpty()) - _menuWndDirtyRect = r; + if (_menuSurfaceDirtyRect.isEmpty()) + _menuSurfaceDirtyRect = r; else - _menuWndDirtyRect.extend(r); - _menuWnd.fillRect(r, 0); + _menuSurfaceDirtyRect.extend(r); + _menuSurface.fillRect(r, 0); } void RenderManager::renderMenuToScreen() { - if (!_menuWndDirtyRect.isEmpty()) { - _menuWndDirtyRect.clip(Common::Rect(_menuWnd.w, _menuWnd.h)); - if (!_menuWndDirtyRect.isEmpty()) - _system->copyRectToScreen(_menuWnd.getBasePtr(_menuWndDirtyRect.left, _menuWndDirtyRect.top), _menuWnd.pitch, - _menuWndDirtyRect.left + _menuWndRect.left, - _menuWndDirtyRect.top + _menuWndRect.top, - _menuWndDirtyRect.width(), - _menuWndDirtyRect.height()); - _menuWndDirtyRect = Common::Rect(); + if (!_menuSurfaceDirtyRect.isEmpty()) { + _menuSurfaceDirtyRect.clip(Common::Rect(_menuSurface.w, _menuSurface.h)); + if (!_menuSurfaceDirtyRect.isEmpty()) + _system->copyRectToScreen(_menuSurface.getBasePtr(_menuSurfaceDirtyRect.left, _menuSurfaceDirtyRect.top), _menuSurface.pitch, + _menuSurfaceDirtyRect.left + _menuArea.left, + _menuSurfaceDirtyRect.top + _menuArea.top, + _menuSurfaceDirtyRect.width(), + _menuSurfaceDirtyRect.height()); + _menuSurfaceDirtyRect = Common::Rect(); } } uint16 RenderManager::createSubArea(const Common::Rect &area) { _subid++; - oneSub sub; + OneSubtitle sub; sub.redraw = false; sub.timer = -1; sub.todelete = false; @@ -801,11 +815,11 @@ uint16 RenderManager::createSubArea(const Common::Rect &area) { uint16 RenderManager::createSubArea() { _subid++; - oneSub sub; + OneSubtitle sub; sub.redraw = false; sub.timer = -1; sub.todelete = false; - sub.r = Common::Rect(_subWndRect.left, _subWndRect.top, _subWndRect.right, _subWndRect.bottom); + sub.r = Common::Rect(_subtitleArea.left, _subtitleArea.top, _subtitleArea.right, _subtitleArea.bottom); sub.r.translate(-_workingWindow.left, -_workingWindow.top); _subsList[_subid] = sub; @@ -825,7 +839,7 @@ void RenderManager::deleteSubArea(uint16 id, int16 delay) { void RenderManager::updateSubArea(uint16 id, const Common::String &txt) { if (_subsList.contains(id)) { - oneSub *sub = &_subsList[id]; + OneSubtitle *sub = &_subsList[id]; sub->txt = txt; sub->redraw = true; } @@ -833,7 +847,7 @@ void RenderManager::updateSubArea(uint16 id, const Common::String &txt) { void RenderManager::processSubs(uint16 deltatime) { bool redraw = false; - for (subMap::iterator it = _subsList.begin(); it != _subsList.end(); it++) { + for (SubtitleMap::iterator it = _subsList.begin(); it != _subsList.end(); it++) { if (it->_value.timer != -1) { it->_value.timer -= deltatime; if (it->_value.timer <= 0) @@ -848,31 +862,31 @@ void RenderManager::processSubs(uint16 deltatime) { } if (redraw) { - _subWnd.fillRect(Common::Rect(_subWnd.w, _subWnd.h), 0); + _subtitleSurface.fillRect(Common::Rect(_subtitleSurface.w, _subtitleSurface.h), 0); - for (subMap::iterator it = _subsList.begin(); it != _subsList.end(); it++) { - oneSub *sub = &it->_value; + for (SubtitleMap::iterator it = _subsList.begin(); it != _subsList.end(); it++) { + OneSubtitle *sub = &it->_value; if (sub->txt.size()) { Graphics::Surface *rndr = new Graphics::Surface(); rndr->create(sub->r.width(), sub->r.height(), _pixelFormat); _engine->getTextRenderer()->drawTxtInOneLine(sub->txt, *rndr); - blitSurfaceToSurface(*rndr, _subWnd, sub->r.left - _subWndRect.left + _workingWindow.left, sub->r.top - _subWndRect.top + _workingWindow.top); + blitSurfaceToSurface(*rndr, _subtitleSurface, sub->r.left - _subtitleArea.left + _workingWindow.left, sub->r.top - _subtitleArea.top + _workingWindow.top); rndr->free(); delete rndr; } sub->redraw = false; } - _system->copyRectToScreen(_subWnd.getPixels(), _subWnd.pitch, - _subWndRect.left, - _subWndRect.top, - _subWnd.w, - _subWnd.h); + _system->copyRectToScreen(_subtitleSurface.getPixels(), _subtitleSurface.pitch, + _subtitleArea.left, + _subtitleArea.top, + _subtitleSurface.w, + _subtitleSurface.h); } } Common::Point RenderManager::getBkgSize() { - return Common::Point(_bkgWidth, _bkgHeight); + return Common::Point(_backgroundWidth, _backgroundHeight); } void RenderManager::addEffect(Effect *_effect) { @@ -880,7 +894,7 @@ void RenderManager::addEffect(Effect *_effect) { } void RenderManager::deleteEffect(uint32 ID) { - for (effectsList::iterator it = _effects.begin(); it != _effects.end(); it++) { + for (EffectsList::iterator it = _effects.begin(); it != _effects.end(); it++) { if ((*it)->getKey() == ID) { delete *it; it = _effects.erase(it); @@ -888,54 +902,54 @@ void RenderManager::deleteEffect(uint32 ID) { } } -Common::Rect RenderManager::bkgRectToScreen(const Common::Rect &src) { +Common::Rect RenderManager::transformBackgroundSpaceRectToScreenSpace(const Common::Rect &src) { Common::Rect tmp = src; RenderTable::RenderState state = _renderTable.getRenderState(); if (state == RenderTable::PANORAMA) { - if (_bkgOff < _screenCenterX) { - Common::Rect rScreen(_screenCenterX + _bkgOff, _wrkHeight); - Common::Rect lScreen(_wrkWidth - rScreen.width(), _wrkHeight); - lScreen.translate(_bkgWidth - lScreen.width(), 0); + if (_backgroundOffset < _screenCenterX) { + Common::Rect rScreen(_screenCenterX + _backgroundOffset, _workingHeight); + Common::Rect lScreen(_workingWidth - rScreen.width(), _workingHeight); + lScreen.translate(_backgroundWidth - lScreen.width(), 0); lScreen.clip(src); rScreen.clip(src); if (rScreen.width() < lScreen.width()) { - tmp.translate(_screenCenterX - _bkgOff - _bkgWidth, 0); + tmp.translate(_screenCenterX - _backgroundOffset - _backgroundWidth, 0); } else { - tmp.translate(_screenCenterX - _bkgOff, 0); + tmp.translate(_screenCenterX - _backgroundOffset, 0); } - } else if (_bkgWidth - _bkgOff < _screenCenterX) { - Common::Rect rScreen(_screenCenterX - (_bkgWidth - _bkgOff), _wrkHeight); - Common::Rect lScreen(_wrkWidth - rScreen.width(), _wrkHeight); - lScreen.translate(_bkgWidth - lScreen.width(), 0); + } else if (_backgroundWidth - _backgroundOffset < _screenCenterX) { + Common::Rect rScreen(_screenCenterX - (_backgroundWidth - _backgroundOffset), _workingHeight); + Common::Rect lScreen(_workingWidth - rScreen.width(), _workingHeight); + lScreen.translate(_backgroundWidth - lScreen.width(), 0); lScreen.clip(src); rScreen.clip(src); if (lScreen.width() < rScreen.width()) { - tmp.translate(_screenCenterX + (_bkgWidth - _bkgOff), 0); + tmp.translate(_screenCenterX + (_backgroundWidth - _backgroundOffset), 0); } else { - tmp.translate(_screenCenterX - _bkgOff, 0); + tmp.translate(_screenCenterX - _backgroundOffset, 0); } } else { - tmp.translate(_screenCenterX - _bkgOff, 0); + tmp.translate(_screenCenterX - _backgroundOffset, 0); } } else if (state == RenderTable::TILT) { - tmp.translate(0, (_screenCenterY - _bkgOff)); + tmp.translate(0, (_screenCenterY - _backgroundOffset)); } return tmp; } EffectMap *RenderManager::makeEffectMap(const Common::Point &xy, int16 depth, const Common::Rect &rect, int8 *_minComp, int8 *_maxComp) { - Common::Rect bkgRect(_bkgWidth, _bkgHeight); + Common::Rect bkgRect(_backgroundWidth, _backgroundHeight); if (!bkgRect.contains(xy)) return NULL; if (!bkgRect.intersects(rect)) return NULL; - uint16 color = *(uint16 *)_curBkg.getBasePtr(xy.x, xy.y); + uint16 color = *(uint16 *)_currentBackgroundImage.getBasePtr(xy.x, xy.y); uint8 stC1, stC2, stC3; - _curBkg.format.colorToRGB(color, stC1, stC2, stC3); + _currentBackgroundImage.format.colorToRGB(color, stC1, stC2, stC3); EffectMap *newMap = new EffectMap; EffectMapUnit unit; @@ -953,11 +967,11 @@ EffectMap *RenderManager::makeEffectMap(const Common::Point &xy, int16 depth, co uint8 depth8 = depth << 3; for (int16 j = 0; j < h; j++) { - uint16 *pix = (uint16 *)_curBkg.getBasePtr(rect.left, rect.top + j); + uint16 *pix = (uint16 *)_currentBackgroundImage.getBasePtr(rect.left, rect.top + j); for (int16 i = 0; i < w; i++) { uint16 curClr = pix[i]; uint8 cC1, cC2, cC3; - _curBkg.format.colorToRGB(curClr, cC1, cC2, cC3); + _currentBackgroundImage.format.colorToRGB(curClr, cC1, cC2, cC3); bool use = false; @@ -1055,11 +1069,11 @@ EffectMap *RenderManager::makeEffectMap(const Graphics::Surface &surf, uint16 tr } void RenderManager::markDirty() { - _bkgDirtyRect = Common::Rect(_bkgWidth, _bkgHeight); + _backgroundDirtyRect = Common::Rect(_backgroundWidth, _backgroundHeight); } void RenderManager::bkgFill(uint8 r, uint8 g, uint8 b) { - _curBkg.fillRect(Common::Rect(_curBkg.w, _curBkg.h), _curBkg.format.RGBToColor(r, g, b)); + _currentBackgroundImage.fillRect(Common::Rect(_currentBackgroundImage.w, _currentBackgroundImage.h), _currentBackgroundImage.format.RGBToColor(r, g, b)); markDirty(); } diff --git a/engines/zvision/graphics/render_manager.h b/engines/zvision/graphics/render_manager.h index 879a8643ce..29bbd8f411 100644 --- a/engines/zvision/graphics/render_manager.h +++ b/engines/zvision/graphics/render_manager.h @@ -52,7 +52,7 @@ public: ~RenderManager(); private: - struct oneSub { + struct OneSubtitle { Common::Rect r; Common::String txt; int16 timer; @@ -60,87 +60,91 @@ private: bool redraw; }; - typedef Common::HashMap subMap; - typedef Common::List effectsList; + typedef Common::HashMap SubtitleMap; + typedef Common::List EffectsList; private: ZVision *_engine; OSystem *_system; const Graphics::PixelFormat _pixelFormat; - // A buffer for blitting background image to working window - Graphics::Surface _wrkWnd; + /** + * A Rectangle centered inside the actual window. All in-game coordinates + * are given in this coordinate space. Also, all images are clipped to the + * edges of this Rectangle + */ + const Common::Rect _workingWindow; - Common::Rect _wrkWndDirtyRect; + // Width of the working window. Saved to prevent extraneous calls to _workingWindow.width() + const int _workingWidth; + // Height of the working window. Saved to prevent extraneous calls to _workingWindow.height() + const int _workingHeight; + // Center of the screen in the x direction + const int _screenCenterX; + // Center of the screen in the y direction + const int _screenCenterY; + + /** A buffer for background image that's being used to create the background */ + Graphics::Surface _currentBackgroundImage; + Common::Rect _backgroundDirtyRect; - // A buffer for mutate image by tilt or panorama renderers - Graphics::Surface _outWnd; + /** + * The x1 or y1 offset of the subRectangle of the background that is currently displayed on the screen + * It will be x1 if PANORAMA, or y1 if TILT + */ + int16 _backgroundOffset; + /** The width of the current background image */ + uint16 _backgroundWidth; + /** The height of the current background image */ + uint16 _backgroundHeight; - Common::Rect _bkgDirtyRect; + // A buffer that holds the portion of the background that is used to render the final image + // If it's a normal scene, the pixels will be blitted directly to the screen + // If it's a panorma / tilt scene, the pixels will be first warped to _warpedSceneSurface + Graphics::Surface _backgroundSurface; + Common::Rect _backgroundSurfaceDirtyRect; // A buffer for subtitles - Graphics::Surface _subWnd; + Graphics::Surface _subtitleSurface; + Common::Rect _subtitleSurfaceDirtyRect; - Common::Rect _subWndDirtyRect; + // Rectangle for subtitles area + Common::Rect _subtitleArea; // A buffer for menu drawing - Graphics::Surface _menuWnd; + Graphics::Surface _menuSurface; + Common::Rect _menuSurfaceDirtyRect; - Common::Rect _menuWndDirtyRect; + // Rectangle for menu area + Common::Rect _menuArea; // A buffer used for apply graphics effects - Graphics::Surface _effectWnd; + Graphics::Surface _effectSurface; - /** Width of the working window. Saved to prevent extraneous calls to _workingWindow.width() */ - const int _wrkWidth; - /** Height of the working window. Saved to prevent extraneous calls to _workingWindow.height() */ - const int _wrkHeight; - /** Center of the screen in the x direction */ - const int _screenCenterX; - /** Center of the screen in the y direction */ - const int _screenCenterY; - - /** - * A Rectangle centered inside the actual window. All in-game coordinates - * are given in this coordinate space. Also, all images are clipped to the - * edges of this Rectangle - */ - const Common::Rect _workingWindow; - - // Recatangle for subtitles area - Common::Rect _subWndRect; + // A buffer to store the result of the panorama / tilt warps + Graphics::Surface _warpedSceneSurface; - // Recatangle for menu area - Common::Rect _menuWndRect; /** Used to warp the background image */ RenderTable _renderTable; - // A buffer for background image - Graphics::Surface _curBkg; - /** The (x1,y1) coordinates of the subRectangle of the background that is currently displayed on the screen */ - int16 _bkgOff; - /** The width of the current background image */ - uint16 _bkgWidth; - /** The height of the current background image */ - uint16 _bkgHeight; - // Internal subtitles counter uint16 _subid; // Subtitle list - subMap _subsList; + SubtitleMap _subsList; // Visual effects list - effectsList _effects; + EffectsList _effects; + public: void initialize(); /** - * Renders the current state of the backbuffer to the screen + * Renders the scene to the screen */ - void renderBackbufferToScreen(); + void renderSceneToScreen(); /** * Blits the image or a portion of the image to the background. @@ -274,7 +278,7 @@ public: void renderMenuToScreen(); // Copy needed portion of background surface to workingWindow surface - void prepareBkg(); + void prepareBackground(); /** * Reads an image file pixel data into a Surface buffer. In the process @@ -319,7 +323,7 @@ public: EffectMap *makeEffectMap(const Graphics::Surface &surf, uint16 transp); // Return background rectangle in screen coordinates - Common::Rect bkgRectToScreen(const Common::Rect &src); + Common::Rect transformBackgroundSpaceRectToScreenSpace(const Common::Rect &src); // Mark whole background surface as dirty void markDirty(); diff --git a/engines/zvision/zvision.cpp b/engines/zvision/zvision.cpp index 4e5307c182..c32cceb26e 100644 --- a/engines/zvision/zvision.cpp +++ b/engines/zvision/zvision.cpp @@ -97,8 +97,8 @@ ZVision::ZVision(OSystem *syst, const ZVisionGameDescription *gameDesc) _textRenderer(nullptr), _halveDelay(false), _audioId(0), - _rendDelay(2), - _kbdVelocity(0), + _frameRenderDelay(2), + _keyboardVelocity(0), _mouseVelocity(0), _videoIsPlaying(false) { @@ -113,7 +113,7 @@ ZVision::ZVision(OSystem *syst, const ZVisionGameDescription *gameDesc) ((WINDOW_HEIGHT - workingWindowHeight) / 2) + workingWindowHeight ); - memset(_cheatBuff, 0, sizeof(_cheatBuff)); + memset(_cheatBuffer, 0, sizeof(_cheatBuffer)); } ZVision::~ZVision() { @@ -233,29 +233,31 @@ Common::Error ZVision::run() { processEvents(); updateRotation(); - // Call _renderManager->update() first so the background renders - // before anything that puzzles/controls will render _scriptManager->update(deltaTime); _menu->process(deltaTime); // Render the backBuffer to the screen - _renderManager->prepareBkg(); + _renderManager->prepareBackground(); _renderManager->renderMenuToScreen(); _renderManager->processSubs(deltaTime); - _renderManager->renderBackbufferToScreen(); + _renderManager->renderSceneToScreen(); // Update the screen - if (_rendDelay <= 0) + if (_frameRenderDelay <= 0) { _system->updateScreen(); - else - _rendDelay--; + } else { + _frameRenderDelay--; + } // Calculate the frame delay based off a desired frame time int delay = _desiredFrameTime - int32(_system->getMillis() - currentTime); // Ensure non-negative delay = delay < 0 ? 0 : delay; - if (_halveDelay) + + if (_halveDelay) { delay >>= 1; + } + _system->delayMillis(delay); } @@ -266,7 +268,7 @@ bool ZVision::askQuestion(const Common::String &str) { uint16 msgid = _renderManager->createSubArea(); _renderManager->updateSubArea(msgid, str); _renderManager->processSubs(0); - _renderManager->renderBackbufferToScreen(); + _renderManager->renderSceneToScreen(); _clock.stop(); int result = 0; @@ -302,7 +304,7 @@ void ZVision::delayedMessage(const Common::String &str, uint16 milsecs) { uint16 msgid = _renderManager->createSubArea(); _renderManager->updateSubArea(msgid, str); _renderManager->processSubs(0); - _renderManager->renderBackbufferToScreen(); + _renderManager->renderSceneToScreen(); _clock.stop(); uint32 stopTime = _system->getMillis() + milsecs; @@ -329,7 +331,7 @@ void ZVision::timedMessage(const Common::String &str, uint16 milsecs) { uint16 msgid = _renderManager->createSubArea(); _renderManager->updateSubArea(msgid, str); _renderManager->processSubs(0); - _renderManager->renderBackbufferToScreen(); + _renderManager->renderSceneToScreen(); _renderManager->deleteSubArea(msgid, milsecs); } @@ -352,15 +354,15 @@ Common::String ZVision::generateAutoSaveFileName() { } void ZVision::setRenderDelay(uint delay) { - _rendDelay = delay; + _frameRenderDelay = delay; } bool ZVision::canRender() { - return _rendDelay <= 0; + return _frameRenderDelay <= 0; } void ZVision::updateRotation() { - int16 _velocity = _mouseVelocity + _kbdVelocity; + int16 _velocity = _mouseVelocity + _keyboardVelocity; if (_halveDelay) _velocity /= 2; @@ -480,8 +482,8 @@ void ZVision::rotateTo(int16 _toPos, int16 _time) { _renderManager->setBackgroundPosition(curX); - _renderManager->prepareBkg(); - _renderManager->renderBackbufferToScreen(); + _renderManager->prepareBackground(); + _renderManager->renderSceneToScreen(); _system->updateScreen(); @@ -512,9 +514,9 @@ bool ZVision::ifQuit() { void ZVision::pushKeyToCheatBuf(uint8 key) { for (int i = 0; i < KEYBUF_SIZE - 1; i++) - _cheatBuff[i] = _cheatBuff[i + 1]; + _cheatBuffer[i] = _cheatBuffer[i + 1]; - _cheatBuff[KEYBUF_SIZE - 1] = key; + _cheatBuffer[KEYBUF_SIZE - 1] = key; } bool ZVision::checkCode(const char *code) { @@ -524,7 +526,7 @@ bool ZVision::checkCode(const char *code) { return false; for (int i = 0; i < codeLen; i++) - if (code[i] != _cheatBuff[KEYBUF_SIZE - codeLen + i] && code[i] != '?') + if (code[i] != _cheatBuffer[KEYBUF_SIZE - codeLen + i] && code[i] != '?') return false; return true; @@ -534,7 +536,7 @@ uint8 ZVision::getBufferedKey(uint8 pos) { if (pos >= KEYBUF_SIZE) return 0; else - return _cheatBuff[KEYBUF_SIZE - pos - 1]; + return _cheatBuffer[KEYBUF_SIZE - pos - 1]; } void ZVision::showDebugMsg(const Common::String &msg, int16 delay) { diff --git a/engines/zvision/zvision.h b/engines/zvision/zvision.h index 78c1c824a1..7ea10ed64d 100644 --- a/engines/zvision/zvision.h +++ b/engines/zvision/zvision.h @@ -117,13 +117,13 @@ private: // To prevent allocation every time we process events Common::Event _event; - int _rendDelay; + int _frameRenderDelay; int16 _mouseVelocity; - int16 _kbdVelocity; + int16 _keyboardVelocity; bool _halveDelay; bool _videoIsPlaying; - uint8 _cheatBuff[KEYBUF_SIZE]; + uint8 _cheatBuffer[KEYBUF_SIZE]; public: uint32 getFeatures() const; Common::Language getLanguage() const; -- cgit v1.2.3 From 808a2045b4a3b210f1f2512617fe1be41c5dc460 Mon Sep 17 00:00:00 2001 From: Adrian Astley Date: Fri, 19 Dec 2014 11:20:01 -0600 Subject: ZVISION: Fix code mis-alignment created from variable rename --- engines/zvision/core/events.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/zvision/core/events.cpp b/engines/zvision/core/events.cpp index fe357c263b..6cf0ae5d0d 100644 --- a/engines/zvision/core/events.cpp +++ b/engines/zvision/core/events.cpp @@ -195,16 +195,16 @@ void ZVision::processEvents() { case Common::KEYCODE_RIGHT: if (_renderManager->getRenderTable()->getRenderState() == RenderTable::PANORAMA) _keyboardVelocity = (_event.kbd.keycode == Common::KEYCODE_LEFT ? - -_scriptManager->getStateValue(StateKey_KbdRotateSpeed) : - _scriptManager->getStateValue(StateKey_KbdRotateSpeed)) * 2; + -_scriptManager->getStateValue(StateKey_KbdRotateSpeed) : + _scriptManager->getStateValue(StateKey_KbdRotateSpeed)) * 2; break; case Common::KEYCODE_UP: case Common::KEYCODE_DOWN: if (_renderManager->getRenderTable()->getRenderState() == RenderTable::TILT) _keyboardVelocity = (_event.kbd.keycode == Common::KEYCODE_UP ? - -_scriptManager->getStateValue(StateKey_KbdRotateSpeed) : - _scriptManager->getStateValue(StateKey_KbdRotateSpeed)) * 2; + -_scriptManager->getStateValue(StateKey_KbdRotateSpeed) : + _scriptManager->getStateValue(StateKey_KbdRotateSpeed)) * 2; break; default: -- cgit v1.2.3 From ff35d7118c0a61a472b74d87337ee62eac993ce1 Mon Sep 17 00:00:00 2001 From: Adrian Astley Date: Wed, 17 Sep 2014 15:49:44 -0500 Subject: SWORD25: Create a set of functions for manually serializing a double Since we can't assume IEEE. --- engines/sword25/util/double_serializer.cpp | 138 +++++++++++++++++++++++++++++ engines/sword25/util/double_serializer.h | 95 ++++++++++++++++++++ 2 files changed, 233 insertions(+) create mode 100644 engines/sword25/util/double_serializer.cpp create mode 100644 engines/sword25/util/double_serializer.h (limited to 'engines') diff --git a/engines/sword25/util/double_serializer.cpp b/engines/sword25/util/double_serializer.cpp new file mode 100644 index 0000000000..d7ba4f3052 --- /dev/null +++ b/engines/sword25/util/double_serializer.cpp @@ -0,0 +1,138 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "sword25/util/double_serializer.h" + +#include "common/scummsys.h" + + +namespace Util { + +SerializedDouble encodeDouble(double value) { + // Split the value into its significand and exponent + int exponent; + double significand = frexp(value, &exponent); + + // Shift the the first part of the significand into the integer range + double shiftedsignificandPart = ldexp(abs(significand), 32); + uint32 significandOne = uint32(floor(shiftedsignificandPart)); + + // Shift the remainder of the significand into the integer range + shiftedsignificandPart -= significandOne; + uint32 significandTwo = (uint32)(ldexp(shiftedsignificandPart, 31)); + + SerializedDouble returnValue; + returnValue.significandOne = significandOne; // SignificandOne + returnValue.signAndSignificandTwo = ((uint32)(value < 0 ? 1 : 0) << 31) | // Sign + significandTwo; // SignificandTwo + returnValue.exponent = (int16)exponent; + return returnValue; +} + +double decodeDouble(SerializedDouble value) { + // Expand the exponent and the parts of the significand + int exponent = (int)value.exponent; + double expandedsignificandOne = (double)value.significandOne; + double expandedsignificandTwo = (double)(value.signAndSignificandTwo & 0x7FFFFFFF); + + // Deflate the significand + double shiftedsignificand = ldexp(expandedsignificandTwo, -21); + double significand = ldexp(expandedsignificandOne + shiftedsignificand, -32); + + // Re-calculate the actual double + double returnValue = ldexp(significand, exponent); + + // Check the sign bit and return + return ((value.signAndSignificandTwo & 0x80000000) == 0x80000000) ? -returnValue : returnValue; +} + +uint64 encodeDouble_64(double value) { + // Split the value into its significand and exponent + int exponent; + double significand = frexp(value, &exponent); + + // Shift the significand into the integer range + double shiftedsignificand = ldexp(abs(significand), 53); + + // Combine everything using the IEEE standard + uint64 uintsignificand = (uint64)shiftedsignificand; + return ((uint64)(value < 0 ? 1 : 0) << 63) | // Sign + ((uint64)(exponent + 1023) << 52) | // Exponent stored as an offset to 1023 + (uintsignificand & 0x000FFFFFFFFFFFFF); // significand with MSB inferred +} + +double decodeDouble_64(uint64 value) { + // Expand the exponent and significand + int exponent = (int)((value >> 52) & 0x7FF) - 1023; + double expandedsignificand = (double)(0x10000000000000 /* Inferred MSB */ | (value & 0x000FFFFFFFFFFFFF)); + + // Deflate the significand + int temp; + double significand = frexp(expandedsignificand, &temp); + + // Re-calculate the actual double + double returnValue = ldexp(significand, exponent); + + // Check the sign bit and return + return ((value & 0x8000000000000000) == 0x8000000000000000) ? -returnValue : returnValue; +} + +CompactSerializedDouble encodeDouble_Compact(double value) { + // Split the value into its significand and exponent + int exponent; + double significand = frexp(value, &exponent); + + // Shift the the first part of the significand into the integer range + double shiftedsignificandPart = ldexp(abs(significand), 32); + uint32 significandOne = uint32(floor(shiftedsignificandPart)); + + // Shift the remainder of the significand into the integer range + shiftedsignificandPart -= significandOne; + uint32 significandTwo = (uint32)(ldexp(shiftedsignificandPart, 21)); + + CompactSerializedDouble returnValue; + returnValue.signAndSignificandOne = ((uint32)(value < 0 ? 1 : 0) << 31) | // Sign + (significandOne & 0x7FFFFFFF); // significandOne with MSB inferred + // Exponent stored as an offset to 1023 + returnValue.exponentAndSignificandTwo = ((uint32)(exponent + 1023) << 21) | significandTwo; + + return returnValue; +} + +double decodeDouble_Compact(CompactSerializedDouble value) { + // Expand the exponent and the parts of the significand + int exponent = (int)(value.exponentAndSignificandTwo >> 21) - 1023; + double expandedsignificandOne = (double)(0x80000000 /* Inferred MSB */ | (value.signAndSignificandOne & 0x7FFFFFFF)); + double expandedsignificandTwo = (double)(value.exponentAndSignificandTwo & 0x1FFFFF); + + // Deflate the significand + double shiftedsignificand = ldexp(expandedsignificandTwo, -21); + double significand = ldexp(expandedsignificandOne + shiftedsignificand, -32); + + // Re-calculate the actual double + double returnValue = ldexp(significand, exponent); + + // Check the sign bit and return + return ((value.signAndSignificandOne & 0x80000000) == 0x80000000) ? -returnValue : returnValue; +} + +} // End of namespace Sword25 diff --git a/engines/sword25/util/double_serializer.h b/engines/sword25/util/double_serializer.h new file mode 100644 index 0000000000..e90338c369 --- /dev/null +++ b/engines/sword25/util/double_serializer.h @@ -0,0 +1,95 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef DOUBLE_SERIALIZATION_H +#define DOUBLE_SERIALIZATION_H + +#include "common/types.h" + + +namespace Util { + +struct SerializedDouble { + uint32 significandOne; + uint32 signAndSignificandTwo; + int16 exponent; +}; + +struct CompactSerializedDouble { + uint32 signAndSignificandOne; + uint32 exponentAndSignificandTwo; +}; + +/** + * Encodes a double as two uint32 and a one int16 + * + * Supports denormalized numbers. Does NOT support NaN, or Inf + * + * @param value The value to encode + * @return The encoded value + */ +SerializedDouble encodeDouble(double value); +/** + * Decodes a previously encoded double + * + * @param value The value to decode + * @return The decoded value + */ +double decodeDouble(SerializedDouble value); + +/** + * Encodes a double as a uint64 + * + * Does NOT support denormalized numbers. Does NOT support NaN, or Inf + * + * @param value The value to encode + * @return The encoded value + */ +uint64 encodeDouble_64(double value); +/** + * Decodes a previously encoded double + * + * @param value The value to decode + * @return The decoded value + */ +double decodeDouble_64(uint64 value); + +/** + * Encodes a double as two uint32 + * + * Does NOT support denormalized numbers. Does NOT support NaN, or Inf + * + * @param value The value to encode + * @return The encoded value + */ +CompactSerializedDouble encodeDouble_Compact(double value); +/** + * Decodes a previously encoded double + * + * @param value The value to decode + * @return The decoded value + */ +double decodeDouble_Compact(CompactSerializedDouble value); + +} // End of namespace Sword25 + +#endif -- cgit v1.2.3 From efcd6196eeaa2bff468bbed8d07040e60ca3c136 Mon Sep 17 00:00:00 2001 From: Adrian Astley Date: Wed, 17 Sep 2014 15:52:26 -0500 Subject: SWORD25: Create a function for serializing lua objects This function is very similar to the Pluto function. However, this code is much cleaner and is endian-safe --- engines/sword25/util/lua_serialization.h | 42 ++ engines/sword25/util/lua_serializer.cpp | 852 +++++++++++++++++++++++++++++++ 2 files changed, 894 insertions(+) create mode 100644 engines/sword25/util/lua_serialization.h create mode 100644 engines/sword25/util/lua_serializer.cpp (limited to 'engines') diff --git a/engines/sword25/util/lua_serialization.h b/engines/sword25/util/lua_serialization.h new file mode 100644 index 0000000000..0f0c3bd0b2 --- /dev/null +++ b/engines/sword25/util/lua_serialization.h @@ -0,0 +1,42 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef LUA_SERIALIZATION_H +#define LUA_SERIALIZATION_H + +#include "sword25/util/lua/lua.h" + + +namespace Common { +class WriteStream; +} + + +namespace Lua { + +#define PERMANENT_TYPE 101 + +void serializeLua(lua_State *luaState, Common::WriteStream *writeStream); + +} // End of namespace Lua + +#endif diff --git a/engines/sword25/util/lua_serializer.cpp b/engines/sword25/util/lua_serializer.cpp new file mode 100644 index 0000000000..b2bbca6be9 --- /dev/null +++ b/engines/sword25/util/lua_serializer.cpp @@ -0,0 +1,852 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "sword25/util/lua_serialization.h" + +#include "sword25/util/double_serializer.h" + +#include "common/stream.h" + +#include "lua/lobject.h" +#include "lua/lstate.h" + + +namespace Lua { + +#define NUMTYPES 9 + +static const char* typenames[] = { + "nil", + "boolean", + "lightuserdata", + "number", + "string", + "table", + "function", + "userdata", + "thread" +}; + +#define PERMANENT_TYPE 101 + +/* A simple reimplementation of the unfortunately static function luaA_index. + * Does not support the global table, registry, or upvalues. */ +static StkId getobject(lua_State *luaState, int stackpos) { + if(stackpos > 0) { + lua_assert(luaState->base+stackpos-1 < luaState->top); + return luaState->base+stackpos-1; + } else { + lua_assert(L->top-stackpos >= L->base); + return luaState->top+stackpos; + } +} + + +struct SerializationInfo { + lua_State *luaState; + Common::WriteStream *writeStream; + uint counter; +}; + +static void serializeObject(SerializationInfo *info); + +static void serializeBoolean(SerializationInfo *info); +static void serializeLightUserData(SerializationInfo *info); +static void serializeNumber(SerializationInfo *info); +static void serializeString(SerializationInfo *info); +static void serializeTable(SerializationInfo *info); +static void serializeFunction(SerializationInfo *info); +static void serializeThread(SerializationInfo *info); +static void serializeProto(SerializationInfo *info); +static void serializeUpValue(SerializationInfo *info); +static void serializeUserData(SerializationInfo *info); + + +void serializeLua(lua_State *luaState, Common::WriteStream *writeStream) { + SerializationInfo info; + info.luaState = luaState; + info.writeStream = writeStream; + info.counter = 0u; + + // The process starts with the lua stack as follows: + // >>>>> permTbl rootObj + // That's the table of permanents and the root object to be serialized + + // Make sure there is enough room on the stack + lua_checkstack(luaState, 4); + assert(lua_gettop(luaState) == 2); + // And that the root isn't nil + assert(!lua_isnil(luaState, 2)); + + // Create a table to hold indexes of everything that's serialized + // This allows us to only serialize an object once + // Every other time, just reference the index + lua_newtable(luaState); + // >>>>> permTbl rootObj indexTbl + + // Now we're going to make the table weakly keyed. This prevents the + // GC from visiting it and trying to mark things it doesn't want to + // mark in tables, e.g. upvalues. All objects in the table are + // a priori reachable, so it doesn't matter that we do this. + + // Create the metatable + lua_newtable(luaState); + // >>>>> permTbl rootObj indexTbl metaTbl + + lua_pushstring(luaState, "__mode"); + // >>>>> permTbl rootObj indexTbl metaTbl "__mode" + + lua_pushstring(luaState, "k"); + // >>>>> permTbl rootObj indexTbl metaTbl "__mode" "k" + + lua_settable(luaState, 4); + // >>>>> permTbl rootObj indexTbl metaTbl + + lua_setmetatable(luaState, 3); + // >>>>> permTbl rootObj indexTbl + + // Swap the indexTable and the rootObj + lua_insert(luaState, 2); + // >>>>> permTbl indexTbl rootObj + + // Serialize the root recursively + serializeObject(&info); + + // Return the stack back to the original state + lua_remove(luaState, 2); + // >>>>> permTbl rootObj +} + +static void serializeObject(SerializationInfo *info) { + // The stack can potentially have many things on it + // The object we want to serialize is the item on the top of the stack + // >>>>> permTbl indexTbl rootObj ...... obj + + // Make sure there is enough room on the stack + lua_checkstack(info->luaState, 2); + + // If the object has already been written, don't write it again + // Instead write the index of the object from the indexTbl + + // Check the indexTbl + lua_pushvalue(info->luaState, -1); + // >>>>> permTbl indexTbl rootObj ...... obj obj + + lua_rawget(info->luaState, 2); + // >>>>> permTbl indexTbl rootObj ...... obj ?index? + + // If the index isn't nil, the object has already been written + if (!lua_isnil(info->luaState, -1)) { + // Write out a flag that indicates that it's an index + info->writeStream->writeByte(0); + + // Retrieve the index from the stack + uint *index = (uint *)lua_touserdata(info->luaState, -1); + + // Write out the index + info->writeStream->writeUint32LE(*index); + + // Pop the index off the stack + lua_pop(info->luaState, 1); + + return; + } + + // Pop the nil off the stack + lua_pop(info->luaState, 1); + + // Write out a flag that indicates that this is a real object + info->writeStream->writeByte(1); + + // If the object itself is nil, then write out a zero as a placeholder + if (lua_isnil(info->luaState, -1)) { + info->writeStream->writeByte(0); + + return; + } + + // Add the object to the indexTbl + + lua_pushvalue(info->luaState, -1); + // >>>>> permTbl indexTbl rootObj ...... obj obj + + uint *ref = (uint *)lua_newuserdata(info->luaState, sizeof(uint)); + *ref = ++(info->counter); + // >>>>> permTbl indexTbl rootObj ...... obj obj index + + lua_rawset(info->luaState, 2); + // >>>>> permTbl indexTbl rootObj ...... obj + + + // Write out the index + info->writeStream->writeUint32LE(info->counter); + + + // Objects that are in the permanents table are serialized in a special way + + lua_pushvalue(info->luaState, -1); + // >>>>> permTbl indexTbl rootObj ...... obj obj + + lua_gettable(info->luaState, 1); + // >>>>> permTbl indexTbl rootObj ...... obj obj ?permKey? + + if (!lua_isnil(info->luaState, -1)) { + // Write out the type + info->writeStream->writeSint32LE(PERMANENT_TYPE); + + // Serialize the key + serializeObject(info); + + // Pop the key off the stack + lua_pop(info->luaState, 1); + + return; + } + + // Pop the nil off the stack + lua_pop(info->luaState, 1); + + // Query the type of the object + int objType = lua_type(info->luaState, -1); + + // Write it out + info->writeStream->writeSint32LE(objType); + + // Serialize the object by its type + + switch (objType) { + case LUA_TBOOLEAN: + serializeBoolean(info); + break; + case LUA_TLIGHTUSERDATA: + // You can't serialize a pointer + // It would be meaningless on the next run + assert(0); + break; + case LUA_TNUMBER: + serializeNumber(info); + break; + case LUA_TSTRING: + serializeString(info); + break; + case LUA_TTABLE: + serializeTable(info); + break; + case LUA_TFUNCTION: + serializeFunction(info); + break; + case LUA_TTHREAD: + serializeThread(info); + break; + case LUA_TPROTO: + serializeProto(info); + break; + case LUA_TUPVAL: + serializeUpValue(info); + break; + case LUA_TUSERDATA: + serializeUserData(info); + break; + default: + assert(0); + } +} + +static void serializeBoolean(SerializationInfo *info) { + int value = lua_toboolean(info->luaState, -1); + + info->writeStream->writeSint32LE(value); +} + +static void serializeNumber(SerializationInfo *info) { + lua_Number value = lua_tonumber(info->luaState, -1); + +#if 1 + Util::SerializedDouble serializedValue(Util::encodeDouble(value)); + + info->writeStream->writeUint32LE(serializedValue.significandOne); + info->writeStream->writeUint32LE(serializedValue.signAndSignificandTwo); + info->writeStream->writeSint16LE(serializedValue.exponent); +#else + // NOTE: We need to store a double. Unfortunately, we have to accommodate endianness. + // Also, I don't know if we can assume all compilers use IEEE double + // Therefore, I have chosen to store the double as a string. + Common::String buffer = Common::String::format("%f", value); + + info->writeStream->write(buffer.c_str(), buffer.size()); +#endif + +} + +static void serializeString(SerializationInfo *info) { + // Hard cast to a uint32 to force size_t to an explicit size + // *Theoretically* this could truncate, but if we have a 4gb string, we have bigger problems + uint32 length = static_cast(lua_strlen(info->luaState, -1)); + info->writeStream->writeUint32LE(length); + + const char* str = lua_tostring(info->luaState, -1); + info->writeStream->write(str, length); +} + +/* Choose whether to do a regular or special persistence based on an object's + * metatable. "default" is whether the object, if it doesn't have a __persist + * entry, is literally persistable or not. + * Pushes the unpersist closure and returns true if special persistence is + * used. */ +static bool serializeSpecialObject(SerializationInfo *info, bool defaction) { + // Make sure there is enough room on the stack + lua_checkstack(info->luaState, 4); + + // Check whether we should persist literally, or via the __persist metafunction + if (!lua_getmetatable(info->luaState, -1)) { + if (defaction) { + // Write out a flag declaring that the metatable doesn't exist + info->writeStream->writeSint32LE(0); + + return false; + } else { + lua_pushstring(info->luaState, "Type not literally persistable by default"); + lua_error(info->luaState); + } + } + + // >>>>> permTbl indexTbl ...... obj metaTbl + lua_pushstring(info->luaState, "__persist"); + // >>>>> permTbl indexTbl rootObj ...... obj metaTbl "__persist" + + lua_rawget(info->luaState, -2); + // >>>>> permTbl indexTbl ...... obj metaTbl ?__persist? + + if (lua_isnil(info->luaState, -1)) { + // >>>>> permTbl indexTbl ...... obj metaTbl nil + lua_pop(info->luaState, 2); + // >>>>> permTbl indexTbl ...... obj + + if (defaction) { + // Write out a flag declaring there is no persistence metafunction + info->writeStream->writeSint32LE(0); + + return 0; + } else { + lua_pushstring(info->luaState, "Type not literally persistable by default"); + lua_error(info->luaState); + + return 0; /* not reached */ + } + + } else if (lua_isboolean(info->luaState, -1)) { + // >>>>> permTbl indexTbl ...... obj metaTbl bool + if (lua_toboolean(info->luaState, -1)) { + // Write out a flag declaring such + info->writeStream->writeSint32LE(0); + + // >>>>> permTbl indexTbl ...... obj metaTbl true */ + lua_pop(info->luaState, 2); + // >>>>> permTbl indexTbl ...... obj + + return false; + } else { + lua_pushstring(info->luaState, "Metatable forbade persistence"); + lua_error(info->luaState); + + return false; /* not reached */ + } + } else if (!lua_isfunction(info->luaState, -1)) { + lua_pushstring(info->luaState, "__persist not nil, boolean, or function"); + lua_error(info->luaState); + } + + // >>>>> permTbl indexTbl ...... obj metaTbl __persist + lua_pushvalue(info->luaState, -3); + // >>>>> permTbl indexTbl ...... obj metaTbl __persist obj + + // >>>>> permTbl indexTbl ...... obj metaTbl ?func? + + if (!lua_isfunction(info->luaState, -1)) { + lua_pushstring(info->luaState, "__persist function did not return a function"); + lua_error(info->luaState); + } + + // >>>>> permTbl indexTbl ...... obj metaTbl func + + // Write out a flag that the function exists + info->writeStream->writeSint32LE(1); + + // Serialize the function + serializeObject(info); + + lua_pop(info->luaState, 2); + // >>>>> permTbl indexTbl ...... obj + + return true; +} + +static void serializeTable(SerializationInfo *info) { + // >>>>> permTbl indexTbl ...... tbl + + // Make sure there is enough room on the stack + lua_checkstack(info->luaState, 3); + + // Test if the object needs special serialization + if (serializeSpecialObject(info, 1)) { + return; + } + + // >>>>> permTbl indexTbl ...... tbl + + // First, serialize the metatable (if any) + if (!lua_getmetatable(info->luaState, -1)) { + lua_pushnil(info->luaState); + } + + // >>>>> permTbl indexTbl ...... tbl metaTbl/nil */ + serializeObject(info); + + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... tbl + + + lua_pushnil(info->luaState); + // >>>>> permTbl indexTbl ...... tbl nil + + // Now, persist all k/v pairs + while (lua_next(info->luaState, -2)) { + // >>>>> permTbl indexTbl ...... tbl k v */ + + lua_pushvalue(info->luaState, -2); + // >>>>> permTbl indexTbl ...... tbl k v k */ + + // Serialize the key + serializeObject(info); + + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... tbl k v */ + + // Serialize the value + serializeObject(info); + + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... tbl k */ + } + + // >>>>> permTbl indexTbl ...... tbl + + // Terminate the list with a nil + lua_pushnil(info->luaState); + // >>>>> permTbl indexTbl ...... tbl + + serializeObject(info); + + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... tbl +} + +static void pushObject(lua_State *luaState, TValue *obj) { + setobj2s(luaState, luaState->top, obj); + + api_check(luaState, luaState->top < luaState->ci->top); + luaState->top++; +} + +static void pushProto(lua_State *luaState, Proto *proto) { + TValue obj; + setptvalue(luaState, &obj, proto); + + pushObject(luaState, &obj); +} + +static void pushUpVal(lua_State *luaState, UpVal *upval) { + TValue obj; + + obj.value.gc = cast(GCObject *, upval); + obj.tt = LUA_TUPVAL; + checkliveness(G(L), obj); + + pushObject(luaState, &obj); +} + +static void pushString(lua_State *luaState, TString *str) { + TValue o; + setsvalue(luaState, &o, str); + + pushObject(luaState, &o); +} + +static void serializeFunction(SerializationInfo *info) { + // >>>>> permTbl indexTbl ...... func + Closure *cl = clvalue(getobject(info->luaState, -1)); + lua_checkstack(info->luaState, 2); + + if (cl->c.isC) { + /* It's a C function. For now, we aren't going to allow + * persistence of C closures, even if the "C proto" is + * already in the permanents table. */ + lua_pushstring(info->luaState, "Attempt to persist a C function"); + lua_error(info->luaState); + } else { + // It's a Lua closure + + // We don't really _NEED_ the number of upvals, but it'll simplify things a bit + info->writeStream->writeByte(cl->l.p->nups); + + // Serialize the prototype + pushProto(info->luaState, cl->l.p); + // >>>>> permTbl indexTbl ...... func proto */ + + serializeObject(info); + + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... func + + // Serialize upvalue values (not the upvalue objects themselves) + for (byte i=0; il.p->nups; i++) { + // >>>>> permTbl indexTbl ...... func + pushUpVal(info->luaState, cl->l.upvals[i]); + // >>>>> permTbl indexTbl ...... func upval + + serializeObject(info); + + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... func + } + + // >>>>> permTbl indexTbl ...... func + + // Serialize function environment + lua_getfenv(info->luaState, -1); + // >>>>> permTbl indexTbl ...... func fenv + + if (lua_equal(info->luaState, -1, LUA_GLOBALSINDEX)) { + // Function has the default fenv + + // >>>>> permTbl indexTbl ...... func _G + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... func + + lua_pushnil(info->luaState); + // >>>>> permTbl indexTbl ...... func nil + } + + // >>>>> permTbl indexTbl ...... func fenv/nil + serializeObject(info); + + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... func + } +} + +/* Appends one stack to another stack, but the stack is reversed in the process */ +static size_t appendStackToStack_rev(lua_State *from, lua_State *to) { + for (StkId id = from->top - 1; id >= from->stack; --id) { + setobj2s(to, to->top, id); + to->top++; + } + + return from->top - from->stack; +} + +static void serializeThread(SerializationInfo *info) { + // >>>>> permTbl indexTbl ...... thread + lua_State *threadState = lua_tothread(info->luaState, -1); + + // Make sure there is enough room on the stack + lua_checkstack(info->luaState, threadState->top - threadState->stack + 1); + + if (info->luaState == threadState) { + lua_pushstring(info->luaState, "Can't persist currently running thread"); + lua_error(info->luaState); + return; /* not reached */ + } + + // Persist the stack + + // We *could* have truncation here, but if we have more than 4 billion items on a stack, we have bigger problems + uint stackSize = static_cast(appendStackToStack_rev(threadState, info->luaState)); + info->writeStream->writeUint32LE(stackSize); + + // >>>>> permTbl indexTbl ...... thread (reversed contents of thread stack) */ + for (; stackSize > 0; --stackSize) { + serializeObject(info); + + lua_pop(info->luaState, 1); + } + + // >>>>> permTbl indexTbl ...... thread + + // Now, serialize the CallInfo stack + + // Again, we *could* have truncation here, but if we have more than 4 billion items on a stack, we have bigger problems + uint32 numFrames = static_cast((threadState->ci - threadState->base_ci) + 1); + info->writeStream->writeUint32LE(numFrames); + + for (uint32 i = 0; i < numFrames; i++) { + CallInfo *ci = threadState->base_ci + i; + + // Same argument as above about truncation + uint32 stackBase = static_cast(ci->base - threadState->stack); + uint32 stackFunc = static_cast(ci->func - threadState->stack); + uint32 stackTop = static_cast(ci->top - threadState->stack); + + info->writeStream->writeUint32LE(stackBase); + info->writeStream->writeUint32LE(stackFunc); + info->writeStream->writeUint32LE(stackTop); + + info->writeStream->writeSint32LE(ci->nresults); + + uint32 savedpc = (ci != threadState->base_ci) ? static_cast(ci->savedpc - ci_func(ci)->l.p->code) : 0u; + info->writeStream->writeUint32LE(savedpc); + } + + + // Serialize the state's other parameters, with the exception of upval stuff + + assert(threadState->nCcalls <= 1); + info->writeStream->writeByte(threadState->status); + + // Same argument as above about truncation + uint32 stackBase = static_cast(threadState->base - threadState->stack); + uint32 stackFunc = static_cast(threadState->top - threadState->stack); + info->writeStream->writeUint32LE(stackBase); + info->writeStream->writeUint32LE(stackFunc); + + // Same argument as above about truncation + uint32 stackOffset = static_cast(threadState->errfunc); + info->writeStream->writeUint32LE(stackOffset); + + // Finally, record upvalues which need to be reopened + // See the comment above serializeUpVal() for why we do this + + UpVal *upVal; + + // >>>>> permTbl indexTbl ...... thread + for (GCObject *gcObject = threadState->openupval; gcObject != NULL; gcObject = upVal->next) { + upVal = gco2uv(gcObject); + + /* Make sure upvalue is really open */ + assert(upVal->v != &upVal->u.value); + + pushUpVal(info->luaState, upVal); + // >>>>> permTbl indexTbl ...... thread upVal + + serializeObject(info); + + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... thread + + // Same argument as above about truncation + uint32 stackpos = static_cast(upVal->v - threadState->stack); + info->writeStream->writeUint32LE(stackpos); + } + + // >>>>> permTbl indexTbl ...... thread + lua_pushnil(info->luaState); + // >>>>> permTbl indexTbl ...... thread nil + + // Use nil as a terminator + serializeObject(info); + + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... thread +} + +static void serializeProto(SerializationInfo *info) { + // >>>>> permTbl indexTbl ...... proto + Proto *proto = gco2p(getobject(info->luaState, -1)->value.gc); + + // Make sure there is enough room on the stack + lua_checkstack(info->luaState, 2); + + // Serialize constant refs */ + info->writeStream->writeSint32LE(proto->sizek); + + for (int i = 0; i < proto->sizek; ++i) { + pushObject(info->luaState, &proto->k[i]); + // >>>>> permTbl indexTbl ...... proto const + + serializeObject(info); + + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... proto + } + + // >>>>> permTbl indexTbl ...... proto + + // Serialize inner Proto refs + info->writeStream->writeSint32LE(proto->sizep); + + for (int i = 0; i < proto->sizep; ++i) + { + pushProto(info->luaState, proto->p[i]); + // >>>>> permTbl indexTbl ...... proto subProto */ + + serializeObject(info); + + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... proto + } + + // >>>>> permTbl indexTbl ...... proto + + // Serialize the code + info->writeStream->writeSint32LE(proto->sizecode); + + uint32 len = static_cast(sizeof(Instruction) * proto->sizecode); + info->writeStream->write(proto->code, len); + + + // Serialize upvalue names + info->writeStream->writeSint32LE(proto->sizeupvalues); + + for (int i = 0; i < proto->sizeupvalues; ++i) + { + pushString(info->luaState, proto->upvalues[i]); + // >>>>> permTbl indexTbl ...... proto str + + serializeObject(info); + + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... proto + } + + + // Serialize local variable infos + info->writeStream->writeSint32LE(proto->sizelocvars); + + for (int i = 0; i < proto->sizelocvars; ++i) { + pushString(info->luaState, proto->locvars[i].varname); + // >>>>> permTbl indexTbl ...... proto str + + serializeObject(info); + + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... proto + + info->writeStream->writeSint32LE(proto->locvars[i].startpc); + info->writeStream->writeSint32LE(proto->locvars[i].endpc); + } + + + // Serialize source string + pushString(info->luaState, proto->source); + // >>>>> permTbl indexTbl ...... proto sourceStr + + serializeObject(info); + + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... proto + + // Serialize line numbers + info->writeStream->writeSint32LE(proto->sizelineinfo); + + if (proto->sizelineinfo) { + uint32 len = static_cast(sizeof(int) * proto->sizelineinfo); + info->writeStream->write(proto->lineinfo, len); + } + + // Serialize linedefined and lastlinedefined + info->writeStream->writeSint32LE(proto->linedefined); + info->writeStream->writeSint32LE(proto->lastlinedefined); + + + // Serialize misc values + info->writeStream->writeByte(proto->nups); + info->writeStream->writeByte(proto->numparams); + info->writeStream->writeByte(proto->is_vararg); + info->writeStream->writeByte(proto->maxstacksize); +} + +/* Upvalues are tricky. Here's why. + * + * A particular upvalue may be either "open", in which case its member v + * points into a thread's stack, or "closed" in which case it points to the + * upvalue itself. An upvalue is closed under any of the following conditions: + * -- The function that initially declared the variable "local" returns + * -- The thread in which the closure was created is garbage collected + * + * To make things wackier, just because a thread is reachable by Lua doesn't + * mean it's in our root set. We need to be able to treat an open upvalue + * from an unreachable thread as a closed upvalue. + * + * The solution: + * (a) For the purposes of serializing, don't indicate whether an upvalue is + * closed or not. + * (b) When unserializing, pretend that all upvalues are closed. + * (c) When serializing, persist all open upvalues referenced by a thread + * that is persisted, and tag each one with the corresponding stack position + * (d) When unserializing, "reopen" each of these upvalues as the thread is + * unserialized + */ +static void serializeUpValue(SerializationInfo *info) { + // >>>>> permTbl indexTbl ...... upval + assert(ttype(getobject(info->luaState, -1)) == LUA_TUPVAL); + UpVal *upValue = gco2uv(getobject(info->luaState, -1)->value.gc); + + // Make sure there is enough room on the stack + lua_checkstack(info->luaState, 1); + + // We can't permit the upValue to linger around on the stack, as Lua + // will bail if its GC finds it. + + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... + + pushObject(info->luaState, upValue->v); + // >>>>> permTbl indexTbl ...... obj + + serializeObject(info); + // >>>>> permTbl indexTbl ...... obj +} + +static void serializeUserData(SerializationInfo *info) { + // >>>>> permTbl rootObj ...... udata + + // Make sure there is enough room on the stack + lua_checkstack(info->luaState, 2); + + // Test if the object needs special serialization + if (serializeSpecialObject(info, 0)) { + return; + } + + // Use literal persistence + + // Hard cast to a uint32 length + // This could lead to truncation, but if we have a 4gb block of data, we have bigger problems + uint32 length = static_cast(uvalue(getobject(info->luaState, -1))->len); + info->writeStream->writeUint32LE(length); + + info->writeStream->write(lua_touserdata(info->luaState, -1), length); + + // Serialize the metatable (if any) + if (!lua_getmetatable(info->luaState, -1)) { + lua_pushnil(info->luaState); + } + + // >>>>> permTbl rootObj ...... udata metaTbl/nil + serializeObject(info); + + lua_pop(info->luaState, 1); + /* perms reftbl ... udata */ +} + + +} // End of namespace Lua -- cgit v1.2.3 From dedfd7aa84360b5950b653109b3679c7f469aebc Mon Sep 17 00:00:00 2001 From: Adrian Astley Date: Fri, 19 Dec 2014 13:38:26 -0600 Subject: SWORD25: Move common functions to their own set of files so they can be shared --- engines/sword25/util/lua_serialization_util.cpp | 77 +++++++++++++++++++++ engines/sword25/util/lua_serialization_util.h | 43 ++++++++++++ engines/sword25/util/lua_serializer.cpp | 91 +++++-------------------- 3 files changed, 138 insertions(+), 73 deletions(-) create mode 100644 engines/sword25/util/lua_serialization_util.cpp create mode 100644 engines/sword25/util/lua_serialization_util.h (limited to 'engines') diff --git a/engines/sword25/util/lua_serialization_util.cpp b/engines/sword25/util/lua_serialization_util.cpp new file mode 100644 index 0000000000..80009aff60 --- /dev/null +++ b/engines/sword25/util/lua_serialization_util.cpp @@ -0,0 +1,77 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distri8buted in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "sword25/util/lua_serialization_util.h" + +#include "common/scummsys.h" + +#include "lua/lobject.h" +#include "lua/lstate.h" +#include "lua/lgc.h" + + +namespace Lua { + +void pushObject(lua_State *luaState, TValue *obj) { + setobj2s(luaState, luaState->top, obj); + + api_check(luaState, luaState->top < luaState->ci->top); + luaState->top++; +} + +void pushProto(lua_State *luaState, Proto *proto) { + TValue obj; + setptvalue(luaState, &obj, proto); + + pushObject(luaState, &obj); +} + +void pushUpValue(lua_State *luaState, UpVal *upval) { + TValue obj; + + obj.value.gc = cast(GCObject *, upval); + obj.tt = LUA_TUPVAL; + checkliveness(G(L), obj); + + pushObject(luaState, &obj); +} + +void pushString(lua_State *luaState, TString *str) { + TValue o; + setsvalue(luaState, &o, str); + + pushObject(luaState, &o); +} + +/* A simple reimplementation of the unfortunately static function luaA_index. + * Does not support the global table, registry, or upvalues. */ +StkId getObject(lua_State *luaState, int stackpos) { + if(stackpos > 0) { + lua_assert(luaState->base+stackpos-1 < luaState->top); + return luaState->base+stackpos-1; + } else { + lua_assert(L->top-stackpos >= L->base); + return luaState->top+stackpos; + } +} + +} // End of namespace Lua diff --git a/engines/sword25/util/lua_serialization_util.h b/engines/sword25/util/lua_serialization_util.h new file mode 100644 index 0000000000..6c55d0dd53 --- /dev/null +++ b/engines/sword25/util/lua_serialization_util.h @@ -0,0 +1,43 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distri8buted in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef LUA_SERIALIZATION_UTIL_H +#define LUA_SERIALIZATION_UTIL_H + + +struct lua_State; + +#include "lua/lobject.h" + +typedef TValue *StkId; + +namespace Lua { + +void pushObject(lua_State *luaState, TValue *obj); +void pushProto(lua_State *luaState, Proto *proto); +void pushUpValue(lua_State *luaState, UpVal *upval); +void pushString(lua_State *luaState, TString *str); +StkId getObject(lua_State *luaState, int stackpos); + +} // End of namespace Lua + +#endif diff --git a/engines/sword25/util/lua_serializer.cpp b/engines/sword25/util/lua_serializer.cpp index b2bbca6be9..8c61383fba 100644 --- a/engines/sword25/util/lua_serializer.cpp +++ b/engines/sword25/util/lua_serializer.cpp @@ -23,44 +23,19 @@ #include "sword25/util/lua_serialization.h" #include "sword25/util/double_serializer.h" +#include "sword25/util/lua_serialization_util.h" #include "common/stream.h" #include "lua/lobject.h" #include "lua/lstate.h" +#include "lua/lgc.h" namespace Lua { -#define NUMTYPES 9 - -static const char* typenames[] = { - "nil", - "boolean", - "lightuserdata", - "number", - "string", - "table", - "function", - "userdata", - "thread" -}; - #define PERMANENT_TYPE 101 -/* A simple reimplementation of the unfortunately static function luaA_index. - * Does not support the global table, registry, or upvalues. */ -static StkId getobject(lua_State *luaState, int stackpos) { - if(stackpos > 0) { - lua_assert(luaState->base+stackpos-1 < luaState->top); - return luaState->base+stackpos-1; - } else { - lua_assert(L->top-stackpos >= L->base); - return luaState->top+stackpos; - } -} - - struct SerializationInfo { lua_State *luaState; Common::WriteStream *writeStream; @@ -70,7 +45,6 @@ struct SerializationInfo { static void serializeObject(SerializationInfo *info); static void serializeBoolean(SerializationInfo *info); -static void serializeLightUserData(SerializationInfo *info); static void serializeNumber(SerializationInfo *info); static void serializeString(SerializationInfo *info); static void serializeTable(SerializationInfo *info); @@ -319,13 +293,15 @@ static bool serializeSpecialObject(SerializationInfo *info, bool defaction) { // Check whether we should persist literally, or via the __persist metafunction if (!lua_getmetatable(info->luaState, -1)) { if (defaction) { - // Write out a flag declaring that the metatable doesn't exist + // Write out a flag declaring that the object isn't special and should be persisted normally info->writeStream->writeSint32LE(0); return false; } else { lua_pushstring(info->luaState, "Type not literally persistable by default"); lua_error(info->luaState); + + return false; // Not reached } } @@ -342,21 +318,21 @@ static bool serializeSpecialObject(SerializationInfo *info, bool defaction) { // >>>>> permTbl indexTbl ...... obj if (defaction) { - // Write out a flag declaring there is no persistence metafunction + // Write out a flag declaring that the object isn't special and should be persisted normally info->writeStream->writeSint32LE(0); - return 0; + return false; } else { lua_pushstring(info->luaState, "Type not literally persistable by default"); lua_error(info->luaState); - return 0; /* not reached */ + return false; // Return false } } else if (lua_isboolean(info->luaState, -1)) { // >>>>> permTbl indexTbl ...... obj metaTbl bool if (lua_toboolean(info->luaState, -1)) { - // Write out a flag declaring such + // Write out a flag declaring that the object isn't special and should be persisted normally info->writeStream->writeSint32LE(0); // >>>>> permTbl indexTbl ...... obj metaTbl true */ @@ -368,7 +344,7 @@ static bool serializeSpecialObject(SerializationInfo *info, bool defaction) { lua_pushstring(info->luaState, "Metatable forbade persistence"); lua_error(info->luaState); - return false; /* not reached */ + return false; // Not reached } } else if (!lua_isfunction(info->luaState, -1)) { lua_pushstring(info->luaState, "__persist not nil, boolean, or function"); @@ -460,40 +436,9 @@ static void serializeTable(SerializationInfo *info) { // >>>>> permTbl indexTbl ...... tbl } -static void pushObject(lua_State *luaState, TValue *obj) { - setobj2s(luaState, luaState->top, obj); - - api_check(luaState, luaState->top < luaState->ci->top); - luaState->top++; -} - -static void pushProto(lua_State *luaState, Proto *proto) { - TValue obj; - setptvalue(luaState, &obj, proto); - - pushObject(luaState, &obj); -} - -static void pushUpVal(lua_State *luaState, UpVal *upval) { - TValue obj; - - obj.value.gc = cast(GCObject *, upval); - obj.tt = LUA_TUPVAL; - checkliveness(G(L), obj); - - pushObject(luaState, &obj); -} - -static void pushString(lua_State *luaState, TString *str) { - TValue o; - setsvalue(luaState, &o, str); - - pushObject(luaState, &o); -} - static void serializeFunction(SerializationInfo *info) { // >>>>> permTbl indexTbl ...... func - Closure *cl = clvalue(getobject(info->luaState, -1)); + Closure *cl = clvalue(getObject(info->luaState, -1)); lua_checkstack(info->luaState, 2); if (cl->c.isC) { @@ -520,7 +465,7 @@ static void serializeFunction(SerializationInfo *info) { // Serialize upvalue values (not the upvalue objects themselves) for (byte i=0; il.p->nups; i++) { // >>>>> permTbl indexTbl ...... func - pushUpVal(info->luaState, cl->l.upvals[i]); + pushUpValue(info->luaState, cl->l.upvals[i]); // >>>>> permTbl indexTbl ...... func upval serializeObject(info); @@ -580,7 +525,7 @@ static void serializeThread(SerializationInfo *info) { // Persist the stack // We *could* have truncation here, but if we have more than 4 billion items on a stack, we have bigger problems - uint stackSize = static_cast(appendStackToStack_rev(threadState, info->luaState)); + uint32 stackSize = static_cast(appendStackToStack_rev(threadState, info->luaState)); info->writeStream->writeUint32LE(stackSize); // >>>>> permTbl indexTbl ...... thread (reversed contents of thread stack) */ @@ -644,7 +589,7 @@ static void serializeThread(SerializationInfo *info) { /* Make sure upvalue is really open */ assert(upVal->v != &upVal->u.value); - pushUpVal(info->luaState, upVal); + pushUpValue(info->luaState, upVal); // >>>>> permTbl indexTbl ...... thread upVal serializeObject(info); @@ -670,7 +615,7 @@ static void serializeThread(SerializationInfo *info) { static void serializeProto(SerializationInfo *info) { // >>>>> permTbl indexTbl ...... proto - Proto *proto = gco2p(getobject(info->luaState, -1)->value.gc); + Proto *proto = gco2p(getObject(info->luaState, -1)->value.gc); // Make sure there is enough room on the stack lua_checkstack(info->luaState, 2); @@ -797,8 +742,8 @@ static void serializeProto(SerializationInfo *info) { */ static void serializeUpValue(SerializationInfo *info) { // >>>>> permTbl indexTbl ...... upval - assert(ttype(getobject(info->luaState, -1)) == LUA_TUPVAL); - UpVal *upValue = gco2uv(getobject(info->luaState, -1)->value.gc); + assert(ttype(getObject(info->luaState, -1)) == LUA_TUPVAL); + UpVal *upValue = gco2uv(getObject(info->luaState, -1)->value.gc); // Make sure there is enough room on the stack lua_checkstack(info->luaState, 1); @@ -831,7 +776,7 @@ static void serializeUserData(SerializationInfo *info) { // Hard cast to a uint32 length // This could lead to truncation, but if we have a 4gb block of data, we have bigger problems - uint32 length = static_cast(uvalue(getobject(info->luaState, -1))->len); + uint32 length = static_cast(uvalue(getObject(info->luaState, -1))->len); info->writeStream->writeUint32LE(length); info->writeStream->write(lua_touserdata(info->luaState, -1), length); -- cgit v1.2.3 From de20880d9d3dbe9ebbc26848d7a672c104495aeb Mon Sep 17 00:00:00 2001 From: Adrian Astley Date: Fri, 19 Dec 2014 13:41:58 -0600 Subject: SWORD25: Re-write the pluto unserializing function(s) --- engines/sword25/util/lua_serialization.h | 2 + engines/sword25/util/lua_unserializer.cpp | 1007 +++++++++++++++++++++++++++++ 2 files changed, 1009 insertions(+) create mode 100644 engines/sword25/util/lua_unserializer.cpp (limited to 'engines') diff --git a/engines/sword25/util/lua_serialization.h b/engines/sword25/util/lua_serialization.h index 0f0c3bd0b2..549ea7968d 100644 --- a/engines/sword25/util/lua_serialization.h +++ b/engines/sword25/util/lua_serialization.h @@ -28,6 +28,7 @@ namespace Common { class WriteStream; +class ReadStream; } @@ -36,6 +37,7 @@ namespace Lua { #define PERMANENT_TYPE 101 void serializeLua(lua_State *luaState, Common::WriteStream *writeStream); +void unserializeLua(lua_State *luaState, Common::ReadStream *readStream); } // End of namespace Lua diff --git a/engines/sword25/util/lua_unserializer.cpp b/engines/sword25/util/lua_unserializer.cpp new file mode 100644 index 0000000000..c561a3d99f --- /dev/null +++ b/engines/sword25/util/lua_unserializer.cpp @@ -0,0 +1,1007 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "sword25/util/lua_serialization.h" + +#include "sword25/util/double_serializer.h" +#include "sword25/util/lua_serialization_util.h" + +#include "common/stream.h" + +#include "lua/lobject.h" +#include "lua/lstate.h" +#include "lua/lgc.h" +#include "lua/lopcodes.h" + + +namespace Lua { + +struct UnSerializationInfo { + lua_State *luaState; + Common::ReadStream *readStream; +}; + +static void unserializeObject(UnSerializationInfo *info); + +static void unserializeBoolean(UnSerializationInfo *info); +static void unserializeNumber(UnSerializationInfo *info); +static void unserializeString(UnSerializationInfo *info); +static void unserializeTable(UnSerializationInfo *info, int index); +static void unserializeFunction(UnSerializationInfo *info, int index); +static void unserializeThread(UnSerializationInfo *info, int index); +static void unserializeProto(UnSerializationInfo *info, int index); +static void unserializeUpValue(UnSerializationInfo *info, int index); +static void unserializeUserData(UnSerializationInfo *info, int index); +static void unserializePermanent(UnSerializationInfo *info, int index); + + +void unserializeLua(lua_State *luaState, Common::ReadStream *readStream) { + UnSerializationInfo info; + info.luaState = luaState; + info.readStream = readStream; + + // The process starts with the lua stack as follows: + // >>>>> permTbl + // That's the table of permanents + + // Make sure there is enough room on the stack + lua_checkstack(luaState, 3); + + // Create a table to hold indexes of everything thats already been read + lua_newtable(luaState); + // >>>>> permTbl indexTbl + + // Prevent garbage collection while we unserialize + lua_gc(luaState, LUA_GCSTOP, 0); + + // Unserialize the root object + unserializeObject(&info); + // >>>>> permTbl indexTbl rootObj + + // Re-start garbage collection + lua_gc(luaState, LUA_GCRESTART, 0); + + // Remove the indexTbl + lua_replace(luaState, 2); + // >>>>> permTbl rootObj +} + +/* The object is left on the stack. This is primarily used by unpersist, but + * may be used by GCed objects that may incur cycles in order to preregister + * the object. */ +static void registerObjectInIndexTable(UnSerializationInfo *info, int index) { + // >>>>> permTbl indexTbl ...... obj + + // Make sure there is enough room on the stack + lua_checkstack(info->luaState, 2); + + lua_pushlightuserdata(info->luaState, (void *)index); + // >>>>> permTbl indexTbl ...... obj index + + lua_pushvalue(info->luaState, -2); + // >>>>> permTbl indexTbl ...... obj index obj + + // Push the k/v pair into the indexTbl + lua_settable(info->luaState, 2); + // >>>>> permTbl indexTbl ...... obj +} + +static void unserializeObject(UnSerializationInfo *info) { + // >>>>> permTbl indexTbl ...... + + // Make sure there is enough room on the stack + lua_checkstack(info->luaState, 2); + + byte isARealValue = info->readStream->readByte(); + if(isARealValue) { + int index = info->readStream->readSint32LE(); + int type = info->readStream->readSint32LE(); + + switch(type) { + case LUA_TBOOLEAN: + unserializeBoolean(info); + break; + case LUA_TLIGHTUSERDATA: + // You can't serialize a pointer + // It would be meaningless on the next run + assert(0); + break; + case LUA_TNUMBER: + unserializeNumber(info); + break; + case LUA_TSTRING: + unserializeString(info); + break; + case LUA_TTABLE: + unserializeTable(info, index); + break; + case LUA_TFUNCTION: + unserializeFunction(info, index); + break; + case LUA_TTHREAD: + unserializeThread(info, index); + break; + case LUA_TPROTO: + unserializeProto(info, index); + break; + case LUA_TUPVAL: + unserializeUpValue(info, index); + break; + case LUA_TUSERDATA: + unserializeUserData(info, index); + break; + case PERMANENT_TYPE: + unserializePermanent(info, index); + break; + default: + assert(0); + } + + + // >>>>> permTbl indexTbl ...... obj + assert(lua_type(info->luaState, -1) == type || + type == PERMANENT_TYPE || + // Remember, upvalues get a special dispensation, as described in boxUpValue + (lua_type(info->luaState, -1) == LUA_TFUNCTION && type == LUA_TUPVAL)); + + registerObjectInIndexTable(info, index); + // >>>>> permTbl indexTbl ...... obj + } else { + int index = info->readStream->readSint32LE(); + + if(index == 0) { + lua_pushnil(info->luaState); + // >>>>> permTbl indexTbl ...... nil + } else { + // Fetch the object from the indexTbl + + lua_pushlightuserdata(info->luaState, (void *)index); + // >>>>> permTbl indexTbl ...... index + + lua_gettable(info->luaState, 2); + // >>>>> permTbl indexTbl ...... ?obj? + + assert(!lua_isnil(info->luaState, -1)); + } + // >>>>> permTbl indexTbl ...... obj/nil + } + + // >>>>> permTbl indexTbl ...... obj/nil +} + +static void unserializeBoolean(UnSerializationInfo *info) { + // >>>>> permTbl indexTbl ...... + + // Make sure there is enough room on the stack + lua_checkstack(info->luaState, 1); + + int value = info->readStream->readSint32LE(); + + lua_pushboolean(info->luaState, value); + // >>>>> permTbl indexTbl ...... bool +} + +static void unserializeNumber(UnSerializationInfo *info) { + // >>>>> permTbl indexTbl ...... + + // Make sure there is enough room on the stack + lua_checkstack(info->luaState, 1); + + // Read the serialized double + Util::SerializedDouble serializedValue; + serializedValue.significandOne = info->readStream->readUint32LE(); + serializedValue.signAndSignificandTwo = info->readStream->readUint32LE(); + serializedValue.exponent = info->readStream->readSint16LE(); + + lua_Number value = Util::decodeDouble(serializedValue); + + lua_pushnumber(info->luaState, value); + // >>>>> permTbl indexTbl ...... num +} + +static void unserializeString(UnSerializationInfo *info) { + // >>>>> permTbl indexTbl ...... + + // Make sure there is enough room on the stack + lua_checkstack(info->luaState, 1); + + uint32 length = info->readStream->readUint32LE(); + char *string = new char[length]; + + info->readStream->read(string, length); + lua_pushlstring(info->luaState, string, length); + + // >>>>> permTbl indexTbl ...... string + + delete[] string; +} + +static void unserializeSpecialTable(UnSerializationInfo *info, int index) { + // >>>>> permTbl indexTbl ...... + + // Make sure there is enough room on the stack + lua_checkstack(info->luaState, 1); + + unserializeObject(info); + + // >>>>> permTbl indexTbl ...... spfunc + lua_call(info->luaState, 0, 1); + // >>>>> permTbl indexTbl ...... tbl +} + +static void unserializeLiteralTable(UnSerializationInfo *info, int index) { + // >>>>> permTbl indexTbl ...... + + // Make sure there is enough room on the stack + lua_checkstack(info->luaState, 3); + + // Preregister table for handling of cycles + lua_newtable(info->luaState); + + // >>>>> permTbl indexTbl ...... tbl + registerObjectInIndexTable(info, index); + // >>>>> permTbl indexTbl ...... tbl + + // Unserialize metatable + unserializeObject(info); + // >>>>> permTbl indexTbl ...... tbl ?metaTbl/nil? + + if (lua_istable(info->luaState, -1)) { + // >>>>> permTbl indexTbl ...... tbl metaTbl + lua_setmetatable(info->luaState, -2); + // >>>>> permTbl indexTbl ...... tbl + } else { + // >>>>> permTbl indexTbl ...... tbl nil + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... tbl + } + // >>>>> permTbl indexTbl ...... tbl + + + while (1) { + // >>>>> permTbl indexTbl ...... tbl + unserializeObject(info); + // >>>>> permTbl indexTbl ...... tbl key/nil + + // The table serialization is nil terminated + if (lua_isnil(info->luaState, -1)) { + // >>>>> permTbl indexTbl ...... tbl nil + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... tbl + + break; + } + + // >>>>> permTbl indexTbl ...... tbl key + unserializeObject(info); + // >>>>> permTbl indexTbl ...... tbl value + + lua_rawset(info->luaState, -3); + // >>>>> permTbl indexTbl ...... tbl + } +} + +void unserializeTable(UnSerializationInfo *info, int index) { + // >>>>> permTbl indexTbl ...... + + // Make sure there is enough room on the stack + lua_checkstack(info->luaState, 1); + + int isSpecial = info->readStream->readSint32LE(); + + if (isSpecial) { + unserializeSpecialTable(info, index); + // >>>>> permTbl indexTbl ...... tbl + } else { + unserializeLiteralTable(info, index); + // >>>>> permTbl indexTbl ...... tbl + } +} + + + +void *lua_realloc(lua_State *luaState, void *block, size_t osize, size_t nsize) { + global_State *globalState = G(luaState); + + block = (*globalState->frealloc)(globalState->ud, block, osize, nsize); + globalState->totalbytes = (globalState->totalbytes - osize) + nsize; + + return block; +} + +#define lua_malloc(luaState, nsize) lua_realloc(luaState, nullptr, 0, nsize) +#define lua_reallocv(luaState, block, on, n, e) lua_realloc(luaState, block, (on) * (e), (n) * (e)) +#define lua_reallocvector(luaState, vec, oldn, n, T) ((vec) = (T *)(lua_reallocv(luaState, vec, oldn, n, sizeof(T)))) +#define lua_newVector(luaState, num, T) ((T *)lua_reallocv(luaState, nullptr, 0, num, sizeof(T))) +#define lua_new(luaState,T) (T *)lua_malloc(luaState, sizeof(T)) + +void lua_linkObjToGC(lua_State *luaState, GCObject *obj, lu_byte type) { + global_State *globalState = G(luaState); + + obj->gch.next = globalState->rootgc; + globalState->rootgc = obj; + obj->gch.marked = luaC_white(globalState); + obj->gch.tt = type; +} + +#define sizeLclosure(n) ((sizeof(LClosure)) + sizeof(TValue *) * ((n) - 1)) + +Closure *newLClosure(lua_State *luaState, byte numUpValues, Table *env) { + Closure *newClosure = (Closure *)lua_malloc(luaState, sizeLclosure(numUpValues)); + + lua_linkObjToGC(luaState, obj2gco(newClosure), LUA_TFUNCTION); + + newClosure->l.isC = 0; + newClosure->l.env = env; + newClosure->l.nupvalues = numUpValues; + + while (numUpValues--) { + newClosure->l.upvals[numUpValues] = NULL; + } + + return newClosure; +} + +static void pushClosure(lua_State *luaState, Closure *closure) { + TValue obj; + setclvalue(luaState, &obj, closure); + pushObject(luaState, &obj); +} + +Proto *createProto(lua_State *luaState) { + Proto *newProto = (Proto *)lua_malloc(luaState, sizeof(Proto)); + lua_linkObjToGC(luaState, obj2gco(newProto), LUA_TPROTO); + + newProto->k = NULL; + newProto->sizek = 0; + newProto->p = NULL; + newProto->sizep = 0; + newProto->code = NULL; + newProto->sizecode = 0; + newProto->sizelineinfo = 0; + newProto->sizeupvalues = 0; + newProto->nups = 0; + newProto->upvalues = NULL; + newProto->numparams = 0; + newProto->is_vararg = 0; + newProto->maxstacksize = 0; + newProto->lineinfo = NULL; + newProto->sizelocvars = 0; + newProto->locvars = NULL; + newProto->linedefined = 0; + newProto->lastlinedefined = 0; + newProto->source = NULL; + + return newProto; +} + +TString *createString(lua_State *luaState, const char *str, size_t len) { + TString *res; + lua_pushlstring(luaState, str, len); + + res = rawtsvalue(luaState->top - 1); + lua_pop(luaState, 1); + + return res; +} + +static Proto *makeFakeProto(lua_State *L, lu_byte nups) { + Proto *p = createProto(L); + + p->sizelineinfo = 1; + p->lineinfo = lua_newVector(L, 1, int); + p->lineinfo[0] = 1; + p->sizecode = 1; + p->code = lua_newVector(L, 1, Instruction); + p->code[0] = CREATE_ABC(OP_RETURN, 0, 1, 0); + p->source = createString(L, "", 0); + p->maxstacksize = 2; + p->nups = nups; + p->sizek = 0; + p->sizep = 0; + + return p; +} + +static UpVal *createUpValue(lua_State *luaState, int stackpos) { + UpVal *upValue = (UpVal *)lua_malloc(luaState, sizeof(UpVal)); + lua_linkObjToGC(luaState, (GCObject *)upValue, LUA_TUPVAL); + upValue->tt = LUA_TUPVAL; + upValue->v = &upValue->u.value; + upValue->u.l.prev = NULL; + upValue->u.l.next = NULL; + + const TValue *o2 = (TValue *)getObject(luaState, stackpos); + upValue->v->value = o2->value; upValue->v->tt = o2->tt; + checkliveness(G(L), upValue->v); + + return upValue; +} + +static void unboxUpValue(lua_State *luaState) { + // >>>>> ...... func + LClosure *lcl; + UpVal *uv; + + lcl = (LClosure *)clvalue(getObject(luaState, -1)); + uv = lcl->upvals[0]; + + lua_pop(luaState, 1); + // >>>>> ...... + + pushUpValue(luaState, uv); + // >>>>> ...... upValue +} + +void unserializeFunction(UnSerializationInfo *info, int index) { + // >>>>> permTbl indexTbl ...... + + // Make sure there is enough room on the stack + lua_checkstack(info->luaState, 2); + + byte numUpValues = info->readStream->readByte(); + + LClosure *lclosure = (LClosure *)newLClosure(info->luaState, numUpValues, hvalue(&info->luaState->l_gt)); + pushClosure(info->luaState, (Closure *)lclosure); + // >>>>> permTbl indexTbl ...... func + + // Put *some* proto in the closure, before the GC can find it + lclosure->p = makeFakeProto(info->luaState, numUpValues); + + //Also, we need to temporarily fill the upvalues + lua_pushnil(info->luaState); + // >>>>> permTbl indexTbl ...... func nil + + for(byte i = 0; i < numUpValues; ++i) { + lclosure->upvals[i] = createUpValue(info->luaState, -1); + } + + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... func + + // I can't see offhand how a function would ever get to be self- + // referential, but just in case let's register it early + registerObjectInIndexTable(info, index); + + // Now that it's safe, we can get the real proto + unserializeObject(info); + // >>>>> permTbl indexTbl ...... func proto + + lclosure->p = gco2p(getObject(info->luaState, -1)->value.gc); + + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... func + + for(byte i = 0; i < numUpValues; ++i) { + // >>>>> permTbl indexTbl ...... func + unserializeObject(info); + // >>>>> permTbl indexTbl ...... func func2 + + unboxUpValue(info->luaState); + // >>>>> permTbl indexTbl ...... func upValue + lclosure->upvals[i] = gco2uv(getObject(info->luaState, -1)->value.gc); + + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... func + } + + // Finally, the fenv + unserializeObject(info); + + // >>>>> permTbl indexTbl ...... func ?fenv/nil? + if(!lua_isnil(info->luaState, -1)) { + // >>>>> permTbl indexTbl ...... func fenv + lua_setfenv(info->luaState, -2); + // >>>>> permTbl indexTbl ...... func + } else { + // >>>>> permTbl indexTbl ...... func nil + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... func + } + + // >>>>> permTbl indexTbl ...... func +} + +static void correctStack(lua_State *L, TValue *oldstack) { + CallInfo *ci; + GCObject *up; + L->top = (L->top - oldstack) + L->stack; + for (up = L->openupval; up != NULL; up = up->gch.next) + gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack; + for (ci = L->base_ci; ci <= L->ci; ci++) { + ci->top = (ci->top - oldstack) + L->stack; + ci->base = (ci->base - oldstack) + L->stack; + ci->func = (ci->func - oldstack) + L->stack; + } + L->base = (L->base - oldstack) + L->stack; +} + +void lua_reallocstack(lua_State *L, int newsize) { + TValue *oldstack = L->stack; + int realsize = newsize + 1 + EXTRA_STACK; + + lua_reallocvector(L, L->stack, L->stacksize, realsize, TValue); + L->stacksize = realsize; + L->stack_last = L->stack + newsize; + correctStack(L, oldstack); +} + +void lua_growstack(lua_State *L, int n) { + // Double size is enough? + if (n <= L->stacksize) { + lua_reallocstack(L, 2 * L->stacksize); + } else { + lua_reallocstack(L, L->stacksize + n); + } +} + +void lua_reallocCallInfo(lua_State *lauState, int newsize) { + CallInfo *oldci = lauState->base_ci; + lua_reallocvector(lauState, lauState->base_ci, lauState->size_ci, newsize, CallInfo); + + lauState->size_ci = newsize; + lauState->ci = (lauState->ci - oldci) + lauState->base_ci; + lauState->end_ci = lauState->base_ci + lauState->size_ci - 1; +} + +void unboxUpVal(lua_State *luaState) { + // >>>>> ... func + LClosure *lcl; + UpVal *uv; + + lcl = (LClosure *)(&getObject(luaState, -1)->value.gc->cl); + uv = lcl->upvals[0]; + lua_pop(luaState, 1); + // >>>>> ... + pushUpValue(luaState, uv); + // >>>>> ... upVal +} + +/* Does basically the opposite of luaC_link(). + * Right now this function is rather inefficient; it requires traversing the + * entire root GC set in order to find one object. If the GC list were doubly + * linked this would be much easier, but there's no reason for Lua to have + * that. */ +static void GCUnlink(lua_State *luaState, GCObject *gco) { + GCObject *prevslot; + if(G(luaState)->rootgc == gco) { + G(luaState)->rootgc = G(luaState)->rootgc->gch.next; + return; + } + + prevslot = G(luaState)->rootgc; + while(prevslot->gch.next != gco) { + prevslot = prevslot->gch.next; + } + + prevslot->gch.next = prevslot->gch.next->gch.next; +} + +void unserializeThread(UnSerializationInfo *info, int index) { + // >>>>> permTbl indexTbl ...... + + lua_State *L2; + uint32 stacklimit = 0; + + L2 = lua_newthread(info->luaState); + lua_checkstack(info->luaState, 3); + + // L1: permTbl indexTbl ...... thread + // L2: (empty) + registerObjectInIndexTable(info, index); + + // First, deserialize the object stack + uint32 stackSize = info->readStream->readUint32LE(); + lua_growstack(info->luaState, (int)stackSize); + + // Make sure that the first stack element (a nil, representing + // the imaginary top-level C function) is written to the very, + // very bottom of the stack + L2->top--; + for(uint32 i = 0; i < stackSize; ++i) { + unserializeObject(info); + // L1: permTbl indexTbl ...... thread obj* + } + + lua_xmove(info->luaState, L2, stackSize); + // L1: permTbl indexTbl ...... thread + // L2: obj* + + // Hereafter, stacks refer to L1 + + + // Now, deserialize the CallInfo stack + + uint32 numFrames = info->readStream->readUint32LE(); + + lua_reallocCallInfo(L2, numFrames*2); + for(uint32 i = 0; i < numFrames; ++i) { + CallInfo *ci = L2->base_ci + i; + uint32 stackbase = info->readStream->readUint32LE(); + uint32 stackfunc = info->readStream->readUint32LE(); + uint32 stacktop = info->readStream->readUint32LE(); + + ci->nresults = info->readStream->readSint32LE(); + + uint32 savedpc = info->readStream->readUint32LE(); + + if (stacklimit < stacktop) { + stacklimit = stacktop; + } + + ci->base = L2->stack + stackbase; + ci->func = L2->stack + stackfunc; + ci->top = L2->stack + stacktop; + ci->savedpc = (ci != L2->base_ci) ? ci_func(ci)->l.p->code + savedpc : 0; + ci->tailcalls = 0; + + // Update the pointer each time, to keep the GC happy + L2->ci = ci; + } + + // >>>>> permTbl indexTbl ...... thread + // Deserialize the state's other parameters, with the exception of upval stuff + + L2->savedpc = L2->ci->savedpc; + L2->status = info->readStream->readByte(); + uint32 stackbase = info->readStream->readUint32LE(); + uint32 stacktop = info->readStream->readUint32LE(); + + + L2->errfunc = info->readStream->readUint32LE(); + + L2->base = L2->stack + stackbase; + L2->top = L2->stack + stacktop; + + // Finally, "reopen" upvalues. See serializeUpVal() for why we do this + UpVal* uv; + GCObject **nextslot = &L2->openupval; + global_State *g = G(L2); + + while (true) { + unserializeObject(info); + // >>>>> permTbl indexTbl ...... thread upVal/nil + + // The list is terminated by a nil + if (lua_isnil(info->luaState, -1)) { + // >>>>> permTbl indexTbl ...... thread nil + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... thread + break; + } + + // >>>>> permTbl indexTbl ...... thread boxedUpVal + unboxUpVal(info->luaState); + // >>>>> permTbl indexTbl ...... thread boxedUpVal + + uv = &(getObject(info->luaState, -1)->value.gc->uv); + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... thread + + uint32 stackpos = info->readStream->readUint32LE(); + uv->v = L2->stack + stackpos; + + GCUnlink(info->luaState, (GCObject *)uv); + + uv->marked = luaC_white(g); + *nextslot = (GCObject *)uv; + nextslot = &uv->next; + uv->u.l.prev = &G(L2)->uvhead; + uv->u.l.next = G(L2)->uvhead.u.l.next; + uv->u.l.next->u.l.prev = uv; + G(L2)->uvhead.u.l.next = uv; + lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); + } + *nextslot = NULL; + + // The stack must be valid at least to the highest value among the CallInfos + // 'top' and the values up to there must be filled with 'nil' + lua_checkstack(L2, (int)stacklimit); + for (StkId o = L2->top; o <= L2->top + stacklimit; ++o) { + setnilvalue(o); + } +} + +TString *lua_newlstr(lua_State *luaState, const char *str, size_t len) { + lua_pushlstring(luaState, str, len); + TString *luaStr = &(luaState->top - 1)->value.gc->ts; + + lua_pop(luaState, 1); + + return luaStr; +} + +void lua_link(lua_State *luaState, GCObject *o, lu_byte tt) { + global_State *g = G(luaState); + o->gch.next = g->rootgc; + g->rootgc = o; + o->gch.marked = luaC_white(g); + o->gch.tt = tt; +} + +Proto *lua_newproto(lua_State *luaState) { + Proto *f = (Proto *)lua_malloc(luaState, sizeof(Proto)); + lua_link(luaState, obj2gco(f), LUA_TPROTO); + f->k = NULL; + f->sizek = 0; + f->p = NULL; + f->sizep = 0; + f->code = NULL; + f->sizecode = 0; + f->sizelineinfo = 0; + f->sizeupvalues = 0; + f->nups = 0; + f->upvalues = NULL; + f->numparams = 0; + f->is_vararg = 0; + f->maxstacksize = 0; + f->lineinfo = NULL; + f->sizelocvars = 0; + f->locvars = NULL; + f->linedefined = 0; + f->lastlinedefined = 0; + f->source = NULL; + return f; +} + +void unserializeProto(UnSerializationInfo *info, int index) { + // >>>>> permTbl indexTbl ...... + + // We have to be careful. The GC expects a lot out of protos. In particular, we need + // to give the function a valid string for its source, and valid code, even before we + // actually read in the real code. + TString *source = lua_newlstr(info->luaState, "", 0); + Proto *p = lua_newproto(info->luaState); + p->source = source; + p->sizecode=1; + p->code = (Instruction *)lua_reallocv(info->luaState, NULL, 0, 1, sizeof(Instruction)); + p->code[0] = CREATE_ABC(OP_RETURN, 0, 1, 0); + p->maxstacksize = 2; + p->sizek = 0; + p->sizep = 0; + + lua_checkstack(info->luaState, 2); + + pushProto(info->luaState, p); + // >>>>> permTbl indexTbl ...... proto + + // We don't need to register early, since protos can never ever be + // involved in cyclic references + + // Read in constant references + int sizek = info->readStream->readSint32LE(); + lua_reallocvector(info->luaState, p->k, 0, sizek, TValue); + for(int i = 0; i < sizek; ++i) { + // >>>>> permTbl indexTbl ...... proto + unserializeObject(info); + // >>>>> permTbl indexTbl ...... proto k + + setobj2s(info->luaState, &p->k[i], getObject(info->luaState, -1)); + p->sizek++; + + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... proto + } + // >>>>> permTbl indexTbl ...... proto + + // Read in sub-proto references + + int sizep = info->readStream->readSint32LE(); + lua_reallocvector(info->luaState, p->p, 0, sizep, Proto *); + for(int i = 0; i < sizep; ++i) { + // >>>>> permTbl indexTbl ...... proto + unserializeObject(info); + // >>>>> permTbl indexTbl ...... proto subproto + + p->p[i] = (Proto *)getObject(info->luaState, -1)->value.gc; + p->sizep++; + + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... proto + } + // >>>>> permTbl indexTbl ...... proto + + + // Read in code + p->sizecode = info->readStream->readSint32LE(); + lua_reallocvector(info->luaState, p->code, 1, p->sizecode, Instruction); + info->readStream->read(p->code, sizeof(Instruction) * p->sizecode); + + + /* Read in upvalue names */ + p->sizeupvalues = info->readStream->readSint32LE(); + if (p->sizeupvalues) { + lua_reallocvector(info->luaState, p->upvalues, 0, p->sizeupvalues, TString *); + for(int i = 0; i < p->sizeupvalues; ++i) { + // >>>>> permTbl indexTbl ...... proto + unserializeObject(info); + // >>>>> permTbl indexTbl ...... proto str + + p->upvalues[i] = lua_newlstr(info->luaState, lua_tostring(info->luaState, -1), strlen(lua_tostring(info->luaState, -1))); + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... proto + } + } + // >>>>> permTbl indexTbl ...... proto + + // Read in local variable infos + p->sizelocvars = info->readStream->readSint32LE(); + if (p->sizelocvars) { + lua_reallocvector(info->luaState, p->locvars, 0, p->sizelocvars, LocVar); + for(int i = 0; i < p->sizelocvars; ++i) { + // >>>>> permTbl indexTbl ...... proto + unserializeObject(info); + // >>>>> permTbl indexTbl ...... proto str + + p->locvars[i].varname = lua_newlstr(info->luaState, lua_tostring(info->luaState, -1), strlen(lua_tostring(info->luaState, -1))); + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... proto + + p->locvars[i].startpc = info->readStream->readSint32LE(); + p->locvars[i].endpc = info->readStream->readSint32LE(); + } + } + // >>>>> permTbl indexTbl ...... proto + + // Read in source string + unserializeObject(info); + // >>>>> permTbl indexTbl ...... proto sourceStr + + p->source = lua_newlstr(info->luaState, lua_tostring(info->luaState, -1), strlen(lua_tostring(info->luaState, -1))); + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... proto + + // Read in line numbers + p->sizelineinfo = info->readStream->readSint32LE(); + if (p->sizelineinfo) { + lua_reallocvector(info->luaState, p->lineinfo, 0, p->sizelineinfo, int); + info->readStream->read(p->lineinfo, sizeof(int) * p->sizelineinfo); + } + + + /* Read in linedefined and lastlinedefined */ + p->linedefined = info->readStream->readSint32LE(); + p->lastlinedefined = info->readStream->readSint32LE(); + + // Read in misc values + p->nups = info->readStream->readByte(); + p->numparams = info->readStream->readByte(); + p->is_vararg = info->readStream->readByte(); + p->maxstacksize = info->readStream->readByte(); +} + +Closure *lua_newLclosure(lua_State *luaState, int numElements, Table *elementTable) { + Closure *c = (Closure *)lua_malloc(luaState, sizeLclosure(numElements)); + lua_link(luaState, obj2gco(c), LUA_TFUNCTION); + c->l.isC = 0; + c->l.env = elementTable; + c->l.nupvalues = cast_byte(numElements); + + while (numElements--) { + c->l.upvals[numElements] = NULL; + } + + return c; +} + +static UpVal *makeUpVal(lua_State *luaState, int stackPos) { + UpVal *uv = lua_new(luaState, UpVal); + lua_link(luaState, (GCObject *)uv, LUA_TUPVAL); + uv->tt = LUA_TUPVAL; + uv->v = &uv->u.value; + uv->u.l.prev = NULL; + uv->u.l.next = NULL; + + setobj(luaState, uv->v, getObject(luaState, stackPos)); + + return uv; +} + +/** + * The GC is not fond of finding upvalues in tables. We get around this + * during persistence using a weakly keyed table, so that the GC doesn't + * bother to mark them. This won't work in unpersisting, however, since + * if we make the values weak they'll be collected (since nothing else + * references them). Our solution, during unpersisting, is to represent + * upvalues as dummy functions, each with one upvalue. + */ +static void boxupval_start(lua_State *luaState) { + LClosure *closure; + closure = (LClosure *)lua_newLclosure(luaState, 1, hvalue(&luaState->l_gt)); + pushClosure(luaState, (Closure *)closure); + // >>>>> ...... func + closure->p = makeFakeProto(luaState, 1); + + // Temporarily initialize the upvalue to nil + lua_pushnil(luaState); + closure->upvals[0] = makeUpVal(luaState, -1); + lua_pop(luaState, 1); +} + +static void boxupval_finish(lua_State *luaState) { + // >>>>> ...... func obj + LClosure *lcl = (LClosure *)clvalue(getObject(luaState, -2)); + + lcl->upvals[0]->u.value = *getObject(luaState, -1); + lua_pop(luaState, 1); + // >>>>> ...... func +} + +void unserializeUpValue(UnSerializationInfo *info, int index) { + // >>>>> permTbl indexTbl ...... + lua_checkstack(upi->L, 2); + + boxupval_start(upi->L); + // >>>>> permTbl indexTbl ...... func + registerObjectInIndexTable(info, index); + + unserializeObject(info); + // >>>>> permTbl indexTbl ...... func obj + + boxupval_finish(upi->L); + // >>>>> permTbl indexTbl ...... func +} + +void unserializeUserData(UnSerializationInfo *info, int index) { + // >>>>> permTbl indexTbl ...... + + // Make sure there is enough room on the stack + lua_checkstack(info->luaState, 2); + + int isspecial = info->readStream->readSint32LE(); + if(isspecial) { + unserializeObject(info); + // >>>>> permTbl indexTbl ...... specialFunc + + lua_call(info->luaState, 0, 1); + // >>>>> permTbl indexTbl ...... udata + } else { + uint32 length = info->readStream->readUint32LE(); + lua_newuserdata(info->luaState, length); + // >>>>> permTbl indexTbl ...... udata + registerObjectInIndexTable(info, index); + + info->readStream->read(lua_touserdata(upi->L, -1), length); + + unserializeObject(info); + // >>>>> permTbl indexTbl ...... udata metaTable/nil + + lua_setmetatable(upi->L, -2); + // >>>>> permTbl indexTbl ...... udata + } + // >>>>> permTbl indexTbl ...... udata +} + +void unserializePermanent(UnSerializationInfo *info, int index) { + // >>>>> permTbl indexTbl ...... + + // Make sure there is enough room on the stack + lua_checkstack(info->luaState, 2); + + unserializeObject(info); + // >>>>> permTbl indexTbl ...... permKey + + lua_gettable(info->luaState, 1); + // >>>>> permTbl indexTbl ...... perm +} + +} // End of namespace Lua -- cgit v1.2.3 From 2c7a87a4e3181f228c43b92ffb15ae47401f64a7 Mon Sep 17 00:00:00 2001 From: Adrian Astley Date: Fri, 19 Dec 2014 14:51:00 -0600 Subject: SWORD25: Fix code formatting ... with AStyle --- engines/sword25/util/lua_serialization_util.cpp | 10 +- engines/sword25/util/lua_serializer.cpp | 62 ++++++------ engines/sword25/util/lua_unserializer.cpp | 127 ++++++++++++------------ 3 files changed, 100 insertions(+), 99 deletions(-) (limited to 'engines') diff --git a/engines/sword25/util/lua_serialization_util.cpp b/engines/sword25/util/lua_serialization_util.cpp index 80009aff60..80c5f86b20 100644 --- a/engines/sword25/util/lua_serialization_util.cpp +++ b/engines/sword25/util/lua_serialization_util.cpp @@ -65,12 +65,12 @@ void pushString(lua_State *luaState, TString *str) { /* A simple reimplementation of the unfortunately static function luaA_index. * Does not support the global table, registry, or upvalues. */ StkId getObject(lua_State *luaState, int stackpos) { - if(stackpos > 0) { - lua_assert(luaState->base+stackpos-1 < luaState->top); - return luaState->base+stackpos-1; + if (stackpos > 0) { + lua_assert(luaState->base + stackpos - 1 < luaState->top); + return luaState->base + stackpos - 1; } else { - lua_assert(L->top-stackpos >= L->base); - return luaState->top+stackpos; + lua_assert(L->top - stackpos >= L->base); + return luaState->top + stackpos; } } diff --git a/engines/sword25/util/lua_serializer.cpp b/engines/sword25/util/lua_serializer.cpp index 8c61383fba..c6c5f99342 100644 --- a/engines/sword25/util/lua_serializer.cpp +++ b/engines/sword25/util/lua_serializer.cpp @@ -81,7 +81,7 @@ void serializeLua(lua_State *luaState, Common::WriteStream *writeStream) { // GC from visiting it and trying to mark things it doesn't want to // mark in tables, e.g. upvalues. All objects in the table are // a priori reachable, so it doesn't matter that we do this. - + // Create the metatable lua_newtable(luaState); // >>>>> permTbl rootObj indexTbl metaTbl @@ -253,22 +253,22 @@ static void serializeBoolean(SerializationInfo *info) { static void serializeNumber(SerializationInfo *info) { lua_Number value = lua_tonumber(info->luaState, -1); - -#if 1 - Util::SerializedDouble serializedValue(Util::encodeDouble(value)); - - info->writeStream->writeUint32LE(serializedValue.significandOne); - info->writeStream->writeUint32LE(serializedValue.signAndSignificandTwo); - info->writeStream->writeSint16LE(serializedValue.exponent); -#else - // NOTE: We need to store a double. Unfortunately, we have to accommodate endianness. - // Also, I don't know if we can assume all compilers use IEEE double - // Therefore, I have chosen to store the double as a string. - Common::String buffer = Common::String::format("%f", value); - - info->writeStream->write(buffer.c_str(), buffer.size()); -#endif - + + #if 1 + Util::SerializedDouble serializedValue(Util::encodeDouble(value)); + + info->writeStream->writeUint32LE(serializedValue.significandOne); + info->writeStream->writeUint32LE(serializedValue.signAndSignificandTwo); + info->writeStream->writeSint16LE(serializedValue.exponent); + #else + // NOTE: We need to store a double. Unfortunately, we have to accommodate endianness. + // Also, I don't know if we can assume all compilers use IEEE double + // Therefore, I have chosen to store the double as a string. + Common::String buffer = Common::String::format("%f", value); + + info->writeStream->write(buffer.c_str(), buffer.size()); + #endif + } static void serializeString(SerializationInfo *info) { @@ -277,7 +277,7 @@ static void serializeString(SerializationInfo *info) { uint32 length = static_cast(lua_strlen(info->luaState, -1)); info->writeStream->writeUint32LE(length); - const char* str = lua_tostring(info->luaState, -1); + const char *str = lua_tostring(info->luaState, -1); info->writeStream->write(str, length); } @@ -350,7 +350,7 @@ static bool serializeSpecialObject(SerializationInfo *info, bool defaction) { lua_pushstring(info->luaState, "__persist not nil, boolean, or function"); lua_error(info->luaState); } - + // >>>>> permTbl indexTbl ...... obj metaTbl __persist lua_pushvalue(info->luaState, -3); // >>>>> permTbl indexTbl ...... obj metaTbl __persist obj @@ -369,7 +369,7 @@ static bool serializeSpecialObject(SerializationInfo *info, bool defaction) { // Serialize the function serializeObject(info); - + lua_pop(info->luaState, 2); // >>>>> permTbl indexTbl ...... obj @@ -396,11 +396,11 @@ static void serializeTable(SerializationInfo *info) { // >>>>> permTbl indexTbl ...... tbl metaTbl/nil */ serializeObject(info); - + lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... tbl - + lua_pushnil(info->luaState); // >>>>> permTbl indexTbl ...... tbl nil @@ -456,14 +456,14 @@ static void serializeFunction(SerializationInfo *info) { // Serialize the prototype pushProto(info->luaState, cl->l.p); // >>>>> permTbl indexTbl ...... func proto */ - + serializeObject(info); lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... func - + // Serialize upvalue values (not the upvalue objects themselves) - for (byte i=0; il.p->nups; i++) { + for (byte i = 0; i < cl->l.p->nups; i++) { // >>>>> permTbl indexTbl ...... func pushUpValue(info->luaState, cl->l.upvals[i]); // >>>>> permTbl indexTbl ...... func upval @@ -536,7 +536,7 @@ static void serializeThread(SerializationInfo *info) { } // >>>>> permTbl indexTbl ...... thread - + // Now, serialize the CallInfo stack // Again, we *could* have truncation here, but if we have more than 4 billion items on a stack, we have bigger problems @@ -550,7 +550,7 @@ static void serializeThread(SerializationInfo *info) { uint32 stackBase = static_cast(ci->base - threadState->stack); uint32 stackFunc = static_cast(ci->func - threadState->stack); uint32 stackTop = static_cast(ci->top - threadState->stack); - + info->writeStream->writeUint32LE(stackBase); info->writeStream->writeUint32LE(stackFunc); info->writeStream->writeUint32LE(stackTop); @@ -560,7 +560,7 @@ static void serializeThread(SerializationInfo *info) { uint32 savedpc = (ci != threadState->base_ci) ? static_cast(ci->savedpc - ci_func(ci)->l.p->code) : 0u; info->writeStream->writeUint32LE(savedpc); } - + // Serialize the state's other parameters, with the exception of upval stuff @@ -671,9 +671,9 @@ static void serializeProto(SerializationInfo *info) { lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... proto } - - // Serialize local variable infos + + // Serialize local variable infos info->writeStream->writeSint32LE(proto->sizelocvars); for (int i = 0; i < proto->sizelocvars; ++i) { @@ -748,7 +748,7 @@ static void serializeUpValue(SerializationInfo *info) { // Make sure there is enough room on the stack lua_checkstack(info->luaState, 1); - // We can't permit the upValue to linger around on the stack, as Lua + // We can't permit the upValue to linger around on the stack, as Lua // will bail if its GC finds it. lua_pop(info->luaState, 1); diff --git a/engines/sword25/util/lua_unserializer.cpp b/engines/sword25/util/lua_unserializer.cpp index c561a3d99f..69cb764dd2 100644 --- a/engines/sword25/util/lua_unserializer.cpp +++ b/engines/sword25/util/lua_unserializer.cpp @@ -79,7 +79,7 @@ void unserializeLua(lua_State *luaState, Common::ReadStream *readStream) { // Re-start garbage collection lua_gc(luaState, LUA_GCRESTART, 0); - + // Remove the indexTbl lua_replace(luaState, 2); // >>>>> permTbl rootObj @@ -106,17 +106,17 @@ static void registerObjectInIndexTable(UnSerializationInfo *info, int index) { } static void unserializeObject(UnSerializationInfo *info) { - // >>>>> permTbl indexTbl ...... + // >>>>> permTbl indexTbl ...... // Make sure there is enough room on the stack lua_checkstack(info->luaState, 2); byte isARealValue = info->readStream->readByte(); - if(isARealValue) { + if (isARealValue) { int index = info->readStream->readSint32LE(); int type = info->readStream->readSint32LE(); - switch(type) { + switch (type) { case LUA_TBOOLEAN: unserializeBoolean(info); break; @@ -156,9 +156,9 @@ static void unserializeObject(UnSerializationInfo *info) { assert(0); } - + // >>>>> permTbl indexTbl ...... obj - assert(lua_type(info->luaState, -1) == type || + assert(lua_type(info->luaState, -1) == type || type == PERMANENT_TYPE || // Remember, upvalues get a special dispensation, as described in boxUpValue (lua_type(info->luaState, -1) == LUA_TFUNCTION && type == LUA_TUPVAL)); @@ -168,7 +168,7 @@ static void unserializeObject(UnSerializationInfo *info) { } else { int index = info->readStream->readSint32LE(); - if(index == 0) { + if (index == 0) { lua_pushnil(info->luaState); // >>>>> permTbl indexTbl ...... nil } else { @@ -184,7 +184,7 @@ static void unserializeObject(UnSerializationInfo *info) { } // >>>>> permTbl indexTbl ...... obj/nil } - + // >>>>> permTbl indexTbl ...... obj/nil } @@ -201,8 +201,8 @@ static void unserializeBoolean(UnSerializationInfo *info) { } static void unserializeNumber(UnSerializationInfo *info) { - // >>>>> permTbl indexTbl ...... - + // >>>>> permTbl indexTbl ...... + // Make sure there is enough room on the stack lua_checkstack(info->luaState, 1); @@ -220,7 +220,7 @@ static void unserializeNumber(UnSerializationInfo *info) { static void unserializeString(UnSerializationInfo *info) { // >>>>> permTbl indexTbl ...... - + // Make sure there is enough room on the stack lua_checkstack(info->luaState, 1); @@ -231,7 +231,7 @@ static void unserializeString(UnSerializationInfo *info) { lua_pushlstring(info->luaState, string, length); // >>>>> permTbl indexTbl ...... string - + delete[] string; } @@ -264,7 +264,7 @@ static void unserializeLiteralTable(UnSerializationInfo *info, int index) { // Unserialize metatable unserializeObject(info); // >>>>> permTbl indexTbl ...... tbl ?metaTbl/nil? - + if (lua_istable(info->luaState, -1)) { // >>>>> permTbl indexTbl ...... tbl metaTbl lua_setmetatable(info->luaState, -2); @@ -343,7 +343,7 @@ void lua_linkObjToGC(lua_State *luaState, GCObject *obj, lu_byte type) { obj->gch.tt = type; } -#define sizeLclosure(n) ((sizeof(LClosure)) + sizeof(TValue *) * ((n) - 1)) +#define sizeLclosure(n) ((sizeof(LClosure)) + sizeof(TValue *) * ((n) - 1)) Closure *newLClosure(lua_State *luaState, byte numUpValues, Table *env) { Closure *newClosure = (Closure *)lua_malloc(luaState, sizeLclosure(numUpValues)); @@ -355,7 +355,7 @@ Closure *newLClosure(lua_State *luaState, byte numUpValues, Table *env) { newClosure->l.nupvalues = numUpValues; while (numUpValues--) { - newClosure->l.upvals[numUpValues] = NULL; + newClosure->l.upvals[numUpValues] = NULL; } return newClosure; @@ -431,7 +431,8 @@ static UpVal *createUpValue(lua_State *luaState, int stackpos) { upValue->u.l.next = NULL; const TValue *o2 = (TValue *)getObject(luaState, stackpos); - upValue->v->value = o2->value; upValue->v->tt = o2->tt; + upValue->v->value = o2->value; + upValue->v->tt = o2->tt; checkliveness(G(L), upValue->v); return upValue; @@ -471,7 +472,7 @@ void unserializeFunction(UnSerializationInfo *info, int index) { lua_pushnil(info->luaState); // >>>>> permTbl indexTbl ...... func nil - for(byte i = 0; i < numUpValues; ++i) { + for (byte i = 0; i < numUpValues; ++i) { lclosure->upvals[i] = createUpValue(info->luaState, -1); } @@ -491,7 +492,7 @@ void unserializeFunction(UnSerializationInfo *info, int index) { lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... func - for(byte i = 0; i < numUpValues; ++i) { + for (byte i = 0; i < numUpValues; ++i) { // >>>>> permTbl indexTbl ...... func unserializeObject(info); // >>>>> permTbl indexTbl ...... func func2 @@ -508,7 +509,7 @@ void unserializeFunction(UnSerializationInfo *info, int index) { unserializeObject(info); // >>>>> permTbl indexTbl ...... func ?fenv/nil? - if(!lua_isnil(info->luaState, -1)) { + if (!lua_isnil(info->luaState, -1)) { // >>>>> permTbl indexTbl ...... func fenv lua_setfenv(info->luaState, -2); // >>>>> permTbl indexTbl ...... func @@ -517,7 +518,7 @@ void unserializeFunction(UnSerializationInfo *info, int index) { lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... func } - + // >>>>> permTbl indexTbl ...... func } @@ -547,7 +548,7 @@ void lua_reallocstack(lua_State *L, int newsize) { void lua_growstack(lua_State *L, int n) { // Double size is enough? - if (n <= L->stacksize) { + if (n <= L->stacksize) { lua_reallocstack(L, 2 * L->stacksize); } else { lua_reallocstack(L, L->stacksize + n); @@ -583,13 +584,13 @@ void unboxUpVal(lua_State *luaState) { * that. */ static void GCUnlink(lua_State *luaState, GCObject *gco) { GCObject *prevslot; - if(G(luaState)->rootgc == gco) { + if (G(luaState)->rootgc == gco) { G(luaState)->rootgc = G(luaState)->rootgc->gch.next; return; } prevslot = G(luaState)->rootgc; - while(prevslot->gch.next != gco) { + while (prevslot->gch.next != gco) { prevslot = prevslot->gch.next; } @@ -604,7 +605,7 @@ void unserializeThread(UnSerializationInfo *info, int index) { L2 = lua_newthread(info->luaState); lua_checkstack(info->luaState, 3); - + // L1: permTbl indexTbl ...... thread // L2: (empty) registerObjectInIndexTable(info, index); @@ -612,14 +613,14 @@ void unserializeThread(UnSerializationInfo *info, int index) { // First, deserialize the object stack uint32 stackSize = info->readStream->readUint32LE(); lua_growstack(info->luaState, (int)stackSize); - + // Make sure that the first stack element (a nil, representing // the imaginary top-level C function) is written to the very, // very bottom of the stack L2->top--; - for(uint32 i = 0; i < stackSize; ++i) { + for (uint32 i = 0; i < stackSize; ++i) { unserializeObject(info); - // L1: permTbl indexTbl ...... thread obj* + // L1: permTbl indexTbl ...... thread obj* } lua_xmove(info->luaState, L2, stackSize); @@ -628,18 +629,18 @@ void unserializeThread(UnSerializationInfo *info, int index) { // Hereafter, stacks refer to L1 - + // Now, deserialize the CallInfo stack uint32 numFrames = info->readStream->readUint32LE(); - lua_reallocCallInfo(L2, numFrames*2); - for(uint32 i = 0; i < numFrames; ++i) { + lua_reallocCallInfo(L2, numFrames * 2); + for (uint32 i = 0; i < numFrames; ++i) { CallInfo *ci = L2->base_ci + i; uint32 stackbase = info->readStream->readUint32LE(); uint32 stackfunc = info->readStream->readUint32LE(); uint32 stacktop = info->readStream->readUint32LE(); - + ci->nresults = info->readStream->readSint32LE(); uint32 savedpc = info->readStream->readUint32LE(); @@ -653,7 +654,7 @@ void unserializeThread(UnSerializationInfo *info, int index) { ci->top = L2->stack + stacktop; ci->savedpc = (ci != L2->base_ci) ? ci_func(ci)->l.p->code + savedpc : 0; ci->tailcalls = 0; - + // Update the pointer each time, to keep the GC happy L2->ci = ci; } @@ -668,12 +669,12 @@ void unserializeThread(UnSerializationInfo *info, int index) { L2->errfunc = info->readStream->readUint32LE(); - + L2->base = L2->stack + stackbase; L2->top = L2->stack + stacktop; - // Finally, "reopen" upvalues. See serializeUpVal() for why we do this - UpVal* uv; + // Finally, "reopen" upvalues. See serializeUpVal() for why we do this + UpVal *uv; GCObject **nextslot = &L2->openupval; global_State *g = G(L2); @@ -688,7 +689,7 @@ void unserializeThread(UnSerializationInfo *info, int index) { // >>>>> permTbl indexTbl ...... thread break; } - + // >>>>> permTbl indexTbl ...... thread boxedUpVal unboxUpVal(info->luaState); // >>>>> permTbl indexTbl ...... thread boxedUpVal @@ -765,15 +766,15 @@ Proto *lua_newproto(lua_State *luaState) { void unserializeProto(UnSerializationInfo *info, int index) { // >>>>> permTbl indexTbl ...... - - // We have to be careful. The GC expects a lot out of protos. In particular, we need - // to give the function a valid string for its source, and valid code, even before we - // actually read in the real code. + + // We have to be careful. The GC expects a lot out of protos. In particular, we need + // to give the function a valid string for its source, and valid code, even before we + // actually read in the real code. TString *source = lua_newlstr(info->luaState, "", 0); Proto *p = lua_newproto(info->luaState); p->source = source; - p->sizecode=1; - p->code = (Instruction *)lua_reallocv(info->luaState, NULL, 0, 1, sizeof(Instruction)); + p->sizecode = 1; + p->code = (Instruction *)lua_reallocv(info->luaState, NULL, 0, 1, sizeof(Instruction)); p->code[0] = CREATE_ABC(OP_RETURN, 0, 1, 0); p->maxstacksize = 2; p->sizek = 0; @@ -782,18 +783,18 @@ void unserializeProto(UnSerializationInfo *info, int index) { lua_checkstack(info->luaState, 2); pushProto(info->luaState, p); - // >>>>> permTbl indexTbl ...... proto + // >>>>> permTbl indexTbl ...... proto // We don't need to register early, since protos can never ever be - // involved in cyclic references + // involved in cyclic references // Read in constant references int sizek = info->readStream->readSint32LE(); lua_reallocvector(info->luaState, p->k, 0, sizek, TValue); - for(int i = 0; i < sizek; ++i) { - // >>>>> permTbl indexTbl ...... proto + for (int i = 0; i < sizek; ++i) { + // >>>>> permTbl indexTbl ...... proto unserializeObject(info); - // >>>>> permTbl indexTbl ...... proto k + // >>>>> permTbl indexTbl ...... proto k setobj2s(info->luaState, &p->k[i], getObject(info->luaState, -1)); p->sizek++; @@ -807,8 +808,8 @@ void unserializeProto(UnSerializationInfo *info, int index) { int sizep = info->readStream->readSint32LE(); lua_reallocvector(info->luaState, p->p, 0, sizep, Proto *); - for(int i = 0; i < sizep; ++i) { - // >>>>> permTbl indexTbl ...... proto + for (int i = 0; i < sizep; ++i) { + // >>>>> permTbl indexTbl ...... proto unserializeObject(info); // >>>>> permTbl indexTbl ...... proto subproto @@ -816,22 +817,22 @@ void unserializeProto(UnSerializationInfo *info, int index) { p->sizep++; lua_pop(info->luaState, 1); - // >>>>> permTbl indexTbl ...... proto + // >>>>> permTbl indexTbl ...... proto } - // >>>>> permTbl indexTbl ...... proto + // >>>>> permTbl indexTbl ...... proto // Read in code p->sizecode = info->readStream->readSint32LE(); lua_reallocvector(info->luaState, p->code, 1, p->sizecode, Instruction); info->readStream->read(p->code, sizeof(Instruction) * p->sizecode); - + /* Read in upvalue names */ p->sizeupvalues = info->readStream->readSint32LE(); if (p->sizeupvalues) { lua_reallocvector(info->luaState, p->upvalues, 0, p->sizeupvalues, TString *); - for(int i = 0; i < p->sizeupvalues; ++i) { + for (int i = 0; i < p->sizeupvalues; ++i) { // >>>>> permTbl indexTbl ...... proto unserializeObject(info); // >>>>> permTbl indexTbl ...... proto str @@ -847,7 +848,7 @@ void unserializeProto(UnSerializationInfo *info, int index) { p->sizelocvars = info->readStream->readSint32LE(); if (p->sizelocvars) { lua_reallocvector(info->luaState, p->locvars, 0, p->sizelocvars, LocVar); - for(int i = 0; i < p->sizelocvars; ++i) { + for (int i = 0; i < p->sizelocvars; ++i) { // >>>>> permTbl indexTbl ...... proto unserializeObject(info); // >>>>> permTbl indexTbl ...... proto str @@ -876,7 +877,7 @@ void unserializeProto(UnSerializationInfo *info, int index) { lua_reallocvector(info->luaState, p->lineinfo, 0, p->sizelineinfo, int); info->readStream->read(p->lineinfo, sizeof(int) * p->sizelineinfo); } - + /* Read in linedefined and lastlinedefined */ p->linedefined = info->readStream->readSint32LE(); @@ -895,7 +896,7 @@ Closure *lua_newLclosure(lua_State *luaState, int numElements, Table *elementTab c->l.isC = 0; c->l.env = elementTable; c->l.nupvalues = cast_byte(numElements); - + while (numElements--) { c->l.upvals[numElements] = NULL; } @@ -916,13 +917,13 @@ static UpVal *makeUpVal(lua_State *luaState, int stackPos) { return uv; } -/** +/** * The GC is not fond of finding upvalues in tables. We get around this * during persistence using a weakly keyed table, so that the GC doesn't * bother to mark them. This won't work in unpersisting, however, since * if we make the values weak they'll be collected (since nothing else * references them). Our solution, during unpersisting, is to represent - * upvalues as dummy functions, each with one upvalue. + * upvalues as dummy functions, each with one upvalue. */ static void boxupval_start(lua_State *luaState) { LClosure *closure; @@ -931,7 +932,7 @@ static void boxupval_start(lua_State *luaState) { // >>>>> ...... func closure->p = makeFakeProto(luaState, 1); - // Temporarily initialize the upvalue to nil + // Temporarily initialize the upvalue to nil lua_pushnil(luaState); closure->upvals[0] = makeUpVal(luaState, -1); lua_pop(luaState, 1); @@ -947,7 +948,7 @@ static void boxupval_finish(lua_State *luaState) { } void unserializeUpValue(UnSerializationInfo *info, int index) { - // >>>>> permTbl indexTbl ...... + // >>>>> permTbl indexTbl ...... lua_checkstack(upi->L, 2); boxupval_start(upi->L); @@ -966,9 +967,9 @@ void unserializeUserData(UnSerializationInfo *info, int index) { // Make sure there is enough room on the stack lua_checkstack(info->luaState, 2); - + int isspecial = info->readStream->readSint32LE(); - if(isspecial) { + if (isspecial) { unserializeObject(info); // >>>>> permTbl indexTbl ...... specialFunc @@ -996,7 +997,7 @@ void unserializePermanent(UnSerializationInfo *info, int index) { // Make sure there is enough room on the stack lua_checkstack(info->luaState, 2); - + unserializeObject(info); // >>>>> permTbl indexTbl ...... permKey -- cgit v1.2.3 From 37b5ee24f520e46eae28c703d189939e0b18c65b Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 19 Dec 2014 22:45:00 -0500 Subject: ACCESS: Rename ASurface copyFrom methods to avoid clash with Graphics::Surface --- engines/access/amazon/amazon_game.cpp | 8 +++---- engines/access/amazon/amazon_logic.cpp | 38 ++++++++++++++++---------------- engines/access/amazon/amazon_scripts.cpp | 30 ++++++++++++------------- engines/access/asurface.cpp | 16 +++++++------- engines/access/asurface.h | 10 ++++----- engines/access/char.cpp | 4 ++-- engines/access/martian/martian_game.cpp | 10 ++++----- engines/access/screen.cpp | 12 +++++----- engines/access/screen.h | 6 ++--- engines/access/scripts.cpp | 2 +- 10 files changed, 68 insertions(+), 68 deletions(-) (limited to 'engines') diff --git a/engines/access/amazon/amazon_game.cpp b/engines/access/amazon/amazon_game.cpp index 933a98aded..6c9a437e77 100644 --- a/engines/access/amazon/amazon_game.cpp +++ b/engines/access/amazon/amazon_game.cpp @@ -552,7 +552,7 @@ void AmazonEngine::startChapter(int chapter) { // Show chapter screen _files->loadScreen(96, 15); - _buffer2.copyFrom(*_screen); + _buffer2.blitFrom(*_screen); const int *chapImg = &CHAPTER_TABLE[_chapter - 1][0]; _screen->plotImage(_objectsTable[0], _chapter - 1, @@ -583,14 +583,14 @@ void AmazonEngine::startChapter(int chapter) { _screen->clearBuffer(); _files->loadScreen(96, 16); - _buffer2.copyFrom(*_screen); + _buffer2.blitFrom(*_screen); _screen->plotImage(_objectsTable[0], chapImg[0], Common::Point(90, 7)); _midi->newMusic(7, 1); _midi->newMusic(34, 0); _screen->forceFadeIn(); - _buffer2.copyFrom(*_screen); + _buffer2.blitFrom(*_screen); _fonts._charSet._lo = 1; _fonts._charSet._hi = 10; @@ -670,7 +670,7 @@ void AmazonEngine::dead(int deathId) { _files->_setPaletteFlag = false; _files->loadScreen(94, 0); _files->_setPaletteFlag = true; - _buffer2.copyFrom(*_screen); + _buffer2.blitFrom(*_screen); if (!isDemo() || deathId != 10) { for (int i = 0; i < 3; ++i) { diff --git a/engines/access/amazon/amazon_logic.cpp b/engines/access/amazon/amazon_logic.cpp index 436a875688..7f802f3cde 100644 --- a/engines/access/amazon/amazon_logic.cpp +++ b/engines/access/amazon/amazon_logic.cpp @@ -106,8 +106,8 @@ void CampScene::mWhileDoOpen() { _vm->_files->_setPaletteFlag = false; _vm->_files->loadScreen(1, 2); - _vm->_buffer2.copyFrom(*_vm->_screen); - _vm->_buffer1.copyFrom(*_vm->_screen); + _vm->_buffer2.blitFrom(*_vm->_screen); + _vm->_buffer1.blitFrom(*_vm->_screen); // Load animation data _vm->_animation->freeAnimationData(); @@ -148,7 +148,7 @@ void CampScene::mWhileDoOpen() { _vm->_animation->animate(0); _vm->_animation->animate(1); pan(); - _vm->_buffer2.copyFrom(_vm->_buffer1); + _vm->_buffer2.blitFrom(_vm->_buffer1); _vm->_newRects.clear(); _vm->plotList(); _vm->copyBlocks(); @@ -176,8 +176,8 @@ void CampScene::mWhileDoOpen() { } events.showCursor(); - _vm->_buffer2.copyFrom(*_vm->_screen); - _vm->_buffer1.copyFrom(*_vm->_screen); + _vm->_buffer2.blitFrom(*_vm->_screen); + _vm->_buffer1.blitFrom(*_vm->_screen); _vm->freeCells(); _vm->_oldRects.clear(); @@ -323,8 +323,8 @@ void Opening::doTitle() { _vm->_files->_setPaletteFlag = false; _vm->_files->loadScreen(0, 3); - _vm->_buffer2.copyFrom(*_vm->_screen); - _vm->_buffer1.copyFrom(*_vm->_screen); + _vm->_buffer2.blitFrom(*_vm->_screen); + _vm->_buffer1.blitFrom(*_vm->_screen); screen.forceFadeIn(); _vm->_sound->playSound(1); @@ -347,13 +347,13 @@ void Opening::doTitle() { _vm->_files->loadScreen(0, 4); _vm->_sound->playSound(1); - _vm->_buffer2.copyFrom(*_vm->_screen); - _vm->_buffer1.copyFrom(*_vm->_screen); + _vm->_buffer2.blitFrom(*_vm->_screen); + _vm->_buffer1.blitFrom(*_vm->_screen); _vm->_sound->playSound(1); const int COUNTDOWN[6] = { 2, 0x80, 1, 0x7d, 0, 0x87 }; for (_pCount = 0; _pCount < 3 && !_vm->shouldQuit(); ++_pCount) { - _vm->_buffer2.copyFrom(_vm->_buffer1); + _vm->_buffer2.blitFrom(_vm->_buffer1); int id = COUNTDOWN[_pCount * 2]; int xp = COUNTDOWN[_pCount * 2 + 1]; _vm->_buffer2.plotImage(_vm->_objectsTable[0], id, Common::Point(xp, 71)); @@ -385,8 +385,8 @@ void Opening::doTitle() { _vm->_files->_setPaletteFlag = false; _vm->_files->loadScreen(0, 5); - _vm->_buffer2.copyFrom(*_vm->_screen); - _vm->_buffer1.copyFrom(*_vm->_screen); + _vm->_buffer2.blitFrom(*_vm->_screen); + _vm->_buffer1.blitFrom(*_vm->_screen); screen.forceFadeIn(); _vm->_midi->newMusic(1, 0); _vm->_events->_vbCount = 700; @@ -503,8 +503,8 @@ void Opening::doTent() { _vm->_files->_setPaletteFlag = false; _vm->_files->loadScreen(2, 0); - _vm->_buffer2.copyFrom(*_vm->_screen); - _vm->_buffer1.copyFrom(*_vm->_screen); + _vm->_buffer2.blitFrom(*_vm->_screen); + _vm->_buffer1.blitFrom(*_vm->_screen); _vm->_screen->forceFadeIn(); _vm->_video->setVideo(_vm->_screen, Common::Point(126, 73), FileIdent(2, 1), 10); @@ -1276,8 +1276,8 @@ void Cast::doCast(int param1) { _vm->_files->_setPaletteFlag = false; _vm->_files->loadScreen(58, 1); - _vm->_buffer2.copyFrom(*_vm->_screen); - _vm->_buffer1.copyFrom(*_vm->_screen); + _vm->_buffer2.blitFrom(*_vm->_screen); + _vm->_buffer1.blitFrom(*_vm->_screen); _xTrack = 0; _yTrack = -6; @@ -1319,7 +1319,7 @@ void Cast::doCast(int param1) { while (!_vm->shouldQuit()) { _vm->_images.clear(); pan(); - _vm->_buffer2.copyFrom(_vm->_buffer1); + _vm->_buffer2.blitFrom(_vm->_buffer1); _vm->_newRects.clear(); _vm->plotList(); _vm->copyBlocks(); @@ -1410,7 +1410,7 @@ void River::initRiver() { _vm->_files->_setPaletteFlag = false; _vm->_files->loadScreen(95, 4); - _vm->_buffer2.copyFrom(*_vm->_screen); + _vm->_buffer2.blitFrom(*_vm->_screen); screen.restorePalette(); screen.setBufferScan(); @@ -1744,7 +1744,7 @@ void River::mWhileDownRiver() { screen.savePalette(); if (!_vm->isDemo()) _vm->_files->loadScreen(95, 4); - _vm->_buffer2.copyFrom(*_vm->_screen); + _vm->_buffer2.blitFrom(*_vm->_screen); screen.restorePalette(); screen.setPalette(); screen.setBufferScan(); diff --git a/engines/access/amazon/amazon_scripts.cpp b/engines/access/amazon/amazon_scripts.cpp index 633188e4dd..0b2ddbc854 100644 --- a/engines/access/amazon/amazon_scripts.cpp +++ b/engines/access/amazon/amazon_scripts.cpp @@ -38,7 +38,7 @@ AmazonScripts::AmazonScripts(AccessEngine *vm) : Scripts(vm) { void AmazonScripts::cLoop() { searchForSequence(); _vm->_images.clear(); - _vm->_buffer2.copyFrom(_vm->_buffer1); + _vm->_buffer2.blitFrom(_vm->_buffer1); _vm->_oldRects.clear(); _vm->_scripts->executeScript(); _vm->plotList1(); @@ -51,8 +51,8 @@ void AmazonScripts::mWhile1() { _vm->_events->hideCursor(); _vm->_files->loadScreen(14, 0); - _vm->_buffer2.copyFrom(*_vm->_screen); - _vm->_buffer1.copyFrom(*_vm->_screen); + _vm->_buffer2.blitFrom(*_vm->_screen); + _vm->_buffer1.blitFrom(*_vm->_screen); _vm->_events->showCursor(); _vm->_screen->setIconPalette(); @@ -86,8 +86,8 @@ void AmazonScripts::mWhile1() { _vm->_files->loadScreen(14, 1); _vm->_screen->setPalette(); - _vm->_buffer2.copyFrom(*_vm->_screen); - _vm->_buffer1.copyFrom(*_vm->_screen); + _vm->_buffer2.blitFrom(*_vm->_screen); + _vm->_buffer1.blitFrom(*_vm->_screen); _vm->_events->showCursor(); _vm->_screen->setIconPalette(); @@ -107,8 +107,8 @@ void AmazonScripts::mWhile1() { _vm->_files->loadScreen(14, 2); _vm->_screen->setPalette(); - _vm->_buffer2.copyFrom(*_vm->_screen); - _vm->_buffer1.copyFrom(*_vm->_screen); + _vm->_buffer2.blitFrom(*_vm->_screen); + _vm->_buffer1.blitFrom(*_vm->_screen); _vm->_events->showCursor(); _vm->_screen->setIconPalette(); @@ -138,8 +138,8 @@ void AmazonScripts::mWhile1() { _vm->_files->loadScreen(14, 3); _vm->_screen->setPalette(); - _vm->_buffer2.copyFrom(*_vm->_screen); - _vm->_buffer1.copyFrom(*_vm->_screen); + _vm->_buffer2.blitFrom(*_vm->_screen); + _vm->_buffer1.blitFrom(*_vm->_screen); _vm->_events->showCursor(); _vm->_screen->setIconPalette(); @@ -159,8 +159,8 @@ void AmazonScripts::mWhile2() { _vm->_events->hideCursor(); _vm->_files->loadScreen(14, 0); - _vm->_buffer2.copyFrom(*_vm->_screen); - _vm->_buffer1.copyFrom(*_vm->_screen); + _vm->_buffer2.blitFrom(*_vm->_screen); + _vm->_buffer1.blitFrom(*_vm->_screen); _vm->_events->showCursor(); _vm->_screen->setIconPalette(); @@ -190,8 +190,8 @@ void AmazonScripts::mWhile2() { _vm->_files->loadScreen(14, 3); _vm->_screen->setPalette(); - _vm->_buffer2.copyFrom(*_vm->_screen); - _vm->_buffer1.copyFrom(*_vm->_screen); + _vm->_buffer2.blitFrom(*_vm->_screen); + _vm->_buffer1.blitFrom(*_vm->_screen); _vm->_events->showCursor(); _vm->_screen->setIconPalette(); @@ -240,8 +240,8 @@ void AmazonScripts::loadBackground(int param1, int param2) { _vm->_files->_setPaletteFlag = false; _vm->_files->loadScreen(param1, param2); - _vm->_buffer2.copyFrom(*_vm->_screen); - _vm->_buffer1.copyFrom(*_vm->_screen); + _vm->_buffer2.blitFrom(*_vm->_screen); + _vm->_buffer1.blitFrom(*_vm->_screen); _vm->_screen->forceFadeIn(); } diff --git a/engines/access/asurface.cpp b/engines/access/asurface.cpp index 38af7add00..f45f121db4 100644 --- a/engines/access/asurface.cpp +++ b/engines/access/asurface.cpp @@ -186,7 +186,7 @@ void ASurface::plotImage(SpriteResource *sprite, int frameNum, const Common::Poi } } -void ASurface::transCopyFrom(ASurface *src, const Common::Point &destPos) { +void ASurface::transBlitFrom(ASurface *src, const Common::Point &destPos) { if (getPixels() == nullptr) create(w, h); @@ -201,7 +201,7 @@ void ASurface::transCopyFrom(ASurface *src, const Common::Point &destPos) { } } -void ASurface::transCopyFrom(ASurface *src, const Common::Rect &bounds) { +void ASurface::transBlitFrom(ASurface *src, const Common::Rect &bounds) { const int SCALE_LIMIT = 0x100; int scaleX = SCALE_LIMIT * bounds.width() / src->w; int scaleY = SCALE_LIMIT * bounds.height() / src->h; @@ -247,11 +247,11 @@ void ASurface::transCopyFrom(ASurface *src, const Common::Rect &bounds) { } } -void ASurface::transCopyFrom(ASurface &src) { - copyFrom(src); +void ASurface::transBlitFrom(ASurface &src) { + blitFrom(src); } -void ASurface::copyFrom(Graphics::Surface &src) { +void ASurface::blitFrom(Graphics::Surface &src) { for (int y = 0; y < src.h; ++y) { const byte *srcP = (const byte *)src.getBasePtr(0, y); byte *destP = (byte *)getBasePtr(0, y); @@ -260,7 +260,7 @@ void ASurface::copyFrom(Graphics::Surface &src) { } void ASurface::copyBuffer(Graphics::Surface *src) { - copyFrom(*src); + blitFrom(*src); } void ASurface::plotF(SpriteFrame *frame, const Common::Point &pt) { @@ -272,14 +272,14 @@ void ASurface::plotB(SpriteFrame *frame, const Common::Point &pt) { } void ASurface::sPlotF(SpriteFrame *frame, const Common::Rect &bounds) { - transCopyFrom(frame, bounds); + transBlitFrom(frame, bounds); } void ASurface::sPlotB(SpriteFrame *frame, const Common::Rect &bounds) { ASurface flippedFrame; frame->flipHorizontal(flippedFrame); - transCopyFrom(&flippedFrame, bounds); + transBlitFrom(&flippedFrame, bounds); } void ASurface::copyBlock(ASurface *src, const Common::Rect &bounds) { diff --git a/engines/access/asurface.h b/engines/access/asurface.h index 763e3e629e..4fb47b9c09 100644 --- a/engines/access/asurface.h +++ b/engines/access/asurface.h @@ -95,19 +95,19 @@ public: virtual void drawRect(); - virtual void transCopyFrom(ASurface *src, const Common::Point &destPos); + virtual void transBlitFrom(ASurface *src, const Common::Point &destPos); - virtual void transCopyFrom(ASurface *src, const Common::Rect &bounds); + virtual void transBlitFrom(ASurface *src, const Common::Rect &bounds); - virtual void transCopyFrom(ASurface &src); + virtual void transBlitFrom(ASurface &src); - virtual void copyFrom(Graphics::Surface &src); + virtual void blitFrom(Graphics::Surface &src); virtual void copyBuffer(Graphics::Surface *src); virtual void addDirtyRect(const Common::Rect &r) {} - void copyTo(ASurface *dest) { dest->copyFrom(*this); } + void copyTo(ASurface *dest) { dest->blitFrom(*this); } void saveBlock(const Common::Rect &bounds); diff --git a/engines/access/char.cpp b/engines/access/char.cpp index 5bc6707509..b359bcf13a 100644 --- a/engines/access/char.cpp +++ b/engines/access/char.cpp @@ -108,8 +108,8 @@ void CharManager::loadChar(int charId) { _vm->_screen->fadeIn(); } - _vm->_buffer1.copyFrom(*_vm->_screen); - _vm->_buffer2.copyFrom(*_vm->_screen); + _vm->_buffer1.blitFrom(*_vm->_screen); + _vm->_buffer2.blitFrom(*_vm->_screen); _vm->_screen->setDisplayScan(); if (_charFlag != 2 && _charFlag != 3) { diff --git a/engines/access/martian/martian_game.cpp b/engines/access/martian/martian_game.cpp index 6392206209..4e4a5135a6 100644 --- a/engines/access/martian/martian_game.cpp +++ b/engines/access/martian/martian_game.cpp @@ -100,8 +100,8 @@ void MartianEngine::doTitle() { _files->_setPaletteFlag = false; _files->loadScreen(0, 3); - _buffer2.copyFrom(*_screen); - _buffer1.copyFrom(*_screen); + _buffer2.blitFrom(*_screen); + _buffer1.blitFrom(*_screen); _screen->forceFadeIn(); _sound->playSound(1); @@ -115,13 +115,13 @@ void MartianEngine::doTitle() { _files->loadScreen(0, 4); _sound->playSound(1); - _buffer2.copyFrom(*_screen); - _buffer1.copyFrom(*_screen); + _buffer2.blitFrom(*_screen); + _buffer1.blitFrom(*_screen); _sound->playSound(1); const int COUNTDOWN[6] = { 2, 0x80, 1, 0x7d, 0, 0x87 }; for (_pCount = 0; _pCount < 3; ++_pCount) { - _buffer2.copyFrom(_buffer1); + _buffer2.blitFrom(_buffer1); int id = READ_LE_UINT16(COUNTDOWN + _pCount * 4); int xp = READ_LE_UINT16(COUNTDOWN + _pCount * 4 + 2); _screen->plotImage(_objectsTable[0], id, Common::Point(xp, 71)); diff --git a/engines/access/screen.cpp b/engines/access/screen.cpp index 35069ba683..d6fddb73b2 100644 --- a/engines/access/screen.cpp +++ b/engines/access/screen.cpp @@ -266,19 +266,19 @@ void Screen::drawRect() { ASurface::drawRect(); } -void Screen::transCopyFrom(ASurface *src, const Common::Point &destPos) { +void Screen::transBlitFrom(ASurface *src, const Common::Point &destPos) { addDirtyRect(Common::Rect(destPos.x, destPos.y, destPos.x + src->w, destPos.y + src->h)); - ASurface::transCopyFrom(src, destPos); + ASurface::transBlitFrom(src, destPos); } -void Screen::transCopyFrom(ASurface *src, const Common::Rect &bounds) { +void Screen::transBlitFrom(ASurface *src, const Common::Rect &bounds) { addDirtyRect(bounds); - ASurface::transCopyFrom(src, bounds); + ASurface::transBlitFrom(src, bounds); } -void Screen::copyFrom(Graphics::Surface &src) { +void Screen::blitFrom(Graphics::Surface &src) { addDirtyRect(Common::Rect(0, 0, src.w, src.h)); - ASurface::copyFrom(src); + ASurface::blitFrom(src); } void Screen::copyBuffer(Graphics::Surface *src) { diff --git a/engines/access/screen.h b/engines/access/screen.h index 0fa111c21c..d45a533f9a 100644 --- a/engines/access/screen.h +++ b/engines/access/screen.h @@ -92,11 +92,11 @@ public: virtual void drawRect(); - virtual void transCopyFrom(ASurface *src, const Common::Point &destPos); + virtual void transBlitFrom(ASurface *src, const Common::Point &destPos); - virtual void transCopyFrom(ASurface *src, const Common::Rect &bounds); + virtual void transBlitFrom(ASurface *src, const Common::Rect &bounds); - virtual void copyFrom(Graphics::Surface &src); + virtual void blitFrom(Graphics::Surface &src); virtual void copyBuffer(Graphics::Surface *src); diff --git a/engines/access/scripts.cpp b/engines/access/scripts.cpp index 2e22d9a2ce..dfb9bd963f 100644 --- a/engines/access/scripts.cpp +++ b/engines/access/scripts.cpp @@ -73,7 +73,7 @@ void Scripts::charLoop() { _sequence = 2000; searchForSequence(); _vm->_images.clear(); - _vm->_buffer2.copyFrom(_vm->_buffer1); + _vm->_buffer2.blitFrom(_vm->_buffer1); _vm->_newRects.clear(); executeScript(); -- cgit v1.2.3 From 18df28f74da91105b8c1898bfe2351b22cbd435f Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 19 Dec 2014 23:36:53 -0500 Subject: ACCESS: Extra initialization for various classes --- engines/access/access.cpp | 3 +++ engines/access/amazon/amazon_game.cpp | 9 ++++++++- engines/access/amazon/amazon_logic.cpp | 12 ++++++++++++ engines/access/amazon/amazon_logic.h | 2 ++ engines/access/animation.cpp | 1 + engines/access/asurface.cpp | 3 ++- engines/access/bubble_box.cpp | 7 +++---- engines/access/bubble_box.h | 4 ---- engines/access/font.cpp | 2 ++ engines/access/inventory.cpp | 1 + engines/access/player.cpp | 6 ++++++ engines/access/screen.cpp | 1 + engines/access/scripts.cpp | 2 ++ engines/access/video.cpp | 8 +++++++- 14 files changed, 50 insertions(+), 11 deletions(-) (limited to 'engines') diff --git a/engines/access/access.cpp b/engines/access/access.cpp index 6ad1b22408..39e6c2b530 100644 --- a/engines/access/access.cpp +++ b/engines/access/access.cpp @@ -41,6 +41,7 @@ AccessEngine::AccessEngine(OSystem *syst, const AccessGameDescription *gameDesc) _events = nullptr; _files = nullptr; _inventory = nullptr; + _midi = nullptr; _player = nullptr; _room = nullptr; _screen = nullptr; @@ -92,6 +93,8 @@ AccessEngine::AccessEngine(OSystem *syst, const AccessGameDescription *gameDesc) _vidX = _vidY = 0; _cheatFl = false; _restartFl = false; + _et = 0; + _printEnd = 0; } AccessEngine::~AccessEngine() { diff --git a/engines/access/amazon/amazon_game.cpp b/engines/access/amazon/amazon_game.cpp index 6c9a437e77..eb4fabdad9 100644 --- a/engines/access/amazon/amazon_game.cpp +++ b/engines/access/amazon/amazon_game.cpp @@ -61,9 +61,16 @@ AmazonEngine::AmazonEngine(OSystem *syst, const AccessGameDescription *gameDesc) _helpTbl[1] = _help2; _helpTbl[2] = _help3; + _chapter = 0; + _rawInactiveX = _rawInactiveY = 0; + _inactiveYOff = 0; + _hintLevel = 0; + _updateChapter = 0; + _oldTitleChapter = 0; + _iqValue = 0; + _chapterCells.push_back(CellIdent(0, 96, 17)); _inactive._spritesPtr = nullptr; - _inactive._altSpritesPtr = nullptr; _inactive._flags = _inactive._frameNumber = _inactive._offsetY = 0; _inactive._position = Common::Point(0, 0); } diff --git a/engines/access/amazon/amazon_logic.cpp b/engines/access/amazon/amazon_logic.cpp index 7f802f3cde..d2ee17a230 100644 --- a/engines/access/amazon/amazon_logic.cpp +++ b/engines/access/amazon/amazon_logic.cpp @@ -1371,6 +1371,18 @@ River::River(AmazonEngine *vm) : PannedScene(vm) { _deathCount = 0; _oldScrollCol = 0; _maxHits = 0; + _mapPtr = nullptr; + _canoeMoveCount = 0; + _canoeVXPos = 0; + _canoeFrame = 0; + _canoeDir = 0; + _canoeLane = 0; + _canoeYPos = 0; + _hitCount = 0; + _riverIndex = 0; + _topList = _botList = nullptr; + _deathType = 0; + _hitSafe = 0; } void River::setRiverPan() { diff --git a/engines/access/amazon/amazon_logic.h b/engines/access/amazon/amazon_logic.h index a1fb4eef77..0d962483e6 100644 --- a/engines/access/amazon/amazon_logic.h +++ b/engines/access/amazon/amazon_logic.h @@ -242,6 +242,8 @@ public: class InactivePlayer : public ImageEntry { public: SpriteResource *_altSpritesPtr; + + InactivePlayer() { _altSpritesPtr = nullptr; } }; } // End of namespace Amazon diff --git a/engines/access/animation.cpp b/engines/access/animation.cpp index 548e7db02d..cc699a27e3 100644 --- a/engines/access/animation.cpp +++ b/engines/access/animation.cpp @@ -63,6 +63,7 @@ Animation::Animation(AccessEngine *vm, Common::SeekableReadStream *stream) : Man _countdownTicks = stream->readUint16LE(); _currentLoopCount = stream->readSint16LE(); stream->readUint16LE(); // unk + _field10 = 0; Common::Array frameOffsets; uint16 ofs; diff --git a/engines/access/asurface.cpp b/engines/access/asurface.cpp index f45f121db4..e9a2e8a427 100644 --- a/engines/access/asurface.cpp +++ b/engines/access/asurface.cpp @@ -102,7 +102,7 @@ void ImageEntryList::addToList(ImageEntry &ie) { int ASurface::_clipWidth; int ASurface::_clipHeight; -ASurface::ASurface() { +ASurface::ASurface(): Graphics::Surface() { _leftSkip = _rightSkip = 0; _topSkip = _bottomSkip = 0; _lastBoundsX = _lastBoundsY = 0; @@ -110,6 +110,7 @@ ASurface::ASurface() { _orgX1 = _orgY1 = 0; _orgX2 = _orgY2 = 0; _lColor = 0; + _maxChars = 0; } ASurface::~ASurface() { diff --git a/engines/access/bubble_box.cpp b/engines/access/bubble_box.cpp index e37a8142e8..28c211991c 100644 --- a/engines/access/bubble_box.cpp +++ b/engines/access/bubble_box.cpp @@ -27,13 +27,12 @@ namespace Access { BubbleBox::BubbleBox(AccessEngine *vm) : Manager(vm) { + _startItem = 0; + _startBox = 0; + _charCol = _rowOff = 0; _type = TYPE_2; _bounds = Common::Rect(64, 32, 64 + 130, 32 + 122); _bubbleDisplStr = ""; - _fieldD = 0; - _fieldE = 0; - _fieldF = 0; - _field10 = 0; } void BubbleBox::load(Common::SeekableReadStream *stream) { diff --git a/engines/access/bubble_box.h b/engines/access/bubble_box.h index 0130344c7e..0b3f139520 100644 --- a/engines/access/bubble_box.h +++ b/engines/access/bubble_box.h @@ -49,10 +49,6 @@ public: Common::StringArray _nameIndex; Common::String _bubbleTitle; Common::String _bubbleDisplStr; - int _fieldD; - int _fieldE; - int _fieldF; - int _field10; Common::Array _bubbles; public: diff --git a/engines/access/font.cpp b/engines/access/font.cpp index da8f0b6ec5..8af183f193 100644 --- a/engines/access/font.cpp +++ b/engines/access/font.cpp @@ -27,6 +27,8 @@ namespace Access { byte Font::_fontColors[4]; Font::Font() { + _bitWidth = 0; + _height = 0; } Font::~Font() { diff --git a/engines/access/inventory.cpp b/engines/access/inventory.cpp index 8db62a45fc..df499ba705 100644 --- a/engines/access/inventory.cpp +++ b/engines/access/inventory.cpp @@ -57,6 +57,7 @@ InventoryManager::InventoryManager(AccessEngine *vm) : Manager(vm) { _startAboutItem = 0; _startTravelItem = 0; _iconDisplayFlag = true; + _boxNum = 0; const char *const *names; const int *combineP; diff --git a/engines/access/player.cpp b/engines/access/player.cpp index d547aedc1d..bcd553c6dc 100644 --- a/engines/access/player.cpp +++ b/engines/access/player.cpp @@ -73,6 +73,12 @@ Player::Player(AccessEngine *vm) : Manager(vm), ImageEntry() { _playerDirection = NONE; _xFlag = _yFlag = 0; _inactiveYOff = 0; + + _sideWalkMin = _sideWalkMax = 0; + _upWalkMin = _upWalkMax = 0; + _downWalkMin = _downWalkMax = 0; + _diagUpWalkMin = _diagUpWalkMax = 0; + _diagDownWalkMin = _diagDownWalkMax = 0; } Player::~Player() { diff --git a/engines/access/screen.cpp b/engines/access/screen.cpp index d6fddb73b2..970a8f3079 100644 --- a/engines/access/screen.cpp +++ b/engines/access/screen.cpp @@ -56,6 +56,7 @@ Screen::Screen(AccessEngine *vm) : _vm(vm) { _bufferBytesWide = _vWindowBytesWide = this->w; _vWindowLinesTall = this->h; + _vWindowWidth = _vWindowHeight = 0; _clipWidth = _vWindowBytesWide - 1; _clipHeight = _vWindowLinesTall - 1; _startCycle = 0; diff --git a/engines/access/scripts.cpp b/engines/access/scripts.cpp index dfb9bd963f..074c781352 100644 --- a/engines/access/scripts.cpp +++ b/engines/access/scripts.cpp @@ -29,10 +29,12 @@ namespace Access { Scripts::Scripts(AccessEngine *vm) : Manager(vm) { _resource = nullptr; + _specialFunction = -1; _data = nullptr; _sequence = 0; _endFlag = false; _returnCode = 0; + _scriptCommand = 0; _choice = 0; _choiceStart = 0; _charsOrg = Common::Point(0, 0); diff --git a/engines/access/video.cpp b/engines/access/video.cpp index b7d5652e5b..920c066898 100644 --- a/engines/access/video.cpp +++ b/engines/access/video.cpp @@ -27,10 +27,16 @@ namespace Access { VideoPlayer::VideoPlayer(AccessEngine *vm) : Manager(vm) { _vidSurface = nullptr; + _videoData = nullptr; + _startCoord = nullptr; + _frameCount = 0; + _xCount = 0; + _scanCount = 0; + _frameSize = 0; _videoFrame = 0; _soundFlag = false; _soundFrame = 0; - _videoData = nullptr; + _videoEnd = false; } VideoPlayer::~VideoPlayer() { -- cgit v1.2.3 From a7bfa55aa802b7f6adfe85cb981af9f2f42c2586 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 20 Dec 2014 10:01:52 -0500 Subject: ACCESS: Fix compiler warnings --- engines/access/amazon/amazon_logic.cpp | 13 +++++-------- engines/access/decompress.cpp | 5 +++-- 2 files changed, 8 insertions(+), 10 deletions(-) (limited to 'engines') diff --git a/engines/access/amazon/amazon_logic.cpp b/engines/access/amazon/amazon_logic.cpp index d2ee17a230..97bd9de650 100644 --- a/engines/access/amazon/amazon_logic.cpp +++ b/engines/access/amazon/amazon_logic.cpp @@ -1492,11 +1492,11 @@ void River::initRiver() { _maxHits = 2 - _vm->_riverFlag; _saveRiver = false; - Font &font2 = _vm->_fonts._font2; - font2._fontColors[0] = 0; - font2._fontColors[1] = 33; - font2._fontColors[2] = 34; - font2._fontColors[3] = 35; + // Set font colors for drawing using font2 + Font::_fontColors[0] = 0; + Font::_fontColors[1] = 33; + Font::_fontColors[2] = 34; + Font::_fontColors[3] = 35; } void River::resetPositions() { @@ -1522,8 +1522,6 @@ void River::checkRiverPan() { } bool River::riverJumpTest() { - Screen &screen = *_vm->_screen; - if (_vm->_scrollCol == 120 || _vm->_scrollCol == 60 || _vm->_scrollCol == 0) { int val = *++_mapPtr; if (val == 0xFF) @@ -1921,7 +1919,6 @@ void River::synchronize(Common::Serializer &s) { if (_vm->_player->_roomNumber == 45) { if (s.isSaving()) { // Set river properties to be saved out - Screen &screen = *_vm->_screen; _rScrollRow = _vm->_scrollRow; _rScrollCol = _vm->_scrollCol; _rScrollX = _vm->_scrollX; diff --git a/engines/access/decompress.cpp b/engines/access/decompress.cpp index 62bff87860..c5656afa51 100644 --- a/engines/access/decompress.cpp +++ b/engines/access/decompress.cpp @@ -32,8 +32,9 @@ void LzwDecompressor::decompress(byte *source, byte *dest) { _source = source; - byte litByte; - uint16 copyLength, maxCodeValue, code, nextCode, lastCode, oldCode; + byte litByte = 0; + uint16 oldCode = 0; + uint16 copyLength, maxCodeValue, code, nextCode, lastCode; byte *copyBuf = new byte[8192]; -- cgit v1.2.3 From 7cb18f8e7ac47e8c8c0b738401534ec0b99c2507 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 20 Dec 2014 10:59:16 -0500 Subject: ACCESS: Fix crash in the introduction sequence --- engines/access/amazon/amazon_logic.cpp | 14 +++++++------- engines/access/asurface.cpp | 1 + 2 files changed, 8 insertions(+), 7 deletions(-) (limited to 'engines') diff --git a/engines/access/amazon/amazon_logic.cpp b/engines/access/amazon/amazon_logic.cpp index 97bd9de650..e6a96b67d6 100644 --- a/engines/access/amazon/amazon_logic.cpp +++ b/engines/access/amazon/amazon_logic.cpp @@ -148,7 +148,7 @@ void CampScene::mWhileDoOpen() { _vm->_animation->animate(0); _vm->_animation->animate(1); pan(); - _vm->_buffer2.blitFrom(_vm->_buffer1); + _vm->_buffer2.copyFrom(_vm->_buffer1); _vm->_newRects.clear(); _vm->plotList(); _vm->copyBlocks(); @@ -176,8 +176,8 @@ void CampScene::mWhileDoOpen() { } events.showCursor(); - _vm->_buffer2.blitFrom(*_vm->_screen); - _vm->_buffer1.blitFrom(*_vm->_screen); + _vm->_buffer2.copyFrom(*_vm->_screen); + _vm->_buffer1.copyFrom(*_vm->_screen); _vm->freeCells(); _vm->_oldRects.clear(); @@ -323,8 +323,8 @@ void Opening::doTitle() { _vm->_files->_setPaletteFlag = false; _vm->_files->loadScreen(0, 3); - _vm->_buffer2.blitFrom(*_vm->_screen); - _vm->_buffer1.blitFrom(*_vm->_screen); + _vm->_buffer2.copyFrom(*_vm->_screen); + _vm->_buffer1.copyFrom(*_vm->_screen); screen.forceFadeIn(); _vm->_sound->playSound(1); @@ -347,8 +347,8 @@ void Opening::doTitle() { _vm->_files->loadScreen(0, 4); _vm->_sound->playSound(1); - _vm->_buffer2.blitFrom(*_vm->_screen); - _vm->_buffer1.blitFrom(*_vm->_screen); + _vm->_buffer2.copyFrom(*_vm->_screen); + _vm->_buffer1.copyFrom(*_vm->_screen); _vm->_sound->playSound(1); const int COUNTDOWN[6] = { 2, 0x80, 1, 0x7d, 0, 0x87 }; diff --git a/engines/access/asurface.cpp b/engines/access/asurface.cpp index e9a2e8a427..5f4372d5af 100644 --- a/engines/access/asurface.cpp +++ b/engines/access/asurface.cpp @@ -253,6 +253,7 @@ void ASurface::transBlitFrom(ASurface &src) { } void ASurface::blitFrom(Graphics::Surface &src) { + assert(w >= src.w && h >= src.h); for (int y = 0; y < src.h; ++y) { const byte *srcP = (const byte *)src.getBasePtr(0, y); byte *destP = (byte *)getBasePtr(0, y); -- cgit v1.2.3 From b41b3e1a89d7646561697b1bc3636345230a9f12 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 20 Dec 2014 13:26:32 +0200 Subject: ZVISION: Fix code formatting --- engines/zvision/file/search_manager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/zvision/file/search_manager.cpp b/engines/zvision/file/search_manager.cpp index 30c269c290..d0d4e43d12 100644 --- a/engines/zvision/file/search_manager.cpp +++ b/engines/zvision/file/search_manager.cpp @@ -265,7 +265,7 @@ void SearchManager::addDir(const Common::String &name) { void SearchManager::listDirRecursive(Common::List &_list, const Common::FSNode &fsNode, int depth) { Common::FSList fsList; - if ( fsNode.getChildren(fsList) ) { + if (fsNode.getChildren(fsList)) { _list.push_back(fsNode.getPath()); -- cgit v1.2.3 From 0f590561bd0fe7238fcfd5fcee0d8a4dc11b9979 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 20 Dec 2014 13:27:16 +0200 Subject: ZVISION: Simplify check Thanks to DrMcCoy for spotting this --- engines/zvision/sound/zork_raw.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/zvision/sound/zork_raw.cpp b/engines/zvision/sound/zork_raw.cpp index 8688039325..b2c88b34df 100644 --- a/engines/zvision/sound/zork_raw.cpp +++ b/engines/zvision/sound/zork_raw.cpp @@ -73,10 +73,7 @@ RawChunkStream::RawChunk RawChunkStream::readNextChunk(Common::SeekableReadStrea tmp.size = 0; tmp.data = NULL; - if (!stream) - return tmp; - - if (stream && (stream->size() == 0 || stream->eos())) + if (!stream || stream->size() == 0 || stream->eos()) return tmp; tmp.size = (stream->size() - stream->pos()) * 2; -- cgit v1.2.3 From 0433eda4dec8b6ac660aacec2ae3866461214ce3 Mon Sep 17 00:00:00 2001 From: Thierry Crozat Date: Sun, 21 Dec 2014 18:25:57 +0000 Subject: CGE2: Add detection for new English freeware version --- engines/cge2/detection.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'engines') diff --git a/engines/cge2/detection.cpp b/engines/cge2/detection.cpp index 6e1b93d0b8..4acdea3fde 100644 --- a/engines/cge2/detection.cpp +++ b/engines/cge2/detection.cpp @@ -80,6 +80,16 @@ static const ADGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformDOS, ADGF_NO_FLAGS, GUIO1(GAMEOPTION_COLOR_BLIND_DEFAULT_OFF) }, + + { + "sfinx", "Freeware v1.1", + { + {"vol.cat", 0, "f158e469dccbebc5a632eb848df89779", 129024}, + {"vol.dat", 0, "d40a6b4ae173d6930be54ba56bee15d5", 34182773}, + AD_LISTEND + }, + Common::EN_ANY, Common::kPlatformDOS, ADGF_NO_FLAGS, GUIO1(GAMEOPTION_COLOR_BLIND_DEFAULT_OFF) + }, AD_TABLE_END_MARKER }; -- cgit v1.2.3 From 965dafe31b1c1f7c4684c0d2cbdb3461e3fddac8 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 21 Dec 2014 23:33:01 +0200 Subject: ZVISION: Implement the "dumpallscripts" console command again --- engines/zvision/core/console.cpp | 40 ++++++++++++++++++++++++++------- engines/zvision/core/console.h | 1 + engines/zvision/file/search_manager.cpp | 7 ++++++ engines/zvision/file/search_manager.h | 18 +++++++-------- 4 files changed, 48 insertions(+), 18 deletions(-) (limited to 'engines') diff --git a/engines/zvision/core/console.cpp b/engines/zvision/core/console.cpp index 4dd10d6f40..0789f8d4fb 100644 --- a/engines/zvision/core/console.cpp +++ b/engines/zvision/core/console.cpp @@ -52,6 +52,7 @@ Console::Console(ZVision *engine) : GUI::Debugger(), _engine(engine) { registerCmd("setpanoramascale", WRAP_METHOD(Console, cmdSetPanoramaScale)); registerCmd("location", WRAP_METHOD(Console, cmdLocation)); registerCmd("dumpfile", WRAP_METHOD(Console, cmdDumpFile)); + registerCmd("dumpallscripts", WRAP_METHOD(Console, cmdDumpAllScripts)); } bool Console::cmdLoadVideo(int argc, const char **argv) { @@ -205,6 +206,20 @@ bool Console::cmdLocation(int argc, const char **argv) { return true; } +void dumpFile(Common::SeekableReadStream *s, const char *outName) { + byte *buffer = new byte[s->size()]; + s->read(buffer, s->size()); + + Common::DumpFile dumpFile; + dumpFile.open(outName); + + dumpFile.write(buffer, s->size()); + dumpFile.flush(); + dumpFile.close(); + + delete[] buffer; +} + bool Console::cmdDumpFile(int argc, const char **argv) { if (argc != 2) { debugPrintf("Use %s to dump a file\n", argv[0]); @@ -217,17 +232,26 @@ bool Console::cmdDumpFile(int argc, const char **argv) { return true; } - byte *buffer = new byte[f.size()]; - f.read(buffer, f.size()); + dumpFile(&f, argv[1]); - Common::DumpFile dumpFile; - dumpFile.open(argv[1]); + return true; +} - dumpFile.write(buffer, f.size()); - dumpFile.flush(); - dumpFile.close(); +bool Console::cmdDumpAllScripts(int argc, const char **argv) { + Common::String fileName; + Common::SeekableReadStream *in; - delete[] buffer; + SearchManager::MatchList fileList; + _engine->getSearchManager()->listMembersWithExtension(fileList, "scr"); + + for (SearchManager::MatchList::iterator iter = fileList.begin(); iter != fileList.end(); ++iter) { + fileName = iter->_value.name; + debugPrintf("Dumping %s\n", fileName.c_str()); + + in = iter->_value.arch->createReadStreamForMember(iter->_value.name); + dumpFile(in, fileName.c_str()); + delete in; + } return true; } diff --git a/engines/zvision/core/console.h b/engines/zvision/core/console.h index 299bd6127f..7e27fe8f26 100644 --- a/engines/zvision/core/console.h +++ b/engines/zvision/core/console.h @@ -46,6 +46,7 @@ private: bool cmdSetPanoramaScale(int argc, const char **argv); bool cmdLocation(int argc, const char **argv); bool cmdDumpFile(int argc, const char **argv); + bool cmdDumpAllScripts(int argc, const char **argv); }; } // End of namespace ZVision diff --git a/engines/zvision/file/search_manager.cpp b/engines/zvision/file/search_manager.cpp index d0d4e43d12..7a907df39c 100644 --- a/engines/zvision/file/search_manager.cpp +++ b/engines/zvision/file/search_manager.cpp @@ -275,4 +275,11 @@ void SearchManager::listDirRecursive(Common::List &_list, const } } +void SearchManager::listMembersWithExtension(MatchList &fileList, Common::String extension) { + for (SearchManager::MatchList::iterator it = _files.begin(); it != _files.end(); ++it) { + if (it->_key.hasSuffix(extension)) + fileList[it->_key] = it->_value; + } +} + } // End of namespace ZVision diff --git a/engines/zvision/file/search_manager.h b/engines/zvision/file/search_manager.h index fdd70fd381..b9ed02ec13 100644 --- a/engines/zvision/file/search_manager.h +++ b/engines/zvision/file/search_manager.h @@ -47,25 +47,23 @@ public: void loadZix(const Common::String &name); -private: - - void listDirRecursive(Common::List &dirList, const Common::FSNode &fsNode, int depth); - struct Node { Common::String name; Common::Archive *arch; }; - Common::List _dirList; - typedef Common::HashMap MatchList; - Common::List _archList; - MatchList _files; - - Common::String _root; + void listMembersWithExtension(MatchList &fileList, Common::String extension); private: + + void listDirRecursive(Common::List &dirList, const Common::FSNode &fsNode, int depth); + + Common::List _dirList; + Common::List _archList; + Common::String _root; + MatchList _files; }; } -- cgit v1.2.3 From e5ecd500cfbf1c91da31dab0a5a71ff43ed82033 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 21 Dec 2014 23:33:48 +0200 Subject: ZVISION: Document some controls that are only used in Zork: Nemesis --- engines/zvision/scripting/controls/fist_control.h | 1 + engines/zvision/scripting/controls/hotmov_control.h | 1 + engines/zvision/scripting/controls/paint_control.h | 1 + engines/zvision/scripting/controls/titler_control.h | 1 + engines/zvision/scripting/scr_file_handling.cpp | 4 ++++ 5 files changed, 8 insertions(+) (limited to 'engines') diff --git a/engines/zvision/scripting/controls/fist_control.h b/engines/zvision/scripting/controls/fist_control.h index 0a6b977ead..bad2daa6d5 100644 --- a/engines/zvision/scripting/controls/fist_control.h +++ b/engines/zvision/scripting/controls/fist_control.h @@ -34,6 +34,7 @@ namespace Video { namespace ZVision { +// Only used in Zork Nemesis, it handles the door lock puzzle with the skeletal fingers (td60, td90, td9e) class FistControl : public Control { public: FistControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream); diff --git a/engines/zvision/scripting/controls/hotmov_control.h b/engines/zvision/scripting/controls/hotmov_control.h index b18d44c7a6..640fab00c0 100644 --- a/engines/zvision/scripting/controls/hotmov_control.h +++ b/engines/zvision/scripting/controls/hotmov_control.h @@ -34,6 +34,7 @@ namespace Video { namespace ZVision { +// Only used in Zork Nemesis, it handles movies where the player needs to click on something (mj7g, vw3g) class HotMovControl : public Control { public: HotMovControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream); diff --git a/engines/zvision/scripting/controls/paint_control.h b/engines/zvision/scripting/controls/paint_control.h index 8097290ac2..0e5b59b821 100644 --- a/engines/zvision/scripting/controls/paint_control.h +++ b/engines/zvision/scripting/controls/paint_control.h @@ -32,6 +32,7 @@ namespace ZVision { +// Only used in Zork Nemesis, it's the painting puzzle screen in Lucien's room in Irondune (ch4g) class PaintControl : public Control { public: PaintControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream); diff --git a/engines/zvision/scripting/controls/titler_control.h b/engines/zvision/scripting/controls/titler_control.h index 075e47c9e9..86bb398b3c 100644 --- a/engines/zvision/scripting/controls/titler_control.h +++ b/engines/zvision/scripting/controls/titler_control.h @@ -32,6 +32,7 @@ namespace ZVision { +// Only used in Zork Nemesis - it's the death screen with the Restore/Exit buttons class TitlerControl : public Control { public: TitlerControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream); diff --git a/engines/zvision/scripting/scr_file_handling.cpp b/engines/zvision/scripting/scr_file_handling.cpp index c117da5ec2..47b8b0aa39 100644 --- a/engines/zvision/scripting/scr_file_handling.cpp +++ b/engines/zvision/scripting/scr_file_handling.cpp @@ -358,12 +358,16 @@ Control *ScriptManager::parseControl(Common::String &line, Common::SeekableReadS } else if (controlType.equalsIgnoreCase("safe")) { return new SafeControl(_engine, key, stream); } else if (controlType.equalsIgnoreCase("hotmovie")) { + // Only used in Zork Nemesis, it handles movies where the player needs to click on something (mj7g, vw3g) return new HotMovControl(_engine, key, stream); } else if (controlType.equalsIgnoreCase("fist")) { + // Only used in Zork Nemesis, it handles the door lock puzzle with the skeletal fingers (td60, td90, td9e) return new FistControl(_engine, key, stream); } else if (controlType.equalsIgnoreCase("paint")) { + // Only used in Zork Nemesis, it's the painting puzzle screen in Lucien's room in Irondune (ch4g) return new PaintControl(_engine, key, stream); } else if (controlType.equalsIgnoreCase("titler")) { + // Only used in Zork Nemesis - it's the death screen with the Restore/Exit buttons (cjde) return new TitlerControl(_engine, key, stream); } return NULL; -- cgit v1.2.3 From 24f0cce9c6b0da33d1558059c6fbdb966eb5fb4e Mon Sep 17 00:00:00 2001 From: Strangerke Date: Sun, 21 Dec 2014 22:28:25 +0100 Subject: ACCESS: Fix bug in setHorizontalCode() --- engines/access/amazon/amazon_logic.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/access/amazon/amazon_logic.cpp b/engines/access/amazon/amazon_logic.cpp index e6a96b67d6..4a313e8880 100644 --- a/engines/access/amazon/amazon_logic.cpp +++ b/engines/access/amazon/amazon_logic.cpp @@ -1035,7 +1035,7 @@ void Guard::setHorizontalCode() { if (_bottomRight.x < screen._orgX1) _gCode2 |= 8; - else if (_bottomRight.y > screen._orgX2) + else if (_bottomRight.x > screen._orgX2) _gCode2 |= 2; } -- cgit v1.2.3 From 4a1ddd5d0c8760dbdee967d8152c8e0e650eb4df Mon Sep 17 00:00:00 2001 From: Strangerke Date: Sun, 21 Dec 2014 22:49:18 +0100 Subject: ACCESS: Remove unused variable --- engines/access/access.cpp | 1 - engines/access/access.h | 1 - engines/access/amazon/amazon_game.cpp | 1 - 3 files changed, 3 deletions(-) (limited to 'engines') diff --git a/engines/access/access.cpp b/engines/access/access.cpp index 39e6c2b530..67255ff5ea 100644 --- a/engines/access/access.cpp +++ b/engines/access/access.cpp @@ -93,7 +93,6 @@ AccessEngine::AccessEngine(OSystem *syst, const AccessGameDescription *gameDesc) _vidX = _vidY = 0; _cheatFl = false; _restartFl = false; - _et = 0; _printEnd = 0; } diff --git a/engines/access/access.h b/engines/access/access.h index a082b969c4..be007e0cb8 100644 --- a/engines/access/access.h +++ b/engines/access/access.h @@ -191,7 +191,6 @@ public: bool _canSaveLoad; Resource *_establish; - int _et; int _printEnd; int _txtPages; int _narateFile; diff --git a/engines/access/amazon/amazon_game.cpp b/engines/access/amazon/amazon_game.cpp index eb4fabdad9..d6b759b308 100644 --- a/engines/access/amazon/amazon_game.cpp +++ b/engines/access/amazon/amazon_game.cpp @@ -268,7 +268,6 @@ void AmazonEngine::doEstablish(int screenId, int estabIndex) { _screen->_maxChars = 37; _screen->_printOrg = _screen->_printStart = Common::Point(48, 35); loadEstablish(estabIndex); - _et = estabIndex; uint16 msgOffset; if (!isCD()) msgOffset = READ_LE_UINT16(_establish->data() + (estabIndex * 2)); -- cgit v1.2.3 From 8bc30d0dfbc538c3631692a807d37e9007958da9 Mon Sep 17 00:00:00 2001 From: Strangerke Date: Sun, 21 Dec 2014 22:53:20 +0100 Subject: ACCESS: Initialize header in videoPlayer constructor --- engines/access/video.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'engines') diff --git a/engines/access/video.cpp b/engines/access/video.cpp index 920c066898..edc0bcda27 100644 --- a/engines/access/video.cpp +++ b/engines/access/video.cpp @@ -29,6 +29,7 @@ VideoPlayer::VideoPlayer(AccessEngine *vm) : Manager(vm) { _vidSurface = nullptr; _videoData = nullptr; _startCoord = nullptr; + _frameCount = 0; _xCount = 0; _scanCount = 0; @@ -37,6 +38,10 @@ VideoPlayer::VideoPlayer(AccessEngine *vm) : Manager(vm) { _soundFlag = false; _soundFrame = 0; _videoEnd = false; + + _header._frameCount = 0; + _header._width = _header._height = 0; + _header._flags = 0; } VideoPlayer::~VideoPlayer() { -- cgit v1.2.3 From 99087c7f454970665391004321c0fc510cdaf9bd Mon Sep 17 00:00:00 2001 From: Strangerke Date: Sun, 21 Dec 2014 22:55:24 +0100 Subject: ACCESS: Use enum instead of int to initialize video flag --- engines/access/video.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/access/video.cpp b/engines/access/video.cpp index edc0bcda27..63d0aa5c89 100644 --- a/engines/access/video.cpp +++ b/engines/access/video.cpp @@ -41,7 +41,7 @@ VideoPlayer::VideoPlayer(AccessEngine *vm) : Manager(vm) { _header._frameCount = 0; _header._width = _header._height = 0; - _header._flags = 0; + _header._flags = VIDEOFLAG_NONE; } VideoPlayer::~VideoPlayer() { -- cgit v1.2.3 From dfae161386a2ad9e6828f71e90dd19598ca52f36 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 22 Dec 2014 00:26:53 +0200 Subject: ZVISION: Implement the Venus hint system in Zork: Nemesis --- engines/zvision/core/events.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'engines') diff --git a/engines/zvision/core/events.cpp b/engines/zvision/core/events.cpp index 6cf0ae5d0d..f0cf3f0789 100644 --- a/engines/zvision/core/events.cpp +++ b/engines/zvision/core/events.cpp @@ -145,6 +145,11 @@ void ZVision::cheatCodes(uint8 key) { getBufferedKey(2), getBufferedKey(1), getBufferedKey(0), 0); + + // Show the Venus screen when "?" or "/" is pressed while inside the temple world + if (_scriptManager->getStateValue(StateKey_VenusEnable) == 1) + if ((checkCode("?") || checkCode("/")) && _scriptManager->getStateValue(StateKey_World) == 't') + _scriptManager->changeLocation('g', 'j', 'h', 'e', 0); } void ZVision::processEvents() { -- cgit v1.2.3 From 41dbbe346c4b46b4b48cdb38687216b1dd254fb4 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 22 Dec 2014 00:29:19 +0200 Subject: ZVISION: Also allow the movement when the cursor is within screen edges This matches the behavior of the original in Zork: Nemesis. ZGI already fills the screen horizontally --- engines/zvision/core/events.cpp | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'engines') diff --git a/engines/zvision/core/events.cpp b/engines/zvision/core/events.cpp index f0cf3f0789..81ad28f29b 100644 --- a/engines/zvision/core/events.cpp +++ b/engines/zvision/core/events.cpp @@ -284,26 +284,30 @@ void ZVision::onMouseMove(const Common::Point &pos) { // | // ^ - if (_workingWindow.contains(pos)) { - cursorWasChanged = _scriptManager->onMouseMove(pos, imageCoord); + // Clip the horizontal mouse position to the working window + Common::Point clippedPos = pos; + clippedPos.x = CLIP(pos.x, _workingWindow.left + 1, _workingWindow.right - 1); + + if (_workingWindow.contains(clippedPos)) { + cursorWasChanged = _scriptManager->onMouseMove(clippedPos, imageCoord); RenderTable::RenderState renderState = _renderManager->getRenderTable()->getRenderState(); if (renderState == RenderTable::PANORAMA) { - if (pos.x >= _workingWindow.left && pos.x < _workingWindow.left + ROTATION_SCREEN_EDGE_OFFSET) { + if (clippedPos.x >= _workingWindow.left && clippedPos.x < _workingWindow.left + ROTATION_SCREEN_EDGE_OFFSET) { int16 mspeed = _scriptManager->getStateValue(StateKey_RotateSpeed) >> 4; if (mspeed <= 0) mspeed = 400 >> 4; - _mouseVelocity = (((pos.x - (ROTATION_SCREEN_EDGE_OFFSET + _workingWindow.left)) << 7) / ROTATION_SCREEN_EDGE_OFFSET * mspeed) >> 7; + _mouseVelocity = (((clippedPos.x - (ROTATION_SCREEN_EDGE_OFFSET + _workingWindow.left)) << 7) / ROTATION_SCREEN_EDGE_OFFSET * mspeed) >> 7; _cursorManager->changeCursor(CursorIndex_Left); cursorWasChanged = true; - } else if (pos.x <= _workingWindow.right && pos.x > _workingWindow.right - ROTATION_SCREEN_EDGE_OFFSET) { + } else if (clippedPos.x <= _workingWindow.right && clippedPos.x > _workingWindow.right - ROTATION_SCREEN_EDGE_OFFSET) { int16 mspeed = _scriptManager->getStateValue(StateKey_RotateSpeed) >> 4; if (mspeed <= 0) mspeed = 400 >> 4; - _mouseVelocity = (((pos.x - (_workingWindow.right - ROTATION_SCREEN_EDGE_OFFSET)) << 7) / ROTATION_SCREEN_EDGE_OFFSET * mspeed) >> 7; + _mouseVelocity = (((clippedPos.x - (_workingWindow.right - ROTATION_SCREEN_EDGE_OFFSET)) << 7) / ROTATION_SCREEN_EDGE_OFFSET * mspeed) >> 7; _cursorManager->changeCursor(CursorIndex_Right); cursorWasChanged = true; @@ -311,21 +315,21 @@ void ZVision::onMouseMove(const Common::Point &pos) { _mouseVelocity = 0; } } else if (renderState == RenderTable::TILT) { - if (pos.y >= _workingWindow.top && pos.y < _workingWindow.top + ROTATION_SCREEN_EDGE_OFFSET) { + if (clippedPos.y >= _workingWindow.top && clippedPos.y < _workingWindow.top + ROTATION_SCREEN_EDGE_OFFSET) { int16 mspeed = _scriptManager->getStateValue(StateKey_RotateSpeed) >> 4; if (mspeed <= 0) mspeed = 400 >> 4; - _mouseVelocity = (((pos.y - (_workingWindow.top + ROTATION_SCREEN_EDGE_OFFSET)) << 7) / ROTATION_SCREEN_EDGE_OFFSET * mspeed) >> 7; + _mouseVelocity = (((clippedPos.y - (_workingWindow.top + ROTATION_SCREEN_EDGE_OFFSET)) << 7) / ROTATION_SCREEN_EDGE_OFFSET * mspeed) >> 7; _cursorManager->changeCursor(CursorIndex_UpArr); cursorWasChanged = true; - } else if (pos.y <= _workingWindow.bottom && pos.y > _workingWindow.bottom - ROTATION_SCREEN_EDGE_OFFSET) { + } else if (clippedPos.y <= _workingWindow.bottom && clippedPos.y > _workingWindow.bottom - ROTATION_SCREEN_EDGE_OFFSET) { int16 mspeed = _scriptManager->getStateValue(StateKey_RotateSpeed) >> 4; if (mspeed <= 0) mspeed = 400 >> 4; - _mouseVelocity = (((pos.y - (_workingWindow.bottom - ROTATION_SCREEN_EDGE_OFFSET)) << 7) / ROTATION_SCREEN_EDGE_OFFSET * mspeed) >> 7; + _mouseVelocity = (((clippedPos.y - (_workingWindow.bottom - ROTATION_SCREEN_EDGE_OFFSET)) << 7) / ROTATION_SCREEN_EDGE_OFFSET * mspeed) >> 7; _cursorManager->changeCursor(CursorIndex_DownArr); cursorWasChanged = true; -- cgit v1.2.3 From b0e6c30ee288130d6b904a6f770044564b0490e6 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 22 Dec 2014 00:45:34 +0200 Subject: ZVISION: Fix Venus key code handling in commit dfae161 --- engines/zvision/core/events.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/zvision/core/events.cpp b/engines/zvision/core/events.cpp index 81ad28f29b..6e8cf1fe4f 100644 --- a/engines/zvision/core/events.cpp +++ b/engines/zvision/core/events.cpp @@ -148,7 +148,7 @@ void ZVision::cheatCodes(uint8 key) { // Show the Venus screen when "?" or "/" is pressed while inside the temple world if (_scriptManager->getStateValue(StateKey_VenusEnable) == 1) - if ((checkCode("?") || checkCode("/")) && _scriptManager->getStateValue(StateKey_World) == 't') + if (getBufferedKey(0) == 0xBF && _scriptManager->getStateValue(StateKey_World) == 't') _scriptManager->changeLocation('g', 'j', 'h', 'e', 0); } -- cgit v1.2.3 From 85644b887944dc4fc261827ae812a4e4684651bb Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 22 Dec 2014 00:54:08 +0200 Subject: ZVISION: Prefix some class member variables with an underscore --- engines/zvision/scripting/sidefx/ttytext_node.cpp | 6 +- engines/zvision/text/text.cpp | 132 +++++++++++----------- engines/zvision/text/text.h | 30 ++--- 3 files changed, 84 insertions(+), 84 deletions(-) (limited to 'engines') diff --git a/engines/zvision/scripting/sidefx/ttytext_node.cpp b/engines/zvision/scripting/sidefx/ttytext_node.cpp index 9a7fa01649..2930118524 100644 --- a/engines/zvision/scripting/sidefx/ttytext_node.cpp +++ b/engines/zvision/scripting/sidefx/ttytext_node.cpp @@ -57,7 +57,7 @@ ttyTextNode::ttyTextNode(ZVision *engine, uint32 key, const Common::String &file delete infile; } _img.create(_r.width(), _r.height(), _engine->_pixelFormat); - _style.sharp = true; + _style._sharp = true; _style.readAllStyle(_txtbuf); _style.setFont(_fnt); _engine->getScriptManager()->setStateValue(_key, 1); @@ -96,7 +96,7 @@ bool ttyTextNode::process(uint32 deltaTimeInMillis) { if (ret & TXT_RET_HASSTBOX) { Common::String buf; - buf = Common::String::format("%d", _engine->getScriptManager()->getStateValue(_style.statebox)); + buf = Common::String::format("%d", _engine->getScriptManager()->getStateValue(_style._statebox)); for (uint8 j = 0; j < buf.size(); j++) outchar(buf[j]); @@ -158,7 +158,7 @@ void ttyTextNode::newline() { } void ttyTextNode::outchar(uint16 chr) { - uint32 clr = _engine->_pixelFormat.RGBToColor(_style.red, _style.green, _style.blue); + uint32 clr = _engine->_pixelFormat.RGBToColor(_style._red, _style._green, _style._blue); if (_dx + _fnt.getCharWidth(chr) > _r.width()) newline(); diff --git a/engines/zvision/text/text.cpp b/engines/zvision/text/text.cpp index 406c36e5b0..08b57914c2 100644 --- a/engines/zvision/text/text.cpp +++ b/engines/zvision/text/text.cpp @@ -39,21 +39,21 @@ namespace ZVision { cTxtStyle::cTxtStyle() { - fontname = "Arial"; - blue = 255; - green = 255; - red = 255; - bold = false; - escapement = 0; - italic = false; - justify = TXT_JUSTIFY_LEFT; - newline = false; - size = 12; - skipcolor = false; - strikeout = false; - underline = false; - statebox = 0; - sharp = false; + _fontname = "Arial"; + _blue = 255; + _green = 255; + _red = 255; + _bold = false; + _escapement = 0; + _italic = false; + _justify = TXT_JUSTIFY_LEFT; + _newline = false; + _size = 12; + _skipcolor = false; + _strikeout = false; + _underline = false; + _statebox = 0; + _sharp = false; } txtReturn cTxtStyle::parseStyle(const Common::String &strin, int16 ln) { @@ -80,10 +80,10 @@ txtReturn cTxtStyle::parseStyle(const Common::String &strin, int16 ln) { if (_tmp.lastChar() == '"') _tmp.deleteLastChar(); - fontname = _tmp; + _fontname = _tmp; } else { if (!tokenizer.empty()) - fontname = token; + _fontname = token; } retval |= TXT_RET_FNTCHG; @@ -91,8 +91,8 @@ txtReturn cTxtStyle::parseStyle(const Common::String &strin, int16 ln) { if (!tokenizer.empty()) { token = tokenizer.nextToken(); int32 tmp = atoi(token.c_str()); - if (blue != tmp) { - blue = tmp; + if (_blue != tmp) { + _blue = tmp; retval |= TXT_RET_FNTSTL; } } @@ -100,8 +100,8 @@ txtReturn cTxtStyle::parseStyle(const Common::String &strin, int16 ln) { if (!tokenizer.empty()) { token = tokenizer.nextToken(); int32 tmp = atoi(token.c_str()); - if (red != tmp) { - red = tmp; + if (_red != tmp) { + _red = tmp; retval |= TXT_RET_FNTSTL; } } @@ -109,23 +109,23 @@ txtReturn cTxtStyle::parseStyle(const Common::String &strin, int16 ln) { if (!tokenizer.empty()) { token = tokenizer.nextToken(); int32 tmp = atoi(token.c_str()); - if (green != tmp) { - green = tmp; + if (_green != tmp) { + _green = tmp; retval |= TXT_RET_FNTSTL; } } } else if (token.matchString("newline", true)) { if ((retval & TXT_RET_NEWLN) == 0) - newline = 0; + _newline = 0; - newline++; + _newline++; retval |= TXT_RET_NEWLN; } else if (token.matchString("point", true)) { if (!tokenizer.empty()) { token = tokenizer.nextToken(); int32 tmp = atoi(token.c_str()); - if (size != tmp) { - size = tmp; + if (_size != tmp) { + _size = tmp; retval |= TXT_RET_FNTCHG; } } @@ -133,19 +133,19 @@ txtReturn cTxtStyle::parseStyle(const Common::String &strin, int16 ln) { if (!tokenizer.empty()) { token = tokenizer.nextToken(); int32 tmp = atoi(token.c_str()); - escapement = tmp; + _escapement = tmp; } } else if (token.matchString("italic", true)) { if (!tokenizer.empty()) { token = tokenizer.nextToken(); if (token.matchString("on", true)) { - if (italic != true) { - italic = true; + if (_italic != true) { + _italic = true; retval |= TXT_RET_FNTSTL; } } else if (token.matchString("off", true)) { - if (italic != false) { - italic = false; + if (_italic != false) { + _italic = false; retval |= TXT_RET_FNTSTL; } } @@ -154,13 +154,13 @@ txtReturn cTxtStyle::parseStyle(const Common::String &strin, int16 ln) { if (!tokenizer.empty()) { token = tokenizer.nextToken(); if (token.matchString("on", true)) { - if (underline != true) { - underline = true; + if (_underline != true) { + _underline = true; retval |= TXT_RET_FNTSTL; } } else if (token.matchString("off", true)) { - if (underline != false) { - underline = false; + if (_underline != false) { + _underline = false; retval |= TXT_RET_FNTSTL; } } @@ -169,13 +169,13 @@ txtReturn cTxtStyle::parseStyle(const Common::String &strin, int16 ln) { if (!tokenizer.empty()) { token = tokenizer.nextToken(); if (token.matchString("on", true)) { - if (strikeout != true) { - strikeout = true; + if (_strikeout != true) { + _strikeout = true; retval |= TXT_RET_FNTSTL; } } else if (token.matchString("off", true)) { - if (strikeout != false) { - strikeout = false; + if (_strikeout != false) { + _strikeout = false; retval |= TXT_RET_FNTSTL; } } @@ -184,13 +184,13 @@ txtReturn cTxtStyle::parseStyle(const Common::String &strin, int16 ln) { if (!tokenizer.empty()) { token = tokenizer.nextToken(); if (token.matchString("on", true)) { - if (bold != true) { - bold = true; + if (_bold != true) { + _bold = true; retval |= TXT_RET_FNTSTL; } } else if (token.matchString("off", true)) { - if (bold != false) { - bold = false; + if (_bold != false) { + _bold = false; retval |= TXT_RET_FNTSTL; } } @@ -199,9 +199,9 @@ txtReturn cTxtStyle::parseStyle(const Common::String &strin, int16 ln) { if (!tokenizer.empty()) { token = tokenizer.nextToken(); if (token.matchString("on", true)) { - skipcolor = true; + _skipcolor = true; } else if (token.matchString("off", true)) { - skipcolor = false; + _skipcolor = false; } } } else if (token.matchString("image", true)) { @@ -209,18 +209,18 @@ txtReturn cTxtStyle::parseStyle(const Common::String &strin, int16 ln) { } else if (token.matchString("statebox", true)) { if (!tokenizer.empty()) { token = tokenizer.nextToken(); - statebox = atoi(token.c_str()); + _statebox = atoi(token.c_str()); retval |= TXT_RET_HASSTBOX; } } else if (token.matchString("justify", true)) { if (!tokenizer.empty()) { token = tokenizer.nextToken(); if (token.matchString("center", true)) - justify = TXT_JUSTIFY_CENTER; + _justify = TXT_JUSTIFY_CENTER; else if (token.matchString("left", true)) - justify = TXT_JUSTIFY_LEFT; + _justify = TXT_JUSTIFY_LEFT; else if (token.matchString("right", true)) - justify = TXT_JUSTIFY_RIGHT; + _justify = TXT_JUSTIFY_RIGHT; } } } @@ -247,19 +247,19 @@ void cTxtStyle::readAllStyle(const Common::String &txt) { void cTxtStyle::setFontStyle(StyledTTFont &font) { uint tempStyle = 0; - if (bold) + if (_bold) tempStyle |= StyledTTFont::STTF_BOLD; - if (italic) + if (_italic) tempStyle |= StyledTTFont::STTF_ITALIC; - if (underline) + if (_underline) tempStyle |= StyledTTFont::STTF_UNDERLINE; - if (strikeout) + if (_strikeout) tempStyle |= StyledTTFont::STTF_STRIKEOUT; - if (sharp) + if (_sharp) tempStyle |= StyledTTFont::STTF_SHARP; font.setStyle(tempStyle); @@ -268,27 +268,27 @@ void cTxtStyle::setFontStyle(StyledTTFont &font) { void cTxtStyle::setFont(StyledTTFont &font) { uint tempStyle = 0; - if (bold) + if (_bold) tempStyle |= StyledTTFont::STTF_BOLD; - if (italic) + if (_italic) tempStyle |= StyledTTFont::STTF_ITALIC; - if (underline) + if (_underline) tempStyle |= StyledTTFont::STTF_UNDERLINE; - if (strikeout) + if (_strikeout) tempStyle |= StyledTTFont::STTF_STRIKEOUT; - if (sharp) + if (_sharp) tempStyle |= StyledTTFont::STTF_SHARP; - font.loadFont(fontname, size, tempStyle); + font.loadFont(_fontname, _size, tempStyle); } Graphics::Surface *TextRenderer::render(StyledTTFont &fnt, const Common::String &txt, cTxtStyle &style) { style.setFontStyle(fnt); - uint32 clr = _engine->_pixelFormat.RGBToColor(style.red, style.green, style.blue); + uint32 clr = _engine->_pixelFormat.RGBToColor(style._red, style._green, style._blue); return fnt.renderSolidText(txt, clr); } @@ -307,13 +307,13 @@ int32 TextRenderer::drawTxt(const Common::String &txt, cTxtStyle &fontStyle, Gra dst.fillRect(Common::Rect(dst.w, dst.h), 0); - uint32 clr = _engine->_pixelFormat.RGBToColor(fontStyle.red, fontStyle.green, fontStyle.blue); + uint32 clr = _engine->_pixelFormat.RGBToColor(fontStyle._red, fontStyle._green, fontStyle._blue); int16 w; w = font.getStringWidth(txt); - drawTxtWithJustify(txt, font, clr, dst, 0, fontStyle.justify); + drawTxtWithJustify(txt, font, clr, dst, 0, fontStyle._justify); return w; } @@ -352,7 +352,7 @@ void TextRenderer::drawTxtInOneLine(const Common::String &text, Graphics::Surfac int16 prevbufspace = 0, prevtxtspace = 0; while (i < stringlen) { - TxtJustify[currentline] = style.justify; + TxtJustify[currentline] = style._justify; if (text[i] == '<') { int16 ret = 0; @@ -396,7 +396,7 @@ void TextRenderer::drawTxtInOneLine(const Common::String &text, Graphics::Surfac if (ret & TXT_RET_HASSTBOX) { Common::String buf3; - buf3 = Common::String::format("%d", _engine->getScriptManager()->getStateValue(style.statebox)); + buf3 = Common::String::format("%d", _engine->getScriptManager()->getStateValue(style._statebox)); buf += buf3; textPosition += buf3.size(); } diff --git a/engines/zvision/text/text.h b/engines/zvision/text/text.h index ecec3ccde6..c3c60f6b76 100644 --- a/engines/zvision/text/text.h +++ b/engines/zvision/text/text.h @@ -55,21 +55,21 @@ public: void setFont(StyledTTFont &font); public: - Common::String fontname; - txtJustify justify; // 0 - center, 1-left, 2-right - int16 size; - uint8 red; // 0-255 - uint8 green; // 0-255 - uint8 blue; // 0-255 - int8 newline; - int8 escapement; - bool italic; - bool bold; - bool underline; - bool strikeout; - bool skipcolor; - int32 statebox; - bool sharp; + Common::String _fontname; + txtJustify _justify; // 0 - center, 1-left, 2-right + int16 _size; + uint8 _red; // 0-255 + uint8 _green; // 0-255 + uint8 _blue; // 0-255 + int8 _newline; + int8 _escapement; + bool _italic; + bool _bold; + bool _underline; + bool _strikeout; + bool _skipcolor; + int32 _statebox; + bool _sharp; // char image ?? }; -- cgit v1.2.3 From c2d83d287faec2bdfd6fac7d665c156670c7b7f7 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 22 Dec 2014 02:50:34 +0200 Subject: ZVISION: Allow dumping any file type via the new "dumpfiles" command --- engines/zvision/core/console.cpp | 11 ++++++++--- engines/zvision/core/console.h | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/zvision/core/console.cpp b/engines/zvision/core/console.cpp index 0789f8d4fb..07d3114ec8 100644 --- a/engines/zvision/core/console.cpp +++ b/engines/zvision/core/console.cpp @@ -52,7 +52,7 @@ Console::Console(ZVision *engine) : GUI::Debugger(), _engine(engine) { registerCmd("setpanoramascale", WRAP_METHOD(Console, cmdSetPanoramaScale)); registerCmd("location", WRAP_METHOD(Console, cmdLocation)); registerCmd("dumpfile", WRAP_METHOD(Console, cmdDumpFile)); - registerCmd("dumpallscripts", WRAP_METHOD(Console, cmdDumpAllScripts)); + registerCmd("dumpfiles", WRAP_METHOD(Console, cmdDumpFiles)); } bool Console::cmdLoadVideo(int argc, const char **argv) { @@ -237,12 +237,17 @@ bool Console::cmdDumpFile(int argc, const char **argv) { return true; } -bool Console::cmdDumpAllScripts(int argc, const char **argv) { +bool Console::cmdDumpFiles(int argc, const char **argv) { Common::String fileName; Common::SeekableReadStream *in; + if (argc != 2) { + debugPrintf("Use %s to dump all files with a specific extension\n", argv[0]); + return true; + } + SearchManager::MatchList fileList; - _engine->getSearchManager()->listMembersWithExtension(fileList, "scr"); + _engine->getSearchManager()->listMembersWithExtension(fileList, argv[1]); for (SearchManager::MatchList::iterator iter = fileList.begin(); iter != fileList.end(); ++iter) { fileName = iter->_value.name; diff --git a/engines/zvision/core/console.h b/engines/zvision/core/console.h index 7e27fe8f26..a7bd88ebc3 100644 --- a/engines/zvision/core/console.h +++ b/engines/zvision/core/console.h @@ -46,7 +46,7 @@ private: bool cmdSetPanoramaScale(int argc, const char **argv); bool cmdLocation(int argc, const char **argv); bool cmdDumpFile(int argc, const char **argv); - bool cmdDumpAllScripts(int argc, const char **argv); + bool cmdDumpFiles(int argc, const char **argv); }; } // End of namespace ZVision -- cgit v1.2.3 From f364756bcfa952e85c2111270ffda15c9809a4b8 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 22 Dec 2014 02:52:55 +0200 Subject: ZVISION: Add support for GNU Freefont fonts. Also, cleanup font loading The Freefont fonts can just be dropped into the extras ScummVM folder, to get the game working under non-Windows systems --- engines/zvision/graphics/truetype_font.cpp | 145 +++++++++++------------------ 1 file changed, 54 insertions(+), 91 deletions(-) (limited to 'engines') diff --git a/engines/zvision/graphics/truetype_font.cpp b/engines/zvision/graphics/truetype_font.cpp index 2dbd7ca358..5c8aa03f6a 100644 --- a/engines/zvision/graphics/truetype_font.cpp +++ b/engines/zvision/graphics/truetype_font.cpp @@ -54,105 +54,68 @@ bool StyledTTFont::loadFont(const Common::String &fontName, int32 point, uint st } bool StyledTTFont::loadFont(const Common::String &fontName, int32 point) { + struct FontStyle { + const char *zorkFont; + const char *fontBase; + const char *freeFontBase; + const char *freeFontItalicName; + }; + + const FontStyle systemFonts[] = { + { "*times new roman*", "times", "FreeSerif", "Italic" }, + { "*times*", "times", "FreeSerif", "Italic" }, + { "*century schoolbook*", "censcbk", "FreeSerif", "Italic" }, + { "*garamond*", "gara", "FreeSerif", "Italic" }, + { "*courier new*", "cour", "FreeMono", "Oblique" }, + { "*courier*", "cour", "FreeMono", "Oblique" }, + { "*ZorkDeath*", "cour", "FreeMono", "Oblique" }, + { "*arial*", "arial", "FreeSans", "Oblique" }, + { "*ZorkNormal*", "arial", "FreeSans", "Oblique" }, + }; + Common::String newFontName; - if (fontName.matchString("*times new roman*", true) || fontName.matchString("*times*", true)) { - if ((_style & (STTF_BOLD | STTF_ITALIC)) == (STTF_BOLD | STTF_ITALIC)) - newFontName = "timesbi.ttf"; - else if (_style & STTF_BOLD) - newFontName = "timesbd.ttf"; - else if (_style & STTF_ITALIC) - newFontName = "timesi.ttf"; - else - newFontName = "times.ttf"; - - } else if (fontName.matchString("*courier new*", true) || fontName.matchString("*courier*", true) || fontName.matchString("*ZorkDeath*", true)) { - if ((_style & (STTF_BOLD | STTF_ITALIC)) == (STTF_BOLD | STTF_ITALIC)) - newFontName = "courbi.ttf"; - else if (_style & STTF_BOLD) - newFontName = "courbd.ttf"; - else if (_style & STTF_ITALIC) - newFontName = "couri.ttf"; - else - newFontName = "cour.ttf"; - - } else if (fontName.matchString("*century schoolbook*", true)) { - if ((_style & (STTF_BOLD | STTF_ITALIC)) == (STTF_BOLD | STTF_ITALIC)) - newFontName = "censcbkbi.ttf"; - else if (_style & STTF_BOLD) - newFontName = "censcbkbd.ttf"; - else if (_style & STTF_ITALIC) - newFontName = "censcbki.ttf"; - else - newFontName = "censcbk.ttf"; - - } else if (fontName.matchString("*garamond*", true)) { - if ((_style & (STTF_BOLD | STTF_ITALIC)) == (STTF_BOLD | STTF_ITALIC)) - newFontName = "garabi.ttf"; - else if (_style & STTF_BOLD) - newFontName = "garabd.ttf"; - else if (_style & STTF_ITALIC) - newFontName = "garai.ttf"; - else - newFontName = "gara.ttf"; - - } else if (fontName.matchString("*arial*", true) || fontName.matchString("*ZorkNormal*", true)) { - if ((_style & (STTF_BOLD | STTF_ITALIC)) == (STTF_BOLD | STTF_ITALIC)) - newFontName = "arialbi.ttf"; - else if (_style & STTF_BOLD) - newFontName = "arialbd.ttf"; - else if (_style & STTF_ITALIC) - newFontName = "ariali.ttf"; - else - newFontName = "arial.ttf"; + Common::String freeFontName; + + for (int i = 0; i < ARRAYSIZE(systemFonts); i++) { + if (fontName.matchString(systemFonts[i].zorkFont, true)) { + newFontName = systemFonts[i].fontBase; + freeFontName = systemFonts[i].freeFontBase; + + if ((_style & STTF_BOLD) && (_style & STTF_ITALIC)) { + newFontName += "bi"; + freeFontName += "Bold"; + freeFontName += systemFonts[i].freeFontItalicName; + } else if (_style & STTF_BOLD) { + newFontName += "bd"; + freeFontName += "Bold"; + } else if (_style & STTF_ITALIC) { + newFontName += "i"; + freeFontName += systemFonts[i].freeFontItalicName; + } - } else { + newFontName += ".ttf"; + freeFontName += ".ttf"; + break; + } + } + + if (newFontName.empty()) { debug("Could not identify font: %s. Reverting to Arial", fontName.c_str()); newFontName = "arial.ttf"; + freeFontName = "FreeSans.ttf"; } bool sharp = (_style & STTF_SHARP) == STTF_SHARP; - Common::File *file = _engine->getSearchManager()->openFile(newFontName); - - if (!file) { - Common::SeekableReadStream *themeFile = nullptr; - if (ConfMan.hasKey("themepath")) { - Common::FSNode themePath(ConfMan.get("themepath")); - if (themePath.exists()) { - Common::FSNode scummModern = themePath.getChild("scummmodern.zip"); - if (scummModern.exists()) { - themeFile = scummModern.createReadStream(); - } - } - } - if (!themeFile) { // Fallback : Search for ScummModern.zip in SearchMan. - themeFile = SearchMan.createReadStreamForMember("scummmodern.zip"); - } - if (themeFile) { - Common::Archive *themeArchive = Common::makeZipArchive(themeFile); - if (themeArchive->hasFile("FreeSans.ttf")) { - Common::SeekableReadStream *stream = nullptr; - stream = themeArchive->createReadStreamForMember("FreeSans.ttf"); - Graphics::Font *_newFont = Graphics::loadTTFFont(*stream, point, 60, (sharp ? Graphics::kTTFRenderModeMonochrome : Graphics::kTTFRenderModeNormal)); // 66 dpi for 640 x 480 on 14" display - if (_newFont) { - if (!_font) - delete _font; - _font = _newFont; - } - if (stream) - delete stream; - } - delete themeArchive; - themeArchive = nullptr; - } - } else { - Graphics::Font *_newFont = Graphics::loadTTFFont(*file, point, 60, (sharp ? Graphics::kTTFRenderModeMonochrome : Graphics::kTTFRenderModeNormal)); // 66 dpi for 640 x 480 on 14" display - if (_newFont) { - if (!_font) - delete _font; - _font = _newFont; - } - delete file; + Common::File file; + if (!file.open(newFontName) && !file.open(freeFontName)) + error("Unable to open font file %s (free alternative: %s)", newFontName.c_str(), freeFontName.c_str()); + + Graphics::Font *_newFont = Graphics::loadTTFFont(file, point, 60, (sharp ? Graphics::kTTFRenderModeMonochrome : Graphics::kTTFRenderModeNormal)); // 66 dpi for 640 x 480 on 14" display + if (_newFont) { + if (!_font) + delete _font; + _font = _newFont; } _fntName = fontName; -- cgit v1.2.3 From b51852c641cf4d558d035d7d1dd9309d6d238647 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 22 Dec 2014 02:58:18 +0200 Subject: ZVISION: Error out when the game string file isn't found --- engines/zvision/text/string_manager.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'engines') diff --git a/engines/zvision/text/string_manager.cpp b/engines/zvision/text/string_manager.cpp index ec10b6220c..6b870d0b8d 100644 --- a/engines/zvision/text/string_manager.cpp +++ b/engines/zvision/text/string_manager.cpp @@ -43,21 +43,18 @@ StringManager::~StringManager() { } void StringManager::initialize(ZVisionGameId gameId) { - if (gameId == GID_NEMESIS) { - // TODO: Check this hardcoded filename against all versions of Nemesis + if (gameId == GID_NEMESIS) loadStrFile("nemesis.str"); - } else if (gameId == GID_GRANDINQUISITOR) { - // TODO: Check this hardcoded filename against all versions of Grand Inquisitor + else if (gameId == GID_GRANDINQUISITOR) loadStrFile("inquis.str"); - } } void StringManager::loadStrFile(const Common::String &fileName) { Common::File file; if (!_engine->getSearchManager()->openFile(file, fileName)) { - warning("%s does not exist. String parsing failed", fileName.c_str()); - return; + error("%s does not exist. String parsing failed", fileName.c_str()); } + uint lineNumber = 0; while (!file.eos()) { _lines[lineNumber] = readWideLine(file); -- cgit v1.2.3 From 04bc635dc702606911b8777a443b9e1f6322a6bf Mon Sep 17 00:00:00 2001 From: Strangerke Date: Mon, 22 Dec 2014 19:05:56 +0100 Subject: ACCESS: Remove a couple of unused variables in CharManager --- engines/access/char.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'engines') diff --git a/engines/access/char.h b/engines/access/char.h index e89cdae49f..6fb4934978 100644 --- a/engines/access/char.h +++ b/engines/access/char.h @@ -51,11 +51,8 @@ private: void charMenu(); public: Common::Array _charTable; - int _converseMode; int _charFlag; - // Fields that are included in savegames - int _conversation; public: CharManager(AccessEngine *vm); -- cgit v1.2.3 From fc9595efdc22aecb77800dca29fbe23291855c48 Mon Sep 17 00:00:00 2001 From: Strangerke Date: Mon, 22 Dec 2014 19:16:11 +0100 Subject: ACCESS: Remove an unused variable in Animation manager --- engines/access/animation.cpp | 5 +---- engines/access/animation.h | 1 - 2 files changed, 1 insertion(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/access/animation.cpp b/engines/access/animation.cpp index cc699a27e3..14d7c0d4cc 100644 --- a/engines/access/animation.cpp +++ b/engines/access/animation.cpp @@ -63,7 +63,6 @@ Animation::Animation(AccessEngine *vm, Common::SeekableReadStream *stream) : Man _countdownTicks = stream->readUint16LE(); _currentLoopCount = stream->readSint16LE(); stream->readUint16LE(); // unk - _field10 = 0; Common::Array frameOffsets; uint16 ofs; @@ -311,9 +310,7 @@ Animation *AnimationManager::setAnimation(int animId) { anim->_countdownTicks = anim->_initialTicks; anim->_frameNumber = 0; - anim->_currentLoopCount = (anim->_type != 3 && anim->_type != 4) ? 0 : - anim->_loopCount; - anim->_field10 = 0; + anim->_currentLoopCount = (anim->_type != 3 && anim->_type != 4) ? 0 : anim->_loopCount; return anim; } diff --git a/engines/access/animation.h b/engines/access/animation.h index 722f5430ab..72621c4d11 100644 --- a/engines/access/animation.h +++ b/engines/access/animation.h @@ -106,7 +106,6 @@ public: int _loopCount; int _countdownTicks; int _currentLoopCount; - int _field10; public: Animation(AccessEngine *vm, Common::SeekableReadStream *stream); ~Animation(); -- cgit v1.2.3 From d1bc69426eac2458b46ab7fede31c6dd71314ccb Mon Sep 17 00:00:00 2001 From: Strangerke Date: Mon, 22 Dec 2014 19:41:40 +0100 Subject: ACCESS: Move variable from Room manager to local function --- engines/access/room.cpp | 6 +++--- engines/access/room.h | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/access/room.cpp b/engines/access/room.cpp index f7c2eabd0f..607259ec6f 100644 --- a/engines/access/room.cpp +++ b/engines/access/room.cpp @@ -370,9 +370,9 @@ void Room::loadPlayField(int fileNum, int subfile) { screen.loadRawPalette(playData->_stream); // Copy off the tile data - _tileSize = (int)header[2] << 8; - _tile = new byte[_tileSize]; - playData->_stream->read(_tile, _tileSize); + int tileSize = (int)header[2] << 8; + _tile = new byte[tileSize]; + playData->_stream->read(_tile, tileSize); // Copy off the playfield data _matrixSize = header[0] * header[1]; diff --git a/engines/access/room.h b/engines/access/room.h index 44279fa6b1..eec273e3f4 100644 --- a/engines/access/room.h +++ b/engines/access/room.h @@ -124,7 +124,6 @@ public: int _playFieldWidth; int _playFieldHeight; byte *_tile; - int _tileSize; int _selectCommand; bool _conFlag; public: -- cgit v1.2.3 From 58f7c12fa941265a79b453df9b32ec41c49d53c4 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 22 Dec 2014 22:11:07 +0200 Subject: ZVISION: Remove dead code --- engines/zvision/graphics/render_table.cpp | 21 --------------------- 1 file changed, 21 deletions(-) (limited to 'engines') diff --git a/engines/zvision/graphics/render_table.cpp b/engines/zvision/graphics/render_table.cpp index c30e0bd472..df73247344 100644 --- a/engines/zvision/graphics/render_table.cpp +++ b/engines/zvision/graphics/render_table.cpp @@ -81,27 +81,6 @@ const Common::Point RenderTable::convertWarpedCoordToFlatCoord(const Common::Poi return newPoint; } -uint16 mixTwoRGB(uint16 colorOne, uint16 colorTwo, float percentColorOne) { - assert(percentColorOne < 1.0f); - - float rOne = float((colorOne & Graphics::ColorMasks<555>::kRedMask) >> Graphics::ColorMasks<555>::kRedShift); - float rTwo = float((colorTwo & Graphics::ColorMasks<555>::kRedMask) >> Graphics::ColorMasks<555>::kRedShift); - float gOne = float((colorOne & Graphics::ColorMasks<555>::kGreenMask) >> Graphics::ColorMasks<555>::kGreenShift); - float gTwo = float((colorTwo & Graphics::ColorMasks<555>::kGreenMask) >> Graphics::ColorMasks<555>::kGreenShift); - float bOne = float((colorOne & Graphics::ColorMasks<555>::kBlueMask) >> Graphics::ColorMasks<555>::kBlueShift); - float bTwo = float((colorTwo & Graphics::ColorMasks<555>::kBlueMask) >> Graphics::ColorMasks<555>::kBlueShift); - - float rFinal = rOne * percentColorOne + rTwo * (1.0f - percentColorOne); - float gFinal = gOne * percentColorOne + gTwo * (1.0f - percentColorOne); - float bFinal = bOne * percentColorOne + bTwo * (1.0f - percentColorOne); - - uint16 returnColor = (byte(rFinal + 0.5f) << Graphics::ColorMasks<555>::kRedShift) | - (byte(gFinal + 0.5f) << Graphics::ColorMasks<555>::kGreenShift) | - (byte(bFinal + 0.5f) << Graphics::ColorMasks<555>::kBlueShift); - - return returnColor; -} - void RenderTable::mutateImage(uint16 *sourceBuffer, uint16 *destBuffer, uint32 destWidth, const Common::Rect &subRect) { uint32 destOffset = 0; -- cgit v1.2.3 From 4e60fa705fd22069565cdb17c907f91301a67dc5 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 22 Dec 2014 22:23:36 +0200 Subject: ZVISION: Fix regression from commit 3806aa4418 --- engines/zvision/scripting/sidefx/music_node.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/zvision/scripting/sidefx/music_node.cpp b/engines/zvision/scripting/sidefx/music_node.cpp index 56598189f6..6be08b46dc 100644 --- a/engines/zvision/scripting/sidefx/music_node.cpp +++ b/engines/zvision/scripting/sidefx/music_node.cpp @@ -88,7 +88,7 @@ MusicNode::MusicNode(ZVision *engine, uint32 key, Common::String &filename, bool } MusicNode::~MusicNode() { - if (!_loaded) + if (_loaded) _engine->_mixer->stopHandle(_handle); if (_key != StateKey_NotSet) _engine->getScriptManager()->setStateValue(_key, 2); -- cgit v1.2.3 From 3f36cc94e45d32dc4784c16ec91b6fc44dbf0ff7 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 23 Dec 2014 00:02:30 +0200 Subject: ZVISION: Limit the default engine delay for all animations This fixes the lag between frames for all in-game animations with a default frame delay --- engines/zvision/scripting/actions.cpp | 7 +++---- engines/zvision/scripting/sidefx/animation_node.cpp | 18 +++++------------- engines/zvision/scripting/sidefx/animation_node.h | 1 - 3 files changed, 8 insertions(+), 18 deletions(-) (limited to 'engines') diff --git a/engines/zvision/scripting/actions.cpp b/engines/zvision/scripting/actions.cpp index 0422a2c028..0ada2edf81 100644 --- a/engines/zvision/scripting/actions.cpp +++ b/engines/zvision/scripting/actions.cpp @@ -577,7 +577,7 @@ ActionPreloadAnimation::ActionPreloadAnimation(ZVision *engine, int32 slotkey, c char fileName[25]; - // The two %*u are always 0 and dont seem to have a use + // The two %*u are usually 0 and dont seem to have a use sscanf(line.c_str(), "%25s %*u %*u %d %d", fileName, &_mask, &_framerate); if (_mask > 0) { @@ -1030,9 +1030,8 @@ bool ActionSyncSound::execute() { if (!(fx->getType() & SideFX::SIDEFX_ANIM)) return true; - AnimationNode *animnode = (AnimationNode *)fx; - if (animnode->getFrameDelay() > 200) // Hack for fix incorrect framedelay in some animpreload - animnode->setNewFrameDelay(66); // ~15fps + if (((AnimationNode *)fx)->getFrameDelay() > 200) + warning("ActionSyncSound: animation frame delay is higher than 200"); _engine->getScriptManager()->addSideFX(new SyncSoundNode(_engine, _slotKey, _fileName, _syncto)); return true; diff --git a/engines/zvision/scripting/sidefx/animation_node.cpp b/engines/zvision/scripting/sidefx/animation_node.cpp index 3a21227d1a..56f1fa3e49 100644 --- a/engines/zvision/scripting/sidefx/animation_node.cpp +++ b/engines/zvision/scripting/sidefx/animation_node.cpp @@ -42,6 +42,11 @@ AnimationNode::AnimationNode(ZVision *engine, uint32 controlKey, const Common::S _animation = engine->loadAnimation(fileName); _frmDelay = 1000.0 / _animation->getDuration().framerate(); + // WORKAROUND: We do not allow the engine to delay more than 66 msec + // per frame (15fps max) + if (_frmDelay > 66) + _frmDelay = 66; + if (frate > 0) _frmDelay = 1000.0 / frate; } @@ -190,19 +195,6 @@ bool AnimationNode::stop() { return false; } -void AnimationNode::setNewFrameDelay(int32 newDelay) { - if (newDelay > 0) { - PlayNodes::iterator it = _playList.begin(); - if (it != _playList.end()) { - playnode *nod = &(*it); - float percent = (float)nod->_delay / (float)_frmDelay; - nod->_delay = percent * newDelay; // Scale to new max - } - - _frmDelay = newDelay; - } -} - int32 AnimationNode::getFrameDelay() { return _frmDelay; } diff --git a/engines/zvision/scripting/sidefx/animation_node.h b/engines/zvision/scripting/sidefx/animation_node.h index 3adfd91f32..74941aa764 100644 --- a/engines/zvision/scripting/sidefx/animation_node.h +++ b/engines/zvision/scripting/sidefx/animation_node.h @@ -73,7 +73,6 @@ public: bool stop(); - void setNewFrameDelay(int32 newDelay); int32 getFrameDelay(); }; -- cgit v1.2.3 From fb924089fc5f6968f5c86fc780131f67268e8de6 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 23 Dec 2014 00:07:17 +0200 Subject: ZVISION: Avoid using color masks for in-game animations This fixes the transparency for some in-game animations. Since colors can be truncated with color masks, and since accurate colors are required for transparency, color masks can't be used. This fixes the transparency of the in-game item examination interface in ZGI --- engines/zvision/video/rlf_decoder.cpp | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'engines') diff --git a/engines/zvision/video/rlf_decoder.cpp b/engines/zvision/video/rlf_decoder.cpp index bdb5dc18bc..d51dee0c6a 100644 --- a/engines/zvision/video/rlf_decoder.cpp +++ b/engines/zvision/video/rlf_decoder.cpp @@ -30,8 +30,6 @@ #include "common/debug.h" #include "common/endian.h" -#include "graphics/colormasks.h" - namespace ZVision { RLFDecoder::~RLFDecoder() { @@ -62,7 +60,7 @@ RLFDecoder::RLFVideoTrack::RLFVideoTrack(Common::SeekableReadStream *stream) return; } - _currentFrameBuffer.create(_width, _height, Graphics::createPixelFormat<565>()); + _currentFrameBuffer.create(_width, _height, Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0)); _frameBufferByteSize = _width * _height * sizeof(uint16); _frames = new Frame[_frameCount]; @@ -243,8 +241,10 @@ void RLFDecoder::RLFVideoTrack::decodeMaskedRunLengthEncoding(int8 *source, int8 } byte r, g, b; - Graphics::colorToRGB >(READ_LE_UINT16(source + sourceOffset), r, g, b); - uint16 destColor = Graphics::RGBToColor >(r, g, b); + // NOTE: Color masks can't be used here, since accurate colors + // are required to handle transparency correctly + Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0).colorToRGB(READ_LE_UINT16(source + sourceOffset), r, g, b); + uint16 destColor = Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0).RGBToColor(r, g, b); WRITE_UINT16(dest + destOffset, destColor); sourceOffset += 2; @@ -290,8 +290,10 @@ void RLFDecoder::RLFVideoTrack::decodeSimpleRunLengthEncoding(int8 *source, int8 } byte r, g, b; - Graphics::colorToRGB >(READ_LE_UINT16(source + sourceOffset), r, g, b); - uint16 destColor = Graphics::RGBToColor >(r, g, b); + // NOTE: Color masks can't be used here, since accurate colors + // are required to handle transparency correctly + Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0).colorToRGB(READ_LE_UINT16(source + sourceOffset), r, g, b); + uint16 destColor = Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0).RGBToColor(r, g, b); WRITE_UINT16(dest + destOffset, destColor); sourceOffset += 2; @@ -307,8 +309,10 @@ void RLFDecoder::RLFVideoTrack::decodeSimpleRunLengthEncoding(int8 *source, int8 } byte r, g, b; - Graphics::colorToRGB >(READ_LE_UINT16(source + sourceOffset), r, g, b); - uint16 sampleColor = Graphics::RGBToColor >(r, g, b); + // NOTE: Color masks can't be used here, since accurate colors + // are required to handle transparency correctly + Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0).colorToRGB(READ_LE_UINT16(source + sourceOffset), r, g, b); + uint16 sampleColor = Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0).RGBToColor(r, g, b); sourceOffset += 2; numberOfCopy = numberOfSamples + 2; -- cgit v1.2.3 From 9bc0686e6076bbe5ca481c6696f0f7d3c86cd570 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 23 Dec 2014 00:09:18 +0200 Subject: ZVISION: Remove leftover warning --- engines/zvision/scripting/actions.cpp | 3 --- 1 file changed, 3 deletions(-) (limited to 'engines') diff --git a/engines/zvision/scripting/actions.cpp b/engines/zvision/scripting/actions.cpp index 0ada2edf81..2a5046f146 100644 --- a/engines/zvision/scripting/actions.cpp +++ b/engines/zvision/scripting/actions.cpp @@ -1030,9 +1030,6 @@ bool ActionSyncSound::execute() { if (!(fx->getType() & SideFX::SIDEFX_ANIM)) return true; - if (((AnimationNode *)fx)->getFrameDelay() > 200) - warning("ActionSyncSound: animation frame delay is higher than 200"); - _engine->getScriptManager()->addSideFX(new SyncSoundNode(_engine, _slotKey, _fileName, _syncto)); return true; } -- cgit v1.2.3 From eb4645cda855b0ac919124fefc79c580883903d3 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 23 Dec 2014 00:10:12 +0200 Subject: ZVISION: Spacing --- engines/zvision/video/rlf_decoder.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/zvision/video/rlf_decoder.cpp b/engines/zvision/video/rlf_decoder.cpp index d51dee0c6a..b798093869 100644 --- a/engines/zvision/video/rlf_decoder.cpp +++ b/engines/zvision/video/rlf_decoder.cpp @@ -309,8 +309,8 @@ void RLFDecoder::RLFVideoTrack::decodeSimpleRunLengthEncoding(int8 *source, int8 } byte r, g, b; - // NOTE: Color masks can't be used here, since accurate colors - // are required to handle transparency correctly + // NOTE: Color masks can't be used here, since accurate colors + // are required to handle transparency correctly Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0).colorToRGB(READ_LE_UINT16(source + sourceOffset), r, g, b); uint16 sampleColor = Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0).RGBToColor(r, g, b); sourceOffset += 2; -- cgit v1.2.3 From cfd00ad6afc09ca6990ce905b1a8db4ea1ad1602 Mon Sep 17 00:00:00 2001 From: Pino Toscano Date: Mon, 22 Dec 2014 22:39:05 +0100 Subject: AGI: use Common::String::format when possible Use Common::String::format instead of a MAXPATHLEN-sized char[] buffer. --- engines/agi/detection.cpp | 6 ++---- engines/agi/loader_v2.cpp | 8 ++++---- engines/agi/loader_v3.cpp | 3 +-- 3 files changed, 7 insertions(+), 10 deletions(-) (limited to 'engines') diff --git a/engines/agi/detection.cpp b/engines/agi/detection.cpp index e7285d8112..3230b4e5d3 100644 --- a/engines/agi/detection.cpp +++ b/engines/agi/detection.cpp @@ -276,15 +276,13 @@ SaveStateList AgiMetaEngine::listSaves(const char *target) const { int AgiMetaEngine::getMaximumSaveSlot() const { return 999; } void AgiMetaEngine::removeSaveState(const char *target, int slot) const { - char fileName[MAXPATHLEN]; - sprintf(fileName, "%s.%03d", target, slot); + Common::String fileName = Common::String::format("%s.%03d", target, slot); g_system->getSavefileManager()->removeSavefile(fileName); } SaveStateDescriptor AgiMetaEngine::querySaveMetaInfos(const char *target, int slot) const { const uint32 AGIflag = MKTAG('A','G','I',':'); - char fileName[MAXPATHLEN]; - sprintf(fileName, "%s.%03d", target, slot); + Common::String fileName = Common::String::format("%s.%03d", target, slot); Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(fileName); diff --git a/engines/agi/loader_v2.cpp b/engines/agi/loader_v2.cpp index 787eeaa0c7..3f164b7fc0 100644 --- a/engines/agi/loader_v2.cpp +++ b/engines/agi/loader_v2.cpp @@ -135,13 +135,13 @@ int AgiLoader_v2::unloadResource(int t, int n) { */ uint8 *AgiLoader_v2::loadVolRes(struct AgiDir *agid) { uint8 *data = NULL; - char x[MAXPATHLEN], *path; + char x[MAXPATHLEN]; Common::File fp; unsigned int sig; + Common::String path; - sprintf(x, "vol.%i", agid->volume); - path = x; - debugC(3, kDebugLevelResources, "Vol res: path = %s", path); + path = Common::String::format("vol.%i", agid->volume); + debugC(3, kDebugLevelResources, "Vol res: path = %s", path.c_str()); if (agid->offset != _EMPTY && fp.open(path)) { debugC(3, kDebugLevelResources, "loading resource at offset %d", agid->offset); diff --git a/engines/agi/loader_v3.cpp b/engines/agi/loader_v3.cpp index fa135e5476..b90c17a1f3 100644 --- a/engines/agi/loader_v3.cpp +++ b/engines/agi/loader_v3.cpp @@ -204,8 +204,7 @@ uint8 *AgiLoader_v3::loadVolRes(AgiDir *agid) { Common::String path; debugC(3, kDebugLevelResources, "(%p)", (void *)agid); - sprintf(x, "vol.%i", agid->volume); - path = Common::String(_vm->_game.name) + x; + path = Common::String::format("%svol.%i", _vm->_game.name, agid->volume); if (agid->offset != _EMPTY && fp.open(path)) { fp.seek(agid->offset, SEEK_SET); -- cgit v1.2.3 From e8fd25e22f4bce6f6df1a49115ece58bc76bdda3 Mon Sep 17 00:00:00 2001 From: Pino Toscano Date: Mon, 22 Dec 2014 22:43:46 +0100 Subject: DRASCULA: use Common::String::format when possible Use Common::String::format instead of a MAXPATHLEN-sized char[] buffer. --- engines/drascula/detection.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/drascula/detection.cpp b/engines/drascula/detection.cpp index 833363669d..a84bd11cb1 100644 --- a/engines/drascula/detection.cpp +++ b/engines/drascula/detection.cpp @@ -382,8 +382,7 @@ SaveStateList DrasculaMetaEngine::listSaves(const char *target) const { } SaveStateDescriptor DrasculaMetaEngine::querySaveMetaInfos(const char *target, int slot) const { - char fileName[MAXPATHLEN]; - sprintf(fileName, "%s.%03d", target, slot); + Common::String fileName = Common::String::format("%s.%03d", target, slot); Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(fileName); -- cgit v1.2.3 From f29b3658b0caa7af2a3972de09069b9ba80eb494 Mon Sep 17 00:00:00 2001 From: Pino Toscano Date: Mon, 22 Dec 2014 22:46:52 +0100 Subject: AGI: use shorter sizes for buffers Instead of allocate them with MAXPATHLEN as size, just give them the size for the data that are going to be written on them. --- engines/agi/loader_v2.cpp | 2 +- engines/agi/loader_v3.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/agi/loader_v2.cpp b/engines/agi/loader_v2.cpp index 3f164b7fc0..693c53c2bf 100644 --- a/engines/agi/loader_v2.cpp +++ b/engines/agi/loader_v2.cpp @@ -135,7 +135,7 @@ int AgiLoader_v2::unloadResource(int t, int n) { */ uint8 *AgiLoader_v2::loadVolRes(struct AgiDir *agid) { uint8 *data = NULL; - char x[MAXPATHLEN]; + char x[6]; Common::File fp; unsigned int sig; Common::String path; diff --git a/engines/agi/loader_v3.cpp b/engines/agi/loader_v3.cpp index b90c17a1f3..39759b4649 100644 --- a/engines/agi/loader_v3.cpp +++ b/engines/agi/loader_v3.cpp @@ -198,7 +198,7 @@ int AgiLoader_v3::unloadResource(int t, int n) { * NULL is returned if unsucsessful. */ uint8 *AgiLoader_v3::loadVolRes(AgiDir *agid) { - char x[MAXPATHLEN]; + char x[8]; uint8 *data = NULL, *compBuffer; Common::File fp; Common::String path; -- cgit v1.2.3 From 6a53c7cac10294d022e3eb5d47142ad46ef29bd9 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 23 Dec 2014 01:45:44 +0200 Subject: ZVISION: Ignore the special 0xCCCC character in subtitles This seems to be used as a newline character --- engines/zvision/text/text.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/zvision/text/text.cpp b/engines/zvision/text/text.cpp index 08b57914c2..4ea40a1d55 100644 --- a/engines/zvision/text/text.cpp +++ b/engines/zvision/text/text.cpp @@ -495,7 +495,7 @@ Common::String readWideLine(Common::SeekableReadStream &stream) { } else if (value >= 0x80 && value < 0x800) { asciiString += (char)(0xC0 | ((value >> 6) & 0x1F)); asciiString += (char)(0x80 | (value & 0x3F)); - } else if (value >= 0x800 && value < 0x10000) { + } else if (value >= 0x800 && value < 0x10000 && value != 0xCCCC) { asciiString += (char)(0xE0 | ((value >> 12) & 0xF)); asciiString += (char)(0x80 | ((value >> 6) & 0x3F)); asciiString += (char)(0x80 | (value & 0x3F)); -- cgit v1.2.3 From 15154641ac5ea674a4865d9478074cf1b1d8a36b Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 23 Dec 2014 01:53:40 +0200 Subject: ZVISION: Move all of the text related code together --- engines/zvision/graphics/render_manager.h | 2 +- engines/zvision/graphics/subtitles.cpp | 108 ---------- engines/zvision/graphics/subtitles.h | 54 ----- engines/zvision/graphics/truetype_font.cpp | 228 ---------------------- engines/zvision/graphics/truetype_font.h | 84 -------- engines/zvision/module.mk | 4 +- engines/zvision/scripting/sidefx/music_node.h | 2 +- engines/zvision/scripting/sidefx/syncsound_node.h | 2 +- engines/zvision/scripting/sidefx/ttytext_node.h | 2 +- engines/zvision/text/string_manager.h | 2 +- engines/zvision/text/subtitles.cpp | 108 ++++++++++ engines/zvision/text/subtitles.h | 54 +++++ engines/zvision/text/text.cpp | 2 +- engines/zvision/text/text.h | 2 +- engines/zvision/text/truetype_font.cpp | 228 ++++++++++++++++++++++ engines/zvision/text/truetype_font.h | 84 ++++++++ engines/zvision/video/video.cpp | 2 +- engines/zvision/zvision.cpp | 2 +- 18 files changed, 485 insertions(+), 485 deletions(-) delete mode 100644 engines/zvision/graphics/subtitles.cpp delete mode 100644 engines/zvision/graphics/subtitles.h delete mode 100644 engines/zvision/graphics/truetype_font.cpp delete mode 100644 engines/zvision/graphics/truetype_font.h create mode 100644 engines/zvision/text/subtitles.cpp create mode 100644 engines/zvision/text/subtitles.h create mode 100644 engines/zvision/text/truetype_font.cpp create mode 100644 engines/zvision/text/truetype_font.h (limited to 'engines') diff --git a/engines/zvision/graphics/render_manager.h b/engines/zvision/graphics/render_manager.h index 29bbd8f411..711c607c7b 100644 --- a/engines/zvision/graphics/render_manager.h +++ b/engines/zvision/graphics/render_manager.h @@ -24,7 +24,7 @@ #define ZVISION_RENDER_MANAGER_H #include "zvision/graphics/render_table.h" -#include "zvision/graphics/truetype_font.h" +#include "zvision/text/truetype_font.h" #include "common/rect.h" #include "common/hashmap.h" diff --git a/engines/zvision/graphics/subtitles.cpp b/engines/zvision/graphics/subtitles.cpp deleted file mode 100644 index d2c56f0991..0000000000 --- a/engines/zvision/graphics/subtitles.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "zvision/graphics/render_manager.h" -#include "zvision/graphics/subtitles.h" -#include "zvision/file/search_manager.h" -#include "zvision/text/text.h" - -namespace ZVision { - -Subtitle::Subtitle(ZVision *engine, const Common::String &subname) : - _engine(engine), - _areaId(-1), - _subId(-1) { - Common::File file; - if (_engine->getSearchManager()->openFile(file, subname)) { - while (!file.eos()) { - Common::String str = file.readLine(); - if (str.lastChar() == '~') - str.deleteLastChar(); - - if (str.matchString("*Initialization*", true)) { - // Not used - } else if (str.matchString("*Rectangle*", true)) { - int32 x1, y1, x2, y2; - sscanf(str.c_str(), "%*[^:]:%d %d %d %d", &x1, &y1, &x2, &y2); - Common::Rect rct = Common::Rect(x1, y1, x2, y2); - _areaId = _engine->getRenderManager()->createSubArea(rct); - } else if (str.matchString("*TextFile*", true)) { - char filename[64]; - sscanf(str.c_str(), "%*[^:]:%s", filename); - Common::File txt; - if (_engine->getSearchManager()->openFile(txt, filename)) { - while (!txt.eos()) { - Common::String txtline = readWideLine(txt); - sub curSubtitle; - curSubtitle.start = -1; - curSubtitle.stop = -1; - curSubtitle.subStr = txtline; - - _subs.push_back(curSubtitle); - } - txt.close(); - } - } else { - int32 st; - int32 en; - int32 sb; - if (sscanf(str.c_str(), "%*[^:]:(%d,%d)=%d", &st, &en, &sb) == 3) { - if (sb <= (int32)_subs.size()) { - _subs[sb].start = st; - _subs[sb].stop = en; - } - } - } - } - } -} - -Subtitle::~Subtitle() { - if (_areaId != -1) - _engine->getRenderManager()->deleteSubArea(_areaId); - - _subs.clear(); -} - -void Subtitle::process(int32 time) { - int16 j = -1; - for (uint16 i = 0; i < _subs.size(); i++) - if (time >= _subs[i].start && time <= _subs[i].stop) { - j = i; - break; - } - - if (j == -1 && _subId != -1) { - if (_areaId != -1) - _engine->getRenderManager()->updateSubArea(_areaId, ""); - _subId = -1; - } - - if (j != -1 && j != _subId) { - if (_subs[j].subStr.size()) - if (_areaId != -1) - _engine->getRenderManager()->updateSubArea(_areaId, _subs[j].subStr); - _subId = j; - } -} - -} // End of namespace ZVision diff --git a/engines/zvision/graphics/subtitles.h b/engines/zvision/graphics/subtitles.h deleted file mode 100644 index c3da6583a4..0000000000 --- a/engines/zvision/graphics/subtitles.h +++ /dev/null @@ -1,54 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#ifndef ZVISION_SUBTITLES_H -#define ZVISION_SUBTITLES_H - -#include "zvision/zvision.h" - -namespace ZVision { - -class ZVision; - -class Subtitle { -public: - Subtitle(ZVision *engine, const Common::String &subname); - ~Subtitle(); - - void process(int32 time); -private: - ZVision *_engine; - int32 _areaId; - int16 _subId; - - struct sub { - int start; - int stop; - Common::String subStr; - }; - - Common::Array _subs; -}; - -} - -#endif diff --git a/engines/zvision/graphics/truetype_font.cpp b/engines/zvision/graphics/truetype_font.cpp deleted file mode 100644 index 5c8aa03f6a..0000000000 --- a/engines/zvision/graphics/truetype_font.cpp +++ /dev/null @@ -1,228 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "common/scummsys.h" -#include "common/config-manager.h" -#include "common/debug.h" -#include "common/file.h" -#include "common/system.h" -#include "common/unzip.h" -#include "graphics/font.h" -#include "graphics/fonts/ttf.h" -#include "graphics/surface.h" - -#include "zvision/zvision.h" -#include "zvision/graphics/render_manager.h" -#include "zvision/graphics/truetype_font.h" - -namespace ZVision { - -StyledTTFont::StyledTTFont(ZVision *engine) { - _engine = engine; - _style = 0; - _font = NULL; - _lineHeight = 0; -} - -StyledTTFont::~StyledTTFont() { - if (_font) - delete _font; -} - -bool StyledTTFont::loadFont(const Common::String &fontName, int32 point, uint style) { - _style = style; - return loadFont(fontName, point); -} - -bool StyledTTFont::loadFont(const Common::String &fontName, int32 point) { - struct FontStyle { - const char *zorkFont; - const char *fontBase; - const char *freeFontBase; - const char *freeFontItalicName; - }; - - const FontStyle systemFonts[] = { - { "*times new roman*", "times", "FreeSerif", "Italic" }, - { "*times*", "times", "FreeSerif", "Italic" }, - { "*century schoolbook*", "censcbk", "FreeSerif", "Italic" }, - { "*garamond*", "gara", "FreeSerif", "Italic" }, - { "*courier new*", "cour", "FreeMono", "Oblique" }, - { "*courier*", "cour", "FreeMono", "Oblique" }, - { "*ZorkDeath*", "cour", "FreeMono", "Oblique" }, - { "*arial*", "arial", "FreeSans", "Oblique" }, - { "*ZorkNormal*", "arial", "FreeSans", "Oblique" }, - }; - - Common::String newFontName; - Common::String freeFontName; - - for (int i = 0; i < ARRAYSIZE(systemFonts); i++) { - if (fontName.matchString(systemFonts[i].zorkFont, true)) { - newFontName = systemFonts[i].fontBase; - freeFontName = systemFonts[i].freeFontBase; - - if ((_style & STTF_BOLD) && (_style & STTF_ITALIC)) { - newFontName += "bi"; - freeFontName += "Bold"; - freeFontName += systemFonts[i].freeFontItalicName; - } else if (_style & STTF_BOLD) { - newFontName += "bd"; - freeFontName += "Bold"; - } else if (_style & STTF_ITALIC) { - newFontName += "i"; - freeFontName += systemFonts[i].freeFontItalicName; - } - - newFontName += ".ttf"; - freeFontName += ".ttf"; - break; - } - } - - if (newFontName.empty()) { - debug("Could not identify font: %s. Reverting to Arial", fontName.c_str()); - newFontName = "arial.ttf"; - freeFontName = "FreeSans.ttf"; - } - - bool sharp = (_style & STTF_SHARP) == STTF_SHARP; - - Common::File file; - if (!file.open(newFontName) && !file.open(freeFontName)) - error("Unable to open font file %s (free alternative: %s)", newFontName.c_str(), freeFontName.c_str()); - - Graphics::Font *_newFont = Graphics::loadTTFFont(file, point, 60, (sharp ? Graphics::kTTFRenderModeMonochrome : Graphics::kTTFRenderModeNormal)); // 66 dpi for 640 x 480 on 14" display - if (_newFont) { - if (!_font) - delete _font; - _font = _newFont; - } - - _fntName = fontName; - _lineHeight = point; - - if (_font) - return true; - return false; -} - -void StyledTTFont::setStyle(uint newStyle) { - if ((_style & (STTF_BOLD | STTF_ITALIC | STTF_SHARP)) != (newStyle & (STTF_BOLD | STTF_ITALIC | STTF_SHARP))) { - _style = newStyle; - loadFont(_fntName, _lineHeight); - } else { - _style = newStyle; - } -} - -int StyledTTFont::getFontHeight() { - if (_font) - return _font->getFontHeight(); - return 0; -} - -int StyledTTFont::getMaxCharWidth() { - if (_font) - return _font->getMaxCharWidth(); - return 0; -} - -int StyledTTFont::getCharWidth(byte chr) { - if (_font) - return _font->getCharWidth(chr); - return 0; -} - -int StyledTTFont::getKerningOffset(byte left, byte right) { - if (_font) - return _font->getKerningOffset(left, right); - return 0; -} - -void StyledTTFont::drawChar(Graphics::Surface *dst, byte chr, int x, int y, uint32 color) { - if (_font) { - _font->drawChar(dst, chr, x, y, color); - if (_style & STTF_UNDERLINE) { - int16 pos = floor(_font->getFontHeight() * 0.87); - int thk = MAX((int)(_font->getFontHeight() * 0.05), 1); - dst->fillRect(Common::Rect(x, y + pos, x + _font->getCharWidth(chr), y + pos + thk), color); - } - if (_style & STTF_STRIKEOUT) { - int16 pos = floor(_font->getFontHeight() * 0.60); - int thk = MAX((int)(_font->getFontHeight() * 0.05), 1); - dst->fillRect(Common::Rect(x, y + pos, x + _font->getCharWidth(chr), y + pos + thk), color); - } - } -} - -void StyledTTFont::drawString(Graphics::Surface *dst, const Common::String &str, int x, int y, int w, uint32 color, Graphics::TextAlign align) { - if (_font) { - _font->drawString(dst, str, x, y, w, color, align); - if (_style & STTF_UNDERLINE) { - int16 pos = floor(_font->getFontHeight() * 0.87); - int16 wd = MIN(_font->getStringWidth(str), w); - int16 stX = x; - if (align == Graphics::kTextAlignCenter) - stX += (w - wd) / 2; - else if (align == Graphics::kTextAlignRight) - stX += (w - wd); - - int thk = MAX((int)(_font->getFontHeight() * 0.05), 1); - - dst->fillRect(Common::Rect(stX, y + pos, stX + wd, y + pos + thk), color); - } - if (_style & STTF_STRIKEOUT) { - int16 pos = floor(_font->getFontHeight() * 0.60); - int16 wd = MIN(_font->getStringWidth(str), w); - int16 stX = x; - if (align == Graphics::kTextAlignCenter) - stX += (w - wd) / 2; - else if (align == Graphics::kTextAlignRight) - stX += (w - wd); - - int thk = MAX((int)(_font->getFontHeight() * 0.05), 1); - - dst->fillRect(Common::Rect(stX, y + pos, stX + wd, y + pos + thk), color); - } - } -} - -int StyledTTFont::getStringWidth(const Common::String &str) { - if (_font) - return _font->getStringWidth(str); - return 0; -} - -Graphics::Surface *StyledTTFont::renderSolidText(const Common::String &str, uint32 color) { - Graphics::Surface *tmp = new Graphics::Surface; - if (_font) { - int16 w = _font->getStringWidth(str); - if (w && w < 1024) { - tmp->create(w, _font->getFontHeight(), _engine->_pixelFormat); - drawString(tmp, str, 0, 0, w, color); - } - } - return tmp; -} - -} // End of namespace ZVision diff --git a/engines/zvision/graphics/truetype_font.h b/engines/zvision/graphics/truetype_font.h deleted file mode 100644 index b5fac4af8a..0000000000 --- a/engines/zvision/graphics/truetype_font.h +++ /dev/null @@ -1,84 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -// This file is based on engines/wintermute/base/fonts/base_font_truetype.h/.cpp - -#ifndef ZVISION_TRUETYPE_FONT_H -#define ZVISION_TRUETYPE_FONT_H - -#include "graphics/font.h" -#include "graphics/pixelformat.h" - -namespace Graphics { -struct Surface; -} - -namespace ZVision { - -class ZVision; - -// Styled TTF -class StyledTTFont { -public: - StyledTTFont(ZVision *engine); - ~StyledTTFont(); - - enum { - STTF_BOLD = 1, - STTF_ITALIC = 2, - STTF_UNDERLINE = 4, - STTF_STRIKEOUT = 8, - STTF_SHARP = 16 - }; - -private: - ZVision *_engine; - Graphics::Font *_font; - int _lineHeight; - uint _style; - Common::String _fntName; - -public: - bool loadFont(const Common::String &fontName, int32 point); - bool loadFont(const Common::String &fontName, int32 point, uint style); - void setStyle(uint newStyle); - - int getFontHeight(); - int getMaxCharWidth(); - int getCharWidth(byte chr); - int getKerningOffset(byte left, byte right); - - void drawChar(Graphics::Surface *dst, byte chr, int x, int y, uint32 color); - - void drawString(Graphics::Surface *dst, const Common::String &str, int x, int y, int w, uint32 color, Graphics::TextAlign align = Graphics::kTextAlignLeft); - int getStringWidth(const Common::String &str); - - Graphics::Surface *renderSolidText(const Common::String &str, uint32 color); - - bool isLoaded() { - return _font != NULL; - }; -}; - -} // End of namespace ZVision - -#endif diff --git a/engines/zvision/module.mk b/engines/zvision/module.mk index 00652f0824..3ea31abe1b 100644 --- a/engines/zvision/module.mk +++ b/engines/zvision/module.mk @@ -17,8 +17,6 @@ MODULE_OBJS := \ graphics/effects/wave.o \ graphics/render_manager.o \ graphics/render_table.o \ - graphics/subtitles.o \ - graphics/truetype_font.o \ scripting/actions.o \ scripting/control.o \ scripting/controls/fist_control.o \ @@ -44,7 +42,9 @@ MODULE_OBJS := \ sound/midi.o \ sound/zork_raw.o \ text/string_manager.o \ + text/subtitles.o \ text/text.o \ + text/truetype_font.o \ video/rlf_decoder.o \ video/video.o \ video/zork_avi_decoder.o \ diff --git a/engines/zvision/scripting/sidefx/music_node.h b/engines/zvision/scripting/sidefx/music_node.h index 09bdc3707e..8f4a46f3fc 100644 --- a/engines/zvision/scripting/sidefx/music_node.h +++ b/engines/zvision/scripting/sidefx/music_node.h @@ -25,7 +25,7 @@ #include "audio/mixer.h" #include "zvision/scripting/sidefx.h" -#include "zvision/graphics/subtitles.h" +#include "zvision/text/subtitles.h" namespace Common { class String; diff --git a/engines/zvision/scripting/sidefx/syncsound_node.h b/engines/zvision/scripting/sidefx/syncsound_node.h index 7cd02a8aef..5961fccab9 100644 --- a/engines/zvision/scripting/sidefx/syncsound_node.h +++ b/engines/zvision/scripting/sidefx/syncsound_node.h @@ -25,7 +25,7 @@ #include "audio/mixer.h" #include "zvision/scripting/sidefx.h" -#include "zvision/graphics/subtitles.h" +#include "zvision/text/subtitles.h" namespace Common { class String; diff --git a/engines/zvision/scripting/sidefx/ttytext_node.h b/engines/zvision/scripting/sidefx/ttytext_node.h index b6cbed3e34..26d9be8e77 100644 --- a/engines/zvision/scripting/sidefx/ttytext_node.h +++ b/engines/zvision/scripting/sidefx/ttytext_node.h @@ -28,7 +28,7 @@ #include "zvision/scripting/sidefx.h" #include "zvision/text/text.h" -#include "zvision/graphics/truetype_font.h" +#include "zvision/text/truetype_font.h" namespace Common { class String; diff --git a/engines/zvision/text/string_manager.h b/engines/zvision/text/string_manager.h index b77ad65040..f4564ee1ec 100644 --- a/engines/zvision/text/string_manager.h +++ b/engines/zvision/text/string_manager.h @@ -24,7 +24,7 @@ #define ZVISION_STRING_MANAGER_H #include "zvision/detection.h" -#include "zvision/graphics/truetype_font.h" +#include "zvision/text/truetype_font.h" namespace Graphics { class FontManager; diff --git a/engines/zvision/text/subtitles.cpp b/engines/zvision/text/subtitles.cpp new file mode 100644 index 0000000000..acf4c37c2f --- /dev/null +++ b/engines/zvision/text/subtitles.cpp @@ -0,0 +1,108 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "zvision/graphics/render_manager.h" +#include "zvision/text/subtitles.h" +#include "zvision/file/search_manager.h" +#include "zvision/text/text.h" + +namespace ZVision { + +Subtitle::Subtitle(ZVision *engine, const Common::String &subname) : + _engine(engine), + _areaId(-1), + _subId(-1) { + Common::File file; + if (_engine->getSearchManager()->openFile(file, subname)) { + while (!file.eos()) { + Common::String str = file.readLine(); + if (str.lastChar() == '~') + str.deleteLastChar(); + + if (str.matchString("*Initialization*", true)) { + // Not used + } else if (str.matchString("*Rectangle*", true)) { + int32 x1, y1, x2, y2; + sscanf(str.c_str(), "%*[^:]:%d %d %d %d", &x1, &y1, &x2, &y2); + Common::Rect rct = Common::Rect(x1, y1, x2, y2); + _areaId = _engine->getRenderManager()->createSubArea(rct); + } else if (str.matchString("*TextFile*", true)) { + char filename[64]; + sscanf(str.c_str(), "%*[^:]:%s", filename); + Common::File txt; + if (_engine->getSearchManager()->openFile(txt, filename)) { + while (!txt.eos()) { + Common::String txtline = readWideLine(txt); + sub curSubtitle; + curSubtitle.start = -1; + curSubtitle.stop = -1; + curSubtitle.subStr = txtline; + + _subs.push_back(curSubtitle); + } + txt.close(); + } + } else { + int32 st; + int32 en; + int32 sb; + if (sscanf(str.c_str(), "%*[^:]:(%d,%d)=%d", &st, &en, &sb) == 3) { + if (sb <= (int32)_subs.size()) { + _subs[sb].start = st; + _subs[sb].stop = en; + } + } + } + } + } +} + +Subtitle::~Subtitle() { + if (_areaId != -1) + _engine->getRenderManager()->deleteSubArea(_areaId); + + _subs.clear(); +} + +void Subtitle::process(int32 time) { + int16 j = -1; + for (uint16 i = 0; i < _subs.size(); i++) + if (time >= _subs[i].start && time <= _subs[i].stop) { + j = i; + break; + } + + if (j == -1 && _subId != -1) { + if (_areaId != -1) + _engine->getRenderManager()->updateSubArea(_areaId, ""); + _subId = -1; + } + + if (j != -1 && j != _subId) { + if (_subs[j].subStr.size()) + if (_areaId != -1) + _engine->getRenderManager()->updateSubArea(_areaId, _subs[j].subStr); + _subId = j; + } +} + +} // End of namespace ZVision diff --git a/engines/zvision/text/subtitles.h b/engines/zvision/text/subtitles.h new file mode 100644 index 0000000000..c3da6583a4 --- /dev/null +++ b/engines/zvision/text/subtitles.h @@ -0,0 +1,54 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef ZVISION_SUBTITLES_H +#define ZVISION_SUBTITLES_H + +#include "zvision/zvision.h" + +namespace ZVision { + +class ZVision; + +class Subtitle { +public: + Subtitle(ZVision *engine, const Common::String &subname); + ~Subtitle(); + + void process(int32 time); +private: + ZVision *_engine; + int32 _areaId; + int16 _subId; + + struct sub { + int start; + int stop; + Common::String subStr; + }; + + Common::Array _subs; +}; + +} + +#endif diff --git a/engines/zvision/text/text.cpp b/engines/zvision/text/text.cpp index 4ea40a1d55..91a06883b6 100644 --- a/engines/zvision/text/text.cpp +++ b/engines/zvision/text/text.cpp @@ -33,7 +33,7 @@ #include "zvision/text/text.h" #include "zvision/graphics/render_manager.h" -#include "zvision/graphics/truetype_font.h" +#include "zvision/text/truetype_font.h" #include "zvision/scripting/script_manager.h" namespace ZVision { diff --git a/engines/zvision/text/text.h b/engines/zvision/text/text.h index c3c60f6b76..c278b011c7 100644 --- a/engines/zvision/text/text.h +++ b/engines/zvision/text/text.h @@ -25,7 +25,7 @@ #define ZVISION_TEXT_H #include "zvision/detection.h" -#include "zvision/graphics/truetype_font.h" +#include "zvision/text/truetype_font.h" #include "zvision/zvision.h" namespace ZVision { diff --git a/engines/zvision/text/truetype_font.cpp b/engines/zvision/text/truetype_font.cpp new file mode 100644 index 0000000000..f373afe437 --- /dev/null +++ b/engines/zvision/text/truetype_font.cpp @@ -0,0 +1,228 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "common/scummsys.h" +#include "common/config-manager.h" +#include "common/debug.h" +#include "common/file.h" +#include "common/system.h" +#include "common/unzip.h" +#include "graphics/font.h" +#include "graphics/fonts/ttf.h" +#include "graphics/surface.h" + +#include "zvision/zvision.h" +#include "zvision/graphics/render_manager.h" +#include "zvision/text/truetype_font.h" + +namespace ZVision { + +StyledTTFont::StyledTTFont(ZVision *engine) { + _engine = engine; + _style = 0; + _font = NULL; + _lineHeight = 0; +} + +StyledTTFont::~StyledTTFont() { + if (_font) + delete _font; +} + +bool StyledTTFont::loadFont(const Common::String &fontName, int32 point, uint style) { + _style = style; + return loadFont(fontName, point); +} + +bool StyledTTFont::loadFont(const Common::String &fontName, int32 point) { + struct FontStyle { + const char *zorkFont; + const char *fontBase; + const char *freeFontBase; + const char *freeFontItalicName; + }; + + const FontStyle systemFonts[] = { + { "*times new roman*", "times", "FreeSerif", "Italic" }, + { "*times*", "times", "FreeSerif", "Italic" }, + { "*century schoolbook*", "censcbk", "FreeSerif", "Italic" }, + { "*garamond*", "gara", "FreeSerif", "Italic" }, + { "*courier new*", "cour", "FreeMono", "Oblique" }, + { "*courier*", "cour", "FreeMono", "Oblique" }, + { "*ZorkDeath*", "cour", "FreeMono", "Oblique" }, + { "*arial*", "arial", "FreeSans", "Oblique" }, + { "*ZorkNormal*", "arial", "FreeSans", "Oblique" }, + }; + + Common::String newFontName; + Common::String freeFontName; + + for (int i = 0; i < ARRAYSIZE(systemFonts); i++) { + if (fontName.matchString(systemFonts[i].zorkFont, true)) { + newFontName = systemFonts[i].fontBase; + freeFontName = systemFonts[i].freeFontBase; + + if ((_style & STTF_BOLD) && (_style & STTF_ITALIC)) { + newFontName += "bi"; + freeFontName += "Bold"; + freeFontName += systemFonts[i].freeFontItalicName; + } else if (_style & STTF_BOLD) { + newFontName += "bd"; + freeFontName += "Bold"; + } else if (_style & STTF_ITALIC) { + newFontName += "i"; + freeFontName += systemFonts[i].freeFontItalicName; + } + + newFontName += ".ttf"; + freeFontName += ".ttf"; + break; + } + } + + if (newFontName.empty()) { + debug("Could not identify font: %s. Reverting to Arial", fontName.c_str()); + newFontName = "arial.ttf"; + freeFontName = "FreeSans.ttf"; + } + + bool sharp = (_style & STTF_SHARP) == STTF_SHARP; + + Common::File file; + if (!file.open(newFontName) && !file.open(freeFontName)) + error("Unable to open font file %s (free alternative: %s)", newFontName.c_str(), freeFontName.c_str()); + + Graphics::Font *_newFont = Graphics::loadTTFFont(file, point, 60, (sharp ? Graphics::kTTFRenderModeMonochrome : Graphics::kTTFRenderModeNormal)); // 66 dpi for 640 x 480 on 14" display + if (_newFont) { + if (!_font) + delete _font; + _font = _newFont; + } + + _fntName = fontName; + _lineHeight = point; + + if (_font) + return true; + return false; +} + +void StyledTTFont::setStyle(uint newStyle) { + if ((_style & (STTF_BOLD | STTF_ITALIC | STTF_SHARP)) != (newStyle & (STTF_BOLD | STTF_ITALIC | STTF_SHARP))) { + _style = newStyle; + loadFont(_fntName, _lineHeight); + } else { + _style = newStyle; + } +} + +int StyledTTFont::getFontHeight() { + if (_font) + return _font->getFontHeight(); + return 0; +} + +int StyledTTFont::getMaxCharWidth() { + if (_font) + return _font->getMaxCharWidth(); + return 0; +} + +int StyledTTFont::getCharWidth(byte chr) { + if (_font) + return _font->getCharWidth(chr); + return 0; +} + +int StyledTTFont::getKerningOffset(byte left, byte right) { + if (_font) + return _font->getKerningOffset(left, right); + return 0; +} + +void StyledTTFont::drawChar(Graphics::Surface *dst, byte chr, int x, int y, uint32 color) { + if (_font) { + _font->drawChar(dst, chr, x, y, color); + if (_style & STTF_UNDERLINE) { + int16 pos = floor(_font->getFontHeight() * 0.87); + int thk = MAX((int)(_font->getFontHeight() * 0.05), 1); + dst->fillRect(Common::Rect(x, y + pos, x + _font->getCharWidth(chr), y + pos + thk), color); + } + if (_style & STTF_STRIKEOUT) { + int16 pos = floor(_font->getFontHeight() * 0.60); + int thk = MAX((int)(_font->getFontHeight() * 0.05), 1); + dst->fillRect(Common::Rect(x, y + pos, x + _font->getCharWidth(chr), y + pos + thk), color); + } + } +} + +void StyledTTFont::drawString(Graphics::Surface *dst, const Common::String &str, int x, int y, int w, uint32 color, Graphics::TextAlign align) { + if (_font) { + _font->drawString(dst, str, x, y, w, color, align); + if (_style & STTF_UNDERLINE) { + int16 pos = floor(_font->getFontHeight() * 0.87); + int16 wd = MIN(_font->getStringWidth(str), w); + int16 stX = x; + if (align == Graphics::kTextAlignCenter) + stX += (w - wd) / 2; + else if (align == Graphics::kTextAlignRight) + stX += (w - wd); + + int thk = MAX((int)(_font->getFontHeight() * 0.05), 1); + + dst->fillRect(Common::Rect(stX, y + pos, stX + wd, y + pos + thk), color); + } + if (_style & STTF_STRIKEOUT) { + int16 pos = floor(_font->getFontHeight() * 0.60); + int16 wd = MIN(_font->getStringWidth(str), w); + int16 stX = x; + if (align == Graphics::kTextAlignCenter) + stX += (w - wd) / 2; + else if (align == Graphics::kTextAlignRight) + stX += (w - wd); + + int thk = MAX((int)(_font->getFontHeight() * 0.05), 1); + + dst->fillRect(Common::Rect(stX, y + pos, stX + wd, y + pos + thk), color); + } + } +} + +int StyledTTFont::getStringWidth(const Common::String &str) { + if (_font) + return _font->getStringWidth(str); + return 0; +} + +Graphics::Surface *StyledTTFont::renderSolidText(const Common::String &str, uint32 color) { + Graphics::Surface *tmp = new Graphics::Surface; + if (_font) { + int16 w = _font->getStringWidth(str); + if (w && w < 1024) { + tmp->create(w, _font->getFontHeight(), _engine->_pixelFormat); + drawString(tmp, str, 0, 0, w, color); + } + } + return tmp; +} + +} // End of namespace ZVision diff --git a/engines/zvision/text/truetype_font.h b/engines/zvision/text/truetype_font.h new file mode 100644 index 0000000000..b5fac4af8a --- /dev/null +++ b/engines/zvision/text/truetype_font.h @@ -0,0 +1,84 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +// This file is based on engines/wintermute/base/fonts/base_font_truetype.h/.cpp + +#ifndef ZVISION_TRUETYPE_FONT_H +#define ZVISION_TRUETYPE_FONT_H + +#include "graphics/font.h" +#include "graphics/pixelformat.h" + +namespace Graphics { +struct Surface; +} + +namespace ZVision { + +class ZVision; + +// Styled TTF +class StyledTTFont { +public: + StyledTTFont(ZVision *engine); + ~StyledTTFont(); + + enum { + STTF_BOLD = 1, + STTF_ITALIC = 2, + STTF_UNDERLINE = 4, + STTF_STRIKEOUT = 8, + STTF_SHARP = 16 + }; + +private: + ZVision *_engine; + Graphics::Font *_font; + int _lineHeight; + uint _style; + Common::String _fntName; + +public: + bool loadFont(const Common::String &fontName, int32 point); + bool loadFont(const Common::String &fontName, int32 point, uint style); + void setStyle(uint newStyle); + + int getFontHeight(); + int getMaxCharWidth(); + int getCharWidth(byte chr); + int getKerningOffset(byte left, byte right); + + void drawChar(Graphics::Surface *dst, byte chr, int x, int y, uint32 color); + + void drawString(Graphics::Surface *dst, const Common::String &str, int x, int y, int w, uint32 color, Graphics::TextAlign align = Graphics::kTextAlignLeft); + int getStringWidth(const Common::String &str); + + Graphics::Surface *renderSolidText(const Common::String &str, uint32 color); + + bool isLoaded() { + return _font != NULL; + }; +}; + +} // End of namespace ZVision + +#endif diff --git a/engines/zvision/video/video.cpp b/engines/zvision/video/video.cpp index 189fb22194..97fbd8721c 100644 --- a/engines/zvision/video/video.cpp +++ b/engines/zvision/video/video.cpp @@ -29,7 +29,7 @@ #include "zvision/zvision.h" #include "zvision/core/clock.h" #include "zvision/graphics/render_manager.h" -#include "zvision/graphics/subtitles.h" +#include "zvision/text/subtitles.h" #include "zvision/video/rlf_decoder.h" #include "zvision/video/zork_avi_decoder.h" diff --git a/engines/zvision/zvision.cpp b/engines/zvision/zvision.cpp index c32cceb26e..cf7ed288d7 100644 --- a/engines/zvision/zvision.cpp +++ b/engines/zvision/zvision.cpp @@ -33,7 +33,7 @@ #include "zvision/core/menu.h" #include "zvision/file/search_manager.h" #include "zvision/text/text.h" -#include "zvision/graphics/truetype_font.h" +#include "zvision/text/truetype_font.h" #include "zvision/sound/midi.h" #include "zvision/file/zfs_archive.h" -- cgit v1.2.3 From 7aeeeabba9de168e76ae4d82b7f033fc877d0671 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 23 Dec 2014 01:57:37 +0200 Subject: ZVISION: Add a comment about the special 0xCCCC character --- engines/zvision/text/text.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'engines') diff --git a/engines/zvision/text/text.cpp b/engines/zvision/text/text.cpp index 91a06883b6..d1dc784f3e 100644 --- a/engines/zvision/text/text.cpp +++ b/engines/zvision/text/text.cpp @@ -499,6 +499,8 @@ Common::String readWideLine(Common::SeekableReadStream &stream) { asciiString += (char)(0xE0 | ((value >> 12) & 0xF)); asciiString += (char)(0x80 | ((value >> 6) & 0x3F)); asciiString += (char)(0x80 | (value & 0x3F)); + } else if (value == 0xCCCC) { + // Ignore, this character is used as newline sometimes } else if (value >= 0x10000 && value < 0x200000) { asciiString += (char)(0xF0); asciiString += (char)(0x80 | ((value >> 12) & 0x3F)); -- cgit v1.2.3 From 99073f9b57580570b5ecec4cb00f020867f02672 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 23 Dec 2014 02:20:17 +0200 Subject: ZVISION: Fix some buffer overruns with the usage of sscanf() --- engines/zvision/scripting/actions.cpp | 18 +++++++++--------- engines/zvision/scripting/controls/input_control.cpp | 2 +- engines/zvision/scripting/controls/lever_control.cpp | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) (limited to 'engines') diff --git a/engines/zvision/scripting/actions.cpp b/engines/zvision/scripting/actions.cpp index 2a5046f146..5af847c61a 100644 --- a/engines/zvision/scripting/actions.cpp +++ b/engines/zvision/scripting/actions.cpp @@ -363,7 +363,7 @@ ActionInventory::ActionInventory(ZVision *engine, int32 slotkey, const Common::S _key = 0; char buf[25]; - sscanf(line.c_str(), "%25s %d", buf, &_key); + sscanf(line.c_str(), "%24s %d", buf, &_key); if (strcmp(buf, "add") == 0) { _type = 0; @@ -414,7 +414,7 @@ ActionKill::ActionKill(ZVision *engine, int32 slotkey, const Common::String &lin _key = 0; _type = 0; char keytype[25]; - sscanf(line.c_str(), "%25s", keytype); + sscanf(line.c_str(), "%24s", keytype); if (keytype[0] == '"') { if (!scumm_stricmp(keytype, "\"ANIM\"")) _type = SideFX::SIDEFX_ANIM; @@ -475,7 +475,7 @@ ActionMusic::ActionMusic(ZVision *engine, int32 slotkey, const Common::String &l uint loop = 0; uint volume = 255; - sscanf(line.c_str(), "%u %25s %u %u", &type, fileNameBuffer, &loop, &volume); + sscanf(line.c_str(), "%u %24s %u %u", &type, fileNameBuffer, &loop, &volume); // type 4 are midi sound effect files if (type == 4) { @@ -578,7 +578,7 @@ ActionPreloadAnimation::ActionPreloadAnimation(ZVision *engine, int32 slotkey, c char fileName[25]; // The two %*u are usually 0 and dont seem to have a use - sscanf(line.c_str(), "%25s %*u %*u %d %d", fileName, &_mask, &_framerate); + sscanf(line.c_str(), "%24s %*u %*u %d %d", fileName, &_mask, &_framerate); if (_mask > 0) { byte r, g, b; @@ -645,7 +645,7 @@ ActionPlayAnimation::ActionPlayAnimation(ZVision *engine, int32 slotkey, const C // The two %*u are always 0 and dont seem to have a use sscanf(line.c_str(), - "%25s %u %u %u %u %u %u %d %*u %*u %d %d", + "%24s %u %u %u %u %u %u %d %*u %*u %d %d", fileName, &_x, &_y, &_x2, &_y2, &_start, &_end, &_loopCount, &_mask, &_framerate); if (_mask > 0) { @@ -863,7 +863,7 @@ ActionSetPartialScreen::ActionSetPartialScreen(ZVision *engine, int32 slotkey, c char fileName[25]; int color; - sscanf(line.c_str(), "%u %u %25s %*u %d", &_x, &_y, fileName, &color); + sscanf(line.c_str(), "%u %u %24s %*u %d", &_x, &_y, fileName, &color); _fileName = Common::String(fileName); @@ -907,7 +907,7 @@ bool ActionSetPartialScreen::execute() { ActionSetScreen::ActionSetScreen(ZVision *engine, int32 slotkey, const Common::String &line) : ResultAction(engine, slotkey) { char fileName[25]; - sscanf(line.c_str(), "%25s", fileName); + sscanf(line.c_str(), "%24s", fileName); _fileName = Common::String(fileName); } @@ -966,7 +966,7 @@ ActionStreamVideo::ActionStreamVideo(ZVision *engine, int32 slotkey, const Commo char fileName[25]; uint skipline = 0; //skipline - render video with skip every second line, not skippable. - sscanf(line.c_str(), "%25s %u %u %u %u %u %u", fileName, &_x1, &_y1, &_x2, &_y2, &_flags, &skipline); + sscanf(line.c_str(), "%24s %u %u %u %u %u %u", fileName, &_x1, &_y1, &_x2, &_y2, &_flags, &skipline); _fileName = Common::String(fileName); _skippable = true; @@ -1017,7 +1017,7 @@ ActionSyncSound::ActionSyncSound(ZVision *engine, int32 slotkey, const Common::S char fileName[25]; int notUsed = 0; - sscanf(line.c_str(), "%d %d %25s", &_syncto, ¬Used, fileName); + sscanf(line.c_str(), "%d %d %24s", &_syncto, ¬Used, fileName); _fileName = Common::String(fileName); } diff --git a/engines/zvision/scripting/controls/input_control.cpp b/engines/zvision/scripting/controls/input_control.cpp index e75cc15743..d7734f6d7a 100644 --- a/engines/zvision/scripting/controls/input_control.cpp +++ b/engines/zvision/scripting/controls/input_control.cpp @@ -96,7 +96,7 @@ InputControl::InputControl(ZVision *engine, uint32 key, Common::SeekableReadStre } else if (param.matchString("cursor_animation", true)) { char fileName[25]; - sscanf(values.c_str(), "%25s %*u", fileName); + sscanf(values.c_str(), "%24s %*u", fileName); _animation = _engine->loadAnimation(fileName); _frame = -1; diff --git a/engines/zvision/scripting/controls/lever_control.cpp b/engines/zvision/scripting/controls/lever_control.cpp index 8faa18357c..bef51f0e91 100644 --- a/engines/zvision/scripting/controls/lever_control.cpp +++ b/engines/zvision/scripting/controls/lever_control.cpp @@ -64,12 +64,12 @@ LeverControl::LeverControl(ZVision *engine, uint32 key, Common::SeekableReadStre while (!stream.eos() && !line.contains('}')) { if (param.matchString("descfile", true)) { char levFileName[25]; - sscanf(values.c_str(), "%25s", levFileName); + sscanf(values.c_str(), "%24s", levFileName); parseLevFile(levFileName); } else if (param.matchString("cursor", true)) { char cursorName[25]; - sscanf(values.c_str(), "%25s", cursorName); + sscanf(values.c_str(), "%24s", cursorName); _cursor = _engine->getCursorManager()->getCursorId(Common::String(cursorName)); } -- cgit v1.2.3 From 11cb47e89772ea59fc55d2801685d1a3505235a0 Mon Sep 17 00:00:00 2001 From: Adrian Astley Date: Tue, 23 Dec 2014 00:25:42 -0600 Subject: ZVISION: Remove unnecessary math --- engines/zvision/core/events.cpp | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'engines') diff --git a/engines/zvision/core/events.cpp b/engines/zvision/core/events.cpp index 6e8cf1fe4f..72e7f33266 100644 --- a/engines/zvision/core/events.cpp +++ b/engines/zvision/core/events.cpp @@ -296,18 +296,20 @@ void ZVision::onMouseMove(const Common::Point &pos) { if (clippedPos.x >= _workingWindow.left && clippedPos.x < _workingWindow.left + ROTATION_SCREEN_EDGE_OFFSET) { int16 mspeed = _scriptManager->getStateValue(StateKey_RotateSpeed) >> 4; - if (mspeed <= 0) - mspeed = 400 >> 4; _mouseVelocity = (((clippedPos.x - (ROTATION_SCREEN_EDGE_OFFSET + _workingWindow.left)) << 7) / ROTATION_SCREEN_EDGE_OFFSET * mspeed) >> 7; + if (mspeed <= 0) { + mspeed = 25; + } _cursorManager->changeCursor(CursorIndex_Left); cursorWasChanged = true; } else if (clippedPos.x <= _workingWindow.right && clippedPos.x > _workingWindow.right - ROTATION_SCREEN_EDGE_OFFSET) { int16 mspeed = _scriptManager->getStateValue(StateKey_RotateSpeed) >> 4; - if (mspeed <= 0) - mspeed = 400 >> 4; _mouseVelocity = (((clippedPos.x - (_workingWindow.right - ROTATION_SCREEN_EDGE_OFFSET)) << 7) / ROTATION_SCREEN_EDGE_OFFSET * mspeed) >> 7; + if (mspeed <= 0) { + mspeed = 25; + } _cursorManager->changeCursor(CursorIndex_Right); cursorWasChanged = true; @@ -318,18 +320,20 @@ void ZVision::onMouseMove(const Common::Point &pos) { if (clippedPos.y >= _workingWindow.top && clippedPos.y < _workingWindow.top + ROTATION_SCREEN_EDGE_OFFSET) { int16 mspeed = _scriptManager->getStateValue(StateKey_RotateSpeed) >> 4; - if (mspeed <= 0) - mspeed = 400 >> 4; _mouseVelocity = (((clippedPos.y - (_workingWindow.top + ROTATION_SCREEN_EDGE_OFFSET)) << 7) / ROTATION_SCREEN_EDGE_OFFSET * mspeed) >> 7; + if (mspeed <= 0) { + mspeed = 25; + } _cursorManager->changeCursor(CursorIndex_UpArr); cursorWasChanged = true; } else if (clippedPos.y <= _workingWindow.bottom && clippedPos.y > _workingWindow.bottom - ROTATION_SCREEN_EDGE_OFFSET) { int16 mspeed = _scriptManager->getStateValue(StateKey_RotateSpeed) >> 4; - if (mspeed <= 0) - mspeed = 400 >> 4; _mouseVelocity = (((clippedPos.y - (_workingWindow.bottom - ROTATION_SCREEN_EDGE_OFFSET)) << 7) / ROTATION_SCREEN_EDGE_OFFSET * mspeed) >> 7; + if (mspeed <= 0) { + mspeed = 25; + } _cursorManager->changeCursor(CursorIndex_DownArr); cursorWasChanged = true; -- cgit v1.2.3 From 6548300a4182e1dc805b390678df800b05d07554 Mon Sep 17 00:00:00 2001 From: Adrian Astley Date: Tue, 23 Dec 2014 00:27:53 -0600 Subject: ZVISION: Use Common::Rational to simplify fixed point math --- engines/zvision/core/events.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/zvision/core/events.cpp b/engines/zvision/core/events.cpp index 72e7f33266..ccd7772975 100644 --- a/engines/zvision/core/events.cpp +++ b/engines/zvision/core/events.cpp @@ -296,20 +296,21 @@ void ZVision::onMouseMove(const Common::Point &pos) { if (clippedPos.x >= _workingWindow.left && clippedPos.x < _workingWindow.left + ROTATION_SCREEN_EDGE_OFFSET) { int16 mspeed = _scriptManager->getStateValue(StateKey_RotateSpeed) >> 4; - _mouseVelocity = (((clippedPos.x - (ROTATION_SCREEN_EDGE_OFFSET + _workingWindow.left)) << 7) / ROTATION_SCREEN_EDGE_OFFSET * mspeed) >> 7; if (mspeed <= 0) { mspeed = 25; } + _mouseVelocity = ((Common::Rational(mspeed, ROTATION_SCREEN_EDGE_OFFSET) * (clippedPos.x - _workingWindow.left)) - mspeed).toInt(); + _cursorManager->changeCursor(CursorIndex_Left); cursorWasChanged = true; } else if (clippedPos.x <= _workingWindow.right && clippedPos.x > _workingWindow.right - ROTATION_SCREEN_EDGE_OFFSET) { int16 mspeed = _scriptManager->getStateValue(StateKey_RotateSpeed) >> 4; - _mouseVelocity = (((clippedPos.x - (_workingWindow.right - ROTATION_SCREEN_EDGE_OFFSET)) << 7) / ROTATION_SCREEN_EDGE_OFFSET * mspeed) >> 7; if (mspeed <= 0) { mspeed = 25; } + _mouseVelocity = (Common::Rational(mspeed, ROTATION_SCREEN_EDGE_OFFSET) * (clippedPos.x - _workingWindow.right + ROTATION_SCREEN_EDGE_OFFSET)).toInt(); _cursorManager->changeCursor(CursorIndex_Right); cursorWasChanged = true; @@ -320,20 +321,20 @@ void ZVision::onMouseMove(const Common::Point &pos) { if (clippedPos.y >= _workingWindow.top && clippedPos.y < _workingWindow.top + ROTATION_SCREEN_EDGE_OFFSET) { int16 mspeed = _scriptManager->getStateValue(StateKey_RotateSpeed) >> 4; - _mouseVelocity = (((clippedPos.y - (_workingWindow.top + ROTATION_SCREEN_EDGE_OFFSET)) << 7) / ROTATION_SCREEN_EDGE_OFFSET * mspeed) >> 7; if (mspeed <= 0) { mspeed = 25; } + _mouseVelocity = ((Common::Rational(mspeed, ROTATION_SCREEN_EDGE_OFFSET) * (pos.y - _workingWindow.top)) - mspeed).toInt(); _cursorManager->changeCursor(CursorIndex_UpArr); cursorWasChanged = true; } else if (clippedPos.y <= _workingWindow.bottom && clippedPos.y > _workingWindow.bottom - ROTATION_SCREEN_EDGE_OFFSET) { int16 mspeed = _scriptManager->getStateValue(StateKey_RotateSpeed) >> 4; - _mouseVelocity = (((clippedPos.y - (_workingWindow.bottom - ROTATION_SCREEN_EDGE_OFFSET)) << 7) / ROTATION_SCREEN_EDGE_OFFSET * mspeed) >> 7; if (mspeed <= 0) { mspeed = 25; } + _mouseVelocity = (Common::Rational(MAX_ROTATION_SPEED, ROTATION_SCREEN_EDGE_OFFSET) * (pos.y - _workingWindow.bottom + ROTATION_SCREEN_EDGE_OFFSET)).toInt(); _cursorManager->changeCursor(CursorIndex_DownArr); cursorWasChanged = true; -- cgit v1.2.3 From 40bd4c485f9ab24e667e66a047214eb7dcef73e8 Mon Sep 17 00:00:00 2001 From: Adrian Astley Date: Tue, 23 Dec 2014 00:38:44 -0600 Subject: ZVISION: Clamp the rotation velocity to never be zero Before, if we set the in-game preferences to have very low rotation speed, the velocity ends up always being 0 - 0.99 Hence, when we convert back to an int, everything gets truncated to zero. Therefore, we clamp, in order to ensure the user can always move, no matter which setting they use. --- engines/zvision/core/events.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/zvision/core/events.cpp b/engines/zvision/core/events.cpp index ccd7772975..1920ffd769 100644 --- a/engines/zvision/core/events.cpp +++ b/engines/zvision/core/events.cpp @@ -299,7 +299,7 @@ void ZVision::onMouseMove(const Common::Point &pos) { if (mspeed <= 0) { mspeed = 25; } - _mouseVelocity = ((Common::Rational(mspeed, ROTATION_SCREEN_EDGE_OFFSET) * (clippedPos.x - _workingWindow.left)) - mspeed).toInt(); + _mouseVelocity = MIN(((Common::Rational(mspeed, ROTATION_SCREEN_EDGE_OFFSET) * (clippedPos.x - _workingWindow.left)) - mspeed).toInt(), -1); _cursorManager->changeCursor(CursorIndex_Left); @@ -310,7 +310,7 @@ void ZVision::onMouseMove(const Common::Point &pos) { if (mspeed <= 0) { mspeed = 25; } - _mouseVelocity = (Common::Rational(mspeed, ROTATION_SCREEN_EDGE_OFFSET) * (clippedPos.x - _workingWindow.right + ROTATION_SCREEN_EDGE_OFFSET)).toInt(); + _mouseVelocity = MAX((Common::Rational(mspeed, ROTATION_SCREEN_EDGE_OFFSET) * (clippedPos.x - _workingWindow.right + ROTATION_SCREEN_EDGE_OFFSET)).toInt(), 1); _cursorManager->changeCursor(CursorIndex_Right); cursorWasChanged = true; @@ -324,7 +324,7 @@ void ZVision::onMouseMove(const Common::Point &pos) { if (mspeed <= 0) { mspeed = 25; } - _mouseVelocity = ((Common::Rational(mspeed, ROTATION_SCREEN_EDGE_OFFSET) * (pos.y - _workingWindow.top)) - mspeed).toInt(); + _mouseVelocity = MIN(((Common::Rational(mspeed, ROTATION_SCREEN_EDGE_OFFSET) * (pos.y - _workingWindow.top)) - mspeed).toInt(), -1); _cursorManager->changeCursor(CursorIndex_UpArr); cursorWasChanged = true; @@ -334,7 +334,7 @@ void ZVision::onMouseMove(const Common::Point &pos) { if (mspeed <= 0) { mspeed = 25; } - _mouseVelocity = (Common::Rational(MAX_ROTATION_SPEED, ROTATION_SCREEN_EDGE_OFFSET) * (pos.y - _workingWindow.bottom + ROTATION_SCREEN_EDGE_OFFSET)).toInt(); + _mouseVelocity = MAX((Common::Rational(MAX_ROTATION_SPEED, ROTATION_SCREEN_EDGE_OFFSET) * (pos.y - _workingWindow.bottom + ROTATION_SCREEN_EDGE_OFFSET)).toInt(), 1); _cursorManager->changeCursor(CursorIndex_DownArr); cursorWasChanged = true; -- cgit v1.2.3 From 9f1fd0dbff6e1702f49708c8ef4cc91f3b44ca4e Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 23 Dec 2014 11:03:02 +0200 Subject: ZVISION: Disable unused code --- engines/zvision/text/text.cpp | 8 +++++++- engines/zvision/text/text.h | 2 ++ 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/zvision/text/text.cpp b/engines/zvision/text/text.cpp index d1dc784f3e..53fcafd027 100644 --- a/engines/zvision/text/text.cpp +++ b/engines/zvision/text/text.cpp @@ -44,10 +44,12 @@ cTxtStyle::cTxtStyle() { _green = 255; _red = 255; _bold = false; +#if 0 + _newline = false; _escapement = 0; +#endif _italic = false; _justify = TXT_JUSTIFY_LEFT; - _newline = false; _size = 12; _skipcolor = false; _strikeout = false; @@ -115,10 +117,12 @@ txtReturn cTxtStyle::parseStyle(const Common::String &strin, int16 ln) { } } } else if (token.matchString("newline", true)) { +#if 0 if ((retval & TXT_RET_NEWLN) == 0) _newline = 0; _newline++; +#endif retval |= TXT_RET_NEWLN; } else if (token.matchString("point", true)) { if (!tokenizer.empty()) { @@ -132,8 +136,10 @@ txtReturn cTxtStyle::parseStyle(const Common::String &strin, int16 ln) { } else if (token.matchString("escapement", true)) { if (!tokenizer.empty()) { token = tokenizer.nextToken(); +#if 0 int32 tmp = atoi(token.c_str()); _escapement = tmp; +#endif } } else if (token.matchString("italic", true)) { if (!tokenizer.empty()) { diff --git a/engines/zvision/text/text.h b/engines/zvision/text/text.h index c278b011c7..c044e91579 100644 --- a/engines/zvision/text/text.h +++ b/engines/zvision/text/text.h @@ -61,8 +61,10 @@ public: uint8 _red; // 0-255 uint8 _green; // 0-255 uint8 _blue; // 0-255 +#if 0 int8 _newline; int8 _escapement; +#endif bool _italic; bool _bold; bool _underline; -- cgit v1.2.3 From 490382098eb122e25aa895dc8de7330c22b1fcf8 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 23 Dec 2014 11:06:39 +0200 Subject: ZVISION: Disable more unused code --- engines/zvision/text/text.cpp | 4 ++++ engines/zvision/text/text.h | 2 ++ 2 files changed, 6 insertions(+) (limited to 'engines') diff --git a/engines/zvision/text/text.cpp b/engines/zvision/text/text.cpp index 53fcafd027..8ddba3fbab 100644 --- a/engines/zvision/text/text.cpp +++ b/engines/zvision/text/text.cpp @@ -51,7 +51,9 @@ cTxtStyle::cTxtStyle() { _italic = false; _justify = TXT_JUSTIFY_LEFT; _size = 12; +#if 0 _skipcolor = false; +#endif _strikeout = false; _underline = false; _statebox = 0; @@ -204,11 +206,13 @@ txtReturn cTxtStyle::parseStyle(const Common::String &strin, int16 ln) { } else if (token.matchString("skipcolor", true)) { if (!tokenizer.empty()) { token = tokenizer.nextToken(); +#if 0 if (token.matchString("on", true)) { _skipcolor = true; } else if (token.matchString("off", true)) { _skipcolor = false; } +#endif } } else if (token.matchString("image", true)) { // Not used diff --git a/engines/zvision/text/text.h b/engines/zvision/text/text.h index c044e91579..c942b8141a 100644 --- a/engines/zvision/text/text.h +++ b/engines/zvision/text/text.h @@ -69,7 +69,9 @@ public: bool _bold; bool _underline; bool _strikeout; +#if 0 bool _skipcolor; +#endif int32 _statebox; bool _sharp; // char image ?? -- cgit v1.2.3 From e8cc098cd4303a959e69769eae2d37dd949d27d3 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 23 Dec 2014 11:54:39 +0200 Subject: ZVISION: Limit the engine delay, even when a custom frame rate is set --- engines/zvision/scripting/sidefx/animation_node.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/zvision/scripting/sidefx/animation_node.cpp b/engines/zvision/scripting/sidefx/animation_node.cpp index 56f1fa3e49..4f26f039cc 100644 --- a/engines/zvision/scripting/sidefx/animation_node.cpp +++ b/engines/zvision/scripting/sidefx/animation_node.cpp @@ -42,13 +42,13 @@ AnimationNode::AnimationNode(ZVision *engine, uint32 controlKey, const Common::S _animation = engine->loadAnimation(fileName); _frmDelay = 1000.0 / _animation->getDuration().framerate(); + if (frate > 0) + _frmDelay = 1000.0 / frate; + // WORKAROUND: We do not allow the engine to delay more than 66 msec // per frame (15fps max) if (_frmDelay > 66) _frmDelay = 66; - - if (frate > 0) - _frmDelay = 1000.0 / frate; } AnimationNode::~AnimationNode() { -- cgit v1.2.3 From 78ba3e32466992ee7d01aabff493617a6401273e Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 23 Dec 2014 21:46:20 +0200 Subject: ZVISION: Add error checking when loading in-game animations and videos --- engines/zvision/video/rlf_decoder.cpp | 14 +++++++------- engines/zvision/video/video.cpp | 7 ++++++- 2 files changed, 13 insertions(+), 8 deletions(-) (limited to 'engines') diff --git a/engines/zvision/video/rlf_decoder.cpp b/engines/zvision/video/rlf_decoder.cpp index b798093869..76fd70cf35 100644 --- a/engines/zvision/video/rlf_decoder.cpp +++ b/engines/zvision/video/rlf_decoder.cpp @@ -39,9 +39,13 @@ RLFDecoder::~RLFDecoder() { bool RLFDecoder::loadStream(Common::SeekableReadStream *stream) { close(); - addTrack(new RLFVideoTrack(stream)); - - return true; + // Check if the stream is valid + if (stream && !stream->err() && stream->readUint32BE() == MKTAG('F', 'E', 'L', 'R')) { + addTrack(new RLFVideoTrack(stream)); + return true; + } else { + return false; + } } RLFDecoder::RLFVideoTrack::RLFVideoTrack(Common::SeekableReadStream *stream) @@ -81,10 +85,6 @@ RLFDecoder::RLFVideoTrack::~RLFVideoTrack() { } bool RLFDecoder::RLFVideoTrack::readHeader() { - if (_readStream->readUint32BE() != MKTAG('F', 'E', 'L', 'R')) { - return false; - } - // Read the header _readStream->readUint32LE(); // Size1 _readStream->readUint32LE(); // Unknown1 diff --git a/engines/zvision/video/video.cpp b/engines/zvision/video/video.cpp index 97fbd8721c..50a6fc136a 100644 --- a/engines/zvision/video/video.cpp +++ b/engines/zvision/video/video.cpp @@ -48,7 +48,12 @@ Video::VideoDecoder *ZVision::loadAnimation(const Common::String &fileName) { error("Unknown suffix for animation %s", fileName.c_str()); Common::File *_file = getSearchManager()->openFile(tmpFileName); - animation->loadStream(_file); + if (!_file) + error("Error opening %s", tmpFileName.c_str()); + + bool loaded = animation->loadStream(_file); + if (!loaded) + error("Error loading animation %s", tmpFileName.c_str()); return animation; } -- cgit v1.2.3 From 6edc16b6863c3957efa5ad23596e904d89f8627c Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 23 Dec 2014 21:54:53 +0200 Subject: ZVISION: Spacing --- engines/zvision/scripting/sidefx/animation_node.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'engines') diff --git a/engines/zvision/scripting/sidefx/animation_node.cpp b/engines/zvision/scripting/sidefx/animation_node.cpp index 4f26f039cc..134ab1396f 100644 --- a/engines/zvision/scripting/sidefx/animation_node.cpp +++ b/engines/zvision/scripting/sidefx/animation_node.cpp @@ -111,7 +111,6 @@ bool AnimationNode::process(uint32 deltaTimeInMillis) { } if (frame) { - uint32 dstw; uint32 dsth; if (_engine->getRenderManager()->getRenderTable()->getRenderState() == RenderTable::PANORAMA) { -- cgit v1.2.3 From 6afeec129504a16ee67c77b35cd27f0808d566d2 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 23 Dec 2014 21:55:42 +0200 Subject: ZVISION: Handle animation rewinding outside the RLF encoder --- engines/zvision/video/rlf_decoder.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/zvision/video/rlf_decoder.cpp b/engines/zvision/video/rlf_decoder.cpp index 76fd70cf35..f1ac10bf88 100644 --- a/engines/zvision/video/rlf_decoder.cpp +++ b/engines/zvision/video/rlf_decoder.cpp @@ -200,9 +200,8 @@ bool RLFDecoder::RLFVideoTrack::seek(const Audio::Timestamp &time) { } const Graphics::Surface *RLFDecoder::RLFVideoTrack::decodeNextFrame() { - // When an animation ends, rewind if (_curFrame == (int)_frameCount) - seek(Audio::Timestamp(0, getFrameRate().toInt())); + return NULL; applyFrameToCurrent(_curFrame); -- cgit v1.2.3 From 9948d3ca16ceff79dd3ccf6dde5024de04470f08 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 24 Dec 2014 06:13:49 +0200 Subject: ZVISION: Add a hack to set the correct frame delay for RLF videos Also, use Common::Rational to avoid using floating point math --- engines/zvision/scripting/sidefx/animation_node.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/zvision/scripting/sidefx/animation_node.cpp b/engines/zvision/scripting/sidefx/animation_node.cpp index 134ab1396f..1f62b61310 100644 --- a/engines/zvision/scripting/sidefx/animation_node.cpp +++ b/engines/zvision/scripting/sidefx/animation_node.cpp @@ -39,8 +39,20 @@ AnimationNode::AnimationNode(ZVision *engine, uint32 controlKey, const Common::S _mask(mask), _animation(NULL) { - _animation = engine->loadAnimation(fileName); - _frmDelay = 1000.0 / _animation->getDuration().framerate(); + if (fileName.hasSuffix(".rlf")) { + // HACK: Read the frame delay directly + Common::File *tmp = engine->getSearchManager()->openFile(fileName); + if (tmp) { + tmp->seek(176, SEEK_SET); + _frmDelay = tmp->readUint32LE() / 10; + delete tmp; + } + + _animation = engine->loadAnimation(fileName); + } else { + _animation = engine->loadAnimation(fileName); + _frmDelay = Common::Rational(1000, _animation->getDuration().framerate()).toInt(); + } if (frate > 0) _frmDelay = 1000.0 / frate; -- cgit v1.2.3 From c93776e1e05bd5a683459831d61542c134d7b856 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 24 Dec 2014 13:55:49 +0200 Subject: ZVISION: Remove dead code --- engines/zvision/graphics/cursors/cursor.cpp | 29 ----------------------------- engines/zvision/graphics/cursors/cursor.h | 1 - 2 files changed, 30 deletions(-) (limited to 'engines') diff --git a/engines/zvision/graphics/cursors/cursor.cpp b/engines/zvision/graphics/cursors/cursor.cpp index 07323b45c4..515358fe59 100644 --- a/engines/zvision/graphics/cursors/cursor.cpp +++ b/engines/zvision/graphics/cursors/cursor.cpp @@ -36,35 +36,6 @@ ZorkCursor::ZorkCursor() _hotspotY(0) { } -ZorkCursor::ZorkCursor(const Common::String &fileName) - : _width(0), - _height(0), - _hotspotX(0), - _hotspotY(0) { - Common::File file; - if (!file.open(fileName)) - return; - - uint32 magic = file.readUint32BE(); - if (magic != MKTAG('Z', 'C', 'R', '1')) { - warning("%s is not a Zork Cursor file", fileName.c_str()); - return; - } - - _hotspotX = file.readUint16LE(); - _hotspotY = file.readUint16LE(); - _width = file.readUint16LE(); - _height = file.readUint16LE(); - - uint dataSize = _width * _height * sizeof(uint16); - _surface.create(_width, _height, Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0)); - uint32 bytesRead = file.read(_surface.getPixels(), dataSize); - assert(bytesRead == dataSize); - - // Convert to RGB 565 - _surface.convertToInPlace(Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0)); -} - ZorkCursor::ZorkCursor(ZVision *engine, const Common::String &fileName) : _width(0), _height(0), diff --git a/engines/zvision/graphics/cursors/cursor.h b/engines/zvision/graphics/cursors/cursor.h index 0c1e99411f..6e0083520a 100644 --- a/engines/zvision/graphics/cursors/cursor.h +++ b/engines/zvision/graphics/cursors/cursor.h @@ -39,7 +39,6 @@ namespace ZVision { class ZorkCursor { public: ZorkCursor(); - ZorkCursor(const Common::String &fileName); ZorkCursor(ZVision *engine, const Common::String &fileName); ZorkCursor(const ZorkCursor &other); ~ZorkCursor(); -- cgit v1.2.3 From 702adaf9f807f19cd8849af737168461169734d3 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 24 Dec 2014 14:04:56 +0200 Subject: ZVISION: Remove duplicate code --- engines/zvision/graphics/render_manager.cpp | 91 +---------------------------- 1 file changed, 1 insertion(+), 90 deletions(-) (limited to 'engines') diff --git a/engines/zvision/graphics/render_manager.cpp b/engines/zvision/graphics/render_manager.cpp index b9305f5dcc..2f0d2a3a2c 100644 --- a/engines/zvision/graphics/render_manager.cpp +++ b/engines/zvision/graphics/render_manager.cpp @@ -162,97 +162,8 @@ void RenderManager::renderImageToBackground(const Common::String &fileName, int1 } void RenderManager::readImageToSurface(const Common::String &fileName, Graphics::Surface &destination) { - Common::File file; - - if (!_engine->getSearchManager()->openFile(file, fileName)) { - warning("Could not open file %s", fileName.c_str()); - return; - } - - // Read the magic number - // Some files are true TGA, while others are TGZ - uint32 fileType = file.readUint32BE(); - - uint32 imageWidth; - uint32 imageHeight; - Image::TGADecoder tga; - uint16 *buffer; bool isTransposed = _renderTable.getRenderState() == RenderTable::PANORAMA; - // All ZVision images are in RGB 555 - Graphics::PixelFormat pixelFormat555 = Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0); - destination.format = pixelFormat555; - - bool isTGZ; - - // Check for TGZ files - if (fileType == MKTAG('T', 'G', 'Z', '\0')) { - isTGZ = true; - - // TGZ files have a header and then Bitmap data that is compressed with LZSS - uint32 decompressedSize = file.readSint32LE(); - imageWidth = file.readSint32LE(); - imageHeight = file.readSint32LE(); - - LzssReadStream lzssStream(&file); - buffer = (uint16 *)(new uint16[decompressedSize]); - lzssStream.read(buffer, decompressedSize); - } else { - isTGZ = false; - - // Reset the cursor - file.seek(0); - - // Decode - if (!tga.loadStream(file)) { - warning("Error while reading TGA image"); - return; - } - - Graphics::Surface tgaSurface = *(tga.getSurface()); - imageWidth = tgaSurface.w; - imageHeight = tgaSurface.h; - - buffer = (uint16 *)tgaSurface.getPixels(); - } - - // Flip the width and height if transposed - if (isTransposed) { - uint16 temp = imageHeight; - imageHeight = imageWidth; - imageWidth = temp; - } - - // If the destination internal buffer is the same size as what we're copying into it, - // there is no need to free() and re-create - if (imageWidth != destination.w || imageHeight != destination.h) { - destination.create(imageWidth, imageHeight, pixelFormat555); - } - - // If transposed, 'un-transpose' the data while copying it to the destination - // Otherwise, just do a simple copy - if (isTransposed) { - uint16 *dest = (uint16 *)destination.getPixels(); - - for (uint32 y = 0; y < imageHeight; ++y) { - uint32 columnIndex = y * imageWidth; - - for (uint32 x = 0; x < imageWidth; ++x) { - dest[columnIndex + x] = buffer[x * imageHeight + y]; - } - } - } else { - memcpy(destination.getPixels(), buffer, imageWidth * imageHeight * _pixelFormat.bytesPerPixel); - } - - // Cleanup - if (isTGZ) { - delete[] buffer; - } else { - tga.destroy(); - } - - // Convert in place to RGB 565 from RGB 555 - destination.convertToInPlace(_pixelFormat); + readImageToSurface(fileName, destination, isTransposed); } void RenderManager::readImageToSurface(const Common::String &fileName, Graphics::Surface &destination, bool transposed) { -- cgit v1.2.3 From 59cd015fc90fcbb92c365ae33fe767cdf7ae863f Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Wed, 24 Dec 2014 10:36:55 -0500 Subject: SCI: Silence a gcc warning --- engines/sci/graphics/screen.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'engines') diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp index 8b0e76332f..2f95bf7751 100644 --- a/engines/sci/graphics/screen.cpp +++ b/engines/sci/graphics/screen.cpp @@ -238,6 +238,8 @@ GfxScreen::GfxScreen(ResourceManager *resMan) : _resMan(resMan) { _vectorPutPixelPtr = &GfxScreen::putPixelDisplayUpscaled; _putPixelPtr = &GfxScreen::putPixelDisplayUpscaled; break; + case GFX_SCREEN_UPSCALED_DISABLED: + break; } } -- cgit v1.2.3 From 970116bc3821b38c9b4882178c6a34082e73698d Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Wed, 24 Dec 2014 20:15:57 +0100 Subject: SCI: added LSL3/German 5 1/4" floppy version --- engines/sci/detection_tables.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'engines') diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h index d6bdef946b..7c9f54aedf 100644 --- a/engines/sci/detection_tables.h +++ b/engines/sci/detection_tables.h @@ -2069,6 +2069,20 @@ static const struct ADGameDescription SciGameDescriptions[] = { AD_LISTEND}, Common::DE_DEU, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Larry 3 - German DOS (German+English, 5 1/4" floppies) + // SCI interpreter version S.old.124 (executable), VERSION is "1.056" + {"lsl3", "", { + {"resource.map", 0, "2468da5d664bb6ca3df866074a05e43c", 8910}, + {"resource.001", 0, "3827a9b17b926e12dcc336860f50612a", 163326}, + {"resource.002", 0, "3827a9b17b926e12dcc336860f50612a", 312436}, + {"resource.003", 0, "3827a9b17b926e12dcc336860f50612a", 347307}, + {"resource.004", 0, "3827a9b17b926e12dcc336860f50612a", 332369}, + {"resource.005", 0, "3827a9b17b926e12dcc336860f50612a", 347654}, + {"resource.006", 0, "3827a9b17b926e12dcc336860f50612a", 326011}, + {"resource.007", 0, "3827a9b17b926e12dcc336860f50612a", 309553}, + AD_LISTEND}, + Common::DE_DEU, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Larry 3 - French DOS (provided by richiefs in bug report #2670691, also includes english language) // Executable scanning reports "S.old.123" // SCI interpreter version 0.000.572 (just a guess) -- cgit v1.2.3 From 11d3227796a5d58a6e0f362e7982e27bf6d8fcd8 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Wed, 24 Dec 2014 20:20:39 +0100 Subject: SCI: fix typo in comment for LSL3/German --- engines/sci/detection_tables.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h index 7c9f54aedf..32d1a58765 100644 --- a/engines/sci/detection_tables.h +++ b/engines/sci/detection_tables.h @@ -2070,7 +2070,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { Common::DE_DEU, Common::kPlatformDOS, ADGF_ADDENGLISH, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Larry 3 - German DOS (German+English, 5 1/4" floppies) - // SCI interpreter version S.old.124 (executable), VERSION is "1.056" + // SCI interpreter version S.old.114 (executable), VERSION is "1.056" {"lsl3", "", { {"resource.map", 0, "2468da5d664bb6ca3df866074a05e43c", 8910}, {"resource.001", 0, "3827a9b17b926e12dcc336860f50612a", 163326}, -- cgit v1.2.3 From 16e208318cf75dbe290060663119d1c533f4dd7b Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 24 Dec 2014 22:07:42 +0200 Subject: ZVISION: Plug a memory leak --- engines/zvision/scripting/sidefx/animation_node.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines') diff --git a/engines/zvision/scripting/sidefx/animation_node.cpp b/engines/zvision/scripting/sidefx/animation_node.cpp index 1f62b61310..bf3509f545 100644 --- a/engines/zvision/scripting/sidefx/animation_node.cpp +++ b/engines/zvision/scripting/sidefx/animation_node.cpp @@ -161,6 +161,7 @@ bool AnimationNode::process(uint32 deltaTimeInMillis) { _engine->getRenderManager()->blitSurfaceToBkg(*transposed, nod->pos.left, nod->pos.top, _mask); else _engine->getRenderManager()->blitSurfaceToBkg(*transposed, nod->pos.left, nod->pos.top); + transposed->free(); delete transposed; } else { if (_mask > 0) -- cgit v1.2.3 From de2c9ed5bf9e3d41ad52de8aa0ddf383efa6b24d Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 24 Dec 2014 22:11:21 +0200 Subject: ZVISION: Disable unused code --- engines/zvision/graphics/render_manager.cpp | 2 ++ engines/zvision/graphics/render_manager.h | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/zvision/graphics/render_manager.cpp b/engines/zvision/graphics/render_manager.cpp index 2f0d2a3a2c..01df82410f 100644 --- a/engines/zvision/graphics/render_manager.cpp +++ b/engines/zvision/graphics/render_manager.cpp @@ -983,9 +983,11 @@ void RenderManager::markDirty() { _backgroundDirtyRect = Common::Rect(_backgroundWidth, _backgroundHeight); } +#if 0 void RenderManager::bkgFill(uint8 r, uint8 g, uint8 b) { _currentBackgroundImage.fillRect(Common::Rect(_currentBackgroundImage.w, _currentBackgroundImage.h), _currentBackgroundImage.format.RGBToColor(r, g, b)); markDirty(); } +#endif } // End of namespace ZVision diff --git a/engines/zvision/graphics/render_manager.h b/engines/zvision/graphics/render_manager.h index 711c607c7b..c2dc169945 100644 --- a/engines/zvision/graphics/render_manager.h +++ b/engines/zvision/graphics/render_manager.h @@ -328,8 +328,10 @@ public: // Mark whole background surface as dirty void markDirty(); - // Fille background surface by color +#if 0 + // Fill background surface by color void bkgFill(uint8 r, uint8 g, uint8 b); +#endif }; } // End of namespace ZVision -- cgit v1.2.3 From 1bc9b13357e36f6f52e3dd6f8223ab569e5b5362 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 24 Dec 2014 22:26:23 +0200 Subject: ZVISION: Introduce pixel formats for resources (555) and screen (565) --- engines/zvision/zvision.cpp | 8 +++++--- engines/zvision/zvision.h | 2 ++ 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/zvision/zvision.cpp b/engines/zvision/zvision.cpp index cf7ed288d7..145b2ebeac 100644 --- a/engines/zvision/zvision.cpp +++ b/engines/zvision/zvision.cpp @@ -82,6 +82,8 @@ ZVision::ZVision(OSystem *syst, const ZVisionGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc), _pixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0), /*RGB 565*/ + _resourcePixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0), /* RGB 555 */ + _screenPixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0), /* RGB 565 */ _desiredFrameTime(33), /* ~30 fps */ _clock(_system), _scriptManager(nullptr), @@ -182,17 +184,17 @@ void ZVision::initialize() { } else if (_gameDescription->gameId == GID_NEMESIS) _searchManager->loadZix("NEMESIS.ZIX"); - initGraphics(WINDOW_WIDTH, WINDOW_HEIGHT, true, &_pixelFormat); + initGraphics(WINDOW_WIDTH, WINDOW_HEIGHT, true, &_screenPixelFormat); // Register random source _rnd = new Common::RandomSource("zvision"); // Create managers _scriptManager = new ScriptManager(this); - _renderManager = new RenderManager(this, WINDOW_WIDTH, WINDOW_HEIGHT, _workingWindow, _pixelFormat); + _renderManager = new RenderManager(this, WINDOW_WIDTH, WINDOW_HEIGHT, _workingWindow, _screenPixelFormat); _saveManager = new SaveManager(this); _stringManager = new StringManager(this); - _cursorManager = new CursorManager(this, &_pixelFormat); + _cursorManager = new CursorManager(this, &_screenPixelFormat); _textRenderer = new TextRenderer(this); _midiManager = new MidiManager(); diff --git a/engines/zvision/zvision.h b/engines/zvision/zvision.h index 7ea10ed64d..a63b66f70f 100644 --- a/engines/zvision/zvision.h +++ b/engines/zvision/zvision.h @@ -69,6 +69,8 @@ public: */ Common::Rect _workingWindow; const Graphics::PixelFormat _pixelFormat; + const Graphics::PixelFormat _resourcePixelFormat; + const Graphics::PixelFormat _screenPixelFormat; private: enum { -- cgit v1.2.3 From 84341a889cfafc4c7ecef6cf7d6841df8353fe4b Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 24 Dec 2014 22:29:52 +0200 Subject: ZVISION: Let the cursor manager do pixel format conversion for cursors --- engines/zvision/graphics/cursors/cursor.cpp | 5 +---- engines/zvision/graphics/cursors/cursor_manager.cpp | 2 +- engines/zvision/graphics/cursors/cursor_manager.h | 4 ++-- engines/zvision/zvision.cpp | 2 +- 4 files changed, 5 insertions(+), 8 deletions(-) (limited to 'engines') diff --git a/engines/zvision/graphics/cursors/cursor.cpp b/engines/zvision/graphics/cursors/cursor.cpp index 515358fe59..eb25e92860 100644 --- a/engines/zvision/graphics/cursors/cursor.cpp +++ b/engines/zvision/graphics/cursors/cursor.cpp @@ -57,12 +57,9 @@ ZorkCursor::ZorkCursor(ZVision *engine, const Common::String &fileName) _height = file.readUint16LE(); uint dataSize = _width * _height * sizeof(uint16); - _surface.create(_width, _height, Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0)); + _surface.create(_width, _height, engine->_resourcePixelFormat); uint32 bytesRead = file.read(_surface.getPixels(), dataSize); assert(bytesRead == dataSize); - - // Convert to RGB 565 - _surface.convertToInPlace(Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0)); } ZorkCursor::ZorkCursor(const ZorkCursor &other) { diff --git a/engines/zvision/graphics/cursors/cursor_manager.cpp b/engines/zvision/graphics/cursors/cursor_manager.cpp index 92fd461c72..a197c7ed87 100644 --- a/engines/zvision/graphics/cursors/cursor_manager.cpp +++ b/engines/zvision/graphics/cursors/cursor_manager.cpp @@ -45,7 +45,7 @@ const char *CursorManager::_zNemCursorFileNames[NUM_CURSORS] = { "00act", "arrow "hright", "hup", "00idle", "left", "right", "ssurr", "stilt", "turn", "up" }; -CursorManager::CursorManager(ZVision *engine, const Graphics::PixelFormat *pixelFormat) +CursorManager::CursorManager(ZVision *engine, const Graphics::PixelFormat pixelFormat) : _engine(engine), _pixelFormat(pixelFormat), _cursorIsPushed(false), diff --git a/engines/zvision/graphics/cursors/cursor_manager.h b/engines/zvision/graphics/cursors/cursor_manager.h index bbfa085c23..35c605baf8 100644 --- a/engines/zvision/graphics/cursors/cursor_manager.h +++ b/engines/zvision/graphics/cursors/cursor_manager.h @@ -58,7 +58,7 @@ enum CursorIndex { */ class CursorManager { public: - CursorManager(ZVision *engine, const Graphics::PixelFormat *pixelFormat); + CursorManager(ZVision *engine, const Graphics::PixelFormat pixelFormat); private: static const int NUM_CURSORS = 18; @@ -67,7 +67,7 @@ private: ZorkCursor _cursors[NUM_CURSORS + 2][2]; ZVision *_engine; - const Graphics::PixelFormat *_pixelFormat; + const Graphics::PixelFormat _pixelFormat; bool _cursorIsPushed; int _item; int _lastitem; diff --git a/engines/zvision/zvision.cpp b/engines/zvision/zvision.cpp index 145b2ebeac..5978316451 100644 --- a/engines/zvision/zvision.cpp +++ b/engines/zvision/zvision.cpp @@ -194,7 +194,7 @@ void ZVision::initialize() { _renderManager = new RenderManager(this, WINDOW_WIDTH, WINDOW_HEIGHT, _workingWindow, _screenPixelFormat); _saveManager = new SaveManager(this); _stringManager = new StringManager(this); - _cursorManager = new CursorManager(this, &_screenPixelFormat); + _cursorManager = new CursorManager(this, _resourcePixelFormat); _textRenderer = new TextRenderer(this); _midiManager = new MidiManager(); -- cgit v1.2.3 From e8e21fabe4dbe4effdfb3df05fd3fae75940f1c5 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 24 Dec 2014 22:40:54 +0200 Subject: ZVISION: Set all the internal graphics operations to use RGB555 (1/2) This is the first part of the changes to make the engine use RGB555 internally again. This is done to simplify the rendering pipeline - the engine will use RGB555 internally, but will output to RGB565. The overall changes have been broken into two commits, thus this first commit will break all the game colors --- engines/zvision/graphics/effect.h | 2 +- engines/zvision/graphics/effects/fog.cpp | 10 ++++----- engines/zvision/graphics/effects/light.cpp | 4 ++-- engines/zvision/scripting/actions.cpp | 25 ++-------------------- .../zvision/scripting/controls/input_control.cpp | 2 +- .../zvision/scripting/controls/titler_control.cpp | 2 +- engines/zvision/scripting/sidefx/ttytext_node.cpp | 4 ++-- engines/zvision/text/text.cpp | 4 ++-- engines/zvision/text/truetype_font.cpp | 2 +- engines/zvision/video/rlf_decoder.cpp | 22 ++++--------------- engines/zvision/video/rlf_decoder.h | 2 +- engines/zvision/zvision.cpp | 2 +- 12 files changed, 23 insertions(+), 58 deletions(-) (limited to 'engines') diff --git a/engines/zvision/graphics/effect.h b/engines/zvision/graphics/effect.h index c6653c6037..234cd8209d 100644 --- a/engines/zvision/graphics/effect.h +++ b/engines/zvision/graphics/effect.h @@ -37,7 +37,7 @@ class Effect { public: Effect(ZVision *engine, uint32 key, Common::Rect region, bool ported) : _engine(engine), _key(key), _region(region), _ported(ported) { - _surface.create(_region.width(), _region.height(), _engine->_pixelFormat); + _surface.create(_region.width(), _region.height(), _engine->_resourcePixelFormat); } virtual ~Effect() {} diff --git a/engines/zvision/graphics/effects/fog.cpp b/engines/zvision/graphics/effects/fog.cpp index f59e82a4a0..c28bdde330 100644 --- a/engines/zvision/graphics/effects/fog.cpp +++ b/engines/zvision/graphics/effects/fog.cpp @@ -79,10 +79,10 @@ const Graphics::Surface *FogFx::draw(const Graphics::Surface &srcSubRect) { if (it->inEffect) { // Not 100% equivalent, but looks nice and not buggy uint8 sr, sg, sb; - _engine->_pixelFormat.colorToRGB(lineBuf[i], sr, sg, sb); + _engine->_resourcePixelFormat.colorToRGB(lineBuf[i], sr, sg, sb); uint16 fogColor = *(uint16 *)_fog.getBasePtr((i + _pos) % _fog.w, j); uint8 dr, dg, db; - _engine->_pixelFormat.colorToRGB(_colorMap[fogColor & 0x1F], dr, dg, db); + _engine->_resourcePixelFormat.colorToRGB(_colorMap[fogColor & 0x1F], dr, dg, db); uint16 fr = dr + sr; if (fr > 255) fr = 255; @@ -92,7 +92,7 @@ const Graphics::Surface *FogFx::draw(const Graphics::Surface &srcSubRect) { uint16 fb = db + sb; if (fb > 255) fb = 255; - lineBuf[i] = _engine->_pixelFormat.RGBToColor(fr, fg, fb); + lineBuf[i] = _engine->_resourcePixelFormat.RGBToColor(fr, fg, fb); } cnt++; if (cnt >= it->count) { @@ -138,14 +138,14 @@ void FogFx::update() { // Not 100% equivalent, but looks nice and not buggy - _colorMap[31] = _engine->_pixelFormat.RGBToColor(_r << 3, _g << 3, _b << 3); + _colorMap[31] = _engine->_resourcePixelFormat.RGBToColor(_r << 3, _g << 3, _b << 3); for (uint8 i = 0; i < 31; i++) { float perc = (float)i / 31.0; uint8 cr = (float)_r * perc; uint8 cg = (float)_g * perc; uint8 cb = (float)_b * perc; - _colorMap[i] = _engine->_pixelFormat.RGBToColor(cr << 3, cg << 3, cb << 3); + _colorMap[i] = _engine->_resourcePixelFormat.RGBToColor(cr << 3, cg << 3, cb << 3); } } diff --git a/engines/zvision/graphics/effects/light.cpp b/engines/zvision/graphics/effects/light.cpp index 00b3811d65..bf6513292f 100644 --- a/engines/zvision/graphics/effects/light.cpp +++ b/engines/zvision/graphics/effects/light.cpp @@ -59,10 +59,10 @@ const Graphics::Surface *LightFx::draw(const Graphics::Surface &srcSubRect) { if (_pos < 0) { uint8 cc = ((-_pos) & 0x1F) << 3; - dcolor = _engine->_pixelFormat.RGBToColor(cc, cc, cc); + dcolor = _engine->_resourcePixelFormat.RGBToColor(cc, cc, cc); } else { uint8 cc = (_pos & 0x1F) << 3; - dcolor = _engine->_pixelFormat.RGBToColor(cc, cc, cc); + dcolor = _engine->_resourcePixelFormat.RGBToColor(cc, cc, cc); } for (uint16 j = 0; j < _surface.h; j++) { diff --git a/engines/zvision/scripting/actions.cpp b/engines/zvision/scripting/actions.cpp index 5af847c61a..1b6e1e2fdc 100644 --- a/engines/zvision/scripting/actions.cpp +++ b/engines/zvision/scripting/actions.cpp @@ -580,12 +580,6 @@ ActionPreloadAnimation::ActionPreloadAnimation(ZVision *engine, int32 slotkey, c // The two %*u are usually 0 and dont seem to have a use sscanf(line.c_str(), "%24s %*u %*u %d %d", fileName, &_mask, &_framerate); - if (_mask > 0) { - byte r, g, b; - Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0).colorToRGB(_mask, r, g, b); - _mask = _engine->_pixelFormat.RGBToColor(r, g, b); - } - _fileName = Common::String(fileName); } @@ -648,12 +642,6 @@ ActionPlayAnimation::ActionPlayAnimation(ZVision *engine, int32 slotkey, const C "%24s %u %u %u %u %u %u %d %*u %*u %d %d", fileName, &_x, &_y, &_x2, &_y2, &_start, &_end, &_loopCount, &_mask, &_framerate); - if (_mask > 0) { - byte r, g, b; - Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0).colorToRGB(_mask, r, g, b); - _mask = _engine->_pixelFormat.RGBToColor(r, g, b); - } - _fileName = Common::String(fileName); } @@ -861,21 +849,12 @@ ActionSetPartialScreen::ActionSetPartialScreen(ZVision *engine, int32 slotkey, c _y = 0; char fileName[25]; - int color; - sscanf(line.c_str(), "%u %u %24s %*u %d", &_x, &_y, fileName, &color); + sscanf(line.c_str(), "%u %u %24s %*u %d", &_x, &_y, fileName, &_backgroundColor); _fileName = Common::String(fileName); - if (color >= 0) { - byte r, g, b; - Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0).colorToRGB(color, r, g, b); - _backgroundColor = _engine->_pixelFormat.RGBToColor(r, g, b); - } else { - _backgroundColor = color; - } - - if (color > 65535) { + if (_backgroundColor > 65535) { warning("Background color for ActionSetPartialScreen is bigger than a uint16"); } } diff --git a/engines/zvision/scripting/controls/input_control.cpp b/engines/zvision/scripting/controls/input_control.cpp index d7734f6d7a..e1e6e6ec9d 100644 --- a/engines/zvision/scripting/controls/input_control.cpp +++ b/engines/zvision/scripting/controls/input_control.cpp @@ -199,7 +199,7 @@ bool InputControl::process(uint32 deltaTimeInMillis) { // Blit the text using the RenderManager Graphics::Surface txt; - txt.create(_textRectangle.width(), _textRectangle.height(), _engine->_pixelFormat); + txt.create(_textRectangle.width(), _textRectangle.height(), _engine->_resourcePixelFormat); if (!_readOnly || !_focused) _txtWidth = _engine->getTextRenderer()->drawTxt(_currentInputText, _stringInit, txt); diff --git a/engines/zvision/scripting/controls/titler_control.cpp b/engines/zvision/scripting/controls/titler_control.cpp index 10ba0af655..d6b1d34bae 100644 --- a/engines/zvision/scripting/controls/titler_control.cpp +++ b/engines/zvision/scripting/controls/titler_control.cpp @@ -67,7 +67,7 @@ TitlerControl::TitlerControl(ZVision *engine, uint32 key, Common::SeekableReadSt if (!_rectangle.isEmpty()) { _surface = new Graphics::Surface; - _surface->create(_rectangle.width(), _rectangle.height(), _engine->_pixelFormat); + _surface->create(_rectangle.width(), _rectangle.height(), _engine->_resourcePixelFormat); _surface->fillRect(Common::Rect(_surface->w, _surface->h), 0); } } diff --git a/engines/zvision/scripting/sidefx/ttytext_node.cpp b/engines/zvision/scripting/sidefx/ttytext_node.cpp index 2930118524..66a27e96c5 100644 --- a/engines/zvision/scripting/sidefx/ttytext_node.cpp +++ b/engines/zvision/scripting/sidefx/ttytext_node.cpp @@ -56,7 +56,7 @@ ttyTextNode::ttyTextNode(ZVision *engine, uint32 key, const Common::String &file delete infile; } - _img.create(_r.width(), _r.height(), _engine->_pixelFormat); + _img.create(_r.width(), _r.height(), _engine->_resourcePixelFormat); _style._sharp = true; _style.readAllStyle(_txtbuf); _style.setFont(_fnt); @@ -158,7 +158,7 @@ void ttyTextNode::newline() { } void ttyTextNode::outchar(uint16 chr) { - uint32 clr = _engine->_pixelFormat.RGBToColor(_style._red, _style._green, _style._blue); + uint32 clr = _engine->_resourcePixelFormat.RGBToColor(_style._red, _style._green, _style._blue); if (_dx + _fnt.getCharWidth(chr) > _r.width()) newline(); diff --git a/engines/zvision/text/text.cpp b/engines/zvision/text/text.cpp index 8ddba3fbab..f28ba6ade3 100644 --- a/engines/zvision/text/text.cpp +++ b/engines/zvision/text/text.cpp @@ -298,7 +298,7 @@ void cTxtStyle::setFont(StyledTTFont &font) { Graphics::Surface *TextRenderer::render(StyledTTFont &fnt, const Common::String &txt, cTxtStyle &style) { style.setFontStyle(fnt); - uint32 clr = _engine->_pixelFormat.RGBToColor(style._red, style._green, style._blue); + uint32 clr = _engine->_resourcePixelFormat.RGBToColor(style._red, style._green, style._blue); return fnt.renderSolidText(txt, clr); } @@ -317,7 +317,7 @@ int32 TextRenderer::drawTxt(const Common::String &txt, cTxtStyle &fontStyle, Gra dst.fillRect(Common::Rect(dst.w, dst.h), 0); - uint32 clr = _engine->_pixelFormat.RGBToColor(fontStyle._red, fontStyle._green, fontStyle._blue); + uint32 clr = _engine->_resourcePixelFormat.RGBToColor(fontStyle._red, fontStyle._green, fontStyle._blue); int16 w; diff --git a/engines/zvision/text/truetype_font.cpp b/engines/zvision/text/truetype_font.cpp index f373afe437..f64c0ab3bc 100644 --- a/engines/zvision/text/truetype_font.cpp +++ b/engines/zvision/text/truetype_font.cpp @@ -218,7 +218,7 @@ Graphics::Surface *StyledTTFont::renderSolidText(const Common::String &str, uint if (_font) { int16 w = _font->getStringWidth(str); if (w && w < 1024) { - tmp->create(w, _font->getFontHeight(), _engine->_pixelFormat); + tmp->create(w, _font->getFontHeight(), _engine->_resourcePixelFormat); drawString(tmp, str, 0, 0, w, color); } } diff --git a/engines/zvision/video/rlf_decoder.cpp b/engines/zvision/video/rlf_decoder.cpp index f1ac10bf88..260f912ade 100644 --- a/engines/zvision/video/rlf_decoder.cpp +++ b/engines/zvision/video/rlf_decoder.cpp @@ -64,7 +64,7 @@ RLFDecoder::RLFVideoTrack::RLFVideoTrack(Common::SeekableReadStream *stream) return; } - _currentFrameBuffer.create(_width, _height, Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0)); + _currentFrameBuffer.create(_width, _height, getPixelFormat()); _frameBufferByteSize = _width * _height * sizeof(uint16); _frames = new Frame[_frameCount]; @@ -239,12 +239,7 @@ void RLFDecoder::RLFVideoTrack::decodeMaskedRunLengthEncoding(int8 *source, int8 return; } - byte r, g, b; - // NOTE: Color masks can't be used here, since accurate colors - // are required to handle transparency correctly - Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0).colorToRGB(READ_LE_UINT16(source + sourceOffset), r, g, b); - uint16 destColor = Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0).RGBToColor(r, g, b); - WRITE_UINT16(dest + destOffset, destColor); + WRITE_UINT16(dest + destOffset, READ_LE_UINT16(source + sourceOffset)); sourceOffset += 2; destOffset += 2; @@ -288,12 +283,7 @@ void RLFDecoder::RLFVideoTrack::decodeSimpleRunLengthEncoding(int8 *source, int8 return; } - byte r, g, b; - // NOTE: Color masks can't be used here, since accurate colors - // are required to handle transparency correctly - Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0).colorToRGB(READ_LE_UINT16(source + sourceOffset), r, g, b); - uint16 destColor = Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0).RGBToColor(r, g, b); - WRITE_UINT16(dest + destOffset, destColor); + WRITE_UINT16(dest + destOffset, READ_LE_UINT16(source + sourceOffset)); sourceOffset += 2; destOffset += 2; @@ -307,11 +297,7 @@ void RLFDecoder::RLFVideoTrack::decodeSimpleRunLengthEncoding(int8 *source, int8 return; } - byte r, g, b; - // NOTE: Color masks can't be used here, since accurate colors - // are required to handle transparency correctly - Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0).colorToRGB(READ_LE_UINT16(source + sourceOffset), r, g, b); - uint16 sampleColor = Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0).RGBToColor(r, g, b); + uint16 sampleColor = READ_LE_UINT16(source + sourceOffset); sourceOffset += 2; numberOfCopy = numberOfSamples + 2; diff --git a/engines/zvision/video/rlf_decoder.h b/engines/zvision/video/rlf_decoder.h index f0f31c2128..d56ff2da92 100644 --- a/engines/zvision/video/rlf_decoder.h +++ b/engines/zvision/video/rlf_decoder.h @@ -45,7 +45,7 @@ private: uint16 getWidth() const { return _width; } uint16 getHeight() const { return _height; } - Graphics::PixelFormat getPixelFormat() const { return Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0); /*RGB 565*/ } + Graphics::PixelFormat getPixelFormat() const { return Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0); /* RGB 555 */ } int getCurFrame() const { return _curFrame; } int getFrameCount() const { return _frameCount; } const Graphics::Surface *decodeNextFrame(); diff --git a/engines/zvision/zvision.cpp b/engines/zvision/zvision.cpp index 5978316451..b865ae9e6e 100644 --- a/engines/zvision/zvision.cpp +++ b/engines/zvision/zvision.cpp @@ -191,7 +191,7 @@ void ZVision::initialize() { // Create managers _scriptManager = new ScriptManager(this); - _renderManager = new RenderManager(this, WINDOW_WIDTH, WINDOW_HEIGHT, _workingWindow, _screenPixelFormat); + _renderManager = new RenderManager(this, WINDOW_WIDTH, WINDOW_HEIGHT, _workingWindow, _resourcePixelFormat); _saveManager = new SaveManager(this); _stringManager = new StringManager(this); _cursorManager = new CursorManager(this, _resourcePixelFormat); -- cgit v1.2.3 From 5f8418394b925adfc62ee6d180515157190a8cd9 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 24 Dec 2014 22:54:24 +0200 Subject: ZVISION: Set all the internal graphics operations to use RGB555 (2/2) This is the second part of the changes to make the engine use RGB555 internally again. This is done to simplify the rendering pipeline - the engine will use RGB555 internally, but will output to RGB565. The overall changes have been broken into two commits, with this commit finishing all the changes. This is needed, as the game uses RGB555 graphics internally, but its AVI animations (full screen and in-game) use RGB565 --- .../zvision/graphics/cursors/cursor_manager.cpp | 2 +- engines/zvision/graphics/render_manager.cpp | 111 +++++++++++++-------- engines/zvision/graphics/render_manager.h | 2 + engines/zvision/video/video.cpp | 3 +- engines/zvision/zvision.cpp | 1 - engines/zvision/zvision.h | 1 - 6 files changed, 72 insertions(+), 48 deletions(-) (limited to 'engines') diff --git a/engines/zvision/graphics/cursors/cursor_manager.cpp b/engines/zvision/graphics/cursors/cursor_manager.cpp index a197c7ed87..c364426bad 100644 --- a/engines/zvision/graphics/cursors/cursor_manager.cpp +++ b/engines/zvision/graphics/cursors/cursor_manager.cpp @@ -106,7 +106,7 @@ void CursorManager::initialize() { } void CursorManager::changeCursor(const ZorkCursor &cursor) { - CursorMan.replaceCursor(cursor.getSurface(), cursor.getWidth(), cursor.getHeight(), cursor.getHotspotX(), cursor.getHotspotY(), cursor.getKeyColor(), false, _pixelFormat); + CursorMan.replaceCursor(cursor.getSurface(), cursor.getWidth(), cursor.getHeight(), cursor.getHotspotX(), cursor.getHotspotY(), cursor.getKeyColor(), false, &_pixelFormat); } void CursorManager::cursorDown(bool pushed) { diff --git a/engines/zvision/graphics/render_manager.cpp b/engines/zvision/graphics/render_manager.cpp index 01df82410f..07ed6d2e2b 100644 --- a/engines/zvision/graphics/render_manager.cpp +++ b/engines/zvision/graphics/render_manager.cpp @@ -127,14 +127,29 @@ void RenderManager::renderSceneToScreen() { } if (!outWndDirtyRect.isEmpty()) { - _system->copyRectToScreen(out->getBasePtr(outWndDirtyRect.left, outWndDirtyRect.top), out->pitch, - outWndDirtyRect.left + _workingWindow.left, - outWndDirtyRect.top + _workingWindow.top, - outWndDirtyRect.width(), - outWndDirtyRect.height()); + Common::Rect rect( + outWndDirtyRect.left + _workingWindow.left, + outWndDirtyRect.top + _workingWindow.top, + outWndDirtyRect.left + _workingWindow.left + outWndDirtyRect.width(), + outWndDirtyRect.top + _workingWindow.top + outWndDirtyRect.height() + ); + copyToScreen(*out, rect, outWndDirtyRect.left, outWndDirtyRect.top); } } +void RenderManager::copyToScreen(const Graphics::Surface &surface, Common::Rect &rect, int16 srcLeft, int16 srcTop) { + // Convert the surface to RGB565, if needed + Graphics::Surface *outSurface = surface.convertTo(_engine->_screenPixelFormat); + _system->copyRectToScreen(outSurface->getBasePtr(srcLeft, srcTop), + outSurface->pitch, + rect.left, + rect.top, + rect.width(), + rect.height()); + outSurface->free(); + delete outSurface; +} + void RenderManager::renderImageToBackground(const Common::String &fileName, int16 destX, int16 destY) { Graphics::Surface surface; readImageToSurface(fileName, surface); @@ -183,8 +198,7 @@ void RenderManager::readImageToSurface(const Common::String &fileName, Graphics: Image::TGADecoder tga; uint16 *buffer; // All ZVision images are in RGB 555 - Graphics::PixelFormat pixelFormat555 = Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0); - destination.format = pixelFormat555; + destination.format = _engine->_resourcePixelFormat; bool isTGZ; @@ -229,7 +243,7 @@ void RenderManager::readImageToSurface(const Common::String &fileName, Graphics: // If the destination internal buffer is the same size as what we're copying into it, // there is no need to free() and re-create if (imageWidth != destination.w || imageHeight != destination.h) { - destination.create(imageWidth, imageHeight, pixelFormat555); + destination.create(imageWidth, imageHeight, _engine->_resourcePixelFormat); } // If transposed, 'un-transpose' the data while copying it to the destination @@ -245,7 +259,7 @@ void RenderManager::readImageToSurface(const Common::String &fileName, Graphics: } } } else { - memcpy(destination.getPixels(), buffer, imageWidth * imageHeight * _pixelFormat.bytesPerPixel); + memcpy(destination.getPixels(), buffer, imageWidth * imageHeight * destination.format.bytesPerPixel); } // Cleanup @@ -254,9 +268,6 @@ void RenderManager::readImageToSurface(const Common::String &fileName, Graphics: } else { tga.destroy(); } - - // Convert in place to RGB 565 from RGB 555 - destination.convertToInPlace(_pixelFormat); } const Common::Point RenderManager::screenSpaceToImageSpace(const Common::Point &point) { @@ -370,10 +381,6 @@ void RenderManager::scaleBuffer(const void *src, void *dst, uint32 srcWidth, uin } void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, const Common::Rect &_srcRect , Graphics::Surface &dst, int _x, int _y) { - - if (src.format != dst.format) - return; - Common::Rect srcRect = _srcRect; if (srcRect.isEmpty()) srcRect = Common::Rect(src.w, src.h); @@ -384,8 +391,10 @@ void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, const Com if (srcRect.isEmpty() || !srcRect.isValidRect()) return; + Graphics::Surface *srcAdapted = src.convertTo(dst.format); + // Copy srcRect from src surface to dst surface - const byte *srcBuffer = (const byte *)src.getBasePtr(srcRect.left, srcRect.top); + const byte *srcBuffer = (const byte *)srcAdapted->getBasePtr(srcRect.left, srcRect.top); int xx = _x; int yy = _y; @@ -395,8 +404,11 @@ void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, const Com if (yy < 0) yy = 0; - if (_x >= dst.w || _y >= dst.h) + if (_x >= dst.w || _y >= dst.h) { + srcAdapted->free(); + delete srcAdapted; return; + } byte *dstBuffer = (byte *)dst.getBasePtr(xx, yy); @@ -404,17 +416,16 @@ void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, const Com int32 h = srcRect.height(); for (int32 y = 0; y < h; y++) { - memcpy(dstBuffer, srcBuffer, w * src.format.bytesPerPixel); - srcBuffer += src.pitch; + memcpy(dstBuffer, srcBuffer, w * srcAdapted->format.bytesPerPixel); + srcBuffer += srcAdapted->pitch; dstBuffer += dst.pitch; } + + srcAdapted->free(); + delete srcAdapted; } void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, const Common::Rect &_srcRect , Graphics::Surface &dst, int _x, int _y, uint32 colorkey) { - - if (src.format != dst.format) - return; - Common::Rect srcRect = _srcRect; if (srcRect.isEmpty()) srcRect = Common::Rect(src.w, src.h); @@ -425,10 +436,11 @@ void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, const Com if (srcRect.isEmpty() || !srcRect.isValidRect()) return; - uint32 _keycolor = colorkey & ((1 << (src.format.bytesPerPixel << 3)) - 1); + Graphics::Surface *srcAdapted = src.convertTo(dst.format); + uint32 keycolor = colorkey & ((1 << (src.format.bytesPerPixel << 3)) - 1); // Copy srcRect from src surface to dst surface - const byte *srcBuffer = (const byte *)src.getBasePtr(srcRect.left, srcRect.top); + const byte *srcBuffer = (const byte *)srcAdapted->getBasePtr(srcRect.left, srcRect.top); int xx = _x; int yy = _y; @@ -438,8 +450,11 @@ void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, const Com if (yy < 0) yy = 0; - if (_x >= dst.w || _y >= dst.h) + if (_x >= dst.w || _y >= dst.h) { + srcAdapted->free(); + delete srcAdapted; return; + } byte *dstBuffer = (byte *)dst.getBasePtr(xx, yy); @@ -447,12 +462,12 @@ void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, const Com int32 h = srcRect.height(); for (int32 y = 0; y < h; y++) { - switch (src.format.bytesPerPixel) { + switch (srcAdapted->format.bytesPerPixel) { case 1: { const uint *srcTemp = (const uint *)srcBuffer; uint *dstTemp = (uint *)dstBuffer; for (int32 x = 0; x < w; x++) { - if (*srcTemp != _keycolor) + if (*srcTemp != keycolor) *dstTemp = *srcTemp; srcTemp++; dstTemp++; @@ -464,7 +479,7 @@ void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, const Com const uint16 *srcTemp = (const uint16 *)srcBuffer; uint16 *dstTemp = (uint16 *)dstBuffer; for (int32 x = 0; x < w; x++) { - if (*srcTemp != _keycolor) + if (*srcTemp != keycolor) *dstTemp = *srcTemp; srcTemp++; dstTemp++; @@ -476,7 +491,7 @@ void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, const Com const uint32 *srcTemp = (const uint32 *)srcBuffer; uint32 *dstTemp = (uint32 *)dstBuffer; for (int32 x = 0; x < w; x++) { - if (*srcTemp != _keycolor) + if (*srcTemp != keycolor) *dstTemp = *srcTemp; srcTemp++; dstTemp++; @@ -487,9 +502,12 @@ void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, const Com default: break; } - srcBuffer += src.pitch; + srcBuffer += srcAdapted->pitch; dstBuffer += dst.pitch; } + + srcAdapted->free(); + delete srcAdapted; } void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, Graphics::Surface &dst, int x, int y) { @@ -699,12 +717,15 @@ void RenderManager::clearMenuSurface(const Common::Rect &r) { void RenderManager::renderMenuToScreen() { if (!_menuSurfaceDirtyRect.isEmpty()) { _menuSurfaceDirtyRect.clip(Common::Rect(_menuSurface.w, _menuSurface.h)); - if (!_menuSurfaceDirtyRect.isEmpty()) - _system->copyRectToScreen(_menuSurface.getBasePtr(_menuSurfaceDirtyRect.left, _menuSurfaceDirtyRect.top), _menuSurface.pitch, - _menuSurfaceDirtyRect.left + _menuArea.left, - _menuSurfaceDirtyRect.top + _menuArea.top, - _menuSurfaceDirtyRect.width(), - _menuSurfaceDirtyRect.height()); + if (!_menuSurfaceDirtyRect.isEmpty()) { + Common::Rect rect( + _menuSurfaceDirtyRect.left + _menuArea.left, + _menuSurfaceDirtyRect.top + _menuArea.top, + _menuSurfaceDirtyRect.left + _menuArea.left + _menuSurfaceDirtyRect.width(), + _menuSurfaceDirtyRect.top + _menuArea.top + _menuSurfaceDirtyRect.height() + ); + copyToScreen(_menuSurface, rect, _menuSurfaceDirtyRect.left, _menuSurfaceDirtyRect.top); + } _menuSurfaceDirtyRect = Common::Rect(); } } @@ -779,7 +800,7 @@ void RenderManager::processSubs(uint16 deltatime) { OneSubtitle *sub = &it->_value; if (sub->txt.size()) { Graphics::Surface *rndr = new Graphics::Surface(); - rndr->create(sub->r.width(), sub->r.height(), _pixelFormat); + rndr->create(sub->r.width(), sub->r.height(), _engine->_resourcePixelFormat); _engine->getTextRenderer()->drawTxtInOneLine(sub->txt, *rndr); blitSurfaceToSurface(*rndr, _subtitleSurface, sub->r.left - _subtitleArea.left + _workingWindow.left, sub->r.top - _subtitleArea.top + _workingWindow.top); rndr->free(); @@ -788,11 +809,13 @@ void RenderManager::processSubs(uint16 deltatime) { sub->redraw = false; } - _system->copyRectToScreen(_subtitleSurface.getPixels(), _subtitleSurface.pitch, - _subtitleArea.left, - _subtitleArea.top, - _subtitleSurface.w, - _subtitleSurface.h); + Common::Rect rect( + _subtitleArea.left, + _subtitleArea.top, + _subtitleArea.left + _subtitleSurface.w, + _subtitleArea.top + _subtitleSurface.h + ); + copyToScreen(_subtitleSurface, rect, 0, 0); } } diff --git a/engines/zvision/graphics/render_manager.h b/engines/zvision/graphics/render_manager.h index c2dc169945..d67ae29a3a 100644 --- a/engines/zvision/graphics/render_manager.h +++ b/engines/zvision/graphics/render_manager.h @@ -146,6 +146,8 @@ public: */ void renderSceneToScreen(); + void copyToScreen(const Graphics::Surface &surface, Common::Rect &rect, int16 srcLeft, int16 srcTop); + /** * Blits the image or a portion of the image to the background. * diff --git a/engines/zvision/video/video.cpp b/engines/zvision/video/video.cpp index 50a6fc136a..e67e6570c5 100644 --- a/engines/zvision/video/video.cpp +++ b/engines/zvision/video/video.cpp @@ -114,7 +114,8 @@ void ZVision::playVideo(Video::VideoDecoder &vid, const Common::Rect &destRect, _renderManager->scaleBuffer(frame->getPixels(), scaled->getPixels(), frame->w, frame->h, frame->format.bytesPerPixel, scaled->w, scaled->h); frame = scaled; } - _system->copyRectToScreen((const byte *)frame->getPixels(), frame->pitch, x, y, finalWidth, finalHeight); + Common::Rect rect = Common::Rect(x, y, x + finalWidth, y + finalHeight); + _renderManager->copyToScreen(*frame, rect, 0, 0); _renderManager->processSubs(0); } } diff --git a/engines/zvision/zvision.cpp b/engines/zvision/zvision.cpp index b865ae9e6e..db96884103 100644 --- a/engines/zvision/zvision.cpp +++ b/engines/zvision/zvision.cpp @@ -81,7 +81,6 @@ struct zvisionIniSettings { ZVision::ZVision(OSystem *syst, const ZVisionGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc), - _pixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0), /*RGB 565*/ _resourcePixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0), /* RGB 555 */ _screenPixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0), /* RGB 565 */ _desiredFrameTime(33), /* ~30 fps */ diff --git a/engines/zvision/zvision.h b/engines/zvision/zvision.h index a63b66f70f..e9b8ca4547 100644 --- a/engines/zvision/zvision.h +++ b/engines/zvision/zvision.h @@ -68,7 +68,6 @@ public: * edges of this Rectangle */ Common::Rect _workingWindow; - const Graphics::PixelFormat _pixelFormat; const Graphics::PixelFormat _resourcePixelFormat; const Graphics::PixelFormat _screenPixelFormat; -- cgit v1.2.3 From 75d78c71cc2190ae4afa655d27cdbc35a748f901 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 24 Dec 2014 23:18:01 +0200 Subject: ZVISION: Plug another memory leak. Some cleanup --- engines/zvision/scripting/sidefx/animation_node.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/zvision/scripting/sidefx/animation_node.cpp b/engines/zvision/scripting/sidefx/animation_node.cpp index bf3509f545..dec70e2642 100644 --- a/engines/zvision/scripting/sidefx/animation_node.cpp +++ b/engines/zvision/scripting/sidefx/animation_node.cpp @@ -44,7 +44,7 @@ AnimationNode::AnimationNode(ZVision *engine, uint32 controlKey, const Common::S Common::File *tmp = engine->getSearchManager()->openFile(fileName); if (tmp) { tmp->seek(176, SEEK_SET); - _frmDelay = tmp->readUint32LE() / 10; + _frmDelay = Common::Rational(tmp->readUint32LE(), 10).toInt(); delete tmp; } @@ -73,8 +73,10 @@ AnimationNode::~AnimationNode() { if (it != _playList.end()) { _engine->getScriptManager()->setStateValue((*it).slot, 2); - if ((*it)._scaled) + if ((*it)._scaled) { + (*it)._scaled->free(); delete(*it)._scaled; + } } _playList.clear(); @@ -109,8 +111,10 @@ bool AnimationNode::process(uint32 deltaTimeInMillis) { if (nod->loop == 0) { if (nod->slot >= 0) _engine->getScriptManager()->setStateValue(nod->slot, 2); - if (nod->_scaled) + if (nod->_scaled) { + nod->_scaled->free(); delete nod->_scaled; + } _playList.erase(it); return _DisposeAfterUse; } @@ -142,6 +146,7 @@ bool AnimationNode::process(uint32 deltaTimeInMillis) { if (frame->w > dstw || frame->h > dsth || (frame->w == dstw / 2 && frame->h == dsth / 2)) { if (nod->_scaled) if (nod->_scaled->w != dstw || nod->_scaled->h != dsth) { + nod->_scaled->free(); delete nod->_scaled; nod->_scaled = NULL; } @@ -197,8 +202,10 @@ bool AnimationNode::stop() { PlayNodes::iterator it = _playList.begin(); if (it != _playList.end()) { _engine->getScriptManager()->setStateValue((*it).slot, 2); - if ((*it)._scaled) + if ((*it)._scaled) { + (*it)._scaled->free(); delete(*it)._scaled; + } } _playList.clear(); -- cgit v1.2.3 From fa2d8d927b353162ac9ee434b4611e03b22246e8 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 24 Dec 2014 23:27:03 +0200 Subject: ZVISION: Plug more memory leaks --- engines/zvision/scripting/controls/paint_control.cpp | 12 +++++++++--- engines/zvision/scripting/controls/titler_control.cpp | 4 +++- 2 files changed, 12 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/zvision/scripting/controls/paint_control.cpp b/engines/zvision/scripting/controls/paint_control.cpp index df06bb814e..62dde3d170 100644 --- a/engines/zvision/scripting/controls/paint_control.cpp +++ b/engines/zvision/scripting/controls/paint_control.cpp @@ -114,12 +114,18 @@ PaintControl::PaintControl(ZVision *engine, uint32 key, Common::SeekableReadStre PaintControl::~PaintControl() { // Clear the state value back to 0 //_engine->getScriptManager()->setStateValue(_key, 0); - if (_paint) + if (_paint) { + _paint->free(); delete _paint; - if (_brush) + } + if (_brush) { + _brush->free(); delete _brush; - if (_bkg) + } + if (_bkg) { + _bkg->free(); delete _bkg; + } } bool PaintControl::onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) { diff --git a/engines/zvision/scripting/controls/titler_control.cpp b/engines/zvision/scripting/controls/titler_control.cpp index d6b1d34bae..542e0a0b67 100644 --- a/engines/zvision/scripting/controls/titler_control.cpp +++ b/engines/zvision/scripting/controls/titler_control.cpp @@ -73,8 +73,10 @@ TitlerControl::TitlerControl(ZVision *engine, uint32 key, Common::SeekableReadSt } TitlerControl::~TitlerControl() { - if (_surface) + if (_surface) { + _surface->free(); delete _surface; + } } void TitlerControl::setString(int strLine) { -- cgit v1.2.3 From 381b7592a49e5d022159b5684dbba32eceaa6657 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Thu, 25 Dec 2014 00:31:17 +0100 Subject: SCI: actor file format, add debug code kPortrait --- engines/sci/graphics/portrait.cpp | 51 +++++++++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 7 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/portrait.cpp b/engines/sci/graphics/portrait.cpp index 668de616fb..959c0f6817 100644 --- a/engines/sci/graphics/portrait.cpp +++ b/engines/sci/graphics/portrait.cpp @@ -57,13 +57,39 @@ void Portrait::init() { // 4 bytes paletteSize (base 1) // -> 17 bytes // paletteSize bytes paletteData - // 14 bytes bitmap header - // -> 4 bytes unknown - // -> 2 bytes height - // -> 2 bytes width - // -> 6 bytes unknown - // height * width bitmap data - // another animation count times bitmap header and data + // + // bitmap-data follows, total of [animation count] + // 14 bytes bitmap header + // -> 4 bytes unknown + // -> 2 bytes height + // -> 2 bytes width + // -> 6 bytes unknown + // height * width bitmap data + // + // 4 bytes offset table size (may be larger than the actual known entries?!) + // 14 bytes all zeroes (dummy entry?!) + // + // 14 bytes for each entry + // -> 2 bytes displace X + // -> 2 bytes displace Y + // -> 2 bytes height (again) + // -> 2 bytes width (again) + // -> 6 bytes unknown (normally 01 00 00 00 00 00 for delta bitmaps, 00 00 00 00 00 00 for first bitmap) + // random data may be used as filler + // + // 4 bytes lip sync id table size (is [lip sync id count] * 4, should be 0x2E0 for all actors) + // 4 bytes per lip sync id + // -> 1 byte length of ID + // -> 3 bytes actual ID + // + // 4 bytes lip sync id data table size (seems to be the same for all actors, always 0x220 in size) + // 1 byte animation number or 0xFF as terminator + // 1 byte delay, if last byte was not terminator + // one array for every lip sync id + // + // 4 bytes appended, seem to be random + // 9E11120E for alex + // 9E9E9E9E for vizier int32 fileSize = 0; Common::SeekableReadStream *file = SearchMan.createReadStreamForMember("actors/" + _resourceName + ".bin"); @@ -202,6 +228,7 @@ void Portrait::doit(Common::Point position, uint16 resourceId, uint16 noun, uint if (raveResource->size < 4000) { memcpy(debugPrint, raveResource->data, raveResource->size); debugPrint[raveResource->size] = 0; // set terminating NUL + debug("kPortrait: using actor %s", _resourceName.c_str()); debug("kPortrait (noun %d, verb %d, cond %d, seq %d)", noun, verb, cond, seq); debug("kPortrait: %s", debugPrint); } @@ -273,6 +300,10 @@ void Portrait::doit(Common::Point position, uint16 resourceId, uint16 noun, uint raveLipSyncData = NULL; } +#ifdef DEBUG_PORTRAIT + debug("kPortrait: %d: %x", raveTicks, raveID); +#endif + timerPosition += raveTicks; // Wait till syncTime passed, then show specific animation bitmap @@ -294,6 +325,9 @@ void Portrait::doit(Common::Point position, uint16 resourceId, uint16 noun, uint // Tick = 0xFF is the terminator for the data timerPositionWithin = timerPosition; raveLipSyncTicks = *raveLipSyncData++; +#ifdef DEBUG_PORTRAIT + debug("kPortrait: waiting %d", raveLipSyncTicks); +#endif while ( (raveLipSyncData < _lipSyncDataOffsetTableEnd) && (raveLipSyncTicks != 0xFF) ) { timerPositionWithin += raveLipSyncTicks; @@ -308,6 +342,9 @@ void Portrait::doit(Common::Point position, uint16 resourceId, uint16 noun, uint } while ((curPosition != -1) && (curPosition < timerPositionWithin) && (!userAbort)); raveLipSyncBitmapNr = *raveLipSyncData++; +#ifdef DEBUG_PORTRAIT + debug("kPortrait: showing bitmap %d", raveLipSyncBitmapNr); +#endif // bitmap nr within sync data is base 1, we need base 0 raveLipSyncBitmapNr--; -- cgit v1.2.3 From 319323c668003b284d51b84ec95a64ba7c072450 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 25 Dec 2014 15:00:49 +0200 Subject: ZVISION: Document some of the ActionRegion effects --- engines/zvision/graphics/effects/fog.h | 1 + engines/zvision/scripting/actions.cpp | 2 +- engines/zvision/scripting/scr_file_handling.cpp | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/zvision/graphics/effects/fog.h b/engines/zvision/graphics/effects/fog.h index 45d6f9596d..fe88707bbe 100644 --- a/engines/zvision/graphics/effects/fog.h +++ b/engines/zvision/graphics/effects/fog.h @@ -29,6 +29,7 @@ namespace ZVision { class ZVision; +// Used by Zork: Nemesis for the mixing chamber gas effect in the gas puzzle (location tt5e, when the blinds are down) class FogFx : public Effect { public: diff --git a/engines/zvision/scripting/actions.cpp b/engines/zvision/scripting/actions.cpp index 1b6e1e2fdc..89b311e81c 100644 --- a/engines/zvision/scripting/actions.cpp +++ b/engines/zvision/scripting/actions.cpp @@ -704,7 +704,7 @@ bool ActionQuit::execute() { } ////////////////////////////////////////////////////////////////////////////// -// ActionRegion +// ActionRegion - only used by Zork: Nemesis ////////////////////////////////////////////////////////////////////////////// ActionRegion::ActionRegion(ZVision *engine, int32 slotkey, const Common::String &line) : diff --git a/engines/zvision/scripting/scr_file_handling.cpp b/engines/zvision/scripting/scr_file_handling.cpp index 47b8b0aa39..cca492d649 100644 --- a/engines/zvision/scripting/scr_file_handling.cpp +++ b/engines/zvision/scripting/scr_file_handling.cpp @@ -264,6 +264,7 @@ void ScriptManager::parseResults(Common::SeekableReadStream &stream, Common::Lis } else if (act.matchString("random", true)) { actionList.push_back(new ActionRandom(_engine, slot, args)); } else if (act.matchString("region", true)) { + // Only used by Zork: Nemesis actionList.push_back(new ActionRegion(_engine, slot, args)); } else if (act.matchString("restore_game", true)) { actionList.push_back(new ActionRestoreGame(_engine, slot, args)); -- cgit v1.2.3 From 5535cb02fc8dfaf2c77911c223c912f5b07bdb63 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 25 Dec 2014 15:14:59 +0200 Subject: ZVISION: Resolve some TODOs --- engines/zvision/scripting/actions.h | 2 +- engines/zvision/scripting/scr_file_handling.cpp | 1 + engines/zvision/scripting/script_manager.h | 3 +-- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/zvision/scripting/actions.h b/engines/zvision/scripting/actions.h index 292e25e19c..3501372c7f 100644 --- a/engines/zvision/scripting/actions.h +++ b/engines/zvision/scripting/actions.h @@ -338,7 +338,7 @@ private: uint16 _unk2; }; -// TODO: See if this exists in ZGI. It doesn't in ZNem +// Only used by ZGI (locations cd6e, cd6k, dg2f, dg4e, dv1j) class ActionUnloadAnimation : public ResultAction { public: ActionUnloadAnimation(ZVision *engine, int32 slotkey, const Common::String &line); diff --git a/engines/zvision/scripting/scr_file_handling.cpp b/engines/zvision/scripting/scr_file_handling.cpp index cca492d649..83be3b5ad4 100644 --- a/engines/zvision/scripting/scr_file_handling.cpp +++ b/engines/zvision/scripting/scr_file_handling.cpp @@ -216,6 +216,7 @@ void ScriptManager::parseResults(Common::SeekableReadStream &stream, Common::Lis } else if (act.matchString("animpreload", true)) { actionList.push_back(new ActionPreloadAnimation(_engine, slot, args)); } else if (act.matchString("animunload", true)) { + // Only used by ZGI (locations cd6e, cd6k, dg2f, dg4e, dv1j) actionList.push_back(new ActionUnloadAnimation(_engine, slot, args)); } else if (act.matchString("attenuate", true)) { actionList.push_back(new ActionAttenuate(_engine, slot, args)); diff --git a/engines/zvision/scripting/script_manager.h b/engines/zvision/scripting/script_manager.h index 1e308faf0d..c5ade08e14 100644 --- a/engines/zvision/scripting/script_manager.h +++ b/engines/zvision/scripting/script_manager.h @@ -282,7 +282,7 @@ public: void inventoryDrop(int16 item); void inventoryCycle(); - // TODO: Make this private. It was only made public so Console::cmdParseAllScrFiles() could use it +private: /** * Parses a script file into triggers and events * @@ -291,7 +291,6 @@ public: */ void parseScrFile(const Common::String &fileName, ScriptScope &scope); -private: /** * Parses the stream into a Puzzle object * Helper method for parseScrFile. -- cgit v1.2.3 From 36c851d0e47b18205ac7ac91eb33666e4abe95ca Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 25 Dec 2014 16:22:36 +0200 Subject: ZVISION: Fix frame rate for RLF videos and remove hack in AnimationNode _frameTime refers to msec, not ticks --- engines/zvision/scripting/sidefx/animation_node.cpp | 16 ++++------------ engines/zvision/video/rlf_decoder.h | 2 +- 2 files changed, 5 insertions(+), 13 deletions(-) (limited to 'engines') diff --git a/engines/zvision/scripting/sidefx/animation_node.cpp b/engines/zvision/scripting/sidefx/animation_node.cpp index dec70e2642..97c6eeeab5 100644 --- a/engines/zvision/scripting/sidefx/animation_node.cpp +++ b/engines/zvision/scripting/sidefx/animation_node.cpp @@ -39,20 +39,12 @@ AnimationNode::AnimationNode(ZVision *engine, uint32 controlKey, const Common::S _mask(mask), _animation(NULL) { - if (fileName.hasSuffix(".rlf")) { - // HACK: Read the frame delay directly - Common::File *tmp = engine->getSearchManager()->openFile(fileName); - if (tmp) { - tmp->seek(176, SEEK_SET); - _frmDelay = Common::Rational(tmp->readUint32LE(), 10).toInt(); - delete tmp; - } + _animation = engine->loadAnimation(fileName); - _animation = engine->loadAnimation(fileName); - } else { - _animation = engine->loadAnimation(fileName); + if (fileName.hasSuffix(".rlf")) + _frmDelay = _animation->getTimeToNextFrame(); + else _frmDelay = Common::Rational(1000, _animation->getDuration().framerate()).toInt(); - } if (frate > 0) _frmDelay = 1000.0 / frate; diff --git a/engines/zvision/video/rlf_decoder.h b/engines/zvision/video/rlf_decoder.h index d56ff2da92..740f3fdd43 100644 --- a/engines/zvision/video/rlf_decoder.h +++ b/engines/zvision/video/rlf_decoder.h @@ -53,7 +53,7 @@ private: bool seek(const Audio::Timestamp &time); protected: - Common::Rational getFrameRate() const { return Common::Rational(60, _frameTime); } + Common::Rational getFrameRate() const { return Common::Rational(1000, _frameTime); } private: enum EncodingType { -- cgit v1.2.3 From 06fbca1e8109bdd3d1fdf72fc1056cbf658659e5 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 25 Dec 2014 20:10:24 +0200 Subject: ZVISION: Remove dead code --- engines/zvision/scripting/sidefx/animation_node.cpp | 4 ---- engines/zvision/scripting/sidefx/animation_node.h | 2 -- 2 files changed, 6 deletions(-) (limited to 'engines') diff --git a/engines/zvision/scripting/sidefx/animation_node.cpp b/engines/zvision/scripting/sidefx/animation_node.cpp index 97c6eeeab5..b966aa9cb8 100644 --- a/engines/zvision/scripting/sidefx/animation_node.cpp +++ b/engines/zvision/scripting/sidefx/animation_node.cpp @@ -206,8 +206,4 @@ bool AnimationNode::stop() { return false; } -int32 AnimationNode::getFrameDelay() { - return _frmDelay; -} - } // End of namespace ZVision diff --git a/engines/zvision/scripting/sidefx/animation_node.h b/engines/zvision/scripting/sidefx/animation_node.h index 74941aa764..368f0291fd 100644 --- a/engines/zvision/scripting/sidefx/animation_node.h +++ b/engines/zvision/scripting/sidefx/animation_node.h @@ -72,8 +72,6 @@ public: void addPlayNode(int32 slot, int x, int y, int x2, int y2, int startFrame, int endFrame, int loops = 1); bool stop(); - - int32 getFrameDelay(); }; } // End of namespace ZVision -- cgit v1.2.3 From dbbcf641874ace35b871226664370413de176c37 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 25 Dec 2014 21:17:47 +0200 Subject: ZVISION: Use the search manager to open files in console commands --- engines/zvision/core/console.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/zvision/core/console.cpp b/engines/zvision/core/console.cpp index 07d3114ec8..c7592c8d9d 100644 --- a/engines/zvision/core/console.cpp +++ b/engines/zvision/core/console.cpp @@ -79,12 +79,14 @@ bool Console::cmdLoadSound(int argc, const char **argv) { Audio::AudioStream *soundStream = makeRawZorkStream(argv[1], _engine); Audio::SoundHandle handle; _engine->_mixer->playStream(Audio::Mixer::kPlainSoundType, &handle, soundStream, -1, 100, 0, DisposeAfterUse::YES, false, false); - } else if (argc == 4) { int isStereo = atoi(argv[3]); Common::File *file = new Common::File(); - file->open(argv[1]); + if (!_engine->getSearchManager()->openFile(*file, argv[1])) { + warning("File not found: %s", argv[1]); + return true; + } Audio::AudioStream *soundStream = makeRawZorkStream(file, atoi(argv[2]), isStereo == 0 ? false : true); Audio::SoundHandle handle; @@ -104,8 +106,10 @@ bool Console::cmdRawToWav(int argc, const char **argv) { } Common::File file; - if (!file.open(argv[1])) + if (!_engine->getSearchManager()->openFile(file, argv[1])) { + warning("File not found: %s", argv[1]); return true; + } Audio::AudioStream *audioStream = makeRawZorkStream(argv[1], _engine); -- cgit v1.2.3 From 11cf9b53ba138b5e069d7ffbd6af7f36b26a9add Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 25 Dec 2014 21:19:19 +0200 Subject: ZVISION: Remove dead code, and fix bad usage of assert() Since some compilers, like MSVC, strip out asserts in non-debug builds, it's a bad idea to perform active commands within assert() statements. In this particular case, the engine would attempt to open a file in an assert statement --- engines/zvision/sound/zork_raw.cpp | 11 ++--------- engines/zvision/sound/zork_raw.h | 14 -------------- 2 files changed, 2 insertions(+), 23 deletions(-) (limited to 'engines') diff --git a/engines/zvision/sound/zork_raw.cpp b/engines/zvision/sound/zork_raw.cpp index b2c88b34df..6d1980b1af 100644 --- a/engines/zvision/sound/zork_raw.cpp +++ b/engines/zvision/sound/zork_raw.cpp @@ -213,7 +213,6 @@ RawZorkStream::RawZorkStream(uint32 rate, bool stereo, DisposeAfterUse::Flag dis } int RawZorkStream::readBuffer(int16 *buffer, const int numSamples) { - int32 bytesRead = _streamReader.readBuffer(buffer, _stream.get(), numSamples); if (_stream->eos()) @@ -241,16 +240,10 @@ Audio::RewindableAudioStream *makeRawZorkStream(Common::SeekableReadStream *stre return new RawZorkStream(rate, stereo, disposeAfterUse, stream); } -Audio::RewindableAudioStream *makeRawZorkStream(const byte *buffer, uint32 size, - int rate, - bool stereo, - DisposeAfterUse::Flag disposeAfterUse) { - return makeRawZorkStream(new Common::MemoryReadStream(buffer, size, disposeAfterUse), rate, stereo, DisposeAfterUse::YES); -} - Audio::RewindableAudioStream *makeRawZorkStream(const Common::String &filePath, ZVision *engine) { Common::File *file = new Common::File(); - assert(engine->getSearchManager()->openFile(*file, filePath)); + if (!engine->getSearchManager()->openFile(*file, filePath)) + error("File not found: %s", filePath.c_str()); // Get the file name Common::StringTokenizer tokenizer(filePath, "/\\"); diff --git a/engines/zvision/sound/zork_raw.h b/engines/zvision/sound/zork_raw.h index 0b408d818c..892bad4d5f 100644 --- a/engines/zvision/sound/zork_raw.h +++ b/engines/zvision/sound/zork_raw.h @@ -122,20 +122,6 @@ public: bool rewind(); }; -/** - * Creates an audio stream, which plays from the given buffer. - * - * @param buffer Buffer to play from. - * @param size Size of the buffer in bytes. - * @param rate Rate of the sound data. - * @param dispose AfterUse Whether to free the buffer after use (with free!). - * @return The new SeekableAudioStream (or 0 on failure). - */ -Audio::RewindableAudioStream *makeRawZorkStream(const byte *buffer, uint32 size, - int rate, - bool stereo, - DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES); - /** * Creates an audio stream, which plays from the given stream. * -- cgit v1.2.3 From 6c451c9cf481dcaa6261c34773b79689386ded42 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 25 Dec 2014 21:48:59 +0200 Subject: ZVISION: Document where MIDI commands are used --- engines/zvision/scripting/actions.cpp | 4 +++- engines/zvision/scripting/sidefx/music_node.h | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/zvision/scripting/actions.cpp b/engines/zvision/scripting/actions.cpp index 89b311e81c..be2079736e 100644 --- a/engines/zvision/scripting/actions.cpp +++ b/engines/zvision/scripting/actions.cpp @@ -477,7 +477,9 @@ ActionMusic::ActionMusic(ZVision *engine, int32 slotkey, const Common::String &l sscanf(line.c_str(), "%u %24s %u %u", &type, fileNameBuffer, &loop, &volume); - // type 4 are midi sound effect files + // Type 4 actions are MIDI commands, not files. These are only used by + // Zork: Nemesis, for the flute and piano puzzles (tj4e and ve6f, as well + // as vr) if (type == 4) { _midi = true; int note; diff --git a/engines/zvision/scripting/sidefx/music_node.h b/engines/zvision/scripting/sidefx/music_node.h index 8f4a46f3fc..3f1ca5cf7b 100644 --- a/engines/zvision/scripting/sidefx/music_node.h +++ b/engines/zvision/scripting/sidefx/music_node.h @@ -91,6 +91,7 @@ private: bool _loaded; }; +// Only used by Zork: Nemesis, for the flute and piano puzzles (tj4e and ve6f, as well as vr) class MusicMidiNode : public MusicNodeBASE { public: MusicMidiNode(ZVision *engine, uint32 key, int8 program, int8 note, int8 volume); -- cgit v1.2.3 From 6368a6ea91364f90bcb0d5d9d88826d856181a52 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 25 Dec 2014 22:00:55 +0200 Subject: ZVISION: Move the menu code together with the other scripting code --- engines/zvision/core/events.cpp | 2 +- engines/zvision/core/menu.cpp | 765 ------------------------------------- engines/zvision/core/menu.h | 125 ------ engines/zvision/module.mk | 2 +- engines/zvision/scripting/menu.cpp | 762 ++++++++++++++++++++++++++++++++++++ engines/zvision/scripting/menu.h | 125 ++++++ engines/zvision/zvision.cpp | 2 +- 7 files changed, 890 insertions(+), 893 deletions(-) delete mode 100644 engines/zvision/core/menu.cpp delete mode 100644 engines/zvision/core/menu.h create mode 100644 engines/zvision/scripting/menu.cpp create mode 100644 engines/zvision/scripting/menu.h (limited to 'engines') diff --git a/engines/zvision/core/events.cpp b/engines/zvision/core/events.cpp index 1920ffd769..89f1595460 100644 --- a/engines/zvision/core/events.cpp +++ b/engines/zvision/core/events.cpp @@ -28,7 +28,7 @@ #include "zvision/graphics/cursors/cursor_manager.h" #include "zvision/graphics/render_manager.h" #include "zvision/scripting/script_manager.h" -#include "zvision/core/menu.h" +#include "zvision/scripting/menu.h" #include "zvision/sound/zork_raw.h" #include "common/events.h" diff --git a/engines/zvision/core/menu.cpp b/engines/zvision/core/menu.cpp deleted file mode 100644 index 31e0d71370..0000000000 --- a/engines/zvision/core/menu.cpp +++ /dev/null @@ -1,765 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "common/scummsys.h" - -#include "zvision/core/menu.h" - -#include "zvision/graphics/render_manager.h" - -namespace ZVision { - -enum { - SLOT_START_SLOT = 151, - SLOT_SPELL_1 = 191, - SLOT_USER_CHOSE_THIS_SPELL = 205, - SLOT_REVERSED_SPELLBOOK = 206 -}; - -enum { - menu_MAIN_SAVE = 0, - menu_MAIN_REST = 1, - menu_MAIN_PREF = 2, - menu_MAIN_EXIT = 3 -}; - -MenuHandler::MenuHandler(ZVision *engine) { - _engine = engine; - menuBarFlag = 0xFFFF; -} - -MenuZGI::MenuZGI(ZVision *engine) : - MenuHandler(engine) { - menuMouseFocus = -1; - inmenu = false; - scrolled[0] = false; - scrolled[1] = false; - scrolled[2] = false; - scrollPos[0] = 0.0; - scrollPos[1] = 0.0; - scrollPos[2] = 0.0; - mouseOnItem = -1; - redraw = false; - clean = false; - - char buf[24]; - for (int i = 1; i < 4; i++) { - sprintf(buf, "gmzau%2.2x1.tga", i); - _engine->getRenderManager()->readImageToSurface(buf, menuback[i - 1][0], false); - sprintf(buf, "gmzau%2.2x1.tga", i + 0x10); - _engine->getRenderManager()->readImageToSurface(buf, menuback[i - 1][1], false); - } - for (int i = 0; i < 4; i++) { - sprintf(buf, "gmzmu%2.2x1.tga", i); - _engine->getRenderManager()->readImageToSurface(buf, menubar[i][0], false); - sprintf(buf, "gmznu%2.2x1.tga", i); - _engine->getRenderManager()->readImageToSurface(buf, menubar[i][1], false); - } - - for (int i = 0; i < 50; i++) { - items[i][0] = NULL; - items[i][1] = NULL; - itemId[i] = 0; - } - - for (int i = 0; i < 12; i++) { - magic[i][0] = NULL; - magic[i][1] = NULL; - magicId[i] = 0; - } -} - -MenuZGI::~MenuZGI() { - for (int i = 0; i < 3; i++) { - menuback[i][0].free(); - menuback[i][1].free(); - } - for (int i = 0; i < 4; i++) { - menubar[i][0].free(); - menubar[i][1].free(); - } - for (int i = 0; i < 50; i++) { - if (items[i][0]) { - items[i][0]->free(); - delete items[i][0]; - } - if (items[i][1]) { - items[i][1]->free(); - delete items[i][1]; - } - } - for (int i = 0; i < 12; i++) { - if (magic[i][0]) { - magic[i][0]->free(); - delete magic[i][0]; - } - if (magic[i][1]) { - magic[i][1]->free(); - delete magic[i][1]; - } - } -} - -void MenuZGI::onMouseUp(const Common::Point &Pos) { - if (Pos.y < 40) { - switch (menuMouseFocus) { - case menu_ITEM: - if (menuBarFlag & menuBar_Items) { - int itemCount = _engine->getScriptManager()->getStateValue(StateKey_Inv_TotalSlots); - if (itemCount == 0) - itemCount = 20; - - for (int i = 0; i < itemCount; i++) { - int itemspace = (600 - 28) / itemCount; - - if (Common::Rect(scrollPos[menu_ITEM] + itemspace * i, 0, - scrollPos[menu_ITEM] + itemspace * i + 28, 32).contains(Pos)) { - int32 mouseItem = _engine->getScriptManager()->getStateValue(StateKey_InventoryItem); - if (mouseItem >= 0 && mouseItem < 0xE0) { - _engine->getScriptManager()->inventoryDrop(mouseItem); - _engine->getScriptManager()->inventoryAdd(_engine->getScriptManager()->getStateValue(SLOT_START_SLOT + i)); - _engine->getScriptManager()->setStateValue(SLOT_START_SLOT + i, mouseItem); - - redraw = true; - } - } - } - } - break; - - case menu_MAGIC: - if (menuBarFlag & menuBar_Magic) { - for (int i = 0; i < 12; i++) { - - uint itemnum = _engine->getScriptManager()->getStateValue(SLOT_SPELL_1 + i); - if (itemnum != 0) { - if (_engine->getScriptManager()->getStateValue(SLOT_REVERSED_SPELLBOOK) == 1) - itemnum = 0xEE + i; - else - itemnum = 0xE0 + i; - } - if (itemnum) - if (_engine->getScriptManager()->getStateValue(StateKey_InventoryItem) == 0 || _engine->getScriptManager()->getStateValue(StateKey_InventoryItem) >= 0xE0) - if (Common::Rect(668 + 47 * i - scrollPos[menu_MAGIC], 0, - 668 + 47 * i - scrollPos[menu_MAGIC] + 28, 32).contains(Pos)) - _engine->getScriptManager()->setStateValue(SLOT_USER_CHOSE_THIS_SPELL, itemnum); - } - - } - break; - - case menu_MAIN: - - // Exit - if (menuBarFlag & menuBar_Exit) - if (Common::Rect(320 + 135, - scrollPos[menu_MAIN], - 320 + 135 + 135, - scrollPos[menu_MAIN] + 32).contains(Pos)) { - _engine->ifQuit(); - } - - // Settings - if (menuBarFlag & menuBar_Settings) - if (Common::Rect(320 , - scrollPos[menu_MAIN], - 320 + 135, - scrollPos[menu_MAIN] + 32).contains(Pos)) { - _engine->getScriptManager()->changeLocation('g', 'j', 'p', 'e', 0); - } - - // Load - if (menuBarFlag & menuBar_Restore) - if (Common::Rect(320 - 135, - scrollPos[menu_MAIN], - 320, - scrollPos[menu_MAIN] + 32).contains(Pos)) { - _engine->getScriptManager()->changeLocation('g', 'j', 'r', 'e', 0); - } - - // Save - if (menuBarFlag & menuBar_Save) - if (Common::Rect(320 - 135 * 2, - scrollPos[menu_MAIN], - 320 - 135, - scrollPos[menu_MAIN] + 32).contains(Pos)) { - _engine->getScriptManager()->changeLocation('g', 'j', 's', 'e', 0); - } - break; - } - } -} - -void MenuZGI::onMouseMove(const Common::Point &Pos) { - if (Pos.y < 40) { - - if (!inmenu) - redraw = true; - inmenu = true; - switch (menuMouseFocus) { - case menu_ITEM: - if (menuBarFlag & menuBar_Items) { - int itemCount = _engine->getScriptManager()->getStateValue(StateKey_Inv_TotalSlots); - if (itemCount == 0) - itemCount = 20; - else if (itemCount > 50) - itemCount = 50; - - int lastItem = mouseOnItem; - - mouseOnItem = -1; - - for (int i = 0; i < itemCount; i++) { - int itemspace = (600 - 28) / itemCount; - - if (Common::Rect(scrollPos[menu_ITEM] + itemspace * i, 0, - scrollPos[menu_ITEM] + itemspace * i + 28, 32).contains(Pos)) { - mouseOnItem = i; - break; - } - } - - if (lastItem != mouseOnItem) - if (_engine->getScriptManager()->getStateValue(SLOT_START_SLOT + mouseOnItem) || - _engine->getScriptManager()->getStateValue(SLOT_START_SLOT + lastItem)) - redraw = true; - } - break; - - case menu_MAGIC: - if (menuBarFlag & menuBar_Magic) { - int lastItem = mouseOnItem; - mouseOnItem = -1; - for (int i = 0; i < 12; i++) { - if (Common::Rect(668 + 47 * i - scrollPos[menu_MAGIC], 0, - 668 + 47 * i - scrollPos[menu_MAGIC] + 28, 32).contains(Pos)) { - mouseOnItem = i; - break; - } - } - - if (lastItem != mouseOnItem) - if (_engine->getScriptManager()->getStateValue(SLOT_SPELL_1 + mouseOnItem) || - _engine->getScriptManager()->getStateValue(SLOT_SPELL_1 + lastItem)) - redraw = true; - - } - break; - - case menu_MAIN: { - int lastItem = mouseOnItem; - mouseOnItem = -1; - - // Exit - if (menuBarFlag & menuBar_Exit) - if (Common::Rect(320 + 135, - scrollPos[menu_MAIN], - 320 + 135 + 135, - scrollPos[menu_MAIN] + 32).contains(Pos)) { - mouseOnItem = menu_MAIN_EXIT; - } - - // Settings - if (menuBarFlag & menuBar_Settings) - if (Common::Rect(320 , - scrollPos[menu_MAIN], - 320 + 135, - scrollPos[menu_MAIN] + 32).contains(Pos)) { - mouseOnItem = menu_MAIN_PREF; - } - - // Load - if (menuBarFlag & menuBar_Restore) - if (Common::Rect(320 - 135, - scrollPos[menu_MAIN], - 320, - scrollPos[menu_MAIN] + 32).contains(Pos)) { - mouseOnItem = menu_MAIN_REST; - } - - // Save - if (menuBarFlag & menuBar_Save) - if (Common::Rect(320 - 135 * 2, - scrollPos[menu_MAIN], - 320 - 135, - scrollPos[menu_MAIN] + 32).contains(Pos)) { - mouseOnItem = menu_MAIN_SAVE; - } - - if (lastItem != mouseOnItem) - redraw = true; - } - break; - - default: - int cur_menu = menuMouseFocus; - if (Common::Rect(64, 0, 64 + 512, 8).contains(Pos)) { // Main - menuMouseFocus = menu_MAIN; - scrolled[menu_MAIN] = false; - scrollPos[menu_MAIN] = menuback[menu_MAIN][1].h - menuback[menu_MAIN][0].h; - _engine->getScriptManager()->setStateValue(StateKey_MenuState, 2); - } - - if (menuBarFlag & menuBar_Magic) - if (Common::Rect(640 - 28, 0, 640, 32).contains(Pos)) { // Magic - menuMouseFocus = menu_MAGIC; - scrolled[menu_MAGIC] = false; - scrollPos[menu_MAGIC] = 28; - _engine->getScriptManager()->setStateValue(StateKey_MenuState, 3); - } - - if (menuBarFlag & menuBar_Items) - if (Common::Rect(0, 0, 28, 32).contains(Pos)) { // Items - menuMouseFocus = menu_ITEM; - scrolled[menu_ITEM] = false; - scrollPos[menu_ITEM] = 28 - 600; - _engine->getScriptManager()->setStateValue(StateKey_MenuState, 1); - } - - if (cur_menu != menuMouseFocus) - clean = true; - - break; - } - } else { - if (inmenu) - clean = true; - inmenu = false; - if (_engine->getScriptManager()->getStateValue(StateKey_MenuState) != 0) - _engine->getScriptManager()->setStateValue(StateKey_MenuState, 0); - menuMouseFocus = -1; - } -} - -void MenuZGI::process(uint32 deltatime) { - if (clean) { - _engine->getRenderManager()->clearMenuSurface(); - clean = false; - } - switch (menuMouseFocus) { - case menu_ITEM: - if (menuBarFlag & menuBar_Items) - if (!scrolled[menu_ITEM]) { - redraw = true; - float scrl = 600.0 * (deltatime / 1000.0); - - if (scrl == 0) - scrl = 1.0; - - scrollPos [menu_ITEM] += scrl; - - if (scrollPos[menu_ITEM] >= 0) { - scrolled[menu_ITEM] = true; - scrollPos [menu_ITEM] = 0; - } - } - if (redraw) { - _engine->getRenderManager()->blitSurfaceToMenu(menuback[menu_ITEM][0], scrollPos[menu_ITEM], 0); - - int itemCount = _engine->getScriptManager()->getStateValue(StateKey_Inv_TotalSlots); - if (itemCount == 0) - itemCount = 20; - else if (itemCount > 50) - itemCount = 50; - - for (int i = 0; i < itemCount; i++) { - int itemspace = (600 - 28) / itemCount; - - bool inrect = false; - - if (mouseOnItem == i) - inrect = true; - - uint curItemId = _engine->getScriptManager()->getStateValue(SLOT_START_SLOT + i); - - if (curItemId != 0) { - if (itemId[i] != curItemId) { - char buf[16]; - sprintf(buf, "gmzwu%2.2x1.tga", curItemId); - items[i][0] = _engine->getRenderManager()->loadImage(buf, false); - sprintf(buf, "gmzxu%2.2x1.tga", curItemId); - items[i][1] = _engine->getRenderManager()->loadImage(buf, false); - itemId[i] = curItemId; - } - - if (inrect) - _engine->getRenderManager()->blitSurfaceToMenu(*items[i][1], scrollPos[menu_ITEM] + itemspace * i, 0, 0); - else - _engine->getRenderManager()->blitSurfaceToMenu(*items[i][0], scrollPos[menu_ITEM] + itemspace * i, 0, 0); - - } else { - if (items[i][0]) { - items[i][0]->free(); - delete items[i][0]; - items[i][0] = NULL; - } - if (items[i][1]) { - items[i][1]->free(); - delete items[i][1]; - items[i][1] = NULL; - } - itemId[i] = 0; - } - } - - redraw = false; - } - break; - - case menu_MAGIC: - if (menuBarFlag & menuBar_Magic) - if (!scrolled[menu_MAGIC]) { - redraw = true; - float scrl = 600.0 * (deltatime / 1000.0); - - if (scrl == 0) - scrl = 1.0; - - scrollPos [menu_MAGIC] += scrl; - - if (scrollPos[menu_MAGIC] >= 600) { - scrolled[menu_MAGIC] = true; - scrollPos [menu_MAGIC] = 600; - } - } - if (redraw) { - _engine->getRenderManager()->blitSurfaceToMenu(menuback[menu_MAGIC][0], 640 - scrollPos[menu_MAGIC], 0); - - for (int i = 0; i < 12; i++) { - bool inrect = false; - - if (mouseOnItem == i) - inrect = true; - - uint curItemId = _engine->getScriptManager()->getStateValue(SLOT_SPELL_1 + i); - if (curItemId) { - if (_engine->getScriptManager()->getStateValue(SLOT_REVERSED_SPELLBOOK) == 1) - curItemId = 0xEE + i; - else - curItemId = 0xE0 + i; - } - - if (curItemId != 0) { - if (itemId[i] != curItemId) { - char buf[16]; - sprintf(buf, "gmzwu%2.2x1.tga", curItemId); - magic[i][0] = _engine->getRenderManager()->loadImage(buf, false); - sprintf(buf, "gmzxu%2.2x1.tga", curItemId); - magic[i][1] = _engine->getRenderManager()->loadImage(buf, false); - magicId[i] = curItemId; - } - - if (inrect) - _engine->getRenderManager()->blitSurfaceToMenu(*magic[i][1], 668 + 47 * i - scrollPos[menu_MAGIC], 0, 0); - else - _engine->getRenderManager()->blitSurfaceToMenu(*magic[i][0], 668 + 47 * i - scrollPos[menu_MAGIC], 0, 0); - - } else { - if (magic[i][0]) { - magic[i][0]->free(); - delete magic[i][0]; - magic[i][0] = NULL; - } - if (magic[i][1]) { - magic[i][1]->free(); - delete magic[i][1]; - magic[i][1] = NULL; - } - magicId[i] = 0; - } - } - redraw = false; - } - break; - - case menu_MAIN: - if (!scrolled[menu_MAIN]) { - redraw = true; - float scrl = 32.0 * 2.0 * (deltatime / 1000.0); - - if (scrl == 0) - scrl = 1.0; - - scrollPos [menu_MAIN] += scrl; - - if (scrollPos[menu_MAIN] >= 0) { - scrolled[menu_MAIN] = true; - scrollPos [menu_MAIN] = 0; - } - } - if (redraw) { - _engine->getRenderManager()->blitSurfaceToMenu(menuback[menu_MAIN][0], 30, scrollPos[menu_MAIN]); - - if (menuBarFlag & menuBar_Exit) { - if (mouseOnItem == menu_MAIN_EXIT) - _engine->getRenderManager()->blitSurfaceToMenu(menubar[menu_MAIN_EXIT][1], 320 + 135, scrollPos[menu_MAIN]); - else - _engine->getRenderManager()->blitSurfaceToMenu(menubar[menu_MAIN_EXIT][0], 320 + 135, scrollPos[menu_MAIN]); - } - if (menuBarFlag & menuBar_Settings) { - if (mouseOnItem == menu_MAIN_PREF) - _engine->getRenderManager()->blitSurfaceToMenu(menubar[menu_MAIN_PREF][1], 320, scrollPos[menu_MAIN]); - else - _engine->getRenderManager()->blitSurfaceToMenu(menubar[menu_MAIN_PREF][0], 320, scrollPos[menu_MAIN]); - } - if (menuBarFlag & menuBar_Restore) { - if (mouseOnItem == menu_MAIN_REST) - _engine->getRenderManager()->blitSurfaceToMenu(menubar[menu_MAIN_REST][1], 320 - 135, scrollPos[menu_MAIN]); - else - _engine->getRenderManager()->blitSurfaceToMenu(menubar[menu_MAIN_REST][0], 320 - 135, scrollPos[menu_MAIN]); - } - if (menuBarFlag & menuBar_Save) { - if (mouseOnItem == menu_MAIN_SAVE) - _engine->getRenderManager()->blitSurfaceToMenu(menubar[menu_MAIN_SAVE][1], 320 - 135 * 2, scrollPos[menu_MAIN]); - else - _engine->getRenderManager()->blitSurfaceToMenu(menubar[menu_MAIN_SAVE][0], 320 - 135 * 2, scrollPos[menu_MAIN]); - } - redraw = false; - } - break; - default: - if (redraw) { - if (inmenu) { - _engine->getRenderManager()->blitSurfaceToMenu(menuback[menu_MAIN][1], 30, 0); - - if (menuBarFlag & menuBar_Items) - _engine->getRenderManager()->blitSurfaceToMenu(menuback[menu_ITEM][1], 0, 0); - - if (menuBarFlag & menuBar_Magic) - _engine->getRenderManager()->blitSurfaceToMenu(menuback[menu_MAGIC][1], 640 - 28, 0); - } - redraw = false; - } - break; - } -} - -MenuNemesis::MenuNemesis(ZVision *engine) : - MenuHandler(engine) { - inmenu = false; - scrolled = false; - scrollPos = 0.0; - mouseOnItem = -1; - redraw = false; - delay = 0; - - char buf[24]; - for (int i = 0; i < 4; i++) - for (int j = 0; j < 6; j++) { - sprintf(buf, "butfrm%d%d.tga", i + 1, j); - _engine->getRenderManager()->readImageToSurface(buf, but[i][j], false); - } - - _engine->getRenderManager()->readImageToSurface("bar.tga", menubar, false); - - frm = 0; -} - -MenuNemesis::~MenuNemesis() { - for (int i = 0; i < 4; i++) - for (int j = 0; j < 6; j++) - but[i][j].free(); - - menubar.free(); -} - -static const int16 buts[4][2] = { {120 , 64}, {144, 184}, {128, 328}, {120, 456} }; - -void MenuNemesis::onMouseUp(const Common::Point &Pos) { - if (Pos.y < 40) { - // Exit - if (menuBarFlag & menuBar_Exit) - if (Common::Rect(buts[3][1], - scrollPos, - buts[3][0] + buts[3][1], - scrollPos + 32).contains(Pos)) { - _engine->ifQuit(); - frm = 5; - redraw = true; - } - - // Settings - if (menuBarFlag & menuBar_Settings) - if (Common::Rect(buts[2][1], - scrollPos, - buts[2][0] + buts[2][1], - scrollPos + 32).contains(Pos)) { - _engine->getScriptManager()->changeLocation('g', 'j', 'p', 'e', 0); - frm = 5; - redraw = true; - } - - // Load - if (menuBarFlag & menuBar_Restore) - if (Common::Rect(buts[1][1], - scrollPos, - buts[1][0] + buts[1][1], - scrollPos + 32).contains(Pos)) { - _engine->getScriptManager()->changeLocation('g', 'j', 'r', 'e', 0); - frm = 5; - redraw = true; - } - - // Save - if (menuBarFlag & menuBar_Save) - if (Common::Rect(buts[0][1], - scrollPos, - buts[0][0] + buts[0][1], - scrollPos + 32).contains(Pos)) { - _engine->getScriptManager()->changeLocation('g', 'j', 's', 'e', 0); - frm = 5; - redraw = true; - } - } -} - -void MenuNemesis::onMouseMove(const Common::Point &Pos) { - if (Pos.y < 40) { - - inmenu = true; - - if (_engine->getScriptManager()->getStateValue(StateKey_MenuState) != 2) - _engine->getScriptManager()->setStateValue(StateKey_MenuState, 2); - - int lastItem = mouseOnItem; - mouseOnItem = -1; - - // Exit - if (menuBarFlag & menuBar_Exit) - if (Common::Rect(buts[3][1], - scrollPos, - buts[3][0] + buts[3][1], - scrollPos + 32).contains(Pos)) { - mouseOnItem = menu_MAIN_EXIT; - } - - // Settings - if (menuBarFlag & menuBar_Settings) - if (Common::Rect(buts[2][1], - scrollPos, - buts[2][0] + buts[2][1], - scrollPos + 32).contains(Pos)) { - mouseOnItem = menu_MAIN_PREF; - } - - // Load - if (menuBarFlag & menuBar_Restore) - if (Common::Rect(buts[1][1], - scrollPos, - buts[1][0] + buts[1][1], - scrollPos + 32).contains(Pos)) { - mouseOnItem = menu_MAIN_REST; - } - - // Save - if (menuBarFlag & menuBar_Save) - if (Common::Rect(buts[0][1], - scrollPos, - buts[0][0] + buts[0][1], - scrollPos + 32).contains(Pos)) { - mouseOnItem = menu_MAIN_SAVE; - } - - if (lastItem != mouseOnItem) { - redraw = true; - frm = 0; - delay = 200; - } - } else { - inmenu = false; - if (_engine->getScriptManager()->getStateValue(StateKey_MenuState) != 0) - _engine->getScriptManager()->setStateValue(StateKey_MenuState, 0); - mouseOnItem = -1; - } -} - -void MenuNemesis::process(uint32 deltatime) { - if (inmenu) { - if (!scrolled) { - float scrl = 32.0 * 2.0 * (deltatime / 1000.0); - - if (scrl == 0) - scrl = 1.0; - - scrollPos += scrl; - redraw = true; - } - - if (scrollPos >= 0) { - scrolled = true; - scrollPos = 0; - } - - if (mouseOnItem != -1) { - delay -= deltatime; - if (delay <= 0 && frm < 4) { - delay = 200; - frm++; - redraw = true; - } - } - - if (redraw) { - _engine->getRenderManager()->blitSurfaceToMenu(menubar, 64, scrollPos); - - if (menuBarFlag & menuBar_Exit) - if (mouseOnItem == menu_MAIN_EXIT) - _engine->getRenderManager()->blitSurfaceToMenu(but[3][frm], buts[3][1], scrollPos); - - if (menuBarFlag & menuBar_Settings) - if (mouseOnItem == menu_MAIN_PREF) - _engine->getRenderManager()->blitSurfaceToMenu(but[2][frm], buts[2][1], scrollPos); - - if (menuBarFlag & menuBar_Restore) - if (mouseOnItem == menu_MAIN_REST) - _engine->getRenderManager()->blitSurfaceToMenu(but[1][frm], buts[1][1], scrollPos); - - if (menuBarFlag & menuBar_Save) - if (mouseOnItem == menu_MAIN_SAVE) - _engine->getRenderManager()->blitSurfaceToMenu(but[0][frm], buts[0][1], scrollPos); - - redraw = false; - } - } else { - scrolled = false; - if (scrollPos > -32) { - float scrl = 32.0 * 2.0 * (deltatime / 1000.0); - - if (scrl == 0) - scrl = 1.0; - - Common::Rect cl(64, 32 + scrollPos - scrl, 64 + 512, 32 + scrollPos + 1); - _engine->getRenderManager()->clearMenuSurface(cl); - - scrollPos -= scrl; - redraw = true; - } else - scrollPos = -32; - - if (redraw) { - _engine->getRenderManager()->blitSurfaceToMenu(menubar, 64, scrollPos); - redraw = false; - } - } -} - -} // End of namespace ZVision diff --git a/engines/zvision/core/menu.h b/engines/zvision/core/menu.h deleted file mode 100644 index ebe0bb50ac..0000000000 --- a/engines/zvision/core/menu.h +++ /dev/null @@ -1,125 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#ifndef ZVISION_MENU_H -#define ZVISION_MENU_H - -#include "graphics/surface.h" -#include "common/rect.h" - -#include "zvision/zvision.h" -#include "zvision/scripting/script_manager.h" - -namespace ZVision { - -enum menuBar { - menuBar_Exit = 0x1, - menuBar_Settings = 0x2, - menuBar_Restore = 0x4, - menuBar_Save = 0x8, - menuBar_Items = 0x100, - menuBar_Magic = 0x200 -}; - -class MenuHandler { -public: - MenuHandler(ZVision *engine); - virtual ~MenuHandler() {}; - virtual void onMouseMove(const Common::Point &Pos) {}; - virtual void onMouseDown(const Common::Point &Pos) {}; - virtual void onMouseUp(const Common::Point &Pos) {}; - virtual void process(uint32 deltaTimeInMillis) {}; - - void setEnable(uint16 flags) { - menuBarFlag = flags; - } - uint16 getEnable() { - return menuBarFlag; - } -protected: - uint16 menuBarFlag; - ZVision *_engine; -}; - -class MenuZGI: public MenuHandler { -public: - MenuZGI(ZVision *engine); - ~MenuZGI(); - void onMouseMove(const Common::Point &Pos); - void onMouseUp(const Common::Point &Pos); - void process(uint32 deltaTimeInMillis); -private: - Graphics::Surface menuback[3][2]; - Graphics::Surface menubar[4][2]; - Graphics::Surface *items[50][2]; - uint itemId[50]; - - Graphics::Surface *magic[12][2]; - uint magicId[12]; - - int menuMouseFocus; - bool inmenu; - - int mouseOnItem; - - bool scrolled[3]; - int16 scrollPos[3]; - - enum { - menu_ITEM = 0, - menu_MAGIC = 1, - menu_MAIN = 2 - }; - - bool clean; - bool redraw; - -}; - -class MenuNemesis: public MenuHandler { -public: - MenuNemesis(ZVision *engine); - ~MenuNemesis(); - void onMouseMove(const Common::Point &Pos); - void onMouseUp(const Common::Point &Pos); - void process(uint32 deltaTimeInMillis); -private: - Graphics::Surface but[4][6]; - Graphics::Surface menubar; - - bool inmenu; - - int mouseOnItem; - - bool scrolled; - int16 scrollPos; - - bool redraw; - - int frm; - int16 delay; - -}; - -} - -#endif diff --git a/engines/zvision/module.mk b/engines/zvision/module.mk index 3ea31abe1b..6955d62534 100644 --- a/engines/zvision/module.mk +++ b/engines/zvision/module.mk @@ -4,7 +4,6 @@ MODULE_OBJS := \ core/console.o \ core/clock.o \ core/events.o \ - core/menu.o \ core/save_manager.o \ detection.o \ file/lzss_read_stream.o \ @@ -30,6 +29,7 @@ MODULE_OBJS := \ scripting/controls/slot_control.o \ scripting/controls/titler_control.o \ scripting/inventory.o \ + scripting/menu.o \ scripting/scr_file_handling.o \ scripting/script_manager.o \ scripting/sidefx/animation_node.o \ diff --git a/engines/zvision/scripting/menu.cpp b/engines/zvision/scripting/menu.cpp new file mode 100644 index 0000000000..fa5e24f39f --- /dev/null +++ b/engines/zvision/scripting/menu.cpp @@ -0,0 +1,762 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "zvision/graphics/render_manager.h" +#include "zvision/scripting/menu.h" + +namespace ZVision { + +enum { + SLOT_START_SLOT = 151, + SLOT_SPELL_1 = 191, + SLOT_USER_CHOSE_THIS_SPELL = 205, + SLOT_REVERSED_SPELLBOOK = 206 +}; + +enum { + menu_MAIN_SAVE = 0, + menu_MAIN_REST = 1, + menu_MAIN_PREF = 2, + menu_MAIN_EXIT = 3 +}; + +MenuHandler::MenuHandler(ZVision *engine) { + _engine = engine; + menuBarFlag = 0xFFFF; +} + +MenuZGI::MenuZGI(ZVision *engine) : + MenuHandler(engine) { + menuMouseFocus = -1; + inmenu = false; + scrolled[0] = false; + scrolled[1] = false; + scrolled[2] = false; + scrollPos[0] = 0.0; + scrollPos[1] = 0.0; + scrollPos[2] = 0.0; + mouseOnItem = -1; + redraw = false; + clean = false; + + char buf[24]; + for (int i = 1; i < 4; i++) { + sprintf(buf, "gmzau%2.2x1.tga", i); + _engine->getRenderManager()->readImageToSurface(buf, menuback[i - 1][0], false); + sprintf(buf, "gmzau%2.2x1.tga", i + 0x10); + _engine->getRenderManager()->readImageToSurface(buf, menuback[i - 1][1], false); + } + for (int i = 0; i < 4; i++) { + sprintf(buf, "gmzmu%2.2x1.tga", i); + _engine->getRenderManager()->readImageToSurface(buf, menubar[i][0], false); + sprintf(buf, "gmznu%2.2x1.tga", i); + _engine->getRenderManager()->readImageToSurface(buf, menubar[i][1], false); + } + + for (int i = 0; i < 50; i++) { + items[i][0] = NULL; + items[i][1] = NULL; + itemId[i] = 0; + } + + for (int i = 0; i < 12; i++) { + magic[i][0] = NULL; + magic[i][1] = NULL; + magicId[i] = 0; + } +} + +MenuZGI::~MenuZGI() { + for (int i = 0; i < 3; i++) { + menuback[i][0].free(); + menuback[i][1].free(); + } + for (int i = 0; i < 4; i++) { + menubar[i][0].free(); + menubar[i][1].free(); + } + for (int i = 0; i < 50; i++) { + if (items[i][0]) { + items[i][0]->free(); + delete items[i][0]; + } + if (items[i][1]) { + items[i][1]->free(); + delete items[i][1]; + } + } + for (int i = 0; i < 12; i++) { + if (magic[i][0]) { + magic[i][0]->free(); + delete magic[i][0]; + } + if (magic[i][1]) { + magic[i][1]->free(); + delete magic[i][1]; + } + } +} + +void MenuZGI::onMouseUp(const Common::Point &Pos) { + if (Pos.y < 40) { + switch (menuMouseFocus) { + case menu_ITEM: + if (menuBarFlag & menuBar_Items) { + int itemCount = _engine->getScriptManager()->getStateValue(StateKey_Inv_TotalSlots); + if (itemCount == 0) + itemCount = 20; + + for (int i = 0; i < itemCount; i++) { + int itemspace = (600 - 28) / itemCount; + + if (Common::Rect(scrollPos[menu_ITEM] + itemspace * i, 0, + scrollPos[menu_ITEM] + itemspace * i + 28, 32).contains(Pos)) { + int32 mouseItem = _engine->getScriptManager()->getStateValue(StateKey_InventoryItem); + if (mouseItem >= 0 && mouseItem < 0xE0) { + _engine->getScriptManager()->inventoryDrop(mouseItem); + _engine->getScriptManager()->inventoryAdd(_engine->getScriptManager()->getStateValue(SLOT_START_SLOT + i)); + _engine->getScriptManager()->setStateValue(SLOT_START_SLOT + i, mouseItem); + + redraw = true; + } + } + } + } + break; + + case menu_MAGIC: + if (menuBarFlag & menuBar_Magic) { + for (int i = 0; i < 12; i++) { + + uint itemnum = _engine->getScriptManager()->getStateValue(SLOT_SPELL_1 + i); + if (itemnum != 0) { + if (_engine->getScriptManager()->getStateValue(SLOT_REVERSED_SPELLBOOK) == 1) + itemnum = 0xEE + i; + else + itemnum = 0xE0 + i; + } + if (itemnum) + if (_engine->getScriptManager()->getStateValue(StateKey_InventoryItem) == 0 || _engine->getScriptManager()->getStateValue(StateKey_InventoryItem) >= 0xE0) + if (Common::Rect(668 + 47 * i - scrollPos[menu_MAGIC], 0, + 668 + 47 * i - scrollPos[menu_MAGIC] + 28, 32).contains(Pos)) + _engine->getScriptManager()->setStateValue(SLOT_USER_CHOSE_THIS_SPELL, itemnum); + } + + } + break; + + case menu_MAIN: + + // Exit + if (menuBarFlag & menuBar_Exit) + if (Common::Rect(320 + 135, + scrollPos[menu_MAIN], + 320 + 135 + 135, + scrollPos[menu_MAIN] + 32).contains(Pos)) { + _engine->ifQuit(); + } + + // Settings + if (menuBarFlag & menuBar_Settings) + if (Common::Rect(320 , + scrollPos[menu_MAIN], + 320 + 135, + scrollPos[menu_MAIN] + 32).contains(Pos)) { + _engine->getScriptManager()->changeLocation('g', 'j', 'p', 'e', 0); + } + + // Load + if (menuBarFlag & menuBar_Restore) + if (Common::Rect(320 - 135, + scrollPos[menu_MAIN], + 320, + scrollPos[menu_MAIN] + 32).contains(Pos)) { + _engine->getScriptManager()->changeLocation('g', 'j', 'r', 'e', 0); + } + + // Save + if (menuBarFlag & menuBar_Save) + if (Common::Rect(320 - 135 * 2, + scrollPos[menu_MAIN], + 320 - 135, + scrollPos[menu_MAIN] + 32).contains(Pos)) { + _engine->getScriptManager()->changeLocation('g', 'j', 's', 'e', 0); + } + break; + } + } +} + +void MenuZGI::onMouseMove(const Common::Point &Pos) { + if (Pos.y < 40) { + + if (!inmenu) + redraw = true; + inmenu = true; + switch (menuMouseFocus) { + case menu_ITEM: + if (menuBarFlag & menuBar_Items) { + int itemCount = _engine->getScriptManager()->getStateValue(StateKey_Inv_TotalSlots); + if (itemCount == 0) + itemCount = 20; + else if (itemCount > 50) + itemCount = 50; + + int lastItem = mouseOnItem; + + mouseOnItem = -1; + + for (int i = 0; i < itemCount; i++) { + int itemspace = (600 - 28) / itemCount; + + if (Common::Rect(scrollPos[menu_ITEM] + itemspace * i, 0, + scrollPos[menu_ITEM] + itemspace * i + 28, 32).contains(Pos)) { + mouseOnItem = i; + break; + } + } + + if (lastItem != mouseOnItem) + if (_engine->getScriptManager()->getStateValue(SLOT_START_SLOT + mouseOnItem) || + _engine->getScriptManager()->getStateValue(SLOT_START_SLOT + lastItem)) + redraw = true; + } + break; + + case menu_MAGIC: + if (menuBarFlag & menuBar_Magic) { + int lastItem = mouseOnItem; + mouseOnItem = -1; + for (int i = 0; i < 12; i++) { + if (Common::Rect(668 + 47 * i - scrollPos[menu_MAGIC], 0, + 668 + 47 * i - scrollPos[menu_MAGIC] + 28, 32).contains(Pos)) { + mouseOnItem = i; + break; + } + } + + if (lastItem != mouseOnItem) + if (_engine->getScriptManager()->getStateValue(SLOT_SPELL_1 + mouseOnItem) || + _engine->getScriptManager()->getStateValue(SLOT_SPELL_1 + lastItem)) + redraw = true; + + } + break; + + case menu_MAIN: { + int lastItem = mouseOnItem; + mouseOnItem = -1; + + // Exit + if (menuBarFlag & menuBar_Exit) + if (Common::Rect(320 + 135, + scrollPos[menu_MAIN], + 320 + 135 + 135, + scrollPos[menu_MAIN] + 32).contains(Pos)) { + mouseOnItem = menu_MAIN_EXIT; + } + + // Settings + if (menuBarFlag & menuBar_Settings) + if (Common::Rect(320 , + scrollPos[menu_MAIN], + 320 + 135, + scrollPos[menu_MAIN] + 32).contains(Pos)) { + mouseOnItem = menu_MAIN_PREF; + } + + // Load + if (menuBarFlag & menuBar_Restore) + if (Common::Rect(320 - 135, + scrollPos[menu_MAIN], + 320, + scrollPos[menu_MAIN] + 32).contains(Pos)) { + mouseOnItem = menu_MAIN_REST; + } + + // Save + if (menuBarFlag & menuBar_Save) + if (Common::Rect(320 - 135 * 2, + scrollPos[menu_MAIN], + 320 - 135, + scrollPos[menu_MAIN] + 32).contains(Pos)) { + mouseOnItem = menu_MAIN_SAVE; + } + + if (lastItem != mouseOnItem) + redraw = true; + } + break; + + default: + int cur_menu = menuMouseFocus; + if (Common::Rect(64, 0, 64 + 512, 8).contains(Pos)) { // Main + menuMouseFocus = menu_MAIN; + scrolled[menu_MAIN] = false; + scrollPos[menu_MAIN] = menuback[menu_MAIN][1].h - menuback[menu_MAIN][0].h; + _engine->getScriptManager()->setStateValue(StateKey_MenuState, 2); + } + + if (menuBarFlag & menuBar_Magic) + if (Common::Rect(640 - 28, 0, 640, 32).contains(Pos)) { // Magic + menuMouseFocus = menu_MAGIC; + scrolled[menu_MAGIC] = false; + scrollPos[menu_MAGIC] = 28; + _engine->getScriptManager()->setStateValue(StateKey_MenuState, 3); + } + + if (menuBarFlag & menuBar_Items) + if (Common::Rect(0, 0, 28, 32).contains(Pos)) { // Items + menuMouseFocus = menu_ITEM; + scrolled[menu_ITEM] = false; + scrollPos[menu_ITEM] = 28 - 600; + _engine->getScriptManager()->setStateValue(StateKey_MenuState, 1); + } + + if (cur_menu != menuMouseFocus) + clean = true; + + break; + } + } else { + if (inmenu) + clean = true; + inmenu = false; + if (_engine->getScriptManager()->getStateValue(StateKey_MenuState) != 0) + _engine->getScriptManager()->setStateValue(StateKey_MenuState, 0); + menuMouseFocus = -1; + } +} + +void MenuZGI::process(uint32 deltatime) { + if (clean) { + _engine->getRenderManager()->clearMenuSurface(); + clean = false; + } + switch (menuMouseFocus) { + case menu_ITEM: + if (menuBarFlag & menuBar_Items) + if (!scrolled[menu_ITEM]) { + redraw = true; + float scrl = 600.0 * (deltatime / 1000.0); + + if (scrl == 0) + scrl = 1.0; + + scrollPos [menu_ITEM] += scrl; + + if (scrollPos[menu_ITEM] >= 0) { + scrolled[menu_ITEM] = true; + scrollPos [menu_ITEM] = 0; + } + } + if (redraw) { + _engine->getRenderManager()->blitSurfaceToMenu(menuback[menu_ITEM][0], scrollPos[menu_ITEM], 0); + + int itemCount = _engine->getScriptManager()->getStateValue(StateKey_Inv_TotalSlots); + if (itemCount == 0) + itemCount = 20; + else if (itemCount > 50) + itemCount = 50; + + for (int i = 0; i < itemCount; i++) { + int itemspace = (600 - 28) / itemCount; + + bool inrect = false; + + if (mouseOnItem == i) + inrect = true; + + uint curItemId = _engine->getScriptManager()->getStateValue(SLOT_START_SLOT + i); + + if (curItemId != 0) { + if (itemId[i] != curItemId) { + char buf[16]; + sprintf(buf, "gmzwu%2.2x1.tga", curItemId); + items[i][0] = _engine->getRenderManager()->loadImage(buf, false); + sprintf(buf, "gmzxu%2.2x1.tga", curItemId); + items[i][1] = _engine->getRenderManager()->loadImage(buf, false); + itemId[i] = curItemId; + } + + if (inrect) + _engine->getRenderManager()->blitSurfaceToMenu(*items[i][1], scrollPos[menu_ITEM] + itemspace * i, 0, 0); + else + _engine->getRenderManager()->blitSurfaceToMenu(*items[i][0], scrollPos[menu_ITEM] + itemspace * i, 0, 0); + + } else { + if (items[i][0]) { + items[i][0]->free(); + delete items[i][0]; + items[i][0] = NULL; + } + if (items[i][1]) { + items[i][1]->free(); + delete items[i][1]; + items[i][1] = NULL; + } + itemId[i] = 0; + } + } + + redraw = false; + } + break; + + case menu_MAGIC: + if (menuBarFlag & menuBar_Magic) + if (!scrolled[menu_MAGIC]) { + redraw = true; + float scrl = 600.0 * (deltatime / 1000.0); + + if (scrl == 0) + scrl = 1.0; + + scrollPos [menu_MAGIC] += scrl; + + if (scrollPos[menu_MAGIC] >= 600) { + scrolled[menu_MAGIC] = true; + scrollPos [menu_MAGIC] = 600; + } + } + if (redraw) { + _engine->getRenderManager()->blitSurfaceToMenu(menuback[menu_MAGIC][0], 640 - scrollPos[menu_MAGIC], 0); + + for (int i = 0; i < 12; i++) { + bool inrect = false; + + if (mouseOnItem == i) + inrect = true; + + uint curItemId = _engine->getScriptManager()->getStateValue(SLOT_SPELL_1 + i); + if (curItemId) { + if (_engine->getScriptManager()->getStateValue(SLOT_REVERSED_SPELLBOOK) == 1) + curItemId = 0xEE + i; + else + curItemId = 0xE0 + i; + } + + if (curItemId != 0) { + if (itemId[i] != curItemId) { + char buf[16]; + sprintf(buf, "gmzwu%2.2x1.tga", curItemId); + magic[i][0] = _engine->getRenderManager()->loadImage(buf, false); + sprintf(buf, "gmzxu%2.2x1.tga", curItemId); + magic[i][1] = _engine->getRenderManager()->loadImage(buf, false); + magicId[i] = curItemId; + } + + if (inrect) + _engine->getRenderManager()->blitSurfaceToMenu(*magic[i][1], 668 + 47 * i - scrollPos[menu_MAGIC], 0, 0); + else + _engine->getRenderManager()->blitSurfaceToMenu(*magic[i][0], 668 + 47 * i - scrollPos[menu_MAGIC], 0, 0); + + } else { + if (magic[i][0]) { + magic[i][0]->free(); + delete magic[i][0]; + magic[i][0] = NULL; + } + if (magic[i][1]) { + magic[i][1]->free(); + delete magic[i][1]; + magic[i][1] = NULL; + } + magicId[i] = 0; + } + } + redraw = false; + } + break; + + case menu_MAIN: + if (!scrolled[menu_MAIN]) { + redraw = true; + float scrl = 32.0 * 2.0 * (deltatime / 1000.0); + + if (scrl == 0) + scrl = 1.0; + + scrollPos [menu_MAIN] += scrl; + + if (scrollPos[menu_MAIN] >= 0) { + scrolled[menu_MAIN] = true; + scrollPos [menu_MAIN] = 0; + } + } + if (redraw) { + _engine->getRenderManager()->blitSurfaceToMenu(menuback[menu_MAIN][0], 30, scrollPos[menu_MAIN]); + + if (menuBarFlag & menuBar_Exit) { + if (mouseOnItem == menu_MAIN_EXIT) + _engine->getRenderManager()->blitSurfaceToMenu(menubar[menu_MAIN_EXIT][1], 320 + 135, scrollPos[menu_MAIN]); + else + _engine->getRenderManager()->blitSurfaceToMenu(menubar[menu_MAIN_EXIT][0], 320 + 135, scrollPos[menu_MAIN]); + } + if (menuBarFlag & menuBar_Settings) { + if (mouseOnItem == menu_MAIN_PREF) + _engine->getRenderManager()->blitSurfaceToMenu(menubar[menu_MAIN_PREF][1], 320, scrollPos[menu_MAIN]); + else + _engine->getRenderManager()->blitSurfaceToMenu(menubar[menu_MAIN_PREF][0], 320, scrollPos[menu_MAIN]); + } + if (menuBarFlag & menuBar_Restore) { + if (mouseOnItem == menu_MAIN_REST) + _engine->getRenderManager()->blitSurfaceToMenu(menubar[menu_MAIN_REST][1], 320 - 135, scrollPos[menu_MAIN]); + else + _engine->getRenderManager()->blitSurfaceToMenu(menubar[menu_MAIN_REST][0], 320 - 135, scrollPos[menu_MAIN]); + } + if (menuBarFlag & menuBar_Save) { + if (mouseOnItem == menu_MAIN_SAVE) + _engine->getRenderManager()->blitSurfaceToMenu(menubar[menu_MAIN_SAVE][1], 320 - 135 * 2, scrollPos[menu_MAIN]); + else + _engine->getRenderManager()->blitSurfaceToMenu(menubar[menu_MAIN_SAVE][0], 320 - 135 * 2, scrollPos[menu_MAIN]); + } + redraw = false; + } + break; + default: + if (redraw) { + if (inmenu) { + _engine->getRenderManager()->blitSurfaceToMenu(menuback[menu_MAIN][1], 30, 0); + + if (menuBarFlag & menuBar_Items) + _engine->getRenderManager()->blitSurfaceToMenu(menuback[menu_ITEM][1], 0, 0); + + if (menuBarFlag & menuBar_Magic) + _engine->getRenderManager()->blitSurfaceToMenu(menuback[menu_MAGIC][1], 640 - 28, 0); + } + redraw = false; + } + break; + } +} + +MenuNemesis::MenuNemesis(ZVision *engine) : + MenuHandler(engine) { + inmenu = false; + scrolled = false; + scrollPos = 0.0; + mouseOnItem = -1; + redraw = false; + delay = 0; + + char buf[24]; + for (int i = 0; i < 4; i++) + for (int j = 0; j < 6; j++) { + sprintf(buf, "butfrm%d%d.tga", i + 1, j); + _engine->getRenderManager()->readImageToSurface(buf, but[i][j], false); + } + + _engine->getRenderManager()->readImageToSurface("bar.tga", menubar, false); + + frm = 0; +} + +MenuNemesis::~MenuNemesis() { + for (int i = 0; i < 4; i++) + for (int j = 0; j < 6; j++) + but[i][j].free(); + + menubar.free(); +} + +static const int16 buts[4][2] = { {120 , 64}, {144, 184}, {128, 328}, {120, 456} }; + +void MenuNemesis::onMouseUp(const Common::Point &Pos) { + if (Pos.y < 40) { + // Exit + if (menuBarFlag & menuBar_Exit) + if (Common::Rect(buts[3][1], + scrollPos, + buts[3][0] + buts[3][1], + scrollPos + 32).contains(Pos)) { + _engine->ifQuit(); + frm = 5; + redraw = true; + } + + // Settings + if (menuBarFlag & menuBar_Settings) + if (Common::Rect(buts[2][1], + scrollPos, + buts[2][0] + buts[2][1], + scrollPos + 32).contains(Pos)) { + _engine->getScriptManager()->changeLocation('g', 'j', 'p', 'e', 0); + frm = 5; + redraw = true; + } + + // Load + if (menuBarFlag & menuBar_Restore) + if (Common::Rect(buts[1][1], + scrollPos, + buts[1][0] + buts[1][1], + scrollPos + 32).contains(Pos)) { + _engine->getScriptManager()->changeLocation('g', 'j', 'r', 'e', 0); + frm = 5; + redraw = true; + } + + // Save + if (menuBarFlag & menuBar_Save) + if (Common::Rect(buts[0][1], + scrollPos, + buts[0][0] + buts[0][1], + scrollPos + 32).contains(Pos)) { + _engine->getScriptManager()->changeLocation('g', 'j', 's', 'e', 0); + frm = 5; + redraw = true; + } + } +} + +void MenuNemesis::onMouseMove(const Common::Point &Pos) { + if (Pos.y < 40) { + + inmenu = true; + + if (_engine->getScriptManager()->getStateValue(StateKey_MenuState) != 2) + _engine->getScriptManager()->setStateValue(StateKey_MenuState, 2); + + int lastItem = mouseOnItem; + mouseOnItem = -1; + + // Exit + if (menuBarFlag & menuBar_Exit) + if (Common::Rect(buts[3][1], + scrollPos, + buts[3][0] + buts[3][1], + scrollPos + 32).contains(Pos)) { + mouseOnItem = menu_MAIN_EXIT; + } + + // Settings + if (menuBarFlag & menuBar_Settings) + if (Common::Rect(buts[2][1], + scrollPos, + buts[2][0] + buts[2][1], + scrollPos + 32).contains(Pos)) { + mouseOnItem = menu_MAIN_PREF; + } + + // Load + if (menuBarFlag & menuBar_Restore) + if (Common::Rect(buts[1][1], + scrollPos, + buts[1][0] + buts[1][1], + scrollPos + 32).contains(Pos)) { + mouseOnItem = menu_MAIN_REST; + } + + // Save + if (menuBarFlag & menuBar_Save) + if (Common::Rect(buts[0][1], + scrollPos, + buts[0][0] + buts[0][1], + scrollPos + 32).contains(Pos)) { + mouseOnItem = menu_MAIN_SAVE; + } + + if (lastItem != mouseOnItem) { + redraw = true; + frm = 0; + delay = 200; + } + } else { + inmenu = false; + if (_engine->getScriptManager()->getStateValue(StateKey_MenuState) != 0) + _engine->getScriptManager()->setStateValue(StateKey_MenuState, 0); + mouseOnItem = -1; + } +} + +void MenuNemesis::process(uint32 deltatime) { + if (inmenu) { + if (!scrolled) { + float scrl = 32.0 * 2.0 * (deltatime / 1000.0); + + if (scrl == 0) + scrl = 1.0; + + scrollPos += scrl; + redraw = true; + } + + if (scrollPos >= 0) { + scrolled = true; + scrollPos = 0; + } + + if (mouseOnItem != -1) { + delay -= deltatime; + if (delay <= 0 && frm < 4) { + delay = 200; + frm++; + redraw = true; + } + } + + if (redraw) { + _engine->getRenderManager()->blitSurfaceToMenu(menubar, 64, scrollPos); + + if (menuBarFlag & menuBar_Exit) + if (mouseOnItem == menu_MAIN_EXIT) + _engine->getRenderManager()->blitSurfaceToMenu(but[3][frm], buts[3][1], scrollPos); + + if (menuBarFlag & menuBar_Settings) + if (mouseOnItem == menu_MAIN_PREF) + _engine->getRenderManager()->blitSurfaceToMenu(but[2][frm], buts[2][1], scrollPos); + + if (menuBarFlag & menuBar_Restore) + if (mouseOnItem == menu_MAIN_REST) + _engine->getRenderManager()->blitSurfaceToMenu(but[1][frm], buts[1][1], scrollPos); + + if (menuBarFlag & menuBar_Save) + if (mouseOnItem == menu_MAIN_SAVE) + _engine->getRenderManager()->blitSurfaceToMenu(but[0][frm], buts[0][1], scrollPos); + + redraw = false; + } + } else { + scrolled = false; + if (scrollPos > -32) { + float scrl = 32.0 * 2.0 * (deltatime / 1000.0); + + if (scrl == 0) + scrl = 1.0; + + Common::Rect cl(64, 32 + scrollPos - scrl, 64 + 512, 32 + scrollPos + 1); + _engine->getRenderManager()->clearMenuSurface(cl); + + scrollPos -= scrl; + redraw = true; + } else + scrollPos = -32; + + if (redraw) { + _engine->getRenderManager()->blitSurfaceToMenu(menubar, 64, scrollPos); + redraw = false; + } + } +} + +} // End of namespace ZVision diff --git a/engines/zvision/scripting/menu.h b/engines/zvision/scripting/menu.h new file mode 100644 index 0000000000..ebe0bb50ac --- /dev/null +++ b/engines/zvision/scripting/menu.h @@ -0,0 +1,125 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef ZVISION_MENU_H +#define ZVISION_MENU_H + +#include "graphics/surface.h" +#include "common/rect.h" + +#include "zvision/zvision.h" +#include "zvision/scripting/script_manager.h" + +namespace ZVision { + +enum menuBar { + menuBar_Exit = 0x1, + menuBar_Settings = 0x2, + menuBar_Restore = 0x4, + menuBar_Save = 0x8, + menuBar_Items = 0x100, + menuBar_Magic = 0x200 +}; + +class MenuHandler { +public: + MenuHandler(ZVision *engine); + virtual ~MenuHandler() {}; + virtual void onMouseMove(const Common::Point &Pos) {}; + virtual void onMouseDown(const Common::Point &Pos) {}; + virtual void onMouseUp(const Common::Point &Pos) {}; + virtual void process(uint32 deltaTimeInMillis) {}; + + void setEnable(uint16 flags) { + menuBarFlag = flags; + } + uint16 getEnable() { + return menuBarFlag; + } +protected: + uint16 menuBarFlag; + ZVision *_engine; +}; + +class MenuZGI: public MenuHandler { +public: + MenuZGI(ZVision *engine); + ~MenuZGI(); + void onMouseMove(const Common::Point &Pos); + void onMouseUp(const Common::Point &Pos); + void process(uint32 deltaTimeInMillis); +private: + Graphics::Surface menuback[3][2]; + Graphics::Surface menubar[4][2]; + Graphics::Surface *items[50][2]; + uint itemId[50]; + + Graphics::Surface *magic[12][2]; + uint magicId[12]; + + int menuMouseFocus; + bool inmenu; + + int mouseOnItem; + + bool scrolled[3]; + int16 scrollPos[3]; + + enum { + menu_ITEM = 0, + menu_MAGIC = 1, + menu_MAIN = 2 + }; + + bool clean; + bool redraw; + +}; + +class MenuNemesis: public MenuHandler { +public: + MenuNemesis(ZVision *engine); + ~MenuNemesis(); + void onMouseMove(const Common::Point &Pos); + void onMouseUp(const Common::Point &Pos); + void process(uint32 deltaTimeInMillis); +private: + Graphics::Surface but[4][6]; + Graphics::Surface menubar; + + bool inmenu; + + int mouseOnItem; + + bool scrolled; + int16 scrollPos; + + bool redraw; + + int frm; + int16 delay; + +}; + +} + +#endif diff --git a/engines/zvision/zvision.cpp b/engines/zvision/zvision.cpp index db96884103..f692969942 100644 --- a/engines/zvision/zvision.cpp +++ b/engines/zvision/zvision.cpp @@ -30,7 +30,7 @@ #include "zvision/core/save_manager.h" #include "zvision/text/string_manager.h" #include "zvision/detection.h" -#include "zvision/core/menu.h" +#include "zvision/scripting/menu.h" #include "zvision/file/search_manager.h" #include "zvision/text/text.h" #include "zvision/text/truetype_font.h" -- cgit v1.2.3 From 3661bc4cf13ac9bb27e60969b4195acc82fee6c5 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 25 Dec 2014 22:11:29 +0200 Subject: ZVISION: Normalize and cleanup all the menu-related enums --- engines/zvision/core/events.cpp | 8 +- engines/zvision/scripting/menu.cpp | 289 ++++++++++++++--------------- engines/zvision/scripting/menu.h | 18 +- engines/zvision/scripting/script_manager.h | 7 +- 4 files changed, 160 insertions(+), 162 deletions(-) (limited to 'engines') diff --git a/engines/zvision/core/events.cpp b/engines/zvision/core/events.cpp index 89f1595460..227cf213dc 100644 --- a/engines/zvision/core/events.cpp +++ b/engines/zvision/core/events.cpp @@ -43,19 +43,19 @@ void ZVision::shortKeys(Common::Event event) { if (event.kbd.hasFlags(Common::KBD_CTRL)) { switch (event.kbd.keycode) { case Common::KEYCODE_s: - if (getMenuBarEnable() & menuBar_Save) + if (getMenuBarEnable() & kMenubarSave) _scriptManager->changeLocation('g', 'j', 's', 'e', 0); break; case Common::KEYCODE_r: - if (getMenuBarEnable() & menuBar_Restore) + if (getMenuBarEnable() & kMenubarRestore) _scriptManager->changeLocation('g', 'j', 'r', 'e', 0); break; case Common::KEYCODE_p: - if (getMenuBarEnable() & menuBar_Settings) + if (getMenuBarEnable() & kMenubarSettings) _scriptManager->changeLocation('g', 'j', 'p', 'e', 0); break; case Common::KEYCODE_q: - if (getMenuBarEnable() & menuBar_Exit) + if (getMenuBarEnable() & kMenubarExit) ifQuit(); break; default: diff --git a/engines/zvision/scripting/menu.cpp b/engines/zvision/scripting/menu.cpp index fa5e24f39f..16aa57e3ae 100644 --- a/engines/zvision/scripting/menu.cpp +++ b/engines/zvision/scripting/menu.cpp @@ -26,17 +26,16 @@ namespace ZVision { enum { - SLOT_START_SLOT = 151, - SLOT_SPELL_1 = 191, - SLOT_USER_CHOSE_THIS_SPELL = 205, - SLOT_REVERSED_SPELLBOOK = 206 + kMainMenuSave = 0, + kMainMenuLoad = 1, + kMainMenuPrefs = 2, + kMainMenuExit = 3 }; enum { - menu_MAIN_SAVE = 0, - menu_MAIN_REST = 1, - menu_MAIN_PREF = 2, - menu_MAIN_EXIT = 3 + kMenuItem = 0, + kMenuMagic = 1, + kMenuMain = 2 }; MenuHandler::MenuHandler(ZVision *engine) { @@ -119,8 +118,8 @@ MenuZGI::~MenuZGI() { void MenuZGI::onMouseUp(const Common::Point &Pos) { if (Pos.y < 40) { switch (menuMouseFocus) { - case menu_ITEM: - if (menuBarFlag & menuBar_Items) { + case kMenuItem: + if (menuBarFlag & kMenubarItems) { int itemCount = _engine->getScriptManager()->getStateValue(StateKey_Inv_TotalSlots); if (itemCount == 0) itemCount = 20; @@ -128,13 +127,13 @@ void MenuZGI::onMouseUp(const Common::Point &Pos) { for (int i = 0; i < itemCount; i++) { int itemspace = (600 - 28) / itemCount; - if (Common::Rect(scrollPos[menu_ITEM] + itemspace * i, 0, - scrollPos[menu_ITEM] + itemspace * i + 28, 32).contains(Pos)) { + if (Common::Rect(scrollPos[kMenuItem] + itemspace * i, 0, + scrollPos[kMenuItem] + itemspace * i + 28, 32).contains(Pos)) { int32 mouseItem = _engine->getScriptManager()->getStateValue(StateKey_InventoryItem); if (mouseItem >= 0 && mouseItem < 0xE0) { _engine->getScriptManager()->inventoryDrop(mouseItem); - _engine->getScriptManager()->inventoryAdd(_engine->getScriptManager()->getStateValue(SLOT_START_SLOT + i)); - _engine->getScriptManager()->setStateValue(SLOT_START_SLOT + i, mouseItem); + _engine->getScriptManager()->inventoryAdd(_engine->getScriptManager()->getStateValue(StateKey_Inv_StartSlot + i)); + _engine->getScriptManager()->setStateValue(StateKey_Inv_StartSlot + i, mouseItem); redraw = true; } @@ -143,62 +142,62 @@ void MenuZGI::onMouseUp(const Common::Point &Pos) { } break; - case menu_MAGIC: - if (menuBarFlag & menuBar_Magic) { + case kMenuMagic: + if (menuBarFlag & kMenubarMagic) { for (int i = 0; i < 12; i++) { - uint itemnum = _engine->getScriptManager()->getStateValue(SLOT_SPELL_1 + i); + uint itemnum = _engine->getScriptManager()->getStateValue(StateKey_Spell_1 + i); if (itemnum != 0) { - if (_engine->getScriptManager()->getStateValue(SLOT_REVERSED_SPELLBOOK) == 1) + if (_engine->getScriptManager()->getStateValue(StateKey_Reversed_Spellbooc) == 1) itemnum = 0xEE + i; else itemnum = 0xE0 + i; } if (itemnum) if (_engine->getScriptManager()->getStateValue(StateKey_InventoryItem) == 0 || _engine->getScriptManager()->getStateValue(StateKey_InventoryItem) >= 0xE0) - if (Common::Rect(668 + 47 * i - scrollPos[menu_MAGIC], 0, - 668 + 47 * i - scrollPos[menu_MAGIC] + 28, 32).contains(Pos)) - _engine->getScriptManager()->setStateValue(SLOT_USER_CHOSE_THIS_SPELL, itemnum); + if (Common::Rect(668 + 47 * i - scrollPos[kMenuMagic], 0, + 668 + 47 * i - scrollPos[kMenuMagic] + 28, 32).contains(Pos)) + _engine->getScriptManager()->setStateValue(StateKey_Active_Spell, itemnum); } } break; - case menu_MAIN: + case kMenuMain: // Exit - if (menuBarFlag & menuBar_Exit) + if (menuBarFlag & kMenubarExit) if (Common::Rect(320 + 135, - scrollPos[menu_MAIN], + scrollPos[kMenuMain], 320 + 135 + 135, - scrollPos[menu_MAIN] + 32).contains(Pos)) { + scrollPos[kMenuMain] + 32).contains(Pos)) { _engine->ifQuit(); } // Settings - if (menuBarFlag & menuBar_Settings) + if (menuBarFlag & kMenubarSettings) if (Common::Rect(320 , - scrollPos[menu_MAIN], + scrollPos[kMenuMain], 320 + 135, - scrollPos[menu_MAIN] + 32).contains(Pos)) { + scrollPos[kMenuMain] + 32).contains(Pos)) { _engine->getScriptManager()->changeLocation('g', 'j', 'p', 'e', 0); } // Load - if (menuBarFlag & menuBar_Restore) + if (menuBarFlag & kMenubarRestore) if (Common::Rect(320 - 135, - scrollPos[menu_MAIN], + scrollPos[kMenuMain], 320, - scrollPos[menu_MAIN] + 32).contains(Pos)) { + scrollPos[kMenuMain] + 32).contains(Pos)) { _engine->getScriptManager()->changeLocation('g', 'j', 'r', 'e', 0); } // Save - if (menuBarFlag & menuBar_Save) + if (menuBarFlag & kMenubarSave) if (Common::Rect(320 - 135 * 2, - scrollPos[menu_MAIN], + scrollPos[kMenuMain], 320 - 135, - scrollPos[menu_MAIN] + 32).contains(Pos)) { + scrollPos[kMenuMain] + 32).contains(Pos)) { _engine->getScriptManager()->changeLocation('g', 'j', 's', 'e', 0); } break; @@ -213,8 +212,8 @@ void MenuZGI::onMouseMove(const Common::Point &Pos) { redraw = true; inmenu = true; switch (menuMouseFocus) { - case menu_ITEM: - if (menuBarFlag & menuBar_Items) { + case kMenuItem: + if (menuBarFlag & kMenubarItems) { int itemCount = _engine->getScriptManager()->getStateValue(StateKey_Inv_TotalSlots); if (itemCount == 0) itemCount = 20; @@ -228,78 +227,78 @@ void MenuZGI::onMouseMove(const Common::Point &Pos) { for (int i = 0; i < itemCount; i++) { int itemspace = (600 - 28) / itemCount; - if (Common::Rect(scrollPos[menu_ITEM] + itemspace * i, 0, - scrollPos[menu_ITEM] + itemspace * i + 28, 32).contains(Pos)) { + if (Common::Rect(scrollPos[kMenuItem] + itemspace * i, 0, + scrollPos[kMenuItem] + itemspace * i + 28, 32).contains(Pos)) { mouseOnItem = i; break; } } if (lastItem != mouseOnItem) - if (_engine->getScriptManager()->getStateValue(SLOT_START_SLOT + mouseOnItem) || - _engine->getScriptManager()->getStateValue(SLOT_START_SLOT + lastItem)) + if (_engine->getScriptManager()->getStateValue(StateKey_Inv_StartSlot + mouseOnItem) || + _engine->getScriptManager()->getStateValue(StateKey_Inv_StartSlot + lastItem)) redraw = true; } break; - case menu_MAGIC: - if (menuBarFlag & menuBar_Magic) { + case kMenuMagic: + if (menuBarFlag & kMenubarMagic) { int lastItem = mouseOnItem; mouseOnItem = -1; for (int i = 0; i < 12; i++) { - if (Common::Rect(668 + 47 * i - scrollPos[menu_MAGIC], 0, - 668 + 47 * i - scrollPos[menu_MAGIC] + 28, 32).contains(Pos)) { + if (Common::Rect(668 + 47 * i - scrollPos[kMenuMagic], 0, + 668 + 47 * i - scrollPos[kMenuMagic] + 28, 32).contains(Pos)) { mouseOnItem = i; break; } } if (lastItem != mouseOnItem) - if (_engine->getScriptManager()->getStateValue(SLOT_SPELL_1 + mouseOnItem) || - _engine->getScriptManager()->getStateValue(SLOT_SPELL_1 + lastItem)) + if (_engine->getScriptManager()->getStateValue(StateKey_Spell_1 + mouseOnItem) || + _engine->getScriptManager()->getStateValue(StateKey_Spell_1 + lastItem)) redraw = true; } break; - case menu_MAIN: { + case kMenuMain: { int lastItem = mouseOnItem; mouseOnItem = -1; // Exit - if (menuBarFlag & menuBar_Exit) + if (menuBarFlag & kMenubarExit) if (Common::Rect(320 + 135, - scrollPos[menu_MAIN], + scrollPos[kMenuMain], 320 + 135 + 135, - scrollPos[menu_MAIN] + 32).contains(Pos)) { - mouseOnItem = menu_MAIN_EXIT; + scrollPos[kMenuMain] + 32).contains(Pos)) { + mouseOnItem = kMainMenuExit; } // Settings - if (menuBarFlag & menuBar_Settings) + if (menuBarFlag & kMenubarSettings) if (Common::Rect(320 , - scrollPos[menu_MAIN], + scrollPos[kMenuMain], 320 + 135, - scrollPos[menu_MAIN] + 32).contains(Pos)) { - mouseOnItem = menu_MAIN_PREF; + scrollPos[kMenuMain] + 32).contains(Pos)) { + mouseOnItem = kMainMenuPrefs; } // Load - if (menuBarFlag & menuBar_Restore) + if (menuBarFlag & kMenubarRestore) if (Common::Rect(320 - 135, - scrollPos[menu_MAIN], + scrollPos[kMenuMain], 320, - scrollPos[menu_MAIN] + 32).contains(Pos)) { - mouseOnItem = menu_MAIN_REST; + scrollPos[kMenuMain] + 32).contains(Pos)) { + mouseOnItem = kMainMenuLoad; } // Save - if (menuBarFlag & menuBar_Save) + if (menuBarFlag & kMenubarSave) if (Common::Rect(320 - 135 * 2, - scrollPos[menu_MAIN], + scrollPos[kMenuMain], 320 - 135, - scrollPos[menu_MAIN] + 32).contains(Pos)) { - mouseOnItem = menu_MAIN_SAVE; + scrollPos[kMenuMain] + 32).contains(Pos)) { + mouseOnItem = kMainMenuSave; } if (lastItem != mouseOnItem) @@ -310,25 +309,25 @@ void MenuZGI::onMouseMove(const Common::Point &Pos) { default: int cur_menu = menuMouseFocus; if (Common::Rect(64, 0, 64 + 512, 8).contains(Pos)) { // Main - menuMouseFocus = menu_MAIN; - scrolled[menu_MAIN] = false; - scrollPos[menu_MAIN] = menuback[menu_MAIN][1].h - menuback[menu_MAIN][0].h; + menuMouseFocus = kMenuMain; + scrolled[kMenuMain] = false; + scrollPos[kMenuMain] = menuback[kMenuMain][1].h - menuback[kMenuMain][0].h; _engine->getScriptManager()->setStateValue(StateKey_MenuState, 2); } - if (menuBarFlag & menuBar_Magic) + if (menuBarFlag & kMenubarMagic) if (Common::Rect(640 - 28, 0, 640, 32).contains(Pos)) { // Magic - menuMouseFocus = menu_MAGIC; - scrolled[menu_MAGIC] = false; - scrollPos[menu_MAGIC] = 28; + menuMouseFocus = kMenuMagic; + scrolled[kMenuMagic] = false; + scrollPos[kMenuMagic] = 28; _engine->getScriptManager()->setStateValue(StateKey_MenuState, 3); } - if (menuBarFlag & menuBar_Items) + if (menuBarFlag & kMenubarItems) if (Common::Rect(0, 0, 28, 32).contains(Pos)) { // Items - menuMouseFocus = menu_ITEM; - scrolled[menu_ITEM] = false; - scrollPos[menu_ITEM] = 28 - 600; + menuMouseFocus = kMenuItem; + scrolled[kMenuItem] = false; + scrollPos[kMenuItem] = 28 - 600; _engine->getScriptManager()->setStateValue(StateKey_MenuState, 1); } @@ -353,24 +352,24 @@ void MenuZGI::process(uint32 deltatime) { clean = false; } switch (menuMouseFocus) { - case menu_ITEM: - if (menuBarFlag & menuBar_Items) - if (!scrolled[menu_ITEM]) { + case kMenuItem: + if (menuBarFlag & kMenubarItems) + if (!scrolled[kMenuItem]) { redraw = true; float scrl = 600.0 * (deltatime / 1000.0); if (scrl == 0) scrl = 1.0; - scrollPos [menu_ITEM] += scrl; + scrollPos [kMenuItem] += scrl; - if (scrollPos[menu_ITEM] >= 0) { - scrolled[menu_ITEM] = true; - scrollPos [menu_ITEM] = 0; + if (scrollPos[kMenuItem] >= 0) { + scrolled[kMenuItem] = true; + scrollPos [kMenuItem] = 0; } } if (redraw) { - _engine->getRenderManager()->blitSurfaceToMenu(menuback[menu_ITEM][0], scrollPos[menu_ITEM], 0); + _engine->getRenderManager()->blitSurfaceToMenu(menuback[kMenuItem][0], scrollPos[kMenuItem], 0); int itemCount = _engine->getScriptManager()->getStateValue(StateKey_Inv_TotalSlots); if (itemCount == 0) @@ -386,7 +385,7 @@ void MenuZGI::process(uint32 deltatime) { if (mouseOnItem == i) inrect = true; - uint curItemId = _engine->getScriptManager()->getStateValue(SLOT_START_SLOT + i); + uint curItemId = _engine->getScriptManager()->getStateValue(StateKey_Inv_StartSlot + i); if (curItemId != 0) { if (itemId[i] != curItemId) { @@ -399,9 +398,9 @@ void MenuZGI::process(uint32 deltatime) { } if (inrect) - _engine->getRenderManager()->blitSurfaceToMenu(*items[i][1], scrollPos[menu_ITEM] + itemspace * i, 0, 0); + _engine->getRenderManager()->blitSurfaceToMenu(*items[i][1], scrollPos[kMenuItem] + itemspace * i, 0, 0); else - _engine->getRenderManager()->blitSurfaceToMenu(*items[i][0], scrollPos[menu_ITEM] + itemspace * i, 0, 0); + _engine->getRenderManager()->blitSurfaceToMenu(*items[i][0], scrollPos[kMenuItem] + itemspace * i, 0, 0); } else { if (items[i][0]) { @@ -422,24 +421,24 @@ void MenuZGI::process(uint32 deltatime) { } break; - case menu_MAGIC: - if (menuBarFlag & menuBar_Magic) - if (!scrolled[menu_MAGIC]) { + case kMenuMagic: + if (menuBarFlag & kMenubarMagic) + if (!scrolled[kMenuMagic]) { redraw = true; float scrl = 600.0 * (deltatime / 1000.0); if (scrl == 0) scrl = 1.0; - scrollPos [menu_MAGIC] += scrl; + scrollPos [kMenuMagic] += scrl; - if (scrollPos[menu_MAGIC] >= 600) { - scrolled[menu_MAGIC] = true; - scrollPos [menu_MAGIC] = 600; + if (scrollPos[kMenuMagic] >= 600) { + scrolled[kMenuMagic] = true; + scrollPos [kMenuMagic] = 600; } } if (redraw) { - _engine->getRenderManager()->blitSurfaceToMenu(menuback[menu_MAGIC][0], 640 - scrollPos[menu_MAGIC], 0); + _engine->getRenderManager()->blitSurfaceToMenu(menuback[kMenuMagic][0], 640 - scrollPos[kMenuMagic], 0); for (int i = 0; i < 12; i++) { bool inrect = false; @@ -447,9 +446,9 @@ void MenuZGI::process(uint32 deltatime) { if (mouseOnItem == i) inrect = true; - uint curItemId = _engine->getScriptManager()->getStateValue(SLOT_SPELL_1 + i); + uint curItemId = _engine->getScriptManager()->getStateValue(StateKey_Spell_1 + i); if (curItemId) { - if (_engine->getScriptManager()->getStateValue(SLOT_REVERSED_SPELLBOOK) == 1) + if (_engine->getScriptManager()->getStateValue(StateKey_Reversed_Spellbooc) == 1) curItemId = 0xEE + i; else curItemId = 0xE0 + i; @@ -466,9 +465,9 @@ void MenuZGI::process(uint32 deltatime) { } if (inrect) - _engine->getRenderManager()->blitSurfaceToMenu(*magic[i][1], 668 + 47 * i - scrollPos[menu_MAGIC], 0, 0); + _engine->getRenderManager()->blitSurfaceToMenu(*magic[i][1], 668 + 47 * i - scrollPos[kMenuMagic], 0, 0); else - _engine->getRenderManager()->blitSurfaceToMenu(*magic[i][0], 668 + 47 * i - scrollPos[menu_MAGIC], 0, 0); + _engine->getRenderManager()->blitSurfaceToMenu(*magic[i][0], 668 + 47 * i - scrollPos[kMenuMagic], 0, 0); } else { if (magic[i][0]) { @@ -488,47 +487,47 @@ void MenuZGI::process(uint32 deltatime) { } break; - case menu_MAIN: - if (!scrolled[menu_MAIN]) { + case kMenuMain: + if (!scrolled[kMenuMain]) { redraw = true; float scrl = 32.0 * 2.0 * (deltatime / 1000.0); if (scrl == 0) scrl = 1.0; - scrollPos [menu_MAIN] += scrl; + scrollPos [kMenuMain] += scrl; - if (scrollPos[menu_MAIN] >= 0) { - scrolled[menu_MAIN] = true; - scrollPos [menu_MAIN] = 0; + if (scrollPos[kMenuMain] >= 0) { + scrolled[kMenuMain] = true; + scrollPos [kMenuMain] = 0; } } if (redraw) { - _engine->getRenderManager()->blitSurfaceToMenu(menuback[menu_MAIN][0], 30, scrollPos[menu_MAIN]); + _engine->getRenderManager()->blitSurfaceToMenu(menuback[kMenuMain][0], 30, scrollPos[kMenuMain]); - if (menuBarFlag & menuBar_Exit) { - if (mouseOnItem == menu_MAIN_EXIT) - _engine->getRenderManager()->blitSurfaceToMenu(menubar[menu_MAIN_EXIT][1], 320 + 135, scrollPos[menu_MAIN]); + if (menuBarFlag & kMenubarExit) { + if (mouseOnItem == kMainMenuExit) + _engine->getRenderManager()->blitSurfaceToMenu(menubar[kMainMenuExit][1], 320 + 135, scrollPos[kMenuMain]); else - _engine->getRenderManager()->blitSurfaceToMenu(menubar[menu_MAIN_EXIT][0], 320 + 135, scrollPos[menu_MAIN]); + _engine->getRenderManager()->blitSurfaceToMenu(menubar[kMainMenuExit][0], 320 + 135, scrollPos[kMenuMain]); } - if (menuBarFlag & menuBar_Settings) { - if (mouseOnItem == menu_MAIN_PREF) - _engine->getRenderManager()->blitSurfaceToMenu(menubar[menu_MAIN_PREF][1], 320, scrollPos[menu_MAIN]); + if (menuBarFlag & kMenubarSettings) { + if (mouseOnItem == kMainMenuPrefs) + _engine->getRenderManager()->blitSurfaceToMenu(menubar[kMainMenuPrefs][1], 320, scrollPos[kMenuMain]); else - _engine->getRenderManager()->blitSurfaceToMenu(menubar[menu_MAIN_PREF][0], 320, scrollPos[menu_MAIN]); + _engine->getRenderManager()->blitSurfaceToMenu(menubar[kMainMenuPrefs][0], 320, scrollPos[kMenuMain]); } - if (menuBarFlag & menuBar_Restore) { - if (mouseOnItem == menu_MAIN_REST) - _engine->getRenderManager()->blitSurfaceToMenu(menubar[menu_MAIN_REST][1], 320 - 135, scrollPos[menu_MAIN]); + if (menuBarFlag & kMenubarRestore) { + if (mouseOnItem == kMainMenuLoad) + _engine->getRenderManager()->blitSurfaceToMenu(menubar[kMainMenuLoad][1], 320 - 135, scrollPos[kMenuMain]); else - _engine->getRenderManager()->blitSurfaceToMenu(menubar[menu_MAIN_REST][0], 320 - 135, scrollPos[menu_MAIN]); + _engine->getRenderManager()->blitSurfaceToMenu(menubar[kMainMenuLoad][0], 320 - 135, scrollPos[kMenuMain]); } - if (menuBarFlag & menuBar_Save) { - if (mouseOnItem == menu_MAIN_SAVE) - _engine->getRenderManager()->blitSurfaceToMenu(menubar[menu_MAIN_SAVE][1], 320 - 135 * 2, scrollPos[menu_MAIN]); + if (menuBarFlag & kMenubarSave) { + if (mouseOnItem == kMainMenuSave) + _engine->getRenderManager()->blitSurfaceToMenu(menubar[kMainMenuSave][1], 320 - 135 * 2, scrollPos[kMenuMain]); else - _engine->getRenderManager()->blitSurfaceToMenu(menubar[menu_MAIN_SAVE][0], 320 - 135 * 2, scrollPos[menu_MAIN]); + _engine->getRenderManager()->blitSurfaceToMenu(menubar[kMainMenuSave][0], 320 - 135 * 2, scrollPos[kMenuMain]); } redraw = false; } @@ -536,13 +535,13 @@ void MenuZGI::process(uint32 deltatime) { default: if (redraw) { if (inmenu) { - _engine->getRenderManager()->blitSurfaceToMenu(menuback[menu_MAIN][1], 30, 0); + _engine->getRenderManager()->blitSurfaceToMenu(menuback[kMenuMain][1], 30, 0); - if (menuBarFlag & menuBar_Items) - _engine->getRenderManager()->blitSurfaceToMenu(menuback[menu_ITEM][1], 0, 0); + if (menuBarFlag & kMenubarItems) + _engine->getRenderManager()->blitSurfaceToMenu(menuback[kMenuItem][1], 0, 0); - if (menuBarFlag & menuBar_Magic) - _engine->getRenderManager()->blitSurfaceToMenu(menuback[menu_MAGIC][1], 640 - 28, 0); + if (menuBarFlag & kMenubarMagic) + _engine->getRenderManager()->blitSurfaceToMenu(menuback[kMenuMagic][1], 640 - 28, 0); } redraw = false; } @@ -584,7 +583,7 @@ static const int16 buts[4][2] = { {120 , 64}, {144, 184}, {128, 328}, {120, 456} void MenuNemesis::onMouseUp(const Common::Point &Pos) { if (Pos.y < 40) { // Exit - if (menuBarFlag & menuBar_Exit) + if (menuBarFlag & kMenubarExit) if (Common::Rect(buts[3][1], scrollPos, buts[3][0] + buts[3][1], @@ -595,7 +594,7 @@ void MenuNemesis::onMouseUp(const Common::Point &Pos) { } // Settings - if (menuBarFlag & menuBar_Settings) + if (menuBarFlag & kMenubarSettings) if (Common::Rect(buts[2][1], scrollPos, buts[2][0] + buts[2][1], @@ -606,7 +605,7 @@ void MenuNemesis::onMouseUp(const Common::Point &Pos) { } // Load - if (menuBarFlag & menuBar_Restore) + if (menuBarFlag & kMenubarRestore) if (Common::Rect(buts[1][1], scrollPos, buts[1][0] + buts[1][1], @@ -617,7 +616,7 @@ void MenuNemesis::onMouseUp(const Common::Point &Pos) { } // Save - if (menuBarFlag & menuBar_Save) + if (menuBarFlag & kMenubarSave) if (Common::Rect(buts[0][1], scrollPos, buts[0][0] + buts[0][1], @@ -641,39 +640,39 @@ void MenuNemesis::onMouseMove(const Common::Point &Pos) { mouseOnItem = -1; // Exit - if (menuBarFlag & menuBar_Exit) + if (menuBarFlag & kMenubarExit) if (Common::Rect(buts[3][1], scrollPos, buts[3][0] + buts[3][1], scrollPos + 32).contains(Pos)) { - mouseOnItem = menu_MAIN_EXIT; + mouseOnItem = kMainMenuExit; } // Settings - if (menuBarFlag & menuBar_Settings) + if (menuBarFlag & kMenubarSettings) if (Common::Rect(buts[2][1], scrollPos, buts[2][0] + buts[2][1], scrollPos + 32).contains(Pos)) { - mouseOnItem = menu_MAIN_PREF; + mouseOnItem = kMainMenuPrefs; } // Load - if (menuBarFlag & menuBar_Restore) + if (menuBarFlag & kMenubarRestore) if (Common::Rect(buts[1][1], scrollPos, buts[1][0] + buts[1][1], scrollPos + 32).contains(Pos)) { - mouseOnItem = menu_MAIN_REST; + mouseOnItem = kMainMenuLoad; } // Save - if (menuBarFlag & menuBar_Save) + if (menuBarFlag & kMenubarSave) if (Common::Rect(buts[0][1], scrollPos, buts[0][0] + buts[0][1], scrollPos + 32).contains(Pos)) { - mouseOnItem = menu_MAIN_SAVE; + mouseOnItem = kMainMenuSave; } if (lastItem != mouseOnItem) { @@ -718,20 +717,20 @@ void MenuNemesis::process(uint32 deltatime) { if (redraw) { _engine->getRenderManager()->blitSurfaceToMenu(menubar, 64, scrollPos); - if (menuBarFlag & menuBar_Exit) - if (mouseOnItem == menu_MAIN_EXIT) + if (menuBarFlag & kMenubarExit) + if (mouseOnItem == kMainMenuExit) _engine->getRenderManager()->blitSurfaceToMenu(but[3][frm], buts[3][1], scrollPos); - if (menuBarFlag & menuBar_Settings) - if (mouseOnItem == menu_MAIN_PREF) + if (menuBarFlag & kMenubarSettings) + if (mouseOnItem == kMainMenuPrefs) _engine->getRenderManager()->blitSurfaceToMenu(but[2][frm], buts[2][1], scrollPos); - if (menuBarFlag & menuBar_Restore) - if (mouseOnItem == menu_MAIN_REST) + if (menuBarFlag & kMenubarRestore) + if (mouseOnItem == kMainMenuLoad) _engine->getRenderManager()->blitSurfaceToMenu(but[1][frm], buts[1][1], scrollPos); - if (menuBarFlag & menuBar_Save) - if (mouseOnItem == menu_MAIN_SAVE) + if (menuBarFlag & kMenubarSave) + if (mouseOnItem == kMainMenuSave) _engine->getRenderManager()->blitSurfaceToMenu(but[0][frm], buts[0][1], scrollPos); redraw = false; diff --git a/engines/zvision/scripting/menu.h b/engines/zvision/scripting/menu.h index ebe0bb50ac..a88587966f 100644 --- a/engines/zvision/scripting/menu.h +++ b/engines/zvision/scripting/menu.h @@ -32,12 +32,12 @@ namespace ZVision { enum menuBar { - menuBar_Exit = 0x1, - menuBar_Settings = 0x2, - menuBar_Restore = 0x4, - menuBar_Save = 0x8, - menuBar_Items = 0x100, - menuBar_Magic = 0x200 + kMenubarExit = 0x1, + kMenubarSettings = 0x2, + kMenubarRestore = 0x4, + kMenubarSave = 0x8, + kMenubarItems = 0x100, + kMenubarMagic = 0x200 }; class MenuHandler { @@ -84,12 +84,6 @@ private: bool scrolled[3]; int16 scrollPos[3]; - enum { - menu_ITEM = 0, - menu_MAGIC = 1, - menu_MAIN = 2 - }; - bool clean; bool redraw; diff --git a/engines/zvision/scripting/script_manager.h b/engines/zvision/scripting/script_manager.h index c5ade08e14..9f0f2f6e10 100644 --- a/engines/zvision/scripting/script_manager.h +++ b/engines/zvision/scripting/script_manager.h @@ -94,7 +94,12 @@ enum StateKey { StateKey_Inv_Cnt_Slot = 100, StateKey_Inv_1_Slot = 101, StateKey_Inv_49_Slot = 149, - StateKey_Inv_TotalSlots = 150 + // ZGI only + StateKey_Inv_TotalSlots = 150, + StateKey_Inv_StartSlot = 151, + StateKey_Spell_1 = 191, + StateKey_Active_Spell = 205, + StateKey_Reversed_Spellbooc = 206 }; struct Location { -- cgit v1.2.3 From 00a252fdc561b31379ddc5f568121b8040986add Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 26 Dec 2014 03:58:37 +0200 Subject: ZVISION: Slight cleanup --- engines/zvision/core/save_manager.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'engines') diff --git a/engines/zvision/core/save_manager.cpp b/engines/zvision/core/save_manager.cpp index 20bd39fde5..b45742154d 100644 --- a/engines/zvision/core/save_manager.cpp +++ b/engines/zvision/core/save_manager.cpp @@ -78,9 +78,6 @@ bool SaveManager::scummVMSaveLoadDialog(bool isSave) { } void SaveManager::saveGame(uint slot, const Common::String &saveName) { - // The games only support 20 slots - //assert(slot <= 1 && slot <= 20); - Common::SaveFileManager *saveFileManager = g_system->getSavefileManager(); Common::OutSaveFile *file = saveFileManager->openForSaving(_engine->generateSaveFileName(slot)); @@ -124,7 +121,6 @@ void SaveManager::autoSave() { } void SaveManager::writeSaveGameHeader(Common::OutSaveFile *file, const Common::String &saveName) { - file->writeUint32BE(SAVEGAME_ID); // Write version @@ -148,9 +144,6 @@ void SaveManager::writeSaveGameHeader(Common::OutSaveFile *file, const Common::S } Common::Error SaveManager::loadGame(uint slot) { - // The games only support 20 slots - //assert(slot <= 1 && slot <= 20); - Common::SeekableReadStream *saveFile = getSlotFile(slot); if (saveFile == 0) { return Common::kPathDoesNotExist; @@ -226,7 +219,13 @@ bool SaveManager::readSaveGameHeader(Common::InSaveFile *in, SaveGameHeader &hea // Check that the save version isn't newer than this binary if (header.version > SAVE_VERSION) { uint tempVersion = header.version; - GUI::MessageDialog dialog(Common::String::format("This save file uses version %u, but this engine only supports up to version %d. You will need an updated version of the engine to use this save file.", tempVersion, SAVE_VERSION), "OK"); + GUI::MessageDialog dialog( + Common::String::format( + "This save file uses version %u, but this engine only " + "supports up to version %d. You will need an updated version " + "of the engine to use this save file.", tempVersion, SAVE_VERSION + ), + "OK"); dialog.runModal(); } -- cgit v1.2.3 From 4d0ebfaa2285e2741a134db36fb4f5bd0317784d Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 26 Dec 2014 04:03:20 +0200 Subject: ZVISION: Move the save manager together with the other file classes --- engines/zvision/core/save_manager.cpp | 294 --------------------- engines/zvision/core/save_manager.h | 106 -------- engines/zvision/detection.cpp | 2 +- engines/zvision/file/save_manager.cpp | 294 +++++++++++++++++++++ engines/zvision/file/save_manager.h | 106 ++++++++ engines/zvision/module.mk | 2 +- engines/zvision/scripting/actions.cpp | 2 +- .../zvision/scripting/controls/save_control.cpp | 2 +- engines/zvision/scripting/script_manager.cpp | 2 +- engines/zvision/zvision.cpp | 2 +- 10 files changed, 406 insertions(+), 406 deletions(-) delete mode 100644 engines/zvision/core/save_manager.cpp delete mode 100644 engines/zvision/core/save_manager.h create mode 100644 engines/zvision/file/save_manager.cpp create mode 100644 engines/zvision/file/save_manager.h (limited to 'engines') diff --git a/engines/zvision/core/save_manager.cpp b/engines/zvision/core/save_manager.cpp deleted file mode 100644 index b45742154d..0000000000 --- a/engines/zvision/core/save_manager.cpp +++ /dev/null @@ -1,294 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "common/scummsys.h" - -#include "zvision/core/save_manager.h" -#include "zvision/zvision.h" -#include "zvision/scripting/script_manager.h" -#include "zvision/graphics/render_manager.h" - -#include "common/system.h" -#include "common/translation.h" - -#include "graphics/surface.h" -#include "graphics/thumbnail.h" - -#include "gui/message.h" -#include "gui/saveload.h" - -namespace ZVision { - -const uint32 SaveManager::SAVEGAME_ID = MKTAG('Z', 'E', 'N', 'G'); - -bool SaveManager::scummVMSaveLoadDialog(bool isSave) { - GUI::SaveLoadChooser *dialog; - Common::String desc; - int slot; - - if (isSave) { - dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true); - - slot = dialog->runModalWithCurrentTarget(); - desc = dialog->getResultString(); - - if (desc.empty()) { - // create our own description for the saved game, the user didnt enter it - desc = dialog->createDefaultSaveDescription(slot); - } - - if (desc.size() > 28) - desc = Common::String(desc.c_str(), 28); - } else { - dialog = new GUI::SaveLoadChooser(_("Restore game:"), _("Restore"), false); - slot = dialog->runModalWithCurrentTarget(); - } - - delete dialog; - - if (slot < 0) - return false; - - if (isSave) { - saveGame(slot, desc); - return true; - } else { - Common::ErrorCode result = loadGame(slot).getCode(); - return (result == Common::kNoError); - } -} - -void SaveManager::saveGame(uint slot, const Common::String &saveName) { - Common::SaveFileManager *saveFileManager = g_system->getSavefileManager(); - Common::OutSaveFile *file = saveFileManager->openForSaving(_engine->generateSaveFileName(slot)); - - writeSaveGameHeader(file, saveName); - - _engine->getScriptManager()->serialize(file); - - file->finalize(); - delete file; -} - -void SaveManager::saveGame(uint slot, const Common::String &saveName, Common::MemoryWriteStreamDynamic *stream) { - Common::SaveFileManager *saveFileManager = g_system->getSavefileManager(); - Common::OutSaveFile *file = saveFileManager->openForSaving(_engine->generateSaveFileName(slot)); - - writeSaveGameHeader(file, saveName); - - file->write(stream->getData(), stream->size()); - - file->finalize(); - delete file; -} - -void SaveManager::saveGameBuffered(uint slot, const Common::String &saveName) { - if (_tempSave) { - saveGame(slot, saveName, _tempSave); - flushSaveBuffer(); - } -} - -void SaveManager::autoSave() { - Common::OutSaveFile *file = g_system->getSavefileManager()->openForSaving(_engine->generateAutoSaveFileName()); - - writeSaveGameHeader(file, "auto"); - - _engine->getScriptManager()->serialize(file); - - // Cleanup - file->finalize(); - delete file; -} - -void SaveManager::writeSaveGameHeader(Common::OutSaveFile *file, const Common::String &saveName) { - file->writeUint32BE(SAVEGAME_ID); - - // Write version - file->writeByte(SAVE_VERSION); - - // Write savegame name - file->writeString(saveName); - file->writeByte(0); - - // Create a thumbnail and save it - Graphics::saveThumbnail(*file); - - // Write out the save date/time - TimeDate td; - g_system->getTimeAndDate(td); - file->writeSint16LE(td.tm_year + 1900); - file->writeSint16LE(td.tm_mon + 1); - file->writeSint16LE(td.tm_mday); - file->writeSint16LE(td.tm_hour); - file->writeSint16LE(td.tm_min); -} - -Common::Error SaveManager::loadGame(uint slot) { - Common::SeekableReadStream *saveFile = getSlotFile(slot); - if (saveFile == 0) { - return Common::kPathDoesNotExist; - } - - // Read the header - SaveGameHeader header; - if (!readSaveGameHeader(saveFile, header)) { - return Common::kUnknownError; - } - - ScriptManager *scriptManager = _engine->getScriptManager(); - // Update the state table values - scriptManager->deserialize(saveFile); - - delete saveFile; - if (header.thumbnail) - delete header.thumbnail; - - return Common::kNoError; -} - -Common::Error SaveManager::loadGame(const Common::String &saveName) { - Common::File *saveFile = _engine->getSearchManager()->openFile(saveName); - if (saveFile == NULL) { - saveFile = new Common::File; - if (!saveFile->open(saveName)) { - delete saveFile; - return Common::kPathDoesNotExist; - } - } - - // Read the header - SaveGameHeader header; - if (!readSaveGameHeader(saveFile, header)) { - return Common::kUnknownError; - } - - ScriptManager *scriptManager = _engine->getScriptManager(); - // Update the state table values - scriptManager->deserialize(saveFile); - - delete saveFile; - if (header.thumbnail) - delete header.thumbnail; - - return Common::kNoError; -} - -bool SaveManager::readSaveGameHeader(Common::InSaveFile *in, SaveGameHeader &header) { - uint32 tag = in->readUint32BE(); - // Check if it's original savegame than fill header structure - if (tag == MKTAG('Z', 'N', 'S', 'G')) { - header.saveYear = 0; - header.saveMonth = 0; - header.saveDay = 0; - header.saveHour = 0; - header.saveMinutes = 0; - header.saveName = "Original Save"; - header.thumbnail = NULL; - header.version = SAVE_ORIGINAL; - in->seek(-4, SEEK_CUR); - return true; - } - if (tag != SAVEGAME_ID) { - warning("File is not a ZVision save file. Aborting load"); - return false; - } - - // Read in the version - header.version = in->readByte(); - - // Check that the save version isn't newer than this binary - if (header.version > SAVE_VERSION) { - uint tempVersion = header.version; - GUI::MessageDialog dialog( - Common::String::format( - "This save file uses version %u, but this engine only " - "supports up to version %d. You will need an updated version " - "of the engine to use this save file.", tempVersion, SAVE_VERSION - ), - "OK"); - dialog.runModal(); - } - - // Read in the save name - header.saveName.clear(); - char ch; - while ((ch = (char)in->readByte()) != '\0') - header.saveName += ch; - - // Get the thumbnail - header.thumbnail = Graphics::loadThumbnail(*in); - if (!header.thumbnail) - return false; - - // Read in save date/time - header.saveYear = in->readSint16LE(); - header.saveMonth = in->readSint16LE(); - header.saveDay = in->readSint16LE(); - header.saveHour = in->readSint16LE(); - header.saveMinutes = in->readSint16LE(); - - return true; -} - -Common::SeekableReadStream *SaveManager::getSlotFile(uint slot) { - Common::SeekableReadStream *saveFile = g_system->getSavefileManager()->openForLoading(_engine->generateSaveFileName(slot)); - if (saveFile == NULL) { - // Try to load standard save file - Common::String filename; - if (_engine->getGameId() == GID_GRANDINQUISITOR) - filename = Common::String::format("inqsav%u.sav", slot); - else if (_engine->getGameId() == GID_NEMESIS) - filename = Common::String::format("nemsav%u.sav", slot); - - saveFile = _engine->getSearchManager()->openFile(filename); - if (saveFile == NULL) { - Common::File *tmpFile = new Common::File; - if (!tmpFile->open(filename)) { - delete tmpFile; - } else { - saveFile = tmpFile; - } - } - - } - - return saveFile; -} - -void SaveManager::prepareSaveBuffer() { - if (_tempSave) - delete _tempSave; - - _tempSave = new Common::MemoryWriteStreamDynamic; - - _engine->getScriptManager()->serialize(_tempSave); -} - -void SaveManager::flushSaveBuffer() { - if (_tempSave) - delete _tempSave; - - _tempSave = NULL; -} - -} // End of namespace ZVision diff --git a/engines/zvision/core/save_manager.h b/engines/zvision/core/save_manager.h deleted file mode 100644 index 75841331e7..0000000000 --- a/engines/zvision/core/save_manager.h +++ /dev/null @@ -1,106 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#ifndef ZVISION_SAVE_MANAGER_H -#define ZVISION_SAVE_MANAGER_H - -#include "common/savefile.h" -#include "common/memstream.h" - -namespace Common { -class String; -} - -namespace Graphics { -struct Surface; -} - -namespace ZVision { - -class ZVision; - -struct SaveGameHeader { - byte version; - Common::String saveName; - Graphics::Surface *thumbnail; - int saveYear, saveMonth, saveDay; - int saveHour, saveMinutes; -}; - -class SaveManager { -public: - SaveManager(ZVision *engine) : _engine(engine), _tempSave(NULL) {} - ~SaveManager() { - flushSaveBuffer(); - } - -private: - ZVision *_engine; - static const uint32 SAVEGAME_ID; - - enum { - SAVE_ORIGINAL = 0, - SAVE_VERSION = 1 - }; - - Common::MemoryWriteStreamDynamic *_tempSave; - -public: - /** - * Called every room change. Saves the state of the room just before - * we switched rooms. Uses ZVision::generateAutoSaveFileName() to - * create the save file name. - */ - void autoSave(); - /** - * Copies the data from the last auto-save into a new save file. We - * can't use the current state data because the save menu *IS* a room. - * The file is named using ZVision::generateSaveFileName(slot) - * - * @param slot The save slot this save pertains to. Must be [1, 20] - * @param saveName The internal name for this save. This is NOT the name of the actual save file. - */ - void saveGame(uint slot, const Common::String &saveName); - void saveGame(uint slot, const Common::String &saveName, Common::MemoryWriteStreamDynamic *stream); - void saveGameBuffered(uint slot, const Common::String &saveName); - /** - * Loads the state data from the save file that slot references. Uses - * ZVision::generateSaveFileName(slot) to get the save file name. - * - * @param slot The save slot to load. Must be [1, 20] - */ - Common::Error loadGame(uint slot); - Common::Error loadGame(const Common::String &saveName); - - Common::SeekableReadStream *getSlotFile(uint slot); - bool readSaveGameHeader(Common::SeekableReadStream *in, SaveGameHeader &header); - - void prepareSaveBuffer(); - void flushSaveBuffer(); - bool scummVMSaveLoadDialog(bool isSave); -private: - void writeSaveGameHeader(Common::OutSaveFile *file, const Common::String &saveName); -}; - -} // End of namespace ZVision - -#endif diff --git a/engines/zvision/detection.cpp b/engines/zvision/detection.cpp index ebf5bdcfdd..b8d6a74eee 100644 --- a/engines/zvision/detection.cpp +++ b/engines/zvision/detection.cpp @@ -26,7 +26,7 @@ #include "zvision/zvision.h" #include "zvision/detection.h" -#include "zvision/core/save_manager.h" +#include "zvision/file/save_manager.h" #include "zvision/scripting/script_manager.h" #include "common/translation.h" diff --git a/engines/zvision/file/save_manager.cpp b/engines/zvision/file/save_manager.cpp new file mode 100644 index 0000000000..05df834497 --- /dev/null +++ b/engines/zvision/file/save_manager.cpp @@ -0,0 +1,294 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "common/scummsys.h" + +#include "zvision/zvision.h" +#include "zvision/file/save_manager.h" +#include "zvision/scripting/script_manager.h" +#include "zvision/graphics/render_manager.h" + +#include "common/system.h" +#include "common/translation.h" + +#include "graphics/surface.h" +#include "graphics/thumbnail.h" + +#include "gui/message.h" +#include "gui/saveload.h" + +namespace ZVision { + +const uint32 SaveManager::SAVEGAME_ID = MKTAG('Z', 'E', 'N', 'G'); + +bool SaveManager::scummVMSaveLoadDialog(bool isSave) { + GUI::SaveLoadChooser *dialog; + Common::String desc; + int slot; + + if (isSave) { + dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true); + + slot = dialog->runModalWithCurrentTarget(); + desc = dialog->getResultString(); + + if (desc.empty()) { + // create our own description for the saved game, the user didnt enter it + desc = dialog->createDefaultSaveDescription(slot); + } + + if (desc.size() > 28) + desc = Common::String(desc.c_str(), 28); + } else { + dialog = new GUI::SaveLoadChooser(_("Restore game:"), _("Restore"), false); + slot = dialog->runModalWithCurrentTarget(); + } + + delete dialog; + + if (slot < 0) + return false; + + if (isSave) { + saveGame(slot, desc); + return true; + } else { + Common::ErrorCode result = loadGame(slot).getCode(); + return (result == Common::kNoError); + } +} + +void SaveManager::saveGame(uint slot, const Common::String &saveName) { + Common::SaveFileManager *saveFileManager = g_system->getSavefileManager(); + Common::OutSaveFile *file = saveFileManager->openForSaving(_engine->generateSaveFileName(slot)); + + writeSaveGameHeader(file, saveName); + + _engine->getScriptManager()->serialize(file); + + file->finalize(); + delete file; +} + +void SaveManager::saveGame(uint slot, const Common::String &saveName, Common::MemoryWriteStreamDynamic *stream) { + Common::SaveFileManager *saveFileManager = g_system->getSavefileManager(); + Common::OutSaveFile *file = saveFileManager->openForSaving(_engine->generateSaveFileName(slot)); + + writeSaveGameHeader(file, saveName); + + file->write(stream->getData(), stream->size()); + + file->finalize(); + delete file; +} + +void SaveManager::saveGameBuffered(uint slot, const Common::String &saveName) { + if (_tempSave) { + saveGame(slot, saveName, _tempSave); + flushSaveBuffer(); + } +} + +void SaveManager::autoSave() { + Common::OutSaveFile *file = g_system->getSavefileManager()->openForSaving(_engine->generateAutoSaveFileName()); + + writeSaveGameHeader(file, "auto"); + + _engine->getScriptManager()->serialize(file); + + // Cleanup + file->finalize(); + delete file; +} + +void SaveManager::writeSaveGameHeader(Common::OutSaveFile *file, const Common::String &saveName) { + file->writeUint32BE(SAVEGAME_ID); + + // Write version + file->writeByte(SAVE_VERSION); + + // Write savegame name + file->writeString(saveName); + file->writeByte(0); + + // Create a thumbnail and save it + Graphics::saveThumbnail(*file); + + // Write out the save date/time + TimeDate td; + g_system->getTimeAndDate(td); + file->writeSint16LE(td.tm_year + 1900); + file->writeSint16LE(td.tm_mon + 1); + file->writeSint16LE(td.tm_mday); + file->writeSint16LE(td.tm_hour); + file->writeSint16LE(td.tm_min); +} + +Common::Error SaveManager::loadGame(uint slot) { + Common::SeekableReadStream *saveFile = getSlotFile(slot); + if (saveFile == 0) { + return Common::kPathDoesNotExist; + } + + // Read the header + SaveGameHeader header; + if (!readSaveGameHeader(saveFile, header)) { + return Common::kUnknownError; + } + + ScriptManager *scriptManager = _engine->getScriptManager(); + // Update the state table values + scriptManager->deserialize(saveFile); + + delete saveFile; + if (header.thumbnail) + delete header.thumbnail; + + return Common::kNoError; +} + +Common::Error SaveManager::loadGame(const Common::String &saveName) { + Common::File *saveFile = _engine->getSearchManager()->openFile(saveName); + if (saveFile == NULL) { + saveFile = new Common::File; + if (!saveFile->open(saveName)) { + delete saveFile; + return Common::kPathDoesNotExist; + } + } + + // Read the header + SaveGameHeader header; + if (!readSaveGameHeader(saveFile, header)) { + return Common::kUnknownError; + } + + ScriptManager *scriptManager = _engine->getScriptManager(); + // Update the state table values + scriptManager->deserialize(saveFile); + + delete saveFile; + if (header.thumbnail) + delete header.thumbnail; + + return Common::kNoError; +} + +bool SaveManager::readSaveGameHeader(Common::InSaveFile *in, SaveGameHeader &header) { + uint32 tag = in->readUint32BE(); + // Check if it's original savegame than fill header structure + if (tag == MKTAG('Z', 'N', 'S', 'G')) { + header.saveYear = 0; + header.saveMonth = 0; + header.saveDay = 0; + header.saveHour = 0; + header.saveMinutes = 0; + header.saveName = "Original Save"; + header.thumbnail = NULL; + header.version = SAVE_ORIGINAL; + in->seek(-4, SEEK_CUR); + return true; + } + if (tag != SAVEGAME_ID) { + warning("File is not a ZVision save file. Aborting load"); + return false; + } + + // Read in the version + header.version = in->readByte(); + + // Check that the save version isn't newer than this binary + if (header.version > SAVE_VERSION) { + uint tempVersion = header.version; + GUI::MessageDialog dialog( + Common::String::format( + "This save file uses version %u, but this engine only " + "supports up to version %d. You will need an updated version " + "of the engine to use this save file.", tempVersion, SAVE_VERSION + ), + "OK"); + dialog.runModal(); + } + + // Read in the save name + header.saveName.clear(); + char ch; + while ((ch = (char)in->readByte()) != '\0') + header.saveName += ch; + + // Get the thumbnail + header.thumbnail = Graphics::loadThumbnail(*in); + if (!header.thumbnail) + return false; + + // Read in save date/time + header.saveYear = in->readSint16LE(); + header.saveMonth = in->readSint16LE(); + header.saveDay = in->readSint16LE(); + header.saveHour = in->readSint16LE(); + header.saveMinutes = in->readSint16LE(); + + return true; +} + +Common::SeekableReadStream *SaveManager::getSlotFile(uint slot) { + Common::SeekableReadStream *saveFile = g_system->getSavefileManager()->openForLoading(_engine->generateSaveFileName(slot)); + if (saveFile == NULL) { + // Try to load standard save file + Common::String filename; + if (_engine->getGameId() == GID_GRANDINQUISITOR) + filename = Common::String::format("inqsav%u.sav", slot); + else if (_engine->getGameId() == GID_NEMESIS) + filename = Common::String::format("nemsav%u.sav", slot); + + saveFile = _engine->getSearchManager()->openFile(filename); + if (saveFile == NULL) { + Common::File *tmpFile = new Common::File; + if (!tmpFile->open(filename)) { + delete tmpFile; + } else { + saveFile = tmpFile; + } + } + + } + + return saveFile; +} + +void SaveManager::prepareSaveBuffer() { + if (_tempSave) + delete _tempSave; + + _tempSave = new Common::MemoryWriteStreamDynamic; + + _engine->getScriptManager()->serialize(_tempSave); +} + +void SaveManager::flushSaveBuffer() { + if (_tempSave) + delete _tempSave; + + _tempSave = NULL; +} + +} // End of namespace ZVision diff --git a/engines/zvision/file/save_manager.h b/engines/zvision/file/save_manager.h new file mode 100644 index 0000000000..75841331e7 --- /dev/null +++ b/engines/zvision/file/save_manager.h @@ -0,0 +1,106 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef ZVISION_SAVE_MANAGER_H +#define ZVISION_SAVE_MANAGER_H + +#include "common/savefile.h" +#include "common/memstream.h" + +namespace Common { +class String; +} + +namespace Graphics { +struct Surface; +} + +namespace ZVision { + +class ZVision; + +struct SaveGameHeader { + byte version; + Common::String saveName; + Graphics::Surface *thumbnail; + int saveYear, saveMonth, saveDay; + int saveHour, saveMinutes; +}; + +class SaveManager { +public: + SaveManager(ZVision *engine) : _engine(engine), _tempSave(NULL) {} + ~SaveManager() { + flushSaveBuffer(); + } + +private: + ZVision *_engine; + static const uint32 SAVEGAME_ID; + + enum { + SAVE_ORIGINAL = 0, + SAVE_VERSION = 1 + }; + + Common::MemoryWriteStreamDynamic *_tempSave; + +public: + /** + * Called every room change. Saves the state of the room just before + * we switched rooms. Uses ZVision::generateAutoSaveFileName() to + * create the save file name. + */ + void autoSave(); + /** + * Copies the data from the last auto-save into a new save file. We + * can't use the current state data because the save menu *IS* a room. + * The file is named using ZVision::generateSaveFileName(slot) + * + * @param slot The save slot this save pertains to. Must be [1, 20] + * @param saveName The internal name for this save. This is NOT the name of the actual save file. + */ + void saveGame(uint slot, const Common::String &saveName); + void saveGame(uint slot, const Common::String &saveName, Common::MemoryWriteStreamDynamic *stream); + void saveGameBuffered(uint slot, const Common::String &saveName); + /** + * Loads the state data from the save file that slot references. Uses + * ZVision::generateSaveFileName(slot) to get the save file name. + * + * @param slot The save slot to load. Must be [1, 20] + */ + Common::Error loadGame(uint slot); + Common::Error loadGame(const Common::String &saveName); + + Common::SeekableReadStream *getSlotFile(uint slot); + bool readSaveGameHeader(Common::SeekableReadStream *in, SaveGameHeader &header); + + void prepareSaveBuffer(); + void flushSaveBuffer(); + bool scummVMSaveLoadDialog(bool isSave); +private: + void writeSaveGameHeader(Common::OutSaveFile *file, const Common::String &saveName); +}; + +} // End of namespace ZVision + +#endif diff --git a/engines/zvision/module.mk b/engines/zvision/module.mk index 6955d62534..8edd67b352 100644 --- a/engines/zvision/module.mk +++ b/engines/zvision/module.mk @@ -4,9 +4,9 @@ MODULE_OBJS := \ core/console.o \ core/clock.o \ core/events.o \ - core/save_manager.o \ detection.o \ file/lzss_read_stream.o \ + file/save_manager.o \ file/search_manager.o \ file/zfs_archive.o \ graphics/cursors/cursor_manager.o \ diff --git a/engines/zvision/scripting/actions.cpp b/engines/zvision/scripting/actions.cpp index be2079736e..ebbd09c8b9 100644 --- a/engines/zvision/scripting/actions.cpp +++ b/engines/zvision/scripting/actions.cpp @@ -29,6 +29,7 @@ #include "zvision/graphics/render_manager.h" #include "zvision/sound/zork_raw.h" #include "zvision/video/zork_avi_decoder.h" +#include "zvision/file/save_manager.h" #include "zvision/scripting/sidefx/timer_node.h" #include "zvision/scripting/sidefx/music_node.h" #include "zvision/scripting/sidefx/syncsound_node.h" @@ -42,7 +43,6 @@ #include "zvision/graphics/effects/fog.h" #include "zvision/graphics/effects/light.h" #include "zvision/graphics/effects/wave.h" -#include "zvision/core/save_manager.h" #include "zvision/graphics/cursors/cursor_manager.h" #include "common/file.h" diff --git a/engines/zvision/scripting/controls/save_control.cpp b/engines/zvision/scripting/controls/save_control.cpp index b35611feca..3a4dc47fe8 100644 --- a/engines/zvision/scripting/controls/save_control.cpp +++ b/engines/zvision/scripting/controls/save_control.cpp @@ -29,7 +29,7 @@ #include "zvision/scripting/script_manager.h" #include "zvision/text/string_manager.h" -#include "zvision/core/save_manager.h" +#include "zvision/file/save_manager.h" #include "common/str.h" #include "common/stream.h" diff --git a/engines/zvision/scripting/script_manager.cpp b/engines/zvision/scripting/script_manager.cpp index 4c1e69072d..2a4aa5fed0 100644 --- a/engines/zvision/scripting/script_manager.cpp +++ b/engines/zvision/scripting/script_manager.cpp @@ -27,7 +27,7 @@ #include "zvision/zvision.h" #include "zvision/graphics/render_manager.h" #include "zvision/graphics/cursors/cursor_manager.h" -#include "zvision/core/save_manager.h" +#include "zvision/file/save_manager.h" #include "zvision/scripting/actions.h" #include "zvision/scripting/sidefx/timer_node.h" diff --git a/engines/zvision/zvision.cpp b/engines/zvision/zvision.cpp index f692969942..11e417d4ac 100644 --- a/engines/zvision/zvision.cpp +++ b/engines/zvision/zvision.cpp @@ -27,7 +27,7 @@ #include "zvision/scripting/script_manager.h" #include "zvision/graphics/render_manager.h" #include "zvision/graphics/cursors/cursor_manager.h" -#include "zvision/core/save_manager.h" +#include "zvision/file/save_manager.h" #include "zvision/text/string_manager.h" #include "zvision/detection.h" #include "zvision/scripting/menu.h" -- cgit v1.2.3 From e4b2913e4ac5584803e65008c44addea05c3892a Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 26 Dec 2014 04:05:48 +0200 Subject: ZVISION: Reorder the detection entries --- engines/zvision/detection.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'engines') diff --git a/engines/zvision/detection.cpp b/engines/zvision/detection.cpp index b8d6a74eee..a361239e9e 100644 --- a/engines/zvision/detection.cpp +++ b/engines/zvision/detection.cpp @@ -100,28 +100,28 @@ static const ZVisionGameDescription gameDescriptions[] = { }, { - // Zork Grand Inquisitor English demo version + // Zork Grand Inquisitor English DVD version { "zgi", - "Demo", - AD_ENTRY1s("SCRIPTS.ZFS", "71a2494fd2fb999347deb13401e9b998", 304239), + "DVD", + AD_ENTRY1s("SCRIPTS.ZFS", "03157a3399513bfaaf8dc6d5ab798b36", 8433326), Common::EN_ANY, Common::kPlatformWindows, - ADGF_DEMO, + ADGF_NO_FLAGS, GUIO1(GUIO_NONE) }, GID_GRANDINQUISITOR }, { - // Zork Grand Inquisitor English DVD version + // Zork Grand Inquisitor English demo version { "zgi", - "DVD", - AD_ENTRY1s("SCRIPTS.ZFS", "03157a3399513bfaaf8dc6d5ab798b36", 8433326), + "Demo", + AD_ENTRY1s("SCRIPTS.ZFS", "71a2494fd2fb999347deb13401e9b998", 304239), Common::EN_ANY, Common::kPlatformWindows, - ADGF_NO_FLAGS, + ADGF_DEMO, GUIO1(GUIO_NONE) }, GID_GRANDINQUISITOR -- cgit v1.2.3 From 2350eca546396775c6e9ac9875ebd59bcc17663f Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 26 Dec 2014 12:04:21 +0200 Subject: ZVISION: Remove some unused actions. Cleanup --- engines/zvision/scripting/actions.cpp | 53 +++++-------------------- engines/zvision/scripting/actions.h | 26 ------------ engines/zvision/scripting/scr_file_handling.cpp | 6 ++- 3 files changed, 13 insertions(+), 72 deletions(-) (limited to 'engines') diff --git a/engines/zvision/scripting/actions.cpp b/engines/zvision/scripting/actions.cpp index ebbd09c8b9..c26a93f529 100644 --- a/engines/zvision/scripting/actions.cpp +++ b/engines/zvision/scripting/actions.cpp @@ -242,23 +242,6 @@ bool ActionDisableControl::execute() { return true; } -////////////////////////////////////////////////////////////////////////////// -// ActionDisableVenus -////////////////////////////////////////////////////////////////////////////// - -ActionDisableVenus::ActionDisableVenus(ZVision *engine, int32 slotkey, const Common::String &line) : - ResultAction(engine, slotkey) { - _key = 0; - - sscanf(line.c_str(), "%d", &_key); -} - -bool ActionDisableVenus::execute() { - _engine->getScriptManager()->setStateValue(_key, 0); - - return true; -} - ////////////////////////////////////////////////////////////////////////////// // ActionDisplayMessage ////////////////////////////////////////////////////////////////////////////// @@ -295,7 +278,7 @@ bool ActionDissolve::execute() { } ////////////////////////////////////////////////////////////////////////////// -// ActionDistort +// ActionDistort - only used by Zork: Nemesis for the "treatment" puzzle in the Sanitarium (aj30) ////////////////////////////////////////////////////////////////////////////// ActionDistort::ActionDistort(ZVision *engine, int32 slotkey, const Common::String &line) : @@ -406,7 +389,7 @@ bool ActionInventory::execute() { } ////////////////////////////////////////////////////////////////////////////// -// ActionKill +// ActionKill - only used by ZGI ////////////////////////////////////////////////////////////////////////////// ActionKill::ActionKill(ZVision *engine, int32 slotkey, const Common::String &line) : @@ -735,13 +718,13 @@ bool ActionRegion::execute() { if (_engine->getScriptManager()->getSideFX(_slotKey)) return true; - Effect *effct = NULL; + Effect *effect = NULL; switch (_type) { case 0: { uint16 centerX, centerY, frames; double amplitude, waveln, speed; sscanf(_custom.c_str(), "%hu,%hu,%hu,%lf,%lf,%lf,", ¢erX, ¢erY, &frames, &litude, &waveln, &speed); - effct = new WaveFx(_engine, _slotKey, _rect, _unk1, frames, centerX, centerY, amplitude, waveln, speed); + effect = new WaveFx(_engine, _slotKey, _rect, _unk1, frames, centerX, centerY, amplitude, waveln, speed); } break; case 1: { @@ -753,7 +736,7 @@ bool ActionRegion::execute() { int8 minD; int8 maxD; EffectMap *_map = _engine->getRenderManager()->makeEffectMap(Common::Point(aX, aY), aD, _rect, &minD, &maxD); - effct = new LightFx(_engine, _slotKey, _rect, _unk1, _map, atoi(_custom.c_str()), minD, maxD); + effect = new LightFx(_engine, _slotKey, _rect, _unk1, _map, atoi(_custom.c_str()), minD, maxD); } break; case 9: { @@ -769,16 +752,16 @@ bool ActionRegion::execute() { _rect.setHeight(tempMask.h); EffectMap *_map = _engine->getRenderManager()->makeEffectMap(tempMask, 0); - effct = new FogFx(_engine, _slotKey, _rect, _unk1, _map, Common::String(buf)); + effect = new FogFx(_engine, _slotKey, _rect, _unk1, _map, Common::String(buf)); } break; default: break; } - if (effct) { - _engine->getScriptManager()->addSideFX(new RegionNode(_engine, _slotKey, effct, _delay)); - _engine->getRenderManager()->addEffect(effct); + if (effect) { + _engine->getScriptManager()->addSideFX(new RegionNode(_engine, _slotKey, effect, _delay)); + _engine->getRenderManager()->addEffect(effect); } return true; @@ -899,24 +882,6 @@ bool ActionSetScreen::execute() { return true; } -////////////////////////////////////////////////////////////////////////////// -// ActionSetVenus -////////////////////////////////////////////////////////////////////////////// - -ActionSetVenus::ActionSetVenus(ZVision *engine, int32 slotkey, const Common::String &line) : - ResultAction(engine, slotkey) { - _key = 0; - - sscanf(line.c_str(), "%d", &_key); -} - -bool ActionSetVenus::execute() { - if (_engine->getScriptManager()->getStateValue(_key)) - _engine->getScriptManager()->setStateValue(StateKey_Venus, _key); - - return true; -} - ////////////////////////////////////////////////////////////////////////////// // ActionStop ////////////////////////////////////////////////////////////////////////////// diff --git a/engines/zvision/scripting/actions.h b/engines/zvision/scripting/actions.h index 3501372c7f..8d43309b74 100644 --- a/engines/zvision/scripting/actions.h +++ b/engines/zvision/scripting/actions.h @@ -124,14 +124,6 @@ private: uint8 _action; }; -class ActionDebug : public ResultAction { -public: - ActionDebug(ZVision *engine, int32 slotkey, const Common::String &line); - bool execute(); - -private: -}; - class ActionDelayRender : public ResultAction { public: ActionDelayRender(ZVision *engine, int32 slotkey, const Common::String &line); @@ -150,15 +142,6 @@ private: uint32 _key; }; -class ActionDisableVenus : public ResultAction { -public: - ActionDisableVenus(ZVision *engine, int32 slotkey, const Common::String &line); - bool execute(); - -private: - int32 _key; -}; - class ActionDisplayMessage : public ResultAction { public: ActionDisplayMessage(ZVision *engine, int32 slotkey, const Common::String &line); @@ -397,15 +380,6 @@ private: Common::String _fileName; }; -class ActionSetVenus : public ResultAction { -public: - ActionSetVenus(ZVision *engine, int32 slotkey, const Common::String &line); - bool execute(); - -private: - int32 _key; -}; - class ActionStop : public ResultAction { public: ActionStop(ZVision *engine, int32 slotkey, const Common::String &line); diff --git a/engines/zvision/scripting/scr_file_handling.cpp b/engines/zvision/scripting/scr_file_handling.cpp index 83be3b5ad4..fd5c158fcc 100644 --- a/engines/zvision/scripting/scr_file_handling.cpp +++ b/engines/zvision/scripting/scr_file_handling.cpp @@ -235,12 +235,13 @@ void ScriptManager::parseResults(Common::SeekableReadStream &stream, Common::Lis } else if (act.matchString("disable_control", true)) { actionList.push_back(new ActionDisableControl(_engine, slot, args)); } else if (act.matchString("disable_venus", true)) { - actionList.push_back(new ActionDisableVenus(_engine, slot, args)); + // Not used. Purposely left empty } else if (act.matchString("display_message", true)) { actionList.push_back(new ActionDisplayMessage(_engine, slot, args)); } else if (act.matchString("dissolve", true)) { actionList.push_back(new ActionDissolve(_engine)); } else if (act.matchString("distort", true)) { + // Only used by Zork: Nemesis for the "treatment" puzzle in the Sanitarium (aj30) actionList.push_back(new ActionDistort(_engine, slot, args)); } else if (act.matchString("enable_control", true)) { actionList.push_back(new ActionEnableControl(_engine, slot, args)); @@ -249,6 +250,7 @@ void ScriptManager::parseResults(Common::SeekableReadStream &stream, Common::Lis } else if (act.matchString("inventory", true)) { actionList.push_back(new ActionInventory(_engine, slot, args)); } else if (act.matchString("kill", true)) { + // Only used by ZGI actionList.push_back(new ActionKill(_engine, slot, args)); } else if (act.matchString("menu_bar_enable", true)) { actionList.push_back(new ActionMenuBarEnable(_engine, slot, args)); @@ -278,7 +280,7 @@ void ScriptManager::parseResults(Common::SeekableReadStream &stream, Common::Lis } else if (act.matchString("set_screen", true)) { actionList.push_back(new ActionSetScreen(_engine, slot, args)); } else if (act.matchString("set_venus", true)) { - actionList.push_back(new ActionSetVenus(_engine, slot, args)); + // Not used. Purposely left empty } else if (act.matchString("stop", true)) { actionList.push_back(new ActionStop(_engine, slot, args)); } else if (act.matchString("streamvideo", true)) { -- cgit v1.2.3 From 4258750f5025e471ba682945e3091fdaa50c7bc9 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 26 Dec 2014 12:07:21 +0200 Subject: ZVISION: Rename _halveDelay to _doubleFPS, to match its config setting --- engines/zvision/zvision.cpp | 12 ++++++------ engines/zvision/zvision.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'engines') diff --git a/engines/zvision/zvision.cpp b/engines/zvision/zvision.cpp index 11e417d4ac..e9a4486ded 100644 --- a/engines/zvision/zvision.cpp +++ b/engines/zvision/zvision.cpp @@ -96,7 +96,7 @@ ZVision::ZVision(OSystem *syst, const ZVisionGameDescription *gameDesc) _menu(nullptr), _searchManager(nullptr), _textRenderer(nullptr), - _halveDelay(false), + _doubleFPS(false), _audioId(0), _frameRenderDelay(2), _keyboardVelocity(0), @@ -213,7 +213,7 @@ void ZVision::initialize() { // Create debugger console. It requires GFX to be initialized _console = new Console(this); - _halveDelay = ConfMan.getBool("doublefps"); + _doubleFPS = ConfMan.getBool("doublefps"); } Common::Error ZVision::run() { @@ -255,7 +255,7 @@ Common::Error ZVision::run() { // Ensure non-negative delay = delay < 0 ? 0 : delay; - if (_halveDelay) { + if (_doubleFPS) { delay >>= 1; } @@ -291,7 +291,7 @@ bool ZVision::askQuestion(const Common::String &str) { } } _system->updateScreen(); - if (_halveDelay) + if (_doubleFPS) _system->delayMillis(33); else _system->delayMillis(66); @@ -319,7 +319,7 @@ void ZVision::delayedMessage(const Common::String &str, uint16 milsecs) { break; } _system->updateScreen(); - if (_halveDelay) + if (_doubleFPS) _system->delayMillis(33); else _system->delayMillis(66); @@ -365,7 +365,7 @@ bool ZVision::canRender() { void ZVision::updateRotation() { int16 _velocity = _mouseVelocity + _keyboardVelocity; - if (_halveDelay) + if (_doubleFPS) _velocity /= 2; if (_velocity) { diff --git a/engines/zvision/zvision.h b/engines/zvision/zvision.h index e9b8ca4547..d3beae5e61 100644 --- a/engines/zvision/zvision.h +++ b/engines/zvision/zvision.h @@ -121,7 +121,7 @@ private: int _frameRenderDelay; int16 _mouseVelocity; int16 _keyboardVelocity; - bool _halveDelay; + bool _doubleFPS; bool _videoIsPlaying; uint8 _cheatBuffer[KEYBUF_SIZE]; -- cgit v1.2.3 From 5a72eea2bb102bafb6da112ea90ad1f4af11e1f2 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 26 Dec 2014 12:41:36 +0200 Subject: ZVISION: Move some event/rendering code out of the main engine code --- engines/zvision/core/events.cpp | 37 ++++++- engines/zvision/graphics/render_manager.cpp | 82 +++++++++++++++- engines/zvision/graphics/render_manager.h | 8 +- .../zvision/scripting/controls/save_control.cpp | 7 +- engines/zvision/zvision.cpp | 108 +-------------------- engines/zvision/zvision.h | 13 ++- 6 files changed, 133 insertions(+), 122 deletions(-) (limited to 'engines') diff --git a/engines/zvision/core/events.cpp b/engines/zvision/core/events.cpp index 227cf213dc..70fd425949 100644 --- a/engines/zvision/core/events.cpp +++ b/engines/zvision/core/events.cpp @@ -39,6 +39,33 @@ namespace ZVision { +void ZVision::pushKeyToCheatBuf(uint8 key) { + for (int i = 0; i < KEYBUF_SIZE - 1; i++) + _cheatBuffer[i] = _cheatBuffer[i + 1]; + + _cheatBuffer[KEYBUF_SIZE - 1] = key; +} + +bool ZVision::checkCode(const char *code) { + int codeLen = strlen(code); + + if (codeLen > KEYBUF_SIZE) + return false; + + for (int i = 0; i < codeLen; i++) + if (code[i] != _cheatBuffer[KEYBUF_SIZE - codeLen + i] && code[i] != '?') + return false; + + return true; +} + +uint8 ZVision::getBufferedKey(uint8 pos) { + if (pos >= KEYBUF_SIZE) + return 0; + else + return _cheatBuffer[KEYBUF_SIZE - pos - 1]; +} + void ZVision::shortKeys(Common::Event event) { if (event.kbd.hasFlags(Common::KBD_CTRL)) { switch (event.kbd.keycode) { @@ -70,11 +97,11 @@ void ZVision::cheatCodes(uint8 key) { if (getGameId() == GID_GRANDINQUISITOR) { if (checkCode("IMNOTDEAF")) { // Unknown cheat - showDebugMsg(Common::String::format("IMNOTDEAF cheat or debug, not implemented")); + _renderManager->showDebugMsg(Common::String::format("IMNOTDEAF cheat or debug, not implemented")); } if (checkCode("3100OPB")) { - showDebugMsg(Common::String::format("Current location: %c%c%c%c", + _renderManager->showDebugMsg(Common::String::format("Current location: %c%c%c%c", _scriptManager->getStateValue(StateKey_World), _scriptManager->getStateValue(StateKey_Room), _scriptManager->getStateValue(StateKey_Node), @@ -101,7 +128,7 @@ void ZVision::cheatCodes(uint8 key) { } if (checkCode("77MASSAVE")) { - showDebugMsg(Common::String::format("Current location: %c%c%c%c", + _renderManager->showDebugMsg(Common::String::format("Current location: %c%c%c%c", _scriptManager->getStateValue(StateKey_World), _scriptManager->getStateValue(StateKey_Room), _scriptManager->getStateValue(StateKey_Node), @@ -131,13 +158,13 @@ void ZVision::cheatCodes(uint8 key) { } if (checkCode("FRAME")) - showDebugMsg(Common::String::format("FPS: ???, not implemented")); + _renderManager->showDebugMsg(Common::String::format("FPS: ???, not implemented")); if (checkCode("XYZZY")) _scriptManager->setStateValue(StateKey_DebugCheats, 1 - _scriptManager->getStateValue(StateKey_DebugCheats)); if (checkCode("COMPUTERARCH")) - showDebugMsg(Common::String::format("COMPUTERARCH: var-viewer not implemented")); + _renderManager->showDebugMsg(Common::String::format("COMPUTERARCH: var-viewer not implemented")); if (_scriptManager->getStateValue(StateKey_DebugCheats) == 1) if (checkCode("GO????")) diff --git a/engines/zvision/graphics/render_manager.cpp b/engines/zvision/graphics/render_manager.cpp index 07ed6d2e2b..35e3b89b09 100644 --- a/engines/zvision/graphics/render_manager.cpp +++ b/engines/zvision/graphics/render_manager.cpp @@ -39,7 +39,7 @@ namespace ZVision { -RenderManager::RenderManager(ZVision *engine, uint32 windowWidth, uint32 windowHeight, const Common::Rect workingWindow, const Graphics::PixelFormat pixelFormat) +RenderManager::RenderManager(ZVision *engine, uint32 windowWidth, uint32 windowHeight, const Common::Rect workingWindow, const Graphics::PixelFormat pixelFormat, bool doubleFPS) : _engine(engine), _system(engine->_system), _workingWidth(workingWindow.width()), @@ -51,7 +51,8 @@ RenderManager::RenderManager(ZVision *engine, uint32 windowWidth, uint32 windowH _backgroundWidth(0), _backgroundHeight(0), _backgroundOffset(0), - _renderTable(_workingWidth, _workingHeight) { + _renderTable(_workingWidth, _workingHeight), + _doubleFPS(doubleFPS) { _backgroundSurface.create(_workingWidth, _workingHeight, _pixelFormat); _effectSurface.create(_workingWidth, _workingHeight, _pixelFormat); @@ -1013,4 +1014,81 @@ void RenderManager::bkgFill(uint8 r, uint8 g, uint8 b) { } #endif +void RenderManager::timedMessage(const Common::String &str, uint16 milsecs) { + uint16 msgid = createSubArea(); + updateSubArea(msgid, str); + processSubs(0); + renderSceneToScreen(); + deleteSubArea(msgid, milsecs); +} + +bool RenderManager::askQuestion(const Common::String &str) { + uint16 msgid = createSubArea(); + updateSubArea(msgid, str); + processSubs(0); + renderSceneToScreen(); + _engine->stopClock(); + + int result = 0; + + while (result == 0) { + Common::Event evnt; + while (_engine->getEventManager()->pollEvent(evnt)) { + if (evnt.type == Common::EVENT_KEYDOWN) { + switch (evnt.kbd.keycode) { + case Common::KEYCODE_y: + result = 2; + break; + case Common::KEYCODE_n: + result = 1; + break; + default: + break; + } + } + } + _system->updateScreen(); + if (_doubleFPS) + _system->delayMillis(33); + else + _system->delayMillis(66); + } + deleteSubArea(msgid); + _engine->startClock(); + return result == 2; +} + +void RenderManager::delayedMessage(const Common::String &str, uint16 milsecs) { + uint16 msgid = createSubArea(); + updateSubArea(msgid, str); + processSubs(0); + renderSceneToScreen(); + _engine->stopClock(); + + uint32 stopTime = _system->getMillis() + milsecs; + while (_system->getMillis() < stopTime) { + Common::Event evnt; + while (_engine->getEventManager()->pollEvent(evnt)) { + if (evnt.type == Common::EVENT_KEYDOWN && + (evnt.kbd.keycode == Common::KEYCODE_SPACE || + evnt.kbd.keycode == Common::KEYCODE_RETURN || + evnt.kbd.keycode == Common::KEYCODE_ESCAPE)) + break; + } + _system->updateScreen(); + if (_doubleFPS) + _system->delayMillis(33); + else + _system->delayMillis(66); + } + deleteSubArea(msgid); + _engine->startClock(); +} + +void RenderManager::showDebugMsg(const Common::String &msg, int16 delay) { + uint16 msgid = createSubArea(); + updateSubArea(msgid, msg); + deleteSubArea(msgid, delay); +} + } // End of namespace ZVision diff --git a/engines/zvision/graphics/render_manager.h b/engines/zvision/graphics/render_manager.h index d67ae29a3a..dbaa8fdc50 100644 --- a/engines/zvision/graphics/render_manager.h +++ b/engines/zvision/graphics/render_manager.h @@ -48,7 +48,7 @@ namespace ZVision { class RenderManager { public: - RenderManager(ZVision *engine, uint32 windowWidth, uint32 windowHeight, const Common::Rect workingWindow, const Graphics::PixelFormat pixelFormat); + RenderManager(ZVision *engine, uint32 windowWidth, uint32 windowHeight, const Common::Rect workingWindow, const Graphics::PixelFormat pixelFormat, bool doubleFPS); ~RenderManager(); private: @@ -137,6 +137,7 @@ private: // Visual effects list EffectsList _effects; + bool _doubleFPS; public: void initialize(); @@ -334,6 +335,11 @@ public: // Fill background surface by color void bkgFill(uint8 r, uint8 g, uint8 b); #endif + + bool askQuestion(const Common::String &str); + void delayedMessage(const Common::String &str, uint16 milsecs); + void timedMessage(const Common::String &str, uint16 milsecs); + void showDebugMsg(const Common::String &msg, int16 delay = 3000); }; } // End of namespace ZVision diff --git a/engines/zvision/scripting/controls/save_control.cpp b/engines/zvision/scripting/controls/save_control.cpp index 3a4dc47fe8..6cedddffeb 100644 --- a/engines/zvision/scripting/controls/save_control.cpp +++ b/engines/zvision/scripting/controls/save_control.cpp @@ -30,6 +30,7 @@ #include "zvision/text/string_manager.h" #include "zvision/file/save_manager.h" +#include "zvision/graphics/render_manager.h" #include "common/str.h" #include "common/stream.h" @@ -97,18 +98,18 @@ bool SaveControl::process(uint32 deltaTimeInMillis) { if (inp->getText().size() > 0) { bool toSave = true; if (iter->exist) - if (!_engine->askQuestion(_engine->getStringManager()->getTextLine(StringManager::ZVISION_STR_SAVEEXIST))) + if (!_engine->getRenderManager()->askQuestion(_engine->getStringManager()->getTextLine(StringManager::ZVISION_STR_SAVEEXIST))) toSave = false; if (toSave) { // FIXME: At this point, the screen shows the save control, so the save game thumbnails will always // show the save control _engine->getSaveManager()->saveGameBuffered(iter->saveId, inp->getText()); - _engine->delayedMessage(_engine->getStringManager()->getTextLine(StringManager::ZVISION_STR_SAVED), 2000); + _engine->getRenderManager()->delayedMessage(_engine->getStringManager()->getTextLine(StringManager::ZVISION_STR_SAVED), 2000); _engine->getScriptManager()->changeLocation(_engine->getScriptManager()->getLastMenuLocation()); } } else { - _engine->timedMessage(_engine->getStringManager()->getTextLine(StringManager::ZVISION_STR_SAVEEMPTY), 2000); + _engine->getRenderManager()->timedMessage(_engine->getStringManager()->getTextLine(StringManager::ZVISION_STR_SAVEEMPTY), 2000); } } else { _engine->getSaveManager()->loadGame(iter->saveId); diff --git a/engines/zvision/zvision.cpp b/engines/zvision/zvision.cpp index e9a4486ded..575a7af6ab 100644 --- a/engines/zvision/zvision.cpp +++ b/engines/zvision/zvision.cpp @@ -190,7 +190,7 @@ void ZVision::initialize() { // Create managers _scriptManager = new ScriptManager(this); - _renderManager = new RenderManager(this, WINDOW_WIDTH, WINDOW_HEIGHT, _workingWindow, _resourcePixelFormat); + _renderManager = new RenderManager(this, WINDOW_WIDTH, WINDOW_HEIGHT, _workingWindow, _resourcePixelFormat, _doubleFPS); _saveManager = new SaveManager(this); _stringManager = new StringManager(this); _cursorManager = new CursorManager(this, _resourcePixelFormat); @@ -265,77 +265,6 @@ Common::Error ZVision::run() { return Common::kNoError; } -bool ZVision::askQuestion(const Common::String &str) { - uint16 msgid = _renderManager->createSubArea(); - _renderManager->updateSubArea(msgid, str); - _renderManager->processSubs(0); - _renderManager->renderSceneToScreen(); - _clock.stop(); - - int result = 0; - - while (result == 0) { - Common::Event evnt; - while (_eventMan->pollEvent(evnt)) { - if (evnt.type == Common::EVENT_KEYDOWN) { - switch (evnt.kbd.keycode) { - case Common::KEYCODE_y: - result = 2; - break; - case Common::KEYCODE_n: - result = 1; - break; - default: - break; - } - } - } - _system->updateScreen(); - if (_doubleFPS) - _system->delayMillis(33); - else - _system->delayMillis(66); - } - _renderManager->deleteSubArea(msgid); - _clock.start(); - return result == 2; -} - -void ZVision::delayedMessage(const Common::String &str, uint16 milsecs) { - uint16 msgid = _renderManager->createSubArea(); - _renderManager->updateSubArea(msgid, str); - _renderManager->processSubs(0); - _renderManager->renderSceneToScreen(); - _clock.stop(); - - uint32 stopTime = _system->getMillis() + milsecs; - while (_system->getMillis() < stopTime) { - Common::Event evnt; - while (_eventMan->pollEvent(evnt)) { - if (evnt.type == Common::EVENT_KEYDOWN && - (evnt.kbd.keycode == Common::KEYCODE_SPACE || - evnt.kbd.keycode == Common::KEYCODE_RETURN || - evnt.kbd.keycode == Common::KEYCODE_ESCAPE)) - break; - } - _system->updateScreen(); - if (_doubleFPS) - _system->delayMillis(33); - else - _system->delayMillis(66); - } - _renderManager->deleteSubArea(msgid); - _clock.start(); -} - -void ZVision::timedMessage(const Common::String &str, uint16 milsecs) { - uint16 msgid = _renderManager->createSubArea(); - _renderManager->updateSubArea(msgid, str); - _renderManager->processSubs(0); - _renderManager->renderSceneToScreen(); - _renderManager->deleteSubArea(msgid, milsecs); -} - void ZVision::pauseEngineIntern(bool pause) { _mixer->pauseAll(pause); @@ -506,44 +435,11 @@ uint16 ZVision::getMenuBarEnable() { } bool ZVision::ifQuit() { - if (askQuestion(_stringManager->getTextLine(StringManager::ZVISION_STR_EXITPROMT))) { + if (_renderManager->askQuestion(_stringManager->getTextLine(StringManager::ZVISION_STR_EXITPROMT))) { quitGame(); return true; } return false; } -void ZVision::pushKeyToCheatBuf(uint8 key) { - for (int i = 0; i < KEYBUF_SIZE - 1; i++) - _cheatBuffer[i] = _cheatBuffer[i + 1]; - - _cheatBuffer[KEYBUF_SIZE - 1] = key; -} - -bool ZVision::checkCode(const char *code) { - int codeLen = strlen(code); - - if (codeLen > KEYBUF_SIZE) - return false; - - for (int i = 0; i < codeLen; i++) - if (code[i] != _cheatBuffer[KEYBUF_SIZE - codeLen + i] && code[i] != '?') - return false; - - return true; -} - -uint8 ZVision::getBufferedKey(uint8 pos) { - if (pos >= KEYBUF_SIZE) - return 0; - else - return _cheatBuffer[KEYBUF_SIZE - pos - 1]; -} - -void ZVision::showDebugMsg(const Common::String &msg, int16 delay) { - uint16 msgid = _renderManager->createSubArea(); - _renderManager->updateSubArea(msgid, msg); - _renderManager->deleteSubArea(msgid, delay); -} - } // End of namespace ZVision diff --git a/engines/zvision/zvision.h b/engines/zvision/zvision.h index d3beae5e61..848b278f69 100644 --- a/engines/zvision/zvision.h +++ b/engines/zvision/zvision.h @@ -164,6 +164,14 @@ public: uint8 getZvisionKey(Common::KeyCode scummKeyCode); + void startClock() { + _clock.start(); + } + + void stopClock() { + _clock.stop(); + } + /** * Play a video until it is finished. This is a blocking call. It will call * _clock.stop() when the video starts and _clock.start() when the video finishes. @@ -181,10 +189,6 @@ public: Common::String generateSaveFileName(uint slot); Common::String generateAutoSaveFileName(); - bool askQuestion(const Common::String &str); - void delayedMessage(const Common::String &str, uint16 milsecs); - void timedMessage(const Common::String &str, uint16 milsecs); - void setRenderDelay(uint); bool canRender(); @@ -197,7 +201,6 @@ public: bool ifQuit(); void checkBorders(); - void showDebugMsg(const Common::String &msg, int16 delay = 3000); // Engine features bool hasFeature(EngineFeature f) const; -- cgit v1.2.3 From e8820d26e7d673f96c416f93dd16811107e94cb4 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 26 Dec 2014 12:42:01 +0200 Subject: ZVISION: Fix a warning --- engines/zvision/scripting/controls/input_control.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/zvision/scripting/controls/input_control.cpp b/engines/zvision/scripting/controls/input_control.cpp index e1e6e6ec9d..4abc0c9e1b 100644 --- a/engines/zvision/scripting/controls/input_control.cpp +++ b/engines/zvision/scripting/controls/input_control.cpp @@ -223,7 +223,7 @@ bool InputControl::process(uint32 deltaTimeInMillis) { if (needDraw) { _animation->seekToFrame(_frame); const Graphics::Surface *srf = _animation->decodeNextFrame(); - uint32 xx = _textRectangle.left + _txtWidth; + int16 xx = _textRectangle.left + _txtWidth; if (xx >= _textRectangle.left + (_textRectangle.width() - (int16)_animation->getWidth())) xx = _textRectangle.left + _textRectangle.width() - (int16)_animation->getWidth(); _engine->getRenderManager()->blitSurfaceToBkg(*srf, xx, _textRectangle.top); -- cgit v1.2.3 From eea1ee445fcac7ecc53e31d258aac697d6b242f1 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 26 Dec 2014 13:14:24 +0200 Subject: ZVISION: Move more graphics code out of the main engine code --- engines/zvision/core/events.cpp | 17 ++- engines/zvision/graphics/render_manager.cpp | 133 +++++++++++++++++++++++ engines/zvision/graphics/render_manager.h | 4 + engines/zvision/scripting/actions.cpp | 5 +- engines/zvision/scripting/script_manager.cpp | 5 +- engines/zvision/zvision.cpp | 155 +-------------------------- engines/zvision/zvision.h | 17 +-- 7 files changed, 167 insertions(+), 169 deletions(-) (limited to 'engines') diff --git a/engines/zvision/core/events.cpp b/engines/zvision/core/events.cpp index 70fd425949..5f29a6879c 100644 --- a/engines/zvision/core/events.cpp +++ b/engines/zvision/core/events.cpp @@ -30,6 +30,7 @@ #include "zvision/scripting/script_manager.h" #include "zvision/scripting/menu.h" #include "zvision/sound/zork_raw.h" +#include "zvision/text/string_manager.h" #include "common/events.h" #include "common/system.h" @@ -70,19 +71,19 @@ void ZVision::shortKeys(Common::Event event) { if (event.kbd.hasFlags(Common::KBD_CTRL)) { switch (event.kbd.keycode) { case Common::KEYCODE_s: - if (getMenuBarEnable() & kMenubarSave) + if (_menu->getEnable() & kMenubarSave) _scriptManager->changeLocation('g', 'j', 's', 'e', 0); break; case Common::KEYCODE_r: - if (getMenuBarEnable() & kMenubarRestore) + if (_menu->getEnable() & kMenubarRestore) _scriptManager->changeLocation('g', 'j', 'r', 'e', 0); break; case Common::KEYCODE_p: - if (getMenuBarEnable() & kMenubarSettings) + if (_menu->getEnable() & kMenubarSettings) _scriptManager->changeLocation('g', 'j', 'p', 'e', 0); break; case Common::KEYCODE_q: - if (getMenuBarEnable() & kMenubarExit) + if (_menu->getEnable() & kMenubarExit) ifQuit(); break; default: @@ -482,4 +483,12 @@ uint8 ZVision::getZvisionKey(Common::KeyCode scummKeyCode) { return 0; } +bool ZVision::ifQuit() { + if (_renderManager->askQuestion(_stringManager->getTextLine(StringManager::ZVISION_STR_EXITPROMT))) { + quitGame(); + return true; + } + return false; +} + } // End of namespace ZVision diff --git a/engines/zvision/graphics/render_manager.cpp b/engines/zvision/graphics/render_manager.cpp index 35e3b89b09..0a48ae6c16 100644 --- a/engines/zvision/graphics/render_manager.cpp +++ b/engines/zvision/graphics/render_manager.cpp @@ -1091,4 +1091,137 @@ void RenderManager::showDebugMsg(const Common::String &msg, int16 delay) { deleteSubArea(msgid, delay); } +void RenderManager::updateRotation() { + int16 _velocity = _engine->getMouseVelocity() + _engine->getKeyboardVelocity(); + ScriptManager *scriptManager = _engine->getScriptManager(); + + if (_doubleFPS) + _velocity /= 2; + + if (_velocity) { + RenderTable::RenderState renderState = _renderTable.getRenderState(); + if (renderState == RenderTable::PANORAMA) { + int16 startPosition = scriptManager->getStateValue(StateKey_ViewPos); + + int16 newPosition = startPosition + (_renderTable.getPanoramaReverse() ? -_velocity : _velocity); + + int16 zeroPoint = _renderTable.getPanoramaZeroPoint(); + if (startPosition >= zeroPoint && newPosition < zeroPoint) + scriptManager->setStateValue(StateKey_Rounds, scriptManager->getStateValue(StateKey_Rounds) - 1); + if (startPosition <= zeroPoint && newPosition > zeroPoint) + scriptManager->setStateValue(StateKey_Rounds, scriptManager->getStateValue(StateKey_Rounds) + 1); + + int16 screenWidth = getBkgSize().x; + if (screenWidth) + newPosition %= screenWidth; + + if (newPosition < 0) + newPosition += screenWidth; + + setBackgroundPosition(newPosition); + } else if (renderState == RenderTable::TILT) { + int16 startPosition = scriptManager->getStateValue(StateKey_ViewPos); + + int16 newPosition = startPosition + _velocity; + + int16 screenHeight = getBkgSize().y; + int16 tiltGap = _renderTable.getTiltGap(); + + if (newPosition >= (screenHeight - tiltGap)) + newPosition = screenHeight - tiltGap; + if (newPosition <= tiltGap) + newPosition = tiltGap; + + setBackgroundPosition(newPosition); + } + } +} + +void RenderManager::checkBorders() { + RenderTable::RenderState renderState = _renderTable.getRenderState(); + if (renderState == RenderTable::PANORAMA) { + int16 startPosition = _engine->getScriptManager()->getStateValue(StateKey_ViewPos); + + int16 newPosition = startPosition; + + int16 screenWidth = getBkgSize().x; + + if (screenWidth) + newPosition %= screenWidth; + + if (newPosition < 0) + newPosition += screenWidth; + + if (startPosition != newPosition) + setBackgroundPosition(newPosition); + } else if (renderState == RenderTable::TILT) { + int16 startPosition = _engine->getScriptManager()->getStateValue(StateKey_ViewPos); + + int16 newPosition = startPosition; + + int16 screenHeight = getBkgSize().y; + int16 tiltGap = _renderTable.getTiltGap(); + + if (newPosition >= (screenHeight - tiltGap)) + newPosition = screenHeight - tiltGap; + if (newPosition <= tiltGap) + newPosition = tiltGap; + + if (startPosition != newPosition) + setBackgroundPosition(newPosition); + } +} + +void RenderManager::rotateTo(int16 _toPos, int16 _time) { + if (_renderTable.getRenderState() != RenderTable::PANORAMA) + return; + + if (_time == 0) + _time = 1; + + int32 maxX = getBkgSize().x; + int32 curX = getCurrentBackgroundOffset(); + int32 dx = 0; + + if (curX == _toPos) + return; + + if (curX > _toPos) { + if (curX - _toPos > maxX / 2) + dx = (_toPos + (maxX - curX)) / _time; + else + dx = -(curX - _toPos) / _time; + } else { + if (_toPos - curX > maxX / 2) + dx = -((maxX - _toPos) + curX) / _time; + else + dx = (_toPos - curX) / _time; + } + + _engine->stopClock(); + + for (int16 i = 0; i <= _time; i++) { + if (i == _time) + curX = _toPos; + else + curX += dx; + + if (curX < 0) + curX = maxX - curX; + else if (curX >= maxX) + curX %= maxX; + + setBackgroundPosition(curX); + + prepareBackground(); + renderSceneToScreen(); + + _system->updateScreen(); + + _system->delayMillis(500 / _time); + } + + _engine->startClock(); +} + } // End of namespace ZVision diff --git a/engines/zvision/graphics/render_manager.h b/engines/zvision/graphics/render_manager.h index dbaa8fdc50..30e51456e9 100644 --- a/engines/zvision/graphics/render_manager.h +++ b/engines/zvision/graphics/render_manager.h @@ -340,6 +340,10 @@ public: void delayedMessage(const Common::String &str, uint16 milsecs); void timedMessage(const Common::String &str, uint16 milsecs); void showDebugMsg(const Common::String &msg, int16 delay = 3000); + + void checkBorders(); + void rotateTo(int16 to, int16 time); + void updateRotation(); }; } // End of namespace ZVision diff --git a/engines/zvision/scripting/actions.cpp b/engines/zvision/scripting/actions.cpp index c26a93f529..7c3463b6d0 100644 --- a/engines/zvision/scripting/actions.cpp +++ b/engines/zvision/scripting/actions.cpp @@ -30,6 +30,7 @@ #include "zvision/sound/zork_raw.h" #include "zvision/video/zork_avi_decoder.h" #include "zvision/file/save_manager.h" +#include "zvision/scripting/menu.h" #include "zvision/scripting/sidefx/timer_node.h" #include "zvision/scripting/sidefx/music_node.h" #include "zvision/scripting/sidefx/syncsound_node.h" @@ -439,7 +440,7 @@ ActionMenuBarEnable::ActionMenuBarEnable(ZVision *engine, int32 slotkey, const C } bool ActionMenuBarEnable::execute() { - _engine->menuBarEnable(_menus); + _engine->getMenuHandler()->setEnable(_menus); return true; } @@ -819,7 +820,7 @@ ActionRotateTo::ActionRotateTo(ZVision *engine, int32 slotkey, const Common::Str } bool ActionRotateTo::execute() { - _engine->rotateTo(_toPos, _time); + _engine->getRenderManager()->rotateTo(_toPos, _time); return true; } diff --git a/engines/zvision/scripting/script_manager.cpp b/engines/zvision/scripting/script_manager.cpp index 2a4aa5fed0..1a2b8362f5 100644 --- a/engines/zvision/scripting/script_manager.cpp +++ b/engines/zvision/scripting/script_manager.cpp @@ -29,6 +29,7 @@ #include "zvision/graphics/cursors/cursor_manager.h" #include "zvision/file/save_manager.h" #include "zvision/scripting/actions.h" +#include "zvision/scripting/menu.h" #include "zvision/scripting/sidefx/timer_node.h" #include "common/algorithm.h" @@ -583,7 +584,7 @@ void ScriptManager::ChangeLocationReal() { _referenceTable.clear(); addPuzzlesToReferenceTable(universe); - _engine->menuBarEnable(0xFFFF); + _engine->getMenuHandler()->setEnable(0xFFFF); if (_nextLocation.world != _currentLocation.world) { cleanScriptScope(nodeview); @@ -652,7 +653,7 @@ void ScriptManager::ChangeLocationReal() { execScope(nodeview); } - _engine->checkBorders(); + _engine->getRenderManager()->checkBorders(); } void ScriptManager::serialize(Common::WriteStream *stream) { diff --git a/engines/zvision/zvision.cpp b/engines/zvision/zvision.cpp index 575a7af6ab..bd215f4f62 100644 --- a/engines/zvision/zvision.cpp +++ b/engines/zvision/zvision.cpp @@ -232,7 +232,7 @@ Common::Error ZVision::run() { _cursorManager->setItemID(_scriptManager->getStateValue(StateKey_InventoryItem)); processEvents(); - updateRotation(); + _renderManager->updateRotation(); _scriptManager->update(deltaTime); _menu->process(deltaTime); @@ -244,7 +244,7 @@ Common::Error ZVision::run() { _renderManager->renderSceneToScreen(); // Update the screen - if (_frameRenderDelay <= 0) { + if (canRender()) { _system->updateScreen(); } else { _frameRenderDelay--; @@ -291,155 +291,4 @@ bool ZVision::canRender() { return _frameRenderDelay <= 0; } -void ZVision::updateRotation() { - int16 _velocity = _mouseVelocity + _keyboardVelocity; - - if (_doubleFPS) - _velocity /= 2; - - if (_velocity) { - RenderTable::RenderState renderState = _renderManager->getRenderTable()->getRenderState(); - if (renderState == RenderTable::PANORAMA) { - int16 startPosition = _scriptManager->getStateValue(StateKey_ViewPos); - - int16 newPosition = startPosition + (_renderManager->getRenderTable()->getPanoramaReverse() ? -_velocity : _velocity); - - int16 zeroPoint = _renderManager->getRenderTable()->getPanoramaZeroPoint(); - if (startPosition >= zeroPoint && newPosition < zeroPoint) - _scriptManager->setStateValue(StateKey_Rounds, _scriptManager->getStateValue(StateKey_Rounds) - 1); - if (startPosition <= zeroPoint && newPosition > zeroPoint) - _scriptManager->setStateValue(StateKey_Rounds, _scriptManager->getStateValue(StateKey_Rounds) + 1); - - int16 screenWidth = _renderManager->getBkgSize().x; - if (screenWidth) - newPosition %= screenWidth; - - if (newPosition < 0) - newPosition += screenWidth; - - _renderManager->setBackgroundPosition(newPosition); - } else if (renderState == RenderTable::TILT) { - int16 startPosition = _scriptManager->getStateValue(StateKey_ViewPos); - - int16 newPosition = startPosition + _velocity; - - int16 screenHeight = _renderManager->getBkgSize().y; - int16 tiltGap = _renderManager->getRenderTable()->getTiltGap(); - - if (newPosition >= (screenHeight - tiltGap)) - newPosition = screenHeight - tiltGap; - if (newPosition <= tiltGap) - newPosition = tiltGap; - - _renderManager->setBackgroundPosition(newPosition); - } - } -} - -void ZVision::checkBorders() { - RenderTable::RenderState renderState = _renderManager->getRenderTable()->getRenderState(); - if (renderState == RenderTable::PANORAMA) { - int16 startPosition = _scriptManager->getStateValue(StateKey_ViewPos); - - int16 newPosition = startPosition; - - int16 screenWidth = _renderManager->getBkgSize().x; - - if (screenWidth) - newPosition %= screenWidth; - - if (newPosition < 0) - newPosition += screenWidth; - - if (startPosition != newPosition) - _renderManager->setBackgroundPosition(newPosition); - } else if (renderState == RenderTable::TILT) { - int16 startPosition = _scriptManager->getStateValue(StateKey_ViewPos); - - int16 newPosition = startPosition; - - int16 screenHeight = _renderManager->getBkgSize().y; - int16 tiltGap = _renderManager->getRenderTable()->getTiltGap(); - - if (newPosition >= (screenHeight - tiltGap)) - newPosition = screenHeight - tiltGap; - if (newPosition <= tiltGap) - newPosition = tiltGap; - - if (startPosition != newPosition) - _renderManager->setBackgroundPosition(newPosition); - } -} - -void ZVision::rotateTo(int16 _toPos, int16 _time) { - if (_renderManager->getRenderTable()->getRenderState() != RenderTable::PANORAMA) - return; - - if (_time == 0) - _time = 1; - - int32 maxX = _renderManager->getBkgSize().x; - int32 curX = _renderManager->getCurrentBackgroundOffset(); - int32 dx = 0; - - if (curX == _toPos) - return; - - if (curX > _toPos) { - if (curX - _toPos > maxX / 2) - dx = (_toPos + (maxX - curX)) / _time; - else - dx = -(curX - _toPos) / _time; - } else { - if (_toPos - curX > maxX / 2) - dx = -((maxX - _toPos) + curX) / _time; - else - dx = (_toPos - curX) / _time; - } - - _clock.stop(); - - for (int16 i = 0; i <= _time; i++) { - if (i == _time) - curX = _toPos; - else - curX += dx; - - if (curX < 0) - curX = maxX - curX; - else if (curX >= maxX) - curX %= maxX; - - _renderManager->setBackgroundPosition(curX); - - _renderManager->prepareBackground(); - _renderManager->renderSceneToScreen(); - - _system->updateScreen(); - - _system->delayMillis(500 / _time); - } - - _clock.start(); -} - -void ZVision::menuBarEnable(uint16 menus) { - if (_menu) - _menu->setEnable(menus); -} - -uint16 ZVision::getMenuBarEnable() { - if (_menu) - return _menu->getEnable(); - return 0; -} - -bool ZVision::ifQuit() { - if (_renderManager->askQuestion(_stringManager->getTextLine(StringManager::ZVISION_STR_EXITPROMT))) { - quitGame(); - return true; - } - return false; -} - } // End of namespace ZVision diff --git a/engines/zvision/zvision.h b/engines/zvision/zvision.h index 848b278f69..dc1ac1b8cb 100644 --- a/engines/zvision/zvision.h +++ b/engines/zvision/zvision.h @@ -155,12 +155,21 @@ public: MidiManager *getMidiManager() const { return _midiManager; } + MenuHandler *getMenuHandler() const { + return _menu; + } Common::RandomSource *getRandomSource() const { return _rnd; } ZVisionGameId getGameId() const { return _gameDescription->gameId; } + int16 getKeyboardVelocity() const { + return _keyboardVelocity; + } + int16 getMouseVelocity() const { + return _mouseVelocity; + } uint8 getZvisionKey(Common::KeyCode scummKeyCode); @@ -184,8 +193,6 @@ public: void playVideo(Video::VideoDecoder &videoDecoder, const Common::Rect &destRect = Common::Rect(0, 0, 0, 0), bool skippable = true, Subtitle *sub = NULL); Video::VideoDecoder *loadAnimation(const Common::String &fileName); - void rotateTo(int16 to, int16 time); - Common::String generateSaveFileName(uint slot); Common::String generateAutoSaveFileName(); @@ -195,13 +202,8 @@ public: void loadSettings(); void saveSettings(); - void menuBarEnable(uint16 menus); - uint16 getMenuBarEnable(); - bool ifQuit(); - void checkBorders(); - // Engine features bool hasFeature(EngineFeature f) const; bool canLoadGameStateCurrently(); @@ -218,7 +220,6 @@ private: void processEvents(); void onMouseMove(const Common::Point &pos); - void updateRotation(); void registerDefaultSettings(); void shortKeys(Common::Event); -- cgit v1.2.3 From e5f0ee2271f4a43ff05b82380ab22eade9763702 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 26 Dec 2014 18:22:18 +0200 Subject: ZVISION: Implement auto-saving --- engines/zvision/detection.cpp | 5 +++++ engines/zvision/file/save_manager.cpp | 14 +++++--------- engines/zvision/file/save_manager.h | 10 +++++++--- engines/zvision/scripting/script_manager.cpp | 4 ---- engines/zvision/zvision.cpp | 8 ++++---- engines/zvision/zvision.h | 1 - 6 files changed, 21 insertions(+), 21 deletions(-) (limited to 'engines') diff --git a/engines/zvision/detection.cpp b/engines/zvision/detection.cpp index a361239e9e..4fcb5c040b 100644 --- a/engines/zvision/detection.cpp +++ b/engines/zvision/detection.cpp @@ -308,6 +308,11 @@ SaveStateDescriptor ZVisionMetaEngine::querySaveMetaInfos(const char *target, in if (successfulRead) { SaveStateDescriptor desc(slot, header.saveName); + // Do not allow save slot 0 (used for auto-saving) to be deleted or + // overwritten. + desc.setDeletableFlag(slot != 0); + desc.setWriteProtectedFlag(slot == 0); + desc.setThumbnail(header.thumbnail); if (header.version > 0) { diff --git a/engines/zvision/file/save_manager.cpp b/engines/zvision/file/save_manager.cpp index 05df834497..042fafd38e 100644 --- a/engines/zvision/file/save_manager.cpp +++ b/engines/zvision/file/save_manager.cpp @@ -87,6 +87,8 @@ void SaveManager::saveGame(uint slot, const Common::String &saveName) { file->finalize(); delete file; + + _lastSaveTime = g_system->getMillis(); } void SaveManager::saveGame(uint slot, const Common::String &saveName, Common::MemoryWriteStreamDynamic *stream) { @@ -99,6 +101,8 @@ void SaveManager::saveGame(uint slot, const Common::String &saveName, Common::Me file->finalize(); delete file; + + _lastSaveTime = g_system->getMillis(); } void SaveManager::saveGameBuffered(uint slot, const Common::String &saveName) { @@ -109,15 +113,7 @@ void SaveManager::saveGameBuffered(uint slot, const Common::String &saveName) { } void SaveManager::autoSave() { - Common::OutSaveFile *file = g_system->getSavefileManager()->openForSaving(_engine->generateAutoSaveFileName()); - - writeSaveGameHeader(file, "auto"); - - _engine->getScriptManager()->serialize(file); - - // Cleanup - file->finalize(); - delete file; + saveGame(0, "Auto save"); } void SaveManager::writeSaveGameHeader(Common::OutSaveFile *file, const Common::String &saveName) { diff --git a/engines/zvision/file/save_manager.h b/engines/zvision/file/save_manager.h index 75841331e7..fc8db67566 100644 --- a/engines/zvision/file/save_manager.h +++ b/engines/zvision/file/save_manager.h @@ -48,13 +48,18 @@ struct SaveGameHeader { class SaveManager { public: - SaveManager(ZVision *engine) : _engine(engine), _tempSave(NULL) {} + SaveManager(ZVision *engine) : _engine(engine), _tempSave(NULL), _lastSaveTime(0) {} ~SaveManager() { flushSaveBuffer(); } + uint32 getLastSaveTime() const { + return _lastSaveTime; + } + private: ZVision *_engine; + uint32 _lastSaveTime; static const uint32 SAVEGAME_ID; enum { @@ -67,8 +72,7 @@ private: public: /** * Called every room change. Saves the state of the room just before - * we switched rooms. Uses ZVision::generateAutoSaveFileName() to - * create the save file name. + * the room changes. */ void autoSave(); /** diff --git a/engines/zvision/scripting/script_manager.cpp b/engines/zvision/scripting/script_manager.cpp index 1a2b8362f5..d0ebb18944 100644 --- a/engines/zvision/scripting/script_manager.cpp +++ b/engines/zvision/scripting/script_manager.cpp @@ -569,10 +569,6 @@ void ScriptManager::ChangeLocationReal() { } else { if (_currentLocation.world == 'g' && _currentLocation.room == 'j') _engine->getSaveManager()->flushSaveBuffer(); - else { - // Auto save - //_engine->getSaveManager()->autoSave(); - } } setStateValue(StateKey_World, _nextLocation.world); diff --git a/engines/zvision/zvision.cpp b/engines/zvision/zvision.cpp index bd215f4f62..b3fc02ee15 100644 --- a/engines/zvision/zvision.cpp +++ b/engines/zvision/zvision.cpp @@ -259,6 +259,10 @@ Common::Error ZVision::run() { delay >>= 1; } + if (canSaveGameStateCurrently() && shouldPerformAutoSave(_saveManager->getLastSaveTime())) { + _saveManager->autoSave(); + } + _system->delayMillis(delay); } @@ -279,10 +283,6 @@ Common::String ZVision::generateSaveFileName(uint slot) { return Common::String::format("%s.%03u", _targetName.c_str(), slot); } -Common::String ZVision::generateAutoSaveFileName() { - return Common::String::format("%s.auto", _targetName.c_str()); -} - void ZVision::setRenderDelay(uint delay) { _frameRenderDelay = delay; } diff --git a/engines/zvision/zvision.h b/engines/zvision/zvision.h index dc1ac1b8cb..6664d0cd5d 100644 --- a/engines/zvision/zvision.h +++ b/engines/zvision/zvision.h @@ -194,7 +194,6 @@ public: Video::VideoDecoder *loadAnimation(const Common::String &fileName); Common::String generateSaveFileName(uint slot); - Common::String generateAutoSaveFileName(); void setRenderDelay(uint); bool canRender(); -- cgit v1.2.3 From 2becc76d5c16d15d5a7a6733b40f7c59e7391c12 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 26 Dec 2014 19:56:37 +0200 Subject: ZVISION: Correct the script names of the location-specific cheats --- engines/zvision/core/events.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/zvision/core/events.cpp b/engines/zvision/core/events.cpp index 5f29a6879c..4438474078 100644 --- a/engines/zvision/core/events.cpp +++ b/engines/zvision/core/events.cpp @@ -119,9 +119,9 @@ void ZVision::cheatCodes(uint8 key) { } // There are 3 more cheats in script files: - // - "EAT ME": gjcr.scr - // - "WHOAMI": hp1e.scr - // - "HUISOK": uh1f.scr + // - "WHOAMI": gjcr.scr + // - "HUISOK": hp1e.scr + // - "EAT ME": uh1f.scr } else if (getGameId() == GID_NEMESIS) { if (checkCode("CHLOE")) { _scriptManager->changeLocation('t', 'm', '2', 'g', 0); -- cgit v1.2.3 From db37cfb1b04fb6d1fb21ef3bd3c0b90128bf4d89 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 26 Dec 2014 22:30:32 +0200 Subject: ZVISION: Remove duplicate blitting code for images and animations --- engines/zvision/graphics/render_manager.cpp | 67 +++++----------------- engines/zvision/graphics/render_manager.h | 11 +--- engines/zvision/scripting/actions.cpp | 12 ++++ .../zvision/scripting/sidefx/animation_node.cpp | 10 +--- engines/zvision/text/text.cpp | 7 ++- 5 files changed, 36 insertions(+), 71 deletions(-) (limited to 'engines') diff --git a/engines/zvision/graphics/render_manager.cpp b/engines/zvision/graphics/render_manager.cpp index 0a48ae6c16..7bbde81e4c 100644 --- a/engines/zvision/graphics/render_manager.cpp +++ b/engines/zvision/graphics/render_manager.cpp @@ -104,7 +104,8 @@ void RenderManager::renderSceneToScreen() { post = (*it)->draw(_currentBackgroundImage.getSubArea(rect)); else post = (*it)->draw(_effectSurface.getSubArea(rect)); - blitSurfaceToSurface(*post, _effectSurface, screenSpaceLocation.left, screenSpaceLocation.top); + Common::Rect empty; + blitSurfaceToSurface(*post, empty, _effectSurface, screenSpaceLocation.left, screenSpaceLocation.top); screenSpaceLocation.clip(windowRect); if (_backgroundSurfaceDirtyRect .isEmpty()) { _backgroundSurfaceDirtyRect = screenSpaceLocation; @@ -511,30 +512,12 @@ void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, const Com delete srcAdapted; } -void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, Graphics::Surface &dst, int x, int y) { +void RenderManager::blitSurfaceToBkg(const Graphics::Surface &src, int x, int y, int32 colorkey) { Common::Rect empt; - blitSurfaceToSurface(src, empt, dst, x, y); -} - -void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, Graphics::Surface &dst, int x, int y, uint32 colorkey) { - Common::Rect empt; - blitSurfaceToSurface(src, empt, dst, x, y, colorkey); -} - -void RenderManager::blitSurfaceToBkg(const Graphics::Surface &src, int x, int y) { - Common::Rect empt; - blitSurfaceToSurface(src, empt, _currentBackgroundImage, x, y); - Common::Rect dirty(src.w, src.h); - dirty.translate(x, y); - if (_backgroundDirtyRect.isEmpty()) - _backgroundDirtyRect = dirty; + if (colorkey >= 0) + blitSurfaceToSurface(src, empt, _currentBackgroundImage, x, y, colorkey); else - _backgroundDirtyRect.extend(dirty); -} - -void RenderManager::blitSurfaceToBkg(const Graphics::Surface &src, int x, int y, uint32 colorkey) { - Common::Rect empt; - blitSurfaceToSurface(src, empt, _currentBackgroundImage, x, y, colorkey); + blitSurfaceToSurface(src, empt, _currentBackgroundImage, x, y); Common::Rect dirty(src.w, src.h); dirty.translate(x, y); if (_backgroundDirtyRect.isEmpty()) @@ -543,23 +526,10 @@ void RenderManager::blitSurfaceToBkg(const Graphics::Surface &src, int x, int y, _backgroundDirtyRect.extend(dirty); } -void RenderManager::blitSurfaceToBkgScaled(const Graphics::Surface &src, const Common::Rect &_dstRect) { - if (src.w == _dstRect.width() && src.h == _dstRect.height()) - blitSurfaceToBkg(src, _dstRect.left, _dstRect.top); - else { - Graphics::Surface *tmp = new Graphics::Surface; - tmp->create(_dstRect.width(), _dstRect.height(), src.format); - scaleBuffer(src.getPixels(), tmp->getPixels(), src.w, src.h, src.format.bytesPerPixel, _dstRect.width(), _dstRect.height()); - blitSurfaceToBkg(*tmp, _dstRect.left, _dstRect.top); - tmp->free(); - delete tmp; - } -} - -void RenderManager::blitSurfaceToBkgScaled(const Graphics::Surface &src, const Common::Rect &_dstRect, uint32 colorkey) { - if (src.w == _dstRect.width() && src.h == _dstRect.height()) +void RenderManager::blitSurfaceToBkgScaled(const Graphics::Surface &src, const Common::Rect &_dstRect, int32 colorkey) { + if (src.w == _dstRect.width() && src.h == _dstRect.height()) { blitSurfaceToBkg(src, _dstRect.left, _dstRect.top, colorkey); - else { + } else { Graphics::Surface *tmp = new Graphics::Surface; tmp->create(_dstRect.width(), _dstRect.height(), src.format); scaleBuffer(src.getPixels(), tmp->getPixels(), src.w, src.h, src.format.bytesPerPixel, _dstRect.width(), _dstRect.height()); @@ -569,20 +539,12 @@ void RenderManager::blitSurfaceToBkgScaled(const Graphics::Surface &src, const C } } -void RenderManager::blitSurfaceToMenu(const Graphics::Surface &src, int x, int y) { +void RenderManager::blitSurfaceToMenu(const Graphics::Surface &src, int x, int y, int32 colorkey) { Common::Rect empt; - blitSurfaceToSurface(src, empt, _menuSurface, x, y); - Common::Rect dirty(src.w, src.h); - dirty.translate(x, y); - if (_menuSurfaceDirtyRect.isEmpty()) - _menuSurfaceDirtyRect = dirty; + if (colorkey >= 0) + blitSurfaceToSurface(src, empt, _menuSurface, x, y, colorkey); else - _menuSurfaceDirtyRect.extend(dirty); -} - -void RenderManager::blitSurfaceToMenu(const Graphics::Surface &src, int x, int y, uint32 colorkey) { - Common::Rect empt; - blitSurfaceToSurface(src, empt, _menuSurface, x, y, colorkey); + blitSurfaceToSurface(src, empt, _menuSurface, x, y); Common::Rect dirty(src.w, src.h); dirty.translate(x, y); if (_menuSurfaceDirtyRect.isEmpty()) @@ -803,7 +765,8 @@ void RenderManager::processSubs(uint16 deltatime) { Graphics::Surface *rndr = new Graphics::Surface(); rndr->create(sub->r.width(), sub->r.height(), _engine->_resourcePixelFormat); _engine->getTextRenderer()->drawTxtInOneLine(sub->txt, *rndr); - blitSurfaceToSurface(*rndr, _subtitleSurface, sub->r.left - _subtitleArea.left + _workingWindow.left, sub->r.top - _subtitleArea.top + _workingWindow.top); + Common::Rect empty; + blitSurfaceToSurface(*rndr, empty, _subtitleSurface, sub->r.left - _subtitleArea.left + _workingWindow.left, sub->r.top - _subtitleArea.top + _workingWindow.top); rndr->free(); delete rndr; } diff --git a/engines/zvision/graphics/render_manager.h b/engines/zvision/graphics/render_manager.h index 30e51456e9..a7e49b7758 100644 --- a/engines/zvision/graphics/render_manager.h +++ b/engines/zvision/graphics/render_manager.h @@ -230,20 +230,15 @@ public: // Blitting surface-to-surface methods void blitSurfaceToSurface(const Graphics::Surface &src, const Common::Rect &_srcRect , Graphics::Surface &dst, int x, int y); void blitSurfaceToSurface(const Graphics::Surface &src, const Common::Rect &_srcRect , Graphics::Surface &dst, int _x, int _y, uint32 colorkey); - void blitSurfaceToSurface(const Graphics::Surface &src, Graphics::Surface &dst, int x, int y); - void blitSurfaceToSurface(const Graphics::Surface &src, Graphics::Surface &dst, int x, int y, uint32 colorkey); // Blitting surface-to-background methods - void blitSurfaceToBkg(const Graphics::Surface &src, int x, int y); - void blitSurfaceToBkg(const Graphics::Surface &src, int x, int y, uint32 colorkey); + void blitSurfaceToBkg(const Graphics::Surface &src, int x, int y, int32 colorkey = -1); // Blitting surface-to-background methods with scale - void blitSurfaceToBkgScaled(const Graphics::Surface &src, const Common::Rect &_dstRect); - void blitSurfaceToBkgScaled(const Graphics::Surface &src, const Common::Rect &_dstRect, uint32 colorkey); + void blitSurfaceToBkgScaled(const Graphics::Surface &src, const Common::Rect &_dstRect, int32 colorkey = -1); // Blitting surface-to-menu methods - void blitSurfaceToMenu(const Graphics::Surface &src, int x, int y); - void blitSurfaceToMenu(const Graphics::Surface &src, int x, int y, uint32 colorkey); + void blitSurfaceToMenu(const Graphics::Surface &src, int x, int y, int32 colorkey = -1); // Subtitles methods diff --git a/engines/zvision/scripting/actions.cpp b/engines/zvision/scripting/actions.cpp index 7c3463b6d0..a91476760d 100644 --- a/engines/zvision/scripting/actions.cpp +++ b/engines/zvision/scripting/actions.cpp @@ -566,6 +566,12 @@ ActionPreloadAnimation::ActionPreloadAnimation(ZVision *engine, int32 slotkey, c // The two %*u are usually 0 and dont seem to have a use sscanf(line.c_str(), "%24s %*u %*u %d %d", fileName, &_mask, &_framerate); + // Mask 0 means "no transparency" in this case. Since we use a common blitting + // code for images and animations, we set it to -1 to avoid confusion with + // color 0, which is used as a mask in some images + if (_mask == 0) + _mask = -1; + _fileName = Common::String(fileName); } @@ -628,6 +634,12 @@ ActionPlayAnimation::ActionPlayAnimation(ZVision *engine, int32 slotkey, const C "%24s %u %u %u %u %u %u %d %*u %*u %d %d", fileName, &_x, &_y, &_x2, &_y2, &_start, &_end, &_loopCount, &_mask, &_framerate); + // Mask 0 means "no transparency" in this case. Since we use a common blitting + // code for images and animations, we set it to -1 to avoid confusion with + // color 0, which is used as a mask in some images + if (_mask == 0) + _mask = -1; + _fileName = Common::String(fileName); } diff --git a/engines/zvision/scripting/sidefx/animation_node.cpp b/engines/zvision/scripting/sidefx/animation_node.cpp index b966aa9cb8..7759758f56 100644 --- a/engines/zvision/scripting/sidefx/animation_node.cpp +++ b/engines/zvision/scripting/sidefx/animation_node.cpp @@ -154,17 +154,11 @@ bool AnimationNode::process(uint32 deltaTimeInMillis) { if (_engine->getRenderManager()->getRenderTable()->getRenderState() == RenderTable::PANORAMA) { Graphics::Surface *transposed = RenderManager::tranposeSurface(frame); - if (_mask > 0) - _engine->getRenderManager()->blitSurfaceToBkg(*transposed, nod->pos.left, nod->pos.top, _mask); - else - _engine->getRenderManager()->blitSurfaceToBkg(*transposed, nod->pos.left, nod->pos.top); + _engine->getRenderManager()->blitSurfaceToBkg(*transposed, nod->pos.left, nod->pos.top, _mask); transposed->free(); delete transposed; } else { - if (_mask > 0) - _engine->getRenderManager()->blitSurfaceToBkg(*frame, nod->pos.left, nod->pos.top, _mask); - else - _engine->getRenderManager()->blitSurfaceToBkg(*frame, nod->pos.left, nod->pos.top); + _engine->getRenderManager()->blitSurfaceToBkg(*frame, nod->pos.left, nod->pos.top, _mask); } } } diff --git a/engines/zvision/text/text.cpp b/engines/zvision/text/text.cpp index f28ba6ade3..a5ed044424 100644 --- a/engines/zvision/text/text.cpp +++ b/engines/zvision/text/text.cpp @@ -462,15 +462,16 @@ void TextRenderer::drawTxtInOneLine(const Common::String &text, Graphics::Surfac j++; } dx = 0; + Common::Rect empty; for (int32 jj = 0; jj < j; jj++) { if (TxtJustify[i] == TXT_JUSTIFY_LEFT) - _engine->getRenderManager()->blitSurfaceToSurface(*TxtSurfaces[i][jj], dst, dx, dy + TxtPoint[i] - TxtSurfaces[i][jj]->h, 0); + _engine->getRenderManager()->blitSurfaceToSurface(*TxtSurfaces[i][jj], empty, dst, dx, dy + TxtPoint[i] - TxtSurfaces[i][jj]->h, 0); else if (TxtJustify[i] == TXT_JUSTIFY_CENTER) - _engine->getRenderManager()->blitSurfaceToSurface(*TxtSurfaces[i][jj], dst, ((dst.w - width) / 2) + dx, dy + TxtPoint[i] - TxtSurfaces[i][jj]->h, 0); + _engine->getRenderManager()->blitSurfaceToSurface(*TxtSurfaces[i][jj], empty, dst, ((dst.w - width) / 2) + dx, dy + TxtPoint[i] - TxtSurfaces[i][jj]->h, 0); else if (TxtJustify[i] == TXT_JUSTIFY_RIGHT) - _engine->getRenderManager()->blitSurfaceToSurface(*TxtSurfaces[i][jj], dst, dst.w - width + dx, dy + TxtPoint[i] - TxtSurfaces[i][jj]->h, 0); + _engine->getRenderManager()->blitSurfaceToSurface(*TxtSurfaces[i][jj], empty, dst, dst.w - width + dx, dy + TxtPoint[i] - TxtSurfaces[i][jj]->h, 0); dx += TxtSurfaces[i][jj]->w; } -- cgit v1.2.3 From a9701d04c17b6f565e5602f12546bfe7aa2848af Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 26 Dec 2014 22:35:02 +0200 Subject: ZVISION: Remove duplicate image loading code --- engines/zvision/graphics/render_manager.cpp | 14 ++------------ engines/zvision/graphics/render_manager.h | 6 ++---- 2 files changed, 4 insertions(+), 16 deletions(-) (limited to 'engines') diff --git a/engines/zvision/graphics/render_manager.cpp b/engines/zvision/graphics/render_manager.cpp index 7bbde81e4c..73483f2309 100644 --- a/engines/zvision/graphics/render_manager.cpp +++ b/engines/zvision/graphics/render_manager.cpp @@ -568,28 +568,18 @@ Graphics::Surface *RenderManager::getBkgRect(Common::Rect &rect) { return srf; } -Graphics::Surface *RenderManager::loadImage(Common::String &file) { +Graphics::Surface *RenderManager::loadImage(Common::String file) { Graphics::Surface *tmp = new Graphics::Surface; readImageToSurface(file, *tmp); return tmp; } -Graphics::Surface *RenderManager::loadImage(const char *file) { - Common::String str = Common::String(file); - return loadImage(str); -} - -Graphics::Surface *RenderManager::loadImage(Common::String &file, bool transposed) { +Graphics::Surface *RenderManager::loadImage(Common::String file, bool transposed) { Graphics::Surface *tmp = new Graphics::Surface; readImageToSurface(file, *tmp, transposed); return tmp; } -Graphics::Surface *RenderManager::loadImage(const char *file, bool transposed) { - Common::String str = Common::String(file); - return loadImage(str, transposed); -} - void RenderManager::prepareBackground() { _backgroundDirtyRect.clip(_backgroundWidth, _backgroundHeight); RenderTable::RenderState state = _renderTable.getRenderState(); diff --git a/engines/zvision/graphics/render_manager.h b/engines/zvision/graphics/render_manager.h index a7e49b7758..d9a6c88896 100644 --- a/engines/zvision/graphics/render_manager.h +++ b/engines/zvision/graphics/render_manager.h @@ -263,10 +263,8 @@ public: Graphics::Surface *getBkgRect(Common::Rect &rect); // Load image into new surface - Graphics::Surface *loadImage(const char *file); - Graphics::Surface *loadImage(Common::String &file); - Graphics::Surface *loadImage(const char *file, bool transposed); - Graphics::Surface *loadImage(Common::String &file, bool transposed); + Graphics::Surface *loadImage(Common::String file); + Graphics::Surface *loadImage(Common::String file, bool transposed); // Clear whole/area of menu surface void clearMenuSurface(); -- cgit v1.2.3 From 85142cd0d7fb6e24fc45b2c61611f848b8c4a102 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 26 Dec 2014 22:48:58 +0200 Subject: ZVISION: Remove duplicate subtitle code --- engines/zvision/graphics/render_manager.cpp | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) (limited to 'engines') diff --git a/engines/zvision/graphics/render_manager.cpp b/engines/zvision/graphics/render_manager.cpp index 73483f2309..4f7b16c833 100644 --- a/engines/zvision/graphics/render_manager.cpp +++ b/engines/zvision/graphics/render_manager.cpp @@ -698,18 +698,9 @@ uint16 RenderManager::createSubArea(const Common::Rect &area) { } uint16 RenderManager::createSubArea() { - _subid++; - - OneSubtitle sub; - sub.redraw = false; - sub.timer = -1; - sub.todelete = false; - sub.r = Common::Rect(_subtitleArea.left, _subtitleArea.top, _subtitleArea.right, _subtitleArea.bottom); - sub.r.translate(-_workingWindow.left, -_workingWindow.top); - - _subsList[_subid] = sub; - - return _subid; + Common::Rect r(_subtitleArea.left, _subtitleArea.top, _subtitleArea.right, _subtitleArea.bottom); + r.translate(-_workingWindow.left, -_workingWindow.top); + return createSubArea(r); } void RenderManager::deleteSubArea(uint16 id) { -- cgit v1.2.3 From 19ce38d40e9f273335b06a62bcb0d3643602080c Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 26 Dec 2014 22:51:33 +0200 Subject: ZVISION: Turn off subtitles, if requested --- engines/zvision/graphics/render_manager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/zvision/graphics/render_manager.cpp b/engines/zvision/graphics/render_manager.cpp index 4f7b16c833..4f26123fc8 100644 --- a/engines/zvision/graphics/render_manager.cpp +++ b/engines/zvision/graphics/render_manager.cpp @@ -737,7 +737,7 @@ void RenderManager::processSubs(uint16 deltatime) { } } - if (redraw) { + if (redraw && _engine->getScriptManager()->getStateValue(StateKey_Subtitles) == 1) { _subtitleSurface.fillRect(Common::Rect(_subtitleSurface.w, _subtitleSurface.h), 0); for (SubtitleMap::iterator it = _subsList.begin(); it != _subsList.end(); it++) { -- cgit v1.2.3 From f9595b11fc2bef08d84a00b81f9b2884f77897b0 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 26 Dec 2014 23:18:54 +0200 Subject: ZVISION: Add an FPS timer (accessible with F10, or the "FRAME" cheat) --- engines/zvision/core/events.cpp | 18 +++++++++++++----- engines/zvision/zvision.cpp | 19 ++++++++++++++++++- engines/zvision/zvision.h | 7 +++++++ 3 files changed, 38 insertions(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/zvision/core/events.cpp b/engines/zvision/core/events.cpp index 4438474078..7804130e2a 100644 --- a/engines/zvision/core/events.cpp +++ b/engines/zvision/core/events.cpp @@ -158,15 +158,18 @@ void ZVision::cheatCodes(uint8 key) { } } - if (checkCode("FRAME")) - _renderManager->showDebugMsg(Common::String::format("FPS: ???, not implemented")); + if (checkCode("FRAME")) { + Common::String fpsStr = Common::String::format("FPS: %d", getFPS()); + _renderManager->showDebugMsg(fpsStr); + } + + if (checkCode("COMPUTERARCH")) + _renderManager->showDebugMsg("COMPUTERARCH: var-viewer not implemented"); + // This cheat essentially toggles the GOxxxx cheat below if (checkCode("XYZZY")) _scriptManager->setStateValue(StateKey_DebugCheats, 1 - _scriptManager->getStateValue(StateKey_DebugCheats)); - if (checkCode("COMPUTERARCH")) - _renderManager->showDebugMsg(Common::String::format("COMPUTERARCH: var-viewer not implemented")); - if (_scriptManager->getStateValue(StateKey_DebugCheats) == 1) if (checkCode("GO????")) _scriptManager->changeLocation(getBufferedKey(3), @@ -240,6 +243,11 @@ void ZVision::processEvents() { _scriptManager->getStateValue(StateKey_KbdRotateSpeed)) * 2; break; + case Common::KEYCODE_F10: { + Common::String fpsStr = Common::String::format("FPS: %d", getFPS()); + _renderManager->showDebugMsg(fpsStr); + } + break; default: break; } diff --git a/engines/zvision/zvision.cpp b/engines/zvision/zvision.cpp index b3fc02ee15..615574bbcd 100644 --- a/engines/zvision/zvision.cpp +++ b/engines/zvision/zvision.cpp @@ -101,7 +101,9 @@ ZVision::ZVision(OSystem *syst, const ZVisionGameDescription *gameDesc) _frameRenderDelay(2), _keyboardVelocity(0), _mouseVelocity(0), - _videoIsPlaying(false) { + _videoIsPlaying(false), + _renderedFrameCount(0), + _fps(0) { debug(1, "ZVision::ZVision"); @@ -130,6 +132,8 @@ ZVision::~ZVision() { delete _rnd; delete _midiManager; + getTimerManager()->removeTimerProc(&fpsTimerCallback); + // Remove all of our debug levels DebugMan.clearAllDebugChannels(); } @@ -214,6 +218,9 @@ void ZVision::initialize() { // Create debugger console. It requires GFX to be initialized _console = new Console(this); _doubleFPS = ConfMan.getBool("doublefps"); + + // Initialize FPS timer callback + getTimerManager()->installTimerProc(&fpsTimerCallback, 1000000, this, "zvisionFPS"); } Common::Error ZVision::run() { @@ -246,6 +253,7 @@ Common::Error ZVision::run() { // Update the screen if (canRender()) { _system->updateScreen(); + _renderedFrameCount++; } else { _frameRenderDelay--; } @@ -291,4 +299,13 @@ bool ZVision::canRender() { return _frameRenderDelay <= 0; } +void ZVision::fpsTimerCallback(void *refCon) { + ((ZVision *)refCon)->fpsTimer(); +} + +void ZVision::fpsTimer() { + _fps = _renderedFrameCount; + _renderedFrameCount = 0; +} + } // End of namespace ZVision diff --git a/engines/zvision/zvision.h b/engines/zvision/zvision.h index 6664d0cd5d..5482060cd0 100644 --- a/engines/zvision/zvision.h +++ b/engines/zvision/zvision.h @@ -119,6 +119,8 @@ private: Common::Event _event; int _frameRenderDelay; + int _renderedFrameCount; + int _fps; int16 _mouseVelocity; int16 _keyboardVelocity; bool _doubleFPS; @@ -197,6 +199,11 @@ public: void setRenderDelay(uint); bool canRender(); + static void fpsTimerCallback(void *refCon); + void fpsTimer(); + int getFPS() const { + return _fps; + } void loadSettings(); void saveSettings(); -- cgit v1.2.3 From eb46e837969f2f650b5debaa387e63127b83db6c Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 27 Dec 2014 00:00:07 +0200 Subject: ZVISION: Quit with an error message dialog if no font files are found --- engines/zvision/zvision.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/zvision/zvision.cpp b/engines/zvision/zvision.cpp index 615574bbcd..fe8e129800 100644 --- a/engines/zvision/zvision.cpp +++ b/engines/zvision/zvision.cpp @@ -46,8 +46,8 @@ #include "common/system.h" #include "common/file.h" +#include "gui/message.h" #include "engines/util.h" - #include "audio/mixer.h" namespace ZVision { @@ -230,6 +230,22 @@ Common::Error ZVision::run() { if (ConfMan.hasKey("save_slot")) _saveManager->loadGame(ConfMan.getInt("save_slot")); + // Before starting, make absolutely sure that the user has copied the needed fonts + if (!Common::File::exists("arial.ttf") && !Common::File::exists("FreeSans.ttf")) { + GUI::MessageDialog dialog( + "Before playing this game, you'll need to copy the required " + "fonts in ScummVM's extras directory, or the game directory. " + "On Windows, you'll need the following font files from the Windows " + "font directory: Times New Roman, Century Schoolbook, Garamond, " + "Courier New and Arial. Alternatively, you can download the GNU " + "FreeFont package. You'll need all the fonts from that package, " + "i.e. FreeMono, FreeSans and FreeSerif." + ); + dialog.runModal(); + quitGame(); + return Common::kUnknownError; + } + // Main loop while (!shouldQuit()) { _clock.update(); -- cgit v1.2.3 From fd34456bb8bcbf39667df50eb6d14a9f4fbe7087 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 27 Dec 2014 01:02:51 +0200 Subject: ZVISION: Delete the render manager after the script manager on quit This is necessary, as the script manager may include references to the render manager, such as side effects in Zork: Nemesis. Fixes a crash on engine exit when the current scene contains such effects --- engines/zvision/zvision.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/zvision/zvision.cpp b/engines/zvision/zvision.cpp index fe8e129800..7c26eba030 100644 --- a/engines/zvision/zvision.cpp +++ b/engines/zvision/zvision.cpp @@ -127,8 +127,8 @@ ZVision::~ZVision() { delete _cursorManager; delete _stringManager; delete _saveManager; - delete _renderManager; delete _scriptManager; + delete _renderManager; // should be deleted after the script manager delete _rnd; delete _midiManager; -- cgit v1.2.3 From 569c06b5105c7bae0a72d4abc72cf5db51541702 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Sat, 27 Dec 2014 11:10:14 +0100 Subject: SCI: Fix warning --- engines/sci/engine/state.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index c07dc925e0..527c8f0ae0 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -205,7 +205,7 @@ static kLanguage charToLanguage(const char c) { Common::String SciEngine::getSciLanguageString(const Common::String &str, kLanguage requestedLanguage, kLanguage *secondaryLanguage, uint16 *languageSplitter) const { kLanguage foundLanguage = K_LANG_NONE; - const byte *textPtr = (byte *)str.c_str(); + const byte *textPtr = (const byte *)str.c_str(); byte curChar = 0; byte curChar2 = 0; -- cgit v1.2.3 From ba40b3ea4905716fc8dd6f01bfec6d414b6b9a58 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 27 Dec 2014 14:27:37 +0200 Subject: ZVISION: Clean up the game settings --- engines/zvision/detection.cpp | 66 ++++++++++++++++++++++-------------- engines/zvision/zvision.cpp | 78 ++++++++++++++++++++++++++++++------------- 2 files changed, 95 insertions(+), 49 deletions(-) (limited to 'engines') diff --git a/engines/zvision/detection.cpp b/engines/zvision/detection.cpp index 4fcb5c040b..c613278fec 100644 --- a/engines/zvision/detection.cpp +++ b/engines/zvision/detection.cpp @@ -55,6 +55,10 @@ static const PlainGameDescriptor zVisionGames[] = { namespace ZVision { +#define GAMEOPTION_ORIGINAL_SAVELOAD GUIO_GAMEOPTIONS1 +#define GAMEOPTION_DOUBLE_FPS GUIO_GAMEOPTIONS2 +#define GAMEOPTION_ENABLE_VENUS GUIO_GAMEOPTIONS3 + static const ZVisionGameDescription gameDescriptions[] = { { @@ -66,7 +70,7 @@ static const ZVisionGameDescription gameDescriptions[] = { Common::EN_ANY, Common::kPlatformDOS, ADGF_NO_FLAGS, - GUIO1(GUIO_NONE) + GUIO3(GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_DOUBLE_FPS, GAMEOPTION_ENABLE_VENUS) }, GID_NEMESIS }, @@ -80,7 +84,7 @@ static const ZVisionGameDescription gameDescriptions[] = { Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO, - GUIO1(GUIO_NONE) + GUIO3(GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_DOUBLE_FPS, GAMEOPTION_ENABLE_VENUS) }, GID_NEMESIS }, @@ -94,7 +98,7 @@ static const ZVisionGameDescription gameDescriptions[] = { Common::EN_ANY, Common::kPlatformWindows, ADGF_NO_FLAGS, - GUIO1(GUIO_NONE) + GUIO2(GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_DOUBLE_FPS) }, GID_GRANDINQUISITOR }, @@ -108,7 +112,7 @@ static const ZVisionGameDescription gameDescriptions[] = { Common::EN_ANY, Common::kPlatformWindows, ADGF_NO_FLAGS, - GUIO1(GUIO_NONE) + GUIO2(GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_DOUBLE_FPS) }, GID_GRANDINQUISITOR }, @@ -122,7 +126,7 @@ static const ZVisionGameDescription gameDescriptions[] = { Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO, - GUIO1(GUIO_NONE) + GUIO2(GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_DOUBLE_FPS) }, GID_GRANDINQUISITOR }, @@ -140,23 +144,43 @@ static const char *directoryGlobs[] = { 0 }; -static const ExtraGuiOption ZVisionExtraGuiOption = { - _s("Use original save/load screens"), - _s("Use the original save/load screens, instead of the ScummVM ones"), - "originalsaveload", - false -}; +static const ADExtraGuiOptionsMap optionsList[] = { + { + GAMEOPTION_ORIGINAL_SAVELOAD, + { + _s("Use original save/load screens"), + _s("Use the original save/load screens, instead of the ScummVM ones"), + "originalsaveload", + false + } + }, -static const ExtraGuiOption ZVisionExtraGuiOption2 = { - _s("Double FPS"), - _s("Halve the update delay"), - "doublefps", - false + { + GAMEOPTION_DOUBLE_FPS, + { + _s("Double FPS"), + _s("Halve the update delay"), + "doublefps", + false + } + }, + + { + GAMEOPTION_ENABLE_VENUS, + { + _s("Enable Venus"), + _s("Enable the Venus help system"), + "venusenabled", + true + } + }, + + AD_EXTRA_GUI_OPTIONS_TERMINATOR }; class ZVisionMetaEngine : public AdvancedMetaEngine { public: - ZVisionMetaEngine() : AdvancedMetaEngine(ZVision::gameDescriptions, sizeof(ZVision::ZVisionGameDescription), zVisionGames) { + ZVisionMetaEngine() : AdvancedMetaEngine(ZVision::gameDescriptions, sizeof(ZVision::ZVisionGameDescription), zVisionGames, optionsList) { _maxScanDepth = 2; _directoryGlobs = directoryGlobs; _singleid = "zvision"; @@ -172,7 +196,6 @@ public: virtual bool hasFeature(MetaEngineFeature f) const; virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const; - virtual const ExtraGuiOptions getExtraGuiOptions(const Common::String &target) const; SaveStateList listSaves(const char *target) const; virtual int getMaximumSaveSlot() const; void removeSaveState(const char *target, int slot) const; @@ -223,13 +246,6 @@ bool ZVisionMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADG return gd != 0; } -const ExtraGuiOptions ZVisionMetaEngine::getExtraGuiOptions(const Common::String &target) const { - ExtraGuiOptions options; - options.push_back(ZVisionExtraGuiOption); - options.push_back(ZVisionExtraGuiOption2); - return options; -} - SaveStateList ZVisionMetaEngine::listSaves(const char *target) const { Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); ZVision::SaveGameHeader header; diff --git a/engines/zvision/zvision.cpp b/engines/zvision/zvision.cpp index 7c26eba030..5f4924d7cf 100644 --- a/engines/zvision/zvision.cpp +++ b/engines/zvision/zvision.cpp @@ -57,25 +57,29 @@ namespace ZVision { struct zvisionIniSettings { const char *name; int16 slot; - int16 deflt; + int16 defaultValue; // -1: use the bool value + bool defaultBoolValue; + bool allowEditing; } settingsKeys[ZVISION_SETTINGS_KEYS_COUNT] = { - {"ZVision_KeyboardTurnSpeed", StateKey_KbdRotateSpeed, 5}, - {"ZVision_PanaRotateSpeed", StateKey_RotateSpeed, 540}, - {"ZVision_QSoundEnabled", StateKey_Qsound, 1}, - {"ZVision_VenusEnabled", StateKey_VenusEnable, 1}, - {"ZVision_HighQuality", StateKey_HighQuality, 1}, - {"ZVision_Platform", StateKey_Platform, 0}, - {"ZVision_InstallLevel", StateKey_InstallLevel, 0}, - {"ZVision_CountryCode", StateKey_CountryCode, 0}, - {"ZVision_CPU", StateKey_CPU, 1}, - {"ZVision_MovieCursor", StateKey_MovieCursor, 1}, - {"ZVision_NoAnimWhileTurning", StateKey_NoTurnAnim, 0}, - {"ZVision_Win958", StateKey_WIN958, 0}, - {"ZVision_ShowErrorDialogs", StateKey_ShowErrorDlg, 0}, - {"ZVision_ShowSubtitles", StateKey_Subtitles, 1}, - {"ZVision_DebugCheats", StateKey_DebugCheats, 0}, - {"ZVision_JapaneseFonts", StateKey_JapanFonts, 0}, - {"ZVision_Brightness", StateKey_Brightness, 0} + // Hardcoded settings + {"qsoundenabled", StateKey_Qsound, 1, false, false}, + {"highquality", StateKey_HighQuality, 1, false, false}, + {"platform", StateKey_Platform, 0, false, false}, + {"installlevel", StateKey_InstallLevel, 0, false, false}, + {"countrycode", StateKey_CountryCode, 0, false, false}, + {"cpu", StateKey_CPU, 1, false, false}, + {"moviecursor", StateKey_MovieCursor, 1, false, false}, + {"noanimwhileturning", StateKey_NoTurnAnim, 0, false, false}, + {"win958", StateKey_WIN958, 0, false, false}, + {"showerrordialogs", StateKey_ShowErrorDlg, 0, false, false}, + {"japanesefonts", StateKey_JapanFonts, 0, false, false}, + {"brightness", StateKey_Brightness, 0, false, false}, + {"debugcheats", StateKey_DebugCheats, 1, false, false}, + // Editable settings + {"keyboardturnspeed", StateKey_KbdRotateSpeed, 5, false, true}, + {"panarotatespeed", StateKey_RotateSpeed, 540, false, true}, + {"venusenabled", StateKey_VenusEnable, -1, true, true}, + {"subtitles", StateKey_Subtitles, -1, true, true}, }; ZVision::ZVision(OSystem *syst, const ZVisionGameDescription *gameDesc) @@ -139,14 +143,33 @@ ZVision::~ZVision() { } void ZVision::registerDefaultSettings() { - for (int i = 0; i < ZVISION_SETTINGS_KEYS_COUNT; i++) - ConfMan.registerDefault(settingsKeys[i].name, settingsKeys[i].deflt); + for (int i = 0; i < ZVISION_SETTINGS_KEYS_COUNT; i++) { + if (settingsKeys[i].allowEditing) { + if (settingsKeys[i].defaultValue >= 0) + ConfMan.registerDefault(settingsKeys[i].name, settingsKeys[i].defaultValue); + else + ConfMan.registerDefault(settingsKeys[i].name, settingsKeys[i].defaultBoolValue); + } + } + + ConfMan.registerDefault("originalsaveload", false); ConfMan.registerDefault("doublefps", false); } void ZVision::loadSettings() { - for (int i = 0; i < ZVISION_SETTINGS_KEYS_COUNT; i++) - _scriptManager->setStateValue(settingsKeys[i].slot, ConfMan.getInt(settingsKeys[i].name)); + int16 value = 0; + bool boolValue = false; + + for (int i = 0; i < ZVISION_SETTINGS_KEYS_COUNT; i++) { + if (settingsKeys[i].defaultValue >= 0) { + value = (settingsKeys[i].allowEditing) ? ConfMan.getInt(settingsKeys[i].name) : settingsKeys[i].defaultValue; + } else { + boolValue = value = (settingsKeys[i].allowEditing) ? ConfMan.getBool(settingsKeys[i].name) : settingsKeys[i].defaultBoolValue; + value = (boolValue) ? 1 : 0; + } + + _scriptManager->setStateValue(settingsKeys[i].slot, value); + } if (getGameId() == GID_NEMESIS) _scriptManager->setStateValue(StateKey_ExecScopeStyle, 1); @@ -155,8 +178,15 @@ void ZVision::loadSettings() { } void ZVision::saveSettings() { - for (int i = 0; i < ZVISION_SETTINGS_KEYS_COUNT; i++) - ConfMan.setInt(settingsKeys[i].name, _scriptManager->getStateValue(settingsKeys[i].slot)); + for (int i = 0; i < ZVISION_SETTINGS_KEYS_COUNT; i++) { + if (settingsKeys[i].allowEditing) { + if (settingsKeys[i].defaultValue >= 0) + ConfMan.setInt(settingsKeys[i].name, _scriptManager->getStateValue(settingsKeys[i].slot)); + else + ConfMan.setBool(settingsKeys[i].name, (_scriptManager->getStateValue(settingsKeys[i].slot) == 1)); + } + } + ConfMan.flushToDisk(); } -- cgit v1.2.3 From e862172460640188363873b9fa1fb46a3f4c7f78 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 27 Dec 2014 14:29:17 +0200 Subject: ZVISION: Add some advanced engine features, and document the engine --- engines/zvision/zvision.cpp | 10 ++++++++++ engines/zvision/zvision.h | 14 ++++++++++++++ 2 files changed, 24 insertions(+) (limited to 'engines') diff --git a/engines/zvision/zvision.cpp b/engines/zvision/zvision.cpp index 5f4924d7cf..03103553cc 100644 --- a/engines/zvision/zvision.cpp +++ b/engines/zvision/zvision.cpp @@ -345,6 +345,16 @@ bool ZVision::canRender() { return _frameRenderDelay <= 0; } +GUI::Debugger *ZVision::getDebugger() { + return _console; +} + +void ZVision::syncSoundSettings() { + Engine::syncSoundSettings(); + + _scriptManager->setStateValue(StateKey_Subtitles, ConfMan.getBool("subtitles") ? 1 : 0); +} + void ZVision::fpsTimerCallback(void *refCon) { ((ZVision *)refCon)->fpsTimer(); } diff --git a/engines/zvision/zvision.h b/engines/zvision/zvision.h index 5482060cd0..ad22ddaaa2 100644 --- a/engines/zvision/zvision.h +++ b/engines/zvision/zvision.h @@ -41,6 +41,17 @@ namespace Video { class VideoDecoder; } +/** + * This is the namespace of the ZVision engine. + * + * Status of this engine: complete + * + * Games using this engine: + * - Zork Nemesis: The Forbidden Lands + * - Zork: Grand Inquisitor + * + */ + namespace ZVision { struct ZVisionGameDescription; @@ -205,6 +216,9 @@ public: return _fps; } + GUI::Debugger *getDebugger(); + void syncSoundSettings(); + void loadSettings(); void saveSettings(); -- cgit v1.2.3 From 39eab59388c6dc43d1f2c72ee708807ef1bdb198 Mon Sep 17 00:00:00 2001 From: Strangerke Date: Sat, 27 Dec 2014 15:31:43 +0100 Subject: ACCESS: Rewrite sound queueing (WIP) --- engines/access/amazon/amazon_logic.cpp | 52 ++++++++++++++++++---------------- engines/access/events.cpp | 2 ++ engines/access/sound.cpp | 50 ++++++++++++++++++++------------ engines/access/sound.h | 5 +++- 4 files changed, 66 insertions(+), 43 deletions(-) (limited to 'engines') diff --git a/engines/access/amazon/amazon_logic.cpp b/engines/access/amazon/amazon_logic.cpp index 4a313e8880..c045377f8a 100644 --- a/engines/access/amazon/amazon_logic.cpp +++ b/engines/access/amazon/amazon_logic.cpp @@ -341,15 +341,12 @@ void Opening::doTitle() { _vm->_objectsTable[0] = new SpriteResource(_vm, spriteData); delete spriteData; - _vm->_sound->playSound(1); - _vm->_files->_setPaletteFlag = false; _vm->_files->loadScreen(0, 4); _vm->_sound->playSound(1); _vm->_buffer2.copyFrom(*_vm->_screen); _vm->_buffer1.copyFrom(*_vm->_screen); - _vm->_sound->playSound(1); const int COUNTDOWN[6] = { 2, 0x80, 1, 0x7d, 0, 0x87 }; for (_pCount = 0; _pCount < 3 && !_vm->shouldQuit(); ++_pCount) { @@ -508,40 +505,47 @@ void Opening::doTent() { _vm->_screen->forceFadeIn(); _vm->_video->setVideo(_vm->_screen, Common::Point(126, 73), FileIdent(2, 1), 10); + int previousFrame = -1; while (!_vm->shouldQuit() && !_vm->_video->_videoEnd) { _vm->_video->playVideo(); - if ((_vm->_video->_videoFrame == 32) || (_vm->_video->_videoFrame == 34)) - _vm->_sound->playSound(4); - else if (_vm->_video->_videoFrame == 36) { - if (step != 2) { - _vm->_sound->playSound(2); - step = 2; - } - } else if (_vm->_video->_videoFrame == 18) { - if (step != 1) { - _vm->_midi->newMusic(73, 1); - _vm->_midi->newMusic(11, 0); - step = 1; - _vm->_sound->playSound(1); + if (previousFrame != _vm->_video->_videoFrame) { + previousFrame = _vm->_video->_videoFrame; + + if ((_vm->_video->_videoFrame == 32) || (_vm->_video->_videoFrame == 34)) + _vm->_sound->playSound(4); + else if (_vm->_video->_videoFrame == 36) { + if (step != 2) { + _vm->_sound->playSound(2); + step = 2; + } + } else if (_vm->_video->_videoFrame == 18) { + if (step != 1) { + _vm->_midi->newMusic(73, 1); + _vm->_midi->newMusic(11, 0); + step = 1; + _vm->_sound->playSound(1); + } } } - _vm->_events->pollEventsAndWait(); } _vm->_sound->playSound(5); _vm->_video->setVideo(_vm->_screen, Common::Point(43, 11), FileIdent(2, 2), 10); + previousFrame = -1; while (!_vm->shouldQuit() && !_vm->_video->_videoEnd) { _vm->_video->playVideo(); - if (_vm->_video->_videoFrame == 26) { - _vm->_sound->playSound(5); - } else if (_vm->_video->_videoFrame == 15) { - if (step !=3) { - _vm->_sound->playSound(3); - step = 3; + if (previousFrame != _vm->_video->_videoFrame) { + previousFrame = _vm->_video->_videoFrame; + if (_vm->_video->_videoFrame == 26) { + _vm->_sound->playSound(5); + } else if (_vm->_video->_videoFrame == 15) { + if (step !=3) { + _vm->_sound->playSound(3); + step = 3; + } } } - _vm->_events->pollEventsAndWait(); } diff --git a/engines/access/events.cpp b/engines/access/events.cpp index 0867b09765..6ffe67acfb 100644 --- a/engines/access/events.cpp +++ b/engines/access/events.cpp @@ -140,6 +140,8 @@ void EventsManager::pollEvents(bool skipTimers) { if (checkForNextTimerUpdate() && !skipTimers) nextTimer(); + _vm->_sound->checkSoundQueue(); + _wheelUp = _wheelDown = false; Common::Event event; diff --git a/engines/access/sound.cpp b/engines/access/sound.cpp index a7d96dac9a..82199a8286 100644 --- a/engines/access/sound.cpp +++ b/engines/access/sound.cpp @@ -22,7 +22,6 @@ #include "common/algorithm.h" #include "audio/mixer.h" -#include "audio/audiostream.h" #include "audio/decoders/raw.h" #include "audio/decoders/wave.h" #include "access/access.h" @@ -44,7 +43,19 @@ void SoundManager::clearSounds() { for (uint i = 0; i < _soundTable.size(); ++i) delete _soundTable[i]._res; + _soundTable.clear(); + + if (_mixer->isSoundHandleActive(_effectsHandle)) + _mixer->stopHandle(_effectsHandle); + + if (_queue.size()) + _queue.remove_at(0); + + while (_queue.size()) { + delete _queue[0]; + _queue.remove_at(0); + } } void SoundManager::queueSound(int idx, int fileNum, int subfile) { @@ -77,19 +88,14 @@ void SoundManager::playSound(Resource *res, int priority) { debugC(1, kDebugSound, "playSound"); byte *resourceData = res->data(); - Audio::SoundHandle audioHandle; - Audio::RewindableAudioStream *audioStream = 0; assert(res->_size >= 32); - // HACK: Simulates queueing for the rare sounds played one after the other - while (_mixer->hasActiveChannelOfType(Audio::Mixer::kSFXSoundType)) - ; - if (READ_BE_UINT32(resourceData) == MKTAG('R','I','F','F')) { // CD version uses WAVE-files Common::SeekableReadStream *waveStream = new Common::MemoryReadStream(resourceData, res->_size, DisposeAfterUse::NO); - audioStream = Audio::makeWAVStream(waveStream, DisposeAfterUse::YES); + Audio::RewindableAudioStream *audioStream = Audio::makeWAVStream(waveStream, DisposeAfterUse::YES); + _queue.push_back(audioStream); } else if (READ_BE_UINT32(resourceData) == MKTAG('S', 'T', 'E', 'V')) { // sound files have a fixed header of 32 bytes in total @@ -130,22 +136,30 @@ void SoundManager::playSound(Resource *res, int priority) { return; } - audioStream = Audio::makeRawStream(resourceData + 32, sampleSize, sampleRate, 0); + Audio::RewindableAudioStream *audioStream = Audio::makeRawStream(resourceData + 32, sampleSize, sampleRate, 0); + _queue.push_back(audioStream); } else error("Unknown format"); - audioHandle = Audio::SoundHandle(); - _mixer->playStream(Audio::Mixer::kSFXSoundType, &audioHandle, - audioStream, -1, _mixer->kMaxChannelVolume, 0, + if (!_mixer->isSoundHandleActive(_effectsHandle)) + _mixer->playStream(Audio::Mixer::kSFXSoundType, &_effectsHandle, + _queue[0], -1, _mixer->kMaxChannelVolume, 0, DisposeAfterUse::NO); +} + +void SoundManager::checkSoundQueue() { + debugC(5, kDebugSound, "checkSoundQueue"); + + if (_queue.empty() || _mixer->isSoundHandleActive(_effectsHandle)) + return; + + _queue.remove_at(0); - /* - Audio::QueuingAudioStream *audioStream = Audio::makeQueuingAudioStream(22050, false); - audioStream->queueBuffer(data, size, DisposeAfterUse::YES, 0); - _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, audioStream, -1, - Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::YES, false); - */ + if (_queue.size()) + _mixer->playStream(Audio::Mixer::kSFXSoundType, &_effectsHandle, + _queue[0], -1, _mixer->kMaxChannelVolume, 0, + DisposeAfterUse::YES); } void SoundManager::loadSounds(Common::Array &sounds) { diff --git a/engines/access/sound.h b/engines/access/sound.h index d0f4584fac..c276648477 100644 --- a/engines/access/sound.h +++ b/engines/access/sound.h @@ -24,6 +24,7 @@ #define ACCESS_SOUND_H #include "common/scummsys.h" +#include "audio/audiostream.h" #include "audio/mixer.h" #include "access/files.h" #include "audio/midiplayer.h" @@ -47,7 +48,8 @@ class SoundManager { private: AccessEngine *_vm; Audio::Mixer *_mixer; - Audio::SoundHandle _soundHandle; + Audio::SoundHandle _effectsHandle; + Common::Array _queue; void clearSounds(); @@ -63,6 +65,7 @@ public: void queueSound(int idx, int fileNum, int subfile); void playSound(int soundIndex); + void checkSoundQueue(); Resource *loadSound(int fileNum, int subfile); void loadSounds(Common::Array &sounds); -- cgit v1.2.3 From 1016838bd5e556a4882f2b07e993ea9e78d12f7f Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 27 Dec 2014 16:33:43 +0200 Subject: ZVISION: Add support for disabling animations while turning Also, clean up and document game configuration options, and add a TODO for QSound support --- engines/zvision/detection.cpp | 27 ++++++++++++++------ .../zvision/scripting/sidefx/animation_node.cpp | 25 +++++++++++++------ engines/zvision/scripting/sidefx/distort_node.cpp | 1 - engines/zvision/zvision.cpp | 29 +++++++++++----------- 4 files changed, 52 insertions(+), 30 deletions(-) (limited to 'engines') diff --git a/engines/zvision/detection.cpp b/engines/zvision/detection.cpp index c613278fec..1eaff83413 100644 --- a/engines/zvision/detection.cpp +++ b/engines/zvision/detection.cpp @@ -55,9 +55,10 @@ static const PlainGameDescriptor zVisionGames[] = { namespace ZVision { -#define GAMEOPTION_ORIGINAL_SAVELOAD GUIO_GAMEOPTIONS1 -#define GAMEOPTION_DOUBLE_FPS GUIO_GAMEOPTIONS2 -#define GAMEOPTION_ENABLE_VENUS GUIO_GAMEOPTIONS3 +#define GAMEOPTION_ORIGINAL_SAVELOAD GUIO_GAMEOPTIONS1 +#define GAMEOPTION_DOUBLE_FPS GUIO_GAMEOPTIONS2 +#define GAMEOPTION_ENABLE_VENUS GUIO_GAMEOPTIONS3 +#define GAMEOPTION_DISABLE_ANIM_WHILE_TURNING GUIO_GAMEOPTIONS4 static const ZVisionGameDescription gameDescriptions[] = { @@ -70,7 +71,7 @@ static const ZVisionGameDescription gameDescriptions[] = { Common::EN_ANY, Common::kPlatformDOS, ADGF_NO_FLAGS, - GUIO3(GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_DOUBLE_FPS, GAMEOPTION_ENABLE_VENUS) + GUIO4(GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_DOUBLE_FPS, GAMEOPTION_ENABLE_VENUS, GAMEOPTION_DISABLE_ANIM_WHILE_TURNING) }, GID_NEMESIS }, @@ -84,7 +85,7 @@ static const ZVisionGameDescription gameDescriptions[] = { Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO, - GUIO3(GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_DOUBLE_FPS, GAMEOPTION_ENABLE_VENUS) + GUIO4(GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_DOUBLE_FPS, GAMEOPTION_ENABLE_VENUS, GAMEOPTION_DISABLE_ANIM_WHILE_TURNING) }, GID_NEMESIS }, @@ -98,7 +99,7 @@ static const ZVisionGameDescription gameDescriptions[] = { Common::EN_ANY, Common::kPlatformWindows, ADGF_NO_FLAGS, - GUIO2(GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_DOUBLE_FPS) + GUIO3(GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_DOUBLE_FPS, GAMEOPTION_DISABLE_ANIM_WHILE_TURNING) }, GID_GRANDINQUISITOR }, @@ -112,7 +113,7 @@ static const ZVisionGameDescription gameDescriptions[] = { Common::EN_ANY, Common::kPlatformWindows, ADGF_NO_FLAGS, - GUIO2(GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_DOUBLE_FPS) + GUIO3(GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_DOUBLE_FPS, GAMEOPTION_DISABLE_ANIM_WHILE_TURNING) }, GID_GRANDINQUISITOR }, @@ -126,7 +127,7 @@ static const ZVisionGameDescription gameDescriptions[] = { Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO, - GUIO2(GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_DOUBLE_FPS) + GUIO3(GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_DOUBLE_FPS, GAMEOPTION_DISABLE_ANIM_WHILE_TURNING) }, GID_GRANDINQUISITOR }, @@ -175,6 +176,16 @@ static const ADExtraGuiOptionsMap optionsList[] = { } }, + { + GAMEOPTION_DISABLE_ANIM_WHILE_TURNING, + { + _s("Disable animation while turning"), + _s("Disable animation while turning in panoramic mode"), + "noanimwhileturning", + false + } + }, + AD_EXTRA_GUI_OPTIONS_TERMINATOR }; diff --git a/engines/zvision/scripting/sidefx/animation_node.cpp b/engines/zvision/scripting/sidefx/animation_node.cpp index 7759758f56..3dd80f3699 100644 --- a/engines/zvision/scripting/sidefx/animation_node.cpp +++ b/engines/zvision/scripting/sidefx/animation_node.cpp @@ -75,6 +75,17 @@ AnimationNode::~AnimationNode() { } bool AnimationNode::process(uint32 deltaTimeInMillis) { + ScriptManager *scriptManager = _engine->getScriptManager(); + RenderManager *renderManager = _engine->getRenderManager(); + RenderTable::RenderState renderState = renderManager->getRenderTable()->getRenderState(); + bool isPanorama = (renderState == RenderTable::PANORAMA); + int16 velocity = _engine->getMouseVelocity() + _engine->getKeyboardVelocity(); + + // Do not update animation nodes in panoramic mode while turning, if the user + // has set this option + if (scriptManager->getStateValue(StateKey_NoTurnAnim) == 1 && isPanorama && velocity) + return false; + PlayNodes::iterator it = _playList.begin(); if (it != _playList.end()) { playnode *nod = &(*it); @@ -93,7 +104,7 @@ bool AnimationNode::process(uint32 deltaTimeInMillis) { nod->_delay = _frmDelay; if (nod->slot) - _engine->getScriptManager()->setStateValue(nod->slot, 1); + scriptManager->setStateValue(nod->slot, 1); } else { nod->_curFrame++; @@ -102,7 +113,7 @@ bool AnimationNode::process(uint32 deltaTimeInMillis) { if (nod->loop == 0) { if (nod->slot >= 0) - _engine->getScriptManager()->setStateValue(nod->slot, 2); + scriptManager->setStateValue(nod->slot, 2); if (nod->_scaled) { nod->_scaled->free(); delete nod->_scaled; @@ -121,7 +132,7 @@ bool AnimationNode::process(uint32 deltaTimeInMillis) { if (frame) { uint32 dstw; uint32 dsth; - if (_engine->getRenderManager()->getRenderTable()->getRenderState() == RenderTable::PANORAMA) { + if (isPanorama) { dstw = nod->pos.height(); dsth = nod->pos.width(); } else { @@ -148,17 +159,17 @@ bool AnimationNode::process(uint32 deltaTimeInMillis) { nod->_scaled->create(dstw, dsth, frame->format); } - _engine->getRenderManager()->scaleBuffer(frame->getPixels(), nod->_scaled->getPixels(), frame->w, frame->h, frame->format.bytesPerPixel, dstw, dsth); + renderManager->scaleBuffer(frame->getPixels(), nod->_scaled->getPixels(), frame->w, frame->h, frame->format.bytesPerPixel, dstw, dsth); frame = nod->_scaled; } - if (_engine->getRenderManager()->getRenderTable()->getRenderState() == RenderTable::PANORAMA) { + if (isPanorama) { Graphics::Surface *transposed = RenderManager::tranposeSurface(frame); - _engine->getRenderManager()->blitSurfaceToBkg(*transposed, nod->pos.left, nod->pos.top, _mask); + renderManager->blitSurfaceToBkg(*transposed, nod->pos.left, nod->pos.top, _mask); transposed->free(); delete transposed; } else { - _engine->getRenderManager()->blitSurfaceToBkg(*frame, nod->pos.left, nod->pos.top, _mask); + renderManager->blitSurfaceToBkg(*frame, nod->pos.left, nod->pos.top, _mask); } } } diff --git a/engines/zvision/scripting/sidefx/distort_node.cpp b/engines/zvision/scripting/sidefx/distort_node.cpp index 0d5c8b1ed5..7d25adc031 100644 --- a/engines/zvision/scripting/sidefx/distort_node.cpp +++ b/engines/zvision/scripting/sidefx/distort_node.cpp @@ -65,7 +65,6 @@ DistortNode::~DistortNode() { } bool DistortNode::process(uint32 deltaTimeInMillis) { - float updTime = deltaTimeInMillis / (1000.0 / 60.0); if (_incr) diff --git a/engines/zvision/zvision.cpp b/engines/zvision/zvision.cpp index 03103553cc..a28ad862d9 100644 --- a/engines/zvision/zvision.cpp +++ b/engines/zvision/zvision.cpp @@ -62,22 +62,23 @@ struct zvisionIniSettings { bool allowEditing; } settingsKeys[ZVISION_SETTINGS_KEYS_COUNT] = { // Hardcoded settings - {"qsoundenabled", StateKey_Qsound, 1, false, false}, - {"highquality", StateKey_HighQuality, 1, false, false}, - {"platform", StateKey_Platform, 0, false, false}, - {"installlevel", StateKey_InstallLevel, 0, false, false}, - {"countrycode", StateKey_CountryCode, 0, false, false}, - {"cpu", StateKey_CPU, 1, false, false}, - {"moviecursor", StateKey_MovieCursor, 1, false, false}, - {"noanimwhileturning", StateKey_NoTurnAnim, 0, false, false}, - {"win958", StateKey_WIN958, 0, false, false}, - {"showerrordialogs", StateKey_ShowErrorDlg, 0, false, false}, - {"japanesefonts", StateKey_JapanFonts, 0, false, false}, - {"brightness", StateKey_Brightness, 0, false, false}, - {"debugcheats", StateKey_DebugCheats, 1, false, false}, + //{"platform", StateKey_Platform, 0, false, false}, // 0 = Windows, 1 = DOS, 2 = DOS, unused + //{"installlevel", StateKey_InstallLevel, 0, false, false}, // 0 = full, unused + //{"countrycode", StateKey_CountryCode, 0, false, false}, // always 0 = US, unused + //{"cpu", StateKey_CPU, 1, false, false}, // always 1 = Pentium (0 is 486), unused + //{"win958", StateKey_WIN958, 0, false, false}, // unused, probably Windows version flag + //{"showerrordialogs", StateKey_ShowErrorDlg, 0, false, false}, // unused + //{"japanesefonts", StateKey_JapanFonts, 0, false, false}, + //{"brightness", StateKey_Brightness, 0, false, false}, + //{"lineskipvideo", StateKey_VideoLineSkip, 0, false, false}, // video line skip, 0 = default, 1 = always, 2 = pixel double when possible, unused + //{"highquality", StateKey_HighQuality, 0, false, false}, // performance related, always high + //{"moviecursor", StateKey_MovieCursor, 0, false, false}, // show mouse cursor in movies, unused + {"qsoundenabled", StateKey_Qsound, 1, false, false}, // 1 = enable QSound - TODO: not supported yet + {"debugcheats", StateKey_DebugCheats, 1, false, false}, // always start with the GOxxxx cheat enabled // Editable settings {"keyboardturnspeed", StateKey_KbdRotateSpeed, 5, false, true}, {"panarotatespeed", StateKey_RotateSpeed, 540, false, true}, + {"noanimwhileturning", StateKey_NoTurnAnim, -1, false, true}, // toggle playing animations during pana rotation {"venusenabled", StateKey_VenusEnable, -1, true, true}, {"subtitles", StateKey_Subtitles, -1, true, true}, }; @@ -164,7 +165,7 @@ void ZVision::loadSettings() { if (settingsKeys[i].defaultValue >= 0) { value = (settingsKeys[i].allowEditing) ? ConfMan.getInt(settingsKeys[i].name) : settingsKeys[i].defaultValue; } else { - boolValue = value = (settingsKeys[i].allowEditing) ? ConfMan.getBool(settingsKeys[i].name) : settingsKeys[i].defaultBoolValue; + boolValue = (settingsKeys[i].allowEditing) ? ConfMan.getBool(settingsKeys[i].name) : settingsKeys[i].defaultBoolValue; value = (boolValue) ? 1 : 0; } -- cgit v1.2.3 From b3712cc877482e150a3532fa0f21f5c03dc839f1 Mon Sep 17 00:00:00 2001 From: Ori Avtalion Date: Sat, 27 Dec 2014 16:36:41 +0200 Subject: ZVISION: Remove dead code (uint is always > 0) --- engines/zvision/video/rlf_decoder.cpp | 5 ----- 1 file changed, 5 deletions(-) (limited to 'engines') diff --git a/engines/zvision/video/rlf_decoder.cpp b/engines/zvision/video/rlf_decoder.cpp index 260f912ade..1478822d00 100644 --- a/engines/zvision/video/rlf_decoder.cpp +++ b/engines/zvision/video/rlf_decoder.cpp @@ -164,11 +164,6 @@ bool RLFDecoder::RLFVideoTrack::seek(const Audio::Timestamp &time) { if ((uint)_curFrame == frame) return true; - if (frame < 0) { - _curFrame = 0; - return false; - } - int closestFrame = _curFrame; int distance = (int)frame - _curFrame; -- cgit v1.2.3 From 6fe9bdf6c6f63320e351c348970c2864af708c42 Mon Sep 17 00:00:00 2001 From: Strangerke Date: Sat, 27 Dec 2014 16:05:23 +0100 Subject: ACCESS: Fix speech --- engines/access/access.cpp | 6 ++++-- engines/access/sound.cpp | 4 ++++ engines/access/sound.h | 1 + 3 files changed, 9 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/access/access.cpp b/engines/access/access.cpp index 67255ff5ea..080a8ef975 100644 --- a/engines/access/access.cpp +++ b/engines/access/access.cpp @@ -227,7 +227,8 @@ void AccessEngine::speakText(ASurface *s, const Common::String &msg) { _sound->playSound(0); _scripts->cmdFreeSound(); - _events->pollEvents(); + while(_sound->isSFXPlaying() && !shouldQuit()) + _events->pollEvents(); if (_events->isKeyMousePressed()) { _sndSubFile += soundsLeft; @@ -258,7 +259,8 @@ void AccessEngine::speakText(ASurface *s, const Common::String &msg) { _sound->playSound(0); _scripts->cmdFreeSound(); - _events->pollEvents(); + while(_sound->isSFXPlaying() && !shouldQuit()) + _events->pollEvents(); if (_events->_leftButton) { _events->debounceLeft(); diff --git a/engines/access/sound.cpp b/engines/access/sound.cpp index 82199a8286..cfc8b7a64c 100644 --- a/engines/access/sound.cpp +++ b/engines/access/sound.cpp @@ -162,6 +162,10 @@ void SoundManager::checkSoundQueue() { DisposeAfterUse::YES); } +bool SoundManager::isSFXPlaying() { + return _mixer->isSoundHandleActive(_effectsHandle); +} + void SoundManager::loadSounds(Common::Array &sounds) { debugC(1, kDebugSound, "loadSounds"); diff --git a/engines/access/sound.h b/engines/access/sound.h index c276648477..3646c2cc16 100644 --- a/engines/access/sound.h +++ b/engines/access/sound.h @@ -66,6 +66,7 @@ public: void playSound(int soundIndex); void checkSoundQueue(); + bool isSFXPlaying(); Resource *loadSound(int fileNum, int subfile); void loadSounds(Common::Array &sounds); -- cgit v1.2.3 From 3c3ff0a3aab13b876e0425c365402ff334743282 Mon Sep 17 00:00:00 2001 From: Strangerke Date: Sat, 27 Dec 2014 16:46:33 +0100 Subject: ACCESS: Remove two useless variables --- engines/access/scripts.cpp | 2 +- engines/access/sound.cpp | 2 -- engines/access/sound.h | 2 -- 3 files changed, 1 insertion(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/access/scripts.cpp b/engines/access/scripts.cpp index 074c781352..1bd24894d7 100644 --- a/engines/access/scripts.cpp +++ b/engines/access/scripts.cpp @@ -794,7 +794,7 @@ void Scripts::cmdFreeSound() { charLoop(); _vm->_events->pollEvents(); - } while (!_vm->shouldQuit() && sound._playingSound); + } while (!_vm->shouldQuit() && sound.isSFXPlaying()); // Free the sounds while (sound._soundTable.size() > 0) { diff --git a/engines/access/sound.cpp b/engines/access/sound.cpp index cfc8b7a64c..fc574dc083 100644 --- a/engines/access/sound.cpp +++ b/engines/access/sound.cpp @@ -30,8 +30,6 @@ namespace Access { SoundManager::SoundManager(AccessEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer) { - _playingSound = false; - _isVoice = false; } SoundManager::~SoundManager() { diff --git a/engines/access/sound.h b/engines/access/sound.h index 3646c2cc16..384e9ac615 100644 --- a/engines/access/sound.h +++ b/engines/access/sound.h @@ -56,8 +56,6 @@ private: void playSound(Resource *res, int priority); public: Common::Array _soundTable; - bool _playingSound; - bool _isVoice; public: SoundManager(AccessEngine *vm, Audio::Mixer *mixer); ~SoundManager(); -- cgit v1.2.3 From 6a7834a05ed880cba32f0adb87950179c4ec404c Mon Sep 17 00:00:00 2001 From: Strangerke Date: Sat, 27 Dec 2014 16:55:07 +0100 Subject: ACCESS: Rename loadSoundTable --- engines/access/amazon/amazon_logic.cpp | 4 ++-- engines/access/amazon/amazon_scripts.cpp | 2 +- engines/access/sound.cpp | 4 ++-- engines/access/sound.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/access/amazon/amazon_logic.cpp b/engines/access/amazon/amazon_logic.cpp index c045377f8a..82f0edfa6e 100644 --- a/engines/access/amazon/amazon_logic.cpp +++ b/engines/access/amazon/amazon_logic.cpp @@ -317,8 +317,8 @@ void Opening::doTitle() { _vm->_events->hideCursor(); if (!_vm->isDemo()) { - _vm->_sound->queueSound(0, 98, 30); - _vm->_sound->queueSound(1, 98, 8); + _vm->_sound->loadSoundTable(0, 98, 30); + _vm->_sound->loadSoundTable(1, 98, 8); _vm->_files->_setPaletteFlag = false; _vm->_files->loadScreen(0, 3); diff --git a/engines/access/amazon/amazon_scripts.cpp b/engines/access/amazon/amazon_scripts.cpp index 0b2ddbc854..92acb3686d 100644 --- a/engines/access/amazon/amazon_scripts.cpp +++ b/engines/access/amazon/amazon_scripts.cpp @@ -95,7 +95,7 @@ void AmazonScripts::mWhile1() { _vm->_oldRects.clear(); _sequence = 2200; - _vm->_sound->queueSound(0, 14, 15); + _vm->_sound->loadSoundTable(0, 14, 15); do { cLoop(); diff --git a/engines/access/sound.cpp b/engines/access/sound.cpp index fc574dc083..53b611b65b 100644 --- a/engines/access/sound.cpp +++ b/engines/access/sound.cpp @@ -56,8 +56,8 @@ void SoundManager::clearSounds() { } } -void SoundManager::queueSound(int idx, int fileNum, int subfile) { - debugC(1, kDebugSound, "queueSound(%d, %d, %d)", idx, fileNum, subfile); +void SoundManager::loadSoundTable(int idx, int fileNum, int subfile) { + debugC(1, kDebugSound, "loadSoundTable(%d, %d, %d)", idx, fileNum, subfile); Resource *soundResource; diff --git a/engines/access/sound.h b/engines/access/sound.h index 384e9ac615..7109438f43 100644 --- a/engines/access/sound.h +++ b/engines/access/sound.h @@ -60,7 +60,7 @@ public: SoundManager(AccessEngine *vm, Audio::Mixer *mixer); ~SoundManager(); - void queueSound(int idx, int fileNum, int subfile); + void loadSoundTable(int idx, int fileNum, int subfile); void playSound(int soundIndex); void checkSoundQueue(); -- cgit v1.2.3 From 576bab349c862b16fcca1e9e0fb3fbb52cc6edc4 Mon Sep 17 00:00:00 2001 From: Strangerke Date: Sat, 27 Dec 2014 17:21:04 +0100 Subject: ACCESS: Use loadSoundTable instead of push_back in several places --- engines/access/access.cpp | 9 +++++---- engines/access/amazon/amazon_game.cpp | 4 ++-- engines/access/amazon/amazon_logic.cpp | 12 ++++++------ engines/access/sound.cpp | 4 ++-- engines/access/sound.h | 2 +- 5 files changed, 16 insertions(+), 15 deletions(-) (limited to 'engines') diff --git a/engines/access/access.cpp b/engines/access/access.cpp index 080a8ef975..7f59ae7ad6 100644 --- a/engines/access/access.cpp +++ b/engines/access/access.cpp @@ -222,14 +222,14 @@ void AccessEngine::speakText(ASurface *s, const Common::String &msg) { _events->clearEvents(); while (!shouldQuit()) { _sound->freeSounds(); - Resource *sound = _sound->loadSound(_narateFile + 99, _sndSubFile); - _sound->_soundTable.push_back(SoundEntry(sound, 1)); + _sound->loadSoundTable(0, _narateFile + 99, _sndSubFile); _sound->playSound(0); - _scripts->cmdFreeSound(); while(_sound->isSFXPlaying() && !shouldQuit()) _events->pollEvents(); + _scripts->cmdFreeSound(); + if (_events->isKeyMousePressed()) { _sndSubFile += soundsLeft; break; @@ -257,11 +257,12 @@ void AccessEngine::speakText(ASurface *s, const Common::String &msg) { Resource *res = _sound->loadSound(_narateFile + 99, _sndSubFile); _sound->_soundTable.push_back(SoundEntry(res, 1)); _sound->playSound(0); - _scripts->cmdFreeSound(); while(_sound->isSFXPlaying() && !shouldQuit()) _events->pollEvents(); + _scripts->cmdFreeSound(); + if (_events->_leftButton) { _events->debounceLeft(); _sndSubFile += soundsLeft; diff --git a/engines/access/amazon/amazon_game.cpp b/engines/access/amazon/amazon_game.cpp index d6b759b308..4c9df7b8ff 100644 --- a/engines/access/amazon/amazon_game.cpp +++ b/engines/access/amazon/amazon_game.cpp @@ -528,8 +528,8 @@ void AmazonEngine::startChapter(int chapter) { _sound->freeSounds(); if (isCD()) { - _sound->_soundTable.push_back(SoundEntry(_sound->loadSound(115, 0), 1)); - _sound->_soundTable.push_back(SoundEntry(_sound->loadSound(115, 1), 1)); + _sound->loadSoundTable(0, 115, 0); + _sound->loadSoundTable(1, 115, 1); _sound->playSound(0); _sound->playSound(1); diff --git a/engines/access/amazon/amazon_logic.cpp b/engines/access/amazon/amazon_logic.cpp index 82f0edfa6e..6dffb85e5e 100644 --- a/engines/access/amazon/amazon_logic.cpp +++ b/engines/access/amazon/amazon_logic.cpp @@ -490,12 +490,12 @@ void Opening::doTent() { _vm->_screen->setDisplayScan(); _vm->_screen->forceFadeOut(); _vm->_events->hideCursor(); - _vm->_sound->_soundTable.push_back(SoundEntry(_vm->_sound->loadSound(98, 39), 1)); - _vm->_sound->_soundTable.push_back(SoundEntry(_vm->_sound->loadSound(98, 14), 1)); - _vm->_sound->_soundTable.push_back(SoundEntry(_vm->_sound->loadSound(98, 15), 1)); - _vm->_sound->_soundTable.push_back(SoundEntry(_vm->_sound->loadSound(98, 16), 1)); - _vm->_sound->_soundTable.push_back(SoundEntry(_vm->_sound->loadSound(98, 31), 2)); - _vm->_sound->_soundTable.push_back(SoundEntry(_vm->_sound->loadSound(98, 52), 2)); + _vm->_sound->loadSoundTable(0, 98, 39); + _vm->_sound->loadSoundTable(1, 98, 14); + _vm->_sound->loadSoundTable(2, 98, 15); + _vm->_sound->loadSoundTable(3, 98, 16); + _vm->_sound->loadSoundTable(4, 98, 31, 2); + _vm->_sound->loadSoundTable(5, 98, 52, 2); _vm->_sound->playSound(0); _vm->_files->_setPaletteFlag = false; diff --git a/engines/access/sound.cpp b/engines/access/sound.cpp index 53b611b65b..221b409aa9 100644 --- a/engines/access/sound.cpp +++ b/engines/access/sound.cpp @@ -56,7 +56,7 @@ void SoundManager::clearSounds() { } } -void SoundManager::loadSoundTable(int idx, int fileNum, int subfile) { +void SoundManager::loadSoundTable(int idx, int fileNum, int subfile, int priority) { debugC(1, kDebugSound, "loadSoundTable(%d, %d, %d)", idx, fileNum, subfile); Resource *soundResource; @@ -67,7 +67,7 @@ void SoundManager::loadSoundTable(int idx, int fileNum, int subfile) { delete _soundTable[idx]._res; soundResource = _vm->_files->loadFile(fileNum, subfile); _soundTable[idx]._res = soundResource; - _soundTable[idx]._priority = 1; + _soundTable[idx]._priority = priority; } Resource *SoundManager::loadSound(int fileNum, int subfile) { diff --git a/engines/access/sound.h b/engines/access/sound.h index 7109438f43..90f6656e26 100644 --- a/engines/access/sound.h +++ b/engines/access/sound.h @@ -60,7 +60,7 @@ public: SoundManager(AccessEngine *vm, Audio::Mixer *mixer); ~SoundManager(); - void loadSoundTable(int idx, int fileNum, int subfile); + void loadSoundTable(int idx, int fileNum, int subfile, int priority = 1); void playSound(int soundIndex); void checkSoundQueue(); -- cgit v1.2.3 From 99fabffde0c8f88d02bba341cd9d504483b86409 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 27 Dec 2014 20:51:39 +0200 Subject: ZVISION: Clean up settings and initialize the ones used by game scripts --- engines/zvision/zvision.cpp | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) (limited to 'engines') diff --git a/engines/zvision/zvision.cpp b/engines/zvision/zvision.cpp index a28ad862d9..0d06f3ce90 100644 --- a/engines/zvision/zvision.cpp +++ b/engines/zvision/zvision.cpp @@ -52,7 +52,7 @@ namespace ZVision { -#define ZVISION_SETTINGS_KEYS_COUNT 17 +#define ZVISION_SETTINGS_KEYS_COUNT 11 struct zvisionIniSettings { const char *name; @@ -62,25 +62,18 @@ struct zvisionIniSettings { bool allowEditing; } settingsKeys[ZVISION_SETTINGS_KEYS_COUNT] = { // Hardcoded settings - //{"platform", StateKey_Platform, 0, false, false}, // 0 = Windows, 1 = DOS, 2 = DOS, unused - //{"installlevel", StateKey_InstallLevel, 0, false, false}, // 0 = full, unused - //{"countrycode", StateKey_CountryCode, 0, false, false}, // always 0 = US, unused - //{"cpu", StateKey_CPU, 1, false, false}, // always 1 = Pentium (0 is 486), unused - //{"win958", StateKey_WIN958, 0, false, false}, // unused, probably Windows version flag - //{"showerrordialogs", StateKey_ShowErrorDlg, 0, false, false}, // unused - //{"japanesefonts", StateKey_JapanFonts, 0, false, false}, - //{"brightness", StateKey_Brightness, 0, false, false}, - //{"lineskipvideo", StateKey_VideoLineSkip, 0, false, false}, // video line skip, 0 = default, 1 = always, 2 = pixel double when possible, unused - //{"highquality", StateKey_HighQuality, 0, false, false}, // performance related, always high - //{"moviecursor", StateKey_MovieCursor, 0, false, false}, // show mouse cursor in movies, unused - {"qsoundenabled", StateKey_Qsound, 1, false, false}, // 1 = enable QSound - TODO: not supported yet - {"debugcheats", StateKey_DebugCheats, 1, false, false}, // always start with the GOxxxx cheat enabled + {"countrycode", StateKey_CountryCode, 0, false, false}, // always 0 = US, subtitles are shown for codes 0 - 4, unused + {"lineskipvideo", StateKey_VideoLineSkip, 0, false, false}, // video line skip, 0 = default, 1 = always, 2 = pixel double when possible, unused + {"installlevel", StateKey_InstallLevel, 0, false, false}, // 0 = full, checked by universe.scr + {"highquality", StateKey_HighQuality, -1, true, false}, // high panorama quality, unused + {"qsoundenabled", StateKey_Qsound, -1, true, false}, // 1 = enable QSound - TODO: not supported yet + {"debugcheats", StateKey_DebugCheats, -1, true, false}, // always start with the GOxxxx cheat enabled // Editable settings {"keyboardturnspeed", StateKey_KbdRotateSpeed, 5, false, true}, - {"panarotatespeed", StateKey_RotateSpeed, 540, false, true}, + {"panarotatespeed", StateKey_RotateSpeed, 540, false, true}, // checked by universe.scr {"noanimwhileturning", StateKey_NoTurnAnim, -1, false, true}, // toggle playing animations during pana rotation {"venusenabled", StateKey_VenusEnable, -1, true, true}, - {"subtitles", StateKey_Subtitles, -1, true, true}, + {"subtitles", StateKey_Subtitles, -1, true, true} }; ZVision::ZVision(OSystem *syst, const ZVisionGameDescription *gameDesc) -- cgit v1.2.3 From 58f328b9af50d66bf8d1be1b19e6059f706ef226 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Sat, 27 Dec 2014 22:22:28 +0100 Subject: ZVISION: Slightly clarify font error message --- engines/zvision/zvision.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/zvision/zvision.cpp b/engines/zvision/zvision.cpp index 0d06f3ce90..88cc1e2fea 100644 --- a/engines/zvision/zvision.cpp +++ b/engines/zvision/zvision.cpp @@ -258,12 +258,12 @@ Common::Error ZVision::run() { if (!Common::File::exists("arial.ttf") && !Common::File::exists("FreeSans.ttf")) { GUI::MessageDialog dialog( "Before playing this game, you'll need to copy the required " - "fonts in ScummVM's extras directory, or the game directory. " + "fonts into ScummVM's extras directory, or into the game directory. " "On Windows, you'll need the following font files from the Windows " "font directory: Times New Roman, Century Schoolbook, Garamond, " "Courier New and Arial. Alternatively, you can download the GNU " "FreeFont package. You'll need all the fonts from that package, " - "i.e. FreeMono, FreeSans and FreeSerif." + "i.e., FreeMono, FreeSans and FreeSerif." ); dialog.runModal(); quitGame(); -- cgit v1.2.3 From 02eada1d0ddd5f5c179ca39840bb7f73286df6e1 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Sat, 27 Dec 2014 23:12:54 +0100 Subject: ZVISION: Fix Zork AVI audio on BE systems --- engines/zvision/video/zork_avi_decoder.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/zvision/video/zork_avi_decoder.cpp b/engines/zvision/video/zork_avi_decoder.cpp index 67fab0a114..5618250d79 100644 --- a/engines/zvision/video/zork_avi_decoder.cpp +++ b/engines/zvision/video/zork_avi_decoder.cpp @@ -45,8 +45,14 @@ void ZorkAVIDecoder::ZorkAVIAudioTrack::queueSound(Common::SeekableReadStream *s RawChunkStream::RawChunk chunk = decoder->readNextChunk(stream); delete stream; - if (chunk.data) - _audStream->queueBuffer((byte *)chunk.data, chunk.size, DisposeAfterUse::YES, Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN | Audio::FLAG_STEREO); + if (chunk.data) { + byte flags = Audio::FLAG_16BITS | Audio::FLAG_STEREO; +#ifdef SCUMM_LITTLE_ENDIAN + // RawChunkStream produces native endianness int16 + flags |= Audio::FLAG_LITTLE_ENDIAN; +#endif + _audStream->queueBuffer((byte *)chunk.data, chunk.size, DisposeAfterUse::YES, flags); + } } else { AVIAudioTrack::queueSound(stream); } -- cgit v1.2.3 From 5791f600e9b9808714b40a63acd09b5657c855f5 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Sat, 27 Dec 2014 23:35:35 +0100 Subject: ZVISION: Fix TGZ images on BE systems --- engines/zvision/graphics/render_manager.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/zvision/graphics/render_manager.cpp b/engines/zvision/graphics/render_manager.cpp index 4f26123fc8..a178c97639 100644 --- a/engines/zvision/graphics/render_manager.cpp +++ b/engines/zvision/graphics/render_manager.cpp @@ -209,13 +209,17 @@ void RenderManager::readImageToSurface(const Common::String &fileName, Graphics: isTGZ = true; // TGZ files have a header and then Bitmap data that is compressed with LZSS - uint32 decompressedSize = file.readSint32LE(); + uint32 decompressedSize = file.readSint32LE() / 2; imageWidth = file.readSint32LE(); imageHeight = file.readSint32LE(); LzssReadStream lzssStream(&file); buffer = (uint16 *)(new uint16[decompressedSize]); - lzssStream.read(buffer, decompressedSize); + lzssStream.read(buffer, 2 * decompressedSize); +#ifndef SCUMMVM_LITTLE_ENDIAN + for (uint32 i = 0; i < decompressedSize; ++i) + buffer[i] = FROM_LE_16(buffer[i]); +#endif } else { isTGZ = false; -- cgit v1.2.3 From cd595cb0ea65b5bd8b79cb7af35457d032d82e98 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Sat, 27 Dec 2014 23:35:47 +0100 Subject: ZVISION: Fix cursors on BE systems --- engines/zvision/graphics/cursors/cursor.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'engines') diff --git a/engines/zvision/graphics/cursors/cursor.cpp b/engines/zvision/graphics/cursors/cursor.cpp index eb25e92860..1b471d88b8 100644 --- a/engines/zvision/graphics/cursors/cursor.cpp +++ b/engines/zvision/graphics/cursors/cursor.cpp @@ -60,6 +60,12 @@ ZorkCursor::ZorkCursor(ZVision *engine, const Common::String &fileName) _surface.create(_width, _height, engine->_resourcePixelFormat); uint32 bytesRead = file.read(_surface.getPixels(), dataSize); assert(bytesRead == dataSize); + +#ifndef SCUMMVM_LITTLE_ENDIAN + int16 *buffer = (int16 *)_surface.getPixels(); + for (uint32 i = 0; i < dataSize / 2; ++i) + buffer[i] = FROM_LE_16(buffer[i]); +#endif } ZorkCursor::ZorkCursor(const ZorkCursor &other) { -- cgit v1.2.3 From 4931aee954704a7ee984ce8cee85bdbec3ddb640 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Sat, 27 Dec 2014 23:51:59 +0100 Subject: ZVISION: Fix typo --- engines/zvision/graphics/cursors/cursor.cpp | 2 +- engines/zvision/graphics/render_manager.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/zvision/graphics/cursors/cursor.cpp b/engines/zvision/graphics/cursors/cursor.cpp index 1b471d88b8..f32c68645d 100644 --- a/engines/zvision/graphics/cursors/cursor.cpp +++ b/engines/zvision/graphics/cursors/cursor.cpp @@ -61,7 +61,7 @@ ZorkCursor::ZorkCursor(ZVision *engine, const Common::String &fileName) uint32 bytesRead = file.read(_surface.getPixels(), dataSize); assert(bytesRead == dataSize); -#ifndef SCUMMVM_LITTLE_ENDIAN +#ifndef SCUMM_LITTLE_ENDIAN int16 *buffer = (int16 *)_surface.getPixels(); for (uint32 i = 0; i < dataSize / 2; ++i) buffer[i] = FROM_LE_16(buffer[i]); diff --git a/engines/zvision/graphics/render_manager.cpp b/engines/zvision/graphics/render_manager.cpp index a178c97639..033d099042 100644 --- a/engines/zvision/graphics/render_manager.cpp +++ b/engines/zvision/graphics/render_manager.cpp @@ -216,7 +216,7 @@ void RenderManager::readImageToSurface(const Common::String &fileName, Graphics: LzssReadStream lzssStream(&file); buffer = (uint16 *)(new uint16[decompressedSize]); lzssStream.read(buffer, 2 * decompressedSize); -#ifndef SCUMMVM_LITTLE_ENDIAN +#ifndef SCUMM_LITTLE_ENDIAN for (uint32 i = 0; i < decompressedSize; ++i) buffer[i] = FROM_LE_16(buffer[i]); #endif -- cgit v1.2.3 From c823a6e825a6474c75f1ddecfcb67a602393fae6 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Sat, 27 Dec 2014 23:52:18 +0100 Subject: ZVISION: Fix cmdRawToWav on BE systems --- engines/zvision/core/console.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'engines') diff --git a/engines/zvision/core/console.cpp b/engines/zvision/core/console.cpp index c7592c8d9d..b5e542d777 100644 --- a/engines/zvision/core/console.cpp +++ b/engines/zvision/core/console.cpp @@ -138,6 +138,10 @@ bool Console::cmdRawToWav(int argc, const char **argv) { output.writeUint32LE(file.size() * 2); int16 *buffer = new int16[file.size()]; audioStream->readBuffer(buffer, file.size()); +#ifndef SCUMM_LITTLE_ENDIAN + for (int i = 0; i < file.size(); ++i) + buffer[i] = TO_LE_16(buffer[i]); +#endif output.write(buffer, file.size() * 2); delete[] buffer; -- cgit v1.2.3 From 329c9386c6db79b3c52fbd6712f3ae1718d04c1f Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 28 Dec 2014 00:22:30 +0100 Subject: SCI: improve kPortrait debug support + fix --- engines/sci/graphics/portrait.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/portrait.cpp b/engines/sci/graphics/portrait.cpp index 959c0f6817..3311f47022 100644 --- a/engines/sci/graphics/portrait.cpp +++ b/engines/sci/graphics/portrait.cpp @@ -230,7 +230,7 @@ void Portrait::doit(Common::Point position, uint16 resourceId, uint16 noun, uint debugPrint[raveResource->size] = 0; // set terminating NUL debug("kPortrait: using actor %s", _resourceName.c_str()); debug("kPortrait (noun %d, verb %d, cond %d, seq %d)", noun, verb, cond, seq); - debug("kPortrait: %s", debugPrint); + debug("kPortrait: rave data is '%s'", debugPrint); } #endif @@ -301,7 +301,11 @@ void Portrait::doit(Common::Point position, uint16 resourceId, uint16 noun, uint } #ifdef DEBUG_PORTRAIT - debug("kPortrait: %d: %x", raveTicks, raveID); + if (raveID & 0x0ff) { + debug("kPortrait: rave '%c%c' after %d ticks", raveID >> 8, raveID & 0x0ff, raveTicks); + } else if (raveID) { + debug("kPortrait: rave '%c' after %d ticks", raveID >> 8, raveTicks); + } #endif timerPosition += raveTicks; @@ -325,10 +329,9 @@ void Portrait::doit(Common::Point position, uint16 resourceId, uint16 noun, uint // Tick = 0xFF is the terminator for the data timerPositionWithin = timerPosition; raveLipSyncTicks = *raveLipSyncData++; -#ifdef DEBUG_PORTRAIT - debug("kPortrait: waiting %d", raveLipSyncTicks); -#endif while ( (raveLipSyncData < _lipSyncDataOffsetTableEnd) && (raveLipSyncTicks != 0xFF) ) { + if (raveLipSyncTicks) + raveLipSyncTicks--; // 1 -> wait 0 ticks, 2 -> wait 1 tick, etc. timerPositionWithin += raveLipSyncTicks; do { @@ -343,7 +346,11 @@ void Portrait::doit(Common::Point position, uint16 resourceId, uint16 noun, uint raveLipSyncBitmapNr = *raveLipSyncData++; #ifdef DEBUG_PORTRAIT - debug("kPortrait: showing bitmap %d", raveLipSyncBitmapNr); + if (!raveLipSyncTicks) { + debug("kPortrait: showing frame %d", raveLipSyncBitmapNr); + } else { + debug("kPortrait: showing frame %d after %d ticks", raveLipSyncBitmapNr, raveLipSyncTicks); + } #endif // bitmap nr within sync data is base 1, we need base 0 -- cgit v1.2.3 From d0ac19062526e5617d08b587e64aee00fd395876 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Sun, 28 Dec 2014 04:43:22 -0500 Subject: ZVISION: Use VideoDecoder facilities better in AnimationNode setEndFrame() will ensure the audio stops when it is supposed to. Also removes the hack of retrieving the frame rate through the getDuration()'s timestamp return value. Thanks to md5 for testing --- .../zvision/scripting/sidefx/animation_node.cpp | 99 ++++++++++++---------- engines/zvision/scripting/sidefx/animation_node.h | 2 +- 2 files changed, 54 insertions(+), 47 deletions(-) (limited to 'engines') diff --git a/engines/zvision/scripting/sidefx/animation_node.cpp b/engines/zvision/scripting/sidefx/animation_node.cpp index 3dd80f3699..1657a6e0ec 100644 --- a/engines/zvision/scripting/sidefx/animation_node.cpp +++ b/engines/zvision/scripting/sidefx/animation_node.cpp @@ -40,19 +40,18 @@ AnimationNode::AnimationNode(ZVision *engine, uint32 controlKey, const Common::S _animation(NULL) { _animation = engine->loadAnimation(fileName); + _animation->start(); - if (fileName.hasSuffix(".rlf")) - _frmDelay = _animation->getTimeToNextFrame(); - else - _frmDelay = Common::Rational(1000, _animation->getDuration().framerate()).toInt(); + if (frate > 0) { + _frmDelayOverride = (int32)(1000.0 / frate); - if (frate > 0) - _frmDelay = 1000.0 / frate; - - // WORKAROUND: We do not allow the engine to delay more than 66 msec - // per frame (15fps max) - if (_frmDelay > 66) - _frmDelay = 66; + // WORKAROUND: We do not allow the engine to delay more than 66 msec + // per frame (15fps max) + if (_frmDelayOverride > 66) + _frmDelayOverride = 66; + } else { + _frmDelayOverride = 0; + } } AnimationNode::~AnimationNode() { @@ -90,44 +89,52 @@ bool AnimationNode::process(uint32 deltaTimeInMillis) { if (it != _playList.end()) { playnode *nod = &(*it); - nod->_delay -= deltaTimeInMillis; - if (nod->_delay <= 0) { - nod->_delay += _frmDelay; - - const Graphics::Surface *frame = NULL; - - if (nod->_curFrame == -1) { // Start of new playlist node - nod->_curFrame = nod->start; - - _animation->seekToFrame(nod->_curFrame); - frame = _animation->decodeNextFrame(); - - nod->_delay = _frmDelay; - if (nod->slot) - scriptManager->setStateValue(nod->slot, 1); - } else { - nod->_curFrame++; - - if (nod->_curFrame > nod->stop) { - nod->loop--; - - if (nod->loop == 0) { - if (nod->slot >= 0) - scriptManager->setStateValue(nod->slot, 2); - if (nod->_scaled) { - nod->_scaled->free(); - delete nod->_scaled; - } - _playList.erase(it); - return _DisposeAfterUse; - } - - nod->_curFrame = nod->start; - _animation->seekToFrame(nod->_curFrame); + if (nod->_curFrame == -1) { + // The node is just beginning playback + nod->_curFrame = nod->start; + + _animation->seekToFrame(nod->start); + _animation->setEndFrame(nod->stop); + + nod->_delay = deltaTimeInMillis; // Force the frame to draw + if (nod->slot) + scriptManager->setStateValue(nod->slot, 1); + } else if (_animation->endOfVideo()) { + // The node has reached the end; check if we need to loop + nod->loop--; + + if (nod->loop == 0) { + if (nod->slot >= 0) + scriptManager->setStateValue(nod->slot, 2); + if (nod->_scaled) { + nod->_scaled->free(); + delete nod->_scaled; } + _playList.erase(it); + return _DisposeAfterUse; + } - frame = _animation->decodeNextFrame(); + nod->_curFrame = nod->start; + _animation->seekToFrame(nod->start); + } + + // Check if we need to draw a frame + bool needsUpdate = false; + if (_frmDelayOverride == 0) { + // If not overridden, use the VideoDecoder's check + needsUpdate = _animation->needsUpdate(); + } else { + // Otherwise, implement our own timing + nod->_delay -= deltaTimeInMillis; + + if (nod->_delay <= 0) { + nod->_delay += _frmDelayOverride; + needsUpdate = true; } + } + + if (needsUpdate) { + const Graphics::Surface *frame = _animation->decodeNextFrame(); if (frame) { uint32 dstw; diff --git a/engines/zvision/scripting/sidefx/animation_node.h b/engines/zvision/scripting/sidefx/animation_node.h index 368f0291fd..64270ebc79 100644 --- a/engines/zvision/scripting/sidefx/animation_node.h +++ b/engines/zvision/scripting/sidefx/animation_node.h @@ -64,7 +64,7 @@ private: bool _DisposeAfterUse; Video::VideoDecoder *_animation; - int32 _frmDelay; + int32 _frmDelayOverride; public: bool process(uint32 deltaTimeInMillis); -- cgit v1.2.3 From 46cd10c5255a7c99620a335094d5af3ccf5a2092 Mon Sep 17 00:00:00 2001 From: Strangerke Date: Sun, 28 Dec 2014 11:35:53 +0100 Subject: ACCESS: Fix DisposeAfterUse flags in sound code (thanks to fuzzie) --- engines/access/sound.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/access/sound.cpp b/engines/access/sound.cpp index 221b409aa9..da267bdc4c 100644 --- a/engines/access/sound.cpp +++ b/engines/access/sound.cpp @@ -134,7 +134,7 @@ void SoundManager::playSound(Resource *res, int priority) { return; } - Audio::RewindableAudioStream *audioStream = Audio::makeRawStream(resourceData + 32, sampleSize, sampleRate, 0); + Audio::RewindableAudioStream *audioStream = Audio::makeRawStream(resourceData + 32, sampleSize, sampleRate, 0, DisposeAfterUse::NO); _queue.push_back(audioStream); } else @@ -143,7 +143,7 @@ void SoundManager::playSound(Resource *res, int priority) { if (!_mixer->isSoundHandleActive(_effectsHandle)) _mixer->playStream(Audio::Mixer::kSFXSoundType, &_effectsHandle, _queue[0], -1, _mixer->kMaxChannelVolume, 0, - DisposeAfterUse::NO); + DisposeAfterUse::YES); } void SoundManager::checkSoundQueue() { -- cgit v1.2.3 From 78b2c87d510f1ad83e8915e15b7e345a2512d99a Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 28 Dec 2014 15:27:55 +0200 Subject: ZVISION: Document some more controls --- engines/zvision/scripting/control.cpp | 1 + engines/zvision/scripting/controls/fist_control.h | 2 +- engines/zvision/scripting/controls/hotmov_control.h | 2 +- engines/zvision/scripting/controls/lever_control.h | 1 + engines/zvision/scripting/controls/paint_control.h | 2 +- engines/zvision/scripting/controls/safe_control.h | 1 + engines/zvision/scripting/controls/titler_control.h | 2 +- engines/zvision/scripting/scr_file_handling.cpp | 15 +++++++++------ 8 files changed, 16 insertions(+), 10 deletions(-) (limited to 'engines') diff --git a/engines/zvision/scripting/control.cpp b/engines/zvision/scripting/control.cpp index 127f35ef12..81123eb99b 100644 --- a/engines/zvision/scripting/control.cpp +++ b/engines/zvision/scripting/control.cpp @@ -72,6 +72,7 @@ void Control::parsePanoramaControl(ZVision *engine, Common::SeekableReadStream & renderTable->generateRenderTable(); } +// Only used in Zork Nemesis, handles tilt controls (ZGI doesn't have a tilt view) void Control::parseTiltControl(ZVision *engine, Common::SeekableReadStream &stream) { RenderTable *renderTable = engine->getRenderManager()->getRenderTable(); renderTable->setRenderState(RenderTable::TILT); diff --git a/engines/zvision/scripting/controls/fist_control.h b/engines/zvision/scripting/controls/fist_control.h index bad2daa6d5..a41d8511ea 100644 --- a/engines/zvision/scripting/controls/fist_control.h +++ b/engines/zvision/scripting/controls/fist_control.h @@ -34,7 +34,7 @@ namespace Video { namespace ZVision { -// Only used in Zork Nemesis, it handles the door lock puzzle with the skeletal fingers (td60, td90, td9e) +// Only used in Zork Nemesis, handles the door lock puzzle with the skeletal fingers (td60, td90, td9e) class FistControl : public Control { public: FistControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream); diff --git a/engines/zvision/scripting/controls/hotmov_control.h b/engines/zvision/scripting/controls/hotmov_control.h index 640fab00c0..01c83b5837 100644 --- a/engines/zvision/scripting/controls/hotmov_control.h +++ b/engines/zvision/scripting/controls/hotmov_control.h @@ -34,7 +34,7 @@ namespace Video { namespace ZVision { -// Only used in Zork Nemesis, it handles movies where the player needs to click on something (mj7g, vw3g) +// Only used in Zork Nemesis, handles movies where the player needs to click on something (mj7g, vw3g) class HotMovControl : public Control { public: HotMovControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream); diff --git a/engines/zvision/scripting/controls/lever_control.h b/engines/zvision/scripting/controls/lever_control.h index fdf4a649dc..8787234c51 100644 --- a/engines/zvision/scripting/controls/lever_control.h +++ b/engines/zvision/scripting/controls/lever_control.h @@ -34,6 +34,7 @@ namespace Video { namespace ZVision { +// Only used in Zork Nemesis, handles draggable levers (te2e, tm7e, tp2e, tt2e, tz2e) class LeverControl : public Control { public: LeverControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream); diff --git a/engines/zvision/scripting/controls/paint_control.h b/engines/zvision/scripting/controls/paint_control.h index 0e5b59b821..8c01f0e68a 100644 --- a/engines/zvision/scripting/controls/paint_control.h +++ b/engines/zvision/scripting/controls/paint_control.h @@ -32,7 +32,7 @@ namespace ZVision { -// Only used in Zork Nemesis, it's the painting puzzle screen in Lucien's room in Irondune (ch4g) +// Only used in Zork Nemesis, handles the painting puzzle screen in Lucien's room in Irondune (ch4g) class PaintControl : public Control { public: PaintControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream); diff --git a/engines/zvision/scripting/controls/safe_control.h b/engines/zvision/scripting/controls/safe_control.h index 6e1095e304..2577ff4f79 100644 --- a/engines/zvision/scripting/controls/safe_control.h +++ b/engines/zvision/scripting/controls/safe_control.h @@ -34,6 +34,7 @@ namespace Video { namespace ZVision { +// Only used in Zork Nemesis, handles the safe in the Asylum (ac4g) class SafeControl : public Control { public: SafeControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream); diff --git a/engines/zvision/scripting/controls/titler_control.h b/engines/zvision/scripting/controls/titler_control.h index 86bb398b3c..dd96e4a846 100644 --- a/engines/zvision/scripting/controls/titler_control.h +++ b/engines/zvision/scripting/controls/titler_control.h @@ -32,7 +32,7 @@ namespace ZVision { -// Only used in Zork Nemesis - it's the death screen with the Restore/Exit buttons +// Only used in Zork Nemesis, handles the death screen with the Restore/Exit buttons class TitlerControl : public Control { public: TitlerControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream); diff --git a/engines/zvision/scripting/scr_file_handling.cpp b/engines/zvision/scripting/scr_file_handling.cpp index fd5c158fcc..4e8c8a6b33 100644 --- a/engines/zvision/scripting/scr_file_handling.cpp +++ b/engines/zvision/scripting/scr_file_handling.cpp @@ -349,29 +349,32 @@ Control *ScriptManager::parseControl(Common::String &line, Common::SeekableReadS Control::parsePanoramaControl(_engine, stream); return NULL; } else if (controlType.equalsIgnoreCase("tilt")) { + // Only used in Zork Nemesis, handles tilt controls (ZGI doesn't have a tilt view) Control::parseTiltControl(_engine, stream); return NULL; - } else if (controlType.equalsIgnoreCase("lever")) { - return new LeverControl(_engine, key, stream); } else if (controlType.equalsIgnoreCase("slot")) { return new SlotControl(_engine, key, stream); } else if (controlType.equalsIgnoreCase("input")) { return new InputControl(_engine, key, stream); } else if (controlType.equalsIgnoreCase("save")) { return new SaveControl(_engine, key, stream); + } else if (controlType.equalsIgnoreCase("lever")) { + // Only used in Zork Nemesis, handles draggable levers (te2e, tm7e, tp2e, tt2e, tz2e) + return new LeverControl(_engine, key, stream); } else if (controlType.equalsIgnoreCase("safe")) { + // Only used in Zork Nemesis, handles the safe in the Asylum (ac4g) return new SafeControl(_engine, key, stream); } else if (controlType.equalsIgnoreCase("hotmovie")) { - // Only used in Zork Nemesis, it handles movies where the player needs to click on something (mj7g, vw3g) + // Only used in Zork Nemesis, handles movies where the player needs to click on something (mj7g, vw3g) return new HotMovControl(_engine, key, stream); } else if (controlType.equalsIgnoreCase("fist")) { - // Only used in Zork Nemesis, it handles the door lock puzzle with the skeletal fingers (td60, td90, td9e) + // Only used in Zork Nemesis, handles the door lock puzzle with the skeletal fingers (td60, td90, td9e) return new FistControl(_engine, key, stream); } else if (controlType.equalsIgnoreCase("paint")) { - // Only used in Zork Nemesis, it's the painting puzzle screen in Lucien's room in Irondune (ch4g) + // Only used in Zork Nemesis, handles the painting puzzle screen in Lucien's room in Irondune (ch4g) return new PaintControl(_engine, key, stream); } else if (controlType.equalsIgnoreCase("titler")) { - // Only used in Zork Nemesis - it's the death screen with the Restore/Exit buttons (cjde) + // Only used in Zork Nemesis, handles the death screen with the Restore/Exit buttons (cjde) return new TitlerControl(_engine, key, stream); } return NULL; -- cgit v1.2.3 From 587b1ad69c200ee5b5c987328a65bd8092d9ea4f Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 28 Dec 2014 18:42:18 +0200 Subject: ZVISION: The fist control is only used in one location --- engines/zvision/scripting/controls/fist_control.h | 2 +- engines/zvision/scripting/scr_file_handling.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/zvision/scripting/controls/fist_control.h b/engines/zvision/scripting/controls/fist_control.h index a41d8511ea..74e8f8d8a5 100644 --- a/engines/zvision/scripting/controls/fist_control.h +++ b/engines/zvision/scripting/controls/fist_control.h @@ -34,7 +34,7 @@ namespace Video { namespace ZVision { -// Only used in Zork Nemesis, handles the door lock puzzle with the skeletal fingers (td60, td90, td9e) +// Only used in Zork Nemesis, handles the door lock puzzle with the skeletal fingers (td9e) class FistControl : public Control { public: FistControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream); diff --git a/engines/zvision/scripting/scr_file_handling.cpp b/engines/zvision/scripting/scr_file_handling.cpp index 4e8c8a6b33..227c43557c 100644 --- a/engines/zvision/scripting/scr_file_handling.cpp +++ b/engines/zvision/scripting/scr_file_handling.cpp @@ -368,7 +368,7 @@ Control *ScriptManager::parseControl(Common::String &line, Common::SeekableReadS // Only used in Zork Nemesis, handles movies where the player needs to click on something (mj7g, vw3g) return new HotMovControl(_engine, key, stream); } else if (controlType.equalsIgnoreCase("fist")) { - // Only used in Zork Nemesis, handles the door lock puzzle with the skeletal fingers (td60, td90, td9e) + // Only used in Zork Nemesis, handles the door lock puzzle with the skeletal fingers (td9e) return new FistControl(_engine, key, stream); } else if (controlType.equalsIgnoreCase("paint")) { // Only used in Zork Nemesis, handles the painting puzzle screen in Lucien's room in Irondune (ch4g) -- cgit v1.2.3 From f1d6ba7085be53cb641f71ef726dadf3f075b311 Mon Sep 17 00:00:00 2001 From: Strangerke Date: Sun, 28 Dec 2014 23:35:14 +0100 Subject: ACCESS: Remove useless variable --- engines/access/player.cpp | 1 - engines/access/player.h | 1 - 2 files changed, 2 deletions(-) (limited to 'engines') diff --git a/engines/access/player.cpp b/engines/access/player.cpp index bcd553c6dc..e47daf532c 100644 --- a/engines/access/player.cpp +++ b/engines/access/player.cpp @@ -48,7 +48,6 @@ Player::Player(AccessEngine *vm) : Manager(vm), ImageEntry() { _playerSprites1 = nullptr; _manPal1 = nullptr; _frameNumber = 0; - _monData = nullptr; _rawTempL = 0; _rawXTemp = 0; _rawYTempL = 0; diff --git a/engines/access/player.h b/engines/access/player.h index 26caec681f..329cc15ed2 100644 --- a/engines/access/player.h +++ b/engines/access/player.h @@ -84,7 +84,6 @@ public: Direction _playerDirection; SpriteResource *_playerSprites; // Fields in original Player structure - byte *_monData; int _walkOffRight[PLAYER_DATA_COUNT]; int _walkOffLeft[PLAYER_DATA_COUNT]; int _walkOffUp[PLAYER_DATA_COUNT]; -- cgit v1.2.3 From 6d55998b40f62518959f849922919b6b0562981e Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Sun, 28 Dec 2014 21:19:27 -0500 Subject: ZVISION: Make the rest of the controls properly use VideoDecoder timing The hacky use of getDuration() to retrieve the framerate() is gone Thanks to md5 for testing (and for filling in a few gaps since I was coding in the blind ;)) --- .../zvision/scripting/controls/fist_control.cpp | 53 +++++++--------------- engines/zvision/scripting/controls/fist_control.h | 5 -- .../zvision/scripting/controls/hotmov_control.cpp | 53 +++++++++------------- .../zvision/scripting/controls/hotmov_control.h | 4 -- .../zvision/scripting/controls/input_control.cpp | 19 ++------ .../zvision/scripting/controls/safe_control.cpp | 53 ++++++---------------- engines/zvision/scripting/controls/safe_control.h | 7 --- 7 files changed, 58 insertions(+), 136 deletions(-) (limited to 'engines') diff --git a/engines/zvision/scripting/controls/fist_control.cpp b/engines/zvision/scripting/controls/fist_control.cpp index 34a64b4298..4a8e8b1bbd 100644 --- a/engines/zvision/scripting/controls/fist_control.cpp +++ b/engines/zvision/scripting/controls/fist_control.cpp @@ -46,10 +46,6 @@ FistControl::FistControl(ZVision *engine, uint32 key, Common::SeekableReadStream _order = 0; _fistnum = 0; - _frameCur = -1; - _frameEnd = -1; - _frameTime = 0; - _lastRenderedFrame = -1; _animationId = 0; clearFistArray(_fistsUp); @@ -95,41 +91,23 @@ FistControl::~FistControl() { _entries.clear(); } -void FistControl::renderFrame(uint frameNumber) { - if ((int32)frameNumber == _lastRenderedFrame) - return; - - _lastRenderedFrame = frameNumber; - - const Graphics::Surface *frameData; - - if (_animation) { - _animation->seekToFrame(frameNumber); - frameData = _animation->decodeNextFrame(); - if (frameData) - _engine->getRenderManager()->blitSurfaceToBkgScaled(*frameData, _anmRect); - } -} - bool FistControl::process(uint32 deltaTimeInMillis) { if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED) return false; - if (_frameCur >= 0 && _frameEnd >= 0) - if (_frameCur <= _frameEnd) { - _frameTime -= deltaTimeInMillis; - - if (_frameTime <= 0) { - _frameTime = 1000.0 / _animation->getDuration().framerate(); - - renderFrame(_frameCur); - - _frameCur++; + if (_animation && _animation->isPlaying()) { + if (_animation->endOfVideo()) { + _animation->stop(); + _engine->getScriptManager()->setStateValue(_animationId, 2); + return false; + } - if (_frameCur > _frameEnd) - _engine->getScriptManager()->setStateValue(_animationId, 2); - } + if (_animation->needsUpdate()) { + const Graphics::Surface *frameData = _animation->decodeNextFrame(); + if (frameData) + _engine->getRenderManager()->blitSurfaceToBkgScaled(*frameData, _anmRect); } + } return false; } @@ -160,9 +138,12 @@ bool FistControl::onMouseUp(const Common::Point &screenSpacePos, const Common::P for (int i = 0; i < _numEntries; i++) if (_entries[i]._bitsStrt == oldStatus && _entries[i]._bitsEnd == _fiststatus) { - _frameCur = _entries[i]._anmStrt; - _frameEnd = _entries[i]._anmEnd; - _frameTime = 0; + if (_animation) { + _animation->stop(); + _animation->seekToFrame(_entries[i]._anmStrt); + _animation->setEndFrame(_entries[i]._anmEnd); + _animation->start(); + } _engine->getScriptManager()->setStateValue(_animationId, 1); _engine->getScriptManager()->setStateValue(_soundKey, _entries[i]._sound); diff --git a/engines/zvision/scripting/controls/fist_control.h b/engines/zvision/scripting/controls/fist_control.h index 74e8f8d8a5..d7cbcb1f71 100644 --- a/engines/zvision/scripting/controls/fist_control.h +++ b/engines/zvision/scripting/controls/fist_control.h @@ -64,10 +64,6 @@ private: Video::VideoDecoder *_animation; Common::Rect _anmRect; int32 _soundKey; - int32 _frameCur; - int32 _frameEnd; - int32 _frameTime; - int32 _lastRenderedFrame; int32 _animationId; public: @@ -76,7 +72,6 @@ public: bool process(uint32 deltaTimeInMillis); private: - void renderFrame(uint frameNumber); void readDescFile(const Common::String &fileName); void clearFistArray(Common::Array< Common::Array > &arr); uint32 readBits(const char *str); diff --git a/engines/zvision/scripting/controls/hotmov_control.cpp b/engines/zvision/scripting/controls/hotmov_control.cpp index e77272ec73..182447a990 100644 --- a/engines/zvision/scripting/controls/hotmov_control.cpp +++ b/engines/zvision/scripting/controls/hotmov_control.cpp @@ -41,10 +41,7 @@ HotMovControl::HotMovControl(ZVision *engine, uint32 key, Common::SeekableReadSt : Control(engine, key, CONTROL_HOTMOV) { _animation = NULL; _cycle = 0; - _curFrame = -1; - _lastRenderedFrame = -1; _frames.clear(); - _frameTime = 0; _cyclesCount = 0; _framesCount = 0; @@ -78,6 +75,7 @@ HotMovControl::HotMovControl(ZVision *engine, uint32 key, Common::SeekableReadSt sscanf(values.c_str(), "%s", filename); values = Common::String(filename); _animation = _engine->loadAnimation(values); + _animation->start(); } else if (param.matchString("venus_id", true)) { _venusId = atoi(values.c_str()); } @@ -95,41 +93,26 @@ HotMovControl::~HotMovControl() { _frames.clear(); } -void HotMovControl::renderFrame(uint frameNumber) { - if ((int)frameNumber == _lastRenderedFrame) - return; - - _lastRenderedFrame = frameNumber; - - const Graphics::Surface *frameData; - - if (_animation) { - _animation->seekToFrame(frameNumber); - frameData = _animation->decodeNextFrame(); - if (frameData) - _engine->getRenderManager()->blitSurfaceToBkgScaled(*frameData, _rectangle); - } -} - bool HotMovControl::process(uint32 deltaTimeInMillis) { if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED) return false; if (_cycle < _cyclesCount) { - _frameTime -= deltaTimeInMillis; + if (_animation && _animation->endOfVideo()) { + _cycle++; - if (_frameTime <= 0) { - _curFrame++; - if (_curFrame >= _framesCount) { - _curFrame = 0; - _cycle++; - } - if (_cycle != _cyclesCount) - renderFrame(_curFrame); - else + if (_cycle == _cyclesCount) { _engine->getScriptManager()->setStateValue(_key, 2); + return false; + } + + _animation->rewind(); + } - _frameTime = 1000.0 / _animation->getDuration().framerate(); + if (_animation && _animation->needsUpdate()) { + const Graphics::Surface *frameData = _animation->decodeNextFrame(); + if (frameData) + _engine->getRenderManager()->blitSurfaceToBkgScaled(*frameData, _rectangle); } } @@ -140,8 +123,11 @@ bool HotMovControl::onMouseMove(const Common::Point &screenSpacePos, const Commo if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED) return false; + if (!_animation) + return false; + if (_cycle < _cyclesCount) { - if (_frames[_curFrame].contains(backgroundImageSpacePos)) { + if (_frames[_animation->getCurFrame()].contains(backgroundImageSpacePos)) { _engine->getCursorManager()->changeCursor(CursorIndex_Active); return true; } @@ -154,8 +140,11 @@ bool HotMovControl::onMouseUp(const Common::Point &screenSpacePos, const Common: if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED) return false; + if (!_animation) + return false; + if (_cycle < _cyclesCount) { - if (_frames[_curFrame].contains(backgroundImageSpacePos)) { + if (_frames[_animation->getCurFrame()].contains(backgroundImageSpacePos)) { setVenus(); _engine->getScriptManager()->setStateValue(_key, 1); return true; diff --git a/engines/zvision/scripting/controls/hotmov_control.h b/engines/zvision/scripting/controls/hotmov_control.h index 01c83b5837..99d1fd0979 100644 --- a/engines/zvision/scripting/controls/hotmov_control.h +++ b/engines/zvision/scripting/controls/hotmov_control.h @@ -42,9 +42,6 @@ public: private: int32 _framesCount; - int32 _frameTime; - int32 _curFrame; - int32 _lastRenderedFrame; int32 _cycle; int32 _cyclesCount; Video::VideoDecoder *_animation; @@ -56,7 +53,6 @@ public: bool process(uint32 deltaTimeInMillis); private: - void renderFrame(uint frameNumber); void readHsFile(const Common::String &fileName); }; diff --git a/engines/zvision/scripting/controls/input_control.cpp b/engines/zvision/scripting/controls/input_control.cpp index 4abc0c9e1b..47da27fa08 100644 --- a/engines/zvision/scripting/controls/input_control.cpp +++ b/engines/zvision/scripting/controls/input_control.cpp @@ -46,9 +46,7 @@ InputControl::InputControl(ZVision *engine, uint32 key, Common::SeekableReadStre _enterPressed(false), _readOnly(false), _txtWidth(0), - _animation(NULL), - _frameDelay(0), - _frame(-1) { + _animation(NULL) { // Loop until we find the closing brace Common::String line = stream.readLine(); _engine->getScriptManager()->trimCommentsAndWhiteSpace(&line); @@ -99,8 +97,7 @@ InputControl::InputControl(ZVision *engine, uint32 key, Common::SeekableReadStre sscanf(values.c_str(), "%24s %*u", fileName); _animation = _engine->loadAnimation(fileName); - _frame = -1; - _frameDelay = 0; + _animation->start(); } else if (param.matchString("focus", true)) { _focused = true; _engine->getScriptManager()->setFocusControlKey(_key); @@ -212,16 +209,10 @@ bool InputControl::process(uint32 deltaTimeInMillis) { } if (_animation && !_readOnly && _focused) { - bool needDraw = true;// = _textChanged; - _frameDelay -= deltaTimeInMillis; - if (_frameDelay <= 0) { - _frame = (_frame + 1) % _animation->getFrameCount(); - _frameDelay = 1000.0 / _animation->getDuration().framerate(); - needDraw = true; - } + if (_animation->endOfVideo()) + _animation->rewind(); - if (needDraw) { - _animation->seekToFrame(_frame); + if (_animation->needsUpdate()) { const Graphics::Surface *srf = _animation->decodeNextFrame(); int16 xx = _textRectangle.left + _txtWidth; if (xx >= _textRectangle.left + (_textRectangle.width() - (int16)_animation->getWidth())) diff --git a/engines/zvision/scripting/controls/safe_control.cpp b/engines/zvision/scripting/controls/safe_control.cpp index 71be692431..6ba34106d0 100644 --- a/engines/zvision/scripting/controls/safe_control.cpp +++ b/engines/zvision/scripting/controls/safe_control.cpp @@ -49,10 +49,7 @@ SafeControl::SafeControl(ZVision *engine, uint32 key, Common::SeekableReadStream _outerRadiusSqr = 0; _zeroPointer = 0; _startPointer = 0; - _curFrame = -1; _targetFrame = 0; - _frameTime = 0; - _lastRenderedFrame = -1; // Loop until we find the closing brace Common::String line = stream.readLine(); @@ -64,6 +61,7 @@ SafeControl::SafeControl(ZVision *engine, uint32 key, Common::SeekableReadStream while (!stream.eos() && !line.contains('}')) { if (param.matchString("animation", true)) { _animation = _engine->loadAnimation(values); + _animation->start(); } else if (param.matchString("rectangle", true)) { int x; int y; @@ -104,7 +102,9 @@ SafeControl::SafeControl(ZVision *engine, uint32 key, Common::SeekableReadStream _engine->getScriptManager()->trimCommentsAndWhiteSpace(&line); getParams(line, param, values); } - renderFrame(_curState); + + if (_animation) + _animation->seekToFrame(_curState); } SafeControl::~SafeControl() { @@ -113,44 +113,20 @@ SafeControl::~SafeControl() { } -void SafeControl::renderFrame(uint frameNumber) { - if (frameNumber == 0) { - _lastRenderedFrame = frameNumber; - } else if ((int16)frameNumber < _lastRenderedFrame) { - _lastRenderedFrame = frameNumber; - frameNumber = (_statesCount * 2) - frameNumber; - } else { - _lastRenderedFrame = frameNumber; - } - - const Graphics::Surface *frameData; - int x = _rectangle.left; - int y = _rectangle.top; - - _animation->seekToFrame(frameNumber); - frameData = _animation->decodeNextFrame(); - if (frameData) - _engine->getRenderManager()->blitSurfaceToBkg(*frameData, x, y); -} - bool SafeControl::process(uint32 deltaTimeInMillis) { if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED) return false; - if (_curFrame != _targetFrame) { - _frameTime -= deltaTimeInMillis; - - if (_frameTime <= 0) { - if (_curFrame < _targetFrame) { - _curFrame++; - renderFrame(_curFrame); - } else if (_curFrame > _targetFrame) { - _curFrame--; - renderFrame(_curFrame); - } - _frameTime = 1000.0 / _animation->getDuration().framerate(); - } + if (_animation && _animation->getCurFrame() != _targetFrame && _animation->needsUpdate()) { + // If we're past the target frame, move back one + if (_animation->getCurFrame() > _targetFrame) + _animation->seekToFrame(_animation->getCurFrame() - 1); + + const Graphics::Surface *frameData = _animation->decodeNextFrame(); + if (frameData) + _engine->getRenderManager()->blitSurfaceToBkg(*frameData, _rectangle.left, _rectangle.top); } + return false; } @@ -187,7 +163,8 @@ bool SafeControl::onMouseUp(const Common::Point &screenSpacePos, const Common::P int16 tmp2 = (m_state + _curState - _zeroPointer + _statesCount - 1) % _statesCount; - _curFrame = (_curState + _statesCount - _startPointer) % _statesCount; + if (_animation) + _animation->seekToFrame((_curState + _statesCount - _startPointer) % _statesCount); _curState = (_statesCount * 2 + tmp2) % _statesCount; diff --git a/engines/zvision/scripting/controls/safe_control.h b/engines/zvision/scripting/controls/safe_control.h index 2577ff4f79..3e8c17635c 100644 --- a/engines/zvision/scripting/controls/safe_control.h +++ b/engines/zvision/scripting/controls/safe_control.h @@ -52,19 +52,12 @@ private: int32 _outerRadiusSqr; int16 _zeroPointer; int16 _startPointer; - int16 _curFrame; int16 _targetFrame; - int32 _frameTime; - - int16 _lastRenderedFrame; public: bool onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos); bool onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos); bool process(uint32 deltaTimeInMillis); - -private: - void renderFrame(uint frameNumber); }; } // End of namespace ZVision -- cgit v1.2.3 From f4d5b150f1e4b786f2f6f79a1acd3315da9a8699 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 29 Dec 2014 12:34:55 +0200 Subject: ZVISION: Show system messages when subtitles are disabled Thanks to Marisa-Chan for spotting this --- engines/zvision/graphics/render_manager.cpp | 2 +- engines/zvision/scripting/sidefx/music_node.cpp | 2 +- engines/zvision/scripting/sidefx/syncsound_node.cpp | 2 +- engines/zvision/video/video.cpp | 4 +++- 4 files changed, 6 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/zvision/graphics/render_manager.cpp b/engines/zvision/graphics/render_manager.cpp index 033d099042..1b80b379bf 100644 --- a/engines/zvision/graphics/render_manager.cpp +++ b/engines/zvision/graphics/render_manager.cpp @@ -741,7 +741,7 @@ void RenderManager::processSubs(uint16 deltatime) { } } - if (redraw && _engine->getScriptManager()->getStateValue(StateKey_Subtitles) == 1) { + if (redraw) { _subtitleSurface.fillRect(Common::Rect(_subtitleSurface.w, _subtitleSurface.h), 0); for (SubtitleMap::iterator it = _subsList.begin(); it != _subsList.end(); it++) { diff --git a/engines/zvision/scripting/sidefx/music_node.cpp b/engines/zvision/scripting/sidefx/music_node.cpp index 6be08b46dc..0cada6d748 100644 --- a/engines/zvision/scripting/sidefx/music_node.cpp +++ b/engines/zvision/scripting/sidefx/music_node.cpp @@ -137,7 +137,7 @@ bool MusicNode::process(uint32 deltaTimeInMillis) { if (_pantrack || _volume != _newvol) setVolume(_newvol); - if (_sub) + if (_sub && _engine->getScriptManager()->getStateValue(StateKey_Subtitles) == 1) _sub->process(_engine->_mixer->getSoundElapsedTime(_handle) / 100); } return false; diff --git a/engines/zvision/scripting/sidefx/syncsound_node.cpp b/engines/zvision/scripting/sidefx/syncsound_node.cpp index c1f139694b..eec320bf2e 100644 --- a/engines/zvision/scripting/sidefx/syncsound_node.cpp +++ b/engines/zvision/scripting/sidefx/syncsound_node.cpp @@ -76,7 +76,7 @@ bool SyncSoundNode::process(uint32 deltaTimeInMillis) { if (_engine->getScriptManager()->getSideFX(_syncto) == NULL) return stop(); - if (_sub) + if (_sub && _engine->getScriptManager()->getStateValue(StateKey_Subtitles) == 1) _sub->process(_engine->_mixer->getSoundElapsedTime(_handle) / 100); } return false; diff --git a/engines/zvision/video/video.cpp b/engines/zvision/video/video.cpp index e67e6570c5..0913b28818 100644 --- a/engines/zvision/video/video.cpp +++ b/engines/zvision/video/video.cpp @@ -29,6 +29,7 @@ #include "zvision/zvision.h" #include "zvision/core/clock.h" #include "zvision/graphics/render_manager.h" +#include "zvision/scripting//script_manager.h" #include "zvision/text/subtitles.h" #include "zvision/video/rlf_decoder.h" #include "zvision/video/zork_avi_decoder.h" @@ -75,6 +76,7 @@ void ZVision::playVideo(Video::VideoDecoder &vid, const Common::Rect &destRect, uint16 y = _workingWindow.top + dst.top; uint16 finalWidth = dst.width() < _workingWindow.width() ? dst.width() : _workingWindow.width(); uint16 finalHeight = dst.height() < _workingWindow.height() ? dst.height() : _workingWindow.height(); + bool showSubs = (_scriptManager->getStateValue(StateKey_Subtitles) == 1); _clock.stop(); vid.start(); @@ -106,7 +108,7 @@ void ZVision::playVideo(Video::VideoDecoder &vid, const Common::Rect &destRect, if (vid.needsUpdate()) { const Graphics::Surface *frame = vid.decodeNextFrame(); - if (sub) + if (sub && showSubs) sub->process(vid.getCurFrame()); if (frame) { -- cgit v1.2.3 From 45280d035afe29dc1f8971eac713ea1fdb64bfb5 Mon Sep 17 00:00:00 2001 From: Marisa-Chan Date: Mon, 29 Dec 2014 15:30:12 +0600 Subject: ZVISION: Fix font error message condition --- engines/zvision/zvision.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/zvision/zvision.cpp b/engines/zvision/zvision.cpp index 88cc1e2fea..10e0aaedc4 100644 --- a/engines/zvision/zvision.cpp +++ b/engines/zvision/zvision.cpp @@ -255,7 +255,7 @@ Common::Error ZVision::run() { _saveManager->loadGame(ConfMan.getInt("save_slot")); // Before starting, make absolutely sure that the user has copied the needed fonts - if (!Common::File::exists("arial.ttf") && !Common::File::exists("FreeSans.ttf")) { + if (!Common::File::exists("arial.ttf") && !Common::File::exists("FreeSans.ttf") && !_searchManager->hasFile("arial.ttf") && !_searchManager->hasFile("FreeSans.ttf") ) { GUI::MessageDialog dialog( "Before playing this game, you'll need to copy the required " "fonts into ScummVM's extras directory, or into the game directory. " -- cgit v1.2.3 From 47b90ef3cde832b6314bbcc0321cb074408d944e Mon Sep 17 00:00:00 2001 From: Marisa-Chan Date: Wed, 24 Dec 2014 09:31:02 +0600 Subject: ZVISION: Search fonts in game directory (e.g. in game/FONTS/) --- engines/zvision/text/truetype_font.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/zvision/text/truetype_font.cpp b/engines/zvision/text/truetype_font.cpp index f64c0ab3bc..85d9fa5a29 100644 --- a/engines/zvision/text/truetype_font.cpp +++ b/engines/zvision/text/truetype_font.cpp @@ -108,7 +108,7 @@ bool StyledTTFont::loadFont(const Common::String &fontName, int32 point) { bool sharp = (_style & STTF_SHARP) == STTF_SHARP; Common::File file; - if (!file.open(newFontName) && !file.open(freeFontName)) + if (!file.open(newFontName) && !file.open(freeFontName) && !_engine->getSearchManager()->openFile(file, newFontName) && !_engine->getSearchManager()->openFile(file, freeFontName)) error("Unable to open font file %s (free alternative: %s)", newFontName.c_str(), freeFontName.c_str()); Graphics::Font *_newFont = Graphics::loadTTFFont(file, point, 60, (sharp ? Graphics::kTTFRenderModeMonochrome : Graphics::kTTFRenderModeNormal)); // 66 dpi for 640 x 480 on 14" display -- cgit v1.2.3 From 0c4e0673c3a7d17aef7c586251c3990104163bc3 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 30 Dec 2014 03:08:39 +0200 Subject: ZVISION: Further cleanup to the AnimationNode class --- engines/zvision/scripting/sidefx/animation_node.cpp | 20 ++++++-------------- engines/zvision/scripting/sidefx/animation_node.h | 6 ++---- 2 files changed, 8 insertions(+), 18 deletions(-) (limited to 'engines') diff --git a/engines/zvision/scripting/sidefx/animation_node.cpp b/engines/zvision/scripting/sidefx/animation_node.cpp index 1657a6e0ec..a0870bf7c2 100644 --- a/engines/zvision/scripting/sidefx/animation_node.cpp +++ b/engines/zvision/scripting/sidefx/animation_node.cpp @@ -33,14 +33,13 @@ namespace ZVision { -AnimationNode::AnimationNode(ZVision *engine, uint32 controlKey, const Common::String &fileName, int32 mask, int32 frate, bool DisposeAfterUse) +AnimationNode::AnimationNode(ZVision *engine, uint32 controlKey, const Common::String &fileName, int32 mask, int32 frate, bool disposeAfterUse) : SideFX(engine, controlKey, SIDEFX_ANIM), - _DisposeAfterUse(DisposeAfterUse), + _disposeAfterUse(disposeAfterUse), _mask(mask), _animation(NULL) { _animation = engine->loadAnimation(fileName); - _animation->start(); if (frate > 0) { _frmDelayOverride = (int32)(1000.0 / frate); @@ -89,12 +88,10 @@ bool AnimationNode::process(uint32 deltaTimeInMillis) { if (it != _playList.end()) { playnode *nod = &(*it); - if (nod->_curFrame == -1) { + if (!_animation->isPlaying()) { // The node is just beginning playback - nod->_curFrame = nod->start; - + _animation->start(); _animation->seekToFrame(nod->start); - _animation->setEndFrame(nod->stop); nod->_delay = deltaTimeInMillis; // Force the frame to draw if (nod->slot) @@ -111,10 +108,9 @@ bool AnimationNode::process(uint32 deltaTimeInMillis) { delete nod->_scaled; } _playList.erase(it); - return _DisposeAfterUse; + return _disposeAfterUse; } - nod->_curFrame = nod->start; _animation->seekToFrame(nod->start); } @@ -190,13 +186,9 @@ void AnimationNode::addPlayNode(int32 slot, int x, int y, int x2, int y2, int st nod.loop = loops; nod.pos = Common::Rect(x, y, x2 + 1, y2 + 1); nod.start = startFrame; - nod.stop = endFrame; - - if (nod.stop >= (int)_animation->getFrameCount()) - nod.stop = _animation->getFrameCount() - 1; + _animation->setEndFrame(CLIP(endFrame, 0,_animation->getFrameCount() - 1)); nod.slot = slot; - nod._curFrame = -1; nod._delay = 0; nod._scaled = NULL; _playList.push_back(nod); diff --git a/engines/zvision/scripting/sidefx/animation_node.h b/engines/zvision/scripting/sidefx/animation_node.h index 64270ebc79..1dc0dc71b8 100644 --- a/engines/zvision/scripting/sidefx/animation_node.h +++ b/engines/zvision/scripting/sidefx/animation_node.h @@ -41,16 +41,14 @@ class ZVision; class AnimationNode : public SideFX { public: - AnimationNode(ZVision *engine, uint32 controlKey, const Common::String &fileName, int32 mask, int32 frate, bool DisposeAfterUse = true); + AnimationNode(ZVision *engine, uint32 controlKey, const Common::String &fileName, int32 mask, int32 frate, bool disposeAfterUse = true); ~AnimationNode(); struct playnode { Common::Rect pos; int32 slot; int32 start; - int32 stop; int32 loop; - int32 _curFrame; int32 _delay; Graphics::Surface *_scaled; }; @@ -61,7 +59,7 @@ private: PlayNodes _playList; int32 _mask; - bool _DisposeAfterUse; + bool _disposeAfterUse; Video::VideoDecoder *_animation; int32 _frmDelayOverride; -- cgit v1.2.3 From 7182b4f704a312427dc701ccc8452331ca66faae Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 30 Dec 2014 03:51:15 +0200 Subject: ZVISION: Initialize the starting frame to -1 in RLF animations --- engines/zvision/video/rlf_decoder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/zvision/video/rlf_decoder.cpp b/engines/zvision/video/rlf_decoder.cpp index 1478822d00..6e2000f93c 100644 --- a/engines/zvision/video/rlf_decoder.cpp +++ b/engines/zvision/video/rlf_decoder.cpp @@ -56,7 +56,7 @@ RLFDecoder::RLFVideoTrack::RLFVideoTrack(Common::SeekableReadStream *stream) _height(0), _frameTime(0), _frames(0), - _curFrame(0), + _curFrame(-1), _frameBufferByteSize(0) { if (!readHeader()) { -- cgit v1.2.3 From 6c3af3c2e7b8d2852669c141944964c82a11ce1b Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 30 Dec 2014 03:51:31 +0200 Subject: ZVISION: White space --- engines/zvision/scripting/sidefx/animation_node.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/zvision/scripting/sidefx/animation_node.cpp b/engines/zvision/scripting/sidefx/animation_node.cpp index a0870bf7c2..07eda692c1 100644 --- a/engines/zvision/scripting/sidefx/animation_node.cpp +++ b/engines/zvision/scripting/sidefx/animation_node.cpp @@ -186,7 +186,7 @@ void AnimationNode::addPlayNode(int32 slot, int x, int y, int x2, int y2, int st nod.loop = loops; nod.pos = Common::Rect(x, y, x2 + 1, y2 + 1); nod.start = startFrame; - _animation->setEndFrame(CLIP(endFrame, 0,_animation->getFrameCount() - 1)); + _animation->setEndFrame(CLIP(endFrame, 0, _animation->getFrameCount() - 1)); nod.slot = slot; nod._delay = 0; -- cgit v1.2.3 From f74ba29753de23bad9a07f531fc4c03ea3375594 Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Tue, 30 Dec 2014 03:45:14 +0100 Subject: SCUMM: Enable Day of the Tentacle easter egg Instead of returning to the launcher, a game may now specify a list of "chained" games and optional save slots. The first game is popped from the list and started. Quitting still quits the entire ScummVM. It seemed like the sensible thing to do. --- engines/scumm/saveload.cpp | 2 +- engines/scumm/script_v6.cpp | 6 +++++- engines/scumm/scumm.cpp | 44 +++++++++++++++++++++++++++++++++++++++++--- engines/scumm/scumm.h | 2 +- 4 files changed, 48 insertions(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp index 0c0f6be73b..e5673c1803 100644 --- a/engines/scumm/saveload.cpp +++ b/engines/scumm/saveload.cpp @@ -149,7 +149,7 @@ void ScummEngine::requestSave(int slot, const Common::String &name) { void ScummEngine::requestLoad(int slot) { _saveLoadSlot = slot; - _saveTemporaryState = false; + _saveTemporaryState = (slot == 100); _saveLoadFlag = 2; // 2 for load } diff --git a/engines/scumm/script_v6.cpp b/engines/scumm/script_v6.cpp index d2f4133f74..6c81f17f2f 100644 --- a/engines/scumm/script_v6.cpp +++ b/engines/scumm/script_v6.cpp @@ -2597,7 +2597,11 @@ void ScummEngine_v6::o6_kernelSetFunctions() { fadeIn(args[1]); break; case 8: - startManiac(); + if (startManiac()) { + // This is so that the surprised exclamation happens + // after we return to the game again, not before. + o6_breakHere(); + } break; case 9: killAllScriptsExceptCurrent(); diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp index 6040344c2c..34ae957951 100644 --- a/engines/scumm/scumm.cpp +++ b/engines/scumm/scumm.cpp @@ -2597,9 +2597,47 @@ void ScummEngine_v90he::runBootscript() { } #endif -void ScummEngine::startManiac() { - debug(0, "stub startManiac()"); - displayMessage(0, "%s", _("Usually, Maniac Mansion would start now. But ScummVM doesn't do that yet. To play it, go to 'Add Game' in the ScummVM start menu and select the 'Maniac' directory inside the Tentacle game directory.")); +bool ScummEngine::startManiac() { + Common::String currentPath = ConfMan.get("path"); + Common::String maniacTarget; + + // Look for a game with a game path pointing to a 'Maniac' directory + // as a subdirectory to the current game. + Common::ConfigManager::DomainMap::iterator iter = ConfMan.beginGameDomains(); + for (; iter != ConfMan.endGameDomains(); ++iter) { + Common::ConfigManager::Domain &dom = iter->_value; + Common::String path = dom.getVal("path"); + + if (path.hasPrefix(currentPath)) { + path.erase(0, currentPath.size() + 1); + if (path.equalsIgnoreCase("maniac")) { + maniacTarget = dom.getVal("gameid"); + break; + } + } + } + + if (!maniacTarget.empty()) { + // Request a temporary save game to be made. + _saveLoadFlag = 1; + _saveLoadSlot = 100; + _saveTemporaryState = true; + + // Set up the chanined games to Maniac Mansion, and then back + // to the current game again with that save slot. + ConfMan.set("chained_games", maniacTarget + "," + ConfMan.getActiveDomainName() + ":100", Common::ConfigManager::kTransientDomain); + + // Force a return to the launcher. This will start the first + // chained game. + Common::EventManager *eventMan = g_system->getEventManager(); + Common::Event event; + event.type = Common::EVENT_RTL; + eventMan->pushEvent(event); + return true; + } else { + displayMessage(0, "%s", _("Usually, Maniac Mansion would start now. But for that to work, the game files for Maniac Mansion have to be in the 'Maniac' directory inside the Tentacle game directory, and the game has to be added to ScummVM.")); + return false; + } } #pragma mark - diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h index 967909e505..30b4d61880 100644 --- a/engines/scumm/scumm.h +++ b/engines/scumm/scumm.h @@ -654,7 +654,7 @@ protected: int getScriptSlot(); void startScene(int room, Actor *a, int b); - void startManiac(); + bool startManiac(); public: void runScript(int script, bool freezeResistant, bool recursive, int *lvarptr, int cycle = 0); -- cgit v1.2.3 From 68d3ebd57b0313e517032681a119b47956803e71 Mon Sep 17 00:00:00 2001 From: RichieSams Date: Tue, 30 Dec 2014 01:10:36 -0600 Subject: ZVISION: Rename some scripting classes to better represent what the classes are Also, rename the graphics 'Effect' class in order to avoid naming clashes (and/or coder confusion) with the newly named ScriptingEffect class. Lastly, add some documentation for the classes for further clarity. --- engines/zvision/graphics/effect.h | 83 ------- engines/zvision/graphics/effects/fog.cpp | 2 +- engines/zvision/graphics/effects/fog.h | 4 +- engines/zvision/graphics/effects/light.cpp | 2 +- engines/zvision/graphics/effects/light.h | 4 +- engines/zvision/graphics/effects/wave.cpp | 2 +- engines/zvision/graphics/effects/wave.h | 4 +- engines/zvision/graphics/graphics_effect.h | 83 +++++++ engines/zvision/graphics/render_manager.cpp | 2 +- engines/zvision/graphics/render_manager.h | 6 +- engines/zvision/module.mk | 14 +- engines/zvision/scripting/actions.cpp | 66 +++--- engines/zvision/scripting/control.h | 5 + .../zvision/scripting/effects/animation_effect.cpp | 213 ++++++++++++++++++ .../zvision/scripting/effects/animation_effect.h | 77 +++++++ .../zvision/scripting/effects/distort_effect.cpp | 104 +++++++++ engines/zvision/scripting/effects/distort_effect.h | 63 ++++++ engines/zvision/scripting/effects/music_effect.cpp | 248 +++++++++++++++++++++ engines/zvision/scripting/effects/music_effect.h | 135 +++++++++++ .../zvision/scripting/effects/region_effect.cpp | 56 +++++ engines/zvision/scripting/effects/region_effect.h | 57 +++++ .../zvision/scripting/effects/syncsound_effect.cpp | 85 +++++++ .../zvision/scripting/effects/syncsound_effect.h | 56 +++++ engines/zvision/scripting/effects/timer_effect.cpp | 81 +++++++ engines/zvision/scripting/effects/timer_effect.h | 59 +++++ .../zvision/scripting/effects/ttytext_effect.cpp | 174 +++++++++++++++ engines/zvision/scripting/effects/ttytext_effect.h | 73 ++++++ engines/zvision/scripting/script_manager.cpp | 8 +- engines/zvision/scripting/script_manager.h | 10 +- engines/zvision/scripting/scripting_effect.h | 124 +++++++++++ engines/zvision/scripting/sidefx.h | 114 ---------- .../zvision/scripting/sidefx/animation_node.cpp | 213 ------------------ engines/zvision/scripting/sidefx/animation_node.h | 77 ------- engines/zvision/scripting/sidefx/distort_node.cpp | 104 --------- engines/zvision/scripting/sidefx/distort_node.h | 63 ------ engines/zvision/scripting/sidefx/music_node.cpp | 248 --------------------- engines/zvision/scripting/sidefx/music_node.h | 135 ----------- engines/zvision/scripting/sidefx/region_node.cpp | 56 ----- engines/zvision/scripting/sidefx/region_node.h | 57 ----- .../zvision/scripting/sidefx/syncsound_node.cpp | 85 ------- engines/zvision/scripting/sidefx/syncsound_node.h | 56 ----- engines/zvision/scripting/sidefx/timer_node.cpp | 81 ------- engines/zvision/scripting/sidefx/timer_node.h | 59 ----- engines/zvision/scripting/sidefx/ttytext_node.cpp | 174 --------------- engines/zvision/scripting/sidefx/ttytext_node.h | 73 ------ 45 files changed, 1755 insertions(+), 1740 deletions(-) delete mode 100644 engines/zvision/graphics/effect.h create mode 100644 engines/zvision/graphics/graphics_effect.h create mode 100644 engines/zvision/scripting/effects/animation_effect.cpp create mode 100644 engines/zvision/scripting/effects/animation_effect.h create mode 100644 engines/zvision/scripting/effects/distort_effect.cpp create mode 100644 engines/zvision/scripting/effects/distort_effect.h create mode 100644 engines/zvision/scripting/effects/music_effect.cpp create mode 100644 engines/zvision/scripting/effects/music_effect.h create mode 100644 engines/zvision/scripting/effects/region_effect.cpp create mode 100644 engines/zvision/scripting/effects/region_effect.h create mode 100644 engines/zvision/scripting/effects/syncsound_effect.cpp create mode 100644 engines/zvision/scripting/effects/syncsound_effect.h create mode 100644 engines/zvision/scripting/effects/timer_effect.cpp create mode 100644 engines/zvision/scripting/effects/timer_effect.h create mode 100644 engines/zvision/scripting/effects/ttytext_effect.cpp create mode 100644 engines/zvision/scripting/effects/ttytext_effect.h create mode 100644 engines/zvision/scripting/scripting_effect.h delete mode 100644 engines/zvision/scripting/sidefx.h delete mode 100644 engines/zvision/scripting/sidefx/animation_node.cpp delete mode 100644 engines/zvision/scripting/sidefx/animation_node.h delete mode 100644 engines/zvision/scripting/sidefx/distort_node.cpp delete mode 100644 engines/zvision/scripting/sidefx/distort_node.h delete mode 100644 engines/zvision/scripting/sidefx/music_node.cpp delete mode 100644 engines/zvision/scripting/sidefx/music_node.h delete mode 100644 engines/zvision/scripting/sidefx/region_node.cpp delete mode 100644 engines/zvision/scripting/sidefx/region_node.h delete mode 100644 engines/zvision/scripting/sidefx/syncsound_node.cpp delete mode 100644 engines/zvision/scripting/sidefx/syncsound_node.h delete mode 100644 engines/zvision/scripting/sidefx/timer_node.cpp delete mode 100644 engines/zvision/scripting/sidefx/timer_node.h delete mode 100644 engines/zvision/scripting/sidefx/ttytext_node.cpp delete mode 100644 engines/zvision/scripting/sidefx/ttytext_node.h (limited to 'engines') diff --git a/engines/zvision/graphics/effect.h b/engines/zvision/graphics/effect.h deleted file mode 100644 index 234cd8209d..0000000000 --- a/engines/zvision/graphics/effect.h +++ /dev/null @@ -1,83 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#ifndef EFFECT_H_INCLUDED -#define EFFECT_H_INCLUDED - -#include "common/rect.h" -#include "common/list.h" -#include "graphics/surface.h" - -#include "zvision/zvision.h" - -namespace ZVision { - -class ZVision; - -class Effect { -public: - - Effect(ZVision *engine, uint32 key, Common::Rect region, bool ported) : _engine(engine), _key(key), _region(region), _ported(ported) { - _surface.create(_region.width(), _region.height(), _engine->_resourcePixelFormat); - } - virtual ~Effect() {} - - uint32 getKey() { - return _key; - } - - Common::Rect getRegion() { - return _region; - } - - bool isPort() { - return _ported; - } - - virtual const Graphics::Surface *draw(const Graphics::Surface &srcSubRect) { - return &_surface; - } - - virtual void update() {} - -protected: - ZVision *_engine; - uint32 _key; - Common::Rect _region; - bool _ported; - Graphics::Surface _surface; - -// Static member functions -public: - -}; - -struct EffectMapUnit { - uint32 count; - bool inEffect; -}; - -typedef Common::List EffectMap; - -} // End of namespace ZVision - -#endif // EFFECT_H_INCLUDED diff --git a/engines/zvision/graphics/effects/fog.cpp b/engines/zvision/graphics/effects/fog.cpp index c28bdde330..32a01915d3 100644 --- a/engines/zvision/graphics/effects/fog.cpp +++ b/engines/zvision/graphics/effects/fog.cpp @@ -31,7 +31,7 @@ namespace ZVision { FogFx::FogFx(ZVision *engine, uint32 key, Common::Rect region, bool ported, EffectMap *Map, const Common::String &clouds): - Effect(engine, key, region, ported) { + GraphicsEffect(engine, key, region, ported) { _map = Map; diff --git a/engines/zvision/graphics/effects/fog.h b/engines/zvision/graphics/effects/fog.h index fe88707bbe..498347609e 100644 --- a/engines/zvision/graphics/effects/fog.h +++ b/engines/zvision/graphics/effects/fog.h @@ -23,14 +23,14 @@ #ifndef ZVISION_FOG_H #define ZVISION_FOG_H -#include "zvision/graphics/effect.h" +#include "zvision/graphics/graphics_effect.h" namespace ZVision { class ZVision; // Used by Zork: Nemesis for the mixing chamber gas effect in the gas puzzle (location tt5e, when the blinds are down) -class FogFx : public Effect { +class FogFx : public GraphicsEffect { public: FogFx(ZVision *engine, uint32 key, Common::Rect region, bool ported, EffectMap *Map, const Common::String &clouds); diff --git a/engines/zvision/graphics/effects/light.cpp b/engines/zvision/graphics/effects/light.cpp index bf6513292f..39341687f8 100644 --- a/engines/zvision/graphics/effects/light.cpp +++ b/engines/zvision/graphics/effects/light.cpp @@ -30,7 +30,7 @@ namespace ZVision { LightFx::LightFx(ZVision *engine, uint32 key, Common::Rect region, bool ported, EffectMap *Map, int8 delta, int8 minD, int8 maxD): - Effect(engine, key, region, ported) { + GraphicsEffect(engine, key, region, ported) { _map = Map; _delta = delta; _up = true; diff --git a/engines/zvision/graphics/effects/light.h b/engines/zvision/graphics/effects/light.h index ae87d66cb3..cd73a585ec 100644 --- a/engines/zvision/graphics/effects/light.h +++ b/engines/zvision/graphics/effects/light.h @@ -23,13 +23,13 @@ #ifndef LIGHTFX_H_INCLUDED #define LIGHTFX_H_INCLUDED -#include "zvision/graphics/effect.h" +#include "zvision/graphics/graphics_effect.h" namespace ZVision { class ZVision; -class LightFx : public Effect { +class LightFx : public GraphicsEffect { public: LightFx(ZVision *engine, uint32 key, Common::Rect region, bool ported, EffectMap *Map, int8 delta, int8 minD = -127, int8 maxD = 127); diff --git a/engines/zvision/graphics/effects/wave.cpp b/engines/zvision/graphics/effects/wave.cpp index 1b3aa040e8..cec631611b 100644 --- a/engines/zvision/graphics/effects/wave.cpp +++ b/engines/zvision/graphics/effects/wave.cpp @@ -30,7 +30,7 @@ namespace ZVision { WaveFx::WaveFx(ZVision *engine, uint32 key, Common::Rect region, bool ported, int16 frames, int16 centerX, int16 centerY, float ampl, float waveln, float spd): - Effect(engine, key, region, ported) { + GraphicsEffect(engine, key, region, ported) { _frame = 0; _frameCount = frames; diff --git a/engines/zvision/graphics/effects/wave.h b/engines/zvision/graphics/effects/wave.h index 2e813ed5b6..8e912372d7 100644 --- a/engines/zvision/graphics/effects/wave.h +++ b/engines/zvision/graphics/effects/wave.h @@ -24,13 +24,13 @@ #define WAVEFX_H_INCLUDED #include "common/array.h" -#include "zvision/graphics/effect.h" +#include "zvision/graphics/graphics_effect.h" namespace ZVision { class ZVision; -class WaveFx : public Effect { +class WaveFx : public GraphicsEffect { public: WaveFx(ZVision *engine, uint32 key, Common::Rect region, bool ported, int16 frames, int16 centerX, int16 centerY, float ampl, float waveln, float spd); diff --git a/engines/zvision/graphics/graphics_effect.h b/engines/zvision/graphics/graphics_effect.h new file mode 100644 index 0000000000..bfa266b11d --- /dev/null +++ b/engines/zvision/graphics/graphics_effect.h @@ -0,0 +1,83 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef GRAPHICS_EFFECT_H_INCLUDED +#define GRAPHICS_EFFECT_H_INCLUDED + +#include "common/rect.h" +#include "common/list.h" +#include "graphics/surface.h" + +#include "zvision/zvision.h" + +namespace ZVision { + +class ZVision; + +class GraphicsEffect { +public: + + GraphicsEffect(ZVision *engine, uint32 key, Common::Rect region, bool ported) : _engine(engine), _key(key), _region(region), _ported(ported) { + _surface.create(_region.width(), _region.height(), _engine->_resourcePixelFormat); + } + virtual ~GraphicsEffect() {} + + uint32 getKey() { + return _key; + } + + Common::Rect getRegion() { + return _region; + } + + bool isPort() { + return _ported; + } + + virtual const Graphics::Surface *draw(const Graphics::Surface &srcSubRect) { + return &_surface; + } + + virtual void update() {} + +protected: + ZVision *_engine; + uint32 _key; + Common::Rect _region; + bool _ported; + Graphics::Surface _surface; + +// Static member functions +public: + +}; + +struct EffectMapUnit { + uint32 count; + bool inEffect; +}; + +typedef Common::List EffectMap; + +} // End of namespace ZVision + +#endif // GRAPHICS_EFFECT_H_INCLUDED diff --git a/engines/zvision/graphics/render_manager.cpp b/engines/zvision/graphics/render_manager.cpp index 1b80b379bf..a1cc8ac53c 100644 --- a/engines/zvision/graphics/render_manager.cpp +++ b/engines/zvision/graphics/render_manager.cpp @@ -772,7 +772,7 @@ Common::Point RenderManager::getBkgSize() { return Common::Point(_backgroundWidth, _backgroundHeight); } -void RenderManager::addEffect(Effect *_effect) { +void RenderManager::addEffect(GraphicsEffect *_effect) { _effects.push_back(_effect); } diff --git a/engines/zvision/graphics/render_manager.h b/engines/zvision/graphics/render_manager.h index d9a6c88896..9002d66b47 100644 --- a/engines/zvision/graphics/render_manager.h +++ b/engines/zvision/graphics/render_manager.h @@ -31,7 +31,7 @@ #include "graphics/surface.h" -#include "effect.h" +#include "graphics_effect.h" class OSystem; @@ -61,7 +61,7 @@ private: }; typedef Common::HashMap SubtitleMap; - typedef Common::List EffectsList; + typedef Common::List EffectsList; private: ZVision *_engine; @@ -302,7 +302,7 @@ public: void readImageToSurface(const Common::String &fileName, Graphics::Surface &destination, bool transposed); // Add visual effect to effects list - void addEffect(Effect *_effect); + void addEffect(GraphicsEffect *_effect); // Delete effect(s) by ID (ID equal to slot of action:region that create this effect) void deleteEffect(uint32 ID); diff --git a/engines/zvision/module.mk b/engines/zvision/module.mk index 8edd67b352..93fba2879d 100644 --- a/engines/zvision/module.mk +++ b/engines/zvision/module.mk @@ -32,13 +32,13 @@ MODULE_OBJS := \ scripting/menu.o \ scripting/scr_file_handling.o \ scripting/script_manager.o \ - scripting/sidefx/animation_node.o \ - scripting/sidefx/distort_node.o \ - scripting/sidefx/music_node.o \ - scripting/sidefx/region_node.o \ - scripting/sidefx/syncsound_node.o \ - scripting/sidefx/timer_node.o \ - scripting/sidefx/ttytext_node.o \ + scripting/effects/animation_effect.o \ + scripting/effects/distort_effect.o \ + scripting/effects/music_effect.o \ + scripting/effects/region_effect.o \ + scripting/effects/syncsound_effect.o \ + scripting/effects/timer_effect.o \ + scripting/effects/ttytext_effect.o \ sound/midi.o \ sound/zork_raw.o \ text/string_manager.o \ diff --git a/engines/zvision/scripting/actions.cpp b/engines/zvision/scripting/actions.cpp index a91476760d..a61fa26223 100644 --- a/engines/zvision/scripting/actions.cpp +++ b/engines/zvision/scripting/actions.cpp @@ -31,16 +31,16 @@ #include "zvision/video/zork_avi_decoder.h" #include "zvision/file/save_manager.h" #include "zvision/scripting/menu.h" -#include "zvision/scripting/sidefx/timer_node.h" -#include "zvision/scripting/sidefx/music_node.h" -#include "zvision/scripting/sidefx/syncsound_node.h" -#include "zvision/scripting/sidefx/animation_node.h" -#include "zvision/scripting/sidefx/distort_node.h" -#include "zvision/scripting/sidefx/ttytext_node.h" -#include "zvision/scripting/sidefx/region_node.h" +#include "zvision/scripting/effects/timer_effect.h" +#include "zvision/scripting/effects/music_effect.h" +#include "zvision/scripting/effects/syncsound_effect.h" +#include "zvision/scripting/effects/animation_effect.h" +#include "zvision/scripting/effects/distort_effect.h" +#include "zvision/scripting/effects/ttytext_effect.h" +#include "zvision/scripting/effects/region_effect.h" #include "zvision/scripting/controls/titler_control.h" #include "zvision/graphics/render_table.h" -#include "zvision/graphics/effect.h" +#include "zvision/graphics/graphics_effect.h" #include "zvision/graphics/effects/fog.h" #include "zvision/graphics/effects/light.h" #include "zvision/graphics/effects/wave.h" @@ -106,8 +106,8 @@ ActionAttenuate::ActionAttenuate(ZVision *engine, int32 slotkey, const Common::S } bool ActionAttenuate::execute() { - SideFX *fx = _engine->getScriptManager()->getSideFX(_key); - if (fx && fx->getType() == SideFX::SIDEFX_AUDIO) { + ScriptingEffect *fx = _engine->getScriptManager()->getSideFX(_key); + if (fx && fx->getType() == ScriptingEffect::SCRIPTING_EFFECT_AUDIO) { MusicNode *mus = (MusicNode *)fx; mus->setVolume(255 - (abs(_attenuation) >> 7)); } @@ -157,8 +157,8 @@ ActionCrossfade::ActionCrossfade(ZVision *engine, int32 slotkey, const Common::S bool ActionCrossfade::execute() { if (_keyOne) { - SideFX *fx = _engine->getScriptManager()->getSideFX(_keyOne); - if (fx && fx->getType() == SideFX::SIDEFX_AUDIO) { + ScriptingEffect *fx = _engine->getScriptManager()->getSideFX(_keyOne); + if (fx && fx->getType() == ScriptingEffect::SCRIPTING_EFFECT_AUDIO) { MusicNode *mus = (MusicNode *)fx; if (_oneStartVolume >= 0) mus->setVolume((_oneStartVolume * 255) / 100); @@ -168,8 +168,8 @@ bool ActionCrossfade::execute() { } if (_keyTwo) { - SideFX *fx = _engine->getScriptManager()->getSideFX(_keyTwo); - if (fx && fx->getType() == SideFX::SIDEFX_AUDIO) { + ScriptingEffect *fx = _engine->getScriptManager()->getSideFX(_keyTwo); + if (fx && fx->getType() == ScriptingEffect::SCRIPTING_EFFECT_AUDIO) { MusicNode *mus = (MusicNode *)fx; if (_twoStartVolume >= 0) mus->setVolume((_twoStartVolume * 255) / 100); @@ -401,28 +401,28 @@ ActionKill::ActionKill(ZVision *engine, int32 slotkey, const Common::String &lin sscanf(line.c_str(), "%24s", keytype); if (keytype[0] == '"') { if (!scumm_stricmp(keytype, "\"ANIM\"")) - _type = SideFX::SIDEFX_ANIM; + _type = ScriptingEffect::SCRIPTING_EFFECT_ANIM; else if (!scumm_stricmp(keytype, "\"AUDIO\"")) - _type = SideFX::SIDEFX_AUDIO; + _type = ScriptingEffect::SCRIPTING_EFFECT_AUDIO; else if (!scumm_stricmp(keytype, "\"DISTORT\"")) - _type = SideFX::SIDEFX_DISTORT; + _type = ScriptingEffect::SCRIPTING_EFFECT_DISTORT; else if (!scumm_stricmp(keytype, "\"PANTRACK\"")) - _type = SideFX::SIDEFX_PANTRACK; + _type = ScriptingEffect::SCRIPTING_EFFECT_PANTRACK; else if (!scumm_stricmp(keytype, "\"REGION\"")) - _type = SideFX::SIDEFX_REGION; + _type = ScriptingEffect::SCRIPTING_EFFECT_REGION; else if (!scumm_stricmp(keytype, "\"TIMER\"")) - _type = SideFX::SIDEFX_TIMER; + _type = ScriptingEffect::SCRIPTING_EFFECT_TIMER; else if (!scumm_stricmp(keytype, "\"TTYTEXT\"")) - _type = SideFX::SIDEFX_TTYTXT; + _type = ScriptingEffect::SCRIPTING_EFFECT_TTYTXT; else if (!scumm_stricmp(keytype, "\"ALL\"")) - _type = SideFX::SIDEFX_ALL; + _type = ScriptingEffect::SCRIPTING_EFFECT_ALL; } else _key = atoi(keytype); } bool ActionKill::execute() { if (_type) - _engine->getScriptManager()->killSideFxType((SideFX::SideFXType)_type); + _engine->getScriptManager()->killSideFxType((ScriptingEffect::ScriptingEffectType)_type); else _engine->getScriptManager()->killSideFx(_key); return true; @@ -580,10 +580,10 @@ ActionPreloadAnimation::~ActionPreloadAnimation() { } bool ActionPreloadAnimation::execute() { - AnimationNode *nod = (AnimationNode *)_engine->getScriptManager()->getSideFX(_slotKey); + AnimationEffect *nod = (AnimationEffect *)_engine->getScriptManager()->getSideFX(_slotKey); if (!nod) { - nod = new AnimationNode(_engine, _slotKey, _fileName, _mask, _framerate, false); + nod = new AnimationEffect(_engine, _slotKey, _fileName, _mask, _framerate, false); _engine->getScriptManager()->addSideFX(nod); } else nod->stop(); @@ -603,9 +603,9 @@ ActionUnloadAnimation::ActionUnloadAnimation(ZVision *engine, int32 slotkey, con } bool ActionUnloadAnimation::execute() { - AnimationNode *nod = (AnimationNode *)_engine->getScriptManager()->getSideFX(_key); + AnimationEffect *nod = (AnimationEffect *)_engine->getScriptManager()->getSideFX(_key); - if (nod && nod->getType() == SideFX::SIDEFX_ANIM) + if (nod && nod->getType() == ScriptingEffect::SCRIPTING_EFFECT_ANIM) _engine->getScriptManager()->deleteSideFx(_key); return true; @@ -648,10 +648,10 @@ ActionPlayAnimation::~ActionPlayAnimation() { } bool ActionPlayAnimation::execute() { - AnimationNode *nod = (AnimationNode *)_engine->getScriptManager()->getSideFX(_slotKey); + AnimationEffect *nod = (AnimationEffect *)_engine->getScriptManager()->getSideFX(_slotKey); if (!nod) { - nod = new AnimationNode(_engine, _slotKey, _fileName, _mask, _framerate); + nod = new AnimationEffect(_engine, _slotKey, _fileName, _mask, _framerate); _engine->getScriptManager()->addSideFX(nod); } else nod->stop(); @@ -683,7 +683,7 @@ ActionPlayPreloadAnimation::ActionPlayPreloadAnimation(ZVision *engine, int32 sl } bool ActionPlayPreloadAnimation::execute() { - AnimationNode *nod = (AnimationNode *)_engine->getScriptManager()->getSideFX(_controlKey); + AnimationEffect *nod = (AnimationEffect *)_engine->getScriptManager()->getSideFX(_controlKey); if (nod) nod->addPlayNode(_slotKey, _x1, _y1, _x2, _y2, _startFrame, _endFrame, _loopCount); @@ -731,7 +731,7 @@ bool ActionRegion::execute() { if (_engine->getScriptManager()->getSideFX(_slotKey)) return true; - Effect *effect = NULL; + GraphicsEffect *effect = NULL; switch (_type) { case 0: { uint16 centerX, centerY, frames; @@ -982,11 +982,11 @@ ActionSyncSound::ActionSyncSound(ZVision *engine, int32 slotkey, const Common::S } bool ActionSyncSound::execute() { - SideFX *fx = _engine->getScriptManager()->getSideFX(_syncto); + ScriptingEffect *fx = _engine->getScriptManager()->getSideFX(_syncto); if (!fx) return true; - if (!(fx->getType() & SideFX::SIDEFX_ANIM)) + if (!(fx->getType() & ScriptingEffect::SCRIPTING_EFFECT_ANIM)) return true; _engine->getScriptManager()->addSideFX(new SyncSoundNode(_engine, _slotKey, _fileName, _syncto)); diff --git a/engines/zvision/scripting/control.h b/engines/zvision/scripting/control.h index 803d0cf1ce..108b83fd00 100644 --- a/engines/zvision/scripting/control.h +++ b/engines/zvision/scripting/control.h @@ -36,6 +36,11 @@ namespace ZVision { class ZVision; +/** + * The base class for all Controls. + * + * Controls are the things that the user interacts with. Ex: A lever on the door + */ class Control { public: diff --git a/engines/zvision/scripting/effects/animation_effect.cpp b/engines/zvision/scripting/effects/animation_effect.cpp new file mode 100644 index 0000000000..c3cbc25406 --- /dev/null +++ b/engines/zvision/scripting/effects/animation_effect.cpp @@ -0,0 +1,213 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "common/scummsys.h" + +#include "zvision/scripting/effects/animation_effect.h" + +#include "zvision/zvision.h" +#include "zvision/graphics/render_manager.h" +#include "zvision/scripting/script_manager.h" + +#include "graphics/surface.h" +#include "video/video_decoder.h" + +namespace ZVision { + +AnimationEffect::AnimationEffect(ZVision *engine, uint32 controlKey, const Common::String &fileName, int32 mask, int32 frate, bool disposeAfterUse) + : ScriptingEffect(engine, controlKey, SCRIPTING_EFFECT_ANIM), + _disposeAfterUse(disposeAfterUse), + _mask(mask), + _animation(NULL) { + + _animation = engine->loadAnimation(fileName); + + if (frate > 0) { + _frmDelayOverride = (int32)(1000.0 / frate); + + // WORKAROUND: We do not allow the engine to delay more than 66 msec + // per frame (15fps max) + if (_frmDelayOverride > 66) + _frmDelayOverride = 66; + } else { + _frmDelayOverride = 0; + } +} + +AnimationEffect::~AnimationEffect() { + if (_animation) + delete _animation; + + _engine->getScriptManager()->setStateValue(_key, 2); + + PlayNodes::iterator it = _playList.begin(); + if (it != _playList.end()) { + _engine->getScriptManager()->setStateValue((*it).slot, 2); + + if ((*it)._scaled) { + (*it)._scaled->free(); + delete(*it)._scaled; + } + } + + _playList.clear(); +} + +bool AnimationEffect::process(uint32 deltaTimeInMillis) { + ScriptManager *scriptManager = _engine->getScriptManager(); + RenderManager *renderManager = _engine->getRenderManager(); + RenderTable::RenderState renderState = renderManager->getRenderTable()->getRenderState(); + bool isPanorama = (renderState == RenderTable::PANORAMA); + int16 velocity = _engine->getMouseVelocity() + _engine->getKeyboardVelocity(); + + // Do not update animation nodes in panoramic mode while turning, if the user + // has set this option + if (scriptManager->getStateValue(StateKey_NoTurnAnim) == 1 && isPanorama && velocity) + return false; + + PlayNodes::iterator it = _playList.begin(); + if (it != _playList.end()) { + playnode *nod = &(*it); + + if (!_animation->isPlaying()) { + // The node is just beginning playback + _animation->start(); + _animation->seekToFrame(nod->start); + + nod->_delay = deltaTimeInMillis; // Force the frame to draw + if (nod->slot) + scriptManager->setStateValue(nod->slot, 1); + } else if (_animation->endOfVideo()) { + // The node has reached the end; check if we need to loop + nod->loop--; + + if (nod->loop == 0) { + if (nod->slot >= 0) + scriptManager->setStateValue(nod->slot, 2); + if (nod->_scaled) { + nod->_scaled->free(); + delete nod->_scaled; + } + _playList.erase(it); + return _disposeAfterUse; + } + + _animation->seekToFrame(nod->start); + } + + // Check if we need to draw a frame + bool needsUpdate = false; + if (_frmDelayOverride == 0) { + // If not overridden, use the VideoDecoder's check + needsUpdate = _animation->needsUpdate(); + } else { + // Otherwise, implement our own timing + nod->_delay -= deltaTimeInMillis; + + if (nod->_delay <= 0) { + nod->_delay += _frmDelayOverride; + needsUpdate = true; + } + } + + if (needsUpdate) { + const Graphics::Surface *frame = _animation->decodeNextFrame(); + + if (frame) { + uint32 dstw; + uint32 dsth; + if (isPanorama) { + dstw = nod->pos.height(); + dsth = nod->pos.width(); + } else { + dstw = nod->pos.width(); + dsth = nod->pos.height(); + } + + // We only scale down the animation to fit its frame, not up, otherwise we + // end up with distorted animations - e.g. the armor visor in location cz1e + // in Nemesis (one of the armors inside Irondune), or the planet in location + // aa10 in Nemesis (Juperon, outside the asylum). We do allow scaling up only + // when a simple 2x filter is requested (e.g. the alchemists and cup sequence + // in Nemesis) + if (frame->w > dstw || frame->h > dsth || (frame->w == dstw / 2 && frame->h == dsth / 2)) { + if (nod->_scaled) + if (nod->_scaled->w != dstw || nod->_scaled->h != dsth) { + nod->_scaled->free(); + delete nod->_scaled; + nod->_scaled = NULL; + } + + if (!nod->_scaled) { + nod->_scaled = new Graphics::Surface; + nod->_scaled->create(dstw, dsth, frame->format); + } + + renderManager->scaleBuffer(frame->getPixels(), nod->_scaled->getPixels(), frame->w, frame->h, frame->format.bytesPerPixel, dstw, dsth); + frame = nod->_scaled; + } + + if (isPanorama) { + Graphics::Surface *transposed = RenderManager::tranposeSurface(frame); + renderManager->blitSurfaceToBkg(*transposed, nod->pos.left, nod->pos.top, _mask); + transposed->free(); + delete transposed; + } else { + renderManager->blitSurfaceToBkg(*frame, nod->pos.left, nod->pos.top, _mask); + } + } + } + } + + return false; +} + +void AnimationEffect::addPlayNode(int32 slot, int x, int y, int x2, int y2, int startFrame, int endFrame, int loops) { + playnode nod; + nod.loop = loops; + nod.pos = Common::Rect(x, y, x2 + 1, y2 + 1); + nod.start = startFrame; + _animation->setEndFrame(CLIP(endFrame, 0, _animation->getFrameCount() - 1)); + + nod.slot = slot; + nod._delay = 0; + nod._scaled = NULL; + _playList.push_back(nod); +} + +bool AnimationEffect::stop() { + PlayNodes::iterator it = _playList.begin(); + if (it != _playList.end()) { + _engine->getScriptManager()->setStateValue((*it).slot, 2); + if ((*it)._scaled) { + (*it)._scaled->free(); + delete(*it)._scaled; + } + } + + _playList.clear(); + + // We don't need to delete, it's may be reused + return false; +} + +} // End of namespace ZVision diff --git a/engines/zvision/scripting/effects/animation_effect.h b/engines/zvision/scripting/effects/animation_effect.h new file mode 100644 index 0000000000..a564b83ff3 --- /dev/null +++ b/engines/zvision/scripting/effects/animation_effect.h @@ -0,0 +1,77 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef ZVISION_ANIMATION_NODE_H +#define ZVISION_ANIMATION_NODE_H + +#include "zvision/scripting/scripting_effect.h" +#include "common/rect.h" +#include "common/list.h" + +namespace Graphics { +struct Surface; +} + +namespace Video { + class VideoDecoder; +} + +namespace ZVision { + +class ZVision; + +class AnimationEffect : public ScriptingEffect { +public: + AnimationEffect(ZVision *engine, uint32 controlKey, const Common::String &fileName, int32 mask, int32 frate, bool disposeAfterUse = true); + ~AnimationEffect(); + + struct playnode { + Common::Rect pos; + int32 slot; + int32 start; + int32 loop; + int32 _delay; + Graphics::Surface *_scaled; + }; + +private: + typedef Common::List PlayNodes; + + PlayNodes _playList; + + int32 _mask; + bool _disposeAfterUse; + + Video::VideoDecoder *_animation; + int32 _frmDelayOverride; + +public: + bool process(uint32 deltaTimeInMillis); + + void addPlayNode(int32 slot, int x, int y, int x2, int y2, int startFrame, int endFrame, int loops = 1); + + bool stop(); +}; + +} // End of namespace ZVision + +#endif diff --git a/engines/zvision/scripting/effects/distort_effect.cpp b/engines/zvision/scripting/effects/distort_effect.cpp new file mode 100644 index 0000000000..78c4a1b9a8 --- /dev/null +++ b/engines/zvision/scripting/effects/distort_effect.cpp @@ -0,0 +1,104 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "common/scummsys.h" + +#include "zvision/scripting/effects/distort_effect.h" + +#include "zvision/zvision.h" +#include "zvision/scripting/script_manager.h" +#include "zvision/graphics/render_manager.h" +#include "zvision/graphics/render_table.h" + +#include "common/stream.h" + +namespace ZVision { + +DistortNode::DistortNode(ZVision *engine, uint32 key, int16 speed, float startAngle, float endAngle, float startLineScale, float endLineScale) + : ScriptingEffect(engine, key, SCRIPTING_EFFECT_DISTORT) { + + _angle = _engine->getRenderManager()->getRenderTable()->getAngle(); + _linScale = _engine->getRenderManager()->getRenderTable()->getLinscale(); + + _speed = speed; + _incr = true; + _startAngle = startAngle; + _endAngle = endAngle; + _startLineScale = startLineScale; + _endLineScale = endLineScale; + + _curFrame = 1.0; + + _diffAngle = endAngle - startAngle; + _diffLinScale = endLineScale - startLineScale; + + _frmSpeed = (float)speed / 15.0; + _frames = ceil((5.0 - _frmSpeed * 2.0) / _frmSpeed); + if (_frames <= 0) + _frames = 1; + + if (_key != StateKey_NotSet) + _engine->getScriptManager()->setStateValue(_key, 1); +} + +DistortNode::~DistortNode() { + setParams(_angle, _linScale); +} + +bool DistortNode::process(uint32 deltaTimeInMillis) { + float updTime = deltaTimeInMillis / (1000.0 / 60.0); + + if (_incr) + _curFrame += updTime; + else + _curFrame -= updTime; + + if (_curFrame < 1.0) { + _curFrame = 1.0; + _incr = true; + } else if (_curFrame > _frames) { + _curFrame = _frames; + _incr = false; + } + + float diff = (1.0 / (5.0 - (_curFrame * _frmSpeed))) / (5.0 - _frmSpeed); + setParams(_startAngle + diff * _diffAngle, _startLineScale + diff * _diffLinScale); + + return false; +} + +void DistortNode::setParams(float angl, float linScale) { + RenderTable *table = _engine->getRenderManager()->getRenderTable(); + if (table->getRenderState() == RenderTable::PANORAMA) { + table->setPanoramaFoV(angl); + table->setPanoramaScale(linScale); + table->generateRenderTable(); + _engine->getRenderManager()->markDirty(); + } else if (table->getRenderState() == RenderTable::TILT) { + table->setTiltFoV(angl); + table->setTiltScale(linScale); + table->generateRenderTable(); + _engine->getRenderManager()->markDirty(); + } +} + +} // End of namespace ZVision diff --git a/engines/zvision/scripting/effects/distort_effect.h b/engines/zvision/scripting/effects/distort_effect.h new file mode 100644 index 0000000000..c64f10e6ff --- /dev/null +++ b/engines/zvision/scripting/effects/distort_effect.h @@ -0,0 +1,63 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef ZVISION_DISTORT_NODE_H +#define ZVISION_DISTORT_NODE_H + +#include "zvision/scripting/scripting_effect.h" + +namespace ZVision { + +class ZVision; + +class DistortNode : public ScriptingEffect { +public: + DistortNode(ZVision *engine, uint32 key, int16 speed, float startAngle, float endAngle, float startLineScale, float endLineScale); + ~DistortNode(); + + bool process(uint32 deltaTimeInMillis); + +private: + int16 _speed; + float _startAngle; + float _endAngle; + float _startLineScale; + float _endLineScale; + + float _frmSpeed; + float _diffAngle; + float _diffLinScale; + bool _incr; + int16 _frames; + + float _curFrame; + + float _angle; + float _linScale; + +private: + void setParams(float angl, float linScale); +}; + +} // End of namespace ZVision + +#endif diff --git a/engines/zvision/scripting/effects/music_effect.cpp b/engines/zvision/scripting/effects/music_effect.cpp new file mode 100644 index 0000000000..102f330305 --- /dev/null +++ b/engines/zvision/scripting/effects/music_effect.cpp @@ -0,0 +1,248 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "common/scummsys.h" + +#include "zvision/scripting/effects/music_effect.h" + +#include "zvision/zvision.h" +#include "zvision/scripting/script_manager.h" +#include "zvision/graphics/render_manager.h" +#include "zvision/sound/midi.h" +#include "zvision/sound/zork_raw.h" + +#include "common/stream.h" +#include "common/file.h" +#include "audio/decoders/wave.h" + +namespace ZVision { + +MusicNode::MusicNode(ZVision *engine, uint32 key, Common::String &filename, bool loop, int8 volume) + : MusicNodeBASE(engine, key, SCRIPTING_EFFECT_AUDIO) { + _loop = loop; + _volume = volume; + _crossfade = false; + _crossfadeTarget = 0; + _crossfadeTime = 0; + _attenuate = 0; + _pantrack = false; + _pantrackPosition = 0; + _sub = NULL; + _stereo = false; + _loaded = false; + + Audio::RewindableAudioStream *audioStream = NULL; + + if (filename.contains(".wav")) { + Common::File *file = new Common::File(); + if (_engine->getSearchManager()->openFile(*file, filename)) { + audioStream = Audio::makeWAVStream(file, DisposeAfterUse::YES); + } + } else { + audioStream = makeRawZorkStream(filename, _engine); + } + + if (audioStream) { + _stereo = audioStream->isStereo(); + + if (_loop) { + Audio::LoopingAudioStream *loopingAudioStream = new Audio::LoopingAudioStream(audioStream, 0, DisposeAfterUse::YES); + _engine->_mixer->playStream(Audio::Mixer::kPlainSoundType, &_handle, loopingAudioStream, -1, _volume); + } else { + _engine->_mixer->playStream(Audio::Mixer::kPlainSoundType, &_handle, audioStream, -1, _volume); + } + + if (_key != StateKey_NotSet) + _engine->getScriptManager()->setStateValue(_key, 1); + + // Change filename.raw into filename.sub + Common::String subname = filename; + subname.setChar('s', subname.size() - 3); + subname.setChar('u', subname.size() - 2); + subname.setChar('b', subname.size() - 1); + + if (_engine->getSearchManager()->hasFile(subname)) + _sub = new Subtitle(_engine, subname); + + _loaded = true; + } +} + +MusicNode::~MusicNode() { + if (_loaded) + _engine->_mixer->stopHandle(_handle); + if (_key != StateKey_NotSet) + _engine->getScriptManager()->setStateValue(_key, 2); + if (_sub) + delete _sub; + debug(1, "MusicNode: %d destroyed\n", _key); +} + +void MusicNode::setPanTrack(int16 pos) { + if (!_stereo) { + _pantrack = true; + _pantrackPosition = pos; + setVolume(_volume); + } +} + +void MusicNode::unsetPanTrack() { + _pantrack = false; + setVolume(_volume); +} + +void MusicNode::setFade(int32 time, uint8 target) { + _crossfadeTarget = target; + _crossfadeTime = time; + _crossfade = true; +} + +bool MusicNode::process(uint32 deltaTimeInMillis) { + if (!_loaded || ! _engine->_mixer->isSoundHandleActive(_handle)) + return stop(); + else { + uint8 _newvol = _volume; + + if (_crossfade) { + if (_crossfadeTime > 0) { + if ((int32)deltaTimeInMillis > _crossfadeTime) + deltaTimeInMillis = _crossfadeTime; + _newvol += floor(((float)(_crossfadeTarget - _newvol) / (float)_crossfadeTime)) * (float)deltaTimeInMillis; + _crossfadeTime -= deltaTimeInMillis; + } else { + _crossfade = false; + _newvol = _crossfadeTarget; + } + } + + if (_pantrack || _volume != _newvol) + setVolume(_newvol); + + if (_sub && _engine->getScriptManager()->getStateValue(StateKey_Subtitles) == 1) + _sub->process(_engine->_mixer->getSoundElapsedTime(_handle) / 100); + } + return false; +} + +void MusicNode::setVolume(uint8 newVolume) { + if (!_loaded) + return; + if (_pantrack) { + int curX = _engine->getScriptManager()->getStateValue(StateKey_ViewPos); + curX -= _pantrackPosition; + int32 _width = _engine->getRenderManager()->getBkgSize().x; + if (curX < (-_width) / 2) + curX += _width; + else if (curX >= _width / 2) + curX -= _width; + + float norm = (float)curX / ((float)_width / 2.0); + float lvl = fabs(norm); + if (lvl > 0.5) + lvl = (lvl - 0.5) * 1.7; + else + lvl = 1.0; + + float bal = sin(-norm * 3.1415926) * 127.0; + + if (_engine->_mixer->isSoundHandleActive(_handle)) { + _engine->_mixer->setChannelBalance(_handle, bal); + _engine->_mixer->setChannelVolume(_handle, newVolume * lvl); + } + } else { + if (_engine->_mixer->isSoundHandleActive(_handle)) { + _engine->_mixer->setChannelBalance(_handle, 0); + _engine->_mixer->setChannelVolume(_handle, newVolume); + } + } + + _volume = newVolume; +} + +PanTrackNode::PanTrackNode(ZVision *engine, uint32 key, uint32 slot, int16 pos) + : ScriptingEffect(engine, key, SCRIPTING_EFFECT_PANTRACK) { + _slot = slot; + + ScriptingEffect *fx = _engine->getScriptManager()->getSideFX(slot); + if (fx && fx->getType() == SCRIPTING_EFFECT_AUDIO) { + MusicNodeBASE *mus = (MusicNodeBASE *)fx; + mus->setPanTrack(pos); + } +} + +PanTrackNode::~PanTrackNode() { + ScriptingEffect *fx = _engine->getScriptManager()->getSideFX(_slot); + if (fx && fx->getType() == SCRIPTING_EFFECT_AUDIO) { + MusicNodeBASE *mus = (MusicNodeBASE *)fx; + mus->unsetPanTrack(); + } +} + +MusicMidiNode::MusicMidiNode(ZVision *engine, uint32 key, int8 program, int8 note, int8 volume) + : MusicNodeBASE(engine, key, SCRIPTING_EFFECT_AUDIO) { + _volume = volume; + _prog = program; + _noteNumber = note; + _pan = 0; + + _chan = _engine->getMidiManager()->getFreeChannel(); + + if (_chan >= 0) { + _engine->getMidiManager()->setVolume(_chan, _volume); + _engine->getMidiManager()->setPan(_chan, _pan); + _engine->getMidiManager()->setProgram(_chan, _prog); + _engine->getMidiManager()->noteOn(_chan, _noteNumber, _volume); + } + + if (_key != StateKey_NotSet) + _engine->getScriptManager()->setStateValue(_key, 1); +} + +MusicMidiNode::~MusicMidiNode() { + if (_chan >= 0) { + _engine->getMidiManager()->noteOff(_chan); + } + if (_key != StateKey_NotSet) + _engine->getScriptManager()->setStateValue(_key, 2); +} + +void MusicMidiNode::setPanTrack(int16 pos) { +} + +void MusicMidiNode::unsetPanTrack() { +} + +void MusicMidiNode::setFade(int32 time, uint8 target) { +} + +bool MusicMidiNode::process(uint32 deltaTimeInMillis) { + return false; +} + +void MusicMidiNode::setVolume(uint8 newVolume) { + if (_chan >= 0) { + _engine->getMidiManager()->setVolume(_chan, newVolume); + } + _volume = newVolume; +} + +} // End of namespace ZVision diff --git a/engines/zvision/scripting/effects/music_effect.h b/engines/zvision/scripting/effects/music_effect.h new file mode 100644 index 0000000000..31d538f668 --- /dev/null +++ b/engines/zvision/scripting/effects/music_effect.h @@ -0,0 +1,135 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef ZVISION_MUSIC_NODE_H +#define ZVISION_MUSIC_NODE_H + +#include "audio/mixer.h" +#include "zvision/scripting/scripting_effect.h" +#include "zvision/text/subtitles.h" + +namespace Common { +class String; +} + +namespace ZVision { + +class MusicNodeBASE : public ScriptingEffect { +public: + MusicNodeBASE(ZVision *engine, uint32 key, ScriptingEffectType type) : ScriptingEffect(engine, key, type) {} + ~MusicNodeBASE() {} + + /** + * Decrement the timer by the delta time. If the timer is finished, set the status + * in _globalState and let this node be deleted + * + * @param deltaTimeInMillis The number of milliseconds that have passed since last frame + * @return If true, the node can be deleted after process() finishes + */ + virtual bool process(uint32 deltaTimeInMillis) = 0; + + virtual void setVolume(uint8 volume) = 0; + + virtual void setPanTrack(int16 pos) = 0; + virtual void unsetPanTrack() = 0; + + virtual void setFade(int32 time, uint8 target) = 0; +}; + +class MusicNode : public MusicNodeBASE { +public: + MusicNode(ZVision *engine, uint32 key, Common::String &file, bool loop, int8 volume); + ~MusicNode(); + + /** + * Decrement the timer by the delta time. If the timer is finished, set the status + * in _globalState and let this node be deleted + * + * @param deltaTimeInMillis The number of milliseconds that have passed since last frame + * @return If true, the node can be deleted after process() finishes + */ + bool process(uint32 deltaTimeInMillis); + + void setVolume(uint8 volume); + + void setPanTrack(int16 pos); + void unsetPanTrack(); + + void setFade(int32 time, uint8 target); + +private: + bool _pantrack; + int32 _pantrackPosition; + int32 _attenuate; + uint8 _volume; + bool _loop; + bool _crossfade; + uint8 _crossfadeTarget; + int32 _crossfadeTime; + bool _stereo; + Audio::SoundHandle _handle; + Subtitle *_sub; + bool _loaded; +}; + +// Only used by Zork: Nemesis, for the flute and piano puzzles (tj4e and ve6f, as well as vr) +class MusicMidiNode : public MusicNodeBASE { +public: + MusicMidiNode(ZVision *engine, uint32 key, int8 program, int8 note, int8 volume); + ~MusicMidiNode(); + + /** + * Decrement the timer by the delta time. If the timer is finished, set the status + * in _globalState and let this node be deleted + * + * @param deltaTimeInMillis The number of milliseconds that have passed since last frame + * @return If true, the node can be deleted after process() finishes + */ + bool process(uint32 deltaTimeInMillis); + + void setVolume(uint8 volume); + + void setPanTrack(int16 pos); + void unsetPanTrack(); + + void setFade(int32 time, uint8 target); + +private: + int8 _chan; + int8 _noteNumber; + int8 _pan; + int8 _volume; + int8 _prog; +}; + +class PanTrackNode : public ScriptingEffect { +public: + PanTrackNode(ZVision *engine, uint32 key, uint32 slot, int16 pos); + ~PanTrackNode(); + +private: + uint32 _slot; +}; + +} // End of namespace ZVision + +#endif diff --git a/engines/zvision/scripting/effects/region_effect.cpp b/engines/zvision/scripting/effects/region_effect.cpp new file mode 100644 index 0000000000..78061cf4de --- /dev/null +++ b/engines/zvision/scripting/effects/region_effect.cpp @@ -0,0 +1,56 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "common/scummsys.h" + +#include "zvision/scripting/effects/region_effect.h" + +#include "zvision/zvision.h" +#include "zvision/scripting/script_manager.h" +#include "zvision/graphics/render_manager.h" + +namespace ZVision { + +RegionNode::RegionNode(ZVision *engine, uint32 key, GraphicsEffect *effect, uint32 delay) + : ScriptingEffect(engine, key, SCRIPTING_EFFECT_REGION) { + _effect = effect; + _delay = delay; + _timeLeft = 0; +} + +RegionNode::~RegionNode() { + _engine->getRenderManager()->deleteEffect(_key); +} + +bool RegionNode::process(uint32 deltaTimeInMillis) { + _timeLeft -= deltaTimeInMillis; + + if (_timeLeft <= 0) { + _timeLeft = _delay; + if (_effect) + _effect->update(); + } + + return false; +} + +} // End of namespace ZVision diff --git a/engines/zvision/scripting/effects/region_effect.h b/engines/zvision/scripting/effects/region_effect.h new file mode 100644 index 0000000000..4fc16224ff --- /dev/null +++ b/engines/zvision/scripting/effects/region_effect.h @@ -0,0 +1,57 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef ZVISION_REGION_NODE_H +#define ZVISION_REGION_NODE_H + +#include "graphics/surface.h" + +#include "zvision/scripting/scripting_effect.h" +#include "zvision/graphics/graphics_effect.h" + +namespace ZVision { + +class ZVision; + +class RegionNode : public ScriptingEffect { +public: + RegionNode(ZVision *engine, uint32 key, GraphicsEffect *effect, uint32 delay); + ~RegionNode(); + + /** + * Decrement the timer by the delta time. If the timer is finished, set the status + * in _globalState and let this node be deleted + * + * @param deltaTimeInMillis The number of milliseconds that have passed since last frame + * @return If true, the node can be deleted after process() finishes + */ + bool process(uint32 deltaTimeInMillis); + +private: + int32 _timeLeft; + uint32 _delay; + GraphicsEffect *_effect; +}; + +} // End of namespace ZVision + +#endif diff --git a/engines/zvision/scripting/effects/syncsound_effect.cpp b/engines/zvision/scripting/effects/syncsound_effect.cpp new file mode 100644 index 0000000000..70ba97deb8 --- /dev/null +++ b/engines/zvision/scripting/effects/syncsound_effect.cpp @@ -0,0 +1,85 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "common/scummsys.h" + +#include "zvision/scripting/effects/syncsound_effect.h" + +#include "zvision/zvision.h" +#include "zvision/scripting/script_manager.h" +#include "zvision/graphics/render_manager.h" +#include "zvision/sound/zork_raw.h" + +#include "common/stream.h" +#include "common/file.h" +#include "audio/decoders/wave.h" + +namespace ZVision { + +SyncSoundNode::SyncSoundNode(ZVision *engine, uint32 key, Common::String &filename, int32 syncto) + : ScriptingEffect(engine, key, SCRIPTING_EFFECT_AUDIO) { + _syncto = syncto; + _sub = NULL; + + Audio::RewindableAudioStream *audioStream = NULL; + + if (filename.contains(".wav")) { + Common::File *file = new Common::File(); + if (_engine->getSearchManager()->openFile(*file, filename)) { + audioStream = Audio::makeWAVStream(file, DisposeAfterUse::YES); + } + } else { + audioStream = makeRawZorkStream(filename, _engine); + } + + _engine->_mixer->playStream(Audio::Mixer::kPlainSoundType, &_handle, audioStream); + + Common::String subname = filename; + subname.setChar('s', subname.size() - 3); + subname.setChar('u', subname.size() - 2); + subname.setChar('b', subname.size() - 1); + + if (_engine->getSearchManager()->hasFile(subname)) + _sub = new Subtitle(_engine, subname); +} + +SyncSoundNode::~SyncSoundNode() { + _engine->_mixer->stopHandle(_handle); + if (_sub) + delete _sub; +} + +bool SyncSoundNode::process(uint32 deltaTimeInMillis) { + if (! _engine->_mixer->isSoundHandleActive(_handle)) + return stop(); + else { + + if (_engine->getScriptManager()->getSideFX(_syncto) == NULL) + return stop(); + + if (_sub && _engine->getScriptManager()->getStateValue(StateKey_Subtitles) == 1) + _sub->process(_engine->_mixer->getSoundElapsedTime(_handle) / 100); + } + return false; +} + +} // End of namespace ZVision diff --git a/engines/zvision/scripting/effects/syncsound_effect.h b/engines/zvision/scripting/effects/syncsound_effect.h new file mode 100644 index 0000000000..0eabff77a3 --- /dev/null +++ b/engines/zvision/scripting/effects/syncsound_effect.h @@ -0,0 +1,56 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef ZVISION_SYNCSOUND_NODE_H +#define ZVISION_SYNCSOUND_NODE_H + +#include "audio/mixer.h" +#include "zvision/scripting/scripting_effect.h" +#include "zvision/text/subtitles.h" + +namespace Common { +class String; +} + +namespace ZVision { +class SyncSoundNode : public ScriptingEffect { +public: + SyncSoundNode(ZVision *engine, uint32 key, Common::String &file, int32 syncto); + ~SyncSoundNode(); + + /** + * Decrement the timer by the delta time. If the timer is finished, set the status + * in _globalState and let this node be deleted + * + * @param deltaTimeInMillis The number of milliseconds that have passed since last frame + * @return If true, the node can be deleted after process() finishes + */ + bool process(uint32 deltaTimeInMillis); +private: + int32 _syncto; + Audio::SoundHandle _handle; + Subtitle *_sub; +}; + +} // End of namespace ZVision + +#endif diff --git a/engines/zvision/scripting/effects/timer_effect.cpp b/engines/zvision/scripting/effects/timer_effect.cpp new file mode 100644 index 0000000000..778f9dec6c --- /dev/null +++ b/engines/zvision/scripting/effects/timer_effect.cpp @@ -0,0 +1,81 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "common/scummsys.h" + +#include "zvision/scripting/effects/timer_effect.h" + +#include "zvision/zvision.h" +#include "zvision/scripting/script_manager.h" + +#include "common/stream.h" + +namespace ZVision { + +TimerNode::TimerNode(ZVision *engine, uint32 key, uint timeInSeconds) + : ScriptingEffect(engine, key, SCRIPTING_EFFECT_TIMER) { + _timeLeft = 0; + + if (_engine->getGameId() == GID_NEMESIS) + _timeLeft = timeInSeconds * 1000; + else if (_engine->getGameId() == GID_GRANDINQUISITOR) + _timeLeft = timeInSeconds * 100; + + if (_key != StateKey_NotSet) + _engine->getScriptManager()->setStateValue(_key, 1); +} + +TimerNode::~TimerNode() { + if (_key != StateKey_NotSet) + _engine->getScriptManager()->setStateValue(_key, 2); + int32 timeLeft = _timeLeft / (_engine->getGameId() == GID_NEMESIS ? 1000 : 100); + if (timeLeft > 0) + _engine->getScriptManager()->setStateValue(_key, timeLeft); // If timer was stopped by stop or kill +} + +bool TimerNode::process(uint32 deltaTimeInMillis) { + _timeLeft -= deltaTimeInMillis; + + if (_timeLeft <= 0) + return stop(); + + return false; +} + +bool TimerNode::stop() { + if (_key != StateKey_NotSet) + _engine->getScriptManager()->setStateValue(_key, 2); + return true; +} + +void TimerNode::serialize(Common::WriteStream *stream) { + stream->writeUint32BE(MKTAG('T', 'I', 'M', 'R')); + stream->writeUint32LE(8); // size + stream->writeUint32LE(_key); + stream->writeUint32LE(_timeLeft); +} + +void TimerNode::deserialize(Common::SeekableReadStream *stream) { + _timeLeft = stream->readUint32LE(); +} + +} // End of namespace ZVision diff --git a/engines/zvision/scripting/effects/timer_effect.h b/engines/zvision/scripting/effects/timer_effect.h new file mode 100644 index 0000000000..5e45d54d7d --- /dev/null +++ b/engines/zvision/scripting/effects/timer_effect.h @@ -0,0 +1,59 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef ZVISION_TIMER_NODE_H +#define ZVISION_TIMER_NODE_H + +#include "zvision/scripting/scripting_effect.h" + +namespace ZVision { + +class ZVision; + +class TimerNode : public ScriptingEffect { +public: + TimerNode(ZVision *engine, uint32 key, uint timeInSeconds); + ~TimerNode(); + + /** + * Decrement the timer by the delta time. If the timer is finished, set the status + * in _globalState and let this node be deleted + * + * @param deltaTimeInMillis The number of milliseconds that have passed since last frame + * @return If true, the node can be deleted after process() finishes + */ + bool process(uint32 deltaTimeInMillis); + void serialize(Common::WriteStream *stream); + void deserialize(Common::SeekableReadStream *stream); + inline bool needsSerialization() { + return true; + } + + bool stop(); + +private: + int32 _timeLeft; +}; + +} // End of namespace ZVision + +#endif diff --git a/engines/zvision/scripting/effects/ttytext_effect.cpp b/engines/zvision/scripting/effects/ttytext_effect.cpp new file mode 100644 index 0000000000..c60b3aa8c5 --- /dev/null +++ b/engines/zvision/scripting/effects/ttytext_effect.cpp @@ -0,0 +1,174 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "common/scummsys.h" + +#include "zvision/scripting/effects/ttytext_effect.h" + +#include "zvision/zvision.h" +#include "zvision/scripting/script_manager.h" +#include "zvision/graphics/render_manager.h" +#include "zvision/text/text.h" + +#include "common/stream.h" +#include "common/file.h" + +namespace ZVision { + +ttyTextNode::ttyTextNode(ZVision *engine, uint32 key, const Common::String &file, const Common::Rect &r, int32 delay) : + ScriptingEffect(engine, key, SCRIPTING_EFFECT_TTYTXT), + _fnt(engine) { + _delay = delay; + _r = r; + _txtpos = 0; + _nexttime = 0; + _dx = 0; + _dy = 0; + + Common::File *infile = _engine->getSearchManager()->openFile(file); + if (infile) { + while (!infile->eos()) { + Common::String asciiLine = readWideLine(*infile); + if (asciiLine.empty()) { + continue; + } + _txtbuf += asciiLine; + } + + delete infile; + } + _img.create(_r.width(), _r.height(), _engine->_resourcePixelFormat); + _style._sharp = true; + _style.readAllStyle(_txtbuf); + _style.setFont(_fnt); + _engine->getScriptManager()->setStateValue(_key, 1); +} + +ttyTextNode::~ttyTextNode() { + _engine->getScriptManager()->setStateValue(_key, 2); + _img.free(); +} + +bool ttyTextNode::process(uint32 deltaTimeInMillis) { + _nexttime -= deltaTimeInMillis; + + if (_nexttime < 0) { + if (_txtpos < _txtbuf.size()) { + if (_txtbuf[_txtpos] == '<') { + int32 strt = _txtpos; + int32 endt = 0; + int16 ret = 0; + while (_txtbuf[_txtpos] != '>' && _txtpos < _txtbuf.size()) + _txtpos++; + endt = _txtpos; + if (strt != -1) + if ((endt - strt - 1) > 0) + ret = _style.parseStyle(_txtbuf.c_str() + strt + 1, endt - strt - 1); + + if (ret & (TXT_RET_FNTCHG | TXT_RET_FNTSTL | TXT_RET_NEWLN)) { + if (ret & TXT_RET_FNTCHG) + _style.setFont(_fnt); + if (ret & TXT_RET_FNTSTL) + _style.setFontStyle(_fnt); + + if (ret & TXT_RET_NEWLN) + newline(); + } + + if (ret & TXT_RET_HASSTBOX) { + Common::String buf; + buf = Common::String::format("%d", _engine->getScriptManager()->getStateValue(_style._statebox)); + + for (uint8 j = 0; j < buf.size(); j++) + outchar(buf[j]); + } + + _txtpos++; + } else { + int8 charsz = getUtf8CharSize(_txtbuf[_txtpos]); + + uint16 chr = readUtf8Char(_txtbuf.c_str() + _txtpos); + + if (chr == ' ') { + uint32 i = _txtpos + charsz; + uint16 width = _fnt.getCharWidth(chr); + + while (i < _txtbuf.size() && _txtbuf[i] != ' ' && _txtbuf[i] != '<') { + + int8 chsz = getUtf8CharSize(_txtbuf[i]); + uint16 uchr = readUtf8Char(_txtbuf.c_str() + _txtpos); + + width += _fnt.getCharWidth(uchr); + + i += chsz; + } + + if (_dx + width > _r.width()) + newline(); + else + outchar(chr); + } else + outchar(chr); + + _txtpos += charsz; + } + _nexttime = _delay; + _engine->getRenderManager()->blitSurfaceToBkg(_img, _r.left, _r.top); + } else + return stop(); + } + + return false; +} + +void ttyTextNode::scroll() { + int32 scrl = 0; + while (_dy - scrl > _r.height() - _fnt.getFontHeight()) + scrl += _fnt.getFontHeight(); + int8 *pixels = (int8 *)_img.getPixels(); + for (uint16 h = scrl; h < _img.h; h++) + memcpy(pixels + _img.pitch * (h - scrl), pixels + _img.pitch * h, _img.pitch); + + _img.fillRect(Common::Rect(0, _img.h - scrl, _img.w, _img.h), 0); + _dy -= scrl; +} + +void ttyTextNode::newline() { + _dy += _fnt.getFontHeight(); + _dx = 0; +} + +void ttyTextNode::outchar(uint16 chr) { + uint32 clr = _engine->_resourcePixelFormat.RGBToColor(_style._red, _style._green, _style._blue); + + if (_dx + _fnt.getCharWidth(chr) > _r.width()) + newline(); + + if (_dy + _fnt.getFontHeight() >= _r.height()) + scroll(); + + _fnt.drawChar(&_img, chr, _dx, _dy, clr); + + _dx += _fnt.getCharWidth(chr); +} + +} // End of namespace ZVision diff --git a/engines/zvision/scripting/effects/ttytext_effect.h b/engines/zvision/scripting/effects/ttytext_effect.h new file mode 100644 index 0000000000..8d8a2518c7 --- /dev/null +++ b/engines/zvision/scripting/effects/ttytext_effect.h @@ -0,0 +1,73 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef ZVISION_TTYTEXT_NODE_H +#define ZVISION_TTYTEXT_NODE_H + +#include "common/rect.h" +#include "graphics/surface.h" + +#include "zvision/scripting/scripting_effect.h" +#include "zvision/text/text.h" +#include "zvision/text/truetype_font.h" + +namespace Common { +class String; +} + +namespace ZVision { +class ttyTextNode : public ScriptingEffect { +public: + ttyTextNode(ZVision *engine, uint32 key, const Common::String &file, const Common::Rect &r, int32 delay); + ~ttyTextNode(); + + /** + * Decrement the timer by the delta time. If the timer is finished, set the status + * in _globalState and let this node be deleted + * + * @param deltaTimeInMillis The number of milliseconds that have passed since last frame + * @return If true, the node can be deleted after process() finishes + */ + bool process(uint32 deltaTimeInMillis); +private: + Common::Rect _r; + + cTxtStyle _style; + StyledTTFont _fnt; + Common::String _txtbuf; + uint32 _txtpos; + + int32 _delay; + int32 _nexttime; + Graphics::Surface _img; + int16 _dx; + int16 _dy; +private: + + void newline(); + void scroll(); + void outchar(uint16 chr); +}; + +} // End of namespace ZVision + +#endif diff --git a/engines/zvision/scripting/script_manager.cpp b/engines/zvision/scripting/script_manager.cpp index d0ebb18944..464e8bfe4d 100644 --- a/engines/zvision/scripting/script_manager.cpp +++ b/engines/zvision/scripting/script_manager.cpp @@ -30,7 +30,7 @@ #include "zvision/file/save_manager.h" #include "zvision/scripting/actions.h" #include "zvision/scripting/menu.h" -#include "zvision/scripting/sidefx/timer_node.h" +#include "zvision/scripting/effects/timer_effect.h" #include "common/algorithm.h" #include "common/hashmap.h" @@ -382,11 +382,11 @@ void ScriptManager::setFocusControlKey(uint32 key) { _currentlyFocusedControl = key; } -void ScriptManager::addSideFX(SideFX *fx) { +void ScriptManager::addSideFX(ScriptingEffect *fx) { _activeSideFx.push_back(fx); } -SideFX *ScriptManager::getSideFX(uint32 key) { +ScriptingEffect *ScriptManager::getSideFX(uint32 key) { for (SideFXList::iterator iter = _activeSideFx.begin(); iter != _activeSideFx.end(); ++iter) { if ((*iter)->getKey() == key) { return (*iter); @@ -430,7 +430,7 @@ void ScriptManager::killSideFx(uint32 key) { } } -void ScriptManager::killSideFxType(SideFX::SideFXType type) { +void ScriptManager::killSideFxType(ScriptingEffect::ScriptingEffectType type) { for (SideFXList::iterator iter = _activeSideFx.begin(); iter != _activeSideFx.end();) { if ((*iter)->getType() & type) { (*iter)->kill(); diff --git a/engines/zvision/scripting/script_manager.h b/engines/zvision/scripting/script_manager.h index 9f0f2f6e10..78c1b77dea 100644 --- a/engines/zvision/scripting/script_manager.h +++ b/engines/zvision/scripting/script_manager.h @@ -25,7 +25,7 @@ #include "zvision/scripting/puzzle.h" #include "zvision/scripting/control.h" -#include "zvision/scripting/sidefx.h" +#include "zvision/scripting/scripting_effect.h" #include "common/hashmap.h" #include "common/queue.h" @@ -116,7 +116,7 @@ typedef Common::List PuzzleList; typedef Common::Queue PuzzleQueue; typedef Common::List ControlList; typedef Common::HashMap StateMap; -typedef Common::List SideFXList; +typedef Common::List SideFXList; typedef Common::List EventList; class ScriptManager { @@ -196,12 +196,12 @@ public: // Only change focus control without call focus/unfocus. void setFocusControlKey(uint32 key); - void addSideFX(SideFX *fx); - SideFX *getSideFX(uint32 key); + void addSideFX(ScriptingEffect *fx); + ScriptingEffect *getSideFX(uint32 key); void deleteSideFx(uint32 key); void stopSideFx(uint32 key); void killSideFx(uint32 key); - void killSideFxType(SideFX::SideFXType type); + void killSideFxType(ScriptingEffect::ScriptingEffectType type); void addEvent(Common::Event); void flushEvent(Common::EventType type); diff --git a/engines/zvision/scripting/scripting_effect.h b/engines/zvision/scripting/scripting_effect.h new file mode 100644 index 0000000000..0af1d9c21c --- /dev/null +++ b/engines/zvision/scripting/scripting_effect.h @@ -0,0 +1,124 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef SCRIPTING_EFFECT_H_INCLUDED +#define SCRIPTING_EFFECT_H_INCLUDED + +namespace Common { +class SeekableReadStream; +struct Point; +class WriteStream; +} + +namespace ZVision { + +class ZVision; + +/** + * The base class that represents effects created from Actions. + * This class is virtual. + * + * Detailed Description: + * A scene has Controls. By interacting with the controls, the user + * causes Actions to execute. Certain Actions create 'effects', for + * example, a sound or an animation. This is the base class for + * those effects. + */ +class ScriptingEffect { +public: + + enum ScriptingEffectType { + SCRIPTING_EFFECT_ANIM = 1, + SCRIPTING_EFFECT_AUDIO = 2, + SCRIPTING_EFFECT_DISTORT = 4, + SCRIPTING_EFFECT_PANTRACK = 8, + SCRIPTING_EFFECT_REGION = 16, + SCRIPTING_EFFECT_TIMER = 32, + SCRIPTING_EFFECT_TTYTXT = 64, + SCRIPTING_EFFECT_UNKNOWN = 128, + SCRIPTING_EFFECT_ALL = 255 + }; + + ScriptingEffect() : _engine(0), _key(0), _type(SCRIPTING_EFFECT_UNKNOWN) {} + ScriptingEffect(ZVision *engine, uint32 key, ScriptingEffectType type) : _engine(engine), _key(key), _type(type) {} + virtual ~ScriptingEffect() {} + + uint32 getKey() { + return _key; + } + ScriptingEffectType getType() { + return _type; + } + + virtual bool process(uint32 deltaTimeInMillis) { + return false; + } + /** + * Serialize a SideFX for save game use. This should only be used if a SideFX needs + * to save values that would be different from initialization. AKA a TimerNode needs to + * store the amount of time left on the timer. Any Controls overriding this *MUST* write + * their key as the first data outputted. The default implementation is NOP. + * + * NOTE: If this method is overridden, you MUST also override deserialize() + * and needsSerialization() + * + * @param stream Stream to write any needed data to + */ + virtual void serialize(Common::WriteStream *stream) {} + /** + * De-serialize data from a save game stream. This should only be implemented if the + * SideFX also implements serialize(). The calling method assumes the size of the + * data read from the stream exactly equals that written in serialize(). The default + * implementation is NOP. + * + * NOTE: If this method is overridden, you MUST also override serialize() + * and needsSerialization() + * + * @param stream Save game file stream + */ + virtual void deserialize(Common::SeekableReadStream *stream) {} + /** + * If a SideFX overrides serialize() and deserialize(), this should return true + * + * @return Does the SideFX need save game serialization? + */ + virtual inline bool needsSerialization() { + return false; + } + + virtual bool stop() { + return true; + } + virtual void kill() {} + +protected: + ZVision *_engine; + uint32 _key; + ScriptingEffectType _type; + +// Static member functions +public: + +}; +} // End of namespace ZVision + +#endif // SCRIPTING_EFFECT_H_INCLUDED diff --git a/engines/zvision/scripting/sidefx.h b/engines/zvision/scripting/sidefx.h deleted file mode 100644 index 5bb14f0cdd..0000000000 --- a/engines/zvision/scripting/sidefx.h +++ /dev/null @@ -1,114 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#ifndef SIDEFX_H_INCLUDED -#define SIDEFX_H_INCLUDED - -namespace Common { -class SeekableReadStream; -struct Point; -class WriteStream; -} - -namespace ZVision { - -class ZVision; - -class SideFX { -public: - - enum SideFXType { - SIDEFX_ANIM = 1, - SIDEFX_AUDIO = 2, - SIDEFX_DISTORT = 4, - SIDEFX_PANTRACK = 8, - SIDEFX_REGION = 16, - SIDEFX_TIMER = 32, - SIDEFX_TTYTXT = 64, - SIDEFX_UNK = 128, - SIDEFX_ALL = 255 - }; - - SideFX() : _engine(0), _key(0), _type(SIDEFX_UNK) {} - SideFX(ZVision *engine, uint32 key, SideFXType type) : _engine(engine), _key(key), _type(type) {} - virtual ~SideFX() {} - - uint32 getKey() { - return _key; - } - SideFXType getType() { - return _type; - } - - virtual bool process(uint32 deltaTimeInMillis) { - return false; - } - /** - * Serialize a SideFX for save game use. This should only be used if a SideFX needs - * to save values that would be different from initialization. AKA a TimerNode needs to - * store the amount of time left on the timer. Any Controls overriding this *MUST* write - * their key as the first data outputted. The default implementation is NOP. - * - * NOTE: If this method is overridden, you MUST also override deserialize() - * and needsSerialization() - * - * @param stream Stream to write any needed data to - */ - virtual void serialize(Common::WriteStream *stream) {} - /** - * De-serialize data from a save game stream. This should only be implemented if the - * SideFX also implements serialize(). The calling method assumes the size of the - * data read from the stream exactly equals that written in serialize(). The default - * implementation is NOP. - * - * NOTE: If this method is overridden, you MUST also override serialize() - * and needsSerialization() - * - * @param stream Save game file stream - */ - virtual void deserialize(Common::SeekableReadStream *stream) {} - /** - * If a SideFX overrides serialize() and deserialize(), this should return true - * - * @return Does the SideFX need save game serialization? - */ - virtual inline bool needsSerialization() { - return false; - } - - virtual bool stop() { - return true; - } - virtual void kill() {} - -protected: - ZVision *_engine; - uint32 _key; - SideFXType _type; - -// Static member functions -public: - -}; -} // End of namespace ZVision - -#endif // SIDEFX_H_INCLUDED diff --git a/engines/zvision/scripting/sidefx/animation_node.cpp b/engines/zvision/scripting/sidefx/animation_node.cpp deleted file mode 100644 index 07eda692c1..0000000000 --- a/engines/zvision/scripting/sidefx/animation_node.cpp +++ /dev/null @@ -1,213 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "common/scummsys.h" - -#include "zvision/scripting/sidefx/animation_node.h" - -#include "zvision/zvision.h" -#include "zvision/graphics/render_manager.h" -#include "zvision/scripting/script_manager.h" - -#include "graphics/surface.h" -#include "video/video_decoder.h" - -namespace ZVision { - -AnimationNode::AnimationNode(ZVision *engine, uint32 controlKey, const Common::String &fileName, int32 mask, int32 frate, bool disposeAfterUse) - : SideFX(engine, controlKey, SIDEFX_ANIM), - _disposeAfterUse(disposeAfterUse), - _mask(mask), - _animation(NULL) { - - _animation = engine->loadAnimation(fileName); - - if (frate > 0) { - _frmDelayOverride = (int32)(1000.0 / frate); - - // WORKAROUND: We do not allow the engine to delay more than 66 msec - // per frame (15fps max) - if (_frmDelayOverride > 66) - _frmDelayOverride = 66; - } else { - _frmDelayOverride = 0; - } -} - -AnimationNode::~AnimationNode() { - if (_animation) - delete _animation; - - _engine->getScriptManager()->setStateValue(_key, 2); - - PlayNodes::iterator it = _playList.begin(); - if (it != _playList.end()) { - _engine->getScriptManager()->setStateValue((*it).slot, 2); - - if ((*it)._scaled) { - (*it)._scaled->free(); - delete(*it)._scaled; - } - } - - _playList.clear(); -} - -bool AnimationNode::process(uint32 deltaTimeInMillis) { - ScriptManager *scriptManager = _engine->getScriptManager(); - RenderManager *renderManager = _engine->getRenderManager(); - RenderTable::RenderState renderState = renderManager->getRenderTable()->getRenderState(); - bool isPanorama = (renderState == RenderTable::PANORAMA); - int16 velocity = _engine->getMouseVelocity() + _engine->getKeyboardVelocity(); - - // Do not update animation nodes in panoramic mode while turning, if the user - // has set this option - if (scriptManager->getStateValue(StateKey_NoTurnAnim) == 1 && isPanorama && velocity) - return false; - - PlayNodes::iterator it = _playList.begin(); - if (it != _playList.end()) { - playnode *nod = &(*it); - - if (!_animation->isPlaying()) { - // The node is just beginning playback - _animation->start(); - _animation->seekToFrame(nod->start); - - nod->_delay = deltaTimeInMillis; // Force the frame to draw - if (nod->slot) - scriptManager->setStateValue(nod->slot, 1); - } else if (_animation->endOfVideo()) { - // The node has reached the end; check if we need to loop - nod->loop--; - - if (nod->loop == 0) { - if (nod->slot >= 0) - scriptManager->setStateValue(nod->slot, 2); - if (nod->_scaled) { - nod->_scaled->free(); - delete nod->_scaled; - } - _playList.erase(it); - return _disposeAfterUse; - } - - _animation->seekToFrame(nod->start); - } - - // Check if we need to draw a frame - bool needsUpdate = false; - if (_frmDelayOverride == 0) { - // If not overridden, use the VideoDecoder's check - needsUpdate = _animation->needsUpdate(); - } else { - // Otherwise, implement our own timing - nod->_delay -= deltaTimeInMillis; - - if (nod->_delay <= 0) { - nod->_delay += _frmDelayOverride; - needsUpdate = true; - } - } - - if (needsUpdate) { - const Graphics::Surface *frame = _animation->decodeNextFrame(); - - if (frame) { - uint32 dstw; - uint32 dsth; - if (isPanorama) { - dstw = nod->pos.height(); - dsth = nod->pos.width(); - } else { - dstw = nod->pos.width(); - dsth = nod->pos.height(); - } - - // We only scale down the animation to fit its frame, not up, otherwise we - // end up with distorted animations - e.g. the armor visor in location cz1e - // in Nemesis (one of the armors inside Irondune), or the planet in location - // aa10 in Nemesis (Juperon, outside the asylum). We do allow scaling up only - // when a simple 2x filter is requested (e.g. the alchemists and cup sequence - // in Nemesis) - if (frame->w > dstw || frame->h > dsth || (frame->w == dstw / 2 && frame->h == dsth / 2)) { - if (nod->_scaled) - if (nod->_scaled->w != dstw || nod->_scaled->h != dsth) { - nod->_scaled->free(); - delete nod->_scaled; - nod->_scaled = NULL; - } - - if (!nod->_scaled) { - nod->_scaled = new Graphics::Surface; - nod->_scaled->create(dstw, dsth, frame->format); - } - - renderManager->scaleBuffer(frame->getPixels(), nod->_scaled->getPixels(), frame->w, frame->h, frame->format.bytesPerPixel, dstw, dsth); - frame = nod->_scaled; - } - - if (isPanorama) { - Graphics::Surface *transposed = RenderManager::tranposeSurface(frame); - renderManager->blitSurfaceToBkg(*transposed, nod->pos.left, nod->pos.top, _mask); - transposed->free(); - delete transposed; - } else { - renderManager->blitSurfaceToBkg(*frame, nod->pos.left, nod->pos.top, _mask); - } - } - } - } - - return false; -} - -void AnimationNode::addPlayNode(int32 slot, int x, int y, int x2, int y2, int startFrame, int endFrame, int loops) { - playnode nod; - nod.loop = loops; - nod.pos = Common::Rect(x, y, x2 + 1, y2 + 1); - nod.start = startFrame; - _animation->setEndFrame(CLIP(endFrame, 0, _animation->getFrameCount() - 1)); - - nod.slot = slot; - nod._delay = 0; - nod._scaled = NULL; - _playList.push_back(nod); -} - -bool AnimationNode::stop() { - PlayNodes::iterator it = _playList.begin(); - if (it != _playList.end()) { - _engine->getScriptManager()->setStateValue((*it).slot, 2); - if ((*it)._scaled) { - (*it)._scaled->free(); - delete(*it)._scaled; - } - } - - _playList.clear(); - - // We don't need to delete, it's may be reused - return false; -} - -} // End of namespace ZVision diff --git a/engines/zvision/scripting/sidefx/animation_node.h b/engines/zvision/scripting/sidefx/animation_node.h deleted file mode 100644 index 1dc0dc71b8..0000000000 --- a/engines/zvision/scripting/sidefx/animation_node.h +++ /dev/null @@ -1,77 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#ifndef ZVISION_ANIMATION_NODE_H -#define ZVISION_ANIMATION_NODE_H - -#include "zvision/scripting/sidefx.h" -#include "common/rect.h" -#include "common/list.h" - -namespace Graphics { -struct Surface; -} - -namespace Video { - class VideoDecoder; -} - -namespace ZVision { - -class ZVision; - -class AnimationNode : public SideFX { -public: - AnimationNode(ZVision *engine, uint32 controlKey, const Common::String &fileName, int32 mask, int32 frate, bool disposeAfterUse = true); - ~AnimationNode(); - - struct playnode { - Common::Rect pos; - int32 slot; - int32 start; - int32 loop; - int32 _delay; - Graphics::Surface *_scaled; - }; - -private: - typedef Common::List PlayNodes; - - PlayNodes _playList; - - int32 _mask; - bool _disposeAfterUse; - - Video::VideoDecoder *_animation; - int32 _frmDelayOverride; - -public: - bool process(uint32 deltaTimeInMillis); - - void addPlayNode(int32 slot, int x, int y, int x2, int y2, int startFrame, int endFrame, int loops = 1); - - bool stop(); -}; - -} // End of namespace ZVision - -#endif diff --git a/engines/zvision/scripting/sidefx/distort_node.cpp b/engines/zvision/scripting/sidefx/distort_node.cpp deleted file mode 100644 index 7d25adc031..0000000000 --- a/engines/zvision/scripting/sidefx/distort_node.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "common/scummsys.h" - -#include "zvision/scripting/sidefx/distort_node.h" - -#include "zvision/zvision.h" -#include "zvision/scripting/script_manager.h" -#include "zvision/graphics/render_manager.h" -#include "zvision/graphics/render_table.h" - -#include "common/stream.h" - -namespace ZVision { - -DistortNode::DistortNode(ZVision *engine, uint32 key, int16 speed, float startAngle, float endAngle, float startLineScale, float endLineScale) - : SideFX(engine, key, SIDEFX_DISTORT) { - - _angle = _engine->getRenderManager()->getRenderTable()->getAngle(); - _linScale = _engine->getRenderManager()->getRenderTable()->getLinscale(); - - _speed = speed; - _incr = true; - _startAngle = startAngle; - _endAngle = endAngle; - _startLineScale = startLineScale; - _endLineScale = endLineScale; - - _curFrame = 1.0; - - _diffAngle = endAngle - startAngle; - _diffLinScale = endLineScale - startLineScale; - - _frmSpeed = (float)speed / 15.0; - _frames = ceil((5.0 - _frmSpeed * 2.0) / _frmSpeed); - if (_frames <= 0) - _frames = 1; - - if (_key != StateKey_NotSet) - _engine->getScriptManager()->setStateValue(_key, 1); -} - -DistortNode::~DistortNode() { - setParams(_angle, _linScale); -} - -bool DistortNode::process(uint32 deltaTimeInMillis) { - float updTime = deltaTimeInMillis / (1000.0 / 60.0); - - if (_incr) - _curFrame += updTime; - else - _curFrame -= updTime; - - if (_curFrame < 1.0) { - _curFrame = 1.0; - _incr = true; - } else if (_curFrame > _frames) { - _curFrame = _frames; - _incr = false; - } - - float diff = (1.0 / (5.0 - (_curFrame * _frmSpeed))) / (5.0 - _frmSpeed); - setParams(_startAngle + diff * _diffAngle, _startLineScale + diff * _diffLinScale); - - return false; -} - -void DistortNode::setParams(float angl, float linScale) { - RenderTable *table = _engine->getRenderManager()->getRenderTable(); - if (table->getRenderState() == RenderTable::PANORAMA) { - table->setPanoramaFoV(angl); - table->setPanoramaScale(linScale); - table->generateRenderTable(); - _engine->getRenderManager()->markDirty(); - } else if (table->getRenderState() == RenderTable::TILT) { - table->setTiltFoV(angl); - table->setTiltScale(linScale); - table->generateRenderTable(); - _engine->getRenderManager()->markDirty(); - } -} - -} // End of namespace ZVision diff --git a/engines/zvision/scripting/sidefx/distort_node.h b/engines/zvision/scripting/sidefx/distort_node.h deleted file mode 100644 index 787a69bdde..0000000000 --- a/engines/zvision/scripting/sidefx/distort_node.h +++ /dev/null @@ -1,63 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#ifndef ZVISION_DISTORT_NODE_H -#define ZVISION_DISTORT_NODE_H - -#include "zvision/scripting/sidefx.h" - -namespace ZVision { - -class ZVision; - -class DistortNode : public SideFX { -public: - DistortNode(ZVision *engine, uint32 key, int16 speed, float startAngle, float endAngle, float startLineScale, float endLineScale); - ~DistortNode(); - - bool process(uint32 deltaTimeInMillis); - -private: - int16 _speed; - float _startAngle; - float _endAngle; - float _startLineScale; - float _endLineScale; - - float _frmSpeed; - float _diffAngle; - float _diffLinScale; - bool _incr; - int16 _frames; - - float _curFrame; - - float _angle; - float _linScale; - -private: - void setParams(float angl, float linScale); -}; - -} // End of namespace ZVision - -#endif diff --git a/engines/zvision/scripting/sidefx/music_node.cpp b/engines/zvision/scripting/sidefx/music_node.cpp deleted file mode 100644 index 0cada6d748..0000000000 --- a/engines/zvision/scripting/sidefx/music_node.cpp +++ /dev/null @@ -1,248 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "common/scummsys.h" - -#include "zvision/scripting/sidefx/music_node.h" - -#include "zvision/zvision.h" -#include "zvision/scripting/script_manager.h" -#include "zvision/graphics/render_manager.h" -#include "zvision/sound/midi.h" -#include "zvision/sound/zork_raw.h" - -#include "common/stream.h" -#include "common/file.h" -#include "audio/decoders/wave.h" - -namespace ZVision { - -MusicNode::MusicNode(ZVision *engine, uint32 key, Common::String &filename, bool loop, int8 volume) - : MusicNodeBASE(engine, key, SIDEFX_AUDIO) { - _loop = loop; - _volume = volume; - _crossfade = false; - _crossfadeTarget = 0; - _crossfadeTime = 0; - _attenuate = 0; - _pantrack = false; - _pantrackPosition = 0; - _sub = NULL; - _stereo = false; - _loaded = false; - - Audio::RewindableAudioStream *audioStream = NULL; - - if (filename.contains(".wav")) { - Common::File *file = new Common::File(); - if (_engine->getSearchManager()->openFile(*file, filename)) { - audioStream = Audio::makeWAVStream(file, DisposeAfterUse::YES); - } - } else { - audioStream = makeRawZorkStream(filename, _engine); - } - - if (audioStream) { - _stereo = audioStream->isStereo(); - - if (_loop) { - Audio::LoopingAudioStream *loopingAudioStream = new Audio::LoopingAudioStream(audioStream, 0, DisposeAfterUse::YES); - _engine->_mixer->playStream(Audio::Mixer::kPlainSoundType, &_handle, loopingAudioStream, -1, _volume); - } else { - _engine->_mixer->playStream(Audio::Mixer::kPlainSoundType, &_handle, audioStream, -1, _volume); - } - - if (_key != StateKey_NotSet) - _engine->getScriptManager()->setStateValue(_key, 1); - - // Change filename.raw into filename.sub - Common::String subname = filename; - subname.setChar('s', subname.size() - 3); - subname.setChar('u', subname.size() - 2); - subname.setChar('b', subname.size() - 1); - - if (_engine->getSearchManager()->hasFile(subname)) - _sub = new Subtitle(_engine, subname); - - _loaded = true; - } -} - -MusicNode::~MusicNode() { - if (_loaded) - _engine->_mixer->stopHandle(_handle); - if (_key != StateKey_NotSet) - _engine->getScriptManager()->setStateValue(_key, 2); - if (_sub) - delete _sub; - debug(1, "MusicNode: %d destroyed\n", _key); -} - -void MusicNode::setPanTrack(int16 pos) { - if (!_stereo) { - _pantrack = true; - _pantrackPosition = pos; - setVolume(_volume); - } -} - -void MusicNode::unsetPanTrack() { - _pantrack = false; - setVolume(_volume); -} - -void MusicNode::setFade(int32 time, uint8 target) { - _crossfadeTarget = target; - _crossfadeTime = time; - _crossfade = true; -} - -bool MusicNode::process(uint32 deltaTimeInMillis) { - if (!_loaded || ! _engine->_mixer->isSoundHandleActive(_handle)) - return stop(); - else { - uint8 _newvol = _volume; - - if (_crossfade) { - if (_crossfadeTime > 0) { - if ((int32)deltaTimeInMillis > _crossfadeTime) - deltaTimeInMillis = _crossfadeTime; - _newvol += floor(((float)(_crossfadeTarget - _newvol) / (float)_crossfadeTime)) * (float)deltaTimeInMillis; - _crossfadeTime -= deltaTimeInMillis; - } else { - _crossfade = false; - _newvol = _crossfadeTarget; - } - } - - if (_pantrack || _volume != _newvol) - setVolume(_newvol); - - if (_sub && _engine->getScriptManager()->getStateValue(StateKey_Subtitles) == 1) - _sub->process(_engine->_mixer->getSoundElapsedTime(_handle) / 100); - } - return false; -} - -void MusicNode::setVolume(uint8 newVolume) { - if (!_loaded) - return; - if (_pantrack) { - int curX = _engine->getScriptManager()->getStateValue(StateKey_ViewPos); - curX -= _pantrackPosition; - int32 _width = _engine->getRenderManager()->getBkgSize().x; - if (curX < (-_width) / 2) - curX += _width; - else if (curX >= _width / 2) - curX -= _width; - - float norm = (float)curX / ((float)_width / 2.0); - float lvl = fabs(norm); - if (lvl > 0.5) - lvl = (lvl - 0.5) * 1.7; - else - lvl = 1.0; - - float bal = sin(-norm * 3.1415926) * 127.0; - - if (_engine->_mixer->isSoundHandleActive(_handle)) { - _engine->_mixer->setChannelBalance(_handle, bal); - _engine->_mixer->setChannelVolume(_handle, newVolume * lvl); - } - } else { - if (_engine->_mixer->isSoundHandleActive(_handle)) { - _engine->_mixer->setChannelBalance(_handle, 0); - _engine->_mixer->setChannelVolume(_handle, newVolume); - } - } - - _volume = newVolume; -} - -PanTrackNode::PanTrackNode(ZVision *engine, uint32 key, uint32 slot, int16 pos) - : SideFX(engine, key, SIDEFX_PANTRACK) { - _slot = slot; - - SideFX *fx = _engine->getScriptManager()->getSideFX(slot); - if (fx && fx->getType() == SIDEFX_AUDIO) { - MusicNodeBASE *mus = (MusicNodeBASE *)fx; - mus->setPanTrack(pos); - } -} - -PanTrackNode::~PanTrackNode() { - SideFX *fx = _engine->getScriptManager()->getSideFX(_slot); - if (fx && fx->getType() == SIDEFX_AUDIO) { - MusicNodeBASE *mus = (MusicNodeBASE *)fx; - mus->unsetPanTrack(); - } -} - -MusicMidiNode::MusicMidiNode(ZVision *engine, uint32 key, int8 program, int8 note, int8 volume) - : MusicNodeBASE(engine, key, SIDEFX_AUDIO) { - _volume = volume; - _prog = program; - _noteNumber = note; - _pan = 0; - - _chan = _engine->getMidiManager()->getFreeChannel(); - - if (_chan >= 0) { - _engine->getMidiManager()->setVolume(_chan, _volume); - _engine->getMidiManager()->setPan(_chan, _pan); - _engine->getMidiManager()->setProgram(_chan, _prog); - _engine->getMidiManager()->noteOn(_chan, _noteNumber, _volume); - } - - if (_key != StateKey_NotSet) - _engine->getScriptManager()->setStateValue(_key, 1); -} - -MusicMidiNode::~MusicMidiNode() { - if (_chan >= 0) { - _engine->getMidiManager()->noteOff(_chan); - } - if (_key != StateKey_NotSet) - _engine->getScriptManager()->setStateValue(_key, 2); -} - -void MusicMidiNode::setPanTrack(int16 pos) { -} - -void MusicMidiNode::unsetPanTrack() { -} - -void MusicMidiNode::setFade(int32 time, uint8 target) { -} - -bool MusicMidiNode::process(uint32 deltaTimeInMillis) { - return false; -} - -void MusicMidiNode::setVolume(uint8 newVolume) { - if (_chan >= 0) { - _engine->getMidiManager()->setVolume(_chan, newVolume); - } - _volume = newVolume; -} - -} // End of namespace ZVision diff --git a/engines/zvision/scripting/sidefx/music_node.h b/engines/zvision/scripting/sidefx/music_node.h deleted file mode 100644 index 3f1ca5cf7b..0000000000 --- a/engines/zvision/scripting/sidefx/music_node.h +++ /dev/null @@ -1,135 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#ifndef ZVISION_MUSIC_NODE_H -#define ZVISION_MUSIC_NODE_H - -#include "audio/mixer.h" -#include "zvision/scripting/sidefx.h" -#include "zvision/text/subtitles.h" - -namespace Common { -class String; -} - -namespace ZVision { - -class MusicNodeBASE : public SideFX { -public: - MusicNodeBASE(ZVision *engine, uint32 key, SideFXType type) : SideFX(engine, key, type) {} - ~MusicNodeBASE() {} - - /** - * Decrement the timer by the delta time. If the timer is finished, set the status - * in _globalState and let this node be deleted - * - * @param deltaTimeInMillis The number of milliseconds that have passed since last frame - * @return If true, the node can be deleted after process() finishes - */ - virtual bool process(uint32 deltaTimeInMillis) = 0; - - virtual void setVolume(uint8 volume) = 0; - - virtual void setPanTrack(int16 pos) = 0; - virtual void unsetPanTrack() = 0; - - virtual void setFade(int32 time, uint8 target) = 0; -}; - -class MusicNode : public MusicNodeBASE { -public: - MusicNode(ZVision *engine, uint32 key, Common::String &file, bool loop, int8 volume); - ~MusicNode(); - - /** - * Decrement the timer by the delta time. If the timer is finished, set the status - * in _globalState and let this node be deleted - * - * @param deltaTimeInMillis The number of milliseconds that have passed since last frame - * @return If true, the node can be deleted after process() finishes - */ - bool process(uint32 deltaTimeInMillis); - - void setVolume(uint8 volume); - - void setPanTrack(int16 pos); - void unsetPanTrack(); - - void setFade(int32 time, uint8 target); - -private: - bool _pantrack; - int32 _pantrackPosition; - int32 _attenuate; - uint8 _volume; - bool _loop; - bool _crossfade; - uint8 _crossfadeTarget; - int32 _crossfadeTime; - bool _stereo; - Audio::SoundHandle _handle; - Subtitle *_sub; - bool _loaded; -}; - -// Only used by Zork: Nemesis, for the flute and piano puzzles (tj4e and ve6f, as well as vr) -class MusicMidiNode : public MusicNodeBASE { -public: - MusicMidiNode(ZVision *engine, uint32 key, int8 program, int8 note, int8 volume); - ~MusicMidiNode(); - - /** - * Decrement the timer by the delta time. If the timer is finished, set the status - * in _globalState and let this node be deleted - * - * @param deltaTimeInMillis The number of milliseconds that have passed since last frame - * @return If true, the node can be deleted after process() finishes - */ - bool process(uint32 deltaTimeInMillis); - - void setVolume(uint8 volume); - - void setPanTrack(int16 pos); - void unsetPanTrack(); - - void setFade(int32 time, uint8 target); - -private: - int8 _chan; - int8 _noteNumber; - int8 _pan; - int8 _volume; - int8 _prog; -}; - -class PanTrackNode : public SideFX { -public: - PanTrackNode(ZVision *engine, uint32 key, uint32 slot, int16 pos); - ~PanTrackNode(); - -private: - uint32 _slot; -}; - -} // End of namespace ZVision - -#endif diff --git a/engines/zvision/scripting/sidefx/region_node.cpp b/engines/zvision/scripting/sidefx/region_node.cpp deleted file mode 100644 index de613d8af2..0000000000 --- a/engines/zvision/scripting/sidefx/region_node.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "common/scummsys.h" - -#include "zvision/scripting/sidefx/region_node.h" - -#include "zvision/zvision.h" -#include "zvision/scripting/script_manager.h" -#include "zvision/graphics/render_manager.h" - -namespace ZVision { - -RegionNode::RegionNode(ZVision *engine, uint32 key, Effect *effect, uint32 delay) - : SideFX(engine, key, SIDEFX_REGION) { - _effect = effect; - _delay = delay; - _timeLeft = 0; -} - -RegionNode::~RegionNode() { - _engine->getRenderManager()->deleteEffect(_key); -} - -bool RegionNode::process(uint32 deltaTimeInMillis) { - _timeLeft -= deltaTimeInMillis; - - if (_timeLeft <= 0) { - _timeLeft = _delay; - if (_effect) - _effect->update(); - } - - return false; -} - -} // End of namespace ZVision diff --git a/engines/zvision/scripting/sidefx/region_node.h b/engines/zvision/scripting/sidefx/region_node.h deleted file mode 100644 index ec716b6e3e..0000000000 --- a/engines/zvision/scripting/sidefx/region_node.h +++ /dev/null @@ -1,57 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#ifndef ZVISION_REGION_NODE_H -#define ZVISION_REGION_NODE_H - -#include "graphics/surface.h" - -#include "zvision/scripting/sidefx.h" -#include "zvision/graphics/effect.h" - -namespace ZVision { - -class ZVision; - -class RegionNode : public SideFX { -public: - RegionNode(ZVision *engine, uint32 key, Effect *effect, uint32 delay); - ~RegionNode(); - - /** - * Decrement the timer by the delta time. If the timer is finished, set the status - * in _globalState and let this node be deleted - * - * @param deltaTimeInMillis The number of milliseconds that have passed since last frame - * @return If true, the node can be deleted after process() finishes - */ - bool process(uint32 deltaTimeInMillis); - -private: - int32 _timeLeft; - uint32 _delay; - Effect *_effect; -}; - -} // End of namespace ZVision - -#endif diff --git a/engines/zvision/scripting/sidefx/syncsound_node.cpp b/engines/zvision/scripting/sidefx/syncsound_node.cpp deleted file mode 100644 index eec320bf2e..0000000000 --- a/engines/zvision/scripting/sidefx/syncsound_node.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "common/scummsys.h" - -#include "zvision/scripting/sidefx/syncsound_node.h" - -#include "zvision/zvision.h" -#include "zvision/scripting/script_manager.h" -#include "zvision/graphics/render_manager.h" -#include "zvision/sound/zork_raw.h" - -#include "common/stream.h" -#include "common/file.h" -#include "audio/decoders/wave.h" - -namespace ZVision { - -SyncSoundNode::SyncSoundNode(ZVision *engine, uint32 key, Common::String &filename, int32 syncto) - : SideFX(engine, key, SIDEFX_AUDIO) { - _syncto = syncto; - _sub = NULL; - - Audio::RewindableAudioStream *audioStream = NULL; - - if (filename.contains(".wav")) { - Common::File *file = new Common::File(); - if (_engine->getSearchManager()->openFile(*file, filename)) { - audioStream = Audio::makeWAVStream(file, DisposeAfterUse::YES); - } - } else { - audioStream = makeRawZorkStream(filename, _engine); - } - - _engine->_mixer->playStream(Audio::Mixer::kPlainSoundType, &_handle, audioStream); - - Common::String subname = filename; - subname.setChar('s', subname.size() - 3); - subname.setChar('u', subname.size() - 2); - subname.setChar('b', subname.size() - 1); - - if (_engine->getSearchManager()->hasFile(subname)) - _sub = new Subtitle(_engine, subname); -} - -SyncSoundNode::~SyncSoundNode() { - _engine->_mixer->stopHandle(_handle); - if (_sub) - delete _sub; -} - -bool SyncSoundNode::process(uint32 deltaTimeInMillis) { - if (! _engine->_mixer->isSoundHandleActive(_handle)) - return stop(); - else { - - if (_engine->getScriptManager()->getSideFX(_syncto) == NULL) - return stop(); - - if (_sub && _engine->getScriptManager()->getStateValue(StateKey_Subtitles) == 1) - _sub->process(_engine->_mixer->getSoundElapsedTime(_handle) / 100); - } - return false; -} - -} // End of namespace ZVision diff --git a/engines/zvision/scripting/sidefx/syncsound_node.h b/engines/zvision/scripting/sidefx/syncsound_node.h deleted file mode 100644 index 5961fccab9..0000000000 --- a/engines/zvision/scripting/sidefx/syncsound_node.h +++ /dev/null @@ -1,56 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#ifndef ZVISION_SYNCSOUND_NODE_H -#define ZVISION_SYNCSOUND_NODE_H - -#include "audio/mixer.h" -#include "zvision/scripting/sidefx.h" -#include "zvision/text/subtitles.h" - -namespace Common { -class String; -} - -namespace ZVision { -class SyncSoundNode : public SideFX { -public: - SyncSoundNode(ZVision *engine, uint32 key, Common::String &file, int32 syncto); - ~SyncSoundNode(); - - /** - * Decrement the timer by the delta time. If the timer is finished, set the status - * in _globalState and let this node be deleted - * - * @param deltaTimeInMillis The number of milliseconds that have passed since last frame - * @return If true, the node can be deleted after process() finishes - */ - bool process(uint32 deltaTimeInMillis); -private: - int32 _syncto; - Audio::SoundHandle _handle; - Subtitle *_sub; -}; - -} // End of namespace ZVision - -#endif diff --git a/engines/zvision/scripting/sidefx/timer_node.cpp b/engines/zvision/scripting/sidefx/timer_node.cpp deleted file mode 100644 index 170f6e7472..0000000000 --- a/engines/zvision/scripting/sidefx/timer_node.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "common/scummsys.h" - -#include "zvision/scripting/sidefx/timer_node.h" - -#include "zvision/zvision.h" -#include "zvision/scripting/script_manager.h" - -#include "common/stream.h" - -namespace ZVision { - -TimerNode::TimerNode(ZVision *engine, uint32 key, uint timeInSeconds) - : SideFX(engine, key, SIDEFX_TIMER) { - _timeLeft = 0; - - if (_engine->getGameId() == GID_NEMESIS) - _timeLeft = timeInSeconds * 1000; - else if (_engine->getGameId() == GID_GRANDINQUISITOR) - _timeLeft = timeInSeconds * 100; - - if (_key != StateKey_NotSet) - _engine->getScriptManager()->setStateValue(_key, 1); -} - -TimerNode::~TimerNode() { - if (_key != StateKey_NotSet) - _engine->getScriptManager()->setStateValue(_key, 2); - int32 timeLeft = _timeLeft / (_engine->getGameId() == GID_NEMESIS ? 1000 : 100); - if (timeLeft > 0) - _engine->getScriptManager()->setStateValue(_key, timeLeft); // If timer was stopped by stop or kill -} - -bool TimerNode::process(uint32 deltaTimeInMillis) { - _timeLeft -= deltaTimeInMillis; - - if (_timeLeft <= 0) - return stop(); - - return false; -} - -bool TimerNode::stop() { - if (_key != StateKey_NotSet) - _engine->getScriptManager()->setStateValue(_key, 2); - return true; -} - -void TimerNode::serialize(Common::WriteStream *stream) { - stream->writeUint32BE(MKTAG('T', 'I', 'M', 'R')); - stream->writeUint32LE(8); // size - stream->writeUint32LE(_key); - stream->writeUint32LE(_timeLeft); -} - -void TimerNode::deserialize(Common::SeekableReadStream *stream) { - _timeLeft = stream->readUint32LE(); -} - -} // End of namespace ZVision diff --git a/engines/zvision/scripting/sidefx/timer_node.h b/engines/zvision/scripting/sidefx/timer_node.h deleted file mode 100644 index 7a26aff251..0000000000 --- a/engines/zvision/scripting/sidefx/timer_node.h +++ /dev/null @@ -1,59 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#ifndef ZVISION_TIMER_NODE_H -#define ZVISION_TIMER_NODE_H - -#include "zvision/scripting/sidefx.h" - -namespace ZVision { - -class ZVision; - -class TimerNode : public SideFX { -public: - TimerNode(ZVision *engine, uint32 key, uint timeInSeconds); - ~TimerNode(); - - /** - * Decrement the timer by the delta time. If the timer is finished, set the status - * in _globalState and let this node be deleted - * - * @param deltaTimeInMillis The number of milliseconds that have passed since last frame - * @return If true, the node can be deleted after process() finishes - */ - bool process(uint32 deltaTimeInMillis); - void serialize(Common::WriteStream *stream); - void deserialize(Common::SeekableReadStream *stream); - inline bool needsSerialization() { - return true; - } - - bool stop(); - -private: - int32 _timeLeft; -}; - -} // End of namespace ZVision - -#endif diff --git a/engines/zvision/scripting/sidefx/ttytext_node.cpp b/engines/zvision/scripting/sidefx/ttytext_node.cpp deleted file mode 100644 index 66a27e96c5..0000000000 --- a/engines/zvision/scripting/sidefx/ttytext_node.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "common/scummsys.h" - -#include "zvision/scripting/sidefx/ttytext_node.h" - -#include "zvision/zvision.h" -#include "zvision/scripting/script_manager.h" -#include "zvision/graphics/render_manager.h" -#include "zvision/text/text.h" - -#include "common/stream.h" -#include "common/file.h" - -namespace ZVision { - -ttyTextNode::ttyTextNode(ZVision *engine, uint32 key, const Common::String &file, const Common::Rect &r, int32 delay) : - SideFX(engine, key, SIDEFX_TTYTXT), - _fnt(engine) { - _delay = delay; - _r = r; - _txtpos = 0; - _nexttime = 0; - _dx = 0; - _dy = 0; - - Common::File *infile = _engine->getSearchManager()->openFile(file); - if (infile) { - while (!infile->eos()) { - Common::String asciiLine = readWideLine(*infile); - if (asciiLine.empty()) { - continue; - } - _txtbuf += asciiLine; - } - - delete infile; - } - _img.create(_r.width(), _r.height(), _engine->_resourcePixelFormat); - _style._sharp = true; - _style.readAllStyle(_txtbuf); - _style.setFont(_fnt); - _engine->getScriptManager()->setStateValue(_key, 1); -} - -ttyTextNode::~ttyTextNode() { - _engine->getScriptManager()->setStateValue(_key, 2); - _img.free(); -} - -bool ttyTextNode::process(uint32 deltaTimeInMillis) { - _nexttime -= deltaTimeInMillis; - - if (_nexttime < 0) { - if (_txtpos < _txtbuf.size()) { - if (_txtbuf[_txtpos] == '<') { - int32 strt = _txtpos; - int32 endt = 0; - int16 ret = 0; - while (_txtbuf[_txtpos] != '>' && _txtpos < _txtbuf.size()) - _txtpos++; - endt = _txtpos; - if (strt != -1) - if ((endt - strt - 1) > 0) - ret = _style.parseStyle(_txtbuf.c_str() + strt + 1, endt - strt - 1); - - if (ret & (TXT_RET_FNTCHG | TXT_RET_FNTSTL | TXT_RET_NEWLN)) { - if (ret & TXT_RET_FNTCHG) - _style.setFont(_fnt); - if (ret & TXT_RET_FNTSTL) - _style.setFontStyle(_fnt); - - if (ret & TXT_RET_NEWLN) - newline(); - } - - if (ret & TXT_RET_HASSTBOX) { - Common::String buf; - buf = Common::String::format("%d", _engine->getScriptManager()->getStateValue(_style._statebox)); - - for (uint8 j = 0; j < buf.size(); j++) - outchar(buf[j]); - } - - _txtpos++; - } else { - int8 charsz = getUtf8CharSize(_txtbuf[_txtpos]); - - uint16 chr = readUtf8Char(_txtbuf.c_str() + _txtpos); - - if (chr == ' ') { - uint32 i = _txtpos + charsz; - uint16 width = _fnt.getCharWidth(chr); - - while (i < _txtbuf.size() && _txtbuf[i] != ' ' && _txtbuf[i] != '<') { - - int8 chsz = getUtf8CharSize(_txtbuf[i]); - uint16 uchr = readUtf8Char(_txtbuf.c_str() + _txtpos); - - width += _fnt.getCharWidth(uchr); - - i += chsz; - } - - if (_dx + width > _r.width()) - newline(); - else - outchar(chr); - } else - outchar(chr); - - _txtpos += charsz; - } - _nexttime = _delay; - _engine->getRenderManager()->blitSurfaceToBkg(_img, _r.left, _r.top); - } else - return stop(); - } - - return false; -} - -void ttyTextNode::scroll() { - int32 scrl = 0; - while (_dy - scrl > _r.height() - _fnt.getFontHeight()) - scrl += _fnt.getFontHeight(); - int8 *pixels = (int8 *)_img.getPixels(); - for (uint16 h = scrl; h < _img.h; h++) - memcpy(pixels + _img.pitch * (h - scrl), pixels + _img.pitch * h, _img.pitch); - - _img.fillRect(Common::Rect(0, _img.h - scrl, _img.w, _img.h), 0); - _dy -= scrl; -} - -void ttyTextNode::newline() { - _dy += _fnt.getFontHeight(); - _dx = 0; -} - -void ttyTextNode::outchar(uint16 chr) { - uint32 clr = _engine->_resourcePixelFormat.RGBToColor(_style._red, _style._green, _style._blue); - - if (_dx + _fnt.getCharWidth(chr) > _r.width()) - newline(); - - if (_dy + _fnt.getFontHeight() >= _r.height()) - scroll(); - - _fnt.drawChar(&_img, chr, _dx, _dy, clr); - - _dx += _fnt.getCharWidth(chr); -} - -} // End of namespace ZVision diff --git a/engines/zvision/scripting/sidefx/ttytext_node.h b/engines/zvision/scripting/sidefx/ttytext_node.h deleted file mode 100644 index 26d9be8e77..0000000000 --- a/engines/zvision/scripting/sidefx/ttytext_node.h +++ /dev/null @@ -1,73 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#ifndef ZVISION_TTYTEXT_NODE_H -#define ZVISION_TTYTEXT_NODE_H - -#include "common/rect.h" -#include "graphics/surface.h" - -#include "zvision/scripting/sidefx.h" -#include "zvision/text/text.h" -#include "zvision/text/truetype_font.h" - -namespace Common { -class String; -} - -namespace ZVision { -class ttyTextNode : public SideFX { -public: - ttyTextNode(ZVision *engine, uint32 key, const Common::String &file, const Common::Rect &r, int32 delay); - ~ttyTextNode(); - - /** - * Decrement the timer by the delta time. If the timer is finished, set the status - * in _globalState and let this node be deleted - * - * @param deltaTimeInMillis The number of milliseconds that have passed since last frame - * @return If true, the node can be deleted after process() finishes - */ - bool process(uint32 deltaTimeInMillis); -private: - Common::Rect _r; - - cTxtStyle _style; - StyledTTFont _fnt; - Common::String _txtbuf; - uint32 _txtpos; - - int32 _delay; - int32 _nexttime; - Graphics::Surface _img; - int16 _dx; - int16 _dy; -private: - - void newline(); - void scroll(); - void outchar(uint16 chr); -}; - -} // End of namespace ZVision - -#endif -- cgit v1.2.3 From 1f5736a9020796e6986a15ea4d3b627b81233241 Mon Sep 17 00:00:00 2001 From: RichieSams Date: Tue, 30 Dec 2014 01:19:54 -0600 Subject: ZVISION: Update function documentation to represent the changes to the internal pixel format Aka: We keep everything as 555, and only convert to 565 before we send everything to the backend --- engines/zvision/graphics/render_manager.h | 6 +- engines/zvision/zvision.cpp | 720 +++++++++++++++--------------- 2 files changed, 362 insertions(+), 364 deletions(-) (limited to 'engines') diff --git a/engines/zvision/graphics/render_manager.h b/engines/zvision/graphics/render_manager.h index 9002d66b47..c22f9a78c9 100644 --- a/engines/zvision/graphics/render_manager.h +++ b/engines/zvision/graphics/render_manager.h @@ -277,8 +277,7 @@ public: void prepareBackground(); /** - * Reads an image file pixel data into a Surface buffer. In the process - * it converts the pixel data from RGB 555 to RGB 565. Also, if the image + * Reads an image file pixel data into a Surface buffer. Also, if the image * is transposed, it will un-transpose the pixel data. The function will * call destination::create() if the dimensions of destination do not match * up with the dimensions of the image. @@ -289,8 +288,7 @@ public: void readImageToSurface(const Common::String &fileName, Graphics::Surface &destination); /** - * Reads an image file pixel data into a Surface buffer. In the process - * it converts the pixel data from RGB 555 to RGB 565. Also, if the image + * Reads an image file pixel data into a Surface buffer. Also, if the image * is transposed, it will un-transpose the pixel data. The function will * call destination::create() if the dimensions of destination do not match * up with the dimensions of the image. diff --git a/engines/zvision/zvision.cpp b/engines/zvision/zvision.cpp index 10e0aaedc4..a70f9d8e39 100644 --- a/engines/zvision/zvision.cpp +++ b/engines/zvision/zvision.cpp @@ -1,361 +1,361 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "common/scummsys.h" - -#include "zvision/zvision.h" -#include "zvision/core/console.h" -#include "zvision/scripting/script_manager.h" -#include "zvision/graphics/render_manager.h" -#include "zvision/graphics/cursors/cursor_manager.h" -#include "zvision/file/save_manager.h" -#include "zvision/text/string_manager.h" -#include "zvision/detection.h" -#include "zvision/scripting/menu.h" -#include "zvision/file/search_manager.h" -#include "zvision/text/text.h" -#include "zvision/text/truetype_font.h" -#include "zvision/sound/midi.h" -#include "zvision/file/zfs_archive.h" - -#include "common/config-manager.h" -#include "common/str.h" -#include "common/debug.h" -#include "common/debug-channels.h" -#include "common/textconsole.h" -#include "common/error.h" -#include "common/system.h" -#include "common/file.h" - -#include "gui/message.h" -#include "engines/util.h" -#include "audio/mixer.h" - -namespace ZVision { - -#define ZVISION_SETTINGS_KEYS_COUNT 11 - -struct zvisionIniSettings { - const char *name; - int16 slot; - int16 defaultValue; // -1: use the bool value - bool defaultBoolValue; - bool allowEditing; -} settingsKeys[ZVISION_SETTINGS_KEYS_COUNT] = { - // Hardcoded settings - {"countrycode", StateKey_CountryCode, 0, false, false}, // always 0 = US, subtitles are shown for codes 0 - 4, unused - {"lineskipvideo", StateKey_VideoLineSkip, 0, false, false}, // video line skip, 0 = default, 1 = always, 2 = pixel double when possible, unused - {"installlevel", StateKey_InstallLevel, 0, false, false}, // 0 = full, checked by universe.scr - {"highquality", StateKey_HighQuality, -1, true, false}, // high panorama quality, unused - {"qsoundenabled", StateKey_Qsound, -1, true, false}, // 1 = enable QSound - TODO: not supported yet - {"debugcheats", StateKey_DebugCheats, -1, true, false}, // always start with the GOxxxx cheat enabled - // Editable settings - {"keyboardturnspeed", StateKey_KbdRotateSpeed, 5, false, true}, - {"panarotatespeed", StateKey_RotateSpeed, 540, false, true}, // checked by universe.scr - {"noanimwhileturning", StateKey_NoTurnAnim, -1, false, true}, // toggle playing animations during pana rotation - {"venusenabled", StateKey_VenusEnable, -1, true, true}, - {"subtitles", StateKey_Subtitles, -1, true, true} -}; - -ZVision::ZVision(OSystem *syst, const ZVisionGameDescription *gameDesc) - : Engine(syst), - _gameDescription(gameDesc), - _resourcePixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0), /* RGB 555 */ - _screenPixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0), /* RGB 565 */ - _desiredFrameTime(33), /* ~30 fps */ - _clock(_system), - _scriptManager(nullptr), - _renderManager(nullptr), - _saveManager(nullptr), - _stringManager(nullptr), - _cursorManager(nullptr), - _midiManager(nullptr), - _rnd(nullptr), - _console(nullptr), - _menu(nullptr), - _searchManager(nullptr), - _textRenderer(nullptr), - _doubleFPS(false), - _audioId(0), - _frameRenderDelay(2), - _keyboardVelocity(0), - _mouseVelocity(0), - _videoIsPlaying(false), - _renderedFrameCount(0), - _fps(0) { - - debug(1, "ZVision::ZVision"); - - uint16 workingWindowWidth = (gameDesc->gameId == GID_NEMESIS) ? ZNM_WORKING_WINDOW_WIDTH : ZGI_WORKING_WINDOW_WIDTH; - uint16 workingWindowHeight = (gameDesc->gameId == GID_NEMESIS) ? ZNM_WORKING_WINDOW_HEIGHT : ZGI_WORKING_WINDOW_HEIGHT; - _workingWindow = Common::Rect( - (WINDOW_WIDTH - workingWindowWidth) / 2, - (WINDOW_HEIGHT - workingWindowHeight) / 2, - ((WINDOW_WIDTH - workingWindowWidth) / 2) + workingWindowWidth, - ((WINDOW_HEIGHT - workingWindowHeight) / 2) + workingWindowHeight - ); - - memset(_cheatBuffer, 0, sizeof(_cheatBuffer)); -} - -ZVision::~ZVision() { - debug(1, "ZVision::~ZVision"); - - // Dispose of resources - delete _console; - delete _cursorManager; - delete _stringManager; - delete _saveManager; - delete _scriptManager; - delete _renderManager; // should be deleted after the script manager - delete _rnd; - delete _midiManager; - - getTimerManager()->removeTimerProc(&fpsTimerCallback); - - // Remove all of our debug levels - DebugMan.clearAllDebugChannels(); -} - -void ZVision::registerDefaultSettings() { - for (int i = 0; i < ZVISION_SETTINGS_KEYS_COUNT; i++) { - if (settingsKeys[i].allowEditing) { - if (settingsKeys[i].defaultValue >= 0) - ConfMan.registerDefault(settingsKeys[i].name, settingsKeys[i].defaultValue); - else - ConfMan.registerDefault(settingsKeys[i].name, settingsKeys[i].defaultBoolValue); - } - } - - ConfMan.registerDefault("originalsaveload", false); - ConfMan.registerDefault("doublefps", false); -} - -void ZVision::loadSettings() { - int16 value = 0; - bool boolValue = false; - - for (int i = 0; i < ZVISION_SETTINGS_KEYS_COUNT; i++) { - if (settingsKeys[i].defaultValue >= 0) { - value = (settingsKeys[i].allowEditing) ? ConfMan.getInt(settingsKeys[i].name) : settingsKeys[i].defaultValue; - } else { - boolValue = (settingsKeys[i].allowEditing) ? ConfMan.getBool(settingsKeys[i].name) : settingsKeys[i].defaultBoolValue; - value = (boolValue) ? 1 : 0; - } - - _scriptManager->setStateValue(settingsKeys[i].slot, value); - } - - if (getGameId() == GID_NEMESIS) - _scriptManager->setStateValue(StateKey_ExecScopeStyle, 1); - else - _scriptManager->setStateValue(StateKey_ExecScopeStyle, 0); -} - -void ZVision::saveSettings() { - for (int i = 0; i < ZVISION_SETTINGS_KEYS_COUNT; i++) { - if (settingsKeys[i].allowEditing) { - if (settingsKeys[i].defaultValue >= 0) - ConfMan.setInt(settingsKeys[i].name, _scriptManager->getStateValue(settingsKeys[i].slot)); - else - ConfMan.setBool(settingsKeys[i].name, (_scriptManager->getStateValue(settingsKeys[i].slot) == 1)); - } - } - - ConfMan.flushToDisk(); -} - -void ZVision::initialize() { - const Common::FSNode gameDataDir(ConfMan.get("path")); - - _searchManager = new SearchManager(ConfMan.get("path"), 6); - - _searchManager->addDir("FONTS"); - _searchManager->addDir("addon"); - - if (_gameDescription->gameId == GID_GRANDINQUISITOR) { - _searchManager->loadZix("INQUIS.ZIX"); - _searchManager->addPatch("C000H01Q.RAW", "C000H01Q.SRC"); - _searchManager->addPatch("CM00H01Q.RAW", "CM00H01Q.SRC"); - _searchManager->addPatch("DM00H01Q.RAW", "DM00H01Q.SRC"); - _searchManager->addPatch("E000H01Q.RAW", "E000H01Q.SRC"); - _searchManager->addPatch("EM00H50Q.RAW", "EM00H50Q.SRC"); - _searchManager->addPatch("GJNPH65P.RAW", "GJNPH65P.SRC"); - _searchManager->addPatch("GJNPH72P.RAW", "GJNPH72P.SRC"); - _searchManager->addPatch("H000H01Q.RAW", "H000H01Q.SRC"); - _searchManager->addPatch("M000H01Q.RAW", "M000H01Q.SRC"); - _searchManager->addPatch("P000H01Q.RAW", "P000H01Q.SRC"); - _searchManager->addPatch("Q000H01Q.RAW", "Q000H01Q.SRC"); - _searchManager->addPatch("SW00H01Q.RAW", "SW00H01Q.SRC"); - _searchManager->addPatch("T000H01Q.RAW", "T000H01Q.SRC"); - _searchManager->addPatch("U000H01Q.RAW", "U000H01Q.SRC"); - } else if (_gameDescription->gameId == GID_NEMESIS) - _searchManager->loadZix("NEMESIS.ZIX"); - - initGraphics(WINDOW_WIDTH, WINDOW_HEIGHT, true, &_screenPixelFormat); - - // Register random source - _rnd = new Common::RandomSource("zvision"); - - // Create managers - _scriptManager = new ScriptManager(this); - _renderManager = new RenderManager(this, WINDOW_WIDTH, WINDOW_HEIGHT, _workingWindow, _resourcePixelFormat, _doubleFPS); - _saveManager = new SaveManager(this); - _stringManager = new StringManager(this); - _cursorManager = new CursorManager(this, _resourcePixelFormat); - _textRenderer = new TextRenderer(this); - _midiManager = new MidiManager(); - - if (_gameDescription->gameId == GID_GRANDINQUISITOR) - _menu = new MenuZGI(this); - else - _menu = new MenuNemesis(this); - - // Initialize the managers - _cursorManager->initialize(); - _scriptManager->initialize(); - _stringManager->initialize(_gameDescription->gameId); - - registerDefaultSettings(); - - loadSettings(); - - // Create debugger console. It requires GFX to be initialized - _console = new Console(this); - _doubleFPS = ConfMan.getBool("doublefps"); - - // Initialize FPS timer callback - getTimerManager()->installTimerProc(&fpsTimerCallback, 1000000, this, "zvisionFPS"); -} - -Common::Error ZVision::run() { - initialize(); - - // Check if a saved game is to be loaded from the launcher - if (ConfMan.hasKey("save_slot")) - _saveManager->loadGame(ConfMan.getInt("save_slot")); - - // Before starting, make absolutely sure that the user has copied the needed fonts +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "common/scummsys.h" + +#include "zvision/zvision.h" +#include "zvision/core/console.h" +#include "zvision/scripting/script_manager.h" +#include "zvision/graphics/render_manager.h" +#include "zvision/graphics/cursors/cursor_manager.h" +#include "zvision/file/save_manager.h" +#include "zvision/text/string_manager.h" +#include "zvision/detection.h" +#include "zvision/scripting/menu.h" +#include "zvision/file/search_manager.h" +#include "zvision/text/text.h" +#include "zvision/text/truetype_font.h" +#include "zvision/sound/midi.h" +#include "zvision/file/zfs_archive.h" + +#include "common/config-manager.h" +#include "common/str.h" +#include "common/debug.h" +#include "common/debug-channels.h" +#include "common/textconsole.h" +#include "common/error.h" +#include "common/system.h" +#include "common/file.h" + +#include "gui/message.h" +#include "engines/util.h" +#include "audio/mixer.h" + +namespace ZVision { + +#define ZVISION_SETTINGS_KEYS_COUNT 11 + +struct zvisionIniSettings { + const char *name; + int16 slot; + int16 defaultValue; // -1: use the bool value + bool defaultBoolValue; + bool allowEditing; +} settingsKeys[ZVISION_SETTINGS_KEYS_COUNT] = { + // Hardcoded settings + {"countrycode", StateKey_CountryCode, 0, false, false}, // always 0 = US, subtitles are shown for codes 0 - 4, unused + {"lineskipvideo", StateKey_VideoLineSkip, 0, false, false}, // video line skip, 0 = default, 1 = always, 2 = pixel double when possible, unused + {"installlevel", StateKey_InstallLevel, 0, false, false}, // 0 = full, checked by universe.scr + {"highquality", StateKey_HighQuality, -1, true, false}, // high panorama quality, unused + {"qsoundenabled", StateKey_Qsound, -1, true, false}, // 1 = enable QSound - TODO: not supported yet + {"debugcheats", StateKey_DebugCheats, -1, true, false}, // always start with the GOxxxx cheat enabled + // Editable settings + {"keyboardturnspeed", StateKey_KbdRotateSpeed, 5, false, true}, + {"panarotatespeed", StateKey_RotateSpeed, 540, false, true}, // checked by universe.scr + {"noanimwhileturning", StateKey_NoTurnAnim, -1, false, true}, // toggle playing animations during pana rotation + {"venusenabled", StateKey_VenusEnable, -1, true, true}, + {"subtitles", StateKey_Subtitles, -1, true, true} +}; + +ZVision::ZVision(OSystem *syst, const ZVisionGameDescription *gameDesc) + : Engine(syst), + _gameDescription(gameDesc), + _resourcePixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0), /* RGB 555 */ + _screenPixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0), /* RGB 565 */ + _desiredFrameTime(33), /* ~30 fps */ + _clock(_system), + _scriptManager(nullptr), + _renderManager(nullptr), + _saveManager(nullptr), + _stringManager(nullptr), + _cursorManager(nullptr), + _midiManager(nullptr), + _rnd(nullptr), + _console(nullptr), + _menu(nullptr), + _searchManager(nullptr), + _textRenderer(nullptr), + _doubleFPS(false), + _audioId(0), + _frameRenderDelay(2), + _keyboardVelocity(0), + _mouseVelocity(0), + _videoIsPlaying(false), + _renderedFrameCount(0), + _fps(0) { + + debug(1, "ZVision::ZVision"); + + uint16 workingWindowWidth = (gameDesc->gameId == GID_NEMESIS) ? ZNM_WORKING_WINDOW_WIDTH : ZGI_WORKING_WINDOW_WIDTH; + uint16 workingWindowHeight = (gameDesc->gameId == GID_NEMESIS) ? ZNM_WORKING_WINDOW_HEIGHT : ZGI_WORKING_WINDOW_HEIGHT; + _workingWindow = Common::Rect( + (WINDOW_WIDTH - workingWindowWidth) / 2, + (WINDOW_HEIGHT - workingWindowHeight) / 2, + ((WINDOW_WIDTH - workingWindowWidth) / 2) + workingWindowWidth, + ((WINDOW_HEIGHT - workingWindowHeight) / 2) + workingWindowHeight + ); + + memset(_cheatBuffer, 0, sizeof(_cheatBuffer)); +} + +ZVision::~ZVision() { + debug(1, "ZVision::~ZVision"); + + // Dispose of resources + delete _console; + delete _cursorManager; + delete _stringManager; + delete _saveManager; + delete _scriptManager; + delete _renderManager; // should be deleted after the script manager + delete _rnd; + delete _midiManager; + + getTimerManager()->removeTimerProc(&fpsTimerCallback); + + // Remove all of our debug levels + DebugMan.clearAllDebugChannels(); +} + +void ZVision::registerDefaultSettings() { + for (int i = 0; i < ZVISION_SETTINGS_KEYS_COUNT; i++) { + if (settingsKeys[i].allowEditing) { + if (settingsKeys[i].defaultValue >= 0) + ConfMan.registerDefault(settingsKeys[i].name, settingsKeys[i].defaultValue); + else + ConfMan.registerDefault(settingsKeys[i].name, settingsKeys[i].defaultBoolValue); + } + } + + ConfMan.registerDefault("originalsaveload", false); + ConfMan.registerDefault("doublefps", false); +} + +void ZVision::loadSettings() { + int16 value = 0; + bool boolValue = false; + + for (int i = 0; i < ZVISION_SETTINGS_KEYS_COUNT; i++) { + if (settingsKeys[i].defaultValue >= 0) { + value = (settingsKeys[i].allowEditing) ? ConfMan.getInt(settingsKeys[i].name) : settingsKeys[i].defaultValue; + } else { + boolValue = (settingsKeys[i].allowEditing) ? ConfMan.getBool(settingsKeys[i].name) : settingsKeys[i].defaultBoolValue; + value = (boolValue) ? 1 : 0; + } + + _scriptManager->setStateValue(settingsKeys[i].slot, value); + } + + if (getGameId() == GID_NEMESIS) + _scriptManager->setStateValue(StateKey_ExecScopeStyle, 1); + else + _scriptManager->setStateValue(StateKey_ExecScopeStyle, 0); +} + +void ZVision::saveSettings() { + for (int i = 0; i < ZVISION_SETTINGS_KEYS_COUNT; i++) { + if (settingsKeys[i].allowEditing) { + if (settingsKeys[i].defaultValue >= 0) + ConfMan.setInt(settingsKeys[i].name, _scriptManager->getStateValue(settingsKeys[i].slot)); + else + ConfMan.setBool(settingsKeys[i].name, (_scriptManager->getStateValue(settingsKeys[i].slot) == 1)); + } + } + + ConfMan.flushToDisk(); +} + +void ZVision::initialize() { + const Common::FSNode gameDataDir(ConfMan.get("path")); + + _searchManager = new SearchManager(ConfMan.get("path"), 6); + + _searchManager->addDir("FONTS"); + _searchManager->addDir("addon"); + + if (_gameDescription->gameId == GID_GRANDINQUISITOR) { + _searchManager->loadZix("INQUIS.ZIX"); + _searchManager->addPatch("C000H01Q.RAW", "C000H01Q.SRC"); + _searchManager->addPatch("CM00H01Q.RAW", "CM00H01Q.SRC"); + _searchManager->addPatch("DM00H01Q.RAW", "DM00H01Q.SRC"); + _searchManager->addPatch("E000H01Q.RAW", "E000H01Q.SRC"); + _searchManager->addPatch("EM00H50Q.RAW", "EM00H50Q.SRC"); + _searchManager->addPatch("GJNPH65P.RAW", "GJNPH65P.SRC"); + _searchManager->addPatch("GJNPH72P.RAW", "GJNPH72P.SRC"); + _searchManager->addPatch("H000H01Q.RAW", "H000H01Q.SRC"); + _searchManager->addPatch("M000H01Q.RAW", "M000H01Q.SRC"); + _searchManager->addPatch("P000H01Q.RAW", "P000H01Q.SRC"); + _searchManager->addPatch("Q000H01Q.RAW", "Q000H01Q.SRC"); + _searchManager->addPatch("SW00H01Q.RAW", "SW00H01Q.SRC"); + _searchManager->addPatch("T000H01Q.RAW", "T000H01Q.SRC"); + _searchManager->addPatch("U000H01Q.RAW", "U000H01Q.SRC"); + } else if (_gameDescription->gameId == GID_NEMESIS) + _searchManager->loadZix("NEMESIS.ZIX"); + + initGraphics(WINDOW_WIDTH, WINDOW_HEIGHT, true, &_screenPixelFormat); + + // Register random source + _rnd = new Common::RandomSource("zvision"); + + // Create managers + _scriptManager = new ScriptManager(this); + _renderManager = new RenderManager(this, WINDOW_WIDTH, WINDOW_HEIGHT, _workingWindow, _resourcePixelFormat, _doubleFPS); + _saveManager = new SaveManager(this); + _stringManager = new StringManager(this); + _cursorManager = new CursorManager(this, _resourcePixelFormat); + _textRenderer = new TextRenderer(this); + _midiManager = new MidiManager(); + + if (_gameDescription->gameId == GID_GRANDINQUISITOR) + _menu = new MenuZGI(this); + else + _menu = new MenuNemesis(this); + + // Initialize the managers + _cursorManager->initialize(); + _scriptManager->initialize(); + _stringManager->initialize(_gameDescription->gameId); + + registerDefaultSettings(); + + loadSettings(); + + // Create debugger console. It requires GFX to be initialized + _console = new Console(this); + _doubleFPS = ConfMan.getBool("doublefps"); + + // Initialize FPS timer callback + getTimerManager()->installTimerProc(&fpsTimerCallback, 1000000, this, "zvisionFPS"); +} + +Common::Error ZVision::run() { + initialize(); + + // Check if a saved game is to be loaded from the launcher + if (ConfMan.hasKey("save_slot")) + _saveManager->loadGame(ConfMan.getInt("save_slot")); + + // Before starting, make absolutely sure that the user has copied the needed fonts if (!Common::File::exists("arial.ttf") && !Common::File::exists("FreeSans.ttf") && !_searchManager->hasFile("arial.ttf") && !_searchManager->hasFile("FreeSans.ttf") ) { - GUI::MessageDialog dialog( - "Before playing this game, you'll need to copy the required " - "fonts into ScummVM's extras directory, or into the game directory. " - "On Windows, you'll need the following font files from the Windows " - "font directory: Times New Roman, Century Schoolbook, Garamond, " - "Courier New and Arial. Alternatively, you can download the GNU " - "FreeFont package. You'll need all the fonts from that package, " - "i.e., FreeMono, FreeSans and FreeSerif." - ); - dialog.runModal(); - quitGame(); - return Common::kUnknownError; - } - - // Main loop - while (!shouldQuit()) { - _clock.update(); - uint32 currentTime = _clock.getLastMeasuredTime(); - uint32 deltaTime = _clock.getDeltaTime(); - - _cursorManager->setItemID(_scriptManager->getStateValue(StateKey_InventoryItem)); - - processEvents(); - _renderManager->updateRotation(); - - _scriptManager->update(deltaTime); - _menu->process(deltaTime); - - // Render the backBuffer to the screen - _renderManager->prepareBackground(); - _renderManager->renderMenuToScreen(); - _renderManager->processSubs(deltaTime); - _renderManager->renderSceneToScreen(); - - // Update the screen - if (canRender()) { - _system->updateScreen(); - _renderedFrameCount++; - } else { - _frameRenderDelay--; - } - - // Calculate the frame delay based off a desired frame time - int delay = _desiredFrameTime - int32(_system->getMillis() - currentTime); - // Ensure non-negative - delay = delay < 0 ? 0 : delay; - - if (_doubleFPS) { - delay >>= 1; - } - - if (canSaveGameStateCurrently() && shouldPerformAutoSave(_saveManager->getLastSaveTime())) { - _saveManager->autoSave(); - } - - _system->delayMillis(delay); - } - - return Common::kNoError; -} - -void ZVision::pauseEngineIntern(bool pause) { - _mixer->pauseAll(pause); - - if (pause) { - _clock.stop(); - } else { - _clock.start(); - } -} - -Common::String ZVision::generateSaveFileName(uint slot) { - return Common::String::format("%s.%03u", _targetName.c_str(), slot); -} - -void ZVision::setRenderDelay(uint delay) { - _frameRenderDelay = delay; -} - -bool ZVision::canRender() { - return _frameRenderDelay <= 0; -} - -GUI::Debugger *ZVision::getDebugger() { - return _console; -} - -void ZVision::syncSoundSettings() { - Engine::syncSoundSettings(); - - _scriptManager->setStateValue(StateKey_Subtitles, ConfMan.getBool("subtitles") ? 1 : 0); -} - -void ZVision::fpsTimerCallback(void *refCon) { - ((ZVision *)refCon)->fpsTimer(); -} - -void ZVision::fpsTimer() { - _fps = _renderedFrameCount; - _renderedFrameCount = 0; -} - -} // End of namespace ZVision + GUI::MessageDialog dialog( + "Before playing this game, you'll need to copy the required " + "fonts into ScummVM's extras directory, or into the game directory. " + "On Windows, you'll need the following font files from the Windows " + "font directory: Times New Roman, Century Schoolbook, Garamond, " + "Courier New and Arial. Alternatively, you can download the GNU " + "FreeFont package. You'll need all the fonts from that package, " + "i.e., FreeMono, FreeSans and FreeSerif." + ); + dialog.runModal(); + quitGame(); + return Common::kUnknownError; + } + + // Main loop + while (!shouldQuit()) { + _clock.update(); + uint32 currentTime = _clock.getLastMeasuredTime(); + uint32 deltaTime = _clock.getDeltaTime(); + + _cursorManager->setItemID(_scriptManager->getStateValue(StateKey_InventoryItem)); + + processEvents(); + _renderManager->updateRotation(); + + _scriptManager->update(deltaTime); + _menu->process(deltaTime); + + // Render the backBuffer to the screen + _renderManager->prepareBackground(); + _renderManager->renderMenuToScreen(); + _renderManager->processSubs(deltaTime); + _renderManager->renderSceneToScreen(); + + // Update the screen + if (canRender()) { + _system->updateScreen(); + _renderedFrameCount++; + } else { + _frameRenderDelay--; + } + + // Calculate the frame delay based off a desired frame time + int delay = _desiredFrameTime - int32(_system->getMillis() - currentTime); + // Ensure non-negative + delay = delay < 0 ? 0 : delay; + + if (_doubleFPS) { + delay >>= 1; + } + + if (canSaveGameStateCurrently() && shouldPerformAutoSave(_saveManager->getLastSaveTime())) { + _saveManager->autoSave(); + } + + _system->delayMillis(delay); + } + + return Common::kNoError; +} + +void ZVision::pauseEngineIntern(bool pause) { + _mixer->pauseAll(pause); + + if (pause) { + _clock.stop(); + } else { + _clock.start(); + } +} + +Common::String ZVision::generateSaveFileName(uint slot) { + return Common::String::format("%s.%03u", _targetName.c_str(), slot); +} + +void ZVision::setRenderDelay(uint delay) { + _frameRenderDelay = delay; +} + +bool ZVision::canRender() { + return _frameRenderDelay <= 0; +} + +GUI::Debugger *ZVision::getDebugger() { + return _console; +} + +void ZVision::syncSoundSettings() { + Engine::syncSoundSettings(); + + _scriptManager->setStateValue(StateKey_Subtitles, ConfMan.getBool("subtitles") ? 1 : 0); +} + +void ZVision::fpsTimerCallback(void *refCon) { + ((ZVision *)refCon)->fpsTimer(); +} + +void ZVision::fpsTimer() { + _fps = _renderedFrameCount; + _renderedFrameCount = 0; +} + +} // End of namespace ZVision -- cgit v1.2.3 From df605069552d680e203b7e16f3bcd0fb31825c2c Mon Sep 17 00:00:00 2001 From: RichieSams Date: Tue, 30 Dec 2014 01:51:22 -0600 Subject: ZVISION: Restore LF line ending that was accidentally changed in 1f5736a9020796e6986a15ea4d3b627b81233241 --- engines/zvision/zvision.cpp | 722 ++++++++++++++++++++++---------------------- 1 file changed, 361 insertions(+), 361 deletions(-) (limited to 'engines') diff --git a/engines/zvision/zvision.cpp b/engines/zvision/zvision.cpp index a70f9d8e39..54991aced3 100644 --- a/engines/zvision/zvision.cpp +++ b/engines/zvision/zvision.cpp @@ -1,361 +1,361 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "common/scummsys.h" - -#include "zvision/zvision.h" -#include "zvision/core/console.h" -#include "zvision/scripting/script_manager.h" -#include "zvision/graphics/render_manager.h" -#include "zvision/graphics/cursors/cursor_manager.h" -#include "zvision/file/save_manager.h" -#include "zvision/text/string_manager.h" -#include "zvision/detection.h" -#include "zvision/scripting/menu.h" -#include "zvision/file/search_manager.h" -#include "zvision/text/text.h" -#include "zvision/text/truetype_font.h" -#include "zvision/sound/midi.h" -#include "zvision/file/zfs_archive.h" - -#include "common/config-manager.h" -#include "common/str.h" -#include "common/debug.h" -#include "common/debug-channels.h" -#include "common/textconsole.h" -#include "common/error.h" -#include "common/system.h" -#include "common/file.h" - -#include "gui/message.h" -#include "engines/util.h" -#include "audio/mixer.h" - -namespace ZVision { - -#define ZVISION_SETTINGS_KEYS_COUNT 11 - -struct zvisionIniSettings { - const char *name; - int16 slot; - int16 defaultValue; // -1: use the bool value - bool defaultBoolValue; - bool allowEditing; -} settingsKeys[ZVISION_SETTINGS_KEYS_COUNT] = { - // Hardcoded settings - {"countrycode", StateKey_CountryCode, 0, false, false}, // always 0 = US, subtitles are shown for codes 0 - 4, unused - {"lineskipvideo", StateKey_VideoLineSkip, 0, false, false}, // video line skip, 0 = default, 1 = always, 2 = pixel double when possible, unused - {"installlevel", StateKey_InstallLevel, 0, false, false}, // 0 = full, checked by universe.scr - {"highquality", StateKey_HighQuality, -1, true, false}, // high panorama quality, unused - {"qsoundenabled", StateKey_Qsound, -1, true, false}, // 1 = enable QSound - TODO: not supported yet - {"debugcheats", StateKey_DebugCheats, -1, true, false}, // always start with the GOxxxx cheat enabled - // Editable settings - {"keyboardturnspeed", StateKey_KbdRotateSpeed, 5, false, true}, - {"panarotatespeed", StateKey_RotateSpeed, 540, false, true}, // checked by universe.scr - {"noanimwhileturning", StateKey_NoTurnAnim, -1, false, true}, // toggle playing animations during pana rotation - {"venusenabled", StateKey_VenusEnable, -1, true, true}, - {"subtitles", StateKey_Subtitles, -1, true, true} -}; - -ZVision::ZVision(OSystem *syst, const ZVisionGameDescription *gameDesc) - : Engine(syst), - _gameDescription(gameDesc), - _resourcePixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0), /* RGB 555 */ - _screenPixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0), /* RGB 565 */ - _desiredFrameTime(33), /* ~30 fps */ - _clock(_system), - _scriptManager(nullptr), - _renderManager(nullptr), - _saveManager(nullptr), - _stringManager(nullptr), - _cursorManager(nullptr), - _midiManager(nullptr), - _rnd(nullptr), - _console(nullptr), - _menu(nullptr), - _searchManager(nullptr), - _textRenderer(nullptr), - _doubleFPS(false), - _audioId(0), - _frameRenderDelay(2), - _keyboardVelocity(0), - _mouseVelocity(0), - _videoIsPlaying(false), - _renderedFrameCount(0), - _fps(0) { - - debug(1, "ZVision::ZVision"); - - uint16 workingWindowWidth = (gameDesc->gameId == GID_NEMESIS) ? ZNM_WORKING_WINDOW_WIDTH : ZGI_WORKING_WINDOW_WIDTH; - uint16 workingWindowHeight = (gameDesc->gameId == GID_NEMESIS) ? ZNM_WORKING_WINDOW_HEIGHT : ZGI_WORKING_WINDOW_HEIGHT; - _workingWindow = Common::Rect( - (WINDOW_WIDTH - workingWindowWidth) / 2, - (WINDOW_HEIGHT - workingWindowHeight) / 2, - ((WINDOW_WIDTH - workingWindowWidth) / 2) + workingWindowWidth, - ((WINDOW_HEIGHT - workingWindowHeight) / 2) + workingWindowHeight - ); - - memset(_cheatBuffer, 0, sizeof(_cheatBuffer)); -} - -ZVision::~ZVision() { - debug(1, "ZVision::~ZVision"); - - // Dispose of resources - delete _console; - delete _cursorManager; - delete _stringManager; - delete _saveManager; - delete _scriptManager; - delete _renderManager; // should be deleted after the script manager - delete _rnd; - delete _midiManager; - - getTimerManager()->removeTimerProc(&fpsTimerCallback); - - // Remove all of our debug levels - DebugMan.clearAllDebugChannels(); -} - -void ZVision::registerDefaultSettings() { - for (int i = 0; i < ZVISION_SETTINGS_KEYS_COUNT; i++) { - if (settingsKeys[i].allowEditing) { - if (settingsKeys[i].defaultValue >= 0) - ConfMan.registerDefault(settingsKeys[i].name, settingsKeys[i].defaultValue); - else - ConfMan.registerDefault(settingsKeys[i].name, settingsKeys[i].defaultBoolValue); - } - } - - ConfMan.registerDefault("originalsaveload", false); - ConfMan.registerDefault("doublefps", false); -} - -void ZVision::loadSettings() { - int16 value = 0; - bool boolValue = false; - - for (int i = 0; i < ZVISION_SETTINGS_KEYS_COUNT; i++) { - if (settingsKeys[i].defaultValue >= 0) { - value = (settingsKeys[i].allowEditing) ? ConfMan.getInt(settingsKeys[i].name) : settingsKeys[i].defaultValue; - } else { - boolValue = (settingsKeys[i].allowEditing) ? ConfMan.getBool(settingsKeys[i].name) : settingsKeys[i].defaultBoolValue; - value = (boolValue) ? 1 : 0; - } - - _scriptManager->setStateValue(settingsKeys[i].slot, value); - } - - if (getGameId() == GID_NEMESIS) - _scriptManager->setStateValue(StateKey_ExecScopeStyle, 1); - else - _scriptManager->setStateValue(StateKey_ExecScopeStyle, 0); -} - -void ZVision::saveSettings() { - for (int i = 0; i < ZVISION_SETTINGS_KEYS_COUNT; i++) { - if (settingsKeys[i].allowEditing) { - if (settingsKeys[i].defaultValue >= 0) - ConfMan.setInt(settingsKeys[i].name, _scriptManager->getStateValue(settingsKeys[i].slot)); - else - ConfMan.setBool(settingsKeys[i].name, (_scriptManager->getStateValue(settingsKeys[i].slot) == 1)); - } - } - - ConfMan.flushToDisk(); -} - -void ZVision::initialize() { - const Common::FSNode gameDataDir(ConfMan.get("path")); - - _searchManager = new SearchManager(ConfMan.get("path"), 6); - - _searchManager->addDir("FONTS"); - _searchManager->addDir("addon"); - - if (_gameDescription->gameId == GID_GRANDINQUISITOR) { - _searchManager->loadZix("INQUIS.ZIX"); - _searchManager->addPatch("C000H01Q.RAW", "C000H01Q.SRC"); - _searchManager->addPatch("CM00H01Q.RAW", "CM00H01Q.SRC"); - _searchManager->addPatch("DM00H01Q.RAW", "DM00H01Q.SRC"); - _searchManager->addPatch("E000H01Q.RAW", "E000H01Q.SRC"); - _searchManager->addPatch("EM00H50Q.RAW", "EM00H50Q.SRC"); - _searchManager->addPatch("GJNPH65P.RAW", "GJNPH65P.SRC"); - _searchManager->addPatch("GJNPH72P.RAW", "GJNPH72P.SRC"); - _searchManager->addPatch("H000H01Q.RAW", "H000H01Q.SRC"); - _searchManager->addPatch("M000H01Q.RAW", "M000H01Q.SRC"); - _searchManager->addPatch("P000H01Q.RAW", "P000H01Q.SRC"); - _searchManager->addPatch("Q000H01Q.RAW", "Q000H01Q.SRC"); - _searchManager->addPatch("SW00H01Q.RAW", "SW00H01Q.SRC"); - _searchManager->addPatch("T000H01Q.RAW", "T000H01Q.SRC"); - _searchManager->addPatch("U000H01Q.RAW", "U000H01Q.SRC"); - } else if (_gameDescription->gameId == GID_NEMESIS) - _searchManager->loadZix("NEMESIS.ZIX"); - - initGraphics(WINDOW_WIDTH, WINDOW_HEIGHT, true, &_screenPixelFormat); - - // Register random source - _rnd = new Common::RandomSource("zvision"); - - // Create managers - _scriptManager = new ScriptManager(this); - _renderManager = new RenderManager(this, WINDOW_WIDTH, WINDOW_HEIGHT, _workingWindow, _resourcePixelFormat, _doubleFPS); - _saveManager = new SaveManager(this); - _stringManager = new StringManager(this); - _cursorManager = new CursorManager(this, _resourcePixelFormat); - _textRenderer = new TextRenderer(this); - _midiManager = new MidiManager(); - - if (_gameDescription->gameId == GID_GRANDINQUISITOR) - _menu = new MenuZGI(this); - else - _menu = new MenuNemesis(this); - - // Initialize the managers - _cursorManager->initialize(); - _scriptManager->initialize(); - _stringManager->initialize(_gameDescription->gameId); - - registerDefaultSettings(); - - loadSettings(); - - // Create debugger console. It requires GFX to be initialized - _console = new Console(this); - _doubleFPS = ConfMan.getBool("doublefps"); - - // Initialize FPS timer callback - getTimerManager()->installTimerProc(&fpsTimerCallback, 1000000, this, "zvisionFPS"); -} - -Common::Error ZVision::run() { - initialize(); - - // Check if a saved game is to be loaded from the launcher - if (ConfMan.hasKey("save_slot")) - _saveManager->loadGame(ConfMan.getInt("save_slot")); - - // Before starting, make absolutely sure that the user has copied the needed fonts - if (!Common::File::exists("arial.ttf") && !Common::File::exists("FreeSans.ttf") && !_searchManager->hasFile("arial.ttf") && !_searchManager->hasFile("FreeSans.ttf") ) { - GUI::MessageDialog dialog( - "Before playing this game, you'll need to copy the required " - "fonts into ScummVM's extras directory, or into the game directory. " - "On Windows, you'll need the following font files from the Windows " - "font directory: Times New Roman, Century Schoolbook, Garamond, " - "Courier New and Arial. Alternatively, you can download the GNU " - "FreeFont package. You'll need all the fonts from that package, " - "i.e., FreeMono, FreeSans and FreeSerif." - ); - dialog.runModal(); - quitGame(); - return Common::kUnknownError; - } - - // Main loop - while (!shouldQuit()) { - _clock.update(); - uint32 currentTime = _clock.getLastMeasuredTime(); - uint32 deltaTime = _clock.getDeltaTime(); - - _cursorManager->setItemID(_scriptManager->getStateValue(StateKey_InventoryItem)); - - processEvents(); - _renderManager->updateRotation(); - - _scriptManager->update(deltaTime); - _menu->process(deltaTime); - - // Render the backBuffer to the screen - _renderManager->prepareBackground(); - _renderManager->renderMenuToScreen(); - _renderManager->processSubs(deltaTime); - _renderManager->renderSceneToScreen(); - - // Update the screen - if (canRender()) { - _system->updateScreen(); - _renderedFrameCount++; - } else { - _frameRenderDelay--; - } - - // Calculate the frame delay based off a desired frame time - int delay = _desiredFrameTime - int32(_system->getMillis() - currentTime); - // Ensure non-negative - delay = delay < 0 ? 0 : delay; - - if (_doubleFPS) { - delay >>= 1; - } - - if (canSaveGameStateCurrently() && shouldPerformAutoSave(_saveManager->getLastSaveTime())) { - _saveManager->autoSave(); - } - - _system->delayMillis(delay); - } - - return Common::kNoError; -} - -void ZVision::pauseEngineIntern(bool pause) { - _mixer->pauseAll(pause); - - if (pause) { - _clock.stop(); - } else { - _clock.start(); - } -} - -Common::String ZVision::generateSaveFileName(uint slot) { - return Common::String::format("%s.%03u", _targetName.c_str(), slot); -} - -void ZVision::setRenderDelay(uint delay) { - _frameRenderDelay = delay; -} - -bool ZVision::canRender() { - return _frameRenderDelay <= 0; -} - -GUI::Debugger *ZVision::getDebugger() { - return _console; -} - -void ZVision::syncSoundSettings() { - Engine::syncSoundSettings(); - - _scriptManager->setStateValue(StateKey_Subtitles, ConfMan.getBool("subtitles") ? 1 : 0); -} - -void ZVision::fpsTimerCallback(void *refCon) { - ((ZVision *)refCon)->fpsTimer(); -} - -void ZVision::fpsTimer() { - _fps = _renderedFrameCount; - _renderedFrameCount = 0; -} - -} // End of namespace ZVision +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "common/scummsys.h" + +#include "zvision/zvision.h" +#include "zvision/core/console.h" +#include "zvision/scripting/script_manager.h" +#include "zvision/graphics/render_manager.h" +#include "zvision/graphics/cursors/cursor_manager.h" +#include "zvision/file/save_manager.h" +#include "zvision/text/string_manager.h" +#include "zvision/detection.h" +#include "zvision/scripting/menu.h" +#include "zvision/file/search_manager.h" +#include "zvision/text/text.h" +#include "zvision/text/truetype_font.h" +#include "zvision/sound/midi.h" +#include "zvision/file/zfs_archive.h" + +#include "common/config-manager.h" +#include "common/str.h" +#include "common/debug.h" +#include "common/debug-channels.h" +#include "common/textconsole.h" +#include "common/error.h" +#include "common/system.h" +#include "common/file.h" + +#include "gui/message.h" +#include "engines/util.h" +#include "audio/mixer.h" + +namespace ZVision { + +#define ZVISION_SETTINGS_KEYS_COUNT 11 + +struct zvisionIniSettings { + const char *name; + int16 slot; + int16 defaultValue; // -1: use the bool value + bool defaultBoolValue; + bool allowEditing; +} settingsKeys[ZVISION_SETTINGS_KEYS_COUNT] = { + // Hardcoded settings + {"countrycode", StateKey_CountryCode, 0, false, false}, // always 0 = US, subtitles are shown for codes 0 - 4, unused + {"lineskipvideo", StateKey_VideoLineSkip, 0, false, false}, // video line skip, 0 = default, 1 = always, 2 = pixel double when possible, unused + {"installlevel", StateKey_InstallLevel, 0, false, false}, // 0 = full, checked by universe.scr + {"highquality", StateKey_HighQuality, -1, true, false}, // high panorama quality, unused + {"qsoundenabled", StateKey_Qsound, -1, true, false}, // 1 = enable QSound - TODO: not supported yet + {"debugcheats", StateKey_DebugCheats, -1, true, false}, // always start with the GOxxxx cheat enabled + // Editable settings + {"keyboardturnspeed", StateKey_KbdRotateSpeed, 5, false, true}, + {"panarotatespeed", StateKey_RotateSpeed, 540, false, true}, // checked by universe.scr + {"noanimwhileturning", StateKey_NoTurnAnim, -1, false, true}, // toggle playing animations during pana rotation + {"venusenabled", StateKey_VenusEnable, -1, true, true}, + {"subtitles", StateKey_Subtitles, -1, true, true} +}; + +ZVision::ZVision(OSystem *syst, const ZVisionGameDescription *gameDesc) + : Engine(syst), + _gameDescription(gameDesc), + _resourcePixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0), /* RGB 555 */ + _screenPixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0), /* RGB 565 */ + _desiredFrameTime(33), /* ~30 fps */ + _clock(_system), + _scriptManager(nullptr), + _renderManager(nullptr), + _saveManager(nullptr), + _stringManager(nullptr), + _cursorManager(nullptr), + _midiManager(nullptr), + _rnd(nullptr), + _console(nullptr), + _menu(nullptr), + _searchManager(nullptr), + _textRenderer(nullptr), + _doubleFPS(false), + _audioId(0), + _frameRenderDelay(2), + _keyboardVelocity(0), + _mouseVelocity(0), + _videoIsPlaying(false), + _renderedFrameCount(0), + _fps(0) { + + debug(1, "ZVision::ZVision"); + + uint16 workingWindowWidth = (gameDesc->gameId == GID_NEMESIS) ? ZNM_WORKING_WINDOW_WIDTH : ZGI_WORKING_WINDOW_WIDTH; + uint16 workingWindowHeight = (gameDesc->gameId == GID_NEMESIS) ? ZNM_WORKING_WINDOW_HEIGHT : ZGI_WORKING_WINDOW_HEIGHT; + _workingWindow = Common::Rect( + (WINDOW_WIDTH - workingWindowWidth) / 2, + (WINDOW_HEIGHT - workingWindowHeight) / 2, + ((WINDOW_WIDTH - workingWindowWidth) / 2) + workingWindowWidth, + ((WINDOW_HEIGHT - workingWindowHeight) / 2) + workingWindowHeight + ); + + memset(_cheatBuffer, 0, sizeof(_cheatBuffer)); +} + +ZVision::~ZVision() { + debug(1, "ZVision::~ZVision"); + + // Dispose of resources + delete _console; + delete _cursorManager; + delete _stringManager; + delete _saveManager; + delete _scriptManager; + delete _renderManager; // should be deleted after the script manager + delete _rnd; + delete _midiManager; + + getTimerManager()->removeTimerProc(&fpsTimerCallback); + + // Remove all of our debug levels + DebugMan.clearAllDebugChannels(); +} + +void ZVision::registerDefaultSettings() { + for (int i = 0; i < ZVISION_SETTINGS_KEYS_COUNT; i++) { + if (settingsKeys[i].allowEditing) { + if (settingsKeys[i].defaultValue >= 0) + ConfMan.registerDefault(settingsKeys[i].name, settingsKeys[i].defaultValue); + else + ConfMan.registerDefault(settingsKeys[i].name, settingsKeys[i].defaultBoolValue); + } + } + + ConfMan.registerDefault("originalsaveload", false); + ConfMan.registerDefault("doublefps", false); +} + +void ZVision::loadSettings() { + int16 value = 0; + bool boolValue = false; + + for (int i = 0; i < ZVISION_SETTINGS_KEYS_COUNT; i++) { + if (settingsKeys[i].defaultValue >= 0) { + value = (settingsKeys[i].allowEditing) ? ConfMan.getInt(settingsKeys[i].name) : settingsKeys[i].defaultValue; + } else { + boolValue = (settingsKeys[i].allowEditing) ? ConfMan.getBool(settingsKeys[i].name) : settingsKeys[i].defaultBoolValue; + value = (boolValue) ? 1 : 0; + } + + _scriptManager->setStateValue(settingsKeys[i].slot, value); + } + + if (getGameId() == GID_NEMESIS) + _scriptManager->setStateValue(StateKey_ExecScopeStyle, 1); + else + _scriptManager->setStateValue(StateKey_ExecScopeStyle, 0); +} + +void ZVision::saveSettings() { + for (int i = 0; i < ZVISION_SETTINGS_KEYS_COUNT; i++) { + if (settingsKeys[i].allowEditing) { + if (settingsKeys[i].defaultValue >= 0) + ConfMan.setInt(settingsKeys[i].name, _scriptManager->getStateValue(settingsKeys[i].slot)); + else + ConfMan.setBool(settingsKeys[i].name, (_scriptManager->getStateValue(settingsKeys[i].slot) == 1)); + } + } + + ConfMan.flushToDisk(); +} + +void ZVision::initialize() { + const Common::FSNode gameDataDir(ConfMan.get("path")); + + _searchManager = new SearchManager(ConfMan.get("path"), 6); + + _searchManager->addDir("FONTS"); + _searchManager->addDir("addon"); + + if (_gameDescription->gameId == GID_GRANDINQUISITOR) { + _searchManager->loadZix("INQUIS.ZIX"); + _searchManager->addPatch("C000H01Q.RAW", "C000H01Q.SRC"); + _searchManager->addPatch("CM00H01Q.RAW", "CM00H01Q.SRC"); + _searchManager->addPatch("DM00H01Q.RAW", "DM00H01Q.SRC"); + _searchManager->addPatch("E000H01Q.RAW", "E000H01Q.SRC"); + _searchManager->addPatch("EM00H50Q.RAW", "EM00H50Q.SRC"); + _searchManager->addPatch("GJNPH65P.RAW", "GJNPH65P.SRC"); + _searchManager->addPatch("GJNPH72P.RAW", "GJNPH72P.SRC"); + _searchManager->addPatch("H000H01Q.RAW", "H000H01Q.SRC"); + _searchManager->addPatch("M000H01Q.RAW", "M000H01Q.SRC"); + _searchManager->addPatch("P000H01Q.RAW", "P000H01Q.SRC"); + _searchManager->addPatch("Q000H01Q.RAW", "Q000H01Q.SRC"); + _searchManager->addPatch("SW00H01Q.RAW", "SW00H01Q.SRC"); + _searchManager->addPatch("T000H01Q.RAW", "T000H01Q.SRC"); + _searchManager->addPatch("U000H01Q.RAW", "U000H01Q.SRC"); + } else if (_gameDescription->gameId == GID_NEMESIS) + _searchManager->loadZix("NEMESIS.ZIX"); + + initGraphics(WINDOW_WIDTH, WINDOW_HEIGHT, true, &_screenPixelFormat); + + // Register random source + _rnd = new Common::RandomSource("zvision"); + + // Create managers + _scriptManager = new ScriptManager(this); + _renderManager = new RenderManager(this, WINDOW_WIDTH, WINDOW_HEIGHT, _workingWindow, _resourcePixelFormat, _doubleFPS); + _saveManager = new SaveManager(this); + _stringManager = new StringManager(this); + _cursorManager = new CursorManager(this, _resourcePixelFormat); + _textRenderer = new TextRenderer(this); + _midiManager = new MidiManager(); + + if (_gameDescription->gameId == GID_GRANDINQUISITOR) + _menu = new MenuZGI(this); + else + _menu = new MenuNemesis(this); + + // Initialize the managers + _cursorManager->initialize(); + _scriptManager->initialize(); + _stringManager->initialize(_gameDescription->gameId); + + registerDefaultSettings(); + + loadSettings(); + + // Create debugger console. It requires GFX to be initialized + _console = new Console(this); + _doubleFPS = ConfMan.getBool("doublefps"); + + // Initialize FPS timer callback + getTimerManager()->installTimerProc(&fpsTimerCallback, 1000000, this, "zvisionFPS"); +} + +Common::Error ZVision::run() { + initialize(); + + // Check if a saved game is to be loaded from the launcher + if (ConfMan.hasKey("save_slot")) + _saveManager->loadGame(ConfMan.getInt("save_slot")); + + // Before starting, make absolutely sure that the user has copied the needed fonts + if (!Common::File::exists("arial.ttf") && !Common::File::exists("FreeSans.ttf") && !_searchManager->hasFile("arial.ttf") && !_searchManager->hasFile("FreeSans.ttf") ) { + GUI::MessageDialog dialog( + "Before playing this game, you'll need to copy the required " + "fonts into ScummVM's extras directory, or into the game directory. " + "On Windows, you'll need the following font files from the Windows " + "font directory: Times New Roman, Century Schoolbook, Garamond, " + "Courier New and Arial. Alternatively, you can download the GNU " + "FreeFont package. You'll need all the fonts from that package, " + "i.e., FreeMono, FreeSans and FreeSerif." + ); + dialog.runModal(); + quitGame(); + return Common::kUnknownError; + } + + // Main loop + while (!shouldQuit()) { + _clock.update(); + uint32 currentTime = _clock.getLastMeasuredTime(); + uint32 deltaTime = _clock.getDeltaTime(); + + _cursorManager->setItemID(_scriptManager->getStateValue(StateKey_InventoryItem)); + + processEvents(); + _renderManager->updateRotation(); + + _scriptManager->update(deltaTime); + _menu->process(deltaTime); + + // Render the backBuffer to the screen + _renderManager->prepareBackground(); + _renderManager->renderMenuToScreen(); + _renderManager->processSubs(deltaTime); + _renderManager->renderSceneToScreen(); + + // Update the screen + if (canRender()) { + _system->updateScreen(); + _renderedFrameCount++; + } else { + _frameRenderDelay--; + } + + // Calculate the frame delay based off a desired frame time + int delay = _desiredFrameTime - int32(_system->getMillis() - currentTime); + // Ensure non-negative + delay = delay < 0 ? 0 : delay; + + if (_doubleFPS) { + delay >>= 1; + } + + if (canSaveGameStateCurrently() && shouldPerformAutoSave(_saveManager->getLastSaveTime())) { + _saveManager->autoSave(); + } + + _system->delayMillis(delay); + } + + return Common::kNoError; +} + +void ZVision::pauseEngineIntern(bool pause) { + _mixer->pauseAll(pause); + + if (pause) { + _clock.stop(); + } else { + _clock.start(); + } +} + +Common::String ZVision::generateSaveFileName(uint slot) { + return Common::String::format("%s.%03u", _targetName.c_str(), slot); +} + +void ZVision::setRenderDelay(uint delay) { + _frameRenderDelay = delay; +} + +bool ZVision::canRender() { + return _frameRenderDelay <= 0; +} + +GUI::Debugger *ZVision::getDebugger() { + return _console; +} + +void ZVision::syncSoundSettings() { + Engine::syncSoundSettings(); + + _scriptManager->setStateValue(StateKey_Subtitles, ConfMan.getBool("subtitles") ? 1 : 0); +} + +void ZVision::fpsTimerCallback(void *refCon) { + ((ZVision *)refCon)->fpsTimer(); +} + +void ZVision::fpsTimer() { + _fps = _renderedFrameCount; + _renderedFrameCount = 0; +} + +} // End of namespace ZVision -- cgit v1.2.3 From cc916625d9025ffaa898854c4de19da5dc2e2925 Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Tue, 30 Dec 2014 10:47:51 +0100 Subject: SCUMM: Add a "chained games manager" This replaces the somewhat ugly use of the config manager to store the chained games. --- engines/engine.cpp | 31 +++++++++++++++++++++++++++++++ engines/engine.h | 28 ++++++++++++++++++++++++++++ engines/scumm/scumm.cpp | 3 ++- 3 files changed, 61 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/engine.cpp b/engines/engine.cpp index c63437f800..24008dd073 100644 --- a/engines/engine.cpp +++ b/engines/engine.cpp @@ -45,6 +45,7 @@ #include "common/taskbar.h" #include "common/textconsole.h" #include "common/translation.h" +#include "common/singleton.h" #include "backends/keymapper/keymapper.h" @@ -101,6 +102,36 @@ static void defaultErrorHandler(const char *msg) { } } +// Chained games manager + +ChainedGamesManager::ChainedGamesManager() { + clear(); +} + +void ChainedGamesManager::clear() { + _chainedGames.clear(); +} + +void ChainedGamesManager::push(const Common::String target, const int slot) { + Game game; + game.target = target; + game.slot = slot; + _chainedGames.push(game); +} + +bool ChainedGamesManager::pop(Common::String &target, int &slot) { + if (_chainedGames.empty()) { + return false; + } + Game game = _chainedGames.pop(); + target = game.target; + slot = game.slot; + return true; +} + +namespace Common { +DECLARE_SINGLETON(ChainedGamesManager); +} Engine::Engine(OSystem *syst) : _system(syst), diff --git a/engines/engine.h b/engines/engine.h index e325cc1ba2..d3415d584c 100644 --- a/engines/engine.h +++ b/engines/engine.h @@ -27,6 +27,8 @@ #include "common/str.h" #include "common/language.h" #include "common/platform.h" +#include "common/queue.h" +#include "common/singleton.h" class OSystem; @@ -334,6 +336,32 @@ protected: }; +// Chained games + +/** + * Singleton class which manages chained games. A chained game is one that + * starts automatically, optionally loading a saved game, instead of returning + * to the launcher. + */ +class ChainedGamesManager : public Common::Singleton { +private: + struct Game { + Common::String target; + int slot; + }; + + Common::Queue _chainedGames; + +public: + ChainedGamesManager(); + void clear(); + void push(const Common::String target, const int slot = -1); + bool pop(Common::String &target, int &slot); +}; + +/** Convenience shortcut for accessing the chained games manager. */ +#define ChainedGamesMan ChainedGamesManager::instance() + // FIXME: HACK for MidiEmu & error() extern Engine *g_engine; diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp index 34ae957951..9518ed4e5c 100644 --- a/engines/scumm/scumm.cpp +++ b/engines/scumm/scumm.cpp @@ -2625,7 +2625,8 @@ bool ScummEngine::startManiac() { // Set up the chanined games to Maniac Mansion, and then back // to the current game again with that save slot. - ConfMan.set("chained_games", maniacTarget + "," + ConfMan.getActiveDomainName() + ":100", Common::ConfigManager::kTransientDomain); + ChainedGamesMan.push(maniacTarget); + ChainedGamesMan.push(ConfMan.getActiveDomainName(), 100); // Force a return to the launcher. This will start the first // chained game. -- cgit v1.2.3 From 7dc316cced4c7a45a376d76a6ca0c84bd563132f Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Tue, 30 Dec 2014 10:54:49 +0100 Subject: SCUMM: Add secret "easter_egg" config key This makes it possible to override the detection of Maniac Mansion when starting the Day of the Tentacle easter egg. There is no GUI for setting this, no error handling, and setting it to Day of the Tentacle itself is probably a bad idea... --- engines/scumm/scumm.cpp | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'engines') diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp index 9518ed4e5c..7d927b0cda 100644 --- a/engines/scumm/scumm.cpp +++ b/engines/scumm/scumm.cpp @@ -2601,20 +2601,24 @@ bool ScummEngine::startManiac() { Common::String currentPath = ConfMan.get("path"); Common::String maniacTarget; - // Look for a game with a game path pointing to a 'Maniac' directory - // as a subdirectory to the current game. - Common::ConfigManager::DomainMap::iterator iter = ConfMan.beginGameDomains(); - for (; iter != ConfMan.endGameDomains(); ++iter) { - Common::ConfigManager::Domain &dom = iter->_value; - Common::String path = dom.getVal("path"); - - if (path.hasPrefix(currentPath)) { - path.erase(0, currentPath.size() + 1); - if (path.equalsIgnoreCase("maniac")) { - maniacTarget = dom.getVal("gameid"); - break; + if (!ConfMan.hasKey("easter_egg")) { + // Look for a game with a game path pointing to a 'Maniac' directory + // as a subdirectory to the current game. + Common::ConfigManager::DomainMap::iterator iter = ConfMan.beginGameDomains(); + for (; iter != ConfMan.endGameDomains(); ++iter) { + Common::ConfigManager::Domain &dom = iter->_value; + Common::String path = dom.getVal("path"); + + if (path.hasPrefix(currentPath)) { + path.erase(0, currentPath.size() + 1); + if (path.equalsIgnoreCase("maniac")) { + maniacTarget = dom.getVal("gameid"); + break; + } } } + } else { + maniacTarget = ConfMan.get("easter_egg"); } if (!maniacTarget.empty()) { -- cgit v1.2.3 From 88ba96aa3cb76c7d251a60f32d41f415a40b3dc4 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 30 Dec 2014 12:55:19 +0200 Subject: ZVISION: Fix an off-by-one error in the RLF decoder A regression from 7f61a09478. The current frame is the currently displayed frame, not the frame that should be displayed next. Thanks to clone2727 and Marisa-Chan for the explanation and fixes --- engines/zvision/video/rlf_decoder.cpp | 16 ++++++++-------- engines/zvision/video/rlf_decoder.h | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'engines') diff --git a/engines/zvision/video/rlf_decoder.cpp b/engines/zvision/video/rlf_decoder.cpp index 6e2000f93c..db598a25b6 100644 --- a/engines/zvision/video/rlf_decoder.cpp +++ b/engines/zvision/video/rlf_decoder.cpp @@ -56,7 +56,7 @@ RLFDecoder::RLFVideoTrack::RLFVideoTrack(Common::SeekableReadStream *stream) _height(0), _frameTime(0), _frames(0), - _curFrame(-1), + _displayedFrame(-1), _frameBufferByteSize(0) { if (!readHeader()) { @@ -161,11 +161,11 @@ bool RLFDecoder::RLFVideoTrack::seek(const Audio::Timestamp &time) { uint frame = getFrameAtTime(time); assert(frame < (int)_frameCount); - if ((uint)_curFrame == frame) + if ((uint)_displayedFrame == frame) return true; - int closestFrame = _curFrame; - int distance = (int)frame - _curFrame; + int closestFrame = _displayedFrame; + int distance = (int)frame - closestFrame; if (distance < 0) { for (uint i = 0; i < _completeFrames.size(); ++i) { @@ -189,18 +189,18 @@ bool RLFDecoder::RLFVideoTrack::seek(const Audio::Timestamp &time) { applyFrameToCurrent(i); } - _curFrame = frame; + _displayedFrame = frame - 1; return true; } const Graphics::Surface *RLFDecoder::RLFVideoTrack::decodeNextFrame() { - if (_curFrame == (int)_frameCount) + if (_displayedFrame >= (int)_frameCount) return NULL; - applyFrameToCurrent(_curFrame); + _displayedFrame++; + applyFrameToCurrent(_displayedFrame); - _curFrame++; return &_currentFrameBuffer; } diff --git a/engines/zvision/video/rlf_decoder.h b/engines/zvision/video/rlf_decoder.h index 740f3fdd43..8b8cbaecd5 100644 --- a/engines/zvision/video/rlf_decoder.h +++ b/engines/zvision/video/rlf_decoder.h @@ -46,7 +46,7 @@ private: uint16 getWidth() const { return _width; } uint16 getHeight() const { return _height; } Graphics::PixelFormat getPixelFormat() const { return Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0); /* RGB 555 */ } - int getCurFrame() const { return _curFrame; } + int getCurFrame() const { return _displayedFrame; } int getFrameCount() const { return _frameCount; } const Graphics::Surface *decodeNextFrame(); bool isSeekable() const { return true; } @@ -121,7 +121,7 @@ private: Frame *_frames; Common::Array _completeFrames; - int _curFrame; + int _displayedFrame; Graphics::Surface _currentFrameBuffer; uint32 _frameBufferByteSize; -- cgit v1.2.3 From 64979d5e453bd279c88e559d295d47b175a6559b Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 30 Dec 2014 15:38:03 +0200 Subject: ZVISION: Fix regression in the handling of multiple animations A regression from 0c4e0673c3. Thanks to Marisa-Chan for noticing --- engines/zvision/scripting/effects/animation_effect.cpp | 10 +++++++--- engines/zvision/scripting/effects/animation_effect.h | 2 ++ 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/zvision/scripting/effects/animation_effect.cpp b/engines/zvision/scripting/effects/animation_effect.cpp index c3cbc25406..511a0db353 100644 --- a/engines/zvision/scripting/effects/animation_effect.cpp +++ b/engines/zvision/scripting/effects/animation_effect.cpp @@ -88,10 +88,13 @@ bool AnimationEffect::process(uint32 deltaTimeInMillis) { if (it != _playList.end()) { playnode *nod = &(*it); - if (!_animation->isPlaying()) { + if (nod->_curFrame == -1) { // The node is just beginning playback + nod->_curFrame = nod->start; + _animation->start(); _animation->seekToFrame(nod->start); + _animation->setEndFrame(nod->stop); nod->_delay = deltaTimeInMillis; // Force the frame to draw if (nod->slot) @@ -111,6 +114,7 @@ bool AnimationEffect::process(uint32 deltaTimeInMillis) { return _disposeAfterUse; } + nod->_curFrame = nod->start; _animation->seekToFrame(nod->start); } @@ -186,9 +190,9 @@ void AnimationEffect::addPlayNode(int32 slot, int x, int y, int x2, int y2, int nod.loop = loops; nod.pos = Common::Rect(x, y, x2 + 1, y2 + 1); nod.start = startFrame; - _animation->setEndFrame(CLIP(endFrame, 0, _animation->getFrameCount() - 1)); - + nod.stop = CLIP(endFrame, 0, _animation->getFrameCount() - 1); nod.slot = slot; + nod._curFrame = -1; nod._delay = 0; nod._scaled = NULL; _playList.push_back(nod); diff --git a/engines/zvision/scripting/effects/animation_effect.h b/engines/zvision/scripting/effects/animation_effect.h index a564b83ff3..fd6e24ab8b 100644 --- a/engines/zvision/scripting/effects/animation_effect.h +++ b/engines/zvision/scripting/effects/animation_effect.h @@ -48,7 +48,9 @@ public: Common::Rect pos; int32 slot; int32 start; + int32 stop; int32 loop; + int32 _curFrame; int32 _delay; Graphics::Surface *_scaled; }; -- cgit v1.2.3 From 2fb116f10eaa1bf682a220c33016fc61492af4fe Mon Sep 17 00:00:00 2001 From: RichieSams Date: Tue, 30 Dec 2014 13:32:44 -0600 Subject: SWORD25: Move all lua serialization helper functions to their own file --- engines/sword25/util/lua_serialization_util.cpp | 269 +++++++++++++++++ engines/sword25/util/lua_serialization_util.h | 55 ++++ engines/sword25/util/lua_serializer.cpp | 56 ++-- engines/sword25/util/lua_unserializer.cpp | 368 ++---------------------- 4 files changed, 376 insertions(+), 372 deletions(-) (limited to 'engines') diff --git a/engines/sword25/util/lua_serialization_util.cpp b/engines/sword25/util/lua_serialization_util.cpp index 80c5f86b20..fc3f73eca6 100644 --- a/engines/sword25/util/lua_serialization_util.cpp +++ b/engines/sword25/util/lua_serialization_util.cpp @@ -27,10 +27,20 @@ #include "lua/lobject.h" #include "lua/lstate.h" #include "lua/lgc.h" +#include "lua/lopcodes.h" namespace Lua { +void *lua_realloc(lua_State *luaState, void *block, size_t osize, size_t nsize) { + global_State *globalState = G(luaState); + + block = (*globalState->frealloc)(globalState->ud, block, osize, nsize); + globalState->totalbytes = (globalState->totalbytes - osize) + nsize; + + return block; +} + void pushObject(lua_State *luaState, TValue *obj) { setobj2s(luaState, luaState->top, obj); @@ -74,4 +84,263 @@ StkId getObject(lua_State *luaState, int stackpos) { } } +void lua_linkObjToGC(lua_State *luaState, GCObject *obj, lu_byte type) { + global_State *globalState = G(luaState); + + obj->gch.next = globalState->rootgc; + globalState->rootgc = obj; + obj->gch.marked = luaC_white(globalState); + obj->gch.tt = type; +} + +Closure *lua_newLclosure(lua_State *luaState, int numElements, Table *elementTable) { + Closure *c = (Closure *)lua_malloc(luaState, sizeLclosure(numElements)); + lua_linkObjToGC(luaState, obj2gco(c), LUA_TFUNCTION); + + c->l.isC = 0; + c->l.env = elementTable; + c->l.nupvalues = cast_byte(numElements); + + while (numElements--) { + c->l.upvals[numElements] = NULL; + } + + return c; +} + +void pushClosure(lua_State *luaState, Closure *closure) { + TValue obj; + setclvalue(luaState, &obj, closure); + pushObject(luaState, &obj); +} + +Proto *createProto(lua_State *luaState) { + Proto *newProto = (Proto *)lua_malloc(luaState, sizeof(Proto)); + lua_linkObjToGC(luaState, obj2gco(newProto), LUA_TPROTO); + + newProto->k = NULL; + newProto->sizek = 0; + newProto->p = NULL; + newProto->sizep = 0; + newProto->code = NULL; + newProto->sizecode = 0; + newProto->sizelineinfo = 0; + newProto->sizeupvalues = 0; + newProto->nups = 0; + newProto->upvalues = NULL; + newProto->numparams = 0; + newProto->is_vararg = 0; + newProto->maxstacksize = 0; + newProto->lineinfo = NULL; + newProto->sizelocvars = 0; + newProto->locvars = NULL; + newProto->linedefined = 0; + newProto->lastlinedefined = 0; + newProto->source = NULL; + + return newProto; +} + +TString *createString(lua_State *luaState, const char *str, size_t len) { + TString *res; + lua_pushlstring(luaState, str, len); + + res = rawtsvalue(luaState->top - 1); + lua_pop(luaState, 1); + + return res; +} + +Proto *makeFakeProto(lua_State *L, lu_byte nups) { + Proto *p = createProto(L); + + p->sizelineinfo = 1; + p->lineinfo = lua_newVector(L, 1, int); + p->lineinfo[0] = 1; + p->sizecode = 1; + p->code = lua_newVector(L, 1, Instruction); + p->code[0] = CREATE_ABC(OP_RETURN, 0, 1, 0); + p->source = createString(L, "", 0); + p->maxstacksize = 2; + p->nups = nups; + p->sizek = 0; + p->sizep = 0; + + return p; +} + +UpVal *createUpValue(lua_State *luaState, int stackpos) { + UpVal *upValue = (UpVal *)lua_malloc(luaState, sizeof(UpVal)); + lua_linkObjToGC(luaState, (GCObject *)upValue, LUA_TUPVAL); + upValue->tt = LUA_TUPVAL; + upValue->v = &upValue->u.value; + upValue->u.l.prev = NULL; + upValue->u.l.next = NULL; + + const TValue *o2 = (TValue *)getObject(luaState, stackpos); + upValue->v->value = o2->value; + upValue->v->tt = o2->tt; + checkliveness(G(L), upValue->v); + + return upValue; +} + +void unboxUpValue(lua_State *luaState) { + // >>>>> ...... func + LClosure *lcl; + UpVal *uv; + + lcl = (LClosure *)clvalue(getObject(luaState, -1)); + uv = lcl->upvals[0]; + + lua_pop(luaState, 1); + // >>>>> ...... + + pushUpValue(luaState, uv); + // >>>>> ...... upValue +} + +size_t appendStackToStack_reverse(lua_State *from, lua_State *to) { + for (StkId id = from->top - 1; id >= from->stack; --id) { + setobj2s(to, to->top, id); + to->top++; + } + + return from->top - from->stack; +} + +void correctStack(lua_State *L, TValue *oldstack) { + CallInfo *ci; + GCObject *up; + L->top = (L->top - oldstack) + L->stack; + for (up = L->openupval; up != NULL; up = up->gch.next) + gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack; + for (ci = L->base_ci; ci <= L->ci; ci++) { + ci->top = (ci->top - oldstack) + L->stack; + ci->base = (ci->base - oldstack) + L->stack; + ci->func = (ci->func - oldstack) + L->stack; + } + L->base = (L->base - oldstack) + L->stack; +} + +void lua_reallocstack(lua_State *L, int newsize) { + TValue *oldstack = L->stack; + int realsize = newsize + 1 + EXTRA_STACK; + + lua_reallocvector(L, L->stack, L->stacksize, realsize, TValue); + L->stacksize = realsize; + L->stack_last = L->stack + newsize; + correctStack(L, oldstack); +} + +void lua_growstack(lua_State *L, int n) { + // Double size is enough? + if (n <= L->stacksize) { + lua_reallocstack(L, 2 * L->stacksize); + } else { + lua_reallocstack(L, L->stacksize + n); + } +} + +void lua_reallocCallInfo(lua_State *lauState, int newsize) { + CallInfo *oldci = lauState->base_ci; + lua_reallocvector(lauState, lauState->base_ci, lauState->size_ci, newsize, CallInfo); + + lauState->size_ci = newsize; + lauState->ci = (lauState->ci - oldci) + lauState->base_ci; + lauState->end_ci = lauState->base_ci + lauState->size_ci - 1; +} + +void GCUnlink(lua_State *luaState, GCObject *gco) { + GCObject *prevslot; + if (G(luaState)->rootgc == gco) { + G(luaState)->rootgc = G(luaState)->rootgc->gch.next; + return; + } + + prevslot = G(luaState)->rootgc; + while (prevslot->gch.next != gco) { + prevslot = prevslot->gch.next; + } + + prevslot->gch.next = prevslot->gch.next->gch.next; +} + +TString *lua_newlstr(lua_State *luaState, const char *str, size_t len) { + lua_pushlstring(luaState, str, len); + TString *luaStr = &(luaState->top - 1)->value.gc->ts; + + lua_pop(luaState, 1); + + return luaStr; +} + +void lua_link(lua_State *luaState, GCObject *o, lu_byte tt) { + global_State *g = G(luaState); + o->gch.next = g->rootgc; + g->rootgc = o; + o->gch.marked = luaC_white(g); + o->gch.tt = tt; +} + +Proto *lua_newproto(lua_State *luaState) { + Proto *f = (Proto *)lua_malloc(luaState, sizeof(Proto)); + lua_link(luaState, obj2gco(f), LUA_TPROTO); + f->k = NULL; + f->sizek = 0; + f->p = NULL; + f->sizep = 0; + f->code = NULL; + f->sizecode = 0; + f->sizelineinfo = 0; + f->sizeupvalues = 0; + f->nups = 0; + f->upvalues = NULL; + f->numparams = 0; + f->is_vararg = 0; + f->maxstacksize = 0; + f->lineinfo = NULL; + f->sizelocvars = 0; + f->locvars = NULL; + f->linedefined = 0; + f->lastlinedefined = 0; + f->source = NULL; + return f; +} + +UpVal *makeUpValue(lua_State *luaState, int stackPos) { + UpVal *uv = lua_new(luaState, UpVal); + lua_link(luaState, (GCObject *)uv, LUA_TUPVAL); + uv->tt = LUA_TUPVAL; + uv->v = &uv->u.value; + uv->u.l.prev = NULL; + uv->u.l.next = NULL; + + setobj(luaState, uv->v, getObject(luaState, stackPos)); + + return uv; +} + +void boxUpValue_start(lua_State *luaState) { + LClosure *closure; + closure = (LClosure *)lua_newLclosure(luaState, 1, hvalue(&luaState->l_gt)); + pushClosure(luaState, (Closure *)closure); + // >>>>> ...... func + closure->p = makeFakeProto(luaState, 1); + + // Temporarily initialize the upvalue to nil + lua_pushnil(luaState); + closure->upvals[0] = makeUpValue(luaState, -1); + lua_pop(luaState, 1); +} + +void boxUpValue_finish(lua_State *luaState) { + // >>>>> ...... func obj + LClosure *lcl = (LClosure *)clvalue(getObject(luaState, -2)); + + lcl->upvals[0]->u.value = *getObject(luaState, -1); + lua_pop(luaState, 1); + // >>>>> ...... func +} + } // End of namespace Lua diff --git a/engines/sword25/util/lua_serialization_util.h b/engines/sword25/util/lua_serialization_util.h index 6c55d0dd53..345996f606 100644 --- a/engines/sword25/util/lua_serialization_util.h +++ b/engines/sword25/util/lua_serialization_util.h @@ -32,12 +32,67 @@ typedef TValue *StkId; namespace Lua { +#define lua_malloc(luaState, nsize) lua_realloc(luaState, nullptr, 0, nsize) +#define lua_reallocv(luaState, block, on, n, e) lua_realloc(luaState, block, (on) * (e), (n) * (e)) +#define lua_reallocvector(luaState, vec, oldn, n, T) ((vec) = (T *)(lua_reallocv(luaState, vec, oldn, n, sizeof(T)))) +#define lua_newVector(luaState, num, T) ((T *)lua_reallocv(luaState, nullptr, 0, num, sizeof(T))) +#define lua_new(luaState,T) (T *)lua_malloc(luaState, sizeof(T)) + +void *lua_realloc(lua_State *luaState, void *block, size_t osize, size_t nsize); + void pushObject(lua_State *luaState, TValue *obj); void pushProto(lua_State *luaState, Proto *proto); void pushUpValue(lua_State *luaState, UpVal *upval); void pushString(lua_State *luaState, TString *str); + StkId getObject(lua_State *luaState, int stackpos); +void lua_linkObjToGC(lua_State *luaState, GCObject *obj, lu_byte type); + +#define sizeLclosure(n) ((sizeof(LClosure)) + sizeof(TValue *) * ((n) - 1)) + +Closure *lua_newLclosure(lua_State *luaState, int numElements, Table *elementTable); +void pushClosure(lua_State *luaState, Closure *closure); + +Proto *createProto(lua_State *luaState); +Proto *makeFakeProto(lua_State *L, lu_byte nups); + +TString *createString(lua_State *luaState, const char *str, size_t len); + +UpVal *createUpValue(lua_State *luaState, int stackpos); +void unboxUpValue(lua_State *luaState); + +/* Appends one stack to another stack, but the stack is reversed in the process */ +size_t appendStackToStack_reverse(lua_State *from, lua_State *to); +void correctStack(lua_State *L, TValue *oldstack); +void lua_reallocstack(lua_State *L, int newsize); +void lua_growstack(lua_State *L, int n); + +void lua_reallocCallInfo(lua_State *lauState, int newsize); + +/* Does basically the opposite of luaC_link(). + * Right now this function is rather inefficient; it requires traversing the + * entire root GC set in order to find one object. If the GC list were doubly + * linked this would be much easier, but there's no reason for Lua to have + * that. */ +void GCUnlink(lua_State *luaState, GCObject *gco); + +TString *lua_newlstr(lua_State *luaState, const char *str, size_t len); +void lua_link(lua_State *luaState, GCObject *o, lu_byte tt); +Proto *lua_newproto(lua_State *luaState) ; + +UpVal *makeUpValue(lua_State *luaState, int stackPos); +/** + * The GC is not fond of finding upvalues in tables. We get around this + * during persistence using a weakly keyed table, so that the GC doesn't + * bother to mark them. This won't work in unpersisting, however, since + * if we make the values weak they'll be collected (since nothing else + * references them). Our solution, during unpersisting, is to represent + * upvalues as dummy functions, each with one upvalue. + */ +void boxUpValue_start(lua_State *luaState); +void boxUpValue_finish(lua_State *luaState); + } // End of namespace Lua #endif diff --git a/engines/sword25/util/lua_serializer.cpp b/engines/sword25/util/lua_serializer.cpp index c6c5f99342..55b6257324 100644 --- a/engines/sword25/util/lua_serializer.cpp +++ b/engines/sword25/util/lua_serializer.cpp @@ -42,7 +42,7 @@ struct SerializationInfo { uint counter; }; -static void serializeObject(SerializationInfo *info); +static void serialize(SerializationInfo *info); static void serializeBoolean(SerializationInfo *info); static void serializeNumber(SerializationInfo *info); @@ -103,14 +103,14 @@ void serializeLua(lua_State *luaState, Common::WriteStream *writeStream) { // >>>>> permTbl indexTbl rootObj // Serialize the root recursively - serializeObject(&info); + serialize(&info); // Return the stack back to the original state lua_remove(luaState, 2); // >>>>> permTbl rootObj } -static void serializeObject(SerializationInfo *info) { +static void serialize(SerializationInfo *info) { // The stack can potentially have many things on it // The object we want to serialize is the item on the top of the stack // >>>>> permTbl indexTbl rootObj ...... obj @@ -188,7 +188,7 @@ static void serializeObject(SerializationInfo *info) { info->writeStream->writeSint32LE(PERMANENT_TYPE); // Serialize the key - serializeObject(info); + serialize(info); // Pop the key off the stack lua_pop(info->luaState, 1); @@ -368,7 +368,7 @@ static bool serializeSpecialObject(SerializationInfo *info, bool defaction) { info->writeStream->writeSint32LE(1); // Serialize the function - serializeObject(info); + serialize(info); lua_pop(info->luaState, 2); // >>>>> permTbl indexTbl ...... obj @@ -395,7 +395,7 @@ static void serializeTable(SerializationInfo *info) { } // >>>>> permTbl indexTbl ...... tbl metaTbl/nil */ - serializeObject(info); + serialize(info); lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... tbl @@ -412,13 +412,13 @@ static void serializeTable(SerializationInfo *info) { // >>>>> permTbl indexTbl ...... tbl k v k */ // Serialize the key - serializeObject(info); + serialize(info); lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... tbl k v */ // Serialize the value - serializeObject(info); + serialize(info); lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... tbl k */ @@ -430,7 +430,7 @@ static void serializeTable(SerializationInfo *info) { lua_pushnil(info->luaState); // >>>>> permTbl indexTbl ...... tbl - serializeObject(info); + serialize(info); lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... tbl @@ -457,7 +457,7 @@ static void serializeFunction(SerializationInfo *info) { pushProto(info->luaState, cl->l.p); // >>>>> permTbl indexTbl ...... func proto */ - serializeObject(info); + serialize(info); lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... func @@ -468,7 +468,7 @@ static void serializeFunction(SerializationInfo *info) { pushUpValue(info->luaState, cl->l.upvals[i]); // >>>>> permTbl indexTbl ...... func upval - serializeObject(info); + serialize(info); lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... func @@ -492,23 +492,13 @@ static void serializeFunction(SerializationInfo *info) { } // >>>>> permTbl indexTbl ...... func fenv/nil - serializeObject(info); + serialize(info); lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... func } } -/* Appends one stack to another stack, but the stack is reversed in the process */ -static size_t appendStackToStack_rev(lua_State *from, lua_State *to) { - for (StkId id = from->top - 1; id >= from->stack; --id) { - setobj2s(to, to->top, id); - to->top++; - } - - return from->top - from->stack; -} - static void serializeThread(SerializationInfo *info) { // >>>>> permTbl indexTbl ...... thread lua_State *threadState = lua_tothread(info->luaState, -1); @@ -525,12 +515,12 @@ static void serializeThread(SerializationInfo *info) { // Persist the stack // We *could* have truncation here, but if we have more than 4 billion items on a stack, we have bigger problems - uint32 stackSize = static_cast(appendStackToStack_rev(threadState, info->luaState)); + uint32 stackSize = static_cast(appendStackToStack_reverse(threadState, info->luaState)); info->writeStream->writeUint32LE(stackSize); // >>>>> permTbl indexTbl ...... thread (reversed contents of thread stack) */ for (; stackSize > 0; --stackSize) { - serializeObject(info); + serialize(info); lua_pop(info->luaState, 1); } @@ -592,7 +582,7 @@ static void serializeThread(SerializationInfo *info) { pushUpValue(info->luaState, upVal); // >>>>> permTbl indexTbl ...... thread upVal - serializeObject(info); + serialize(info); lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... thread @@ -607,7 +597,7 @@ static void serializeThread(SerializationInfo *info) { // >>>>> permTbl indexTbl ...... thread nil // Use nil as a terminator - serializeObject(info); + serialize(info); lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... thread @@ -627,7 +617,7 @@ static void serializeProto(SerializationInfo *info) { pushObject(info->luaState, &proto->k[i]); // >>>>> permTbl indexTbl ...... proto const - serializeObject(info); + serialize(info); lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... proto @@ -643,7 +633,7 @@ static void serializeProto(SerializationInfo *info) { pushProto(info->luaState, proto->p[i]); // >>>>> permTbl indexTbl ...... proto subProto */ - serializeObject(info); + serialize(info); lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... proto @@ -666,7 +656,7 @@ static void serializeProto(SerializationInfo *info) { pushString(info->luaState, proto->upvalues[i]); // >>>>> permTbl indexTbl ...... proto str - serializeObject(info); + serialize(info); lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... proto @@ -680,7 +670,7 @@ static void serializeProto(SerializationInfo *info) { pushString(info->luaState, proto->locvars[i].varname); // >>>>> permTbl indexTbl ...... proto str - serializeObject(info); + serialize(info); lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... proto @@ -694,7 +684,7 @@ static void serializeProto(SerializationInfo *info) { pushString(info->luaState, proto->source); // >>>>> permTbl indexTbl ...... proto sourceStr - serializeObject(info); + serialize(info); lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... proto @@ -757,7 +747,7 @@ static void serializeUpValue(SerializationInfo *info) { pushObject(info->luaState, upValue->v); // >>>>> permTbl indexTbl ...... obj - serializeObject(info); + serialize(info); // >>>>> permTbl indexTbl ...... obj } @@ -787,7 +777,7 @@ static void serializeUserData(SerializationInfo *info) { } // >>>>> permTbl rootObj ...... udata metaTbl/nil - serializeObject(info); + serialize(info); lua_pop(info->luaState, 1); /* perms reftbl ... udata */ diff --git a/engines/sword25/util/lua_unserializer.cpp b/engines/sword25/util/lua_unserializer.cpp index 69cb764dd2..803c79c8c2 100644 --- a/engines/sword25/util/lua_unserializer.cpp +++ b/engines/sword25/util/lua_unserializer.cpp @@ -40,7 +40,7 @@ struct UnSerializationInfo { Common::ReadStream *readStream; }; -static void unserializeObject(UnSerializationInfo *info); +static void unserialize(UnSerializationInfo *info); static void unserializeBoolean(UnSerializationInfo *info); static void unserializeNumber(UnSerializationInfo *info); @@ -74,7 +74,7 @@ void unserializeLua(lua_State *luaState, Common::ReadStream *readStream) { lua_gc(luaState, LUA_GCSTOP, 0); // Unserialize the root object - unserializeObject(&info); + unserialize(&info); // >>>>> permTbl indexTbl rootObj // Re-start garbage collection @@ -85,7 +85,7 @@ void unserializeLua(lua_State *luaState, Common::ReadStream *readStream) { // >>>>> permTbl rootObj } -/* The object is left on the stack. This is primarily used by unpersist, but +/* The object is left on the stack. This is primarily used by unserialize, but * may be used by GCed objects that may incur cycles in order to preregister * the object. */ static void registerObjectInIndexTable(UnSerializationInfo *info, int index) { @@ -105,7 +105,7 @@ static void registerObjectInIndexTable(UnSerializationInfo *info, int index) { // >>>>> permTbl indexTbl ...... obj } -static void unserializeObject(UnSerializationInfo *info) { +static void unserialize(UnSerializationInfo *info) { // >>>>> permTbl indexTbl ...... // Make sure there is enough room on the stack @@ -241,7 +241,7 @@ static void unserializeSpecialTable(UnSerializationInfo *info, int index) { // Make sure there is enough room on the stack lua_checkstack(info->luaState, 1); - unserializeObject(info); + unserialize(info); // >>>>> permTbl indexTbl ...... spfunc lua_call(info->luaState, 0, 1); @@ -262,7 +262,7 @@ static void unserializeLiteralTable(UnSerializationInfo *info, int index) { // >>>>> permTbl indexTbl ...... tbl // Unserialize metatable - unserializeObject(info); + unserialize(info); // >>>>> permTbl indexTbl ...... tbl ?metaTbl/nil? if (lua_istable(info->luaState, -1)) { @@ -279,7 +279,7 @@ static void unserializeLiteralTable(UnSerializationInfo *info, int index) { while (1) { // >>>>> permTbl indexTbl ...... tbl - unserializeObject(info); + unserialize(info); // >>>>> permTbl indexTbl ...... tbl key/nil // The table serialization is nil terminated @@ -292,7 +292,7 @@ static void unserializeLiteralTable(UnSerializationInfo *info, int index) { } // >>>>> permTbl indexTbl ...... tbl key - unserializeObject(info); + unserialize(info); // >>>>> permTbl indexTbl ...... tbl value lua_rawset(info->luaState, -3); @@ -317,142 +317,6 @@ void unserializeTable(UnSerializationInfo *info, int index) { } } - - -void *lua_realloc(lua_State *luaState, void *block, size_t osize, size_t nsize) { - global_State *globalState = G(luaState); - - block = (*globalState->frealloc)(globalState->ud, block, osize, nsize); - globalState->totalbytes = (globalState->totalbytes - osize) + nsize; - - return block; -} - -#define lua_malloc(luaState, nsize) lua_realloc(luaState, nullptr, 0, nsize) -#define lua_reallocv(luaState, block, on, n, e) lua_realloc(luaState, block, (on) * (e), (n) * (e)) -#define lua_reallocvector(luaState, vec, oldn, n, T) ((vec) = (T *)(lua_reallocv(luaState, vec, oldn, n, sizeof(T)))) -#define lua_newVector(luaState, num, T) ((T *)lua_reallocv(luaState, nullptr, 0, num, sizeof(T))) -#define lua_new(luaState,T) (T *)lua_malloc(luaState, sizeof(T)) - -void lua_linkObjToGC(lua_State *luaState, GCObject *obj, lu_byte type) { - global_State *globalState = G(luaState); - - obj->gch.next = globalState->rootgc; - globalState->rootgc = obj; - obj->gch.marked = luaC_white(globalState); - obj->gch.tt = type; -} - -#define sizeLclosure(n) ((sizeof(LClosure)) + sizeof(TValue *) * ((n) - 1)) - -Closure *newLClosure(lua_State *luaState, byte numUpValues, Table *env) { - Closure *newClosure = (Closure *)lua_malloc(luaState, sizeLclosure(numUpValues)); - - lua_linkObjToGC(luaState, obj2gco(newClosure), LUA_TFUNCTION); - - newClosure->l.isC = 0; - newClosure->l.env = env; - newClosure->l.nupvalues = numUpValues; - - while (numUpValues--) { - newClosure->l.upvals[numUpValues] = NULL; - } - - return newClosure; -} - -static void pushClosure(lua_State *luaState, Closure *closure) { - TValue obj; - setclvalue(luaState, &obj, closure); - pushObject(luaState, &obj); -} - -Proto *createProto(lua_State *luaState) { - Proto *newProto = (Proto *)lua_malloc(luaState, sizeof(Proto)); - lua_linkObjToGC(luaState, obj2gco(newProto), LUA_TPROTO); - - newProto->k = NULL; - newProto->sizek = 0; - newProto->p = NULL; - newProto->sizep = 0; - newProto->code = NULL; - newProto->sizecode = 0; - newProto->sizelineinfo = 0; - newProto->sizeupvalues = 0; - newProto->nups = 0; - newProto->upvalues = NULL; - newProto->numparams = 0; - newProto->is_vararg = 0; - newProto->maxstacksize = 0; - newProto->lineinfo = NULL; - newProto->sizelocvars = 0; - newProto->locvars = NULL; - newProto->linedefined = 0; - newProto->lastlinedefined = 0; - newProto->source = NULL; - - return newProto; -} - -TString *createString(lua_State *luaState, const char *str, size_t len) { - TString *res; - lua_pushlstring(luaState, str, len); - - res = rawtsvalue(luaState->top - 1); - lua_pop(luaState, 1); - - return res; -} - -static Proto *makeFakeProto(lua_State *L, lu_byte nups) { - Proto *p = createProto(L); - - p->sizelineinfo = 1; - p->lineinfo = lua_newVector(L, 1, int); - p->lineinfo[0] = 1; - p->sizecode = 1; - p->code = lua_newVector(L, 1, Instruction); - p->code[0] = CREATE_ABC(OP_RETURN, 0, 1, 0); - p->source = createString(L, "", 0); - p->maxstacksize = 2; - p->nups = nups; - p->sizek = 0; - p->sizep = 0; - - return p; -} - -static UpVal *createUpValue(lua_State *luaState, int stackpos) { - UpVal *upValue = (UpVal *)lua_malloc(luaState, sizeof(UpVal)); - lua_linkObjToGC(luaState, (GCObject *)upValue, LUA_TUPVAL); - upValue->tt = LUA_TUPVAL; - upValue->v = &upValue->u.value; - upValue->u.l.prev = NULL; - upValue->u.l.next = NULL; - - const TValue *o2 = (TValue *)getObject(luaState, stackpos); - upValue->v->value = o2->value; - upValue->v->tt = o2->tt; - checkliveness(G(L), upValue->v); - - return upValue; -} - -static void unboxUpValue(lua_State *luaState) { - // >>>>> ...... func - LClosure *lcl; - UpVal *uv; - - lcl = (LClosure *)clvalue(getObject(luaState, -1)); - uv = lcl->upvals[0]; - - lua_pop(luaState, 1); - // >>>>> ...... - - pushUpValue(luaState, uv); - // >>>>> ...... upValue -} - void unserializeFunction(UnSerializationInfo *info, int index) { // >>>>> permTbl indexTbl ...... @@ -461,7 +325,7 @@ void unserializeFunction(UnSerializationInfo *info, int index) { byte numUpValues = info->readStream->readByte(); - LClosure *lclosure = (LClosure *)newLClosure(info->luaState, numUpValues, hvalue(&info->luaState->l_gt)); + LClosure *lclosure = (LClosure *)lua_newLclosure(info->luaState, numUpValues, hvalue(&info->luaState->l_gt)); pushClosure(info->luaState, (Closure *)lclosure); // >>>>> permTbl indexTbl ...... func @@ -484,7 +348,7 @@ void unserializeFunction(UnSerializationInfo *info, int index) { registerObjectInIndexTable(info, index); // Now that it's safe, we can get the real proto - unserializeObject(info); + unserialize(info); // >>>>> permTbl indexTbl ...... func proto lclosure->p = gco2p(getObject(info->luaState, -1)->value.gc); @@ -494,7 +358,7 @@ void unserializeFunction(UnSerializationInfo *info, int index) { for (byte i = 0; i < numUpValues; ++i) { // >>>>> permTbl indexTbl ...... func - unserializeObject(info); + unserialize(info); // >>>>> permTbl indexTbl ...... func func2 unboxUpValue(info->luaState); @@ -506,7 +370,7 @@ void unserializeFunction(UnSerializationInfo *info, int index) { } // Finally, the fenv - unserializeObject(info); + unserialize(info); // >>>>> permTbl indexTbl ...... func ?fenv/nil? if (!lua_isnil(info->luaState, -1)) { @@ -522,81 +386,6 @@ void unserializeFunction(UnSerializationInfo *info, int index) { // >>>>> permTbl indexTbl ...... func } -static void correctStack(lua_State *L, TValue *oldstack) { - CallInfo *ci; - GCObject *up; - L->top = (L->top - oldstack) + L->stack; - for (up = L->openupval; up != NULL; up = up->gch.next) - gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack; - for (ci = L->base_ci; ci <= L->ci; ci++) { - ci->top = (ci->top - oldstack) + L->stack; - ci->base = (ci->base - oldstack) + L->stack; - ci->func = (ci->func - oldstack) + L->stack; - } - L->base = (L->base - oldstack) + L->stack; -} - -void lua_reallocstack(lua_State *L, int newsize) { - TValue *oldstack = L->stack; - int realsize = newsize + 1 + EXTRA_STACK; - - lua_reallocvector(L, L->stack, L->stacksize, realsize, TValue); - L->stacksize = realsize; - L->stack_last = L->stack + newsize; - correctStack(L, oldstack); -} - -void lua_growstack(lua_State *L, int n) { - // Double size is enough? - if (n <= L->stacksize) { - lua_reallocstack(L, 2 * L->stacksize); - } else { - lua_reallocstack(L, L->stacksize + n); - } -} - -void lua_reallocCallInfo(lua_State *lauState, int newsize) { - CallInfo *oldci = lauState->base_ci; - lua_reallocvector(lauState, lauState->base_ci, lauState->size_ci, newsize, CallInfo); - - lauState->size_ci = newsize; - lauState->ci = (lauState->ci - oldci) + lauState->base_ci; - lauState->end_ci = lauState->base_ci + lauState->size_ci - 1; -} - -void unboxUpVal(lua_State *luaState) { - // >>>>> ... func - LClosure *lcl; - UpVal *uv; - - lcl = (LClosure *)(&getObject(luaState, -1)->value.gc->cl); - uv = lcl->upvals[0]; - lua_pop(luaState, 1); - // >>>>> ... - pushUpValue(luaState, uv); - // >>>>> ... upVal -} - -/* Does basically the opposite of luaC_link(). - * Right now this function is rather inefficient; it requires traversing the - * entire root GC set in order to find one object. If the GC list were doubly - * linked this would be much easier, but there's no reason for Lua to have - * that. */ -static void GCUnlink(lua_State *luaState, GCObject *gco) { - GCObject *prevslot; - if (G(luaState)->rootgc == gco) { - G(luaState)->rootgc = G(luaState)->rootgc->gch.next; - return; - } - - prevslot = G(luaState)->rootgc; - while (prevslot->gch.next != gco) { - prevslot = prevslot->gch.next; - } - - prevslot->gch.next = prevslot->gch.next->gch.next; -} - void unserializeThread(UnSerializationInfo *info, int index) { // >>>>> permTbl indexTbl ...... @@ -619,7 +408,7 @@ void unserializeThread(UnSerializationInfo *info, int index) { // very bottom of the stack L2->top--; for (uint32 i = 0; i < stackSize; ++i) { - unserializeObject(info); + unserialize(info); // L1: permTbl indexTbl ...... thread obj* } @@ -679,7 +468,7 @@ void unserializeThread(UnSerializationInfo *info, int index) { global_State *g = G(L2); while (true) { - unserializeObject(info); + unserialize(info); // >>>>> permTbl indexTbl ...... thread upVal/nil // The list is terminated by a nil @@ -691,7 +480,7 @@ void unserializeThread(UnSerializationInfo *info, int index) { } // >>>>> permTbl indexTbl ...... thread boxedUpVal - unboxUpVal(info->luaState); + unboxUpValue(info->luaState); // >>>>> permTbl indexTbl ...... thread boxedUpVal uv = &(getObject(info->luaState, -1)->value.gc->uv); @@ -722,48 +511,6 @@ void unserializeThread(UnSerializationInfo *info, int index) { } } -TString *lua_newlstr(lua_State *luaState, const char *str, size_t len) { - lua_pushlstring(luaState, str, len); - TString *luaStr = &(luaState->top - 1)->value.gc->ts; - - lua_pop(luaState, 1); - - return luaStr; -} - -void lua_link(lua_State *luaState, GCObject *o, lu_byte tt) { - global_State *g = G(luaState); - o->gch.next = g->rootgc; - g->rootgc = o; - o->gch.marked = luaC_white(g); - o->gch.tt = tt; -} - -Proto *lua_newproto(lua_State *luaState) { - Proto *f = (Proto *)lua_malloc(luaState, sizeof(Proto)); - lua_link(luaState, obj2gco(f), LUA_TPROTO); - f->k = NULL; - f->sizek = 0; - f->p = NULL; - f->sizep = 0; - f->code = NULL; - f->sizecode = 0; - f->sizelineinfo = 0; - f->sizeupvalues = 0; - f->nups = 0; - f->upvalues = NULL; - f->numparams = 0; - f->is_vararg = 0; - f->maxstacksize = 0; - f->lineinfo = NULL; - f->sizelocvars = 0; - f->locvars = NULL; - f->linedefined = 0; - f->lastlinedefined = 0; - f->source = NULL; - return f; -} - void unserializeProto(UnSerializationInfo *info, int index) { // >>>>> permTbl indexTbl ...... @@ -793,7 +540,7 @@ void unserializeProto(UnSerializationInfo *info, int index) { lua_reallocvector(info->luaState, p->k, 0, sizek, TValue); for (int i = 0; i < sizek; ++i) { // >>>>> permTbl indexTbl ...... proto - unserializeObject(info); + unserialize(info); // >>>>> permTbl indexTbl ...... proto k setobj2s(info->luaState, &p->k[i], getObject(info->luaState, -1)); @@ -810,7 +557,7 @@ void unserializeProto(UnSerializationInfo *info, int index) { lua_reallocvector(info->luaState, p->p, 0, sizep, Proto *); for (int i = 0; i < sizep; ++i) { // >>>>> permTbl indexTbl ...... proto - unserializeObject(info); + unserialize(info); // >>>>> permTbl indexTbl ...... proto subproto p->p[i] = (Proto *)getObject(info->luaState, -1)->value.gc; @@ -834,7 +581,7 @@ void unserializeProto(UnSerializationInfo *info, int index) { lua_reallocvector(info->luaState, p->upvalues, 0, p->sizeupvalues, TString *); for (int i = 0; i < p->sizeupvalues; ++i) { // >>>>> permTbl indexTbl ...... proto - unserializeObject(info); + unserialize(info); // >>>>> permTbl indexTbl ...... proto str p->upvalues[i] = lua_newlstr(info->luaState, lua_tostring(info->luaState, -1), strlen(lua_tostring(info->luaState, -1))); @@ -850,7 +597,7 @@ void unserializeProto(UnSerializationInfo *info, int index) { lua_reallocvector(info->luaState, p->locvars, 0, p->sizelocvars, LocVar); for (int i = 0; i < p->sizelocvars; ++i) { // >>>>> permTbl indexTbl ...... proto - unserializeObject(info); + unserialize(info); // >>>>> permTbl indexTbl ...... proto str p->locvars[i].varname = lua_newlstr(info->luaState, lua_tostring(info->luaState, -1), strlen(lua_tostring(info->luaState, -1))); @@ -864,7 +611,7 @@ void unserializeProto(UnSerializationInfo *info, int index) { // >>>>> permTbl indexTbl ...... proto // Read in source string - unserializeObject(info); + unserialize(info); // >>>>> permTbl indexTbl ...... proto sourceStr p->source = lua_newlstr(info->luaState, lua_tostring(info->luaState, -1), strlen(lua_tostring(info->luaState, -1))); @@ -890,75 +637,18 @@ void unserializeProto(UnSerializationInfo *info, int index) { p->maxstacksize = info->readStream->readByte(); } -Closure *lua_newLclosure(lua_State *luaState, int numElements, Table *elementTable) { - Closure *c = (Closure *)lua_malloc(luaState, sizeLclosure(numElements)); - lua_link(luaState, obj2gco(c), LUA_TFUNCTION); - c->l.isC = 0; - c->l.env = elementTable; - c->l.nupvalues = cast_byte(numElements); - - while (numElements--) { - c->l.upvals[numElements] = NULL; - } - - return c; -} - -static UpVal *makeUpVal(lua_State *luaState, int stackPos) { - UpVal *uv = lua_new(luaState, UpVal); - lua_link(luaState, (GCObject *)uv, LUA_TUPVAL); - uv->tt = LUA_TUPVAL; - uv->v = &uv->u.value; - uv->u.l.prev = NULL; - uv->u.l.next = NULL; - - setobj(luaState, uv->v, getObject(luaState, stackPos)); - - return uv; -} - -/** - * The GC is not fond of finding upvalues in tables. We get around this - * during persistence using a weakly keyed table, so that the GC doesn't - * bother to mark them. This won't work in unpersisting, however, since - * if we make the values weak they'll be collected (since nothing else - * references them). Our solution, during unpersisting, is to represent - * upvalues as dummy functions, each with one upvalue. - */ -static void boxupval_start(lua_State *luaState) { - LClosure *closure; - closure = (LClosure *)lua_newLclosure(luaState, 1, hvalue(&luaState->l_gt)); - pushClosure(luaState, (Closure *)closure); - // >>>>> ...... func - closure->p = makeFakeProto(luaState, 1); - - // Temporarily initialize the upvalue to nil - lua_pushnil(luaState); - closure->upvals[0] = makeUpVal(luaState, -1); - lua_pop(luaState, 1); -} - -static void boxupval_finish(lua_State *luaState) { - // >>>>> ...... func obj - LClosure *lcl = (LClosure *)clvalue(getObject(luaState, -2)); - - lcl->upvals[0]->u.value = *getObject(luaState, -1); - lua_pop(luaState, 1); - // >>>>> ...... func -} - void unserializeUpValue(UnSerializationInfo *info, int index) { // >>>>> permTbl indexTbl ...... - lua_checkstack(upi->L, 2); + lua_checkstack(info->luaState, 2); - boxupval_start(upi->L); + boxUpValue_start(info->luaState); // >>>>> permTbl indexTbl ...... func registerObjectInIndexTable(info, index); - unserializeObject(info); + unserialize(info); // >>>>> permTbl indexTbl ...... func obj - boxupval_finish(upi->L); + boxUpValue_finish(info->luaState); // >>>>> permTbl indexTbl ...... func } @@ -970,7 +660,7 @@ void unserializeUserData(UnSerializationInfo *info, int index) { int isspecial = info->readStream->readSint32LE(); if (isspecial) { - unserializeObject(info); + unserialize(info); // >>>>> permTbl indexTbl ...... specialFunc lua_call(info->luaState, 0, 1); @@ -981,12 +671,12 @@ void unserializeUserData(UnSerializationInfo *info, int index) { // >>>>> permTbl indexTbl ...... udata registerObjectInIndexTable(info, index); - info->readStream->read(lua_touserdata(upi->L, -1), length); + info->readStream->read(lua_touserdata(info->luaState, -1), length); - unserializeObject(info); + unserialize(info); // >>>>> permTbl indexTbl ...... udata metaTable/nil - lua_setmetatable(upi->L, -2); + lua_setmetatable(info->luaState, -2); // >>>>> permTbl indexTbl ...... udata } // >>>>> permTbl indexTbl ...... udata @@ -998,7 +688,7 @@ void unserializePermanent(UnSerializationInfo *info, int index) { // Make sure there is enough room on the stack lua_checkstack(info->luaState, 2); - unserializeObject(info); + unserialize(info); // >>>>> permTbl indexTbl ...... permKey lua_gettable(info->luaState, 1); -- cgit v1.2.3 From 0b8482b55fb38147927d2c27478aae59c0f98dab Mon Sep 17 00:00:00 2001 From: RichieSams Date: Tue, 30 Dec 2014 13:42:02 -0600 Subject: SWORD25: Update module.mk with lua serialization changes --- engines/sword25/module.mk | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sword25/module.mk b/engines/sword25/module.mk index 234baec165..0135f53783 100644 --- a/engines/sword25/module.mk +++ b/engines/sword25/module.mk @@ -82,9 +82,10 @@ MODULE_OBJS := \ util/lua/lvm.o \ util/lua/lzio.o \ util/lua/scummvm_file.o \ - util/pluto/pdep.o \ - util/pluto/pluto.o \ - util/pluto/plzio.o + util/double_serializer.o \ + util/lua_serialization_util.o \ + util/lua_serializer.o \ + util/lua_unserializer.o # This module can be built as a plugin ifeq ($(ENABLE_SWORD25), DYNAMIC_PLUGIN) -- cgit v1.2.3 From a188b31d15711bd86725ca4feb0dc36fb2ab71ac Mon Sep 17 00:00:00 2001 From: RichieSams Date: Tue, 30 Dec 2014 13:42:45 -0600 Subject: SWORD25: Use new lua serialization functions to persist state --- engines/sword25/kernel/outputpersistenceblock.cpp | 7 +++ engines/sword25/kernel/outputpersistenceblock.h | 1 + engines/sword25/script/luascript.cpp | 61 +++++------------------ 3 files changed, 20 insertions(+), 49 deletions(-) (limited to 'engines') diff --git a/engines/sword25/kernel/outputpersistenceblock.cpp b/engines/sword25/kernel/outputpersistenceblock.cpp index 9003b5d58a..3e25fce5c7 100644 --- a/engines/sword25/kernel/outputpersistenceblock.cpp +++ b/engines/sword25/kernel/outputpersistenceblock.cpp @@ -41,6 +41,13 @@ OutputPersistenceBlock::OutputPersistenceBlock() { _data.reserve(INITIAL_BUFFER_SIZE); } +void OutputPersistenceBlock::write(const void *data, uint32 size) { + writeMarker(BLOCK_MARKER); + + write(size); + rawWrite(data, size); +} + void OutputPersistenceBlock::write(int32 value) { writeMarker(SINT_MARKER); value = TO_LE_32(value); diff --git a/engines/sword25/kernel/outputpersistenceblock.h b/engines/sword25/kernel/outputpersistenceblock.h index c7d8dfc6aa..bdbd20d3e0 100644 --- a/engines/sword25/kernel/outputpersistenceblock.h +++ b/engines/sword25/kernel/outputpersistenceblock.h @@ -41,6 +41,7 @@ class OutputPersistenceBlock : public PersistenceBlock { public: OutputPersistenceBlock(); + void write(const void *data, uint32 size); void write(int32 value); void write(uint32 value); void write(float value); diff --git a/engines/sword25/script/luascript.cpp b/engines/sword25/script/luascript.cpp index f62a08005b..6cf287c643 100644 --- a/engines/sword25/script/luascript.cpp +++ b/engines/sword25/script/luascript.cpp @@ -29,7 +29,7 @@ * */ -#include "common/array.h" +#include "common/memstream.h" #include "common/debug-channels.h" #include "sword25/sword25.h" @@ -43,7 +43,7 @@ #include "sword25/util/lua/lua.h" #include "sword25/util/lua/lualib.h" #include "sword25/util/lua/lauxlib.h" -#include "sword25/util/pluto/pluto.h" +#include "sword25/util/lua_serialization.h" namespace Sword25 { @@ -112,10 +112,6 @@ bool LuaScriptEngine::init() { // Place the error handler function in the Lua registry, and remember the index _pcallErrorhandlerRegistryIndex = luaL_ref(_state, LUA_REGISTRYINDEX); - // Initialize the Pluto-Persistence library - luaopen_pluto(_state); - lua_pop(_state, 1); - // Initialize debugging callback if (DebugMan.isDebugChannelEnabled(kDebugScript)) { int mask = 0; @@ -383,19 +379,8 @@ bool pushPermanentsTable(lua_State *L, PERMANENT_TABLE_TYPE tableType) { return true; } -} - -namespace { -int chunkwriter(lua_State *L, const void *p, size_t sz, void *ud) { - Common::Array & chunkData = *reinterpret_cast * >(ud); - const byte *buffer = reinterpret_cast(p); - while (sz--) - chunkData.push_back(*buffer++); - - return 1; -} -} +} // End of anonymous namespace bool LuaScriptEngine::persist(OutputPersistenceBlock &writer) { // Empty the Lua stack. pluto_persist() xepects that the stack is empty except for its parameters @@ -409,12 +394,12 @@ bool LuaScriptEngine::persist(OutputPersistenceBlock &writer) { pushPermanentsTable(_state, PTT_PERSIST); lua_getglobal(_state, "_G"); - // Lua persists and stores the data in a Common::Array - Common::Array chunkData; - pluto_persist(_state, chunkwriter, &chunkData); + // Lua persists and stores the data in a WriteStream + Common::MemoryWriteStreamDynamic writeStream; + Lua::serializeLua(_state, &writeStream); // Persistenzdaten in den Writer schreiben. - writer.writeByteArray(chunkData); + writer.write(writeStream.getData(), writeStream.size()); // Die beiden Tabellen vom Stack nehmen. lua_pop(_state, 2); @@ -424,24 +409,6 @@ bool LuaScriptEngine::persist(OutputPersistenceBlock &writer) { namespace { -struct ChunkreaderData { - void *BufferPtr; - size_t Size; - bool BufferReturned; -}; - -const char *chunkreader(lua_State *L, void *ud, size_t *sz) { - ChunkreaderData &cd = *reinterpret_cast(ud); - - if (!cd.BufferReturned) { - cd.BufferReturned = true; - *sz = cd.Size; - return reinterpret_cast(cd.BufferPtr); - } else { - return 0; - } -} - void clearGlobalTable(lua_State *L, const char **exceptions) { // Iterate over all elements of the global table lua_pushvalue(L, LUA_GLOBALSINDEX); @@ -479,7 +446,8 @@ void clearGlobalTable(lua_State *L, const char **exceptions) { // Perform garbage collection, so that all removed elements are deleted lua_gc(L, LUA_GCCOLLECT, 0); } -} + +} // End of anonymous namespace bool LuaScriptEngine::unpersist(InputPersistenceBlock &reader) { // Empty the Lua stack. pluto_persist() xepects that the stack is empty except for its parameters @@ -512,14 +480,9 @@ bool LuaScriptEngine::unpersist(InputPersistenceBlock &reader) { // Persisted Lua data Common::Array chunkData; reader.readByteArray(chunkData); + Common::MemoryReadStream readStream(&chunkData[0], chunkData.size(), DisposeAfterUse::NO); - // Chunk-Reader initialisation. It is used with pluto_unpersist to restore read data - ChunkreaderData cd; - cd.BufferPtr = &chunkData[0]; - cd.Size = chunkData.size(); - cd.BufferReturned = false; - - pluto_unpersist(_state, chunkreader, &cd); + Lua::unserializeLua(_state, &readStream); // Permanents-Table is removed from stack lua_remove(_state, -2); @@ -527,7 +490,7 @@ bool LuaScriptEngine::unpersist(InputPersistenceBlock &reader) { // The read elements in the global table about lua_pushnil(_state); while (lua_next(_state, -2) != 0) { - // The referenec to the global table (_G) must not be overwritten, or ticks from Lua total + // The reference to the global table (_G) must not be overwritten, or ticks from Lua total bool isGlobalReference = lua_isstring(_state, -2) && strcmp(lua_tostring(_state, -2), "_G") == 0; if (!isGlobalReference) { lua_pushvalue(_state, -2); -- cgit v1.2.3 From 97c35714ce3986b99848a780f6b195a63f8910b7 Mon Sep 17 00:00:00 2001 From: RichieSams Date: Tue, 30 Dec 2014 15:19:29 -0600 Subject: SWORD25: Rename lua serialization functions to use 'persist' in order to match the rest of the engine --- engines/sword25/module.mk | 6 +- engines/sword25/script/luascript.cpp | 6 +- engines/sword25/util/lua_persist.cpp | 787 ++++++++++++++++++++++++ engines/sword25/util/lua_persistence.h | 44 ++ engines/sword25/util/lua_persistence_util.cpp | 346 +++++++++++ engines/sword25/util/lua_persistence_util.h | 98 +++ engines/sword25/util/lua_serialization.h | 44 -- engines/sword25/util/lua_serialization_util.cpp | 346 ----------- engines/sword25/util/lua_serialization_util.h | 98 --- engines/sword25/util/lua_serializer.cpp | 787 ------------------------ engines/sword25/util/lua_unpersist.cpp | 698 +++++++++++++++++++++ engines/sword25/util/lua_unserializer.cpp | 698 --------------------- 12 files changed, 1979 insertions(+), 1979 deletions(-) create mode 100644 engines/sword25/util/lua_persist.cpp create mode 100644 engines/sword25/util/lua_persistence.h create mode 100644 engines/sword25/util/lua_persistence_util.cpp create mode 100644 engines/sword25/util/lua_persistence_util.h delete mode 100644 engines/sword25/util/lua_serialization.h delete mode 100644 engines/sword25/util/lua_serialization_util.cpp delete mode 100644 engines/sword25/util/lua_serialization_util.h delete mode 100644 engines/sword25/util/lua_serializer.cpp create mode 100644 engines/sword25/util/lua_unpersist.cpp delete mode 100644 engines/sword25/util/lua_unserializer.cpp (limited to 'engines') diff --git a/engines/sword25/module.mk b/engines/sword25/module.mk index 0135f53783..129b4f040e 100644 --- a/engines/sword25/module.mk +++ b/engines/sword25/module.mk @@ -83,9 +83,9 @@ MODULE_OBJS := \ util/lua/lzio.o \ util/lua/scummvm_file.o \ util/double_serializer.o \ - util/lua_serialization_util.o \ - util/lua_serializer.o \ - util/lua_unserializer.o + util/lua_persistence_util.o \ + util/lua_persist.o \ + util/lua_unpersist.o # This module can be built as a plugin ifeq ($(ENABLE_SWORD25), DYNAMIC_PLUGIN) diff --git a/engines/sword25/script/luascript.cpp b/engines/sword25/script/luascript.cpp index 6cf287c643..e93289596b 100644 --- a/engines/sword25/script/luascript.cpp +++ b/engines/sword25/script/luascript.cpp @@ -43,7 +43,7 @@ #include "sword25/util/lua/lua.h" #include "sword25/util/lua/lualib.h" #include "sword25/util/lua/lauxlib.h" -#include "sword25/util/lua_serialization.h" +#include "sword25/util/lua_persistence.h" namespace Sword25 { @@ -396,7 +396,7 @@ bool LuaScriptEngine::persist(OutputPersistenceBlock &writer) { // Lua persists and stores the data in a WriteStream Common::MemoryWriteStreamDynamic writeStream; - Lua::serializeLua(_state, &writeStream); + Lua::persistLua(_state, &writeStream); // Persistenzdaten in den Writer schreiben. writer.write(writeStream.getData(), writeStream.size()); @@ -482,7 +482,7 @@ bool LuaScriptEngine::unpersist(InputPersistenceBlock &reader) { reader.readByteArray(chunkData); Common::MemoryReadStream readStream(&chunkData[0], chunkData.size(), DisposeAfterUse::NO); - Lua::unserializeLua(_state, &readStream); + Lua::unpersistLua(_state, &readStream); // Permanents-Table is removed from stack lua_remove(_state, -2); diff --git a/engines/sword25/util/lua_persist.cpp b/engines/sword25/util/lua_persist.cpp new file mode 100644 index 0000000000..b9c0b13e11 --- /dev/null +++ b/engines/sword25/util/lua_persist.cpp @@ -0,0 +1,787 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "sword25/util/lua_persistence.h" + +#include "sword25/util/double_serializer.h" +#include "sword25/util/lua_persistence_util.h" + +#include "common/stream.h" + +#include "lua/lobject.h" +#include "lua/lstate.h" +#include "lua/lgc.h" + + +namespace Lua { + +#define PERMANENT_TYPE 101 + +struct SerializationInfo { + lua_State *luaState; + Common::WriteStream *writeStream; + uint counter; +}; + +static void serialize(SerializationInfo *info); + +static void serializeBoolean(SerializationInfo *info); +static void serializeNumber(SerializationInfo *info); +static void serializeString(SerializationInfo *info); +static void serializeTable(SerializationInfo *info); +static void serializeFunction(SerializationInfo *info); +static void serializeThread(SerializationInfo *info); +static void serializeProto(SerializationInfo *info); +static void serializeUpValue(SerializationInfo *info); +static void serializeUserData(SerializationInfo *info); + + +void persistLua(lua_State *luaState, Common::WriteStream *writeStream) { + SerializationInfo info; + info.luaState = luaState; + info.writeStream = writeStream; + info.counter = 0u; + + // The process starts with the lua stack as follows: + // >>>>> permTbl rootObj + // That's the table of permanents and the root object to be serialized + + // Make sure there is enough room on the stack + lua_checkstack(luaState, 4); + assert(lua_gettop(luaState) == 2); + // And that the root isn't nil + assert(!lua_isnil(luaState, 2)); + + // Create a table to hold indexes of everything that's serialized + // This allows us to only serialize an object once + // Every other time, just reference the index + lua_newtable(luaState); + // >>>>> permTbl rootObj indexTbl + + // Now we're going to make the table weakly keyed. This prevents the + // GC from visiting it and trying to mark things it doesn't want to + // mark in tables, e.g. upvalues. All objects in the table are + // a priori reachable, so it doesn't matter that we do this. + + // Create the metatable + lua_newtable(luaState); + // >>>>> permTbl rootObj indexTbl metaTbl + + lua_pushstring(luaState, "__mode"); + // >>>>> permTbl rootObj indexTbl metaTbl "__mode" + + lua_pushstring(luaState, "k"); + // >>>>> permTbl rootObj indexTbl metaTbl "__mode" "k" + + lua_settable(luaState, 4); + // >>>>> permTbl rootObj indexTbl metaTbl + + lua_setmetatable(luaState, 3); + // >>>>> permTbl rootObj indexTbl + + // Swap the indexTable and the rootObj + lua_insert(luaState, 2); + // >>>>> permTbl indexTbl rootObj + + // Serialize the root recursively + serialize(&info); + + // Return the stack back to the original state + lua_remove(luaState, 2); + // >>>>> permTbl rootObj +} + +static void serialize(SerializationInfo *info) { + // The stack can potentially have many things on it + // The object we want to serialize is the item on the top of the stack + // >>>>> permTbl indexTbl rootObj ...... obj + + // Make sure there is enough room on the stack + lua_checkstack(info->luaState, 2); + + // If the object has already been written, don't write it again + // Instead write the index of the object from the indexTbl + + // Check the indexTbl + lua_pushvalue(info->luaState, -1); + // >>>>> permTbl indexTbl rootObj ...... obj obj + + lua_rawget(info->luaState, 2); + // >>>>> permTbl indexTbl rootObj ...... obj ?index? + + // If the index isn't nil, the object has already been written + if (!lua_isnil(info->luaState, -1)) { + // Write out a flag that indicates that it's an index + info->writeStream->writeByte(0); + + // Retrieve the index from the stack + uint *index = (uint *)lua_touserdata(info->luaState, -1); + + // Write out the index + info->writeStream->writeUint32LE(*index); + + // Pop the index off the stack + lua_pop(info->luaState, 1); + + return; + } + + // Pop the nil off the stack + lua_pop(info->luaState, 1); + + // Write out a flag that indicates that this is a real object + info->writeStream->writeByte(1); + + // If the object itself is nil, then write out a zero as a placeholder + if (lua_isnil(info->luaState, -1)) { + info->writeStream->writeByte(0); + + return; + } + + // Add the object to the indexTbl + + lua_pushvalue(info->luaState, -1); + // >>>>> permTbl indexTbl rootObj ...... obj obj + + uint *ref = (uint *)lua_newuserdata(info->luaState, sizeof(uint)); + *ref = ++(info->counter); + // >>>>> permTbl indexTbl rootObj ...... obj obj index + + lua_rawset(info->luaState, 2); + // >>>>> permTbl indexTbl rootObj ...... obj + + + // Write out the index + info->writeStream->writeUint32LE(info->counter); + + + // Objects that are in the permanents table are serialized in a special way + + lua_pushvalue(info->luaState, -1); + // >>>>> permTbl indexTbl rootObj ...... obj obj + + lua_gettable(info->luaState, 1); + // >>>>> permTbl indexTbl rootObj ...... obj obj ?permKey? + + if (!lua_isnil(info->luaState, -1)) { + // Write out the type + info->writeStream->writeSint32LE(PERMANENT_TYPE); + + // Serialize the key + serialize(info); + + // Pop the key off the stack + lua_pop(info->luaState, 1); + + return; + } + + // Pop the nil off the stack + lua_pop(info->luaState, 1); + + // Query the type of the object + int objType = lua_type(info->luaState, -1); + + // Write it out + info->writeStream->writeSint32LE(objType); + + // Serialize the object by its type + + switch (objType) { + case LUA_TBOOLEAN: + serializeBoolean(info); + break; + case LUA_TLIGHTUSERDATA: + // You can't serialize a pointer + // It would be meaningless on the next run + assert(0); + break; + case LUA_TNUMBER: + serializeNumber(info); + break; + case LUA_TSTRING: + serializeString(info); + break; + case LUA_TTABLE: + serializeTable(info); + break; + case LUA_TFUNCTION: + serializeFunction(info); + break; + case LUA_TTHREAD: + serializeThread(info); + break; + case LUA_TPROTO: + serializeProto(info); + break; + case LUA_TUPVAL: + serializeUpValue(info); + break; + case LUA_TUSERDATA: + serializeUserData(info); + break; + default: + assert(0); + } +} + +static void serializeBoolean(SerializationInfo *info) { + int value = lua_toboolean(info->luaState, -1); + + info->writeStream->writeSint32LE(value); +} + +static void serializeNumber(SerializationInfo *info) { + lua_Number value = lua_tonumber(info->luaState, -1); + + #if 1 + Util::SerializedDouble serializedValue(Util::encodeDouble(value)); + + info->writeStream->writeUint32LE(serializedValue.significandOne); + info->writeStream->writeUint32LE(serializedValue.signAndSignificandTwo); + info->writeStream->writeSint16LE(serializedValue.exponent); + #else + // NOTE: We need to store a double. Unfortunately, we have to accommodate endianness. + // Also, I don't know if we can assume all compilers use IEEE double + // Therefore, I have chosen to store the double as a string. + Common::String buffer = Common::String::format("%f", value); + + info->writeStream->write(buffer.c_str(), buffer.size()); + #endif + +} + +static void serializeString(SerializationInfo *info) { + // Hard cast to a uint32 to force size_t to an explicit size + // *Theoretically* this could truncate, but if we have a 4gb string, we have bigger problems + uint32 length = static_cast(lua_strlen(info->luaState, -1)); + info->writeStream->writeUint32LE(length); + + const char *str = lua_tostring(info->luaState, -1); + info->writeStream->write(str, length); +} + +/* Choose whether to do a regular or special persistence based on an object's + * metatable. "default" is whether the object, if it doesn't have a __persist + * entry, is literally persistable or not. + * Pushes the unpersist closure and returns true if special persistence is + * used. */ +static bool serializeSpecialObject(SerializationInfo *info, bool defaction) { + // Make sure there is enough room on the stack + lua_checkstack(info->luaState, 4); + + // Check whether we should persist literally, or via the __persist metafunction + if (!lua_getmetatable(info->luaState, -1)) { + if (defaction) { + // Write out a flag declaring that the object isn't special and should be persisted normally + info->writeStream->writeSint32LE(0); + + return false; + } else { + lua_pushstring(info->luaState, "Type not literally persistable by default"); + lua_error(info->luaState); + + return false; // Not reached + } + } + + // >>>>> permTbl indexTbl ...... obj metaTbl + lua_pushstring(info->luaState, "__persist"); + // >>>>> permTbl indexTbl rootObj ...... obj metaTbl "__persist" + + lua_rawget(info->luaState, -2); + // >>>>> permTbl indexTbl ...... obj metaTbl ?__persist? + + if (lua_isnil(info->luaState, -1)) { + // >>>>> permTbl indexTbl ...... obj metaTbl nil + lua_pop(info->luaState, 2); + // >>>>> permTbl indexTbl ...... obj + + if (defaction) { + // Write out a flag declaring that the object isn't special and should be persisted normally + info->writeStream->writeSint32LE(0); + + return false; + } else { + lua_pushstring(info->luaState, "Type not literally persistable by default"); + lua_error(info->luaState); + + return false; // Return false + } + + } else if (lua_isboolean(info->luaState, -1)) { + // >>>>> permTbl indexTbl ...... obj metaTbl bool + if (lua_toboolean(info->luaState, -1)) { + // Write out a flag declaring that the object isn't special and should be persisted normally + info->writeStream->writeSint32LE(0); + + // >>>>> permTbl indexTbl ...... obj metaTbl true */ + lua_pop(info->luaState, 2); + // >>>>> permTbl indexTbl ...... obj + + return false; + } else { + lua_pushstring(info->luaState, "Metatable forbade persistence"); + lua_error(info->luaState); + + return false; // Not reached + } + } else if (!lua_isfunction(info->luaState, -1)) { + lua_pushstring(info->luaState, "__persist not nil, boolean, or function"); + lua_error(info->luaState); + } + + // >>>>> permTbl indexTbl ...... obj metaTbl __persist + lua_pushvalue(info->luaState, -3); + // >>>>> permTbl indexTbl ...... obj metaTbl __persist obj + + // >>>>> permTbl indexTbl ...... obj metaTbl ?func? + + if (!lua_isfunction(info->luaState, -1)) { + lua_pushstring(info->luaState, "__persist function did not return a function"); + lua_error(info->luaState); + } + + // >>>>> permTbl indexTbl ...... obj metaTbl func + + // Write out a flag that the function exists + info->writeStream->writeSint32LE(1); + + // Serialize the function + serialize(info); + + lua_pop(info->luaState, 2); + // >>>>> permTbl indexTbl ...... obj + + return true; +} + +static void serializeTable(SerializationInfo *info) { + // >>>>> permTbl indexTbl ...... tbl + + // Make sure there is enough room on the stack + lua_checkstack(info->luaState, 3); + + // Test if the object needs special serialization + if (serializeSpecialObject(info, 1)) { + return; + } + + // >>>>> permTbl indexTbl ...... tbl + + // First, serialize the metatable (if any) + if (!lua_getmetatable(info->luaState, -1)) { + lua_pushnil(info->luaState); + } + + // >>>>> permTbl indexTbl ...... tbl metaTbl/nil */ + serialize(info); + + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... tbl + + + lua_pushnil(info->luaState); + // >>>>> permTbl indexTbl ...... tbl nil + + // Now, persist all k/v pairs + while (lua_next(info->luaState, -2)) { + // >>>>> permTbl indexTbl ...... tbl k v */ + + lua_pushvalue(info->luaState, -2); + // >>>>> permTbl indexTbl ...... tbl k v k */ + + // Serialize the key + serialize(info); + + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... tbl k v */ + + // Serialize the value + serialize(info); + + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... tbl k */ + } + + // >>>>> permTbl indexTbl ...... tbl + + // Terminate the list with a nil + lua_pushnil(info->luaState); + // >>>>> permTbl indexTbl ...... tbl + + serialize(info); + + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... tbl +} + +static void serializeFunction(SerializationInfo *info) { + // >>>>> permTbl indexTbl ...... func + Closure *cl = clvalue(getObject(info->luaState, -1)); + lua_checkstack(info->luaState, 2); + + if (cl->c.isC) { + /* It's a C function. For now, we aren't going to allow + * persistence of C closures, even if the "C proto" is + * already in the permanents table. */ + lua_pushstring(info->luaState, "Attempt to persist a C function"); + lua_error(info->luaState); + } else { + // It's a Lua closure + + // We don't really _NEED_ the number of upvals, but it'll simplify things a bit + info->writeStream->writeByte(cl->l.p->nups); + + // Serialize the prototype + pushProto(info->luaState, cl->l.p); + // >>>>> permTbl indexTbl ...... func proto */ + + serialize(info); + + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... func + + // Serialize upvalue values (not the upvalue objects themselves) + for (byte i = 0; i < cl->l.p->nups; i++) { + // >>>>> permTbl indexTbl ...... func + pushUpValue(info->luaState, cl->l.upvals[i]); + // >>>>> permTbl indexTbl ...... func upval + + serialize(info); + + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... func + } + + // >>>>> permTbl indexTbl ...... func + + // Serialize function environment + lua_getfenv(info->luaState, -1); + // >>>>> permTbl indexTbl ...... func fenv + + if (lua_equal(info->luaState, -1, LUA_GLOBALSINDEX)) { + // Function has the default fenv + + // >>>>> permTbl indexTbl ...... func _G + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... func + + lua_pushnil(info->luaState); + // >>>>> permTbl indexTbl ...... func nil + } + + // >>>>> permTbl indexTbl ...... func fenv/nil + serialize(info); + + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... func + } +} + +static void serializeThread(SerializationInfo *info) { + // >>>>> permTbl indexTbl ...... thread + lua_State *threadState = lua_tothread(info->luaState, -1); + + // Make sure there is enough room on the stack + lua_checkstack(info->luaState, threadState->top - threadState->stack + 1); + + if (info->luaState == threadState) { + lua_pushstring(info->luaState, "Can't persist currently running thread"); + lua_error(info->luaState); + return; /* not reached */ + } + + // Persist the stack + + // We *could* have truncation here, but if we have more than 4 billion items on a stack, we have bigger problems + uint32 stackSize = static_cast(appendStackToStack_reverse(threadState, info->luaState)); + info->writeStream->writeUint32LE(stackSize); + + // >>>>> permTbl indexTbl ...... thread (reversed contents of thread stack) */ + for (; stackSize > 0; --stackSize) { + serialize(info); + + lua_pop(info->luaState, 1); + } + + // >>>>> permTbl indexTbl ...... thread + + // Now, serialize the CallInfo stack + + // Again, we *could* have truncation here, but if we have more than 4 billion items on a stack, we have bigger problems + uint32 numFrames = static_cast((threadState->ci - threadState->base_ci) + 1); + info->writeStream->writeUint32LE(numFrames); + + for (uint32 i = 0; i < numFrames; i++) { + CallInfo *ci = threadState->base_ci + i; + + // Same argument as above about truncation + uint32 stackBase = static_cast(ci->base - threadState->stack); + uint32 stackFunc = static_cast(ci->func - threadState->stack); + uint32 stackTop = static_cast(ci->top - threadState->stack); + + info->writeStream->writeUint32LE(stackBase); + info->writeStream->writeUint32LE(stackFunc); + info->writeStream->writeUint32LE(stackTop); + + info->writeStream->writeSint32LE(ci->nresults); + + uint32 savedpc = (ci != threadState->base_ci) ? static_cast(ci->savedpc - ci_func(ci)->l.p->code) : 0u; + info->writeStream->writeUint32LE(savedpc); + } + + + // Serialize the state's other parameters, with the exception of upval stuff + + assert(threadState->nCcalls <= 1); + info->writeStream->writeByte(threadState->status); + + // Same argument as above about truncation + uint32 stackBase = static_cast(threadState->base - threadState->stack); + uint32 stackFunc = static_cast(threadState->top - threadState->stack); + info->writeStream->writeUint32LE(stackBase); + info->writeStream->writeUint32LE(stackFunc); + + // Same argument as above about truncation + uint32 stackOffset = static_cast(threadState->errfunc); + info->writeStream->writeUint32LE(stackOffset); + + // Finally, record upvalues which need to be reopened + // See the comment above serializeUpVal() for why we do this + + UpVal *upVal; + + // >>>>> permTbl indexTbl ...... thread + for (GCObject *gcObject = threadState->openupval; gcObject != NULL; gcObject = upVal->next) { + upVal = gco2uv(gcObject); + + /* Make sure upvalue is really open */ + assert(upVal->v != &upVal->u.value); + + pushUpValue(info->luaState, upVal); + // >>>>> permTbl indexTbl ...... thread upVal + + serialize(info); + + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... thread + + // Same argument as above about truncation + uint32 stackpos = static_cast(upVal->v - threadState->stack); + info->writeStream->writeUint32LE(stackpos); + } + + // >>>>> permTbl indexTbl ...... thread + lua_pushnil(info->luaState); + // >>>>> permTbl indexTbl ...... thread nil + + // Use nil as a terminator + serialize(info); + + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... thread +} + +static void serializeProto(SerializationInfo *info) { + // >>>>> permTbl indexTbl ...... proto + Proto *proto = gco2p(getObject(info->luaState, -1)->value.gc); + + // Make sure there is enough room on the stack + lua_checkstack(info->luaState, 2); + + // Serialize constant refs */ + info->writeStream->writeSint32LE(proto->sizek); + + for (int i = 0; i < proto->sizek; ++i) { + pushObject(info->luaState, &proto->k[i]); + // >>>>> permTbl indexTbl ...... proto const + + serialize(info); + + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... proto + } + + // >>>>> permTbl indexTbl ...... proto + + // Serialize inner Proto refs + info->writeStream->writeSint32LE(proto->sizep); + + for (int i = 0; i < proto->sizep; ++i) + { + pushProto(info->luaState, proto->p[i]); + // >>>>> permTbl indexTbl ...... proto subProto */ + + serialize(info); + + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... proto + } + + // >>>>> permTbl indexTbl ...... proto + + // Serialize the code + info->writeStream->writeSint32LE(proto->sizecode); + + uint32 len = static_cast(sizeof(Instruction) * proto->sizecode); + info->writeStream->write(proto->code, len); + + + // Serialize upvalue names + info->writeStream->writeSint32LE(proto->sizeupvalues); + + for (int i = 0; i < proto->sizeupvalues; ++i) + { + pushString(info->luaState, proto->upvalues[i]); + // >>>>> permTbl indexTbl ...... proto str + + serialize(info); + + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... proto + } + + + // Serialize local variable infos + info->writeStream->writeSint32LE(proto->sizelocvars); + + for (int i = 0; i < proto->sizelocvars; ++i) { + pushString(info->luaState, proto->locvars[i].varname); + // >>>>> permTbl indexTbl ...... proto str + + serialize(info); + + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... proto + + info->writeStream->writeSint32LE(proto->locvars[i].startpc); + info->writeStream->writeSint32LE(proto->locvars[i].endpc); + } + + + // Serialize source string + pushString(info->luaState, proto->source); + // >>>>> permTbl indexTbl ...... proto sourceStr + + serialize(info); + + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... proto + + // Serialize line numbers + info->writeStream->writeSint32LE(proto->sizelineinfo); + + if (proto->sizelineinfo) { + uint32 len = static_cast(sizeof(int) * proto->sizelineinfo); + info->writeStream->write(proto->lineinfo, len); + } + + // Serialize linedefined and lastlinedefined + info->writeStream->writeSint32LE(proto->linedefined); + info->writeStream->writeSint32LE(proto->lastlinedefined); + + + // Serialize misc values + info->writeStream->writeByte(proto->nups); + info->writeStream->writeByte(proto->numparams); + info->writeStream->writeByte(proto->is_vararg); + info->writeStream->writeByte(proto->maxstacksize); +} + +/* Upvalues are tricky. Here's why. + * + * A particular upvalue may be either "open", in which case its member v + * points into a thread's stack, or "closed" in which case it points to the + * upvalue itself. An upvalue is closed under any of the following conditions: + * -- The function that initially declared the variable "local" returns + * -- The thread in which the closure was created is garbage collected + * + * To make things wackier, just because a thread is reachable by Lua doesn't + * mean it's in our root set. We need to be able to treat an open upvalue + * from an unreachable thread as a closed upvalue. + * + * The solution: + * (a) For the purposes of serializing, don't indicate whether an upvalue is + * closed or not. + * (b) When unserializing, pretend that all upvalues are closed. + * (c) When serializing, persist all open upvalues referenced by a thread + * that is persisted, and tag each one with the corresponding stack position + * (d) When unserializing, "reopen" each of these upvalues as the thread is + * unserialized + */ +static void serializeUpValue(SerializationInfo *info) { + // >>>>> permTbl indexTbl ...... upval + assert(ttype(getObject(info->luaState, -1)) == LUA_TUPVAL); + UpVal *upValue = gco2uv(getObject(info->luaState, -1)->value.gc); + + // Make sure there is enough room on the stack + lua_checkstack(info->luaState, 1); + + // We can't permit the upValue to linger around on the stack, as Lua + // will bail if its GC finds it. + + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... + + pushObject(info->luaState, upValue->v); + // >>>>> permTbl indexTbl ...... obj + + serialize(info); + // >>>>> permTbl indexTbl ...... obj +} + +static void serializeUserData(SerializationInfo *info) { + // >>>>> permTbl rootObj ...... udata + + // Make sure there is enough room on the stack + lua_checkstack(info->luaState, 2); + + // Test if the object needs special serialization + if (serializeSpecialObject(info, 0)) { + return; + } + + // Use literal persistence + + // Hard cast to a uint32 length + // This could lead to truncation, but if we have a 4gb block of data, we have bigger problems + uint32 length = static_cast(uvalue(getObject(info->luaState, -1))->len); + info->writeStream->writeUint32LE(length); + + info->writeStream->write(lua_touserdata(info->luaState, -1), length); + + // Serialize the metatable (if any) + if (!lua_getmetatable(info->luaState, -1)) { + lua_pushnil(info->luaState); + } + + // >>>>> permTbl rootObj ...... udata metaTbl/nil + serialize(info); + + lua_pop(info->luaState, 1); + /* perms reftbl ... udata */ +} + + +} // End of namespace Lua diff --git a/engines/sword25/util/lua_persistence.h b/engines/sword25/util/lua_persistence.h new file mode 100644 index 0000000000..cf7d7e03ca --- /dev/null +++ b/engines/sword25/util/lua_persistence.h @@ -0,0 +1,44 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef LUA_SERIALIZATION_H +#define LUA_SERIALIZATION_H + +#include "sword25/util/lua/lua.h" + + +namespace Common { +class WriteStream; +class ReadStream; +} + + +namespace Lua { + +#define PERMANENT_TYPE 101 + +void persistLua(lua_State *luaState, Common::WriteStream *writeStream); +void unpersistLua(lua_State *luaState, Common::ReadStream *readStream); + +} // End of namespace Lua + +#endif diff --git a/engines/sword25/util/lua_persistence_util.cpp b/engines/sword25/util/lua_persistence_util.cpp new file mode 100644 index 0000000000..8365f5d483 --- /dev/null +++ b/engines/sword25/util/lua_persistence_util.cpp @@ -0,0 +1,346 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distri8buted in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "sword25/util/lua_persistence_util.h" + +#include "common/scummsys.h" + +#include "lua/lobject.h" +#include "lua/lstate.h" +#include "lua/lgc.h" +#include "lua/lopcodes.h" + + +namespace Lua { + +void *lua_realloc(lua_State *luaState, void *block, size_t osize, size_t nsize) { + global_State *globalState = G(luaState); + + block = (*globalState->frealloc)(globalState->ud, block, osize, nsize); + globalState->totalbytes = (globalState->totalbytes - osize) + nsize; + + return block; +} + +void pushObject(lua_State *luaState, TValue *obj) { + setobj2s(luaState, luaState->top, obj); + + api_check(luaState, luaState->top < luaState->ci->top); + luaState->top++; +} + +void pushProto(lua_State *luaState, Proto *proto) { + TValue obj; + setptvalue(luaState, &obj, proto); + + pushObject(luaState, &obj); +} + +void pushUpValue(lua_State *luaState, UpVal *upval) { + TValue obj; + + obj.value.gc = cast(GCObject *, upval); + obj.tt = LUA_TUPVAL; + checkliveness(G(L), obj); + + pushObject(luaState, &obj); +} + +void pushString(lua_State *luaState, TString *str) { + TValue o; + setsvalue(luaState, &o, str); + + pushObject(luaState, &o); +} + +/* A simple reimplementation of the unfortunately static function luaA_index. + * Does not support the global table, registry, or upvalues. */ +StkId getObject(lua_State *luaState, int stackpos) { + if (stackpos > 0) { + lua_assert(luaState->base + stackpos - 1 < luaState->top); + return luaState->base + stackpos - 1; + } else { + lua_assert(L->top - stackpos >= L->base); + return luaState->top + stackpos; + } +} + +void lua_linkObjToGC(lua_State *luaState, GCObject *obj, lu_byte type) { + global_State *globalState = G(luaState); + + obj->gch.next = globalState->rootgc; + globalState->rootgc = obj; + obj->gch.marked = luaC_white(globalState); + obj->gch.tt = type; +} + +Closure *lua_newLclosure(lua_State *luaState, int numElements, Table *elementTable) { + Closure *c = (Closure *)lua_malloc(luaState, sizeLclosure(numElements)); + lua_linkObjToGC(luaState, obj2gco(c), LUA_TFUNCTION); + + c->l.isC = 0; + c->l.env = elementTable; + c->l.nupvalues = cast_byte(numElements); + + while (numElements--) { + c->l.upvals[numElements] = NULL; + } + + return c; +} + +void pushClosure(lua_State *luaState, Closure *closure) { + TValue obj; + setclvalue(luaState, &obj, closure); + pushObject(luaState, &obj); +} + +Proto *createProto(lua_State *luaState) { + Proto *newProto = (Proto *)lua_malloc(luaState, sizeof(Proto)); + lua_linkObjToGC(luaState, obj2gco(newProto), LUA_TPROTO); + + newProto->k = NULL; + newProto->sizek = 0; + newProto->p = NULL; + newProto->sizep = 0; + newProto->code = NULL; + newProto->sizecode = 0; + newProto->sizelineinfo = 0; + newProto->sizeupvalues = 0; + newProto->nups = 0; + newProto->upvalues = NULL; + newProto->numparams = 0; + newProto->is_vararg = 0; + newProto->maxstacksize = 0; + newProto->lineinfo = NULL; + newProto->sizelocvars = 0; + newProto->locvars = NULL; + newProto->linedefined = 0; + newProto->lastlinedefined = 0; + newProto->source = NULL; + + return newProto; +} + +TString *createString(lua_State *luaState, const char *str, size_t len) { + TString *res; + lua_pushlstring(luaState, str, len); + + res = rawtsvalue(luaState->top - 1); + lua_pop(luaState, 1); + + return res; +} + +Proto *makeFakeProto(lua_State *L, lu_byte nups) { + Proto *p = createProto(L); + + p->sizelineinfo = 1; + p->lineinfo = lua_newVector(L, 1, int); + p->lineinfo[0] = 1; + p->sizecode = 1; + p->code = lua_newVector(L, 1, Instruction); + p->code[0] = CREATE_ABC(OP_RETURN, 0, 1, 0); + p->source = createString(L, "", 0); + p->maxstacksize = 2; + p->nups = nups; + p->sizek = 0; + p->sizep = 0; + + return p; +} + +UpVal *createUpValue(lua_State *luaState, int stackpos) { + UpVal *upValue = (UpVal *)lua_malloc(luaState, sizeof(UpVal)); + lua_linkObjToGC(luaState, (GCObject *)upValue, LUA_TUPVAL); + upValue->tt = LUA_TUPVAL; + upValue->v = &upValue->u.value; + upValue->u.l.prev = NULL; + upValue->u.l.next = NULL; + + const TValue *o2 = (TValue *)getObject(luaState, stackpos); + upValue->v->value = o2->value; + upValue->v->tt = o2->tt; + checkliveness(G(L), upValue->v); + + return upValue; +} + +void unboxUpValue(lua_State *luaState) { + // >>>>> ...... func + LClosure *lcl; + UpVal *uv; + + lcl = (LClosure *)clvalue(getObject(luaState, -1)); + uv = lcl->upvals[0]; + + lua_pop(luaState, 1); + // >>>>> ...... + + pushUpValue(luaState, uv); + // >>>>> ...... upValue +} + +size_t appendStackToStack_reverse(lua_State *from, lua_State *to) { + for (StkId id = from->top - 1; id >= from->stack; --id) { + setobj2s(to, to->top, id); + to->top++; + } + + return from->top - from->stack; +} + +void correctStack(lua_State *L, TValue *oldstack) { + CallInfo *ci; + GCObject *up; + L->top = (L->top - oldstack) + L->stack; + for (up = L->openupval; up != NULL; up = up->gch.next) + gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack; + for (ci = L->base_ci; ci <= L->ci; ci++) { + ci->top = (ci->top - oldstack) + L->stack; + ci->base = (ci->base - oldstack) + L->stack; + ci->func = (ci->func - oldstack) + L->stack; + } + L->base = (L->base - oldstack) + L->stack; +} + +void lua_reallocstack(lua_State *L, int newsize) { + TValue *oldstack = L->stack; + int realsize = newsize + 1 + EXTRA_STACK; + + lua_reallocvector(L, L->stack, L->stacksize, realsize, TValue); + L->stacksize = realsize; + L->stack_last = L->stack + newsize; + correctStack(L, oldstack); +} + +void lua_growstack(lua_State *L, int n) { + // Double size is enough? + if (n <= L->stacksize) { + lua_reallocstack(L, 2 * L->stacksize); + } else { + lua_reallocstack(L, L->stacksize + n); + } +} + +void lua_reallocCallInfo(lua_State *lauState, int newsize) { + CallInfo *oldci = lauState->base_ci; + lua_reallocvector(lauState, lauState->base_ci, lauState->size_ci, newsize, CallInfo); + + lauState->size_ci = newsize; + lauState->ci = (lauState->ci - oldci) + lauState->base_ci; + lauState->end_ci = lauState->base_ci + lauState->size_ci - 1; +} + +void GCUnlink(lua_State *luaState, GCObject *gco) { + GCObject *prevslot; + if (G(luaState)->rootgc == gco) { + G(luaState)->rootgc = G(luaState)->rootgc->gch.next; + return; + } + + prevslot = G(luaState)->rootgc; + while (prevslot->gch.next != gco) { + prevslot = prevslot->gch.next; + } + + prevslot->gch.next = prevslot->gch.next->gch.next; +} + +TString *lua_newlstr(lua_State *luaState, const char *str, size_t len) { + lua_pushlstring(luaState, str, len); + TString *luaStr = &(luaState->top - 1)->value.gc->ts; + + lua_pop(luaState, 1); + + return luaStr; +} + +void lua_link(lua_State *luaState, GCObject *o, lu_byte tt) { + global_State *g = G(luaState); + o->gch.next = g->rootgc; + g->rootgc = o; + o->gch.marked = luaC_white(g); + o->gch.tt = tt; +} + +Proto *lua_newproto(lua_State *luaState) { + Proto *f = (Proto *)lua_malloc(luaState, sizeof(Proto)); + lua_link(luaState, obj2gco(f), LUA_TPROTO); + f->k = NULL; + f->sizek = 0; + f->p = NULL; + f->sizep = 0; + f->code = NULL; + f->sizecode = 0; + f->sizelineinfo = 0; + f->sizeupvalues = 0; + f->nups = 0; + f->upvalues = NULL; + f->numparams = 0; + f->is_vararg = 0; + f->maxstacksize = 0; + f->lineinfo = NULL; + f->sizelocvars = 0; + f->locvars = NULL; + f->linedefined = 0; + f->lastlinedefined = 0; + f->source = NULL; + return f; +} + +UpVal *makeUpValue(lua_State *luaState, int stackPos) { + UpVal *uv = lua_new(luaState, UpVal); + lua_link(luaState, (GCObject *)uv, LUA_TUPVAL); + uv->tt = LUA_TUPVAL; + uv->v = &uv->u.value; + uv->u.l.prev = NULL; + uv->u.l.next = NULL; + + setobj(luaState, uv->v, getObject(luaState, stackPos)); + + return uv; +} + +void boxUpValue_start(lua_State *luaState) { + LClosure *closure; + closure = (LClosure *)lua_newLclosure(luaState, 1, hvalue(&luaState->l_gt)); + pushClosure(luaState, (Closure *)closure); + // >>>>> ...... func + closure->p = makeFakeProto(luaState, 1); + + // Temporarily initialize the upvalue to nil + lua_pushnil(luaState); + closure->upvals[0] = makeUpValue(luaState, -1); + lua_pop(luaState, 1); +} + +void boxUpValue_finish(lua_State *luaState) { + // >>>>> ...... func obj + LClosure *lcl = (LClosure *)clvalue(getObject(luaState, -2)); + + lcl->upvals[0]->u.value = *getObject(luaState, -1); + lua_pop(luaState, 1); + // >>>>> ...... func +} + +} // End of namespace Lua diff --git a/engines/sword25/util/lua_persistence_util.h b/engines/sword25/util/lua_persistence_util.h new file mode 100644 index 0000000000..345996f606 --- /dev/null +++ b/engines/sword25/util/lua_persistence_util.h @@ -0,0 +1,98 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distri8buted in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef LUA_SERIALIZATION_UTIL_H +#define LUA_SERIALIZATION_UTIL_H + + +struct lua_State; + +#include "lua/lobject.h" + +typedef TValue *StkId; + +namespace Lua { + +#define lua_malloc(luaState, nsize) lua_realloc(luaState, nullptr, 0, nsize) +#define lua_reallocv(luaState, block, on, n, e) lua_realloc(luaState, block, (on) * (e), (n) * (e)) +#define lua_reallocvector(luaState, vec, oldn, n, T) ((vec) = (T *)(lua_reallocv(luaState, vec, oldn, n, sizeof(T)))) +#define lua_newVector(luaState, num, T) ((T *)lua_reallocv(luaState, nullptr, 0, num, sizeof(T))) +#define lua_new(luaState,T) (T *)lua_malloc(luaState, sizeof(T)) + +void *lua_realloc(lua_State *luaState, void *block, size_t osize, size_t nsize); + +void pushObject(lua_State *luaState, TValue *obj); +void pushProto(lua_State *luaState, Proto *proto); +void pushUpValue(lua_State *luaState, UpVal *upval); +void pushString(lua_State *luaState, TString *str); + +StkId getObject(lua_State *luaState, int stackpos); + +void lua_linkObjToGC(lua_State *luaState, GCObject *obj, lu_byte type); + +#define sizeLclosure(n) ((sizeof(LClosure)) + sizeof(TValue *) * ((n) - 1)) + +Closure *lua_newLclosure(lua_State *luaState, int numElements, Table *elementTable); +void pushClosure(lua_State *luaState, Closure *closure); + +Proto *createProto(lua_State *luaState); +Proto *makeFakeProto(lua_State *L, lu_byte nups); + +TString *createString(lua_State *luaState, const char *str, size_t len); + +UpVal *createUpValue(lua_State *luaState, int stackpos); +void unboxUpValue(lua_State *luaState); + +/* Appends one stack to another stack, but the stack is reversed in the process */ +size_t appendStackToStack_reverse(lua_State *from, lua_State *to); +void correctStack(lua_State *L, TValue *oldstack); +void lua_reallocstack(lua_State *L, int newsize); +void lua_growstack(lua_State *L, int n); + +void lua_reallocCallInfo(lua_State *lauState, int newsize); + +/* Does basically the opposite of luaC_link(). + * Right now this function is rather inefficient; it requires traversing the + * entire root GC set in order to find one object. If the GC list were doubly + * linked this would be much easier, but there's no reason for Lua to have + * that. */ +void GCUnlink(lua_State *luaState, GCObject *gco); + +TString *lua_newlstr(lua_State *luaState, const char *str, size_t len); +void lua_link(lua_State *luaState, GCObject *o, lu_byte tt); +Proto *lua_newproto(lua_State *luaState) ; + +UpVal *makeUpValue(lua_State *luaState, int stackPos); +/** + * The GC is not fond of finding upvalues in tables. We get around this + * during persistence using a weakly keyed table, so that the GC doesn't + * bother to mark them. This won't work in unpersisting, however, since + * if we make the values weak they'll be collected (since nothing else + * references them). Our solution, during unpersisting, is to represent + * upvalues as dummy functions, each with one upvalue. + */ +void boxUpValue_start(lua_State *luaState); +void boxUpValue_finish(lua_State *luaState); + +} // End of namespace Lua + +#endif diff --git a/engines/sword25/util/lua_serialization.h b/engines/sword25/util/lua_serialization.h deleted file mode 100644 index 549ea7968d..0000000000 --- a/engines/sword25/util/lua_serialization.h +++ /dev/null @@ -1,44 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#ifndef LUA_SERIALIZATION_H -#define LUA_SERIALIZATION_H - -#include "sword25/util/lua/lua.h" - - -namespace Common { -class WriteStream; -class ReadStream; -} - - -namespace Lua { - -#define PERMANENT_TYPE 101 - -void serializeLua(lua_State *luaState, Common::WriteStream *writeStream); -void unserializeLua(lua_State *luaState, Common::ReadStream *readStream); - -} // End of namespace Lua - -#endif diff --git a/engines/sword25/util/lua_serialization_util.cpp b/engines/sword25/util/lua_serialization_util.cpp deleted file mode 100644 index fc3f73eca6..0000000000 --- a/engines/sword25/util/lua_serialization_util.cpp +++ /dev/null @@ -1,346 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distri8buted in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "sword25/util/lua_serialization_util.h" - -#include "common/scummsys.h" - -#include "lua/lobject.h" -#include "lua/lstate.h" -#include "lua/lgc.h" -#include "lua/lopcodes.h" - - -namespace Lua { - -void *lua_realloc(lua_State *luaState, void *block, size_t osize, size_t nsize) { - global_State *globalState = G(luaState); - - block = (*globalState->frealloc)(globalState->ud, block, osize, nsize); - globalState->totalbytes = (globalState->totalbytes - osize) + nsize; - - return block; -} - -void pushObject(lua_State *luaState, TValue *obj) { - setobj2s(luaState, luaState->top, obj); - - api_check(luaState, luaState->top < luaState->ci->top); - luaState->top++; -} - -void pushProto(lua_State *luaState, Proto *proto) { - TValue obj; - setptvalue(luaState, &obj, proto); - - pushObject(luaState, &obj); -} - -void pushUpValue(lua_State *luaState, UpVal *upval) { - TValue obj; - - obj.value.gc = cast(GCObject *, upval); - obj.tt = LUA_TUPVAL; - checkliveness(G(L), obj); - - pushObject(luaState, &obj); -} - -void pushString(lua_State *luaState, TString *str) { - TValue o; - setsvalue(luaState, &o, str); - - pushObject(luaState, &o); -} - -/* A simple reimplementation of the unfortunately static function luaA_index. - * Does not support the global table, registry, or upvalues. */ -StkId getObject(lua_State *luaState, int stackpos) { - if (stackpos > 0) { - lua_assert(luaState->base + stackpos - 1 < luaState->top); - return luaState->base + stackpos - 1; - } else { - lua_assert(L->top - stackpos >= L->base); - return luaState->top + stackpos; - } -} - -void lua_linkObjToGC(lua_State *luaState, GCObject *obj, lu_byte type) { - global_State *globalState = G(luaState); - - obj->gch.next = globalState->rootgc; - globalState->rootgc = obj; - obj->gch.marked = luaC_white(globalState); - obj->gch.tt = type; -} - -Closure *lua_newLclosure(lua_State *luaState, int numElements, Table *elementTable) { - Closure *c = (Closure *)lua_malloc(luaState, sizeLclosure(numElements)); - lua_linkObjToGC(luaState, obj2gco(c), LUA_TFUNCTION); - - c->l.isC = 0; - c->l.env = elementTable; - c->l.nupvalues = cast_byte(numElements); - - while (numElements--) { - c->l.upvals[numElements] = NULL; - } - - return c; -} - -void pushClosure(lua_State *luaState, Closure *closure) { - TValue obj; - setclvalue(luaState, &obj, closure); - pushObject(luaState, &obj); -} - -Proto *createProto(lua_State *luaState) { - Proto *newProto = (Proto *)lua_malloc(luaState, sizeof(Proto)); - lua_linkObjToGC(luaState, obj2gco(newProto), LUA_TPROTO); - - newProto->k = NULL; - newProto->sizek = 0; - newProto->p = NULL; - newProto->sizep = 0; - newProto->code = NULL; - newProto->sizecode = 0; - newProto->sizelineinfo = 0; - newProto->sizeupvalues = 0; - newProto->nups = 0; - newProto->upvalues = NULL; - newProto->numparams = 0; - newProto->is_vararg = 0; - newProto->maxstacksize = 0; - newProto->lineinfo = NULL; - newProto->sizelocvars = 0; - newProto->locvars = NULL; - newProto->linedefined = 0; - newProto->lastlinedefined = 0; - newProto->source = NULL; - - return newProto; -} - -TString *createString(lua_State *luaState, const char *str, size_t len) { - TString *res; - lua_pushlstring(luaState, str, len); - - res = rawtsvalue(luaState->top - 1); - lua_pop(luaState, 1); - - return res; -} - -Proto *makeFakeProto(lua_State *L, lu_byte nups) { - Proto *p = createProto(L); - - p->sizelineinfo = 1; - p->lineinfo = lua_newVector(L, 1, int); - p->lineinfo[0] = 1; - p->sizecode = 1; - p->code = lua_newVector(L, 1, Instruction); - p->code[0] = CREATE_ABC(OP_RETURN, 0, 1, 0); - p->source = createString(L, "", 0); - p->maxstacksize = 2; - p->nups = nups; - p->sizek = 0; - p->sizep = 0; - - return p; -} - -UpVal *createUpValue(lua_State *luaState, int stackpos) { - UpVal *upValue = (UpVal *)lua_malloc(luaState, sizeof(UpVal)); - lua_linkObjToGC(luaState, (GCObject *)upValue, LUA_TUPVAL); - upValue->tt = LUA_TUPVAL; - upValue->v = &upValue->u.value; - upValue->u.l.prev = NULL; - upValue->u.l.next = NULL; - - const TValue *o2 = (TValue *)getObject(luaState, stackpos); - upValue->v->value = o2->value; - upValue->v->tt = o2->tt; - checkliveness(G(L), upValue->v); - - return upValue; -} - -void unboxUpValue(lua_State *luaState) { - // >>>>> ...... func - LClosure *lcl; - UpVal *uv; - - lcl = (LClosure *)clvalue(getObject(luaState, -1)); - uv = lcl->upvals[0]; - - lua_pop(luaState, 1); - // >>>>> ...... - - pushUpValue(luaState, uv); - // >>>>> ...... upValue -} - -size_t appendStackToStack_reverse(lua_State *from, lua_State *to) { - for (StkId id = from->top - 1; id >= from->stack; --id) { - setobj2s(to, to->top, id); - to->top++; - } - - return from->top - from->stack; -} - -void correctStack(lua_State *L, TValue *oldstack) { - CallInfo *ci; - GCObject *up; - L->top = (L->top - oldstack) + L->stack; - for (up = L->openupval; up != NULL; up = up->gch.next) - gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack; - for (ci = L->base_ci; ci <= L->ci; ci++) { - ci->top = (ci->top - oldstack) + L->stack; - ci->base = (ci->base - oldstack) + L->stack; - ci->func = (ci->func - oldstack) + L->stack; - } - L->base = (L->base - oldstack) + L->stack; -} - -void lua_reallocstack(lua_State *L, int newsize) { - TValue *oldstack = L->stack; - int realsize = newsize + 1 + EXTRA_STACK; - - lua_reallocvector(L, L->stack, L->stacksize, realsize, TValue); - L->stacksize = realsize; - L->stack_last = L->stack + newsize; - correctStack(L, oldstack); -} - -void lua_growstack(lua_State *L, int n) { - // Double size is enough? - if (n <= L->stacksize) { - lua_reallocstack(L, 2 * L->stacksize); - } else { - lua_reallocstack(L, L->stacksize + n); - } -} - -void lua_reallocCallInfo(lua_State *lauState, int newsize) { - CallInfo *oldci = lauState->base_ci; - lua_reallocvector(lauState, lauState->base_ci, lauState->size_ci, newsize, CallInfo); - - lauState->size_ci = newsize; - lauState->ci = (lauState->ci - oldci) + lauState->base_ci; - lauState->end_ci = lauState->base_ci + lauState->size_ci - 1; -} - -void GCUnlink(lua_State *luaState, GCObject *gco) { - GCObject *prevslot; - if (G(luaState)->rootgc == gco) { - G(luaState)->rootgc = G(luaState)->rootgc->gch.next; - return; - } - - prevslot = G(luaState)->rootgc; - while (prevslot->gch.next != gco) { - prevslot = prevslot->gch.next; - } - - prevslot->gch.next = prevslot->gch.next->gch.next; -} - -TString *lua_newlstr(lua_State *luaState, const char *str, size_t len) { - lua_pushlstring(luaState, str, len); - TString *luaStr = &(luaState->top - 1)->value.gc->ts; - - lua_pop(luaState, 1); - - return luaStr; -} - -void lua_link(lua_State *luaState, GCObject *o, lu_byte tt) { - global_State *g = G(luaState); - o->gch.next = g->rootgc; - g->rootgc = o; - o->gch.marked = luaC_white(g); - o->gch.tt = tt; -} - -Proto *lua_newproto(lua_State *luaState) { - Proto *f = (Proto *)lua_malloc(luaState, sizeof(Proto)); - lua_link(luaState, obj2gco(f), LUA_TPROTO); - f->k = NULL; - f->sizek = 0; - f->p = NULL; - f->sizep = 0; - f->code = NULL; - f->sizecode = 0; - f->sizelineinfo = 0; - f->sizeupvalues = 0; - f->nups = 0; - f->upvalues = NULL; - f->numparams = 0; - f->is_vararg = 0; - f->maxstacksize = 0; - f->lineinfo = NULL; - f->sizelocvars = 0; - f->locvars = NULL; - f->linedefined = 0; - f->lastlinedefined = 0; - f->source = NULL; - return f; -} - -UpVal *makeUpValue(lua_State *luaState, int stackPos) { - UpVal *uv = lua_new(luaState, UpVal); - lua_link(luaState, (GCObject *)uv, LUA_TUPVAL); - uv->tt = LUA_TUPVAL; - uv->v = &uv->u.value; - uv->u.l.prev = NULL; - uv->u.l.next = NULL; - - setobj(luaState, uv->v, getObject(luaState, stackPos)); - - return uv; -} - -void boxUpValue_start(lua_State *luaState) { - LClosure *closure; - closure = (LClosure *)lua_newLclosure(luaState, 1, hvalue(&luaState->l_gt)); - pushClosure(luaState, (Closure *)closure); - // >>>>> ...... func - closure->p = makeFakeProto(luaState, 1); - - // Temporarily initialize the upvalue to nil - lua_pushnil(luaState); - closure->upvals[0] = makeUpValue(luaState, -1); - lua_pop(luaState, 1); -} - -void boxUpValue_finish(lua_State *luaState) { - // >>>>> ...... func obj - LClosure *lcl = (LClosure *)clvalue(getObject(luaState, -2)); - - lcl->upvals[0]->u.value = *getObject(luaState, -1); - lua_pop(luaState, 1); - // >>>>> ...... func -} - -} // End of namespace Lua diff --git a/engines/sword25/util/lua_serialization_util.h b/engines/sword25/util/lua_serialization_util.h deleted file mode 100644 index 345996f606..0000000000 --- a/engines/sword25/util/lua_serialization_util.h +++ /dev/null @@ -1,98 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distri8buted in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#ifndef LUA_SERIALIZATION_UTIL_H -#define LUA_SERIALIZATION_UTIL_H - - -struct lua_State; - -#include "lua/lobject.h" - -typedef TValue *StkId; - -namespace Lua { - -#define lua_malloc(luaState, nsize) lua_realloc(luaState, nullptr, 0, nsize) -#define lua_reallocv(luaState, block, on, n, e) lua_realloc(luaState, block, (on) * (e), (n) * (e)) -#define lua_reallocvector(luaState, vec, oldn, n, T) ((vec) = (T *)(lua_reallocv(luaState, vec, oldn, n, sizeof(T)))) -#define lua_newVector(luaState, num, T) ((T *)lua_reallocv(luaState, nullptr, 0, num, sizeof(T))) -#define lua_new(luaState,T) (T *)lua_malloc(luaState, sizeof(T)) - -void *lua_realloc(lua_State *luaState, void *block, size_t osize, size_t nsize); - -void pushObject(lua_State *luaState, TValue *obj); -void pushProto(lua_State *luaState, Proto *proto); -void pushUpValue(lua_State *luaState, UpVal *upval); -void pushString(lua_State *luaState, TString *str); - -StkId getObject(lua_State *luaState, int stackpos); - -void lua_linkObjToGC(lua_State *luaState, GCObject *obj, lu_byte type); - -#define sizeLclosure(n) ((sizeof(LClosure)) + sizeof(TValue *) * ((n) - 1)) - -Closure *lua_newLclosure(lua_State *luaState, int numElements, Table *elementTable); -void pushClosure(lua_State *luaState, Closure *closure); - -Proto *createProto(lua_State *luaState); -Proto *makeFakeProto(lua_State *L, lu_byte nups); - -TString *createString(lua_State *luaState, const char *str, size_t len); - -UpVal *createUpValue(lua_State *luaState, int stackpos); -void unboxUpValue(lua_State *luaState); - -/* Appends one stack to another stack, but the stack is reversed in the process */ -size_t appendStackToStack_reverse(lua_State *from, lua_State *to); -void correctStack(lua_State *L, TValue *oldstack); -void lua_reallocstack(lua_State *L, int newsize); -void lua_growstack(lua_State *L, int n); - -void lua_reallocCallInfo(lua_State *lauState, int newsize); - -/* Does basically the opposite of luaC_link(). - * Right now this function is rather inefficient; it requires traversing the - * entire root GC set in order to find one object. If the GC list were doubly - * linked this would be much easier, but there's no reason for Lua to have - * that. */ -void GCUnlink(lua_State *luaState, GCObject *gco); - -TString *lua_newlstr(lua_State *luaState, const char *str, size_t len); -void lua_link(lua_State *luaState, GCObject *o, lu_byte tt); -Proto *lua_newproto(lua_State *luaState) ; - -UpVal *makeUpValue(lua_State *luaState, int stackPos); -/** - * The GC is not fond of finding upvalues in tables. We get around this - * during persistence using a weakly keyed table, so that the GC doesn't - * bother to mark them. This won't work in unpersisting, however, since - * if we make the values weak they'll be collected (since nothing else - * references them). Our solution, during unpersisting, is to represent - * upvalues as dummy functions, each with one upvalue. - */ -void boxUpValue_start(lua_State *luaState); -void boxUpValue_finish(lua_State *luaState); - -} // End of namespace Lua - -#endif diff --git a/engines/sword25/util/lua_serializer.cpp b/engines/sword25/util/lua_serializer.cpp deleted file mode 100644 index 55b6257324..0000000000 --- a/engines/sword25/util/lua_serializer.cpp +++ /dev/null @@ -1,787 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "sword25/util/lua_serialization.h" - -#include "sword25/util/double_serializer.h" -#include "sword25/util/lua_serialization_util.h" - -#include "common/stream.h" - -#include "lua/lobject.h" -#include "lua/lstate.h" -#include "lua/lgc.h" - - -namespace Lua { - -#define PERMANENT_TYPE 101 - -struct SerializationInfo { - lua_State *luaState; - Common::WriteStream *writeStream; - uint counter; -}; - -static void serialize(SerializationInfo *info); - -static void serializeBoolean(SerializationInfo *info); -static void serializeNumber(SerializationInfo *info); -static void serializeString(SerializationInfo *info); -static void serializeTable(SerializationInfo *info); -static void serializeFunction(SerializationInfo *info); -static void serializeThread(SerializationInfo *info); -static void serializeProto(SerializationInfo *info); -static void serializeUpValue(SerializationInfo *info); -static void serializeUserData(SerializationInfo *info); - - -void serializeLua(lua_State *luaState, Common::WriteStream *writeStream) { - SerializationInfo info; - info.luaState = luaState; - info.writeStream = writeStream; - info.counter = 0u; - - // The process starts with the lua stack as follows: - // >>>>> permTbl rootObj - // That's the table of permanents and the root object to be serialized - - // Make sure there is enough room on the stack - lua_checkstack(luaState, 4); - assert(lua_gettop(luaState) == 2); - // And that the root isn't nil - assert(!lua_isnil(luaState, 2)); - - // Create a table to hold indexes of everything that's serialized - // This allows us to only serialize an object once - // Every other time, just reference the index - lua_newtable(luaState); - // >>>>> permTbl rootObj indexTbl - - // Now we're going to make the table weakly keyed. This prevents the - // GC from visiting it and trying to mark things it doesn't want to - // mark in tables, e.g. upvalues. All objects in the table are - // a priori reachable, so it doesn't matter that we do this. - - // Create the metatable - lua_newtable(luaState); - // >>>>> permTbl rootObj indexTbl metaTbl - - lua_pushstring(luaState, "__mode"); - // >>>>> permTbl rootObj indexTbl metaTbl "__mode" - - lua_pushstring(luaState, "k"); - // >>>>> permTbl rootObj indexTbl metaTbl "__mode" "k" - - lua_settable(luaState, 4); - // >>>>> permTbl rootObj indexTbl metaTbl - - lua_setmetatable(luaState, 3); - // >>>>> permTbl rootObj indexTbl - - // Swap the indexTable and the rootObj - lua_insert(luaState, 2); - // >>>>> permTbl indexTbl rootObj - - // Serialize the root recursively - serialize(&info); - - // Return the stack back to the original state - lua_remove(luaState, 2); - // >>>>> permTbl rootObj -} - -static void serialize(SerializationInfo *info) { - // The stack can potentially have many things on it - // The object we want to serialize is the item on the top of the stack - // >>>>> permTbl indexTbl rootObj ...... obj - - // Make sure there is enough room on the stack - lua_checkstack(info->luaState, 2); - - // If the object has already been written, don't write it again - // Instead write the index of the object from the indexTbl - - // Check the indexTbl - lua_pushvalue(info->luaState, -1); - // >>>>> permTbl indexTbl rootObj ...... obj obj - - lua_rawget(info->luaState, 2); - // >>>>> permTbl indexTbl rootObj ...... obj ?index? - - // If the index isn't nil, the object has already been written - if (!lua_isnil(info->luaState, -1)) { - // Write out a flag that indicates that it's an index - info->writeStream->writeByte(0); - - // Retrieve the index from the stack - uint *index = (uint *)lua_touserdata(info->luaState, -1); - - // Write out the index - info->writeStream->writeUint32LE(*index); - - // Pop the index off the stack - lua_pop(info->luaState, 1); - - return; - } - - // Pop the nil off the stack - lua_pop(info->luaState, 1); - - // Write out a flag that indicates that this is a real object - info->writeStream->writeByte(1); - - // If the object itself is nil, then write out a zero as a placeholder - if (lua_isnil(info->luaState, -1)) { - info->writeStream->writeByte(0); - - return; - } - - // Add the object to the indexTbl - - lua_pushvalue(info->luaState, -1); - // >>>>> permTbl indexTbl rootObj ...... obj obj - - uint *ref = (uint *)lua_newuserdata(info->luaState, sizeof(uint)); - *ref = ++(info->counter); - // >>>>> permTbl indexTbl rootObj ...... obj obj index - - lua_rawset(info->luaState, 2); - // >>>>> permTbl indexTbl rootObj ...... obj - - - // Write out the index - info->writeStream->writeUint32LE(info->counter); - - - // Objects that are in the permanents table are serialized in a special way - - lua_pushvalue(info->luaState, -1); - // >>>>> permTbl indexTbl rootObj ...... obj obj - - lua_gettable(info->luaState, 1); - // >>>>> permTbl indexTbl rootObj ...... obj obj ?permKey? - - if (!lua_isnil(info->luaState, -1)) { - // Write out the type - info->writeStream->writeSint32LE(PERMANENT_TYPE); - - // Serialize the key - serialize(info); - - // Pop the key off the stack - lua_pop(info->luaState, 1); - - return; - } - - // Pop the nil off the stack - lua_pop(info->luaState, 1); - - // Query the type of the object - int objType = lua_type(info->luaState, -1); - - // Write it out - info->writeStream->writeSint32LE(objType); - - // Serialize the object by its type - - switch (objType) { - case LUA_TBOOLEAN: - serializeBoolean(info); - break; - case LUA_TLIGHTUSERDATA: - // You can't serialize a pointer - // It would be meaningless on the next run - assert(0); - break; - case LUA_TNUMBER: - serializeNumber(info); - break; - case LUA_TSTRING: - serializeString(info); - break; - case LUA_TTABLE: - serializeTable(info); - break; - case LUA_TFUNCTION: - serializeFunction(info); - break; - case LUA_TTHREAD: - serializeThread(info); - break; - case LUA_TPROTO: - serializeProto(info); - break; - case LUA_TUPVAL: - serializeUpValue(info); - break; - case LUA_TUSERDATA: - serializeUserData(info); - break; - default: - assert(0); - } -} - -static void serializeBoolean(SerializationInfo *info) { - int value = lua_toboolean(info->luaState, -1); - - info->writeStream->writeSint32LE(value); -} - -static void serializeNumber(SerializationInfo *info) { - lua_Number value = lua_tonumber(info->luaState, -1); - - #if 1 - Util::SerializedDouble serializedValue(Util::encodeDouble(value)); - - info->writeStream->writeUint32LE(serializedValue.significandOne); - info->writeStream->writeUint32LE(serializedValue.signAndSignificandTwo); - info->writeStream->writeSint16LE(serializedValue.exponent); - #else - // NOTE: We need to store a double. Unfortunately, we have to accommodate endianness. - // Also, I don't know if we can assume all compilers use IEEE double - // Therefore, I have chosen to store the double as a string. - Common::String buffer = Common::String::format("%f", value); - - info->writeStream->write(buffer.c_str(), buffer.size()); - #endif - -} - -static void serializeString(SerializationInfo *info) { - // Hard cast to a uint32 to force size_t to an explicit size - // *Theoretically* this could truncate, but if we have a 4gb string, we have bigger problems - uint32 length = static_cast(lua_strlen(info->luaState, -1)); - info->writeStream->writeUint32LE(length); - - const char *str = lua_tostring(info->luaState, -1); - info->writeStream->write(str, length); -} - -/* Choose whether to do a regular or special persistence based on an object's - * metatable. "default" is whether the object, if it doesn't have a __persist - * entry, is literally persistable or not. - * Pushes the unpersist closure and returns true if special persistence is - * used. */ -static bool serializeSpecialObject(SerializationInfo *info, bool defaction) { - // Make sure there is enough room on the stack - lua_checkstack(info->luaState, 4); - - // Check whether we should persist literally, or via the __persist metafunction - if (!lua_getmetatable(info->luaState, -1)) { - if (defaction) { - // Write out a flag declaring that the object isn't special and should be persisted normally - info->writeStream->writeSint32LE(0); - - return false; - } else { - lua_pushstring(info->luaState, "Type not literally persistable by default"); - lua_error(info->luaState); - - return false; // Not reached - } - } - - // >>>>> permTbl indexTbl ...... obj metaTbl - lua_pushstring(info->luaState, "__persist"); - // >>>>> permTbl indexTbl rootObj ...... obj metaTbl "__persist" - - lua_rawget(info->luaState, -2); - // >>>>> permTbl indexTbl ...... obj metaTbl ?__persist? - - if (lua_isnil(info->luaState, -1)) { - // >>>>> permTbl indexTbl ...... obj metaTbl nil - lua_pop(info->luaState, 2); - // >>>>> permTbl indexTbl ...... obj - - if (defaction) { - // Write out a flag declaring that the object isn't special and should be persisted normally - info->writeStream->writeSint32LE(0); - - return false; - } else { - lua_pushstring(info->luaState, "Type not literally persistable by default"); - lua_error(info->luaState); - - return false; // Return false - } - - } else if (lua_isboolean(info->luaState, -1)) { - // >>>>> permTbl indexTbl ...... obj metaTbl bool - if (lua_toboolean(info->luaState, -1)) { - // Write out a flag declaring that the object isn't special and should be persisted normally - info->writeStream->writeSint32LE(0); - - // >>>>> permTbl indexTbl ...... obj metaTbl true */ - lua_pop(info->luaState, 2); - // >>>>> permTbl indexTbl ...... obj - - return false; - } else { - lua_pushstring(info->luaState, "Metatable forbade persistence"); - lua_error(info->luaState); - - return false; // Not reached - } - } else if (!lua_isfunction(info->luaState, -1)) { - lua_pushstring(info->luaState, "__persist not nil, boolean, or function"); - lua_error(info->luaState); - } - - // >>>>> permTbl indexTbl ...... obj metaTbl __persist - lua_pushvalue(info->luaState, -3); - // >>>>> permTbl indexTbl ...... obj metaTbl __persist obj - - // >>>>> permTbl indexTbl ...... obj metaTbl ?func? - - if (!lua_isfunction(info->luaState, -1)) { - lua_pushstring(info->luaState, "__persist function did not return a function"); - lua_error(info->luaState); - } - - // >>>>> permTbl indexTbl ...... obj metaTbl func - - // Write out a flag that the function exists - info->writeStream->writeSint32LE(1); - - // Serialize the function - serialize(info); - - lua_pop(info->luaState, 2); - // >>>>> permTbl indexTbl ...... obj - - return true; -} - -static void serializeTable(SerializationInfo *info) { - // >>>>> permTbl indexTbl ...... tbl - - // Make sure there is enough room on the stack - lua_checkstack(info->luaState, 3); - - // Test if the object needs special serialization - if (serializeSpecialObject(info, 1)) { - return; - } - - // >>>>> permTbl indexTbl ...... tbl - - // First, serialize the metatable (if any) - if (!lua_getmetatable(info->luaState, -1)) { - lua_pushnil(info->luaState); - } - - // >>>>> permTbl indexTbl ...... tbl metaTbl/nil */ - serialize(info); - - lua_pop(info->luaState, 1); - // >>>>> permTbl indexTbl ...... tbl - - - lua_pushnil(info->luaState); - // >>>>> permTbl indexTbl ...... tbl nil - - // Now, persist all k/v pairs - while (lua_next(info->luaState, -2)) { - // >>>>> permTbl indexTbl ...... tbl k v */ - - lua_pushvalue(info->luaState, -2); - // >>>>> permTbl indexTbl ...... tbl k v k */ - - // Serialize the key - serialize(info); - - lua_pop(info->luaState, 1); - // >>>>> permTbl indexTbl ...... tbl k v */ - - // Serialize the value - serialize(info); - - lua_pop(info->luaState, 1); - // >>>>> permTbl indexTbl ...... tbl k */ - } - - // >>>>> permTbl indexTbl ...... tbl - - // Terminate the list with a nil - lua_pushnil(info->luaState); - // >>>>> permTbl indexTbl ...... tbl - - serialize(info); - - lua_pop(info->luaState, 1); - // >>>>> permTbl indexTbl ...... tbl -} - -static void serializeFunction(SerializationInfo *info) { - // >>>>> permTbl indexTbl ...... func - Closure *cl = clvalue(getObject(info->luaState, -1)); - lua_checkstack(info->luaState, 2); - - if (cl->c.isC) { - /* It's a C function. For now, we aren't going to allow - * persistence of C closures, even if the "C proto" is - * already in the permanents table. */ - lua_pushstring(info->luaState, "Attempt to persist a C function"); - lua_error(info->luaState); - } else { - // It's a Lua closure - - // We don't really _NEED_ the number of upvals, but it'll simplify things a bit - info->writeStream->writeByte(cl->l.p->nups); - - // Serialize the prototype - pushProto(info->luaState, cl->l.p); - // >>>>> permTbl indexTbl ...... func proto */ - - serialize(info); - - lua_pop(info->luaState, 1); - // >>>>> permTbl indexTbl ...... func - - // Serialize upvalue values (not the upvalue objects themselves) - for (byte i = 0; i < cl->l.p->nups; i++) { - // >>>>> permTbl indexTbl ...... func - pushUpValue(info->luaState, cl->l.upvals[i]); - // >>>>> permTbl indexTbl ...... func upval - - serialize(info); - - lua_pop(info->luaState, 1); - // >>>>> permTbl indexTbl ...... func - } - - // >>>>> permTbl indexTbl ...... func - - // Serialize function environment - lua_getfenv(info->luaState, -1); - // >>>>> permTbl indexTbl ...... func fenv - - if (lua_equal(info->luaState, -1, LUA_GLOBALSINDEX)) { - // Function has the default fenv - - // >>>>> permTbl indexTbl ...... func _G - lua_pop(info->luaState, 1); - // >>>>> permTbl indexTbl ...... func - - lua_pushnil(info->luaState); - // >>>>> permTbl indexTbl ...... func nil - } - - // >>>>> permTbl indexTbl ...... func fenv/nil - serialize(info); - - lua_pop(info->luaState, 1); - // >>>>> permTbl indexTbl ...... func - } -} - -static void serializeThread(SerializationInfo *info) { - // >>>>> permTbl indexTbl ...... thread - lua_State *threadState = lua_tothread(info->luaState, -1); - - // Make sure there is enough room on the stack - lua_checkstack(info->luaState, threadState->top - threadState->stack + 1); - - if (info->luaState == threadState) { - lua_pushstring(info->luaState, "Can't persist currently running thread"); - lua_error(info->luaState); - return; /* not reached */ - } - - // Persist the stack - - // We *could* have truncation here, but if we have more than 4 billion items on a stack, we have bigger problems - uint32 stackSize = static_cast(appendStackToStack_reverse(threadState, info->luaState)); - info->writeStream->writeUint32LE(stackSize); - - // >>>>> permTbl indexTbl ...... thread (reversed contents of thread stack) */ - for (; stackSize > 0; --stackSize) { - serialize(info); - - lua_pop(info->luaState, 1); - } - - // >>>>> permTbl indexTbl ...... thread - - // Now, serialize the CallInfo stack - - // Again, we *could* have truncation here, but if we have more than 4 billion items on a stack, we have bigger problems - uint32 numFrames = static_cast((threadState->ci - threadState->base_ci) + 1); - info->writeStream->writeUint32LE(numFrames); - - for (uint32 i = 0; i < numFrames; i++) { - CallInfo *ci = threadState->base_ci + i; - - // Same argument as above about truncation - uint32 stackBase = static_cast(ci->base - threadState->stack); - uint32 stackFunc = static_cast(ci->func - threadState->stack); - uint32 stackTop = static_cast(ci->top - threadState->stack); - - info->writeStream->writeUint32LE(stackBase); - info->writeStream->writeUint32LE(stackFunc); - info->writeStream->writeUint32LE(stackTop); - - info->writeStream->writeSint32LE(ci->nresults); - - uint32 savedpc = (ci != threadState->base_ci) ? static_cast(ci->savedpc - ci_func(ci)->l.p->code) : 0u; - info->writeStream->writeUint32LE(savedpc); - } - - - // Serialize the state's other parameters, with the exception of upval stuff - - assert(threadState->nCcalls <= 1); - info->writeStream->writeByte(threadState->status); - - // Same argument as above about truncation - uint32 stackBase = static_cast(threadState->base - threadState->stack); - uint32 stackFunc = static_cast(threadState->top - threadState->stack); - info->writeStream->writeUint32LE(stackBase); - info->writeStream->writeUint32LE(stackFunc); - - // Same argument as above about truncation - uint32 stackOffset = static_cast(threadState->errfunc); - info->writeStream->writeUint32LE(stackOffset); - - // Finally, record upvalues which need to be reopened - // See the comment above serializeUpVal() for why we do this - - UpVal *upVal; - - // >>>>> permTbl indexTbl ...... thread - for (GCObject *gcObject = threadState->openupval; gcObject != NULL; gcObject = upVal->next) { - upVal = gco2uv(gcObject); - - /* Make sure upvalue is really open */ - assert(upVal->v != &upVal->u.value); - - pushUpValue(info->luaState, upVal); - // >>>>> permTbl indexTbl ...... thread upVal - - serialize(info); - - lua_pop(info->luaState, 1); - // >>>>> permTbl indexTbl ...... thread - - // Same argument as above about truncation - uint32 stackpos = static_cast(upVal->v - threadState->stack); - info->writeStream->writeUint32LE(stackpos); - } - - // >>>>> permTbl indexTbl ...... thread - lua_pushnil(info->luaState); - // >>>>> permTbl indexTbl ...... thread nil - - // Use nil as a terminator - serialize(info); - - lua_pop(info->luaState, 1); - // >>>>> permTbl indexTbl ...... thread -} - -static void serializeProto(SerializationInfo *info) { - // >>>>> permTbl indexTbl ...... proto - Proto *proto = gco2p(getObject(info->luaState, -1)->value.gc); - - // Make sure there is enough room on the stack - lua_checkstack(info->luaState, 2); - - // Serialize constant refs */ - info->writeStream->writeSint32LE(proto->sizek); - - for (int i = 0; i < proto->sizek; ++i) { - pushObject(info->luaState, &proto->k[i]); - // >>>>> permTbl indexTbl ...... proto const - - serialize(info); - - lua_pop(info->luaState, 1); - // >>>>> permTbl indexTbl ...... proto - } - - // >>>>> permTbl indexTbl ...... proto - - // Serialize inner Proto refs - info->writeStream->writeSint32LE(proto->sizep); - - for (int i = 0; i < proto->sizep; ++i) - { - pushProto(info->luaState, proto->p[i]); - // >>>>> permTbl indexTbl ...... proto subProto */ - - serialize(info); - - lua_pop(info->luaState, 1); - // >>>>> permTbl indexTbl ...... proto - } - - // >>>>> permTbl indexTbl ...... proto - - // Serialize the code - info->writeStream->writeSint32LE(proto->sizecode); - - uint32 len = static_cast(sizeof(Instruction) * proto->sizecode); - info->writeStream->write(proto->code, len); - - - // Serialize upvalue names - info->writeStream->writeSint32LE(proto->sizeupvalues); - - for (int i = 0; i < proto->sizeupvalues; ++i) - { - pushString(info->luaState, proto->upvalues[i]); - // >>>>> permTbl indexTbl ...... proto str - - serialize(info); - - lua_pop(info->luaState, 1); - // >>>>> permTbl indexTbl ...... proto - } - - - // Serialize local variable infos - info->writeStream->writeSint32LE(proto->sizelocvars); - - for (int i = 0; i < proto->sizelocvars; ++i) { - pushString(info->luaState, proto->locvars[i].varname); - // >>>>> permTbl indexTbl ...... proto str - - serialize(info); - - lua_pop(info->luaState, 1); - // >>>>> permTbl indexTbl ...... proto - - info->writeStream->writeSint32LE(proto->locvars[i].startpc); - info->writeStream->writeSint32LE(proto->locvars[i].endpc); - } - - - // Serialize source string - pushString(info->luaState, proto->source); - // >>>>> permTbl indexTbl ...... proto sourceStr - - serialize(info); - - lua_pop(info->luaState, 1); - // >>>>> permTbl indexTbl ...... proto - - // Serialize line numbers - info->writeStream->writeSint32LE(proto->sizelineinfo); - - if (proto->sizelineinfo) { - uint32 len = static_cast(sizeof(int) * proto->sizelineinfo); - info->writeStream->write(proto->lineinfo, len); - } - - // Serialize linedefined and lastlinedefined - info->writeStream->writeSint32LE(proto->linedefined); - info->writeStream->writeSint32LE(proto->lastlinedefined); - - - // Serialize misc values - info->writeStream->writeByte(proto->nups); - info->writeStream->writeByte(proto->numparams); - info->writeStream->writeByte(proto->is_vararg); - info->writeStream->writeByte(proto->maxstacksize); -} - -/* Upvalues are tricky. Here's why. - * - * A particular upvalue may be either "open", in which case its member v - * points into a thread's stack, or "closed" in which case it points to the - * upvalue itself. An upvalue is closed under any of the following conditions: - * -- The function that initially declared the variable "local" returns - * -- The thread in which the closure was created is garbage collected - * - * To make things wackier, just because a thread is reachable by Lua doesn't - * mean it's in our root set. We need to be able to treat an open upvalue - * from an unreachable thread as a closed upvalue. - * - * The solution: - * (a) For the purposes of serializing, don't indicate whether an upvalue is - * closed or not. - * (b) When unserializing, pretend that all upvalues are closed. - * (c) When serializing, persist all open upvalues referenced by a thread - * that is persisted, and tag each one with the corresponding stack position - * (d) When unserializing, "reopen" each of these upvalues as the thread is - * unserialized - */ -static void serializeUpValue(SerializationInfo *info) { - // >>>>> permTbl indexTbl ...... upval - assert(ttype(getObject(info->luaState, -1)) == LUA_TUPVAL); - UpVal *upValue = gco2uv(getObject(info->luaState, -1)->value.gc); - - // Make sure there is enough room on the stack - lua_checkstack(info->luaState, 1); - - // We can't permit the upValue to linger around on the stack, as Lua - // will bail if its GC finds it. - - lua_pop(info->luaState, 1); - // >>>>> permTbl indexTbl ...... - - pushObject(info->luaState, upValue->v); - // >>>>> permTbl indexTbl ...... obj - - serialize(info); - // >>>>> permTbl indexTbl ...... obj -} - -static void serializeUserData(SerializationInfo *info) { - // >>>>> permTbl rootObj ...... udata - - // Make sure there is enough room on the stack - lua_checkstack(info->luaState, 2); - - // Test if the object needs special serialization - if (serializeSpecialObject(info, 0)) { - return; - } - - // Use literal persistence - - // Hard cast to a uint32 length - // This could lead to truncation, but if we have a 4gb block of data, we have bigger problems - uint32 length = static_cast(uvalue(getObject(info->luaState, -1))->len); - info->writeStream->writeUint32LE(length); - - info->writeStream->write(lua_touserdata(info->luaState, -1), length); - - // Serialize the metatable (if any) - if (!lua_getmetatable(info->luaState, -1)) { - lua_pushnil(info->luaState); - } - - // >>>>> permTbl rootObj ...... udata metaTbl/nil - serialize(info); - - lua_pop(info->luaState, 1); - /* perms reftbl ... udata */ -} - - -} // End of namespace Lua diff --git a/engines/sword25/util/lua_unpersist.cpp b/engines/sword25/util/lua_unpersist.cpp new file mode 100644 index 0000000000..aa924ff7c5 --- /dev/null +++ b/engines/sword25/util/lua_unpersist.cpp @@ -0,0 +1,698 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "sword25/util/lua_persistence.h" + +#include "sword25/util/double_serializer.h" +#include "sword25/util/lua_persistence_util.h" + +#include "common/stream.h" + +#include "lua/lobject.h" +#include "lua/lstate.h" +#include "lua/lgc.h" +#include "lua/lopcodes.h" + + +namespace Lua { + +struct UnSerializationInfo { + lua_State *luaState; + Common::ReadStream *readStream; +}; + +static void unserialize(UnSerializationInfo *info); + +static void unserializeBoolean(UnSerializationInfo *info); +static void unserializeNumber(UnSerializationInfo *info); +static void unserializeString(UnSerializationInfo *info); +static void unserializeTable(UnSerializationInfo *info, int index); +static void unserializeFunction(UnSerializationInfo *info, int index); +static void unserializeThread(UnSerializationInfo *info, int index); +static void unserializeProto(UnSerializationInfo *info, int index); +static void unserializeUpValue(UnSerializationInfo *info, int index); +static void unserializeUserData(UnSerializationInfo *info, int index); +static void unserializePermanent(UnSerializationInfo *info, int index); + + +void unpersistLua(lua_State *luaState, Common::ReadStream *readStream) { + UnSerializationInfo info; + info.luaState = luaState; + info.readStream = readStream; + + // The process starts with the lua stack as follows: + // >>>>> permTbl + // That's the table of permanents + + // Make sure there is enough room on the stack + lua_checkstack(luaState, 3); + + // Create a table to hold indexes of everything thats already been read + lua_newtable(luaState); + // >>>>> permTbl indexTbl + + // Prevent garbage collection while we unserialize + lua_gc(luaState, LUA_GCSTOP, 0); + + // Unserialize the root object + unserialize(&info); + // >>>>> permTbl indexTbl rootObj + + // Re-start garbage collection + lua_gc(luaState, LUA_GCRESTART, 0); + + // Remove the indexTbl + lua_replace(luaState, 2); + // >>>>> permTbl rootObj +} + +/* The object is left on the stack. This is primarily used by unserialize, but + * may be used by GCed objects that may incur cycles in order to preregister + * the object. */ +static void registerObjectInIndexTable(UnSerializationInfo *info, int index) { + // >>>>> permTbl indexTbl ...... obj + + // Make sure there is enough room on the stack + lua_checkstack(info->luaState, 2); + + lua_pushlightuserdata(info->luaState, (void *)index); + // >>>>> permTbl indexTbl ...... obj index + + lua_pushvalue(info->luaState, -2); + // >>>>> permTbl indexTbl ...... obj index obj + + // Push the k/v pair into the indexTbl + lua_settable(info->luaState, 2); + // >>>>> permTbl indexTbl ...... obj +} + +static void unserialize(UnSerializationInfo *info) { + // >>>>> permTbl indexTbl ...... + + // Make sure there is enough room on the stack + lua_checkstack(info->luaState, 2); + + byte isARealValue = info->readStream->readByte(); + if (isARealValue) { + int index = info->readStream->readSint32LE(); + int type = info->readStream->readSint32LE(); + + switch (type) { + case LUA_TBOOLEAN: + unserializeBoolean(info); + break; + case LUA_TLIGHTUSERDATA: + // You can't serialize a pointer + // It would be meaningless on the next run + assert(0); + break; + case LUA_TNUMBER: + unserializeNumber(info); + break; + case LUA_TSTRING: + unserializeString(info); + break; + case LUA_TTABLE: + unserializeTable(info, index); + break; + case LUA_TFUNCTION: + unserializeFunction(info, index); + break; + case LUA_TTHREAD: + unserializeThread(info, index); + break; + case LUA_TPROTO: + unserializeProto(info, index); + break; + case LUA_TUPVAL: + unserializeUpValue(info, index); + break; + case LUA_TUSERDATA: + unserializeUserData(info, index); + break; + case PERMANENT_TYPE: + unserializePermanent(info, index); + break; + default: + assert(0); + } + + + // >>>>> permTbl indexTbl ...... obj + assert(lua_type(info->luaState, -1) == type || + type == PERMANENT_TYPE || + // Remember, upvalues get a special dispensation, as described in boxUpValue + (lua_type(info->luaState, -1) == LUA_TFUNCTION && type == LUA_TUPVAL)); + + registerObjectInIndexTable(info, index); + // >>>>> permTbl indexTbl ...... obj + } else { + int index = info->readStream->readSint32LE(); + + if (index == 0) { + lua_pushnil(info->luaState); + // >>>>> permTbl indexTbl ...... nil + } else { + // Fetch the object from the indexTbl + + lua_pushlightuserdata(info->luaState, (void *)index); + // >>>>> permTbl indexTbl ...... index + + lua_gettable(info->luaState, 2); + // >>>>> permTbl indexTbl ...... ?obj? + + assert(!lua_isnil(info->luaState, -1)); + } + // >>>>> permTbl indexTbl ...... obj/nil + } + + // >>>>> permTbl indexTbl ...... obj/nil +} + +static void unserializeBoolean(UnSerializationInfo *info) { + // >>>>> permTbl indexTbl ...... + + // Make sure there is enough room on the stack + lua_checkstack(info->luaState, 1); + + int value = info->readStream->readSint32LE(); + + lua_pushboolean(info->luaState, value); + // >>>>> permTbl indexTbl ...... bool +} + +static void unserializeNumber(UnSerializationInfo *info) { + // >>>>> permTbl indexTbl ...... + + // Make sure there is enough room on the stack + lua_checkstack(info->luaState, 1); + + // Read the serialized double + Util::SerializedDouble serializedValue; + serializedValue.significandOne = info->readStream->readUint32LE(); + serializedValue.signAndSignificandTwo = info->readStream->readUint32LE(); + serializedValue.exponent = info->readStream->readSint16LE(); + + lua_Number value = Util::decodeDouble(serializedValue); + + lua_pushnumber(info->luaState, value); + // >>>>> permTbl indexTbl ...... num +} + +static void unserializeString(UnSerializationInfo *info) { + // >>>>> permTbl indexTbl ...... + + // Make sure there is enough room on the stack + lua_checkstack(info->luaState, 1); + + uint32 length = info->readStream->readUint32LE(); + char *string = new char[length]; + + info->readStream->read(string, length); + lua_pushlstring(info->luaState, string, length); + + // >>>>> permTbl indexTbl ...... string + + delete[] string; +} + +static void unserializeSpecialTable(UnSerializationInfo *info, int index) { + // >>>>> permTbl indexTbl ...... + + // Make sure there is enough room on the stack + lua_checkstack(info->luaState, 1); + + unserialize(info); + + // >>>>> permTbl indexTbl ...... spfunc + lua_call(info->luaState, 0, 1); + // >>>>> permTbl indexTbl ...... tbl +} + +static void unserializeLiteralTable(UnSerializationInfo *info, int index) { + // >>>>> permTbl indexTbl ...... + + // Make sure there is enough room on the stack + lua_checkstack(info->luaState, 3); + + // Preregister table for handling of cycles + lua_newtable(info->luaState); + + // >>>>> permTbl indexTbl ...... tbl + registerObjectInIndexTable(info, index); + // >>>>> permTbl indexTbl ...... tbl + + // Unserialize metatable + unserialize(info); + // >>>>> permTbl indexTbl ...... tbl ?metaTbl/nil? + + if (lua_istable(info->luaState, -1)) { + // >>>>> permTbl indexTbl ...... tbl metaTbl + lua_setmetatable(info->luaState, -2); + // >>>>> permTbl indexTbl ...... tbl + } else { + // >>>>> permTbl indexTbl ...... tbl nil + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... tbl + } + // >>>>> permTbl indexTbl ...... tbl + + + while (1) { + // >>>>> permTbl indexTbl ...... tbl + unserialize(info); + // >>>>> permTbl indexTbl ...... tbl key/nil + + // The table serialization is nil terminated + if (lua_isnil(info->luaState, -1)) { + // >>>>> permTbl indexTbl ...... tbl nil + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... tbl + + break; + } + + // >>>>> permTbl indexTbl ...... tbl key + unserialize(info); + // >>>>> permTbl indexTbl ...... tbl value + + lua_rawset(info->luaState, -3); + // >>>>> permTbl indexTbl ...... tbl + } +} + +void unserializeTable(UnSerializationInfo *info, int index) { + // >>>>> permTbl indexTbl ...... + + // Make sure there is enough room on the stack + lua_checkstack(info->luaState, 1); + + int isSpecial = info->readStream->readSint32LE(); + + if (isSpecial) { + unserializeSpecialTable(info, index); + // >>>>> permTbl indexTbl ...... tbl + } else { + unserializeLiteralTable(info, index); + // >>>>> permTbl indexTbl ...... tbl + } +} + +void unserializeFunction(UnSerializationInfo *info, int index) { + // >>>>> permTbl indexTbl ...... + + // Make sure there is enough room on the stack + lua_checkstack(info->luaState, 2); + + byte numUpValues = info->readStream->readByte(); + + LClosure *lclosure = (LClosure *)lua_newLclosure(info->luaState, numUpValues, hvalue(&info->luaState->l_gt)); + pushClosure(info->luaState, (Closure *)lclosure); + // >>>>> permTbl indexTbl ...... func + + // Put *some* proto in the closure, before the GC can find it + lclosure->p = makeFakeProto(info->luaState, numUpValues); + + //Also, we need to temporarily fill the upvalues + lua_pushnil(info->luaState); + // >>>>> permTbl indexTbl ...... func nil + + for (byte i = 0; i < numUpValues; ++i) { + lclosure->upvals[i] = createUpValue(info->luaState, -1); + } + + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... func + + // I can't see offhand how a function would ever get to be self- + // referential, but just in case let's register it early + registerObjectInIndexTable(info, index); + + // Now that it's safe, we can get the real proto + unserialize(info); + // >>>>> permTbl indexTbl ...... func proto + + lclosure->p = gco2p(getObject(info->luaState, -1)->value.gc); + + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... func + + for (byte i = 0; i < numUpValues; ++i) { + // >>>>> permTbl indexTbl ...... func + unserialize(info); + // >>>>> permTbl indexTbl ...... func func2 + + unboxUpValue(info->luaState); + // >>>>> permTbl indexTbl ...... func upValue + lclosure->upvals[i] = gco2uv(getObject(info->luaState, -1)->value.gc); + + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... func + } + + // Finally, the fenv + unserialize(info); + + // >>>>> permTbl indexTbl ...... func ?fenv/nil? + if (!lua_isnil(info->luaState, -1)) { + // >>>>> permTbl indexTbl ...... func fenv + lua_setfenv(info->luaState, -2); + // >>>>> permTbl indexTbl ...... func + } else { + // >>>>> permTbl indexTbl ...... func nil + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... func + } + + // >>>>> permTbl indexTbl ...... func +} + +void unserializeThread(UnSerializationInfo *info, int index) { + // >>>>> permTbl indexTbl ...... + + lua_State *L2; + uint32 stacklimit = 0; + + L2 = lua_newthread(info->luaState); + lua_checkstack(info->luaState, 3); + + // L1: permTbl indexTbl ...... thread + // L2: (empty) + registerObjectInIndexTable(info, index); + + // First, deserialize the object stack + uint32 stackSize = info->readStream->readUint32LE(); + lua_growstack(info->luaState, (int)stackSize); + + // Make sure that the first stack element (a nil, representing + // the imaginary top-level C function) is written to the very, + // very bottom of the stack + L2->top--; + for (uint32 i = 0; i < stackSize; ++i) { + unserialize(info); + // L1: permTbl indexTbl ...... thread obj* + } + + lua_xmove(info->luaState, L2, stackSize); + // L1: permTbl indexTbl ...... thread + // L2: obj* + + // Hereafter, stacks refer to L1 + + + // Now, deserialize the CallInfo stack + + uint32 numFrames = info->readStream->readUint32LE(); + + lua_reallocCallInfo(L2, numFrames * 2); + for (uint32 i = 0; i < numFrames; ++i) { + CallInfo *ci = L2->base_ci + i; + uint32 stackbase = info->readStream->readUint32LE(); + uint32 stackfunc = info->readStream->readUint32LE(); + uint32 stacktop = info->readStream->readUint32LE(); + + ci->nresults = info->readStream->readSint32LE(); + + uint32 savedpc = info->readStream->readUint32LE(); + + if (stacklimit < stacktop) { + stacklimit = stacktop; + } + + ci->base = L2->stack + stackbase; + ci->func = L2->stack + stackfunc; + ci->top = L2->stack + stacktop; + ci->savedpc = (ci != L2->base_ci) ? ci_func(ci)->l.p->code + savedpc : 0; + ci->tailcalls = 0; + + // Update the pointer each time, to keep the GC happy + L2->ci = ci; + } + + // >>>>> permTbl indexTbl ...... thread + // Deserialize the state's other parameters, with the exception of upval stuff + + L2->savedpc = L2->ci->savedpc; + L2->status = info->readStream->readByte(); + uint32 stackbase = info->readStream->readUint32LE(); + uint32 stacktop = info->readStream->readUint32LE(); + + + L2->errfunc = info->readStream->readUint32LE(); + + L2->base = L2->stack + stackbase; + L2->top = L2->stack + stacktop; + + // Finally, "reopen" upvalues. See serializeUpVal() for why we do this + UpVal *uv; + GCObject **nextslot = &L2->openupval; + global_State *g = G(L2); + + while (true) { + unserialize(info); + // >>>>> permTbl indexTbl ...... thread upVal/nil + + // The list is terminated by a nil + if (lua_isnil(info->luaState, -1)) { + // >>>>> permTbl indexTbl ...... thread nil + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... thread + break; + } + + // >>>>> permTbl indexTbl ...... thread boxedUpVal + unboxUpValue(info->luaState); + // >>>>> permTbl indexTbl ...... thread boxedUpVal + + uv = &(getObject(info->luaState, -1)->value.gc->uv); + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... thread + + uint32 stackpos = info->readStream->readUint32LE(); + uv->v = L2->stack + stackpos; + + GCUnlink(info->luaState, (GCObject *)uv); + + uv->marked = luaC_white(g); + *nextslot = (GCObject *)uv; + nextslot = &uv->next; + uv->u.l.prev = &G(L2)->uvhead; + uv->u.l.next = G(L2)->uvhead.u.l.next; + uv->u.l.next->u.l.prev = uv; + G(L2)->uvhead.u.l.next = uv; + lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); + } + *nextslot = NULL; + + // The stack must be valid at least to the highest value among the CallInfos + // 'top' and the values up to there must be filled with 'nil' + lua_checkstack(L2, (int)stacklimit); + for (StkId o = L2->top; o <= L2->top + stacklimit; ++o) { + setnilvalue(o); + } +} + +void unserializeProto(UnSerializationInfo *info, int index) { + // >>>>> permTbl indexTbl ...... + + // We have to be careful. The GC expects a lot out of protos. In particular, we need + // to give the function a valid string for its source, and valid code, even before we + // actually read in the real code. + TString *source = lua_newlstr(info->luaState, "", 0); + Proto *p = lua_newproto(info->luaState); + p->source = source; + p->sizecode = 1; + p->code = (Instruction *)lua_reallocv(info->luaState, NULL, 0, 1, sizeof(Instruction)); + p->code[0] = CREATE_ABC(OP_RETURN, 0, 1, 0); + p->maxstacksize = 2; + p->sizek = 0; + p->sizep = 0; + + lua_checkstack(info->luaState, 2); + + pushProto(info->luaState, p); + // >>>>> permTbl indexTbl ...... proto + + // We don't need to register early, since protos can never ever be + // involved in cyclic references + + // Read in constant references + int sizek = info->readStream->readSint32LE(); + lua_reallocvector(info->luaState, p->k, 0, sizek, TValue); + for (int i = 0; i < sizek; ++i) { + // >>>>> permTbl indexTbl ...... proto + unserialize(info); + // >>>>> permTbl indexTbl ...... proto k + + setobj2s(info->luaState, &p->k[i], getObject(info->luaState, -1)); + p->sizek++; + + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... proto + } + // >>>>> permTbl indexTbl ...... proto + + // Read in sub-proto references + + int sizep = info->readStream->readSint32LE(); + lua_reallocvector(info->luaState, p->p, 0, sizep, Proto *); + for (int i = 0; i < sizep; ++i) { + // >>>>> permTbl indexTbl ...... proto + unserialize(info); + // >>>>> permTbl indexTbl ...... proto subproto + + p->p[i] = (Proto *)getObject(info->luaState, -1)->value.gc; + p->sizep++; + + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... proto + } + // >>>>> permTbl indexTbl ...... proto + + + // Read in code + p->sizecode = info->readStream->readSint32LE(); + lua_reallocvector(info->luaState, p->code, 1, p->sizecode, Instruction); + info->readStream->read(p->code, sizeof(Instruction) * p->sizecode); + + + /* Read in upvalue names */ + p->sizeupvalues = info->readStream->readSint32LE(); + if (p->sizeupvalues) { + lua_reallocvector(info->luaState, p->upvalues, 0, p->sizeupvalues, TString *); + for (int i = 0; i < p->sizeupvalues; ++i) { + // >>>>> permTbl indexTbl ...... proto + unserialize(info); + // >>>>> permTbl indexTbl ...... proto str + + p->upvalues[i] = lua_newlstr(info->luaState, lua_tostring(info->luaState, -1), strlen(lua_tostring(info->luaState, -1))); + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... proto + } + } + // >>>>> permTbl indexTbl ...... proto + + // Read in local variable infos + p->sizelocvars = info->readStream->readSint32LE(); + if (p->sizelocvars) { + lua_reallocvector(info->luaState, p->locvars, 0, p->sizelocvars, LocVar); + for (int i = 0; i < p->sizelocvars; ++i) { + // >>>>> permTbl indexTbl ...... proto + unserialize(info); + // >>>>> permTbl indexTbl ...... proto str + + p->locvars[i].varname = lua_newlstr(info->luaState, lua_tostring(info->luaState, -1), strlen(lua_tostring(info->luaState, -1))); + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... proto + + p->locvars[i].startpc = info->readStream->readSint32LE(); + p->locvars[i].endpc = info->readStream->readSint32LE(); + } + } + // >>>>> permTbl indexTbl ...... proto + + // Read in source string + unserialize(info); + // >>>>> permTbl indexTbl ...... proto sourceStr + + p->source = lua_newlstr(info->luaState, lua_tostring(info->luaState, -1), strlen(lua_tostring(info->luaState, -1))); + lua_pop(info->luaState, 1); + // >>>>> permTbl indexTbl ...... proto + + // Read in line numbers + p->sizelineinfo = info->readStream->readSint32LE(); + if (p->sizelineinfo) { + lua_reallocvector(info->luaState, p->lineinfo, 0, p->sizelineinfo, int); + info->readStream->read(p->lineinfo, sizeof(int) * p->sizelineinfo); + } + + + /* Read in linedefined and lastlinedefined */ + p->linedefined = info->readStream->readSint32LE(); + p->lastlinedefined = info->readStream->readSint32LE(); + + // Read in misc values + p->nups = info->readStream->readByte(); + p->numparams = info->readStream->readByte(); + p->is_vararg = info->readStream->readByte(); + p->maxstacksize = info->readStream->readByte(); +} + +void unserializeUpValue(UnSerializationInfo *info, int index) { + // >>>>> permTbl indexTbl ...... + lua_checkstack(info->luaState, 2); + + boxUpValue_start(info->luaState); + // >>>>> permTbl indexTbl ...... func + registerObjectInIndexTable(info, index); + + unserialize(info); + // >>>>> permTbl indexTbl ...... func obj + + boxUpValue_finish(info->luaState); + // >>>>> permTbl indexTbl ...... func +} + +void unserializeUserData(UnSerializationInfo *info, int index) { + // >>>>> permTbl indexTbl ...... + + // Make sure there is enough room on the stack + lua_checkstack(info->luaState, 2); + + int isspecial = info->readStream->readSint32LE(); + if (isspecial) { + unserialize(info); + // >>>>> permTbl indexTbl ...... specialFunc + + lua_call(info->luaState, 0, 1); + // >>>>> permTbl indexTbl ...... udata + } else { + uint32 length = info->readStream->readUint32LE(); + lua_newuserdata(info->luaState, length); + // >>>>> permTbl indexTbl ...... udata + registerObjectInIndexTable(info, index); + + info->readStream->read(lua_touserdata(info->luaState, -1), length); + + unserialize(info); + // >>>>> permTbl indexTbl ...... udata metaTable/nil + + lua_setmetatable(info->luaState, -2); + // >>>>> permTbl indexTbl ...... udata + } + // >>>>> permTbl indexTbl ...... udata +} + +void unserializePermanent(UnSerializationInfo *info, int index) { + // >>>>> permTbl indexTbl ...... + + // Make sure there is enough room on the stack + lua_checkstack(info->luaState, 2); + + unserialize(info); + // >>>>> permTbl indexTbl ...... permKey + + lua_gettable(info->luaState, 1); + // >>>>> permTbl indexTbl ...... perm +} + +} // End of namespace Lua diff --git a/engines/sword25/util/lua_unserializer.cpp b/engines/sword25/util/lua_unserializer.cpp deleted file mode 100644 index 803c79c8c2..0000000000 --- a/engines/sword25/util/lua_unserializer.cpp +++ /dev/null @@ -1,698 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "sword25/util/lua_serialization.h" - -#include "sword25/util/double_serializer.h" -#include "sword25/util/lua_serialization_util.h" - -#include "common/stream.h" - -#include "lua/lobject.h" -#include "lua/lstate.h" -#include "lua/lgc.h" -#include "lua/lopcodes.h" - - -namespace Lua { - -struct UnSerializationInfo { - lua_State *luaState; - Common::ReadStream *readStream; -}; - -static void unserialize(UnSerializationInfo *info); - -static void unserializeBoolean(UnSerializationInfo *info); -static void unserializeNumber(UnSerializationInfo *info); -static void unserializeString(UnSerializationInfo *info); -static void unserializeTable(UnSerializationInfo *info, int index); -static void unserializeFunction(UnSerializationInfo *info, int index); -static void unserializeThread(UnSerializationInfo *info, int index); -static void unserializeProto(UnSerializationInfo *info, int index); -static void unserializeUpValue(UnSerializationInfo *info, int index); -static void unserializeUserData(UnSerializationInfo *info, int index); -static void unserializePermanent(UnSerializationInfo *info, int index); - - -void unserializeLua(lua_State *luaState, Common::ReadStream *readStream) { - UnSerializationInfo info; - info.luaState = luaState; - info.readStream = readStream; - - // The process starts with the lua stack as follows: - // >>>>> permTbl - // That's the table of permanents - - // Make sure there is enough room on the stack - lua_checkstack(luaState, 3); - - // Create a table to hold indexes of everything thats already been read - lua_newtable(luaState); - // >>>>> permTbl indexTbl - - // Prevent garbage collection while we unserialize - lua_gc(luaState, LUA_GCSTOP, 0); - - // Unserialize the root object - unserialize(&info); - // >>>>> permTbl indexTbl rootObj - - // Re-start garbage collection - lua_gc(luaState, LUA_GCRESTART, 0); - - // Remove the indexTbl - lua_replace(luaState, 2); - // >>>>> permTbl rootObj -} - -/* The object is left on the stack. This is primarily used by unserialize, but - * may be used by GCed objects that may incur cycles in order to preregister - * the object. */ -static void registerObjectInIndexTable(UnSerializationInfo *info, int index) { - // >>>>> permTbl indexTbl ...... obj - - // Make sure there is enough room on the stack - lua_checkstack(info->luaState, 2); - - lua_pushlightuserdata(info->luaState, (void *)index); - // >>>>> permTbl indexTbl ...... obj index - - lua_pushvalue(info->luaState, -2); - // >>>>> permTbl indexTbl ...... obj index obj - - // Push the k/v pair into the indexTbl - lua_settable(info->luaState, 2); - // >>>>> permTbl indexTbl ...... obj -} - -static void unserialize(UnSerializationInfo *info) { - // >>>>> permTbl indexTbl ...... - - // Make sure there is enough room on the stack - lua_checkstack(info->luaState, 2); - - byte isARealValue = info->readStream->readByte(); - if (isARealValue) { - int index = info->readStream->readSint32LE(); - int type = info->readStream->readSint32LE(); - - switch (type) { - case LUA_TBOOLEAN: - unserializeBoolean(info); - break; - case LUA_TLIGHTUSERDATA: - // You can't serialize a pointer - // It would be meaningless on the next run - assert(0); - break; - case LUA_TNUMBER: - unserializeNumber(info); - break; - case LUA_TSTRING: - unserializeString(info); - break; - case LUA_TTABLE: - unserializeTable(info, index); - break; - case LUA_TFUNCTION: - unserializeFunction(info, index); - break; - case LUA_TTHREAD: - unserializeThread(info, index); - break; - case LUA_TPROTO: - unserializeProto(info, index); - break; - case LUA_TUPVAL: - unserializeUpValue(info, index); - break; - case LUA_TUSERDATA: - unserializeUserData(info, index); - break; - case PERMANENT_TYPE: - unserializePermanent(info, index); - break; - default: - assert(0); - } - - - // >>>>> permTbl indexTbl ...... obj - assert(lua_type(info->luaState, -1) == type || - type == PERMANENT_TYPE || - // Remember, upvalues get a special dispensation, as described in boxUpValue - (lua_type(info->luaState, -1) == LUA_TFUNCTION && type == LUA_TUPVAL)); - - registerObjectInIndexTable(info, index); - // >>>>> permTbl indexTbl ...... obj - } else { - int index = info->readStream->readSint32LE(); - - if (index == 0) { - lua_pushnil(info->luaState); - // >>>>> permTbl indexTbl ...... nil - } else { - // Fetch the object from the indexTbl - - lua_pushlightuserdata(info->luaState, (void *)index); - // >>>>> permTbl indexTbl ...... index - - lua_gettable(info->luaState, 2); - // >>>>> permTbl indexTbl ...... ?obj? - - assert(!lua_isnil(info->luaState, -1)); - } - // >>>>> permTbl indexTbl ...... obj/nil - } - - // >>>>> permTbl indexTbl ...... obj/nil -} - -static void unserializeBoolean(UnSerializationInfo *info) { - // >>>>> permTbl indexTbl ...... - - // Make sure there is enough room on the stack - lua_checkstack(info->luaState, 1); - - int value = info->readStream->readSint32LE(); - - lua_pushboolean(info->luaState, value); - // >>>>> permTbl indexTbl ...... bool -} - -static void unserializeNumber(UnSerializationInfo *info) { - // >>>>> permTbl indexTbl ...... - - // Make sure there is enough room on the stack - lua_checkstack(info->luaState, 1); - - // Read the serialized double - Util::SerializedDouble serializedValue; - serializedValue.significandOne = info->readStream->readUint32LE(); - serializedValue.signAndSignificandTwo = info->readStream->readUint32LE(); - serializedValue.exponent = info->readStream->readSint16LE(); - - lua_Number value = Util::decodeDouble(serializedValue); - - lua_pushnumber(info->luaState, value); - // >>>>> permTbl indexTbl ...... num -} - -static void unserializeString(UnSerializationInfo *info) { - // >>>>> permTbl indexTbl ...... - - // Make sure there is enough room on the stack - lua_checkstack(info->luaState, 1); - - uint32 length = info->readStream->readUint32LE(); - char *string = new char[length]; - - info->readStream->read(string, length); - lua_pushlstring(info->luaState, string, length); - - // >>>>> permTbl indexTbl ...... string - - delete[] string; -} - -static void unserializeSpecialTable(UnSerializationInfo *info, int index) { - // >>>>> permTbl indexTbl ...... - - // Make sure there is enough room on the stack - lua_checkstack(info->luaState, 1); - - unserialize(info); - - // >>>>> permTbl indexTbl ...... spfunc - lua_call(info->luaState, 0, 1); - // >>>>> permTbl indexTbl ...... tbl -} - -static void unserializeLiteralTable(UnSerializationInfo *info, int index) { - // >>>>> permTbl indexTbl ...... - - // Make sure there is enough room on the stack - lua_checkstack(info->luaState, 3); - - // Preregister table for handling of cycles - lua_newtable(info->luaState); - - // >>>>> permTbl indexTbl ...... tbl - registerObjectInIndexTable(info, index); - // >>>>> permTbl indexTbl ...... tbl - - // Unserialize metatable - unserialize(info); - // >>>>> permTbl indexTbl ...... tbl ?metaTbl/nil? - - if (lua_istable(info->luaState, -1)) { - // >>>>> permTbl indexTbl ...... tbl metaTbl - lua_setmetatable(info->luaState, -2); - // >>>>> permTbl indexTbl ...... tbl - } else { - // >>>>> permTbl indexTbl ...... tbl nil - lua_pop(info->luaState, 1); - // >>>>> permTbl indexTbl ...... tbl - } - // >>>>> permTbl indexTbl ...... tbl - - - while (1) { - // >>>>> permTbl indexTbl ...... tbl - unserialize(info); - // >>>>> permTbl indexTbl ...... tbl key/nil - - // The table serialization is nil terminated - if (lua_isnil(info->luaState, -1)) { - // >>>>> permTbl indexTbl ...... tbl nil - lua_pop(info->luaState, 1); - // >>>>> permTbl indexTbl ...... tbl - - break; - } - - // >>>>> permTbl indexTbl ...... tbl key - unserialize(info); - // >>>>> permTbl indexTbl ...... tbl value - - lua_rawset(info->luaState, -3); - // >>>>> permTbl indexTbl ...... tbl - } -} - -void unserializeTable(UnSerializationInfo *info, int index) { - // >>>>> permTbl indexTbl ...... - - // Make sure there is enough room on the stack - lua_checkstack(info->luaState, 1); - - int isSpecial = info->readStream->readSint32LE(); - - if (isSpecial) { - unserializeSpecialTable(info, index); - // >>>>> permTbl indexTbl ...... tbl - } else { - unserializeLiteralTable(info, index); - // >>>>> permTbl indexTbl ...... tbl - } -} - -void unserializeFunction(UnSerializationInfo *info, int index) { - // >>>>> permTbl indexTbl ...... - - // Make sure there is enough room on the stack - lua_checkstack(info->luaState, 2); - - byte numUpValues = info->readStream->readByte(); - - LClosure *lclosure = (LClosure *)lua_newLclosure(info->luaState, numUpValues, hvalue(&info->luaState->l_gt)); - pushClosure(info->luaState, (Closure *)lclosure); - // >>>>> permTbl indexTbl ...... func - - // Put *some* proto in the closure, before the GC can find it - lclosure->p = makeFakeProto(info->luaState, numUpValues); - - //Also, we need to temporarily fill the upvalues - lua_pushnil(info->luaState); - // >>>>> permTbl indexTbl ...... func nil - - for (byte i = 0; i < numUpValues; ++i) { - lclosure->upvals[i] = createUpValue(info->luaState, -1); - } - - lua_pop(info->luaState, 1); - // >>>>> permTbl indexTbl ...... func - - // I can't see offhand how a function would ever get to be self- - // referential, but just in case let's register it early - registerObjectInIndexTable(info, index); - - // Now that it's safe, we can get the real proto - unserialize(info); - // >>>>> permTbl indexTbl ...... func proto - - lclosure->p = gco2p(getObject(info->luaState, -1)->value.gc); - - lua_pop(info->luaState, 1); - // >>>>> permTbl indexTbl ...... func - - for (byte i = 0; i < numUpValues; ++i) { - // >>>>> permTbl indexTbl ...... func - unserialize(info); - // >>>>> permTbl indexTbl ...... func func2 - - unboxUpValue(info->luaState); - // >>>>> permTbl indexTbl ...... func upValue - lclosure->upvals[i] = gco2uv(getObject(info->luaState, -1)->value.gc); - - lua_pop(info->luaState, 1); - // >>>>> permTbl indexTbl ...... func - } - - // Finally, the fenv - unserialize(info); - - // >>>>> permTbl indexTbl ...... func ?fenv/nil? - if (!lua_isnil(info->luaState, -1)) { - // >>>>> permTbl indexTbl ...... func fenv - lua_setfenv(info->luaState, -2); - // >>>>> permTbl indexTbl ...... func - } else { - // >>>>> permTbl indexTbl ...... func nil - lua_pop(info->luaState, 1); - // >>>>> permTbl indexTbl ...... func - } - - // >>>>> permTbl indexTbl ...... func -} - -void unserializeThread(UnSerializationInfo *info, int index) { - // >>>>> permTbl indexTbl ...... - - lua_State *L2; - uint32 stacklimit = 0; - - L2 = lua_newthread(info->luaState); - lua_checkstack(info->luaState, 3); - - // L1: permTbl indexTbl ...... thread - // L2: (empty) - registerObjectInIndexTable(info, index); - - // First, deserialize the object stack - uint32 stackSize = info->readStream->readUint32LE(); - lua_growstack(info->luaState, (int)stackSize); - - // Make sure that the first stack element (a nil, representing - // the imaginary top-level C function) is written to the very, - // very bottom of the stack - L2->top--; - for (uint32 i = 0; i < stackSize; ++i) { - unserialize(info); - // L1: permTbl indexTbl ...... thread obj* - } - - lua_xmove(info->luaState, L2, stackSize); - // L1: permTbl indexTbl ...... thread - // L2: obj* - - // Hereafter, stacks refer to L1 - - - // Now, deserialize the CallInfo stack - - uint32 numFrames = info->readStream->readUint32LE(); - - lua_reallocCallInfo(L2, numFrames * 2); - for (uint32 i = 0; i < numFrames; ++i) { - CallInfo *ci = L2->base_ci + i; - uint32 stackbase = info->readStream->readUint32LE(); - uint32 stackfunc = info->readStream->readUint32LE(); - uint32 stacktop = info->readStream->readUint32LE(); - - ci->nresults = info->readStream->readSint32LE(); - - uint32 savedpc = info->readStream->readUint32LE(); - - if (stacklimit < stacktop) { - stacklimit = stacktop; - } - - ci->base = L2->stack + stackbase; - ci->func = L2->stack + stackfunc; - ci->top = L2->stack + stacktop; - ci->savedpc = (ci != L2->base_ci) ? ci_func(ci)->l.p->code + savedpc : 0; - ci->tailcalls = 0; - - // Update the pointer each time, to keep the GC happy - L2->ci = ci; - } - - // >>>>> permTbl indexTbl ...... thread - // Deserialize the state's other parameters, with the exception of upval stuff - - L2->savedpc = L2->ci->savedpc; - L2->status = info->readStream->readByte(); - uint32 stackbase = info->readStream->readUint32LE(); - uint32 stacktop = info->readStream->readUint32LE(); - - - L2->errfunc = info->readStream->readUint32LE(); - - L2->base = L2->stack + stackbase; - L2->top = L2->stack + stacktop; - - // Finally, "reopen" upvalues. See serializeUpVal() for why we do this - UpVal *uv; - GCObject **nextslot = &L2->openupval; - global_State *g = G(L2); - - while (true) { - unserialize(info); - // >>>>> permTbl indexTbl ...... thread upVal/nil - - // The list is terminated by a nil - if (lua_isnil(info->luaState, -1)) { - // >>>>> permTbl indexTbl ...... thread nil - lua_pop(info->luaState, 1); - // >>>>> permTbl indexTbl ...... thread - break; - } - - // >>>>> permTbl indexTbl ...... thread boxedUpVal - unboxUpValue(info->luaState); - // >>>>> permTbl indexTbl ...... thread boxedUpVal - - uv = &(getObject(info->luaState, -1)->value.gc->uv); - lua_pop(info->luaState, 1); - // >>>>> permTbl indexTbl ...... thread - - uint32 stackpos = info->readStream->readUint32LE(); - uv->v = L2->stack + stackpos; - - GCUnlink(info->luaState, (GCObject *)uv); - - uv->marked = luaC_white(g); - *nextslot = (GCObject *)uv; - nextslot = &uv->next; - uv->u.l.prev = &G(L2)->uvhead; - uv->u.l.next = G(L2)->uvhead.u.l.next; - uv->u.l.next->u.l.prev = uv; - G(L2)->uvhead.u.l.next = uv; - lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); - } - *nextslot = NULL; - - // The stack must be valid at least to the highest value among the CallInfos - // 'top' and the values up to there must be filled with 'nil' - lua_checkstack(L2, (int)stacklimit); - for (StkId o = L2->top; o <= L2->top + stacklimit; ++o) { - setnilvalue(o); - } -} - -void unserializeProto(UnSerializationInfo *info, int index) { - // >>>>> permTbl indexTbl ...... - - // We have to be careful. The GC expects a lot out of protos. In particular, we need - // to give the function a valid string for its source, and valid code, even before we - // actually read in the real code. - TString *source = lua_newlstr(info->luaState, "", 0); - Proto *p = lua_newproto(info->luaState); - p->source = source; - p->sizecode = 1; - p->code = (Instruction *)lua_reallocv(info->luaState, NULL, 0, 1, sizeof(Instruction)); - p->code[0] = CREATE_ABC(OP_RETURN, 0, 1, 0); - p->maxstacksize = 2; - p->sizek = 0; - p->sizep = 0; - - lua_checkstack(info->luaState, 2); - - pushProto(info->luaState, p); - // >>>>> permTbl indexTbl ...... proto - - // We don't need to register early, since protos can never ever be - // involved in cyclic references - - // Read in constant references - int sizek = info->readStream->readSint32LE(); - lua_reallocvector(info->luaState, p->k, 0, sizek, TValue); - for (int i = 0; i < sizek; ++i) { - // >>>>> permTbl indexTbl ...... proto - unserialize(info); - // >>>>> permTbl indexTbl ...... proto k - - setobj2s(info->luaState, &p->k[i], getObject(info->luaState, -1)); - p->sizek++; - - lua_pop(info->luaState, 1); - // >>>>> permTbl indexTbl ...... proto - } - // >>>>> permTbl indexTbl ...... proto - - // Read in sub-proto references - - int sizep = info->readStream->readSint32LE(); - lua_reallocvector(info->luaState, p->p, 0, sizep, Proto *); - for (int i = 0; i < sizep; ++i) { - // >>>>> permTbl indexTbl ...... proto - unserialize(info); - // >>>>> permTbl indexTbl ...... proto subproto - - p->p[i] = (Proto *)getObject(info->luaState, -1)->value.gc; - p->sizep++; - - lua_pop(info->luaState, 1); - // >>>>> permTbl indexTbl ...... proto - } - // >>>>> permTbl indexTbl ...... proto - - - // Read in code - p->sizecode = info->readStream->readSint32LE(); - lua_reallocvector(info->luaState, p->code, 1, p->sizecode, Instruction); - info->readStream->read(p->code, sizeof(Instruction) * p->sizecode); - - - /* Read in upvalue names */ - p->sizeupvalues = info->readStream->readSint32LE(); - if (p->sizeupvalues) { - lua_reallocvector(info->luaState, p->upvalues, 0, p->sizeupvalues, TString *); - for (int i = 0; i < p->sizeupvalues; ++i) { - // >>>>> permTbl indexTbl ...... proto - unserialize(info); - // >>>>> permTbl indexTbl ...... proto str - - p->upvalues[i] = lua_newlstr(info->luaState, lua_tostring(info->luaState, -1), strlen(lua_tostring(info->luaState, -1))); - lua_pop(info->luaState, 1); - // >>>>> permTbl indexTbl ...... proto - } - } - // >>>>> permTbl indexTbl ...... proto - - // Read in local variable infos - p->sizelocvars = info->readStream->readSint32LE(); - if (p->sizelocvars) { - lua_reallocvector(info->luaState, p->locvars, 0, p->sizelocvars, LocVar); - for (int i = 0; i < p->sizelocvars; ++i) { - // >>>>> permTbl indexTbl ...... proto - unserialize(info); - // >>>>> permTbl indexTbl ...... proto str - - p->locvars[i].varname = lua_newlstr(info->luaState, lua_tostring(info->luaState, -1), strlen(lua_tostring(info->luaState, -1))); - lua_pop(info->luaState, 1); - // >>>>> permTbl indexTbl ...... proto - - p->locvars[i].startpc = info->readStream->readSint32LE(); - p->locvars[i].endpc = info->readStream->readSint32LE(); - } - } - // >>>>> permTbl indexTbl ...... proto - - // Read in source string - unserialize(info); - // >>>>> permTbl indexTbl ...... proto sourceStr - - p->source = lua_newlstr(info->luaState, lua_tostring(info->luaState, -1), strlen(lua_tostring(info->luaState, -1))); - lua_pop(info->luaState, 1); - // >>>>> permTbl indexTbl ...... proto - - // Read in line numbers - p->sizelineinfo = info->readStream->readSint32LE(); - if (p->sizelineinfo) { - lua_reallocvector(info->luaState, p->lineinfo, 0, p->sizelineinfo, int); - info->readStream->read(p->lineinfo, sizeof(int) * p->sizelineinfo); - } - - - /* Read in linedefined and lastlinedefined */ - p->linedefined = info->readStream->readSint32LE(); - p->lastlinedefined = info->readStream->readSint32LE(); - - // Read in misc values - p->nups = info->readStream->readByte(); - p->numparams = info->readStream->readByte(); - p->is_vararg = info->readStream->readByte(); - p->maxstacksize = info->readStream->readByte(); -} - -void unserializeUpValue(UnSerializationInfo *info, int index) { - // >>>>> permTbl indexTbl ...... - lua_checkstack(info->luaState, 2); - - boxUpValue_start(info->luaState); - // >>>>> permTbl indexTbl ...... func - registerObjectInIndexTable(info, index); - - unserialize(info); - // >>>>> permTbl indexTbl ...... func obj - - boxUpValue_finish(info->luaState); - // >>>>> permTbl indexTbl ...... func -} - -void unserializeUserData(UnSerializationInfo *info, int index) { - // >>>>> permTbl indexTbl ...... - - // Make sure there is enough room on the stack - lua_checkstack(info->luaState, 2); - - int isspecial = info->readStream->readSint32LE(); - if (isspecial) { - unserialize(info); - // >>>>> permTbl indexTbl ...... specialFunc - - lua_call(info->luaState, 0, 1); - // >>>>> permTbl indexTbl ...... udata - } else { - uint32 length = info->readStream->readUint32LE(); - lua_newuserdata(info->luaState, length); - // >>>>> permTbl indexTbl ...... udata - registerObjectInIndexTable(info, index); - - info->readStream->read(lua_touserdata(info->luaState, -1), length); - - unserialize(info); - // >>>>> permTbl indexTbl ...... udata metaTable/nil - - lua_setmetatable(info->luaState, -2); - // >>>>> permTbl indexTbl ...... udata - } - // >>>>> permTbl indexTbl ...... udata -} - -void unserializePermanent(UnSerializationInfo *info, int index) { - // >>>>> permTbl indexTbl ...... - - // Make sure there is enough room on the stack - lua_checkstack(info->luaState, 2); - - unserialize(info); - // >>>>> permTbl indexTbl ...... permKey - - lua_gettable(info->luaState, 1); - // >>>>> permTbl indexTbl ...... perm -} - -} // End of namespace Lua -- cgit v1.2.3 From 08e3f21a8df184bc697e6c03adf968d0cbdbac21 Mon Sep 17 00:00:00 2001 From: RichieSams Date: Tue, 30 Dec 2014 15:22:43 -0600 Subject: SWORD25: Rename double serialization file to better represent what it is AKA functions, rather than a class --- engines/sword25/module.mk | 2 +- engines/sword25/util/double_serialization.cpp | 138 ++++++++++++++++++++++++++ engines/sword25/util/double_serialization.h | 95 ++++++++++++++++++ engines/sword25/util/double_serializer.cpp | 138 -------------------------- engines/sword25/util/double_serializer.h | 95 ------------------ engines/sword25/util/lua_persist.cpp | 2 +- engines/sword25/util/lua_unpersist.cpp | 2 +- 7 files changed, 236 insertions(+), 236 deletions(-) create mode 100644 engines/sword25/util/double_serialization.cpp create mode 100644 engines/sword25/util/double_serialization.h delete mode 100644 engines/sword25/util/double_serializer.cpp delete mode 100644 engines/sword25/util/double_serializer.h (limited to 'engines') diff --git a/engines/sword25/module.mk b/engines/sword25/module.mk index 129b4f040e..0842eb9aa8 100644 --- a/engines/sword25/module.mk +++ b/engines/sword25/module.mk @@ -82,7 +82,7 @@ MODULE_OBJS := \ util/lua/lvm.o \ util/lua/lzio.o \ util/lua/scummvm_file.o \ - util/double_serializer.o \ + util/double_serialization.o \ util/lua_persistence_util.o \ util/lua_persist.o \ util/lua_unpersist.o diff --git a/engines/sword25/util/double_serialization.cpp b/engines/sword25/util/double_serialization.cpp new file mode 100644 index 0000000000..48fd75cb33 --- /dev/null +++ b/engines/sword25/util/double_serialization.cpp @@ -0,0 +1,138 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "sword25/util/double_serialization.h" + +#include "common/scummsys.h" + + +namespace Util { + +SerializedDouble encodeDouble(double value) { + // Split the value into its significand and exponent + int exponent; + double significand = frexp(value, &exponent); + + // Shift the the first part of the significand into the integer range + double shiftedsignificandPart = ldexp(abs(significand), 32); + uint32 significandOne = uint32(floor(shiftedsignificandPart)); + + // Shift the remainder of the significand into the integer range + shiftedsignificandPart -= significandOne; + uint32 significandTwo = (uint32)(ldexp(shiftedsignificandPart, 31)); + + SerializedDouble returnValue; + returnValue.significandOne = significandOne; // SignificandOne + returnValue.signAndSignificandTwo = ((uint32)(value < 0 ? 1 : 0) << 31) | // Sign + significandTwo; // SignificandTwo + returnValue.exponent = (int16)exponent; + return returnValue; +} + +double decodeDouble(SerializedDouble value) { + // Expand the exponent and the parts of the significand + int exponent = (int)value.exponent; + double expandedsignificandOne = (double)value.significandOne; + double expandedsignificandTwo = (double)(value.signAndSignificandTwo & 0x7FFFFFFF); + + // Deflate the significand + double shiftedsignificand = ldexp(expandedsignificandTwo, -21); + double significand = ldexp(expandedsignificandOne + shiftedsignificand, -32); + + // Re-calculate the actual double + double returnValue = ldexp(significand, exponent); + + // Check the sign bit and return + return ((value.signAndSignificandTwo & 0x80000000) == 0x80000000) ? -returnValue : returnValue; +} + +uint64 encodeDouble_64(double value) { + // Split the value into its significand and exponent + int exponent; + double significand = frexp(value, &exponent); + + // Shift the significand into the integer range + double shiftedsignificand = ldexp(abs(significand), 53); + + // Combine everything using the IEEE standard + uint64 uintsignificand = (uint64)shiftedsignificand; + return ((uint64)(value < 0 ? 1 : 0) << 63) | // Sign + ((uint64)(exponent + 1023) << 52) | // Exponent stored as an offset to 1023 + (uintsignificand & 0x000FFFFFFFFFFFFF); // significand with MSB inferred +} + +double decodeDouble_64(uint64 value) { + // Expand the exponent and significand + int exponent = (int)((value >> 52) & 0x7FF) - 1023; + double expandedsignificand = (double)(0x10000000000000 /* Inferred MSB */ | (value & 0x000FFFFFFFFFFFFF)); + + // Deflate the significand + int temp; + double significand = frexp(expandedsignificand, &temp); + + // Re-calculate the actual double + double returnValue = ldexp(significand, exponent); + + // Check the sign bit and return + return ((value & 0x8000000000000000) == 0x8000000000000000) ? -returnValue : returnValue; +} + +CompactSerializedDouble encodeDouble_Compact(double value) { + // Split the value into its significand and exponent + int exponent; + double significand = frexp(value, &exponent); + + // Shift the the first part of the significand into the integer range + double shiftedsignificandPart = ldexp(abs(significand), 32); + uint32 significandOne = uint32(floor(shiftedsignificandPart)); + + // Shift the remainder of the significand into the integer range + shiftedsignificandPart -= significandOne; + uint32 significandTwo = (uint32)(ldexp(shiftedsignificandPart, 21)); + + CompactSerializedDouble returnValue; + returnValue.signAndSignificandOne = ((uint32)(value < 0 ? 1 : 0) << 31) | // Sign + (significandOne & 0x7FFFFFFF); // significandOne with MSB inferred + // Exponent stored as an offset to 1023 + returnValue.exponentAndSignificandTwo = ((uint32)(exponent + 1023) << 21) | significandTwo; + + return returnValue; +} + +double decodeDouble_Compact(CompactSerializedDouble value) { + // Expand the exponent and the parts of the significand + int exponent = (int)(value.exponentAndSignificandTwo >> 21) - 1023; + double expandedsignificandOne = (double)(0x80000000 /* Inferred MSB */ | (value.signAndSignificandOne & 0x7FFFFFFF)); + double expandedsignificandTwo = (double)(value.exponentAndSignificandTwo & 0x1FFFFF); + + // Deflate the significand + double shiftedsignificand = ldexp(expandedsignificandTwo, -21); + double significand = ldexp(expandedsignificandOne + shiftedsignificand, -32); + + // Re-calculate the actual double + double returnValue = ldexp(significand, exponent); + + // Check the sign bit and return + return ((value.signAndSignificandOne & 0x80000000) == 0x80000000) ? -returnValue : returnValue; +} + +} // End of namespace Sword25 diff --git a/engines/sword25/util/double_serialization.h b/engines/sword25/util/double_serialization.h new file mode 100644 index 0000000000..e90338c369 --- /dev/null +++ b/engines/sword25/util/double_serialization.h @@ -0,0 +1,95 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef DOUBLE_SERIALIZATION_H +#define DOUBLE_SERIALIZATION_H + +#include "common/types.h" + + +namespace Util { + +struct SerializedDouble { + uint32 significandOne; + uint32 signAndSignificandTwo; + int16 exponent; +}; + +struct CompactSerializedDouble { + uint32 signAndSignificandOne; + uint32 exponentAndSignificandTwo; +}; + +/** + * Encodes a double as two uint32 and a one int16 + * + * Supports denormalized numbers. Does NOT support NaN, or Inf + * + * @param value The value to encode + * @return The encoded value + */ +SerializedDouble encodeDouble(double value); +/** + * Decodes a previously encoded double + * + * @param value The value to decode + * @return The decoded value + */ +double decodeDouble(SerializedDouble value); + +/** + * Encodes a double as a uint64 + * + * Does NOT support denormalized numbers. Does NOT support NaN, or Inf + * + * @param value The value to encode + * @return The encoded value + */ +uint64 encodeDouble_64(double value); +/** + * Decodes a previously encoded double + * + * @param value The value to decode + * @return The decoded value + */ +double decodeDouble_64(uint64 value); + +/** + * Encodes a double as two uint32 + * + * Does NOT support denormalized numbers. Does NOT support NaN, or Inf + * + * @param value The value to encode + * @return The encoded value + */ +CompactSerializedDouble encodeDouble_Compact(double value); +/** + * Decodes a previously encoded double + * + * @param value The value to decode + * @return The decoded value + */ +double decodeDouble_Compact(CompactSerializedDouble value); + +} // End of namespace Sword25 + +#endif diff --git a/engines/sword25/util/double_serializer.cpp b/engines/sword25/util/double_serializer.cpp deleted file mode 100644 index d7ba4f3052..0000000000 --- a/engines/sword25/util/double_serializer.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "sword25/util/double_serializer.h" - -#include "common/scummsys.h" - - -namespace Util { - -SerializedDouble encodeDouble(double value) { - // Split the value into its significand and exponent - int exponent; - double significand = frexp(value, &exponent); - - // Shift the the first part of the significand into the integer range - double shiftedsignificandPart = ldexp(abs(significand), 32); - uint32 significandOne = uint32(floor(shiftedsignificandPart)); - - // Shift the remainder of the significand into the integer range - shiftedsignificandPart -= significandOne; - uint32 significandTwo = (uint32)(ldexp(shiftedsignificandPart, 31)); - - SerializedDouble returnValue; - returnValue.significandOne = significandOne; // SignificandOne - returnValue.signAndSignificandTwo = ((uint32)(value < 0 ? 1 : 0) << 31) | // Sign - significandTwo; // SignificandTwo - returnValue.exponent = (int16)exponent; - return returnValue; -} - -double decodeDouble(SerializedDouble value) { - // Expand the exponent and the parts of the significand - int exponent = (int)value.exponent; - double expandedsignificandOne = (double)value.significandOne; - double expandedsignificandTwo = (double)(value.signAndSignificandTwo & 0x7FFFFFFF); - - // Deflate the significand - double shiftedsignificand = ldexp(expandedsignificandTwo, -21); - double significand = ldexp(expandedsignificandOne + shiftedsignificand, -32); - - // Re-calculate the actual double - double returnValue = ldexp(significand, exponent); - - // Check the sign bit and return - return ((value.signAndSignificandTwo & 0x80000000) == 0x80000000) ? -returnValue : returnValue; -} - -uint64 encodeDouble_64(double value) { - // Split the value into its significand and exponent - int exponent; - double significand = frexp(value, &exponent); - - // Shift the significand into the integer range - double shiftedsignificand = ldexp(abs(significand), 53); - - // Combine everything using the IEEE standard - uint64 uintsignificand = (uint64)shiftedsignificand; - return ((uint64)(value < 0 ? 1 : 0) << 63) | // Sign - ((uint64)(exponent + 1023) << 52) | // Exponent stored as an offset to 1023 - (uintsignificand & 0x000FFFFFFFFFFFFF); // significand with MSB inferred -} - -double decodeDouble_64(uint64 value) { - // Expand the exponent and significand - int exponent = (int)((value >> 52) & 0x7FF) - 1023; - double expandedsignificand = (double)(0x10000000000000 /* Inferred MSB */ | (value & 0x000FFFFFFFFFFFFF)); - - // Deflate the significand - int temp; - double significand = frexp(expandedsignificand, &temp); - - // Re-calculate the actual double - double returnValue = ldexp(significand, exponent); - - // Check the sign bit and return - return ((value & 0x8000000000000000) == 0x8000000000000000) ? -returnValue : returnValue; -} - -CompactSerializedDouble encodeDouble_Compact(double value) { - // Split the value into its significand and exponent - int exponent; - double significand = frexp(value, &exponent); - - // Shift the the first part of the significand into the integer range - double shiftedsignificandPart = ldexp(abs(significand), 32); - uint32 significandOne = uint32(floor(shiftedsignificandPart)); - - // Shift the remainder of the significand into the integer range - shiftedsignificandPart -= significandOne; - uint32 significandTwo = (uint32)(ldexp(shiftedsignificandPart, 21)); - - CompactSerializedDouble returnValue; - returnValue.signAndSignificandOne = ((uint32)(value < 0 ? 1 : 0) << 31) | // Sign - (significandOne & 0x7FFFFFFF); // significandOne with MSB inferred - // Exponent stored as an offset to 1023 - returnValue.exponentAndSignificandTwo = ((uint32)(exponent + 1023) << 21) | significandTwo; - - return returnValue; -} - -double decodeDouble_Compact(CompactSerializedDouble value) { - // Expand the exponent and the parts of the significand - int exponent = (int)(value.exponentAndSignificandTwo >> 21) - 1023; - double expandedsignificandOne = (double)(0x80000000 /* Inferred MSB */ | (value.signAndSignificandOne & 0x7FFFFFFF)); - double expandedsignificandTwo = (double)(value.exponentAndSignificandTwo & 0x1FFFFF); - - // Deflate the significand - double shiftedsignificand = ldexp(expandedsignificandTwo, -21); - double significand = ldexp(expandedsignificandOne + shiftedsignificand, -32); - - // Re-calculate the actual double - double returnValue = ldexp(significand, exponent); - - // Check the sign bit and return - return ((value.signAndSignificandOne & 0x80000000) == 0x80000000) ? -returnValue : returnValue; -} - -} // End of namespace Sword25 diff --git a/engines/sword25/util/double_serializer.h b/engines/sword25/util/double_serializer.h deleted file mode 100644 index e90338c369..0000000000 --- a/engines/sword25/util/double_serializer.h +++ /dev/null @@ -1,95 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#ifndef DOUBLE_SERIALIZATION_H -#define DOUBLE_SERIALIZATION_H - -#include "common/types.h" - - -namespace Util { - -struct SerializedDouble { - uint32 significandOne; - uint32 signAndSignificandTwo; - int16 exponent; -}; - -struct CompactSerializedDouble { - uint32 signAndSignificandOne; - uint32 exponentAndSignificandTwo; -}; - -/** - * Encodes a double as two uint32 and a one int16 - * - * Supports denormalized numbers. Does NOT support NaN, or Inf - * - * @param value The value to encode - * @return The encoded value - */ -SerializedDouble encodeDouble(double value); -/** - * Decodes a previously encoded double - * - * @param value The value to decode - * @return The decoded value - */ -double decodeDouble(SerializedDouble value); - -/** - * Encodes a double as a uint64 - * - * Does NOT support denormalized numbers. Does NOT support NaN, or Inf - * - * @param value The value to encode - * @return The encoded value - */ -uint64 encodeDouble_64(double value); -/** - * Decodes a previously encoded double - * - * @param value The value to decode - * @return The decoded value - */ -double decodeDouble_64(uint64 value); - -/** - * Encodes a double as two uint32 - * - * Does NOT support denormalized numbers. Does NOT support NaN, or Inf - * - * @param value The value to encode - * @return The encoded value - */ -CompactSerializedDouble encodeDouble_Compact(double value); -/** - * Decodes a previously encoded double - * - * @param value The value to decode - * @return The decoded value - */ -double decodeDouble_Compact(CompactSerializedDouble value); - -} // End of namespace Sword25 - -#endif diff --git a/engines/sword25/util/lua_persist.cpp b/engines/sword25/util/lua_persist.cpp index b9c0b13e11..939dbf38a8 100644 --- a/engines/sword25/util/lua_persist.cpp +++ b/engines/sword25/util/lua_persist.cpp @@ -22,7 +22,7 @@ #include "sword25/util/lua_persistence.h" -#include "sword25/util/double_serializer.h" +#include "sword25/util/double_serialization.h" #include "sword25/util/lua_persistence_util.h" #include "common/stream.h" diff --git a/engines/sword25/util/lua_unpersist.cpp b/engines/sword25/util/lua_unpersist.cpp index aa924ff7c5..8d644302f9 100644 --- a/engines/sword25/util/lua_unpersist.cpp +++ b/engines/sword25/util/lua_unpersist.cpp @@ -22,7 +22,7 @@ #include "sword25/util/lua_persistence.h" -#include "sword25/util/double_serializer.h" +#include "sword25/util/double_serialization.h" #include "sword25/util/lua_persistence_util.h" #include "common/stream.h" -- cgit v1.2.3 From 8668707f160fa171edfa68df036f28c7ba4e9a88 Mon Sep 17 00:00:00 2001 From: RichieSams Date: Tue, 30 Dec 2014 15:11:17 -0600 Subject: SWORD25: Fix how nils are persisted The unpersist code expects nils to be represented as an index with value 0. The persist code incorrectly wrote out this data --- engines/sword25/util/lua_persist.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/sword25/util/lua_persist.cpp b/engines/sword25/util/lua_persist.cpp index 939dbf38a8..6d758067ad 100644 --- a/engines/sword25/util/lua_persist.cpp +++ b/engines/sword25/util/lua_persist.cpp @@ -59,7 +59,7 @@ void persistLua(lua_State *luaState, Common::WriteStream *writeStream) { SerializationInfo info; info.luaState = luaState; info.writeStream = writeStream; - info.counter = 0u; + info.counter = 1u; // The process starts with the lua stack as follows: // >>>>> permTbl rootObj @@ -145,19 +145,22 @@ static void serialize(SerializationInfo *info) { return; } - // Pop the nil off the stack + // Pop the index/nil off the stack lua_pop(info->luaState, 1); - // Write out a flag that indicates that this is a real object - info->writeStream->writeByte(1); - - // If the object itself is nil, then write out a zero as a placeholder + // If the obj itself is nil, we represent it as an index of 0 if (lua_isnil(info->luaState, -1)) { + // Write out a flag that indicates that it's an index info->writeStream->writeByte(0); + // Write out the index + info->writeStream->writeUint32LE(0); return; } + // Write out a flag that indicates that this is a real object + info->writeStream->writeByte(1); + // Add the object to the indexTbl lua_pushvalue(info->luaState, -1); -- cgit v1.2.3 From 67114c3e7eafdd6ba8c7bc799a40f789acc1efa3 Mon Sep 17 00:00:00 2001 From: RichieSams Date: Tue, 30 Dec 2014 15:30:55 -0600 Subject: SWORD25: Remove old lua persistence files --- engines/sword25/util/pluto/CHANGELOG | 37 - engines/sword25/util/pluto/FILEFORMAT | 168 --- engines/sword25/util/pluto/README | 133 -- engines/sword25/util/pluto/THANKS | 9 - engines/sword25/util/pluto/pdep.cpp | 112 -- engines/sword25/util/pluto/pdep/README | 5 - engines/sword25/util/pluto/pdep/lzio.h | 65 - engines/sword25/util/pluto/pdep/pdep.h | 42 - engines/sword25/util/pluto/pluto.cpp | 2083 -------------------------------- engines/sword25/util/pluto/pluto.h | 25 - engines/sword25/util/pluto/plzio.cpp | 74 -- 11 files changed, 2753 deletions(-) delete mode 100644 engines/sword25/util/pluto/CHANGELOG delete mode 100644 engines/sword25/util/pluto/FILEFORMAT delete mode 100644 engines/sword25/util/pluto/README delete mode 100644 engines/sword25/util/pluto/THANKS delete mode 100644 engines/sword25/util/pluto/pdep.cpp delete mode 100644 engines/sword25/util/pluto/pdep/README delete mode 100644 engines/sword25/util/pluto/pdep/lzio.h delete mode 100644 engines/sword25/util/pluto/pdep/pdep.h delete mode 100644 engines/sword25/util/pluto/pluto.cpp delete mode 100644 engines/sword25/util/pluto/pluto.h delete mode 100644 engines/sword25/util/pluto/plzio.cpp (limited to 'engines') diff --git a/engines/sword25/util/pluto/CHANGELOG b/engines/sword25/util/pluto/CHANGELOG deleted file mode 100644 index 1be321f898..0000000000 --- a/engines/sword25/util/pluto/CHANGELOG +++ /dev/null @@ -1,37 +0,0 @@ -$Id$ - --- 2.4 -- -* Changed upval unboxing to allow upvals which contain func-housed cycles -* Added stack checking to all stack-growing functions -* Serialized debug information for functions - --- 2.3 -- -* Added LUALIB_API declaration for luaopen_pluto - --- 2.2 -- -* Rolled all internal Lua dependencies into the Pluto distribution -* Made the unit tests depend on dynamically loading Pluto - --- 2.1 -- -* Various fixes to make the GC happy -* stack size always expanded where necessary -* fixed some memory leaks -* GC disabled during unpersist -* callstack initialized for traversal - -This changelog is maintained as of version 2.0alpha1. -Earlier versions are changelogged on the LuaForge site. - --- 2.0 -- -* Fixed a few format changes to 5.1.3 -* Fixed myriad warnings -* GCC compliance: not incrementing cast results -* Fix for self-referring upvals -* Renamed loading function to work with Lua module system -* Loading tables with __newindex works -* unpersist makes buffer copy - --- 2.0alpha1 -- -* Fixed all outstanding 5.0->5.1 conversion issues -* Made heavier use of size_t in preference to int -* Fixed GC/Upval issue (thanks to Eric Jacobs) diff --git a/engines/sword25/util/pluto/FILEFORMAT b/engines/sword25/util/pluto/FILEFORMAT deleted file mode 100644 index e7716675c7..0000000000 --- a/engines/sword25/util/pluto/FILEFORMAT +++ /dev/null @@ -1,168 +0,0 @@ -$Id$ - -pluto_persist() produces a "hunk" of objects. Here's the file format adhered -to by the function, and expected by pluto_unpersist(). - -As a developer, I feel that where file format information is given it is of -utmost importance that that information precisely and accurately reflects the -actual operation of the application. Therefore, if you find any discrepancy -between this and actual operation, please lambast me thoroughly over email. - -Pseudo-C is used to express the file format. Padding is assumed to be -nonexistent. The keyword "one_of" is used to express a concept similar to -"union", except that its size is the size of the actual datatype chosen. Thus, -objects which contain, directly or indirectly, a one_of, may vary in size. - - -struct Object { - int firstTime; /* Whether this is the first time the object - is being referenced */ - one_of { - RealObject o; /* if firstTime == 1 */ - Reference r; /* if firstTime == 0 */ - }; -}; - -struct Reference { - int ref; /* The index the object was registered with */ -}; - -struct RealObject { - int type; /* The type of the object */ - one_of { - Boolean b; /* If type == LUA_TBOOLEAN */ - LightUserData l; /* If type == LUA_TLIGHTUSERDATA */ - Number n; /* If type == LUA_TNUMBER */ - String s; /* If type == LUA_TSTRING */ - Table t; /* If type == LUA_TTABLE */ - Function f; /* If type == LUA_TFUNCTION */ - Userdata u; /* If type == LUA_TUSERDATA */ - Thread th; /* If type == LUA_TTHREAD */ - Proto p; /* If type == LUA_TPROTO (from lobject.h) */ - Upval uv; /* If type == LUA_TUPVAL (from lobject.h) */ - }; /* The actual object */ -}; - -struct Boolean { - int32 bvalue; /* 0 for false, 1 for true */ -}; - -struct LightUserData { - void* luvalue; /* The actual, literal pointer */ -}; - -struct Number { - lua_Number nvalue; /* The actual number */ -}; - -struct String { - int length; /* The length of the string */ - char str[length]; /* The actual string (not null terminated) */ -}; - -struct Table { - int isspecial; /* 1 if SP is used; 0 otherwise */ - one_of { - Closure c; /* if isspecial == 1; closure to refill the table */ - LiteralTable t; /* if isspecial == 0; literal table info */ - }; -}; - -struct LiteralTable { - Object metatable; /* nil for default metatable */ - Pair p[]; /* key/value pairs */ - Object nil = nil; /* Nil reference to terminate */ -}; - -struct Pair { - Object key; - Object value; -}; - -struct Function { /* Actually a closure */ - lu_byte nups; /* Number of upvalues the function uses */ - Object proto; /* The proto this function uses */ - Object upvals[nups]; /* All upvalues */ - Object fenv; /* The FEnv (nil for the global table) -}; - -struct Upval { - Object obj; /* The object this upval refers to */ -} - -struct Userdata { - int isSpecial; /* 1 for special persistence, 0 for literal - one_of { - LiteralUserdata lu; /* if is_special is 0 */ - SpecialUserdata su; /* if is_special is 1 */ - }; -}; - -struct LiteralUserdata { - Object metatable; /* The metatable (nil for default) */ - int length; /* Size of the data */ - char data[length]; /* The actual data */ -}; - -struct SpecialUserdata { - int length; /* The size of the data */ - Object func; /* The closure used to fill the userdata */ -}; - -struct Thread { - int stacksize; /* The size of the stack filled with objects, - * including the "nil" that is hidden below - * the bottom of the stack visible to C */ - Object stack[stacksize];/* Indices of all stack values, bottom up */ - int callinfosize; /* Number of elements in the CallInfo stack */ - CallInfo callinfostack[callinfosize]; /* The CallInfo stack */ - int base; /* base = L->base - L->stack; */ - int top; /* top = L->top - L->stack; */ - OpenUpval openupvals[]; /* Upvalues to open */ - Object nil = nil; /* To terminate the open upvalues list */ -}; - -struct OpenUpval { - Object upval; /* The upvalue */ - int stackpos; /* The stack position to "reopen" it to */ - -}; - -struct CallInfo { - int base; /* base = ci->base - L->stack; */ - int top; /* top = ci->top - L->stack; */ - int pc; /* pc = ci->pc - proto->code; */ - int state; /* flags used by the CallInfo */ -}; - -struct Proto { - int sizek; /* Number of constants referenced */ - Object k[sizek]; /* Constants referenced */ - int sizep; /* Number of inner Protos referenced */ - Object p[sizep]; /* Inner Protos referenced */ - int sizecode; /* Number of instructions in code */ - Instruction code[sizecode]; /* The proto's code */ - ProtoDebug debuginfo; /* Debug information for the proto */ - lu_byte nups; /* Number of upvalues used */ - lu_byte numparams; /* Number of parameters taken */ - lu_byte is_vararg; /* 1 if function accepts varargs, 0 otherwise */ - lu_byte maxstacksize; /* Size of stack reserved for the function */ -}; - -struct ProtoDebug { - int sizeupvals; /* Number of upvalue names */ - Object upvals; /* Upvalue names */ - int sizelocvars; /* Number of local variable names */ - LocVar[sizelocvars]; /* Local variable names */ - Object source; /* The source code */ - int sizelineinfo; /* Number of opcode-line mappings */ - int lineinfo[sizelineinfo]; /* opcode-line mappings */ - int linedefined; /* Start of line range */ - int lastlinedefined; /* End of line range */ -}; - -struct LocVar { - Object name; /* Name of the local variable */ - int startpc; /* Point where variable is active */ - int endpc; /* Point where variable is dead */ -}; diff --git a/engines/sword25/util/pluto/README b/engines/sword25/util/pluto/README deleted file mode 100644 index 838fce498b..0000000000 --- a/engines/sword25/util/pluto/README +++ /dev/null @@ -1,133 +0,0 @@ -$Id$ - -PLUTO - Heavy duty persistence for Lua - -Pluto is a library which allows users to write arbitrarily large portions -of the "Lua universe" into a flat file, and later read them back into the -same or a different Lua universe. Object references are appropriately -handled, such that the file contains everything needed to recreate the -objects in question. - -Pluto has the following major features: -* Can persist any Lua function -* Can persist threads -* Works with any Lua chunkreader/chunkwriter -* Support for "invariant" permanent objects, of all datatypes -* Can invoke metafunctions for custom persistence of tables and userdata - -Pluto 2.2 requires Lua 5.1.3. If you need to use Pluto with Lua -5.0, please use version 1.2 of Pluto. - -Starting with version 2.2, Pluto no longer depends on the Lua sources. -Instead, it subsumes the required headers into its own codebase. -As a result, it may not work properly with Lua version 5.1.4 or later. - -Pluto may have bugs. Users are advised to define lua_assert in -luaconf.h to something useful when compiling in debug mode, to catch -assertions by Pluto and Lua. - -The Pluto library consists of two public functions. - -int pluto_persist(lua_State *L, lua_Chunkwriter writer, void *ud) - -This function recursively persists the Lua object in stack position 2 -and all other objects which are directly or indirectly referenced by -it, except those referenced in the permanent object table. The data -is written using the chunk-writer given, and that writer is passed -the arbitrary pointer value ud. - -The Lua stack must contain exactly and only these two items, in order: - -1. A table of permanent objects, that should not be persisted. For each -permanent object, the object itself should be the key, and a unique -object of any type should be the value. Likely candidates for this table -include Lua functions (including those in the Lua libraries) that are -loaded at load-time. It must include all non-persistable objects that -are referenced by the object to be persisted. The table is not modified -by the function. Objects in this table are considered "opaque" and are -not examined or descended into. Objects should not appear in the table -multiple times; the result of doing this is undefined (though probably -harmless). NOTE: If you are planning to persist threads, keep in mind -that all yielded threads have coroutine.yield on the tops of their -stacks. Since it's a C function, it should be put here. For complex -permanents, it may be a good idea to use the __index meta-function of -the permanents table to "search" for permanents. - -2. The single object to be persisted. In many cases, this will be the -global table. For more flexibility, however, it may be something like a -table built for the occasion, with various values to keep track of. The -object may not be nil. - - -int pluto_unpersist(lua_State *L, lua_Chunkreader reader, void *ud) - -This function loads in a Lua object and places it on top of the stack. All -objects directly or indirectly referenced by it are also loaded. - -The Lua stack must contain, as its top value, a table of permanent -objects. This table should be like the permanent object table used when -persisting, but with the key and value of each pair reversed. These -objects are used as substitutes for those referenced in their positions -when persisting, and under most circumstances should be identical objects -to those referenced in the permanents table used for persisting. It's -okay for multiple keys to refer to the same object. - - -RUNNING PLUTO FROM LUA: -It is also possible to invoke pluto from a Lua script. The C function -pluto_open() will register pluto.persist and pluto.unpersist, lua functions -which operate on strings. The first takes a permanents table and a root -object, and returns a string; the second takes a permanents table and a -string, and returns the root object. - -An error will be raised if pluto.persist is called from a thread which is -itself referenced by the root object. - -SPECIAL PERSISTENCE: -Tables and userdata have special persistence semantics. These semantics are -keyed to the value of the object's metatable's __persist member, if any. This -member may be any of the following four values: -1. Boolean "true": The table or userdata is persisted literally; tables are -persisted member-by-member, and userdata are written out as literal data. -2. Boolean "false": An error is returned, indicating that the object cannot -be persisted. -3. A function: This function should take one argument, the object in question, -and return one result, a closure. This "fixup closure", in turn, will be -persisted, and during unpersistence will be called. The closure will be -responsible for recreating the object with the appropriate data, based on -its upvalues. -4. Nil, or no metatable. In the case of tables, the table is literally -persisted. In the case of userdata, an error is returned. - -Here's an example of special persistence for a simple 3d vector object: - -vec = { x = 2, y = 1, z = 4 } -setmetatable(vec, { __persist = function(oldtbl) - local x = oldtbl.x - local y = oldtbl.y - local z = oldtbl.z - local mt = getmetatable(oldtbl) - return function() - newtbl = {} - newtbl.x = x - newtbl.y = y - newtbl.z = z - setmetatable(newtbl, mt) - return newtbl - end -end }) - -Note how x, y, z, and the mt are explicitly pulled out of the table. It is -important that the fixup closure returned not reference the original table -directly, as that table would again be persisted as an upvalue, leading to an -infinite loop. Also note that the object's metatable is NOT automatically -persisted; it is necessary for the fixup closure to reset it, if it wants. - -LIMITATIONS/TODO: -* Light userdata are persisted literally, as their pointer values. This -may or may not be what you want. -* Closures of C functions may not be persisted. Once it becomes possible -to specify a C function "proto" as a permanent object, this restriction -will be relaxed. - -BUGS: None known. Emphasis on the 'known'. diff --git a/engines/sword25/util/pluto/THANKS b/engines/sword25/util/pluto/THANKS deleted file mode 100644 index 443713fa61..0000000000 --- a/engines/sword25/util/pluto/THANKS +++ /dev/null @@ -1,9 +0,0 @@ -Pluto is surprisingly robust and useful. This would not be the case without -the hard work and helpfulness of the following people, mentioned in no -particular order: - -Ivko Stanilov -Goran Adrinek -Eric Jacobs -Anolan Milanes -Malte Thiesen diff --git a/engines/sword25/util/pluto/pdep.cpp b/engines/sword25/util/pluto/pdep.cpp deleted file mode 100644 index a32c43b42d..0000000000 --- a/engines/sword25/util/pluto/pdep.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/* This file is derived from the Lua source code. Please see lua.h for -the copyright statement. -*/ - -#include "pdep/pdep.h" - -#define api_incr_top(L) {api_check(L, L->top < L->ci->top); L->top++;} - -void pdep_pushobject (lua_State *L, const TValue *o) { - setobj2s(L, L->top, o); - api_incr_top(L); -} - -void *pdep_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { - global_State *g = G(L); - lua_assert((osize == 0) == (block == NULL)); - block = (*g->frealloc)(g->ud, block, osize, nsize); - lua_assert((nsize == 0) == (block == NULL)); - g->totalbytes = (g->totalbytes - osize) + nsize; - return block; -} - -void pdep_link (lua_State *L, GCObject *o, lu_byte tt) { - global_State *g = G(L); - o->gch.next = g->rootgc; - g->rootgc = o; - o->gch.marked = luaC_white(g); - o->gch.tt = tt; -} - -Proto *pdep_newproto (lua_State *L) { - Proto *f = pdep_new(L, Proto); - pdep_link(L, obj2gco(f), LUA_TPROTO); - f->k = NULL; - f->sizek = 0; - f->p = NULL; - f->sizep = 0; - f->code = NULL; - f->sizecode = 0; - f->sizelineinfo = 0; - f->sizeupvalues = 0; - f->nups = 0; - f->upvalues = NULL; - f->numparams = 0; - f->is_vararg = 0; - f->maxstacksize = 0; - f->lineinfo = NULL; - f->sizelocvars = 0; - f->locvars = NULL; - f->linedefined = 0; - f->lastlinedefined = 0; - f->source = NULL; - return f; -} - -Closure *pdep_newLclosure (lua_State *L, int nelems, Table *e) { - Closure *c = cast(Closure *, pdep_malloc(L, sizeLclosure(nelems))); - pdep_link(L, obj2gco(c), LUA_TFUNCTION); - c->l.isC = 0; - c->l.env = e; - c->l.nupvalues = cast_byte(nelems); - while (nelems--) c->l.upvals[nelems] = NULL; - return c; -} - -static void correctstack (lua_State *L, TValue *oldstack) { - CallInfo *ci; - GCObject *up; - L->top = (L->top - oldstack) + L->stack; - for (up = L->openupval; up != NULL; up = up->gch.next) - gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack; - for (ci = L->base_ci; ci <= L->ci; ci++) { - ci->top = (ci->top - oldstack) + L->stack; - ci->base = (ci->base - oldstack) + L->stack; - ci->func = (ci->func - oldstack) + L->stack; - } - L->base = (L->base - oldstack) + L->stack; -} - - -void pdep_reallocstack (lua_State *L, int newsize) { - TValue *oldstack = L->stack; - int realsize = newsize + 1 + EXTRA_STACK; - lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); - pdep_reallocvector(L, L->stack, L->stacksize, realsize, TValue); - L->stacksize = realsize; - L->stack_last = L->stack+newsize; - correctstack(L, oldstack); -} - -void pdep_growstack (lua_State *L, int n) { - if (n <= L->stacksize) /* double size is enough? */ - pdep_reallocstack(L, 2*L->stacksize); - else - pdep_reallocstack(L, L->stacksize + n); -} - -void pdep_reallocCI (lua_State *L, int newsize) { - CallInfo *oldci = L->base_ci; - pdep_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo); - L->size_ci = newsize; - L->ci = (L->ci - oldci) + L->base_ci; - L->end_ci = L->base_ci + L->size_ci - 1; -} - -TString *pdep_newlstr (lua_State *L, const char *str, size_t l) { - TString *res; - lua_pushlstring(L, str, l); - res = rawtsvalue(L->top-1); - lua_pop(L, 1); - return res; -} diff --git a/engines/sword25/util/pluto/pdep/README b/engines/sword25/util/pluto/pdep/README deleted file mode 100644 index 3592754da0..0000000000 --- a/engines/sword25/util/pluto/pdep/README +++ /dev/null @@ -1,5 +0,0 @@ -These files are directly copied from the Lua distribution, with the -exception of lzio.h, which is s/lua{ZM}/pdep/g and has an include removed. - -As such, unlike the rest of Pluto, they are released under the -same terms as Lua. See "lua.h" for the copyright notice. diff --git a/engines/sword25/util/pluto/pdep/lzio.h b/engines/sword25/util/pluto/pdep/lzio.h deleted file mode 100644 index 2e37f8d202..0000000000 --- a/engines/sword25/util/pluto/pdep/lzio.h +++ /dev/null @@ -1,65 +0,0 @@ -/* -** $Id$ -** Buffered streams -** See Copyright Notice in lua.h -*/ - - -#ifndef lzio_h -#define lzio_h - -#include "sword25/util/lua/lua.h" - - -#define EOZ (-1) /* end of stream */ - -typedef struct Zio ZIO; - -#define char2int(c) cast(int, cast(unsigned char, (c))) - -#define zgetc(z) (((z)->n--)>0 ? char2int(*(z)->p++) : pdep_fill(z)) - -typedef struct Mbuffer { - char *buffer; - size_t n; - size_t buffsize; -} Mbuffer; - -#define pdep_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0) - -#define pdep_buffer(buff) ((buff)->buffer) -#define pdep_sizebuffer(buff) ((buff)->buffsize) -#define pdep_bufflen(buff) ((buff)->n) - -#define pdep_resetbuffer(buff) ((buff)->n = 0) - - -#define pdep_resizebuffer(L, buff, size) \ - (pdep_reallocvector(L, (buff)->buffer, (buff)->buffsize, size, char), \ - (buff)->buffsize = size) - -#define pdep_freebuffer(L, buff) pdep_resizebuffer(L, buff, 0) - - -LUAI_FUNC char *pdep_openspace (lua_State *L, Mbuffer *buff, size_t n); -LUAI_FUNC void pdep_init (lua_State *L, ZIO *z, lua_Reader reader, - void *data); -LUAI_FUNC size_t pdep_read (ZIO* z, void* b, size_t n); /* read next n bytes */ -LUAI_FUNC int pdep_lookahead (ZIO *z); - - - -/* --------- Private Part ------------------ */ - -struct Zio { - size_t n; /* bytes still unread */ - const char *p; /* current position in buffer */ - lua_Reader reader; - void* data; /* additional data */ - lua_State *L; /* Lua state (for reader) */ -}; - - -LUAI_FUNC int pdep_fill (ZIO *z); - -#endif diff --git a/engines/sword25/util/pluto/pdep/pdep.h b/engines/sword25/util/pluto/pdep/pdep.h deleted file mode 100644 index 664fc812b5..0000000000 --- a/engines/sword25/util/pluto/pdep/pdep.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef PDEP_H -#define PDEP_H - -#include "sword25/util/lua/lua.h" -#include "sword25/util/pluto/pdep/lzio.h" -#include "sword25/util/lua/ldo.h" -#include "sword25/util/lua/lfunc.h" -#include "sword25/util/lua/lgc.h" -#include "sword25/util/lua/llimits.h" -#include "sword25/util/lua/lobject.h" -#include "sword25/util/lua/lopcodes.h" -#include "sword25/util/lua/lstate.h" -#include "sword25/util/lua/lstring.h" -#include "sword25/util/lua/lauxlib.h" - - -#define pdep_reallocv(L,b,on,n,e) \ - pdep_realloc_(L, (b), (on)*(e), (n)*(e)) -#define pdep_reallocvector(L, v,oldn,n,t) \ - ((v)=cast(t *, pdep_reallocv(L, v, oldn, n, sizeof(t)))) -#define pdep_freearray(L, b, n, t) pdep_reallocv(L, (b), n, 0, sizeof(t)) -#define pdep_newvector(L,n,t) \ - cast(t *, pdep_reallocv(L, NULL, 0, n, sizeof(t))) -#define pdep_new(L,t) cast(t *, pdep_malloc(L, sizeof(t))) -#define pdep_malloc(L,t) pdep_realloc_(L, NULL, 0, (t)) -#define pdep_checkstack(L,n) \ - if ((char *)L->stack_last - (char *)L->top <= (n)*(int)sizeof(TValue)) \ - pdep_growstack(L, n); \ - else pdep_reallocstack(L, L->stacksize - EXTRA_STACK - 1); - - -void pdep_pushobject (lua_State *L, const TValue *o); -void *pdep_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize); -void pdep_link (lua_State *L, GCObject *o, lu_byte tt); -Proto *pdep_newproto (lua_State *L); -Closure *pdep_newLclosure (lua_State *L, int nelems, Table *e); -void pdep_reallocstack (lua_State *L, int newsize); -void pdep_growstack (lua_State *L, int n); -void pdep_reallocCI (lua_State *L, int newsize); -TString *pdep_newlstr (lua_State *L, const char *str, size_t l); - -#endif diff --git a/engines/sword25/util/pluto/pluto.cpp b/engines/sword25/util/pluto/pluto.cpp deleted file mode 100644 index cbe16b0d5b..0000000000 --- a/engines/sword25/util/pluto/pluto.cpp +++ /dev/null @@ -1,2083 +0,0 @@ -/* $Id$ */ - -/* Tamed Pluto - Heavy-duty persistence for Lua - * Copyright (C) 2004 by Ben Sunshine-Hill, and released into the public - * domain. People making use of this software as part of an application - * are politely requested to email the author at sneftel@gmail.com - * with a brief description of the application, primarily to satisfy his - * curiosity. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Instrumented by Stefan Reich (info@luaos.net) - * for Mobile Lua (http://luaos.net/pages/mobile-lua.php) - */ - -#include "sword25/util/lua/lua.h" -#include "pluto.h" - -#undef TOTEXT - -#define USE_PDEP - -#ifdef USE_PDEP -#include "pdep/pdep.h" -#define LIF(prefix, name) pdep ## _ ## name -#else -#include "lapi.h" -#include "ldo.h" -#include "lfunc.h" -#include "lgc.h" -#include "llimits.h" -#include "lmem.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lstate.h" -#include "lstring.h" -#include "lauxlib.h" -#define LIF(prefix, name) lua ## prefix ## _ ## name -#endif - -#include - - -/* Define this if you want size_t values to be written in 64-bit - (even on 32-bit systems). Should eliminate at least one source of - 32/64 bit incompatibility. */ -#define SIZES64 - - -/* #define PLUTO_DEBUG */ - - -#ifdef SIZES64 -#define VERSION "Tamed Pluto 1.0 with SIZES64 flag" -#else -#define VERSION "Tamed Pluto 1.0" -#endif - - -#ifdef PLUTO_DEBUG -#include -#endif - -#define PLUTO_TPERMANENT 101 - -#define verify(x) { int v = (int)((x)); v=v; lua_assert(v); } - -#define NUMTYPES 9 -static const char* typenames[] = { - "nil", - "boolean", - "lightuserdata", - "number", - "string", - "table", - "function", - "userdata", - "thread" -}; - -static int humanReadable = 0; -#define hrBufSize 200 -static char hrBuf[hrBufSize]; - -typedef struct PersistInfo_t { - lua_State *L; - int counter; - lua_Chunkwriter writer; - void *ud; -#ifdef PLUTO_DEBUG - int level; -#endif -} PersistInfo; - -#ifdef PLUTO_DEBUG -void printindent(int indent) -{ - int il; - for(il=0; ilwriter(pi->L, hrBuf, strlen(hrBuf), ud); - for (i = 0; i < size; i++) { - char b = ((char *)p)[i]; - snprintf(hrBuf, hrBufSize, "%X%X", (b >> 4) & 0xF, b & 0xF); - pi->writer(pi->L, hrBuf, strlen(hrBuf), ud); - } - snprintf(hrBuf, hrBufSize, "\n"); - pi->writer(pi->L, hrBuf, strlen(hrBuf), ud); - } else { - pi->writer(pi->L, p, size, ud); - } -#ifdef TOTEXT - int i; - printf(" pi_write %d ", (int) size); - for (i = 0; i < size; i++) { - char b = ((char *)p)[i]; - printf("%X%X", (b >> 4) & 0xF, b & 0xF); - } - printf("\n"); -#endif -} - -static void hrOut(PersistInfo *pi) { - pi->writer(pi->L, hrBuf, strlen(hrBuf), pi->ud); -} - -static void write_size(PersistInfo *pi, size_t *val) -{ -#ifdef SIZES64 - int64 longval; /* yeah, you really need long long to get 8 bytes on win32... duh. */ - longval = *val; - pi_write(pi, &longval, 8, pi->ud); - if (humanReadable) { - snprintf(hrBuf, hrBufSize, "write_size64 %ld\n", longval); - hrOut(pi); - } -#ifdef TOTEXT - printf("write_size64 %ld\n", longval); -#endif -#else - pi_write(pi, val, sizeof(size_t), pi->ud); - if (humanReadable) { - snprintf(hrBuf, hrBufSize, "write_size %ld\n", *((size_t *)val)); - hrOut(pi); - } -#ifdef TOTEXT - printf("write_size %ld\n", *val); -#endif -#endif -} - -static void read_size(ZIO *zio, size_t *val) -{ -#ifdef SIZES64 - int64 longval; - verify(LIF(Z,read)(zio, &longval, 8) == 0); - *val = longval; -#else - verify(LIF(Z,read)(zio, val, sizeof(size_t)) == 0); -#endif -} - - -/* Mutual recursion requires prototype */ -static void persist(PersistInfo *pi); - -/* A simple reimplementation of the unfortunately static function luaA_index. - * Does not support the global table, registry, or upvalues. */ -static StkId getobject(lua_State *L, int stackpos) -{ - if(stackpos > 0) { - lua_assert(L->base+stackpos-1 < L->top); - return L->base+stackpos-1; - } else { - lua_assert(L->top-stackpos >= L->base); - return L->top+stackpos; - } -} - -/* Choose whether to do a regular or special persistence based on an object's - * metatable. "default" is whether the object, if it doesn't have a __persist - * entry, is literally persistable or not. - * Pushes the unpersist closure and returns true if special persistence is - * used. */ -static int persistspecialobject(PersistInfo *pi, int defaction) -{ - /* perms reftbl ... obj */ - lua_checkstack(pi->L, 4); - /* Check whether we should persist literally, or via the __persist - * metafunction */ - if(!lua_getmetatable(pi->L, -1)) { - if(defaction) { - { - int zero = 0; - pi_write(pi, &zero, sizeof(int), pi->ud); - if (humanReadable) { - snprintf(hrBuf, hrBufSize, "persistspecialobject_write_zero\n"); - hrOut(pi); - } -#ifdef TOTEXT - printf("persistspecialobject_write_zero\n"); -#endif - } - return 0; - } else { - lua_pushstring(pi->L, "Type not literally persistable by default"); - lua_error(pi->L); - } - } - /* perms reftbl sptbl ... obj mt */ - lua_pushstring(pi->L, "__persist"); - /* perms reftbl sptbl ... obj mt "__persist" */ - lua_rawget(pi->L, -2); - /* perms reftbl sptbl ... obj mt __persist? */ - if(lua_isnil(pi->L, -1)) { - /* perms reftbl sptbl ... obj mt nil */ - lua_pop(pi->L, 2); - /* perms reftbl sptbl ... obj */ - if(defaction) { - { - int zero = 0; - pi_write(pi, &zero, sizeof(int), pi->ud); - if (humanReadable) { - snprintf(hrBuf, hrBufSize, "persistspecialobject_write_zero2\n"); - hrOut(pi); - } -#ifdef TOTEXT - printf("persistspecialobject_write_zero2\n"); -#endif - } - return 0; - } else { - lua_pushstring(pi->L, "Type not literally persistable by default"); - lua_error(pi->L); - return 0; /* not reached */ - } - } else if(lua_isboolean(pi->L, -1)) { - /* perms reftbl sptbl ... obj mt bool */ - if(lua_toboolean(pi->L, -1)) { - /* perms reftbl sptbl ... obj mt true */ - lua_pop(pi->L, 2); - /* perms reftbl sptbl ... obj */ - { - int zero = 0; - pi_write(pi, &zero, sizeof(int), pi->ud); - if (humanReadable) { - snprintf(hrBuf, hrBufSize, "persistspecialobject_write_zero3\n"); - hrOut(pi); - } -#ifdef TOTEXT - printf("persistspecialobject_write_zero3\n"); -#endif - } - return 0; - } else { - lua_pushstring(pi->L, "Metatable forbade persistence"); - lua_error(pi->L); - return 0; /* not reached */ - } - } else if(!lua_isfunction(pi->L, -1)) { - lua_pushstring(pi->L, "__persist not nil, boolean, or function"); - lua_error(pi->L); - } - /* perms reftbl ... obj mt __persist */ - lua_pushvalue(pi->L, -3); - /* perms reftbl ... obj mt __persist obj */ -#ifdef PLUTO_PASS_USERDATA_TO_PERSIST - lua_pushlightuserdata(pi->L, (void *)pi->writer); - lua_pushlightuserdata(pi->L, pi->ud); - /* perms reftbl ... obj mt __persist obj ud */ - lua_call(pi->L, 3, 1); - /* perms reftbl ... obj mt func? */ -#else - lua_call(pi->L, 1, 1); - /* perms reftbl ... obj mt func? */ -#endif - /* perms reftbl ... obj mt func? */ - if(!lua_isfunction(pi->L, -1)) { - lua_pushstring(pi->L, "__persist function did not return a function"); - lua_error(pi->L); - } - /* perms reftbl ... obj mt func */ - { - int one = 1; - pi_write(pi, &one, sizeof(int), pi->ud); - if (humanReadable) { - snprintf(hrBuf, hrBufSize, "persistspecialobject_write_one\n"); - hrOut(pi); - } -#ifdef TOTEXT - printf("persistspecialobject_write_one\n"); -#endif - } - persist(pi); - /* perms reftbl ... obj mt func */ - lua_pop(pi->L, 2); - /* perms reftbl ... obj */ - return 1; -} - -static void persisttable(PersistInfo *pi) -{ - if (humanReadable) { - snprintf(hrBuf, hrBufSize, "persisttable\n"); - hrOut(pi); - } -#ifdef TOTEXT - printf("persisttable\n"); -#endif - - /* perms reftbl ... tbl */ - lua_checkstack(pi->L, 3); - if(persistspecialobject(pi, 1)) { - /* perms reftbl ... tbl */ - return; - } - /* perms reftbl ... tbl */ - /* First, persist the metatable (if any) */ - if(!lua_getmetatable(pi->L, -1)) { - lua_pushnil(pi->L); - } - /* perms reftbl ... tbl mt/nil */ - persist(pi); - lua_pop(pi->L, 1); - /* perms reftbl ... tbl */ - - /* Now, persist all k/v pairs */ - lua_pushnil(pi->L); - /* perms reftbl ... tbl nil */ - while(lua_next(pi->L, -2)) { - /* perms reftbl ... tbl k v */ - lua_pushvalue(pi->L, -2); - /* perms reftbl ... tbl k v k */ - persist(pi); - lua_pop(pi->L, 1); - /* perms reftbl ... tbl k v */ - persist(pi); - lua_pop(pi->L, 1); - /* perms reftbl ... tbl k */ - } - /* perms reftbl ... tbl */ - /* Terminate list */ - lua_pushnil(pi->L); - /* perms reftbl ... tbl nil */ - persist(pi); - lua_pop(pi->L, 1); - /* perms reftbl ... tbl */ -} - -static void persistuserdata(PersistInfo *pi) { - /* perms reftbl ... udata */ - lua_checkstack(pi->L, 2); - if(persistspecialobject(pi, 0)) { - /* perms reftbl ... udata */ - return; - } else { - /* Use literal persistence */ - size_t length = uvalue(getobject(pi->L, -1))->len; - write_size(pi, &length); - pi_write(pi, lua_touserdata(pi->L, -1), length, pi->ud); - if (humanReadable) { - snprintf(hrBuf, hrBufSize, "persistuserdata %ld\n", (long) length); - hrOut(pi); - } -#ifdef TOTEXT - printf("persistuserdata %ld\n", (long) length); -#endif - if(!lua_getmetatable(pi->L, -1)) { - /* perms reftbl ... udata */ - lua_pushnil(pi->L); - /* perms reftbl ... udata mt/nil */ - } - persist(pi); - lua_pop(pi->L, 1); - /* perms reftbl ... udata */ - } -} - - -static Proto *toproto(lua_State *L, int stackpos) -{ - return gco2p(getobject(L, stackpos)->value.gc); -} - -static UpVal *toupval(lua_State *L, int stackpos) -{ - lua_assert(ttype(getobject(L, stackpos)) == LUA_TUPVAL); - return gco2uv(getobject(L, stackpos)->value.gc); -} - -static void pushproto(lua_State *L, Proto *proto) -{ - TValue o; - setptvalue(L, &o, proto); - LIF(A,pushobject)(L, &o); -} - -#define setuvvalue(L,obj,x) \ - { TValue *i_o=(obj); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TUPVAL; \ - checkliveness(G(L),i_o); } - -static void pushupval(lua_State *L, UpVal *upval) -{ - TValue o; - setuvvalue(L, &o, upval); - LIF(A,pushobject)(L, &o); -} - -static void pushclosure(lua_State *L, Closure *closure) -{ - TValue o; - setclvalue(L, &o, closure); - LIF(A,pushobject)(L, &o); -} - -static void pushstring(lua_State *L, TString *s) -{ - TValue o; - setsvalue(L, &o, s); - LIF(A,pushobject)(L, &o); -} - -static void persistfunction(PersistInfo *pi) -{ - /* perms reftbl ... func */ - Closure *cl = clvalue(getobject(pi->L, -1)); - lua_checkstack(pi->L, 2); - if(cl->c.isC) { - /* It's a C function. For now, we aren't going to allow - * persistence of C closures, even if the "C proto" is - * already in the permanents table. */ - lua_pushstring(pi->L, "Attempt to persist a C function"); - lua_error(pi->L); - } else { - /* It's a Lua closure. */ - { - /* We don't really _NEED_ the number of upvals, - * but it'll simplify things a bit */ - pi_write(pi, &cl->l.p->nups, sizeof(lu_byte), pi->ud); - if (humanReadable) { - snprintf(hrBuf, hrBufSize, "persistfunction_number_upvalues %d\n", (int) cl->l.p->nups); - hrOut(pi); - } -#ifdef TOTEXT - printf("persistfunction_number_upvalues %d\n", (int) cl->l.p->nups); -#endif - } - /* Persist prototype */ - { - pushproto(pi->L, cl->l.p); - /* perms reftbl ... func proto */ - persist(pi); - lua_pop(pi->L, 1); - /* perms reftbl ... func */ - } - /* Persist upvalue values (not the upvalue objects - * themselves) */ - { - int i; - for(i=0; il.p->nups; i++) { - /* perms reftbl ... func */ - pushupval(pi->L, cl->l.upvals[i]); - /* perms reftbl ... func upval */ - persist(pi); - lua_pop(pi->L, 1); - /* perms reftbl ... func */ - } - /* perms reftbl ... func */ - } - /* Persist function environment */ - { - lua_getfenv(pi->L, -1); - /* perms reftbl ... func fenv */ - if(lua_equal(pi->L, -1, LUA_GLOBALSINDEX)) { - /* Function has the default fenv */ - /* perms reftbl ... func _G */ - lua_pop(pi->L, 1); - /* perms reftbl ... func */ - lua_pushnil(pi->L); - /* perms reftbl ... func nil */ - } - /* perms reftbl ... func fenv/nil */ - persist(pi); - lua_pop(pi->L, 1); - /* perms reftbl ... func */ - } - } -} - - -/* Upvalues are tricky. Here's why. - * - * A particular upvalue may be either "open", in which case its member v - * points into a thread's stack, or "closed" in which case it points to the - * upvalue itself. An upvalue is closed under any of the following conditions: - * -- The function that initially declared the variable "local" returns - * -- The thread in which the closure was created is garbage collected - * - * To make things wackier, just because a thread is reachable by Lua doesn't - * mean it's in our root set. We need to be able to treat an open upvalue - * from an unreachable thread as a closed upvalue. - * - * The solution: - * (a) For the purposes of persisting, don't indicate whether an upvalue is - * closed or not. - * (b) When unpersisting, pretend that all upvalues are closed. - * (c) When persisting, persist all open upvalues referenced by a thread - * that is persisted, and tag each one with the corresponding stack position - * (d) When unpersisting, "reopen" each of these upvalues as the thread is - * unpersisted - */ -static void persistupval(PersistInfo *pi) -{ - /* perms reftbl ... upval */ - UpVal *uv = toupval(pi->L, -1); - lua_checkstack(pi->L, 1); - - /* We can't permit the upval to linger around on the stack, as Lua - * will bail if its GC finds it. */ - - lua_pop(pi->L, 1); - /* perms reftbl ... */ - LIF(A,pushobject)(pi->L, uv->v); - /* perms reftbl ... obj */ - persist(pi); - /* perms reftbl ... obj */ -} - -static void persistproto(PersistInfo *pi) -{ - /* perms reftbl ... proto */ - Proto *p = toproto(pi->L, -1); - lua_checkstack(pi->L, 2); - - /* Persist constant refs */ - { - int i; - pi_write(pi, &p->sizek, sizeof(int), pi->ud); - if (humanReadable) { - snprintf(hrBuf, hrBufSize, "persistproto_sizek %d\n", p->sizek); - hrOut(pi); - } - #ifdef TOTEXT - printf("persistproto_sizek %d\n", p->sizek); - #endif - for(i=0; isizek; i++) { - LIF(A,pushobject)(pi->L, &p->k[i]); - /* perms reftbl ... proto const */ - persist(pi); - lua_pop(pi->L, 1); - /* perms reftbl ... proto */ - } - } - /* perms reftbl ... proto */ - - /* serialize inner Proto refs */ - { - int i; - pi_write(pi, &p->sizep, sizeof(int), pi->ud); - if (humanReadable) { - snprintf(hrBuf, hrBufSize, "persistproto_sizep %d\n", p->sizep); - hrOut(pi); - } -#ifdef TOTEXT - printf("persistproto_sizep %d\n", p->sizep); -#endif - for(i=0; isizep; i++) - { - pushproto(pi->L, p->p[i]); - /* perms reftbl ... proto subproto */ - persist(pi); - lua_pop(pi->L, 1); - /* perms reftbl ... proto */ - } - } - /* perms reftbl ... proto */ - - /* Serialize code */ - { - int len; - pi_write(pi, &p->sizecode, sizeof(int), pi->ud); - if (humanReadable) { - snprintf(hrBuf, hrBufSize, "persistproto_sizecode %d\n", p->sizecode); - hrOut(pi); - } -#ifdef TOTEXT - printf("persistproto_sizecode %d\n", p->sizecode); -#endif - len = sizeof(Instruction) * p->sizecode; - pi_write(pi, p->code, len, pi->ud); - if (humanReadable) { - snprintf(hrBuf, hrBufSize, "persistproto_code %d\n", len); - hrOut(pi); - } -#ifdef TOTEXT - printf("persistproto_code %d\n", len); -#endif - } - - /* Serialize upvalue names */ - { - int i; - pi_write(pi, &p->sizeupvalues, sizeof(int), pi->ud); - if (humanReadable) { - snprintf(hrBuf, hrBufSize, "persistproto_upvalues %d\n", p->sizeupvalues); - hrOut(pi); - } -#ifdef TOTEXT - printf("persistproto_upvalues %d\n", p->sizeupvalues); -#endif - for(i=0; isizeupvalues; i++) - { - pushstring(pi->L, p->upvalues[i]); - persist(pi); - lua_pop(pi->L, 1); - } - } - /* Serialize local variable infos */ - { - int i; - pi_write(pi, &p->sizelocvars, sizeof(int), pi->ud); - if (humanReadable) { - snprintf(hrBuf, hrBufSize, "persistproto_sizelocvars %d\n", p->sizelocvars); - hrOut(pi); - } -#ifdef TOTEXT - printf("persistproto_sizelocvars %d\n", p->sizelocvars); -#endif - for(i=0; isizelocvars; i++) - { - pushstring(pi->L, p->locvars[i].varname); - persist(pi); - lua_pop(pi->L, 1); - - pi_write(pi, &p->locvars[i].startpc, sizeof(int), pi->ud); - if (humanReadable) { - snprintf(hrBuf, hrBufSize, "persistproto_startpc %d\n", p->locvars[i].startpc); - hrOut(pi); - } -#ifdef TOTEXT - printf("persistproto_startpc %d\n", p->locvars[i].startpc); -#endif - pi_write(pi, &p->locvars[i].endpc, sizeof(int), pi->ud); - if (humanReadable) { - snprintf(hrBuf, hrBufSize, "persistproto_endpc %d\n", p->locvars[i].endpc); - hrOut(pi); - } -#ifdef TOTEXT - printf("persistproto_endpc %d\n", p->locvars[i].endpc); -#endif - } - } - - /* Serialize source string */ - pushstring(pi->L, p->source); - persist(pi); - lua_pop(pi->L, 1); - - /* Serialize line numbers */ - { - pi_write(pi, &p->sizelineinfo, sizeof(int), pi->ud); - if (humanReadable) { - snprintf(hrBuf, hrBufSize, "persistproto_sizelineinfo %d\n", p->sizelineinfo); - hrOut(pi); - } -#ifdef TOTEXT - printf("persistproto_sizelineinfo %d\n", p->sizelineinfo); -#endif - if (p->sizelineinfo) - { - int len; - len = sizeof(int) * p->sizelineinfo; - pi_write(pi, p->lineinfo, len, pi->ud); - if (humanReadable) { - snprintf(hrBuf, hrBufSize, "persistproto_lineinfo %d\n", len); - hrOut(pi); - } -#ifdef TOTEXT - printf("persistproto_lineinfo %d\n", len); -#endif - } - } - - /* Serialize linedefined and lastlinedefined */ - pi_write(pi, &p->linedefined, sizeof(int), pi->ud); - if (humanReadable) { - snprintf(hrBuf, hrBufSize, "persistproto_linedefined %d\n", p->linedefined); - hrOut(pi); - } -#ifdef TOTEXT - printf("persistproto_linedefined %d\n", p->linedefined); -#endif - pi_write(pi, &p->lastlinedefined, sizeof(int), pi->ud); - if (humanReadable) { - snprintf(hrBuf, hrBufSize, "persistproto_lastlinedefined %d\n", p->lastlinedefined); - hrOut(pi); - } -#ifdef TOTEXT - printf("persistproto_lastlinedefined %d\n", p->lastlinedefined); -#endif - - /* Serialize misc values */ - { - pi_write(pi, &p->nups, sizeof(lu_byte), pi->ud); - if (humanReadable) { - snprintf(hrBuf, hrBufSize, "persistproto_nups %d\n", (int) p->nups); - hrOut(pi); - } -#ifdef TOTEXT - printf("persistproto_nups %d\n", (int) p->nups); -#endif - pi_write(pi, &p->numparams, sizeof(lu_byte), pi->ud); - if (humanReadable) { - snprintf(hrBuf, hrBufSize, "persistproto_numparams %d\n", (int) p->numparams); - hrOut(pi); - } -#ifdef TOTEXT - printf("persistproto_numparams %d\n", (int) p->numparams); -#endif - pi_write(pi, &p->is_vararg, sizeof(lu_byte), pi->ud); - if (humanReadable) { - snprintf(hrBuf, hrBufSize, "persistproto_is_vararg %d\n", (int) p->is_vararg); - hrOut(pi); - } -#ifdef TOTEXT - printf("persistproto_is_vararg %d\n", (int) p->is_vararg); -#endif - pi_write(pi, &p->maxstacksize, sizeof(lu_byte), pi->ud); - if (humanReadable) { - snprintf(hrBuf, hrBufSize, "persistproto_maxstacksize %d\n", (int) p->maxstacksize); - hrOut(pi); - } -#ifdef TOTEXT - printf("persistproto_maxstacksize %d\n", (int) p->maxstacksize); -#endif - } - /* We do not currently persist upvalue names, local variable names, - * variable lifetimes, line info, or source code. */ -} - -/* Copies a stack, but the stack is reversed in the process - */ -static size_t revappendstack(lua_State *from, lua_State *to) -{ - StkId o; - for(o=from->top-1; o>=from->stack; o--) { - setobj2s(to, to->top, o); - to->top++; - } - return from->top - from->stack; -} - -/* Persist all stack members - */ -static void persistthread(PersistInfo *pi) -{ - size_t posremaining; - lua_State *L2; - /* perms reftbl ... thr */ - L2 = lua_tothread(pi->L, -1); - lua_checkstack(pi->L, L2->top - L2->stack + 1); - if(pi->L == L2) { - lua_pushstring(pi->L, "Can't persist currently running thread"); - lua_error(pi->L); - return; /* not reached */ - } - - /* Persist the stack */ - posremaining = revappendstack(L2, pi->L); - /* perms reftbl ... thr (rev'ed contents of L2) */ - write_size(pi, &posremaining); - for(; posremaining > 0; posremaining--) { - persist(pi); - lua_pop(pi->L, 1); - } - /* perms reftbl ... thr */ - /* Now, persist the CallInfo stack. */ - { - size_t i, numframes = (L2->ci - L2->base_ci) + 1; - write_size(pi, &numframes); - for(i=0; ibase_ci + i; - size_t stackbase = ci->base - L2->stack; - size_t stackfunc = ci->func - L2->stack; - size_t stacktop = ci->top - L2->stack; - size_t savedpc = (ci != L2->base_ci) ? - ci->savedpc - ci_func(ci)->l.p->code : - 0; - write_size(pi, &stackbase); - write_size(pi, &stackfunc); - write_size(pi, &stacktop); - pi_write(pi, &ci->nresults, sizeof(int), pi->ud); - if (humanReadable) { - snprintf(hrBuf, hrBufSize, "persistthread %d\n", ci->nresults); - hrOut(pi); - } -#ifdef TOTEXT - printf("persistthread %d\n", ci->nresults); -#endif - write_size(pi, &savedpc); - } - } - - /* Serialize the state's other parameters, with the exception of upval stuff */ - { - size_t stackbase = L2->base - L2->stack; - size_t stacktop = L2->top - L2->stack; - lua_assert(L2->nCcalls <= 1); - pi_write(pi, &L2->status, sizeof(lu_byte), pi->ud); - if (humanReadable) { - snprintf(hrBuf, hrBufSize, "persistthread_status %d\n", (int) L2->status); - hrOut(pi); - } -#ifdef TOTEXT - printf("persistthread_status %d\n", (int) L2->status); -#endif - write_size(pi, &stackbase); - write_size(pi, &stacktop); - - // ptrdiff_t changes sizes based on 32/64 bit - // Hard cast to 64 bit size if SIZE64 is defined -#ifdef SIZES64 - uint64 ptrIndex = static_cast(L2->errfunc); - pi_write(pi, &ptrIndex, sizeof(uint64), pi->ud); -#else - pi_write(pi, &L2->errfunc, sizeof(ptrdiff_t), pi->ud); -#endif - //write_size(pi, (size_t *)&L2->errfunc); - } - - /* Finally, record upvalues which need to be reopened */ - /* See the comment above persistupval() for why we do this */ - { - GCObject *gco; - UpVal *uv; - /* perms reftbl ... thr */ - for(gco = L2->openupval; gco != NULL; gco = uv->next) { - size_t stackpos; - uv = gco2uv(gco); - - /* Make sure upvalue is really open */ - lua_assert(uv->v != &uv->u.value); - pushupval(pi->L, uv); - /* perms reftbl ... thr uv */ - persist(pi); - lua_pop(pi->L, 1); - /* perms reftbl ... thr */ - stackpos = uv->v - L2->stack; - write_size(pi, &stackpos); - } - /* perms reftbl ... thr */ - lua_pushnil(pi->L); - /* perms reftbl ... thr nil */ - persist(pi); - lua_pop(pi->L, 1); - /* perms reftbl ... thr */ - } - /* perms reftbl ... thr */ -} - -static void persistboolean(PersistInfo *pi) -{ - int b = lua_toboolean(pi->L, -1); - pi_write(pi, &b, sizeof(int), pi->ud); - if (humanReadable) { - snprintf(hrBuf, hrBufSize, "persistboolean %d\n", b); - hrOut(pi); - } -#ifdef TOTEXT - printf("persistboolean %d\n", b); -#endif -} - -static void persistlightuserdata(PersistInfo *pi) -{ - void *p = lua_touserdata(pi->L, -1); - pi_write(pi, &p, sizeof(void *), pi->ud); - if (humanReadable) { - snprintf(hrBuf, hrBufSize, "persistlightuserdata %p\n", p); - hrOut(pi); - } -#ifdef TOTEXT - printf("persistlightuserdata %d\n", (int) p); -#endif -} - -static void persistnumber(PersistInfo *pi) -{ - lua_Number n = lua_tonumber(pi->L, -1); - pi_write(pi, &n, sizeof(lua_Number), pi->ud); - if (humanReadable) { - snprintf(hrBuf, hrBufSize, "persistnumber %d (%d)\n", (int) n, (int) sizeof(lua_Number)); - hrOut(pi); - } -#ifdef TOTEXT - printf("persistnumber %d (%d)\n", (int) n, (int) sizeof(lua_Number)); -#endif -} - -static void persiststring(PersistInfo *pi) -{ - if (humanReadable) { - snprintf(hrBuf, hrBufSize, "persiststring\n"); - hrOut(pi); - } -#ifdef TOTEXT - printf("persiststring\n"); -#endif - size_t length = lua_strlen(pi->L, -1); - write_size(pi, &length); - const char* s = lua_tostring(pi->L, -1); - pi_write(pi, s, length, pi->ud); - if (humanReadable) { - snprintf(hrBuf, hrBufSize, "persiststring %d \"%s\"\n", (int)length, s); - hrOut(pi); - } -#ifdef TOTEXT - printf("persiststring %d \"%s\"\n", length, s); -#endif -} - -/* Top-level delegating persist function - */ -static void persist(PersistInfo *pi) -{ - /* perms reftbl ... obj */ - lua_checkstack(pi->L, 2); - /* If the object has already been written, write a reference to it */ - lua_pushvalue(pi->L, -1); - /* perms reftbl ... obj obj */ - lua_rawget(pi->L, 2); - /* perms reftbl ... obj ref? */ - if(!lua_isnil(pi->L, -1)) { - /* perms reftbl ... obj ref */ - int zero = 0; - pi_write(pi, &zero, sizeof(int), pi->ud); - if (humanReadable) { - snprintf(hrBuf, hrBufSize, "persist_seenobject\n"); - hrOut(pi); - } -#ifdef TOTEXT - printf("persist_seenobject\n"); -#endif - int *ref = (int *)lua_touserdata(pi->L, -1); - pi_write(pi, ref, sizeof(int), pi->ud); - if (humanReadable) { - snprintf(hrBuf, hrBufSize, "persist_touserdata_ref %d\n", ref); - hrOut(pi); - } -#ifdef TOTEXT - printf("persist_touserdata_ref %d\n", ref); -#endif - lua_pop(pi->L, 1); - /* perms reftbl ... obj ref */ -#ifdef PLUTO_DEBUG - printindent(pi->level); - printf("0 %d\n", ref); -#endif - return; - } - /* perms reftbl ... obj nil */ - lua_pop(pi->L, 1); - /* perms reftbl ... obj */ - /* If the object is nil, write the pseudoreference 0 */ - if(lua_isnil(pi->L, -1)) { - int zero = 0; - /* firsttime */ - pi_write(pi, &zero, sizeof(int), pi->ud); - /* ref */ - pi_write(pi, &zero, sizeof(int), pi->ud); - if (humanReadable) { - snprintf(hrBuf, hrBufSize, "persist_nil (last 2 lines)\n"); - hrOut(pi); - } -#ifdef TOTEXT - printf("persist_nil (last 2 lines)\n"); -#endif -#ifdef PLUTO_DEBUG - printindent(pi->level); - printf("0 0\n"); -#endif - return; - } - { - /* indicate that it's the first time */ - int one = 1; - pi_write(pi, &one, sizeof(int), pi->ud); - if (humanReadable) { - snprintf(hrBuf, hrBufSize, "persist_newobject\n"); - hrOut(pi); - } -#ifdef TOTEXT - printf("persist_newobject\n"); -#endif - } - lua_pushvalue(pi->L, -1); - /* perms reftbl ... obj obj */ - int *ref = (int *)lua_newuserdata(pi->L, sizeof(int)); - *ref = ++(pi->counter); - /* perms reftbl ... obj obj ref */ - lua_rawset(pi->L, 2); - /* perms reftbl ... obj */ - - pi_write(pi, &pi->counter, sizeof(int), pi->ud); - if (humanReadable) { - snprintf(hrBuf, hrBufSize, "persist_counter %d\n", pi->counter); - hrOut(pi); - } -#ifdef TOTEXT - printf("persist_counter %d\n", pi->counter); -#endif - - - /* At this point, we'll give the permanents table a chance to play. */ - { - lua_pushvalue(pi->L, -1); - /* perms reftbl ... obj obj */ - lua_gettable(pi->L, 1); - /* perms reftbl ... obj permkey? */ - if(!lua_isnil(pi->L, -1)) { - /* perms reftbl ... obj permkey */ - int type = PLUTO_TPERMANENT; -#ifdef PLUTO_DEBUG - printindent(pi->level); - printf("1 %d PERM\n", pi->counter); - pi->level++; -#endif - pi_write(pi, &type, sizeof(int), pi->ud); - if (humanReadable) { - snprintf(hrBuf, hrBufSize, "persist_permtype %d\n", type); - hrOut(pi); - } -#ifdef TOTEXT - printf("persist_permtype %d\n", type); -#endif - persist(pi); - lua_pop(pi->L, 1); - /* perms reftbl ... obj */ -#ifdef PLUTO_DEBUG - pi->level--; -#endif - return; - } else { - /* perms reftbl ... obj nil */ - lua_pop(pi->L, 1); - /* perms reftbl ... obj */ - } - /* perms reftbl ... obj */ - } - { - int type = lua_type(pi->L, -1); - pi_write(pi, &type, sizeof(int), pi->ud); - if (humanReadable) { - snprintf(hrBuf, hrBufSize, "persist %s\n", type >= 0 && type < NUMTYPES ? typenames[type] : "?"); - hrOut(pi); - } -#ifdef TOTEXT - printf("persist %s\n", type >= 0 && type < NUMTYPES ? typenames[type] : "?"); -#endif - -#ifdef PLUTO_DEBUG - printindent(pi->level); - printf("1 %d %d\n", pi->counter, type); - pi->level++; -#endif - } - - switch(lua_type(pi->L, -1)) { - case LUA_TBOOLEAN: - persistboolean(pi); - break; - case LUA_TLIGHTUSERDATA: - persistlightuserdata(pi); - break; - case LUA_TNUMBER: - persistnumber(pi); - break; - case LUA_TSTRING: - persiststring(pi); - break; - case LUA_TTABLE: - persisttable(pi); - break; - case LUA_TFUNCTION: - persistfunction(pi); - break; - case LUA_TTHREAD: - persistthread(pi); - break; - case LUA_TPROTO: - persistproto(pi); - break; - case LUA_TUPVAL: - persistupval(pi); - break; - case LUA_TUSERDATA: - persistuserdata(pi); - break; - default: - lua_assert(0); - } -#ifdef PLUTO_DEBUG - pi->level--; -#endif -} - -void pluto_persist(lua_State *L, lua_Chunkwriter writer, void *ud) -{ - PersistInfo pi; - - pi.counter = 0; - pi.L = L; - pi.writer = writer; - pi.ud = ud; -#ifdef PLUTO_DEBUG - pi.level = 0; -#endif - - lua_checkstack(L, 4); - /* perms? rootobj? ...? */ - lua_assert(lua_gettop(L) == 2); - /* perms rootobj */ - lua_assert(!lua_isnil(L, 2)); - /* perms rootobj */ - lua_newtable(L); - /* perms rootobj reftbl */ - - /* Now we're going to make the table weakly keyed. This prevents the - * GC from visiting it and trying to mark things it doesn't want to - * mark in tables, e.g. upvalues. All objects in the table are - * a priori reachable, so it doesn't matter that we do this. */ - lua_newtable(L); - /* perms rootobj reftbl mt */ - lua_pushstring(L, "__mode"); - /* perms rootobj reftbl mt "__mode" */ - lua_pushstring(L, "k"); - /* perms rootobj reftbl mt "__mode" "k" */ - lua_settable(L, 4); - /* perms rootobj reftbl mt */ - lua_setmetatable(L, 3); - /* perms rootobj reftbl */ - lua_insert(L, 2); - /* perms reftbl rootobj */ - persist(&pi); - /* perms reftbl rootobj */ - lua_remove(L, 2); - /* perms rootobj */ -} - -typedef struct WriterInfo_t { - char* buf; - size_t buflen; -} WriterInfo; - -static int bufwriter (lua_State *L, const void *p, size_t sz, void *ud) { - const char *cp = (const char *)p; - WriterInfo *wi = (WriterInfo *)ud; - - LIF(M,reallocvector)(L, wi->buf, wi->buflen, wi->buflen+sz, char); - while(sz) - { - /* how dearly I love ugly C pointer twiddling */ - wi->buf[wi->buflen++] = *cp++; - sz--; - } - return 0; -} - -int persist_l(lua_State *L) -{ - /* perms? rootobj? ...? */ - WriterInfo wi; - - wi.buf = NULL; - wi.buflen = 0; - - lua_settop(L, 2); - /* perms? rootobj? */ - luaL_checktype(L, 1, LUA_TTABLE); - /* perms rootobj? */ - luaL_checktype(L, 1, LUA_TTABLE); - /* perms rootobj */ - - pluto_persist(L, bufwriter, &wi); - - lua_settop(L, 0); - /* (empty) */ - lua_pushlstring(L, wi.buf, wi.buflen); - /* str */ - pdep_freearray(L, wi.buf, wi.buflen, char); - return 1; -} - -typedef struct UnpersistInfo_t { - lua_State *L; - ZIO zio; -#ifdef PLUTO_DEBUG - int level; -#endif -} UnpersistInfo; - -static void unpersist(UnpersistInfo *upi); - -/* The object is left on the stack. This is primarily used by unpersist, but - * may be used by GCed objects that may incur cycles in order to preregister - * the object. */ -static void registerobject(int ref, UnpersistInfo *upi) -{ - /* perms reftbl ... obj */ - lua_checkstack(upi->L, 2); - lua_pushlightuserdata(upi->L, (void *)ref); - /* perms reftbl ... obj ref */ - lua_pushvalue(upi->L, -2); - /* perms reftbl ... obj ref obj */ - lua_settable(upi->L, 2); - /* perms reftbl ... obj */ -} - -static void unpersistboolean(UnpersistInfo *upi) -{ - /* perms reftbl ... */ - int b; - lua_checkstack(upi->L, 1); - verify(LIF(Z,read)(&upi->zio, &b, sizeof(int)) == 0); - lua_pushboolean(upi->L, b); - /* perms reftbl ... bool */ -} - -static void unpersistlightuserdata(UnpersistInfo *upi) -{ - /* perms reftbl ... */ - void *p; - lua_checkstack(upi->L, 1); - verify(LIF(Z,read)(&upi->zio, &p, sizeof(void *)) == 0); - lua_pushlightuserdata(upi->L, p); - /* perms reftbl ... ludata */ -} - -static void unpersistnumber(UnpersistInfo *upi) -{ - /* perms reftbl ... */ - lua_Number n; - lua_checkstack(upi->L, 1); - verify(LIF(Z,read)(&upi->zio, &n, sizeof(lua_Number)) == 0); - lua_pushnumber(upi->L, n); - /* perms reftbl ... num */ -} - -static void unpersiststring(UnpersistInfo *upi) -{ - /* perms reftbl sptbl ref */ - /*int length;*/ - size_t length; - char* string; - lua_checkstack(upi->L, 1); - /*verify(LIF(Z,read)(&upi->zio, &length, sizeof(int)) == 0);*/ - /*verify(LIF(Z,read)(&upi->zio, &length, sizeof(size_t)) == 0);*/ - read_size(&upi->zio, &length); - string = pdep_newvector(upi->L, length, char); - verify(LIF(Z,read)(&upi->zio, string, length) == 0); - lua_pushlstring(upi->L, string, length); - /* perms reftbl sptbl ref str */ - pdep_freearray(upi->L, string, length, char); -} - -static void unpersistspecialtable(int ref, UnpersistInfo *upi) -{ - /* perms reftbl ... */ - lua_checkstack(upi->L, 1); - unpersist(upi); - /* perms reftbl ... spfunc? */ - lua_assert(lua_isfunction(upi->L, -1)); - /* perms reftbl ... spfunc */ - lua_call(upi->L, 0, 1); - /* perms reftbl ... tbl? */ - lua_assert(lua_istable(upi->L, -1)); - /* perms reftbl ... tbl */ -} - -static void unpersistliteraltable(int ref, UnpersistInfo *upi) -{ - /* perms reftbl ... */ - lua_checkstack(upi->L, 3); - /* Preregister table for handling of cycles */ - lua_newtable(upi->L); - /* perms reftbl ... tbl */ - registerobject(ref, upi); - /* perms reftbl ... tbl */ - /* Unpersist metatable */ - { - unpersist(upi); - /* perms reftbl ... tbl mt/nil? */ - if(lua_istable(upi->L, -1)) { - /* perms reftbl ... tbl mt */ - lua_setmetatable(upi->L, -2); - /* perms reftbl ... tbl */ - } else { - /* perms reftbl ... tbl nil? */ - lua_assert(lua_isnil(upi->L, -1)); - /* perms reftbl ... tbl nil */ - lua_pop(upi->L, 1); - /* perms reftbl ... tbl */ - } - /* perms reftbl ... tbl */ - } - - while(1) - { - /* perms reftbl ... tbl */ - unpersist(upi); - /* perms reftbl ... tbl key/nil */ - if(lua_isnil(upi->L, -1)) { - /* perms reftbl ... tbl nil */ - lua_pop(upi->L, 1); - /* perms reftbl ... tbl */ - break; - } - /* perms reftbl ... tbl key */ - unpersist(upi); - /* perms reftbl ... tbl key value? */ - lua_assert(!lua_isnil(upi->L, -1)); - /* perms reftbl ... tbl key value */ - lua_rawset(upi->L, -3); - /* perms reftbl ... tbl */ - } -} - -static void unpersisttable(int ref, UnpersistInfo *upi) -{ - /* perms reftbl ... */ - lua_checkstack(upi->L, 1); - { - int isspecial; - verify(LIF(Z,read)(&upi->zio, &isspecial, sizeof(int)) == 0); - if(isspecial) { - unpersistspecialtable(ref, upi); - /* perms reftbl ... tbl */ - } else { - unpersistliteraltable(ref, upi); - /* perms reftbl ... tbl */ - } - /* perms reftbl ... tbl */ - } -} - -static UpVal *makeupval(lua_State *L, int stackpos) -{ - UpVal *uv = pdep_new(L, UpVal); - pdep_link(L, (GCObject *)uv, LUA_TUPVAL); - uv->tt = LUA_TUPVAL; - uv->v = &uv->u.value; - uv->u.l.prev = NULL; - uv->u.l.next = NULL; - setobj(L, uv->v, getobject(L, stackpos)); - return uv; -} - -static Proto *makefakeproto(lua_State *L, lu_byte nups) -{ - Proto *p = pdep_newproto(L); - p->sizelineinfo = 1; - p->lineinfo = pdep_newvector(L, 1, int); - p->lineinfo[0] = 1; - p->sizecode = 1; - p->code = pdep_newvector(L, 1, Instruction); - p->code[0] = CREATE_ABC(OP_RETURN, 0, 1, 0); - p->source = pdep_newlstr(L, "", 0); - p->maxstacksize = 2; - p->nups = nups; - p->sizek = 0; - p->sizep = 0; - - return p; -} - -/* The GC is not fond of finding upvalues in tables. We get around this - * during persistence using a weakly keyed table, so that the GC doesn't - * bother to mark them. This won't work in unpersisting, however, since - * if we make the values weak they'll be collected (since nothing else - * references them). Our solution, during unpersisting, is to represent - * upvalues as dummy functions, each with one upvalue. */ -static void boxupval_start(lua_State *L) -{ - LClosure *lcl; - lcl = (LClosure *)pdep_newLclosure(L, 1, hvalue(&L->l_gt)); - pushclosure(L, (Closure *)lcl); - /* ... func */ - lcl->p = makefakeproto(L, 1); - - /* Temporarily initialize the upvalue to nil */ - - lua_pushnil(L); - lcl->upvals[0] = makeupval(L, -1); - lua_pop(L, 1); -} - -static void boxupval_finish(lua_State *L) -{ - /* ... func obj */ - LClosure *lcl = (LClosure *) clvalue(getobject(L, -2)); - - lcl->upvals[0]->u.value = *getobject(L, -1); - lua_pop(L, 1); -} - - -static void unboxupval(lua_State *L) -{ - /* ... func */ - LClosure *lcl; - UpVal *uv; - - lcl = (LClosure *)clvalue(getobject(L, -1)); - uv = lcl->upvals[0]; - lua_pop(L, 1); - /* ... */ - pushupval(L, uv); - /* ... upval */ -} - -static void unpersistfunction(int ref, UnpersistInfo *upi) -{ - /* perms reftbl ... */ - LClosure *lcl; - int i; - lu_byte nupvalues; - lua_checkstack(upi->L, 2); - - verify(LIF(Z,read)(&upi->zio, &nupvalues, sizeof(lu_byte)) == 0); - - lcl = (LClosure *)pdep_newLclosure(upi->L, nupvalues, hvalue(&upi->L->l_gt)); - pushclosure(upi->L, (Closure *)lcl); - - /* perms reftbl ... func */ - /* Put *some* proto in the closure, before the GC can find it */ - lcl->p = makefakeproto(upi->L, nupvalues); - - /* Also, we need to temporarily fill the upvalues */ - lua_pushnil(upi->L); - /* perms reftbl ... func nil */ - for(i=0; iupvals[i] = makeupval(upi->L, -1); - } - lua_pop(upi->L, 1); - /* perms reftbl ... func */ - - /* I can't see offhand how a function would ever get to be self- - * referential, but just in case let's register it early */ - registerobject(ref, upi); - - /* Now that it's safe, we can get the real proto */ - unpersist(upi); - /* perms reftbl ... func proto? */ - lua_assert(lua_type(upi->L, -1) == LUA_TPROTO); - /* perms reftbl ... func proto */ - lcl->p = toproto(upi->L, -1); - lua_pop(upi->L, 1); - /* perms reftbl ... func */ - - for(i=0; iL); - /* perms reftbl ... func upval */ - lcl->upvals[i] = toupval(upi->L, -1); - lua_pop(upi->L, 1); - /* perms reftbl ... func */ - } - /* perms reftbl ... func */ - - /* Finally, the fenv */ - unpersist(upi); - /* perms reftbl ... func fenv/nil? */ - lua_assert(lua_type(upi->L, -1) == LUA_TNIL || - lua_type(upi->L, -1) == LUA_TTABLE); - /* perms reftbl ... func fenv/nil */ - if(!lua_isnil(upi->L, -1)) { - /* perms reftbl ... func fenv */ - lua_setfenv(upi->L, -2); - /* perms reftbl ... func */ - } else { - /* perms reftbl ... func nil */ - lua_pop(upi->L, 1); - /* perms reftbl ... func */ - } - /* perms reftbl ... func */ -} - -static void unpersistupval(int ref, UnpersistInfo *upi) -{ - /* perms reftbl ... */ - lua_checkstack(upi->L, 2); - - boxupval_start(upi->L); - /* perms reftbl ... func */ - registerobject(ref, upi); - - unpersist(upi); - /* perms reftbl ... func obj */ - boxupval_finish(upi->L); - /* perms reftbl ... func */ -} - -static void unpersistproto(int ref, UnpersistInfo *upi) -{ - /* perms reftbl ... */ - Proto *p; - int i; - int sizep, sizek; - - /* We have to be careful. The GC expects a lot out of protos. In - * particular, we need to give the function a valid string for its - * source, and valid code, even before we actually read in the real - * code. */ - TString *source = pdep_newlstr(upi->L, "", 0); - p = pdep_newproto(upi->L); - p->source = source; - p->sizecode=1; - p->code = pdep_newvector(upi->L, 1, Instruction); - p->code[0] = CREATE_ABC(OP_RETURN, 0, 1, 0); - p->maxstacksize = 2; - p->sizek = 0; - p->sizep = 0; - - lua_checkstack(upi->L, 2); - - pushproto(upi->L, p); - /* perms reftbl ... proto */ - /* We don't need to register early, since protos can never ever be - * involved in cyclic references */ - - /* Read in constant references */ - { - verify(LIF(Z,read)(&upi->zio, &sizek, sizeof(int)) == 0); - LIF(M,reallocvector)(upi->L, p->k, 0, sizek, TValue); - for(i=0; iL, &p->k[i], getobject(upi->L, -1)); - p->sizek++; - lua_pop(upi->L, 1); - /* perms reftbl ... proto */ - } - /* perms reftbl ... proto */ - } - /* Read in sub-proto references */ - { - verify(LIF(Z,read)(&upi->zio, &sizep, sizeof(int)) == 0); - LIF(M,reallocvector)(upi->L, p->p, 0, sizep, Proto*); - for(i=0; ip[i] = toproto(upi->L, -1); - p->sizep++; - lua_pop(upi->L, 1); - /* perms reftbl ... proto */ - } - /* perms reftbl ... proto */ - } - - /* Read in code */ - { - verify(LIF(Z,read)(&upi->zio, &p->sizecode, sizeof(int)) == 0); - LIF(M,reallocvector)(upi->L, p->code, 1, p->sizecode, Instruction); - verify(LIF(Z,read)(&upi->zio, p->code, - sizeof(Instruction) * p->sizecode) == 0); - } - - /* Read in upvalue names */ - { - verify(LIF(Z,read)(&upi->zio, &p->sizeupvalues, sizeof(int)) == 0); - if (p->sizeupvalues) - { - LIF(M,reallocvector)(upi->L, p->upvalues, 0, p->sizeupvalues, TString *); - for(i=0; isizeupvalues; i++) - { - unpersist(upi); - p->upvalues[i] = pdep_newlstr(upi->L, lua_tostring(upi->L, -1), strlen(lua_tostring(upi->L, -1))); - lua_pop(upi->L, 1); - } - } - } - - /* Read in local variable infos */ - { - verify(LIF(Z,read)(&upi->zio, &p->sizelocvars, sizeof(int)) == 0); - if (p->sizelocvars) - { - LIF(M,reallocvector)(upi->L, p->locvars, 0, p->sizelocvars, LocVar); - for(i=0; isizelocvars; i++) - { - unpersist(upi); - p->locvars[i].varname = pdep_newlstr(upi->L, lua_tostring(upi->L, -1), strlen(lua_tostring(upi->L, -1))); - lua_pop(upi->L, 1); - - verify(LIF(Z,read)(&upi->zio, &p->locvars[i].startpc, sizeof(int)) == 0); - verify(LIF(Z,read)(&upi->zio, &p->locvars[i].endpc, sizeof(int)) == 0); - } - } - } - - /* Read in source string*/ - unpersist(upi); - p->source = pdep_newlstr(upi->L, lua_tostring(upi->L, -1), strlen(lua_tostring(upi->L, -1))); - lua_pop(upi->L, 1); - - /* Read in line numbers */ - { - verify(LIF(Z,read)(&upi->zio, &p->sizelineinfo, sizeof(int)) == 0); - if (p->sizelineinfo) - { - LIF(M,reallocvector)(upi->L, p->lineinfo, 0, p->sizelineinfo, int); - verify(LIF(Z,read)(&upi->zio, p->lineinfo, - sizeof(int) * p->sizelineinfo) == 0); - } - } - - /* Read in linedefined and lastlinedefined */ - verify(LIF(Z,read)(&upi->zio, &p->linedefined, sizeof(int)) == 0); - verify(LIF(Z,read)(&upi->zio, &p->lastlinedefined, sizeof(int)) == 0); - - /* Read in misc values */ - { - verify(LIF(Z,read)(&upi->zio, &p->nups, sizeof(lu_byte)) == 0); - verify(LIF(Z,read)(&upi->zio, &p->numparams, sizeof(lu_byte)) == 0); - verify(LIF(Z,read)(&upi->zio, &p->is_vararg, sizeof(lu_byte)) == 0); - verify(LIF(Z,read)(&upi->zio, &p->maxstacksize, sizeof(lu_byte)) == 0); - } -} - - -/* Does basically the opposite of luaC_link(). - * Right now this function is rather inefficient; it requires traversing the - * entire root GC set in order to find one object. If the GC list were doubly - * linked this would be much easier, but there's no reason for Lua to have - * that. */ -static void gcunlink(lua_State *L, GCObject *gco) -{ - GCObject *prevslot; - if(G(L)->rootgc == gco) { - G(L)->rootgc = G(L)->rootgc->gch.next; - return; - } - - prevslot = G(L)->rootgc; - while(prevslot->gch.next != gco) { - lua_assert(prevslot->gch.next != NULL); - prevslot = prevslot->gch.next; - } - - prevslot->gch.next = prevslot->gch.next->gch.next; -} - -/* FIXME __ALL__ field ordering */ -static void unpersistthread(int ref, UnpersistInfo *upi) -{ - /* perms reftbl ... */ - lua_State *L2; - size_t stacklimit = 0; - L2 = lua_newthread(upi->L); - lua_checkstack(upi->L, 3); - /* L1: perms reftbl ... thr */ - /* L2: (empty) */ - registerobject(ref, upi); - - /* First, deserialize the object stack. */ - { - size_t i, stacksize; - read_size(&upi->zio, &stacksize); - LIF(D,growstack)(L2, (int)stacksize); - /* Make sure that the first stack element (a nil, representing - * the imaginary top-level C function) is written to the very, - * very bottom of the stack */ - L2->top--; - for(i=0; iL, L2, stacksize); - /* L1: perms reftbl ... thr */ - /* L2: obj* */ - } - /* (hereafter, stacks refer to L1) */ - - /* Now, deserialize the CallInfo stack. */ - { - size_t i, numframes; - read_size(&upi->zio, &numframes); - LIF(D,reallocCI)(L2,numframes*2); - for(i=0; ibase_ci + i; - size_t stackbase, stackfunc, stacktop, savedpc; - read_size(&upi->zio, &stackbase); - read_size(&upi->zio, &stackfunc); - read_size(&upi->zio, &stacktop); - verify(LIF(Z,read)(&upi->zio, &ci->nresults, sizeof(int)) == 0); - read_size(&upi->zio, &savedpc); - - if(stacklimit < stacktop) - stacklimit = stacktop; - - ci->base = L2->stack+stackbase; - ci->func = L2->stack+stackfunc; - ci->top = L2->stack+stacktop; - ci->savedpc = (ci != L2->base_ci) ? - ci_func(ci)->l.p->code+savedpc : - 0; - ci->tailcalls = 0; - /* Update the pointer each time, to keep the GC - * happy*/ - L2->ci = ci; - } - } - /* perms reftbl ... thr */ - /* Deserialize the state's other parameters, with the exception of upval stuff */ - { - size_t stackbase, stacktop; - L2->savedpc = L2->ci->savedpc; - verify(LIF(Z,read)(&upi->zio, &L2->status, sizeof(lu_byte)) == 0); - read_size(&upi->zio, &stackbase); - read_size(&upi->zio, &stacktop); - -#ifdef SIZES64 - uint64 value; - verify(LIF(Z,read)(&upi->zio, &value, sizeof(uint64)) == 0); - - L2->errfunc = static_cast(value); -#else - verify(LIF(Z,read)(&upi->zio, &L2->errfunc, sizeof(ptrdiff_t)) == 0); -#endif - - //read_size(&upi->zio, (size_t *)&L2->errfunc); - L2->base = L2->stack + stackbase; - L2->top = L2->stack + stacktop; - } - /* Finally, "reopen" upvalues (see persistupval() for why) */ - { - UpVal* uv; - GCObject **nextslot = &L2->openupval; - global_State *g = G(L2); - while(1) { - size_t stackpos; - unpersist(upi); - /* perms reftbl ... thr uv/nil */ - if(lua_isnil(upi->L, -1)) { - /* perms reftbl ... thr nil */ - lua_pop(upi->L, 1); - /* perms reftbl ... thr */ - break; - } - /* perms reftbl ... thr boxeduv */ - unboxupval(upi->L); - /* perms reftbl ... thr uv */ - uv = toupval(upi->L, -1); - lua_pop(upi->L, 1); - /* perms reftbl ... thr */ - - read_size(&upi->zio, &stackpos); - uv->v = L2->stack + stackpos; - gcunlink(upi->L, (GCObject *)uv); - uv->marked = luaC_white(g); - *nextslot = (GCObject *)uv; - nextslot = &uv->next; - uv->u.l.prev = &G(L2)->uvhead; - uv->u.l.next = G(L2)->uvhead.u.l.next; - uv->u.l.next->u.l.prev = uv; - G(L2)->uvhead.u.l.next = uv; - lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); - } - *nextslot = NULL; - } - - /* The stack must be valid at least to the highest value among the CallInfos */ - /* 'top' and the values up to there must be filled with 'nil' */ - { - StkId o; - LIF(D,checkstack)(L2, (int)stacklimit); - for (o = L2->top; o <= L2->top + stacklimit; o++) - setnilvalue(o); - } -} - -static void unpersistuserdata(int ref, UnpersistInfo *upi) -{ - /* perms reftbl ... */ - int isspecial; - lua_checkstack(upi->L, 2); - verify(LIF(Z,read)(&upi->zio, &isspecial, sizeof(int)) == 0); - if(isspecial) { - unpersist(upi); - /* perms reftbl ... spfunc? */ - lua_assert(lua_isfunction(upi->L, -1)); - /* perms reftbl ... spfunc */ -#ifdef PLUTO_PASS_USERDATA_TO_PERSIST - lua_pushlightuserdata(upi->L, &upi->zio); - lua_call(upi->L, 1, 1); -#else - lua_call(upi->L, 0, 1); -#endif - /* perms reftbl ... udata? */ -/* This assertion might not be necessary; it's conceivable, for - * example, that the SP function might decide to return a table - * with equivalent functionality. For the time being, we'll - * ignore this possibility in favor of stricter and more testable - * requirements. */ - lua_assert(lua_isuserdata(upi->L, -1)); - /* perms reftbl ... udata */ - } else { - size_t length; - read_size(&upi->zio, &length); - - lua_newuserdata(upi->L, length); - /* perms reftbl ... udata */ - registerobject(ref, upi); - verify(LIF(Z,read)(&upi->zio, lua_touserdata(upi->L, -1), length) == 0); - - unpersist(upi); - /* perms reftbl ... udata mt/nil? */ - lua_assert(lua_istable(upi->L, -1) || lua_isnil(upi->L, -1)); - /* perms reftbl ... udata mt/nil */ - lua_setmetatable(upi->L, -2); - /* perms reftbl ... udata */ - } - /* perms reftbl ... udata */ -} - -static void unpersistpermanent(int ref, UnpersistInfo *upi) -{ - /* perms reftbl ... */ - lua_checkstack(upi->L, 2); - unpersist(upi); - /* perms reftbl permkey */ - lua_gettable(upi->L, 1); - /* perms reftbl perm? */ - /* We assume currently that the substituted permanent value - * shouldn't be nil. This may be a bad assumption. Real-life - * experience is needed to evaluate this. */ - lua_assert(!lua_isnil(upi->L, -1)); - /* perms reftbl perm */ -} - -#if 0 -/* For debugging only; not called when lua_assert is empty */ -static int inreftable(lua_State *L, int ref) -{ - int res; - lua_checkstack(L, 1); - /* perms reftbl ... */ - lua_pushlightuserdata(L, (void *)ref); - /* perms reftbl ... ref */ - lua_gettable(L, 2); - /* perms reftbl ... obj? */ - res = !lua_isnil(L, -1); - lua_pop(L, 1); - /* perms reftbl ... */ - return res; -} -#endif - -static void unpersist(UnpersistInfo *upi) -{ - /* perms reftbl ... */ - int firstTime; - int stacksize = lua_gettop(upi->L); stacksize = stacksize; /* DEBUG */ - lua_checkstack(upi->L, 2); - LIF(Z,read)(&upi->zio, &firstTime, sizeof(int)); - if(firstTime) { - int ref; - int type; - LIF(Z,read)(&upi->zio, &ref, sizeof(int)); - lua_assert(!inreftable(upi->L, ref)); - LIF(Z,read)(&upi->zio, &type, sizeof(int)); -#ifdef PLUTO_DEBUG - printindent(upi->level); - printf("1 %d %d\n", ref, type); - upi->level++; -#endif - switch(type) { - case LUA_TBOOLEAN: - unpersistboolean(upi); - break; - case LUA_TLIGHTUSERDATA: - unpersistlightuserdata(upi); - break; - case LUA_TNUMBER: - unpersistnumber(upi); - break; - case LUA_TSTRING: - unpersiststring(upi); - break; - case LUA_TTABLE: - unpersisttable(ref, upi); - break; - case LUA_TFUNCTION: - unpersistfunction(ref, upi); - break; - case LUA_TTHREAD: - unpersistthread(ref, upi); - break; - case LUA_TPROTO: - unpersistproto(ref, upi); - break; - case LUA_TUPVAL: - unpersistupval(ref, upi); - break; - case LUA_TUSERDATA: - unpersistuserdata(ref, upi); - break; - case PLUTO_TPERMANENT: - unpersistpermanent(ref, upi); - break; - default: - lua_assert(0); - } - /* perms reftbl ... obj */ - lua_assert(lua_type(upi->L, -1) == type || - type == PLUTO_TPERMANENT || - /* Remember, upvalues get a special dispensation, as - * described in boxupval */ - (lua_type(upi->L, -1) == LUA_TFUNCTION && - type == LUA_TUPVAL)); - registerobject(ref, upi); - /* perms reftbl ... obj */ -#ifdef PLUTO_DEBUG - upi->level--; -#endif - } else { - int ref; - LIF(Z,read)(&upi->zio, &ref, sizeof(int)); -#ifdef PLUTO_DEBUG - printindent(upi->level); - printf("0 %d\n", ref); -#endif - if(ref == 0) { - lua_pushnil(upi->L); - /* perms reftbl ... nil */ - } else { - lua_pushlightuserdata(upi->L, (void *)ref); - /* perms reftbl ... ref */ - lua_gettable(upi->L, 2); - /* perms reftbl ... obj? */ - lua_assert(!lua_isnil(upi->L, -1)); - } - /* perms reftbl ... obj/nil */ - } - /* perms reftbl ... obj/nil */ - lua_assert(lua_gettop(upi->L) == stacksize + 1); -} - -void pluto_unpersist(lua_State *L, lua_Chunkreader reader, void *ud) -{ - /* We use the graciously provided ZIO (what the heck does the Z stand - * for?) library so that we don't have to deal with the reader directly. - * Letting the reader function decide how much data to return can be - * very unpleasant. - */ - UnpersistInfo upi; - upi.L = L; -#ifdef PLUTO_DEBUG - upi.level = 0; -#endif - - lua_checkstack(L, 3); - LIF(Z,init)(L, &upi.zio, reader, ud); - - /* perms */ - lua_newtable(L); - /* perms reftbl */ - lua_gc(L, LUA_GCSTOP, 0); - unpersist(&upi); - lua_gc(L, LUA_GCRESTART, 0); - /* perms reftbl rootobj */ - lua_replace(L, 2); - /* perms rootobj */ -} - -typedef struct LoadInfo_t { - char *buf; - size_t size; -} LoadInfo; - - -static const char *bufreader(lua_State *L, void *ud, size_t *sz) { - LoadInfo *li = (LoadInfo *)ud; - if(li->size == 0) { - return NULL; - } - *sz = li->size; - li->size = 0; - return li->buf; -} - -int unpersist_l(lua_State *L) -{ - LoadInfo li; - char const *origbuf; - char *tempbuf; - size_t bufsize; - /* perms? str? ...? */ - lua_settop(L, 2); - /* perms? str? */ - origbuf = luaL_checklstring(L, 2, &bufsize); - tempbuf = LIF(M,newvector)(L, bufsize, char); - memcpy(tempbuf, origbuf, bufsize); - - li.buf = tempbuf; - li.size = bufsize; - - /* perms? str */ - lua_pop(L, 1); - /* perms? */ - luaL_checktype(L, 1, LUA_TTABLE); - /* perms */ - pluto_unpersist(L, bufreader, &li); - /* perms rootobj */ - LIF(M,freearray)(L, tempbuf, bufsize, char); - return 1; -} - -/* Stefan's first C function for Lua! :) - Returns a string describing the Pluto version you're using. */ - -int version_l(lua_State *L) -{ - const char *version = VERSION; - - lua_settop(L, 0); - /* (empty) */ - lua_pushlstring(L, version, strlen(version)); - /* str */ - return 1; -} - -/* Set human-readable output on or off. */ -int human_l(lua_State *L) -{ - /* flag? ...? */ - lua_settop(L, 1); - /* flag? */ - /*luaL_checktype(L, 1, LUA_TBOOLEAN);*/ - /* flag */ - - humanReadable = lua_toboolean(L, 1); - - lua_settop(L, 0); - /* (empty) */ - return 0; -} - -static luaL_reg pluto_reg[] = { - { "persist", persist_l }, - { "unpersist", unpersist_l }, - { "version", version_l }, - { "human", human_l }, - { NULL, NULL } -}; - -LUALIB_API int luaopen_pluto(lua_State *L) { - luaL_openlib(L, "pluto", pluto_reg, 0); - return 1; -} diff --git a/engines/sword25/util/pluto/pluto.h b/engines/sword25/util/pluto/pluto.h deleted file mode 100644 index 3674842d44..0000000000 --- a/engines/sword25/util/pluto/pluto.h +++ /dev/null @@ -1,25 +0,0 @@ -/* $Id$ */ - -/* Pluto - Heavy-duty persistence for Lua - * Copyright (C) 2004 by Ben Sunshine-Hill, and released into the public - * domain. People making use of this software as part of an application - * are politely requested to email the author at sneftel@gmail.com - * with a brief description of the application, primarily to satisfy his - * curiosity. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/* lua.h must be included before this file */ - -void pluto_persist(lua_State *L, lua_Chunkwriter writer, void *ud); - -void pluto_unpersist(lua_State *L, lua_Chunkreader reader, void *ud); - -LUALIB_API int luaopen_pluto(lua_State *L); diff --git a/engines/sword25/util/pluto/plzio.cpp b/engines/sword25/util/pluto/plzio.cpp deleted file mode 100644 index 21f69a9e8d..0000000000 --- a/engines/sword25/util/pluto/plzio.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/* -** $Id$ -** a generic input stream interface -** See Copyright Notice in lua.h -*/ - - -#include - -#define lzio_c -#define LUA_CORE - -#include "pdep/pdep.h" - -int pdep_fill (ZIO *z) { - size_t size; - lua_State *L = z->L; - const char *buff; - lua_unlock(L); - buff = z->reader(L, z->data, &size); - lua_lock(L); - if (buff == NULL || size == 0) return EOZ; - z->n = size - 1; - z->p = buff; - return char2int(*(z->p++)); -} - - -int pdep_lookahead (ZIO *z) { - if (z->n == 0) { - if (pdep_fill(z) == EOZ) - return EOZ; - else { - z->n++; /* pdep_fill removed first byte; put back it */ - z->p--; - } - } - return char2int(*z->p); -} - - -void pdep_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) { - z->L = L; - z->reader = reader; - z->data = data; - z->n = 0; - z->p = NULL; -} - - -/* --------------------------------------------------------------- read --- */ -size_t pdep_read (ZIO *z, void *b, size_t n) { - while (n) { - size_t m; - if (pdep_lookahead(z) == EOZ) - return n; /* return number of missing bytes */ - m = (n <= z->n) ? n : z->n; /* min. between n and z->n */ - memcpy(b, z->p, m); - z->n -= m; - z->p += m; - b = (char *)b + m; - n -= m; - } - return 0; -} - -/* ------------------------------------------------------------------------ */ -char *pdep_openspace (lua_State *L, Mbuffer *buff, size_t n) { - if (n > buff->buffsize) { - if (n < LUA_MINBUFFER) n = LUA_MINBUFFER; - pdep_resizebuffer(L, buff, n); - } - return buff->buffer; -} -- cgit v1.2.3 From eaff6a40f6f9cb8a5817c7b90a7e24c8c12da3fe Mon Sep 17 00:00:00 2001 From: RichieSams Date: Tue, 30 Dec 2014 18:21:43 -0600 Subject: SWORD25: Correct include guards to reflect the changes to the file names --- engines/sword25/util/lua_persistence.h | 4 ++-- engines/sword25/util/lua_persistence_util.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/sword25/util/lua_persistence.h b/engines/sword25/util/lua_persistence.h index cf7d7e03ca..88cbb04ad2 100644 --- a/engines/sword25/util/lua_persistence.h +++ b/engines/sword25/util/lua_persistence.h @@ -20,8 +20,8 @@ * */ -#ifndef LUA_SERIALIZATION_H -#define LUA_SERIALIZATION_H +#ifndef LUA_PERSISTENCE_H +#define LUA_PERSISTENCE_H #include "sword25/util/lua/lua.h" diff --git a/engines/sword25/util/lua_persistence_util.h b/engines/sword25/util/lua_persistence_util.h index 345996f606..305eea4aaf 100644 --- a/engines/sword25/util/lua_persistence_util.h +++ b/engines/sword25/util/lua_persistence_util.h @@ -20,8 +20,8 @@ * */ -#ifndef LUA_SERIALIZATION_UTIL_H -#define LUA_SERIALIZATION_UTIL_H +#ifndef LUA_PERISTENCE_UTIL_H +#define LUA_PERISTENCE_UTIL_H struct lua_State; -- cgit v1.2.3 From 8ee75e1dc56681337a3ae98c9d207e70e28c5ff5 Mon Sep 17 00:00:00 2001 From: RichieSams Date: Tue, 30 Dec 2014 18:22:15 -0600 Subject: SWORD25: Add Pluto copyright message to new persistence code Since the code is based off the Pluto code --- engines/sword25/util/lua_persist.cpp | 24 ++++++++++++++ engines/sword25/util/lua_persistence.h | 23 +++++++++++++ engines/sword25/util/lua_persistence_util.cpp | 47 +++++++++++++++++++++++++++ engines/sword25/util/lua_persistence_util.h | 24 ++++++++++++++ engines/sword25/util/lua_unpersist.cpp | 24 ++++++++++++++ 5 files changed, 142 insertions(+) (limited to 'engines') diff --git a/engines/sword25/util/lua_persist.cpp b/engines/sword25/util/lua_persist.cpp index 6d758067ad..aea4e70036 100644 --- a/engines/sword25/util/lua_persist.cpp +++ b/engines/sword25/util/lua_persist.cpp @@ -20,6 +20,30 @@ * */ +/** + * This code is heavily based on the Pluto code base. Copyright below + */ + +/* Tamed Pluto - Heavy-duty persistence for Lua + * Copyright (C) 2004 by Ben Sunshine-Hill, and released into the public + * domain. People making use of this software as part of an application + * are politely requested to email the author at sneftel@gmail.com + * with a brief description of the application, primarily to satisfy his + * curiosity. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Instrumented by Stefan Reich (info@luaos.net) + * for Mobile Lua (http://luaos.net/pages/mobile-lua.php) + */ + + #include "sword25/util/lua_persistence.h" #include "sword25/util/double_serialization.h" diff --git a/engines/sword25/util/lua_persistence.h b/engines/sword25/util/lua_persistence.h index 88cbb04ad2..53e3dee02e 100644 --- a/engines/sword25/util/lua_persistence.h +++ b/engines/sword25/util/lua_persistence.h @@ -20,6 +20,29 @@ * */ +/** + * This code is heavily based on the Pluto code base. Copyright below + */ + +/* Tamed Pluto - Heavy-duty persistence for Lua + * Copyright (C) 2004 by Ben Sunshine-Hill, and released into the public + * domain. People making use of this software as part of an application + * are politely requested to email the author at sneftel@gmail.com + * with a brief description of the application, primarily to satisfy his + * curiosity. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Instrumented by Stefan Reich (info@luaos.net) + * for Mobile Lua (http://luaos.net/pages/mobile-lua.php) + */ + #ifndef LUA_PERSISTENCE_H #define LUA_PERSISTENCE_H diff --git a/engines/sword25/util/lua_persistence_util.cpp b/engines/sword25/util/lua_persistence_util.cpp index 8365f5d483..958fb7ac3c 100644 --- a/engines/sword25/util/lua_persistence_util.cpp +++ b/engines/sword25/util/lua_persistence_util.cpp @@ -20,6 +20,53 @@ * */ +/** + * This code is heavily based on the pluto code base. Copyright below + */ + +/* Tamed Pluto - Heavy-duty persistence for Lua + * Copyright (C) 2004 by Ben Sunshine-Hill, and released into the public + * domain. People making use of this software as part of an application + * are politely requested to email the author at sneftel@gmail.com + * with a brief description of the application, primarily to satisfy his + * curiosity. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Instrumented by Stefan Reich (info@luaos.net) + * for Mobile Lua (http://luaos.net/pages/mobile-lua.php) + */ + +/** + * This code is heavily based on the Pluto code base. Copyright below + */ + +/* Tamed Pluto - Heavy-duty persistence for Lua + * Copyright (C) 2004 by Ben Sunshine-Hill, and released into the public + * domain. People making use of this software as part of an application + * are politely requested to email the author at sneftel@gmail.com + * with a brief description of the application, primarily to satisfy his + * curiosity. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Instrumented by Stefan Reich (info@luaos.net) + * for Mobile Lua (http://luaos.net/pages/mobile-lua.php) + */ + + #include "sword25/util/lua_persistence_util.h" #include "common/scummsys.h" diff --git a/engines/sword25/util/lua_persistence_util.h b/engines/sword25/util/lua_persistence_util.h index 305eea4aaf..4d0085e242 100644 --- a/engines/sword25/util/lua_persistence_util.h +++ b/engines/sword25/util/lua_persistence_util.h @@ -20,6 +20,30 @@ * */ +/** + * This code is heavily based on the Pluto code base. Copyright below + */ + +/* Tamed Pluto - Heavy-duty persistence for Lua + * Copyright (C) 2004 by Ben Sunshine-Hill, and released into the public + * domain. People making use of this software as part of an application + * are politely requested to email the author at sneftel@gmail.com + * with a brief description of the application, primarily to satisfy his + * curiosity. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Instrumented by Stefan Reich (info@luaos.net) + * for Mobile Lua (http://luaos.net/pages/mobile-lua.php) + */ + + #ifndef LUA_PERISTENCE_UTIL_H #define LUA_PERISTENCE_UTIL_H diff --git a/engines/sword25/util/lua_unpersist.cpp b/engines/sword25/util/lua_unpersist.cpp index 8d644302f9..6f3275741a 100644 --- a/engines/sword25/util/lua_unpersist.cpp +++ b/engines/sword25/util/lua_unpersist.cpp @@ -20,6 +20,30 @@ * */ +/** + * This code is heavily based on the Pluto code base. Copyright below + */ + +/* Tamed Pluto - Heavy-duty persistence for Lua + * Copyright (C) 2004 by Ben Sunshine-Hill, and released into the public + * domain. People making use of this software as part of an application + * are politely requested to email the author at sneftel@gmail.com + * with a brief description of the application, primarily to satisfy his + * curiosity. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Instrumented by Stefan Reich (info@luaos.net) + * for Mobile Lua (http://luaos.net/pages/mobile-lua.php) + */ + + #include "sword25/util/lua_persistence.h" #include "sword25/util/double_serialization.h" -- cgit v1.2.3 From 9a4d62e76a29647ed7f2c0b16f009ff143fdf739 Mon Sep 17 00:00:00 2001 From: RichieSams Date: Tue, 30 Dec 2014 18:26:59 -0600 Subject: SWORD25: Change function names to use persist instead of serialize Same argument as in 97c35714ce3986b99848a780f6b195a63f8910b7. To match the rest of the SWORD25 code base --- engines/sword25/util/lua_persist.cpp | 98 +++++++++++++++---------------- engines/sword25/util/lua_unpersist.cpp | 102 ++++++++++++++++----------------- 2 files changed, 100 insertions(+), 100 deletions(-) (limited to 'engines') diff --git a/engines/sword25/util/lua_persist.cpp b/engines/sword25/util/lua_persist.cpp index aea4e70036..6038111bbc 100644 --- a/engines/sword25/util/lua_persist.cpp +++ b/engines/sword25/util/lua_persist.cpp @@ -66,17 +66,17 @@ struct SerializationInfo { uint counter; }; -static void serialize(SerializationInfo *info); +static void persist(SerializationInfo *info); -static void serializeBoolean(SerializationInfo *info); -static void serializeNumber(SerializationInfo *info); -static void serializeString(SerializationInfo *info); -static void serializeTable(SerializationInfo *info); -static void serializeFunction(SerializationInfo *info); -static void serializeThread(SerializationInfo *info); -static void serializeProto(SerializationInfo *info); -static void serializeUpValue(SerializationInfo *info); -static void serializeUserData(SerializationInfo *info); +static void persistBoolean(SerializationInfo *info); +static void persistNumber(SerializationInfo *info); +static void persistString(SerializationInfo *info); +static void persistTable(SerializationInfo *info); +static void persistFunction(SerializationInfo *info); +static void persistThread(SerializationInfo *info); +static void persistProto(SerializationInfo *info); +static void persistUpValue(SerializationInfo *info); +static void persistUserData(SerializationInfo *info); void persistLua(lua_State *luaState, Common::WriteStream *writeStream) { @@ -127,14 +127,14 @@ void persistLua(lua_State *luaState, Common::WriteStream *writeStream) { // >>>>> permTbl indexTbl rootObj // Serialize the root recursively - serialize(&info); + persist(&info); // Return the stack back to the original state lua_remove(luaState, 2); // >>>>> permTbl rootObj } -static void serialize(SerializationInfo *info) { +static void persist(SerializationInfo *info) { // The stack can potentially have many things on it // The object we want to serialize is the item on the top of the stack // >>>>> permTbl indexTbl rootObj ...... obj @@ -215,7 +215,7 @@ static void serialize(SerializationInfo *info) { info->writeStream->writeSint32LE(PERMANENT_TYPE); // Serialize the key - serialize(info); + persist(info); // Pop the key off the stack lua_pop(info->luaState, 1); @@ -236,7 +236,7 @@ static void serialize(SerializationInfo *info) { switch (objType) { case LUA_TBOOLEAN: - serializeBoolean(info); + persistBoolean(info); break; case LUA_TLIGHTUSERDATA: // You can't serialize a pointer @@ -244,41 +244,41 @@ static void serialize(SerializationInfo *info) { assert(0); break; case LUA_TNUMBER: - serializeNumber(info); + persistNumber(info); break; case LUA_TSTRING: - serializeString(info); + persistString(info); break; case LUA_TTABLE: - serializeTable(info); + persistTable(info); break; case LUA_TFUNCTION: - serializeFunction(info); + persistFunction(info); break; case LUA_TTHREAD: - serializeThread(info); + persistThread(info); break; case LUA_TPROTO: - serializeProto(info); + persistProto(info); break; case LUA_TUPVAL: - serializeUpValue(info); + persistUpValue(info); break; case LUA_TUSERDATA: - serializeUserData(info); + persistUserData(info); break; default: assert(0); } } -static void serializeBoolean(SerializationInfo *info) { +static void persistBoolean(SerializationInfo *info) { int value = lua_toboolean(info->luaState, -1); info->writeStream->writeSint32LE(value); } -static void serializeNumber(SerializationInfo *info) { +static void persistNumber(SerializationInfo *info) { lua_Number value = lua_tonumber(info->luaState, -1); #if 1 @@ -298,7 +298,7 @@ static void serializeNumber(SerializationInfo *info) { } -static void serializeString(SerializationInfo *info) { +static void persistString(SerializationInfo *info) { // Hard cast to a uint32 to force size_t to an explicit size // *Theoretically* this could truncate, but if we have a 4gb string, we have bigger problems uint32 length = static_cast(lua_strlen(info->luaState, -1)); @@ -395,7 +395,7 @@ static bool serializeSpecialObject(SerializationInfo *info, bool defaction) { info->writeStream->writeSint32LE(1); // Serialize the function - serialize(info); + persist(info); lua_pop(info->luaState, 2); // >>>>> permTbl indexTbl ...... obj @@ -403,7 +403,7 @@ static bool serializeSpecialObject(SerializationInfo *info, bool defaction) { return true; } -static void serializeTable(SerializationInfo *info) { +static void persistTable(SerializationInfo *info) { // >>>>> permTbl indexTbl ...... tbl // Make sure there is enough room on the stack @@ -422,7 +422,7 @@ static void serializeTable(SerializationInfo *info) { } // >>>>> permTbl indexTbl ...... tbl metaTbl/nil */ - serialize(info); + persist(info); lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... tbl @@ -439,13 +439,13 @@ static void serializeTable(SerializationInfo *info) { // >>>>> permTbl indexTbl ...... tbl k v k */ // Serialize the key - serialize(info); + persist(info); lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... tbl k v */ // Serialize the value - serialize(info); + persist(info); lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... tbl k */ @@ -457,13 +457,13 @@ static void serializeTable(SerializationInfo *info) { lua_pushnil(info->luaState); // >>>>> permTbl indexTbl ...... tbl - serialize(info); + persist(info); lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... tbl } -static void serializeFunction(SerializationInfo *info) { +static void persistFunction(SerializationInfo *info) { // >>>>> permTbl indexTbl ...... func Closure *cl = clvalue(getObject(info->luaState, -1)); lua_checkstack(info->luaState, 2); @@ -484,7 +484,7 @@ static void serializeFunction(SerializationInfo *info) { pushProto(info->luaState, cl->l.p); // >>>>> permTbl indexTbl ...... func proto */ - serialize(info); + persist(info); lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... func @@ -495,7 +495,7 @@ static void serializeFunction(SerializationInfo *info) { pushUpValue(info->luaState, cl->l.upvals[i]); // >>>>> permTbl indexTbl ...... func upval - serialize(info); + persist(info); lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... func @@ -519,14 +519,14 @@ static void serializeFunction(SerializationInfo *info) { } // >>>>> permTbl indexTbl ...... func fenv/nil - serialize(info); + persist(info); lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... func } } -static void serializeThread(SerializationInfo *info) { +static void persistThread(SerializationInfo *info) { // >>>>> permTbl indexTbl ...... thread lua_State *threadState = lua_tothread(info->luaState, -1); @@ -547,7 +547,7 @@ static void serializeThread(SerializationInfo *info) { // >>>>> permTbl indexTbl ...... thread (reversed contents of thread stack) */ for (; stackSize > 0; --stackSize) { - serialize(info); + persist(info); lua_pop(info->luaState, 1); } @@ -609,7 +609,7 @@ static void serializeThread(SerializationInfo *info) { pushUpValue(info->luaState, upVal); // >>>>> permTbl indexTbl ...... thread upVal - serialize(info); + persist(info); lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... thread @@ -624,13 +624,13 @@ static void serializeThread(SerializationInfo *info) { // >>>>> permTbl indexTbl ...... thread nil // Use nil as a terminator - serialize(info); + persist(info); lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... thread } -static void serializeProto(SerializationInfo *info) { +static void persistProto(SerializationInfo *info) { // >>>>> permTbl indexTbl ...... proto Proto *proto = gco2p(getObject(info->luaState, -1)->value.gc); @@ -644,7 +644,7 @@ static void serializeProto(SerializationInfo *info) { pushObject(info->luaState, &proto->k[i]); // >>>>> permTbl indexTbl ...... proto const - serialize(info); + persist(info); lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... proto @@ -660,7 +660,7 @@ static void serializeProto(SerializationInfo *info) { pushProto(info->luaState, proto->p[i]); // >>>>> permTbl indexTbl ...... proto subProto */ - serialize(info); + persist(info); lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... proto @@ -683,7 +683,7 @@ static void serializeProto(SerializationInfo *info) { pushString(info->luaState, proto->upvalues[i]); // >>>>> permTbl indexTbl ...... proto str - serialize(info); + persist(info); lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... proto @@ -697,7 +697,7 @@ static void serializeProto(SerializationInfo *info) { pushString(info->luaState, proto->locvars[i].varname); // >>>>> permTbl indexTbl ...... proto str - serialize(info); + persist(info); lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... proto @@ -711,7 +711,7 @@ static void serializeProto(SerializationInfo *info) { pushString(info->luaState, proto->source); // >>>>> permTbl indexTbl ...... proto sourceStr - serialize(info); + persist(info); lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... proto @@ -757,7 +757,7 @@ static void serializeProto(SerializationInfo *info) { * (d) When unserializing, "reopen" each of these upvalues as the thread is * unserialized */ -static void serializeUpValue(SerializationInfo *info) { +static void persistUpValue(SerializationInfo *info) { // >>>>> permTbl indexTbl ...... upval assert(ttype(getObject(info->luaState, -1)) == LUA_TUPVAL); UpVal *upValue = gco2uv(getObject(info->luaState, -1)->value.gc); @@ -774,11 +774,11 @@ static void serializeUpValue(SerializationInfo *info) { pushObject(info->luaState, upValue->v); // >>>>> permTbl indexTbl ...... obj - serialize(info); + persist(info); // >>>>> permTbl indexTbl ...... obj } -static void serializeUserData(SerializationInfo *info) { +static void persistUserData(SerializationInfo *info) { // >>>>> permTbl rootObj ...... udata // Make sure there is enough room on the stack @@ -804,7 +804,7 @@ static void serializeUserData(SerializationInfo *info) { } // >>>>> permTbl rootObj ...... udata metaTbl/nil - serialize(info); + persist(info); lua_pop(info->luaState, 1); /* perms reftbl ... udata */ diff --git a/engines/sword25/util/lua_unpersist.cpp b/engines/sword25/util/lua_unpersist.cpp index 6f3275741a..ef0ef31041 100644 --- a/engines/sword25/util/lua_unpersist.cpp +++ b/engines/sword25/util/lua_unpersist.cpp @@ -64,18 +64,18 @@ struct UnSerializationInfo { Common::ReadStream *readStream; }; -static void unserialize(UnSerializationInfo *info); +static void unpersist(UnSerializationInfo *info); -static void unserializeBoolean(UnSerializationInfo *info); -static void unserializeNumber(UnSerializationInfo *info); -static void unserializeString(UnSerializationInfo *info); -static void unserializeTable(UnSerializationInfo *info, int index); -static void unserializeFunction(UnSerializationInfo *info, int index); -static void unserializeThread(UnSerializationInfo *info, int index); -static void unserializeProto(UnSerializationInfo *info, int index); -static void unserializeUpValue(UnSerializationInfo *info, int index); -static void unserializeUserData(UnSerializationInfo *info, int index); -static void unserializePermanent(UnSerializationInfo *info, int index); +static void unpersistBoolean(UnSerializationInfo *info); +static void unpersistNumber(UnSerializationInfo *info); +static void unpersistString(UnSerializationInfo *info); +static void unpersistTable(UnSerializationInfo *info, int index); +static void unpersistFunction(UnSerializationInfo *info, int index); +static void unpersistThread(UnSerializationInfo *info, int index); +static void unpersistProto(UnSerializationInfo *info, int index); +static void unpersistUpValue(UnSerializationInfo *info, int index); +static void unpersistUserData(UnSerializationInfo *info, int index); +static void unpersistPermanent(UnSerializationInfo *info, int index); void unpersistLua(lua_State *luaState, Common::ReadStream *readStream) { @@ -98,7 +98,7 @@ void unpersistLua(lua_State *luaState, Common::ReadStream *readStream) { lua_gc(luaState, LUA_GCSTOP, 0); // Unserialize the root object - unserialize(&info); + unpersist(&info); // >>>>> permTbl indexTbl rootObj // Re-start garbage collection @@ -129,7 +129,7 @@ static void registerObjectInIndexTable(UnSerializationInfo *info, int index) { // >>>>> permTbl indexTbl ...... obj } -static void unserialize(UnSerializationInfo *info) { +static void unpersist(UnSerializationInfo *info) { // >>>>> permTbl indexTbl ...... // Make sure there is enough room on the stack @@ -142,7 +142,7 @@ static void unserialize(UnSerializationInfo *info) { switch (type) { case LUA_TBOOLEAN: - unserializeBoolean(info); + unpersistBoolean(info); break; case LUA_TLIGHTUSERDATA: // You can't serialize a pointer @@ -150,31 +150,31 @@ static void unserialize(UnSerializationInfo *info) { assert(0); break; case LUA_TNUMBER: - unserializeNumber(info); + unpersistNumber(info); break; case LUA_TSTRING: - unserializeString(info); + unpersistString(info); break; case LUA_TTABLE: - unserializeTable(info, index); + unpersistTable(info, index); break; case LUA_TFUNCTION: - unserializeFunction(info, index); + unpersistFunction(info, index); break; case LUA_TTHREAD: - unserializeThread(info, index); + unpersistThread(info, index); break; case LUA_TPROTO: - unserializeProto(info, index); + unpersistProto(info, index); break; case LUA_TUPVAL: - unserializeUpValue(info, index); + unpersistUpValue(info, index); break; case LUA_TUSERDATA: - unserializeUserData(info, index); + unpersistUserData(info, index); break; case PERMANENT_TYPE: - unserializePermanent(info, index); + unpersistPermanent(info, index); break; default: assert(0); @@ -212,7 +212,7 @@ static void unserialize(UnSerializationInfo *info) { // >>>>> permTbl indexTbl ...... obj/nil } -static void unserializeBoolean(UnSerializationInfo *info) { +static void unpersistBoolean(UnSerializationInfo *info) { // >>>>> permTbl indexTbl ...... // Make sure there is enough room on the stack @@ -224,7 +224,7 @@ static void unserializeBoolean(UnSerializationInfo *info) { // >>>>> permTbl indexTbl ...... bool } -static void unserializeNumber(UnSerializationInfo *info) { +static void unpersistNumber(UnSerializationInfo *info) { // >>>>> permTbl indexTbl ...... // Make sure there is enough room on the stack @@ -242,7 +242,7 @@ static void unserializeNumber(UnSerializationInfo *info) { // >>>>> permTbl indexTbl ...... num } -static void unserializeString(UnSerializationInfo *info) { +static void unpersistString(UnSerializationInfo *info) { // >>>>> permTbl indexTbl ...... // Make sure there is enough room on the stack @@ -265,7 +265,7 @@ static void unserializeSpecialTable(UnSerializationInfo *info, int index) { // Make sure there is enough room on the stack lua_checkstack(info->luaState, 1); - unserialize(info); + unpersist(info); // >>>>> permTbl indexTbl ...... spfunc lua_call(info->luaState, 0, 1); @@ -286,7 +286,7 @@ static void unserializeLiteralTable(UnSerializationInfo *info, int index) { // >>>>> permTbl indexTbl ...... tbl // Unserialize metatable - unserialize(info); + unpersist(info); // >>>>> permTbl indexTbl ...... tbl ?metaTbl/nil? if (lua_istable(info->luaState, -1)) { @@ -303,7 +303,7 @@ static void unserializeLiteralTable(UnSerializationInfo *info, int index) { while (1) { // >>>>> permTbl indexTbl ...... tbl - unserialize(info); + unpersist(info); // >>>>> permTbl indexTbl ...... tbl key/nil // The table serialization is nil terminated @@ -316,7 +316,7 @@ static void unserializeLiteralTable(UnSerializationInfo *info, int index) { } // >>>>> permTbl indexTbl ...... tbl key - unserialize(info); + unpersist(info); // >>>>> permTbl indexTbl ...... tbl value lua_rawset(info->luaState, -3); @@ -324,7 +324,7 @@ static void unserializeLiteralTable(UnSerializationInfo *info, int index) { } } -void unserializeTable(UnSerializationInfo *info, int index) { +void unpersistTable(UnSerializationInfo *info, int index) { // >>>>> permTbl indexTbl ...... // Make sure there is enough room on the stack @@ -341,7 +341,7 @@ void unserializeTable(UnSerializationInfo *info, int index) { } } -void unserializeFunction(UnSerializationInfo *info, int index) { +void unpersistFunction(UnSerializationInfo *info, int index) { // >>>>> permTbl indexTbl ...... // Make sure there is enough room on the stack @@ -372,7 +372,7 @@ void unserializeFunction(UnSerializationInfo *info, int index) { registerObjectInIndexTable(info, index); // Now that it's safe, we can get the real proto - unserialize(info); + unpersist(info); // >>>>> permTbl indexTbl ...... func proto lclosure->p = gco2p(getObject(info->luaState, -1)->value.gc); @@ -382,7 +382,7 @@ void unserializeFunction(UnSerializationInfo *info, int index) { for (byte i = 0; i < numUpValues; ++i) { // >>>>> permTbl indexTbl ...... func - unserialize(info); + unpersist(info); // >>>>> permTbl indexTbl ...... func func2 unboxUpValue(info->luaState); @@ -394,7 +394,7 @@ void unserializeFunction(UnSerializationInfo *info, int index) { } // Finally, the fenv - unserialize(info); + unpersist(info); // >>>>> permTbl indexTbl ...... func ?fenv/nil? if (!lua_isnil(info->luaState, -1)) { @@ -410,7 +410,7 @@ void unserializeFunction(UnSerializationInfo *info, int index) { // >>>>> permTbl indexTbl ...... func } -void unserializeThread(UnSerializationInfo *info, int index) { +void unpersistThread(UnSerializationInfo *info, int index) { // >>>>> permTbl indexTbl ...... lua_State *L2; @@ -432,7 +432,7 @@ void unserializeThread(UnSerializationInfo *info, int index) { // very bottom of the stack L2->top--; for (uint32 i = 0; i < stackSize; ++i) { - unserialize(info); + unpersist(info); // L1: permTbl indexTbl ...... thread obj* } @@ -492,7 +492,7 @@ void unserializeThread(UnSerializationInfo *info, int index) { global_State *g = G(L2); while (true) { - unserialize(info); + unpersist(info); // >>>>> permTbl indexTbl ...... thread upVal/nil // The list is terminated by a nil @@ -535,7 +535,7 @@ void unserializeThread(UnSerializationInfo *info, int index) { } } -void unserializeProto(UnSerializationInfo *info, int index) { +void unpersistProto(UnSerializationInfo *info, int index) { // >>>>> permTbl indexTbl ...... // We have to be careful. The GC expects a lot out of protos. In particular, we need @@ -564,7 +564,7 @@ void unserializeProto(UnSerializationInfo *info, int index) { lua_reallocvector(info->luaState, p->k, 0, sizek, TValue); for (int i = 0; i < sizek; ++i) { // >>>>> permTbl indexTbl ...... proto - unserialize(info); + unpersist(info); // >>>>> permTbl indexTbl ...... proto k setobj2s(info->luaState, &p->k[i], getObject(info->luaState, -1)); @@ -581,7 +581,7 @@ void unserializeProto(UnSerializationInfo *info, int index) { lua_reallocvector(info->luaState, p->p, 0, sizep, Proto *); for (int i = 0; i < sizep; ++i) { // >>>>> permTbl indexTbl ...... proto - unserialize(info); + unpersist(info); // >>>>> permTbl indexTbl ...... proto subproto p->p[i] = (Proto *)getObject(info->luaState, -1)->value.gc; @@ -605,7 +605,7 @@ void unserializeProto(UnSerializationInfo *info, int index) { lua_reallocvector(info->luaState, p->upvalues, 0, p->sizeupvalues, TString *); for (int i = 0; i < p->sizeupvalues; ++i) { // >>>>> permTbl indexTbl ...... proto - unserialize(info); + unpersist(info); // >>>>> permTbl indexTbl ...... proto str p->upvalues[i] = lua_newlstr(info->luaState, lua_tostring(info->luaState, -1), strlen(lua_tostring(info->luaState, -1))); @@ -621,7 +621,7 @@ void unserializeProto(UnSerializationInfo *info, int index) { lua_reallocvector(info->luaState, p->locvars, 0, p->sizelocvars, LocVar); for (int i = 0; i < p->sizelocvars; ++i) { // >>>>> permTbl indexTbl ...... proto - unserialize(info); + unpersist(info); // >>>>> permTbl indexTbl ...... proto str p->locvars[i].varname = lua_newlstr(info->luaState, lua_tostring(info->luaState, -1), strlen(lua_tostring(info->luaState, -1))); @@ -635,7 +635,7 @@ void unserializeProto(UnSerializationInfo *info, int index) { // >>>>> permTbl indexTbl ...... proto // Read in source string - unserialize(info); + unpersist(info); // >>>>> permTbl indexTbl ...... proto sourceStr p->source = lua_newlstr(info->luaState, lua_tostring(info->luaState, -1), strlen(lua_tostring(info->luaState, -1))); @@ -661,7 +661,7 @@ void unserializeProto(UnSerializationInfo *info, int index) { p->maxstacksize = info->readStream->readByte(); } -void unserializeUpValue(UnSerializationInfo *info, int index) { +void unpersistUpValue(UnSerializationInfo *info, int index) { // >>>>> permTbl indexTbl ...... lua_checkstack(info->luaState, 2); @@ -669,14 +669,14 @@ void unserializeUpValue(UnSerializationInfo *info, int index) { // >>>>> permTbl indexTbl ...... func registerObjectInIndexTable(info, index); - unserialize(info); + unpersist(info); // >>>>> permTbl indexTbl ...... func obj boxUpValue_finish(info->luaState); // >>>>> permTbl indexTbl ...... func } -void unserializeUserData(UnSerializationInfo *info, int index) { +void unpersistUserData(UnSerializationInfo *info, int index) { // >>>>> permTbl indexTbl ...... // Make sure there is enough room on the stack @@ -684,7 +684,7 @@ void unserializeUserData(UnSerializationInfo *info, int index) { int isspecial = info->readStream->readSint32LE(); if (isspecial) { - unserialize(info); + unpersist(info); // >>>>> permTbl indexTbl ...... specialFunc lua_call(info->luaState, 0, 1); @@ -697,7 +697,7 @@ void unserializeUserData(UnSerializationInfo *info, int index) { info->readStream->read(lua_touserdata(info->luaState, -1), length); - unserialize(info); + unpersist(info); // >>>>> permTbl indexTbl ...... udata metaTable/nil lua_setmetatable(info->luaState, -2); @@ -706,13 +706,13 @@ void unserializeUserData(UnSerializationInfo *info, int index) { // >>>>> permTbl indexTbl ...... udata } -void unserializePermanent(UnSerializationInfo *info, int index) { +void unpersistPermanent(UnSerializationInfo *info, int index) { // >>>>> permTbl indexTbl ...... // Make sure there is enough room on the stack lua_checkstack(info->luaState, 2); - unserialize(info); + unpersist(info); // >>>>> permTbl indexTbl ...... permKey lua_gettable(info->luaState, 1); -- cgit v1.2.3 From e4f74b6c346023608841d9f871b16069e5b54194 Mon Sep 17 00:00:00 2001 From: RichieSams Date: Tue, 30 Dec 2014 18:28:14 -0600 Subject: SWORD25: Remove the option to persist a double as a string Since the current method *should* be more accurate --- engines/sword25/util/lua_persist.cpp | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) (limited to 'engines') diff --git a/engines/sword25/util/lua_persist.cpp b/engines/sword25/util/lua_persist.cpp index 6038111bbc..6fe88fe9a3 100644 --- a/engines/sword25/util/lua_persist.cpp +++ b/engines/sword25/util/lua_persist.cpp @@ -281,21 +281,11 @@ static void persistBoolean(SerializationInfo *info) { static void persistNumber(SerializationInfo *info) { lua_Number value = lua_tonumber(info->luaState, -1); - #if 1 - Util::SerializedDouble serializedValue(Util::encodeDouble(value)); - - info->writeStream->writeUint32LE(serializedValue.significandOne); - info->writeStream->writeUint32LE(serializedValue.signAndSignificandTwo); - info->writeStream->writeSint16LE(serializedValue.exponent); - #else - // NOTE: We need to store a double. Unfortunately, we have to accommodate endianness. - // Also, I don't know if we can assume all compilers use IEEE double - // Therefore, I have chosen to store the double as a string. - Common::String buffer = Common::String::format("%f", value); - - info->writeStream->write(buffer.c_str(), buffer.size()); - #endif + Util::SerializedDouble serializedValue(Util::encodeDouble(value)); + info->writeStream->writeUint32LE(serializedValue.significandOne); + info->writeStream->writeUint32LE(serializedValue.signAndSignificandTwo); + info->writeStream->writeSint16LE(serializedValue.exponent); } static void persistString(SerializationInfo *info) { -- cgit v1.2.3 From 0c54278f6c2ea6d2a2ba10ed1e833695620625ca Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 2 Jan 2015 00:28:20 +0200 Subject: ZVISION: Fix newline in truetype_font.cpp --- engines/zvision/text/truetype_font.cpp | 454 ++++++++++++++++----------------- 1 file changed, 227 insertions(+), 227 deletions(-) (limited to 'engines') diff --git a/engines/zvision/text/truetype_font.cpp b/engines/zvision/text/truetype_font.cpp index 85d9fa5a29..e378ccd127 100644 --- a/engines/zvision/text/truetype_font.cpp +++ b/engines/zvision/text/truetype_font.cpp @@ -1,228 +1,228 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "common/scummsys.h" -#include "common/config-manager.h" -#include "common/debug.h" -#include "common/file.h" -#include "common/system.h" -#include "common/unzip.h" -#include "graphics/font.h" -#include "graphics/fonts/ttf.h" -#include "graphics/surface.h" - -#include "zvision/zvision.h" -#include "zvision/graphics/render_manager.h" -#include "zvision/text/truetype_font.h" - -namespace ZVision { - -StyledTTFont::StyledTTFont(ZVision *engine) { - _engine = engine; - _style = 0; - _font = NULL; - _lineHeight = 0; -} - -StyledTTFont::~StyledTTFont() { - if (_font) - delete _font; -} - -bool StyledTTFont::loadFont(const Common::String &fontName, int32 point, uint style) { - _style = style; - return loadFont(fontName, point); -} - -bool StyledTTFont::loadFont(const Common::String &fontName, int32 point) { - struct FontStyle { - const char *zorkFont; - const char *fontBase; - const char *freeFontBase; - const char *freeFontItalicName; - }; - - const FontStyle systemFonts[] = { - { "*times new roman*", "times", "FreeSerif", "Italic" }, - { "*times*", "times", "FreeSerif", "Italic" }, - { "*century schoolbook*", "censcbk", "FreeSerif", "Italic" }, - { "*garamond*", "gara", "FreeSerif", "Italic" }, - { "*courier new*", "cour", "FreeMono", "Oblique" }, - { "*courier*", "cour", "FreeMono", "Oblique" }, - { "*ZorkDeath*", "cour", "FreeMono", "Oblique" }, - { "*arial*", "arial", "FreeSans", "Oblique" }, - { "*ZorkNormal*", "arial", "FreeSans", "Oblique" }, - }; - - Common::String newFontName; - Common::String freeFontName; - - for (int i = 0; i < ARRAYSIZE(systemFonts); i++) { - if (fontName.matchString(systemFonts[i].zorkFont, true)) { - newFontName = systemFonts[i].fontBase; - freeFontName = systemFonts[i].freeFontBase; - - if ((_style & STTF_BOLD) && (_style & STTF_ITALIC)) { - newFontName += "bi"; - freeFontName += "Bold"; - freeFontName += systemFonts[i].freeFontItalicName; - } else if (_style & STTF_BOLD) { - newFontName += "bd"; - freeFontName += "Bold"; - } else if (_style & STTF_ITALIC) { - newFontName += "i"; - freeFontName += systemFonts[i].freeFontItalicName; - } - - newFontName += ".ttf"; - freeFontName += ".ttf"; - break; - } - } - - if (newFontName.empty()) { - debug("Could not identify font: %s. Reverting to Arial", fontName.c_str()); - newFontName = "arial.ttf"; - freeFontName = "FreeSans.ttf"; - } - - bool sharp = (_style & STTF_SHARP) == STTF_SHARP; - - Common::File file; +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "common/scummsys.h" +#include "common/config-manager.h" +#include "common/debug.h" +#include "common/file.h" +#include "common/system.h" +#include "common/unzip.h" +#include "graphics/font.h" +#include "graphics/fonts/ttf.h" +#include "graphics/surface.h" + +#include "zvision/zvision.h" +#include "zvision/graphics/render_manager.h" +#include "zvision/text/truetype_font.h" + +namespace ZVision { + +StyledTTFont::StyledTTFont(ZVision *engine) { + _engine = engine; + _style = 0; + _font = NULL; + _lineHeight = 0; +} + +StyledTTFont::~StyledTTFont() { + if (_font) + delete _font; +} + +bool StyledTTFont::loadFont(const Common::String &fontName, int32 point, uint style) { + _style = style; + return loadFont(fontName, point); +} + +bool StyledTTFont::loadFont(const Common::String &fontName, int32 point) { + struct FontStyle { + const char *zorkFont; + const char *fontBase; + const char *freeFontBase; + const char *freeFontItalicName; + }; + + const FontStyle systemFonts[] = { + { "*times new roman*", "times", "FreeSerif", "Italic" }, + { "*times*", "times", "FreeSerif", "Italic" }, + { "*century schoolbook*", "censcbk", "FreeSerif", "Italic" }, + { "*garamond*", "gara", "FreeSerif", "Italic" }, + { "*courier new*", "cour", "FreeMono", "Oblique" }, + { "*courier*", "cour", "FreeMono", "Oblique" }, + { "*ZorkDeath*", "cour", "FreeMono", "Oblique" }, + { "*arial*", "arial", "FreeSans", "Oblique" }, + { "*ZorkNormal*", "arial", "FreeSans", "Oblique" }, + }; + + Common::String newFontName; + Common::String freeFontName; + + for (int i = 0; i < ARRAYSIZE(systemFonts); i++) { + if (fontName.matchString(systemFonts[i].zorkFont, true)) { + newFontName = systemFonts[i].fontBase; + freeFontName = systemFonts[i].freeFontBase; + + if ((_style & STTF_BOLD) && (_style & STTF_ITALIC)) { + newFontName += "bi"; + freeFontName += "Bold"; + freeFontName += systemFonts[i].freeFontItalicName; + } else if (_style & STTF_BOLD) { + newFontName += "bd"; + freeFontName += "Bold"; + } else if (_style & STTF_ITALIC) { + newFontName += "i"; + freeFontName += systemFonts[i].freeFontItalicName; + } + + newFontName += ".ttf"; + freeFontName += ".ttf"; + break; + } + } + + if (newFontName.empty()) { + debug("Could not identify font: %s. Reverting to Arial", fontName.c_str()); + newFontName = "arial.ttf"; + freeFontName = "FreeSans.ttf"; + } + + bool sharp = (_style & STTF_SHARP) == STTF_SHARP; + + Common::File file; if (!file.open(newFontName) && !file.open(freeFontName) && !_engine->getSearchManager()->openFile(file, newFontName) && !_engine->getSearchManager()->openFile(file, freeFontName)) - error("Unable to open font file %s (free alternative: %s)", newFontName.c_str(), freeFontName.c_str()); - - Graphics::Font *_newFont = Graphics::loadTTFFont(file, point, 60, (sharp ? Graphics::kTTFRenderModeMonochrome : Graphics::kTTFRenderModeNormal)); // 66 dpi for 640 x 480 on 14" display - if (_newFont) { - if (!_font) - delete _font; - _font = _newFont; - } - - _fntName = fontName; - _lineHeight = point; - - if (_font) - return true; - return false; -} - -void StyledTTFont::setStyle(uint newStyle) { - if ((_style & (STTF_BOLD | STTF_ITALIC | STTF_SHARP)) != (newStyle & (STTF_BOLD | STTF_ITALIC | STTF_SHARP))) { - _style = newStyle; - loadFont(_fntName, _lineHeight); - } else { - _style = newStyle; - } -} - -int StyledTTFont::getFontHeight() { - if (_font) - return _font->getFontHeight(); - return 0; -} - -int StyledTTFont::getMaxCharWidth() { - if (_font) - return _font->getMaxCharWidth(); - return 0; -} - -int StyledTTFont::getCharWidth(byte chr) { - if (_font) - return _font->getCharWidth(chr); - return 0; -} - -int StyledTTFont::getKerningOffset(byte left, byte right) { - if (_font) - return _font->getKerningOffset(left, right); - return 0; -} - -void StyledTTFont::drawChar(Graphics::Surface *dst, byte chr, int x, int y, uint32 color) { - if (_font) { - _font->drawChar(dst, chr, x, y, color); - if (_style & STTF_UNDERLINE) { - int16 pos = floor(_font->getFontHeight() * 0.87); - int thk = MAX((int)(_font->getFontHeight() * 0.05), 1); - dst->fillRect(Common::Rect(x, y + pos, x + _font->getCharWidth(chr), y + pos + thk), color); - } - if (_style & STTF_STRIKEOUT) { - int16 pos = floor(_font->getFontHeight() * 0.60); - int thk = MAX((int)(_font->getFontHeight() * 0.05), 1); - dst->fillRect(Common::Rect(x, y + pos, x + _font->getCharWidth(chr), y + pos + thk), color); - } - } -} - -void StyledTTFont::drawString(Graphics::Surface *dst, const Common::String &str, int x, int y, int w, uint32 color, Graphics::TextAlign align) { - if (_font) { - _font->drawString(dst, str, x, y, w, color, align); - if (_style & STTF_UNDERLINE) { - int16 pos = floor(_font->getFontHeight() * 0.87); - int16 wd = MIN(_font->getStringWidth(str), w); - int16 stX = x; - if (align == Graphics::kTextAlignCenter) - stX += (w - wd) / 2; - else if (align == Graphics::kTextAlignRight) - stX += (w - wd); - - int thk = MAX((int)(_font->getFontHeight() * 0.05), 1); - - dst->fillRect(Common::Rect(stX, y + pos, stX + wd, y + pos + thk), color); - } - if (_style & STTF_STRIKEOUT) { - int16 pos = floor(_font->getFontHeight() * 0.60); - int16 wd = MIN(_font->getStringWidth(str), w); - int16 stX = x; - if (align == Graphics::kTextAlignCenter) - stX += (w - wd) / 2; - else if (align == Graphics::kTextAlignRight) - stX += (w - wd); - - int thk = MAX((int)(_font->getFontHeight() * 0.05), 1); - - dst->fillRect(Common::Rect(stX, y + pos, stX + wd, y + pos + thk), color); - } - } -} - -int StyledTTFont::getStringWidth(const Common::String &str) { - if (_font) - return _font->getStringWidth(str); - return 0; -} - -Graphics::Surface *StyledTTFont::renderSolidText(const Common::String &str, uint32 color) { - Graphics::Surface *tmp = new Graphics::Surface; - if (_font) { - int16 w = _font->getStringWidth(str); - if (w && w < 1024) { - tmp->create(w, _font->getFontHeight(), _engine->_resourcePixelFormat); - drawString(tmp, str, 0, 0, w, color); - } - } - return tmp; -} - -} // End of namespace ZVision + error("Unable to open font file %s (free alternative: %s)", newFontName.c_str(), freeFontName.c_str()); + + Graphics::Font *_newFont = Graphics::loadTTFFont(file, point, 60, (sharp ? Graphics::kTTFRenderModeMonochrome : Graphics::kTTFRenderModeNormal)); // 66 dpi for 640 x 480 on 14" display + if (_newFont) { + if (!_font) + delete _font; + _font = _newFont; + } + + _fntName = fontName; + _lineHeight = point; + + if (_font) + return true; + return false; +} + +void StyledTTFont::setStyle(uint newStyle) { + if ((_style & (STTF_BOLD | STTF_ITALIC | STTF_SHARP)) != (newStyle & (STTF_BOLD | STTF_ITALIC | STTF_SHARP))) { + _style = newStyle; + loadFont(_fntName, _lineHeight); + } else { + _style = newStyle; + } +} + +int StyledTTFont::getFontHeight() { + if (_font) + return _font->getFontHeight(); + return 0; +} + +int StyledTTFont::getMaxCharWidth() { + if (_font) + return _font->getMaxCharWidth(); + return 0; +} + +int StyledTTFont::getCharWidth(byte chr) { + if (_font) + return _font->getCharWidth(chr); + return 0; +} + +int StyledTTFont::getKerningOffset(byte left, byte right) { + if (_font) + return _font->getKerningOffset(left, right); + return 0; +} + +void StyledTTFont::drawChar(Graphics::Surface *dst, byte chr, int x, int y, uint32 color) { + if (_font) { + _font->drawChar(dst, chr, x, y, color); + if (_style & STTF_UNDERLINE) { + int16 pos = floor(_font->getFontHeight() * 0.87); + int thk = MAX((int)(_font->getFontHeight() * 0.05), 1); + dst->fillRect(Common::Rect(x, y + pos, x + _font->getCharWidth(chr), y + pos + thk), color); + } + if (_style & STTF_STRIKEOUT) { + int16 pos = floor(_font->getFontHeight() * 0.60); + int thk = MAX((int)(_font->getFontHeight() * 0.05), 1); + dst->fillRect(Common::Rect(x, y + pos, x + _font->getCharWidth(chr), y + pos + thk), color); + } + } +} + +void StyledTTFont::drawString(Graphics::Surface *dst, const Common::String &str, int x, int y, int w, uint32 color, Graphics::TextAlign align) { + if (_font) { + _font->drawString(dst, str, x, y, w, color, align); + if (_style & STTF_UNDERLINE) { + int16 pos = floor(_font->getFontHeight() * 0.87); + int16 wd = MIN(_font->getStringWidth(str), w); + int16 stX = x; + if (align == Graphics::kTextAlignCenter) + stX += (w - wd) / 2; + else if (align == Graphics::kTextAlignRight) + stX += (w - wd); + + int thk = MAX((int)(_font->getFontHeight() * 0.05), 1); + + dst->fillRect(Common::Rect(stX, y + pos, stX + wd, y + pos + thk), color); + } + if (_style & STTF_STRIKEOUT) { + int16 pos = floor(_font->getFontHeight() * 0.60); + int16 wd = MIN(_font->getStringWidth(str), w); + int16 stX = x; + if (align == Graphics::kTextAlignCenter) + stX += (w - wd) / 2; + else if (align == Graphics::kTextAlignRight) + stX += (w - wd); + + int thk = MAX((int)(_font->getFontHeight() * 0.05), 1); + + dst->fillRect(Common::Rect(stX, y + pos, stX + wd, y + pos + thk), color); + } + } +} + +int StyledTTFont::getStringWidth(const Common::String &str) { + if (_font) + return _font->getStringWidth(str); + return 0; +} + +Graphics::Surface *StyledTTFont::renderSolidText(const Common::String &str, uint32 color) { + Graphics::Surface *tmp = new Graphics::Surface; + if (_font) { + int16 w = _font->getStringWidth(str); + if (w && w < 1024) { + tmp->create(w, _font->getFontHeight(), _engine->_resourcePixelFormat); + drawString(tmp, str, 0, 0, w, color); + } + } + return tmp; +} + +} // End of namespace ZVision -- cgit v1.2.3 From 976b4adb4e114c19e47efb3b18a52b1c1c1f44c4 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 2 Jan 2015 00:31:19 +0200 Subject: ZVISION: Add support for unmodified INQUIS.ZIX files This will greatly help users copy the unmodified file from the game CDs of ZGI and get the game working straight away --- engines/zvision/file/search_manager.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/zvision/file/search_manager.cpp b/engines/zvision/file/search_manager.cpp index 7a907df39c..ec250ff648 100644 --- a/engines/zvision/file/search_manager.cpp +++ b/engines/zvision/file/search_manager.cpp @@ -169,8 +169,13 @@ void SearchManager::loadZix(const Common::String &name) { line.trim(); if (line.matchString("----------*", true)) break; - else if (line.matchString("DIR:*", true)) { + else if (line.matchString("DIR:*", true) || line.matchString("CD0:*", true) || line.matchString("CD1:*", true)) { Common::String path(line.c_str() + 5); + // Check if INQUIS.ZIX refers to the ZGI folder, and check the game + // root folder instead + if (path.hasPrefix("zgi\\")) + path = Common::String(path.c_str() + 4); + Common::Archive *arc; char tempPath[128]; strcpy(tempPath, path.c_str()); -- cgit v1.2.3 From 34ec4ed6b51b81afa012543040951091ee1208ee Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Thu, 1 Jan 2015 17:36:12 -0500 Subject: ZVISION: Really fix truetype_font.cpp newlines They are now all LF. --- engines/zvision/text/truetype_font.cpp | 456 ++++++++++++++++----------------- 1 file changed, 228 insertions(+), 228 deletions(-) (limited to 'engines') diff --git a/engines/zvision/text/truetype_font.cpp b/engines/zvision/text/truetype_font.cpp index e378ccd127..622a02a6a8 100644 --- a/engines/zvision/text/truetype_font.cpp +++ b/engines/zvision/text/truetype_font.cpp @@ -1,228 +1,228 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "common/scummsys.h" -#include "common/config-manager.h" -#include "common/debug.h" -#include "common/file.h" -#include "common/system.h" -#include "common/unzip.h" -#include "graphics/font.h" -#include "graphics/fonts/ttf.h" -#include "graphics/surface.h" - -#include "zvision/zvision.h" -#include "zvision/graphics/render_manager.h" -#include "zvision/text/truetype_font.h" - -namespace ZVision { - -StyledTTFont::StyledTTFont(ZVision *engine) { - _engine = engine; - _style = 0; - _font = NULL; - _lineHeight = 0; -} - -StyledTTFont::~StyledTTFont() { - if (_font) - delete _font; -} - -bool StyledTTFont::loadFont(const Common::String &fontName, int32 point, uint style) { - _style = style; - return loadFont(fontName, point); -} - -bool StyledTTFont::loadFont(const Common::String &fontName, int32 point) { - struct FontStyle { - const char *zorkFont; - const char *fontBase; - const char *freeFontBase; - const char *freeFontItalicName; - }; - - const FontStyle systemFonts[] = { - { "*times new roman*", "times", "FreeSerif", "Italic" }, - { "*times*", "times", "FreeSerif", "Italic" }, - { "*century schoolbook*", "censcbk", "FreeSerif", "Italic" }, - { "*garamond*", "gara", "FreeSerif", "Italic" }, - { "*courier new*", "cour", "FreeMono", "Oblique" }, - { "*courier*", "cour", "FreeMono", "Oblique" }, - { "*ZorkDeath*", "cour", "FreeMono", "Oblique" }, - { "*arial*", "arial", "FreeSans", "Oblique" }, - { "*ZorkNormal*", "arial", "FreeSans", "Oblique" }, - }; - - Common::String newFontName; - Common::String freeFontName; - - for (int i = 0; i < ARRAYSIZE(systemFonts); i++) { - if (fontName.matchString(systemFonts[i].zorkFont, true)) { - newFontName = systemFonts[i].fontBase; - freeFontName = systemFonts[i].freeFontBase; - - if ((_style & STTF_BOLD) && (_style & STTF_ITALIC)) { - newFontName += "bi"; - freeFontName += "Bold"; - freeFontName += systemFonts[i].freeFontItalicName; - } else if (_style & STTF_BOLD) { - newFontName += "bd"; - freeFontName += "Bold"; - } else if (_style & STTF_ITALIC) { - newFontName += "i"; - freeFontName += systemFonts[i].freeFontItalicName; - } - - newFontName += ".ttf"; - freeFontName += ".ttf"; - break; - } - } - - if (newFontName.empty()) { - debug("Could not identify font: %s. Reverting to Arial", fontName.c_str()); - newFontName = "arial.ttf"; - freeFontName = "FreeSans.ttf"; - } - - bool sharp = (_style & STTF_SHARP) == STTF_SHARP; - - Common::File file; - if (!file.open(newFontName) && !file.open(freeFontName) && !_engine->getSearchManager()->openFile(file, newFontName) && !_engine->getSearchManager()->openFile(file, freeFontName)) - error("Unable to open font file %s (free alternative: %s)", newFontName.c_str(), freeFontName.c_str()); - - Graphics::Font *_newFont = Graphics::loadTTFFont(file, point, 60, (sharp ? Graphics::kTTFRenderModeMonochrome : Graphics::kTTFRenderModeNormal)); // 66 dpi for 640 x 480 on 14" display - if (_newFont) { - if (!_font) - delete _font; - _font = _newFont; - } - - _fntName = fontName; - _lineHeight = point; - - if (_font) - return true; - return false; -} - -void StyledTTFont::setStyle(uint newStyle) { - if ((_style & (STTF_BOLD | STTF_ITALIC | STTF_SHARP)) != (newStyle & (STTF_BOLD | STTF_ITALIC | STTF_SHARP))) { - _style = newStyle; - loadFont(_fntName, _lineHeight); - } else { - _style = newStyle; - } -} - -int StyledTTFont::getFontHeight() { - if (_font) - return _font->getFontHeight(); - return 0; -} - -int StyledTTFont::getMaxCharWidth() { - if (_font) - return _font->getMaxCharWidth(); - return 0; -} - -int StyledTTFont::getCharWidth(byte chr) { - if (_font) - return _font->getCharWidth(chr); - return 0; -} - -int StyledTTFont::getKerningOffset(byte left, byte right) { - if (_font) - return _font->getKerningOffset(left, right); - return 0; -} - -void StyledTTFont::drawChar(Graphics::Surface *dst, byte chr, int x, int y, uint32 color) { - if (_font) { - _font->drawChar(dst, chr, x, y, color); - if (_style & STTF_UNDERLINE) { - int16 pos = floor(_font->getFontHeight() * 0.87); - int thk = MAX((int)(_font->getFontHeight() * 0.05), 1); - dst->fillRect(Common::Rect(x, y + pos, x + _font->getCharWidth(chr), y + pos + thk), color); - } - if (_style & STTF_STRIKEOUT) { - int16 pos = floor(_font->getFontHeight() * 0.60); - int thk = MAX((int)(_font->getFontHeight() * 0.05), 1); - dst->fillRect(Common::Rect(x, y + pos, x + _font->getCharWidth(chr), y + pos + thk), color); - } - } -} - -void StyledTTFont::drawString(Graphics::Surface *dst, const Common::String &str, int x, int y, int w, uint32 color, Graphics::TextAlign align) { - if (_font) { - _font->drawString(dst, str, x, y, w, color, align); - if (_style & STTF_UNDERLINE) { - int16 pos = floor(_font->getFontHeight() * 0.87); - int16 wd = MIN(_font->getStringWidth(str), w); - int16 stX = x; - if (align == Graphics::kTextAlignCenter) - stX += (w - wd) / 2; - else if (align == Graphics::kTextAlignRight) - stX += (w - wd); - - int thk = MAX((int)(_font->getFontHeight() * 0.05), 1); - - dst->fillRect(Common::Rect(stX, y + pos, stX + wd, y + pos + thk), color); - } - if (_style & STTF_STRIKEOUT) { - int16 pos = floor(_font->getFontHeight() * 0.60); - int16 wd = MIN(_font->getStringWidth(str), w); - int16 stX = x; - if (align == Graphics::kTextAlignCenter) - stX += (w - wd) / 2; - else if (align == Graphics::kTextAlignRight) - stX += (w - wd); - - int thk = MAX((int)(_font->getFontHeight() * 0.05), 1); - - dst->fillRect(Common::Rect(stX, y + pos, stX + wd, y + pos + thk), color); - } - } -} - -int StyledTTFont::getStringWidth(const Common::String &str) { - if (_font) - return _font->getStringWidth(str); - return 0; -} - -Graphics::Surface *StyledTTFont::renderSolidText(const Common::String &str, uint32 color) { - Graphics::Surface *tmp = new Graphics::Surface; - if (_font) { - int16 w = _font->getStringWidth(str); - if (w && w < 1024) { - tmp->create(w, _font->getFontHeight(), _engine->_resourcePixelFormat); - drawString(tmp, str, 0, 0, w, color); - } - } - return tmp; -} - -} // End of namespace ZVision +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "common/scummsys.h" +#include "common/config-manager.h" +#include "common/debug.h" +#include "common/file.h" +#include "common/system.h" +#include "common/unzip.h" +#include "graphics/font.h" +#include "graphics/fonts/ttf.h" +#include "graphics/surface.h" + +#include "zvision/zvision.h" +#include "zvision/graphics/render_manager.h" +#include "zvision/text/truetype_font.h" + +namespace ZVision { + +StyledTTFont::StyledTTFont(ZVision *engine) { + _engine = engine; + _style = 0; + _font = NULL; + _lineHeight = 0; +} + +StyledTTFont::~StyledTTFont() { + if (_font) + delete _font; +} + +bool StyledTTFont::loadFont(const Common::String &fontName, int32 point, uint style) { + _style = style; + return loadFont(fontName, point); +} + +bool StyledTTFont::loadFont(const Common::String &fontName, int32 point) { + struct FontStyle { + const char *zorkFont; + const char *fontBase; + const char *freeFontBase; + const char *freeFontItalicName; + }; + + const FontStyle systemFonts[] = { + { "*times new roman*", "times", "FreeSerif", "Italic" }, + { "*times*", "times", "FreeSerif", "Italic" }, + { "*century schoolbook*", "censcbk", "FreeSerif", "Italic" }, + { "*garamond*", "gara", "FreeSerif", "Italic" }, + { "*courier new*", "cour", "FreeMono", "Oblique" }, + { "*courier*", "cour", "FreeMono", "Oblique" }, + { "*ZorkDeath*", "cour", "FreeMono", "Oblique" }, + { "*arial*", "arial", "FreeSans", "Oblique" }, + { "*ZorkNormal*", "arial", "FreeSans", "Oblique" }, + }; + + Common::String newFontName; + Common::String freeFontName; + + for (int i = 0; i < ARRAYSIZE(systemFonts); i++) { + if (fontName.matchString(systemFonts[i].zorkFont, true)) { + newFontName = systemFonts[i].fontBase; + freeFontName = systemFonts[i].freeFontBase; + + if ((_style & STTF_BOLD) && (_style & STTF_ITALIC)) { + newFontName += "bi"; + freeFontName += "Bold"; + freeFontName += systemFonts[i].freeFontItalicName; + } else if (_style & STTF_BOLD) { + newFontName += "bd"; + freeFontName += "Bold"; + } else if (_style & STTF_ITALIC) { + newFontName += "i"; + freeFontName += systemFonts[i].freeFontItalicName; + } + + newFontName += ".ttf"; + freeFontName += ".ttf"; + break; + } + } + + if (newFontName.empty()) { + debug("Could not identify font: %s. Reverting to Arial", fontName.c_str()); + newFontName = "arial.ttf"; + freeFontName = "FreeSans.ttf"; + } + + bool sharp = (_style & STTF_SHARP) == STTF_SHARP; + + Common::File file; + if (!file.open(newFontName) && !file.open(freeFontName) && !_engine->getSearchManager()->openFile(file, newFontName) && !_engine->getSearchManager()->openFile(file, freeFontName)) + error("Unable to open font file %s (free alternative: %s)", newFontName.c_str(), freeFontName.c_str()); + + Graphics::Font *_newFont = Graphics::loadTTFFont(file, point, 60, (sharp ? Graphics::kTTFRenderModeMonochrome : Graphics::kTTFRenderModeNormal)); // 66 dpi for 640 x 480 on 14" display + if (_newFont) { + if (!_font) + delete _font; + _font = _newFont; + } + + _fntName = fontName; + _lineHeight = point; + + if (_font) + return true; + return false; +} + +void StyledTTFont::setStyle(uint newStyle) { + if ((_style & (STTF_BOLD | STTF_ITALIC | STTF_SHARP)) != (newStyle & (STTF_BOLD | STTF_ITALIC | STTF_SHARP))) { + _style = newStyle; + loadFont(_fntName, _lineHeight); + } else { + _style = newStyle; + } +} + +int StyledTTFont::getFontHeight() { + if (_font) + return _font->getFontHeight(); + return 0; +} + +int StyledTTFont::getMaxCharWidth() { + if (_font) + return _font->getMaxCharWidth(); + return 0; +} + +int StyledTTFont::getCharWidth(byte chr) { + if (_font) + return _font->getCharWidth(chr); + return 0; +} + +int StyledTTFont::getKerningOffset(byte left, byte right) { + if (_font) + return _font->getKerningOffset(left, right); + return 0; +} + +void StyledTTFont::drawChar(Graphics::Surface *dst, byte chr, int x, int y, uint32 color) { + if (_font) { + _font->drawChar(dst, chr, x, y, color); + if (_style & STTF_UNDERLINE) { + int16 pos = floor(_font->getFontHeight() * 0.87); + int thk = MAX((int)(_font->getFontHeight() * 0.05), 1); + dst->fillRect(Common::Rect(x, y + pos, x + _font->getCharWidth(chr), y + pos + thk), color); + } + if (_style & STTF_STRIKEOUT) { + int16 pos = floor(_font->getFontHeight() * 0.60); + int thk = MAX((int)(_font->getFontHeight() * 0.05), 1); + dst->fillRect(Common::Rect(x, y + pos, x + _font->getCharWidth(chr), y + pos + thk), color); + } + } +} + +void StyledTTFont::drawString(Graphics::Surface *dst, const Common::String &str, int x, int y, int w, uint32 color, Graphics::TextAlign align) { + if (_font) { + _font->drawString(dst, str, x, y, w, color, align); + if (_style & STTF_UNDERLINE) { + int16 pos = floor(_font->getFontHeight() * 0.87); + int16 wd = MIN(_font->getStringWidth(str), w); + int16 stX = x; + if (align == Graphics::kTextAlignCenter) + stX += (w - wd) / 2; + else if (align == Graphics::kTextAlignRight) + stX += (w - wd); + + int thk = MAX((int)(_font->getFontHeight() * 0.05), 1); + + dst->fillRect(Common::Rect(stX, y + pos, stX + wd, y + pos + thk), color); + } + if (_style & STTF_STRIKEOUT) { + int16 pos = floor(_font->getFontHeight() * 0.60); + int16 wd = MIN(_font->getStringWidth(str), w); + int16 stX = x; + if (align == Graphics::kTextAlignCenter) + stX += (w - wd) / 2; + else if (align == Graphics::kTextAlignRight) + stX += (w - wd); + + int thk = MAX((int)(_font->getFontHeight() * 0.05), 1); + + dst->fillRect(Common::Rect(stX, y + pos, stX + wd, y + pos + thk), color); + } + } +} + +int StyledTTFont::getStringWidth(const Common::String &str) { + if (_font) + return _font->getStringWidth(str); + return 0; +} + +Graphics::Surface *StyledTTFont::renderSolidText(const Common::String &str, uint32 color) { + Graphics::Surface *tmp = new Graphics::Surface; + if (_font) { + int16 w = _font->getStringWidth(str); + if (w && w < 1024) { + tmp->create(w, _font->getFontHeight(), _engine->_resourcePixelFormat); + drawString(tmp, str, 0, 0, w, color); + } + } + return tmp; +} + +} // End of namespace ZVision -- cgit v1.2.3 From f4a99656ceab94cfc1c75d34180a5a49dfd43c0f Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Fri, 2 Jan 2015 01:38:49 +0100 Subject: FULLPIPE: Fix bug with spring in scene04 --- engines/fullpipe/scenes/scene04.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/fullpipe/scenes/scene04.cpp b/engines/fullpipe/scenes/scene04.cpp index fd1ececdf2..6b3ddf9640 100644 --- a/engines/fullpipe/scenes/scene04.cpp +++ b/engines/fullpipe/scenes/scene04.cpp @@ -949,7 +949,7 @@ void sceneHandler04_springWobble() { if (g_vars->scene04_bottleWeight < newdelta) g_vars->scene04_springOffset--; - if ((oldDynIndex > g_vars->scene04_bottleWeight && newdelta > g_vars->scene04_bottleWeight) || newdelta <= g_vars->scene04_bottleWeight) { + if ((oldDynIndex <= g_vars->scene04_bottleWeight && newdelta > g_vars->scene04_bottleWeight) || newdelta <= g_vars->scene04_bottleWeight) { g_vars->scene04_springDelay++; if (g_vars->scene04_springOffset && g_vars->scene04_springDelay > 1) { -- cgit v1.2.3 From 76b71cabb9946b443afc803d04b1ca9e71cf5143 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Fri, 2 Jan 2015 13:10:04 +0100 Subject: FULLPIPE: Fix bug with unmovable jar in scene04 --- engines/fullpipe/scenes/scene04.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/fullpipe/scenes/scene04.cpp b/engines/fullpipe/scenes/scene04.cpp index 6b3ddf9640..4a87ae5b87 100644 --- a/engines/fullpipe/scenes/scene04.cpp +++ b/engines/fullpipe/scenes/scene04.cpp @@ -960,6 +960,8 @@ void sceneHandler04_springWobble() { Common::Point point; + int oldpos = g_vars->scene04_spring->getCurrDimensions(point)->y - oldDynIndex; + if (g_vars->scene04_dynamicPhaseIndex) { if (!g_vars->scene04_spring->_movement) g_vars->scene04_spring->startAnim(MV_SPR_LOWER, 0, -1); @@ -969,8 +971,9 @@ void sceneHandler04_springWobble() { g_vars->scene04_spring->changeStatics2(ST_SPR_UP); } - if (g_vars->scene04_dynamicPhaseIndex != oldDynIndex) - sceneHandler04_bottleUpdateObjects(oldDynIndex - g_vars->scene04_dynamicPhaseIndex); + if (g_vars->scene04_dynamicPhaseIndex != oldDynIndex) { + sceneHandler04_bottleUpdateObjects(oldpos - (g_vars->scene04_spring->getCurrDimensions(point)->y - g_vars->scene04_dynamicPhaseIndex)); + } } void sceneHandler04_leaveScene() { -- cgit v1.2.3 From c3def28b9964066165b8627d0129578504734ab2 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Sat, 3 Jan 2015 20:17:47 +0100 Subject: FULLPIPE: Fix crash in scene04 --- engines/fullpipe/mgm.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/fullpipe/mgm.cpp b/engines/fullpipe/mgm.cpp index aacfd5452a..1c8ca2a7b1 100644 --- a/engines/fullpipe/mgm.cpp +++ b/engines/fullpipe/mgm.cpp @@ -155,13 +155,14 @@ void MGM::rebuildTables(int objId) { if (!obj) return; - for (uint i = 0; i < obj->_staticsList.size(); i++) + for (uint i = 0; i < obj->_staticsList.size(); i++) { _items[idx]->statics.push_back((Statics *)obj->_staticsList[i]); + _items[idx]->subItems.push_back(new MGMSubItem); + } + for (uint i = 0; i < obj->_movements.size(); i++) _items[idx]->movements1.push_back((Movement *)obj->_movements[i]); - - _items[idx]->subItems.clear(); } int MGM::getItemIndexById(int objId) { -- cgit v1.2.3 From 308bfe3b9cfda6ae2dd0558fcecfaa628e816b60 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Sun, 4 Jan 2015 19:16:34 +0100 Subject: FULLPIPE: Remove redundant check --- engines/fullpipe/scenes/scene16.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/fullpipe/scenes/scene16.cpp b/engines/fullpipe/scenes/scene16.cpp index e9d3a37efd..df005950d2 100644 --- a/engines/fullpipe/scenes/scene16.cpp +++ b/engines/fullpipe/scenes/scene16.cpp @@ -182,7 +182,7 @@ void sceneHandler16_fillMug() { mq = new MessageQueue(g_fp->_currentScene->getMessageQueueById(QU_SC16_BOYOUT), 0, 1); mq->replaceKeyCode(-1, g_vars->scene16_walkingBoy->_okeyCode); - if (!mq || mq->chain(g_vars->scene16_walkingBoy)) + if (mq->chain(g_vars->scene16_walkingBoy)) return; } else { if (!g_vars->scene16_walkingGirl) -- cgit v1.2.3 From 4393d38a311df69f473febc5c2fdf135694609e9 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Sun, 4 Jan 2015 19:18:41 +0100 Subject: FULLPIPE: Plug memory leak --- engines/fullpipe/statics.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/fullpipe/statics.cpp b/engines/fullpipe/statics.cpp index 880c2eb0df..6b35159fd1 100644 --- a/engines/fullpipe/statics.cpp +++ b/engines/fullpipe/statics.cpp @@ -1048,8 +1048,11 @@ MessageQueue *StaticANIObject::changeStatics1(int msgNum) { if (_flags & 1) _messageQueueId = mq->_id; } else { - if (!queueMessageQueue(mq)) + if (!queueMessageQueue(mq)) { + delete mq; + return 0; + } g_fp->_globalMessageQueueList->addMessageQueue(mq); } -- cgit v1.2.3 From 882e0ca8cbc507cfba8dec1a340be9f5462069c3 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Sun, 4 Jan 2015 19:23:43 +0100 Subject: FULLPIPE: Sanity check --- engines/fullpipe/statics.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'engines') diff --git a/engines/fullpipe/statics.cpp b/engines/fullpipe/statics.cpp index 6b35159fd1..de3e1ea728 100644 --- a/engines/fullpipe/statics.cpp +++ b/engines/fullpipe/statics.cpp @@ -1597,6 +1597,12 @@ Movement::Movement(Movement *src, int *oldIdxs, int newSize, StaticANIObject *an newSize = src->_dynamicPhases.size(); } + if (!newSize) { + warning("Movement::Movement: newSize = 0"); + + return; + } + _framePosOffsets = (Common::Point **)calloc(newSize, sizeof(Common::Point *)); for (int i = 0; i < newSize; i++) -- cgit v1.2.3 From 7da48233ce9a0154364bf26c1e419d24e70f2a26 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Sun, 4 Jan 2015 19:32:26 +0100 Subject: FULLPIPE: Fix bug in inventory --- engines/fullpipe/inventory.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/fullpipe/inventory.cpp b/engines/fullpipe/inventory.cpp index e79f9c54df..f9b507c50b 100644 --- a/engines/fullpipe/inventory.cpp +++ b/engines/fullpipe/inventory.cpp @@ -126,7 +126,7 @@ void Inventory2::removeItem2(Scene *sceneObj, int itemId, int x, int y, int prio int idx = getInventoryItemIndexById(itemId); if (idx >= 0) { - if (_inventoryItems[idx]->itemId >> 16) { + if (_inventoryItems[idx]->count) { removeItem(itemId, 1); Scene *sc = g_fp->accessScene(_sceneId); -- cgit v1.2.3 From ce45caaf83cae5990416aa2d6e833f309f7ce5c0 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Sun, 4 Jan 2015 21:06:49 +0100 Subject: SWORD25: Fix warning --- engines/sword25/util/lua_persist.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/sword25/util/lua_persist.cpp b/engines/sword25/util/lua_persist.cpp index 6fe88fe9a3..03f305b2c5 100644 --- a/engines/sword25/util/lua_persist.cpp +++ b/engines/sword25/util/lua_persist.cpp @@ -645,8 +645,7 @@ static void persistProto(SerializationInfo *info) { // Serialize inner Proto refs info->writeStream->writeSint32LE(proto->sizep); - for (int i = 0; i < proto->sizep; ++i) - { + for (int i = 0; i < proto->sizep; ++i) { pushProto(info->luaState, proto->p[i]); // >>>>> permTbl indexTbl ...... proto subProto */ @@ -668,8 +667,7 @@ static void persistProto(SerializationInfo *info) { // Serialize upvalue names info->writeStream->writeSint32LE(proto->sizeupvalues); - for (int i = 0; i < proto->sizeupvalues; ++i) - { + for (int i = 0; i < proto->sizeupvalues; ++i) { pushString(info->luaState, proto->upvalues[i]); // >>>>> permTbl indexTbl ...... proto str @@ -710,7 +708,7 @@ static void persistProto(SerializationInfo *info) { info->writeStream->writeSint32LE(proto->sizelineinfo); if (proto->sizelineinfo) { - uint32 len = static_cast(sizeof(int) * proto->sizelineinfo); + len = static_cast(sizeof(int) * proto->sizelineinfo); info->writeStream->write(proto->lineinfo, len); } -- cgit v1.2.3 From 17fe53a34c442da7ccf28721179a88ed2087f7b2 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Sun, 4 Jan 2015 22:09:46 +0100 Subject: SWORD25: Hopefully fix compilation errors --- engines/sword25/util/double_serialization.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sword25/util/double_serialization.cpp b/engines/sword25/util/double_serialization.cpp index 48fd75cb33..0d41ddc503 100644 --- a/engines/sword25/util/double_serialization.cpp +++ b/engines/sword25/util/double_serialization.cpp @@ -77,13 +77,13 @@ uint64 encodeDouble_64(double value) { uint64 uintsignificand = (uint64)shiftedsignificand; return ((uint64)(value < 0 ? 1 : 0) << 63) | // Sign ((uint64)(exponent + 1023) << 52) | // Exponent stored as an offset to 1023 - (uintsignificand & 0x000FFFFFFFFFFFFF); // significand with MSB inferred + (uintsignificand & 0x000FFFFFFFFFFFFFLL); // significand with MSB inferred } double decodeDouble_64(uint64 value) { // Expand the exponent and significand int exponent = (int)((value >> 52) & 0x7FF) - 1023; - double expandedsignificand = (double)(0x10000000000000 /* Inferred MSB */ | (value & 0x000FFFFFFFFFFFFF)); + double expandedsignificand = (double)(0x10000000000000LL /* Inferred MSB */ | (value & 0x000FFFFFFFFFFFFFLL)); // Deflate the significand int temp; @@ -93,7 +93,7 @@ double decodeDouble_64(uint64 value) { double returnValue = ldexp(significand, exponent); // Check the sign bit and return - return ((value & 0x8000000000000000) == 0x8000000000000000) ? -returnValue : returnValue; + return ((value & 0x8000000000000000LL) == 0x8000000000000000LL) ? -returnValue : returnValue; } CompactSerializedDouble encodeDouble_Compact(double value) { -- cgit v1.2.3 From baacf0be61cf8f31a72b593d320c62393241e951 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Sun, 4 Jan 2015 22:16:50 +0100 Subject: SWORD25: Commend unused and unportable functions --- engines/sword25/util/double_serialization.cpp | 6 ++++++ engines/sword25/util/double_serialization.h | 3 +++ 2 files changed, 9 insertions(+) (limited to 'engines') diff --git a/engines/sword25/util/double_serialization.cpp b/engines/sword25/util/double_serialization.cpp index 0d41ddc503..a34eb0fbff 100644 --- a/engines/sword25/util/double_serialization.cpp +++ b/engines/sword25/util/double_serialization.cpp @@ -65,6 +65,10 @@ double decodeDouble(SerializedDouble value) { return ((value.signAndSignificandTwo & 0x80000000) == 0x80000000) ? -returnValue : returnValue; } +#if 0 + +// Why these are needed? + uint64 encodeDouble_64(double value) { // Split the value into its significand and exponent int exponent; @@ -135,4 +139,6 @@ double decodeDouble_Compact(CompactSerializedDouble value) { return ((value.signAndSignificandOne & 0x80000000) == 0x80000000) ? -returnValue : returnValue; } +#endif + } // End of namespace Sword25 diff --git a/engines/sword25/util/double_serialization.h b/engines/sword25/util/double_serialization.h index e90338c369..a910a66f20 100644 --- a/engines/sword25/util/double_serialization.h +++ b/engines/sword25/util/double_serialization.h @@ -56,6 +56,7 @@ SerializedDouble encodeDouble(double value); */ double decodeDouble(SerializedDouble value); +#if 0 /** * Encodes a double as a uint64 * @@ -90,6 +91,8 @@ CompactSerializedDouble encodeDouble_Compact(double value); */ double decodeDouble_Compact(CompactSerializedDouble value); +#endif + } // End of namespace Sword25 #endif -- cgit v1.2.3 From 02e3e82e8210abe9f496f978917c9b134b5e0ad9 Mon Sep 17 00:00:00 2001 From: Kirben Date: Mon, 5 Jan 2015 22:33:19 +1100 Subject: SCUMM: Correct game flags for HE72 version of Putt-Putt Saves the Zoo. --- engines/scumm/detection_tables.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/scumm/detection_tables.h b/engines/scumm/detection_tables.h index 82a8b4452b..6eab5c752f 100644 --- a/engines/scumm/detection_tables.h +++ b/engines/scumm/detection_tables.h @@ -310,7 +310,7 @@ static const GameSettings gameVariantsTable[] = { // Changed o_getResourceSize to cover all resource types {"farm", "", 0, GID_HEGAME, 6, 73, MDT_NONE, GF_USE_KEY, UNK, GUIO3(GUIO_NOLAUNCHLOAD, GUIO_NOMIDI, GUIO_NOASPECT)}, {"puttzoo", "", 0, GID_PUTTZOO, 6, 73, MDT_NONE, GF_USE_KEY, UNK, GUIO3(GUIO_NOLAUNCHLOAD, GUIO_NOMIDI, GUIO_NOASPECT)}, - {"puttzoo", "HE 72", 0, GID_PUTTZOO, 6, 72, MDT_NONE, GF_USE_KEY | GF_HE_985, UNK, GUIO3(GUIO_NOLAUNCHLOAD, GUIO_NOMIDI, GUIO_NOASPECT)}, + {"puttzoo", "HE 72", 0, GID_PUTTZOO, 6, 72, MDT_NONE, GF_USE_KEY, UNK, GUIO3(GUIO_NOLAUNCHLOAD, GUIO_NOMIDI, GUIO_NOASPECT)}, {"puttzoo", "HE 98.5", 0, GID_PUTTZOO, 6, 98, MDT_NONE, GF_USE_KEY | GF_HE_985, UNK, GUIO3(GUIO_NOLAUNCHLOAD, GUIO_NOMIDI, GUIO_NOASPECT)}, {"puttzoo", "HE 99", 0, GID_PUTTZOO, 6, 99, MDT_NONE, GF_USE_KEY, UNK, GUIO3(GUIO_NOLAUNCHLOAD, GUIO_NOMIDI, GUIO_NOASPECT)}, {"puttzoo", "HE 100", 0, GID_PUTTZOO, 6, 100, MDT_NONE, GF_USE_KEY, UNK, GUIO3(GUIO_NOLAUNCHLOAD, GUIO_NOMIDI, GUIO_NOASPECT)}, -- cgit v1.2.3 From 5d852b5c56cf54cbd447ad29b6ab2318ac8ef8ae Mon Sep 17 00:00:00 2001 From: MestreLion Date: Tue, 6 Jan 2015 08:39:23 -0200 Subject: SCUMM: Improve FOA keyboard help --- engines/scumm/help.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/scumm/help.cpp b/engines/scumm/help.cpp index cfb23a392a..2281e954ef 100644 --- a/engines/scumm/help.cpp +++ b/engines/scumm/help.cpp @@ -36,6 +36,8 @@ int ScummHelp::numPages(byte gameId) { case GID_MANIAC: case GID_ZAK: return 4; + case GID_INDY4: + return 5; case GID_INDY3: return 6; case GID_LOOM: @@ -43,7 +45,6 @@ int ScummHelp::numPages(byte gameId) { case GID_MONKEY_VGA: case GID_MONKEY: case GID_MONKEY2: - case GID_INDY4: case GID_TENTACLE: case GID_SAMNMAX: case GID_DIG: @@ -287,10 +288,19 @@ void ScummHelp::updateStrings(byte gameId, byte version, Common::Platform platfo ADD_BIND("F3", "Melissa"); ADD_BIND("F4", "Leslie"); } + if (gameId == GID_INDY4) { + ADD_BIND("i", _("Toggle Inventory/IQ Points display")); + ADD_BIND("f", _("Toggle Keyboard/Mouse Fighting (*)")); + ADD_LINE; + ADD_TEXT(_("* Keyboard Fighting is always on,")); + ADD_TEXT(_(" so despite the in-game message this")); + ADD_TEXT(_(" actually toggles Mouse Fighting Off/On")); + } break; case 5: switch (gameId) { case GID_INDY3: + case GID_INDY4: title = _("Fighting controls (numpad):"); ADD_BIND("7", _("Step back")); ADD_BIND("4", _("Step back")); @@ -301,7 +311,9 @@ void ScummHelp::updateStrings(byte gameId, byte version, Common::Platform platfo ADD_BIND("9", _("Punch high")); ADD_BIND("6", _("Punch middle")); ADD_BIND("3", _("Punch low")); - ADD_LINE; + if (gameId == GID_INDY4) { + ADD_BIND("0", _("Sucker punch")); + } ADD_LINE; ADD_TEXT(_("These are for Indy on left.")); ADD_TEXT(_("When Indy is on the right,")); -- cgit v1.2.3 From 6dbdf037461eced4a86b7da0b2da13329d9cb3f7 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Wed, 7 Jan 2015 00:23:28 -0500 Subject: SCI: Fix Mac games with a height of 190 A regression from 72e6a9eeab1082892e5d77fabc4f0b50f839615a --- engines/sci/graphics/screen.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp index 2f95bf7751..5a3b30f7ef 100644 --- a/engines/sci/graphics/screen.cpp +++ b/engines/sci/graphics/screen.cpp @@ -81,7 +81,8 @@ GfxScreen::GfxScreen(ResourceManager *resMan) : _resMan(resMan) { case GID_LSL1: case GID_LSL5: case GID_SQ1: - _width = 190; + _scriptHeight = 190; + break; default: break; } -- cgit v1.2.3 From 535249389a16f780fba51dd2c7ca8e1eddf65de9 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 2 Jan 2015 03:59:35 +0200 Subject: ZVISION: Add a new command, "dumpimage", to dump any game image to BMP --- engines/zvision/core/console.cpp | 59 ++++++++++++++++++++++++++++++++++++++++ engines/zvision/core/console.h | 1 + 2 files changed, 60 insertions(+) (limited to 'engines') diff --git a/engines/zvision/core/console.cpp b/engines/zvision/core/console.cpp index b5e542d777..65821b1702 100644 --- a/engines/zvision/core/console.cpp +++ b/engines/zvision/core/console.cpp @@ -53,6 +53,7 @@ Console::Console(ZVision *engine) : GUI::Debugger(), _engine(engine) { registerCmd("location", WRAP_METHOD(Console, cmdLocation)); registerCmd("dumpfile", WRAP_METHOD(Console, cmdDumpFile)); registerCmd("dumpfiles", WRAP_METHOD(Console, cmdDumpFiles)); + registerCmd("dumpimage", WRAP_METHOD(Console, cmdDumpImage)); } bool Console::cmdLoadVideo(int argc, const char **argv) { @@ -269,4 +270,62 @@ bool Console::cmdDumpFiles(int argc, const char **argv) { return true; } +bool Console::cmdDumpImage(int argc, const char **argv) { + if (argc != 2) { + debugPrintf("Use %s to dump a ZVision TGA/TGZ image into a regular BMP image\n", argv[0]); + return true; + } + + Common::String fileName = argv[1]; + if (!fileName.hasSuffix(".tga")) { + debugPrintf("%s is not an image file", argv[1]); + } + + Common::File f; + if (!_engine->getSearchManager()->openFile(f, argv[1])) { + warning("File not found: %s", argv[1]); + return true; + } + + Graphics::Surface surface; + _engine->getRenderManager()->readImageToSurface(argv[1], surface, false); + + // Open file + Common::DumpFile out; + + fileName.setChar('b', fileName.size() - 3); + fileName.setChar('m', fileName.size() - 2); + fileName.setChar('p', fileName.size() - 1); + + out.open(fileName); + + // Write BMP header + out.writeByte('B'); + out.writeByte('M'); + out.writeUint32LE(surface.h * surface.pitch + 54); + out.writeUint32LE(0); + out.writeUint32LE(54); + out.writeUint32LE(40); + out.writeUint32LE(surface.w); + out.writeUint32LE(surface.h); + out.writeUint16LE(1); + out.writeUint16LE(16); + out.writeUint32LE(0); + out.writeUint32LE(0); + out.writeUint32LE(0); + out.writeUint32LE(0); + out.writeUint32LE(0); + out.writeUint32LE(0); + + // Write pixel data to BMP + out.write(surface.getPixels(), surface.pitch * surface.h); + + out.flush(); + out.close(); + + surface.free(); + + return true; +} + } // End of namespace ZVision diff --git a/engines/zvision/core/console.h b/engines/zvision/core/console.h index a7bd88ebc3..ffce87869f 100644 --- a/engines/zvision/core/console.h +++ b/engines/zvision/core/console.h @@ -47,6 +47,7 @@ private: bool cmdLocation(int argc, const char **argv); bool cmdDumpFile(int argc, const char **argv); bool cmdDumpFiles(int argc, const char **argv); + bool cmdDumpImage(int argc, const char **argv); }; } // End of namespace ZVision -- cgit v1.2.3 From 9420cc2faaa54a782084d7386be29e72d97ffcef Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 2 Jan 2015 04:01:40 +0200 Subject: ZVISION: Also handle paths in INQUIS.ZIX for the DVD version of ZGI --- engines/zvision/file/search_manager.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'engines') diff --git a/engines/zvision/file/search_manager.cpp b/engines/zvision/file/search_manager.cpp index ec250ff648..814393a374 100644 --- a/engines/zvision/file/search_manager.cpp +++ b/engines/zvision/file/search_manager.cpp @@ -175,6 +175,8 @@ void SearchManager::loadZix(const Common::String &name) { // root folder instead if (path.hasPrefix("zgi\\")) path = Common::String(path.c_str() + 4); + if (path.hasPrefix("zgi_e\\")) + path = Common::String(path.c_str() + 6); Common::Archive *arc; char tempPath[128]; -- cgit v1.2.3 From 9f642074ba8e17aa23b01bcee82b2293fe84f8f1 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 2 Jan 2015 04:52:53 +0200 Subject: ZVISION: Remove ActionRestoreGame and loading of r.svr (restart slot) This is handled internally now, so r.svr isn't needed anymore --- engines/zvision/scripting/actions.cpp | 19 +------------------ engines/zvision/scripting/actions.h | 9 --------- engines/zvision/scripting/scr_file_handling.cpp | 4 +++- engines/zvision/scripting/script_manager.cpp | 6 +++++- engines/zvision/scripting/script_manager.h | 1 + 5 files changed, 10 insertions(+), 29 deletions(-) (limited to 'engines') diff --git a/engines/zvision/scripting/actions.cpp b/engines/zvision/scripting/actions.cpp index a61fa26223..e41ac90c20 100644 --- a/engines/zvision/scripting/actions.cpp +++ b/engines/zvision/scripting/actions.cpp @@ -22,14 +22,13 @@ #include "common/scummsys.h" -#include "zvision/scripting/actions.h" - #include "zvision/zvision.h" #include "zvision/scripting/script_manager.h" #include "zvision/graphics/render_manager.h" #include "zvision/sound/zork_raw.h" #include "zvision/video/zork_avi_decoder.h" #include "zvision/file/save_manager.h" +#include "zvision/scripting/actions.h" #include "zvision/scripting/menu.h" #include "zvision/scripting/effects/timer_effect.h" #include "zvision/scripting/effects/music_effect.h" @@ -803,22 +802,6 @@ bool ActionRandom::execute() { return true; } -////////////////////////////////////////////////////////////////////////////// -// ActionRestoreGame -////////////////////////////////////////////////////////////////////////////// - -ActionRestoreGame::ActionRestoreGame(ZVision *engine, int32 slotkey, const Common::String &line) : - ResultAction(engine, slotkey) { - char buf[128]; - sscanf(line.c_str(), "%s", buf); - _fileName = Common::String(buf); -} - -bool ActionRestoreGame::execute() { - _engine->getSaveManager()->loadGame(_fileName); - return false; -} - ////////////////////////////////////////////////////////////////////////////// // ActionRotateTo ////////////////////////////////////////////////////////////////////////////// diff --git a/engines/zvision/scripting/actions.h b/engines/zvision/scripting/actions.h index 8d43309b74..c2350bc83a 100644 --- a/engines/zvision/scripting/actions.h +++ b/engines/zvision/scripting/actions.h @@ -340,15 +340,6 @@ private: ValueSlot *_max; }; -class ActionRestoreGame : public ResultAction { -public: - ActionRestoreGame(ZVision *engine, int32 slotkey, const Common::String &line); - bool execute(); - -private: - Common::String _fileName; -}; - class ActionRotateTo : public ResultAction { public: ActionRotateTo(ZVision *engine, int32 slotkey, const Common::String &line); diff --git a/engines/zvision/scripting/scr_file_handling.cpp b/engines/zvision/scripting/scr_file_handling.cpp index 227c43557c..7856bf7b2e 100644 --- a/engines/zvision/scripting/scr_file_handling.cpp +++ b/engines/zvision/scripting/scr_file_handling.cpp @@ -270,7 +270,9 @@ void ScriptManager::parseResults(Common::SeekableReadStream &stream, Common::Lis // Only used by Zork: Nemesis actionList.push_back(new ActionRegion(_engine, slot, args)); } else if (act.matchString("restore_game", true)) { - actionList.push_back(new ActionRestoreGame(_engine, slot, args)); + // Only used by ZGI to load the restart game slot, r.svr. + _engine->getScriptManager()->reset(); + _engine->getScriptManager()->changeLocation('g', 'a', 'r', 'y', 0); } else if (act.matchString("rotate_to", true)) { actionList.push_back(new ActionRotateTo(_engine, slot, args)); } else if (act.matchString("save_game", true)) { diff --git a/engines/zvision/scripting/script_manager.cpp b/engines/zvision/scripting/script_manager.cpp index 464e8bfe4d..ba38d3a0e4 100644 --- a/engines/zvision/scripting/script_manager.cpp +++ b/engines/zvision/scripting/script_manager.cpp @@ -686,7 +686,7 @@ void ScriptManager::serialize(Common::WriteStream *stream) { stream->writeSint16LE(getStateValue(i)); } -void ScriptManager::deserialize(Common::SeekableReadStream *stream) { +void ScriptManager::reset() { // Clear out the current table values _globalState.clear(); _globalStateFlags.clear(); @@ -706,6 +706,10 @@ void ScriptManager::deserialize(Common::SeekableReadStream *stream) { _activeSideFx.clear(); _referenceTable.clear(); +} + +void ScriptManager::deserialize(Common::SeekableReadStream *stream) { + reset(); if (stream->readUint32BE() != MKTAG('Z', 'N', 'S', 'G') || stream->readUint32LE() != 4) { changeLocation('g', 'a', 'r', 'y', 0); diff --git a/engines/zvision/scripting/script_manager.h b/engines/zvision/scripting/script_manager.h index 78c1b77dea..136b3427f7 100644 --- a/engines/zvision/scripting/script_manager.h +++ b/engines/zvision/scripting/script_manager.h @@ -247,6 +247,7 @@ public: void serialize(Common::WriteStream *stream); void deserialize(Common::SeekableReadStream *stream); + void reset(); Location getCurrentLocation() const; Location getLastLocation(); -- cgit v1.2.3 From 5949ab5aa6ce6a8b39ea44795e638204393adaf6 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 7 Jan 2015 11:02:24 +0200 Subject: ZVISION: Error out when a cursor file can't be found --- engines/zvision/graphics/cursors/cursor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/zvision/graphics/cursors/cursor.cpp b/engines/zvision/graphics/cursors/cursor.cpp index f32c68645d..2c011668ac 100644 --- a/engines/zvision/graphics/cursors/cursor.cpp +++ b/engines/zvision/graphics/cursors/cursor.cpp @@ -43,7 +43,7 @@ ZorkCursor::ZorkCursor(ZVision *engine, const Common::String &fileName) _hotspotY(0) { Common::File file; if (!engine->getSearchManager()->openFile(file, fileName)) - return; + error("Cursor file %s does not exist", fileName.c_str()); uint32 magic = file.readUint32BE(); if (magic != MKTAG('Z', 'C', 'R', '1')) { -- cgit v1.2.3 From 364b72c29b2f4e9d3cd45f644523966c6564e5d5 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 7 Jan 2015 11:02:56 +0200 Subject: ZVISION: Fix incorrect reference to cursor file --- engines/zvision/graphics/cursors/cursor_manager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/zvision/graphics/cursors/cursor_manager.cpp b/engines/zvision/graphics/cursors/cursor_manager.cpp index c364426bad..f3a5e736f6 100644 --- a/engines/zvision/graphics/cursors/cursor_manager.cpp +++ b/engines/zvision/graphics/cursors/cursor_manager.cpp @@ -37,7 +37,7 @@ const char *CursorManager::_cursorNames[NUM_CURSORS] = { "active", "arrow", "bac "hright", "hup", "idle", "leftarrow", "rightarrow", "suggest_surround", "suggest_tilt", "turnaround", "zuparrow" }; -const char *CursorManager::_zgiCursorFileNames[NUM_CURSORS] = { "g0gbc011.zcr", "g0gac001.zcr", "g0gac021.zcr", "g0gac031.zcr", "g0gac041.zcr", "g0gac051.zcr", "g0gac061.zcr", "g0gac071.zcr", "g0gac081.zcr", +const char *CursorManager::_zgiCursorFileNames[NUM_CURSORS] = { "g0gbc011.zcr", "g0gac011.zcr", "g0gac021.zcr", "g0gac031.zcr", "g0gac041.zcr", "g0gac051.zcr", "g0gac061.zcr", "g0gac071.zcr", "g0gac081.zcr", "g0gac091.zcr", "g0gac101.zcr", "g0gac011.zcr", "g0gac111.zcr", "g0gac121.zcr", "g0gac131.zcr", "g0gac141.zcr", "g0gac151.zcr", "g0gac161.zcr" }; -- cgit v1.2.3 From d70503cc9842059302c73c7861ada557e25a52b5 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 7 Jan 2015 11:08:02 +0200 Subject: ZVISION: Cleanup the ZIX file code Also, add handling for 3 CDs, for Zork: Nemesis --- engines/zvision/file/search_manager.cpp | 38 +++++++++++---------------------- 1 file changed, 13 insertions(+), 25 deletions(-) (limited to 'engines') diff --git a/engines/zvision/file/search_manager.cpp b/engines/zvision/file/search_manager.cpp index 814393a374..626c7775a1 100644 --- a/engines/zvision/file/search_manager.cpp +++ b/engines/zvision/file/search_manager.cpp @@ -169,44 +169,32 @@ void SearchManager::loadZix(const Common::String &name) { line.trim(); if (line.matchString("----------*", true)) break; - else if (line.matchString("DIR:*", true) || line.matchString("CD0:*", true) || line.matchString("CD1:*", true)) { + else if (line.matchString("DIR:*", true) || line.matchString("CD0:*", true) || line.matchString("CD1:*", true) || line.matchString("CD2:*", true)) { + Common::Archive *arc; + Common::String path(line.c_str() + 5); + for (uint i = 0; i < path.size(); i++) + if (path[i] == '\\') + path.setChar('/', i); + // Check if INQUIS.ZIX refers to the ZGI folder, and check the game // root folder instead - if (path.hasPrefix("zgi\\")) + if (path.hasPrefix("zgi/")) path = Common::String(path.c_str() + 4); - if (path.hasPrefix("zgi_e\\")) + if (path.hasPrefix("zgi_e/")) path = Common::String(path.c_str() + 6); - Common::Archive *arc; - char tempPath[128]; - strcpy(tempPath, path.c_str()); - for (uint i = 0; i < path.size(); i++) - if (tempPath[i] == '\\') - tempPath[i] = '/'; - - path = Common::String(tempPath); if (path.size() && path[0] == '.') path.deleteChar(0); if (path.size() && path[0] == '/') path.deleteChar(0); + if (path.size() && path.hasSuffix("/")) + path.deleteLastChar(); - if (path.matchString("*.zfs", true)) + if (path.matchString("*.zfs", true)) { arc = new ZfsArchive(path); - else { - if (path.size()) { - if (path[path.size() - 1] == '\\' || path[path.size() - 1] == '/') - path.deleteLastChar(); - if (path.size()) - for (Common::List::iterator it = _dirList.begin(); it != _dirList.end(); ++it) - if (path.equalsIgnoreCase(*it)) { - path = *it; - break; - } - } - + } else { path = Common::String::format("%s/%s", _root.c_str(), path.c_str()); - arc = new Common::FSDirectory(path); } archives.push_back(arc); -- cgit v1.2.3 From fb135b38ed25605d7b7bece9180784376e8408cc Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 7 Jan 2015 11:08:39 +0200 Subject: ZVISION: Cleanup --- engines/zvision/text/string_manager.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/zvision/text/string_manager.cpp b/engines/zvision/text/string_manager.cpp index 6b870d0b8d..c62e18f4b0 100644 --- a/engines/zvision/text/string_manager.cpp +++ b/engines/zvision/text/string_manager.cpp @@ -51,9 +51,8 @@ void StringManager::initialize(ZVisionGameId gameId) { void StringManager::loadStrFile(const Common::String &fileName) { Common::File file; - if (!_engine->getSearchManager()->openFile(file, fileName)) { + if (!_engine->getSearchManager()->openFile(file, fileName)) error("%s does not exist. String parsing failed", fileName.c_str()); - } uint lineNumber = 0; while (!file.eos()) { -- cgit v1.2.3 From 2d0e9fc74afd7578b368794a40afbc06f05c92db Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 7 Jan 2015 11:22:26 +0200 Subject: ZVISION: Move the screen initialization code into a separate function --- engines/zvision/zvision.cpp | 24 ++++++++++++++---------- engines/zvision/zvision.h | 2 ++ 2 files changed, 16 insertions(+), 10 deletions(-) (limited to 'engines') diff --git a/engines/zvision/zvision.cpp b/engines/zvision/zvision.cpp index 54991aced3..b05c790109 100644 --- a/engines/zvision/zvision.cpp +++ b/engines/zvision/zvision.cpp @@ -105,15 +105,6 @@ ZVision::ZVision(OSystem *syst, const ZVisionGameDescription *gameDesc) debug(1, "ZVision::ZVision"); - uint16 workingWindowWidth = (gameDesc->gameId == GID_NEMESIS) ? ZNM_WORKING_WINDOW_WIDTH : ZGI_WORKING_WINDOW_WIDTH; - uint16 workingWindowHeight = (gameDesc->gameId == GID_NEMESIS) ? ZNM_WORKING_WINDOW_HEIGHT : ZGI_WORKING_WINDOW_HEIGHT; - _workingWindow = Common::Rect( - (WINDOW_WIDTH - workingWindowWidth) / 2, - (WINDOW_HEIGHT - workingWindowHeight) / 2, - ((WINDOW_WIDTH - workingWindowWidth) / 2) + workingWindowWidth, - ((WINDOW_HEIGHT - workingWindowHeight) / 2) + workingWindowHeight - ); - memset(_cheatBuffer, 0, sizeof(_cheatBuffer)); } @@ -211,7 +202,7 @@ void ZVision::initialize() { } else if (_gameDescription->gameId == GID_NEMESIS) _searchManager->loadZix("NEMESIS.ZIX"); - initGraphics(WINDOW_WIDTH, WINDOW_HEIGHT, true, &_screenPixelFormat); + initScreen(); // Register random source _rnd = new Common::RandomSource("zvision"); @@ -358,4 +349,17 @@ void ZVision::fpsTimer() { _renderedFrameCount = 0; } +void ZVision::initScreen() { + uint16 workingWindowWidth = (_gameDescription->gameId == GID_NEMESIS) ? ZNM_WORKING_WINDOW_WIDTH : ZGI_WORKING_WINDOW_WIDTH; + uint16 workingWindowHeight = (_gameDescription->gameId == GID_NEMESIS) ? ZNM_WORKING_WINDOW_HEIGHT : ZGI_WORKING_WINDOW_HEIGHT; + _workingWindow = Common::Rect( + (WINDOW_WIDTH - workingWindowWidth) / 2, + (WINDOW_HEIGHT - workingWindowHeight) / 2, + ((WINDOW_WIDTH - workingWindowWidth) / 2) + workingWindowWidth, + ((WINDOW_HEIGHT - workingWindowHeight) / 2) + workingWindowHeight + ); + + initGraphics(WINDOW_WIDTH, WINDOW_HEIGHT, true, &_screenPixelFormat); +} + } // End of namespace ZVision diff --git a/engines/zvision/zvision.h b/engines/zvision/zvision.h index ad22ddaaa2..a3bcb384d1 100644 --- a/engines/zvision/zvision.h +++ b/engines/zvision/zvision.h @@ -194,6 +194,8 @@ public: _clock.stop(); } + void initScreen(); + /** * Play a video until it is finished. This is a blocking call. It will call * _clock.stop() when the video starts and _clock.start() when the video finishes. -- cgit v1.2.3 From cdbc06d0f74453584eac0611fcbe01785c6619c4 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 7 Jan 2015 11:29:28 +0200 Subject: ZVISION: Use a common function for loading game animations --- engines/zvision/scripting/actions.cpp | 45 +++++++++++++++-------------------- 1 file changed, 19 insertions(+), 26 deletions(-) (limited to 'engines') diff --git a/engines/zvision/scripting/actions.cpp b/engines/zvision/scripting/actions.cpp index e41ac90c20..4474a8801a 100644 --- a/engines/zvision/scripting/actions.cpp +++ b/engines/zvision/scripting/actions.cpp @@ -21,12 +21,11 @@ */ #include "common/scummsys.h" +#include "video/video_decoder.h" #include "zvision/zvision.h" #include "zvision/scripting/script_manager.h" #include "zvision/graphics/render_manager.h" -#include "zvision/sound/zork_raw.h" -#include "zvision/video/zork_avi_decoder.h" #include "zvision/file/save_manager.h" #include "zvision/scripting/actions.h" #include "zvision/scripting/menu.h" @@ -45,10 +44,6 @@ #include "zvision/graphics/effects/wave.h" #include "zvision/graphics/cursors/cursor_manager.h" -#include "common/file.h" - -#include "audio/decoders/wave.h" - namespace ZVision { ////////////////////////////////////////////////////////////////////////////// @@ -915,35 +910,33 @@ ActionStreamVideo::ActionStreamVideo(ZVision *engine, int32 slotkey, const Commo } bool ActionStreamVideo::execute() { - ZorkAVIDecoder decoder; - Common::File *_file = _engine->getSearchManager()->openFile(_fileName); + Video::VideoDecoder *decoder; + Common::Rect destRect = Common::Rect(_x1, _y1, _x2 + 1, _y2 + 1); - if (_file) { - if (!decoder.loadStream(_file)) { - return true; - } + Common::String subname = _fileName; + subname.setChar('s', subname.size() - 3); + subname.setChar('u', subname.size() - 2); + subname.setChar('b', subname.size() - 1); - _engine->getCursorManager()->showMouse(false); + if (!_engine->getSearchManager()->hasFile(_fileName)) + return true; - Common::Rect destRect = Common::Rect(_x1, _y1, _x2 + 1, _y2 + 1); + decoder = _engine->loadAnimation(_fileName); - Common::String subname = _fileName; - subname.setChar('s', subname.size() - 3); - subname.setChar('u', subname.size() - 2); - subname.setChar('b', subname.size() - 1); + _engine->getCursorManager()->showMouse(false); - Subtitle *sub = NULL; + Subtitle *sub = NULL; - if (_engine->getSearchManager()->hasFile(subname)) - sub = new Subtitle(_engine, subname); + if (_engine->getSearchManager()->hasFile(subname)) + sub = new Subtitle(_engine, subname); - _engine->playVideo(decoder, destRect, _skippable, sub); + _engine->playVideo(*decoder, destRect, _skippable, sub); + delete decoder; - _engine->getCursorManager()->showMouse(true); + _engine->getCursorManager()->showMouse(true); - if (sub) - delete sub; - } + if (sub) + delete sub; return true; } -- cgit v1.2.3 From e4969a98f82f151382106b89f170990cb7eed54b Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 7 Jan 2015 11:31:07 +0200 Subject: ZVISION: Fix typo in include --- engines/zvision/video/video.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/zvision/video/video.cpp b/engines/zvision/video/video.cpp index 0913b28818..3edad7a193 100644 --- a/engines/zvision/video/video.cpp +++ b/engines/zvision/video/video.cpp @@ -29,7 +29,7 @@ #include "zvision/zvision.h" #include "zvision/core/clock.h" #include "zvision/graphics/render_manager.h" -#include "zvision/scripting//script_manager.h" +#include "zvision/scripting/script_manager.h" #include "zvision/text/subtitles.h" #include "zvision/video/rlf_decoder.h" #include "zvision/video/zork_avi_decoder.h" -- cgit v1.2.3 From 4ffaf4df376e6d93c1b5c4c820c975fdee64ec8f Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 7 Jan 2015 11:39:02 +0200 Subject: ZVISION: Add stubs for the hires VOB MPEG2 videos of ZGI DVD VOB file handling is based on clone2727's work. The lowres videos are played for now, until AC3 sound handling is implemented --- engines/zvision/detection.cpp | 13 ++++++++++++- engines/zvision/scripting/actions.cpp | 13 +++++++++++++ engines/zvision/scripting/script_manager.h | 1 + engines/zvision/video/video.cpp | 11 +++++++++++ engines/zvision/zvision.cpp | 10 ++++++++-- 5 files changed, 45 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/zvision/detection.cpp b/engines/zvision/detection.cpp index 1eaff83413..5792377f8e 100644 --- a/engines/zvision/detection.cpp +++ b/engines/zvision/detection.cpp @@ -59,6 +59,7 @@ namespace ZVision { #define GAMEOPTION_DOUBLE_FPS GUIO_GAMEOPTIONS2 #define GAMEOPTION_ENABLE_VENUS GUIO_GAMEOPTIONS3 #define GAMEOPTION_DISABLE_ANIM_WHILE_TURNING GUIO_GAMEOPTIONS4 +#define GAMEOPTION_USE_HIRES_MPEG_MOVIES GUIO_GAMEOPTIONS5 static const ZVisionGameDescription gameDescriptions[] = { @@ -113,7 +114,7 @@ static const ZVisionGameDescription gameDescriptions[] = { Common::EN_ANY, Common::kPlatformWindows, ADGF_NO_FLAGS, - GUIO3(GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_DOUBLE_FPS, GAMEOPTION_DISABLE_ANIM_WHILE_TURNING) + GUIO4(GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_DOUBLE_FPS, GAMEOPTION_DISABLE_ANIM_WHILE_TURNING, GAMEOPTION_USE_HIRES_MPEG_MOVIES) }, GID_GRANDINQUISITOR }, @@ -186,6 +187,16 @@ static const ADExtraGuiOptionsMap optionsList[] = { } }, + { + GAMEOPTION_USE_HIRES_MPEG_MOVIES, + { + _s("Use the hires MPEG movies"), + _s("Use the hires MPEG movies of the DVD version, instead of the lowres AVI ones"), + "mpegmovies", + true + } + }, + AD_EXTRA_GUI_OPTIONS_TERMINATOR }; diff --git a/engines/zvision/scripting/actions.cpp b/engines/zvision/scripting/actions.cpp index 4474a8801a..f60fdbb973 100644 --- a/engines/zvision/scripting/actions.cpp +++ b/engines/zvision/scripting/actions.cpp @@ -913,6 +913,19 @@ bool ActionStreamVideo::execute() { Video::VideoDecoder *decoder; Common::Rect destRect = Common::Rect(_x1, _y1, _x2 + 1, _y2 + 1); +#ifdef USE_MPEG2 + Common::String hiresFileName = _fileName; + hiresFileName.setChar('d', hiresFileName.size() - 8); + hiresFileName.setChar('v', hiresFileName.size() - 3); + hiresFileName.setChar('o', hiresFileName.size() - 2); + hiresFileName.setChar('b', hiresFileName.size() - 1); + + if (_engine->getScriptManager()->getStateValue(StateKey_MPEGMovies) == 1 &&_engine->getSearchManager()->hasFile(hiresFileName)) + // TODO: Enable once VOB + AC3 support is implemented + //_fileName = hiresFileName; + warning("The hires videos of the DVD version of ZGI aren't supported yet, using lowres"); +#endif + Common::String subname = _fileName; subname.setChar('s', subname.size() - 3); subname.setChar('u', subname.size() - 2); diff --git a/engines/zvision/scripting/script_manager.h b/engines/zvision/scripting/script_manager.h index 136b3427f7..a05c112a18 100644 --- a/engines/zvision/scripting/script_manager.h +++ b/engines/zvision/scripting/script_manager.h @@ -87,6 +87,7 @@ enum StateKey { StateKey_JapanFonts = 75, StateKey_ExecScopeStyle = 76, StateKey_Brightness = 77, + StateKey_MPEGMovies = 78, StateKey_EF9_R = 91, StateKey_EF9_G = 92, StateKey_EF9_B = 93, diff --git a/engines/zvision/video/video.cpp b/engines/zvision/video/video.cpp index 3edad7a193..66a567abb2 100644 --- a/engines/zvision/video/video.cpp +++ b/engines/zvision/video/video.cpp @@ -23,6 +23,11 @@ #include "common/scummsys.h" #include "common/system.h" #include "video/video_decoder.h" +// TODO: Enable once VOB + AC3 support is implemented +#if 0 +//#ifdef USE_MPEG2 +#include "video/mpegps_decoder.h" +#endif #include "engines/util.h" #include "graphics/surface.h" @@ -45,6 +50,12 @@ Video::VideoDecoder *ZVision::loadAnimation(const Common::String &fileName) { animation = new RLFDecoder(); else if (tmpFileName.hasSuffix(".avi")) animation = new ZorkAVIDecoder(); +// TODO: Enable once VOB + AC3 support is implemented +#if 0 +//#ifdef USE_MPEG2 + else if (tmpFileName.hasSuffix(".vob")) + animation = new Video::MPEGPSDecoder(); +#endif else error("Unknown suffix for animation %s", fileName.c_str()); diff --git a/engines/zvision/zvision.cpp b/engines/zvision/zvision.cpp index b05c790109..1349aaa683 100644 --- a/engines/zvision/zvision.cpp +++ b/engines/zvision/zvision.cpp @@ -52,7 +52,7 @@ namespace ZVision { -#define ZVISION_SETTINGS_KEYS_COUNT 11 +#define ZVISION_SETTINGS_KEYS_COUNT 12 struct zvisionIniSettings { const char *name; @@ -73,7 +73,8 @@ struct zvisionIniSettings { {"panarotatespeed", StateKey_RotateSpeed, 540, false, true}, // checked by universe.scr {"noanimwhileturning", StateKey_NoTurnAnim, -1, false, true}, // toggle playing animations during pana rotation {"venusenabled", StateKey_VenusEnable, -1, true, true}, - {"subtitles", StateKey_Subtitles, -1, true, true} + {"subtitles", StateKey_Subtitles, -1, true, true}, + {"mpegmovies", StateKey_MPEGMovies, -1, true, true} // Zork: Grand Inquisitor DVD hi-res MPEG movies (0 = normal, 1 = hires, 2 = disable option) }; ZVision::ZVision(OSystem *syst, const ZVisionGameDescription *gameDesc) @@ -230,6 +231,11 @@ void ZVision::initialize() { loadSettings(); +#ifndef USE_MPEG2 + // libmpeg2 not loaded, disable the MPEG2 movies option + _scriptManager->setStateValue(StateKey_MPEGMovies, 2); +#endif + // Create debugger console. It requires GFX to be initialized _console = new Console(this); _doubleFPS = ConfMan.getBool("doublefps"); -- cgit v1.2.3 From 4c64f7e194e5ce74a9213ef09648e615f3661de6 Mon Sep 17 00:00:00 2001 From: RichieSams Date: Wed, 7 Jan 2015 07:00:13 -0600 Subject: SWORD25: Remove unused code The original idea was to keep the code variation and pick the best one. However, these two methods we're portable enough for our needs. --- engines/sword25/util/double_serialization.cpp | 76 --------------------------- engines/sword25/util/double_serialization.h | 37 ------------- 2 files changed, 113 deletions(-) (limited to 'engines') diff --git a/engines/sword25/util/double_serialization.cpp b/engines/sword25/util/double_serialization.cpp index a34eb0fbff..73da296e40 100644 --- a/engines/sword25/util/double_serialization.cpp +++ b/engines/sword25/util/double_serialization.cpp @@ -65,80 +65,4 @@ double decodeDouble(SerializedDouble value) { return ((value.signAndSignificandTwo & 0x80000000) == 0x80000000) ? -returnValue : returnValue; } -#if 0 - -// Why these are needed? - -uint64 encodeDouble_64(double value) { - // Split the value into its significand and exponent - int exponent; - double significand = frexp(value, &exponent); - - // Shift the significand into the integer range - double shiftedsignificand = ldexp(abs(significand), 53); - - // Combine everything using the IEEE standard - uint64 uintsignificand = (uint64)shiftedsignificand; - return ((uint64)(value < 0 ? 1 : 0) << 63) | // Sign - ((uint64)(exponent + 1023) << 52) | // Exponent stored as an offset to 1023 - (uintsignificand & 0x000FFFFFFFFFFFFFLL); // significand with MSB inferred -} - -double decodeDouble_64(uint64 value) { - // Expand the exponent and significand - int exponent = (int)((value >> 52) & 0x7FF) - 1023; - double expandedsignificand = (double)(0x10000000000000LL /* Inferred MSB */ | (value & 0x000FFFFFFFFFFFFFLL)); - - // Deflate the significand - int temp; - double significand = frexp(expandedsignificand, &temp); - - // Re-calculate the actual double - double returnValue = ldexp(significand, exponent); - - // Check the sign bit and return - return ((value & 0x8000000000000000LL) == 0x8000000000000000LL) ? -returnValue : returnValue; -} - -CompactSerializedDouble encodeDouble_Compact(double value) { - // Split the value into its significand and exponent - int exponent; - double significand = frexp(value, &exponent); - - // Shift the the first part of the significand into the integer range - double shiftedsignificandPart = ldexp(abs(significand), 32); - uint32 significandOne = uint32(floor(shiftedsignificandPart)); - - // Shift the remainder of the significand into the integer range - shiftedsignificandPart -= significandOne; - uint32 significandTwo = (uint32)(ldexp(shiftedsignificandPart, 21)); - - CompactSerializedDouble returnValue; - returnValue.signAndSignificandOne = ((uint32)(value < 0 ? 1 : 0) << 31) | // Sign - (significandOne & 0x7FFFFFFF); // significandOne with MSB inferred - // Exponent stored as an offset to 1023 - returnValue.exponentAndSignificandTwo = ((uint32)(exponent + 1023) << 21) | significandTwo; - - return returnValue; -} - -double decodeDouble_Compact(CompactSerializedDouble value) { - // Expand the exponent and the parts of the significand - int exponent = (int)(value.exponentAndSignificandTwo >> 21) - 1023; - double expandedsignificandOne = (double)(0x80000000 /* Inferred MSB */ | (value.signAndSignificandOne & 0x7FFFFFFF)); - double expandedsignificandTwo = (double)(value.exponentAndSignificandTwo & 0x1FFFFF); - - // Deflate the significand - double shiftedsignificand = ldexp(expandedsignificandTwo, -21); - double significand = ldexp(expandedsignificandOne + shiftedsignificand, -32); - - // Re-calculate the actual double - double returnValue = ldexp(significand, exponent); - - // Check the sign bit and return - return ((value.signAndSignificandOne & 0x80000000) == 0x80000000) ? -returnValue : returnValue; -} - -#endif - } // End of namespace Sword25 diff --git a/engines/sword25/util/double_serialization.h b/engines/sword25/util/double_serialization.h index a910a66f20..af58d03c17 100644 --- a/engines/sword25/util/double_serialization.h +++ b/engines/sword25/util/double_serialization.h @@ -56,43 +56,6 @@ SerializedDouble encodeDouble(double value); */ double decodeDouble(SerializedDouble value); -#if 0 -/** - * Encodes a double as a uint64 - * - * Does NOT support denormalized numbers. Does NOT support NaN, or Inf - * - * @param value The value to encode - * @return The encoded value - */ -uint64 encodeDouble_64(double value); -/** - * Decodes a previously encoded double - * - * @param value The value to decode - * @return The decoded value - */ -double decodeDouble_64(uint64 value); - -/** - * Encodes a double as two uint32 - * - * Does NOT support denormalized numbers. Does NOT support NaN, or Inf - * - * @param value The value to encode - * @return The encoded value - */ -CompactSerializedDouble encodeDouble_Compact(double value); -/** - * Decodes a previously encoded double - * - * @param value The value to decode - * @return The decoded value - */ -double decodeDouble_Compact(CompactSerializedDouble value); - -#endif - } // End of namespace Sword25 #endif -- cgit v1.2.3 From 339abc781c09cec263a67e886ab4305368f7bfb5 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 7 Jan 2015 23:40:30 +0200 Subject: ZVISION: Add detection for the French version of Zork: Nemesis --- engines/zvision/detection.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'engines') diff --git a/engines/zvision/detection.cpp b/engines/zvision/detection.cpp index 5792377f8e..66152403cf 100644 --- a/engines/zvision/detection.cpp +++ b/engines/zvision/detection.cpp @@ -77,6 +77,20 @@ static const ZVisionGameDescription gameDescriptions[] = { GID_NEMESIS }, + { + // Zork Nemesis French version + { + "znemesis", + 0, + AD_ENTRY1s("CSCR.ZFS", "f04113357b4748c13efcb58b4629887c", 2577873), + Common::FR_FRA, + Common::kPlatformDOS, + ADGF_NO_FLAGS, + GUIO4(GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_DOUBLE_FPS, GAMEOPTION_ENABLE_VENUS, GAMEOPTION_DISABLE_ANIM_WHILE_TURNING) + }, + GID_NEMESIS + }, + { // Zork Nemesis English demo version { -- cgit v1.2.3 From 5e1702d60e4e6b6e618be36a64dc4ef563c80e47 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 7 Jan 2015 23:42:10 +0200 Subject: Cursors "arrowa.zcr" and "arrowb.zcr" are missing from Zork: Nemesis --- engines/zvision/graphics/cursors/cursor_manager.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'engines') diff --git a/engines/zvision/graphics/cursors/cursor_manager.cpp b/engines/zvision/graphics/cursors/cursor_manager.cpp index f3a5e736f6..1e048efedf 100644 --- a/engines/zvision/graphics/cursors/cursor_manager.cpp +++ b/engines/zvision/graphics/cursors/cursor_manager.cpp @@ -55,6 +55,11 @@ CursorManager::CursorManager(ZVision *engine, const Graphics::PixelFormat pixelF for (int i = 0; i < NUM_CURSORS; i++) { if (_engine->getGameId() == GID_NEMESIS) { Common::String name; + if (i == 1) { + // Cursors "arrowa.zcr" and "arrowb.zcr" are missing + _cursors[i][0] = _cursors[i][1] = ZorkCursor(); + continue; + } name = Common::String::format("%sa.zcr", _zNemCursorFileNames[i]); _cursors[i][0] = ZorkCursor(_engine, name); // Up cursor name = Common::String::format("%sb.zcr", _zNemCursorFileNames[i]); -- cgit v1.2.3 From 07ad10babe6eed96ac1d3ff8e9fc9580ec21b7bd Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 7 Jan 2015 23:45:43 +0200 Subject: ZVISION: Handle sound patches (.src files) dynamically --- engines/zvision/file/search_manager.cpp | 13 ------------- engines/zvision/file/search_manager.h | 1 - engines/zvision/sound/zork_raw.cpp | 22 +++++++++++++++++++--- engines/zvision/zvision.cpp | 14 -------------- 4 files changed, 19 insertions(+), 31 deletions(-) (limited to 'engines') diff --git a/engines/zvision/file/search_manager.cpp b/engines/zvision/file/search_manager.cpp index 626c7775a1..aecfff5208 100644 --- a/engines/zvision/file/search_manager.cpp +++ b/engines/zvision/file/search_manager.cpp @@ -62,19 +62,6 @@ SearchManager::~SearchManager() { _archList.clear(); } -void SearchManager::addPatch(const Common::String &src, const Common::String &dst) { - Common::String lowerCaseName = dst; - lowerCaseName.toLowercase(); - - SearchManager::MatchList::iterator it = _files.find(lowerCaseName); - - if (it != _files.end()) { - lowerCaseName = src; - lowerCaseName.toLowercase(); - _files[lowerCaseName] = it->_value; - } -} - void SearchManager::addFile(const Common::String &name, Common::Archive *arch) { bool addArch = true; Common::List::iterator it = _archList.begin(); diff --git a/engines/zvision/file/search_manager.h b/engines/zvision/file/search_manager.h index b9ed02ec13..43e7ff4d14 100644 --- a/engines/zvision/file/search_manager.h +++ b/engines/zvision/file/search_manager.h @@ -39,7 +39,6 @@ public: void addFile(const Common::String &name, Common::Archive *arch); void addDir(const Common::String &name); - void addPatch(const Common::String &src, const Common::String &dst); Common::File *openFile(const Common::String &name); bool openFile(Common::File &file, const Common::String &name); diff --git a/engines/zvision/sound/zork_raw.cpp b/engines/zvision/sound/zork_raw.cpp index 6d1980b1af..0ef5de2f55 100644 --- a/engines/zvision/sound/zork_raw.cpp +++ b/engines/zvision/sound/zork_raw.cpp @@ -242,11 +242,27 @@ Audio::RewindableAudioStream *makeRawZorkStream(Common::SeekableReadStream *stre Audio::RewindableAudioStream *makeRawZorkStream(const Common::String &filePath, ZVision *engine) { Common::File *file = new Common::File(); - if (!engine->getSearchManager()->openFile(*file, filePath)) - error("File not found: %s", filePath.c_str()); + Common::String actualName = filePath; + bool found = engine->getSearchManager()->openFile(*file, actualName); + bool isRaw = actualName.hasSuffix(".raw"); + + if ((!found && isRaw) || (found && isRaw && file->size() < 10)) { + if (found) + file->close(); + + // Check for an audio patch (.src) + actualName.setChar('s', actualName.size() - 3); + actualName.setChar('r', actualName.size() - 2); + actualName.setChar('c', actualName.size() - 1); + + if (!engine->getSearchManager()->openFile(*file, actualName)) + error("File not found: %s", actualName.c_str()); + } else if (!found && !isRaw) { + error("File not found: %s", actualName.c_str()); + } // Get the file name - Common::StringTokenizer tokenizer(filePath, "/\\"); + Common::StringTokenizer tokenizer(actualName, "/\\"); Common::String fileName; while (!tokenizer.empty()) { fileName = tokenizer.nextToken(); diff --git a/engines/zvision/zvision.cpp b/engines/zvision/zvision.cpp index 1349aaa683..848cba0f66 100644 --- a/engines/zvision/zvision.cpp +++ b/engines/zvision/zvision.cpp @@ -186,20 +186,6 @@ void ZVision::initialize() { if (_gameDescription->gameId == GID_GRANDINQUISITOR) { _searchManager->loadZix("INQUIS.ZIX"); - _searchManager->addPatch("C000H01Q.RAW", "C000H01Q.SRC"); - _searchManager->addPatch("CM00H01Q.RAW", "CM00H01Q.SRC"); - _searchManager->addPatch("DM00H01Q.RAW", "DM00H01Q.SRC"); - _searchManager->addPatch("E000H01Q.RAW", "E000H01Q.SRC"); - _searchManager->addPatch("EM00H50Q.RAW", "EM00H50Q.SRC"); - _searchManager->addPatch("GJNPH65P.RAW", "GJNPH65P.SRC"); - _searchManager->addPatch("GJNPH72P.RAW", "GJNPH72P.SRC"); - _searchManager->addPatch("H000H01Q.RAW", "H000H01Q.SRC"); - _searchManager->addPatch("M000H01Q.RAW", "M000H01Q.SRC"); - _searchManager->addPatch("P000H01Q.RAW", "P000H01Q.SRC"); - _searchManager->addPatch("Q000H01Q.RAW", "Q000H01Q.SRC"); - _searchManager->addPatch("SW00H01Q.RAW", "SW00H01Q.SRC"); - _searchManager->addPatch("T000H01Q.RAW", "T000H01Q.SRC"); - _searchManager->addPatch("U000H01Q.RAW", "U000H01Q.SRC"); } else if (_gameDescription->gameId == GID_NEMESIS) _searchManager->loadZix("NEMESIS.ZIX"); -- cgit v1.2.3 From 474ef741226ac56bd146c79be96c55c00551593b Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 7 Jan 2015 23:46:49 +0200 Subject: ZVISION: Check the validity of ZIX files --- engines/zvision/file/search_manager.cpp | 11 +++++++---- engines/zvision/file/search_manager.h | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/zvision/file/search_manager.cpp b/engines/zvision/file/search_manager.cpp index aecfff5208..80792b07d8 100644 --- a/engines/zvision/file/search_manager.cpp +++ b/engines/zvision/file/search_manager.cpp @@ -134,9 +134,10 @@ bool SearchManager::hasFile(const Common::String &name) { return false; } -void SearchManager::loadZix(const Common::String &name) { +bool SearchManager::loadZix(const Common::String &name) { Common::File file; - file.open(name); + if (!file.open(name)) + return false; Common::String line; @@ -147,7 +148,7 @@ void SearchManager::loadZix(const Common::String &name) { } if (file.eos()) - return; + error("Corrupt ZIX file: %s", name.c_str()); Common::Array archives; @@ -189,7 +190,7 @@ void SearchManager::loadZix(const Common::String &name) { } if (file.eos()) - return; + error("Corrupt ZIX file: %s", name.c_str()); while (!file.eos()) { line = file.readLine(); @@ -202,6 +203,8 @@ void SearchManager::loadZix(const Common::String &name) { } } } + + return true; } void SearchManager::addDir(const Common::String &name) { diff --git a/engines/zvision/file/search_manager.h b/engines/zvision/file/search_manager.h index 43e7ff4d14..0d0ab14d31 100644 --- a/engines/zvision/file/search_manager.h +++ b/engines/zvision/file/search_manager.h @@ -44,7 +44,7 @@ public: bool openFile(Common::File &file, const Common::String &name); bool hasFile(const Common::String &name); - void loadZix(const Common::String &name); + bool loadZix(const Common::String &name); struct Node { Common::String name; -- cgit v1.2.3 From a9b79544a11eba0649905330f58c4ff6161687e8 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 7 Jan 2015 23:48:01 +0200 Subject: ZVISION: Add support for an unmodified ZIX file for Zork: Nemesis This helps in copying the game files straight off the CD --- engines/zvision/zvision.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/zvision/zvision.cpp b/engines/zvision/zvision.cpp index 848cba0f66..5b6d63e869 100644 --- a/engines/zvision/zvision.cpp +++ b/engines/zvision/zvision.cpp @@ -185,9 +185,15 @@ void ZVision::initialize() { _searchManager->addDir("addon"); if (_gameDescription->gameId == GID_GRANDINQUISITOR) { - _searchManager->loadZix("INQUIS.ZIX"); - } else if (_gameDescription->gameId == GID_NEMESIS) - _searchManager->loadZix("NEMESIS.ZIX"); + if (!_searchManager->loadZix("INQUIS.ZIX")) + error("Unable to load the game ZIX file"); + } else if (_gameDescription->gameId == GID_NEMESIS) { + if (!_searchManager->loadZix("NEMESIS.ZIX")) { + // The game might not be installed, try MEDIUM.ZIX instead + if (!_searchManager->loadZix("ZNEMSCR/MEDIUM.ZIX")) + error("Unable to load the game ZIX file"); + } + } initScreen(); -- cgit v1.2.3 From 913075df90307a5331870009e0b29bfc87103ef6 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 8 Jan 2015 01:44:06 +0200 Subject: ZVISION: Also handle paths in NEMESIS.ZIX for the DVD ver. of Nemesis --- engines/zvision/file/search_manager.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'engines') diff --git a/engines/zvision/file/search_manager.cpp b/engines/zvision/file/search_manager.cpp index 80792b07d8..9f709dd0a1 100644 --- a/engines/zvision/file/search_manager.cpp +++ b/engines/zvision/file/search_manager.cpp @@ -165,6 +165,11 @@ bool SearchManager::loadZix(const Common::String &name) { if (path[i] == '\\') path.setChar('/', i); + // Check if NEMESIS.ZIX/MEDIUM.ZIX refers to the znemesis folder, and + // check the game root folder instead + if (path.hasPrefix("znemesis/")) + path = Common::String(path.c_str() + 9); + // Check if INQUIS.ZIX refers to the ZGI folder, and check the game // root folder instead if (path.hasPrefix("zgi/")) -- cgit v1.2.3 From 9e1510e715465db8930d8d241bdad2ca6020326d Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 9 Jan 2015 00:37:16 +0200 Subject: ZVISION: Provide a better description for the double FPS game option --- engines/zvision/detection.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/zvision/detection.cpp b/engines/zvision/detection.cpp index 66152403cf..0385a0fd99 100644 --- a/engines/zvision/detection.cpp +++ b/engines/zvision/detection.cpp @@ -175,7 +175,7 @@ static const ADExtraGuiOptionsMap optionsList[] = { GAMEOPTION_DOUBLE_FPS, { _s("Double FPS"), - _s("Halve the update delay"), + _s("Increase game FPS from 30 to 60"), "doublefps", false } -- cgit v1.2.3 From 345b33d9f0ea971e0ca69f1165d9d3b69d67984c Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 9 Jan 2015 00:38:15 +0200 Subject: ZVISION: Remove dead code --- engines/zvision/file/save_manager.cpp | 27 --------------------------- engines/zvision/file/save_manager.h | 1 - 2 files changed, 28 deletions(-) (limited to 'engines') diff --git a/engines/zvision/file/save_manager.cpp b/engines/zvision/file/save_manager.cpp index 042fafd38e..022b08884f 100644 --- a/engines/zvision/file/save_manager.cpp +++ b/engines/zvision/file/save_manager.cpp @@ -162,33 +162,6 @@ Common::Error SaveManager::loadGame(uint slot) { return Common::kNoError; } -Common::Error SaveManager::loadGame(const Common::String &saveName) { - Common::File *saveFile = _engine->getSearchManager()->openFile(saveName); - if (saveFile == NULL) { - saveFile = new Common::File; - if (!saveFile->open(saveName)) { - delete saveFile; - return Common::kPathDoesNotExist; - } - } - - // Read the header - SaveGameHeader header; - if (!readSaveGameHeader(saveFile, header)) { - return Common::kUnknownError; - } - - ScriptManager *scriptManager = _engine->getScriptManager(); - // Update the state table values - scriptManager->deserialize(saveFile); - - delete saveFile; - if (header.thumbnail) - delete header.thumbnail; - - return Common::kNoError; -} - bool SaveManager::readSaveGameHeader(Common::InSaveFile *in, SaveGameHeader &header) { uint32 tag = in->readUint32BE(); // Check if it's original savegame than fill header structure diff --git a/engines/zvision/file/save_manager.h b/engines/zvision/file/save_manager.h index fc8db67566..516d0e75cd 100644 --- a/engines/zvision/file/save_manager.h +++ b/engines/zvision/file/save_manager.h @@ -93,7 +93,6 @@ public: * @param slot The save slot to load. Must be [1, 20] */ Common::Error loadGame(uint slot); - Common::Error loadGame(const Common::String &saveName); Common::SeekableReadStream *getSlotFile(uint slot); bool readSaveGameHeader(Common::SeekableReadStream *in, SaveGameHeader &header); -- cgit v1.2.3 From 79b92fe04698d3336f1d5232d4701133ff3ac10c Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 9 Jan 2015 01:09:53 +0200 Subject: ZVISION: Clean up save logic, and fix a thumbnail-related FIXME This fixes the save game thumbnails when using the original save/load screens --- engines/zvision/detection.cpp | 2 +- engines/zvision/file/save_manager.cpp | 59 ++++++++++------------ engines/zvision/file/save_manager.h | 9 ++-- .../zvision/scripting/controls/save_control.cpp | 4 +- 4 files changed, 32 insertions(+), 42 deletions(-) (limited to 'engines') diff --git a/engines/zvision/detection.cpp b/engines/zvision/detection.cpp index 0385a0fd99..1295f76705 100644 --- a/engines/zvision/detection.cpp +++ b/engines/zvision/detection.cpp @@ -261,7 +261,7 @@ Common::Error ZVision::ZVision::loadGameState(int slot) { } Common::Error ZVision::ZVision::saveGameState(int slot, const Common::String &desc) { - _saveManager->saveGame(slot, desc); + _saveManager->saveGame(slot, desc, false); return Common::kNoError; } diff --git a/engines/zvision/file/save_manager.cpp b/engines/zvision/file/save_manager.cpp index 022b08884f..fb9cceecbe 100644 --- a/engines/zvision/file/save_manager.cpp +++ b/engines/zvision/file/save_manager.cpp @@ -69,7 +69,7 @@ bool SaveManager::scummVMSaveLoadDialog(bool isSave) { return false; if (isSave) { - saveGame(slot, desc); + saveGame(slot, desc, false); return true; } else { Common::ErrorCode result = loadGame(slot).getCode(); @@ -77,46 +77,34 @@ bool SaveManager::scummVMSaveLoadDialog(bool isSave) { } } -void SaveManager::saveGame(uint slot, const Common::String &saveName) { - Common::SaveFileManager *saveFileManager = g_system->getSavefileManager(); - Common::OutSaveFile *file = saveFileManager->openForSaving(_engine->generateSaveFileName(slot)); - - writeSaveGameHeader(file, saveName); +void SaveManager::saveGame(uint slot, const Common::String &saveName, bool useSaveBuffer) { + if (!_tempSave && useSaveBuffer) + return; - _engine->getScriptManager()->serialize(file); - - file->finalize(); - delete file; - - _lastSaveTime = g_system->getMillis(); -} - -void SaveManager::saveGame(uint slot, const Common::String &saveName, Common::MemoryWriteStreamDynamic *stream) { Common::SaveFileManager *saveFileManager = g_system->getSavefileManager(); Common::OutSaveFile *file = saveFileManager->openForSaving(_engine->generateSaveFileName(slot)); - writeSaveGameHeader(file, saveName); + writeSaveGameHeader(file, saveName, useSaveBuffer); - file->write(stream->getData(), stream->size()); + if (useSaveBuffer) + file->write(_tempSave->getData(), _tempSave->size()); + else + _engine->getScriptManager()->serialize(file); file->finalize(); delete file; - _lastSaveTime = g_system->getMillis(); -} - -void SaveManager::saveGameBuffered(uint slot, const Common::String &saveName) { - if (_tempSave) { - saveGame(slot, saveName, _tempSave); + if (useSaveBuffer) flushSaveBuffer(); - } + + _lastSaveTime = g_system->getMillis(); } void SaveManager::autoSave() { - saveGame(0, "Auto save"); + saveGame(0, "Auto save", false); } -void SaveManager::writeSaveGameHeader(Common::OutSaveFile *file, const Common::String &saveName) { +void SaveManager::writeSaveGameHeader(Common::OutSaveFile *file, const Common::String &saveName, bool useSaveBuffer) { file->writeUint32BE(SAVEGAME_ID); // Write version @@ -126,8 +114,11 @@ void SaveManager::writeSaveGameHeader(Common::OutSaveFile *file, const Common::S file->writeString(saveName); file->writeByte(0); - // Create a thumbnail and save it - Graphics::saveThumbnail(*file); + // Save the game thumbnail + if (useSaveBuffer) + file->write(_tempThumbnail->getData(), _tempThumbnail->size()); + else + Graphics::saveThumbnail(*file); // Write out the save date/time TimeDate td; @@ -245,18 +236,20 @@ Common::SeekableReadStream *SaveManager::getSlotFile(uint slot) { } void SaveManager::prepareSaveBuffer() { - if (_tempSave) - delete _tempSave; + delete _tempThumbnail; + _tempThumbnail = new Common::MemoryWriteStreamDynamic; + Graphics::saveThumbnail(*_tempThumbnail); + delete _tempSave; _tempSave = new Common::MemoryWriteStreamDynamic; - _engine->getScriptManager()->serialize(_tempSave); } void SaveManager::flushSaveBuffer() { - if (_tempSave) - delete _tempSave; + delete _tempThumbnail; + _tempThumbnail = NULL; + delete _tempSave; _tempSave = NULL; } diff --git a/engines/zvision/file/save_manager.h b/engines/zvision/file/save_manager.h index 516d0e75cd..d3f6aaaedc 100644 --- a/engines/zvision/file/save_manager.h +++ b/engines/zvision/file/save_manager.h @@ -48,7 +48,7 @@ struct SaveGameHeader { class SaveManager { public: - SaveManager(ZVision *engine) : _engine(engine), _tempSave(NULL), _lastSaveTime(0) {} + SaveManager(ZVision *engine) : _engine(engine), _tempSave(NULL), _tempThumbnail(NULL), _lastSaveTime(0) {} ~SaveManager() { flushSaveBuffer(); } @@ -67,6 +67,7 @@ private: SAVE_VERSION = 1 }; + Common::MemoryWriteStreamDynamic *_tempThumbnail; Common::MemoryWriteStreamDynamic *_tempSave; public: @@ -83,9 +84,7 @@ public: * @param slot The save slot this save pertains to. Must be [1, 20] * @param saveName The internal name for this save. This is NOT the name of the actual save file. */ - void saveGame(uint slot, const Common::String &saveName); - void saveGame(uint slot, const Common::String &saveName, Common::MemoryWriteStreamDynamic *stream); - void saveGameBuffered(uint slot, const Common::String &saveName); + void saveGame(uint slot, const Common::String &saveName, bool useSaveBuffer); /** * Loads the state data from the save file that slot references. Uses * ZVision::generateSaveFileName(slot) to get the save file name. @@ -101,7 +100,7 @@ public: void flushSaveBuffer(); bool scummVMSaveLoadDialog(bool isSave); private: - void writeSaveGameHeader(Common::OutSaveFile *file, const Common::String &saveName); + void writeSaveGameHeader(Common::OutSaveFile *file, const Common::String &saveName, bool useSaveBuffer); }; } // End of namespace ZVision diff --git a/engines/zvision/scripting/controls/save_control.cpp b/engines/zvision/scripting/controls/save_control.cpp index 6cedddffeb..2ac77c4776 100644 --- a/engines/zvision/scripting/controls/save_control.cpp +++ b/engines/zvision/scripting/controls/save_control.cpp @@ -102,9 +102,7 @@ bool SaveControl::process(uint32 deltaTimeInMillis) { toSave = false; if (toSave) { - // FIXME: At this point, the screen shows the save control, so the save game thumbnails will always - // show the save control - _engine->getSaveManager()->saveGameBuffered(iter->saveId, inp->getText()); + _engine->getSaveManager()->saveGame(iter->saveId, inp->getText(), true); _engine->getRenderManager()->delayedMessage(_engine->getStringManager()->getTextLine(StringManager::ZVISION_STR_SAVED), 2000); _engine->getScriptManager()->changeLocation(_engine->getScriptManager()->getLastMenuLocation()); } -- cgit v1.2.3 From c82480461cacab7893053d8e4821b3a6987552c9 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 10 Jan 2015 01:36:20 +0200 Subject: ZVISION: Make sure only existing files are dumped --- engines/zvision/core/console.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/zvision/core/console.cpp b/engines/zvision/core/console.cpp index 65821b1702..f39c06b57e 100644 --- a/engines/zvision/core/console.cpp +++ b/engines/zvision/core/console.cpp @@ -263,7 +263,8 @@ bool Console::cmdDumpFiles(int argc, const char **argv) { debugPrintf("Dumping %s\n", fileName.c_str()); in = iter->_value.arch->createReadStreamForMember(iter->_value.name); - dumpFile(in, fileName.c_str()); + if (in) + dumpFile(in, fileName.c_str()); delete in; } -- cgit v1.2.3 From 2d0075817ae6203063fb01f61b0828712e0259f0 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 10 Jan 2015 01:37:39 +0200 Subject: ZVISION: Remove unused variable --- engines/zvision/graphics/render_manager.h | 1 - 1 file changed, 1 deletion(-) (limited to 'engines') diff --git a/engines/zvision/graphics/render_manager.h b/engines/zvision/graphics/render_manager.h index c22f9a78c9..6081e982f9 100644 --- a/engines/zvision/graphics/render_manager.h +++ b/engines/zvision/graphics/render_manager.h @@ -106,7 +106,6 @@ private: // A buffer for subtitles Graphics::Surface _subtitleSurface; - Common::Rect _subtitleSurfaceDirtyRect; // Rectangle for subtitles area Common::Rect _subtitleArea; -- cgit v1.2.3 From 616b34e629686d7bfc3e5a74658c6a76b4a45c94 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 10 Jan 2015 17:30:11 +0200 Subject: ZVISION: Change wording --- engines/zvision/scripting/script_manager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/zvision/scripting/script_manager.cpp b/engines/zvision/scripting/script_manager.cpp index ba38d3a0e4..8220d5c37c 100644 --- a/engines/zvision/scripting/script_manager.cpp +++ b/engines/zvision/scripting/script_manager.cpp @@ -500,7 +500,7 @@ void ScriptManager::changeLocation(char _world, char _room, char _node, char _vi _nextLocation.node = _node; _nextLocation.view = _view; _nextLocation.offset = offset; - // If next location 0000 - it's indicate to go to previous location. + // If next location is 0000, return to the previous location. if (_nextLocation.world == '0' && _nextLocation.room == '0' && _nextLocation.node == '0' && _nextLocation.view == '0') { if (getStateValue(StateKey_World) != 'g' || getStateValue(StateKey_Room) != 'j') { _nextLocation.world = getStateValue(StateKey_LastWorld); -- cgit v1.2.3 From 899cf4813c7e009e1dbee56be8ad10d20650cf10 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 10 Jan 2015 21:32:15 +0200 Subject: ZVISION: Change screen resolution for the hires DVD videos to 800x600 Also, this hooks up the MPEG-PS decoder, but only if libmpeg2 is compiled in. The DVD videos are still disabled until AC3 audio support is implemented. The hires DVD videos are encoded a 720x480 resolution, with double the frame rate of the lowres ones (29.97FPS up from 15FPS) --- engines/zvision/graphics/render_manager.cpp | 57 ++++++++++++++++++----------- engines/zvision/graphics/render_manager.h | 10 ++--- engines/zvision/scripting/actions.cpp | 50 ++++++++++++++++--------- engines/zvision/text/subtitles.cpp | 9 ++++- engines/zvision/text/subtitles.h | 2 +- engines/zvision/video/video.cpp | 8 +--- engines/zvision/zvision.cpp | 6 +++ engines/zvision/zvision.h | 40 +++++++++++--------- 8 files changed, 112 insertions(+), 70 deletions(-) (limited to 'engines') diff --git a/engines/zvision/graphics/render_manager.cpp b/engines/zvision/graphics/render_manager.cpp index a1cc8ac53c..4a43e09b07 100644 --- a/engines/zvision/graphics/render_manager.cpp +++ b/engines/zvision/graphics/render_manager.cpp @@ -42,28 +42,25 @@ namespace ZVision { RenderManager::RenderManager(ZVision *engine, uint32 windowWidth, uint32 windowHeight, const Common::Rect workingWindow, const Graphics::PixelFormat pixelFormat, bool doubleFPS) : _engine(engine), _system(engine->_system), - _workingWidth(workingWindow.width()), - _workingHeight(workingWindow.height()), - _screenCenterX(_workingWidth / 2), - _screenCenterY(_workingHeight / 2), + _screenCenterX(_workingWindow.width() / 2), + _screenCenterY(_workingWindow.height() / 2), _workingWindow(workingWindow), _pixelFormat(pixelFormat), _backgroundWidth(0), _backgroundHeight(0), _backgroundOffset(0), - _renderTable(_workingWidth, _workingHeight), - _doubleFPS(doubleFPS) { + _renderTable(_workingWindow.width(), _workingWindow.height()), + _doubleFPS(doubleFPS), + _subid(0) { - _backgroundSurface.create(_workingWidth, _workingHeight, _pixelFormat); - _effectSurface.create(_workingWidth, _workingHeight, _pixelFormat); - _warpedSceneSurface.create(_workingWidth, _workingHeight, _pixelFormat); + _backgroundSurface.create(_workingWindow.width(), _workingWindow.height(), _pixelFormat); + _effectSurface.create(_workingWindow.width(), _workingWindow.height(), _pixelFormat); + _warpedSceneSurface.create(_workingWindow.width(), _workingWindow.height(), _pixelFormat); _menuSurface.create(windowWidth, workingWindow.top, _pixelFormat); - _subtitleSurface.create(windowWidth, windowHeight - workingWindow.bottom, _pixelFormat); - + _menuArea = Common::Rect(0, 0, windowWidth, workingWindow.top); - _subtitleArea = Common::Rect(0, workingWindow.bottom, windowWidth, windowHeight); - _subid = 0; + initSubArea(windowWidth, windowHeight, workingWindow); } RenderManager::~RenderManager() { @@ -83,7 +80,7 @@ void RenderManager::renderSceneToScreen() { // If we have graphical effects, we apply them using a temporary buffer if (!_effects.empty()) { bool copied = false; - Common::Rect windowRect(_workingWidth, _workingHeight); + Common::Rect windowRect(_workingWindow.width(), _workingWindow.height()); for (EffectsList::iterator it = _effects.begin(); it != _effects.end(); it++) { Common::Rect rect = (*it)->getRegion(); @@ -121,7 +118,7 @@ void RenderManager::renderSceneToScreen() { if (!_backgroundSurfaceDirtyRect.isEmpty()) { _renderTable.mutateImage(&_warpedSceneSurface, in); out = &_warpedSceneSurface; - outWndDirtyRect = Common::Rect(_workingWidth, _workingHeight); + outWndDirtyRect = Common::Rect(_workingWindow.width(), _workingWindow.height()); } } else { out = in; @@ -590,7 +587,7 @@ void RenderManager::prepareBackground() { if (state == RenderTable::PANORAMA) { // Calculate the visible portion of the background - Common::Rect viewPort(_workingWidth, _workingHeight); + Common::Rect viewPort(_workingWindow.width(), _workingWindow.height()); viewPort.translate(-(_screenCenterX - _backgroundOffset), 0); Common::Rect drawRect = _backgroundDirtyRect; drawRect.clip(viewPort); @@ -635,7 +632,7 @@ void RenderManager::prepareBackground() { } } else if (state == RenderTable::TILT) { // Tilt doesn't allow wrapping, so we just do a simple clip - Common::Rect viewPort(_workingWidth, _workingHeight); + Common::Rect viewPort(_workingWindow.width(), _workingWindow.height()); viewPort.translate(0, -(_screenCenterY - _backgroundOffset)); Common::Rect drawRect = _backgroundDirtyRect; drawRect.clip(viewPort); @@ -655,7 +652,7 @@ void RenderManager::prepareBackground() { // Clear the dirty rect since everything is clean now _backgroundDirtyRect = Common::Rect(); - _backgroundSurfaceDirtyRect.clip(_workingWidth, _workingHeight); + _backgroundSurfaceDirtyRect.clip(_workingWindow.width(), _workingWindow.height()); } void RenderManager::clearMenuSurface() { @@ -687,6 +684,15 @@ void RenderManager::renderMenuToScreen() { } } +void RenderManager::initSubArea(uint32 windowWidth, uint32 windowHeight, const Common::Rect workingWindow) { + _workingWindow = workingWindow; + + _subtitleSurface.free(); + + _subtitleSurface.create(windowWidth, windowHeight - workingWindow.bottom, _pixelFormat); + _subtitleArea = Common::Rect(0, workingWindow.bottom, windowWidth, windowHeight); +} + uint16 RenderManager::createSubArea(const Common::Rect &area) { _subid++; @@ -791,8 +797,8 @@ Common::Rect RenderManager::transformBackgroundSpaceRectToScreenSpace(const Comm if (state == RenderTable::PANORAMA) { if (_backgroundOffset < _screenCenterX) { - Common::Rect rScreen(_screenCenterX + _backgroundOffset, _workingHeight); - Common::Rect lScreen(_workingWidth - rScreen.width(), _workingHeight); + Common::Rect rScreen(_screenCenterX + _backgroundOffset, _workingWindow.height()); + Common::Rect lScreen(_workingWindow.width() - rScreen.width(), _workingWindow.height()); lScreen.translate(_backgroundWidth - lScreen.width(), 0); lScreen.clip(src); rScreen.clip(src); @@ -802,8 +808,8 @@ Common::Rect RenderManager::transformBackgroundSpaceRectToScreenSpace(const Comm tmp.translate(_screenCenterX - _backgroundOffset, 0); } } else if (_backgroundWidth - _backgroundOffset < _screenCenterX) { - Common::Rect rScreen(_screenCenterX - (_backgroundWidth - _backgroundOffset), _workingHeight); - Common::Rect lScreen(_workingWidth - rScreen.width(), _workingHeight); + Common::Rect rScreen(_screenCenterX - (_backgroundWidth - _backgroundOffset), _workingWindow.height()); + Common::Rect lScreen(_workingWindow.width() - rScreen.width(), _workingWindow.height()); lScreen.translate(_backgroundWidth - lScreen.width(), 0); lScreen.clip(src); rScreen.clip(src); @@ -1172,4 +1178,11 @@ void RenderManager::rotateTo(int16 _toPos, int16 _time) { _engine->startClock(); } +void RenderManager::upscaleRect(Common::Rect &rect) { + rect.top = rect.top * HIRES_WINDOW_HEIGHT / WINDOW_HEIGHT; + rect.left = rect.left * HIRES_WINDOW_WIDTH / WINDOW_WIDTH; + rect.bottom = rect.bottom * HIRES_WINDOW_HEIGHT / WINDOW_HEIGHT; + rect.right = rect.right * HIRES_WINDOW_WIDTH / WINDOW_WIDTH; +} + } // End of namespace ZVision diff --git a/engines/zvision/graphics/render_manager.h b/engines/zvision/graphics/render_manager.h index 6081e982f9..e3cbbc34ce 100644 --- a/engines/zvision/graphics/render_manager.h +++ b/engines/zvision/graphics/render_manager.h @@ -73,12 +73,8 @@ private: * are given in this coordinate space. Also, all images are clipped to the * edges of this Rectangle */ - const Common::Rect _workingWindow; + Common::Rect _workingWindow; - // Width of the working window. Saved to prevent extraneous calls to _workingWindow.width() - const int _workingWidth; - // Height of the working window. Saved to prevent extraneous calls to _workingWindow.height() - const int _workingHeight; // Center of the screen in the x direction const int _screenCenterX; // Center of the screen in the y direction @@ -241,6 +237,8 @@ public: // Subtitles methods + void initSubArea(uint32 windowWidth, uint32 windowHeight, const Common::Rect workingWindow); + // Create subtitle area and return ID uint16 createSubArea(const Common::Rect &area); uint16 createSubArea(); @@ -334,6 +332,8 @@ public: void checkBorders(); void rotateTo(int16 to, int16 time); void updateRotation(); + + void upscaleRect(Common::Rect &rect); }; } // End of namespace ZVision diff --git a/engines/zvision/scripting/actions.cpp b/engines/zvision/scripting/actions.cpp index f60fdbb973..e3fc6fa549 100644 --- a/engines/zvision/scripting/actions.cpp +++ b/engines/zvision/scripting/actions.cpp @@ -912,7 +912,15 @@ ActionStreamVideo::ActionStreamVideo(ZVision *engine, int32 slotkey, const Commo bool ActionStreamVideo::execute() { Video::VideoDecoder *decoder; Common::Rect destRect = Common::Rect(_x1, _y1, _x2 + 1, _y2 + 1); + Common::String subname = _fileName; + subname.setChar('s', subname.size() - 3); + subname.setChar('u', subname.size() - 2); + subname.setChar('b', subname.size() - 1); + bool subtitleExists = _engine->getSearchManager()->hasFile(subname); + bool switchToHires = false; +// NOTE: We only show the hires MPEG2 videos when libmpeg2 is compiled in, +// otherwise we fall back to the lowres ones #ifdef USE_MPEG2 Common::String hiresFileName = _fileName; hiresFileName.setChar('d', hiresFileName.size() - 8); @@ -920,36 +928,44 @@ bool ActionStreamVideo::execute() { hiresFileName.setChar('o', hiresFileName.size() - 2); hiresFileName.setChar('b', hiresFileName.size() - 1); - if (_engine->getScriptManager()->getStateValue(StateKey_MPEGMovies) == 1 &&_engine->getSearchManager()->hasFile(hiresFileName)) - // TODO: Enable once VOB + AC3 support is implemented - //_fileName = hiresFileName; + if (_engine->getScriptManager()->getStateValue(StateKey_MPEGMovies) == 1 &&_engine->getSearchManager()->hasFile(hiresFileName)) { + // TODO: Enable once AC3 support is implemented + if (!_engine->getSearchManager()->hasFile(_fileName)) // Check for the regular video + return true; warning("The hires videos of the DVD version of ZGI aren't supported yet, using lowres"); -#endif - - Common::String subname = _fileName; - subname.setChar('s', subname.size() - 3); - subname.setChar('u', subname.size() - 2); - subname.setChar('b', subname.size() - 1); - + //_fileName = hiresFileName; + //switchToHires = true; + } else if (!_engine->getSearchManager()->hasFile(_fileName)) + return true; +#else if (!_engine->getSearchManager()->hasFile(_fileName)) return true; +#endif decoder = _engine->loadAnimation(_fileName); + Subtitle *sub = (subtitleExists) ? new Subtitle(_engine, subname, switchToHires) : NULL; _engine->getCursorManager()->showMouse(false); - Subtitle *sub = NULL; - - if (_engine->getSearchManager()->hasFile(subname)) - sub = new Subtitle(_engine, subname); + if (switchToHires) { + _engine->initHiresScreen(); + destRect = Common::Rect(40, -40, 760, 440); + Common::Rect workingWindow = _engine->_workingWindow; + workingWindow.translate(0, -40); + _engine->getRenderManager()->initSubArea(HIRES_WINDOW_WIDTH, HIRES_WINDOW_HEIGHT, workingWindow); + } _engine->playVideo(*decoder, destRect, _skippable, sub); - delete decoder; + + if (switchToHires) { + _engine->initScreen(); + _engine->getRenderManager()->initSubArea(WINDOW_WIDTH, WINDOW_HEIGHT, _engine->_workingWindow); + } _engine->getCursorManager()->showMouse(true); - if (sub) - delete sub; + delete decoder; + delete sub; return true; } diff --git a/engines/zvision/text/subtitles.cpp b/engines/zvision/text/subtitles.cpp index acf4c37c2f..d549e2a0c6 100644 --- a/engines/zvision/text/subtitles.cpp +++ b/engines/zvision/text/subtitles.cpp @@ -27,7 +27,7 @@ namespace ZVision { -Subtitle::Subtitle(ZVision *engine, const Common::String &subname) : +Subtitle::Subtitle(ZVision *engine, const Common::String &subname, bool upscaleToHires) : _engine(engine), _areaId(-1), _subId(-1) { @@ -44,6 +44,8 @@ Subtitle::Subtitle(ZVision *engine, const Common::String &subname) : int32 x1, y1, x2, y2; sscanf(str.c_str(), "%*[^:]:%d %d %d %d", &x1, &y1, &x2, &y2); Common::Rect rct = Common::Rect(x1, y1, x2, y2); + if (upscaleToHires) + _engine->getRenderManager()->upscaleRect(rct); _areaId = _engine->getRenderManager()->createSubArea(rct); } else if (str.matchString("*TextFile*", true)) { char filename[64]; @@ -67,6 +69,11 @@ Subtitle::Subtitle(ZVision *engine, const Common::String &subname) : int32 sb; if (sscanf(str.c_str(), "%*[^:]:(%d,%d)=%d", &st, &en, &sb) == 3) { if (sb <= (int32)_subs.size()) { + if (upscaleToHires) { + // Convert from 15FPS (AVI) to 29.97FPS (VOB) + st = st * 29.97 / 15; + en = en * 29.97 / 15; + } _subs[sb].start = st; _subs[sb].stop = en; } diff --git a/engines/zvision/text/subtitles.h b/engines/zvision/text/subtitles.h index c3da6583a4..329339be55 100644 --- a/engines/zvision/text/subtitles.h +++ b/engines/zvision/text/subtitles.h @@ -31,7 +31,7 @@ class ZVision; class Subtitle { public: - Subtitle(ZVision *engine, const Common::String &subname); + Subtitle(ZVision *engine, const Common::String &subname, bool upscaleToHires = false); ~Subtitle(); void process(int32 time); diff --git a/engines/zvision/video/video.cpp b/engines/zvision/video/video.cpp index 66a567abb2..d5ffbeb536 100644 --- a/engines/zvision/video/video.cpp +++ b/engines/zvision/video/video.cpp @@ -23,9 +23,7 @@ #include "common/scummsys.h" #include "common/system.h" #include "video/video_decoder.h" -// TODO: Enable once VOB + AC3 support is implemented -#if 0 -//#ifdef USE_MPEG2 +#ifdef USE_MPEG2 #include "video/mpegps_decoder.h" #endif #include "engines/util.h" @@ -50,9 +48,7 @@ Video::VideoDecoder *ZVision::loadAnimation(const Common::String &fileName) { animation = new RLFDecoder(); else if (tmpFileName.hasSuffix(".avi")) animation = new ZorkAVIDecoder(); -// TODO: Enable once VOB + AC3 support is implemented -#if 0 -//#ifdef USE_MPEG2 +#ifdef USE_MPEG2 else if (tmpFileName.hasSuffix(".vob")) animation = new Video::MPEGPSDecoder(); #endif diff --git a/engines/zvision/zvision.cpp b/engines/zvision/zvision.cpp index 5b6d63e869..b42906fef3 100644 --- a/engines/zvision/zvision.cpp +++ b/engines/zvision/zvision.cpp @@ -360,4 +360,10 @@ void ZVision::initScreen() { initGraphics(WINDOW_WIDTH, WINDOW_HEIGHT, true, &_screenPixelFormat); } +void ZVision::initHiresScreen() { + _renderManager->upscaleRect(_workingWindow); + + initGraphics(HIRES_WINDOW_WIDTH, HIRES_WINDOW_HEIGHT, true, &_screenPixelFormat); +} + } // End of namespace ZVision diff --git a/engines/zvision/zvision.h b/engines/zvision/zvision.h index a3bcb384d1..854cd77bb8 100644 --- a/engines/zvision/zvision.h +++ b/engines/zvision/zvision.h @@ -67,6 +67,27 @@ class TextRenderer; class Subtitle; class MidiManager; +enum { + WINDOW_WIDTH = 640, + WINDOW_HEIGHT = 480, + + HIRES_WINDOW_WIDTH = 800, + HIRES_WINDOW_HEIGHT = 600, + + // Zork nemesis working window sizes + ZNM_WORKING_WINDOW_WIDTH = 512, + ZNM_WORKING_WINDOW_HEIGHT = 320, + + // ZGI working window sizes + ZGI_WORKING_WINDOW_WIDTH = 640, + ZGI_WORKING_WINDOW_HEIGHT = 344, + + ROTATION_SCREEN_EDGE_OFFSET = 60, + MAX_ROTATION_SPEED = 400, // Pixels per second + + KEYBUF_SIZE = 20 +}; + class ZVision : public Engine { public: ZVision(OSystem *syst, const ZVisionGameDescription *gameDesc); @@ -83,24 +104,6 @@ public: const Graphics::PixelFormat _screenPixelFormat; private: - enum { - WINDOW_WIDTH = 640, - WINDOW_HEIGHT = 480, - - // Zork nemesis working window sizes - ZNM_WORKING_WINDOW_WIDTH = 512, - ZNM_WORKING_WINDOW_HEIGHT = 320, - - // ZGI working window sizes - ZGI_WORKING_WINDOW_WIDTH = 640, - ZGI_WORKING_WINDOW_HEIGHT = 344, - - ROTATION_SCREEN_EDGE_OFFSET = 60, - MAX_ROTATION_SPEED = 400, // Pixels per second - - KEYBUF_SIZE = 20 - }; - Console *_console; const ZVisionGameDescription *_gameDescription; @@ -195,6 +198,7 @@ public: } void initScreen(); + void initHiresScreen(); /** * Play a video until it is finished. This is a blocking call. It will call -- cgit v1.2.3 From 21e9007d80ee60e519896c330324e5e3a95f772f Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 10 Jan 2015 22:03:15 +0200 Subject: Revert "ZVISION: Remove ActionRestoreGame and loading of r.svr (restart slot)" This reverts commit 9f642074ba8e17aa23b01bcee82b2293fe84f8f1, as it broke the credits screen in ZGI. This has been rewritten to use the common save code --- engines/zvision/file/save_manager.cpp | 21 +++++++++++++++++---- engines/zvision/file/save_manager.h | 2 +- engines/zvision/scripting/actions.cpp | 19 ++++++++++++++++++- engines/zvision/scripting/actions.h | 9 +++++++++ engines/zvision/scripting/scr_file_handling.cpp | 4 ++-- engines/zvision/scripting/script_manager.cpp | 6 +----- engines/zvision/scripting/script_manager.h | 1 - 7 files changed, 48 insertions(+), 14 deletions(-) (limited to 'engines') diff --git a/engines/zvision/file/save_manager.cpp b/engines/zvision/file/save_manager.cpp index fb9cceecbe..5e96e4ab5e 100644 --- a/engines/zvision/file/save_manager.cpp +++ b/engines/zvision/file/save_manager.cpp @@ -130,12 +130,25 @@ void SaveManager::writeSaveGameHeader(Common::OutSaveFile *file, const Common::S file->writeSint16LE(td.tm_min); } -Common::Error SaveManager::loadGame(uint slot) { - Common::SeekableReadStream *saveFile = getSlotFile(slot); - if (saveFile == 0) { - return Common::kPathDoesNotExist; +Common::Error SaveManager::loadGame(int slot) { + Common::SeekableReadStream *saveFile = NULL; + + if (slot >= 0) { + saveFile = getSlotFile(slot); + } else { + Common::File *saveFile = _engine->getSearchManager()->openFile("r.svr"); + if (!saveFile) { + saveFile = new Common::File; + if (!saveFile->open("r.svr")) { + delete saveFile; + return Common::kPathDoesNotExist; + } + } } + if (!saveFile) + return Common::kPathDoesNotExist; + // Read the header SaveGameHeader header; if (!readSaveGameHeader(saveFile, header)) { diff --git a/engines/zvision/file/save_manager.h b/engines/zvision/file/save_manager.h index d3f6aaaedc..9e816373ea 100644 --- a/engines/zvision/file/save_manager.h +++ b/engines/zvision/file/save_manager.h @@ -91,7 +91,7 @@ public: * * @param slot The save slot to load. Must be [1, 20] */ - Common::Error loadGame(uint slot); + Common::Error loadGame(int slot); Common::SeekableReadStream *getSlotFile(uint slot); bool readSaveGameHeader(Common::SeekableReadStream *in, SaveGameHeader &header); diff --git a/engines/zvision/scripting/actions.cpp b/engines/zvision/scripting/actions.cpp index e3fc6fa549..e989478dd1 100644 --- a/engines/zvision/scripting/actions.cpp +++ b/engines/zvision/scripting/actions.cpp @@ -23,11 +23,12 @@ #include "common/scummsys.h" #include "video/video_decoder.h" +#include "zvision/scripting/actions.h" + #include "zvision/zvision.h" #include "zvision/scripting/script_manager.h" #include "zvision/graphics/render_manager.h" #include "zvision/file/save_manager.h" -#include "zvision/scripting/actions.h" #include "zvision/scripting/menu.h" #include "zvision/scripting/effects/timer_effect.h" #include "zvision/scripting/effects/music_effect.h" @@ -797,6 +798,22 @@ bool ActionRandom::execute() { return true; } +////////////////////////////////////////////////////////////////////////////// +// ActionRestoreGame +////////////////////////////////////////////////////////////////////////////// + +ActionRestoreGame::ActionRestoreGame(ZVision *engine, int32 slotkey, const Common::String &line) : + ResultAction(engine, slotkey) { + char buf[128]; + sscanf(line.c_str(), "%s", buf); + _fileName = Common::String(buf); +} + +bool ActionRestoreGame::execute() { + _engine->getSaveManager()->loadGame(-1); + return false; +} + ////////////////////////////////////////////////////////////////////////////// // ActionRotateTo ////////////////////////////////////////////////////////////////////////////// diff --git a/engines/zvision/scripting/actions.h b/engines/zvision/scripting/actions.h index c2350bc83a..8d43309b74 100644 --- a/engines/zvision/scripting/actions.h +++ b/engines/zvision/scripting/actions.h @@ -340,6 +340,15 @@ private: ValueSlot *_max; }; +class ActionRestoreGame : public ResultAction { +public: + ActionRestoreGame(ZVision *engine, int32 slotkey, const Common::String &line); + bool execute(); + +private: + Common::String _fileName; +}; + class ActionRotateTo : public ResultAction { public: ActionRotateTo(ZVision *engine, int32 slotkey, const Common::String &line); diff --git a/engines/zvision/scripting/scr_file_handling.cpp b/engines/zvision/scripting/scr_file_handling.cpp index 7856bf7b2e..b4da61a119 100644 --- a/engines/zvision/scripting/scr_file_handling.cpp +++ b/engines/zvision/scripting/scr_file_handling.cpp @@ -271,8 +271,8 @@ void ScriptManager::parseResults(Common::SeekableReadStream &stream, Common::Lis actionList.push_back(new ActionRegion(_engine, slot, args)); } else if (act.matchString("restore_game", true)) { // Only used by ZGI to load the restart game slot, r.svr. - _engine->getScriptManager()->reset(); - _engine->getScriptManager()->changeLocation('g', 'a', 'r', 'y', 0); + // Used by the credits screen. + actionList.push_back(new ActionRestoreGame(_engine, slot, args)); } else if (act.matchString("rotate_to", true)) { actionList.push_back(new ActionRotateTo(_engine, slot, args)); } else if (act.matchString("save_game", true)) { diff --git a/engines/zvision/scripting/script_manager.cpp b/engines/zvision/scripting/script_manager.cpp index 8220d5c37c..ad049434c3 100644 --- a/engines/zvision/scripting/script_manager.cpp +++ b/engines/zvision/scripting/script_manager.cpp @@ -686,7 +686,7 @@ void ScriptManager::serialize(Common::WriteStream *stream) { stream->writeSint16LE(getStateValue(i)); } -void ScriptManager::reset() { +void ScriptManager::deserialize(Common::SeekableReadStream *stream) { // Clear out the current table values _globalState.clear(); _globalStateFlags.clear(); @@ -706,10 +706,6 @@ void ScriptManager::reset() { _activeSideFx.clear(); _referenceTable.clear(); -} - -void ScriptManager::deserialize(Common::SeekableReadStream *stream) { - reset(); if (stream->readUint32BE() != MKTAG('Z', 'N', 'S', 'G') || stream->readUint32LE() != 4) { changeLocation('g', 'a', 'r', 'y', 0); diff --git a/engines/zvision/scripting/script_manager.h b/engines/zvision/scripting/script_manager.h index a05c112a18..f6201c3572 100644 --- a/engines/zvision/scripting/script_manager.h +++ b/engines/zvision/scripting/script_manager.h @@ -248,7 +248,6 @@ public: void serialize(Common::WriteStream *stream); void deserialize(Common::SeekableReadStream *stream); - void reset(); Location getCurrentLocation() const; Location getLastLocation(); -- cgit v1.2.3 From 5b3705660dd075ed249b3f18ef106e71f259af21 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 11 Jan 2015 04:51:07 +0200 Subject: ZVISION: Avoid using floating point math when upscaling subtitle timing Spotted by clone2727 --- engines/zvision/text/subtitles.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/zvision/text/subtitles.cpp b/engines/zvision/text/subtitles.cpp index d549e2a0c6..ffc9e2b808 100644 --- a/engines/zvision/text/subtitles.cpp +++ b/engines/zvision/text/subtitles.cpp @@ -71,8 +71,8 @@ Subtitle::Subtitle(ZVision *engine, const Common::String &subname, bool upscaleT if (sb <= (int32)_subs.size()) { if (upscaleToHires) { // Convert from 15FPS (AVI) to 29.97FPS (VOB) - st = st * 29.97 / 15; - en = en * 29.97 / 15; + st = st * 2997 / 1500; + en = en * 2997 / 1500; } _subs[sb].start = st; _subs[sb].stop = en; -- cgit v1.2.3 From 468a26be405f17de00186f51978b00f6b2406726 Mon Sep 17 00:00:00 2001 From: RichieSams Date: Sat, 10 Jan 2015 22:19:46 -0600 Subject: ZVISION: Add detection for Nemesis CD - German version CSCR.ZFS is the same between the German and the French versions. Therefore we added a detection entry using the language file NEMESIS.STR --- engines/zvision/detection.cpp | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/zvision/detection.cpp b/engines/zvision/detection.cpp index 1295f76705..545ebe35d4 100644 --- a/engines/zvision/detection.cpp +++ b/engines/zvision/detection.cpp @@ -82,7 +82,10 @@ static const ZVisionGameDescription gameDescriptions[] = { { "znemesis", 0, - AD_ENTRY1s("CSCR.ZFS", "f04113357b4748c13efcb58b4629887c", 2577873), + {{"CSCR.ZFS", 0, "f04113357b4748c13efcb58b4629887c", 2577873}, + {"NEMESIS.STR", 0, "333bcb17bbb7f57cae742fbbe44f56f3", 9219}, + AD_LISTEND + }, Common::FR_FRA, Common::kPlatformDOS, ADGF_NO_FLAGS, @@ -91,6 +94,23 @@ static const ZVisionGameDescription gameDescriptions[] = { GID_NEMESIS }, + { + // Zork Nemesis German version + { + "znemesis", + 0, + {{"CSCR.ZFS", 0, "f04113357b4748c13efcb58b4629887c", 2577873}, + {"NEMESIS.STR", 0, "3d1a12b907751653866cffc6d4dfb331", 9505}, + AD_LISTEND + }, + Common::DE_DEU, + Common::kPlatformDOS, + ADGF_NO_FLAGS, + GUIO4(GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_DOUBLE_FPS, GAMEOPTION_ENABLE_VENUS, GAMEOPTION_DISABLE_ANIM_WHILE_TURNING) + }, + GID_NEMESIS + }, + { // Zork Nemesis English demo version { -- cgit v1.2.3 From bc959e54dc96b702a0bddaef2b8fc006087c035a Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 11 Jan 2015 17:00:00 +0200 Subject: ZVISION: Build the engine by default --- engines/zvision/configure.engine | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/zvision/configure.engine b/engines/zvision/configure.engine index 02e31943af..38a5959995 100644 --- a/engines/zvision/configure.engine +++ b/engines/zvision/configure.engine @@ -1,3 +1,3 @@ # This file is included from the main "configure" script # add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps] -add_engine zvision "ZVision" no "" "" "freetype2 16bit" +add_engine zvision "ZVision" yes "" "" "freetype2 16bit" -- cgit v1.2.3 From d603fe32e4b94f6b5c9382eaf6725664b9d68a95 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sun, 11 Jan 2015 21:14:36 +0000 Subject: SCI: fix definition of GK1 police-sleep patch --- engines/sci/engine/script_patches.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp index 03cd1d06e9..c2a0b8b95d 100644 --- a/engines/sci/engine/script_patches.cpp +++ b/engines/sci/engine/script_patches.cpp @@ -562,12 +562,12 @@ static const uint16 gk1SignatureDay6PoliceSleep[] = { 0x34, SIG_UINT16(0x00dc), // ldi 220 0x65, SIG_ADDTOOFFSET(+1), // aTop cycles (1a for PC, 1c for Mac) 0x32, // jmp [end] - 0 + SIG_END }; static const uint16 gk1PatchDay6PoliceSleep[] = { PATCH_ADDTOOFFSET(+5), - 0x34, SIG_UINT16(0x002a), // ldi 42 + 0x34, PATCH_UINT16(0x002a), // ldi 42 0x65, PATCH_GETORIGINALBYTEADJUST(+9, +2), // aTop seconds (1c for PC, 1e for Mac) PATCH_END }; -- cgit v1.2.3 From 3f4c924c9e6b26260e06d385a71b874d32371903 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 12 Jan 2015 02:37:27 +0200 Subject: ZVISION: Check for all the required fonts before starting a game --- engines/zvision/text/truetype_font.cpp | 19 ------------------- engines/zvision/text/truetype_font.h | 19 +++++++++++++++++++ engines/zvision/zvision.cpp | 30 +++++++++++++++++++++++++++++- 3 files changed, 48 insertions(+), 20 deletions(-) (limited to 'engines') diff --git a/engines/zvision/text/truetype_font.cpp b/engines/zvision/text/truetype_font.cpp index 622a02a6a8..5cb09226e8 100644 --- a/engines/zvision/text/truetype_font.cpp +++ b/engines/zvision/text/truetype_font.cpp @@ -54,25 +54,6 @@ bool StyledTTFont::loadFont(const Common::String &fontName, int32 point, uint st } bool StyledTTFont::loadFont(const Common::String &fontName, int32 point) { - struct FontStyle { - const char *zorkFont; - const char *fontBase; - const char *freeFontBase; - const char *freeFontItalicName; - }; - - const FontStyle systemFonts[] = { - { "*times new roman*", "times", "FreeSerif", "Italic" }, - { "*times*", "times", "FreeSerif", "Italic" }, - { "*century schoolbook*", "censcbk", "FreeSerif", "Italic" }, - { "*garamond*", "gara", "FreeSerif", "Italic" }, - { "*courier new*", "cour", "FreeMono", "Oblique" }, - { "*courier*", "cour", "FreeMono", "Oblique" }, - { "*ZorkDeath*", "cour", "FreeMono", "Oblique" }, - { "*arial*", "arial", "FreeSans", "Oblique" }, - { "*ZorkNormal*", "arial", "FreeSans", "Oblique" }, - }; - Common::String newFontName; Common::String freeFontName; diff --git a/engines/zvision/text/truetype_font.h b/engines/zvision/text/truetype_font.h index b5fac4af8a..f63e09b1fc 100644 --- a/engines/zvision/text/truetype_font.h +++ b/engines/zvision/text/truetype_font.h @@ -34,6 +34,25 @@ struct Surface; namespace ZVision { +struct FontStyle { + const char *zorkFont; + const char *fontBase; + const char *freeFontBase; + const char *freeFontItalicName; +}; + +const FontStyle systemFonts[] = { + { "*times new roman*", "times", "FreeSerif", "Italic" }, + { "*times*", "times", "FreeSerif", "Italic" }, + { "*century schoolbook*", "censcbk", "FreeSerif", "Italic" }, + { "*garamond*", "gara", "FreeSerif", "Italic" }, + { "*courier new*", "cour", "FreeMono", "Oblique" }, + { "*courier*", "cour", "FreeMono", "Oblique" }, + { "*ZorkDeath*", "cour", "FreeMono", "Oblique" }, + { "*arial*", "arial", "FreeSans", "Oblique" }, + { "*ZorkNormal*", "arial", "FreeSans", "Oblique" }, +}; + class ZVision; // Styled TTF diff --git a/engines/zvision/zvision.cpp b/engines/zvision/zvision.cpp index b42906fef3..103839158a 100644 --- a/engines/zvision/zvision.cpp +++ b/engines/zvision/zvision.cpp @@ -243,8 +243,36 @@ Common::Error ZVision::run() { if (ConfMan.hasKey("save_slot")) _saveManager->loadGame(ConfMan.getInt("save_slot")); + bool foundAllFonts = true; + // Before starting, make absolutely sure that the user has copied the needed fonts - if (!Common::File::exists("arial.ttf") && !Common::File::exists("FreeSans.ttf") && !_searchManager->hasFile("arial.ttf") && !_searchManager->hasFile("FreeSans.ttf") ) { + for (int i = 0; i < ARRAYSIZE(systemFonts); i++) { + Common::String freeFontBoldItalic = Common::String("Bold") + systemFonts[i].freeFontItalicName; + + const char *fontSuffixes[4] = { "", "bd", "i", "bi" }; + const char *freeFontSuffixes[4] = { "", "Bold", systemFonts[i].freeFontItalicName, freeFontBoldItalic.c_str() }; + + for (int j = 0; j < 4; j++) { + Common::String fontName = systemFonts[i].fontBase; + fontName += fontSuffixes[j]; + fontName += ".ttf"; + + Common::String freeFontName = systemFonts[i].freeFontBase; + freeFontName += freeFontSuffixes[j]; + freeFontName += ".ttf"; + + if (!Common::File::exists(fontName) && !Common::File::exists(freeFontName) && + !_searchManager->hasFile(fontName) && !_searchManager->hasFile(freeFontName)) { + foundAllFonts = false; + break; + } + } + + if (!foundAllFonts) + break; + } + + if (!foundAllFonts) { GUI::MessageDialog dialog( "Before playing this game, you'll need to copy the required " "fonts into ScummVM's extras directory, or into the game directory. " -- cgit v1.2.3 From b247515c587e1b9da4765b7108ce2ae0321f13c5 Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Mon, 12 Jan 2015 06:47:12 +0100 Subject: ZVISION: Check eos() after reading from stream, not before This fixes stray character in ZGI game over screen, when it reads an empty line of text. --- engines/zvision/text/text.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/zvision/text/text.cpp b/engines/zvision/text/text.cpp index a5ed044424..e0501ae9c8 100644 --- a/engines/zvision/text/text.cpp +++ b/engines/zvision/text/text.cpp @@ -490,8 +490,10 @@ void TextRenderer::drawTxtInOneLine(const Common::String &text, Graphics::Surfac Common::String readWideLine(Common::SeekableReadStream &stream) { Common::String asciiString; - while (!stream.eos()) { + while (true) { uint32 value = stream.readUint16LE(); + if (stream.eos()) + break; // Check for CRLF if (value == 0x0A0D) { // Read in the extra NULL char -- cgit v1.2.3 From 1b829b95b42e1123c8079e8d7628307ba5a9103f Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 13 Jan 2015 03:07:53 +0200 Subject: ZVISION: Add support for Liberation Fonts These look better than the GNU FreeType fonts, and are thus preferred over them. Many thanks to eriktorbjorn for his work on the different fonts available Also, this commit cleans up the font style array, moving it back into the CPP file --- engines/zvision/text/truetype_font.cpp | 44 +++++++++++++++++++++++++++------- engines/zvision/text/truetype_font.h | 13 ++-------- engines/zvision/zvision.cpp | 31 ++++++++++++++++-------- 3 files changed, 59 insertions(+), 29 deletions(-) (limited to 'engines') diff --git a/engines/zvision/text/truetype_font.cpp b/engines/zvision/text/truetype_font.cpp index 5cb09226e8..9f4fbe797b 100644 --- a/engines/zvision/text/truetype_font.cpp +++ b/engines/zvision/text/truetype_font.cpp @@ -36,6 +36,22 @@ namespace ZVision { +const FontStyle systemFonts[] = { + { "*times new roman*", "times", "FreeSerif", "Italic", "LiberationSerif" }, + { "*times*", "times", "FreeSerif", "Italic", "LiberationSerif" }, + { "*century schoolbook*", "censcbk", "FreeSerif", "Italic", "LiberationSerif" }, + { "*garamond*", "gara", "FreeSerif", "Italic", "LiberationSerif" }, + { "*courier new*", "cour", "FreeMono", "Oblique", "LiberationMono" }, + { "*courier*", "cour", "FreeMono", "Oblique", "LiberationMono" }, + { "*ZorkDeath*", "cour", "FreeMono", "Oblique", "LiberationMono" }, + { "*arial*", "arial", "FreeSans", "Oblique", "LiberationSans" }, + { "*ZorkNormal*", "arial", "FreeSans", "Oblique", "LiberationSans" } +}; + +const FontStyle getSystemFont(int fontIndex) { + return systemFonts[fontIndex]; +} + StyledTTFont::StyledTTFont(ZVision *engine) { _engine = engine; _style = 0; @@ -56,26 +72,35 @@ bool StyledTTFont::loadFont(const Common::String &fontName, int32 point, uint st bool StyledTTFont::loadFont(const Common::String &fontName, int32 point) { Common::String newFontName; Common::String freeFontName; + Common::String liberationFontName; - for (int i = 0; i < ARRAYSIZE(systemFonts); i++) { - if (fontName.matchString(systemFonts[i].zorkFont, true)) { - newFontName = systemFonts[i].fontBase; - freeFontName = systemFonts[i].freeFontBase; + for (int i = 0; i < FONT_COUNT; i++) { + FontStyle curFont = getSystemFont(i); + if (fontName.matchString(curFont.zorkFont, true)) { + newFontName = curFont.fontBase; + freeFontName = curFont.freeFontBase; + liberationFontName = curFont.liberationFontBase; if ((_style & STTF_BOLD) && (_style & STTF_ITALIC)) { newFontName += "bi"; freeFontName += "Bold"; - freeFontName += systemFonts[i].freeFontItalicName; + freeFontName += curFont.freeFontItalicName; + liberationFontName += "-BoldItalic"; } else if (_style & STTF_BOLD) { newFontName += "bd"; freeFontName += "Bold"; + liberationFontName += "-Bold"; } else if (_style & STTF_ITALIC) { newFontName += "i"; - freeFontName += systemFonts[i].freeFontItalicName; + freeFontName += curFont.freeFontItalicName; + liberationFontName += "-Italic"; + } else { + liberationFontName += "-Regular"; } newFontName += ".ttf"; freeFontName += ".ttf"; + liberationFontName += ".ttf"; break; } } @@ -84,13 +109,16 @@ bool StyledTTFont::loadFont(const Common::String &fontName, int32 point) { debug("Could not identify font: %s. Reverting to Arial", fontName.c_str()); newFontName = "arial.ttf"; freeFontName = "FreeSans.ttf"; + liberationFontName = "LiberationSans-Regular.ttf"; } bool sharp = (_style & STTF_SHARP) == STTF_SHARP; Common::File file; - if (!file.open(newFontName) && !file.open(freeFontName) && !_engine->getSearchManager()->openFile(file, newFontName) && !_engine->getSearchManager()->openFile(file, freeFontName)) - error("Unable to open font file %s (free alternative: %s)", newFontName.c_str(), freeFontName.c_str()); + if (!file.open(newFontName) && !_engine->getSearchManager()->openFile(file, newFontName) && + !file.open(liberationFontName) && !_engine->getSearchManager()->openFile(file, liberationFontName) && + !file.open(freeFontName) && !_engine->getSearchManager()->openFile(file, freeFontName)) + error("Unable to open font file %s (Liberation Font alternative: %s, FreeFont alternative: %s)", newFontName.c_str(), liberationFontName.c_str(), freeFontName.c_str()); Graphics::Font *_newFont = Graphics::loadTTFFont(file, point, 60, (sharp ? Graphics::kTTFRenderModeMonochrome : Graphics::kTTFRenderModeNormal)); // 66 dpi for 640 x 480 on 14" display if (_newFont) { diff --git a/engines/zvision/text/truetype_font.h b/engines/zvision/text/truetype_font.h index f63e09b1fc..6fbb1f0504 100644 --- a/engines/zvision/text/truetype_font.h +++ b/engines/zvision/text/truetype_font.h @@ -39,19 +39,10 @@ struct FontStyle { const char *fontBase; const char *freeFontBase; const char *freeFontItalicName; + const char *liberationFontBase; }; -const FontStyle systemFonts[] = { - { "*times new roman*", "times", "FreeSerif", "Italic" }, - { "*times*", "times", "FreeSerif", "Italic" }, - { "*century schoolbook*", "censcbk", "FreeSerif", "Italic" }, - { "*garamond*", "gara", "FreeSerif", "Italic" }, - { "*courier new*", "cour", "FreeMono", "Oblique" }, - { "*courier*", "cour", "FreeMono", "Oblique" }, - { "*ZorkDeath*", "cour", "FreeMono", "Oblique" }, - { "*arial*", "arial", "FreeSans", "Oblique" }, - { "*ZorkNormal*", "arial", "FreeSans", "Oblique" }, -}; +#define FONT_COUNT 9 class ZVision; diff --git a/engines/zvision/zvision.cpp b/engines/zvision/zvision.cpp index 103839158a..f9973d2280 100644 --- a/engines/zvision/zvision.cpp +++ b/engines/zvision/zvision.cpp @@ -236,6 +236,8 @@ void ZVision::initialize() { getTimerManager()->installTimerProc(&fpsTimerCallback, 1000000, this, "zvisionFPS"); } +extern const FontStyle getSystemFont(int fontIndex); + Common::Error ZVision::run() { initialize(); @@ -246,23 +248,30 @@ Common::Error ZVision::run() { bool foundAllFonts = true; // Before starting, make absolutely sure that the user has copied the needed fonts - for (int i = 0; i < ARRAYSIZE(systemFonts); i++) { - Common::String freeFontBoldItalic = Common::String("Bold") + systemFonts[i].freeFontItalicName; + for (int i = 0; i < FONT_COUNT; i++) { + FontStyle curFont = getSystemFont(i); + Common::String freeFontBoldItalic = Common::String("Bold") + curFont.freeFontItalicName; const char *fontSuffixes[4] = { "", "bd", "i", "bi" }; - const char *freeFontSuffixes[4] = { "", "Bold", systemFonts[i].freeFontItalicName, freeFontBoldItalic.c_str() }; + const char *freeFontSuffixes[4] = { "", "Bold", curFont.freeFontItalicName, freeFontBoldItalic.c_str() }; + const char *liberationFontSuffixes[4] = { "-Regular", "-Bold", "-Italic", "-BoldItalic" }; for (int j = 0; j < 4; j++) { - Common::String fontName = systemFonts[i].fontBase; + Common::String fontName = curFont.fontBase; fontName += fontSuffixes[j]; fontName += ".ttf"; - Common::String freeFontName = systemFonts[i].freeFontBase; + Common::String freeFontName = curFont.freeFontBase; freeFontName += freeFontSuffixes[j]; freeFontName += ".ttf"; - if (!Common::File::exists(fontName) && !Common::File::exists(freeFontName) && - !_searchManager->hasFile(fontName) && !_searchManager->hasFile(freeFontName)) { + Common::String liberationFontName = curFont.liberationFontBase; + liberationFontName += liberationFontSuffixes[j]; + liberationFontName += ".ttf"; + + if (!Common::File::exists(fontName) && !_searchManager->hasFile(fontName) && + !Common::File::exists(liberationFontName) && !_searchManager->hasFile(liberationFontName) && + !Common::File::exists(freeFontName) && !_searchManager->hasFile(freeFontName)) { foundAllFonts = false; break; } @@ -278,9 +287,11 @@ Common::Error ZVision::run() { "fonts into ScummVM's extras directory, or into the game directory. " "On Windows, you'll need the following font files from the Windows " "font directory: Times New Roman, Century Schoolbook, Garamond, " - "Courier New and Arial. Alternatively, you can download the GNU " - "FreeFont package. You'll need all the fonts from that package, " - "i.e., FreeMono, FreeSans and FreeSerif." + "Courier New and Arial. Alternatively, you can download the " + "Liberation Fonts or the GNU FreeFont package. You'll need all the " + "fonts from the font package you choose, i.e., LiberationMono, " + "LiberationSans and LiberationSerif, or FreeMono, FreeSans and " + "FreeSerif respectively." ); dialog.runModal(); quitGame(); -- cgit v1.2.3 From 4b1cec62473c821cf0701a46f3989ff3c82990b9 Mon Sep 17 00:00:00 2001 From: Bastien Bouclet Date: Tue, 13 Jan 2015 15:47:30 +0100 Subject: ZVISION: Add detection for the French version of ZGI --- engines/zvision/detection.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'engines') diff --git a/engines/zvision/detection.cpp b/engines/zvision/detection.cpp index 545ebe35d4..82150a6489 100644 --- a/engines/zvision/detection.cpp +++ b/engines/zvision/detection.cpp @@ -139,6 +139,20 @@ static const ZVisionGameDescription gameDescriptions[] = { GID_GRANDINQUISITOR }, + { + // Zork Grand Inquisitor French CD version, reported by ulrichh on IRC + { + "zgi", + "CD", + AD_ENTRY1s("SCRIPTS.ZFS", "4d1ec4ade7ecc9ee9ec591d43ca3d213", 8338133), + Common::FR_FRA, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + GUIO3(GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_DOUBLE_FPS, GAMEOPTION_DISABLE_ANIM_WHILE_TURNING) + }, + GID_GRANDINQUISITOR + }, + { // Zork Grand Inquisitor English DVD version { -- cgit v1.2.3 From fb97e58886832f695c8cb217b1d8d4ee2d7958f0 Mon Sep 17 00:00:00 2001 From: RichieSams Date: Tue, 13 Jan 2015 19:53:38 -0600 Subject: ZVISION: Add support for German ZGI - CD version Fixes #6760 --- engines/zvision/detection.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'engines') diff --git a/engines/zvision/detection.cpp b/engines/zvision/detection.cpp index 82150a6489..c1592ff5a4 100644 --- a/engines/zvision/detection.cpp +++ b/engines/zvision/detection.cpp @@ -153,6 +153,20 @@ static const ZVisionGameDescription gameDescriptions[] = { GID_GRANDINQUISITOR }, + { + // Zork Grand Inquisitor German CD version, reported by breit in bug #6760 + { + "zgi", + "CD", + AD_ENTRY1s("SCRIPTS.ZFS", "b7ac7e331b9b7f884590b0b325b560c8", 8338133), + Common::DE_DEU, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + GUIO3(GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_DOUBLE_FPS, GAMEOPTION_DISABLE_ANIM_WHILE_TURNING) + }, + GID_GRANDINQUISITOR + }, + { // Zork Grand Inquisitor English DVD version { -- cgit v1.2.3 From 28e27ea1d94f1df4c8e68216c086cb57c396ccd8 Mon Sep 17 00:00:00 2001 From: RichieSams Date: Thu, 15 Jan 2015 00:31:39 -0600 Subject: ZVISION: Allow multiple sound effects to play at the same time This is the original behavior. This was noted in bug #6761. Specifically, the knocker on the door plays a sound whenever it is a the top of the bottom of the swing. By only allowing one sound effect to play at the same time, the knocker would only play once, even though it bounces at the bottom. --- engines/zvision/scripting/actions.cpp | 3 --- 1 file changed, 3 deletions(-) (limited to 'engines') diff --git a/engines/zvision/scripting/actions.cpp b/engines/zvision/scripting/actions.cpp index e989478dd1..3aab6d8830 100644 --- a/engines/zvision/scripting/actions.cpp +++ b/engines/zvision/scripting/actions.cpp @@ -486,9 +486,6 @@ ActionMusic::~ActionMusic() { } bool ActionMusic::execute() { - if (_engine->getScriptManager()->getSideFX(_slotKey)) - return true; - if (_midi) { _engine->getScriptManager()->addSideFX(new MusicMidiNode(_engine, _slotKey, _prog, _note, _volume)); } else { -- cgit v1.2.3 From 4f28cec6ac7ef68df373f6c1139a852150789851 Mon Sep 17 00:00:00 2001 From: RichieSams Date: Thu, 15 Jan 2015 00:37:39 -0600 Subject: ZVISION: Keep the hand cursor during lever movement We have to explicitly set the cursor each call otherwise the cursor will be reset to the idle cursor. Addresses part of bug #6761 --- engines/zvision/scripting/controls/lever_control.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'engines') diff --git a/engines/zvision/scripting/controls/lever_control.cpp b/engines/zvision/scripting/controls/lever_control.cpp index bef51f0e91..249c4c6f9b 100644 --- a/engines/zvision/scripting/controls/lever_control.cpp +++ b/engines/zvision/scripting/controls/lever_control.cpp @@ -236,6 +236,8 @@ bool LeverControl::onMouseMove(const Common::Point &screenSpacePos, const Common } } } + _engine->getCursorManager()->changeCursor(_cursor); + cursorWasChanged = true; } else if (_frameInfo[_currentFrame].hotspot.contains(backgroundImageSpacePos)) { _engine->getCursorManager()->changeCursor(_cursor); cursorWasChanged = true; -- cgit v1.2.3 From 89f233f4881589b925e871becbf3ec1b08db108e Mon Sep 17 00:00:00 2001 From: RichieSams Date: Thu, 15 Jan 2015 00:40:07 -0600 Subject: ZVISION: Set the state value for the lever position during user dragging Not just during the "returning" animation. Addresses part of bug #6761 --- engines/zvision/scripting/controls/lever_control.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines') diff --git a/engines/zvision/scripting/controls/lever_control.cpp b/engines/zvision/scripting/controls/lever_control.cpp index 249c4c6f9b..0f105b424c 100644 --- a/engines/zvision/scripting/controls/lever_control.cpp +++ b/engines/zvision/scripting/controls/lever_control.cpp @@ -232,6 +232,7 @@ bool LeverControl::onMouseMove(const Common::Point &screenSpacePos, const Common if (angle >= (int)iter->angle - ANGLE_DELTA && angle <= (int)iter->angle + ANGLE_DELTA) { _currentFrame = iter->toFrame; renderFrame(_currentFrame); + _engine->getScriptManager()->setStateValue(_key, _currentFrame); break; } } -- cgit v1.2.3 From 4287e2ebcaf2d78d5dd0d112ec8db4a8c916f6d1 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 16 Jan 2015 01:44:15 +0200 Subject: ZVISION: Allow empty sound streams. Fixes bugs #6762 and #6763 A regression from commit 07ad10babe --- engines/zvision/sound/zork_raw.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/zvision/sound/zork_raw.cpp b/engines/zvision/sound/zork_raw.cpp index 0ef5de2f55..7bdd4875fc 100644 --- a/engines/zvision/sound/zork_raw.cpp +++ b/engines/zvision/sound/zork_raw.cpp @@ -256,9 +256,9 @@ Audio::RewindableAudioStream *makeRawZorkStream(const Common::String &filePath, actualName.setChar('c', actualName.size() - 1); if (!engine->getSearchManager()->openFile(*file, actualName)) - error("File not found: %s", actualName.c_str()); + return NULL; } else if (!found && !isRaw) { - error("File not found: %s", actualName.c_str()); + return NULL; } // Get the file name -- cgit v1.2.3 From 11e429672e59f69a67820c937269026f651d4998 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 16 Jan 2015 01:52:24 +0200 Subject: ZVISION: Add detection for the Spanish version of ZGI (bug #6764) --- engines/zvision/detection.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'engines') diff --git a/engines/zvision/detection.cpp b/engines/zvision/detection.cpp index c1592ff5a4..b69eee000a 100644 --- a/engines/zvision/detection.cpp +++ b/engines/zvision/detection.cpp @@ -167,6 +167,20 @@ static const ZVisionGameDescription gameDescriptions[] = { GID_GRANDINQUISITOR }, + { + // Zork Grand Inquisitor Spanish CD version, reported by dianiu in bug #6764 + { + "zgi", + "CD", + AD_ENTRY1s("SCRIPTS.ZFS", "5cdc4b99c1134053af135aae71326fd1", 8338141), + Common::ES_ESP, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + GUIO3(GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_DOUBLE_FPS, GAMEOPTION_DISABLE_ANIM_WHILE_TURNING) + }, + GID_GRANDINQUISITOR + }, + { // Zork Grand Inquisitor English DVD version { -- cgit v1.2.3 From 3fe7c645ed11d57cc5f7e1da588fb43cfe1affa3 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 16 Jan 2015 03:43:42 +0200 Subject: ZVISION: Fix detection of Windows fonts --- engines/zvision/zvision.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'engines') diff --git a/engines/zvision/zvision.cpp b/engines/zvision/zvision.cpp index f9973d2280..3085a79de8 100644 --- a/engines/zvision/zvision.cpp +++ b/engines/zvision/zvision.cpp @@ -258,9 +258,18 @@ Common::Error ZVision::run() { for (int j = 0; j < 4; j++) { Common::String fontName = curFont.fontBase; + if (fontName == "censcbk" && j > 0) + fontName = "schlbk"; fontName += fontSuffixes[j]; fontName += ".ttf"; + if (fontName == "schlbkbd.ttf") + fontName = "schlbkb.ttf"; + if (fontName == "garabi.ttf") + continue; + if (fontName == "garai.ttf") + fontName = "garait.ttf"; + Common::String freeFontName = curFont.freeFontBase; freeFontName += freeFontSuffixes[j]; freeFontName += ".ttf"; -- cgit v1.2.3 From 9f00880aa40abb7584a007e10591ee5aa593ae7a Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 16 Jan 2015 14:08:15 +0200 Subject: ZVISION: Properly handle sounds reusing the same sound slot (bug #6761) This is based on Marisa-Chan's observations in commit 28e27ea1d9. Tested with both ZNEM and ZGI --- engines/zvision/scripting/actions.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'engines') diff --git a/engines/zvision/scripting/actions.cpp b/engines/zvision/scripting/actions.cpp index 3aab6d8830..ce6bd31ee4 100644 --- a/engines/zvision/scripting/actions.cpp +++ b/engines/zvision/scripting/actions.cpp @@ -486,6 +486,11 @@ ActionMusic::~ActionMusic() { } bool ActionMusic::execute() { + if (_engine->getScriptManager()->getSideFX(_slotKey)) { + _engine->getScriptManager()->killSideFx(_slotKey); + _engine->getScriptManager()->setStateValue(_slotKey, 2); + } + if (_midi) { _engine->getScriptManager()->addSideFX(new MusicMidiNode(_engine, _slotKey, _prog, _note, _volume)); } else { -- cgit v1.2.3 From 9c25e2eea0e257de67c8d8f8cbd3e114585ed72b Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 17 Jan 2015 10:57:51 -0500 Subject: MADS: Fix crash on exit after watching introduction twice --- engines/mads/sound.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'engines') diff --git a/engines/mads/sound.cpp b/engines/mads/sound.cpp index 1652550ba3..fbf217ba0c 100644 --- a/engines/mads/sound.cpp +++ b/engines/mads/sound.cpp @@ -62,6 +62,9 @@ SoundManager::~SoundManager() { void SoundManager::init(int sectionNumber) { assert(sectionNumber > 0 && sectionNumber < 10); + if (_driver != nullptr) + delete _driver; + switch (_vm->getGameID()) { case GType_RexNebular: switch (sectionNumber) { -- cgit v1.2.3 From b3c204e2ba5350b81690e48fb7a23accaf257d0a Mon Sep 17 00:00:00 2001 From: Fedor Date: Sat, 17 Jan 2015 19:24:21 +0300 Subject: ZVISION: made error messages more detailed --- engines/zvision/zvision.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/zvision/zvision.cpp b/engines/zvision/zvision.cpp index 3085a79de8..d50c7d53c4 100644 --- a/engines/zvision/zvision.cpp +++ b/engines/zvision/zvision.cpp @@ -186,12 +186,12 @@ void ZVision::initialize() { if (_gameDescription->gameId == GID_GRANDINQUISITOR) { if (!_searchManager->loadZix("INQUIS.ZIX")) - error("Unable to load the game ZIX file"); + error("Unable to load file INQUIS.ZIX"); } else if (_gameDescription->gameId == GID_NEMESIS) { if (!_searchManager->loadZix("NEMESIS.ZIX")) { // The game might not be installed, try MEDIUM.ZIX instead if (!_searchManager->loadZix("ZNEMSCR/MEDIUM.ZIX")) - error("Unable to load the game ZIX file"); + error("Unable to load the file ZNEMSCR/MEDIUM.ZIX"); } } -- cgit v1.2.3 From ccd0c63a7b91031c8a172a60634506a3c810554b Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 17 Jan 2015 12:23:41 -0500 Subject: MADS: Implement background scrolling in anim views --- engines/mads/animation.cpp | 2 +- engines/mads/menu_views.cpp | 25 +++++++++++++++++++++++++ engines/mads/menu_views.h | 3 +++ 3 files changed, 29 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mads/animation.cpp b/engines/mads/animation.cpp index 2b999fa305..469d42cc1b 100644 --- a/engines/mads/animation.cpp +++ b/engines/mads/animation.cpp @@ -41,7 +41,7 @@ void AAHeader::load(Common::SeekableReadStream *f) { _spritesIndex = f->readUint16LE(); _scrollPosition.x = f->readSint16LE(); _scrollPosition.y = f->readSint16LE(); - _scrollTicks = f->readUint32LE(); + _scrollTicks = f->readUint32LE() & 0xffff; f->skip(6); char buffer[FILENAME_SIZE]; diff --git a/engines/mads/menu_views.cpp b/engines/mads/menu_views.cpp index ee4268a650..b492d98125 100644 --- a/engines/mads/menu_views.cpp +++ b/engines/mads/menu_views.cpp @@ -484,6 +484,7 @@ AnimationView::AnimationView(MADSEngine *vm) : MenuView(vm) { _animFrameNumber = 0; _nextCyclingActive = false; _sceneInfo = SceneInfo::init(_vm); + _scrollFrameCtr = 0; load(); } @@ -549,6 +550,11 @@ void AnimationView::doFrame() { scene._cyclingActive = _nextCyclingActive; } + if (++_scrollFrameCtr >= _currentAnimation->_header._scrollTicks) { + _scrollFrameCtr = 0; + scroll(); + } + if (_currentAnimation) { ++scene._frameStartTime; _currentAnimation->update(); @@ -636,6 +642,21 @@ void AnimationView::loadNextResource() { scene.initPaletteAnimation(paletteCycles, _nextCyclingActive && !_vm->_game->_fx); } +void AnimationView::scroll() { + Scene &scene = _vm->_game->_scene; + Common::Point pt = _currentAnimation->_header._scrollPosition; + + if (pt.x != 0) { + scene._backgroundSurface.scrollX(pt.x); + scene._spriteSlots.fullRefresh(); + } + + if (pt.y != 0) { + scene._backgroundSurface.scrollY(pt.y); + scene._spriteSlots.fullRefresh(); + } +} + void AnimationView::scriptDone() { _breakFlag = true; _vm->_dialogs->_pendingDialog = DIALOG_MAIN_MENU; @@ -657,6 +678,10 @@ void AnimationView::processLines() { _currentLine += c; } + // Check for comment line + if (_currentLine.hasPrefix("#")) + continue; + // Process the line while (!_currentLine.empty()) { if (_currentLine.hasPrefix("-")) { diff --git a/engines/mads/menu_views.h b/engines/mads/menu_views.h index cc5a13006f..871c0d1d37 100644 --- a/engines/mads/menu_views.h +++ b/engines/mads/menu_views.h @@ -191,6 +191,7 @@ private: int _manualFrame2; int _animFrameNumber; bool _nextCyclingActive; + int _scrollFrameCtr; private: void load(); @@ -201,6 +202,8 @@ private: int getParameter(); void loadNextResource(); + + void scroll(); protected: virtual void display(); -- cgit v1.2.3 From 263c5924906b2fcb3303850ad919e158cb06e120 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 17 Jan 2015 23:37:59 +0200 Subject: ZVISION: Fix bug #6769 (the "Alchemical debacle" video in ZGI) --- engines/zvision/scripting/actions.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'engines') diff --git a/engines/zvision/scripting/actions.cpp b/engines/zvision/scripting/actions.cpp index ce6bd31ee4..758158817e 100644 --- a/engines/zvision/scripting/actions.cpp +++ b/engines/zvision/scripting/actions.cpp @@ -638,6 +638,13 @@ ActionPlayAnimation::ActionPlayAnimation(ZVision *engine, int32 slotkey, const C _mask = -1; _fileName = Common::String(fileName); + + // WORKAROUND for bug #6769, location me1g.scr (the "Alchemical debacle" + // video in ZGI). We only scale up by 2x, in AnimationEffect::process(), + // but the dimensions of the target frame are off by 2 pixels. We fix that + // here, so that the video can be scaled. + if (_fileName == "me1ga011.avi" && _y2 == 213) + _y2 = 215; } ActionPlayAnimation::~ActionPlayAnimation() { -- cgit v1.2.3 From 4ee29ef3a84186b79e00e3f50d3fb15e4c13d213 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 17 Jan 2015 16:46:57 -0500 Subject: MADS: Add loading of SpriteInfo frame numbers for scene background sprites --- engines/mads/scene_data.cpp | 5 +++-- engines/mads/scene_data.h | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/mads/scene_data.cpp b/engines/mads/scene_data.cpp index b5e219ed04..7233e42456 100644 --- a/engines/mads/scene_data.cpp +++ b/engines/mads/scene_data.cpp @@ -86,7 +86,8 @@ void ARTHeader::load(Common::SeekableReadStream *f, bool isV2) { void SceneInfo::SpriteInfo::load(Common::SeekableReadStream *f) { f->skip(3); _spriteSetIndex = f->readByte(); - f->skip(2); + _frameNumber = f->readSByte(); + f->skip(1); _position.x = f->readSint16LE(); _position.y = f->readSint16LE(); _depth = f->readByte(); @@ -263,7 +264,7 @@ void SceneInfo::load(int sceneId, int variant, const Common::String &resName, SpriteAsset *asset = spriteSets[si._spriteSetIndex]; assert(asset && _depthStyle != 2); - MSprite *spr = asset->getFrame(asset->getCount() - 1); + MSprite *spr = asset->getFrame(si._frameNumber); bgSurface.copyFrom(spr, si._position, si._depth, &depthSurface, si._scale, spr->getTransparencyIndex()); } diff --git a/engines/mads/scene_data.h b/engines/mads/scene_data.h index 41e094b8f5..41a08f74eb 100644 --- a/engines/mads/scene_data.h +++ b/engines/mads/scene_data.h @@ -144,6 +144,7 @@ class SceneInfo { public: int _spriteSetIndex; Common::Point _position; + int _frameNumber; int _depth; int _scale; -- cgit v1.2.3 From 9b8fa20c7610567475c5b41678d41fa618adc49e Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 17 Jan 2015 17:29:08 -0500 Subject: MADS: Fix horizontal flipping of scene background sprites --- engines/mads/scene_data.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mads/scene_data.cpp b/engines/mads/scene_data.cpp index 7233e42456..d0e96be1d7 100644 --- a/engines/mads/scene_data.cpp +++ b/engines/mads/scene_data.cpp @@ -266,7 +266,7 @@ void SceneInfo::load(int sceneId, int variant, const Common::String &resName, MSprite *spr = asset->getFrame(si._frameNumber); bgSurface.copyFrom(spr, si._position, si._depth, &depthSurface, - si._scale, spr->getTransparencyIndex()); + si._scale, false, spr->getTransparencyIndex()); } // Free the sprite sets -- cgit v1.2.3 From 926404bd10309e98d353acd5515c678234de28aa Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 17 Jan 2015 20:51:52 -0500 Subject: MADS: Renamings of Layer and a transition type --- engines/mads/dialogs.cpp | 2 +- engines/mads/game.cpp | 4 ++-- engines/mads/hotspots.cpp | 2 +- engines/mads/nebular/dialogs_nebular.cpp | 8 ++++---- engines/mads/nebular/menu_nebular.cpp | 4 ++-- engines/mads/scene.cpp | 2 +- engines/mads/scene.h | 2 +- engines/mads/screen.cpp | 20 ++++++++++---------- engines/mads/screen.h | 10 +++++----- engines/mads/user_interface.cpp | 14 +++++++------- 10 files changed, 34 insertions(+), 34 deletions(-) (limited to 'engines') diff --git a/engines/mads/dialogs.cpp b/engines/mads/dialogs.cpp index 5e38f34fc6..c02f027302 100644 --- a/engines/mads/dialogs.cpp +++ b/engines/mads/dialogs.cpp @@ -449,7 +449,7 @@ void FullScreenDialog::display() { } // Set Fx state and palette entries - game._fx = _vm->_screenFade == SCREEN_FADE_SMOOTH ? kTransitionFadeIn : kCenterVertTransition; + game._fx = _vm->_screenFade == SCREEN_FADE_SMOOTH ? kTransitionFadeIn : kNullPaletteCopy; game._trigger = 0; // Clear the screen and draw the upper and lower horizontal lines diff --git a/engines/mads/game.cpp b/engines/mads/game.cpp index 94653f9a39..0ce24daf7a 100644 --- a/engines/mads/game.cpp +++ b/engines/mads/game.cpp @@ -240,7 +240,7 @@ void Game::sectionLoop() { _fx = kTransitionFadeOutIn; break; case SCREEN_FADE_FAST: - _fx = kCenterVertTransition; + _fx = kNullPaletteCopy; break; default: _fx = kTransitionNone; @@ -324,7 +324,7 @@ void Game::initSection(int sectionNumber) { _vm->_palette->resetGamePalette(18, 10); _vm->_palette->setLowRange(); - if (_scene._layer == LAYER_GUI) + if (_scene._mode == SCREENMODE_VGA) _vm->_palette->setPalette(_vm->_palette->_mainPalette, 0, 4); _vm->_events->loadCursors("*CURSOR.SS"); diff --git a/engines/mads/hotspots.cpp b/engines/mads/hotspots.cpp index d75d7ae13e..2af421a112 100644 --- a/engines/mads/hotspots.cpp +++ b/engines/mads/hotspots.cpp @@ -137,7 +137,7 @@ void DynamicHotspots::refresh() { switch (scrObjects._inputMode) { case kInputBuildingSentences: case kInputLimitedSentences: - scrObjects.add(dh._bounds, _vm->_game->_scene._layer, CAT_12, dh._descId); + scrObjects.add(dh._bounds, _vm->_game->_scene._mode, CAT_12, dh._descId); scrObjects._forceRescan = true; break; default: diff --git a/engines/mads/nebular/dialogs_nebular.cpp b/engines/mads/nebular/dialogs_nebular.cpp index f5355517bd..74da378128 100644 --- a/engines/mads/nebular/dialogs_nebular.cpp +++ b/engines/mads/nebular/dialogs_nebular.cpp @@ -643,14 +643,14 @@ void GameDialog::setClickableLines() { int maxHeight = _lines[idx]._font->getHeight(); screenObjects.add(Common::Rect(pt.x, pt.y, pt.x + strWidth, pt.y + maxHeight - 1), - LAYER_GUI, CAT_COMMAND, idx); + SCREENMODE_VGA, CAT_COMMAND, idx); } } if (_vm->_dialogs->_pendingDialog == DIALOG_SAVE || _vm->_dialogs->_pendingDialog == DIALOG_RESTORE) { - screenObjects.add(Common::Rect(293, 26, 312, 75), LAYER_GUI, CAT_INV_LIST, 50); - screenObjects.add(Common::Rect(293, 78, 312, 127), LAYER_GUI, CAT_INV_LIST, 51); + screenObjects.add(Common::Rect(293, 26, 312, 75), SCREENMODE_VGA, CAT_INV_LIST, 50); + screenObjects.add(Common::Rect(293, 78, 312, 127), SCREENMODE_VGA, CAT_INV_LIST, 51); } } @@ -825,7 +825,7 @@ void GameDialog::handleEvents() { // Scan for objects in the dialog Common::Point mousePos = events.currentPos() - Common::Point(0, DIALOG_TOP); - int objIndex = screenObjects.scan(mousePos, LAYER_GUI); + int objIndex = screenObjects.scan(mousePos, SCREENMODE_VGA); if (_movedFlag) { int yp = mousePos.y; diff --git a/engines/mads/nebular/menu_nebular.cpp b/engines/mads/nebular/menu_nebular.cpp index 28de4e5650..2fdef3443d 100644 --- a/engines/mads/nebular/menu_nebular.cpp +++ b/engines/mads/nebular/menu_nebular.cpp @@ -86,7 +86,7 @@ void MainMenu::display() { frame0->_offset.y - frame0->h); screenObjects.add( Common::Rect(pt.x, pt.y + DIALOG_TOP, pt.x + frame0->w, - pt.y + frame0->h + DIALOG_TOP), LAYER_GUI, CAT_COMMAND, i); + pt.y + frame0->h + DIALOG_TOP), SCREENMODE_VGA, CAT_COMMAND, i); } // Set the cursor for when it's shown @@ -292,7 +292,7 @@ bool MainMenu::onEvent(Common::Event &event) { } int MainMenu::getHighlightedItem(const Common::Point &pt) { - return _vm->_game->_screenObjects.scan(pt, LAYER_GUI) - 1; + return _vm->_game->_screenObjects.scan(pt, SCREENMODE_VGA) - 1; } void MainMenu::unhighlightItem() { diff --git a/engines/mads/scene.cpp b/engines/mads/scene.cpp index d2b4b29622..ea3fe2c148 100644 --- a/engines/mads/scene.cpp +++ b/engines/mads/scene.cpp @@ -52,7 +52,7 @@ Scene::Scene(MADSEngine *vm) _activeAnimation = nullptr; _textSpacing = -1; _frameStartTime = 0; - _layer = LAYER_GUI; + _mode = SCREENMODE_VGA; _lookFlag = false; _bandsRange = 0; _scaleRange = 0; diff --git a/engines/mads/scene.h b/engines/mads/scene.h index 9fd99ad8e5..05053c3166 100644 --- a/engines/mads/scene.h +++ b/engines/mads/scene.h @@ -121,7 +121,7 @@ public: bool _reloadSceneFlag; Common::Point _posAdjust; uint32 _frameStartTime; - Layer _layer; + ScreenMode _mode; bool _lookFlag; Common::Point _customDest; Common::Array _paletteUsageF; diff --git a/engines/mads/screen.cpp b/engines/mads/screen.cpp index c9a0863d85..8552effd98 100644 --- a/engines/mads/screen.cpp +++ b/engines/mads/screen.cpp @@ -244,7 +244,7 @@ void DirtyAreas::reset() { ScreenObject::ScreenObject() { _category = CAT_NONE; _descId = 0; - _layer = 0; + _mode = 0; _active = false; } @@ -265,14 +265,12 @@ ScreenObjects::ScreenObjects(MADSEngine *vm) : _vm(vm) { _baseTime = 0; } -void ScreenObjects::add(const Common::Rect &bounds, Layer layer, ScrCategory category, int descId) { - //assert(size() < 100); - +void ScreenObjects::add(const Common::Rect &bounds, ScreenMode mode, ScrCategory category, int descId) { ScreenObject so; so._bounds = bounds; so._category = category; so._descId = descId; - so._layer = layer; + so._mode = mode; so._active = true; push_back(so); @@ -288,7 +286,7 @@ void ScreenObjects::check(bool scanFlag) { if ((_vm->_events->_mouseMoved || userInterface._scrollbarActive || _v8332A || _forceRescan) && scanFlag) { _category = CAT_NONE; - _selectedObject = scanBackwards(_vm->_events->currentPos(), LAYER_GUI); + _selectedObject = scanBackwards(_vm->_events->currentPos(), SCREENMODE_VGA); if (_selectedObject > 0) { ScreenObject &scrObject = (*this)[_selectedObject]; _category = (ScrCategory)(scrObject._category & 7); @@ -365,7 +363,7 @@ void ScreenObjects::check(bool scanFlag) { int ScreenObjects::scan(const Common::Point &pt, int layer) { for (uint i = 1; i <= size(); ++i) { ScreenObject &sObj = (*this)[i]; - if (sObj._active && sObj._bounds.contains(pt) && sObj._layer == layer) + if (sObj._active && sObj._bounds.contains(pt) && sObj._mode == layer) return i; } @@ -376,7 +374,7 @@ int ScreenObjects::scan(const Common::Point &pt, int layer) { int ScreenObjects::scanBackwards(const Common::Point &pt, int layer) { for (int i = (int)size(); i >= 1; --i) { ScreenObject &sObj = (*this)[i]; - if (sObj._active && sObj._bounds.contains(pt) && sObj._layer == layer) + if (sObj._active && sObj._bounds.contains(pt) && sObj._mode == layer) return i; } @@ -653,8 +651,10 @@ void ScreenSurface::transition(ScreenTransition transitionType, bool surfaceFlag transition(kTransitionFadeIn, surfaceFlag); break; - case kCenterVertTransition: - warning("TODO: center vert transition"); + case kNullPaletteCopy: + // Original temporarily set the palette to black, copied the scene to the + // screen, and then restored the palette. We can give a similiar effect + // by doing a standard quick palette fade in transition(kTransitionFadeIn, surfaceFlag); break; diff --git a/engines/mads/screen.h b/engines/mads/screen.h index 9d01ca82e3..6800523f92 100644 --- a/engines/mads/screen.h +++ b/engines/mads/screen.h @@ -33,8 +33,8 @@ namespace MADS { #define MADS_SCREEN_WIDTH 320 #define MADS_SCREEN_HEIGHT 200 -enum Layer { - LAYER_GUI = 19 +enum ScreenMode { + SCREENMODE_VGA = 19 }; enum ScreenTransition { @@ -47,7 +47,7 @@ enum ScreenTransition { kTransitionCircleIn3, kTransitionCircleIn4, kVertTransition1, kVertTransition2, kVertTransition3, kVertTransition4, kVertTransition5, kVertTransition6, - kVertTransition7, kCenterVertTransition + kVertTransition7, kNullPaletteCopy }; enum InputMode { @@ -130,7 +130,7 @@ public: Common::Rect _bounds; ScrCategory _category; int _descId; - int _layer; + int _mode; ScreenObject(); }; @@ -162,7 +162,7 @@ public: /** * Add a new item to the list */ - void add(const Common::Rect &bounds, Layer layer, ScrCategory category, int descId); + void add(const Common::Rect &bounds, ScreenMode mode, ScrCategory category, int descId); /** * Check objects on the screen diff --git a/engines/mads/user_interface.cpp b/engines/mads/user_interface.cpp index 1f8d5037bc..822460d549 100644 --- a/engines/mads/user_interface.cpp +++ b/engines/mads/user_interface.cpp @@ -673,7 +673,7 @@ void UserInterface::loadElements() { getBounds(CAT_INV_SCROLLER, idx, bounds); moveRect(bounds); - _vm->_game->_screenObjects.add(bounds, LAYER_GUI, CAT_INV_SCROLLER, idx); + _vm->_game->_screenObjects.add(bounds, SCREENMODE_VGA, CAT_INV_SCROLLER, idx); } // Set up actions @@ -682,7 +682,7 @@ void UserInterface::loadElements() { getBounds(CAT_COMMAND, idx, bounds); moveRect(bounds); - _vm->_game->_screenObjects.add(bounds, LAYER_GUI, CAT_COMMAND, idx); + _vm->_game->_screenObjects.add(bounds, SCREENMODE_VGA, CAT_COMMAND, idx); } // Set up inventory list @@ -691,7 +691,7 @@ void UserInterface::loadElements() { getBounds(CAT_INV_LIST, _inventoryTopIndex + idx, bounds); moveRect(bounds); - _vm->_game->_screenObjects.add(bounds, LAYER_GUI, CAT_INV_LIST, idx); + _vm->_game->_screenObjects.add(bounds, SCREENMODE_VGA, CAT_INV_LIST, idx); } // Set up the inventory vocab list @@ -700,12 +700,12 @@ void UserInterface::loadElements() { getBounds(CAT_INV_VOCAB, idx, bounds); moveRect(bounds); - _vm->_game->_screenObjects.add(bounds, LAYER_GUI, CAT_INV_VOCAB, idx); + _vm->_game->_screenObjects.add(bounds, SCREENMODE_VGA, CAT_INV_VOCAB, idx); } // Set up the inventory item picture _categoryIndexes[CAT_INV_ANIM - 1] = _vm->_game->_screenObjects.size() + 1; - _vm->_game->_screenObjects.add(Common::Rect(160, 159, 231, 194), LAYER_GUI, + _vm->_game->_screenObjects.add(Common::Rect(160, 159, 231, 194), SCREENMODE_VGA, CAT_INV_ANIM, 0); } @@ -714,7 +714,7 @@ void UserInterface::loadElements() { _categoryIndexes[CAT_HOTSPOT - 1] = _vm->_game->_screenObjects.size() + 1; for (int hotspotIdx = scene._hotspots.size() - 1; hotspotIdx >= 0; --hotspotIdx) { Hotspot &hs = scene._hotspots[hotspotIdx]; - _vm->_game->_screenObjects.add(hs._bounds, LAYER_GUI, CAT_HOTSPOT, hotspotIdx); + _vm->_game->_screenObjects.add(hs._bounds, SCREENMODE_VGA, CAT_HOTSPOT, hotspotIdx); } } @@ -725,7 +725,7 @@ void UserInterface::loadElements() { getBounds(CAT_TALK_ENTRY, idx, bounds); moveRect(bounds); - _vm->_game->_screenObjects.add(bounds, LAYER_GUI, CAT_TALK_ENTRY, idx); + _vm->_game->_screenObjects.add(bounds, SCREENMODE_VGA, CAT_TALK_ENTRY, idx); } } -- cgit v1.2.3 From 7c23eae1027d242c9169b791d99d5f22e3159816 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 18 Jan 2015 21:30:07 +0200 Subject: ZVISION: Fix path handling in case-sensitive file systems (bug #6775) A regression from commit d70503cc98. Thanks to wjp for bisecting. --- engines/zvision/file/search_manager.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'engines') diff --git a/engines/zvision/file/search_manager.cpp b/engines/zvision/file/search_manager.cpp index 9f709dd0a1..1ae1ff71ae 100644 --- a/engines/zvision/file/search_manager.cpp +++ b/engines/zvision/file/search_manager.cpp @@ -183,6 +183,16 @@ bool SearchManager::loadZix(const Common::String &name) { path.deleteChar(0); if (path.size() && path.hasSuffix("/")) path.deleteLastChar(); + + // Handle paths in case-sensitive file systems (bug #6775) + if (path.size()) { + for (Common::List::iterator it = _dirList.begin(); it != _dirList.end(); ++it) { + if (path.equalsIgnoreCase(*it)) { + path = *it; + break; + } + } + } if (path.matchString("*.zfs", true)) { arc = new ZfsArchive(path); -- cgit v1.2.3 From 3f66f28624812910834600d8a2cecb084dedea9f Mon Sep 17 00:00:00 2001 From: Sven Hesse Date: Sun, 18 Jan 2015 20:32:55 +0100 Subject: ZVISION: Remove trailing whitespace --- engines/zvision/core/console.cpp | 2 +- engines/zvision/core/events.cpp | 2 +- engines/zvision/file/save_manager.cpp | 2 +- engines/zvision/file/search_manager.cpp | 2 +- engines/zvision/graphics/render_manager.cpp | 4 ++-- engines/zvision/graphics/render_manager.h | 4 ++-- engines/zvision/scripting/scripting_effect.h | 2 +- engines/zvision/video/rlf_decoder.cpp | 2 +- engines/zvision/video/video.cpp | 2 +- engines/zvision/zvision.cpp | 2 +- 10 files changed, 12 insertions(+), 12 deletions(-) (limited to 'engines') diff --git a/engines/zvision/core/console.cpp b/engines/zvision/core/console.cpp index f39c06b57e..e54e986bd7 100644 --- a/engines/zvision/core/console.cpp +++ b/engines/zvision/core/console.cpp @@ -204,7 +204,7 @@ bool Console::cmdLocation(int argc, const char **argv) { Common::String scrFile = Common::String::format("%c%c%c%c.scr", curLocation.world, curLocation.room, curLocation.node, curLocation.view); debugPrintf("Current location: world '%c', room '%c', node '%c', view '%c', offset %d, script %s\n", curLocation.world, curLocation.room, curLocation.node, curLocation.view, curLocation.offset, scrFile.c_str()); - + if (argc != 6) { debugPrintf("Use %s to change your location\n", argv[0]); return true; diff --git a/engines/zvision/core/events.cpp b/engines/zvision/core/events.cpp index 7804130e2a..4c7d395892 100644 --- a/engines/zvision/core/events.cpp +++ b/engines/zvision/core/events.cpp @@ -336,7 +336,7 @@ void ZVision::onMouseMove(const Common::Point &pos) { mspeed = 25; } _mouseVelocity = MIN(((Common::Rational(mspeed, ROTATION_SCREEN_EDGE_OFFSET) * (clippedPos.x - _workingWindow.left)) - mspeed).toInt(), -1); - + _cursorManager->changeCursor(CursorIndex_Left); cursorWasChanged = true; diff --git a/engines/zvision/file/save_manager.cpp b/engines/zvision/file/save_manager.cpp index 5e96e4ab5e..55be8d2530 100644 --- a/engines/zvision/file/save_manager.cpp +++ b/engines/zvision/file/save_manager.cpp @@ -132,7 +132,7 @@ void SaveManager::writeSaveGameHeader(Common::OutSaveFile *file, const Common::S Common::Error SaveManager::loadGame(int slot) { Common::SeekableReadStream *saveFile = NULL; - + if (slot >= 0) { saveFile = getSlotFile(slot); } else { diff --git a/engines/zvision/file/search_manager.cpp b/engines/zvision/file/search_manager.cpp index 1ae1ff71ae..821b85b053 100644 --- a/engines/zvision/file/search_manager.cpp +++ b/engines/zvision/file/search_manager.cpp @@ -183,7 +183,7 @@ bool SearchManager::loadZix(const Common::String &name) { path.deleteChar(0); if (path.size() && path.hasSuffix("/")) path.deleteLastChar(); - + // Handle paths in case-sensitive file systems (bug #6775) if (path.size()) { for (Common::List::iterator it = _dirList.begin(); it != _dirList.end(); ++it) { diff --git a/engines/zvision/graphics/render_manager.cpp b/engines/zvision/graphics/render_manager.cpp index 4a43e09b07..da6655b310 100644 --- a/engines/zvision/graphics/render_manager.cpp +++ b/engines/zvision/graphics/render_manager.cpp @@ -57,7 +57,7 @@ RenderManager::RenderManager(ZVision *engine, uint32 windowWidth, uint32 windowH _effectSurface.create(_workingWindow.width(), _workingWindow.height(), _pixelFormat); _warpedSceneSurface.create(_workingWindow.width(), _workingWindow.height(), _pixelFormat); _menuSurface.create(windowWidth, workingWindow.top, _pixelFormat); - + _menuArea = Common::Rect(0, 0, windowWidth, workingWindow.top); initSubArea(windowWidth, windowHeight, workingWindow); @@ -601,7 +601,7 @@ void RenderManager::prepareBackground() { _backgroundSurfaceDirtyRect = _backgroundDirtyRect; _backgroundSurfaceDirtyRect.translate(_screenCenterX - _backgroundOffset, 0); - // Panorama mode allows the user to spin in circles. Therefore, we need to render + // Panorama mode allows the user to spin in circles. Therefore, we need to render // the portion of the image that wrapped to the other side of the screen if (_backgroundOffset < _screenCenterX) { viewPort.moveTo(-(_screenCenterX - (_backgroundOffset + _backgroundWidth)), 0); diff --git a/engines/zvision/graphics/render_manager.h b/engines/zvision/graphics/render_manager.h index e3cbbc34ce..33d8a88e78 100644 --- a/engines/zvision/graphics/render_manager.h +++ b/engines/zvision/graphics/render_manager.h @@ -84,7 +84,7 @@ private: Graphics::Surface _currentBackgroundImage; Common::Rect _backgroundDirtyRect; - /** + /** * The x1 or y1 offset of the subRectangle of the background that is currently displayed on the screen * It will be x1 if PANORAMA, or y1 if TILT */ @@ -133,7 +133,7 @@ private: EffectsList _effects; bool _doubleFPS; - + public: void initialize(); diff --git a/engines/zvision/scripting/scripting_effect.h b/engines/zvision/scripting/scripting_effect.h index 0af1d9c21c..2a2153204f 100644 --- a/engines/zvision/scripting/scripting_effect.h +++ b/engines/zvision/scripting/scripting_effect.h @@ -37,7 +37,7 @@ class ZVision; * The base class that represents effects created from Actions. * This class is virtual. * - * Detailed Description: + * Detailed Description: * A scene has Controls. By interacting with the controls, the user * causes Actions to execute. Certain Actions create 'effects', for * example, a sound or an animation. This is the base class for diff --git a/engines/zvision/video/rlf_decoder.cpp b/engines/zvision/video/rlf_decoder.cpp index db598a25b6..040582bcf8 100644 --- a/engines/zvision/video/rlf_decoder.cpp +++ b/engines/zvision/video/rlf_decoder.cpp @@ -197,7 +197,7 @@ bool RLFDecoder::RLFVideoTrack::seek(const Audio::Timestamp &time) { const Graphics::Surface *RLFDecoder::RLFVideoTrack::decodeNextFrame() { if (_displayedFrame >= (int)_frameCount) return NULL; - + _displayedFrame++; applyFrameToCurrent(_displayedFrame); diff --git a/engines/zvision/video/video.cpp b/engines/zvision/video/video.cpp index d5ffbeb536..1cfd0f4197 100644 --- a/engines/zvision/video/video.cpp +++ b/engines/zvision/video/video.cpp @@ -62,7 +62,7 @@ Video::VideoDecoder *ZVision::loadAnimation(const Common::String &fileName) { bool loaded = animation->loadStream(_file); if (!loaded) error("Error loading animation %s", tmpFileName.c_str()); - + return animation; } diff --git a/engines/zvision/zvision.cpp b/engines/zvision/zvision.cpp index d50c7d53c4..da80ff9d02 100644 --- a/engines/zvision/zvision.cpp +++ b/engines/zvision/zvision.cpp @@ -251,7 +251,7 @@ Common::Error ZVision::run() { for (int i = 0; i < FONT_COUNT; i++) { FontStyle curFont = getSystemFont(i); Common::String freeFontBoldItalic = Common::String("Bold") + curFont.freeFontItalicName; - + const char *fontSuffixes[4] = { "", "bd", "i", "bi" }; const char *freeFontSuffixes[4] = { "", "Bold", curFont.freeFontItalicName, freeFontBoldItalic.c_str() }; const char *liberationFontSuffixes[4] = { "-Regular", "-Bold", "-Italic", "-BoldItalic" }; -- cgit v1.2.3 From a26a9c7268d27cb1f7407f5cf48038303f443197 Mon Sep 17 00:00:00 2001 From: RichieSams Date: Sun, 18 Jan 2015 17:06:24 -0600 Subject: ZVISION: Fix formatting and add curlies --- .../zvision/graphics/cursors/cursor_manager.cpp | 31 ++-- engines/zvision/scripting/script_manager.cpp | 196 +++++++++++++-------- 2 files changed, 141 insertions(+), 86 deletions(-) (limited to 'engines') diff --git a/engines/zvision/graphics/cursors/cursor_manager.cpp b/engines/zvision/graphics/cursors/cursor_manager.cpp index 1e048efedf..eeab18f4ba 100644 --- a/engines/zvision/graphics/cursors/cursor_manager.cpp +++ b/engines/zvision/graphics/cursors/cursor_manager.cpp @@ -124,31 +124,30 @@ void CursorManager::cursorDown(bool pushed) { } void CursorManager::changeCursor(int id) { - int _id = id; - - if (_item && - (_id == CursorIndex_Active || - _id == CursorIndex_Idle || - _id == CursorIndex_HandPu)) { - - if (_id == CursorIndex_Idle) - _id = CursorIndex_ItemIdle; - else - _id = CursorIndex_ItemAct; + if (_item && (id == CursorIndex_Active || + id == CursorIndex_Idle || + id == CursorIndex_HandPu)) { + if (id == CursorIndex_Idle) { + id = CursorIndex_ItemIdle; + } else { + id = CursorIndex_ItemAct; + } } - if (_currentCursor != _id || - ((_id == CursorIndex_ItemAct || _id == CursorIndex_ItemIdle) && _lastitem != _item)) { - _currentCursor = _id; + if (_currentCursor != id || ((id == CursorIndex_ItemAct || id == CursorIndex_ItemIdle) && _lastitem != _item)) { + _currentCursor = id; _lastitem = _item; changeCursor(_cursors[_currentCursor][_cursorIsPushed]); } } int CursorManager::getCursorId(const Common::String &name) { - for (int i = 0; i < NUM_CURSORS; i++) - if (name.equals(_cursorNames[i])) + for (int i = 0; i < NUM_CURSORS; i++) { + if (name.equals(_cursorNames[i])) { return i; + } + } + return CursorIndex_Idle; } diff --git a/engines/zvision/scripting/script_manager.cpp b/engines/zvision/scripting/script_manager.cpp index ad049434c3..4792a02045 100644 --- a/engines/zvision/scripting/script_manager.cpp +++ b/engines/zvision/scripting/script_manager.cpp @@ -72,21 +72,24 @@ void ScriptManager::initialize() { } void ScriptManager::update(uint deltaTimeMillis) { - if (_currentLocation.node != _nextLocation.node || - _currentLocation.room != _nextLocation.room || - _currentLocation.view != _nextLocation.view || - _currentLocation.world != _nextLocation.world) + if (_currentLocation.node != _nextLocation.node || _currentLocation.room != _nextLocation.room || + _currentLocation.view != _nextLocation.view || _currentLocation.world != _nextLocation.world) { ChangeLocationReal(); + } updateNodes(deltaTimeMillis); - if (! execScope(nodeview)) + if (! execScope(nodeview)) { return; - if (! execScope(room)) + } + if (! execScope(room)) { return; - if (! execScope(world)) + } + if (! execScope(world)) { return; - if (! execScope(universe)) + } + if (! execScope(universe)) { return; + } updateControls(deltaTimeMillis); } @@ -97,17 +100,22 @@ bool ScriptManager::execScope(ScriptScope &scope) { scope.scopeQueue = tmp; scope.scopeQueue->clear(); - for (PuzzleList::iterator PuzzleIter = scope.puzzles.begin(); PuzzleIter != scope.puzzles.end(); ++PuzzleIter) + for (PuzzleList::iterator PuzzleIter = scope.puzzles.begin(); PuzzleIter != scope.puzzles.end(); ++PuzzleIter) { (*PuzzleIter)->addedBySetState = false; + } if (scope.procCount < 2 || getStateValue(StateKey_ExecScopeStyle)) { - for (PuzzleList::iterator PuzzleIter = scope.puzzles.begin(); PuzzleIter != scope.puzzles.end(); ++PuzzleIter) - if (!checkPuzzleCriteria(*PuzzleIter, scope.procCount)) + for (PuzzleList::iterator PuzzleIter = scope.puzzles.begin(); PuzzleIter != scope.puzzles.end(); ++PuzzleIter) { + if (!checkPuzzleCriteria(*PuzzleIter, scope.procCount)) { return false; + } + } } else { - for (PuzzleList::iterator PuzzleIter = scope.execQueue->begin(); PuzzleIter != scope.execQueue->end(); ++PuzzleIter) - if (!checkPuzzleCriteria(*PuzzleIter, scope.procCount)) + for (PuzzleList::iterator PuzzleIter = scope.execQueue->begin(); PuzzleIter != scope.execQueue->end(); ++PuzzleIter) { + if (!checkPuzzleCriteria(*PuzzleIter, scope.procCount)) { return false; + } + } } if (scope.procCount < 2) { @@ -119,9 +127,11 @@ bool ScriptManager::execScope(ScriptScope &scope) { void ScriptManager::referenceTableAddPuzzle(uint32 key, PuzzleRef ref) { if (_referenceTable.contains(key)) { Common::Array *arr = &_referenceTable[key]; - for (uint32 i = 0; i < arr->size(); i++) - if ((*arr)[i].puz == ref.puz) + for (uint32 i = 0; i < arr->size(); i++) { + if ((*arr)[i].puz == ref.puz) { return; + } + } } _referenceTable[key].push_back(ref); @@ -139,9 +149,11 @@ void ScriptManager::addPuzzlesToReferenceTable(ScriptScope &scope) { referenceTableAddPuzzle(puzzlePtr->key, ref); // Iterate through each CriteriaEntry and add a reference from the criteria key to the Puzzle - for (Common::List >::iterator criteriaIter = (*PuzzleIter)->criteriaList.begin(); criteriaIter != (*PuzzleIter)->criteriaList.end(); ++criteriaIter) - for (Common::List::iterator entryIter = criteriaIter->begin(); entryIter != criteriaIter->end(); ++entryIter) + for (Common::List >::iterator criteriaIter = (*PuzzleIter)->criteriaList.begin(); criteriaIter != (*PuzzleIter)->criteriaList.end(); ++criteriaIter) { + for (Common::List::iterator entryIter = criteriaIter->begin(); entryIter != criteriaIter->end(); ++entryIter) { referenceTableAddPuzzle(entryIter->key, ref); + } + } } } @@ -159,8 +171,9 @@ void ScriptManager::updateNodes(uint deltaTimeMillis) { } void ScriptManager::updateControls(uint deltaTimeMillis) { - if (!_activeControls) + if (!_activeControls) { return; + } // Process only one event if (!_controlEvents.empty()) { @@ -187,9 +200,11 @@ void ScriptManager::updateControls(uint deltaTimeMillis) { _controlEvents.pop_front(); } - for (ControlList::iterator iter = _activeControls->begin(); iter != _activeControls->end(); iter++) - if ((*iter)->process(deltaTimeMillis)) + for (ControlList::iterator iter = _activeControls->begin(); iter != _activeControls->end(); iter++) { + if ((*iter)->process(deltaTimeMillis)) { break; + } + } } bool ScriptManager::checkPuzzleCriteria(Puzzle *puzzle, uint counter) { @@ -200,8 +215,9 @@ bool ScriptManager::checkPuzzleCriteria(Puzzle *puzzle, uint counter) { } // Check each Criteria - if (counter == 0 && (getStateFlag(puzzle->key) & Puzzle::DO_ME_NOW) == 0) + if (counter == 0 && (getStateFlag(puzzle->key) & Puzzle::DO_ME_NOW) == 0) { return true; + } bool criteriaMet = false; for (Common::List >::iterator criteriaIter = puzzle->criteriaList.begin(); criteriaIter != puzzle->criteriaList.end(); ++criteriaIter) { @@ -210,10 +226,11 @@ bool ScriptManager::checkPuzzleCriteria(Puzzle *puzzle, uint counter) { for (Common::List::iterator entryIter = criteriaIter->begin(); entryIter != criteriaIter->end(); ++entryIter) { // Get the value to compare against int argumentValue; - if (entryIter->argumentIsAKey) + if (entryIter->argumentIsAKey) { argumentValue = getStateValue(entryIter->argument); - else + } else { argumentValue = entryIter->argument; + } // Do the comparison switch (entryIter->criteriaOperator) { @@ -251,8 +268,9 @@ bool ScriptManager::checkPuzzleCriteria(Puzzle *puzzle, uint counter) { setStateValue(puzzle->key, 1); for (Common::List::iterator resultIter = puzzle->resultActions.begin(); resultIter != puzzle->resultActions.end(); ++resultIter) { - if (!(*resultIter)->execute()) + if (!(*resultIter)->execute()) { return false; + } } } @@ -275,13 +293,15 @@ void ScriptManager::cleanScriptScope(ScriptScope &scope) { scope.privQueueTwo.clear(); scope.scopeQueue = &scope.privQueueOne; scope.execQueue = &scope.privQueueTwo; - for (PuzzleList::iterator iter = scope.puzzles.begin(); iter != scope.puzzles.end(); ++iter) + for (PuzzleList::iterator iter = scope.puzzles.begin(); iter != scope.puzzles.end(); ++iter) { delete(*iter); + } scope.puzzles.clear(); - for (ControlList::iterator iter = scope.controls.begin(); iter != scope.controls.end(); ++iter) + for (ControlList::iterator iter = scope.controls.begin(); iter != scope.controls.end(); ++iter) { delete(*iter); + } scope.controls.clear(); @@ -289,44 +309,49 @@ void ScriptManager::cleanScriptScope(ScriptScope &scope) { } int ScriptManager::getStateValue(uint32 key) { - if (_globalState.contains(key)) + if (_globalState.contains(key)) { return _globalState[key]; - else + } else { return 0; + } } void ScriptManager::queuePuzzles(uint32 key) { if (_referenceTable.contains(key)) { Common::Array *arr = &_referenceTable[key]; - for (int32 i = arr->size() - 1; i >= 0; i--) + for (int32 i = arr->size() - 1; i >= 0; i--) { if (!(*arr)[i].puz->addedBySetState) { (*arr)[i].scope->scopeQueue->push_back((*arr)[i].puz); (*arr)[i].puz->addedBySetState = true; } + } } } void ScriptManager::setStateValue(uint32 key, int value) { - if (value == 0) + if (value == 0) { _globalState.erase(key); - else + } else { _globalState[key] = value; + } queuePuzzles(key); } void ScriptManager::setStateValueSilent(uint32 key, int value) { - if (value == 0) + if (value == 0) { _globalState.erase(key); - else + } else { _globalState[key] = value; + } } uint ScriptManager::getStateFlag(uint32 key) { - if (_globalStateFlags.contains(key)) + if (_globalStateFlags.contains(key)) { return _globalStateFlags[key]; - else + } else { return 0; + } } void ScriptManager::setStateFlag(uint32 key, uint value) { @@ -336,10 +361,11 @@ void ScriptManager::setStateFlag(uint32 key, uint value) { } void ScriptManager::setStateFlagSilent(uint32 key, uint value) { - if (value == 0) + if (value == 0) { _globalStateFlags.erase(key); - else + } else { _globalStateFlags[key] = value; + } } void ScriptManager::unsetStateFlag(uint32 key, uint value) { @@ -348,23 +374,29 @@ void ScriptManager::unsetStateFlag(uint32 key, uint value) { if (_globalStateFlags.contains(key)) { _globalStateFlags[key] &= ~value; - if (_globalStateFlags[key] == 0) + if (_globalStateFlags[key] == 0) { _globalStateFlags.erase(key); + } } } Control *ScriptManager::getControl(uint32 key) { - for (ControlList::iterator iter = _activeControls->begin(); iter != _activeControls->end(); ++iter) - if ((*iter)->getKey() == key) + for (ControlList::iterator iter = _activeControls->begin(); iter != _activeControls->end(); ++iter) { + if ((*iter)->getKey() == key) { return *iter; + } + } + return nullptr; } void ScriptManager::focusControl(uint32 key) { - if (!_activeControls) + if (!_activeControls) { return; - if (_currentlyFocusedControl == key) + } + if (_currentlyFocusedControl == key) { return; + } for (ControlList::iterator iter = _activeControls->begin(); iter != _activeControls->end(); ++iter) { uint32 controlKey = (*iter)->getKey(); @@ -443,50 +475,60 @@ void ScriptManager::killSideFxType(ScriptingEffect::ScriptingEffectType type) { } void ScriptManager::onMouseDown(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) { - if (!_activeControls) + if (!_activeControls) { return; + } for (ControlList::iterator iter = _activeControls->reverse_begin(); iter != _activeControls->end(); iter--) { - if ((*iter)->onMouseDown(screenSpacePos, backgroundImageSpacePos)) + if ((*iter)->onMouseDown(screenSpacePos, backgroundImageSpacePos)) { return; + } } } void ScriptManager::onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) { - if (!_activeControls) + if (!_activeControls) { return; + } for (ControlList::iterator iter = _activeControls->reverse_begin(); iter != _activeControls->end(); iter--) { - if ((*iter)->onMouseUp(screenSpacePos, backgroundImageSpacePos)) + if ((*iter)->onMouseUp(screenSpacePos, backgroundImageSpacePos)) { return; + } } } bool ScriptManager::onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) { - if (!_activeControls) + if (!_activeControls) { return false; + } for (ControlList::iterator iter = _activeControls->reverse_begin(); iter != _activeControls->end(); iter--) { - if ((*iter)->onMouseMove(screenSpacePos, backgroundImageSpacePos)) + if ((*iter)->onMouseMove(screenSpacePos, backgroundImageSpacePos)) { return true; + } } return false; } void ScriptManager::onKeyDown(Common::KeyState keyState) { - if (!_activeControls) + if (!_activeControls) { return; + } for (ControlList::iterator iter = _activeControls->begin(); iter != _activeControls->end(); ++iter) { - if ((*iter)->onKeyDown(keyState)) + if ((*iter)->onKeyDown(keyState)) { return; + } } } void ScriptManager::onKeyUp(Common::KeyState keyState) { - if (!_activeControls) + if (!_activeControls) { return; + } for (ControlList::iterator iter = _activeControls->begin(); iter != _activeControls->end(); ++iter) { - if ((*iter)->onKeyUp(keyState)) + if ((*iter)->onKeyUp(keyState)) { return; + } } } @@ -539,8 +581,9 @@ void ScriptManager::ChangeLocationReal() { _currentLocation.node = '0'; _currentLocation.view = '0'; _currentLocation.offset = 0; - } else + } else { return; + } } } @@ -563,12 +606,13 @@ void ScriptManager::ChangeLocationReal() { } if (_nextLocation.world == 'g' && _nextLocation.room == 'j') { - if (_nextLocation.node == 's' && _nextLocation.view == 'e' && - _currentLocation.world != 'g' && _currentLocation.room != 'j') + if (_nextLocation.node == 's' && _nextLocation.view == 'e' && _currentLocation.world != 'g' && _currentLocation.room != 'j') { _engine->getSaveManager()->prepareSaveBuffer(); + } } else { - if (_currentLocation.world == 'g' && _currentLocation.room == 'j') + if (_currentLocation.world == 'g' && _currentLocation.room == 'j') { _engine->getSaveManager()->flushSaveBuffer(); + } } setStateValue(StateKey_World, _nextLocation.world); @@ -664,26 +708,30 @@ void ScriptManager::serialize(Common::WriteStream *stream) { stream->writeByte(getStateValue(StateKey_View)); stream->writeUint32LE(getStateValue(StateKey_ViewPos)); - for (SideFXList::iterator iter = _activeSideFx.begin(); iter != _activeSideFx.end(); ++iter) + for (SideFXList::iterator iter = _activeSideFx.begin(); iter != _activeSideFx.end(); ++iter) { (*iter)->serialize(stream); + } stream->writeUint32BE(MKTAG('F', 'L', 'A', 'G')); int32 slots = 20000; - if (_engine->getGameId() == GID_NEMESIS) + if (_engine->getGameId() == GID_NEMESIS) { slots = 30000; + } stream->writeUint32LE(slots * 2); - for (int32 i = 0; i < slots; i++) + for (int32 i = 0; i < slots; i++) { stream->writeUint16LE(getStateFlag(i)); + } stream->writeUint32BE(MKTAG('P', 'U', 'Z', 'Z')); stream->writeUint32LE(slots * 2); - for (int32 i = 0; i < slots; i++) + for (int32 i = 0; i < slots; i++) { stream->writeSint16LE(getStateValue(i)); + } } void ScriptManager::deserialize(Common::SeekableReadStream *stream) { @@ -700,8 +748,9 @@ void ScriptManager::deserialize(Common::SeekableReadStream *stream) { _currentLocation.room = 0; _currentLocation.view = 0; - for (SideFXList::iterator iter = _activeSideFx.begin(); iter != _activeSideFx.end(); iter++) + for (SideFXList::iterator iter = _activeSideFx.begin(); iter != _activeSideFx.end(); iter++) { delete(*iter); + } _activeSideFx.clear(); @@ -734,20 +783,23 @@ void ScriptManager::deserialize(Common::SeekableReadStream *stream) { case MKTAG('T', 'I', 'M', 'R'): { uint32 key = stream->readUint32LE(); uint32 time = stream->readUint32LE(); - if (_engine->getGameId() == GID_GRANDINQUISITOR) + if (_engine->getGameId() == GID_GRANDINQUISITOR) { time /= 100; - else if (_engine->getGameId() == GID_NEMESIS) + } else if (_engine->getGameId() == GID_NEMESIS) { time /= 1000; + } addSideFX(new TimerNode(_engine, key, time)); } break; case MKTAG('F', 'L', 'A', 'G'): - for (uint32 i = 0; i < tagSize / 2; i++) + for (uint32 i = 0; i < tagSize / 2; i++) { setStateFlagSilent(i, stream->readUint16LE()); + } break; case MKTAG('P', 'U', 'Z', 'Z'): - for (uint32 i = 0; i < tagSize / 2; i++) + for (uint32 i = 0; i < tagSize / 2; i++) { setStateValueSilent(i, stream->readUint16LE()); + } break; default: stream->seek(tagSize, SEEK_CUR); @@ -801,10 +853,11 @@ void ScriptManager::flushEvent(Common::EventType type) { EventList::iterator it = _controlEvents.begin(); while (it != _controlEvents.end()) { - if ((*it).type == type) + if ((*it).type == type) { it = _controlEvents.erase(it); - else + } else { it++; + } } } @@ -833,12 +886,15 @@ ValueSlot::ValueSlot(ScriptManager *scriptManager, const char *slotValue): } int16 ValueSlot::getValue() { if (slot) { - if (value >= 0) + if (value >= 0) { return _scriptManager->getStateValue(value); - else + } + else { return 0; - } else + } + } else { return value; + } } } // End of namespace ZVision -- cgit v1.2.3 From b835eacc0cd401bb0d15a33e60d2ac47ebb4d718 Mon Sep 17 00:00:00 2001 From: RichieSams Date: Sun, 18 Jan 2015 19:26:49 -0600 Subject: ZVISION: Don't change location when coming back from ScummVM save dialog Fixes bug # 6771 We don't need to change locations, since we use the ScummVM save dialog instead of the original one (which is actually a location). Instead we just need to reset _nextLocation to _currentLocation so the engine can stop trying to save. If we change locations, the StateKey_LastWorld/Room/etc. end up being overwritten with the current room. So if a script refers to location 0, 0, 0, 0 (aka, the last room), the engine will try to change location to the same room. --- engines/zvision/scripting/script_manager.cpp | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'engines') diff --git a/engines/zvision/scripting/script_manager.cpp b/engines/zvision/scripting/script_manager.cpp index 4792a02045..a4ab4579b5 100644 --- a/engines/zvision/scripting/script_manager.cpp +++ b/engines/zvision/scripting/script_manager.cpp @@ -576,11 +576,8 @@ void ScriptManager::ChangeLocationReal() { _nextLocation.node = _currentLocation.node; _nextLocation.view = _currentLocation.view; _nextLocation.offset = _currentLocation.offset; - _currentLocation.world = '0'; - _currentLocation.room = '0'; - _currentLocation.node = '0'; - _currentLocation.view = '0'; - _currentLocation.offset = 0; + + return; } else { return; } @@ -743,11 +740,6 @@ void ScriptManager::deserialize(Common::SeekableReadStream *stream) { cleanScriptScope(room); cleanScriptScope(world); - _currentLocation.node = 0; - _currentLocation.world = 0; - _currentLocation.room = 0; - _currentLocation.view = 0; - for (SideFXList::iterator iter = _activeSideFx.begin(); iter != _activeSideFx.end(); iter++) { delete(*iter); } -- cgit v1.2.3 From 0fafb6a62c13f6f5a4ef6215a4be592ed84f248c Mon Sep 17 00:00:00 2001 From: RichieSams Date: Sun, 18 Jan 2015 20:11:10 -0600 Subject: Revert "ZVISION: Don't change location when coming back from ScummVM save dialog" This reverts commit b835eacc0cd401bb0d15a33e60d2ac47ebb4d718. --- engines/zvision/scripting/script_manager.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/zvision/scripting/script_manager.cpp b/engines/zvision/scripting/script_manager.cpp index a4ab4579b5..4792a02045 100644 --- a/engines/zvision/scripting/script_manager.cpp +++ b/engines/zvision/scripting/script_manager.cpp @@ -576,8 +576,11 @@ void ScriptManager::ChangeLocationReal() { _nextLocation.node = _currentLocation.node; _nextLocation.view = _currentLocation.view; _nextLocation.offset = _currentLocation.offset; - - return; + _currentLocation.world = '0'; + _currentLocation.room = '0'; + _currentLocation.node = '0'; + _currentLocation.view = '0'; + _currentLocation.offset = 0; } else { return; } @@ -740,6 +743,11 @@ void ScriptManager::deserialize(Common::SeekableReadStream *stream) { cleanScriptScope(room); cleanScriptScope(world); + _currentLocation.node = 0; + _currentLocation.world = 0; + _currentLocation.room = 0; + _currentLocation.view = 0; + for (SideFXList::iterator iter = _activeSideFx.begin(); iter != _activeSideFx.end(); iter++) { delete(*iter); } -- cgit v1.2.3 From 3a31e1de96a860b9f971cef939cb8a4aed8bcd5d Mon Sep 17 00:00:00 2001 From: RichieSams Date: Sun, 18 Jan 2015 20:22:02 -0600 Subject: ZVISION: Don't change location when coming back from ScummVM save dialog and do change location when coming back from restore dialog Fixes bug # 6771 We don't need to change locations, since we use the ScummVM save dialog instead of the original one (which is actually a location). Instead we just need to reset _nextLocation to _currentLocation so the engine can stop trying to save. If we change locations, the StateKey_LastWorld/Room/etc. end up being overwritten with the current room. So if a script refers to location 0, 0, 0, 0 (aka, the last room), the engine will try to change location to the same room. On restore, we have to force a location change, just in case we restore to the same room. (Since the logic will only do a location change if _nextLocation != _currentLocation) --- engines/zvision/scripting/script_manager.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/zvision/scripting/script_manager.cpp b/engines/zvision/scripting/script_manager.cpp index 4792a02045..b45f17a6f1 100644 --- a/engines/zvision/scripting/script_manager.cpp +++ b/engines/zvision/scripting/script_manager.cpp @@ -576,13 +576,14 @@ void ScriptManager::ChangeLocationReal() { _nextLocation.node = _currentLocation.node; _nextLocation.view = _currentLocation.view; _nextLocation.offset = _currentLocation.offset; - _currentLocation.world = '0'; + + return; + } else { + _currentLocation.world = 'g'; _currentLocation.room = '0'; _currentLocation.node = '0'; _currentLocation.view = '0'; _currentLocation.offset = 0; - } else { - return; } } } -- cgit v1.2.3 From 68b7839d994d536c7e65b3bfe5045ba164bbedd5 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 19 Jan 2015 05:09:03 +0200 Subject: ZVISION: Fix bug #6768 (unable to save in the prison area) The save buffer preparation code had a bug, which triggered in the jail area because its room is 'j' --- engines/zvision/scripting/script_manager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/zvision/scripting/script_manager.cpp b/engines/zvision/scripting/script_manager.cpp index b45f17a6f1..df74fd69dc 100644 --- a/engines/zvision/scripting/script_manager.cpp +++ b/engines/zvision/scripting/script_manager.cpp @@ -607,7 +607,7 @@ void ScriptManager::ChangeLocationReal() { } if (_nextLocation.world == 'g' && _nextLocation.room == 'j') { - if (_nextLocation.node == 's' && _nextLocation.view == 'e' && _currentLocation.world != 'g' && _currentLocation.room != 'j') { + if (_nextLocation.node == 's' && _nextLocation.view == 'e' && _currentLocation.world != 'g') { _engine->getSaveManager()->prepareSaveBuffer(); } } else { -- cgit v1.2.3 From 08b6a5b4865453e916709003e3a0b1a032b8e97e Mon Sep 17 00:00:00 2001 From: Fedor Date: Mon, 19 Jan 2015 23:25:40 +0300 Subject: ZVISION: Fix comparison between signed and unsigned integers --- engines/zvision/video/rlf_decoder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/zvision/video/rlf_decoder.cpp b/engines/zvision/video/rlf_decoder.cpp index 040582bcf8..3e11a70f27 100644 --- a/engines/zvision/video/rlf_decoder.cpp +++ b/engines/zvision/video/rlf_decoder.cpp @@ -169,7 +169,7 @@ bool RLFDecoder::RLFVideoTrack::seek(const Audio::Timestamp &time) { if (distance < 0) { for (uint i = 0; i < _completeFrames.size(); ++i) { - if ((int)_completeFrames[i] > frame) + if (_completeFrames[i] > frame) break; closestFrame = _completeFrames[i]; } -- cgit v1.2.3 From dcac5be493a98764239619d5da60d6bc0f608383 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 19 Jan 2015 23:52:08 +0200 Subject: ZVISION: Simplify the checks in the location changing code --- engines/zvision/scripting/script_manager.cpp | 42 ++++++++++++++-------------- 1 file changed, 21 insertions(+), 21 deletions(-) (limited to 'engines') diff --git a/engines/zvision/scripting/script_manager.cpp b/engines/zvision/scripting/script_manager.cpp index df74fd69dc..bcc1f0a5ff 100644 --- a/engines/zvision/scripting/script_manager.cpp +++ b/engines/zvision/scripting/script_manager.cpp @@ -564,12 +564,16 @@ void ScriptManager::ChangeLocationReal() { assert(_nextLocation.world != 0); debug(1, "Changing location to: %c %c %c %c %u", _nextLocation.world, _nextLocation.room, _nextLocation.node, _nextLocation.view, _nextLocation.offset); - if (_nextLocation.world == 'g' && _nextLocation.room == 'j' && !ConfMan.getBool("originalsaveload")) { - if ((_nextLocation.node == 's' || _nextLocation.node == 'r') && _nextLocation.view == 'e') { + const bool enteringMenu = (_nextLocation.world == 'g' && _nextLocation.room == 'j'); + const bool leavingMenu = (_currentLocation.world == 'g' && _currentLocation.room == 'j'); + const bool isSaveScreen = (enteringMenu && _nextLocation.node == 's' && _nextLocation.view == 'e'); + const bool isRestoreScreen = (enteringMenu && _nextLocation.node == 'r' && _nextLocation.view == 'e'); + + if (enteringMenu && !ConfMan.getBool("originalsaveload")) { + if (isSaveScreen || isRestoreScreen) { // Hook up the ScummVM save/restore dialog - bool isSave = (_nextLocation.node == 's'); - bool gameSavedOrLoaded = _engine->getSaveManager()->scummVMSaveLoadDialog(isSave); - if (!gameSavedOrLoaded || isSave) { + bool gameSavedOrLoaded = _engine->getSaveManager()->scummVMSaveLoadDialog(isSaveScreen); + if (!gameSavedOrLoaded || isSaveScreen) { // Reload the current room _nextLocation.world = _currentLocation.world; _nextLocation.room = _currentLocation.room; @@ -590,30 +594,26 @@ void ScriptManager::ChangeLocationReal() { _engine->setRenderDelay(2); - if (getStateValue(StateKey_World) != 'g' || getStateValue(StateKey_Room) != 'j') { - if (_nextLocation.world != 'g' || _nextLocation.room != 'j') { + if (!enteringMenu) { + if (!leavingMenu) { setStateValue(StateKey_LastWorld, getStateValue(StateKey_World)); setStateValue(StateKey_LastRoom, getStateValue(StateKey_Room)); setStateValue(StateKey_LastNode, getStateValue(StateKey_Node)); setStateValue(StateKey_LastView, getStateValue(StateKey_View)); setStateValue(StateKey_LastViewPos, getStateValue(StateKey_ViewPos)); - } else { - setStateValue(StateKey_Menu_LastWorld, getStateValue(StateKey_World)); - setStateValue(StateKey_Menu_LastRoom, getStateValue(StateKey_Room)); - setStateValue(StateKey_Menu_LastNode, getStateValue(StateKey_Node)); - setStateValue(StateKey_Menu_LastView, getStateValue(StateKey_View)); - setStateValue(StateKey_Menu_LastViewPos, getStateValue(StateKey_ViewPos)); } + } else { + setStateValue(StateKey_Menu_LastWorld, getStateValue(StateKey_World)); + setStateValue(StateKey_Menu_LastRoom, getStateValue(StateKey_Room)); + setStateValue(StateKey_Menu_LastNode, getStateValue(StateKey_Node)); + setStateValue(StateKey_Menu_LastView, getStateValue(StateKey_View)); + setStateValue(StateKey_Menu_LastViewPos, getStateValue(StateKey_ViewPos)); } - if (_nextLocation.world == 'g' && _nextLocation.room == 'j') { - if (_nextLocation.node == 's' && _nextLocation.view == 'e' && _currentLocation.world != 'g') { - _engine->getSaveManager()->prepareSaveBuffer(); - } - } else { - if (_currentLocation.world == 'g' && _currentLocation.room == 'j') { - _engine->getSaveManager()->flushSaveBuffer(); - } + if (isSaveScreen && !leavingMenu) { + _engine->getSaveManager()->prepareSaveBuffer(); + } else if (leavingMenu) { + _engine->getSaveManager()->flushSaveBuffer(); } setStateValue(StateKey_World, _nextLocation.world); -- cgit v1.2.3 From 5df2e08c1668c6649f7817688ce1ce198e563083 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 19 Jan 2015 23:54:07 +0200 Subject: ZVISION: Fix bug #6771 (unable to leave room when loading a game) Avoid overwriting the previous location when loading a saved game --- engines/zvision/scripting/script_manager.cpp | 8 ++++---- engines/zvision/scripting/script_manager.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/zvision/scripting/script_manager.cpp b/engines/zvision/scripting/script_manager.cpp index bcc1f0a5ff..34376cee5b 100644 --- a/engines/zvision/scripting/script_manager.cpp +++ b/engines/zvision/scripting/script_manager.cpp @@ -74,7 +74,7 @@ void ScriptManager::initialize() { void ScriptManager::update(uint deltaTimeMillis) { if (_currentLocation.node != _nextLocation.node || _currentLocation.room != _nextLocation.room || _currentLocation.view != _nextLocation.view || _currentLocation.world != _nextLocation.world) { - ChangeLocationReal(); + ChangeLocationReal(false); } updateNodes(deltaTimeMillis); @@ -560,7 +560,7 @@ void ScriptManager::changeLocation(char _world, char _room, char _node, char _vi } } -void ScriptManager::ChangeLocationReal() { +void ScriptManager::ChangeLocationReal(bool isLoading) { assert(_nextLocation.world != 0); debug(1, "Changing location to: %c %c %c %c %u", _nextLocation.world, _nextLocation.room, _nextLocation.node, _nextLocation.view, _nextLocation.offset); @@ -595,7 +595,7 @@ void ScriptManager::ChangeLocationReal() { _engine->setRenderDelay(2); if (!enteringMenu) { - if (!leavingMenu) { + if (!isLoading && !leavingMenu) { setStateValue(StateKey_LastWorld, getStateValue(StateKey_World)); setStateValue(StateKey_LastRoom, getStateValue(StateKey_Room)); setStateValue(StateKey_LastNode, getStateValue(StateKey_Node)); @@ -809,7 +809,7 @@ void ScriptManager::deserialize(Common::SeekableReadStream *stream) { _nextLocation = nextLocation; - ChangeLocationReal(); + ChangeLocationReal(true); _engine->setRenderDelay(10); setStateValue(StateKey_RestoreFlag, 1); diff --git a/engines/zvision/scripting/script_manager.h b/engines/zvision/scripting/script_manager.h index f6201c3572..6d025bf2e9 100644 --- a/engines/zvision/scripting/script_manager.h +++ b/engines/zvision/scripting/script_manager.h @@ -273,7 +273,7 @@ private: bool execScope(ScriptScope &scope); /** Perform change location */ - void ChangeLocationReal(); + void ChangeLocationReal(bool isLoading); int8 inventoryGetCount(); void inventorySetCount(int8 cnt); -- cgit v1.2.3 From 5f9858844a24b00e75ef2c504b2d68c189261dd2 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 20 Jan 2015 01:21:16 +0200 Subject: ZVISION: Fix saving when using the original save dialog A regression from commit dcac5be493 --- engines/zvision/scripting/script_manager.cpp | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'engines') diff --git a/engines/zvision/scripting/script_manager.cpp b/engines/zvision/scripting/script_manager.cpp index 34376cee5b..a4491103e6 100644 --- a/engines/zvision/scripting/script_manager.cpp +++ b/engines/zvision/scripting/script_manager.cpp @@ -594,26 +594,30 @@ void ScriptManager::ChangeLocationReal(bool isLoading) { _engine->setRenderDelay(2); - if (!enteringMenu) { - if (!isLoading && !leavingMenu) { + if (!leavingMenu) { + if (!isLoading && !enteringMenu) { setStateValue(StateKey_LastWorld, getStateValue(StateKey_World)); setStateValue(StateKey_LastRoom, getStateValue(StateKey_Room)); setStateValue(StateKey_LastNode, getStateValue(StateKey_Node)); setStateValue(StateKey_LastView, getStateValue(StateKey_View)); setStateValue(StateKey_LastViewPos, getStateValue(StateKey_ViewPos)); + } else { + setStateValue(StateKey_Menu_LastWorld, getStateValue(StateKey_World)); + setStateValue(StateKey_Menu_LastRoom, getStateValue(StateKey_Room)); + setStateValue(StateKey_Menu_LastNode, getStateValue(StateKey_Node)); + setStateValue(StateKey_Menu_LastView, getStateValue(StateKey_View)); + setStateValue(StateKey_Menu_LastViewPos, getStateValue(StateKey_ViewPos)); } - } else { - setStateValue(StateKey_Menu_LastWorld, getStateValue(StateKey_World)); - setStateValue(StateKey_Menu_LastRoom, getStateValue(StateKey_Room)); - setStateValue(StateKey_Menu_LastNode, getStateValue(StateKey_Node)); - setStateValue(StateKey_Menu_LastView, getStateValue(StateKey_View)); - setStateValue(StateKey_Menu_LastViewPos, getStateValue(StateKey_ViewPos)); } - if (isSaveScreen && !leavingMenu) { - _engine->getSaveManager()->prepareSaveBuffer(); - } else if (leavingMenu) { - _engine->getSaveManager()->flushSaveBuffer(); + if (enteringMenu) { + if (isSaveScreen && !leavingMenu) { + _engine->getSaveManager()->prepareSaveBuffer(); + } + } else { + if (leavingMenu) { + _engine->getSaveManager()->flushSaveBuffer(); + } } setStateValue(StateKey_World, _nextLocation.world); -- cgit v1.2.3 From 750d72812b36bfed3043080d633798854dc4008d Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 20 Jan 2015 02:16:21 +0200 Subject: ZVISION: Properly skip commented out puzzle criteria - fixes bug #6776 In the Zork: Nemesis version bundled in the ZGI SE DVD, the bell rope puzzle has been modified so that it's non-interactive, i.e. there isn't a hotspot to click while the video is playing, and the player is transported to the next room. In the patched script, all criteria of that puzzle were commented out, resulting in an invalid criteria list. Skip any commented out criteria, to avoid ending with an invalid list. --- engines/zvision/scripting/scr_file_handling.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'engines') diff --git a/engines/zvision/scripting/scr_file_handling.cpp b/engines/zvision/scripting/scr_file_handling.cpp index b4da61a119..277702d287 100644 --- a/engines/zvision/scripting/scr_file_handling.cpp +++ b/engines/zvision/scripting/scr_file_handling.cpp @@ -104,6 +104,13 @@ bool ScriptManager::parseCriteria(Common::SeekableReadStream &stream, Common::Li Common::String line = stream.readLine(); trimCommentsAndWhiteSpace(&line); + // Skip any commented out criteria. If all the criteria are commented out, + // we might end up with an invalid criteria list (bug #6776). + while (line.empty()) { + line = stream.readLine(); + trimCommentsAndWhiteSpace(&line); + } + // Criteria can be empty if (line.contains('}')) { return false; -- cgit v1.2.3 From ad83f033151ac6cf6345e6a83a0903ad6499c0ca Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Tue, 20 Jan 2015 19:21:39 +0100 Subject: ZVISION: Fix mis-parsing of criteria, a.k.a bug #6774 A condition in a criteria is made up of three tokens: An id, an operator and an id/value. However, in my copy of ZGI, puzzle:07507 has "[00202] !3 # SPELL_12_IN_BOOK", i.e. there was no space between the second and third tokens. This caused the "glorf" spell to not be properly inscribed in your spell book. To fix this, if the second token is more than one character we use the rest of it as the third token. --- engines/zvision/scripting/scr_file_handling.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/zvision/scripting/scr_file_handling.cpp b/engines/zvision/scripting/scr_file_handling.cpp index 277702d287..8f0f80e39e 100644 --- a/engines/zvision/scripting/scr_file_handling.cpp +++ b/engines/zvision/scripting/scr_file_handling.cpp @@ -141,9 +141,17 @@ bool ScriptManager::parseCriteria(Common::SeekableReadStream &stream, Common::Li else if (token.c_str()[0] == '<') entry.criteriaOperator = Puzzle::LESS_THAN; + // There are supposed to be three tokens, but there is no + // guarantee that there will be a space between the second and + // the third one (bug #6774) + if (token.size() == 1) { + token = tokenizer.nextToken(); + } else { + token.deleteChar(0); + } + // First determine if the last token is an id or a value // Then parse it into 'argument' - token = tokenizer.nextToken(); if (token.contains('[')) { sscanf(token.c_str(), "[%u]", &(entry.argument)); entry.argumentIsAKey = true; -- cgit v1.2.3 From 1d6a80734969d2475c7d97945a74225b12dae297 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 20 Jan 2015 05:19:44 +0200 Subject: ZVISION: Adapt confirmation dialogs for non-English versions --- engines/zvision/graphics/render_manager.cpp | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/zvision/graphics/render_manager.cpp b/engines/zvision/graphics/render_manager.cpp index da6655b310..a65117f2b5 100644 --- a/engines/zvision/graphics/render_manager.cpp +++ b/engines/zvision/graphics/render_manager.cpp @@ -989,14 +989,33 @@ bool RenderManager::askQuestion(const Common::String &str) { Common::Event evnt; while (_engine->getEventManager()->pollEvent(evnt)) { if (evnt.type == Common::EVENT_KEYDOWN) { + // English: yes/no + // German: ja/nein + // Spanish: si/no + // French: F4/any other key switch (evnt.kbd.keycode) { case Common::KEYCODE_y: - result = 2; + if (_engine->getLanguage() == Common::EN_ANY) + result = 2; + break; + case Common::KEYCODE_j: + if (_engine->getLanguage() == Common::DE_DEU) + result = 2; + break; + case Common::KEYCODE_s: + if (_engine->getLanguage() == Common::ES_ESP) + result = 2; + break; + case Common::KEYCODE_F4: + if (_engine->getLanguage() == Common::FR_FRA) + result = 2; break; case Common::KEYCODE_n: result = 1; break; default: + if (_engine->getLanguage() == Common::FR_FRA) + result = 1; break; } } -- cgit v1.2.3 From 0776709f3175da3ebca69f8a4866d4d98a1e9be9 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 21 Jan 2015 00:33:54 +0200 Subject: ZVISION: Do not process cheat codes while in the game menus This prevents the cheat codes from being accidentally triggered when using the save screen, for example --- engines/zvision/core/events.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/zvision/core/events.cpp b/engines/zvision/core/events.cpp index 4c7d395892..9cf5d04a7a 100644 --- a/engines/zvision/core/events.cpp +++ b/engines/zvision/core/events.cpp @@ -93,6 +93,11 @@ void ZVision::shortKeys(Common::Event event) { } void ZVision::cheatCodes(uint8 key) { + Location loc = _scriptManager->getCurrentLocation(); + // Do not process cheat codes while in the game menus + if (loc.world == 'g' && loc.room == 'j') + return; + pushKeyToCheatBuf(key); if (getGameId() == GID_GRANDINQUISITOR) { @@ -146,7 +151,6 @@ void ZVision::cheatCodes(uint8 key) { } if (checkCode("HELLOSAILOR")) { - Location loc = _scriptManager->getCurrentLocation(); Audio::AudioStream *soundStream; if (loc.world == 'v' && loc.room == 'b' && loc.node == '1' && loc.view == '0') { soundStream = makeRawZorkStream("v000hpta.raw", this); -- cgit v1.2.3 From 5a6f711d07f64193692451c9969b661c094e2021 Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Tue, 20 Jan 2015 23:30:32 +0100 Subject: ZVISION: Convert subtitles to UTF-32 before rendering them (bug #6772) Because we use Common::String to store UTF-8 data, the font renderer will draw the wrong glyphs for non-ASCII characters, unless we first convert the string to UTF-32. (I thought the same change would have to be made for the ZGI game over screens, but apparently they work anyway. At least the German version, I'm told.) I've discussed this change with [md5], and while it would probably be more correct to make the engine use UTF-32 throughout, that is also rather painful. --- engines/zvision/text/truetype_font.cpp | 38 +++++++++++++++++++++++++++++++--- engines/zvision/text/truetype_font.h | 2 ++ 2 files changed, 37 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/zvision/text/truetype_font.cpp b/engines/zvision/text/truetype_font.cpp index 9f4fbe797b..f7580fb553 100644 --- a/engines/zvision/text/truetype_font.cpp +++ b/engines/zvision/text/truetype_font.cpp @@ -26,6 +26,7 @@ #include "common/file.h" #include "common/system.h" #include "common/unzip.h" +#include "common/ustr.h" #include "graphics/font.h" #include "graphics/fonts/ttf.h" #include "graphics/surface.h" @@ -168,6 +169,36 @@ int StyledTTFont::getKerningOffset(byte left, byte right) { return 0; } +Common::U32String StyledTTFont::convertUtf8ToUtf32(const Common::String &str) { + // The String class, and therefore the Font class as well, assume one + // character is one byte, but in this case it's actually an UTF-8 + // string with up to 4 bytes per character. To work around this, + // convert it to an U32String before drawing it, because our Font class + // can handle that. + Common::U32String u32str; + uint i = 0; + while (i < str.size()) { + uint32 chr = 0; + if ((str[i] & 0xF8) == 0xF0) { + chr |= (str[i++] & 0x07) << 18; + chr |= (str[i++] & 0x3F) << 12; + chr |= (str[i++] & 0x3F) << 6; + chr |= (str[i++] & 0x3F); + } else if ((str[i] & 0xF0) == 0xE0) { + chr |= (str[i++] & 0x0F) << 12; + chr |= (str[i++] & 0x3F) << 6; + chr |= (str[i++] & 0x3F); + } else if ((str[i] & 0xE0) == 0xC0) { + chr |= (str[i++] & 0x1F) << 6; + chr |= (str[i++] & 0x3F); + } else { + chr = (str[i++] & 0x7F); + } + u32str += chr; + } + return u32str; +} + void StyledTTFont::drawChar(Graphics::Surface *dst, byte chr, int x, int y, uint32 color) { if (_font) { _font->drawChar(dst, chr, x, y, color); @@ -186,10 +217,11 @@ void StyledTTFont::drawChar(Graphics::Surface *dst, byte chr, int x, int y, uint void StyledTTFont::drawString(Graphics::Surface *dst, const Common::String &str, int x, int y, int w, uint32 color, Graphics::TextAlign align) { if (_font) { - _font->drawString(dst, str, x, y, w, color, align); + Common::U32String u32str = convertUtf8ToUtf32(str); + _font->drawString(dst, u32str, x, y, w, color, align); if (_style & STTF_UNDERLINE) { int16 pos = floor(_font->getFontHeight() * 0.87); - int16 wd = MIN(_font->getStringWidth(str), w); + int16 wd = MIN(_font->getStringWidth(u32str), w); int16 stX = x; if (align == Graphics::kTextAlignCenter) stX += (w - wd) / 2; @@ -202,7 +234,7 @@ void StyledTTFont::drawString(Graphics::Surface *dst, const Common::String &str, } if (_style & STTF_STRIKEOUT) { int16 pos = floor(_font->getFontHeight() * 0.60); - int16 wd = MIN(_font->getStringWidth(str), w); + int16 wd = MIN(_font->getStringWidth(u32str), w); int16 stX = x; if (align == Graphics::kTextAlignCenter) stX += (w - wd) / 2; diff --git a/engines/zvision/text/truetype_font.h b/engines/zvision/text/truetype_font.h index 6fbb1f0504..caa9c09a76 100644 --- a/engines/zvision/text/truetype_font.h +++ b/engines/zvision/text/truetype_font.h @@ -77,6 +77,8 @@ public: int getCharWidth(byte chr); int getKerningOffset(byte left, byte right); + Common::U32String convertUtf8ToUtf32(const Common::String &str); + void drawChar(Graphics::Surface *dst, byte chr, int x, int y, uint32 color); void drawString(Graphics::Surface *dst, const Common::String &str, int x, int y, int w, uint32 color, Graphics::TextAlign align = Graphics::kTextAlignLeft); -- cgit v1.2.3 From 1330cb7c99478c67a722ff3bd35567dcd59f8fdf Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 21 Jan 2015 01:41:35 +0200 Subject: ZVISION: Remove superfluous check --- engines/zvision/scripting/script_manager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/zvision/scripting/script_manager.cpp b/engines/zvision/scripting/script_manager.cpp index a4491103e6..d10cd81438 100644 --- a/engines/zvision/scripting/script_manager.cpp +++ b/engines/zvision/scripting/script_manager.cpp @@ -210,7 +210,7 @@ void ScriptManager::updateControls(uint deltaTimeMillis) { bool ScriptManager::checkPuzzleCriteria(Puzzle *puzzle, uint counter) { // Check if the puzzle is already finished // Also check that the puzzle isn't disabled - if (getStateValue(puzzle->key) == 1 || (getStateFlag(puzzle->key) & Puzzle::DISABLED) == Puzzle::DISABLED) { + if (getStateValue(puzzle->key) == 1 || (getStateFlag(puzzle->key) & Puzzle::DISABLED)) { return true; } -- cgit v1.2.3 From 796fb134f1af6b3617b7687d2a89ab51dd1aa63d Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Wed, 21 Jan 2015 01:24:59 +0100 Subject: ZVISION: Remove unnecessary spaces --- engines/zvision/scripting/script_manager.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/zvision/scripting/script_manager.cpp b/engines/zvision/scripting/script_manager.cpp index d10cd81438..71966b3125 100644 --- a/engines/zvision/scripting/script_manager.cpp +++ b/engines/zvision/scripting/script_manager.cpp @@ -78,16 +78,16 @@ void ScriptManager::update(uint deltaTimeMillis) { } updateNodes(deltaTimeMillis); - if (! execScope(nodeview)) { + if (!execScope(nodeview)) { return; } - if (! execScope(room)) { + if (!execScope(room)) { return; } - if (! execScope(world)) { + if (!execScope(world)) { return; } - if (! execScope(universe)) { + if (!execScope(universe)) { return; } updateControls(deltaTimeMillis); -- cgit v1.2.3 From dfe04491c1d8ecb45f4952af96c9d73e9e654a32 Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Wed, 21 Jan 2015 01:29:22 +0100 Subject: JANITORIAL: Remove unnecessary semicolons --- engines/access/player.cpp | 2 +- engines/fullpipe/gameloader.cpp | 2 +- engines/fullpipe/modal.cpp | 2 +- engines/fullpipe/scenes/scene23.cpp | 4 ++-- engines/hopkins/lines.cpp | 2 +- engines/mads/nebular/game_nebular.cpp | 2 +- engines/neverhood/menumodule.cpp | 2 +- engines/wintermute/debugger.cpp | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) (limited to 'engines') diff --git a/engines/access/player.cpp b/engines/access/player.cpp index e47daf532c..5a2b98293f 100644 --- a/engines/access/player.cpp +++ b/engines/access/player.cpp @@ -388,7 +388,7 @@ void Player::walkUpLeft() { tempL = _rawPlayerLow.y - _vm->_screen->_scaleTable2[walkOffset]; _rawYTempL = (byte)tempL; _rawYTemp = _rawPlayer.y - _vm->_screen->_scaleTable1[walkOffset] - - (tempL < 0 ? 1 : 0);; + (tempL < 0 ? 1 : 0); if (_vm->_room->codeWalls()) { plotCom2(); diff --git a/engines/fullpipe/gameloader.cpp b/engines/fullpipe/gameloader.cpp index fbf96b3060..7815475d37 100644 --- a/engines/fullpipe/gameloader.cpp +++ b/engines/fullpipe/gameloader.cpp @@ -323,7 +323,7 @@ bool preloadCallback(PreloadItem &pre, int flag) { if (!g_fp->_loaderScene) { g_fp->_gameLoader->loadScene(SC_LDR); - g_fp->_loaderScene = g_fp->accessScene(SC_LDR);; + g_fp->_loaderScene = g_fp->accessScene(SC_LDR); } StaticANIObject *pbar = g_fp->_loaderScene->getStaticANIObject1ById(ANI_PBAR, -1); diff --git a/engines/fullpipe/modal.cpp b/engines/fullpipe/modal.cpp index 2fd7ef0c21..096323781f 100644 --- a/engines/fullpipe/modal.cpp +++ b/engines/fullpipe/modal.cpp @@ -305,7 +305,7 @@ bool ModalMap::init(int counterdiff) { if (_flag) { _rect2.left = _mouseX + _field_38 - g_fp->_mouseScreenPos.x; - _rect2.top = _mouseY + _field_3C - g_fp->_mouseScreenPos.y;; + _rect2.top = _mouseY + _field_3C - g_fp->_mouseScreenPos.y; _rect2.right = _rect2.left + 800; _rect2.bottom = _rect2.top + 600; diff --git a/engines/fullpipe/scenes/scene23.cpp b/engines/fullpipe/scenes/scene23.cpp index f66ea12b4b..ded467e438 100644 --- a/engines/fullpipe/scenes/scene23.cpp +++ b/engines/fullpipe/scenes/scene23.cpp @@ -299,14 +299,14 @@ void sceneHandler23_pushButton(ExCommand *cmd) { MessageQueue *mq = getCurrSceneSc2MotionController()->method34(g_fp->_aniMan, 276, 438, 1, ST_MAN_RIGHT); if (mq) { - mq->addExCommandToEnd(cmd->createClone());; + mq->addExCommandToEnd(cmd->createClone()); postExCommand(g_fp->_aniMan->_id, 2, 276, 438, 0, -1); } } else { MessageQueue *mq = new MessageQueue(g_fp->_currentScene->getMessageQueueById(QU_SC23_TOCALENDAR), 0, 0); - mq->addExCommandToEnd(cmd->createClone());; + mq->addExCommandToEnd(cmd->createClone()); mq->setFlags(mq->getFlags() | 1); mq->chain(0); } diff --git a/engines/hopkins/lines.cpp b/engines/hopkins/lines.cpp index 709f17a8b2..f511e6aa5a 100644 --- a/engines/hopkins/lines.cpp +++ b/engines/hopkins/lines.cpp @@ -2110,7 +2110,7 @@ RouteItem *LinesManager::cityMapCarRoute(int x1, int y1, int x2, int y2) { _testRoute0[superRouteIdx].set(curRouteX, curRouteY, curRouteDir); superRouteIdx++; if (curRouteX == -1) - break;; + break; } if (curRouteX != -1) { curRouteLineIdx = arrLineIdx[DIR_UP]; diff --git a/engines/mads/nebular/game_nebular.cpp b/engines/mads/nebular/game_nebular.cpp index fd669bc5cf..8c0c00428a 100644 --- a/engines/mads/nebular/game_nebular.cpp +++ b/engines/mads/nebular/game_nebular.cpp @@ -810,7 +810,7 @@ void GameNebular::step() { (_player._facing == _player._turnToFacing)) { if (_scene._frameStartTime >= *((uint32 *)&_globals[kWalkerTiming])) { if (!_player._stopWalkerIndex) { - int randomVal = _vm->getRandomNumber(29999);; + int randomVal = _vm->getRandomNumber(29999); if (_globals[kSexOfRex] == REX_MALE) { switch (_player._facing) { case FACING_SOUTHWEST: diff --git a/engines/neverhood/menumodule.cpp b/engines/neverhood/menumodule.cpp index 255d04dc86..6911041e58 100644 --- a/engines/neverhood/menumodule.cpp +++ b/engines/neverhood/menumodule.cpp @@ -202,7 +202,7 @@ uint32 MenuModule::handleMessage(int messageNum, const MessageParam ¶m, Enti break; } - return Module::handleMessage(messageNum, param, sender);; + return Module::handleMessage(messageNum, param, sender); } void MenuModule::createLoadGameMenu() { diff --git a/engines/wintermute/debugger.cpp b/engines/wintermute/debugger.cpp index a313314a8b..5b617d9db9 100644 --- a/engines/wintermute/debugger.cpp +++ b/engines/wintermute/debugger.cpp @@ -42,7 +42,7 @@ bool Console::Cmd_ShowFps(int argc, const char **argv) { if (Common::String(argv[1]) == "true") { _engineRef->_game->setShowFPS(true); } else if (Common::String(argv[1]) == "false") { - _engineRef->_game->setShowFPS(false);; + _engineRef->_game->setShowFPS(false); } } return true; -- cgit v1.2.3 From 46fe6b64b9bac081384107192b7bcd24fbb255f5 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 21 Jan 2015 12:35:12 +0200 Subject: ZVISION: Properly handle confirmation dialogs in the French ver. of ZGI --- engines/zvision/graphics/render_manager.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/zvision/graphics/render_manager.cpp b/engines/zvision/graphics/render_manager.cpp index a65117f2b5..3cd9701b7c 100644 --- a/engines/zvision/graphics/render_manager.cpp +++ b/engines/zvision/graphics/render_manager.cpp @@ -992,7 +992,8 @@ bool RenderManager::askQuestion(const Common::String &str) { // English: yes/no // German: ja/nein // Spanish: si/no - // French: F4/any other key + // French Nemesis: F4/any other key + // French ZGI: oui/non switch (evnt.kbd.keycode) { case Common::KEYCODE_y: if (_engine->getLanguage() == Common::EN_ANY) @@ -1006,15 +1007,19 @@ bool RenderManager::askQuestion(const Common::String &str) { if (_engine->getLanguage() == Common::ES_ESP) result = 2; break; + case Common::KEYCODE_o: + if (_engine->getLanguage() == Common::FR_FRA && _engine->getGameId() == GID_GRANDINQUISITOR) + result = 2; + break; case Common::KEYCODE_F4: - if (_engine->getLanguage() == Common::FR_FRA) + if (_engine->getLanguage() == Common::FR_FRA && _engine->getGameId() == GID_NEMESIS) result = 2; break; case Common::KEYCODE_n: result = 1; break; default: - if (_engine->getLanguage() == Common::FR_FRA) + if (_engine->getLanguage() == Common::FR_FRA && _engine->getGameId() == GID_NEMESIS) result = 1; break; } -- cgit v1.2.3 From e66883d5cbae4d92264cd1c2b5784af79d30f152 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 21 Jan 2015 14:06:13 +0200 Subject: ZVISION: Add console commands to manipulate state flags and variables --- engines/zvision/core/console.cpp | 38 ++++++++++++++++++++++++++++++++++++++ engines/zvision/core/console.h | 2 ++ 2 files changed, 40 insertions(+) (limited to 'engines') diff --git a/engines/zvision/core/console.cpp b/engines/zvision/core/console.cpp index e54e986bd7..f5cacb582c 100644 --- a/engines/zvision/core/console.cpp +++ b/engines/zvision/core/console.cpp @@ -54,6 +54,8 @@ Console::Console(ZVision *engine) : GUI::Debugger(), _engine(engine) { registerCmd("dumpfile", WRAP_METHOD(Console, cmdDumpFile)); registerCmd("dumpfiles", WRAP_METHOD(Console, cmdDumpFiles)); registerCmd("dumpimage", WRAP_METHOD(Console, cmdDumpImage)); + registerCmd("statevalue", WRAP_METHOD(Console, cmdStateValue)); + registerCmd("stateflag", WRAP_METHOD(Console, cmdStateFlag)); } bool Console::cmdLoadVideo(int argc, const char **argv) { @@ -329,4 +331,40 @@ bool Console::cmdDumpImage(int argc, const char **argv) { return true; } +bool Console::cmdStateValue(int argc, const char **argv) { + if (argc < 2) { + debugPrintf("Use %s to show the value of a state variable\n", argv[0]); + debugPrintf("Use %s to set the value of a state variable\n", argv[0]); + return true; + } + + int valueNum = atoi(argv[1]); + int newValue = (argc > 2) ? atoi(argv[2]) : -1; + + if (argc == 2) + debugPrintf("[%d] = %d\n", valueNum, _engine->getScriptManager()->getStateValue(valueNum)); + else if (argc == 3) + _engine->getScriptManager()->setStateValue(valueNum, newValue); + + return true; +} + +bool Console::cmdStateFlag(int argc, const char **argv) { + if (argc < 2) { + debugPrintf("Use %s to show the value of a state flag\n", argv[0]); + debugPrintf("Use %s to set the value of a state flag\n", argv[0]); + return true; + } + + int valueNum = atoi(argv[1]); + int newValue = (argc > 2) ? atoi(argv[2]) : -1; + + if (argc == 2) + debugPrintf("[%d] = %d\n", valueNum, _engine->getScriptManager()->getStateFlag(valueNum)); + else if (argc == 3) + _engine->getScriptManager()->setStateFlag(valueNum, newValue); + + return true; +} + } // End of namespace ZVision diff --git a/engines/zvision/core/console.h b/engines/zvision/core/console.h index ffce87869f..ac834185a0 100644 --- a/engines/zvision/core/console.h +++ b/engines/zvision/core/console.h @@ -48,6 +48,8 @@ private: bool cmdDumpFile(int argc, const char **argv); bool cmdDumpFiles(int argc, const char **argv); bool cmdDumpImage(int argc, const char **argv); + bool cmdStateValue(int argc, const char **argv); + bool cmdStateFlag(int argc, const char **argv); }; } // End of namespace ZVision -- cgit v1.2.3 From f7e0d1e958f3b6a4bfff9ba2c9ade03375e8f9d9 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 23 Jan 2015 03:01:29 +0200 Subject: ZVISION: Fix shadowed variable A bug in commit 21e9007d80. Thanks to fingolfin for pointing it out --- engines/zvision/file/save_manager.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/zvision/file/save_manager.cpp b/engines/zvision/file/save_manager.cpp index 55be8d2530..1e0c57e2b3 100644 --- a/engines/zvision/file/save_manager.cpp +++ b/engines/zvision/file/save_manager.cpp @@ -136,13 +136,15 @@ Common::Error SaveManager::loadGame(int slot) { if (slot >= 0) { saveFile = getSlotFile(slot); } else { - Common::File *saveFile = _engine->getSearchManager()->openFile("r.svr"); + saveFile = _engine->getSearchManager()->openFile("r.svr"); if (!saveFile) { - saveFile = new Common::File; - if (!saveFile->open("r.svr")) { - delete saveFile; + Common::File *restoreFile = new Common::File(); + if (!restoreFile->open("r.svr")) { + delete restoreFile; return Common::kPathDoesNotExist; } + + saveFile = restoreFile; } } -- cgit v1.2.3 From 1bd83a96f00c4d25cf4060ba8faffda81865ad7d Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 23 Jan 2015 03:02:24 +0200 Subject: ZVISION: Fix script bug #6780 (invalid hotspot at base of tower in ZGI) --- engines/zvision/scripting/scr_file_handling.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'engines') diff --git a/engines/zvision/scripting/scr_file_handling.cpp b/engines/zvision/scripting/scr_file_handling.cpp index 8f0f80e39e..b9cafa77ed 100644 --- a/engines/zvision/scripting/scr_file_handling.cpp +++ b/engines/zvision/scripting/scr_file_handling.cpp @@ -358,6 +358,16 @@ Control *ScriptManager::parseControl(Common::String &line, Common::SeekableReadS Common::String controlType(controlTypeBuffer); if (controlType.equalsIgnoreCase("push_toggle")) { + // WORKAROUND for a script bug in ZGI: There is an invalid hotspot + // at scene em1h (bottom of tower), which points to a missing + // script em1n. This is a hotspot at the right of the screen. + // In the original, this hotspot doesn't lead anywhere anyway, + // so instead of moving to a missing scene, we just remove the + // hotspot altogether. The alternative would be to just process + // and ignore invalid scenes, but I don't think it's worth the + // effort. Fixes bug #6780. + if (_engine->getGameId() == GID_GRANDINQUISITOR && key == 5653) + return NULL; return new PushToggleControl(_engine, key, stream); } else if (controlType.equalsIgnoreCase("flat")) { Control::parseFlatControl(_engine); -- cgit v1.2.3 From d75fbe79f064e3ee017764024aac173a7d599583 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 23 Jan 2015 03:04:50 +0200 Subject: ZVISION: Error out when a script file can't be found or be parsed This should be an error, as we've effectively reached a non-existing scene (such as in bug #6780), or we haven't parsed script files of a scene fully, thus unexpected behavior will likely occur --- engines/zvision/scripting/scr_file_handling.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/zvision/scripting/scr_file_handling.cpp b/engines/zvision/scripting/scr_file_handling.cpp index b9cafa77ed..b047c14430 100644 --- a/engines/zvision/scripting/scr_file_handling.cpp +++ b/engines/zvision/scripting/scr_file_handling.cpp @@ -47,15 +47,13 @@ namespace ZVision { void ScriptManager::parseScrFile(const Common::String &fileName, ScriptScope &scope) { Common::File file; if (!_engine->getSearchManager()->openFile(file, fileName)) { - warning("Script file not found: %s", fileName.c_str()); - return; + error("Script file not found: %s", fileName.c_str()); } while (!file.eos()) { Common::String line = file.readLine(); if (file.err()) { - warning("Error parsing scr file: %s", fileName.c_str()); - return; + error("Error parsing scr file: %s", fileName.c_str()); } trimCommentsAndWhiteSpace(&line); -- cgit v1.2.3 From d67727a7a452354587fb49e58ac3a61cd4ac1fec Mon Sep 17 00:00:00 2001 From: Marisa-Chan Date: Fri, 23 Jan 2015 11:13:06 +0600 Subject: ZVISION: Fix sound bug #6767 by making pan_track code similar to original --- engines/zvision/scripting/effects/music_effect.cpp | 129 +++++++++++++-------- engines/zvision/scripting/effects/music_effect.h | 26 +++-- 2 files changed, 94 insertions(+), 61 deletions(-) (limited to 'engines') diff --git a/engines/zvision/scripting/effects/music_effect.cpp b/engines/zvision/scripting/effects/music_effect.cpp index 102f330305..3d3fc88751 100644 --- a/engines/zvision/scripting/effects/music_effect.cpp +++ b/engines/zvision/scripting/effects/music_effect.cpp @@ -40,12 +40,11 @@ MusicNode::MusicNode(ZVision *engine, uint32 key, Common::String &filename, bool : MusicNodeBASE(engine, key, SCRIPTING_EFFECT_AUDIO) { _loop = loop; _volume = volume; + _deltaVolume = 0; + _balance = 0; _crossfade = false; _crossfadeTarget = 0; _crossfadeTime = 0; - _attenuate = 0; - _pantrack = false; - _pantrackPosition = 0; _sub = NULL; _stereo = false; _loaded = false; @@ -97,17 +96,14 @@ MusicNode::~MusicNode() { debug(1, "MusicNode: %d destroyed\n", _key); } -void MusicNode::setPanTrack(int16 pos) { - if (!_stereo) { - _pantrack = true; - _pantrackPosition = pos; - setVolume(_volume); - } +void MusicNode::setDeltaVolume(uint8 volume) { + _deltaVolume = volume; + setVolume(_volume); } -void MusicNode::unsetPanTrack() { - _pantrack = false; - setVolume(_volume); +void MusicNode::setBalance(int8 balance) { + _balance = balance; + _engine->_mixer->setChannelBalance(_handle, _balance); } void MusicNode::setFade(int32 time, uint8 target) { @@ -134,7 +130,7 @@ bool MusicNode::process(uint32 deltaTimeInMillis) { } } - if (_pantrack || _volume != _newvol) + if (_volume != _newvol) setVolume(_newvol); if (_sub && _engine->getScriptManager()->getStateValue(StateKey_Subtitles) == 1) @@ -146,55 +142,86 @@ bool MusicNode::process(uint32 deltaTimeInMillis) { void MusicNode::setVolume(uint8 newVolume) { if (!_loaded) return; - if (_pantrack) { - int curX = _engine->getScriptManager()->getStateValue(StateKey_ViewPos); - curX -= _pantrackPosition; - int32 _width = _engine->getRenderManager()->getBkgSize().x; - if (curX < (-_width) / 2) - curX += _width; - else if (curX >= _width / 2) - curX -= _width; - - float norm = (float)curX / ((float)_width / 2.0); - float lvl = fabs(norm); - if (lvl > 0.5) - lvl = (lvl - 0.5) * 1.7; - else - lvl = 1.0; - float bal = sin(-norm * 3.1415926) * 127.0; + _volume = newVolume; - if (_engine->_mixer->isSoundHandleActive(_handle)) { - _engine->_mixer->setChannelBalance(_handle, bal); - _engine->_mixer->setChannelVolume(_handle, newVolume * lvl); - } - } else { - if (_engine->_mixer->isSoundHandleActive(_handle)) { - _engine->_mixer->setChannelBalance(_handle, 0); - _engine->_mixer->setChannelVolume(_handle, newVolume); - } - } + if (_deltaVolume >= _volume) + _engine->_mixer->setChannelVolume(_handle, 0); + else + _engine->_mixer->setChannelVolume(_handle, _volume - _deltaVolume); +} - _volume = newVolume; +uint8 MusicNode::getVolume() { + return _volume; } PanTrackNode::PanTrackNode(ZVision *engine, uint32 key, uint32 slot, int16 pos) : ScriptingEffect(engine, key, SCRIPTING_EFFECT_PANTRACK) { _slot = slot; + _position = pos; - ScriptingEffect *fx = _engine->getScriptManager()->getSideFX(slot); - if (fx && fx->getType() == SCRIPTING_EFFECT_AUDIO) { - MusicNodeBASE *mus = (MusicNodeBASE *)fx; - mus->setPanTrack(pos); - } + // Try to set pan value for music node immediately + process(0); } PanTrackNode::~PanTrackNode() { - ScriptingEffect *fx = _engine->getScriptManager()->getSideFX(_slot); +} + +bool PanTrackNode::process(uint32 deltaTimeInMillis) { + ScriptManager * scriptManager = _engine->getScriptManager(); + ScriptingEffect *fx = scriptManager->getSideFX(_slot); if (fx && fx->getType() == SCRIPTING_EFFECT_AUDIO) { MusicNodeBASE *mus = (MusicNodeBASE *)fx; - mus->unsetPanTrack(); + + int curPos = scriptManager->getStateValue(StateKey_ViewPos); + int16 _width = _engine->getRenderManager()->getBkgSize().x; + int16 _halfWidth = _width / 2; + int16 _quarterWidth = _width / 4; + + int tmp = 0; + if (curPos <= _position) + tmp = _position - curPos; + else + tmp = _position - curPos + _width; + + int balance = 0; + + if (tmp > _halfWidth) + tmp -= _width; + + if (tmp > _quarterWidth) { + balance = 1; + tmp = _halfWidth - tmp; + } else if (tmp < -_quarterWidth) { + balance = -1; + tmp = -_halfWidth - tmp; + } + + // Originally it's value -90...90 but we use -127...127 and therefore 360 replaced by 508 + mus->setBalance( (508 * tmp) / _width ); + + tmp = (360 * tmp) / _width; + + int deltaVol = balance; + + // This value sets how fast volume goes off than sound source back of you + // By this value we can hack some "bugs" have place in originall game engine like beat sound in ZGI-dc10 + int volumeCorrection = 2; + + if (_engine->getGameId() == GID_GRANDINQUISITOR) { + Location loc = scriptManager->getCurrentLocation(); + if (loc.world == 'd' && loc.room == 'c' && loc.node == '1' && loc.view == '0') + volumeCorrection = 5; + } + + if (deltaVol != 0) + deltaVol = (mus->getVolume() * volumeCorrection) * (90 - tmp * balance) / 90; + if (deltaVol > 255) + deltaVol = 255; + + mus->setDeltaVolume(deltaVol); } + return false; } MusicMidiNode::MusicMidiNode(ZVision *engine, uint32 key, int8 program, int8 note, int8 volume) @@ -225,10 +252,10 @@ MusicMidiNode::~MusicMidiNode() { _engine->getScriptManager()->setStateValue(_key, 2); } -void MusicMidiNode::setPanTrack(int16 pos) { +void MusicMidiNode::setDeltaVolume(uint8 volume) { } -void MusicMidiNode::unsetPanTrack() { +void MusicMidiNode::setBalance(int8 balance) { } void MusicMidiNode::setFade(int32 time, uint8 target) { @@ -245,4 +272,8 @@ void MusicMidiNode::setVolume(uint8 newVolume) { _volume = newVolume; } +uint8 MusicMidiNode::getVolume() { + return _volume; +} + } // End of namespace ZVision diff --git a/engines/zvision/scripting/effects/music_effect.h b/engines/zvision/scripting/effects/music_effect.h index 31d538f668..f6cb4a5a1c 100644 --- a/engines/zvision/scripting/effects/music_effect.h +++ b/engines/zvision/scripting/effects/music_effect.h @@ -48,9 +48,9 @@ public: virtual bool process(uint32 deltaTimeInMillis) = 0; virtual void setVolume(uint8 volume) = 0; - - virtual void setPanTrack(int16 pos) = 0; - virtual void unsetPanTrack() = 0; + virtual uint8 getVolume() = 0; + virtual void setDeltaVolume(uint8 volume) = 0; + virtual void setBalance(int8 balance) = 0; virtual void setFade(int32 time, uint8 target) = 0; }; @@ -70,17 +70,16 @@ public: bool process(uint32 deltaTimeInMillis); void setVolume(uint8 volume); - - void setPanTrack(int16 pos); - void unsetPanTrack(); + uint8 getVolume(); + void setDeltaVolume(uint8 volume); + void setBalance(int8 balance); void setFade(int32 time, uint8 target); private: - bool _pantrack; - int32 _pantrackPosition; - int32 _attenuate; uint8 _volume; + uint8 _deltaVolume; + int8 _balance; bool _loop; bool _crossfade; uint8 _crossfadeTarget; @@ -107,9 +106,9 @@ public: bool process(uint32 deltaTimeInMillis); void setVolume(uint8 volume); - - void setPanTrack(int16 pos); - void unsetPanTrack(); + uint8 getVolume(); + void setDeltaVolume(uint8 volume); + void setBalance(int8 balance); void setFade(int32 time, uint8 target); @@ -126,8 +125,11 @@ public: PanTrackNode(ZVision *engine, uint32 key, uint32 slot, int16 pos); ~PanTrackNode(); + bool process(uint32 deltaTimeInMillis); + private: uint32 _slot; + int16 _position; }; } // End of namespace ZVision -- cgit v1.2.3 From ad2ab98474cecc8f8764697b3aa2acc16912368f Mon Sep 17 00:00:00 2001 From: Marisa-Chan Date: Fri, 23 Jan 2015 16:20:59 +0600 Subject: ZVISION: Use correct int type for volume --- engines/zvision/scripting/effects/music_effect.cpp | 2 +- engines/zvision/scripting/effects/music_effect.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/zvision/scripting/effects/music_effect.cpp b/engines/zvision/scripting/effects/music_effect.cpp index 3d3fc88751..6c1a5f7376 100644 --- a/engines/zvision/scripting/effects/music_effect.cpp +++ b/engines/zvision/scripting/effects/music_effect.cpp @@ -36,7 +36,7 @@ namespace ZVision { -MusicNode::MusicNode(ZVision *engine, uint32 key, Common::String &filename, bool loop, int8 volume) +MusicNode::MusicNode(ZVision *engine, uint32 key, Common::String &filename, bool loop, uint8 volume) : MusicNodeBASE(engine, key, SCRIPTING_EFFECT_AUDIO) { _loop = loop; _volume = volume; diff --git a/engines/zvision/scripting/effects/music_effect.h b/engines/zvision/scripting/effects/music_effect.h index f6cb4a5a1c..7657be8e09 100644 --- a/engines/zvision/scripting/effects/music_effect.h +++ b/engines/zvision/scripting/effects/music_effect.h @@ -57,7 +57,7 @@ public: class MusicNode : public MusicNodeBASE { public: - MusicNode(ZVision *engine, uint32 key, Common::String &file, bool loop, int8 volume); + MusicNode(ZVision *engine, uint32 key, Common::String &file, bool loop, uint8 volume); ~MusicNode(); /** -- cgit v1.2.3 From 0bc61d3c2130981e06199b60fe553b2095af287a Mon Sep 17 00:00:00 2001 From: Marisa-Chan Date: Fri, 23 Jan 2015 16:25:21 +0600 Subject: ZVISION: Volume is not linear value, use dB map to linear for -100...0dB --- engines/zvision/scripting/effects/music_effect.cpp | 24 +++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/zvision/scripting/effects/music_effect.cpp b/engines/zvision/scripting/effects/music_effect.cpp index 6c1a5f7376..ee2232d962 100644 --- a/engines/zvision/scripting/effects/music_effect.cpp +++ b/engines/zvision/scripting/effects/music_effect.cpp @@ -36,6 +36,24 @@ namespace ZVision { +static const uint8 dbMapLinear[256] = +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, +2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, +4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, +8, 8, 8, 9, 9, 9, 10, 10, 11, 11, 11, 12, 12, 13, 13, 14, +14, 15, 15, 16, 16, 17, 18, 18, 19, 20, 21, 21, 22, 23, 24, 25, +26, 27, 28, 29, 30, 31, 32, 33, 34, 36, 37, 38, 40, 41, 43, 45, +46, 48, 50, 52, 53, 55, 57, 60, 62, 64, 67, 69, 72, 74, 77, 80, +83, 86, 89, 92, 96, 99, 103, 107, 111, 115, 119, 123, 128, 133, 137, 143, +148, 153, 159, 165, 171, 177, 184, 191, 198, 205, 212, 220, 228, 237, 245, 255}; + MusicNode::MusicNode(ZVision *engine, uint32 key, Common::String &filename, bool loop, uint8 volume) : MusicNodeBASE(engine, key, SCRIPTING_EFFECT_AUDIO) { _loop = loop; @@ -65,9 +83,9 @@ MusicNode::MusicNode(ZVision *engine, uint32 key, Common::String &filename, bool if (_loop) { Audio::LoopingAudioStream *loopingAudioStream = new Audio::LoopingAudioStream(audioStream, 0, DisposeAfterUse::YES); - _engine->_mixer->playStream(Audio::Mixer::kPlainSoundType, &_handle, loopingAudioStream, -1, _volume); + _engine->_mixer->playStream(Audio::Mixer::kPlainSoundType, &_handle, loopingAudioStream, -1, dbMapLinear[_volume]); } else { - _engine->_mixer->playStream(Audio::Mixer::kPlainSoundType, &_handle, audioStream, -1, _volume); + _engine->_mixer->playStream(Audio::Mixer::kPlainSoundType, &_handle, audioStream, -1, dbMapLinear[_volume]); } if (_key != StateKey_NotSet) @@ -148,7 +166,7 @@ void MusicNode::setVolume(uint8 newVolume) { if (_deltaVolume >= _volume) _engine->_mixer->setChannelVolume(_handle, 0); else - _engine->_mixer->setChannelVolume(_handle, _volume - _deltaVolume); + _engine->_mixer->setChannelVolume(_handle, dbMapLinear[_volume - _deltaVolume]); } uint8 MusicNode::getVolume() { -- cgit v1.2.3 From 9b498d576ed9b922ef61175310a6b369e4d30e3f Mon Sep 17 00:00:00 2001 From: Marisa-Chan Date: Fri, 23 Jan 2015 16:26:17 +0600 Subject: ZVISION: Correct value for attenuate --- engines/zvision/scripting/actions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/zvision/scripting/actions.cpp b/engines/zvision/scripting/actions.cpp index 758158817e..b12ecf66ee 100644 --- a/engines/zvision/scripting/actions.cpp +++ b/engines/zvision/scripting/actions.cpp @@ -104,7 +104,7 @@ bool ActionAttenuate::execute() { ScriptingEffect *fx = _engine->getScriptManager()->getSideFX(_key); if (fx && fx->getType() == ScriptingEffect::SCRIPTING_EFFECT_AUDIO) { MusicNode *mus = (MusicNode *)fx; - mus->setVolume(255 - (abs(_attenuation) >> 7)); + mus->setVolume(255 * (10000 - abs(_attenuation)) / 10000 ); } return true; } -- cgit v1.2.3 From 568c13b11531fcfb10b53bbc84d723e6fd1d0e40 Mon Sep 17 00:00:00 2001 From: Marisa-Chan Date: Fri, 23 Jan 2015 16:31:10 +0600 Subject: ZVISION: Use correct virtual class type instead of MusicNode --- engines/zvision/scripting/actions.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/zvision/scripting/actions.cpp b/engines/zvision/scripting/actions.cpp index b12ecf66ee..9a2f1d10ff 100644 --- a/engines/zvision/scripting/actions.cpp +++ b/engines/zvision/scripting/actions.cpp @@ -103,7 +103,7 @@ ActionAttenuate::ActionAttenuate(ZVision *engine, int32 slotkey, const Common::S bool ActionAttenuate::execute() { ScriptingEffect *fx = _engine->getScriptManager()->getSideFX(_key); if (fx && fx->getType() == ScriptingEffect::SCRIPTING_EFFECT_AUDIO) { - MusicNode *mus = (MusicNode *)fx; + MusicNodeBASE *mus = (MusicNodeBASE *)fx; mus->setVolume(255 * (10000 - abs(_attenuation)) / 10000 ); } return true; @@ -154,7 +154,7 @@ bool ActionCrossfade::execute() { if (_keyOne) { ScriptingEffect *fx = _engine->getScriptManager()->getSideFX(_keyOne); if (fx && fx->getType() == ScriptingEffect::SCRIPTING_EFFECT_AUDIO) { - MusicNode *mus = (MusicNode *)fx; + MusicNodeBASE *mus = (MusicNodeBASE *)fx; if (_oneStartVolume >= 0) mus->setVolume((_oneStartVolume * 255) / 100); @@ -165,7 +165,7 @@ bool ActionCrossfade::execute() { if (_keyTwo) { ScriptingEffect *fx = _engine->getScriptManager()->getSideFX(_keyTwo); if (fx && fx->getType() == ScriptingEffect::SCRIPTING_EFFECT_AUDIO) { - MusicNode *mus = (MusicNode *)fx; + MusicNodeBASE *mus = (MusicNodeBASE *)fx; if (_twoStartVolume >= 0) mus->setVolume((_twoStartVolume * 255) / 100); -- cgit v1.2.3 From 3839d9ce0b0b746da62cd3380f91a48c9748b033 Mon Sep 17 00:00:00 2001 From: chrilith Date: Fri, 23 Jan 2015 13:11:28 +0100 Subject: MORTEVIELLE: Fixed drawBox() to match original code --- engines/mortevielle/dialogs.cpp | 2 +- engines/mortevielle/graphics.cpp | 2 ++ engines/mortevielle/utils.cpp | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/mortevielle/dialogs.cpp b/engines/mortevielle/dialogs.cpp index 89098fabe5..95388c7b6a 100644 --- a/engines/mortevielle/dialogs.cpp +++ b/engines/mortevielle/dialogs.cpp @@ -405,7 +405,7 @@ void DialogManager::drawF3F8() { int f8Width = _vm->_screenSurface->getStringWidth(f8); // Write out the bounding box - _vm->_screenSurface->drawBox(0, 42, MAX(f3Width, f8Width) + 6, 18, 7); + _vm->_screenSurface->drawBox(0, 42, MAX(f3Width, f8Width) + 4, 16, 7); } /** diff --git a/engines/mortevielle/graphics.cpp b/engines/mortevielle/graphics.cpp index 553c1a759e..aa479fdd44 100644 --- a/engines/mortevielle/graphics.cpp +++ b/engines/mortevielle/graphics.cpp @@ -1019,6 +1019,8 @@ void ScreenSurface::writeCharacter(const Common::Point &pt, unsigned char ch, in * simulate the original 640x400 surface, all Y values have to be doubled */ void ScreenSurface::drawBox(int x, int y, int dx, int dy, int col) { + dx++; dy++; // Original function draws 1px bigger + Graphics::Surface destSurface = lockArea(Common::Rect(x, y * 2, x + dx, (y + dy) * 2)); destSurface.hLine(0, 0, dx, col); diff --git a/engines/mortevielle/utils.cpp b/engines/mortevielle/utils.cpp index 40136ad78b..8ae4951c50 100644 --- a/engines/mortevielle/utils.cpp +++ b/engines/mortevielle/utils.cpp @@ -1653,11 +1653,11 @@ void MortevielleEngine::clearDescriptionBar() { _mouse->hideMouse(); if (_largestClearScreen) { _screenSurface->fillRect(0, Common::Rect(1, 176, 633, 199)); - _screenSurface->drawBox(0, 176, 634, 23, 15); + _screenSurface->drawBox(0, 175, 634, 24, 15); _largestClearScreen = false; } else { _screenSurface->fillRect(0, Common::Rect(1, 176, 633, 190)); - _screenSurface->drawBox(0, 176, 634, 14, 15); + _screenSurface->drawBox(0, 175, 634, 15, 15); } _mouse->showMouse(); } -- cgit v1.2.3 From a7d5ac9963ceb209d99f3c00fe1b16694e6ab8e0 Mon Sep 17 00:00:00 2001 From: chrilith Date: Fri, 23 Jan 2015 13:13:59 +0100 Subject: MORTEVIELLE: Fixed read index parsing alert strings because Pascal code is base 1 --- engines/mortevielle/dialogs.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/mortevielle/dialogs.cpp b/engines/mortevielle/dialogs.cpp index 95388c7b6a..9df66846d2 100644 --- a/engines/mortevielle/dialogs.cpp +++ b/engines/mortevielle/dialogs.cpp @@ -66,12 +66,12 @@ int DialogManager::show(const Common::String &msg) { drawAlertBox(10, 5, colNumb); } else { drawAlertBox(8, 7, colNumb); - int i = 0; + int i = -1; _vm->_screenSurface->_textPos.y = 70; do { curPos.x = 320; Common::String displayStr = ""; - while ((alertStr[i + 1] != '\174') && (alertStr[i + 1] != '\135')) { + while ((alertStr[i + 1] != '|') && (alertStr[i + 1] != ']')) { ++i; displayStr += alertStr[i]; curPos.x -= 3; -- cgit v1.2.3 From 6691f9d8122aa36a0640fa33f6c2a3c6a72a6dd8 Mon Sep 17 00:00:00 2001 From: Chris Apers Date: Sat, 24 Jan 2015 10:51:51 +0100 Subject: MORTEVIELLE: Added missing mesgId handling for 3rd intro screen This message is displayed during disk access, so it is not visible as is in ScummVM version, a delay is required. Also delay should hide the mouse to prevent frozen screen. --- engines/mortevielle/mortevielle.h | 1 + engines/mortevielle/mouse.cpp | 4 ++-- engines/mortevielle/utils.cpp | 15 +++++++++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/mortevielle/mortevielle.h b/engines/mortevielle/mortevielle.h index 5f7f175c26..b6fee3f19f 100644 --- a/engines/mortevielle/mortevielle.h +++ b/engines/mortevielle/mortevielle.h @@ -92,6 +92,7 @@ enum DataType { #define MORT_DAT_REQUIRED_VERSION 1 #define MORT_DAT "mort.dat" #define GAME_FRAME_DELAY (1000 / 50) +#define DISK_ACCESS_DELAY 3000 const int kTime1 = 410; const int kTime2 = 250; diff --git a/engines/mortevielle/mouse.cpp b/engines/mortevielle/mouse.cpp index 8f96ba3ef5..7551da3934 100644 --- a/engines/mortevielle/mouse.cpp +++ b/engines/mortevielle/mouse.cpp @@ -51,7 +51,7 @@ void MouseHandler::initMouse() { * @remarks Originally called 'hide_mouse' */ void MouseHandler::hideMouse() { - // No implementation needed in ScummVM + g_system->showMouse(false); } /** @@ -59,7 +59,7 @@ void MouseHandler::hideMouse() { * @remarks Originally called 'show_mouse' */ void MouseHandler::showMouse() { - // ScummVM implementation uses CursorMan for drawing the cursor + g_system->showMouse(true); } /** diff --git a/engines/mortevielle/utils.cpp b/engines/mortevielle/utils.cpp index 40136ad78b..a89af1ab5c 100644 --- a/engines/mortevielle/utils.cpp +++ b/engines/mortevielle/utils.cpp @@ -234,6 +234,7 @@ void MortevielleEngine::setMousePos(const Common::Point &pt) { void MortevielleEngine::delay(int amount) { uint32 endTime = g_system->getMillis() + amount; + _mouse->hideMouse(); while (g_system->getMillis() < endTime) { if (g_system->getMillis() > (_lastGameFrame + GAME_FRAME_DELAY)) { _lastGameFrame = g_system->getMillis(); @@ -244,6 +245,7 @@ void MortevielleEngine::delay(int amount) { g_system->delayMillis(10); } + _mouse->showMouse(); } /** @@ -2124,6 +2126,7 @@ void MortevielleEngine::showTitleScreen() { _caff = 51; _text->taffich(); testKeyboard(); + delay(DISK_ACCESS_DELAY); clearScreen(); draw(0, 0); @@ -2521,6 +2524,18 @@ void MortevielleEngine::handleDescriptionText(int f, int mesgId) { _coreVar._pctHintFound[10] = '*'; } break; + case 7: { + prepareScreenType3(); + Common::String tmpStr = getString(mesgId); + // CHECKME: original code seems to consider one extra character + // See text position in the 3rd intro screen + int size = tmpStr.size() + 1; + if (size < 40) + _text->displayStr(tmpStr, 252 - size * 3, 86, 50, 3, 5); + else + _text->displayStr(tmpStr, 144, 86, 50, 3, 5); + } + break; default: break; } -- cgit v1.2.3 From a4d822f98a3df3c64daafbc1cb5166ad6295d47a Mon Sep 17 00:00:00 2001 From: Chris Apers Date: Sat, 24 Jan 2015 14:03:22 +0100 Subject: MORTEVIELLE: alternatively we can make it local to delay() --- engines/mortevielle/mouse.cpp | 4 ++-- engines/mortevielle/utils.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/mortevielle/mouse.cpp b/engines/mortevielle/mouse.cpp index 7551da3934..8f96ba3ef5 100644 --- a/engines/mortevielle/mouse.cpp +++ b/engines/mortevielle/mouse.cpp @@ -51,7 +51,7 @@ void MouseHandler::initMouse() { * @remarks Originally called 'hide_mouse' */ void MouseHandler::hideMouse() { - g_system->showMouse(false); + // No implementation needed in ScummVM } /** @@ -59,7 +59,7 @@ void MouseHandler::hideMouse() { * @remarks Originally called 'show_mouse' */ void MouseHandler::showMouse() { - g_system->showMouse(true); + // ScummVM implementation uses CursorMan for drawing the cursor } /** diff --git a/engines/mortevielle/utils.cpp b/engines/mortevielle/utils.cpp index a89af1ab5c..50dcb4eb9b 100644 --- a/engines/mortevielle/utils.cpp +++ b/engines/mortevielle/utils.cpp @@ -234,7 +234,7 @@ void MortevielleEngine::setMousePos(const Common::Point &pt) { void MortevielleEngine::delay(int amount) { uint32 endTime = g_system->getMillis() + amount; - _mouse->hideMouse(); + g_system->showMouse(false); while (g_system->getMillis() < endTime) { if (g_system->getMillis() > (_lastGameFrame + GAME_FRAME_DELAY)) { _lastGameFrame = g_system->getMillis(); @@ -245,7 +245,7 @@ void MortevielleEngine::delay(int amount) { g_system->delayMillis(10); } - _mouse->showMouse(); + g_system->showMouse(true); } /** -- cgit v1.2.3 From ca83ecd8c22c132da3f9b8963ffb76702692a272 Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Sat, 24 Jan 2015 14:54:25 +0100 Subject: ZVISION: Fix lag at beginning of cutscenes We have to update _curChunk when decoding audio, otherwise it will decode the entire audio track on the first frame. For the ZGI intro this would take 700-800 ms, and since the audio started playing before the video it looked to me as if it had to play the first bit faster to catch up. Thanks to fuzzie for setting me on the right track with an off-hand remark about the Zork AVI decoder (I was looking at the standard AVI decoder), and for finding the cause a few seconds before I did. --- engines/zvision/video/zork_avi_decoder.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'engines') diff --git a/engines/zvision/video/zork_avi_decoder.cpp b/engines/zvision/video/zork_avi_decoder.cpp index 5618250d79..abf48543c9 100644 --- a/engines/zvision/video/zork_avi_decoder.cpp +++ b/engines/zvision/video/zork_avi_decoder.cpp @@ -39,6 +39,7 @@ Video::AVIDecoder::AVIAudioTrack *ZorkAVIDecoder::createAudioTrack(Video::AVIDec } void ZorkAVIDecoder::ZorkAVIAudioTrack::queueSound(Common::SeekableReadStream *stream) { + bool updateCurChunk = true; if (_audStream) { if (_wvInfo.tag == kWaveFormatZorkPCM) { assert(_wvInfo.size == 8); @@ -54,9 +55,17 @@ void ZorkAVIDecoder::ZorkAVIAudioTrack::queueSound(Common::SeekableReadStream *s _audStream->queueBuffer((byte *)chunk.data, chunk.size, DisposeAfterUse::YES, flags); } } else { + updateCurChunk = false; AVIAudioTrack::queueSound(stream); } } + + // The superclass always updates _curChunk, whether or not audio has + // been queued, so we should do that too. Unless the superclass already + // has done it for us. + if (updateCurChunk) { + _curChunk++; + } } void ZorkAVIDecoder::ZorkAVIAudioTrack::resetStream() { -- cgit v1.2.3 From 4e1ffc9434f771d3f43e66104adeea9e0166123c Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Sat, 24 Jan 2015 14:56:48 +0100 Subject: ZVISION: Delete stream if there is no audio stream to queue to This probably never happens, but is consistent with our common AVI decoder. --- engines/zvision/video/zork_avi_decoder.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'engines') diff --git a/engines/zvision/video/zork_avi_decoder.cpp b/engines/zvision/video/zork_avi_decoder.cpp index abf48543c9..cf8505ec82 100644 --- a/engines/zvision/video/zork_avi_decoder.cpp +++ b/engines/zvision/video/zork_avi_decoder.cpp @@ -58,6 +58,8 @@ void ZorkAVIDecoder::ZorkAVIAudioTrack::queueSound(Common::SeekableReadStream *s updateCurChunk = false; AVIAudioTrack::queueSound(stream); } + } else { + delete stream; } // The superclass always updates _curChunk, whether or not audio has -- cgit v1.2.3 From 975b1cf7fb7f936971c553e5ed30492ad9e7e94d Mon Sep 17 00:00:00 2001 From: Chris Apers Date: Sun, 25 Jan 2015 20:53:42 +0100 Subject: MORTEVIELLE: more drawBox() adjustments --- engines/mortevielle/utils.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/mortevielle/utils.cpp b/engines/mortevielle/utils.cpp index 61f58c0972..aa58dc6f7c 100644 --- a/engines/mortevielle/utils.cpp +++ b/engines/mortevielle/utils.cpp @@ -391,7 +391,7 @@ void MortevielleEngine::setTextColor(int col) { */ void MortevielleEngine::prepareScreenType1() { // Large drawing - _screenSurface->drawBox(0, 11, 512, 164, 15); + _screenSurface->drawBox(0, 11, 512, 163, 15); } /** @@ -1381,7 +1381,7 @@ void MortevielleEngine::gotoDiningRoom() { showPeoplePresent(_currBitIndex); _caff = 77; drawPictureWithText(); - _screenSurface->drawBox(223, 47, 155, 92, 15); + _screenSurface->drawBox(223, 47, 155, 91, 15); handleDescriptionText(2, 33); testKey(false); menuUp(); @@ -2885,10 +2885,10 @@ void MortevielleEngine::drawPicture() { clearUpperLeftPart(); if (_caff > 99) { draw(60, 33); - _screenSurface->drawBox(118, 32, 291, 122, 15); // Medium box + _screenSurface->drawBox(118, 32, 291, 121, 15); // Medium box } else if (_caff > 69) { draw(112, 48); // Heads - _screenSurface->drawBox(222, 47, 155, 92, 15); + _screenSurface->drawBox(222, 47, 155, 91, 15); } else { draw(0, 12); prepareScreenType1(); @@ -2926,6 +2926,9 @@ void MortevielleEngine::drawPicture() { } } +/** + * @remarks Originally called 'afdes' + */ void MortevielleEngine::drawPictureWithText() { _text->taffich(); drawPicture(); @@ -3087,7 +3090,7 @@ void MortevielleEngine::menuUp() { */ void MortevielleEngine::drawDiscussionBox() { draw(10, 80); - _screenSurface->drawBox(18, 79, 155, 92, 15); + _screenSurface->drawBox(18, 79, 155, 91, 15); } /** -- cgit v1.2.3 From e695c018629a1a648892fe5474d2049a429e8dc8 Mon Sep 17 00:00:00 2001 From: Chris Apers Date: Sun, 25 Jan 2015 20:54:09 +0100 Subject: MORTEVIELLE: 1sec seems to be far enough here --- engines/mortevielle/mortevielle.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mortevielle/mortevielle.h b/engines/mortevielle/mortevielle.h index b6fee3f19f..b0faff3510 100644 --- a/engines/mortevielle/mortevielle.h +++ b/engines/mortevielle/mortevielle.h @@ -92,7 +92,7 @@ enum DataType { #define MORT_DAT_REQUIRED_VERSION 1 #define MORT_DAT "mort.dat" #define GAME_FRAME_DELAY (1000 / 50) -#define DISK_ACCESS_DELAY 3000 +#define DISK_ACCESS_DELAY 1000 const int kTime1 = 410; const int kTime2 = 250; -- cgit v1.2.3 From 51e90b2422f0bf3b4b9b1a71c23ae12a359dead2 Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Mon, 26 Jan 2015 19:34:21 +0100 Subject: ZVISION: Fix ActionMusic volume The volume can be either a constant or a state value. The latter is used by ZGI to simulate a sound being heard at different distances, e.g. the beehive in the Dungeon Master's hideout. --- engines/zvision/scripting/actions.cpp | 63 ++++++++++++++++++++++------------- engines/zvision/scripting/actions.h | 3 +- 2 files changed, 42 insertions(+), 24 deletions(-) (limited to 'engines') diff --git a/engines/zvision/scripting/actions.cpp b/engines/zvision/scripting/actions.cpp index 9a2f1d10ff..81d6655fa9 100644 --- a/engines/zvision/scripting/actions.cpp +++ b/engines/zvision/scripting/actions.cpp @@ -21,6 +21,7 @@ */ #include "common/scummsys.h" +#include "common/tokenizer.h" #include "video/video_decoder.h" #include "zvision/scripting/actions.h" @@ -449,33 +450,40 @@ ActionMusic::ActionMusic(ZVision *engine, int32 slotkey, const Common::String &l _note(0), _prog(0), _universe(global) { - uint type = 0; - char fileNameBuffer[25]; - uint loop = 0; - uint volume = 255; + Common::StringTokenizer tokenizer(line); - sscanf(line.c_str(), "%u %24s %u %u", &type, fileNameBuffer, &loop, &volume); + // Parse the type of action. Type 4 actions are MIDI commands, not + // files. These are only used by Zork: Nemesis, for the flute and piano + // puzzles (tj4e and ve6f, as well as vr) + uint type = atoi(tokenizer.nextToken().c_str()); - // Type 4 actions are MIDI commands, not files. These are only used by - // Zork: Nemesis, for the flute and piano puzzles (tj4e and ve6f, as well - // as vr) if (type == 4) { _midi = true; - int note; - int prog; - sscanf(line.c_str(), "%u %d %d %u", &type, &prog, ¬e, &volume); - _volume = volume; - _note = note; - _prog = prog; + _prog = atoi(tokenizer.nextToken().c_str()); + _note = atoi(tokenizer.nextToken().c_str()); + _volume = atoi(tokenizer.nextToken().c_str()); + _volumeIsAKey = false; } else { _midi = false; - _fileName = Common::String(fileNameBuffer); - _loop = loop == 1 ? true : false; - - // Volume is optional. If it doesn't appear, assume full volume - if (volume != 255) { - // Volume in the script files is mapped to [0, 100], but the ScummVM mixer uses [0, 255] - _volume = volume * 255 / 100; + _fileName = tokenizer.nextToken(); + _loop = atoi(tokenizer.nextToken().c_str()) == 1; + if (!tokenizer.empty()) { + Common::String token = tokenizer.nextToken(); + if (token.contains('[')) { + sscanf(token.c_str(), "[%u]", &_volume); + _volumeIsAKey = true; + } else { + _volume = atoi(token.c_str()); + if (_volume > 100) { + warning("ActionMusic: Adjusting volume for %s from %d to 100", _fileName.c_str(), _volume); + _volume = 100; + } + _volumeIsAKey = false; + } + } else { + // Volume is optional. If it doesn't appear, assume full volume + _volume = 100; + _volumeIsAKey = false; } } } @@ -491,13 +499,22 @@ bool ActionMusic::execute() { _engine->getScriptManager()->setStateValue(_slotKey, 2); } + uint volume; + if (_volumeIsAKey) { + volume = _engine->getScriptManager()->getStateValue(_volume); + } else { + volume = _volume; + } + if (_midi) { - _engine->getScriptManager()->addSideFX(new MusicMidiNode(_engine, _slotKey, _prog, _note, _volume)); + _engine->getScriptManager()->addSideFX(new MusicMidiNode(_engine, _slotKey, _prog, _note, volume)); } else { if (!_engine->getSearchManager()->hasFile(_fileName)) return true; - _engine->getScriptManager()->addSideFX(new MusicNode(_engine, _slotKey, _fileName, _loop, _volume)); + // Volume in the script files is mapped to [0, 100], but the ScummVM mixer uses [0, 255] + + _engine->getScriptManager()->addSideFX(new MusicNode(_engine, _slotKey, _fileName, _loop, volume * 255 / 100)); } return true; diff --git a/engines/zvision/scripting/actions.h b/engines/zvision/scripting/actions.h index 8d43309b74..cbb91fa8d3 100644 --- a/engines/zvision/scripting/actions.h +++ b/engines/zvision/scripting/actions.h @@ -224,7 +224,8 @@ public: private: Common::String _fileName; bool _loop; - byte _volume; + uint32 _volume; + bool _volumeIsAKey; bool _universe; bool _midi; int8 _note; -- cgit v1.2.3 From bdd75f975df17679af140895f8c544cd019eeb61 Mon Sep 17 00:00:00 2001 From: Chris Apers Date: Mon, 26 Jan 2015 22:16:31 +0100 Subject: MORTEVIELLE: added missing inter screen messages --- engines/mortevielle/actions.cpp | 6 +++--- engines/mortevielle/mortevielle.h | 2 ++ engines/mortevielle/outtext.cpp | 24 ++++++++++++++++++++++++ engines/mortevielle/utils.cpp | 23 +++++++++++++++++++++++ 4 files changed, 52 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/mortevielle/actions.cpp b/engines/mortevielle/actions.cpp index 556475d515..b7b9c1e000 100644 --- a/engines/mortevielle/actions.cpp +++ b/engines/mortevielle/actions.cpp @@ -571,6 +571,7 @@ void MortevielleEngine::fctSearch() { _curSearchObjId = getFirstObject(); if (_curSearchObjId != 0) { _searchCount = 0; + _is = 0; _heroSearching = true; _menu->setSearchMenu(); prepareNextObject(); @@ -1678,9 +1679,8 @@ void MortevielleEngine::endGame() { handleDescriptionText(2, 35); startMusicOrSpeech(0); testKey(false); - // A wait message was displayed. - // testKey (aka tkey1) was called before and after. - // This double call is useless, thus removed + displayInterScreenMessage(2036); + testKey(false); resetVariables(); } diff --git a/engines/mortevielle/mortevielle.h b/engines/mortevielle/mortevielle.h index b0faff3510..f260edba09 100644 --- a/engines/mortevielle/mortevielle.h +++ b/engines/mortevielle/mortevielle.h @@ -416,6 +416,7 @@ public: int _maff; int _caff; int _crep; + int _is; // ??? byte _destinationArray[7][25]; @@ -466,6 +467,7 @@ public: void gameLoaded(); void initGame(); void displayAloneText(); + void displayInterScreenMessage(int mesgId); void draw(int x, int y); void charToHour(); void hourToChar(); diff --git a/engines/mortevielle/outtext.cpp b/engines/mortevielle/outtext.cpp index 6a479c0859..5cbe4deab3 100644 --- a/engines/mortevielle/outtext.cpp +++ b/engines/mortevielle/outtext.cpp @@ -227,7 +227,31 @@ void TextHandler::taffich() { Common::String filename, altFilename; if ((a != 50) && (a != 51)) { + int m = a + 2000; + + if ((m > 2001) && (m < 2010)) + m = 2001; + else if (m == 2011) + m = 2010; + if (a == 32) + m = 2034; + else if ((a == 17) && (_vm->_maff == 14)) + m = 2018; + else if (a > 99) { + if ((_vm->_is == 1) || (_vm->_is == 0)) + m = 2031; + else + m = 2032; + } + + if ( ((a > 69) && (a < 80)) || (a == 30) || (a == 31) || (a == 144) || (a == 147) || (a == 149) ) + m = 2030; + else if ( ((a < 27) && ( ((_vm->_maff > 69) && (!_vm->_coreVar._alreadyEnteredManor)) || (_vm->_maff > 99) )) || ((_vm->_maff > 29) && (_vm->_maff < 33)) ) + m = 2033; + + _vm->displayInterScreenMessage(m); _vm->_maff = a; + if (a == 159) a = 86; else if (a > 140) diff --git a/engines/mortevielle/utils.cpp b/engines/mortevielle/utils.cpp index aa58dc6f7c..74f2bc5897 100644 --- a/engines/mortevielle/utils.cpp +++ b/engines/mortevielle/utils.cpp @@ -1359,6 +1359,7 @@ void MortevielleEngine::endSearch() { _heroSearching = false; _obpart = false; _searchCount = 0; + _is = 0; _menu->unsetSearchMenu(); } @@ -1469,6 +1470,7 @@ void MortevielleEngine::gameLoaded() { _num = 0; _startTime = 0; _endTime = 0; + _is = 0; _searchCount = 0; _roomDoorId = OWN_ROOM; _syn = true; @@ -2988,6 +2990,26 @@ void MortevielleEngine::displayNarrativePicture(int af, int ob) { _crep = 998; } +/** + * Display a message switching from a screen to another. + * @remarks Originally called 'messint' + */ +void MortevielleEngine::displayInterScreenMessage(int mesgId) { + clearUpperLeftPart(); + clearDescriptionBar(); + clearVerbBar(); + + GfxSurface surface; + surface.decode(_rightFramePict + 1008); + surface._offset.x = 80; + surface._offset.y = 40; + setPal(90); + _screenSurface->drawPicture(surface, 0, 0); + _screenSurface->drawPicture(surface, 0, 70); + handleDescriptionText(7, mesgId); + delay(DISK_ACCESS_DELAY); +} + /** * Prepare Display Text * @remarks Originally called 'affrep' @@ -3196,6 +3218,7 @@ void MortevielleEngine::prepareNextObject() { } while ((objId == 0) && (_searchCount <= 9)); if ((objId != 0) && (_searchCount < 11)) { + _is++; _caff = objId; _crep = _caff + 400; if (_currBitIndex != 0) -- cgit v1.2.3 From dd5cd42f2eff7ca320fe507916b65a06c3a0ee74 Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Mon, 26 Jan 2015 22:07:47 +0100 Subject: ZVISION: Use ValueSlot for volume in ActionMusic As suggested by Marisa-Chan. I had based my earlier implementation on parseCritera(), and was unaware of this alternative. The good thing is that the diff from the old code is now much smaller, which should reduce the risk of regressions. (There is a lot I haven't tested here...) --- engines/zvision/scripting/actions.cpp | 64 +++++++++++++++-------------------- engines/zvision/scripting/actions.h | 3 +- 2 files changed, 28 insertions(+), 39 deletions(-) (limited to 'engines') diff --git a/engines/zvision/scripting/actions.cpp b/engines/zvision/scripting/actions.cpp index 81d6655fa9..d851a74dec 100644 --- a/engines/zvision/scripting/actions.cpp +++ b/engines/zvision/scripting/actions.cpp @@ -21,7 +21,6 @@ */ #include "common/scummsys.h" -#include "common/tokenizer.h" #include "video/video_decoder.h" #include "zvision/scripting/actions.h" @@ -446,51 +445,48 @@ bool ActionMenuBarEnable::execute() { ActionMusic::ActionMusic(ZVision *engine, int32 slotkey, const Common::String &line, bool global) : ResultAction(engine, slotkey), - _volume(255), _note(0), _prog(0), _universe(global) { - Common::StringTokenizer tokenizer(line); + uint type = 0; + char fileNameBuffer[25]; + uint loop = 0; + char volumeBuffer[15]; - // Parse the type of action. Type 4 actions are MIDI commands, not - // files. These are only used by Zork: Nemesis, for the flute and piano - // puzzles (tj4e and ve6f, as well as vr) - uint type = atoi(tokenizer.nextToken().c_str()); + // Volume is optional. If it doesn't appear, assume full volume + strcpy(volumeBuffer, "100"); + sscanf(line.c_str(), "%u %24s %u %14s", &type, fileNameBuffer, &loop, volumeBuffer); + + // Type 4 actions are MIDI commands, not files. These are only used by + // Zork: Nemesis, for the flute and piano puzzles (tj4e and ve6f, as well + // as vr) if (type == 4) { _midi = true; - _prog = atoi(tokenizer.nextToken().c_str()); - _note = atoi(tokenizer.nextToken().c_str()); - _volume = atoi(tokenizer.nextToken().c_str()); - _volumeIsAKey = false; + int note; + int prog; + sscanf(line.c_str(), "%u %d %d %14s", &type, &prog, ¬e, volumeBuffer); + _volume = new ValueSlot(_engine->getScriptManager(), volumeBuffer); + _note = note; + _prog = prog; } else { _midi = false; - _fileName = tokenizer.nextToken(); - _loop = atoi(tokenizer.nextToken().c_str()) == 1; - if (!tokenizer.empty()) { - Common::String token = tokenizer.nextToken(); - if (token.contains('[')) { - sscanf(token.c_str(), "[%u]", &_volume); - _volumeIsAKey = true; - } else { - _volume = atoi(token.c_str()); - if (_volume > 100) { - warning("ActionMusic: Adjusting volume for %s from %d to 100", _fileName.c_str(), _volume); - _volume = 100; - } - _volumeIsAKey = false; - } - } else { - // Volume is optional. If it doesn't appear, assume full volume - _volume = 100; - _volumeIsAKey = false; + _fileName = Common::String(fileNameBuffer); + _loop = loop == 1 ? true : false; + if (volumeBuffer[0] != '[' && atoi(volumeBuffer) > 100) { + // I thought I saw a case like this in Zork Nemesis, so + // let's guard against it. + warning("ActionMusic: Adjusting volume for %s from %s to 100", _fileName.c_str(), volumeBuffer); + strcpy(volumeBuffer, "100"); } + _volume = new ValueSlot(engine->getScriptManager(), volumeBuffer); } } ActionMusic::~ActionMusic() { if (!_universe) _engine->getScriptManager()->killSideFx(_slotKey); + delete _volume; } bool ActionMusic::execute() { @@ -499,12 +495,7 @@ bool ActionMusic::execute() { _engine->getScriptManager()->setStateValue(_slotKey, 2); } - uint volume; - if (_volumeIsAKey) { - volume = _engine->getScriptManager()->getStateValue(_volume); - } else { - volume = _volume; - } + uint volume = _volume->getValue(); if (_midi) { _engine->getScriptManager()->addSideFX(new MusicMidiNode(_engine, _slotKey, _prog, _note, volume)); @@ -513,7 +504,6 @@ bool ActionMusic::execute() { return true; // Volume in the script files is mapped to [0, 100], but the ScummVM mixer uses [0, 255] - _engine->getScriptManager()->addSideFX(new MusicNode(_engine, _slotKey, _fileName, _loop, volume * 255 / 100)); } diff --git a/engines/zvision/scripting/actions.h b/engines/zvision/scripting/actions.h index cbb91fa8d3..94c2d041fc 100644 --- a/engines/zvision/scripting/actions.h +++ b/engines/zvision/scripting/actions.h @@ -224,8 +224,7 @@ public: private: Common::String _fileName; bool _loop; - uint32 _volume; - bool _volumeIsAKey; + ValueSlot *_volume; bool _universe; bool _midi; int8 _note; -- cgit v1.2.3 From 8c8261aa2a381c3e7f12c5dd0aaf33a69e1f7eb3 Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Mon, 26 Jan 2015 22:14:26 +0100 Subject: ZVISION: Cleanup. We usually don't check a pointer before deleting it. --- engines/zvision/scripting/actions.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/zvision/scripting/actions.cpp b/engines/zvision/scripting/actions.cpp index d851a74dec..5238561149 100644 --- a/engines/zvision/scripting/actions.cpp +++ b/engines/zvision/scripting/actions.cpp @@ -79,8 +79,7 @@ ActionAssign::ActionAssign(ZVision *engine, int32 slotkey, const Common::String } ActionAssign::~ActionAssign() { - if (_value) - delete _value; + delete _value; } bool ActionAssign::execute() { @@ -804,8 +803,7 @@ ActionRandom::ActionRandom(ZVision *engine, int32 slotkey, const Common::String } ActionRandom::~ActionRandom() { - if (_max) - delete _max; + delete _max; } bool ActionRandom::execute() { @@ -1044,8 +1042,7 @@ ActionTimer::ActionTimer(ZVision *engine, int32 slotkey, const Common::String &l } ActionTimer::~ActionTimer() { - if (_time) - delete _time; + delete _time; _engine->getScriptManager()->killSideFx(_slotKey); } -- cgit v1.2.3 From 21a66189194d277a98b8337cc077c11179d81d34 Mon Sep 17 00:00:00 2001 From: Strangerke Date: Mon, 26 Jan 2015 22:30:51 +0100 Subject: VOYEUR: Add missing break --- engines/voyeur/files_threads.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines') diff --git a/engines/voyeur/files_threads.cpp b/engines/voyeur/files_threads.cpp index 0615c67ba0..53eb5ce3c5 100644 --- a/engines/voyeur/files_threads.cpp +++ b/engines/voyeur/files_threads.cpp @@ -1082,6 +1082,7 @@ int ThreadResource::doApt() { break; case 2: _vm->_voy->_aptLoadMode = 142; + break; case 5: _vm->_voy->_aptLoadMode = 141; break; -- cgit v1.2.3 From b336e9b12c819d663484a044ea5730a8ec1aa01e Mon Sep 17 00:00:00 2001 From: Strangerke Date: Mon, 26 Jan 2015 22:51:41 +0100 Subject: TSAGE: BF - Remove unused variable --- engines/tsage/blue_force/blueforce_scenes8.cpp | 3 ++- engines/tsage/blue_force/blueforce_scenes8.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/tsage/blue_force/blueforce_scenes8.cpp b/engines/tsage/blue_force/blueforce_scenes8.cpp index 6855fd41b9..698162c71d 100644 --- a/engines/tsage/blue_force/blueforce_scenes8.cpp +++ b/engines/tsage/blue_force/blueforce_scenes8.cpp @@ -964,9 +964,10 @@ Scene810::Scene810(): SceneExt() { } void Scene810::synchronize(Serializer &s) { + int dummy = 0; SceneExt::synchronize(s); s.syncAsSint16LE(_fieldA70); - s.syncAsSint16LE(_fieldA72); + s.syncAsSint16LE(dummy); s.syncAsSint16LE(_fieldA74); } diff --git a/engines/tsage/blue_force/blueforce_scenes8.h b/engines/tsage/blue_force/blueforce_scenes8.h index 140327e85d..09de14f150 100644 --- a/engines/tsage/blue_force/blueforce_scenes8.h +++ b/engines/tsage/blue_force/blueforce_scenes8.h @@ -229,7 +229,7 @@ public: Exit _exit; ASoundExt _sound1; Rect _rect1, _rect2, _rect3; - int _fieldA70, _fieldA72, _fieldA74; + int _fieldA70, _fieldA74; Scene810(); virtual void synchronize(Serializer &s); -- cgit v1.2.3 From 46c3b8c3187736e12c433104de7ad247f31534a5 Mon Sep 17 00:00:00 2001 From: Strangerke Date: Mon, 26 Jan 2015 22:59:04 +0100 Subject: TSAGE: Ringworld - Fix unitialized variable --- engines/tsage/blue_force/blueforce_scenes8.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines') diff --git a/engines/tsage/blue_force/blueforce_scenes8.cpp b/engines/tsage/blue_force/blueforce_scenes8.cpp index 698162c71d..337e73dad0 100644 --- a/engines/tsage/blue_force/blueforce_scenes8.cpp +++ b/engines/tsage/blue_force/blueforce_scenes8.cpp @@ -2221,6 +2221,7 @@ Scene840::Scene840(): PalettedScene() { _field1AC2 = 0; _field1AC4 = 0; _field1AC6 = (BF_GLOBALS._dayNumber > 3) ? 1 : 0; + _field1ABA = 0; } void Scene840::synchronize(Serializer &s) { -- cgit v1.2.3 From 3e8456e0f861b968410c3ab4a750be52f522b743 Mon Sep 17 00:00:00 2001 From: Strangerke Date: Mon, 26 Jan 2015 22:59:32 +0100 Subject: TSAGE: Ringworld - Fix unitialized variable --- engines/tsage/ringworld/ringworld_scenes3.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines') diff --git a/engines/tsage/ringworld/ringworld_scenes3.cpp b/engines/tsage/ringworld/ringworld_scenes3.cpp index d8556c691e..735722a062 100644 --- a/engines/tsage/ringworld/ringworld_scenes3.cpp +++ b/engines/tsage/ringworld/ringworld_scenes3.cpp @@ -5789,6 +5789,7 @@ Scene2320::Scene2320() : _area3._pt = Common::Point(200, 75); _area4.setup(2153, 1, 1, 10); _area4._pt = Common::Point(237, 77); + _hotspotPtr = nullptr; } void Scene2320::postInit(SceneObjectList *OwnerList) { -- cgit v1.2.3 From 27febf8574c81c43375067346f9733df37f2d6d2 Mon Sep 17 00:00:00 2001 From: Strangerke Date: Mon, 26 Jan 2015 23:13:40 +0100 Subject: TSAGE: Ringworld - Declare _sitFl as a boolean --- engines/tsage/ringworld/ringworld_scenes3.cpp | 13 +++++++------ engines/tsage/ringworld/ringworld_scenes3.h | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) (limited to 'engines') diff --git a/engines/tsage/ringworld/ringworld_scenes3.cpp b/engines/tsage/ringworld/ringworld_scenes3.cpp index 735722a062..a515224964 100644 --- a/engines/tsage/ringworld/ringworld_scenes3.cpp +++ b/engines/tsage/ringworld/ringworld_scenes3.cpp @@ -494,7 +494,7 @@ void Scene2100::Action1::signal() { setDelay(1); else { setAction(&scene->_sequenceManager, this, 2102, &g_globals->_player, NULL); - scene->_sitFl = 0; + scene->_sitFl = false; } break; case 1: { @@ -1548,6 +1548,7 @@ Scene2100::Scene2100() : _area3._pt = Common::Point(200, 75); _area4.setup(2153, 1, 1, OBJECT_TRANSLATOR); _area4._pt = Common::Point(237, 77); + _sitFl = false; } void Scene2100::postInit(SceneObjectList *OwnerList) { @@ -1688,7 +1689,7 @@ void Scene2100::postInit(SceneObjectList *OwnerList) { g_globals->_player._moveDiff.x = 4; g_globals->_player.changeZoom(-1); g_globals->_player.disableControl(); - _sitFl = 0; + _sitFl = false; switch (g_globals->_sceneManager._previousScene) { case 2120: @@ -1824,7 +1825,7 @@ void Scene2100::postInit(SceneObjectList *OwnerList) { g_globals->_player.fixPriority(152); g_globals->_player.setStrip(2); - _sitFl = 1; + _sitFl = true; _object4.postInit(); _object4.setVisage(2102); @@ -1858,7 +1859,7 @@ void Scene2100::postInit(SceneObjectList *OwnerList) { g_globals->_player.fixPriority(152); g_globals->_player.setStrip(2); - _sitFl = 1; + _sitFl = true; setAction(&_action16); } break; @@ -1932,12 +1933,12 @@ void Scene2100::stripCallback(int v) { void Scene2100::signal() { switch (_sceneMode) { case 2101: - _sitFl = 1; + _sitFl = true; g_globals->_player._uiEnabled = true; g_globals->_events.setCursor(CURSOR_USE); break; case 2102: - _sitFl = 0; + _sitFl = false; g_globals->_player.enableControl(); break; case 2103: diff --git a/engines/tsage/ringworld/ringworld_scenes3.h b/engines/tsage/ringworld/ringworld_scenes3.h index a371f800b9..752b6acd48 100644 --- a/engines/tsage/ringworld/ringworld_scenes3.h +++ b/engines/tsage/ringworld/ringworld_scenes3.h @@ -283,7 +283,7 @@ public: Action15 _action15; Action16 _action16; Action17 _action17; - int _sitFl; + bool _sitFl; SceneArea _area1, _area2, _area3, _area4; Scene2100(); -- cgit v1.2.3 From 7ebd6c974cb0aed319b2f7c6a38f909a920b4e6c Mon Sep 17 00:00:00 2001 From: Strangerke Date: Mon, 26 Jan 2015 23:14:16 +0100 Subject: VOYEUR: Fix bug in vDoCycleInt --- engines/voyeur/events.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/voyeur/events.cpp b/engines/voyeur/events.cpp index 7ce7351e65..320c92283c 100644 --- a/engines/voyeur/events.cpp +++ b/engines/voyeur/events.cpp @@ -403,7 +403,7 @@ void EventsManager::vDoCycleInt() { int palIndex = READ_LE_UINT16(pSrc); pPal[palIndex * 3] = pSrc[3]; pPal[palIndex * 3 + 1] = pSrc[4]; - pPal[palIndex * 3 + 1] = pSrc[5]; + pPal[palIndex * 3 + 2] = pSrc[5]; pSrc += 6; if ((int16)READ_LE_UINT16(pSrc) >= 0) { -- cgit v1.2.3 From e8c9a828da890fb6803629e66f18f9096ca03e8e Mon Sep 17 00:00:00 2001 From: Strangerke Date: Mon, 26 Jan 2015 23:14:42 +0100 Subject: TSAGE: Fix 3 uninitialized variables --- engines/tsage/core.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'engines') diff --git a/engines/tsage/core.cpp b/engines/tsage/core.cpp index f35aa583e2..3105a9008e 100644 --- a/engines/tsage/core.cpp +++ b/engines/tsage/core.cpp @@ -56,6 +56,9 @@ InvObject::InvObject(int sceneNumber, int rlbNum, int cursorNum, CursorType curs _bounds = s.getBounds(); DEALLOCATE(imgData); + _visage = 0; + _strip = 0; + _frame = 0; } InvObject::InvObject(int visage, int strip, int frame) { -- cgit v1.2.3 From 50be542f9cacc7eba5879d8279d65b2637205b1d Mon Sep 17 00:00:00 2001 From: Strangerke Date: Mon, 26 Jan 2015 23:33:26 +0100 Subject: TSAGE: BF - Fix a glitch in scene 935 --- engines/tsage/blue_force/blueforce_scenes9.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/tsage/blue_force/blueforce_scenes9.cpp b/engines/tsage/blue_force/blueforce_scenes9.cpp index 53000d6997..fcbfcb8cd7 100644 --- a/engines/tsage/blue_force/blueforce_scenes9.cpp +++ b/engines/tsage/blue_force/blueforce_scenes9.cpp @@ -3521,7 +3521,7 @@ void Scene935::Action1::signal() { scene->_visualSpeaker.removeText(); scene->_visualSpeaker._textPos.y = scene->_sceneBounds.top + 80; scene->_visualSpeaker._color1 = 252; - scene->_visualSpeaker._color1 = 251; + scene->_visualSpeaker._color2 = 251; scene->_visualSpeaker.setText("Jake! Hide in the closet!"); setDelay(3); break; -- cgit v1.2.3 From f2e3bdd2e887aac3f749184bf31c41da6cb571d8 Mon Sep 17 00:00:00 2001 From: Strangerke Date: Mon, 26 Jan 2015 23:34:48 +0100 Subject: TSAGE: BF - Fix another color glitch --- engines/tsage/blue_force/blueforce_scenes9.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/tsage/blue_force/blueforce_scenes9.cpp b/engines/tsage/blue_force/blueforce_scenes9.cpp index fcbfcb8cd7..5ba82a4714 100644 --- a/engines/tsage/blue_force/blueforce_scenes9.cpp +++ b/engines/tsage/blue_force/blueforce_scenes9.cpp @@ -3538,7 +3538,7 @@ void Scene935::Action1::signal() { scene->_visualSpeaker.removeText(); scene->_visualSpeaker._textPos.y = scene->_sceneBounds.top + 150; scene->_visualSpeaker._color1 = 250; - scene->_visualSpeaker._color1 = 249; + scene->_visualSpeaker._color2 = 249; scene->_visualSpeaker.setText("Jake! Hide in the closet!"); setDelay(3); break; -- cgit v1.2.3 From 77302c406f5fa3641ff7dd3454d8b87d43274c86 Mon Sep 17 00:00:00 2001 From: Strangerke Date: Tue, 27 Jan 2015 07:02:46 +0100 Subject: ACCESS: Initialize some variables --- engines/access/access.cpp | 3 +++ engines/access/files.cpp | 4 ++++ engines/access/files.h | 2 +- 3 files changed, 8 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/access/access.cpp b/engines/access/access.cpp index 7f59ae7ad6..0a4e519c91 100644 --- a/engines/access/access.cpp +++ b/engines/access/access.cpp @@ -94,6 +94,9 @@ AccessEngine::AccessEngine(OSystem *syst, const AccessGameDescription *gameDesc) _cheatFl = false; _restartFl = false; _printEnd = 0; + for (int i = 0; i < 100; i++) + _objectsTable[i] = nullptr; + _clearSummaryFlag = false; } AccessEngine::~AccessEngine() { diff --git a/engines/access/files.cpp b/engines/access/files.cpp index 42a7914638..4d734a67a9 100644 --- a/engines/access/files.cpp +++ b/engines/access/files.cpp @@ -40,6 +40,10 @@ void FileIdent::load(Common::SeekableReadStream &s) { /*------------------------------------------------------------------------*/ +CellIdent:: CellIdent() { + _cell = 0; +} + CellIdent::CellIdent(int cell, int fileNum, int subfile) { _cell = cell; _fileNum = fileNum; diff --git a/engines/access/files.h b/engines/access/files.h index 8b1aef0363..714ea44c75 100644 --- a/engines/access/files.h +++ b/engines/access/files.h @@ -46,7 +46,7 @@ struct FileIdent { struct CellIdent : FileIdent { byte _cell; - CellIdent() {} + CellIdent(); CellIdent(int cell, int fileNum, int subfile); }; -- cgit v1.2.3 From 849f383169d57b0dee7b33ab0c2166007b50b8c2 Mon Sep 17 00:00:00 2001 From: Strangerke Date: Tue, 27 Jan 2015 07:14:55 +0100 Subject: MADE: Initialize some variables, remove a useless variable --- engines/made/script.cpp | 5 +++++ engines/made/script.h | 1 - engines/made/scriptfuncs.cpp | 2 ++ 3 files changed, 7 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/made/script.cpp b/engines/made/script.cpp index 20fa026a40..f9f7acffde 100644 --- a/engines/made/script.cpp +++ b/engines/made/script.cpp @@ -122,6 +122,11 @@ ScriptInterpreter::ScriptInterpreter(MadeEngine *vm) : _vm(vm) { _functions = new ScriptFunctions(_vm); _functions->setupExternalsTable(); + _localStackPos = 0; + _runningScriptObjectIndex = 0; + _codeBase = nullptr; + _codeIp = nullptr; + #undef COMMAND } diff --git a/engines/made/script.h b/engines/made/script.h index bf75bc0875..f28425d13b 100644 --- a/engines/made/script.h +++ b/engines/made/script.h @@ -84,7 +84,6 @@ protected: int16 _localStackPos; int16 _runningScriptObjectIndex; byte *_codeBase, *_codeIp; - bool _terminated; ScriptFunctions *_functions; diff --git a/engines/made/scriptfuncs.cpp b/engines/made/scriptfuncs.cpp index efa765c7eb..bcc08e0dcc 100644 --- a/engines/made/scriptfuncs.cpp +++ b/engines/made/scriptfuncs.cpp @@ -42,6 +42,8 @@ ScriptFunctions::ScriptFunctions(MadeEngine *vm) : _vm(vm), _soundStarted(false) _pcSpeaker2 = new Audio::PCSpeaker(); _vm->_system->getMixer()->playStream(Audio::Mixer::kMusicSoundType, &_pcSpeakerHandle1, _pcSpeaker1); _vm->_system->getMixer()->playStream(Audio::Mixer::kMusicSoundType, &_pcSpeakerHandle2, _pcSpeaker2); + _soundResource = nullptr; + _musicRes = nullptr; } ScriptFunctions::~ScriptFunctions() { -- cgit v1.2.3 From a1a99745f6f120354c0565e96e0636c0d303ed52 Mon Sep 17 00:00:00 2001 From: Strangerke Date: Tue, 27 Jan 2015 07:21:52 +0100 Subject: MADE: Initialize some more variables, remove an useless variable --- engines/made/resource.cpp | 4 ++++ engines/made/screenfx.cpp | 7 ++++++- engines/made/screenfx.h | 1 - 3 files changed, 10 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/made/resource.cpp b/engines/made/resource.cpp index 2c75965976..f8e763e74e 100644 --- a/engines/made/resource.cpp +++ b/engines/made/resource.cpp @@ -241,6 +241,7 @@ void AnimationResource::load(byte *source, int size) { /* SoundResource */ SoundResource::SoundResource() : _soundSize(0), _soundData(NULL) { + _soundEnergyArray = nullptr; } SoundResource::~SoundResource() { @@ -377,6 +378,9 @@ void GenericResource::load(byte *source, int size) { ResourceReader::ResourceReader() { _isV1 = false; _cacheDataSize = 0; + + _fd = _fdMusic = _fdPics = _fdSounds = nullptr; + _cacheCount = 0; } ResourceReader::~ResourceReader() { diff --git a/engines/made/screenfx.cpp b/engines/made/screenfx.cpp index 2a155d67ac..3f98cbb9ab 100644 --- a/engines/made/screenfx.cpp +++ b/engines/made/screenfx.cpp @@ -51,7 +51,12 @@ ScreenEffects::ScreenEffects(Screen *screen) : _screen(screen) { vfxHeight = 0; _fxPalette = new byte[768]; - + + _blendedPaletteStatus._active = false; + _blendedPaletteStatus._palette = _blendedPaletteStatus._newPalette = nullptr; + _blendedPaletteStatus._colorCount = 0; + _blendedPaletteStatus._value = _blendedPaletteStatus._maxValue = 0; + _blendedPaletteStatus._incr = 0; } ScreenEffects::~ScreenEffects() { diff --git a/engines/made/screenfx.h b/engines/made/screenfx.h index fd216bfd63..cedb059927 100644 --- a/engines/made/screenfx.h +++ b/engines/made/screenfx.h @@ -38,7 +38,6 @@ struct BlendedPaletteStatus { byte *_palette, *_newPalette; int _colorCount; int16 _value, _maxValue, _incr; - int cnt; }; class ScreenEffects { -- cgit v1.2.3 From d928871f7a03b410f4fcac43c44315e2f999efc9 Mon Sep 17 00:00:00 2001 From: Chris Apers Date: Tue, 27 Jan 2015 20:48:31 +0100 Subject: MORTEVIELLE: added starting screen To give credits to the original authors and developers. --- engines/mortevielle/utils.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'engines') diff --git a/engines/mortevielle/utils.cpp b/engines/mortevielle/utils.cpp index 74f2bc5897..49e1777c5e 100644 --- a/engines/mortevielle/utils.cpp +++ b/engines/mortevielle/utils.cpp @@ -1726,6 +1726,22 @@ void MortevielleEngine::showMoveMenuAlert() { * @remarks Originally called 'dialpre' */ void MortevielleEngine::showConfigScreen() { + // FIXME: need a DOS palette, index 9 (light blue). Also we should show DOS font here + Common::String tmpStr; + int width, cy = 0; + clearScreen(); + do { + ++cy; + tmpStr = getString(cy + 456); + width = _screenSurface->getStringWidth(tmpStr); + _text->displayStr(tmpStr, 320 - width / 2, cy * 8, 80, 1, 2); + } while (cy != 20); + + int ix = 0; + do { + ++ix; + } while (!(keyPressed() || ix == 0x5e5)); + _crep = 998; } @@ -2132,6 +2148,7 @@ void MortevielleEngine::showTitleScreen() { clearScreen(); draw(0, 0); + // FIXME: should be a DOS font here Common::String cpr = "COPYRIGHT 1989 : LANKHOR"; _screenSurface->putxy(104 + 72 * kResolutionScaler, 185); _screenSurface->drawString(cpr, 0); -- cgit v1.2.3 From 58565c43da24553bfd9bea4e58de2d9191993ed3 Mon Sep 17 00:00:00 2001 From: Chris Apers Date: Tue, 27 Jan 2015 20:55:47 +0100 Subject: MORTEVIELLE: added starting screen string index constant --- engines/mortevielle/mortevielle.h | 1 + engines/mortevielle/utils.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mortevielle/mortevielle.h b/engines/mortevielle/mortevielle.h index f260edba09..42d70fcb37 100644 --- a/engines/mortevielle/mortevielle.h +++ b/engines/mortevielle/mortevielle.h @@ -116,6 +116,7 @@ const int kInventoryStringIndex = 186; const int kQuestionStringIndex = 247; const int kDialogStringIndex = 292; const int kMenuPlaceStringIndex = 435; +const int kStartingScreenStringIndex = 456; const int kMenuActionStringIndex = 476; const int kMenuSelfStringIndex = 497; const int kMenuSayStringIndex = 502; diff --git a/engines/mortevielle/utils.cpp b/engines/mortevielle/utils.cpp index 49e1777c5e..5fe47674c8 100644 --- a/engines/mortevielle/utils.cpp +++ b/engines/mortevielle/utils.cpp @@ -1732,7 +1732,7 @@ void MortevielleEngine::showConfigScreen() { clearScreen(); do { ++cy; - tmpStr = getString(cy + 456); + tmpStr = getString(cy + kStartingScreenStringIndex); width = _screenSurface->getStringWidth(tmpStr); _text->displayStr(tmpStr, 320 - width / 2, cy * 8, 80, 1, 2); } while (cy != 20); -- cgit v1.2.3 From f46af2eded0155a05d0e19717e6c4efd1191dab3 Mon Sep 17 00:00:00 2001 From: Marisa-Chan Date: Wed, 28 Jan 2015 09:26:45 +0600 Subject: ZVISION: Fix bug #6787 init lzss window by same values as in original game --- engines/zvision/file/lzss_read_stream.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/zvision/file/lzss_read_stream.cpp b/engines/zvision/file/lzss_read_stream.cpp index 6f27eaa765..ca10af7d72 100644 --- a/engines/zvision/file/lzss_read_stream.cpp +++ b/engines/zvision/file/lzss_read_stream.cpp @@ -31,8 +31,9 @@ LzssReadStream::LzssReadStream(Common::SeekableReadStream *source) // It's convention to set the starting cursor position to blockSize - 16 _windowCursor(0x0FEE), _eosFlag(false) { - // Clear the window to null - memset(_window, 0, BLOCK_SIZE); + // All values up to _windowCursor inits by 0x20 + memset(_window, 0x20, _windowCursor); + memset(_window + _windowCursor, 0, BLOCK_SIZE - _windowCursor); } uint32 LzssReadStream::decompressBytes(byte *destination, uint32 numberOfBytes) { -- cgit v1.2.3 From ae2ba18af360b5578eaa38ac7aacce3264f8d7bf Mon Sep 17 00:00:00 2001 From: Strangerke Date: Wed, 28 Jan 2015 07:47:28 +0100 Subject: MADE: Initialize some variables --- engines/made/database.cpp | 6 ++++++ engines/made/pmvplayer.cpp | 15 ++++++++++----- engines/made/redreader.cpp | 16 ++++++++++++++++ 3 files changed, 32 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/made/database.cpp b/engines/made/database.cpp index a9855ba1fe..3eab31acc2 100644 --- a/engines/made/database.cpp +++ b/engines/made/database.cpp @@ -252,6 +252,10 @@ byte *ObjectV3::getData() { GameDatabase::GameDatabase(MadeEngine *vm) : _vm(vm) { + _gameState = nullptr; + _gameStateSize = 0; + _mainCodeObjectIndex = 0; + _isRedSource = false; } GameDatabase::~GameDatabase() { @@ -595,6 +599,8 @@ const char *GameDatabaseV2::getString(uint16 offset) { /* GameDatabaseV3 */ GameDatabaseV3::GameDatabaseV3(MadeEngine *vm) : GameDatabase(vm) { + _gameText = nullptr; + _gameStateOffs = 0; } void GameDatabaseV3::load(Common::SeekableReadStream &sourceS) { diff --git a/engines/made/pmvplayer.cpp b/engines/made/pmvplayer.cpp index 3cac017e10..6ea0dc24d0 100644 --- a/engines/made/pmvplayer.cpp +++ b/engines/made/pmvplayer.cpp @@ -37,16 +37,18 @@ namespace Made { -PmvPlayer::PmvPlayer(MadeEngine *vm, Audio::Mixer *mixer) : _fd(NULL), _vm(vm), _mixer(mixer) { +PmvPlayer::PmvPlayer(MadeEngine *vm, Audio::Mixer *mixer) : _fd(nullptr), _vm(vm), _mixer(mixer) { + _audioStream = nullptr; + _surface = nullptr; + _aborted = false; } PmvPlayer::~PmvPlayer() { } bool PmvPlayer::play(const char *filename) { - _aborted = false; - _surface = NULL; + _surface = nullptr; _fd = new Common::File(); if (!_fd->open(filename)) { @@ -81,8 +83,11 @@ bool PmvPlayer::play(const char *filename) { // results to sound being choppy. Therefore, we set them to more // "common" values here (11025 instead of 11127 and 22050 instead // of 22254) - if (soundFreq == 11127) soundFreq = 11025; - if (soundFreq == 22254) soundFreq = 22050; + if (soundFreq == 11127) + soundFreq = 11025; + + if (soundFreq == 22254) + soundFreq = 22050; for (int i = 0; i < 22; i++) { int unk = _fd->readUint16LE(); diff --git a/engines/made/redreader.cpp b/engines/made/redreader.cpp index f5e6ca85b3..f92ffd8dd8 100644 --- a/engines/made/redreader.cpp +++ b/engines/made/redreader.cpp @@ -76,6 +76,22 @@ bool RedReader::seekFile(Common::File &fd, FileEntry &fileEntry, const char *fil } LzhDecompressor::LzhDecompressor() { + freq = nullptr; + len_table = nullptr; + sortptr = nullptr; + _source = nullptr; + + _compSize = 0; + _blockPos = 0; + _bitbuf = 0; + _subbitbuf = 0; + _bitcount = 0; + _blocksize = 0; + tree_n = 0; + heapsize = 0; + decode_i = 0; + decode_j = 0; + count_len_depth = 0; } LzhDecompressor::~LzhDecompressor() { -- cgit v1.2.3 From a48a6ad30e52f52793ba9b09271146f2553a656d Mon Sep 17 00:00:00 2001 From: johndoe123 Date: Thu, 22 Jan 2015 13:06:02 +0100 Subject: BBVS: Implement loading and saving in the air guitar minigame --- engines/bbvs/minigames/bbairguitar.cpp | 113 ++++++++++++++++++++++++++++++++- engines/bbvs/minigames/bbairguitar.h | 11 +++- 2 files changed, 120 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/bbvs/minigames/bbairguitar.cpp b/engines/bbvs/minigames/bbairguitar.cpp index 1984dbb0fd..6f198cb42a 100644 --- a/engines/bbvs/minigames/bbairguitar.cpp +++ b/engines/bbvs/minigames/bbairguitar.cpp @@ -22,6 +22,12 @@ #include "bbvs/minigames/bbairguitar.h" +#include "common/savefile.h" +#include "common/translation.h" + +#include "gui/dialog.h" +#include "gui/message.h" + namespace Bbvs { static const char * const kNoteSoundFilenames[] = { @@ -805,7 +811,7 @@ void MinigameBbAirGuitar::update() { } if (_vm->_keyCode == Common::KEYCODE_ESCAPE) { - _gameDone = true; + _gameDone = querySaveModifiedTracks(); return; } @@ -925,7 +931,8 @@ void MinigameBbAirGuitar::afterButtonReleased() { break; case 4: *_currFrameIndex = 1; - // TODO Run load dialog + loadTracks(); + _objects[1].kind = 0; break; case 5: _objects[3].kind = 0; @@ -950,7 +957,8 @@ void MinigameBbAirGuitar::afterButtonReleased() { break; case 12: *_currFrameIndex = 1; - // TODO Run save dialog + saveTracks(); + _objects[2].kind = 0; break; case 13: _objects[4].kind = 0; @@ -1195,4 +1203,103 @@ void MinigameBbAirGuitar::stopNote(int noteNum) { stopSound(2 + _currPatchNum * kNoteSoundFilenamesCount + noteNum); } +bool MinigameBbAirGuitar::getLoadFilename(Common::String &filename) { + // TODO Run dialog and return actual filename + filename = "test.air"; + return true; +} + +bool MinigameBbAirGuitar::getSaveFilename(Common::String &filename) { + // TODO Run dialog and return actual filename + filename = "test.air"; + return true; +} + +bool MinigameBbAirGuitar::querySaveModifiedDialog() { + /* NOTE The original button captions don't fit so shortened variants are used + Original ok button caption: "Yeah, heh, heh, save it!" + Original discard button caption: "Who cares? It sucked!" + */ + GUI::MessageDialog query(_("Hey Beavis - you didn't save that last Jam!"), + _("Save it!"), + _("It sucked!")); + return query.runModal() == GUI::kMessageOK; +} + +bool MinigameBbAirGuitar::querySaveModifiedTracks() { + if (_modified && querySaveModifiedDialog()) { + if (!saveTracks()) + return false; + } + return true; +} + +bool MinigameBbAirGuitar::loadTracks() { + if (_playerMode != 0) + return false; + + if (!querySaveModifiedTracks()) + return false; + + Common::String filename; + if (!getLoadFilename(filename)) + return false; + + Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); + Common::InSaveFile *stream = saveFileMan->openForLoading(filename); + if (!loadFromStream(stream)) { + Common::String msg = Common::String::format("%s is not a valid Air Guitar file", filename.c_str()); + GUI::MessageDialog dialog(msg); + dialog.runModal(); + } + delete stream; + + return true; +} + +bool MinigameBbAirGuitar::saveTracks() { + if (_playerMode != 0) + return false; + + Common::String filename; + if (!getSaveFilename(filename)) + return false; + + Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); + Common::OutSaveFile *stream = saveFileMan->openForSaving(filename); + saveToStream(stream); + delete stream; + _modified = false; + + return true; +} + +bool MinigameBbAirGuitar::loadFromStream(Common::ReadStream *stream) { + uint32 magic = stream->readUint32BE(); + if (magic != MKTAG('A', 'I', 'R', 'G')) + return false; + for (uint i = 0; i < kMaxTracks; ++i) { + _track[i].noteNum = stream->readByte(); + _track[i].ticks = stream->readUint16LE(); + } + _trackCount = 0; + _actionTrackPos = 0; + while (_track[_trackCount].noteNum != -1) { + _actionTrackPos += _track[_trackCount].ticks; + ++_trackCount; + } + _totalTrackLength = _actionTrackPos; + _trackIndex = 0; + _currTrackPos = 0; + return true; +} + +void MinigameBbAirGuitar::saveToStream(Common::WriteStream *stream) { + stream->writeUint32BE(MKTAG('A', 'I', 'R', 'G')); + for (uint i = 0; i < kMaxTracks; ++i) { + stream->writeByte(_track[i].noteNum); + stream->writeUint16LE(_track[i].ticks); + } +} + } // End of namespace Bbvs diff --git a/engines/bbvs/minigames/bbairguitar.h b/engines/bbvs/minigames/bbairguitar.h index 40b8a50a03..b8b92ef433 100644 --- a/engines/bbvs/minigames/bbairguitar.h +++ b/engines/bbvs/minigames/bbairguitar.h @@ -47,7 +47,7 @@ public: enum { kMaxObjectsCount = 256, - kMaxTracks = 2049 + kMaxTracks = 2048 }; struct PianoKeyInfo { @@ -141,6 +141,15 @@ public: void playNote(int noteNum); void stopNote(int noteNum); + bool getLoadFilename(Common::String &filename); + bool getSaveFilename(Common::String &filename); + bool querySaveModifiedDialog(); + bool querySaveModifiedTracks(); + bool loadTracks(); + bool saveTracks(); + bool loadFromStream(Common::ReadStream *stream); + void saveToStream(Common::WriteStream *stream); + }; } // End of namespace Bbvs -- cgit v1.2.3 From ebc5c55ce3d22f6e353bce07d1d797176a641208 Mon Sep 17 00:00:00 2001 From: Chris Apers Date: Thu, 29 Jan 2015 12:47:23 +0100 Subject: MORTEVIELLE: fixed text position Checked against french and german versions. “Your are alone†text isn’t centred in original code. --- engines/mortevielle/utils.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/mortevielle/utils.cpp b/engines/mortevielle/utils.cpp index 5fe47674c8..5137e1892b 100644 --- a/engines/mortevielle/utils.cpp +++ b/engines/mortevielle/utils.cpp @@ -707,11 +707,11 @@ void MortevielleEngine::displayAloneText() { Common::String sAlone = getEngineString(S_ALONE); clearUpperRightPart(); - _screenSurface->putxy(580 - (_screenSurface->getStringWidth(sYou) / 2), 30); + _screenSurface->putxy(560, 30); _screenSurface->drawString(sYou, 4); - _screenSurface->putxy(580 - (_screenSurface->getStringWidth(sAre) / 2), 50); + _screenSurface->putxy(560, 50); _screenSurface->drawString(sAre, 4); - _screenSurface->putxy(580 - (_screenSurface->getStringWidth(sAlone) / 2), 70); + _screenSurface->putxy(560, 70); _screenSurface->drawString(sAlone, 4); _currBitIndex = 0; @@ -1695,7 +1695,7 @@ void MortevielleEngine::clearUpperRightPart() { else if (_coreVar._faithScore > 65) st = getEngineString(S_MALSAINE); - int x1 = 580 - (_screenSurface->getStringWidth(st) / 2); + int x1 = 574 - (_screenSurface->getStringWidth(st) / 2); _screenSurface->putxy(x1, 92); _screenSurface->drawString(st, 4); -- cgit v1.2.3 From c0b2d47f383984d7f36743b9b8b51fd23e34632a Mon Sep 17 00:00:00 2001 From: Strangerke Date: Sat, 31 Jan 2015 12:10:55 +0100 Subject: MADS: Add safeguards in DialogsNebular::show --- engines/mads/nebular/dialogs_nebular.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'engines') diff --git a/engines/mads/nebular/dialogs_nebular.cpp b/engines/mads/nebular/dialogs_nebular.cpp index 74da378128..b3d3e0687d 100644 --- a/engines/mads/nebular/dialogs_nebular.cpp +++ b/engines/mads/nebular/dialogs_nebular.cpp @@ -91,6 +91,8 @@ bool DialogsNebular::show(int messageId, int objectId) { dialog->incNumLines(); } } else if (commandCheck("ASK", valStr, commandText)) { + if (!dialog) + error("DialogsNebular::show - Uninitialized dialog"); dialog->addInput(); } else if (commandCheck("VERB", valStr, commandText)) { dialogText += getVocab(action._activeAction._verbId); @@ -114,12 +116,18 @@ bool DialogsNebular::show(int messageId, int objectId) { } else if (commandCheck("WIDTH", valStr, commandText)) { _dialogWidth = atoi(valStr.c_str()); } else if (commandCheck("BAR", valStr, commandText)) { + if (!dialog) + error("DialogsNebular::show - Uninitialized dialog"); dialog->addBarLine(); } else if (commandCheck("UNDER", valStr, commandText)) { underlineFlag = true; } else if (commandCheck("DOWN", valStr, commandText)) { + if (!dialog) + error("DialogsNebular::show - Uninitialized dialog"); dialog->downPixelLine(); } else if (commandCheck("TAB", valStr, commandText)) { + if (!dialog) + error("DialogsNebular::show - Uninitialized dialog"); int xp = atoi(valStr.c_str()); dialog->setLineXp(xp); } @@ -164,6 +172,9 @@ bool DialogsNebular::show(int messageId, int objectId) { if (!centerFlag) dialog->incNumLines(); + if (!dialog) + error("DialogsNebular::show - Uninitialized dialog"); + // Show the dialog _vm->_events->setCursor(CURSOR_ARROW); dialog->show(); -- cgit v1.2.3 From 15a10d27449d039dc01a712f2ad4bb93f062db01 Mon Sep 17 00:00:00 2001 From: Strangerke Date: Sat, 31 Jan 2015 12:41:03 +0100 Subject: MADS: Remove a useless variable --- engines/mads/events.cpp | 3 +-- engines/mads/events.h | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/mads/events.cpp b/engines/mads/events.cpp index de4dc3c070..e7ec8b0821 100644 --- a/engines/mads/events.cpp +++ b/engines/mads/events.cpp @@ -44,7 +44,6 @@ EventsManager::EventsManager(MADSEngine *vm) { _vD2 = 0; _mouseStatusCopy = 0; _mouseMoved = false; - _vD8 = 0; _rightMousePressed = false; _eventTarget = nullptr; } @@ -261,7 +260,7 @@ void EventsManager::waitForNextFrame() { void EventsManager::initVars() { _mousePos = Common::Point(-1, -1); _mouseStatusCopy = _mouseStatus; - _vD2 = _vD8 = 0; + _vD2 = 0; } } // End of namespace MADS diff --git a/engines/mads/events.h b/engines/mads/events.h index 54df337efd..870d6e03b8 100644 --- a/engines/mads/events.h +++ b/engines/mads/events.h @@ -70,7 +70,6 @@ public: int _vD2; int _mouseStatusCopy; bool _mouseMoved; - int _vD8; Common::Stack _pendingKeys; public: /** -- cgit v1.2.3 From 1c8ecb41bde0bdaba132af3c6fc768813de6d26f Mon Sep 17 00:00:00 2001 From: Strangerke Date: Sat, 31 Jan 2015 12:41:46 +0100 Subject: MADS: Fix signed/unsigned comparison warning --- engines/mads/menu_views.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mads/menu_views.h b/engines/mads/menu_views.h index 871c0d1d37..f39ea4c3b5 100644 --- a/engines/mads/menu_views.h +++ b/engines/mads/menu_views.h @@ -191,7 +191,7 @@ private: int _manualFrame2; int _animFrameNumber; bool _nextCyclingActive; - int _scrollFrameCtr; + uint _scrollFrameCtr; private: void load(); -- cgit v1.2.3 From 772cbc122d4cbfc06021facaa687921a138b98ab Mon Sep 17 00:00:00 2001 From: Strangerke Date: Sat, 31 Jan 2015 12:42:36 +0100 Subject: MADS: Fix a bug in PaletteUsage::process, some renaming --- engines/mads/palette.cpp | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) (limited to 'engines') diff --git a/engines/mads/palette.cpp b/engines/mads/palette.cpp index 836d04f7c0..95de307f8e 100644 --- a/engines/mads/palette.cpp +++ b/engines/mads/palette.cpp @@ -178,31 +178,29 @@ int PaletteUsage::process(Common::Array &palette, uint flags) { } if (!changed && !noUsageFlag) { - int var2 = (palette[palIndex]._flags & 0x20) || - (((flags & 0x2000) || (palette[palIndex]._flags & 0x4000)) && + int bestHash = (palette[palIndex]._flags & 0x20) || + (((flags & 0x2000) || (palette[palIndex]._flags & 0x40)) && ((flags & 0x1000) || (palCount == 0))) ? 0x7fff : 1; int var36 = (palette[palIndex]._flags & 0x80) ? 0 : 2; for (int idx = palLow; idx < palIdx; ++idx) { uint32 v = _vm->_palette->_palFlags[idx]; if ((v & var3A) && !(v & var36)) { - int var10; - - if (var2 > 1) { - var10 = rgbFactor(&_vm->_palette->_mainPalette[idx * 3], palette[palIndex]); - } - else if (_vm->_palette->_mainPalette[idx * 3] != palette[palIndex].r || + int hash; + if (bestHash > 1) { + hash = rgbFactor(&_vm->_palette->_mainPalette[idx * 3], palette[palIndex]); + } else if (_vm->_palette->_mainPalette[idx * 3] != palette[palIndex].r || _vm->_palette->_mainPalette[idx * 3 + 1] != palette[palIndex].g || _vm->_palette->_mainPalette[idx * 3 + 2] != palette[palIndex].b) { - var10 = 1; + hash = 1; } else { - var10 = 0; + hash = 0; } - if (var2 > var10) { + if (bestHash > hash) { changed = true; newPalIndex = idx; - var2 = var10; + bestHash = hash; } } } -- cgit v1.2.3 From 0fcd78391b584cee9ca6435d9ee5e88c339aa0cc Mon Sep 17 00:00:00 2001 From: Strangerke Date: Sat, 31 Jan 2015 12:53:35 +0100 Subject: MADS: Add a safeguard in doFrame --- engines/mads/menu_views.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mads/menu_views.cpp b/engines/mads/menu_views.cpp index b492d98125..8f1fd2d7a5 100644 --- a/engines/mads/menu_views.cpp +++ b/engines/mads/menu_views.cpp @@ -550,7 +550,7 @@ void AnimationView::doFrame() { scene._cyclingActive = _nextCyclingActive; } - if (++_scrollFrameCtr >= _currentAnimation->_header._scrollTicks) { + if (_currentAnimation && (++_scrollFrameCtr >= _currentAnimation->_header._scrollTicks)) { _scrollFrameCtr = 0; scroll(); } -- cgit v1.2.3 From 35c17d50663eeeecec5d14744149ac6004135a93 Mon Sep 17 00:00:00 2001 From: Strangerke Date: Sat, 31 Jan 2015 13:01:23 +0100 Subject: MADS: Janitorial - fix some else statements with braces on separate lines or extra tabs --- engines/mads/action.cpp | 3 +-- engines/mads/nebular/dialogs_nebular.cpp | 3 +-- engines/mads/nebular/game_nebular.cpp | 2 +- engines/mads/nebular/nebular_scenes8.cpp | 3 +-- engines/mads/palette.cpp | 10 +++------- engines/mads/sequence.cpp | 3 +-- 6 files changed, 8 insertions(+), 16 deletions(-) (limited to 'engines') diff --git a/engines/mads/action.cpp b/engines/mads/action.cpp index 199ae39000..628f03526f 100644 --- a/engines/mads/action.cpp +++ b/engines/mads/action.cpp @@ -567,9 +567,8 @@ void MADSAction::leftClick() { switch (userInterface._category) { case CAT_COMMAND: if (_selectedRow >= 0) { - if (_verbType == VERB_ONLY) { + if (_verbType == VERB_ONLY) _selectedAction = -1; - } else { _recentCommand = _selectedRow; _recentCommandSource = _commandSource; diff --git a/engines/mads/nebular/dialogs_nebular.cpp b/engines/mads/nebular/dialogs_nebular.cpp index b3d3e0687d..05c2e4ba96 100644 --- a/engines/mads/nebular/dialogs_nebular.cpp +++ b/engines/mads/nebular/dialogs_nebular.cpp @@ -387,8 +387,7 @@ TextDialog(vm, FONT_INTERFACE, Common::Point(-1, -1), 32) { addLine("ANSWER INCORRECT!", true); wordWrap("\n"); addLine("(But we'll give you another chance!)"); - } - else { + } else { addLine("REX NEBULAR version 8.43", true); wordWrap("\n"); addLine("(Copy Protection, for your convenience)"); diff --git a/engines/mads/nebular/game_nebular.cpp b/engines/mads/nebular/game_nebular.cpp index 8c0c00428a..965ef7fad2 100644 --- a/engines/mads/nebular/game_nebular.cpp +++ b/engines/mads/nebular/game_nebular.cpp @@ -454,7 +454,7 @@ void GameNebular::doObjectAction() { dialogs.show(464); } else if (action.isAction(VERB_REFLECT)) { dialogs.show(466); - } else if (action.isAction(VERB_GAZE_INTO, NOUN_REARVIEW_MIRROR)) { + } else if (action.isAction(VERB_GAZE_INTO, NOUN_REARVIEW_MIRROR)) { dialogs.show(467); } else if (action.isAction(VERB_EAT, NOUN_CHICKEN_BOMB)) { dialogs.show(469); diff --git a/engines/mads/nebular/nebular_scenes8.cpp b/engines/mads/nebular/nebular_scenes8.cpp index 62a1a262b0..7e8366c179 100644 --- a/engines/mads/nebular/nebular_scenes8.cpp +++ b/engines/mads/nebular/nebular_scenes8.cpp @@ -1129,8 +1129,7 @@ void Scene804::actions() { } else { _messWithThrottle = true; } - } - else if (_action.isAction(VERB_APPLY, NOUN_POLYCEMENT, NOUN_CRACK) || + } else if (_action.isAction(VERB_APPLY, NOUN_POLYCEMENT, NOUN_CRACK) || _action.isAction(VERB_PUT, NOUN_POLYCEMENT, NOUN_CRACK)) { if (!_globals[kWindowFixed]) { _resetFrame = 2; diff --git a/engines/mads/palette.cpp b/engines/mads/palette.cpp index 95de307f8e..250eb75955 100644 --- a/engines/mads/palette.cpp +++ b/engines/mads/palette.cpp @@ -503,16 +503,12 @@ void Fader::fadeIn(byte palette[PALETTE_SIZE], byte destPalette[PALETTE_SIZE], for (int colorCtr = 0; colorCtr < 3; ++colorCtr) { if (_colorFlags[colorCtr]) { int shiftSign = _colorValues[colorCtr]; - if (shiftSign >= 0) { + if (shiftSign >= 0) intensity = map[index]._intensity << shiftSign; - } - else { + else intensity = map[index]._intensity >> abs(shiftSign); - } - } - else { + } else intensity = _colorValues[colorCtr]; - } int diff = _rgb64Map[destPalette[palCtr * 3 + colorCtr]] - intensity; palIndex[palCtr][colorCtr] = (byte)ABS(diff); diff --git a/engines/mads/sequence.cpp b/engines/mads/sequence.cpp index 05f00afb5a..c94f3e3ad4 100644 --- a/engines/mads/sequence.cpp +++ b/engines/mads/sequence.cpp @@ -526,8 +526,7 @@ void SequenceList::setMotion(int seqIndex, int flags, int deltaX, int deltaY) { if (deltaY > 0) { se._posSign.y = 1; - } - else if (deltaY < 0) { + } else if (deltaY < 0) { se._posSign.y = -1; } else { se._posSign.y = 0; -- cgit v1.2.3 From 76eadc75e27ae5cb64b2114835db0bfacd516768 Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Sat, 31 Jan 2015 19:43:57 +0100 Subject: ZVISION: Add detection for Italian Zork Nemeis (bug #6786) --- engines/zvision/detection.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'engines') diff --git a/engines/zvision/detection.cpp b/engines/zvision/detection.cpp index b69eee000a..c817cbf3e9 100644 --- a/engines/zvision/detection.cpp +++ b/engines/zvision/detection.cpp @@ -111,6 +111,23 @@ static const ZVisionGameDescription gameDescriptions[] = { GID_NEMESIS }, + { + // Zork Nemesis Italian version + { + "znemesis", + 0, + {{"CSCR.ZFS", 0, "f04113357b4748c13efcb58b4629887c", 2577873}, + {"NEMESIS.STR", 0, "7c568feca8d9f9ae855c47183612c305", 9061}, + AD_LISTEND + }, + Common::IT_ITA, + Common::kPlatformDOS, + ADGF_NO_FLAGS, + GUIO4(GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_DOUBLE_FPS, GAMEOPTION_ENABLE_VENUS, GAMEOPTION_DISABLE_ANIM_WHILE_TURNING) + }, + GID_NEMESIS + }, + { // Zork Nemesis English demo version { -- cgit v1.2.3 From aa518306b8a82e22806cdb9820a6ac217a06c16f Mon Sep 17 00:00:00 2001 From: johndoe123 Date: Sun, 1 Feb 2015 17:21:34 +0100 Subject: BBVS: Fix out-of-bounds array access in air guitar minigame as reported by Coverity --- engines/bbvs/minigames/bbairguitar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/bbvs/minigames/bbairguitar.cpp b/engines/bbvs/minigames/bbairguitar.cpp index 6f198cb42a..26e27a966f 100644 --- a/engines/bbvs/minigames/bbairguitar.cpp +++ b/engines/bbvs/minigames/bbairguitar.cpp @@ -1121,7 +1121,7 @@ void MinigameBbAirGuitar::noteOff(int noteNum) { if (_actionTrackPos + _ticksDelta > 15000) _ticksDelta = 15000 - _actionTrackPos; _track[_trackCount].ticks = _ticksDelta; - if (_trackCount < 2048) + if (_trackCount + 1 < 2048) ++_trackCount; _track[_trackCount].noteNum = -2; _noteStartTime = _vm->_system->getMillis(); -- cgit v1.2.3 From bc2c1c6a3c11c10883e21dde1b68aafc9bf42620 Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Mon, 2 Feb 2015 01:11:53 +0100 Subject: ZVISION: Remove \n from debug message --- engines/zvision/scripting/effects/music_effect.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/zvision/scripting/effects/music_effect.cpp b/engines/zvision/scripting/effects/music_effect.cpp index ee2232d962..2e2084783d 100644 --- a/engines/zvision/scripting/effects/music_effect.cpp +++ b/engines/zvision/scripting/effects/music_effect.cpp @@ -111,7 +111,7 @@ MusicNode::~MusicNode() { _engine->getScriptManager()->setStateValue(_key, 2); if (_sub) delete _sub; - debug(1, "MusicNode: %d destroyed\n", _key); + debug(1, "MusicNode: %d destroyed", _key); } void MusicNode::setDeltaVolume(uint8 volume) { -- cgit v1.2.3 From 1adcb23d71a1f1ef6c4bc3b98fb474959fd14462 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 3 Feb 2015 04:15:11 +0200 Subject: ZVISION: Fix bug #6784 (wrong scaling in the fist control) --- engines/zvision/scripting/controls/fist_control.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/zvision/scripting/controls/fist_control.cpp b/engines/zvision/scripting/controls/fist_control.cpp index 4a8e8b1bbd..f79c82dc79 100644 --- a/engines/zvision/scripting/controls/fist_control.cpp +++ b/engines/zvision/scripting/controls/fist_control.cpp @@ -105,7 +105,12 @@ bool FistControl::process(uint32 deltaTimeInMillis) { if (_animation->needsUpdate()) { const Graphics::Surface *frameData = _animation->decodeNextFrame(); if (frameData) - _engine->getRenderManager()->blitSurfaceToBkgScaled(*frameData, _anmRect); + // WORKAROUND: Ignore the target frame dimensions for the finger animations. + // The target dimensions specify an area smaller than expected, thus if we + // scale the finger videos to fit these dimensions, they are not aligned + // correctly. Not scaling these videos yields a result identical to the + // original. Fixes bug #6784. + _engine->getRenderManager()->blitSurfaceToBkg(*frameData, _anmRect.left, _anmRect.top); } } -- cgit v1.2.3 From f1c64c2afe7d9de5ea337d61b4443376e4685ab0 Mon Sep 17 00:00:00 2001 From: Thierry Crozat Date: Tue, 3 Feb 2015 08:49:26 +0000 Subject: SCUMM: Fix handling of string resources in smash player for Steam mac games The Dig Steam/mac uses LF instead of CRLF for end of line. This fixes display of subtitles in that version. This also fixes the crash described in bug #6796. --- engines/scumm/smush/smush_player.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'engines') diff --git a/engines/scumm/smush/smush_player.cpp b/engines/scumm/smush/smush_player.cpp index 7617fc541f..2014462ab7 100644 --- a/engines/scumm/smush/smush_player.cpp +++ b/engines/scumm/smush/smush_player.cpp @@ -115,6 +115,10 @@ public: if (data_end[-2] == '\r' && data_end[-1] == '\n' && data_end[0] == '\r' && data_end[1] == '\n') { break; } + // In Steam mac version LF is used instead of CR-LF + if (data_end[-2] == '\n' && data_end[-1] == '\n') { + break; + } // In Russian Full Throttle strings are finished with // just one pair of CR-LF if (data_end[-2] == '\r' && data_end[-1] == '\n' && data_end[0] == '#') { -- cgit v1.2.3 From 6c07f918c698ff23a917857434200e51179bc111 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 3 Feb 2015 12:31:30 +0200 Subject: ZVISION: Fix for script bug #6783 (no sound in the ZNem fist puzzle) This is a bug in the original game script of the Zork Nemesis fist puzzle, which we now patch so that the sound checks are correct for the left fist animation --- engines/zvision/scripting/scr_file_handling.cpp | 26 +++++++++++++++++++++++-- engines/zvision/scripting/script_manager.h | 3 ++- 2 files changed, 26 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/zvision/scripting/scr_file_handling.cpp b/engines/zvision/scripting/scr_file_handling.cpp index b047c14430..a9f3a55021 100644 --- a/engines/zvision/scripting/scr_file_handling.cpp +++ b/engines/zvision/scripting/scr_file_handling.cpp @@ -83,7 +83,7 @@ void ScriptManager::parsePuzzle(Puzzle *puzzle, Common::SeekableReadStream &stre while (!stream.eos() && !line.contains('}')) { if (line.matchString("criteria {", true)) { - parseCriteria(stream, puzzle->criteriaList); + parseCriteria(stream, puzzle->criteriaList, puzzle->key); } else if (line.matchString("results {", true)) { parseResults(stream, puzzle->resultActions); } else if (line.matchString("flags {", true)) { @@ -97,7 +97,7 @@ void ScriptManager::parsePuzzle(Puzzle *puzzle, Common::SeekableReadStream &stre puzzle->addedBySetState = false; } -bool ScriptManager::parseCriteria(Common::SeekableReadStream &stream, Common::List > &criteriaList) const { +bool ScriptManager::parseCriteria(Common::SeekableReadStream &stream, Common::List > &criteriaList, uint32 key) const { // Loop until we find the closing brace Common::String line = stream.readLine(); trimCommentsAndWhiteSpace(&line); @@ -117,6 +117,21 @@ bool ScriptManager::parseCriteria(Common::SeekableReadStream &stream, Common::Li // Create a new List to hold the CriteriaEntries criteriaList.push_back(Common::List()); + // WORKAROUND for a script bug in Zork: Nemesis, room td9e (fist puzzle) + // Since we patch the script that triggers when manipulating the left fist + // (below), we add an additional check for the left fist sound, so that it + // doesn't get killed immediately when the left fist animation starts. + // Together with the workaround below, it fixes bug #6783. + if (_engine->getGameId() == GID_NEMESIS && key == 3594) { + Puzzle::CriteriaEntry entry; + entry.key = 567; + entry.criteriaOperator = Puzzle::NOT_EQUAL_TO; + entry.argumentIsAKey = false; + entry.argument = 1; + + criteriaList.back().push_back(entry); + } + while (!stream.eos() && !line.contains('}')) { Puzzle::CriteriaEntry entry; @@ -128,6 +143,13 @@ bool ScriptManager::parseCriteria(Common::SeekableReadStream &stream, Common::Li token = tokenizer.nextToken(); sscanf(token.c_str(), "[%u]", &(entry.key)); + // WORKAROUND for a script bug in Zork: Nemesis, room td9e (fist puzzle) + // Check for the state of animation 567 (left fist) when manipulating + // the fingers of the left fist (puzzle slots 3582, 3583). + // Together with the workaround above, it fixes bug #6783. + if (_engine->getGameId() == GID_NEMESIS && (key == 3582 || key == 3583) && entry.key == 568) + entry.key = 567; + // Parse the operator out of the second token token = tokenizer.nextToken(); if (token.c_str()[0] == '=') diff --git a/engines/zvision/scripting/script_manager.h b/engines/zvision/scripting/script_manager.h index 6d025bf2e9..d8e3721d43 100644 --- a/engines/zvision/scripting/script_manager.h +++ b/engines/zvision/scripting/script_manager.h @@ -312,9 +312,10 @@ private: * * @param criteria Pointer to the Criteria object to fill * @param stream Scr file stream + * @param key Puzzle key (for workarounds) * @return Whether any criteria were read */ - bool parseCriteria(Common::SeekableReadStream &stream, Common::List > &criteriaList) const; + bool parseCriteria(Common::SeekableReadStream &stream, Common::List > &criteriaList, uint32 key) const; /** * Parses the stream into a ResultAction objects -- cgit v1.2.3 From 666a4f3a57361e711a2854a4aa4fb5df19bc5569 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 3 Feb 2015 12:35:17 +0200 Subject: SCUMM: Adapt wording for the fix in commit f1c64c2afe --- engines/scumm/smush/smush_player.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/scumm/smush/smush_player.cpp b/engines/scumm/smush/smush_player.cpp index 2014462ab7..05c7ff2d9a 100644 --- a/engines/scumm/smush/smush_player.cpp +++ b/engines/scumm/smush/smush_player.cpp @@ -115,7 +115,8 @@ public: if (data_end[-2] == '\r' && data_end[-1] == '\n' && data_end[0] == '\r' && data_end[1] == '\n') { break; } - // In Steam mac version LF is used instead of CR-LF + // In the Steam Mac version of The Dig, LF-LF is used + // instead of CR-LF if (data_end[-2] == '\n' && data_end[-1] == '\n') { break; } -- cgit v1.2.3 From 531029f54aa5381a72d5f08a2e31721932dcfaa0 Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Thu, 5 Feb 2015 00:04:04 +0100 Subject: HUGO: Avoid drawing text above screen (bug #6799) When drawing cursor text, don't draw it above the top of the screen, since this would lead to memory corruption and crashes. I'm not quite sure this is all of bug #6799 since it also mentioned that "sometimes simply using a hotspot will be enough", but it's a start. --- engines/hugo/mouse.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/hugo/mouse.cpp b/engines/hugo/mouse.cpp index 558a596b35..3674c90757 100644 --- a/engines/hugo/mouse.cpp +++ b/engines/hugo/mouse.cpp @@ -121,12 +121,24 @@ void MouseHandler::cursorText(const char *buffer, const int16 cx, const int16 cy int16 sx, sy; if (cx < kXPix / 2) { sx = cx + kCursorNameOffX; - sy = (_vm->_inventory->getInventoryObjId() == -1) ? cy + kCursorNameOffY : cy + kCursorNameOffY - (_vm->_screen->fontHeight() + 1); + if (_vm->_inventory->getInventoryObjId() == -1) { + sy = cy + kCursorNameOffY; + } else { + sy = cy + kCursorNameOffY - (_vm->_screen->fontHeight() + 1); + if (sy < 0) { + sx = cx + kCursorNameOffX + 25; + sy = cy + kCursorNameOffY; + } + } } else { sx = cx - sdx - kCursorNameOffX / 2; sy = cy + kCursorNameOffY; } + if (sy < 0) { + sy = 0; + } + // Display the string and add rect to display list _vm->_screen->shadowStr(sx, sy, buffer, _TBRIGHTWHITE); _vm->_screen->displayList(kDisplayAdd, sx, sy, sdx, sdy); -- cgit v1.2.3 From a0661328b94f0d452995da4f91318d0952ab8346 Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Sat, 7 Feb 2015 21:55:24 +0100 Subject: SCUMM: Fix detection of the DoTT Maniac Mansion easter egg target It's the key, not the gameid, that is the proper target name. In my case, the key for that version of MM had the target name "maniac-old" and gameid "maniac" (can you tell I've messed around with this file a bit on my own?), so it tried to use "maniac" as the target, which happened to be the target name for the enhanced version instead. --- engines/scumm/scumm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp index 7d927b0cda..99b4e695bb 100644 --- a/engines/scumm/scumm.cpp +++ b/engines/scumm/scumm.cpp @@ -2612,7 +2612,7 @@ bool ScummEngine::startManiac() { if (path.hasPrefix(currentPath)) { path.erase(0, currentPath.size() + 1); if (path.equalsIgnoreCase("maniac")) { - maniacTarget = dom.getVal("gameid"); + maniacTarget = iter->_key; break; } } -- cgit v1.2.3 From b7b4e9cc5899eff0810d97a848ace0fa2ede5548 Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Sun, 8 Feb 2015 10:13:18 +0100 Subject: ZVISION: Draw transparent text in original save dialog Before this change, text was drawn in black boxes in Zork Nemesis, so while this does make it look better (and more like the original) this may actually make the text slightly harder to read. The original dialogs allowed only upper-case letters, but I think that it's better to leave that to the player. --- engines/zvision/scripting/controls/input_control.cpp | 12 +++++++++++- engines/zvision/scripting/controls/input_control.h | 2 ++ engines/zvision/text/text.cpp | 2 -- 3 files changed, 13 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/zvision/scripting/controls/input_control.cpp b/engines/zvision/scripting/controls/input_control.cpp index 47da27fa08..b25aa13543 100644 --- a/engines/zvision/scripting/controls/input_control.cpp +++ b/engines/zvision/scripting/controls/input_control.cpp @@ -39,6 +39,7 @@ namespace ZVision { InputControl::InputControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream) : Control(engine, key, CONTROL_INPUT), + _background(0), _nextTabstop(0), _focused(false), _textChanged(false), @@ -111,6 +112,11 @@ InputControl::InputControl(ZVision *engine, uint32 key, Common::SeekableReadStre } } +InputControl::~InputControl() { + _background->free(); + delete _background; +} + bool InputControl::onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) { if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED) return false; @@ -191,12 +197,16 @@ bool InputControl::process(uint32 deltaTimeInMillis) { if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED) return false; + if (!_background) { + _background = _engine->getRenderManager()->getBkgRect(_textRectangle); + } + // First see if we need to render the text if (_textChanged) { // Blit the text using the RenderManager Graphics::Surface txt; - txt.create(_textRectangle.width(), _textRectangle.height(), _engine->_resourcePixelFormat); + txt.copyFrom(*_background); if (!_readOnly || !_focused) _txtWidth = _engine->getTextRenderer()->drawTxt(_currentInputText, _stringInit, txt); diff --git a/engines/zvision/scripting/controls/input_control.h b/engines/zvision/scripting/controls/input_control.h index 99f7f5287d..e23ba0b9de 100644 --- a/engines/zvision/scripting/controls/input_control.h +++ b/engines/zvision/scripting/controls/input_control.h @@ -38,8 +38,10 @@ namespace ZVision { class InputControl : public Control { public: InputControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream); + ~InputControl(); private: + Graphics::Surface *_background; Common::Rect _textRectangle; Common::Rect _headerRectangle; cTxtStyle _stringInit; diff --git a/engines/zvision/text/text.cpp b/engines/zvision/text/text.cpp index e0501ae9c8..4af3b967f3 100644 --- a/engines/zvision/text/text.cpp +++ b/engines/zvision/text/text.cpp @@ -315,8 +315,6 @@ int32 TextRenderer::drawTxt(const Common::String &txt, cTxtStyle &fontStyle, Gra StyledTTFont font(_engine); fontStyle.setFont(font); - dst.fillRect(Common::Rect(dst.w, dst.h), 0); - uint32 clr = _engine->_resourcePixelFormat.RGBToColor(fontStyle._red, fontStyle._green, fontStyle._blue); int16 w; -- cgit v1.2.3 From 8725f2cff2357049a3759f24e3fa530c25644e25 Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Sun, 8 Feb 2015 13:56:01 +0100 Subject: ZVISION: Limit input text to the width of the input control This is to prevent the player from entering ridiculously long savegame descriptions. --- engines/zvision/scripting/controls/input_control.cpp | 14 +++++++++++++- engines/zvision/scripting/controls/input_control.h | 1 + 2 files changed, 14 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/zvision/scripting/controls/input_control.cpp b/engines/zvision/scripting/controls/input_control.cpp index b25aa13543..20c8e7ccbc 100644 --- a/engines/zvision/scripting/controls/input_control.cpp +++ b/engines/zvision/scripting/controls/input_control.cpp @@ -110,6 +110,10 @@ InputControl::InputControl(ZVision *engine, uint32 key, Common::SeekableReadStre _engine->getScriptManager()->trimCommentsAndWhiteSpace(&line); getParams(line, param, values); } + + _maxTxtWidth = _textRectangle.width(); + if (_animation) + _maxTxtWidth -= _animation->getWidth(); } InputControl::~InputControl() { @@ -208,12 +212,20 @@ bool InputControl::process(uint32 deltaTimeInMillis) { Graphics::Surface txt; txt.copyFrom(*_background); + int32 oldTxtWidth = _txtWidth; + if (!_readOnly || !_focused) _txtWidth = _engine->getTextRenderer()->drawTxt(_currentInputText, _stringInit, txt); else _txtWidth = _engine->getTextRenderer()->drawTxt(_currentInputText, _stringChooserInit, txt); - _engine->getRenderManager()->blitSurfaceToBkg(txt, _textRectangle.left, _textRectangle.top); + if (_readOnly || _txtWidth <= _maxTxtWidth) + _engine->getRenderManager()->blitSurfaceToBkg(txt, _textRectangle.left, _textRectangle.top); + else { + // Assume the last character caused the overflow. + _currentInputText.deleteLastChar(); + _txtWidth = oldTxtWidth; + } txt.free(); } diff --git a/engines/zvision/scripting/controls/input_control.h b/engines/zvision/scripting/controls/input_control.h index e23ba0b9de..7f272e8d81 100644 --- a/engines/zvision/scripting/controls/input_control.h +++ b/engines/zvision/scripting/controls/input_control.h @@ -56,6 +56,7 @@ private: bool _readOnly; int16 _txtWidth; + int16 _maxTxtWidth; Video::VideoDecoder *_animation; int32 _frameDelay; int16 _frame; -- cgit v1.2.3 From cbbd1a92192ad118897f645f1aa6e968bff01466 Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Sun, 8 Feb 2015 15:47:20 +0100 Subject: ZVISION: Set safe control state value after animation finishes If we set it before the animation starts, the final turn of the wheel won't be animated, because the puzzle will already be solved. --- engines/zvision/scripting/controls/safe_control.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/zvision/scripting/controls/safe_control.cpp b/engines/zvision/scripting/controls/safe_control.cpp index 6ba34106d0..4d2a91a1ad 100644 --- a/engines/zvision/scripting/controls/safe_control.cpp +++ b/engines/zvision/scripting/controls/safe_control.cpp @@ -123,6 +123,8 @@ bool SafeControl::process(uint32 deltaTimeInMillis) { _animation->seekToFrame(_animation->getCurFrame() - 1); const Graphics::Surface *frameData = _animation->decodeNextFrame(); + if (_animation->getCurFrame() == _targetFrame) + _engine->getScriptManager()->setStateValue(_key, _curState); if (frameData) _engine->getRenderManager()->blitSurfaceToBkg(*frameData, _rectangle.left, _rectangle.top); } @@ -169,8 +171,6 @@ bool SafeControl::onMouseUp(const Common::Point &screenSpacePos, const Common::P _curState = (_statesCount * 2 + tmp2) % _statesCount; _targetFrame = (_curState + _statesCount - _startPointer) % _statesCount; - - _engine->getScriptManager()->setStateValue(_key, _curState); return true; } } -- cgit v1.2.3 From 5e00b39caec66e1c5626a89f207c26c577fd30d8 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 8 Feb 2015 22:07:42 -0500 Subject: MADS: Implementing code for panning screen transitions --- engines/mads/msurface.cpp | 15 +++++- engines/mads/msurface.h | 7 +++ engines/mads/palette.cpp | 26 ++++++++++ engines/mads/palette.h | 3 ++ engines/mads/screen.cpp | 122 +++++++++++++++++++++++++++++++++++++++++++++- engines/mads/screen.h | 13 +++++ 6 files changed, 183 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/mads/msurface.cpp b/engines/mads/msurface.cpp index 39824bac4b..d8d01f307c 100644 --- a/engines/mads/msurface.cpp +++ b/engines/mads/msurface.cpp @@ -485,7 +485,6 @@ void MSurface::scrollY(int yAmount) { delete[] tempData; } - void MSurface::translate(Common::Array &palette) { for (int y = 0; y < this->h; ++y) { byte *pDest = getBasePtr(0, y); @@ -521,6 +520,20 @@ MSurface *MSurface::flipHorizontal() const { return dest; } +void MSurface::copyRectTranslate(MSurface &srcSurface, const byte *paletteMap, + const Common::Point &destPos, const Common::Rect &srcRect) { + // Loop through the lines + for (int yCtr = 0; yCtr < srcRect.height(); ++yCtr) { + const byte *srcP = srcSurface.getBasePtr(srcRect.left, srcRect.top + yCtr); + byte *destP = getBasePtr(destPos.x, destPos.y + yCtr); + + // Copy the line over + for (int xCtr = 0; xCtr < srcRect.width(); ++xCtr, ++srcP, ++destP) { + *destP = paletteMap[*srcP]; + } + } +} + /*------------------------------------------------------------------------*/ int DepthSurface::getDepth(const Common::Point &pt) { diff --git a/engines/mads/msurface.h b/engines/mads/msurface.h index 650d7fdaee..754e70bf7f 100644 --- a/engines/mads/msurface.h +++ b/engines/mads/msurface.h @@ -220,6 +220,13 @@ public: * Create a new surface which is a flipped horizontal copy of the current one */ MSurface *flipHorizontal() const; + + /** + * Copy an area from one surface to another, translating it using a palette + * map as it's done + */ + void copyRectTranslate(MSurface &srcSurface, const byte *paletteMap, + const Common::Point &destPos, const Common::Rect &srcRect); }; class DepthSurface : public MSurface { diff --git a/engines/mads/palette.cpp b/engines/mads/palette.cpp index 250eb75955..250c98b074 100644 --- a/engines/mads/palette.cpp +++ b/engines/mads/palette.cpp @@ -885,4 +885,30 @@ void Palette::refreshSceneColors() { setPalette(_mainPalette + (val * 3), val, 256 - val); } +int Palette::closestColor(const byte *matchColor, const byte *refPalette, + int listWrap, int count) { + int bestColor = 0; + int bestDifference = 0x7fff; + + for (int idx = 0; idx < count; ++idx) { + // Figure out hash for color + int hash = 0; + for (int rgbIdx = 0; rgbIdx < 3; ++rgbIdx, ++refPalette) { + byte diff = *refPalette - matchColor[rgbIdx]; + hash += (int)diff * (int)diff; + } + + // If the given color is a closer match to our color, store the index + if (hash < bestDifference) { + bestDifference = hash; + bestColor = idx; + } + + refPalette += listWrap - 3; + } + + return bestColor; +} + + } // End of namespace MADS diff --git a/engines/mads/palette.h b/engines/mads/palette.h index 27d25f266b..1c387b4368 100644 --- a/engines/mads/palette.h +++ b/engines/mads/palette.h @@ -318,6 +318,9 @@ public: void unlock(); void refreshSceneColors(); + + static int closestColor(const byte *matchColor, const byte *refPalette, + int listWrap, int count); }; } // End of namespace MADS diff --git a/engines/mads/screen.cpp b/engines/mads/screen.cpp index 8552effd98..f7179877d5 100644 --- a/engines/mads/screen.cpp +++ b/engines/mads/screen.cpp @@ -607,6 +607,7 @@ void ScreenSurface::updateScreen() { void ScreenSurface::transition(ScreenTransition transitionType, bool surfaceFlag) { Palette &pal = *_vm->_palette; + Scene &scene = _vm->_game->_scene; byte palData[PALETTE_SIZE]; switch (transitionType) { @@ -639,8 +640,9 @@ void ScreenSurface::transition(ScreenTransition transitionType, bool surfaceFlag case kTransitionPanLeftToRight: case kTransitionPanRightToLeft: - warning("TODO: pan transition"); - transition(kTransitionFadeIn, surfaceFlag); + panTransition(scene._backgroundSurface, pal._mainPalette, + transitionType - kTransitionPanLeftToRight, + Common::Point(0, 0), scene._posAdjust, THROUGH_BLACK2, true, 1); break; case kTransitionCircleIn1: @@ -674,5 +676,121 @@ void ScreenSurface::resetClipBounds() { setClipBounds(Common::Rect(0, 0, MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT)); } +void ScreenSurface::panTransition(MSurface &newScreen, byte *palData, int entrySide, + const Common::Point &srcPos, const Common::Point &destPos, + ThroughBlack throughBlack, bool setPalette, int numTicks) { + EventsManager &events = *_vm->_events; + Palette &palette = *_vm->_palette; + Common::Point size; + int y1, y2; + int startX = 0; + int deltaX; + int sizeY; + int xAt; + int loopStart; +// uint32 baseTicks, currentTicks; + byte paletteMap[256]; + + size.x = MIN(newScreen.w, (uint16)MADS_SCREEN_WIDTH); + size.y = newScreen.h; + if (newScreen.h >= MADS_SCREEN_HEIGHT) + size.y = MADS_SCENE_HEIGHT; + + // Set starting position and direction delta for the transition + if (entrySide == 1) + // Right to left + startX = size.x - 1; + deltaX = startX ? -1 : 1; + + if (setPalette & !throughBlack) + palette.setFullPalette(palData); + + // TODO: Original uses a different frequency ticks counter. Need to + // confirm frequency and see whether we need to implement it, or + // if the current frame ticks can substitute for it +// baseTicks = events.getFrameCounter(); + + y1 = 0; + y2 = size.y - 1; + sizeY = y2 - y1 + 1; + + if (throughBlack == THROUGH_BLACK2) + swapForeground(palData, &paletteMap[0]); + + loopStart = throughBlack == THROUGH_BLACK1 ? 0 : 1; + for (int loop = loopStart; loop < 2; ++loop) { + xAt = startX; + for (int xCtr = 0; xCtr < size.x; ++xCtr, xAt += deltaX) { + if (!loop) { + fillRect(Common::Rect(xAt + destPos.x, y1 + destPos.y, + xAt + destPos.x + 1, y2 + destPos.y), 0); + } else if (throughBlack == THROUGH_BLACK2) { + copyRectTranslate(newScreen, paletteMap, + Common::Point(xAt, destPos.y), + Common::Rect(srcPos.x + xAt, srcPos.y, + srcPos.x + xAt + 1, srcPos.y + size.y)); + } else { + newScreen.copyRectToSurface(*this, xAt, destPos.y, + Common::Rect(srcPos.x + xAt, srcPos.y, + srcPos.x + xAt + 1, srcPos.y + size.y)); + } + + copyRectToScreen(Common::Rect(xAt, destPos.y, xAt + 1, destPos.y + size.y)); + + // Slight delay + events.delay(1); + } + + if ((setPalette && !loop) || throughBlack == THROUGH_BLACK2) + palette.setFullPalette(palData); + } + + if (throughBlack == THROUGH_BLACK2) { + Common::Rect r(srcPos.x, srcPos.y, srcPos.x + size.x, srcPos.y + size.y); + copyRectToSurface(newScreen, destPos.x, destPos.y, r); + copyRectToScreen(r); + } +} + +void ScreenSurface::swapForeground(byte palData[PALETTE_SIZE], byte *paletteMap) { + Palette &palette = *_vm->_palette; + byte oldPalette[PALETTE_SIZE]; + byte oldMap[256]; + byte newMap[256]; + + palette.getFullPalette(oldPalette); + swapPalette(oldPalette, oldMap, true); + swapPalette(palData, newMap, false); + + Common::copy(&palData[3], &palData[PALETTE_SIZE], &oldPalette[3]); + + copyRectTranslate(*this, oldMap, Common::Point(0, 0), + Common::Rect(0, 0, MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT)); + palette.setFullPalette(oldPalette); +} + +void ScreenSurface::swapPalette(byte *palData, byte swapTable[PALETTE_COUNT], + int start) { + byte *dynamicList = &palData[start * 3]; + int staticStart = 1 - start; + byte *staticList = &palData[staticStart * 3]; + const int PALETTE_START = 1; + const int PALETTE_END = 252; + + // Set initial index values + for (int idx = 0; idx < PALETTE_COUNT; ++idx) + swapTable[idx] = idx; + + for (int idx = 0; idx < 128; ++idx) { + if (start >= PALETTE_START && start <= PALETTE_END) { + swapTable[start] = Palette::closestColor(dynamicList, staticList, + 6, 128) * 2 + staticStart; + } + + dynamicList += 6; + start += 2; + } +} + } // End of namespace MADS diff --git a/engines/mads/screen.h b/engines/mads/screen.h index 6800523f92..35042e88d2 100644 --- a/engines/mads/screen.h +++ b/engines/mads/screen.h @@ -56,6 +56,11 @@ enum InputMode { kInputLimitedSentences = 2 // Use only scene hotspots }; +enum ThroughBlack { + THROUGH_BLACK1 = 1, + THROUGH_BLACK2 = 2 +}; + class SpriteSlot; class TextDisplay; class UISlot; @@ -207,6 +212,14 @@ private: uint16 _random; byte *_surfacePixels; Common::Rect _clipBounds; + + void panTransition(MSurface &newScreen, byte *palData, int entrySide, + const Common::Point &srcPos, const Common::Point &destPos, + ThroughBlack throughBlack, bool setPalette, int numTicks); + + void swapForeground(byte *palData, byte *paletteMap); + + void swapPalette(byte palData[PALETTE_SIZE], byte swapTable[PALETTE_COUNT], int start); public: int _shakeCountdown; public: -- cgit v1.2.3 From 55be1b82a84454ae838419e22ce15cade5298665 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 8 Feb 2015 23:54:51 -0500 Subject: MADS: Variable renaming in closestColor --- engines/mads/palette.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/mads/palette.cpp b/engines/mads/palette.cpp index 250c98b074..b41eaedfcc 100644 --- a/engines/mads/palette.cpp +++ b/engines/mads/palette.cpp @@ -888,19 +888,19 @@ void Palette::refreshSceneColors() { int Palette::closestColor(const byte *matchColor, const byte *refPalette, int listWrap, int count) { int bestColor = 0; - int bestDifference = 0x7fff; + int bestDistance = 0x7fff; for (int idx = 0; idx < count; ++idx) { // Figure out hash for color - int hash = 0; + int distance = 0; for (int rgbIdx = 0; rgbIdx < 3; ++rgbIdx, ++refPalette) { byte diff = *refPalette - matchColor[rgbIdx]; - hash += (int)diff * (int)diff; + distance += (int)diff * (int)diff; } // If the given color is a closer match to our color, store the index - if (hash < bestDifference) { - bestDifference = hash; + if (distance < bestDistance) { + bestDistance = distance; bestColor = idx; } -- cgit v1.2.3 From a851fa8e1aef50334402fec65bf89ee8b582ea62 Mon Sep 17 00:00:00 2001 From: RichieSams Date: Wed, 11 Feb 2015 14:57:05 -0600 Subject: ZVISION: Refactor text rendering code in order to fix word wrapping and clarify the logic. Fixes bug #6801 --- engines/zvision/graphics/render_manager.cpp | 2 +- .../zvision/scripting/controls/input_control.cpp | 8 +- engines/zvision/scripting/controls/input_control.h | 4 +- .../zvision/scripting/controls/titler_control.cpp | 2 +- .../zvision/scripting/effects/ttytext_effect.cpp | 40 +- engines/zvision/scripting/effects/ttytext_effect.h | 2 +- engines/zvision/text/text.cpp | 425 +++++++++++---------- engines/zvision/text/text.h | 52 ++- engines/zvision/text/truetype_font.cpp | 60 ++- engines/zvision/text/truetype_font.h | 14 +- 10 files changed, 308 insertions(+), 301 deletions(-) (limited to 'engines') diff --git a/engines/zvision/graphics/render_manager.cpp b/engines/zvision/graphics/render_manager.cpp index 3cd9701b7c..8758097c93 100644 --- a/engines/zvision/graphics/render_manager.cpp +++ b/engines/zvision/graphics/render_manager.cpp @@ -755,7 +755,7 @@ void RenderManager::processSubs(uint16 deltatime) { if (sub->txt.size()) { Graphics::Surface *rndr = new Graphics::Surface(); rndr->create(sub->r.width(), sub->r.height(), _engine->_resourcePixelFormat); - _engine->getTextRenderer()->drawTxtInOneLine(sub->txt, *rndr); + _engine->getTextRenderer()->drawTextWithWordWrapping(sub->txt, *rndr); Common::Rect empty; blitSurfaceToSurface(*rndr, empty, _subtitleSurface, sub->r.left - _subtitleArea.left + _workingWindow.left, sub->r.top - _subtitleArea.top + _workingWindow.top); rndr->free(); diff --git a/engines/zvision/scripting/controls/input_control.cpp b/engines/zvision/scripting/controls/input_control.cpp index 20c8e7ccbc..df0c77ba96 100644 --- a/engines/zvision/scripting/controls/input_control.cpp +++ b/engines/zvision/scripting/controls/input_control.cpp @@ -79,13 +79,13 @@ InputControl::InputControl(ZVision *engine, uint32 key, Common::SeekableReadStre sscanf(values.c_str(), "%u", &fontFormatNumber); - _stringInit.readAllStyle(_engine->getStringManager()->getTextLine(fontFormatNumber)); + _stringInit.readAllStyles(_engine->getStringManager()->getTextLine(fontFormatNumber)); } else if (param.matchString("chooser_init_string", true)) { uint fontFormatNumber; sscanf(values.c_str(), "%u", &fontFormatNumber); - _stringChooserInit.readAllStyle(_engine->getStringManager()->getTextLine(fontFormatNumber)); + _stringChooserInit.readAllStyles(_engine->getStringManager()->getTextLine(fontFormatNumber)); } else if (param.matchString("next_tabstop", true)) { sscanf(values.c_str(), "%u", &_nextTabstop); } else if (param.matchString("cursor_dimensions", true)) { @@ -215,9 +215,9 @@ bool InputControl::process(uint32 deltaTimeInMillis) { int32 oldTxtWidth = _txtWidth; if (!_readOnly || !_focused) - _txtWidth = _engine->getTextRenderer()->drawTxt(_currentInputText, _stringInit, txt); + _txtWidth = _engine->getTextRenderer()->drawText(_currentInputText, _stringInit, txt); else - _txtWidth = _engine->getTextRenderer()->drawTxt(_currentInputText, _stringChooserInit, txt); + _txtWidth = _engine->getTextRenderer()->drawText(_currentInputText, _stringChooserInit, txt); if (_readOnly || _txtWidth <= _maxTxtWidth) _engine->getRenderManager()->blitSurfaceToBkg(txt, _textRectangle.left, _textRectangle.top); diff --git a/engines/zvision/scripting/controls/input_control.h b/engines/zvision/scripting/controls/input_control.h index 7f272e8d81..9b48514e16 100644 --- a/engines/zvision/scripting/controls/input_control.h +++ b/engines/zvision/scripting/controls/input_control.h @@ -44,8 +44,8 @@ private: Graphics::Surface *_background; Common::Rect _textRectangle; Common::Rect _headerRectangle; - cTxtStyle _stringInit; - cTxtStyle _stringChooserInit; + TextStyleState _stringInit; + TextStyleState _stringChooserInit; uint32 _nextTabstop; bool _focused; diff --git a/engines/zvision/scripting/controls/titler_control.cpp b/engines/zvision/scripting/controls/titler_control.cpp index 542e0a0b67..683d6660af 100644 --- a/engines/zvision/scripting/controls/titler_control.cpp +++ b/engines/zvision/scripting/controls/titler_control.cpp @@ -82,7 +82,7 @@ TitlerControl::~TitlerControl() { void TitlerControl::setString(int strLine) { if (strLine != _curString && strLine >= 0 && strLine < (int)_strings.size()) { _surface->fillRect(Common::Rect(_surface->w, _surface->h), 0); - _engine->getTextRenderer()->drawTxtInOneLine(_strings[strLine], *_surface); + _engine->getTextRenderer()->drawTextWithWordWrapping(_strings[strLine], *_surface); _engine->getRenderManager()->blitSurfaceToBkg(*_surface, _rectangle.left, _rectangle.top); _curString = strLine; } diff --git a/engines/zvision/scripting/effects/ttytext_effect.cpp b/engines/zvision/scripting/effects/ttytext_effect.cpp index c60b3aa8c5..8d340dae39 100644 --- a/engines/zvision/scripting/effects/ttytext_effect.cpp +++ b/engines/zvision/scripting/effects/ttytext_effect.cpp @@ -57,9 +57,9 @@ ttyTextNode::ttyTextNode(ZVision *engine, uint32 key, const Common::String &file delete infile; } _img.create(_r.width(), _r.height(), _engine->_resourcePixelFormat); - _style._sharp = true; - _style.readAllStyle(_txtbuf); - _style.setFont(_fnt); + _state._sharp = true; + _state.readAllStyles(_txtbuf); + _state.updateFontWithTextState(_fnt); _engine->getScriptManager()->setStateValue(_key, 1); } @@ -74,29 +74,27 @@ bool ttyTextNode::process(uint32 deltaTimeInMillis) { if (_nexttime < 0) { if (_txtpos < _txtbuf.size()) { if (_txtbuf[_txtpos] == '<') { - int32 strt = _txtpos; - int32 endt = 0; + int32 start = _txtpos; + int32 end = 0; int16 ret = 0; while (_txtbuf[_txtpos] != '>' && _txtpos < _txtbuf.size()) _txtpos++; - endt = _txtpos; - if (strt != -1) - if ((endt - strt - 1) > 0) - ret = _style.parseStyle(_txtbuf.c_str() + strt + 1, endt - strt - 1); - - if (ret & (TXT_RET_FNTCHG | TXT_RET_FNTSTL | TXT_RET_NEWLN)) { - if (ret & TXT_RET_FNTCHG) - _style.setFont(_fnt); - if (ret & TXT_RET_FNTSTL) - _style.setFontStyle(_fnt); - - if (ret & TXT_RET_NEWLN) - newline(); + end = _txtpos; + if (start != -1) { + if ((end - start - 1) > 0) { + ret = _state.parseStyle(_txtbuf.c_str() + start + 1, end - start - 1); + } + } + + if (ret & (TEXT_CHANGE_FONT_TYPE | TEXT_CHANGE_FONT_STYLE)) { + _state.updateFontWithTextState(_fnt); + } else if (ret & TEXT_CHANGE_NEWLINE) { + newline(); } - if (ret & TXT_RET_HASSTBOX) { + if (ret & TEXT_CHANGE_HAS_STATE_BOX) { Common::String buf; - buf = Common::String::format("%d", _engine->getScriptManager()->getStateValue(_style._statebox)); + buf = Common::String::format("%d", _engine->getScriptManager()->getStateValue(_state._statebox)); for (uint8 j = 0; j < buf.size(); j++) outchar(buf[j]); @@ -158,7 +156,7 @@ void ttyTextNode::newline() { } void ttyTextNode::outchar(uint16 chr) { - uint32 clr = _engine->_resourcePixelFormat.RGBToColor(_style._red, _style._green, _style._blue); + uint32 clr = _engine->_resourcePixelFormat.RGBToColor(_state._red, _state._green, _state._blue); if (_dx + _fnt.getCharWidth(chr) > _r.width()) newline(); diff --git a/engines/zvision/scripting/effects/ttytext_effect.h b/engines/zvision/scripting/effects/ttytext_effect.h index 8d8a2518c7..18cbbbaee3 100644 --- a/engines/zvision/scripting/effects/ttytext_effect.h +++ b/engines/zvision/scripting/effects/ttytext_effect.h @@ -51,7 +51,7 @@ public: private: Common::Rect _r; - cTxtStyle _style; + TextStyleState _state; StyledTTFont _fnt; Common::String _txtbuf; uint32 _txtpos; diff --git a/engines/zvision/text/text.cpp b/engines/zvision/text/text.cpp index 4af3b967f3..868ee4f1ae 100644 --- a/engines/zvision/text/text.cpp +++ b/engines/zvision/text/text.cpp @@ -38,7 +38,7 @@ namespace ZVision { -cTxtStyle::cTxtStyle() { +TextStyleState::TextStyleState() { _fontname = "Arial"; _blue = 255; _green = 255; @@ -49,7 +49,7 @@ cTxtStyle::cTxtStyle() { _escapement = 0; #endif _italic = false; - _justify = TXT_JUSTIFY_LEFT; + _justification = TEXT_JUSTIFY_LEFT; _size = 12; #if 0 _skipcolor = false; @@ -60,10 +60,10 @@ cTxtStyle::cTxtStyle() { _sharp = false; } -txtReturn cTxtStyle::parseStyle(const Common::String &strin, int16 ln) { - Common::String buf = Common::String(strin.c_str(), ln); +TextChange TextStyleState::parseStyle(const Common::String &str, int16 len) { + Common::String buf = Common::String(str.c_str(), len); - int8 retval = TXT_RET_NOTHING; + uint retval = TEXT_CHANGE_NONE; Common::StringTokenizer tokenizer(buf, " "); Common::String token; @@ -89,7 +89,7 @@ txtReturn cTxtStyle::parseStyle(const Common::String &strin, int16 ln) { if (!tokenizer.empty()) _fontname = token; } - retval |= TXT_RET_FNTCHG; + retval |= TEXT_CHANGE_FONT_TYPE; } else if (token.matchString("blue", true)) { if (!tokenizer.empty()) { @@ -97,7 +97,7 @@ txtReturn cTxtStyle::parseStyle(const Common::String &strin, int16 ln) { int32 tmp = atoi(token.c_str()); if (_blue != tmp) { _blue = tmp; - retval |= TXT_RET_FNTSTL; + retval |= TEXT_CHANGE_FONT_STYLE; } } } else if (token.matchString("red", true)) { @@ -106,7 +106,7 @@ txtReturn cTxtStyle::parseStyle(const Common::String &strin, int16 ln) { int32 tmp = atoi(token.c_str()); if (_red != tmp) { _red = tmp; - retval |= TXT_RET_FNTSTL; + retval |= TEXT_CHANGE_FONT_STYLE; } } } else if (token.matchString("green", true)) { @@ -115,7 +115,7 @@ txtReturn cTxtStyle::parseStyle(const Common::String &strin, int16 ln) { int32 tmp = atoi(token.c_str()); if (_green != tmp) { _green = tmp; - retval |= TXT_RET_FNTSTL; + retval |= TEXT_CHANGE_FONT_STYLE; } } } else if (token.matchString("newline", true)) { @@ -125,14 +125,14 @@ txtReturn cTxtStyle::parseStyle(const Common::String &strin, int16 ln) { _newline++; #endif - retval |= TXT_RET_NEWLN; + retval |= TEXT_CHANGE_NEWLINE; } else if (token.matchString("point", true)) { if (!tokenizer.empty()) { token = tokenizer.nextToken(); int32 tmp = atoi(token.c_str()); if (_size != tmp) { _size = tmp; - retval |= TXT_RET_FNTCHG; + retval |= TEXT_CHANGE_FONT_TYPE; } } } else if (token.matchString("escapement", true)) { @@ -149,12 +149,12 @@ txtReturn cTxtStyle::parseStyle(const Common::String &strin, int16 ln) { if (token.matchString("on", true)) { if (_italic != true) { _italic = true; - retval |= TXT_RET_FNTSTL; + retval |= TEXT_CHANGE_FONT_STYLE; } } else if (token.matchString("off", true)) { if (_italic != false) { _italic = false; - retval |= TXT_RET_FNTSTL; + retval |= TEXT_CHANGE_FONT_STYLE; } } } @@ -164,12 +164,12 @@ txtReturn cTxtStyle::parseStyle(const Common::String &strin, int16 ln) { if (token.matchString("on", true)) { if (_underline != true) { _underline = true; - retval |= TXT_RET_FNTSTL; + retval |= TEXT_CHANGE_FONT_STYLE; } } else if (token.matchString("off", true)) { if (_underline != false) { _underline = false; - retval |= TXT_RET_FNTSTL; + retval |= TEXT_CHANGE_FONT_STYLE; } } } @@ -179,12 +179,12 @@ txtReturn cTxtStyle::parseStyle(const Common::String &strin, int16 ln) { if (token.matchString("on", true)) { if (_strikeout != true) { _strikeout = true; - retval |= TXT_RET_FNTSTL; + retval |= TEXT_CHANGE_FONT_STYLE; } } else if (token.matchString("off", true)) { if (_strikeout != false) { _strikeout = false; - retval |= TXT_RET_FNTSTL; + retval |= TEXT_CHANGE_FONT_STYLE; } } } @@ -194,12 +194,12 @@ txtReturn cTxtStyle::parseStyle(const Common::String &strin, int16 ln) { if (token.matchString("on", true)) { if (_bold != true) { _bold = true; - retval |= TXT_RET_FNTSTL; + retval |= TEXT_CHANGE_FONT_STYLE; } } else if (token.matchString("off", true)) { if (_bold != false) { _bold = false; - retval |= TXT_RET_FNTSTL; + retval |= TEXT_CHANGE_FONT_STYLE; } } } @@ -220,24 +220,24 @@ txtReturn cTxtStyle::parseStyle(const Common::String &strin, int16 ln) { if (!tokenizer.empty()) { token = tokenizer.nextToken(); _statebox = atoi(token.c_str()); - retval |= TXT_RET_HASSTBOX; + retval |= TEXT_CHANGE_HAS_STATE_BOX; } } else if (token.matchString("justify", true)) { if (!tokenizer.empty()) { token = tokenizer.nextToken(); if (token.matchString("center", true)) - _justify = TXT_JUSTIFY_CENTER; + _justification = TEXT_JUSTIFY_CENTER; else if (token.matchString("left", true)) - _justify = TXT_JUSTIFY_LEFT; + _justification = TEXT_JUSTIFY_LEFT; else if (token.matchString("right", true)) - _justify = TXT_JUSTIFY_RIGHT; + _justification = TEXT_JUSTIFY_RIGHT; } } } - return (txtReturn)retval; + return (TextChange)retval; } -void cTxtStyle::readAllStyle(const Common::String &txt) { +void TextStyleState::readAllStyles(const Common::String &txt) { int16 startTextPosition = -1; int16 endTextPosition = -1; @@ -246,243 +246,264 @@ void cTxtStyle::readAllStyle(const Common::String &txt) { startTextPosition = i; else if (txt[i] == '>') { endTextPosition = i; - if (startTextPosition != -1) - if ((endTextPosition - startTextPosition - 1) > 0) + if (startTextPosition != -1) { + if ((endTextPosition - startTextPosition - 1) > 0) { parseStyle(Common::String(txt.c_str() + startTextPosition + 1), endTextPosition - startTextPosition - 1); + } + } } } } -void cTxtStyle::setFontStyle(StyledTTFont &font) { +void TextStyleState::updateFontWithTextState(StyledTTFont &font) { uint tempStyle = 0; - if (_bold) - tempStyle |= StyledTTFont::STTF_BOLD; - - if (_italic) - tempStyle |= StyledTTFont::STTF_ITALIC; - - if (_underline) - tempStyle |= StyledTTFont::STTF_UNDERLINE; - - if (_strikeout) - tempStyle |= StyledTTFont::STTF_STRIKEOUT; - - if (_sharp) - tempStyle |= StyledTTFont::STTF_SHARP; + if (_bold) { + tempStyle |= StyledTTFont::TTF_STYLE_BOLD; + } + if (_italic) { + tempStyle |= StyledTTFont::TTF_STYLE_ITALIC; + } + if (_underline) { + tempStyle |= StyledTTFont::TTF_STYLE_UNDERLINE; + } + if (_strikeout) { + tempStyle |= StyledTTFont::TTF_STYLE_STRIKETHROUGH; + } + if (_sharp) { + tempStyle |= StyledTTFont::TTF_STYLE_SHARP; + } - font.setStyle(tempStyle); + font.loadFont(_fontname, _size, tempStyle); } -void cTxtStyle::setFont(StyledTTFont &font) { - uint tempStyle = 0; - - if (_bold) - tempStyle |= StyledTTFont::STTF_BOLD; +void TextRenderer::drawTextWithJustification(const Common::String &text, StyledTTFont &font, uint32 color, Graphics::Surface &dest, int lineY, TextJustification justify) { + if (justify == TEXT_JUSTIFY_LEFT) + font.drawString(&dest, text, 0, lineY, dest.w, color, Graphics::kTextAlignLeft); + else if (justify == TEXT_JUSTIFY_CENTER) + font.drawString(&dest, text, 0, lineY, dest.w, color, Graphics::kTextAlignCenter); + else if (justify == TEXT_JUSTIFY_RIGHT) + font.drawString(&dest, text, 0, lineY, dest.w, color, Graphics::kTextAlignRight); +} - if (_italic) - tempStyle |= StyledTTFont::STTF_ITALIC; +int32 TextRenderer::drawText(const Common::String &text, TextStyleState &state, Graphics::Surface &dest) { + StyledTTFont font(_engine); + state.updateFontWithTextState(font); - if (_underline) - tempStyle |= StyledTTFont::STTF_UNDERLINE; + uint32 color = _engine->_resourcePixelFormat.RGBToColor(state._red, state._green, state._blue); + drawTextWithJustification(text, font, color, dest, 0, state._justification); - if (_strikeout) - tempStyle |= StyledTTFont::STTF_STRIKEOUT; + return font.getStringWidth(text); +} - if (_sharp) - tempStyle |= StyledTTFont::STTF_SHARP; +struct TextSurface { + TextSurface(Graphics::Surface *surface, Common::Point surfaceOffset, uint lineNumber) + : _surface(surface), + _surfaceOffset(surfaceOffset), + _lineNumber(lineNumber) { + } - font.loadFont(_fontname, _size, tempStyle); -} + Graphics::Surface *_surface; + Common::Point _surfaceOffset; + uint _lineNumber; +}; -Graphics::Surface *TextRenderer::render(StyledTTFont &fnt, const Common::String &txt, cTxtStyle &style) { - style.setFontStyle(fnt); - uint32 clr = _engine->_resourcePixelFormat.RGBToColor(style._red, style._green, style._blue); - return fnt.renderSolidText(txt, clr); -} +void TextRenderer::drawTextWithWordWrapping(const Common::String &text, Graphics::Surface &dest) { + Common::Array textSurfaces; + Common::Array lineWidths; + Common::Array lineJustifications; -void TextRenderer::drawTxtWithJustify(const Common::String &txt, StyledTTFont &fnt, uint32 color, Graphics::Surface &dst, int lineY, txtJustify justify) { - if (justify == TXT_JUSTIFY_LEFT) - fnt.drawString(&dst, txt, 0, lineY, dst.w, color, Graphics::kTextAlignLeft); - else if (justify == TXT_JUSTIFY_CENTER) - fnt.drawString(&dst, txt, 0, lineY, dst.w, color, Graphics::kTextAlignCenter); - else if (justify == TXT_JUSTIFY_RIGHT) - fnt.drawString(&dst, txt, 0, lineY, dst.w, color, Graphics::kTextAlignRight); -} + // Create the initial text state + TextStyleState currentState; -int32 TextRenderer::drawTxt(const Common::String &txt, cTxtStyle &fontStyle, Graphics::Surface &dst) { + // Create an empty font and bind it to the state StyledTTFont font(_engine); - fontStyle.setFont(font); + currentState.updateFontWithTextState(font); - uint32 clr = _engine->_resourcePixelFormat.RGBToColor(fontStyle._red, fontStyle._green, fontStyle._blue); + Common::String currentSentence; // Not a true 'grammatical' sentence. Rather, it's just a collection of words + Common::String currentWord; + int sentenceWidth = 0; + int wordWidth = 0; + int lineWidth = 0; + int lineHeight = font.getFontHeight(); - int16 w; + uint currentLineNumber = 0u; - w = font.getStringWidth(txt); + uint numSpaces = 0u; + int spaceWidth = 0; - drawTxtWithJustify(txt, font, clr, dst, 0, fontStyle._justify); + // The pixel offset to the currentSentence + Common::Point sentencePixelOffset; - return w; -} + uint i = 0u; + uint stringlen = text.size(); -void TextRenderer::drawTxtInOneLine(const Common::String &text, Graphics::Surface &dst) { - const int16 TXT_CFG_TEXTURES_LINES = 256; // For now I don't want remake it - const int TXT_CFG_TEXTURES_PER_LINE = 6; - cTxtStyle style, style2; - int16 startTextPosition = -1; - int16 endTextPosition = -1; - int16 i = 0; - int16 dx = 0, dy = 0; - int16 textPixelWidth; - int16 textPosition = 0; - Common::String buf; - Common::String buf2; - - Graphics::Surface *TxtSurfaces[TXT_CFG_TEXTURES_LINES][TXT_CFG_TEXTURES_PER_LINE]; - int16 currentline = 0, currentlineitm = 0; - - int TxtJustify[TXT_CFG_TEXTURES_LINES]; - int TxtPoint[TXT_CFG_TEXTURES_LINES]; - - for (int16 k = 0; k < TXT_CFG_TEXTURES_LINES; k++) { - TxtPoint[k] = 0; - for (int j = 0; j < TXT_CFG_TEXTURES_PER_LINE; j++) - TxtSurfaces[k][j] = NULL; - } - - int16 stringlen = text.size(); + while (i < stringlen) { + if (text[i] == '<') { + // Flush the currentWord to the currentSentence + currentSentence += currentWord; + sentenceWidth += wordWidth; + + // Reset the word variables + currentWord.clear(); + wordWidth = 0; + + // Parse the style tag + uint startTextPosition = i; + while (i < stringlen && text[i] != '>') { + ++i; + } + uint endTextPosition = i; - StyledTTFont font(_engine); + uint32 textColor = currentState.getTextColor(_engine); - style.setFont(font); + uint stateChanges = 0u; + if ((endTextPosition - startTextPosition - 1) > 0) { + stateChanges = currentState.parseStyle(Common::String(text.c_str() + startTextPosition + 1), endTextPosition - startTextPosition - 1); + } - int16 prevbufspace = 0, prevtxtspace = 0; + if (stateChanges & (TEXT_CHANGE_FONT_TYPE | TEXT_CHANGE_FONT_STYLE)) { + // Use the last state to render out the current sentence + // Styles apply to the text 'after' them + if (!currentSentence.empty()) { + textSurfaces.push_back(TextSurface(font.renderSolidText(currentSentence, textColor), sentencePixelOffset, currentLineNumber)); - while (i < stringlen) { - TxtJustify[currentline] = style._justify; - if (text[i] == '<') { - int16 ret = 0; + lineWidth += sentenceWidth; + sentencePixelOffset.x += sentenceWidth; - startTextPosition = i; - while (i < stringlen && text[i] != '>') - i++; - endTextPosition = i; - if (startTextPosition != -1) - if ((endTextPosition - startTextPosition - 1) > 0) { - style2 = style; - ret = style.parseStyle(Common::String(text.c_str() + startTextPosition + 1), endTextPosition - startTextPosition - 1); + // Reset the sentence variables + currentSentence.clear(); + sentenceWidth = 0; } - if (ret & (TXT_RET_FNTCHG | TXT_RET_FNTSTL | TXT_RET_NEWLN)) { - if (buf.size() > 0) { - textPixelWidth = font.getStringWidth(buf); + // Update the current state with the style information + currentState.updateFontWithTextState(font); + + lineHeight = MAX(lineHeight, font.getFontHeight()); + spaceWidth = font.getCharWidth(' '); + } + if (stateChanges & TEXT_CHANGE_NEWLINE) { + // If the current sentence has content, render it out + if (!currentSentence.empty()) { + textSurfaces.push_back(TextSurface(font.renderSolidText(currentSentence, textColor), sentencePixelOffset, currentLineNumber)); + } + + // Set line width + lineWidths.push_back(lineWidth + sentenceWidth - (numSpaces * spaceWidth)); + + currentSentence.clear(); + sentenceWidth = 0; + + // Update the offsets + sentencePixelOffset.x = 0u; + sentencePixelOffset.y += lineHeight; + + // Reset the line variables + lineHeight = font.getFontHeight(); + lineWidth = 0; + ++currentLineNumber; + lineJustifications.push_back(currentState._justification); + } + if (stateChanges & TEXT_CHANGE_HAS_STATE_BOX) { + Common::String temp = Common::String::format("%d", _engine->getScriptManager()->getStateValue(currentState._statebox)); + wordWidth += font.getStringWidth(temp); - TxtSurfaces[currentline][currentlineitm] = render(font, buf, style2); - TxtPoint[currentline] = MAX(font.getFontHeight(), TxtPoint[currentline]); + // If the word causes the line to overflow, render the sentence and start a new line + if (lineWidth + sentenceWidth + wordWidth > dest.w) { + textSurfaces.push_back(TextSurface(font.renderSolidText(currentSentence, textColor), sentencePixelOffset, currentLineNumber)); - currentlineitm++; + // Set line width + lineWidths.push_back(lineWidth + sentenceWidth - (numSpaces * spaceWidth)); - buf.clear(); - prevbufspace = 0; - textPosition = 0; - dx += textPixelWidth; + currentSentence.clear(); + sentenceWidth = 0; - } - if (ret & TXT_RET_FNTCHG) { - style.setFont(font); - } - if (ret & TXT_RET_FNTSTL) - style.setFontStyle(font); + // Update the offsets + sentencePixelOffset.x = 0u; + sentencePixelOffset.y += lineHeight; - if (ret & TXT_RET_NEWLN) { - currentline++; - currentlineitm = 0; - dx = 0; + // Reset the line variables + lineHeight = font.getFontHeight(); + lineWidth = 0; + ++currentLineNumber; + lineJustifications.push_back(currentState._justification); } } - - if (ret & TXT_RET_HASSTBOX) { - Common::String buf3; - buf3 = Common::String::format("%d", _engine->getScriptManager()->getStateValue(style._statebox)); - buf += buf3; - textPosition += buf3.size(); - } - } else { - - buf += text[i]; - textPosition++; + currentWord += text[i]; + wordWidth += font.getCharWidth(text[i]); if (text[i] == ' ') { - prevbufspace = textPosition - 1; - prevtxtspace = i; - } + // When we hit the first space, flush the current word to the sentence + if (!currentWord.empty()) { + currentSentence += currentWord; + sentenceWidth += wordWidth; - if (font.isLoaded()) { - textPixelWidth = font.getStringWidth(buf); - if (textPixelWidth + dx > dst.w) { - if (prevbufspace == 0) { - prevtxtspace = i; - prevbufspace = textPosition - 1; - } - buf2 = Common::String(buf.c_str(), prevbufspace + 1); + currentWord.clear(); + wordWidth = 0; + } - if (buf2.size() > 0) { - TxtSurfaces[currentline][currentlineitm] = render(font, buf2, style); - TxtPoint[currentline] = MAX(font.getFontHeight(), TxtPoint[currentline]); + // We track the number of spaces so we can disregard their width in lineWidth calculations + ++numSpaces; + } else { + // If the word causes the line to overflow, render the sentence and start a new line + if (lineWidth + sentenceWidth + wordWidth > dest.w) { + // Only render out content + if (!currentSentence.empty()) { + textSurfaces.push_back(TextSurface(font.renderSolidText(currentSentence, currentState.getTextColor(_engine)), sentencePixelOffset, currentLineNumber)); } - buf.clear(); - i = prevtxtspace; - prevbufspace = 0; - textPosition = 0; - currentline++; - currentlineitm = 0; - dx = 0; + // Set line width + lineWidths.push_back(lineWidth + sentenceWidth - (numSpaces * spaceWidth)); + + currentSentence.clear(); + sentenceWidth = 0; + + // Update the offsets + sentencePixelOffset.x = 0u; + sentencePixelOffset.y += lineHeight; + + // Reset the line variables + lineHeight = font.getFontHeight(); + lineWidth = 0; + ++currentLineNumber; + lineJustifications.push_back(currentState._justification); } + + numSpaces = 0u; } } + i++; } - if (buf.size() > 0) { - TxtSurfaces[currentline][currentlineitm] = render(font, buf, style); - TxtPoint[currentline] = MAX(font.getFontHeight(), TxtPoint[currentline]); + // Render out any remaining words/sentences + if (!currentWord.empty() || !currentSentence.empty()) { + currentSentence += currentWord; + sentenceWidth += wordWidth; + + textSurfaces.push_back(TextSurface(font.renderSolidText(currentSentence, currentState.getTextColor(_engine)), sentencePixelOffset, currentLineNumber)); } - dy = 0; - for (i = 0; i <= currentline; i++) { - int16 j = 0; - int16 width = 0; - while (TxtSurfaces[i][j] != NULL) { - width += TxtSurfaces[i][j]->w; - j++; - } - dx = 0; - Common::Rect empty; - for (int32 jj = 0; jj < j; jj++) { - if (TxtJustify[i] == TXT_JUSTIFY_LEFT) - _engine->getRenderManager()->blitSurfaceToSurface(*TxtSurfaces[i][jj], empty, dst, dx, dy + TxtPoint[i] - TxtSurfaces[i][jj]->h, 0); - - else if (TxtJustify[i] == TXT_JUSTIFY_CENTER) - _engine->getRenderManager()->blitSurfaceToSurface(*TxtSurfaces[i][jj], empty, dst, ((dst.w - width) / 2) + dx, dy + TxtPoint[i] - TxtSurfaces[i][jj]->h, 0); + lineWidths.push_back(lineWidth + sentenceWidth); + lineJustifications.push_back(currentState._justification); - else if (TxtJustify[i] == TXT_JUSTIFY_RIGHT) - _engine->getRenderManager()->blitSurfaceToSurface(*TxtSurfaces[i][jj], empty, dst, dst.w - width + dx, dy + TxtPoint[i] - TxtSurfaces[i][jj]->h, 0); + for (Common::Array::iterator iter = textSurfaces.begin(); iter != textSurfaces.end(); ++iter) { + Common::Rect empty; - dx += TxtSurfaces[i][jj]->w; + if (lineJustifications[iter->_lineNumber] == TEXT_JUSTIFY_LEFT) { + _engine->getRenderManager()->blitSurfaceToSurface(*iter->_surface, empty, dest, iter->_surfaceOffset.x, iter->_surfaceOffset.y, 0); + } else if (lineJustifications[iter->_lineNumber] == TEXT_JUSTIFY_CENTER) { + _engine->getRenderManager()->blitSurfaceToSurface(*iter->_surface, empty, dest, ((dest.w - lineWidths[iter->_lineNumber]) / 2) + iter->_surfaceOffset.x, iter->_surfaceOffset.y, 0); + } else if (lineJustifications[iter->_lineNumber] == TEXT_JUSTIFY_RIGHT) { + _engine->getRenderManager()->blitSurfaceToSurface(*iter->_surface, empty, dest, dest.w - lineWidths[iter->_lineNumber] + iter->_surfaceOffset.x, iter->_surfaceOffset.y, 0); } - dy += TxtPoint[i]; + // Release memory + iter->_surface->free(); + delete iter->_surface; } - - for (i = 0; i < TXT_CFG_TEXTURES_LINES; i++) - for (int32 j = 0; j < TXT_CFG_TEXTURES_PER_LINE; j++) - if (TxtSurfaces[i][j] != NULL) { - TxtSurfaces[i][j]->free(); - delete TxtSurfaces[i][j]; - } } Common::String readWideLine(Common::SeekableReadStream &stream) { diff --git a/engines/zvision/text/text.h b/engines/zvision/text/text.h index c942b8141a..d35b90499d 100644 --- a/engines/zvision/text/text.h +++ b/engines/zvision/text/text.h @@ -32,59 +32,53 @@ namespace ZVision { class ZVision; -enum txtJustify { - TXT_JUSTIFY_CENTER = 0, - TXT_JUSTIFY_LEFT = 1, - TXT_JUSTIFY_RIGHT = 2 +enum TextJustification { + TEXT_JUSTIFY_CENTER = 0, + TEXT_JUSTIFY_LEFT = 1, + TEXT_JUSTIFY_RIGHT = 2 }; -enum txtReturn { - TXT_RET_NOTHING = 0x0, - TXT_RET_FNTCHG = 0x1, - TXT_RET_FNTSTL = 0x2, - TXT_RET_NEWLN = 0x4, - TXT_RET_HASSTBOX = 0x8 +enum TextChange { + TEXT_CHANGE_NONE = 0x0, + TEXT_CHANGE_FONT_TYPE = 0x1, + TEXT_CHANGE_FONT_STYLE = 0x2, + TEXT_CHANGE_NEWLINE = 0x4, + TEXT_CHANGE_HAS_STATE_BOX = 0x8 }; -class cTxtStyle { +class TextStyleState { public: - cTxtStyle(); - txtReturn parseStyle(const Common::String &strin, int16 len); - void readAllStyle(const Common::String &txt); - void setFontStyle(StyledTTFont &font); - void setFont(StyledTTFont &font); + TextStyleState(); + TextChange parseStyle(const Common::String &str, int16 len); + void readAllStyles(const Common::String &txt); + void updateFontWithTextState(StyledTTFont &font); + + uint32 getTextColor(ZVision *engine) { + return engine->_resourcePixelFormat.RGBToColor(_red, _green, _blue); + } public: Common::String _fontname; - txtJustify _justify; // 0 - center, 1-left, 2-right + TextJustification _justification; // 0 - center, 1-left, 2-right int16 _size; uint8 _red; // 0-255 uint8 _green; // 0-255 uint8 _blue; // 0-255 -#if 0 - int8 _newline; - int8 _escapement; -#endif bool _italic; bool _bold; bool _underline; bool _strikeout; -#if 0 - bool _skipcolor; -#endif int32 _statebox; bool _sharp; - // char image ?? }; class TextRenderer { public: TextRenderer(ZVision *engine): _engine(engine) {}; - void drawTxtWithJustify(const Common::String &txt, StyledTTFont &fnt, uint32 color, Graphics::Surface &dst, int lineY, txtJustify justify); - int32 drawTxt(const Common::String &txt, cTxtStyle &fontStyle, Graphics::Surface &dst); - Graphics::Surface *render(StyledTTFont &fnt, const Common::String &txt, cTxtStyle &style); - void drawTxtInOneLine(const Common::String &txt, Graphics::Surface &dst); + void drawTextWithJustification(const Common::String &text, StyledTTFont &font, uint32 color, Graphics::Surface &dest, int lineY, TextJustification jusification); + int32 drawText(const Common::String &text, TextStyleState &state, Graphics::Surface &dest); + void drawTextWithWordWrapping(const Common::String &text, Graphics::Surface &dest); private: ZVision *_engine; diff --git a/engines/zvision/text/truetype_font.cpp b/engines/zvision/text/truetype_font.cpp index f7580fb553..8e402efc08 100644 --- a/engines/zvision/text/truetype_font.cpp +++ b/engines/zvision/text/truetype_font.cpp @@ -56,21 +56,23 @@ const FontStyle getSystemFont(int fontIndex) { StyledTTFont::StyledTTFont(ZVision *engine) { _engine = engine; _style = 0; - _font = NULL; + _font = nullptr; _lineHeight = 0; } StyledTTFont::~StyledTTFont() { - if (_font) - delete _font; + delete _font; } bool StyledTTFont::loadFont(const Common::String &fontName, int32 point, uint style) { _style = style; - return loadFont(fontName, point); -} -bool StyledTTFont::loadFont(const Common::String &fontName, int32 point) { + // Don't re-load the font if we've already loaded it + // We have to check for empty so we can default to Arial + if (!fontName.empty() && _fontName.equalsIgnoreCase(fontName)) { + return true; + } + Common::String newFontName; Common::String freeFontName; Common::String liberationFontName; @@ -82,16 +84,16 @@ bool StyledTTFont::loadFont(const Common::String &fontName, int32 point) { freeFontName = curFont.freeFontBase; liberationFontName = curFont.liberationFontBase; - if ((_style & STTF_BOLD) && (_style & STTF_ITALIC)) { + if ((_style & TTF_STYLE_BOLD) && (_style & TTF_STYLE_ITALIC)) { newFontName += "bi"; freeFontName += "Bold"; freeFontName += curFont.freeFontItalicName; liberationFontName += "-BoldItalic"; - } else if (_style & STTF_BOLD) { + } else if (_style & TTF_STYLE_BOLD) { newFontName += "bd"; freeFontName += "Bold"; liberationFontName += "-Bold"; - } else if (_style & STTF_ITALIC) { + } else if (_style & TTF_STYLE_ITALIC) { newFontName += "i"; freeFontName += curFont.freeFontItalicName; liberationFontName += "-Italic"; @@ -113,7 +115,7 @@ bool StyledTTFont::loadFont(const Common::String &fontName, int32 point) { liberationFontName = "LiberationSans-Regular.ttf"; } - bool sharp = (_style & STTF_SHARP) == STTF_SHARP; + bool sharp = (_style & TTF_STYLE_SHARP) == TTF_STYLE_SHARP; Common::File file; if (!file.open(newFontName) && !_engine->getSearchManager()->openFile(file, newFontName) && @@ -121,51 +123,45 @@ bool StyledTTFont::loadFont(const Common::String &fontName, int32 point) { !file.open(freeFontName) && !_engine->getSearchManager()->openFile(file, freeFontName)) error("Unable to open font file %s (Liberation Font alternative: %s, FreeFont alternative: %s)", newFontName.c_str(), liberationFontName.c_str(), freeFontName.c_str()); - Graphics::Font *_newFont = Graphics::loadTTFFont(file, point, 60, (sharp ? Graphics::kTTFRenderModeMonochrome : Graphics::kTTFRenderModeNormal)); // 66 dpi for 640 x 480 on 14" display - if (_newFont) { - if (!_font) - delete _font; - _font = _newFont; + Graphics::Font *newFont = Graphics::loadTTFFont(file, point, 60, (sharp ? Graphics::kTTFRenderModeMonochrome : Graphics::kTTFRenderModeNormal)); // 66 dpi for 640 x 480 on 14" display + if (newFont == nullptr) { + return false; } - _fntName = fontName; - _lineHeight = point; + delete _font; + _font = newFont; - if (_font) - return true; - return false; -} + _fontName = fontName; + _lineHeight = point; -void StyledTTFont::setStyle(uint newStyle) { - if ((_style & (STTF_BOLD | STTF_ITALIC | STTF_SHARP)) != (newStyle & (STTF_BOLD | STTF_ITALIC | STTF_SHARP))) { - _style = newStyle; - loadFont(_fntName, _lineHeight); - } else { - _style = newStyle; - } + return true; } int StyledTTFont::getFontHeight() { if (_font) return _font->getFontHeight(); + return 0; } int StyledTTFont::getMaxCharWidth() { if (_font) return _font->getMaxCharWidth(); + return 0; } int StyledTTFont::getCharWidth(byte chr) { if (_font) return _font->getCharWidth(chr); + return 0; } int StyledTTFont::getKerningOffset(byte left, byte right) { if (_font) return _font->getKerningOffset(left, right); + return 0; } @@ -202,12 +198,12 @@ Common::U32String StyledTTFont::convertUtf8ToUtf32(const Common::String &str) { void StyledTTFont::drawChar(Graphics::Surface *dst, byte chr, int x, int y, uint32 color) { if (_font) { _font->drawChar(dst, chr, x, y, color); - if (_style & STTF_UNDERLINE) { + if (_style & TTF_STYLE_UNDERLINE) { int16 pos = floor(_font->getFontHeight() * 0.87); int thk = MAX((int)(_font->getFontHeight() * 0.05), 1); dst->fillRect(Common::Rect(x, y + pos, x + _font->getCharWidth(chr), y + pos + thk), color); } - if (_style & STTF_STRIKEOUT) { + if (_style & TTF_STYLE_STRIKETHROUGH) { int16 pos = floor(_font->getFontHeight() * 0.60); int thk = MAX((int)(_font->getFontHeight() * 0.05), 1); dst->fillRect(Common::Rect(x, y + pos, x + _font->getCharWidth(chr), y + pos + thk), color); @@ -219,7 +215,7 @@ void StyledTTFont::drawString(Graphics::Surface *dst, const Common::String &str, if (_font) { Common::U32String u32str = convertUtf8ToUtf32(str); _font->drawString(dst, u32str, x, y, w, color, align); - if (_style & STTF_UNDERLINE) { + if (_style & TTF_STYLE_UNDERLINE) { int16 pos = floor(_font->getFontHeight() * 0.87); int16 wd = MIN(_font->getStringWidth(u32str), w); int16 stX = x; @@ -232,7 +228,7 @@ void StyledTTFont::drawString(Graphics::Surface *dst, const Common::String &str, dst->fillRect(Common::Rect(stX, y + pos, stX + wd, y + pos + thk), color); } - if (_style & STTF_STRIKEOUT) { + if (_style & TTF_STYLE_STRIKETHROUGH) { int16 pos = floor(_font->getFontHeight() * 0.60); int16 wd = MIN(_font->getStringWidth(u32str), w); int16 stX = x; diff --git a/engines/zvision/text/truetype_font.h b/engines/zvision/text/truetype_font.h index caa9c09a76..6abe05cda6 100644 --- a/engines/zvision/text/truetype_font.h +++ b/engines/zvision/text/truetype_font.h @@ -53,11 +53,11 @@ public: ~StyledTTFont(); enum { - STTF_BOLD = 1, - STTF_ITALIC = 2, - STTF_UNDERLINE = 4, - STTF_STRIKEOUT = 8, - STTF_SHARP = 16 + TTF_STYLE_BOLD = 0x01, + TTF_STYLE_ITALIC = 0x02, + TTF_STYLE_UNDERLINE = 0x04, + TTF_STYLE_STRIKETHROUGH = 0x08, + TTF_STYLE_SHARP = 0x10 }; private: @@ -65,12 +65,10 @@ private: Graphics::Font *_font; int _lineHeight; uint _style; - Common::String _fntName; + Common::String _fontName; public: - bool loadFont(const Common::String &fontName, int32 point); bool loadFont(const Common::String &fontName, int32 point, uint style); - void setStyle(uint newStyle); int getFontHeight(); int getMaxCharWidth(); -- cgit v1.2.3 From cff81cd70cbd2453619f43ec0e3cc5cab826d91e Mon Sep 17 00:00:00 2001 From: RichieSams Date: Wed, 11 Feb 2015 15:01:46 -0600 Subject: ZVISION: Remove forced render to screen timedMessage() is always called from the scripting system. Which is updated before the rendering system. Therefore, the message will already be rendered this frame, when the renderingManager->update() is called. --- engines/zvision/graphics/render_manager.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'engines') diff --git a/engines/zvision/graphics/render_manager.cpp b/engines/zvision/graphics/render_manager.cpp index 8758097c93..b8fa16bc1b 100644 --- a/engines/zvision/graphics/render_manager.cpp +++ b/engines/zvision/graphics/render_manager.cpp @@ -971,8 +971,6 @@ void RenderManager::bkgFill(uint8 r, uint8 g, uint8 b) { void RenderManager::timedMessage(const Common::String &str, uint16 milsecs) { uint16 msgid = createSubArea(); updateSubArea(msgid, str); - processSubs(0); - renderSceneToScreen(); deleteSubArea(msgid, milsecs); } -- cgit v1.2.3 From 8ecc5e52c5ad49d9fe40490d666d47349569d151 Mon Sep 17 00:00:00 2001 From: RichieSams Date: Wed, 11 Feb 2015 15:03:21 -0600 Subject: ZVISION: Handle question text rendering manually, rather than forcing an entire screen refresh --- engines/zvision/graphics/render_manager.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/zvision/graphics/render_manager.cpp b/engines/zvision/graphics/render_manager.cpp index b8fa16bc1b..67410b4b6a 100644 --- a/engines/zvision/graphics/render_manager.cpp +++ b/engines/zvision/graphics/render_manager.cpp @@ -975,10 +975,11 @@ void RenderManager::timedMessage(const Common::String &str, uint16 milsecs) { } bool RenderManager::askQuestion(const Common::String &str) { - uint16 msgid = createSubArea(); - updateSubArea(msgid, str); - processSubs(0); - renderSceneToScreen(); + Graphics::Surface textSurface; + textSurface.create(_subtitleArea.width(), _subtitleArea.height(), _engine->_resourcePixelFormat); + _engine->getTextRenderer()->drawTextWithWordWrapping(str, textSurface); + copyToScreen(textSurface, _subtitleArea, 0, 0); + _engine->stopClock(); int result = 0; @@ -1029,7 +1030,14 @@ bool RenderManager::askQuestion(const Common::String &str) { else _system->delayMillis(66); } - deleteSubArea(msgid); + + // Draw over the text in order to clear it + textSurface.fillRect(Common::Rect(_subtitleArea.width(), _subtitleArea.height()), 0); + copyToScreen(textSurface, _subtitleArea, 0, 0); + + // Free the surface + textSurface.free(); + _engine->startClock(); return result == 2; } -- cgit v1.2.3 From 2d2cfbe005b93397f1e121888b0358e137ccc863 Mon Sep 17 00:00:00 2001 From: RichieSams Date: Wed, 11 Feb 2015 15:08:32 -0600 Subject: ZVISION: Create temporary subtitle surfaces on the stack rather than the heap --- engines/zvision/graphics/render_manager.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/zvision/graphics/render_manager.cpp b/engines/zvision/graphics/render_manager.cpp index 67410b4b6a..3772d5909e 100644 --- a/engines/zvision/graphics/render_manager.cpp +++ b/engines/zvision/graphics/render_manager.cpp @@ -753,13 +753,12 @@ void RenderManager::processSubs(uint16 deltatime) { for (SubtitleMap::iterator it = _subsList.begin(); it != _subsList.end(); it++) { OneSubtitle *sub = &it->_value; if (sub->txt.size()) { - Graphics::Surface *rndr = new Graphics::Surface(); - rndr->create(sub->r.width(), sub->r.height(), _engine->_resourcePixelFormat); - _engine->getTextRenderer()->drawTextWithWordWrapping(sub->txt, *rndr); + Graphics::Surface subtitleSurface; + subtitleSurface.create(sub->r.width(), sub->r.height(), _engine->_resourcePixelFormat); + _engine->getTextRenderer()->drawTextWithWordWrapping(sub->txt, subtitleSurface); Common::Rect empty; - blitSurfaceToSurface(*rndr, empty, _subtitleSurface, sub->r.left - _subtitleArea.left + _workingWindow.left, sub->r.top - _subtitleArea.top + _workingWindow.top); - rndr->free(); - delete rndr; + blitSurfaceToSurface(subtitleSurface, empty, _subtitleSurface, sub->r.left - _subtitleArea.left + _workingWindow.left, sub->r.top - _subtitleArea.top + _workingWindow.top); + subtitleSurface.free(); } sub->redraw = false; } -- cgit v1.2.3 From 14914b2a31399ceb6b2e4d7616535e346ee3acd6 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 14 Feb 2015 14:45:08 +0200 Subject: ZVISION: Add custom equality operators for game location This makes the location checks more readable --- engines/zvision/core/events.cpp | 2 +- engines/zvision/scripting/effects/music_effect.cpp | 3 +-- engines/zvision/scripting/script_manager.cpp | 7 +++---- engines/zvision/scripting/script_manager.h | 22 ++++++++++++++++++++++ 4 files changed, 27 insertions(+), 7 deletions(-) (limited to 'engines') diff --git a/engines/zvision/core/events.cpp b/engines/zvision/core/events.cpp index 9cf5d04a7a..cc1c00b6d0 100644 --- a/engines/zvision/core/events.cpp +++ b/engines/zvision/core/events.cpp @@ -152,7 +152,7 @@ void ZVision::cheatCodes(uint8 key) { if (checkCode("HELLOSAILOR")) { Audio::AudioStream *soundStream; - if (loc.world == 'v' && loc.room == 'b' && loc.node == '1' && loc.view == '0') { + if (loc == "vb10") { soundStream = makeRawZorkStream("v000hpta.raw", this); } else { soundStream = makeRawZorkStream("v000hnta.raw", this); diff --git a/engines/zvision/scripting/effects/music_effect.cpp b/engines/zvision/scripting/effects/music_effect.cpp index 2e2084783d..ad3c0f6d22 100644 --- a/engines/zvision/scripting/effects/music_effect.cpp +++ b/engines/zvision/scripting/effects/music_effect.cpp @@ -227,8 +227,7 @@ bool PanTrackNode::process(uint32 deltaTimeInMillis) { int volumeCorrection = 2; if (_engine->getGameId() == GID_GRANDINQUISITOR) { - Location loc = scriptManager->getCurrentLocation(); - if (loc.world == 'd' && loc.room == 'c' && loc.node == '1' && loc.view == '0') + if (scriptManager->getCurrentLocation() == "dc10") volumeCorrection = 5; } diff --git a/engines/zvision/scripting/script_manager.cpp b/engines/zvision/scripting/script_manager.cpp index 71966b3125..70eaab2a0a 100644 --- a/engines/zvision/scripting/script_manager.cpp +++ b/engines/zvision/scripting/script_manager.cpp @@ -72,8 +72,7 @@ void ScriptManager::initialize() { } void ScriptManager::update(uint deltaTimeMillis) { - if (_currentLocation.node != _nextLocation.node || _currentLocation.room != _nextLocation.room || - _currentLocation.view != _nextLocation.view || _currentLocation.world != _nextLocation.world) { + if (_currentLocation != _nextLocation) { ChangeLocationReal(false); } @@ -543,7 +542,7 @@ void ScriptManager::changeLocation(char _world, char _room, char _node, char _vi _nextLocation.view = _view; _nextLocation.offset = offset; // If next location is 0000, return to the previous location. - if (_nextLocation.world == '0' && _nextLocation.room == '0' && _nextLocation.node == '0' && _nextLocation.view == '0') { + if (_nextLocation == "0000") { if (getStateValue(StateKey_World) != 'g' || getStateValue(StateKey_Room) != 'j') { _nextLocation.world = getStateValue(StateKey_LastWorld); _nextLocation.room = getStateValue(StateKey_LastRoom); @@ -680,7 +679,7 @@ void ScriptManager::ChangeLocationReal(bool isLoading) { // Change the background position _engine->getRenderManager()->setBackgroundPosition(_nextLocation.offset); - if (_currentLocation.world == 0 && _currentLocation.room == 0 && _currentLocation.node == 0 && _currentLocation.view == 0) { + if (_currentLocation == "0000") { _currentLocation = _nextLocation; execScope(world); execScope(room); diff --git a/engines/zvision/scripting/script_manager.h b/engines/zvision/scripting/script_manager.h index d8e3721d43..7c276bf917 100644 --- a/engines/zvision/scripting/script_manager.h +++ b/engines/zvision/scripting/script_manager.h @@ -113,6 +113,28 @@ struct Location { uint32 offset; }; +inline bool operator==(const Location& lhs, const Location& rhs) { + return ( + lhs.world == rhs.world && + lhs.room == rhs.room && + lhs.node == rhs.node && + lhs.view == rhs.view + ); +} + +inline bool operator==(const Location& lhs, const char* rhs) { + Common::String lhsStr = Common::String::format("%c%c%c%c", lhs.world, lhs.room, lhs.node, lhs.view); + return lhsStr == rhs; +} + +inline bool operator!=(const Location& lhs, const Location& rhs) { + return !(lhs == rhs); +} + +inline bool operator!=(const Location& lhs, const char* rhs) { + return !(lhs == rhs); +} + typedef Common::List PuzzleList; typedef Common::Queue PuzzleQueue; typedef Common::List ControlList; -- cgit v1.2.3 From 60c06b84b68a5711db442d8fd296f3978d685da5 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 14 Feb 2015 14:55:09 +0200 Subject: ZVISION: Fix script bug #6794 - "ZVISION: Yoruk's coffin instant death" Fixes an edge case where the player goes to the dark room with the grue without holding a torch, and then quickly runs away before the grue's sound effect finishes. Many thanks to eriktorbjorn for the original workaround --- engines/zvision/scripting/actions.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'engines') diff --git a/engines/zvision/scripting/actions.cpp b/engines/zvision/scripting/actions.cpp index 5238561149..248ebaec49 100644 --- a/engines/zvision/scripting/actions.cpp +++ b/engines/zvision/scripting/actions.cpp @@ -480,6 +480,14 @@ ActionMusic::ActionMusic(ZVision *engine, int32 slotkey, const Common::String &l } _volume = new ValueSlot(engine->getScriptManager(), volumeBuffer); } + + // WORKAROUND for a script bug in Zork Nemesis, rooms mq70/mq80. + // Fixes an edge case where the player goes to the dark room with the grue + // without holding a torch, and then quickly runs away before the grue's + // sound effect finishes. Fixes script bug #6794. + if (engine->getGameId() == GID_NEMESIS && _slotKey == 14822 && engine->getScriptManager()->getStateValue(_slotKey) == 2) + engine->getScriptManager()->setStateValue(_slotKey, 0); + } ActionMusic::~ActionMusic() { -- cgit v1.2.3 From 9ce285a11e1bfc981c518e89f2401b1896b4a367 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 14 Feb 2015 15:07:15 +0200 Subject: ZVISION: Also reference the script manager in ResultAction members --- engines/zvision/scripting/actions.cpp | 127 +++++++++++++++++----------------- engines/zvision/scripting/actions.h | 4 +- 2 files changed, 68 insertions(+), 63 deletions(-) (limited to 'engines') diff --git a/engines/zvision/scripting/actions.cpp b/engines/zvision/scripting/actions.cpp index 248ebaec49..90d32e47ce 100644 --- a/engines/zvision/scripting/actions.cpp +++ b/engines/zvision/scripting/actions.cpp @@ -47,6 +47,9 @@ namespace ZVision { +ResultAction::ResultAction(ZVision *engine, int32 slotkey) : _engine(engine), _slotKey(slotkey), _scriptManager(engine->getScriptManager()) { +} + ////////////////////////////////////////////////////////////////////////////// // ActionAdd ////////////////////////////////////////////////////////////////////////////// @@ -60,7 +63,7 @@ ActionAdd::ActionAdd(ZVision *engine, int32 slotkey, const Common::String &line) } bool ActionAdd::execute() { - _engine->getScriptManager()->setStateValue(_key, _engine->getScriptManager()->getStateValue(_key) + _value); + _scriptManager->setStateValue(_key, _scriptManager->getStateValue(_key) + _value); return true; } @@ -75,7 +78,7 @@ ActionAssign::ActionAssign(ZVision *engine, int32 slotkey, const Common::String char buf[64]; memset(buf, 0, 64); sscanf(line.c_str(), "%u, %s", &_key, buf); - _value = new ValueSlot(_engine->getScriptManager(), buf); + _value = new ValueSlot(_scriptManager, buf); } ActionAssign::~ActionAssign() { @@ -83,7 +86,7 @@ ActionAssign::~ActionAssign() { } bool ActionAssign::execute() { - _engine->getScriptManager()->setStateValue(_key, _value->getValue()); + _scriptManager->setStateValue(_key, _value->getValue()); return true; } @@ -100,7 +103,7 @@ ActionAttenuate::ActionAttenuate(ZVision *engine, int32 slotkey, const Common::S } bool ActionAttenuate::execute() { - ScriptingEffect *fx = _engine->getScriptManager()->getSideFX(_key); + ScriptingEffect *fx = _scriptManager->getSideFX(_key); if (fx && fx->getType() == ScriptingEffect::SCRIPTING_EFFECT_AUDIO) { MusicNodeBASE *mus = (MusicNodeBASE *)fx; mus->setVolume(255 * (10000 - abs(_attenuation)) / 10000 ); @@ -125,7 +128,7 @@ ActionChangeLocation::ActionChangeLocation(ZVision *engine, int32 slotkey, const bool ActionChangeLocation::execute() { // We can't directly call ScriptManager::ChangeLocationIntern() because doing so clears all the Puzzles, and thus would corrupt the current puzzle checking - _engine->getScriptManager()->changeLocation(_world, _room, _node, _view, _offset); + _scriptManager->changeLocation(_world, _room, _node, _view, _offset); // Tell the puzzle system to stop checking any more puzzles return false; } @@ -151,7 +154,7 @@ ActionCrossfade::ActionCrossfade(ZVision *engine, int32 slotkey, const Common::S bool ActionCrossfade::execute() { if (_keyOne) { - ScriptingEffect *fx = _engine->getScriptManager()->getSideFX(_keyOne); + ScriptingEffect *fx = _scriptManager->getSideFX(_keyOne); if (fx && fx->getType() == ScriptingEffect::SCRIPTING_EFFECT_AUDIO) { MusicNodeBASE *mus = (MusicNodeBASE *)fx; if (_oneStartVolume >= 0) @@ -162,7 +165,7 @@ bool ActionCrossfade::execute() { } if (_keyTwo) { - ScriptingEffect *fx = _engine->getScriptManager()->getSideFX(_keyTwo); + ScriptingEffect *fx = _scriptManager->getSideFX(_keyTwo); if (fx && fx->getType() == ScriptingEffect::SCRIPTING_EFFECT_AUDIO) { MusicNodeBASE *mus = (MusicNodeBASE *)fx; if (_twoStartVolume >= 0) @@ -233,7 +236,7 @@ ActionDisableControl::ActionDisableControl(ZVision *engine, int32 slotkey, const } bool ActionDisableControl::execute() { - _engine->getScriptManager()->setStateFlag(_key, Puzzle::DISABLED); + _scriptManager->setStateFlag(_key, Puzzle::DISABLED); return true; } @@ -250,7 +253,7 @@ ActionDisplayMessage::ActionDisplayMessage(ZVision *engine, int32 slotkey, const } bool ActionDisplayMessage::execute() { - Control *ctrl = _engine->getScriptManager()->getControl(_control); + Control *ctrl = _scriptManager->getControl(_control); if (ctrl && ctrl->getType() == Control::CONTROL_TITLER) { TitlerControl *titler = (TitlerControl *)ctrl; titler->setString(_msgid); @@ -289,14 +292,14 @@ ActionDistort::ActionDistort(ZVision *engine, int32 slotkey, const Common::Strin } ActionDistort::~ActionDistort() { - _engine->getScriptManager()->killSideFx(_distSlot); + _scriptManager->killSideFx(_distSlot); } bool ActionDistort::execute() { - if (_engine->getScriptManager()->getSideFX(_distSlot)) + if (_scriptManager->getSideFX(_distSlot)) return true; - _engine->getScriptManager()->addSideFX(new DistortNode(_engine, _distSlot, _speed, _startAngle, _endAngle, _startLineScale, _endLineScale)); + _scriptManager->addSideFX(new DistortNode(_engine, _distSlot, _speed, _startAngle, _endAngle, _startLineScale, _endLineScale)); return true; } @@ -313,7 +316,7 @@ ActionEnableControl::ActionEnableControl(ZVision *engine, int32 slotkey, const C } bool ActionEnableControl::execute() { - _engine->getScriptManager()->unsetStateFlag(_key, Puzzle::DISABLED); + _scriptManager->unsetStateFlag(_key, Puzzle::DISABLED); return true; } @@ -326,8 +329,8 @@ ActionFlushMouseEvents::ActionFlushMouseEvents(ZVision *engine, int32 slotkey) : } bool ActionFlushMouseEvents::execute() { - _engine->getScriptManager()->flushEvent(Common::EVENT_LBUTTONUP); - _engine->getScriptManager()->flushEvent(Common::EVENT_LBUTTONDOWN); + _scriptManager->flushEvent(Common::EVENT_LBUTTONUP); + _scriptManager->flushEvent(Common::EVENT_LBUTTONDOWN); return true; } @@ -360,22 +363,22 @@ ActionInventory::ActionInventory(ZVision *engine, int32 slotkey, const Common::S bool ActionInventory::execute() { switch (_type) { case 0: // add - _engine->getScriptManager()->inventoryAdd(_key); + _scriptManager->inventoryAdd(_key); break; case 1: // addi - _engine->getScriptManager()->inventoryAdd(_engine->getScriptManager()->getStateValue(_key)); + _scriptManager->inventoryAdd(_scriptManager->getStateValue(_key)); break; case 2: // drop if (_key >= 0) - _engine->getScriptManager()->inventoryDrop(_key); + _scriptManager->inventoryDrop(_key); else - _engine->getScriptManager()->inventoryDrop(_engine->getScriptManager()->getStateValue(StateKey_InventoryItem)); + _scriptManager->inventoryDrop(_scriptManager->getStateValue(StateKey_InventoryItem)); break; case 3: // dropi - _engine->getScriptManager()->inventoryDrop(_engine->getScriptManager()->getStateValue(_key)); + _scriptManager->inventoryDrop(_scriptManager->getStateValue(_key)); break; case 4: // cycle - _engine->getScriptManager()->inventoryCycle(); + _scriptManager->inventoryCycle(); break; default: break; @@ -416,9 +419,9 @@ ActionKill::ActionKill(ZVision *engine, int32 slotkey, const Common::String &lin bool ActionKill::execute() { if (_type) - _engine->getScriptManager()->killSideFxType((ScriptingEffect::ScriptingEffectType)_type); + _scriptManager->killSideFxType((ScriptingEffect::ScriptingEffectType)_type); else - _engine->getScriptManager()->killSideFx(_key); + _scriptManager->killSideFx(_key); return true; } @@ -465,7 +468,7 @@ ActionMusic::ActionMusic(ZVision *engine, int32 slotkey, const Common::String &l int note; int prog; sscanf(line.c_str(), "%u %d %d %14s", &type, &prog, ¬e, volumeBuffer); - _volume = new ValueSlot(_engine->getScriptManager(), volumeBuffer); + _volume = new ValueSlot(_scriptManager, volumeBuffer); _note = note; _prog = prog; } else { @@ -478,40 +481,40 @@ ActionMusic::ActionMusic(ZVision *engine, int32 slotkey, const Common::String &l warning("ActionMusic: Adjusting volume for %s from %s to 100", _fileName.c_str(), volumeBuffer); strcpy(volumeBuffer, "100"); } - _volume = new ValueSlot(engine->getScriptManager(), volumeBuffer); + _volume = new ValueSlot(_scriptManager, volumeBuffer); } // WORKAROUND for a script bug in Zork Nemesis, rooms mq70/mq80. // Fixes an edge case where the player goes to the dark room with the grue // without holding a torch, and then quickly runs away before the grue's // sound effect finishes. Fixes script bug #6794. - if (engine->getGameId() == GID_NEMESIS && _slotKey == 14822 && engine->getScriptManager()->getStateValue(_slotKey) == 2) - engine->getScriptManager()->setStateValue(_slotKey, 0); + if (engine->getGameId() == GID_NEMESIS && _slotKey == 14822 && _scriptManager->getStateValue(_slotKey) == 2) + _scriptManager->setStateValue(_slotKey, 0); } ActionMusic::~ActionMusic() { if (!_universe) - _engine->getScriptManager()->killSideFx(_slotKey); + _scriptManager->killSideFx(_slotKey); delete _volume; } bool ActionMusic::execute() { - if (_engine->getScriptManager()->getSideFX(_slotKey)) { - _engine->getScriptManager()->killSideFx(_slotKey); - _engine->getScriptManager()->setStateValue(_slotKey, 2); + if (_scriptManager->getSideFX(_slotKey)) { + _scriptManager->killSideFx(_slotKey); + _scriptManager->setStateValue(_slotKey, 2); } uint volume = _volume->getValue(); if (_midi) { - _engine->getScriptManager()->addSideFX(new MusicMidiNode(_engine, _slotKey, _prog, _note, volume)); + _scriptManager->addSideFX(new MusicMidiNode(_engine, _slotKey, _prog, _note, volume)); } else { if (!_engine->getSearchManager()->hasFile(_fileName)) return true; // Volume in the script files is mapped to [0, 100], but the ScummVM mixer uses [0, 255] - _engine->getScriptManager()->addSideFX(new MusicNode(_engine, _slotKey, _fileName, _loop, volume * 255 / 100)); + _scriptManager->addSideFX(new MusicNode(_engine, _slotKey, _fileName, _loop, volume * 255 / 100)); } return true; @@ -530,14 +533,14 @@ ActionPanTrack::ActionPanTrack(ZVision *engine, int32 slotkey, const Common::Str } ActionPanTrack::~ActionPanTrack() { - _engine->getScriptManager()->killSideFx(_slotKey); + _scriptManager->killSideFx(_slotKey); } bool ActionPanTrack::execute() { - if (_engine->getScriptManager()->getSideFX(_slotKey)) + if (_scriptManager->getSideFX(_slotKey)) return true; - _engine->getScriptManager()->addSideFX(new PanTrackNode(_engine, _slotKey, _musicSlot, _pos)); + _scriptManager->addSideFX(new PanTrackNode(_engine, _slotKey, _musicSlot, _pos)); return true; } @@ -587,18 +590,18 @@ ActionPreloadAnimation::ActionPreloadAnimation(ZVision *engine, int32 slotkey, c } ActionPreloadAnimation::~ActionPreloadAnimation() { - _engine->getScriptManager()->deleteSideFx(_slotKey); + _scriptManager->deleteSideFx(_slotKey); } bool ActionPreloadAnimation::execute() { - AnimationEffect *nod = (AnimationEffect *)_engine->getScriptManager()->getSideFX(_slotKey); + AnimationEffect *nod = (AnimationEffect *)_scriptManager->getSideFX(_slotKey); if (!nod) { nod = new AnimationEffect(_engine, _slotKey, _fileName, _mask, _framerate, false); - _engine->getScriptManager()->addSideFX(nod); + _scriptManager->addSideFX(nod); } else nod->stop(); - _engine->getScriptManager()->setStateValue(_slotKey, 2); + _scriptManager->setStateValue(_slotKey, 2); return true; } @@ -614,10 +617,10 @@ ActionUnloadAnimation::ActionUnloadAnimation(ZVision *engine, int32 slotkey, con } bool ActionUnloadAnimation::execute() { - AnimationEffect *nod = (AnimationEffect *)_engine->getScriptManager()->getSideFX(_key); + AnimationEffect *nod = (AnimationEffect *)_scriptManager->getSideFX(_key); if (nod && nod->getType() == ScriptingEffect::SCRIPTING_EFFECT_ANIM) - _engine->getScriptManager()->deleteSideFx(_key); + _scriptManager->deleteSideFx(_key); return true; } @@ -662,15 +665,15 @@ ActionPlayAnimation::ActionPlayAnimation(ZVision *engine, int32 slotkey, const C } ActionPlayAnimation::~ActionPlayAnimation() { - _engine->getScriptManager()->deleteSideFx(_slotKey); + _scriptManager->deleteSideFx(_slotKey); } bool ActionPlayAnimation::execute() { - AnimationEffect *nod = (AnimationEffect *)_engine->getScriptManager()->getSideFX(_slotKey); + AnimationEffect *nod = (AnimationEffect *)_scriptManager->getSideFX(_slotKey); if (!nod) { nod = new AnimationEffect(_engine, _slotKey, _fileName, _mask, _framerate); - _engine->getScriptManager()->addSideFX(nod); + _scriptManager->addSideFX(nod); } else nod->stop(); @@ -701,7 +704,7 @@ ActionPlayPreloadAnimation::ActionPlayPreloadAnimation(ZVision *engine, int32 sl } bool ActionPlayPreloadAnimation::execute() { - AnimationEffect *nod = (AnimationEffect *)_engine->getScriptManager()->getSideFX(_controlKey); + AnimationEffect *nod = (AnimationEffect *)_scriptManager->getSideFX(_controlKey); if (nod) nod->addPlayNode(_slotKey, _x1, _y1, _x2, _y2, _startFrame, _endFrame, _loopCount); @@ -742,11 +745,11 @@ ActionRegion::ActionRegion(ZVision *engine, int32 slotkey, const Common::String } ActionRegion::~ActionRegion() { - _engine->getScriptManager()->killSideFx(_slotKey); + _scriptManager->killSideFx(_slotKey); } bool ActionRegion::execute() { - if (_engine->getScriptManager()->getSideFX(_slotKey)) + if (_scriptManager->getSideFX(_slotKey)) return true; GraphicsEffect *effect = NULL; @@ -791,7 +794,7 @@ bool ActionRegion::execute() { } if (effect) { - _engine->getScriptManager()->addSideFX(new RegionNode(_engine, _slotKey, effect, _delay)); + _scriptManager->addSideFX(new RegionNode(_engine, _slotKey, effect, _delay)); _engine->getRenderManager()->addEffect(effect); } @@ -807,7 +810,7 @@ ActionRandom::ActionRandom(ZVision *engine, int32 slotkey, const Common::String char maxBuffer[64]; memset(maxBuffer, 0, 64); sscanf(line.c_str(), "%s", maxBuffer); - _max = new ValueSlot(_engine->getScriptManager(), maxBuffer); + _max = new ValueSlot(_scriptManager, maxBuffer); } ActionRandom::~ActionRandom() { @@ -816,7 +819,7 @@ ActionRandom::~ActionRandom() { bool ActionRandom::execute() { uint randNumber = _engine->getRandomSource()->getRandomNumber(_max->getValue()); - _engine->getScriptManager()->setStateValue(_slotKey, randNumber); + _scriptManager->setStateValue(_slotKey, randNumber); return true; } @@ -923,7 +926,7 @@ ActionStop::ActionStop(ZVision *engine, int32 slotkey, const Common::String &lin } bool ActionStop::execute() { - _engine->getScriptManager()->stopSideFx(_key); + _scriptManager->stopSideFx(_key); return true; } @@ -967,7 +970,7 @@ bool ActionStreamVideo::execute() { hiresFileName.setChar('o', hiresFileName.size() - 2); hiresFileName.setChar('b', hiresFileName.size() - 1); - if (_engine->getScriptManager()->getStateValue(StateKey_MPEGMovies) == 1 &&_engine->getSearchManager()->hasFile(hiresFileName)) { + if (_scriptManager->getStateValue(StateKey_MPEGMovies) == 1 &&_engine->getSearchManager()->hasFile(hiresFileName)) { // TODO: Enable once AC3 support is implemented if (!_engine->getSearchManager()->hasFile(_fileName)) // Check for the regular video return true; @@ -1026,14 +1029,14 @@ ActionSyncSound::ActionSyncSound(ZVision *engine, int32 slotkey, const Common::S } bool ActionSyncSound::execute() { - ScriptingEffect *fx = _engine->getScriptManager()->getSideFX(_syncto); + ScriptingEffect *fx = _scriptManager->getSideFX(_syncto); if (!fx) return true; if (!(fx->getType() & ScriptingEffect::SCRIPTING_EFFECT_ANIM)) return true; - _engine->getScriptManager()->addSideFX(new SyncSoundNode(_engine, _slotKey, _fileName, _syncto)); + _scriptManager->addSideFX(new SyncSoundNode(_engine, _slotKey, _fileName, _syncto)); return true; } @@ -1046,18 +1049,18 @@ ActionTimer::ActionTimer(ZVision *engine, int32 slotkey, const Common::String &l char timeBuffer[64]; memset(timeBuffer, 0, 64); sscanf(line.c_str(), "%s", timeBuffer); - _time = new ValueSlot(_engine->getScriptManager(), timeBuffer); + _time = new ValueSlot(_scriptManager, timeBuffer); } ActionTimer::~ActionTimer() { delete _time; - _engine->getScriptManager()->killSideFx(_slotKey); + _scriptManager->killSideFx(_slotKey); } bool ActionTimer::execute() { - if (_engine->getScriptManager()->getSideFX(_slotKey)) + if (_scriptManager->getSideFX(_slotKey)) return true; - _engine->getScriptManager()->addSideFX(new TimerNode(_engine, _slotKey, _time->getValue())); + _scriptManager->addSideFX(new TimerNode(_engine, _slotKey, _time->getValue())); return true; } @@ -1077,13 +1080,13 @@ ActionTtyText::ActionTtyText(ZVision *engine, int32 slotkey, const Common::Strin } ActionTtyText::~ActionTtyText() { - _engine->getScriptManager()->killSideFx(_slotKey); + _scriptManager->killSideFx(_slotKey); } bool ActionTtyText::execute() { - if (_engine->getScriptManager()->getSideFX(_slotKey)) + if (_scriptManager->getSideFX(_slotKey)) return true; - _engine->getScriptManager()->addSideFX(new ttyTextNode(_engine, _slotKey, _filename, _r, _delay)); + _scriptManager->addSideFX(new ttyTextNode(_engine, _slotKey, _filename, _r, _delay)); return true; } diff --git a/engines/zvision/scripting/actions.h b/engines/zvision/scripting/actions.h index 94c2d041fc..ff19fc54fc 100644 --- a/engines/zvision/scripting/actions.h +++ b/engines/zvision/scripting/actions.h @@ -32,6 +32,7 @@ namespace ZVision { // Forward declaration of ZVision. This file is included before ZVision is declared class ZVision; +class ScriptManager; class ValueSlot; /** @@ -40,7 +41,7 @@ class ValueSlot; */ class ResultAction { public: - ResultAction(ZVision *engine, int32 slotkey) : _engine(engine), _slotKey(slotkey) {} + ResultAction(ZVision *engine, int32 slotkey); virtual ~ResultAction() {} /** * This is called by the script system whenever a Puzzle's criteria are found to be true. @@ -53,6 +54,7 @@ public: virtual bool execute() = 0; protected: ZVision *_engine; + ScriptManager *_scriptManager; int32 _slotKey; }; -- cgit v1.2.3 From 53a2c30cb014997887e29f5fd0db1348d05990f0 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 14 Feb 2015 15:27:01 +0200 Subject: ZVISION: Fix script bug #6791 (max value of delay_render) This fixes the delay outside the Frobozz Electric building. In all other places, delay_render is called with a value ranging from 1 to 10, so the 100 here looks to be a script bug, and causes an unnecessary long pause in that scene. Thus, we're capping the frame delay value to 10. --- engines/zvision/scripting/actions.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'engines') diff --git a/engines/zvision/scripting/actions.cpp b/engines/zvision/scripting/actions.cpp index 90d32e47ce..21c97e766b 100644 --- a/engines/zvision/scripting/actions.cpp +++ b/engines/zvision/scripting/actions.cpp @@ -217,6 +217,9 @@ ActionDelayRender::ActionDelayRender(ZVision *engine, int32 slotkey, const Commo ResultAction(engine, slotkey) { _framesToDelay = 0; sscanf(line.c_str(), "%u", &_framesToDelay); + // Limit to 10 frames maximum. This fixes the script bug in ZGI scene px10 + // (outside Frobozz Electric building), where this is set to 100 (bug #6791). + _framesToDelay = MIN(_framesToDelay, 10); } bool ActionDelayRender::execute() { -- cgit v1.2.3 From 84d2414a7dceca9d5140936667aae05fbbfdcf99 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Thu, 2 Oct 2014 18:22:41 +0200 Subject: SCI: Avoid resetting already unused channels --- engines/sci/sound/music.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index 7a6eaf62b4..5a37357045 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -1063,7 +1063,7 @@ void SciMusic::remapChannels() { // And finally, stop any empty channels for (int i = _driverFirstChannel; i <= _driverLastChannel; ++i) { - if (!_channelMap[i]._song) + if (!_channelMap[i]._song && currentMap[i]._song) resetDeviceChannel(i); } -- cgit v1.2.3 From f1e34f11d742ef32ed48926092d93f3448732f2e Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Thu, 2 Oct 2014 18:23:00 +0200 Subject: SCI: Initialize voice counts in SCI1+ --- engines/sci/sound/midiparser_sci.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'engines') diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index c0b4f3122e..7ee9cc9d28 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -360,6 +360,13 @@ void MidiParser_SCI::sendInitCommands() { sendToDriver(0xB0 | i, 0x4B, voiceCount); } } + } else { + for (int i = 0; i < _track->channelCount; ++i) { + byte voiceCount = _track->channels[i].poly; + byte num = _track->channels[i].number; + // TODO: Should we skip the control channel? + sendToDriver(0xB0 | num, 0x4B, voiceCount); + } } } -- cgit v1.2.3 From 26d55b09a8b198b0a9b9349d684eec6376d98c8c Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Thu, 2 Oct 2014 18:24:14 +0200 Subject: SCI: Match SSCI channel reset order It may or may not matter for a driver's voice mapping. --- engines/sci/sound/music.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index 5a37357045..05605c0c45 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -1062,7 +1062,7 @@ void SciMusic::remapChannels() { } // And finally, stop any empty channels - for (int i = _driverFirstChannel; i <= _driverLastChannel; ++i) { + for (int i = _driverLastChannel; i >= _driverFirstChannel; --i) { if (!_channelMap[i]._song && currentMap[i]._song) resetDeviceChannel(i); } -- cgit v1.2.3 From 58ef44eb8d9d3eb78eb013441a8d6d12940ee5e3 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Tue, 7 Oct 2014 19:48:18 +0200 Subject: SCI: Register and save playBed option to PlaySound The playBed option is not handled yet, only stored. This increases the savegame format version. --- engines/sci/console.cpp | 8 +++++--- engines/sci/engine/kernel_tables.h | 4 ---- engines/sci/engine/savegame.cpp | 6 +++++- engines/sci/engine/savegame.h | 3 ++- engines/sci/sound/music.cpp | 2 ++ engines/sci/sound/music.h | 1 + engines/sci/sound/soundcmd.cpp | 16 +++++++++++----- engines/sci/sound/soundcmd.h | 2 +- 8 files changed, 27 insertions(+), 15 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index e233c4cba4..a3abf606d0 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -2172,6 +2172,7 @@ bool Console::cmdStartSound(int argc, const char **argv) { return true; } + // TODO: Maybe also add a playBed option. g_sci->_soundCmd->startNewSound(number); return cmdExit(0, 0); } @@ -2198,9 +2199,10 @@ bool Console::cmdToggleSound(int argc, const char **argv) { Common::String newState = argv[2]; newState.toLowercase(); - if (newState == "play") - g_sci->_soundCmd->processPlaySound(id); - else if (newState == "stop") + if (newState == "play") { + // Maybe also have a 'playbed' option. (Second argument to processPlaySound.) + g_sci->_soundCmd->processPlaySound(id, false); + } else if (newState == "stop") g_sci->_soundCmd->processStopSound(id, false); else debugPrintf("New state can either be 'play' or 'stop'"); diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h index 0c2fd4e3ea..2cbd79366d 100644 --- a/engines/sci/engine/kernel_tables.h +++ b/engines/sci/engine/kernel_tables.h @@ -105,10 +105,6 @@ static const SciKernelMapSubEntry kDoSound_subops[] = { { SIG_SOUNDSCI1EARLY, 5, MAP_CALL(DoSoundInit), NULL, NULL }, { SIG_SOUNDSCI1EARLY, 6, MAP_CALL(DoSoundDispose), NULL, NULL }, { SIG_SOUNDSCI1EARLY, 7, MAP_CALL(DoSoundPlay), "oi", NULL }, - // ^^ TODO: In SCI1-SCI1.1 DoSound (play) is called by 2 methods of the Sound object: play and - // playBed. The methods are the same, apart from the second integer parameter: it's 0 in - // play and 1 in playBed, to distinguish the caller. It's passed on, we should find out what - // it actually does internally { SIG_SOUNDSCI1EARLY, 8, MAP_CALL(DoSoundStop), NULL, NULL }, { SIG_SOUNDSCI1EARLY, 9, MAP_CALL(DoSoundPause), "[o0]i", NULL }, { SIG_SOUNDSCI1EARLY, 10, MAP_CALL(DoSoundFade), "oiiii", kDoSoundFade_workarounds }, diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 0b55425406..692fa77a80 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -617,6 +617,10 @@ void MusicEntry::saveLoadWithSerializer(Common::Serializer &s) { s.syncAsSint32LE(fadeTicker); s.syncAsSint32LE(fadeTickerStep); s.syncAsByte(status); + if (s.getVersion() >= 32) + s.syncAsByte(playBed); + else if (s.isLoading()) + playBed = false; // pMidiParser and pStreamAud will be initialized when the // sound list is reconstructed in gamestate_restore() @@ -650,7 +654,7 @@ void SoundCommandParser::reconstructPlayList() { if (_soundVersion >= SCI_VERSION_1_EARLY) writeSelectorValue(_segMan, (*i)->soundObj, SELECTOR(vol), (*i)->volume); - processPlaySound((*i)->soundObj); + processPlaySound((*i)->soundObj, (*i)->playBed); } } } diff --git a/engines/sci/engine/savegame.h b/engines/sci/engine/savegame.h index 8f2835654b..be6d05cdc5 100644 --- a/engines/sci/engine/savegame.h +++ b/engines/sci/engine/savegame.h @@ -37,6 +37,7 @@ struct EngineState; * * Version - new/changed feature * ============================= + * 32 - new playBed flag in MusicEntry * 31 - priority for sound effects/music is now a signed int16, instead of a byte * 30 - synonyms * 29 - system strings @@ -56,7 +57,7 @@ struct EngineState; */ enum { - CURRENT_SAVEGAME_VERSION = 31, + CURRENT_SAVEGAME_VERSION = 32, MINIMUM_SAVEGAME_VERSION = 14 }; diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index 05605c0c45..4606d66ace 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -334,6 +334,7 @@ void SciMusic::soundInitSnd(MusicEntry *pSnd) { pSnd->pLoopStream = 0; pSnd->soundType = Audio::Mixer::kSFXSoundType; pSnd->hCurrentAud = Audio::SoundHandle(); + pSnd->playBed = false; } else { // play MIDI track Common::StackLock lock(_mutex); @@ -380,6 +381,7 @@ void SciMusic::soundInitSnd(MusicEntry *pSnd) { int16 prevHold = pSnd->hold; pSnd->loop = 0; pSnd->hold = -1; + pSnd->playBed = false; pSnd->pMidiParser->loadMusic(track, pSnd, channelFilterMask, _soundVersion); pSnd->reverb = pSnd->pMidiParser->getSongReverb(); diff --git a/engines/sci/sound/music.h b/engines/sci/sound/music.h index 4e44074630..0fbd5a0c0e 100644 --- a/engines/sci/sound/music.h +++ b/engines/sci/sound/music.h @@ -85,6 +85,7 @@ public: int16 volume; int16 hold; int8 reverb; + bool playBed; int16 pauseCounter; uint sampleLoopCounter; diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp index 73e0a23a6a..47ab9bdc71 100644 --- a/engines/sci/sound/soundcmd.cpp +++ b/engines/sci/sound/soundcmd.cpp @@ -142,11 +142,14 @@ void SoundCommandParser::processInitSound(reg_t obj) { reg_t SoundCommandParser::kDoSoundPlay(int argc, reg_t *argv, reg_t acc) { debugC(kDebugLevelSound, "kDoSound(play): %04x:%04x", PRINT_REG(argv[0])); - processPlaySound(argv[0]); + bool playBed = false; + if (argc >= 2 && !argv[1].isNull()) + playBed = true; + processPlaySound(argv[0], playBed); return acc; } -void SoundCommandParser::processPlaySound(reg_t obj) { +void SoundCommandParser::processPlaySound(reg_t obj, bool playBed) { MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { warning("kDoSound(play): Slot not found (%04x:%04x), initializing it manually", PRINT_REG(obj)); @@ -185,11 +188,12 @@ void SoundCommandParser::processPlaySound(reg_t obj) { // Reset hold when starting a new song. kDoSoundSetHold is always called after // kDoSoundPlay to set it properly, if needed. Fixes bug #3413589. musicSlot->hold = -1; + musicSlot->playBed = playBed; if (_soundVersion >= SCI_VERSION_1_EARLY) musicSlot->volume = readSelectorValue(_segMan, obj, SELECTOR(vol)); - debugC(kDebugLevelSound, "kDoSound(play): %04x:%04x number %d, loop %d, prio %d, vol %d", PRINT_REG(obj), - resourceId, musicSlot->loop, musicSlot->priority, musicSlot->volume); + debugC(kDebugLevelSound, "kDoSound(play): %04x:%04x number %d, loop %d, prio %d, vol %d, bed %d", PRINT_REG(obj), + resourceId, musicSlot->loop, musicSlot->priority, musicSlot->volume, playBed ? 1 : 0); _music->soundPlay(musicSlot); @@ -777,6 +781,8 @@ void SoundCommandParser::stopAllSounds() { } void SoundCommandParser::startNewSound(int number) { + // NB: This is only used by the debugging console. + Common::StackLock lock(_music->_mutex); // Overwrite the first sound in the playlist @@ -785,7 +791,7 @@ void SoundCommandParser::startNewSound(int number) { processDisposeSound(soundObj); writeSelectorValue(_segMan, soundObj, SELECTOR(number), number); processInitSound(soundObj); - processPlaySound(soundObj); + processPlaySound(soundObj, false); } void SoundCommandParser::setMasterVolume(int vol) { diff --git a/engines/sci/sound/soundcmd.h b/engines/sci/sound/soundcmd.h index 4effda68e4..5bb7cf2cb1 100644 --- a/engines/sci/sound/soundcmd.h +++ b/engines/sci/sound/soundcmd.h @@ -63,7 +63,7 @@ public: void printPlayList(Console *con); void printSongInfo(reg_t obj, Console *con); - void processPlaySound(reg_t obj); + void processPlaySound(reg_t obj, bool playBed); void processStopSound(reg_t obj, bool sampleFinishedPlaying); void initSoundResource(MusicEntry *newSound); -- cgit v1.2.3 From 52adf5135b7b075c1cfc63ce8094538edf279039 Mon Sep 17 00:00:00 2001 From: RichieSams Date: Sat, 14 Feb 2015 12:06:14 -0600 Subject: ZVISION: Check for point and style changes when early breaking from a font change --- engines/zvision/text/truetype_font.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/zvision/text/truetype_font.cpp b/engines/zvision/text/truetype_font.cpp index 8e402efc08..7ad8d6db61 100644 --- a/engines/zvision/text/truetype_font.cpp +++ b/engines/zvision/text/truetype_font.cpp @@ -65,14 +65,14 @@ StyledTTFont::~StyledTTFont() { } bool StyledTTFont::loadFont(const Common::String &fontName, int32 point, uint style) { - _style = style; - // Don't re-load the font if we've already loaded it // We have to check for empty so we can default to Arial - if (!fontName.empty() && _fontName.equalsIgnoreCase(fontName)) { + if (!fontName.empty() && _fontName.equalsIgnoreCase(fontName) && _lineHeight == point && _style == style) { return true; } + _style = style; + Common::String newFontName; Common::String freeFontName; Common::String liberationFontName; -- cgit v1.2.3 From 1aa9181466d1916824abb7301ea3e67781d08183 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 14 Feb 2015 15:34:11 -0500 Subject: MADS: Cleanup and bugfixes for panning transition support methods --- engines/mads/palette.cpp | 22 +++++++++++++------- engines/mads/palette.h | 11 ++++------ engines/mads/screen.cpp | 53 ++++++++++++++++++++++++++++++++++-------------- engines/mads/screen.h | 4 ++-- 4 files changed, 59 insertions(+), 31 deletions(-) (limited to 'engines') diff --git a/engines/mads/palette.cpp b/engines/mads/palette.cpp index b41eaedfcc..b5ea136abd 100644 --- a/engines/mads/palette.cpp +++ b/engines/mads/palette.cpp @@ -428,6 +428,14 @@ void Fader::grabPalette(byte *colors, uint start, uint num) { g_system->getPaletteManager()->grabPalette(colors, start, num); } +void Fader::getFullPalette(byte palette[PALETTE_SIZE]) { + grabPalette(&palette[0], 0, PALETTE_COUNT); +} + +void Fader::setFullPalette(byte palette[PALETTE_SIZE]) { + setPalette(&palette[0], 0, PALETTE_COUNT); +} + void Fader::fadeOut(byte palette[PALETTE_SIZE], byte *paletteMap, int baseColor, int numColors, int baseGrey, int numGreys, int tickDelay, int steps) { @@ -886,25 +894,25 @@ void Palette::refreshSceneColors() { } int Palette::closestColor(const byte *matchColor, const byte *refPalette, - int listWrap, int count) { + int paletteInc, int count) { int bestColor = 0; int bestDistance = 0x7fff; for (int idx = 0; idx < count; ++idx) { - // Figure out hash for color + // Figure out figure for 'distance' between two colors int distance = 0; - for (int rgbIdx = 0; rgbIdx < 3; ++rgbIdx, ++refPalette) { - byte diff = *refPalette - matchColor[rgbIdx]; - distance += (int)diff * (int)diff; + for (int rgbIdx = 0; rgbIdx < RGB_SIZE; ++rgbIdx) { + int diff = refPalette[rgbIdx] - matchColor[rgbIdx]; + distance += diff * diff; } // If the given color is a closer match to our color, store the index - if (distance < bestDistance) { + if (distance <= bestDistance) { bestDistance = distance; bestColor = idx; } - refPalette += listWrap - 3; + refPalette += paletteInc; } return bestColor; diff --git a/engines/mads/palette.h b/engines/mads/palette.h index 1c387b4368..5d3bc3a82e 100644 --- a/engines/mads/palette.h +++ b/engines/mads/palette.h @@ -36,6 +36,7 @@ class MADSEngine; #define PALETTE_RESERVED_HIGH_COUNT 10 #define PALETTE_COUNT 256 +#define RGB_SIZE 3 #define PALETTE_SIZE (256 * 3) /** @@ -212,16 +213,12 @@ public: /** * Gets the entire palette at once */ - void getFullPalette(byte palette[PALETTE_SIZE]) { - grabPalette(&palette[0], 0, PALETTE_COUNT); - } + void getFullPalette(byte palette[PALETTE_SIZE]); /** * Sets the entire palette at once */ - void setFullPalette(byte palette[PALETTE_SIZE]) { - setPalette(&palette[0], 0, PALETTE_COUNT); - } + void setFullPalette(byte palette[PALETTE_SIZE]); /** * Calculates a merge/hash for a given palette entry @@ -320,7 +317,7 @@ public: void refreshSceneColors(); static int closestColor(const byte *matchColor, const byte *refPalette, - int listWrap, int count); + int paletteInc, int count); }; } // End of namespace MADS diff --git a/engines/mads/screen.cpp b/engines/mads/screen.cpp index f7179877d5..60f3d8aeaf 100644 --- a/engines/mads/screen.cpp +++ b/engines/mads/screen.cpp @@ -610,7 +610,7 @@ void ScreenSurface::transition(ScreenTransition transitionType, bool surfaceFlag Scene &scene = _vm->_game->_scene; byte palData[PALETTE_SIZE]; - switch (transitionType) { + switch (transitionType) { case kTransitionFadeIn: case kTransitionFadeOutIn: Common::fill(&pal._colorValues[0], &pal._colorValues[3], 0); @@ -738,7 +738,8 @@ void ScreenSurface::panTransition(MSurface &newScreen, byte *palData, int entryS copyRectToScreen(Common::Rect(xAt, destPos.y, xAt + 1, destPos.y + size.y)); // Slight delay - events.delay(1); + events.pollEvents(); + g_system->delayMillis(1); } if ((setPalette && !loop) || throughBlack == THROUGH_BLACK2) @@ -752,28 +753,49 @@ void ScreenSurface::panTransition(MSurface &newScreen, byte *palData, int entryS } } -void ScreenSurface::swapForeground(byte palData[PALETTE_SIZE], byte *paletteMap) { +/** + * Translates the current screen from the old palette to the new palette + */ +void ScreenSurface::swapForeground(byte newPalette[PALETTE_SIZE], byte *paletteMap) { Palette &palette = *_vm->_palette; byte oldPalette[PALETTE_SIZE]; - byte oldMap[256]; - byte newMap[256]; + byte oldMap[PALETTE_COUNT]; palette.getFullPalette(oldPalette); swapPalette(oldPalette, oldMap, true); - swapPalette(palData, newMap, false); - - Common::copy(&palData[3], &palData[PALETTE_SIZE], &oldPalette[3]); + swapPalette(newPalette, paletteMap, false); + + // Transfer translated foreground colors. Since foregrounds are interleaved + // with background, we only copy over each alternate RGB tuplet + const byte *srcP = &newPalette[RGB_SIZE]; + byte *destP = &oldPalette[RGB_SIZE]; + while (destP < &oldPalette[PALETTE_SIZE]) { + Common::copy(srcP, srcP + RGB_SIZE, destP); + srcP += 2 * RGB_SIZE; + destP += 2 * RGB_SIZE; + } + Common::Rect oldClip = _clipBounds; + resetClipBounds(); + copyRectTranslate(*this, oldMap, Common::Point(0, 0), Common::Rect(0, 0, MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT)); palette.setFullPalette(oldPalette); + + setClipBounds(oldClip); } -void ScreenSurface::swapPalette(byte *palData, byte swapTable[PALETTE_COUNT], - int start) { - byte *dynamicList = &palData[start * 3]; +/** + * Translates a given palette into a mapping table. + * Palettes consist of 128 RGB entries for the foreground and background + * respectively, with the two interleaved together. So the start + */ +void ScreenSurface::swapPalette(const byte *palData, byte swapTable[PALETTE_COUNT], + bool foreground) { + int start = foreground ? 1 : 0; + const byte *dynamicList = &palData[start * RGB_SIZE]; int staticStart = 1 - start; - byte *staticList = &palData[staticStart * 3]; + const byte *staticList = &palData[staticStart * RGB_SIZE]; const int PALETTE_START = 1; const int PALETTE_END = 252; @@ -781,13 +803,14 @@ void ScreenSurface::swapPalette(byte *palData, byte swapTable[PALETTE_COUNT], for (int idx = 0; idx < PALETTE_COUNT; ++idx) swapTable[idx] = idx; - for (int idx = 0; idx < 128; ++idx) { + // Handle the 128 palette entries for the foreground or background + for (int idx = 0; idx < (PALETTE_COUNT / 2); ++idx) { if (start >= PALETTE_START && start <= PALETTE_END) { swapTable[start] = Palette::closestColor(dynamicList, staticList, - 6, 128) * 2 + staticStart; + 2 * RGB_SIZE, PALETTE_COUNT / 2) * 2 + staticStart; } - dynamicList += 6; + dynamicList += 2 * RGB_SIZE; start += 2; } } diff --git a/engines/mads/screen.h b/engines/mads/screen.h index 35042e88d2..e2462aff18 100644 --- a/engines/mads/screen.h +++ b/engines/mads/screen.h @@ -217,9 +217,9 @@ private: const Common::Point &srcPos, const Common::Point &destPos, ThroughBlack throughBlack, bool setPalette, int numTicks); - void swapForeground(byte *palData, byte *paletteMap); + void swapForeground(byte newPalette[PALETTE_SIZE], byte *paletteMap); - void swapPalette(byte palData[PALETTE_SIZE], byte swapTable[PALETTE_COUNT], int start); + void swapPalette(const byte palData[PALETTE_SIZE], byte swapTable[PALETTE_COUNT], bool foreground); public: int _shakeCountdown; public: -- cgit v1.2.3 From d31e602add7e5466754d4b651ce7f947f6effdda Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 14 Feb 2015 16:54:47 -0500 Subject: MADS: Allow Escape key to close game options dialog --- engines/mads/events.cpp | 2 +- engines/mads/events.h | 4 +++- engines/mads/game.cpp | 8 ++++---- engines/mads/game.h | 2 +- engines/mads/nebular/dialogs_nebular.cpp | 21 ++++++++++++++++----- engines/mads/scene.cpp | 8 +++++--- 6 files changed, 30 insertions(+), 15 deletions(-) (limited to 'engines') diff --git a/engines/mads/events.cpp b/engines/mads/events.cpp index e7ec8b0821..586ef7cbf3 100644 --- a/engines/mads/events.cpp +++ b/engines/mads/events.cpp @@ -157,7 +157,7 @@ void EventsManager::pollEvents() { _vm->_debugger->attach(); _vm->_debugger->onFrame(); } else { - _pendingKeys.push(event); + _pendingKeys.push(event.kbd); } return; case Common::EVENT_KEYUP: diff --git a/engines/mads/events.h b/engines/mads/events.h index 870d6e03b8..21ef37407b 100644 --- a/engines/mads/events.h +++ b/engines/mads/events.h @@ -70,7 +70,7 @@ public: int _vD2; int _mouseStatusCopy; bool _mouseMoved; - Common::Stack _pendingKeys; + Common::Stack _pendingKeys; public: /** * Constructor @@ -168,6 +168,8 @@ public: * Returns true if there's any pending keys to be processed */ bool isKeyPressed() const { return !_pendingKeys.empty(); } + + Common::KeyState getKey() { return _pendingKeys.pop(); } }; } // End of namespace MADS diff --git a/engines/mads/game.cpp b/engines/mads/game.cpp index 0ce24daf7a..27691d3380 100644 --- a/engines/mads/game.cpp +++ b/engines/mads/game.cpp @@ -403,12 +403,12 @@ Common::StringArray Game::getMessage(uint32 id) { static const char *const DEBUG_STRING = "WIDEPIPE"; -void Game::handleKeypress(const Common::Event &event) { - if (event.kbd.flags & Common::KBD_CTRL) { +void Game::handleKeypress(const Common::KeyState &kbd) { + if (kbd.flags & Common::KBD_CTRL) { if (_widepipeCtr == 8) { // Implement original game cheating keys here someday } else { - if (event.kbd.keycode == (Common::KEYCODE_a + + if (kbd.keycode == (Common::KEYCODE_a + (DEBUG_STRING[_widepipeCtr] - 'a'))) { if (++_widepipeCtr == 8) { MessageDialog *dlg = new MessageDialog(_vm, 2, @@ -420,7 +420,7 @@ void Game::handleKeypress(const Common::Event &event) { } } - switch (event.kbd.keycode) { + switch (kbd.keycode) { case Common::KEYCODE_F1: _vm->_dialogs->_pendingDialog = DIALOG_GAME_MENU; break; diff --git a/engines/mads/game.h b/engines/mads/game.h index 1a61fc8ac8..66f2580249 100644 --- a/engines/mads/game.h +++ b/engines/mads/game.h @@ -204,7 +204,7 @@ public: /** * Handle a keyboard event */ - void handleKeypress(const Common::Event &event); + void handleKeypress(const Common::KeyState &kbd); /** * Starts a savegame loading. diff --git a/engines/mads/nebular/dialogs_nebular.cpp b/engines/mads/nebular/dialogs_nebular.cpp index 05c2e4ba96..be683d0b51 100644 --- a/engines/mads/nebular/dialogs_nebular.cpp +++ b/engines/mads/nebular/dialogs_nebular.cpp @@ -804,7 +804,7 @@ void GameDialog::show() { Scene &scene = _vm->_game->_scene; - while (_selectedLine < 1 && !_vm->shouldQuit()) { + while (_selectedLine == -1 && !_vm->shouldQuit()) { handleEvents(); if (_redrawFlag) { if (!_tempLine) @@ -831,7 +831,17 @@ void GameDialog::handleEvents() { _lines[i]._state = DLGSTATE_UNSELECTED; // Process pending events - _vm->_events->pollEvents(); + events.pollEvents(); + + if (events.isKeyPressed()) { + switch (events.getKey().keycode) { + case Common::KEYCODE_ESCAPE: + _selectedLine = 0; + break; + default: + break; + } + } // Scan for objects in the dialog Common::Point mousePos = events.currentPos() - Common::Point(0, DIALOG_TOP); @@ -1010,12 +1020,13 @@ void GameMenuDialog::show() { _vm->_dialogs->_pendingDialog = DIALOG_OPTIONS; _vm->_dialogs->showDialog(); break; + case 5: + _vm->quitGame(); + break; case 4: + default: // Resume game break; - case 5: - default: - _vm->quitGame(); } } diff --git a/engines/mads/scene.cpp b/engines/mads/scene.cpp index ea3fe2c148..61db1a6a32 100644 --- a/engines/mads/scene.cpp +++ b/engines/mads/scene.cpp @@ -592,12 +592,14 @@ void Scene::doSceneStep() { } void Scene::checkKeyboard() { - if (_vm->_events->isKeyPressed()) { - Common::Event evt = _vm->_events->_pendingKeys.pop(); + EventsManager &events = *_vm->_events; + + if (events.isKeyPressed()) { + Common::KeyState evt = events.getKey(); _vm->_game->handleKeypress(evt); } - if ((_vm->_events->_mouseStatus & 3) == 3 && _vm->_game->_player._stepEnabled) { + if ((events._mouseStatus & 3) == 3 && _vm->_game->_player._stepEnabled) { _reloadSceneFlag = true; _vm->_dialogs->_pendingDialog = DIALOG_GAME_MENU; _action.clear(); -- cgit v1.2.3 From be489d88e6f4e17e4c1873f97831237091c899c4 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 14 Feb 2015 18:03:45 -0500 Subject: MADS: Fix palette loading for in-game dialogs --- engines/mads/nebular/dialogs_nebular.cpp | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) (limited to 'engines') diff --git a/engines/mads/nebular/dialogs_nebular.cpp b/engines/mads/nebular/dialogs_nebular.cpp index be683d0b51..6985455d2a 100644 --- a/engines/mads/nebular/dialogs_nebular.cpp +++ b/engines/mads/nebular/dialogs_nebular.cpp @@ -612,9 +612,12 @@ GameDialog::GameDialog(MADSEngine *vm) : FullScreenDialog(vm) { } void GameDialog::display() { + Palette &palette = *_vm->_palette; + palette.initPalette(); + palette.resetGamePalette(18, 10); + FullScreenDialog::display(); - Palette &palette = *_vm->_palette; palette.setEntry(10, 0, 63, 0); palette.setEntry(11, 0, 45, 0); palette.setEntry(12, 63, 63, 0); @@ -1094,7 +1097,7 @@ void OptionsDialog::show() { StoryMode prevStoryMode = game._storyMode; do { - _selectedLine = 0; + _selectedLine = -1; GameDialog::show(); switch (_selectedLine) { @@ -1133,22 +1136,16 @@ void OptionsDialog::show() { clearLines(); setLines(); setClickableLines(); - } while (_selectedLine <= 7); + } while (!_vm->shouldQuit() && _selectedLine != 0 && _selectedLine <= 7); - switch (_selectedLine) { - case 8: // Done - // New options will be applied - break; - case 9: // Cancel + // If Done button not pressed, reset settings + if (_selectedLine != 8) { // Revert all options from the saved ones _vm->_easyMouse = prevEasyMouse; _vm->_invObjectsAnimated = prevInvObjectsAnimated; _vm->_textWindowStill = prevTextWindowStill; _vm->_screenFade = prevScreenFade; game._storyMode = prevStoryMode; - break; - default: - break; } } -- cgit v1.2.3 From a505ae941c22149c9892470f6b11087f8ececb91 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 14 Feb 2015 20:44:59 -0500 Subject: MADS: Fix picture when picking up timer module --- engines/mads/nebular/nebular_scenes1.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes1.cpp b/engines/mads/nebular/nebular_scenes1.cpp index ab072c1d3c..7c85fd44db 100644 --- a/engines/mads/nebular/nebular_scenes1.cpp +++ b/engines/mads/nebular/nebular_scenes1.cpp @@ -1453,7 +1453,7 @@ void Scene103::actions() { _scene->_hotspots.activate(371, false); _vm->_game->_player._visible = true; _vm->_game->_player._stepEnabled = true; - _vm->_dialogs->showItem(OBJ_REBREATHER, 805); + _vm->_dialogs->showItem(OBJ_TIMER_MODULE, 805); break; default: -- cgit v1.2.3 From 2c9ad1ee9b439998b2dac178d295ce3f328b41ae Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 14 Feb 2015 21:34:09 -0500 Subject: MADS: Fix death animations for seaweed and underwater mine --- engines/mads/scene.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mads/scene.cpp b/engines/mads/scene.cpp index 61db1a6a32..a72648f0c9 100644 --- a/engines/mads/scene.cpp +++ b/engines/mads/scene.cpp @@ -675,7 +675,7 @@ void Scene::freeCurrentScene() { } void Scene::removeSprites() { - for (int idx = _sprites.size() - 1; idx >= _spritesCount; --idx) + for (int idx = _sprites._assetCount - 1; idx >= _spritesCount; --idx) _sprites.remove(idx); } -- cgit v1.2.3 From 51561c80c0002ea3f59bc513592f04c656d32a65 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 15 Feb 2015 07:19:42 -0500 Subject: MADS: Fix left edge screen clipping for non-scaled flipped sprites --- engines/mads/msurface.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'engines') diff --git a/engines/mads/msurface.cpp b/engines/mads/msurface.cpp index d8d01f307c..cc12442db1 100644 --- a/engines/mads/msurface.cpp +++ b/engines/mads/msurface.cpp @@ -308,6 +308,9 @@ void MSurface::copyFrom(MSurface *src, const Common::Point &destPos, int depth, if (!copyRect.isValidRect()) return; + if (flipped) + copyRect.moveTo(0, copyRect.top); + byte *data = src->getData(); byte *srcPtr = data + (src->getWidth() * copyRect.top + copyRect.left); byte *destPtr = (byte *)pixels + (destY * pitch) + destX; -- cgit v1.2.3 From 5964cc239b920a4a5d3b8475cb6c0b111e968e03 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Tue, 7 Oct 2014 21:24:49 +0200 Subject: SCI: Always re-sort playlist in soundPlay Previously, it would only sort if a song wasn't already in the playlist. Since initSound already adds it, this effectively prevented the list from being sorted. --- engines/sci/engine/savegame.cpp | 8 ++++++-- engines/sci/sound/music.cpp | 3 ++- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 692fa77a80..eee4c49729 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -639,8 +639,12 @@ void SoundCommandParser::syncPlayList(Common::Serializer &s) { void SoundCommandParser::reconstructPlayList() { Common::StackLock lock(_music->_mutex); - const MusicList::iterator end = _music->getPlayListEnd(); - for (MusicList::iterator i = _music->getPlayListStart(); i != end; ++i) { + // We store all songs here because starting songs may re-shuffle their order + MusicList songs; + for (MusicList::iterator i = _music->getPlayListStart(); i != _music->getPlayListEnd(); ++i) + songs.push_back(*i); + + for (MusicList::iterator i = songs.begin(); i != songs.end(); ++i) { initSoundResource(*i); if ((*i)->status == kSoundPlaying) { diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index 4606d66ace..5b205c82d7 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -410,9 +410,10 @@ void SciMusic::soundPlay(MusicEntry *pSnd) { } if (playListNo == playListCount) { // not found _playList.push_back(pSnd); - sortPlayList(); } + sortPlayList(); + _mutex.unlock(); // unlock to perform mixer-related calls if (pSnd->pMidiParser) { -- cgit v1.2.3 From e42a5123572cabf435a90eee2f9c01ababbe8528 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Tue, 7 Oct 2014 21:30:45 +0200 Subject: SCI: Don't remap channels from playBed songs --- engines/sci/sound/music.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index 5b205c82d7..d58479f18e 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -397,6 +397,9 @@ void SciMusic::soundInitSnd(MusicEntry *pSnd) { void SciMusic::soundPlay(MusicEntry *pSnd) { _mutex.lock(); + // TODO: if pSnd->playBed, and version <= SCI1_EARLY, then kill + // existing sounds with playBed enabled. + uint playListCount = _playList.size(); uint playListNo = playListCount; MusicEntry *alreadyPlaying = NULL; @@ -1126,8 +1129,10 @@ ChannelRemapping *SciMusic::determineChannelMap() { if (channel._mute) continue; + bool dontRemap = channel._dontRemap || song->playBed; + #ifdef DEBUG_REMAP - debug(" Channel %d: prio %d, %d voice%s%s", c, channel._prio, channel._voices, channel._voices == 1 ? "" : "s", channel._dontRemap ? ", dontRemap" : "" ); + debug(" Channel %d: prio %d, %d voice%s%s", c, channel._prio, channel._voices, channel._voices == 1 ? "" : "s", dontRemap ? ", dontRemap" : "" ); #endif DeviceChannelUsage dc = { song, c }; @@ -1135,7 +1140,7 @@ ChannelRemapping *SciMusic::determineChannelMap() { // our target int devChannel = -1; - if (channel._dontRemap && map->_map[c]._song == 0) { + if (dontRemap && map->_map[c]._song == 0) { // unremappable channel, with channel still free devChannel = c; } @@ -1232,10 +1237,10 @@ ChannelRemapping *SciMusic::determineChannelMap() { map->_map[devChannel] = dc; map->_voices[devChannel] = neededVoices; map->_prio[devChannel] = prio; - map->_dontRemap[devChannel] = channel._dontRemap; + map->_dontRemap[devChannel] = dontRemap; map->_freeVoices -= neededVoices; - if (!channel._dontRemap || devChannel == c) { + if (!dontRemap || devChannel == c) { // If this channel fits here, we're done. #ifdef DEBUG_REMAP debug(" OK"); -- cgit v1.2.3 From b80e74af5dec7675a2bf4a3f51da8501518c2be2 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Sat, 11 Oct 2014 17:31:12 +0200 Subject: SCI: Handle voice limits differently For playBed songs, SCI1early remappers didn't unmap the entire song when there weren't enough voices for a channel. Thanks waltervn. --- engines/sci/sound/music.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index d58479f18e..f69f40eeca 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -1200,8 +1200,12 @@ ChannelRemapping *SciMusic::determineChannelMap() { int neededVoices = channel._voices; // do we have enough free voices? if (map->_freeVoices < neededVoices) { - // We only care for essential channels - if (prio > 0) { + // We only care for essential channels. + // Note: In early SCI1 interpreters, a song started by 'playBed' + // would not be skipped even if some channels couldn't be + // mapped due to voice limits. So, we treat all channels as + // non-essential here for playBed songs. + if (prio > 0 || (song->playBed && _soundVersion <= SCI_VERSION_1_EARLY)) { #ifdef DEBUG_REMAP debug(" not enough voices; need %d, have %d. Skipping this channel.", neededVoices, map->_freeVoices); #endif -- cgit v1.2.3 From 0aadd20aeaac1d241087e913a2bf8171bb0def68 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Sun, 19 Oct 2014 11:34:14 +0200 Subject: SCI: Add debugging output --- engines/sci/sound/midiparser_sci.cpp | 2 ++ engines/sci/sound/music.cpp | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index 7ee9cc9d28..7ebe47633a 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -487,6 +487,8 @@ void MidiParser_SCI::trackState(uint32 b) { s._sustain = (op2 != 0); break; case 0x4B: // voices + if (s._voices != op2) + warning("Voice change (%d to %d) without remapping", s._voices, op2); s._voices = op2; _pSnd->_chan[channel]._voices = op2; // Also sync our MusicEntry break; diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index f69f40eeca..62b17b2064 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -1111,7 +1111,8 @@ ChannelRemapping *SciMusic::determineChannelMap() { #ifdef DEBUG_REMAP - debug(" Song %d (%p), prio %d", songIndex, (void*)song, song->priority); + const char* name = g_sci->getEngineState()->_segMan->getObjectName(song->soundObj); + debug(" Song %d (%p) [%s], prio %d%s", songIndex, (void*)song, name, song->priority, song->playBed ? ", bed" : ""); #endif // Store backup. If we fail to map this song, we will revert to this. -- cgit v1.2.3 From 0018bb0f6f36fd1798ec92d2e7e6654e026fe19b Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Sun, 19 Oct 2014 13:01:56 +0200 Subject: SCI: Give songs that start playing later higher priority --- engines/sci/sound/music.cpp | 9 ++++++++- engines/sci/sound/music.h | 5 +++++ 2 files changed, 13 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index 62b17b2064..2b73bcf8b3 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -144,6 +144,7 @@ void SciMusic::init() { _globalReverb = _pMidiDrv->getReverb(); // Init global reverb for SCI0 _currentlyPlayingSample = NULL; + _timeCounter = 0; } void SciMusic::miditimerCallback(void *p) { @@ -285,8 +286,10 @@ byte SciMusic::getCurrentReverb() { return _pMidiDrv->getReverb(); } +// A larger priority value has higher priority. For equal priority values, +// songs that have been added later have higher priority. static bool musicEntryCompare(const MusicEntry *l, const MusicEntry *r) { - return (l->priority > r->priority); + return (l->priority > r->priority) || (l->priority == r->priority && l->time > r->time); } void SciMusic::sortPlayList() { @@ -317,6 +320,8 @@ void SciMusic::soundInitSnd(MusicEntry *pSnd) { track = digital; } + pSnd->time = ++_timeCounter; + if (track) { // Play digital sample if (track->digitalChannelNr != -1) { @@ -415,6 +420,7 @@ void SciMusic::soundPlay(MusicEntry *pSnd) { _playList.push_back(pSnd); } + pSnd->time = ++_timeCounter; sortPlayList(); _mutex.unlock(); // unlock to perform mixer-related calls @@ -560,6 +566,7 @@ void SciMusic::soundSetPriority(MusicEntry *pSnd, byte prio) { Common::StackLock lock(_mutex); pSnd->priority = prio; + pSnd->time = ++_timeCounter; sortPlayList(); } diff --git a/engines/sci/sound/music.h b/engines/sci/sound/music.h index 0fbd5a0c0e..1347177054 100644 --- a/engines/sci/sound/music.h +++ b/engines/sci/sound/music.h @@ -75,6 +75,8 @@ public: SoundResource *soundRes; uint16 resourceId; + int time; // "tim"estamp to indicate in which order songs have been added + bool isQueued; // for SCI0 only! uint16 dataInc; @@ -267,6 +269,9 @@ private: int _driverLastChannel; MusicEntry *_currentlyPlayingSample; + + int _timeCounter; // Used to keep track of the order in which MusicEntries + // are added, for priority purposes. }; } // End of namespace Sci -- cgit v1.2.3 From 5028487038fd3572d68af3cd253fc28917245e63 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Sat, 14 Feb 2015 15:20:23 +0100 Subject: SCI: Use sound resource priority by default for songs SCI1 sound resources can have an embedded priority. We now use that by default, unless an explicit DoSound/SetPriority call overrides it. Thanks waltervn. This fixes relative priority of songs in at least PQ3 room 29. Also increase savegame version to 33. --- engines/sci/engine/savegame.cpp | 4 ++++ engines/sci/engine/savegame.h | 3 ++- engines/sci/resource.h | 2 ++ engines/sci/resource_audio.cpp | 4 ++++ engines/sci/sound/music.cpp | 2 ++ engines/sci/sound/music.h | 1 + engines/sci/sound/soundcmd.cpp | 26 +++++++++++++++----------- 7 files changed, 30 insertions(+), 12 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index eee4c49729..61f8058e45 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -621,6 +621,10 @@ void MusicEntry::saveLoadWithSerializer(Common::Serializer &s) { s.syncAsByte(playBed); else if (s.isLoading()) playBed = false; + if (s.getVersion() >= 33) + s.syncAsByte(overridePriority); + else if (s.isLoading()) + overridePriority = false; // pMidiParser and pStreamAud will be initialized when the // sound list is reconstructed in gamestate_restore() diff --git a/engines/sci/engine/savegame.h b/engines/sci/engine/savegame.h index be6d05cdc5..7f482ed0a1 100644 --- a/engines/sci/engine/savegame.h +++ b/engines/sci/engine/savegame.h @@ -37,6 +37,7 @@ struct EngineState; * * Version - new/changed feature * ============================= + * 33 - new overridePriority flag in MusicEntry * 32 - new playBed flag in MusicEntry * 31 - priority for sound effects/music is now a signed int16, instead of a byte * 30 - synonyms @@ -57,7 +58,7 @@ struct EngineState; */ enum { - CURRENT_SAVEGAME_VERSION = 32, + CURRENT_SAVEGAME_VERSION = 33, MINIMUM_SAVEGAME_VERSION = 14 }; diff --git a/engines/sci/resource.h b/engines/sci/resource.h index 62f3c584ac..ef48998b04 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -596,6 +596,7 @@ public: Track *getDigitalTrack(); int getChannelFilterMask(int hardwareMask, bool wantsRhythm); byte getInitialVoiceCount(byte channel); + byte getSoundPriority() const { return _soundPriority; } private: SciVersion _soundVersion; @@ -603,6 +604,7 @@ private: Track *_tracks; Resource *_innerResource; ResourceManager *_resMan; + byte _soundPriority; }; } // End of namespace Sci diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp index c775f502c5..3a43774492 100644 --- a/engines/sci/resource_audio.cpp +++ b/engines/sci/resource_audio.cpp @@ -579,6 +579,7 @@ SoundResource::SoundResource(uint32 resourceNr, ResourceManager *resMan, SciVers return; _innerResource = resource; + _soundPriority = 0xFF; byte *data, *data2; byte *dataEnd; @@ -725,6 +726,9 @@ SoundResource::SoundResource(uint32 resourceNr, ResourceManager *resMan, SciVers data += 6; } } else { + // The first byte of the 0xF0 track's channel list is priority + _soundPriority = *data; + // Skip over digital track data += 6; } diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index 2b73bcf8b3..dab02c9eb7 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -340,6 +340,7 @@ void SciMusic::soundInitSnd(MusicEntry *pSnd) { pSnd->soundType = Audio::Mixer::kSFXSoundType; pSnd->hCurrentAud = Audio::SoundHandle(); pSnd->playBed = false; + pSnd->overridePriority = false; } else { // play MIDI track Common::StackLock lock(_mutex); @@ -387,6 +388,7 @@ void SciMusic::soundInitSnd(MusicEntry *pSnd) { pSnd->loop = 0; pSnd->hold = -1; pSnd->playBed = false; + pSnd->overridePriority = false; pSnd->pMidiParser->loadMusic(track, pSnd, channelFilterMask, _soundVersion); pSnd->reverb = pSnd->pMidiParser->getSongReverb(); diff --git a/engines/sci/sound/music.h b/engines/sci/sound/music.h index 1347177054..8770748c3d 100644 --- a/engines/sci/sound/music.h +++ b/engines/sci/sound/music.h @@ -88,6 +88,7 @@ public: int16 hold; int8 reverb; bool playBed; + bool overridePriority; // Use soundObj's priority instead of resource's int16 pauseCounter; uint sampleLoopCounter; diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp index 47ab9bdc71..682c88f382 100644 --- a/engines/sci/sound/soundcmd.cpp +++ b/engines/sci/sound/soundcmd.cpp @@ -184,7 +184,15 @@ void SoundCommandParser::processPlaySound(reg_t obj, bool playBed) { } musicSlot->loop = readSelectorValue(_segMan, obj, SELECTOR(loop)); - musicSlot->priority = readSelectorValue(_segMan, obj, SELECTOR(priority)); + + // Get song priority from either obj or soundRes + byte resourcePriority = musicSlot->soundRes->getSoundPriority(); + if (!musicSlot->overridePriority && resourcePriority != 0xFF) { + musicSlot->priority = resourcePriority; + } else { + musicSlot->priority = readSelectorValue(_segMan, obj, SELECTOR(priority)); + } + // Reset hold when starting a new song. kDoSoundSetHold is always called after // kDoSoundPlay to set it properly, if needed. Fixes bug #3413589. musicSlot->hold = -1; @@ -677,23 +685,19 @@ reg_t SoundCommandParser::kDoSoundSetPriority(int argc, reg_t *argv, reg_t acc) } if (value == -1) { - uint16 resourceId = musicSlot->resourceId; + musicSlot->overridePriority = false; + musicSlot->priority = 0; - // Set priority from the song data - Resource *song = _resMan->findResource(ResourceId(kResourceTypeSound, resourceId), 0); - if (song->data[0] == 0xf0) - _music->soundSetPriority(musicSlot, song->data[1]); - else - warning("kDoSound(setPriority): Attempt to unset song priority when there is no built-in value"); + // NB: It seems SSCI doesn't actually reset the priority here. - //pSnd->prio=0;field_15B=0 writeSelectorValue(_segMan, obj, SELECTOR(flags), readSelectorValue(_segMan, obj, SELECTOR(flags)) & 0xFD); } else { // Scripted priority + musicSlot->overridePriority = true; - //pSnd->field_15B=1; writeSelectorValue(_segMan, obj, SELECTOR(flags), readSelectorValue(_segMan, obj, SELECTOR(flags)) | 2); - //DoSOund(0xF,hobj,w) + + _music->soundSetPriority(musicSlot, value); } return acc; } -- cgit v1.2.3 From 1c5722f014d1f5a34c79d8d1cb7f5ed86e0b822d Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Sat, 14 Feb 2015 15:58:47 +0100 Subject: SCI: Allow channel remapping from audio thread too --- engines/sci/sound/midiparser_sci.cpp | 12 +++++++---- engines/sci/sound/music.cpp | 42 ++++++++++++++++++++++-------------- engines/sci/sound/music.h | 7 ++++-- 3 files changed, 39 insertions(+), 22 deletions(-) (limited to 'engines') diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index 7ebe47633a..25facacced 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -487,8 +487,11 @@ void MidiParser_SCI::trackState(uint32 b) { s._sustain = (op2 != 0); break; case 0x4B: // voices - if (s._voices != op2) - warning("Voice change (%d to %d) without remapping", s._voices, op2); + if (s._voices != op2) { + // CHECKME: Should we directly call remapChannels() if _mainThreadCalled? + debugC(2, kDebugLevelSound, "Dynamic voice change (%d to %d)", s._voices, op2); + _music->needsRemap(); + } s._voices = op2; _pSnd->_chan[channel]._voices = op2; // Also sync our MusicEntry break; @@ -500,8 +503,9 @@ void MidiParser_SCI::trackState(uint32 b) { bool m = op2; if (_pSnd->_chan[channel]._mute != m) { _pSnd->_chan[channel]._mute = m; - // TODO: If muting/unmuting a channel, remap channels. - warning("Mute change without immediate remapping (mainThread = %d)", _mainThreadCalled); + // CHECKME: Should we directly call remapChannels() if _mainThreadCalled? + _music->needsRemap(); + debugC(2, kDebugLevelSound, "Dynamic mute change (mainThread = %d)", _mainThreadCalled); } } break; diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index dab02c9eb7..37bf6a7b1b 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -145,6 +145,7 @@ void SciMusic::init() { _currentlyPlayingSample = NULL; _timeCounter = 0; + _needsRemap = false; } void SciMusic::miditimerCallback(void *p) { @@ -159,6 +160,11 @@ void SciMusic::onTimer() { // sending out queued commands that were "sent" via main thread sendMidiCommandsFromQueue(); + // remap channels, if requested + if (_needsRemap) + remapChannels(false); + _needsRemap = false; + for (MusicList::iterator i = _playList.begin(); i != end; ++i) (*i)->onTimer(); } @@ -920,12 +926,12 @@ int ChannelRemapping::lowestPrio() const { } -void SciMusic::remapChannels() { +void SciMusic::remapChannels(bool mainThread) { if (_soundVersion <= SCI_VERSION_0_LATE) return; - // NB: This function should only be called from the main thread, - // with _mutex locked + // NB: This function should only be called with _mutex locked + // Make sure to set the mainThread argument correctly. ChannelRemapping *map = determineChannelMap(); @@ -978,9 +984,9 @@ void SciMusic::remapChannels() { for (int j = 0; j < 16; ++j) { if (!channelMapped[j]) { - song->pMidiParser->mainThreadBegin(); + if (mainThread) song->pMidiParser->mainThreadBegin(); song->pMidiParser->remapChannel(j, -1); - song->pMidiParser->mainThreadEnd(); + if (mainThread) song->pMidiParser->mainThreadEnd(); #ifdef DEBUG_REMAP if (channelUsed[j]) debug(" Unmapping song %d, channel %d", songIndex, j); @@ -1012,9 +1018,9 @@ void SciMusic::remapChannels() { #ifdef DEBUG_REMAP debug(" Mapping (dontRemap) song %d, channel %d to device channel %d", songIndex, _channelMap[i]._channel, i); #endif - _channelMap[i]._song->pMidiParser->mainThreadBegin(); + if (mainThread) _channelMap[i]._song->pMidiParser->mainThreadBegin(); _channelMap[i]._song->pMidiParser->remapChannel(_channelMap[i]._channel, i); - _channelMap[i]._song->pMidiParser->mainThreadEnd(); + if (mainThread) _channelMap[i]._song->pMidiParser->mainThreadEnd(); } } @@ -1067,9 +1073,9 @@ void SciMusic::remapChannels() { #ifdef DEBUG_REMAP debug(" Mapping song %d, channel %d to device channel %d", songIndex, _channelMap[j]._channel, j); #endif - _channelMap[j]._song->pMidiParser->mainThreadBegin(); + if (mainThread) _channelMap[j]._song->pMidiParser->mainThreadBegin(); _channelMap[j]._song->pMidiParser->remapChannel(_channelMap[j]._channel, j); - _channelMap[j]._song->pMidiParser->mainThreadEnd(); + if (mainThread) _channelMap[j]._song->pMidiParser->mainThreadEnd(); break; } } @@ -1079,7 +1085,7 @@ void SciMusic::remapChannels() { // And finally, stop any empty channels for (int i = _driverLastChannel; i >= _driverFirstChannel; --i) { if (!_channelMap[i]._song && currentMap[i]._song) - resetDeviceChannel(i); + resetDeviceChannel(i, mainThread); } delete map; @@ -1307,14 +1313,18 @@ ChannelRemapping *SciMusic::determineChannelMap() { return map; } -void SciMusic::resetDeviceChannel(int devChannel) { - // NB: This function should only be called from the main thread - +void SciMusic::resetDeviceChannel(int devChannel, bool mainThread) { assert(devChannel >= 0 && devChannel <= 0x0F); - putMidiCommandInQueue(0x0040B0 | devChannel); // sustain off - putMidiCommandInQueue(0x007BB0 | devChannel); // notes off - putMidiCommandInQueue(0x004BB0 | devChannel); // release voices + if (mainThread) { + putMidiCommandInQueue(0x0040B0 | devChannel); // sustain off + putMidiCommandInQueue(0x007BB0 | devChannel); // notes off + putMidiCommandInQueue(0x004BB0 | devChannel); // release voices + } else { + _pMidiDrv->send(0x0040B0 | devChannel); // sustain off + _pMidiDrv->send(0x007BB0 | devChannel); // notes off + _pMidiDrv->send(0x004BB0 | devChannel); // release voices + } } diff --git a/engines/sci/sound/music.h b/engines/sci/sound/music.h index 8770748c3d..a610f32d89 100644 --- a/engines/sci/sound/music.h +++ b/engines/sci/sound/music.h @@ -228,6 +228,8 @@ public: byte getCurrentReverb(); + void needsRemap() { _needsRemap = true; } + virtual void saveLoadWithSerializer(Common::Serializer &ser); // Mutex for music code. Used to guard access to the song playlist, to the @@ -249,9 +251,9 @@ protected: bool _useDigitalSFX; // remapping: - void remapChannels(); + void remapChannels(bool mainThread = true); ChannelRemapping *determineChannelMap(); - void resetDeviceChannel(int devChannel); + void resetDeviceChannel(int devChannel, bool mainThread); private: MusicList _playList; @@ -260,6 +262,7 @@ private: MusicEntry *_usedChannel[16]; int8 _channelRemap[16]; int8 _globalReverb; + bool _needsRemap; DeviceChannelUsage _channelMap[16]; -- cgit v1.2.3 From 7658821afd7a6d2e70286866c15eff7dd2618115 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 15 Feb 2015 08:10:13 -0500 Subject: MADS: Fix left screen clipping for scaled flipped sprites --- engines/mads/msurface.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/mads/msurface.cpp b/engines/mads/msurface.cpp index cc12442db1..702b9e5f08 100644 --- a/engines/mads/msurface.cpp +++ b/engines/mads/msurface.cpp @@ -400,14 +400,16 @@ void MSurface::copyFrom(MSurface *src, const Common::Point &destPos, int depth, const byte *srcP = srcPixelsP; byte *destP = destPixelsP; - for (int xp = 0, sprX = 0; xp < frameWidth; ++xp, ++srcP) { - if (xp < spriteLeft) - // Not yet reached start of display area - continue; - if (!lineDist[sprX++]) + for (int xp = 0, sprX = -1; xp < frameWidth; ++xp, ++srcP) { + if (!lineDist[xp]) // Not a display pixel continue; + ++sprX; + if (sprX < spriteLeft || sprX >= spriteRight) + // Skip pixel if it's not in horizontal display portion + continue; + // Get depth of current output pixel in depth surface Common::Point pt((destP - (byte *)this->pixels) % this->pitch, (destP - (byte *)this->pixels) / this->pitch); -- cgit v1.2.3 From d0cb5f51fddcd74461914fb28ef4fbd685833eae Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Sun, 15 Feb 2015 10:28:06 +0100 Subject: SCI: Only allow a single 'playBed' song in SCI1early --- engines/sci/sound/music.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index 37bf6a7b1b..7156e3c099 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -410,8 +410,22 @@ void SciMusic::soundInitSnd(MusicEntry *pSnd) { void SciMusic::soundPlay(MusicEntry *pSnd) { _mutex.lock(); - // TODO: if pSnd->playBed, and version <= SCI1_EARLY, then kill - // existing sounds with playBed enabled. + if (_soundVersion <= SCI_VERSION_1_EARLY && pSnd->playBed) { + // If pSnd->playBed, and version <= SCI1_EARLY, then kill + // existing sounds with playBed enabled. + + uint playListCount = _playList.size(); + for (uint i = 0; i < playListCount; i++) { + if (_playList[i] != pSnd && _playList[i]->playBed) { + debugC(2, kDebugLevelSound, "Automatically stopping old playBed song from soundPlay"); + MusicEntry *old = _playList[i]; + _mutex.unlock(); + soundStop(old); + _mutex.lock(); + break; + } + } + } uint playListCount = _playList.size(); uint playListNo = playListCount; -- cgit v1.2.3 From 2b49b5f95e8d6bd5ea3ab8ffb20ebad2ae7fc95e Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Sun, 15 Feb 2015 14:14:46 +0100 Subject: SCI: Fix sound object frame selector rate Thanks waltervn. Verified against asm (QfG2, KQ6CD) --- engines/sci/sound/soundcmd.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp index 682c88f382..64991cbf5c 100644 --- a/engines/sci/sound/soundcmd.cpp +++ b/engines/sci/sound/soundcmd.cpp @@ -550,7 +550,7 @@ void SoundCommandParser::processUpdateCues(reg_t obj) { if (_soundVersion >= SCI_VERSION_1_EARLY) { writeSelectorValue(_segMan, obj, SELECTOR(min), musicSlot->ticker / 3600); writeSelectorValue(_segMan, obj, SELECTOR(sec), musicSlot->ticker % 3600 / 60); - writeSelectorValue(_segMan, obj, SELECTOR(frame), musicSlot->ticker); + writeSelectorValue(_segMan, obj, SELECTOR(frame), musicSlot->ticker % 60 / 2); } } -- cgit v1.2.3 From 7739e12e42edae68264a9675ede1bd840ae3be6b Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 15 Feb 2015 09:50:14 -0500 Subject: MADS: Stop player disappearing after cutscene of fish being eaten --- engines/mads/player.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/mads/player.cpp b/engines/mads/player.cpp index bde313af8d..e7993f378a 100644 --- a/engines/mads/player.cpp +++ b/engines/mads/player.cpp @@ -509,10 +509,11 @@ void Player::idle() { return; } - if ((_spritesStart + _spritesIdx) < 0 || !_spriteSetsPresent[_spritesStart + _spritesIdx]) + int idx = _spritesStart + _spritesIdx; + if (idx < 0 || (idx < PLAYER_SPRITES_FILE_COUNT && !_spriteSetsPresent[idx])) return; - SpriteAsset &spriteSet = *scene._sprites[_spritesStart + _spritesIdx]; + SpriteAsset &spriteSet = *scene._sprites[idx]; assert(spriteSet._charInfo); if (spriteSet._charInfo->_numEntries == 0) // No entries, so exit immediately -- cgit v1.2.3 From db325695f42e2dec3163b9a371085d8561e5a42a Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 15 Feb 2015 11:07:33 -0500 Subject: MADS: Fix proper cycling of idle animations --- engines/mads/player.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/mads/player.cpp b/engines/mads/player.cpp index e7993f378a..1622031c6c 100644 --- a/engines/mads/player.cpp +++ b/engines/mads/player.cpp @@ -235,11 +235,12 @@ void Player::selectSeries() { void Player::updateFrame() { // WORKAROUND: Prevent character info being referenced when not present - if ((_spritesStart + _spritesIdx) < 0 || !_spriteSetsPresent[_spritesStart + _spritesIdx]) + int idx = _spritesStart + _spritesIdx; + if (idx < 0 || (idx < PLAYER_SPRITES_FILE_COUNT && !_spriteSetsPresent[idx])) return; Scene &scene = _vm->_game->_scene; - SpriteAsset &spriteSet = *scene._sprites[_spritesStart + _spritesIdx]; + SpriteAsset &spriteSet = *scene._sprites[idx]; assert(spriteSet._charInfo); if (!spriteSet._charInfo->_numEntries) { @@ -529,11 +530,11 @@ void Player::idle() { _frameNumber += direction; _forceRefresh = true; - if (spriteSet._charInfo->_stopFrames[frameIndex] < _frameNumber) { + if (_frameNumber > spriteSet._charInfo->_stopFrames[frameIndex]) { _trigger = _upcomingTrigger; updateFrame(); } - if (spriteSet._charInfo->_startFrames[frameIndex] < _frameNumber) { + if (_frameNumber < spriteSet._charInfo->_startFrames[frameIndex]) { _trigger = _upcomingTrigger; updateFrame(); } -- cgit v1.2.3 From 165a8c26b9c47c056e679eb55ae9e73e15af2b14 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Sun, 15 Feb 2015 18:25:50 +0100 Subject: SCI: Fix version check for MIDI controller 4E This is only supported since SCI1 middle, as verified with xmas1990, SCI1 mgoose, SQ4 floppy, LSL1, Jones floppy. Fixes missing sounds in Jones floppy. --- engines/sci/sound/midiparser_sci.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index 25facacced..ed61a57729 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -498,7 +498,7 @@ void MidiParser_SCI::trackState(uint32 b) { case 0x4E: // mute // This is channel mute only for sci1. // (It's velocity control for sci0, but we don't need state in sci0) - if (_soundVersion >= SCI_VERSION_1_EARLY) { + if (_soundVersion > SCI_VERSION_1_EARLY) { // FIXME: mute is a level, not a bool, in some SCI versions bool m = op2; if (_pSnd->_chan[channel]._mute != m) { -- cgit v1.2.3 From f477de200916f68fe8e82025f80b13e8288f6589 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Sun, 15 Feb 2015 18:28:34 +0100 Subject: SCI: Add more audio debugging output --- engines/sci/sound/midiparser_sci.cpp | 2 +- engines/sci/sound/music.cpp | 12 ++++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index ed61a57729..9f0d8d150f 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -505,7 +505,7 @@ void MidiParser_SCI::trackState(uint32 b) { _pSnd->_chan[channel]._mute = m; // CHECKME: Should we directly call remapChannels() if _mainThreadCalled? _music->needsRemap(); - debugC(2, kDebugLevelSound, "Dynamic mute change (mainThread = %d)", _mainThreadCalled); + debugC(2, kDebugLevelSound, "Dynamic mute change (arg = %d, mainThread = %d)", m, _mainThreadCalled); } } break; diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index 7156e3c099..dca73c3f51 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -1154,10 +1154,18 @@ ChannelRemapping *SciMusic::determineChannelMap() { if (c == 0xFF || c == 0xFE || c == 0x0F) continue; const MusicEntryChannel &channel = song->_chan[c]; - if (channel._dontMap) + if (channel._dontMap) { +#ifdef DEBUG_REMAP + debug(" Channel %d dontMap, skipping", c); +#endif continue; - if (channel._mute) + } + if (channel._mute) { +#ifdef DEBUG_REMAP + debug(" Channel %d muted, skipping", c); +#endif continue; + } bool dontRemap = channel._dontRemap || song->playBed; -- cgit v1.2.3 From 60e83c2d9ca68e4dd90c0d644ac500b5f3be491e Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 15 Feb 2015 20:49:16 +0200 Subject: PEGASUS: Silence two MSVC warnings --- engines/pegasus/menu.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/pegasus/menu.cpp b/engines/pegasus/menu.cpp index 4bbda8fd93..3e9bf540fe 100644 --- a/engines/pegasus/menu.cpp +++ b/engines/pegasus/menu.cpp @@ -258,12 +258,12 @@ void MainMenu::handleInput(const Input &input, const Hotspot *cursorSpot) { bool isDemo = vm->isDemo(); if (input.upButtonDown()) { - if (_menuSelection > (isDemo ? kFirstSelectionDemo : kFirstSelection)) { + if (_menuSelection > (uint32)(isDemo ? kFirstSelectionDemo : kFirstSelection)) { _menuSelection--; updateDisplay(); } } else if (input.downButtonDown()) { - if (_menuSelection < (isDemo ? kLastSelectionDemo : kLastSelection)) { + if (_menuSelection < (uint32)(isDemo ? kLastSelectionDemo : kLastSelection)) { _menuSelection++; updateDisplay(); } -- cgit v1.2.3 From f04ef8b7282477cda5121b6c8a6e838eb35a1760 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 16 Feb 2015 12:11:50 +0200 Subject: ZVISION: Fix script bug #6793 in Zork Nemesis --- engines/zvision/file/save_manager.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'engines') diff --git a/engines/zvision/file/save_manager.cpp b/engines/zvision/file/save_manager.cpp index 1e0c57e2b3..63b54269de 100644 --- a/engines/zvision/file/save_manager.cpp +++ b/engines/zvision/file/save_manager.cpp @@ -165,6 +165,27 @@ Common::Error SaveManager::loadGame(int slot) { if (header.thumbnail) delete header.thumbnail; + if (_engine->getGameId() == GID_NEMESIS && scriptManager->getCurrentLocation() == "tv2f") { + // WORKAROUND for script bug #6793: location tv2f (stairs) has two states: + // one at the top of the stairs, and one at the bottom. When the player + // goes to the bottom of the stairs, the screen changes, and hotspot + // 4652 (exit opposite the stairs) is enabled. However, the variable that + // controls the state (2408) is reset when the player goes down the stairs. + // Furthermore, the room's initialization script disables the stair exit + // control (4652). This leads to an impossible situation, where all the + // exit controls are disabled, and the player can't more anywhere. Thus, + // when loading a game in that room, we check for that impossible + // situation, which only occurs after the player has moved down the stairs, + // and fix it here by setting the correct background, and enabling the + // stair exit hotspot. + if ((scriptManager->getStateFlag(2411) & Puzzle::DISABLED) && + (scriptManager->getStateFlag(2408) & Puzzle::DISABLED) && + (scriptManager->getStateFlag(4652) & Puzzle::DISABLED)) { + _engine->getRenderManager()->setBackgroundImage("tv2fb21c.tga"); + scriptManager->unsetStateFlag(4652, Puzzle::DISABLED); + } + } + return Common::kNoError; } -- cgit v1.2.3 From b45e706012d7131035867fdd1e6f7109db1ae635 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 17 Feb 2015 01:49:59 +0200 Subject: ZVISION: Fix script bug #6803 (tuning fork box state) --- engines/zvision/scripting/scr_file_handling.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'engines') diff --git a/engines/zvision/scripting/scr_file_handling.cpp b/engines/zvision/scripting/scr_file_handling.cpp index a9f3a55021..edc1b8622c 100644 --- a/engines/zvision/scripting/scr_file_handling.cpp +++ b/engines/zvision/scripting/scr_file_handling.cpp @@ -86,6 +86,15 @@ void ScriptManager::parsePuzzle(Puzzle *puzzle, Common::SeekableReadStream &stre parseCriteria(stream, puzzle->criteriaList, puzzle->key); } else if (line.matchString("results {", true)) { parseResults(stream, puzzle->resultActions); + + // WORKAROUND for a script bug in Zork Nemesis, room ve5e (tuning + // fork box closeup). If the player leaves the screen while the + // box is open, puzzle 19398 shows the animation where the box + // closes, but the box state (state variable 19397) is not updated. + // We insert the missing assignment for the box state here. + // Fixes bug #6803. + if (_engine->getGameId() == GID_NEMESIS && puzzle->key == 19398) + puzzle->resultActions.push_back(new ActionAssign(_engine, 11, "19397, 0")); } else if (line.matchString("flags {", true)) { setStateFlag(puzzle->key, parseFlags(stream)); } -- cgit v1.2.3 From fdc09c2cb7ff3041dbd11c146d3d669cc7aa4777 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Tue, 17 Feb 2015 19:53:43 +0100 Subject: SCI: Add alternative version of QfG3 "Woo" dialog patch The GOG version of QfG3 is shipped with a patch to script 440 that broke our existing internal script patch for this script bug. See bug #6806. --- engines/sci/engine/script_patches.cpp | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'engines') diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp index c2a0b8b95d..45e0155950 100644 --- a/engines/sci/engine/script_patches.cpp +++ b/engines/sci/engine/script_patches.cpp @@ -2282,10 +2282,40 @@ static const uint16 qfg3PatchWooDialog[] = { PATCH_END }; +// Alternative version, with uint16 offsets, for GOG release of QfG3. +static const uint16 qfg3SignatureWooDialogAlt[] = { + SIG_MAGICDWORD, + 0x67, 0x12, // pTos 12 (query) + 0x35, 0xb6, // ldi b6 + 0x1a, // eq? + 0x2e, SIG_UINT16(0x0005), // bt 05 + 0x67, 0x12, // pTos 12 (query) + 0x35, 0x9b, // ldi 9b + 0x1a, // eq? + 0x30, SIG_UINT16(0x000c), // bnt 0c + 0x38, SIG_SELECTOR16(solvePuzzle), // pushi 0297 + 0x7a, // push2 + 0x38, SIG_UINT16(0x010c), // pushi 010c + 0x7a, // push2 + 0x81, 0x00, // lag 00 + 0x4a, 0x08, // send 08 + 0x67, 0x12, // pTos 12 (query) + 0x35, 0xb5, // ldi b5 + SIG_END +}; + +static const uint16 qfg3PatchWooDialogAlt[] = { + PATCH_ADDTOOFFSET(+0x2C), + 0x33, 0x12, // jmp to 0x708, the call to hero::solvePuzzle for 0xFFFC + PATCH_END +}; + + // script, description, signature patch static const SciScriptPatcherEntry qfg3Signatures[] = { { true, 944, "import dialog continuous calls", 1, qfg3SignatureImportDialog, qfg3PatchImportDialog }, { true, 440, "dialog crash when asking about Woo", 1, qfg3SignatureWooDialog, qfg3PatchWooDialog }, + { true, 440, "dialog crash when asking about Woo", 1, qfg3SignatureWooDialogAlt, qfg3PatchWooDialogAlt }, SCI_SIGNATUREENTRY_TERMINATOR }; -- cgit v1.2.3 From 4f6f0fb148133df632104071185efa049c7d5fea Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Wed, 18 Feb 2015 09:33:03 +0100 Subject: SCI: Fix digital audio Regression from 5028487038fd, where I assumed all songs were MIDI. --- engines/sci/sound/soundcmd.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp index 64991cbf5c..ee5903fda2 100644 --- a/engines/sci/sound/soundcmd.cpp +++ b/engines/sci/sound/soundcmd.cpp @@ -186,7 +186,9 @@ void SoundCommandParser::processPlaySound(reg_t obj, bool playBed) { musicSlot->loop = readSelectorValue(_segMan, obj, SELECTOR(loop)); // Get song priority from either obj or soundRes - byte resourcePriority = musicSlot->soundRes->getSoundPriority(); + byte resourcePriority = 0xFF; + if (musicSlot->soundRes) + resourcePriority = musicSlot->soundRes->getSoundPriority(); if (!musicSlot->overridePriority && resourcePriority != 0xFF) { musicSlot->priority = resourcePriority; } else { -- cgit v1.2.3 From df5742eee41abe7e74a2b47a0ddcc183bf52fe09 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 21 Feb 2015 15:52:01 -0500 Subject: MADS: Fix player animation when getting blown up by mine --- engines/mads/player.cpp | 10 +++++++--- engines/mads/sprites.cpp | 7 ++----- 2 files changed, 9 insertions(+), 8 deletions(-) (limited to 'engines') diff --git a/engines/mads/player.cpp b/engines/mads/player.cpp index 1622031c6c..8720aeead3 100644 --- a/engines/mads/player.cpp +++ b/engines/mads/player.cpp @@ -240,8 +240,13 @@ void Player::updateFrame() { return; Scene &scene = _vm->_game->_scene; + assert(scene._sprites[idx] != nullptr); SpriteAsset &spriteSet = *scene._sprites[idx]; - assert(spriteSet._charInfo); + + // WORKAROUND: Certain cutscenes set up player sprites that don't have any + // character info. In such cases, simply ignore player updates + if (!spriteSet._charInfo) + return; if (!spriteSet._charInfo->_numEntries) { _frameNumber = 1; @@ -515,8 +520,7 @@ void Player::idle() { return; SpriteAsset &spriteSet = *scene._sprites[idx]; - assert(spriteSet._charInfo); - if (spriteSet._charInfo->_numEntries == 0) + if (spriteSet._charInfo == nullptr || spriteSet._charInfo->_numEntries == 0) // No entries, so exit immediately return; diff --git a/engines/mads/sprites.cpp b/engines/mads/sprites.cpp index fd73930475..f74edafc93 100644 --- a/engines/mads/sprites.cpp +++ b/engines/mads/sprites.cpp @@ -371,16 +371,13 @@ int SpriteSets::add(SpriteAsset *asset, int idx) { if (idx) idx = idx + 49; else - idx = size(); + idx = _assetCount++; if (idx >= (int)size()) resize(idx + 1); - if ((*this)[idx]) { + if ((*this)[idx]) delete (*this)[idx]; - } else { - ++_assetCount; - } (*this)[idx] = asset; return idx; -- cgit v1.2.3 From 549b5d435a897e1f6d306d2bdb902cac18159491 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 21 Feb 2015 16:14:59 -0500 Subject: MADS: Fix crash when trapping bouncy native in pit --- engines/mads/nebular/nebular_scenes2.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes2.cpp b/engines/mads/nebular/nebular_scenes2.cpp index 94e30aa4f2..d00857f0a2 100644 --- a/engines/mads/nebular/nebular_scenes2.cpp +++ b/engines/mads/nebular/nebular_scenes2.cpp @@ -1745,7 +1745,8 @@ void Scene208::enter() { } void Scene208::step() { - if (_boundingFl && (_rhotundaTime <= _scene->_activeAnimation->getCurrentFrame())) { + if (_boundingFl && _scene->_activeAnimation && + (_rhotundaTime <= _scene->_activeAnimation->getCurrentFrame())) { _rhotundaTime = _scene->_activeAnimation->getCurrentFrame(); if (_rhotundaTime == 125) -- cgit v1.2.3 From 6ca8d22fb100f2b3f3549b8785801ffd470135b9 Mon Sep 17 00:00:00 2001 From: jammm Date: Sun, 22 Feb 2015 02:02:41 +0530 Subject: WINTERMUTE: Fixed parentFolder name check when testing for "language"/"languages", Fix bug #6655 (Dead City - hotspot text issue) Fixed Wintermute incorretly parsing folder names with trailing \ (Windows-only issue) It seems that calling getParent returns trailing '\' which is absent on POSIX based file systems but not on Windows. This causes Wintermute to load outline_red2.font from russian.dcp, which is not desired. This is fixed by calling it->getName() directly, which returns the folder name (without the trailing '\'). --- engines/wintermute/base/base_file_manager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/wintermute/base/base_file_manager.cpp b/engines/wintermute/base/base_file_manager.cpp index 58684b66a0..05830ffcd8 100644 --- a/engines/wintermute/base/base_file_manager.cpp +++ b/engines/wintermute/base/base_file_manager.cpp @@ -227,7 +227,7 @@ bool BaseFileManager::registerPackages() { // Again, make the parent's name all lowercase to avoid any case // issues. - Common::String parentName = fileIt->getParent().getName(); + Common::String parentName = it->getName(); parentName.toLowercase(); // Avoid registering all the language files -- cgit v1.2.3 From c660119c2282a4a501ab88e9a65e3064fccad21d Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 21 Feb 2015 16:48:04 -0500 Subject: MADS: Fix depth for seaweed in scene 104 --- engines/mads/nebular/nebular_scenes1.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes1.cpp b/engines/mads/nebular/nebular_scenes1.cpp index 7c85fd44db..3149343aee 100644 --- a/engines/mads/nebular/nebular_scenes1.cpp +++ b/engines/mads/nebular/nebular_scenes1.cpp @@ -1621,6 +1621,7 @@ void Scene104::setup() { void Scene104::enter() { _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('h', -1)); _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 14, 0, 0, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 8); if (_scene->_priorSceneId == 105) _game._player._playerPos = Common::Point(302, 107); -- cgit v1.2.3 From 076ce7e6c158878305ace5d7f334d54f8d44e966 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 21 Feb 2015 17:45:20 -0500 Subject: MADS: Implement scroll wheel support for scrolling inventory --- engines/mads/events.cpp | 6 +++ engines/mads/game.cpp | 11 +++++ engines/mads/user_interface.cpp | 90 +++++++++++++++++++++++------------------ engines/mads/user_interface.h | 7 +++- 4 files changed, 73 insertions(+), 41 deletions(-) (limited to 'engines') diff --git a/engines/mads/events.cpp b/engines/mads/events.cpp index 586ef7cbf3..06c6055f01 100644 --- a/engines/mads/events.cpp +++ b/engines/mads/events.cpp @@ -162,6 +162,12 @@ void EventsManager::pollEvents() { return; case Common::EVENT_KEYUP: return; + case Common::EVENT_WHEELUP: + _pendingKeys.push(Common::KeyState(Common::KEYCODE_PAGEUP)); + return; + case Common::EVENT_WHEELDOWN: + _pendingKeys.push(Common::KeyState(Common::KEYCODE_PAGEDOWN)); + return; case Common::EVENT_LBUTTONDOWN: case Common::EVENT_RBUTTONDOWN: _mouseClicked = true; diff --git a/engines/mads/game.cpp b/engines/mads/game.cpp index 27691d3380..3b8b053fec 100644 --- a/engines/mads/game.cpp +++ b/engines/mads/game.cpp @@ -420,6 +420,7 @@ void Game::handleKeypress(const Common::KeyState &kbd) { } } + Scene &scene = _vm->_game->_scene; switch (kbd.keycode) { case Common::KEYCODE_F1: _vm->_dialogs->_pendingDialog = DIALOG_GAME_MENU; @@ -430,6 +431,16 @@ void Game::handleKeypress(const Common::KeyState &kbd) { case Common::KEYCODE_F7: _vm->_dialogs->_pendingDialog = DIALOG_RESTORE; break; + case Common::KEYCODE_PAGEUP: + scene._userInterface._scrollbarStrokeType = SCROLLBAR_UP; + scene._userInterface.changeScrollBar(); + break; + case Common::KEYCODE_PAGEDOWN: + scene._userInterface._scrollbarStrokeType = SCROLLBAR_DOWN; + scene._userInterface.changeScrollBar(); + break; + + default: break; } diff --git a/engines/mads/user_interface.cpp b/engines/mads/user_interface.cpp index 822460d549..929390a073 100644 --- a/engines/mads/user_interface.cpp +++ b/engines/mads/user_interface.cpp @@ -495,7 +495,6 @@ void UserInterface::drawScroller() { void UserInterface::updateInventoryScroller() { ScreenObjects &screenObjects = _vm->_game->_screenObjects; - Common::Array &inventoryList = _vm->_game->_objects._inventoryList; if (screenObjects._inputMode != kInputBuildingSentences) return; @@ -518,45 +517,8 @@ void UserInterface::updateInventoryScroller() { _scrollbarQuickly = _vm->_events->_vD2 < 1; _scrollbarMilliTime = currentMilli; - switch (_scrollbarStrokeType) { - case SCROLLBAR_UP: - // Scroll up - if (_inventoryTopIndex > 0 && inventoryList.size() > 0) { - --_inventoryTopIndex; - _inventoryChanged = true; - } - break; - - case SCROLLBAR_DOWN: - // Scroll down - if (_inventoryTopIndex < ((int)inventoryList.size() - 1) && inventoryList.size() > 1) { - ++_inventoryTopIndex; - _inventoryChanged = true; - } - break; - - case SCROLLBAR_ELEVATOR: { - // Inventory slider - int newIndex = CLIP((int)_vm->_events->currentPos().y - 170, 0, 17) - * inventoryList.size() / 10; - if (newIndex >= (int)inventoryList.size()) - newIndex = inventoryList.size() - 1; - - if (inventoryList.size() > 0) { - _inventoryChanged = newIndex != _inventoryTopIndex; - _inventoryTopIndex = newIndex; - } - break; - } - - default: - break; - } - - if (_inventoryChanged) { - int dummy; - updateSelection(CAT_INV_LIST, 0, &dummy); - } + // Change the scrollbar and visible inventory list + changeScrollBar(); } } } @@ -569,6 +531,54 @@ void UserInterface::updateInventoryScroller() { _scrollbarOldElevator = _scrollbarElevator; } +void UserInterface::changeScrollBar() { + Common::Array &inventoryList = _vm->_game->_objects._inventoryList; + ScreenObjects &screenObjects = _vm->_game->_screenObjects; + + if (screenObjects._inputMode != kInputBuildingSentences) + return; + + switch (_scrollbarStrokeType) { + case SCROLLBAR_UP: + // Scroll up + if (_inventoryTopIndex > 0 && inventoryList.size() > 0) { + --_inventoryTopIndex; + _inventoryChanged = true; + } + break; + + case SCROLLBAR_DOWN: + // Scroll down + if (_inventoryTopIndex < ((int)inventoryList.size() - 1) && inventoryList.size() > 1) { + ++_inventoryTopIndex; + _inventoryChanged = true; + } + break; + + case SCROLLBAR_ELEVATOR: { + // Inventory slider + int newIndex = CLIP((int)_vm->_events->currentPos().y - 170, 0, 17) + * inventoryList.size() / 10; + if (newIndex >= (int)inventoryList.size()) + newIndex = inventoryList.size() - 1; + + if (inventoryList.size() > 0) { + _inventoryChanged = newIndex != _inventoryTopIndex; + _inventoryTopIndex = newIndex; + } + break; + } + + default: + break; + } + + if (_inventoryChanged) { + int dummy; + updateSelection(CAT_INV_LIST, 0, &dummy); + } +} + void UserInterface::scrollbarChanged() { Common::Rect r(73, 4, 73 + 9, 4 + 38); _uiSlots.add(r); diff --git a/engines/mads/user_interface.h b/engines/mads/user_interface.h index 89044c9bf1..71c6f64c2a 100644 --- a/engines/mads/user_interface.h +++ b/engines/mads/user_interface.h @@ -140,7 +140,6 @@ private: bool _scrollFlag; int _noSegmentsActive; int _someSegmentsActive; - ScrollbarActive _scrollbarStrokeType; /** * Loads the elements of the user interface @@ -216,6 +215,7 @@ public: bool _scrollbarQuickly; uint32 _scrollbarMilliTime; int _scrollbarElevator, _scrollbarOldElevator; + ScrollbarActive _scrollbarStrokeType; public: /** * Constructor @@ -275,6 +275,11 @@ public: void updateSelection(ScrCategory category, int newIndex, int *idx); + /** + * Updates the current top visible item of the scrollbar + */ + void changeScrollBar(); + void scrollerChanged(); void scrollInventory(); -- cgit v1.2.3 From 85aecfaad4d9a0067a10580cea587996f2f37461 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 21 Feb 2015 18:56:06 -0500 Subject: MADS: Fix animations of spider and vulture in witch doctor's hut scene --- engines/mads/nebular/nebular_scenes2.cpp | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes2.cpp b/engines/mads/nebular/nebular_scenes2.cpp index d00857f0a2..3eef545b09 100644 --- a/engines/mads/nebular/nebular_scenes2.cpp +++ b/engines/mads/nebular/nebular_scenes2.cpp @@ -1448,12 +1448,14 @@ Scene207::Scene207(MADSEngine *vm) : Scene2xx(vm) { _eyeFl = false; _spiderHotspotId = -1; _vultureHotspotId = -1; - _spiderTime = 0; - _vultureTime = 0; + + _spiderTime = _game._player._priorTimer; + _vultureTime = _game._player._priorTimer; } void Scene207::synchronize(Common::Serializer &s) { Scene2xx::synchronize(s); + uint32 unused; s.syncAsByte(_vultureFl); s.syncAsByte(_spiderFl); @@ -1461,8 +1463,8 @@ void Scene207::synchronize(Common::Serializer &s) { s.syncAsSint32LE(_spiderHotspotId); s.syncAsSint32LE(_vultureHotspotId); - s.syncAsSint32LE(_spiderTime); - s.syncAsSint32LE(_vultureTime); + s.syncAsSint32LE(unused); + s.syncAsSint32LE(unused); } void Scene207::setup() { @@ -1501,7 +1503,6 @@ void Scene207::enter() { if (_vultureFl) { _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 30, 0, 0, 400); - _vultureTime = _game._player._priorTimer; _vultureHotspotId = _scene->_dynamicHotspots.add(389, 13, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); _scene->_dynamicHotspots.setPosition(_vultureHotspotId, Common::Point(254, 94), FACING_WEST); } @@ -1509,7 +1510,6 @@ void Scene207::enter() { if (_spiderFl) { _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 7, 1, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], -1, -1); - _spiderTime = _game._player._priorTimer; _spiderHotspotId = _scene->_dynamicHotspots.add(333, 13, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0)); _scene->_dynamicHotspots.setPosition(_spiderHotspotId, Common::Point(59, 132), FACING_SOUTH); } @@ -1549,11 +1549,17 @@ void Scene207::moveSpider() { } void Scene207::step() { - if (!_vultureFl) - moveVulture(); + Player &player = _game._player; + + if (_vultureFl) { + if (((int32)player._priorTimer - _vultureTime) > 1700) + moveVulture(); + } - if (_spiderFl) - moveSpider(); + if (_spiderFl) { + if (((int32)player._priorTimer - _spiderTime) > 800) + moveSpider(); + } if (_game._trigger == 70) { _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 10, 0, 0, 0); -- cgit v1.2.3 From 877474cd327c1fab98c296b4786f3c98b9c93714 Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Sun, 22 Feb 2015 01:43:02 +0100 Subject: MADS: Allow text to scroll off screen before removing it For example in the credits scroll. Clipping was already done elsewhere, so this really is just a change in how soon the line is removed from the list of text to display. --- engines/mads/menu_views.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mads/menu_views.cpp b/engines/mads/menu_views.cpp index 8f1fd2d7a5..5a0c7ee92e 100644 --- a/engines/mads/menu_views.cpp +++ b/engines/mads/menu_views.cpp @@ -426,7 +426,7 @@ void TextView::doFrame() { scene._textDisplay.expire(tl._textDisplayIndex); tl._pos.y--; - if (tl._pos.y < 0) { + if (tl._pos.y + _font->getHeight() < 0) { _textLines.remove_at(i); } else { tl._textDisplayIndex = scene._textDisplay.add(tl._pos.x, tl._pos.y, -- cgit v1.2.3 From 320139760cf4e964f5cc7ce8d71938377e293ec9 Mon Sep 17 00:00:00 2001 From: jammm Date: Mon, 23 Feb 2015 23:37:04 +0530 Subject: WINTERMUTE: Add mappings for VKeyCodes->ScummVM KeyCodes Fix bug #6654 (white chamber - some keys don't work) Wintermute games on ScummVM used ScummVM keycodes for keyboard mapping, whereas the game scripts only accepted Windows VKeyCodes. Therefore an initial set of mappings are added and the debug room is now loading properly, when HOME is pressed (Rest of the keys need to be tested in-game) --- engines/wintermute/base/base_keyboard_state.cpp | 101 ++++++++++++++++++------ engines/wintermute/base/base_keyboard_state.h | 2 +- 2 files changed, 77 insertions(+), 26 deletions(-) (limited to 'engines') diff --git a/engines/wintermute/base/base_keyboard_state.cpp b/engines/wintermute/base/base_keyboard_state.cpp index 0babc07586..f672c83d39 100644 --- a/engines/wintermute/base/base_keyboard_state.cpp +++ b/engines/wintermute/base/base_keyboard_state.cpp @@ -261,42 +261,93 @@ bool BaseKeyboardState::isCurrentPrintable() const { return _currentPrintable; } +////////////////////////////////////////////////////////////////////////// +enum VKeyCodes { + kVkReturn = 13, + + kVkEscape = 27, + + kVkSpace = 32, + kVkEnd = 35, + kVkHome = 36, + kVkLeft = 37, + kVkUp = 38, + kVkRight = 39, + kVkDown = 40, + + kVkF1 = 112, + kVkF2 = 113, + kVkF3 = 114, + kVkF4 = 115, + kVkF5 = 116, + kVkF6 = 117, + kVkF7 = 118, + kVkF8 = 119, + kVkF9 = 120, + kVkF10 = 121, + kVkF11 = 122, + kVkF12 = 123 + +}; + ////////////////////////////////////////////////////////////////////////// uint32 BaseKeyboardState::keyCodeToVKey(Common::Event *event) { + // todo if (event->type != Common::EVENT_KEYDOWN) { return 0; } switch (event->kbd.keycode) { + case Common::KEYCODE_RETURN: case Common::KEYCODE_KP_ENTER: - return Common::KEYCODE_RETURN; + return kVkReturn; + case Common::KEYCODE_ESCAPE: + return kVkEscape; + case Common::KEYCODE_SPACE: + return kVkSpace; + case Common::KEYCODE_END: + return kVkEnd; + case Common::KEYCODE_HOME: + return kVkHome; + case Common::KEYCODE_LEFT: + return kVkLeft; + case Common::KEYCODE_RIGHT: + return kVkRight; + case Common::KEYCODE_UP: + return kVkUp; + case Common::KEYCODE_DOWN: + return kVkDown; + case Common::KEYCODE_F1: + return kVkF1; + case Common::KEYCODE_F2: + return kVkF2; + case Common::KEYCODE_F3: + return kVkF3; + case Common::KEYCODE_F4: + return kVkF4; + case Common::KEYCODE_F5: + return kVkF5; + case Common::KEYCODE_F6: + return kVkF6; + case Common::KEYCODE_F7: + return kVkF7; + case Common::KEYCODE_F8: + return kVkF8; + case Common::KEYCODE_F9: + return kVkF9; + case Common::KEYCODE_F10: + return kVkF10; + case Common::KEYCODE_F11: + return kVkF11; + case Common::KEYCODE_F12: + return kVkF12; default: - return (uint32)event->kbd.ascii; + warning("Key not handled: %d '%c'", event->kbd.keycode, event->kbd.keycode); + return event->kbd.keycode; + break; } -} -enum VKeyCodes { - kVkEscape = 27, - kVkSpace = 32, - kVkHome = 36, - kVkLeft = 37, - kVkUp = 38, - kVkRight = 39, - kVkDown = 40, - - kVkF1 = 112, - kVkF2 = 113, - kVkF3 = 114, - kVkF4 = 115, - kVkF5 = 116, - kVkF6 = 117, - kVkF7 = 118, - kVkF8 = 119, - kVkF9 = 120, - kVkF10 = 121, - kVkF11 = 122, - kVkF12 = 123 -}; +} ////////////////////////////////////////////////////////////////////////// Common::KeyCode BaseKeyboardState::vKeyToKeyCode(uint32 vkey) { diff --git a/engines/wintermute/base/base_keyboard_state.h b/engines/wintermute/base/base_keyboard_state.h index c74bd5b0f7..32680b34c1 100644 --- a/engines/wintermute/base/base_keyboard_state.h +++ b/engines/wintermute/base/base_keyboard_state.h @@ -67,7 +67,7 @@ private: bool _currentControl; uint8 *_keyStates; - uint32 keyCodeToVKey(Common::Event *event); + uint32 keyCodeToVKey(Common::Event *event); //TODO, add more mappings Common::KeyCode vKeyToKeyCode(uint32 vkey); //TODO, reimplement using ScummVM-backend }; -- cgit v1.2.3 From 8778603d342da33957cf995dd3547231795b14ba Mon Sep 17 00:00:00 2001 From: Norbert Bajkó Date: Sun, 1 Mar 2015 14:48:34 +0100 Subject: DRASCULA: fix crash/graphic glitch at castle towers Fix bug #5903 DRASCULA-IT: Crash/graphic glitch at castle towers --- engines/drascula/actors.cpp | 7 +++++++ engines/drascula/talk.cpp | 41 ++++++++++++++++++++++++++--------------- 2 files changed, 33 insertions(+), 15 deletions(-) (limited to 'engines') diff --git a/engines/drascula/actors.cpp b/engines/drascula/actors.cpp index 51148bbc05..0c18f513e1 100644 --- a/engines/drascula/actors.cpp +++ b/engines/drascula/actors.cpp @@ -396,6 +396,13 @@ void DrasculaEngine::increaseFrameNum() { curHeight = (int)newHeight; curWidth = (int)newWidth; } + + if ((currentChapter == 5) && (_roomNumber == 45)) { + curY = 0; + curX = 0; + curHeight = 0; + curWidth = 0; + } } void DrasculaEngine::walkDown() { diff --git a/engines/drascula/talk.cpp b/engines/drascula/talk.cpp index ed29dc5fe4..9773ceca5c 100644 --- a/engines/drascula/talk.cpp +++ b/engines/drascula/talk.cpp @@ -379,6 +379,7 @@ void DrasculaEngine::talk(const char *said, const char *filename) { int y_mask_talk = 170; int face; + bool notTowers = !((currentChapter == 5) && (_roomNumber == 45)); if (currentChapter == 6) { if (flags[0] == 0 && _roomNumber == 102) { @@ -434,44 +435,54 @@ void DrasculaEngine::talk(const char *said, const char *filename) { if (currentChapter == 2) copyRect(x_talk_izq[face], y_mask_talk, curX + 8, curY - 1, TALK_WIDTH, TALK_HEIGHT, extraSurface, screenSurface); - else + else if (notTowers) { reduce_hare_chico(x_talk_izq[face], y_mask_talk, curX + (int)((8.0f / 100) * factor_red[MIN(201, curY + curHeight)]), - curY, TALK_WIDTH, TALK_HEIGHT, factor_red[MIN(201, curY + curHeight)], - extraSurface, screenSurface); - + curY, TALK_WIDTH, TALK_HEIGHT, factor_red[MIN(201, curY + curHeight)], + extraSurface, screenSurface); + } updateRefresh(); } else if (trackProtagonist == 1) { if (currentChapter == 2) copyRect(x_talk_dch[face], y_mask_talk, curX + 12, curY, TALK_WIDTH, TALK_HEIGHT, extraSurface, screenSurface); - else + else if (notTowers) { reduce_hare_chico(x_talk_dch[face], y_mask_talk, curX + (int)((12.0f / 100) * factor_red[MIN(201, curY + curHeight)]), curY, TALK_WIDTH, TALK_HEIGHT, factor_red[MIN(201, curY + curHeight)], extraSurface, screenSurface); + } updateRefresh(); } else if (trackProtagonist == 2) { if (currentChapter == 2) copyRect(x_talk_izq[face], y_mask_talk, curX + 12, curY, TALK_WIDTH, TALK_HEIGHT, frontSurface, screenSurface); - else + else if (notTowers) { reduce_hare_chico(x_talk_izq[face], y_mask_talk, - talkOffset + curX + (int)((12.0f / 100) * factor_red[MIN(201, curY + curHeight)]), - curY, TALK_WIDTH, TALK_HEIGHT, factor_red[MIN(201, curY + curHeight)], - frontSurface, screenSurface); + talkOffset + curX + (int)((12.0f / 100) * factor_red[MIN(201, curY + curHeight)]), + curY, TALK_WIDTH, TALK_HEIGHT, factor_red[MIN(201, curY + curHeight)], + frontSurface, screenSurface); + } updateRefresh(); } else if (trackProtagonist == 3) { if (currentChapter == 2) copyRect(x_talk_dch[face], y_mask_talk, curX + 8, curY, TALK_WIDTH, TALK_HEIGHT, frontSurface, screenSurface); - else + else if (notTowers) { reduce_hare_chico(x_talk_dch[face], y_mask_talk, - talkOffset + curX + (int)((8.0f / 100) * factor_red[MIN(201, curY + curHeight)]), - curY, TALK_WIDTH,TALK_HEIGHT, factor_red[MIN(201, curY + curHeight)], - frontSurface, screenSurface); + talkOffset + curX + (int)((8.0f / 100) * factor_red[MIN(201, curY + curHeight)]), + curY, TALK_WIDTH, TALK_HEIGHT, factor_red[MIN(201, curY + curHeight)], + frontSurface, screenSurface); + } updateRefresh(); } - if (!_subtitlesDisabled) - centerText(said, curX, curY); + if (!_subtitlesDisabled) { + if (notTowers) { + centerText(said, curX, curY); + } + else { + centerText(said, 160, 25); + } + } + updateScreen(); updateEvents(); -- cgit v1.2.3 From 43a09925381838efbcd36dadba465cb5cae3eb11 Mon Sep 17 00:00:00 2001 From: norbertbajko Date: Sun, 1 Mar 2015 17:06:20 +0100 Subject: DRASCULA: comment "actors.cpp" Explain #5903 DRASCULA-IT bug fix--- engines/drascula/actors.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/drascula/actors.cpp b/engines/drascula/actors.cpp index 0c18f513e1..849e2ccd24 100644 --- a/engines/drascula/actors.cpp +++ b/engines/drascula/actors.cpp @@ -396,7 +396,10 @@ void DrasculaEngine::increaseFrameNum() { curHeight = (int)newHeight; curWidth = (int)newWidth; } - + + // Fix bug #5903 DRASCULA-IT: Crash/graphic glitch at castle towers + // Chapter 5 Room 45 is the castle tower part + // Fixing the character's coordinate(0,0) in the tower section to prevent out of window coordinates and crash if ((currentChapter == 5) && (_roomNumber == 45)) { curY = 0; curX = 0; -- cgit v1.2.3 From 0abf6d72b0ca15a81518190cb2040eb798754ebd Mon Sep 17 00:00:00 2001 From: norbertbajko Date: Sun, 1 Mar 2015 17:16:54 +0100 Subject: DRASCULA: comment "talk.cpp" Explain #5903 DRASCULA-IT bug fix--- engines/drascula/talk.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'engines') diff --git a/engines/drascula/talk.cpp b/engines/drascula/talk.cpp index 9773ceca5c..6e0dd2a011 100644 --- a/engines/drascula/talk.cpp +++ b/engines/drascula/talk.cpp @@ -379,6 +379,10 @@ void DrasculaEngine::talk(const char *said, const char *filename) { int y_mask_talk = 170; int face; + + // Fix bug #5903 DRASCULA-IT: Crash/graphic glitch at castle towers + // Chapter 5 Room 45 is the castle tower part + // We use this variable as a condition below because at the castle towers we don't want to draw out the head bool notTowers = !((currentChapter == 5) && (_roomNumber == 45)); if (currentChapter == 6) { -- cgit v1.2.3 From bcf2e8204c481d9c4df17786e16591c100eb6c82 Mon Sep 17 00:00:00 2001 From: norbertbajko Date: Sun, 1 Mar 2015 17:23:28 +0100 Subject: DRASCULA: comment "talk.cpp" Explain #5903 DRASCULA-IT bug fix--- engines/drascula/talk.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'engines') diff --git a/engines/drascula/talk.cpp b/engines/drascula/talk.cpp index 6e0dd2a011..e9fec868f8 100644 --- a/engines/drascula/talk.cpp +++ b/engines/drascula/talk.cpp @@ -478,6 +478,8 @@ void DrasculaEngine::talk(const char *said, const char *filename) { updateRefresh(); } + // Fix bug #5903 DRASCULA-IT: Crash/graphic glitch at castle towers + // Without the head we have to fix the subtitle's coordinates(upper-center) at the tower section if (!_subtitlesDisabled) { if (notTowers) { centerText(said, curX, curY); -- cgit v1.2.3 From e664e9167a599e1e8ac7d8bb8f5349547fb49832 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 1 Mar 2015 18:21:39 -0500 Subject: MADS: Fix display of teleporter values with leading zeroes --- engines/mads/nebular/nebular_scenes.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes.cpp b/engines/mads/nebular/nebular_scenes.cpp index b5e2491624..0019118593 100644 --- a/engines/mads/nebular/nebular_scenes.cpp +++ b/engines/mads/nebular/nebular_scenes.cpp @@ -451,7 +451,10 @@ void SceneTeleporter::teleporterHandleKey() { _curCode *= 10; _curCode += _buttonTyped; _digitCount++; - _msgText = Common::String::format("%d", _curCode); + + Common::String format = "%01d"; + format.setChar('0' + _digitCount, 2); + _msgText = Common::String::format(format.c_str(), _curCode); if (_digitCount < 4) _msgText += "_"; -- cgit v1.2.3 From aef874cf50da10f4c18ba450648ac7b84224d710 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 1 Mar 2015 19:05:47 -0500 Subject: MADS: Fix animation of hand typing code in teleporter --- engines/mads/nebular/nebular_scenes.cpp | 2 +- engines/mads/nebular/nebular_scenes1.cpp | 16 +++---- engines/mads/nebular/nebular_scenes2.cpp | 44 +++++++++--------- engines/mads/nebular/nebular_scenes3.cpp | 68 ++++++++++++++-------------- engines/mads/nebular/nebular_scenes4.cpp | 46 +++++++++---------- engines/mads/nebular/nebular_scenes5.cpp | 54 +++++++++++----------- engines/mads/nebular/nebular_scenes6.cpp | 78 ++++++++++++++++---------------- engines/mads/nebular/nebular_scenes7.cpp | 30 ++++++------ engines/mads/nebular/nebular_scenes8.cpp | 32 ++++++------- engines/mads/sequence.cpp | 6 +-- engines/mads/sequence.h | 4 +- 11 files changed, 190 insertions(+), 190 deletions(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes.cpp b/engines/mads/nebular/nebular_scenes.cpp index 0019118593..72073b1c7b 100644 --- a/engines/mads/nebular/nebular_scenes.cpp +++ b/engines/mads/nebular/nebular_scenes.cpp @@ -432,7 +432,7 @@ void SceneTeleporter::teleporterHandleKey() { case 0: { _game._player._stepEnabled = false; Common::Point msgPos = teleporterComputeLocation(); - _handSequenceId = _scene->_sequences.startReverseCycle(_handSpriteId, false, 4, 2, 0, 0); + _handSequenceId = _scene->_sequences.startPingPongCycle(_handSpriteId, false, 4, 2, 0, 0); _scene->_sequences.setPosition(_handSequenceId, msgPos); _scene->_sequences.setDepth(_handSequenceId, 2); _scene->_sequences.addSubEntry(_handSequenceId, SEQUENCE_TRIGGER_LOOP, 0, 1); diff --git a/engines/mads/nebular/nebular_scenes1.cpp b/engines/mads/nebular/nebular_scenes1.cpp index 3149343aee..f21ab94bcb 100644 --- a/engines/mads/nebular/nebular_scenes1.cpp +++ b/engines/mads/nebular/nebular_scenes1.cpp @@ -134,7 +134,7 @@ void Scene101::sayDang() { switch (_game._trigger) { case 0: _scene->_sequences.remove(_globals._sequenceIndexes[11]); - _globals._sequenceIndexes[11] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[11], false, 3, 6, 0, 0); + _globals._sequenceIndexes[11] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[11], false, 3, 6, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[11], 17, 21); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[11], SEQUENCE_TRIGGER_EXPIRE, 0, 72); _vm->_sound->command(17); @@ -696,7 +696,7 @@ void Scene102::enter() { _globals._spriteIndexes[11] = _scene->_sprites.addSprites("*RXMRC_8"); _globals._spriteIndexes[13] = _scene->_sprites.addSprites(formAnimName('x', 0)); - _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 8, 0, 0, 0); + _globals._sequenceIndexes[1] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[1], false, 8, 0, 0, 0); _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 170, 0, 1, 6); _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 11, 0, 2, 3); _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 4, 0, 1, 0); @@ -1201,7 +1201,7 @@ void Scene102::actions() { if (_action.isAction(VERB_TAKE, NOUN_BINOCULARS) && _game._objects.isInRoom(OBJ_BINOCULARS)) { switch (_game._trigger) { case 0: - _globals._sequenceIndexes[11] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[11], false, 3, 1, 0, 0); + _globals._sequenceIndexes[11] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[11], false, 3, 1, 0, 0); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[11]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[11], SEQUENCE_TRIGGER_EXPIRE, 0, 1); _game._player._visible = false; @@ -1433,7 +1433,7 @@ void Scene103::actions() { switch (_vm->_game->_trigger) { case 0: _scene->changeVariant(1); - _globals._sequenceIndexes[13] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[13], false, 3, 2); + _globals._sequenceIndexes[13] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[13], false, 3, 2); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[13]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_SPRITE, 7, 1); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 2); @@ -1463,7 +1463,7 @@ void Scene103::actions() { switch (_vm->_game->_trigger) { case 0: _scene->changeVariant(1); - _globals._sequenceIndexes[12] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[12], false, 3, 2); + _globals._sequenceIndexes[12] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[12], false, 3, 2); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[12]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_SPRITE, 6, 1); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_EXPIRE, 0, 2); @@ -2010,7 +2010,7 @@ void Scene106::enter() { } _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('G', -1)); - _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 21, 0, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], false, 21, 0, 0, 0); _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('I', -1)); _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 6, 0, 32, 47); @@ -2503,7 +2503,7 @@ void Scene109::enter() { _globals._spriteIndexes[10] = _scene->_sprites.addSprites(Resources::formatName(105, 'F', 1, EXT_SS, "")); _globals._spriteIndexes[9] = _scene->_sprites.addSprites(formAnimName('H', 1)); - _globals._sequenceIndexes[10] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[10], true, 4, 0, 0, 0); + _globals._sequenceIndexes[10] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[10], true, 4, 0, 0, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 5); _scene->_sequences.setPosition(_globals._sequenceIndexes[10], Common::Point(126, 39)); _scene->_sequences.setMotion(_globals._sequenceIndexes[10], 0, 200, 0); @@ -2676,7 +2676,7 @@ void Scene109::actions() { case 2: if (_hoovicDifficultFl) - _globals._sequenceIndexes[8] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[8], false, 4, 2, 0, 0); + _globals._sequenceIndexes[8] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[8], false, 4, 2, 0, 0); else _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 4, 1, 0, 0); diff --git a/engines/mads/nebular/nebular_scenes2.cpp b/engines/mads/nebular/nebular_scenes2.cpp index 3eef545b09..b8629a3915 100644 --- a/engines/mads/nebular/nebular_scenes2.cpp +++ b/engines/mads/nebular/nebular_scenes2.cpp @@ -556,7 +556,7 @@ void Scene202::step() { case 90: _vm->_sound->command(41); _scene->_sequences.remove(_globals._sequenceIndexes[10]); - _globals._sequenceIndexes[9] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[9], true, 6, 1, 0, 0); + _globals._sequenceIndexes[9] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[9], true, 6, 1, 0, 0); _scene->_sequences.setPosition(_globals._sequenceIndexes[9], Common::Point(247, 82)); _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 1); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 0, 91); @@ -811,7 +811,7 @@ void Scene202::actions() { } else { _game._player._stepEnabled = false; _game._player._visible = false; - _globals._sequenceIndexes[7] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[7], false, 3, 2, 0, 0); + _globals._sequenceIndexes[7] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[7], false, 3, 2, 0, 0); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[7]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_SPRITE, 6, 1); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 2); @@ -1502,7 +1502,7 @@ void Scene207::enter() { _spiderFl = (var2 & 1); if (_vultureFl) { - _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 30, 0, 0, 400); + _globals._sequenceIndexes[1] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[1], false, 30, 0, 0, 400); _vultureHotspotId = _scene->_dynamicHotspots.add(389, 13, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); _scene->_dynamicHotspots.setPosition(_vultureHotspotId, Common::Point(254, 94), FACING_WEST); } @@ -2164,7 +2164,7 @@ void Scene209::handleLookRight() { switch (_game._trigger) { case 151: _scene->_sequences.remove(_globals._sequenceIndexes[3]); - _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 8, 2, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 8, 2, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 8, 14); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 152); break; @@ -2231,7 +2231,7 @@ void Scene209::handleGetBinoculars() { case 162: { int oldIdx = _globals._sequenceIndexes[3]; - _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 8, 6, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 8, 6, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 23, 25); _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 163); @@ -2240,7 +2240,7 @@ void Scene209::handleGetBinoculars() { case 163: { int oldIdx = _globals._sequenceIndexes[3]; - _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 8, 0, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 8, 0, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 23, 24); _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); _scene->_sequences.addTimer(8, 164); @@ -2264,7 +2264,7 @@ void Scene209::handleBinocularBlink() { case 167: { int oldIdx = _globals._sequenceIndexes[3]; _scene->_sequences.remove(_globals._sequenceIndexes[3]); - _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 8, 2, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 8, 2, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 23, 25); _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 168); @@ -2273,7 +2273,7 @@ void Scene209::handleBinocularBlink() { case 168: { int oldIdx = _globals._sequenceIndexes[3]; - _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 8, 0, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 8, 0, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 23, 24); _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); _scene->_sequences.addTimer(30, 169); @@ -2293,7 +2293,7 @@ void Scene209::handleBinocularScan() { case 171: { int oldIdx = _globals._sequenceIndexes[3]; _scene->_sequences.remove(_globals._sequenceIndexes[3]); - _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 12, 2, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 12, 2, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 43, 45); _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 172); @@ -2305,10 +2305,10 @@ void Scene209::handleBinocularScan() { int randAction = _vm->getRandomNumber(1,2); switch (randAction) { case 1: - _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 12, 2, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 12, 2, 0, 0); break; case 2: - _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 12, 4, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 12, 4, 0, 0); break; } _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 23, 25); @@ -2319,7 +2319,7 @@ void Scene209::handleBinocularScan() { case 173: { int oldIdx = _globals._sequenceIndexes[3]; - _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 12, 2, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 12, 2, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 26, 30); _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 174); @@ -2328,7 +2328,7 @@ void Scene209::handleBinocularScan() { case 174: { int oldIdx = _globals._sequenceIndexes[3]; - _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 12, 0, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 12, 0, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 23, 24); _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); _scene->_sequences.addTimer(60, 175); @@ -2414,7 +2414,7 @@ void Scene209::handleTongue() { case 185: { _vm->_sound->command(18); int oldIdx = _globals._sequenceIndexes[3]; - _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 6, 20, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 6, 20, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 38, 39); _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 186); @@ -2534,7 +2534,7 @@ void Scene209::handleMonkeyEating() { case 200: { int oldIdx = _globals._sequenceIndexes[4]; - _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 10, 10, 0, 0); + _globals._sequenceIndexes[4] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[4], false, 10, 10, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 15, 16); _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], oldIdx); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 201); @@ -2563,14 +2563,14 @@ void Scene209::handleMonkeyEating() { case 204: _scene->_sequences.remove(_globals._sequenceIndexes[4]); - _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 10, 8, 0, 0); + _globals._sequenceIndexes[4] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[4], false, 10, 8, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 18, 19); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 205); break; case 205: { int oldIdx = _globals._sequenceIndexes[4]; - _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 10, 8, 0, 0); + _globals._sequenceIndexes[4] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[4], false, 10, 8, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 20, 21); _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], oldIdx); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 206); @@ -2595,7 +2595,7 @@ void Scene209::handleMonkeyEating() { _scene->_kernelMessages.setQuoted(msgIndex, 4, true); int oldIdx = _globals._sequenceIndexes[4]; - _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 15, 4, 0, 0); + _globals._sequenceIndexes[4] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[4], false, 15, 4, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 26, 27); _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], oldIdx); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 208); @@ -2605,7 +2605,7 @@ void Scene209::handleMonkeyEating() { case 208: { _scene->_kernelMessages.add(Common::Point(180, 39), 0xFDFC, 0, 0, 90, _game.getQuote(131)); int oldIdx = _globals._sequenceIndexes[4]; - _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 10, 4, 0, 0); + _globals._sequenceIndexes[4] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[4], false, 10, 4, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 28, 29); _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], oldIdx); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 209); @@ -3448,7 +3448,7 @@ void Scene209::actions() { _globals._spriteIndexes[11] = _scene->_sprites.addSprites("*RXMBD_2"); _game._player._stepEnabled = false; _game._player._visible = false; - _globals._sequenceIndexes[11] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[11], false, 3, 2, 0, 0); + _globals._sequenceIndexes[11] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[11], false, 3, 2, 0, 0); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[11]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[11], SEQUENCE_TRIGGER_SPRITE, 4, 1); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[11], SEQUENCE_TRIGGER_EXPIRE, 0, 2); @@ -3480,7 +3480,7 @@ void Scene209::actions() { _globals._spriteIndexes[10] = _scene->_sprites.addSprites("*RXMBD_8"); _game._player._stepEnabled = false; _game._player._visible = false; - _globals._sequenceIndexes[10] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[10], false, 3, 2, 0, 0); + _globals._sequenceIndexes[10] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[10], false, 3, 2, 0, 0); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[10]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[10], SEQUENCE_TRIGGER_SPRITE, 4, 1); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[10], SEQUENCE_TRIGGER_EXPIRE, 0, 2); @@ -5297,7 +5297,7 @@ void Scene215::actions() { if (_globals[kSexOfRex] == REX_MALE) { _game._player._visible = false; _game._player._stepEnabled = false; - _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 6, 2, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], false, 6, 2, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 4); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_LOOP, 0, 1); diff --git a/engines/mads/nebular/nebular_scenes3.cpp b/engines/mads/nebular/nebular_scenes3.cpp index bcedf95a27..478a733485 100644 --- a/engines/mads/nebular/nebular_scenes3.cpp +++ b/engines/mads/nebular/nebular_scenes3.cpp @@ -370,7 +370,7 @@ void Scene304::enter() { _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('a', 1)); _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('b', 0)); - _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 150, 0, 3, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 150, 0, 3, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 2); _vm->_palette->setEntry(252, 45, 63, 45); _vm->_palette->setEntry(253, 20, 45, 20); @@ -953,7 +953,7 @@ void Scene307::actions() { case 2: { int oldIdx = _globals._sequenceIndexes[5]; - _globals._sequenceIndexes[5] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[5], false, 12, 6, 0, 0); + _globals._sequenceIndexes[5] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[5], false, 12, 6, 0, 0); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 2, 3); _scene->_sequences.updateTimeout(_globals._sequenceIndexes[5], oldIdx); @@ -1245,7 +1245,7 @@ void Scene308::step() { switch (_game._trigger) { case 70: { _scene->_sequences.remove(_globals._sequenceIndexes[3]); - _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 18, 9, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 18, 9, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 2, 3); _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 9); _scene->_kernelMessages.reset(); @@ -1266,7 +1266,7 @@ void Scene308::step() { case 72: _scene->_sequences.remove(_globals._sequenceIndexes[3]); - _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 20, 5, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 20, 5, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 3, 4); _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 9); _scene->_kernelMessages.reset(); @@ -1284,7 +1284,7 @@ void Scene308::step() { case 74: { _scene->_sequences.remove(_globals._sequenceIndexes[3]); - _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 20, 8, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 20, 8, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 6, 7); _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 9); _scene->_kernelMessages.reset(); @@ -1306,7 +1306,7 @@ void Scene308::step() { case 76: { int seqIdx = _globals._sequenceIndexes[3]; - _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 26, 0, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 26, 0, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 2, 3); _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 9); _scene->_kernelMessages.reset(); @@ -1441,7 +1441,7 @@ void Scene309::step() { case 70: { int idx = _scene->_dynamicHotspots.add(689, 690, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0)); _scene->_dynamicHotspots.setPosition(idx, Common::Point(142, 146), FACING_NORTHEAST); - _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 7, 4, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 7, 4, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 2, 3); _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 11); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 71); @@ -1462,7 +1462,7 @@ void Scene309::step() { case 72: { int _oldIdx = _globals._sequenceIndexes[3]; - _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 7, 8, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 7, 8, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 8, 11); _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 11); _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], _oldIdx); @@ -1484,7 +1484,7 @@ void Scene309::step() { case 74: { int _oldIdx = _globals._sequenceIndexes[3]; - _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 7, 6, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 7, 6, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 21, 23); _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 11); _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], _oldIdx); @@ -1494,7 +1494,7 @@ void Scene309::step() { case 75: { int _oldIdx = _globals._sequenceIndexes[3]; - _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 12, 6, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 12, 6, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 24, 25); _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], _oldIdx); _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 11); @@ -1513,7 +1513,7 @@ void Scene309::step() { break; case 77: { - _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 90, 0, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 90, 0, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 29, 30); _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 11); int idx = _scene->_kernelMessages.add(Common::Point(15, 46), 0xFDFC, 0, 0, 120, _game.getQuote(247)); @@ -1965,7 +1965,7 @@ void Scene316::handleRexInGrate() { case 1: _scene->_sequences.setDone(_globals._sequenceIndexes[4]); - _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 12, 3, 0, 0); + _globals._sequenceIndexes[4] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[4], false, 12, 3, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 2, 3); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 2); @@ -2085,7 +2085,7 @@ void Scene316::handleRoxInGrate() { case 1: _scene->_sequences.setDone(_globals._sequenceIndexes[5]); - _globals._sequenceIndexes[5] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[5], false, 17, 3, 0, 0); + _globals._sequenceIndexes[5] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[5], false, 17, 3, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 2, 3); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 2); @@ -2523,7 +2523,7 @@ void Scene318::handleDialog() { case 0x19C: case 0x19D: _scene->_sequences.remove(_globals._sequenceIndexes[2]); - _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(142, 121)); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 6, 8); @@ -2883,7 +2883,7 @@ void Scene318::actions() { case 0: _game._player._stepEnabled = false; _scene->_sequences.remove(_globals._sequenceIndexes[2]); - _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 8, 2, 0, 80); + _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], false, 8, 2, 0, 80); _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(142, 121)); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 2, 5); @@ -3588,7 +3588,7 @@ void Scene320::setLeftView(int view) { _scene->_sequences.remove(_globals._sequenceIndexes[0]); if (view != 10) { - _globals._sequenceIndexes[0] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[view], false, 6, 0, 0, 18); + _globals._sequenceIndexes[0] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[view], false, 6, 0, 0, 18); _scene->_sequences.setDepth(_globals._sequenceIndexes[0], 0); if (!_blinkFl) _scene->_sequences.setAnimRange(_globals._sequenceIndexes[0], 2, 2); @@ -3752,7 +3752,7 @@ void Scene320::actions() { case 0: _game._player._stepEnabled = false; handleButtons(); - _globals._sequenceIndexes[18] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[18], _flippedFl, 4, 2, 0, 0); + _globals._sequenceIndexes[18] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[18], _flippedFl, 4, 2, 0, 0); _scene->_sequences.setScale(_globals._sequenceIndexes[18], 60); _scene->_sequences.setPosition(_globals._sequenceIndexes[18], Common::Point(_posX, 170)); _scene->_sequences.setDepth(_globals._sequenceIndexes[18], 0); @@ -4053,12 +4053,12 @@ void Scene351::actions() { _game._player._stepEnabled = false; _game._player._visible = false; if (_globals[kSexOfRex] == REX_FEMALE) { - _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 5, 2, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], false, 5, 2, 0, 0); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 5, 1); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2); } else { - _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 5, 2, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 5, 2, 0, 0); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_SPRITE, 6, 1); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 2); @@ -4160,12 +4160,12 @@ void Scene352::putArmDown(bool corridorExit, bool doorwayExit) { _game._player._stepEnabled = false; _game._player._visible = false; if (_globals[kSexOfRex] == REX_FEMALE) { - _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 5, 2, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 5, 2, 0, 0); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_SPRITE, 5, 2); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 3); } else { - _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 5, 2, 0, 0); + _globals._sequenceIndexes[4] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[4], false, 5, 2, 0, 0); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_SPRITE, 6, 2); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 3); @@ -4305,7 +4305,7 @@ void Scene352::preActions() { _game._player._stepEnabled = false; _scene->_sequences.remove(_commonSequenceIdx); _vm->_sound->command(20); - _commonSequenceIdx = _scene->_sequences.startReverseCycle(_commonSpriteIndex, false, 6, 1, 0, 0); + _commonSequenceIdx = _scene->_sequences.startPingPongCycle(_commonSpriteIndex, false, 6, 1, 0, 0); _scene->_sequences.addSubEntry(_commonSequenceIdx, SEQUENCE_TRIGGER_EXPIRE, 0, 1); _scene->_sequences.setDepth(_commonSequenceIdx, 15); } @@ -4364,7 +4364,7 @@ void Scene352::actions() { case 1: { _vm->_sound->command(21); - _globals._sequenceIndexes[12] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[12], false, 7, 2, 20, 0); + _globals._sequenceIndexes[12] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[12], false, 7, 2, 20, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[12], FACING_NORTH); int oldIdx = _commonSequenceIdx; _commonSequenceIdx = _scene->_sequences.startCycle(_commonSpriteIndex, false, -2); @@ -4376,7 +4376,7 @@ void Scene352::actions() { case 2: _vm->_sound->command(22); _scene->_sequences.remove(_commonSequenceIdx); - _commonSequenceIdx = _scene->_sequences.startReverseCycle(_commonSpriteIndex, false, 8, 1, 0, 0); + _commonSequenceIdx = _scene->_sequences.startPingPongCycle(_commonSpriteIndex, false, 8, 1, 0, 0); _scene->_sequences.setAnimRange(_commonSequenceIdx, 1, 3); _scene->_sequences.addSubEntry(_commonSequenceIdx, SEQUENCE_TRIGGER_EXPIRE, 0, 3); break; @@ -4431,12 +4431,12 @@ void Scene352::actions() { _game._player._stepEnabled = false; _game._player._visible = false; if (_globals[kSexOfRex] == REX_FEMALE) { - _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 5, 2, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 5, 2, 0, 0); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_SPRITE, 5, 1); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 2); } else { - _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 5, 2, 0, 0); + _globals._sequenceIndexes[4] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[4], false, 5, 2, 0, 0); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_SPRITE, 6, 1); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 2); @@ -4478,7 +4478,7 @@ void Scene352::actions() { case 1: { _vm->_sound->command(21); - _globals._sequenceIndexes[12] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[12], false, 7, 2, 20, 0); + _globals._sequenceIndexes[12] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[12], false, 7, 2, 20, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[12], 8); int oldIdx = _commonSequenceIdx; _commonSequenceIdx = _scene->_sequences.startCycle(_commonSpriteIndex, false, -2); @@ -4490,7 +4490,7 @@ void Scene352::actions() { case 2: _vm->_sound->command(23); _scene->_sequences.remove(_commonSequenceIdx); - _commonSequenceIdx = _scene->_sequences.startReverseCycle(_commonSpriteIndex, false, 8, 1, 0, 0); + _commonSequenceIdx = _scene->_sequences.startPingPongCycle(_commonSpriteIndex, false, 8, 1, 0, 0); _scene->_sequences.setAnimRange(_commonSequenceIdx, 1, 4); _scene->_sequences.addSubEntry(_commonSequenceIdx, SEQUENCE_TRIGGER_EXPIRE, 0, 3); break; @@ -4545,13 +4545,13 @@ void Scene352::actions() { _game._player._stepEnabled = false; _game._player._visible = false; if (_globals[kSexOfRex] == REX_MALE) { - _globals._sequenceIndexes[14] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[14], false, 8, 1, 0, 0); + _globals._sequenceIndexes[14] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[14], false, 8, 1, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[14], 1, 2); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[14]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[14], SEQUENCE_TRIGGER_SPRITE, 2, 1); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[14], SEQUENCE_TRIGGER_EXPIRE, 0, 2); } else { - _globals._sequenceIndexes[15] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[15], false, 8, 1, 0, 0); + _globals._sequenceIndexes[15] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[15], false, 8, 1, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[15], 1, 2); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[15]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[15], SEQUENCE_TRIGGER_SPRITE, 2, 1); @@ -4592,12 +4592,12 @@ void Scene352::actions() { _game._player._stepEnabled = false; _game._player._visible = false; if (_globals[kSexOfRex] == REX_MALE) { - _globals._sequenceIndexes[6] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[6], true, 6, 2, 0, 0); + _globals._sequenceIndexes[6] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[6], true, 6, 2, 0, 0); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[6]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_SPRITE, 6, 1); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 2); } else { - _globals._sequenceIndexes[7] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[7], true, 6, 2, 0, 0); + _globals._sequenceIndexes[7] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[7], true, 6, 2, 0, 0); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[7]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_SPRITE, 6, 1); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 2); @@ -4980,12 +4980,12 @@ void Scene359::actions() { _game._player._visible = false; _vm->_dialogs->show(35920); if (_globals[kSexOfRex] == REX_MALE) { - _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 4, 2, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], false, 4, 2, 0, 0); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 6, 1); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2); } else { - _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], true, 7, 2, 0, 0); + _globals._sequenceIndexes[4] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[4], true, 7, 2, 0, 0); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(106, 110)); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_SPRITE, 6, 1); diff --git a/engines/mads/nebular/nebular_scenes4.cpp b/engines/mads/nebular/nebular_scenes4.cpp index 56f6fb4466..8a9e510591 100644 --- a/engines/mads/nebular/nebular_scenes4.cpp +++ b/engines/mads/nebular/nebular_scenes4.cpp @@ -962,7 +962,7 @@ void Scene402::step() { } if (!_bartenderTalking) { - _globals._sequenceIndexes[10] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[10], false, 7, 0, 0, 0); + _globals._sequenceIndexes[10] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[10], false, 7, 0, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[10], 3, 4); _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 8); int idx = _scene->_dynamicHotspots.add(NOUN_BARTENDER, VERB_WALKTO, _globals._sequenceIndexes[10], Common::Rect(0, 0, 0, 0)); @@ -1514,7 +1514,7 @@ void Scene402::step() { break; case 3: - _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 12, 2, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 12, 2, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 4, 5); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 32); _rightWomanMoving = true; @@ -1697,7 +1697,7 @@ void Scene402::step() { _scene->_kernelMessages.add(Common::Point(171, 47), 0xFBFA, 0, 0, 130, _game.getQuote(0x200)); _scene->_sequences.addTimer(150, 63); _scene->_sequences.remove(_globals._sequenceIndexes[13]); - _globals._sequenceIndexes[13] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[13], false, 30, 4, 0, 0); + _globals._sequenceIndexes[13] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[13], false, 30, 4, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 10, 11); _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 62); @@ -1769,7 +1769,7 @@ void Scene402::step() { case 69: { int seqIdx = _globals._sequenceIndexes[13]; - _globals._sequenceIndexes[13] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[13], false, 25, 4, 0, 0); + _globals._sequenceIndexes[13] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[13], false, 25, 4, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 10, 11); _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], seqIdx); @@ -1783,7 +1783,7 @@ void Scene402::step() { break; case 70: - _globals._sequenceIndexes[13] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[13], false, 25, 4, 0, 0); + _globals._sequenceIndexes[13] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[13], false, 25, 4, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 10, 12); _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 72); @@ -1840,7 +1840,7 @@ void Scene402::step() { _cutSceneReady = false; _helgaReady = false; _scene->_sequences.remove(_globals._sequenceIndexes[13]); - _globals._sequenceIndexes[13] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[13], false, 15, 2, 0, 0); + _globals._sequenceIndexes[13] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[13], false, 15, 2, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 11, 13); _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 26); @@ -1860,7 +1860,7 @@ void Scene402::step() { _cutSceneReady = false; _helgaReady = false; _scene->_sequences.remove(_globals._sequenceIndexes[13]); - _globals._sequenceIndexes[13] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[13], false, 15, 2, 0, 0); + _globals._sequenceIndexes[13] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[13], false, 15, 2, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 14, 15); _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 26); @@ -2069,7 +2069,7 @@ void Scene402::actions() { if (_game._trigger == 0) { _game._player._stepEnabled = false; _game._player._visible = false; - _globals._sequenceIndexes[21] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[21], false, 7, 2, 0, 0); + _globals._sequenceIndexes[21] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[21], false, 7, 2, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[21], 1, 2); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[21]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[21], SEQUENCE_TRIGGER_SPRITE, 2, 165); @@ -2202,7 +2202,7 @@ void Scene402::actions() { _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; _game._player._stepEnabled = false; _game._player._visible = false; - _globals._sequenceIndexes[22] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[22], false, 7, 2, 0, 0); + _globals._sequenceIndexes[22] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[22], false, 7, 2, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[22], 1, 2); _scene->_sequences.setPosition(_globals._sequenceIndexes[22], Common::Point(_game._player._playerPos.x, _game._player._playerPos.y + 1)); _scene->_sequences.setDepth(_globals._sequenceIndexes[22], 5); @@ -2445,7 +2445,7 @@ void Scene405::step() { if (_game._trigger == 70) { _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount ; _game._player._visible = true; - _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0); + _globals._sequenceIndexes[1] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 71); _vm->_sound->command(19); } @@ -2495,7 +2495,7 @@ void Scene405::actions() { _game._player._stepEnabled = false; _game._player._visible = false; _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; - _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 7, 2, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 7, 2, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 2); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 75); Common::Point msgPos = Common::Point(_game._player._playerPos.x, _game._player._playerPos.y + 1); @@ -2505,7 +2505,7 @@ void Scene405::actions() { _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; _game._player._stepEnabled = false; _game._player._visible = false; - _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 7, 2, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 7, 2, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 2); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 70); _scene->_sequences.setPosition(_globals._sequenceIndexes[3], _game._player._playerPos); @@ -2514,7 +2514,7 @@ void Scene405::actions() { _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; _game._player._stepEnabled = false; _game._player._visible = false; - _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 7, 2, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 7, 2, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 2); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 80); _scene->_sequences.setPosition(_globals._sequenceIndexes[3], _game._player._playerPos); @@ -2609,7 +2609,7 @@ void Scene406::enter() { else { _game._player._stepEnabled = false; _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; - _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 3, 1, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 3, 1, 0, 0); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 90); _vm->_sound->command(19); } @@ -2647,7 +2647,7 @@ void Scene406::step() { if (_game._trigger == 70) { _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount; _game._player._visible = true; - _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 4, 1, 0, 0); + _globals._sequenceIndexes[1] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[1], false, 4, 1, 0, 0); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 71); _vm->_sound->command(19); } @@ -2703,7 +2703,7 @@ void Scene406::actions() { _game._player._stepEnabled = false; _game._player._visible = false; _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; - _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 7, 2, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], false, 7, 2, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 2); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 75); Common::Point msgPos = Common::Point(_game._player._playerPos.x, _game._player._playerPos.y + 1); @@ -2713,7 +2713,7 @@ void Scene406::actions() { _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; _game._player._stepEnabled = false; _game._player._visible = false; - _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 7, 2, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], false, 7, 2, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 2); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 70); Common::Point msgPos = Common::Point(_game._player._playerPos.x, _game._player._playerPos.y + 1); @@ -2723,7 +2723,7 @@ void Scene406::actions() { _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; _game._player._stepEnabled = false; _game._player._visible = false; - _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 7, 2, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], false, 7, 2, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 2); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 110); _scene->_sequences.setPosition(_globals._sequenceIndexes[2], _game._player._playerPos); @@ -2934,7 +2934,7 @@ void Scene408::actions() { _vm->_sound->command(57); _game._player._stepEnabled = false; _game._player._visible = false; - _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], true, 7, 2, 0, 0); + _globals._sequenceIndexes[1] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[1], true, 7, 2, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 1, 2); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[1]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_SPRITE, 2, 1); @@ -3182,7 +3182,7 @@ void Scene410::actions() { _vm->_sound->command(57); _game._player._stepEnabled = false; _game._player._visible = false; - _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 7, 2, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], false, 7, 2, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 3); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 3, 1); @@ -3842,7 +3842,7 @@ void Scene411::actions() { _vm->_sound->command(57); _game._player._stepEnabled = false; _game._player._visible = false; - _globals._sequenceIndexes[8] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[8], false, 7, 2, 0, 0); + _globals._sequenceIndexes[8] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[8], false, 7, 2, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[8], 1, 2); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[8]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_SPRITE, 2, 1); @@ -3879,7 +3879,7 @@ void Scene411::actions() { _vm->_sound->command(57); _game._player._stepEnabled = false; _game._player._visible = false; - _globals._sequenceIndexes[8] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[8], false, 7, 2, 0, 0); + _globals._sequenceIndexes[8] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[8], false, 7, 2, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[8], 1, 2); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[8]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_SPRITE, 2, 1); @@ -4078,7 +4078,7 @@ void Scene413::enter() { case 1: _vm->_sound->command(30); _game._player._visible = false; - _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 7, 1, 0, 0); + _globals._sequenceIndexes[1] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[1], false, 7, 1, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 1, 19); _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 8); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 76); diff --git a/engines/mads/nebular/nebular_scenes5.cpp b/engines/mads/nebular/nebular_scenes5.cpp index 66d8294fc6..fe15fe0636 100644 --- a/engines/mads/nebular/nebular_scenes5.cpp +++ b/engines/mads/nebular/nebular_scenes5.cpp @@ -132,7 +132,7 @@ void Scene501::handleSlotActions() { frameIndex = 2; } - _mainSequenceId = _scene->_sequences.startReverseCycle(_mainSpriteId, false, numTicks, 1, 0, 0); + _mainSequenceId = _scene->_sequences.startPingPongCycle(_mainSpriteId, false, numTicks, 1, 0, 0); _scene->_sequences.setAnimRange(_mainSequenceId, 1, frameIndex); _scene->_sequences.setMsgLayout(_mainSequenceId); _vm->_sound->command(10); @@ -238,7 +238,7 @@ void Scene501::step() { break; case 82: - _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 9, 1, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 9, 1, 0, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 7); _vm->_sound->command(12); _doorHotspotid = _scene->_dynamicHotspots.add(NOUN_DOOR, VERB_WALK_THROUGH, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0)); @@ -273,7 +273,7 @@ void Scene501::step() { case 72: _scene->_sequences.remove(_globals._sequenceIndexes[2]); - _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 73); break; @@ -415,7 +415,7 @@ void Scene501::actions() { case 7: { _vm->_sound->command(12); int syncIdx = _globals._sequenceIndexes[3]; - _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 9, 1, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 9, 1, 0, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 7); _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], syncIdx); _vm->_sound->command(12); @@ -581,13 +581,13 @@ void Scene503::actions() { _game._player._stepEnabled = false; _game._player._visible = false; if (_globals[kSexOfRex] == REX_MALE) { - _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 3); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 3, 1); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2); } else { - _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], true, 8, 1, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], true, 8, 1, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 4); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_SPRITE, 4, 1); @@ -800,7 +800,7 @@ void Scene504::actions() { case 1: { int syncIdx = _globals._sequenceIndexes[3]; - _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 6, 1, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 6, 1, 0, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 13); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 6); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 2); @@ -913,7 +913,7 @@ void Scene505::enter() { _globals._spriteIndexes[12] = _scene->_sprites.addSprites(formAnimName('e', -1)); if (_scene->_priorSceneId != -2) - _globals._sequenceIndexes[12] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[12], false, 6, 1, 0, 0); + _globals._sequenceIndexes[12] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[12], false, 6, 1, 0, 0); _globals._sequenceIndexes[13] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[13], false, 6, 1, 120, 0); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 60); @@ -996,7 +996,7 @@ void Scene505::step() { _scene->_sequences.remove(_globals._sequenceIndexes[1]); _scene->_sequences.remove(_globals._sequenceIndexes[0]); _scene->_sequences.remove(_globals._sequenceIndexes[13]); - _globals._sequenceIndexes[13] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[13], false, 6, 1, 0, 0); + _globals._sequenceIndexes[13] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[13], false, 6, 1, 0, 0); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 63); _vm->_sound->command(18); } @@ -1260,7 +1260,7 @@ void Scene506::step() { case 71: _scene->_sequences.remove(_globals._sequenceIndexes[3]); - _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 6, 1, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 6, 1, 0, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 5); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 72); break; @@ -1317,7 +1317,7 @@ void Scene506::handleDoorSequences() { case 82: _scene->_sequences.remove(_doorSequenceIdx); - _doorSequenceIdx = _scene->_sequences.startReverseCycle(_doorSpriteIdx, false, 7, 1, 0, 0); + _doorSequenceIdx = _scene->_sequences.startPingPongCycle(_doorSpriteIdx, false, 7, 1, 0, 0); _scene->_sequences.setDepth(_doorSequenceIdx, _doorDepth); if (_actionFl) _scene->_sequences.addSubEntry(_doorSequenceIdx, SEQUENCE_TRIGGER_EXPIRE, 0, 84); @@ -1487,7 +1487,7 @@ void Scene507::actions() { case 0: _game._player._stepEnabled = false; _game._player._visible = false; - _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 5); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 5, 1); @@ -1613,7 +1613,7 @@ void Scene508::enter() { _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 11); int idx = _scene->_dynamicHotspots.add(NOUN_LASER_BEAM, VERB_WALKTO, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0)); _scene->_dynamicHotspots.setPosition(idx, Common::Point(57, 116), FACING_NORTHEAST); - _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 15, 0, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], false, 15, 0, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 6, 8); _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 6); if (_globals[kLaserHoleIsThere]) { @@ -1659,7 +1659,7 @@ void Scene508::handlePedestral() { case 0: _game._player._stepEnabled = false; _game._player._visible = false; - _globals._sequenceIndexes[6] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[6], false, 9, 1, 0, 0); + _globals._sequenceIndexes[6] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[6], false, 9, 1, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], 1, 4); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[6]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_SPRITE, 4, 1); @@ -1732,7 +1732,7 @@ void Scene508::actions() { break; case 4: - _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 15, 0, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], false, 15, 0, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 6, 8); _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 6); break; @@ -2024,7 +2024,7 @@ void Scene511::actions() { case 0: _game._player._stepEnabled = false; _scene->_sequences.remove(_globals._sequenceIndexes[1]); - _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0); + _globals._sequenceIndexes[1] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 1); break; @@ -2257,7 +2257,7 @@ void Scene512::actions() { case 0: _game._player._stepEnabled = false; _game._player._visible = false; - _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 5, 1); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2); @@ -2293,7 +2293,7 @@ void Scene512::actions() { case 1: _game._player._visible = false; - _globals._sequenceIndexes[8] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[8], false, 9, 1, 0, 0); + _globals._sequenceIndexes[8] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[8], false, 9, 1, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[8], 1, 3); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[8]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 2); @@ -2326,7 +2326,7 @@ void Scene512::actions() { break; case 5: - _globals._sequenceIndexes[5] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[5], false, 14, 0, 0, 0); + _globals._sequenceIndexes[5] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[5], false, 14, 0, 0, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 3); _scene->_hotspots.activate(NOUN_PADLOCK_KEY, true); _scene->_sequences.addTimer(60, 6); @@ -2347,7 +2347,7 @@ void Scene512::actions() { case 0: _game._player._stepEnabled = false; _game._player._visible = false; - _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 10, 1, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], false, 10, 1, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 2); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 1); @@ -2358,12 +2358,12 @@ void Scene512::actions() { _game._player._visible = true; if (!_game._objects.isInRoom(OBJ_PADLOCK_KEY) || _game._difficulty == DIFFICULTY_EASY) { _scene->_sequences.remove(_globals._sequenceIndexes[3]); - _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 2); } else { _scene->_sequences.remove(_globals._sequenceIndexes[5]); - _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 12, 1, 0, 0); + _globals._sequenceIndexes[4] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[4], false, 12, 1, 0, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 3); _scene->_hotspots.activate(NOUN_PADLOCK_KEY, false); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 2); @@ -2391,7 +2391,7 @@ void Scene512::actions() { else endVal = 2; - _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 10, 1, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], false, 10, 1, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, endVal); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, endVal, 1); @@ -2529,7 +2529,7 @@ void Scene513::step() { case 80: _game._player._stepEnabled = false; _scene->_sequences.remove(_globals._sequenceIndexes[2]); - _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 2); _vm->_sound->command(24); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 81); @@ -2588,7 +2588,7 @@ void Scene513::actions() { case 0: _game._player._stepEnabled = false; _scene->_sequences.remove(_globals._sequenceIndexes[1]); - _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0); + _globals._sequenceIndexes[1] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 1); break; @@ -2626,7 +2626,7 @@ void Scene513::actions() { case 0: _game._player._stepEnabled = false; _game._player._visible = false; - _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 7, 1, 0, 0); + _globals._sequenceIndexes[4] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[4], false, 7, 1, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 1, 2); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 1); @@ -2636,7 +2636,7 @@ void Scene513::actions() { _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[4]); _game._player._visible = true; _scene->_sequences.remove(_globals._sequenceIndexes[2]); - _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 2); _vm->_sound->command(24); _scene->_kernelMessages.reset(); diff --git a/engines/mads/nebular/nebular_scenes6.cpp b/engines/mads/nebular/nebular_scenes6.cpp index 679039535f..b0777c13c3 100644 --- a/engines/mads/nebular/nebular_scenes6.cpp +++ b/engines/mads/nebular/nebular_scenes6.cpp @@ -130,7 +130,7 @@ void Scene601::step() { case 71: _scene->_sequences.remove(_globals._sequenceIndexes[2]); - _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 3); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 72); break; @@ -313,7 +313,7 @@ void Scene602::handleSafeActions() { case 0: _game._player._stepEnabled = false; _game._player._visible = false; - _globals._sequenceIndexes[5] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[5], true, 12, 1, 0, 0); + _globals._sequenceIndexes[5] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[5], true, 12, 1, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 1, 3); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_SPRITE, 3, 1); @@ -348,7 +348,7 @@ void Scene602::handleSafeActions() { else _lastSpriteIdx = _globals._spriteIndexes[3]; - _lastSequenceIdx = _scene->_sequences.startReverseCycle(_lastSpriteIdx, false, 12, 1, 0, 0); + _lastSequenceIdx = _scene->_sequences.startPingPongCycle(_lastSpriteIdx, false, 12, 1, 0, 0); _scene->_sequences.setDepth(_lastSequenceIdx, 14); if (_game._objects[OBJ_DOOR_KEY]._roomNumber == _scene->_currentSceneId) _scene->_hotspots.activate(NOUN_DOOR_KEY, false); @@ -460,7 +460,7 @@ void Scene602::actions() { case 0: _game._player._stepEnabled = false; _game._player._visible = false; - _globals._sequenceIndexes[5] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[5], true, 8, 1, 0, 0); + _globals._sequenceIndexes[5] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[5], true, 8, 1, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 1, 3); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_SPRITE, 3, 1); @@ -600,7 +600,7 @@ void Scene603::actions() { case 0: _game._player._stepEnabled = false; _game._player._visible = false; - _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 8, 1, 0, 0); + _globals._sequenceIndexes[4] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[4], false, 8, 1, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 1, 5); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_SPRITE, 5, 1); @@ -858,7 +858,7 @@ void Scene604::handleBombActions() { case 0: _game._player._stepEnabled = false; _game._player._visible = false; - _globals._sequenceIndexes[5] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[5], false, 9, 1, 0, 0); + _globals._sequenceIndexes[5] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[5], false, 9, 1, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 1, 3); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); if (_bombMode == 1) @@ -908,7 +908,7 @@ void Scene604::actions() { case 0: _game._player._stepEnabled = false; _scene->_sequences.remove(_globals._sequenceIndexes[2]); - _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 1); break; @@ -1003,12 +1003,12 @@ void Scene605::enter() { _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('n', -1)); _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('f', -1)); - _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 15, 0, 0, 0); - _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 17, 0, 0, 0); - _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 14, 0, 0, 0); - _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 13, 0, 0, 0); - _globals._sequenceIndexes[5] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[5], false, 17, 0, 0, 0); - _globals._sequenceIndexes[6] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[6], false, 18, 0, 0, 0); + _globals._sequenceIndexes[1] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[1], false, 15, 0, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], false, 17, 0, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 14, 0, 0, 0); + _globals._sequenceIndexes[4] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[4], false, 13, 0, 0, 0); + _globals._sequenceIndexes[5] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[5], false, 17, 0, 0, 0); + _globals._sequenceIndexes[6] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[6], false, 18, 0, 0, 0); _game._player._visible = false; _game._player._stepEnabled = false; @@ -1164,7 +1164,7 @@ void Scene607::step() { && !_dogBarking && (_vm->getRandomNumber(1, 50) == 10)) { _dogBarking = true; _scene->_sequences.remove(_globals._sequenceIndexes[1]); - _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 5, 8, 0, 0); + _globals._sequenceIndexes[1] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[1], false, 5, 8, 0, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 6); _scene->_kernelMessages.reset(); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_SPRITE, 2, 100); @@ -1250,7 +1250,7 @@ void Scene607::step() { case 61: { int syncIdx = _globals._sequenceIndexes[4]; - _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 15, 3, 0, 0); + _globals._sequenceIndexes[4] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[4], false, 15, 3, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 46, -2); _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 1); _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], syncIdx); @@ -1397,7 +1397,7 @@ void Scene607::actions() { case 0: _game._player._stepEnabled = false; _scene->_sequences.remove(_globals._sequenceIndexes[2]); - _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 1); break; @@ -1791,7 +1791,7 @@ void Scene608::enter() { if (!_dogUnderCar) resetDogVariables(); else { - _globals._sequenceIndexes[10] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[10], false, 9, 0, 0, 0); + _globals._sequenceIndexes[10] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[10], false, 9, 0, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[10], 10, 11); _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 6); } @@ -1833,7 +1833,7 @@ void Scene608::step() { if (_vm->getRandomNumber(1, 50) == 10) { _dogBarkingFl = true; _scene->_sequences.remove(_globals._sequenceIndexes[5]); - _globals._sequenceIndexes[5] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[5], false, 5, 8, 0, 0); + _globals._sequenceIndexes[5] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[5], false, 5, 8, 0, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 4); int idx = _scene->_dynamicHotspots.add(NOUN_OBNOXIOUS_DOG, VERB_WALKTO, _globals._sequenceIndexes[5], Common::Rect(0, 0, 0, 0)); _scene->_dynamicHotspots.setPosition(idx, Common::Point(194, 142), FACING_EAST); @@ -1958,7 +1958,7 @@ void Scene608::step() { _game._player._visible = true; _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount; } else if (_carFrame == 41) { - _globals._sequenceIndexes[10] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[10], false, 9, 0, 0, 0); + _globals._sequenceIndexes[10] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[10], false, 9, 0, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[10], 10, 11); _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 6); _dogUnderCar = true; @@ -2148,7 +2148,7 @@ void Scene608::step() { case 82: { int syncIdx = _globals._sequenceIndexes[9]; - _globals._sequenceIndexes[9] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[9], false, 15, 5, 0, 0); + _globals._sequenceIndexes[9] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[9], false, 15, 5, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[9], 39, 40); _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 5); _scene->_sequences.updateTimeout(_globals._sequenceIndexes[9], syncIdx); @@ -2219,7 +2219,7 @@ void Scene608::actions() { if ((_globals[kCarStatus] == CAR_UP) || (_globals[kCarStatus] == CAR_SQUASHES_DOG) || (_globals[kCarStatus] == CAR_SQUASHES_DOG_AGAIN)) { _game._player._stepEnabled = false; _game._player._visible = false; - _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], true, 6, 2, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], true, 6, 2, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 2); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 1); @@ -2293,7 +2293,7 @@ void Scene608::actions() { if ((_globals[kCarStatus] == CAR_DOWN) || (_globals[kCarStatus] == CAR_DOWN_ON_SQUASHED_DOG)) { _game._player._stepEnabled = false; _game._player._visible = false; - _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], true, 6, 2, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], true, 6, 2, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 3); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 1); @@ -2379,7 +2379,7 @@ void Scene608::actions() { case 0: _game._player._stepEnabled = false; _game._player._visible = false; - _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], true, 6, 2, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], true, 6, 2, 0, 0); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 4, 1); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2); @@ -2407,7 +2407,7 @@ void Scene608::actions() { case 0: _game._player._stepEnabled = false; _game._player._visible = false; - _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], true, 6, 2, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], true, 6, 2, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 2); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 2, 1); @@ -2574,7 +2574,7 @@ void Scene609::step() { case 62: _scene->_sequences.remove( _globals._sequenceIndexes[2]); - _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0); _scene->_hotspots.activate(NOUN_VIDEO_STORE_DOOR, true); _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 9); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 63); @@ -2582,7 +2582,7 @@ void Scene609::step() { case 63: if (!_globals[kHasTalkedToHermit] && (_game._difficulty != DIFFICULTY_HARD)) { - _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 26, 2, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 26, 2, 0, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 7); _scene->_sequences.setPosition(_globals._sequenceIndexes[3], Common::Point(287, 73)); _scene->_sequences.setScale(_globals._sequenceIndexes[3], 47); @@ -2605,7 +2605,7 @@ void Scene609::step() { case 71: if (!_globals[kHasTalkedToHermit]) { - _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 26, 2, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 26, 2, 0, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 7); _scene->_sequences.setPosition(_globals._sequenceIndexes[3], Common::Point(287, 73)); _scene->_sequences.setScale(_globals._sequenceIndexes[3], 47); @@ -2648,7 +2648,7 @@ void Scene609::enterStore() { case 2: _game._player._visible = false; - _globals._sequenceIndexes[5] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[5], true, 11, 2, 0, 0); + _globals._sequenceIndexes[5] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[5], true, 11, 2, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 1, 2); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 3); @@ -2690,7 +2690,7 @@ void Scene609::enterStore() { case 7: _scene->_sequences.remove(_globals._sequenceIndexes[2]); - _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 9); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 8); break; @@ -2766,7 +2766,7 @@ void Scene609::actions() { case 0: _game._player._stepEnabled = false; _scene->_sequences.remove(_globals._sequenceIndexes[1]); - _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0); + _globals._sequenceIndexes[1] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 5); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 1); break; @@ -2922,7 +2922,7 @@ void Scene610::actions() { case 0: _game._player._stepEnabled = false; _game._player._visible = false; - _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], true, 8, 1, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], true, 8, 1, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 2); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 2, 1); @@ -2952,7 +2952,7 @@ void Scene610::actions() { case 0: _game._player._stepEnabled = false; _game._player._visible = false; - _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], true, 8, 1, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], true, 8, 1, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 2); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 2, 1); @@ -4012,7 +4012,7 @@ void Scene611::step() { _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 81); } else if (_game._trigger == 81) { int syncId = _globals._sequenceIndexes[1]; - _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 20, 0, 0, 0); + _globals._sequenceIndexes[1] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[1], false, 20, 0, 0, 0); int idx = _scene->_dynamicHotspots.add(NOUN_RAT, VERB_WALKTO, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); _ratHotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(272, 154), FACING_SOUTHEAST); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 9, 10); @@ -4040,7 +4040,7 @@ void Scene611::step() { break; case 6: - _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 12, 3, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], false, 12, 3, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 2, 4); _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 71); @@ -4260,7 +4260,7 @@ void Scene611::step() { if (_hermitMode == 6) { if ((_scene->_activeAnimation->getCurrentFrame() == 9) && _check1Fl) { _scene->_sequences.remove(_globals._sequenceIndexes[3]); - _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 7, 1, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 7, 1, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 2); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 112); @@ -4300,7 +4300,7 @@ void Scene611::step() { _resetBatterieText = true; int syncIdx = _globals._sequenceIndexes[3]; _nextFrame = 10; - _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 7, 1, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 7, 1, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 2); _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], syncIdx); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); @@ -4488,7 +4488,7 @@ void Scene612::handleWinchMovement() { case 0: _game._player._stepEnabled = false; _game._player._visible = false; - _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 10, 1, 0, 0); + _globals._sequenceIndexes[4] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[4], false, 10, 1, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 1, 5); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_SPRITE, 5, 1); @@ -4506,7 +4506,7 @@ void Scene612::handleWinchMovement() { _globals[kBoatRaised] = false; } else { _scene->_sequences.remove(_globals._sequenceIndexes[2]); - _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 17, 9, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], false, 17, 9, 0, 0); _vm->_sound->command(18); } _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); @@ -4608,7 +4608,7 @@ void Scene612::actions() { case 0: _game._player._stepEnabled = false; _scene->_sequences.remove(_globals._sequenceIndexes[1]); - _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0); + _globals._sequenceIndexes[1] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 2); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 1); break; diff --git a/engines/mads/nebular/nebular_scenes7.cpp b/engines/mads/nebular/nebular_scenes7.cpp index 0f019c4b19..4838ee27d9 100644 --- a/engines/mads/nebular/nebular_scenes7.cpp +++ b/engines/mads/nebular/nebular_scenes7.cpp @@ -148,11 +148,11 @@ void Scene701::enter() { switch (boatStatus) { case BOAT_TIED_FLOATING: - _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 20, 0, 0, 0); + _globals._sequenceIndexes[4] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[4], false, 20, 0, 0, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 10); break; case BOAT_ADRIFT: - _globals._sequenceIndexes[6] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[6], false, 20, 0, 0, 0); + _globals._sequenceIndexes[6] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[6], false, 20, 0, 0, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 10); break; case BOAT_TIED: @@ -206,7 +206,7 @@ void Scene701::step() { switch(_game._trigger) { case 60: _scene->_sequences.remove(_globals._sequenceIndexes[5]); - _globals._sequenceIndexes[5] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[5], false, 6, 1, 0, 0); + _globals._sequenceIndexes[5] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[5], false, 6, 1, 0, 0); _scene->_sequences.setPosition(_globals._sequenceIndexes[5], Common::Point(155, 129)); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 61); break; @@ -326,7 +326,7 @@ void Scene701::actions() { case 3: _vm->_sound->command(17); - _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 5, 1, 0, 0); + _globals._sequenceIndexes[1] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[1], false, 5, 1, 0, 0); _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136)); _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 4); @@ -502,7 +502,7 @@ void Scene702::actions() { case 0: _game._player._stepEnabled = false; _game._player._visible = false; - _globals._sequenceIndexes[12] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[12], false, 5, 2, 0, 0); + _globals._sequenceIndexes[12] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[12], false, 5, 2, 0, 0); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[12]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_SPRITE, 4, 1); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_EXPIRE, 0, 2); @@ -1218,7 +1218,7 @@ void Scene704::handleFillBottle(int quote) { void Scene704::enter() { if (_game._objects[OBJ_BOTTLE]._roomNumber == _scene->_currentSceneId) { _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('b', 0)); - _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 6, 0, 0, 0); + _globals._sequenceIndexes[1] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[1], false, 6, 0, 0, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); if (_scene->_priorSceneId == 705) { _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(123, 125)); @@ -1585,7 +1585,7 @@ void Scene705::enter() { void Scene705::step() { switch (_game._trigger) { case 70: - _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 9, 1, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 9, 1, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 4); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 71); break; @@ -1798,7 +1798,7 @@ void Scene706::handleTakeVase() { case 0: _game._player._stepEnabled = false; _game._player._visible = false; - _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 4, 2, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 4, 2, 0, 0); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_SPRITE, 7, 1); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 2); @@ -2087,7 +2087,7 @@ void Scene710::enter() { if (_game._objects[OBJ_VASE]._roomNumber == 706) { _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('g', -1)); - _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 6, 0, 0, 0); + _globals._sequenceIndexes[1] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[1], false, 6, 0, 0, 0); } _game._player._visible = false; @@ -2248,7 +2248,7 @@ void Scene751::step() { switch (_game._trigger) { case 70: _scene->_sequences.remove(_globals._sequenceIndexes[4]); - _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 6, 1, 0, 0); + _globals._sequenceIndexes[4] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[4], false, 6, 1, 0, 0); _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(155, 129)); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 71); break; @@ -2287,7 +2287,7 @@ void Scene751::step() { case 62: _vm->_sound->command(17); - _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 5, 1, 0, 0); + _globals._sequenceIndexes[1] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[1], false, 5, 1, 0, 0); _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136)); _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 63); @@ -2329,7 +2329,7 @@ void Scene751::preActions() { _game._player._readyToWalk = false; _game._player._stepEnabled = false; _scene->_sequences.remove(_globals._sequenceIndexes[2]); - _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 11, 1, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], false, 11, 1, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], -1, 7); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 1); break; @@ -2398,7 +2398,7 @@ void Scene751::actions() { case 3: _vm->_sound->command(17); - _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 5, 1, 0, 0); + _globals._sequenceIndexes[1] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[1], false, 5, 1, 0, 0); _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136)); _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 4); @@ -2597,7 +2597,7 @@ void Scene752::actions() { case 0: _game._player._stepEnabled = false; _game._player._visible = false; - _globals._sequenceIndexes[12] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[12], false, 5, 2, 0, 0); + _globals._sequenceIndexes[12] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[12], false, 5, 2, 0, 0); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[12]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_SPRITE, 4, 1); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_EXPIRE, 0, 2); @@ -2622,7 +2622,7 @@ void Scene752::actions() { case 0: _game._player._stepEnabled = false; _game._player._visible = false; - _globals._sequenceIndexes[12] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[12], false, 5, 2, 0, 0); + _globals._sequenceIndexes[12] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[12], false, 5, 2, 0, 0); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[12]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_SPRITE, 4, 1); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_EXPIRE, 0, 2); diff --git a/engines/mads/nebular/nebular_scenes8.cpp b/engines/mads/nebular/nebular_scenes8.cpp index 7e8366c179..95b3c24938 100644 --- a/engines/mads/nebular/nebular_scenes8.cpp +++ b/engines/mads/nebular/nebular_scenes8.cpp @@ -145,7 +145,7 @@ void Scene801::enter() { case 2: _game._player._playerPos = Common::Point(8, 117); _globals[kTeleporterUnderstood] = true; - _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 8, 1, 0, 0); + _globals._sequenceIndexes[1] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[1], false, 8, 1, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 1, 13); _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 8090); @@ -283,7 +283,7 @@ void Scene801::actions() { _globals[kBetweenRooms] = true; _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; _scene->_sequences.remove(_globals._sequenceIndexes[2]); - _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 4, 1, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], false, 4, 1, 0, 0); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 90); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 5); _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 13); @@ -419,7 +419,7 @@ void Scene802::actions() { case 0: _game._player._stepEnabled = false; _game._player._visible = false; - _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], true, 7, 2, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], true, 7, 2, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 2); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 2, 1); @@ -451,7 +451,7 @@ void Scene802::actions() { case 0: _game._player._stepEnabled = false; _game._player._visible = false; - _globals._sequenceIndexes[5] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[5], true, 7, 2, 0, 0); + _globals._sequenceIndexes[5] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[5], true, 7, 2, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 1, 4); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_SPRITE, 4, 1); @@ -692,7 +692,7 @@ void Scene803::step() { if (_game._trigger == 90) { int syncIdx = _globals._sequenceIndexes[4]; - _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 15, 0, 0, 0); + _globals._sequenceIndexes[4] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[4], false, 15, 0, 0, 0); _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], syncIdx); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 4, 9); if (_globals[kHoppyDead]) @@ -726,7 +726,7 @@ void Scene803::step() { if (_game._trigger == 150) { _scene->_sequences.remove(_globals._sequenceIndexes[6]); _vm->_sound->command(18); - _globals._sequenceIndexes[6] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[6], false, 8, 1, 0, 0); + _globals._sequenceIndexes[6] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[6], false, 8, 1, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], 1, 19); _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 4); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 151); @@ -778,7 +778,7 @@ void Scene803::actions() { case 162: _scene->_sequences.remove(_globals._sequenceIndexes[9]); - _globals._sequenceIndexes[9] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[9], true, 6, 1, 0, 0); + _globals._sequenceIndexes[9] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[9], true, 6, 1, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[9], 1, 4); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[9]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 0, 163); @@ -899,7 +899,7 @@ void Scene804::enter() { _scene->_sequences.addTimer(60, 100); } else { _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, 1); - _globals._sequenceIndexes[7] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[7], false, 4, 0, 0, 0); + _globals._sequenceIndexes[7] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[7], false, 4, 0, 0, 0); _scene->_sequences.addTimer(160, 70); _game._player._stepEnabled = false; } @@ -1277,14 +1277,14 @@ void Scene805::actions() { } else if (_action.isAction(VERB_REMOVE, NOUN_SHIELD_MODULATOR) && _globals[kShieldModInstalled]) { _scene->_sequences.remove(_globals._sequenceIndexes[1]); _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; - _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 7, 1, 0, 0); + _globals._sequenceIndexes[1] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[1], false, 7, 1, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], -1, -2); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 71); _game._player._stepEnabled = false; } else if (_action.isAction(VERB_REMOVE, NOUN_TARGET_MODULE) && _globals[kTargetModInstalled]) { _scene->_sequences.remove(_globals._sequenceIndexes[2]); _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; - _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], -1, -2); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 81); _game._player._stepEnabled = false; @@ -1433,7 +1433,7 @@ void Scene808::actions() { _vm->_sound->command(20); _vm->_sound->command(25); } - _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 4, 1, 0, 0); + _globals._sequenceIndexes[4] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[4], false, 4, 1, 0, 0); _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(248, 211)); _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 2); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 71); @@ -1468,7 +1468,7 @@ void Scene808::actions() { _vm->_sound->command(20); } _globals[kTopButtonPushed] = false; - _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 4, 1, 0, 0); + _globals._sequenceIndexes[4] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[4], false, 4, 1, 0, 0); _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(248, 186)); _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 2); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 91); @@ -1499,7 +1499,7 @@ void Scene808::actions() { _vm->_sound->command(20); } _globals[kTopButtonPushed] = true; - _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 4, 1, 0, 0); + _globals._sequenceIndexes[4] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[4], false, 4, 1, 0, 0); _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(248, 163)); _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 2); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 81); @@ -1516,7 +1516,7 @@ void Scene808::actions() { switch (_game._trigger) { case 0: _game._player._stepEnabled = false; - _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 4, 2, 0, 0); + _globals._sequenceIndexes[4] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[4], false, 4, 2, 0, 0); _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(168, 211)); _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 2); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 70); @@ -1533,7 +1533,7 @@ void Scene808::actions() { switch (_game._trigger) { case 0: _game._player._stepEnabled = false; - _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 4, 2, 0, 0); + _globals._sequenceIndexes[4] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[4], false, 4, 2, 0, 0); _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(172, 163)); _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 2); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 80); @@ -1550,7 +1550,7 @@ void Scene808::actions() { switch (_game._trigger) { case 0: _game._player._stepEnabled = false; - _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 4, 2, 0, 0); + _globals._sequenceIndexes[4] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[4], false, 4, 2, 0, 0); _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(172, 186)); _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 2); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 90); diff --git a/engines/mads/sequence.cpp b/engines/mads/sequence.cpp index c94f3e3ad4..ab73d70b10 100644 --- a/engines/mads/sequence.cpp +++ b/engines/mads/sequence.cpp @@ -466,15 +466,15 @@ int SequenceList::startCycle(int srcSpriteIndex, bool flipped, int cycleIndex) { return result; } -int SequenceList::startReverseCycle(int srcSpriteIndex, bool flipped, int numTicks, +int SequenceList::startPingPongCycle(int srcSpriteIndex, bool flipped, int numTicks, int triggerCountdown, int timeoutTicks, int extraTicks) { SpriteAsset *sprites = _vm->_game->_scene._sprites[srcSpriteIndex]; MSprite *frame = sprites->getFrame(0); int depth = _vm->_game->_scene._depthSurface.getDepth(Common::Point( frame->_offset.x + frame->w / 2, frame->_offset.y + frame->h / 2)); - return add(srcSpriteIndex, flipped, sprites->getCount(), triggerCountdown, timeoutTicks, - extraTicks, numTicks, 0, 0, true, 100, depth - 1, -1, ANIMTYPE_REVERSIBLE, 0, 0); + return add(srcSpriteIndex, flipped, 1, triggerCountdown, timeoutTicks, + extraTicks, numTicks, 0, 0, true, 100, depth - 1, 1, ANIMTYPE_PING_PONG, 0, 0); } void SequenceList::updateTimeout(int spriteIdx, int seqIndex) { diff --git a/engines/mads/sequence.h b/engines/mads/sequence.h index ee587ff02d..9603296717 100644 --- a/engines/mads/sequence.h +++ b/engines/mads/sequence.h @@ -38,7 +38,7 @@ enum SequenceTrigger { SEQUENCE_TRIGGER_SPRITE = 2 // Trigger when sequence reaches specific sprite }; -enum SpriteAnimType { ANIMTYPE_NONE = 0, ANIMTYPE_CYCLED = 1, ANIMTYPE_REVERSIBLE = 2 }; +enum SpriteAnimType { ANIMTYPE_NONE = 0, ANIMTYPE_CYCLED = 1, ANIMTYPE_PING_PONG = 2 }; #define SEQUENCE_ENTRY_SUBSET_MAX 5 @@ -117,7 +117,7 @@ public: int triggerCountdown = 0, int timeoutTicks = 0, int extraTicks = 0); int startCycle(int srcSpriteIdx, bool flipped, int cycleIndex); - int startReverseCycle(int srcSpriteIndex, bool flipped, int numTicks, + int startPingPongCycle(int srcSpriteIndex, bool flipped, int numTicks, int triggerCountdown = 0, int timeoutTicks = 0, int extraTicks = 0); void updateTimeout(int spriteIdx, int seqIndex); void setScale(int spriteIdx, int scale); -- cgit v1.2.3 From cecb9a9ecc1ec1897fdd27e1bafc7f6d494cd6af Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 4 Mar 2015 18:55:05 -0500 Subject: MADS: Fix crash throwing bones to dog --- engines/mads/player.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/mads/player.cpp b/engines/mads/player.cpp index 8720aeead3..a257cea264 100644 --- a/engines/mads/player.cpp +++ b/engines/mads/player.cpp @@ -790,9 +790,7 @@ void Player::removePlayerSprites() { } } - if (scene._activeAnimation != nullptr) - scene._activeAnimation->resetSpriteSetsCount(); - + scene._spriteSlots.clear(); scene._spriteSlots.fullRefresh(); _visible = false; } -- cgit v1.2.3 From 0780ec95c2a035d122e2afba1beb2143033943a6 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 4 Mar 2015 20:43:57 -0500 Subject: MADS: Fix Herman animating too quickly --- engines/mads/animation.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'engines') diff --git a/engines/mads/animation.cpp b/engines/mads/animation.cpp index 469d42cc1b..7e616bffbc 100644 --- a/engines/mads/animation.cpp +++ b/engines/mads/animation.cpp @@ -598,8 +598,6 @@ void Animation::setCurrentFrame(int frameNumber) { _currentFrame = frameNumber; _oldFrameEntry = 0; _freeFlag = false; - - _nextScrollTimer = _nextFrameTimer = _vm->_game->_scene._frameStartTime; } void Animation::setNextFrameTimer(int frameNumber) { -- cgit v1.2.3 From 16ced34bc2a21c99f775103008da0f1caf99e26d Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 4 Mar 2015 20:54:35 -0500 Subject: MADS: Fix assert when there are more than 5 talk options available --- engines/mads/user_interface.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/mads/user_interface.cpp b/engines/mads/user_interface.cpp index 929390a073..a53ab31968 100644 --- a/engines/mads/user_interface.cpp +++ b/engines/mads/user_interface.cpp @@ -843,10 +843,11 @@ void UserInterface::emptyConversationList() { } void UserInterface::addConversationMessage(int vocabId, const Common::String &msg) { - assert(_talkStrings.size() < 5); - - _talkStrings.push_back(msg); - _talkIds.push_back(vocabId); + // Only allow a maximum of 5 talk entries to be displayed + if (_talkStrings.size() < 5) { + _talkStrings.push_back(msg); + _talkIds.push_back(vocabId); + } } void UserInterface::loadInventoryAnim(int objectId) { -- cgit v1.2.3 From 51797d1438e1e0e34e5878e9b6e759870d7b016d Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 4 Mar 2015 21:30:04 -0500 Subject: MADS: Fix gender scanning animation in car --- engines/mads/nebular/nebular_scenes5.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes5.cpp b/engines/mads/nebular/nebular_scenes5.cpp index fe15fe0636..63b03bc097 100644 --- a/engines/mads/nebular/nebular_scenes5.cpp +++ b/engines/mads/nebular/nebular_scenes5.cpp @@ -800,7 +800,7 @@ void Scene504::actions() { case 1: { int syncIdx = _globals._sequenceIndexes[3]; - _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 6, 1, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[3], false, 6, 1, 0, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 13); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 6); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 2); -- cgit v1.2.3 From ce4c030117ece5f9c0d0384556f82125b2a5ed29 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 4 Mar 2015 21:51:01 -0500 Subject: MADS: Fix animations for opening car door at various car locations --- engines/mads/nebular/nebular_scenes5.cpp | 4 ++-- engines/mads/nebular/nebular_scenes6.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes5.cpp b/engines/mads/nebular/nebular_scenes5.cpp index 63b03bc097..b657a61c2f 100644 --- a/engines/mads/nebular/nebular_scenes5.cpp +++ b/engines/mads/nebular/nebular_scenes5.cpp @@ -2024,7 +2024,7 @@ void Scene511::actions() { case 0: _game._player._stepEnabled = false; _scene->_sequences.remove(_globals._sequenceIndexes[1]); - _globals._sequenceIndexes[1] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0); + _globals._sequenceIndexes[1] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 1); break; @@ -2588,7 +2588,7 @@ void Scene513::actions() { case 0: _game._player._stepEnabled = false; _scene->_sequences.remove(_globals._sequenceIndexes[1]); - _globals._sequenceIndexes[1] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0); + _globals._sequenceIndexes[1] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 1); break; diff --git a/engines/mads/nebular/nebular_scenes6.cpp b/engines/mads/nebular/nebular_scenes6.cpp index b0777c13c3..cb36064458 100644 --- a/engines/mads/nebular/nebular_scenes6.cpp +++ b/engines/mads/nebular/nebular_scenes6.cpp @@ -908,7 +908,7 @@ void Scene604::actions() { case 0: _game._player._stepEnabled = false; _scene->_sequences.remove(_globals._sequenceIndexes[2]); - _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 1); break; @@ -1397,7 +1397,7 @@ void Scene607::actions() { case 0: _game._player._stepEnabled = false; _scene->_sequences.remove(_globals._sequenceIndexes[2]); - _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 1); break; -- cgit v1.2.3 From 53cd90b32c7ad6fe7e1ac5f4c781c5e776bd9348 Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Thu, 5 Mar 2015 07:28:40 +0100 Subject: ZVISION: Fix GCC signed/unsigned warning --- engines/zvision/video/rlf_decoder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/zvision/video/rlf_decoder.cpp b/engines/zvision/video/rlf_decoder.cpp index 3e11a70f27..3bbf22edff 100644 --- a/engines/zvision/video/rlf_decoder.cpp +++ b/engines/zvision/video/rlf_decoder.cpp @@ -159,7 +159,7 @@ RLFDecoder::RLFVideoTrack::Frame RLFDecoder::RLFVideoTrack::readNextFrame() { bool RLFDecoder::RLFVideoTrack::seek(const Audio::Timestamp &time) { uint frame = getFrameAtTime(time); - assert(frame < (int)_frameCount); + assert(frame < _frameCount); if ((uint)_displayedFrame == frame) return true; -- cgit v1.2.3 From bb175b39c1aa9f6b03431bc2e89817ec138f91c3 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 5 Mar 2015 07:40:47 -0500 Subject: MADS: Fix screwed up death animation when getting eaten in village stream --- engines/mads/player.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mads/player.cpp b/engines/mads/player.cpp index a257cea264..68e0355df9 100644 --- a/engines/mads/player.cpp +++ b/engines/mads/player.cpp @@ -785,8 +785,10 @@ void Player::removePlayerSprites() { int heroSpriteId = _spritesStart; for (int i = 0; i < 8; i++) { if (_spriteSetsPresent[i]) { - scene._sprites.remove(heroSpriteId++); + delete scene._sprites[heroSpriteId]; + scene._sprites[heroSpriteId] = nullptr; _spriteSetsPresent[i] = false; + ++heroSpriteId; } } -- cgit v1.2.3 From b84d2e8d73c18c427ef1527b2b066642cfc981c4 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 5 Mar 2015 07:49:00 -0500 Subject: MADS: Fix timer initialization in two scenes --- engines/mads/nebular/nebular_scenes2.cpp | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes2.cpp b/engines/mads/nebular/nebular_scenes2.cpp index b8629a3915..2eb7f93a60 100644 --- a/engines/mads/nebular/nebular_scenes2.cpp +++ b/engines/mads/nebular/nebular_scenes2.cpp @@ -1152,8 +1152,9 @@ void Scene205::setup() { } Scene205::Scene205(MADSEngine *vm) : Scene2xx(vm) { - _lastFishTime = 0; - _chickenTime = 0; + _lastFishTime = _scene->_frameStartTime; + _chickenTime = _scene->_frameStartTime; + _beingKicked = false; _kernelMessage = -1; } @@ -1161,8 +1162,6 @@ Scene205::Scene205(MADSEngine *vm) : Scene2xx(vm) { void Scene205::synchronize(Common::Serializer &s) { Scene2xx::synchronize(s); - s.syncAsUint32LE(_lastFishTime); - s.syncAsUint32LE(_chickenTime); s.syncAsByte(_beingKicked); s.syncAsSint16LE(_kernelMessage); } @@ -1191,7 +1190,6 @@ void Scene205::enter() { _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 11); if (!_game._visitedScenes._sceneRevisited) { - _lastFishTime = _scene->_frameStartTime; _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 7, 1, 0, 0); idx = _scene->_dynamicHotspots.add(269, 13, _globals._sequenceIndexes[6], Common::Rect(0, 0, 0, 0)); _scene->_dynamicHotspots.setPosition(idx, Common::Point(49, 86), FACING_NORTH); @@ -1455,7 +1453,6 @@ Scene207::Scene207(MADSEngine *vm) : Scene2xx(vm) { void Scene207::synchronize(Common::Serializer &s) { Scene2xx::synchronize(s); - uint32 unused; s.syncAsByte(_vultureFl); s.syncAsByte(_spiderFl); @@ -1463,8 +1460,6 @@ void Scene207::synchronize(Common::Serializer &s) { s.syncAsSint32LE(_spiderHotspotId); s.syncAsSint32LE(_vultureHotspotId); - s.syncAsSint32LE(unused); - s.syncAsSint32LE(unused); } void Scene207::setup() { -- cgit v1.2.3 From f501e91ed1490fde5227015dc02fbe6c0cee2b5f Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 5 Mar 2015 09:12:20 -0500 Subject: MADS: Fix crash after throwing both bones to dog --- engines/mads/sprites.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mads/sprites.cpp b/engines/mads/sprites.cpp index f74edafc93..aa73fce712 100644 --- a/engines/mads/sprites.cpp +++ b/engines/mads/sprites.cpp @@ -406,7 +406,7 @@ void SpriteSets::remove(int idx) { } while (size() > 0 && (*this)[size() - 1] == nullptr); } - if (_assetCount > 0) + if (idx < 50 && _assetCount > 0) --_assetCount; } } -- cgit v1.2.3 From 3fae9f17dacaa4f8253c2f6b47adb9845cdb52b0 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 5 Mar 2015 12:16:24 -0500 Subject: MADS: Show a warning if sound code reads beyond end of sound data blocks --- engines/mads/nebular/sound_nebular.cpp | 24 ++++++++++++++++++++++++ engines/mads/nebular/sound_nebular.h | 20 ++++++++++++++++---- 2 files changed, 40 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/mads/nebular/sound_nebular.cpp b/engines/mads/nebular/sound_nebular.cpp index 0a054440b2..d41d0075eb 100644 --- a/engines/mads/nebular/sound_nebular.cpp +++ b/engines/mads/nebular/sound_nebular.cpp @@ -36,6 +36,7 @@ namespace Nebular { bool AdlibChannel::_channelsEnabled; AdlibChannel::AdlibChannel() { + _owner = nullptr; _activeCount = 0; _field1 = 0; _field2 = 0; @@ -55,6 +56,7 @@ AdlibChannel::AdlibChannel() { _pSrc = nullptr; _ptr3 = nullptr; _ptr4 = nullptr; + _ptrEnd = nullptr; _field17 = 0; _field19 = 0; _soundData = nullptr; @@ -108,6 +110,9 @@ void AdlibChannel::load(byte *pData) { _fieldB = 0; _field17 = 0; _field19 = 0; + + CachedDataEntry &cacheEntry = _owner->getCachedData(pData); + _ptrEnd = cacheEntry._dataEnd; } void AdlibChannel::check(byte *nullPtr) { @@ -192,6 +197,9 @@ ASound::ASound(Audio::Mixer *mixer, FM_OPL *opl, const Common::String &filename, _channelData[i]._freqBase = 0; _channelData[i]._field6 = 0; } + + for (int i = 0; i < ADLIB_CHANNEL_COUNT; ++i) + _channels[i]._owner = this; AdlibChannel::_channelsEnabled = false; @@ -283,6 +291,17 @@ void ASound::noise() { } } +CachedDataEntry &ASound::getCachedData(byte *pData) { + Common::List::iterator i; + for (i = _dataCache.begin(); i != _dataCache.end(); ++i) { + CachedDataEntry &e = *i; + if (e._data == pData) + return e; + } + + error("Could not find previously loaded data"); +} + void ASound::write(int reg, int val) { _queue.push(RegisterValue(reg, val)); } @@ -331,6 +350,7 @@ byte *ASound::loadData(int offset, int size) { CachedDataEntry rec; rec._offset = offset; rec._data = new byte[size]; + rec._dataEnd = rec._data + size - 1; _soundFile.seek(_dataOffset + offset); _soundFile.read(rec._data, size); _dataCache.push_back(rec); @@ -449,6 +469,10 @@ void ASound::pollActiveChannel() { warning("pollActiveChannel(): No data found for sound channel"); break; } + if (pSrc > chan->_ptrEnd) { + warning("Read beyond end of loaded sound data"); + } + if (!(*pSrc & 0x80) || (*pSrc <= 0xF0)) { if (updateFlag) updateActiveChannel(); diff --git a/engines/mads/nebular/sound_nebular.h b/engines/mads/nebular/sound_nebular.h index ccfd40ad52..cfacb211a4 100644 --- a/engines/mads/nebular/sound_nebular.h +++ b/engines/mads/nebular/sound_nebular.h @@ -37,11 +37,15 @@ class SoundManager; namespace Nebular { +class ASound; + /** * Represents the data for a channel on the Adlib */ class AdlibChannel { public: + ASound *_owner; + int _activeCount; int _field1; int _field2; @@ -61,6 +65,7 @@ public: byte *_pSrc; byte *_ptr3; byte *_ptr4; + byte *_ptrEnd; int _field17; int _field19; byte *_soundData; @@ -128,15 +133,17 @@ struct RegisterValue { #define ADLIB_CHANNEL_MIDWAY 5 #define CALLBACKS_PER_SECOND 60 +struct CachedDataEntry { + int _offset; + byte *_data; + byte *_dataEnd; +}; + /** * Base class for the sound player resource files */ class ASound : public Audio::AudioStream { private: - struct CachedDataEntry { - int _offset; - byte *_data; - }; Common::List _dataCache; uint16 _randomSeed; @@ -350,6 +357,11 @@ public: */ int getFrameCounter() { return _frameCounter; } + /** + * Return the cached data block record for previously loaded sound data + */ + CachedDataEntry &getCachedData(byte *pData); + // AudioStream interface /** * Main buffer read -- cgit v1.2.3 From c0fafcf33f374fdf85590108835585a0411a0661 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 5 Mar 2015 12:24:25 -0500 Subject: MADS: Fix mismatched delete/free releasing screen surface --- engines/mads/screen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mads/screen.cpp b/engines/mads/screen.cpp index 60f3d8aeaf..8db034c467 100644 --- a/engines/mads/screen.cpp +++ b/engines/mads/screen.cpp @@ -569,7 +569,7 @@ void ScreenSurface::init() { } ScreenSurface::~ScreenSurface() { - delete[] _surfacePixels; + ::free(_surfacePixels); } void ScreenSurface::copyRectToScreen(const Common::Rect &bounds) { -- cgit v1.2.3 From 76e824eddca2afbdccd109c3c3311e8af0f2bd83 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 5 Mar 2015 17:42:16 -0500 Subject: MADS: Bugfixes and cleanup for Herman conversation --- engines/mads/nebular/globals_nebular.h | 2 +- engines/mads/nebular/nebular_scenes6.cpp | 22 ++++++++++++++-------- 2 files changed, 15 insertions(+), 9 deletions(-) (limited to 'engines') diff --git a/engines/mads/nebular/globals_nebular.h b/engines/mads/nebular/globals_nebular.h index bd1c6d84b0..ce671f653d 100644 --- a/engines/mads/nebular/globals_nebular.h +++ b/engines/mads/nebular/globals_nebular.h @@ -148,7 +148,7 @@ enum GlobalId { /* Section #6 Variables */ kConvHermit1 = 130, - kconvHermit2 = 131, + kConvHermit2 = 131, kHasTalkedToHermit = 132, kExecuted_1_11 = 133, kHandsetCellStatus = 134, diff --git a/engines/mads/nebular/nebular_scenes6.cpp b/engines/mads/nebular/nebular_scenes6.cpp index cb36064458..5ef175d396 100644 --- a/engines/mads/nebular/nebular_scenes6.cpp +++ b/engines/mads/nebular/nebular_scenes6.cpp @@ -3253,6 +3253,8 @@ void Scene611::handleSubDialog1() { handleTalking(500); displayHermitQuestions(17); _dialog1.write(0x290, false); + _dialog1.write(0x28e, false); + if (!_dialog1.read(0x28F)) _dialog1.write(0x291, true); @@ -3271,8 +3273,10 @@ void Scene611::handleSubDialog1() { if ((_game._objects.isInInventory(OBJ_DURAFAIL_CELLS)) || (_game._objects.isInInventory(OBJ_PHONE_CELLS))) _dialog1.write(0x294, true); - if (!_game._objects.isInInventory(OBJ_DURAFAIL_CELLS) && !_game._objects.isInInventory(OBJ_PHONE_CELLS)) - _globals[kExecuted_1_11] = true; + // WORKAROUND: Fix bug in the original where the option to give Hermit batteries + // would be given before the player even has any batteries + //if (!_game._objects.isInInventory(OBJ_DURAFAIL_CELLS) && !_game._objects.isInInventory(OBJ_PHONE_CELLS)) + // _globals[kExecuted_1_11] = true; setDialogNode(1); break; @@ -3921,14 +3925,14 @@ void Scene611::enter() { 0x2D9, 0x2DA, 0x2DB, 0x2DC, 0x2DD, 0x2DE, 0x2DF, 0x2E0, 0x2E1, 0x2E2, 0x2E3, 0x2E4, 0x2E5, 0x2E6, 0x323, 0x324, 0); - _dialog1.setup(0x82, 0x287, 0x288, 0x289, 0x28A, 0x28B, 0x28C, 0x28D, 0x28E, 0x28F, 0x290, + _dialog1.setup(kConvHermit1, 0x287, 0x288, 0x289, 0x28A, 0x28B, 0x28C, 0x28D, 0x28E, 0x28F, 0x290, 0x291, 0x292, 0x293, 0x294, 0x295, 0x296, 0); - _dialog2.setup(0x83, 0x29C, 0x29D, 0x29E, 0x29F, 0); + _dialog2.setup(kConvHermit2, 0x29C, 0x29D, 0x29E, 0x29F, 0); if (!_game._visitedScenes._sceneRevisited) { - _dialog1.set(0x82, 0x287, 0x288, 0x296, 0); - _dialog2.set(0x83, 0x29F, 0); + _dialog1.set(kConvHermit1, 0x287, 0x288, 0x296, 0); + _dialog2.set(kConvHermit2, 0x29F, 0); } _vm->_palette->setEntry(252, 51, 51, 47); @@ -3964,12 +3968,14 @@ void Scene611::enter() { _scene->_hotspots.activate(NOUN_HERMIT, false); } - // CHECKME: The last line of the block looks extremely useless + /* WORKAROUND: Pretty sure this is a debugging code fragment that should be ignored if (_globals[kExecuted_1_11]) { _dialog1.write(0x294, true); _dialog1.write(0x292, false); _globals[kExecuted_1_11] = true; - } + }*/ + if ((_game._objects.isInInventory(OBJ_DURAFAIL_CELLS)) || (_game._objects.isInInventory(OBJ_PHONE_CELLS))) + _dialog1.write(0x294, true); if (_duringDialogFl) { _game._player._playerPos = Common::Point(237, 129); -- cgit v1.2.3 From 4c88d81cc2cbaf244922f01466447a1cef60f7fa Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 6 Mar 2015 08:30:26 -0500 Subject: MADS: Fix another incorrect car door opening animation --- engines/mads/nebular/nebular_scenes6.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes6.cpp b/engines/mads/nebular/nebular_scenes6.cpp index 5ef175d396..b50032352f 100644 --- a/engines/mads/nebular/nebular_scenes6.cpp +++ b/engines/mads/nebular/nebular_scenes6.cpp @@ -4614,7 +4614,7 @@ void Scene612::actions() { case 0: _game._player._stepEnabled = false; _scene->_sequences.remove(_globals._sequenceIndexes[1]); - _globals._sequenceIndexes[1] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0); + _globals._sequenceIndexes[1] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 2); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 1); break; -- cgit v1.2.3 From 763a962e1456fd8402be4992ab9069e9e507ebc8 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 6 Mar 2015 08:39:39 -0500 Subject: MADS: Fix animation of lab door opening --- engines/mads/nebular/nebular_scenes5.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes5.cpp b/engines/mads/nebular/nebular_scenes5.cpp index b657a61c2f..4fc603b607 100644 --- a/engines/mads/nebular/nebular_scenes5.cpp +++ b/engines/mads/nebular/nebular_scenes5.cpp @@ -1317,7 +1317,7 @@ void Scene506::handleDoorSequences() { case 82: _scene->_sequences.remove(_doorSequenceIdx); - _doorSequenceIdx = _scene->_sequences.startPingPongCycle(_doorSpriteIdx, false, 7, 1, 0, 0); + _doorSequenceIdx = _scene->_sequences.addReverseSpriteCycle(_doorSpriteIdx, false, 7, 1, 0, 0); _scene->_sequences.setDepth(_doorSequenceIdx, _doorDepth); if (_actionFl) _scene->_sequences.addSubEntry(_doorSequenceIdx, SEQUENCE_TRIGGER_EXPIRE, 0, 84); -- cgit v1.2.3 From cf845c6dbb6c57f65255e0abd70524d9b9187dd5 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 6 Mar 2015 18:40:53 -0500 Subject: MADS: Another car opening animation fix --- engines/mads/nebular/nebular_scenes6.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes6.cpp b/engines/mads/nebular/nebular_scenes6.cpp index b50032352f..43c8193828 100644 --- a/engines/mads/nebular/nebular_scenes6.cpp +++ b/engines/mads/nebular/nebular_scenes6.cpp @@ -2766,7 +2766,7 @@ void Scene609::actions() { case 0: _game._player._stepEnabled = false; _scene->_sequences.remove(_globals._sequenceIndexes[1]); - _globals._sequenceIndexes[1] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0); + _globals._sequenceIndexes[1] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 5); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 1); break; -- cgit v1.2.3 From 177d7ac24f9a1cdd884b9f947a0f50c656942ec0 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 6 Mar 2015 18:57:00 -0500 Subject: MADS: Fix car door exiting animations --- engines/mads/nebular/nebular_scenes5.cpp | 4 ++-- engines/mads/nebular/nebular_scenes6.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes5.cpp b/engines/mads/nebular/nebular_scenes5.cpp index 4fc603b607..85725a75ee 100644 --- a/engines/mads/nebular/nebular_scenes5.cpp +++ b/engines/mads/nebular/nebular_scenes5.cpp @@ -273,7 +273,7 @@ void Scene501::step() { case 72: _scene->_sequences.remove(_globals._sequenceIndexes[2]); - _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 73); break; @@ -1260,7 +1260,7 @@ void Scene506::step() { case 71: _scene->_sequences.remove(_globals._sequenceIndexes[3]); - _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 6, 1, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[3], false, 6, 1, 0, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 5); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 72); break; diff --git a/engines/mads/nebular/nebular_scenes6.cpp b/engines/mads/nebular/nebular_scenes6.cpp index 43c8193828..c862017462 100644 --- a/engines/mads/nebular/nebular_scenes6.cpp +++ b/engines/mads/nebular/nebular_scenes6.cpp @@ -130,7 +130,7 @@ void Scene601::step() { case 71: _scene->_sequences.remove(_globals._sequenceIndexes[2]); - _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 3); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 72); break; -- cgit v1.2.3 From 0deee07844f4748d00c753af283ee52a57654611 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 6 Mar 2015 19:03:49 -0500 Subject: MADS: Fix map fade out when choosing a car destination --- engines/mads/nebular/nebular_scenes5.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes5.cpp b/engines/mads/nebular/nebular_scenes5.cpp index 85725a75ee..dea5f678c4 100644 --- a/engines/mads/nebular/nebular_scenes5.cpp +++ b/engines/mads/nebular/nebular_scenes5.cpp @@ -996,7 +996,7 @@ void Scene505::step() { _scene->_sequences.remove(_globals._sequenceIndexes[1]); _scene->_sequences.remove(_globals._sequenceIndexes[0]); _scene->_sequences.remove(_globals._sequenceIndexes[13]); - _globals._sequenceIndexes[13] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[13], false, 6, 1, 0, 0); + _globals._sequenceIndexes[13] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[13], false, 6, 1, 0, 0); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 63); _vm->_sound->command(18); } -- cgit v1.2.3 From 62d007168a82614f30a8aa64ae613e30ba111771 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 6 Mar 2015 19:24:30 -0500 Subject: MADS: Animation fixes for scene group 8 --- engines/mads/nebular/nebular_scenes8.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes8.cpp b/engines/mads/nebular/nebular_scenes8.cpp index 95b3c24938..a0bfa0689a 100644 --- a/engines/mads/nebular/nebular_scenes8.cpp +++ b/engines/mads/nebular/nebular_scenes8.cpp @@ -283,7 +283,7 @@ void Scene801::actions() { _globals[kBetweenRooms] = true; _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; _scene->_sequences.remove(_globals._sequenceIndexes[2]); - _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], false, 4, 1, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[2], false, 4, 1, 0, 0); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 90); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 5); _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 13); @@ -726,7 +726,7 @@ void Scene803::step() { if (_game._trigger == 150) { _scene->_sequences.remove(_globals._sequenceIndexes[6]); _vm->_sound->command(18); - _globals._sequenceIndexes[6] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[6], false, 8, 1, 0, 0); + _globals._sequenceIndexes[6] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[6], false, 8, 1, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], 1, 19); _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 4); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 151); @@ -778,7 +778,7 @@ void Scene803::actions() { case 162: _scene->_sequences.remove(_globals._sequenceIndexes[9]); - _globals._sequenceIndexes[9] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[9], true, 6, 1, 0, 0); + _globals._sequenceIndexes[9] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[9], true, 6, 1, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[9], 1, 4); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[9]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 0, 163); @@ -1277,14 +1277,14 @@ void Scene805::actions() { } else if (_action.isAction(VERB_REMOVE, NOUN_SHIELD_MODULATOR) && _globals[kShieldModInstalled]) { _scene->_sequences.remove(_globals._sequenceIndexes[1]); _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; - _globals._sequenceIndexes[1] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[1], false, 7, 1, 0, 0); + _globals._sequenceIndexes[1] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[1], false, 7, 1, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], -1, -2); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 71); _game._player._stepEnabled = false; } else if (_action.isAction(VERB_REMOVE, NOUN_TARGET_MODULE) && _globals[kTargetModInstalled]) { _scene->_sequences.remove(_globals._sequenceIndexes[2]); _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; - _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], -1, -2); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 81); _game._player._stepEnabled = false; -- cgit v1.2.3 From 1cb764b08629c2171314a88c491f8fc461202cc6 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 6 Mar 2015 20:20:25 -0500 Subject: MADS: Fix crash after installing cards in ship --- engines/mads/nebular/nebular_scenes8.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes8.cpp b/engines/mads/nebular/nebular_scenes8.cpp index a0bfa0689a..75b6b17a94 100644 --- a/engines/mads/nebular/nebular_scenes8.cpp +++ b/engines/mads/nebular/nebular_scenes8.cpp @@ -1218,6 +1218,8 @@ void Scene805::enter() { } void Scene805::step() { + UserInterface &userInterface = _vm->_game->_scene._userInterface; + if (_game._trigger == 70) { _scene->_hotspots.activate(OBJ_SHIELD_MODULATOR, false); _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 25); @@ -1225,6 +1227,7 @@ void Scene805::step() { _scene->_dynamicHotspots.setPosition(idx, Common::Point(0, 0), FACING_DUMMY); _globals[kShieldModInstalled] = true; _game._objects.setRoom(OBJ_SHIELD_MODULATOR, NOWHERE); + userInterface._selectedInvIndex = -1; _game._player._stepEnabled = true; _vm->_sound->command(24); } @@ -1236,6 +1239,7 @@ void Scene805::step() { _scene->_dynamicHotspots.setPosition(idx, Common::Point(0, 0), FACING_DUMMY); _globals[kTargetModInstalled] = true; _game._objects.setRoom(OBJ_TARGET_MODULE, NOWHERE); + userInterface._selectedInvIndex = -1; _game._player._stepEnabled = true; _vm->_sound->command(24); } -- cgit v1.2.3 From 119c179d5aa432a0dc3e1b522639478cd5377b83 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 6 Mar 2015 20:25:25 -0500 Subject: MADS: Fix hand animations on Antigrav control panel --- engines/mads/nebular/nebular_scenes8.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes8.cpp b/engines/mads/nebular/nebular_scenes8.cpp index 75b6b17a94..64b6c26bbc 100644 --- a/engines/mads/nebular/nebular_scenes8.cpp +++ b/engines/mads/nebular/nebular_scenes8.cpp @@ -1437,7 +1437,7 @@ void Scene808::actions() { _vm->_sound->command(20); _vm->_sound->command(25); } - _globals._sequenceIndexes[4] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[4], false, 4, 1, 0, 0); + _globals._sequenceIndexes[4] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[4], false, 4, 1, 0, 0); _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(248, 211)); _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 2); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 71); @@ -1472,7 +1472,7 @@ void Scene808::actions() { _vm->_sound->command(20); } _globals[kTopButtonPushed] = false; - _globals._sequenceIndexes[4] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[4], false, 4, 1, 0, 0); + _globals._sequenceIndexes[4] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[4], false, 4, 1, 0, 0); _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(248, 186)); _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 2); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 91); @@ -1503,7 +1503,7 @@ void Scene808::actions() { _vm->_sound->command(20); } _globals[kTopButtonPushed] = true; - _globals._sequenceIndexes[4] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[4], false, 4, 1, 0, 0); + _globals._sequenceIndexes[4] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[4], false, 4, 1, 0, 0); _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(248, 163)); _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 2); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 81); -- cgit v1.2.3 From a22d7f2d5f27701766dbf36d50e0a31ea7b26d69 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 6 Mar 2015 20:55:53 -0500 Subject: MADS: Fix crash on leaving planeet --- engines/mads/nebular/nebular_scenes8.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes8.cpp b/engines/mads/nebular/nebular_scenes8.cpp index 64b6c26bbc..4b8d7d5dd8 100644 --- a/engines/mads/nebular/nebular_scenes8.cpp +++ b/engines/mads/nebular/nebular_scenes8.cpp @@ -1604,7 +1604,8 @@ void Scene810::enter() { } void Scene810::step() { - if ((_scene->_activeAnimation->getCurrentFrame() == 200) && _moveAllowed) { + if (_scene->_activeAnimation && (_scene->_activeAnimation->getCurrentFrame() == 200) + && _moveAllowed) { _scene->_sequences.addTimer(100, 70); _moveAllowed = false; } -- cgit v1.2.3 From c80c74e49926daed108f73e115fda7ba5901eb61 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 7 Mar 2015 17:01:07 -0500 Subject: MADS: Refactoring of text/animation views to show outside game loop --- engines/mads/game.cpp | 25 +++++++------- engines/mads/nebular/game_nebular.cpp | 56 ++++++++++++++++++-------------- engines/mads/nebular/menu_nebular.cpp | 2 ++ engines/mads/nebular/nebular_scenes8.cpp | 6 ++-- 4 files changed, 50 insertions(+), 39 deletions(-) (limited to 'engines') diff --git a/engines/mads/game.cpp b/engines/mads/game.cpp index 3b8b053fec..74c2a3f416 100644 --- a/engines/mads/game.cpp +++ b/engines/mads/game.cpp @@ -105,8 +105,6 @@ Game::~Game() { } void Game::run() { - initializeGlobals(); - // If requested, load a savegame instead of showing the intro if (ConfMan.hasKey("save_slot")) { int saveSlot = ConfMan.getInt("save_slot"); @@ -116,15 +114,19 @@ void Game::run() { _statusFlag = true; - if (_loadGameSlot == -1) { - startGame(); - } + while (!_vm->shouldQuit()) { + initializeGlobals(); - // Get the initial starting time for the first scene - _scene._frameStartTime = _vm->_events->getFrameCounter(); + if (_loadGameSlot == -1) { + startGame(); + } + + // Get the initial starting time for the first scene + _scene._frameStartTime = _vm->_events->getFrameCounter(); - if (!_vm->shouldQuit()) - gameLoop(); + if (!_vm->shouldQuit()) + gameLoop(); + } } void Game::splitQuote(const Common::String &source, Common::String &line1, Common::String &line2) { @@ -140,7 +142,7 @@ void Game::splitQuote(const Common::String &source, Common::String &line1, Commo } void Game::gameLoop() { - while (!_vm->shouldQuit() && _statusFlag) { + while (!_vm->shouldQuit() && _statusFlag && !_winStatus) { if (_loadGameSlot != -1) { loadGame(_loadGameSlot); _loadGameSlot = -1; @@ -168,7 +170,8 @@ void Game::gameLoop() { } void Game::sectionLoop() { - while (!_vm->shouldQuit() && _statusFlag && (_sectionNumber == _currentSectionNumber)) { + while (!_vm->shouldQuit() && _statusFlag && !_winStatus && + (_sectionNumber == _currentSectionNumber)) { _kernelMode = KERNEL_ROOM_PRELOAD; _player._spritesChanged = true; _quoteEmergency = false; diff --git a/engines/mads/nebular/game_nebular.cpp b/engines/mads/nebular/game_nebular.cpp index 965ef7fad2..8c8d4ab974 100644 --- a/engines/mads/nebular/game_nebular.cpp +++ b/engines/mads/nebular/game_nebular.cpp @@ -61,6 +61,35 @@ ProtectionResult GameNebular::checkCopyProtection() { } void GameNebular::startGame() { + // First handle any ending credits from a just finished game session. + // Note that, with the exception of the decompression ending, which doesn't + // use animations, the remaining animations will automatically launch their + // own text view credits when the animation is completed + switch (_winStatus) { + case 1: + // No shields failure ending + AnimationView::execute(_vm, "rexend1"); + break; + case 2: + // Shields, but no targetting failure ending + AnimationView::execute(_vm, "rexend2"); + break; + case 3: + // Completed game successfully, so activate quotes item on the main menu + ConfMan.setBool("ShowQuotes", true); + ConfMan.flushToDisk(); + + AnimationView::execute(_vm, "rexend3"); + break; + case 4: + // Decompression ending + TextView::execute(_vm, "ending4"); + break; + } + + checkShowDialog(); + _winStatus = 0; + /* // Check copy protection ProtectionResult protectionResult = checkCopyProtection(); @@ -310,32 +339,9 @@ void GameNebular::setSectionHandler() { } void GameNebular::checkShowDialog() { - // Handling to start endgame sequences if the win/lose type has been set - switch (_winStatus) { - case 1: - // No shields failure ending - AnimationView::execute(_vm, "rexend1"); - break; - case 2: - // Shields, but no targetting failure ending - AnimationView::execute(_vm, "rexend2"); - break; - case 3: - // Completed game successfully, so activate quotes item on the main menu - ConfMan.setBool("ShowQuotes", true); - ConfMan.flushToDisk(); - - AnimationView::execute(_vm, "rexend3"); - break; - case 4: - // Decompression ending - TextView::execute(_vm, "ending4"); - break; - } - _winStatus = 0; - // Loop for showing dialogs, if any need to be shown - if (_vm->_dialogs->_pendingDialog && _player._stepEnabled && !_globals[kCopyProtectFailed]) { + if (_vm->_dialogs->_pendingDialog && (_player._stepEnabled || _winStatus) + && !_globals[kCopyProtectFailed]) { _player.releasePlayerSprites(); // Make a thumbnail in case it's needed for making a savegame diff --git a/engines/mads/nebular/menu_nebular.cpp b/engines/mads/nebular/menu_nebular.cpp index 2fdef3443d..358a978cfa 100644 --- a/engines/mads/nebular/menu_nebular.cpp +++ b/engines/mads/nebular/menu_nebular.cpp @@ -136,12 +136,14 @@ void MainMenu::doFrame() { addSpriteSlot(); } + _vm->_events->setCursor(CURSOR_ARROW); _vm->_events->showCursor(); } else { if ((_menuItemIndex == -1) || (_frameIndex == 0)) { if (++_menuItemIndex == 6) { // Reached end of display animation + _vm->_events->setCursor(CURSOR_ARROW); _vm->_events->showCursor(); return; } else if (_menuItemIndex == 4 && !shouldShowQuotes()) { diff --git a/engines/mads/nebular/nebular_scenes8.cpp b/engines/mads/nebular/nebular_scenes8.cpp index 4b8d7d5dd8..8a30f88548 100644 --- a/engines/mads/nebular/nebular_scenes8.cpp +++ b/engines/mads/nebular/nebular_scenes8.cpp @@ -719,7 +719,7 @@ void Scene803::step() { else _game._winStatus = 3; - _vm->quitGame(); + return; } } @@ -957,7 +957,7 @@ void Scene804::step() { assert(!_globals[kCopyProtectFailed]); _game._winStatus = 4; - _vm->quitGame(); + return; } break; @@ -969,7 +969,7 @@ void Scene804::step() { assert(!_globals[kCopyProtectFailed]); _game._winStatus = 4; - _vm->quitGame(); + return; } } -- cgit v1.2.3 From dacd7d4022ef049fbcf59a3b555b6d9ee8c1511e Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 7 Mar 2015 17:14:49 -0500 Subject: MADS: Correctly show main menu after showing credits --- engines/mads/nebular/dialogs_nebular.cpp | 2 +- engines/mads/nebular/game_nebular.cpp | 2 ++ engines/mads/nebular/menu_nebular.cpp | 2 -- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/mads/nebular/dialogs_nebular.cpp b/engines/mads/nebular/dialogs_nebular.cpp index 6985455d2a..23aef6bdb5 100644 --- a/engines/mads/nebular/dialogs_nebular.cpp +++ b/engines/mads/nebular/dialogs_nebular.cpp @@ -328,7 +328,7 @@ void DialogsNebular::showDialog() { TextView *dlg = new RexTextView(_vm); dlg->show(); delete dlg; - break; + return; } case DIALOG_ANIMVIEW: { AnimationView *dlg = new RexAnimationView(_vm); diff --git a/engines/mads/nebular/game_nebular.cpp b/engines/mads/nebular/game_nebular.cpp index 8c8d4ab974..ce3b5a8f58 100644 --- a/engines/mads/nebular/game_nebular.cpp +++ b/engines/mads/nebular/game_nebular.cpp @@ -110,7 +110,9 @@ void GameNebular::startGame() { } */ + _sectionNumber = 1; initSection(_sectionNumber); + _vm->_events->setCursor(CURSOR_ARROW); _statusFlag = true; // Show the main menu diff --git a/engines/mads/nebular/menu_nebular.cpp b/engines/mads/nebular/menu_nebular.cpp index 358a978cfa..2fdef3443d 100644 --- a/engines/mads/nebular/menu_nebular.cpp +++ b/engines/mads/nebular/menu_nebular.cpp @@ -136,14 +136,12 @@ void MainMenu::doFrame() { addSpriteSlot(); } - _vm->_events->setCursor(CURSOR_ARROW); _vm->_events->showCursor(); } else { if ((_menuItemIndex == -1) || (_frameIndex == 0)) { if (++_menuItemIndex == 6) { // Reached end of display animation - _vm->_events->setCursor(CURSOR_ARROW); _vm->_events->showCursor(); return; } else if (_menuItemIndex == 4 && !shouldShowQuotes()) { -- cgit v1.2.3 From 27b6ded6f95fdc01faa5816b8577464685357c2d Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 7 Mar 2015 17:18:51 -0500 Subject: MADS: Fix Credits and Quotes option on the main menu --- engines/mads/nebular/game_nebular.cpp | 41 ++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 20 deletions(-) (limited to 'engines') diff --git a/engines/mads/nebular/game_nebular.cpp b/engines/mads/nebular/game_nebular.cpp index ce3b5a8f58..53cdc4df13 100644 --- a/engines/mads/nebular/game_nebular.cpp +++ b/engines/mads/nebular/game_nebular.cpp @@ -87,38 +87,39 @@ void GameNebular::startGame() { break; } - checkShowDialog(); - _winStatus = 0; - - /* - // Check copy protection - ProtectionResult protectionResult = checkCopyProtection(); - switch (protectionResult) { - case PROTECTION_FAIL: + do { + checkShowDialog(); + _winStatus = 0; + + /* + // Check copy protection + ProtectionResult protectionResult = checkCopyProtection(); + switch (protectionResult) { + case PROTECTION_FAIL: // Copy protection failed _scene._nextSceneId = 804; initializeGlobals(); _globals[kCopyProtectFailed] = true; return; - case PROTECTION_ESCAPE: + case PROTECTION_ESCAPE: // User escaped out of copy protection dialog _vm->quitGame(); return; - default: + default: // Copy protection check succeeded break; - } - */ + } + */ - _sectionNumber = 1; - initSection(_sectionNumber); - _vm->_events->setCursor(CURSOR_ARROW); - _statusFlag = true; + _sectionNumber = 1; + initSection(_sectionNumber); + _vm->_events->setCursor(CURSOR_ARROW); + _statusFlag = true; - // Show the main menu - _vm->_dialogs->_pendingDialog = DIALOG_MAIN_MENU; - _vm->_dialogs->showDialog(); - _vm->_dialogs->_pendingDialog = DIALOG_NONE; + // Show the main menu + _vm->_dialogs->_pendingDialog = DIALOG_MAIN_MENU; + _vm->_dialogs->showDialog(); + } while (!_vm->shouldQuit() && _vm->_dialogs->_pendingDialog != DIALOG_NONE); _priorSectionNumber = 0; _priorSectionNumber = -1; -- cgit v1.2.3 From d7460701ea345dbe6d610b98a9c14993ff2f1f88 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 7 Mar 2015 17:36:32 -0500 Subject: MADS: Fix not being able to leave hanger via teleporter --- engines/mads/nebular/nebular_scenes8.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes8.cpp b/engines/mads/nebular/nebular_scenes8.cpp index 8a30f88548..24a1855c36 100644 --- a/engines/mads/nebular/nebular_scenes8.cpp +++ b/engines/mads/nebular/nebular_scenes8.cpp @@ -145,10 +145,10 @@ void Scene801::enter() { case 2: _game._player._playerPos = Common::Point(8, 117); _globals[kTeleporterUnderstood] = true; - _globals._sequenceIndexes[1] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[1], false, 8, 1, 0, 0); + _globals._sequenceIndexes[1] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[1], false, 8, 1, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 1, 13); _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; - _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 8090); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 80); _vm->_sound->command(30); break; -- cgit v1.2.3 From adc5b5ca2e3b967d51685fec749fc0864b55fa8f Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 7 Mar 2015 17:39:00 -0500 Subject: MADS: Fix animation for teleporting into conveyor belt scene --- engines/mads/nebular/nebular_scenes4.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes4.cpp b/engines/mads/nebular/nebular_scenes4.cpp index 8a9e510591..8191d7fe49 100644 --- a/engines/mads/nebular/nebular_scenes4.cpp +++ b/engines/mads/nebular/nebular_scenes4.cpp @@ -4078,7 +4078,7 @@ void Scene413::enter() { case 1: _vm->_sound->command(30); _game._player._visible = false; - _globals._sequenceIndexes[1] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[1], false, 7, 1, 0, 0); + _globals._sequenceIndexes[1] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[1], false, 7, 1, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 1, 19); _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 8); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 76); -- cgit v1.2.3 From a35aa07c7911010d21bb79209d88b07ddbfd7c30 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 7 Mar 2015 17:43:15 -0500 Subject: MADS: Fix crash looking at fishing rod in restaurant --- engines/mads/nebular/nebular_scenes5.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes5.cpp b/engines/mads/nebular/nebular_scenes5.cpp index dea5f678c4..b297d2048c 100644 --- a/engines/mads/nebular/nebular_scenes5.cpp +++ b/engines/mads/nebular/nebular_scenes5.cpp @@ -2427,7 +2427,8 @@ void Scene512::actions() { _vm->_dialogs->show(51225); else if (_action.isAction(VERB_LOOK, NOUN_PADLOCK_KEY) && _game._objects.isInRoom(OBJ_PADLOCK_KEY)) _vm->_dialogs->show(51215); - else if (_action.isAction(VERB_LOOK, NOUN_FISHING_ROD) && (_scene->_activeAnimation->getCurrentFrame() == 4)) + else if (_action.isAction(VERB_LOOK, NOUN_FISHING_ROD) && (!_scene->_activeAnimation || + _scene->_activeAnimation->getCurrentFrame() == 4)) _vm->_dialogs->show(51216); else if (_action.isAction(VERB_LOOK, NOUN_SHIPS_WHEEL)) _vm->_dialogs->show(51218); -- cgit v1.2.3 From 14a8bb52a0fd92ed1033473d5941a36d5be32d18 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 7 Mar 2015 18:33:11 -0500 Subject: MADS: Fix a large number of incorrect animations --- engines/mads/nebular/nebular_scenes1.cpp | 2 +- engines/mads/nebular/nebular_scenes2.cpp | 2 +- engines/mads/nebular/nebular_scenes3.cpp | 6 +++--- engines/mads/nebular/nebular_scenes4.cpp | 4 ++-- engines/mads/nebular/nebular_scenes5.cpp | 8 ++++---- engines/mads/nebular/nebular_scenes7.cpp | 12 ++++++------ 6 files changed, 17 insertions(+), 17 deletions(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes1.cpp b/engines/mads/nebular/nebular_scenes1.cpp index f21ab94bcb..d505bb3d4e 100644 --- a/engines/mads/nebular/nebular_scenes1.cpp +++ b/engines/mads/nebular/nebular_scenes1.cpp @@ -1459,7 +1459,7 @@ void Scene103::actions() { default: break; } - } else if (_action.isAction(VERB_TAKE, 289, 0) && _game._objects.isInRoom(OBJ_REBREATHER)) { + } else if (_action.isAction(VERB_TAKE, NOUN_REBREATHER, 0) && _game._objects.isInRoom(OBJ_REBREATHER)) { switch (_vm->_game->_trigger) { case 0: _scene->changeVariant(1); diff --git a/engines/mads/nebular/nebular_scenes2.cpp b/engines/mads/nebular/nebular_scenes2.cpp index 2eb7f93a60..bd8e8aae82 100644 --- a/engines/mads/nebular/nebular_scenes2.cpp +++ b/engines/mads/nebular/nebular_scenes2.cpp @@ -556,7 +556,7 @@ void Scene202::step() { case 90: _vm->_sound->command(41); _scene->_sequences.remove(_globals._sequenceIndexes[10]); - _globals._sequenceIndexes[9] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[9], true, 6, 1, 0, 0); + _globals._sequenceIndexes[9] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[9], true, 6, 1, 0, 0); _scene->_sequences.setPosition(_globals._sequenceIndexes[9], Common::Point(247, 82)); _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 1); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 0, 91); diff --git a/engines/mads/nebular/nebular_scenes3.cpp b/engines/mads/nebular/nebular_scenes3.cpp index 478a733485..61618ff7e3 100644 --- a/engines/mads/nebular/nebular_scenes3.cpp +++ b/engines/mads/nebular/nebular_scenes3.cpp @@ -2523,7 +2523,7 @@ void Scene318::handleDialog() { case 0x19C: case 0x19D: _scene->_sequences.remove(_globals._sequenceIndexes[2]); - _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(142, 121)); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 6, 8); @@ -3588,7 +3588,7 @@ void Scene320::setLeftView(int view) { _scene->_sequences.remove(_globals._sequenceIndexes[0]); if (view != 10) { - _globals._sequenceIndexes[0] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[view], false, 6, 0, 0, 18); + _globals._sequenceIndexes[0] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[view], false, 6, 0, 0, 18); _scene->_sequences.setDepth(_globals._sequenceIndexes[0], 0); if (!_blinkFl) _scene->_sequences.setAnimRange(_globals._sequenceIndexes[0], 2, 2); @@ -4305,7 +4305,7 @@ void Scene352::preActions() { _game._player._stepEnabled = false; _scene->_sequences.remove(_commonSequenceIdx); _vm->_sound->command(20); - _commonSequenceIdx = _scene->_sequences.startPingPongCycle(_commonSpriteIndex, false, 6, 1, 0, 0); + _commonSequenceIdx = _scene->_sequences.addReverseSpriteCycle(_commonSpriteIndex, false, 6, 1, 0, 0); _scene->_sequences.addSubEntry(_commonSequenceIdx, SEQUENCE_TRIGGER_EXPIRE, 0, 1); _scene->_sequences.setDepth(_commonSequenceIdx, 15); } diff --git a/engines/mads/nebular/nebular_scenes4.cpp b/engines/mads/nebular/nebular_scenes4.cpp index 8191d7fe49..9db597c312 100644 --- a/engines/mads/nebular/nebular_scenes4.cpp +++ b/engines/mads/nebular/nebular_scenes4.cpp @@ -2445,7 +2445,7 @@ void Scene405::step() { if (_game._trigger == 70) { _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount ; _game._player._visible = true; - _globals._sequenceIndexes[1] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0); + _globals._sequenceIndexes[1] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 71); _vm->_sound->command(19); } @@ -2609,7 +2609,7 @@ void Scene406::enter() { else { _game._player._stepEnabled = false; _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; - _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 3, 1, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[3], false, 3, 1, 0, 0); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 90); _vm->_sound->command(19); } diff --git a/engines/mads/nebular/nebular_scenes5.cpp b/engines/mads/nebular/nebular_scenes5.cpp index b297d2048c..f520fd5ed0 100644 --- a/engines/mads/nebular/nebular_scenes5.cpp +++ b/engines/mads/nebular/nebular_scenes5.cpp @@ -238,7 +238,7 @@ void Scene501::step() { break; case 82: - _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 9, 1, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[3], false, 9, 1, 0, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 7); _vm->_sound->command(12); _doorHotspotid = _scene->_dynamicHotspots.add(NOUN_DOOR, VERB_WALK_THROUGH, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0)); @@ -415,7 +415,7 @@ void Scene501::actions() { case 7: { _vm->_sound->command(12); int syncIdx = _globals._sequenceIndexes[3]; - _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 9, 1, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[3], false, 9, 1, 0, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 7); _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], syncIdx); _vm->_sound->command(12); @@ -913,7 +913,7 @@ void Scene505::enter() { _globals._spriteIndexes[12] = _scene->_sprites.addSprites(formAnimName('e', -1)); if (_scene->_priorSceneId != -2) - _globals._sequenceIndexes[12] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[12], false, 6, 1, 0, 0); + _globals._sequenceIndexes[12] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[12], false, 6, 1, 0, 0); _globals._sequenceIndexes[13] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[13], false, 6, 1, 120, 0); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 60); @@ -2530,7 +2530,7 @@ void Scene513::step() { case 80: _game._player._stepEnabled = false; _scene->_sequences.remove(_globals._sequenceIndexes[2]); - _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 2); _vm->_sound->command(24); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 81); diff --git a/engines/mads/nebular/nebular_scenes7.cpp b/engines/mads/nebular/nebular_scenes7.cpp index 4838ee27d9..006b3ca6ec 100644 --- a/engines/mads/nebular/nebular_scenes7.cpp +++ b/engines/mads/nebular/nebular_scenes7.cpp @@ -206,7 +206,7 @@ void Scene701::step() { switch(_game._trigger) { case 60: _scene->_sequences.remove(_globals._sequenceIndexes[5]); - _globals._sequenceIndexes[5] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[5], false, 6, 1, 0, 0); + _globals._sequenceIndexes[5] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[5], false, 6, 1, 0, 0); _scene->_sequences.setPosition(_globals._sequenceIndexes[5], Common::Point(155, 129)); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 61); break; @@ -326,7 +326,7 @@ void Scene701::actions() { case 3: _vm->_sound->command(17); - _globals._sequenceIndexes[1] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[1], false, 5, 1, 0, 0); + _globals._sequenceIndexes[1] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[1], false, 5, 1, 0, 0); _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136)); _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 4); @@ -1585,7 +1585,7 @@ void Scene705::enter() { void Scene705::step() { switch (_game._trigger) { case 70: - _globals._sequenceIndexes[3] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[3], false, 9, 1, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[3], false, 9, 1, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 4); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 71); break; @@ -2248,7 +2248,7 @@ void Scene751::step() { switch (_game._trigger) { case 70: _scene->_sequences.remove(_globals._sequenceIndexes[4]); - _globals._sequenceIndexes[4] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[4], false, 6, 1, 0, 0); + _globals._sequenceIndexes[4] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[4], false, 6, 1, 0, 0); _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(155, 129)); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 71); break; @@ -2329,7 +2329,7 @@ void Scene751::preActions() { _game._player._readyToWalk = false; _game._player._stepEnabled = false; _scene->_sequences.remove(_globals._sequenceIndexes[2]); - _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], false, 11, 1, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[2], false, 11, 1, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], -1, 7); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 1); break; @@ -2398,7 +2398,7 @@ void Scene751::actions() { case 3: _vm->_sound->command(17); - _globals._sequenceIndexes[1] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[1], false, 5, 1, 0, 0); + _globals._sequenceIndexes[1] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[1], false, 5, 1, 0, 0); _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136)); _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 4); -- cgit v1.2.3 From 10361d077a5637f4e64620011b67190bfdeaaf9b Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 8 Mar 2015 11:18:10 -0400 Subject: MADS: Fix game startup settings for pit & batteries based on difficulty --- engines/mads/nebular/game_nebular.cpp | 6 ++++-- engines/mads/nebular/nebular_scenes2.cpp | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/mads/nebular/game_nebular.cpp b/engines/mads/nebular/game_nebular.cpp index 53cdc4df13..6de7ad9932 100644 --- a/engines/mads/nebular/game_nebular.cpp +++ b/engines/mads/nebular/game_nebular.cpp @@ -280,7 +280,9 @@ void GameNebular::initializeGlobals() { _objects.setRoom(OBJ_PLANT_STALK, NOWHERE); _objects.setRoom(OBJ_PENLIGHT, NOWHERE); - _globals[kLeavesStatus] = LEAVES_ON_TRAP; + _globals[kLeavesStatus] = LEAVES_ON_GROUND; + _globals[kDurafailRecharged] = 0; + _globals[kPenlightCellStatus] = FIRST_TIME_UNCHARGED_DURAFAIL; break; case DIFFICULTY_MEDIUM: @@ -295,7 +297,7 @@ void GameNebular::initializeGlobals() { _objects.setRoom(OBJ_BLOWGUN, NOWHERE); _objects.setRoom(OBJ_NOTE, NOWHERE); - _globals[kLeavesStatus] = LEAVES_ON_GROUND; + _globals[kLeavesStatus] = LEAVES_ON_TRAP; _globals[kPenlightCellStatus] = FIRST_TIME_UNCHARGED_DURAFAIL; _globals[kDurafailRecharged] = 0; break; diff --git a/engines/mads/nebular/nebular_scenes2.cpp b/engines/mads/nebular/nebular_scenes2.cpp index bd8e8aae82..499073e28a 100644 --- a/engines/mads/nebular/nebular_scenes2.cpp +++ b/engines/mads/nebular/nebular_scenes2.cpp @@ -1686,14 +1686,14 @@ void Scene208::updateTrap() { } switch (_globals[kLeavesStatus]) { - case 0: { + case LEAVES_ON_GROUND: { _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 1); _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 15); int idx = _scene->_dynamicHotspots.add(NOUN_PILE_OF_LEAVES, VERB_WALKTO, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0)); _scene->_dynamicHotspots.setPosition(idx, Common::Point(60, 152), FACING_NORTH); } break; - case 2: { + case LEAVES_ON_TRAP: { _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 15); _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); _scene->_hotspots.activate(NOUN_DEEP_PIT, false); -- cgit v1.2.3 From 2b1155711fe09bb71cc3678a70eca3aab7766885 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 8 Mar 2015 11:44:06 -0400 Subject: MADS: Fix showing covered pit by default in Easy mode --- engines/mads/nebular/nebular_scenes2.cpp | 17 ++++++++--------- engines/mads/sequence.cpp | 14 +++++++------- engines/mads/sequence.h | 2 +- 3 files changed, 16 insertions(+), 17 deletions(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes2.cpp b/engines/mads/nebular/nebular_scenes2.cpp index 499073e28a..cb22a2312d 100644 --- a/engines/mads/nebular/nebular_scenes2.cpp +++ b/engines/mads/nebular/nebular_scenes2.cpp @@ -1697,7 +1697,7 @@ void Scene208::updateTrap() { _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 15); _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); _scene->_hotspots.activate(NOUN_DEEP_PIT, false); - int idx = _scene->_dynamicHotspots.add(NOUN_LEAF_COVERED_PIT, VERB_WALKTO, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0)); + int idx = _scene->_dynamicHotspots.add(NOUN_LEAF_COVERED_PIT, VERB_WALKTO, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0)); _scene->_dynamicHotspots.setPosition(idx, Common::Point(100, 146), FACING_NORTH); _scene->_dynamicHotspots[idx]._articleNumber = PREP_ON; } @@ -1796,7 +1796,6 @@ void Scene208::preActions() { } void Scene208::subAction(int mode) { - switch (_game._trigger) { case 0: { _game._player._stepEnabled = false; @@ -1804,21 +1803,21 @@ void Scene208::subAction(int mode) { _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 6, 1, 0, 0); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); - int abortVal; + int endTrigger; if ((mode == 1) || (mode == 2)) - abortVal = 1; + endTrigger = 1; else - abortVal = 2; + endTrigger = 2; - _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, abortVal); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, endTrigger); } break; case 1: { - int oldVal = _globals._sequenceIndexes[5]; - _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 12, 3, 0, 0); + int oldSeq = _globals._sequenceIndexes[5]; + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 12, 3, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 3, 4); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); - _scene->_sequences.updateTimeout(_globals._sequenceIndexes[5], oldVal); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[5], oldSeq); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 2); _vm->_sound->command(20); } diff --git a/engines/mads/sequence.cpp b/engines/mads/sequence.cpp index ab73d70b10..7dbf4cf3be 100644 --- a/engines/mads/sequence.cpp +++ b/engines/mads/sequence.cpp @@ -95,8 +95,8 @@ bool SequenceList::addSubEntry(int index, SequenceTrigger mode, int frameIndex, } int SequenceList::add(int spriteListIndex, bool flipped, int frameIndex, int triggerCountdown, int delayTicks, int extraTicks, int numTicks, - int msgX, int msgY, bool nonFixed, int scale, int depth, int frameInc, SpriteAnimType animType, int numSprites, - int frameStart) { + int msgX, int msgY, bool nonFixed, int scale, int depth, int frameInc, SpriteAnimType animType, int numSprites, + int frameStart) { Scene &scene = _vm->_game->_scene; // Find a free slot @@ -477,17 +477,17 @@ int SequenceList::startPingPongCycle(int srcSpriteIndex, bool flipped, int numTi extraTicks, numTicks, 0, 0, true, 100, depth - 1, 1, ANIMTYPE_PING_PONG, 0, 0); } -void SequenceList::updateTimeout(int spriteIdx, int seqIndex) { +void SequenceList::updateTimeout(int srcSeqIndex, int destSeqIndex) { Player &player = _vm->_game->_player; int timeout; - if (spriteIdx >= 0) - timeout = _entries[spriteIdx]._timeout; + if (srcSeqIndex >= 0) + timeout = _entries[srcSeqIndex]._timeout; else timeout = player._priorTimer + player._ticksAmount; - if (seqIndex >= 0) - _entries[seqIndex]._timeout = timeout; + if (destSeqIndex >= 0) + _entries[destSeqIndex]._timeout = timeout; else player._priorTimer = timeout - player._ticksAmount; diff --git a/engines/mads/sequence.h b/engines/mads/sequence.h index 9603296717..1555232780 100644 --- a/engines/mads/sequence.h +++ b/engines/mads/sequence.h @@ -119,7 +119,7 @@ public: int startCycle(int srcSpriteIdx, bool flipped, int cycleIndex); int startPingPongCycle(int srcSpriteIndex, bool flipped, int numTicks, int triggerCountdown = 0, int timeoutTicks = 0, int extraTicks = 0); - void updateTimeout(int spriteIdx, int seqIndex); + void updateTimeout(int destSeqIndex, int srcSeqIndex); void setScale(int spriteIdx, int scale); void setMsgLayout(int seqIndex); void setDone(int seqIndex); -- cgit v1.2.3 From 6454c5f35d2fa7d749266bcdb9346944dd6709d0 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 8 Mar 2015 11:49:47 -0400 Subject: MADS: Fix closing door animation for video store --- engines/mads/nebular/nebular_scenes6.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes6.cpp b/engines/mads/nebular/nebular_scenes6.cpp index c862017462..11e3ff78b0 100644 --- a/engines/mads/nebular/nebular_scenes6.cpp +++ b/engines/mads/nebular/nebular_scenes6.cpp @@ -2690,7 +2690,7 @@ void Scene609::enterStore() { case 7: _scene->_sequences.remove(_globals._sequenceIndexes[2]); - _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 9); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 8); break; -- cgit v1.2.3 From b25325599d4b88c323d3bf3319f7b6ee78f2e4c4 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 8 Mar 2015 12:05:54 -0400 Subject: MADS: Fix for penlight when starting a new game in Hard mode --- engines/mads/nebular/game_nebular.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/mads/nebular/game_nebular.cpp b/engines/mads/nebular/game_nebular.cpp index 6de7ad9932..cde998e66a 100644 --- a/engines/mads/nebular/game_nebular.cpp +++ b/engines/mads/nebular/game_nebular.cpp @@ -277,8 +277,8 @@ void GameNebular::initializeGlobals() { // Final setup based on selected difficulty level switch (_difficulty) { case DIFFICULTY_HARD: - _objects.setRoom(OBJ_PLANT_STALK, NOWHERE); - _objects.setRoom(OBJ_PENLIGHT, NOWHERE); + _objects.setRoom(OBJ_BLOWGUN, NOWHERE); + _objects.setRoom(OBJ_NOTE, NOWHERE); _globals[kLeavesStatus] = LEAVES_ON_GROUND; _globals[kDurafailRecharged] = 0; @@ -294,12 +294,10 @@ void GameNebular::initializeGlobals() { break; case DIFFICULTY_EASY: - _objects.setRoom(OBJ_BLOWGUN, NOWHERE); - _objects.setRoom(OBJ_NOTE, NOWHERE); + _objects.setRoom(OBJ_PLANT_STALK, NOWHERE); + _objects.setRoom(OBJ_PENLIGHT, NOWHERE); _globals[kLeavesStatus] = LEAVES_ON_TRAP; - _globals[kPenlightCellStatus] = FIRST_TIME_UNCHARGED_DURAFAIL; - _globals[kDurafailRecharged] = 0; break; } -- cgit v1.2.3 From 62c1485df2ab17ab18b377b49055c6fcd6a6b15c Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 8 Mar 2015 19:51:33 -0400 Subject: MADS: Fix flickering message from sitting at ruined security desk --- engines/mads/nebular/nebular_scenes3.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes3.cpp b/engines/mads/nebular/nebular_scenes3.cpp index 61618ff7e3..2febbf6bbd 100644 --- a/engines/mads/nebular/nebular_scenes3.cpp +++ b/engines/mads/nebular/nebular_scenes3.cpp @@ -5466,7 +5466,7 @@ void Scene361::actions() { _vm->_dialogs->show(36119); else if (_action.isAction(VERB_SIT_AT, NOUN_DESK)) { _scene->_kernelMessages.reset(); - _scene->_kernelMessages.addQuote(0xFC, 120, 0); + _scene->_kernelMessages.addQuote(252, 0, 120); } else if (_action.isAction(VERB_CLIMB_INTO, NOUN_AIR_VENT)) { if (_globals[kSexOfRex] == REX_FEMALE) handleRoxAction(); -- cgit v1.2.3 From 29ac19947f5c95a5133bc7d6f8ee75a0719fe58d Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 8 Mar 2015 19:54:00 -0400 Subject: MADS: Rename some outstanding 'abortTimers' to the more proper 'endTrigger' --- engines/mads/messages.cpp | 10 +++++----- engines/mads/messages.h | 4 ++-- engines/mads/nebular/nebular_scenes2.cpp | 10 +++++----- 3 files changed, 12 insertions(+), 12 deletions(-) (limited to 'engines') diff --git a/engines/mads/messages.cpp b/engines/mads/messages.cpp index e83b69d210..4b105630d6 100644 --- a/engines/mads/messages.cpp +++ b/engines/mads/messages.cpp @@ -69,7 +69,7 @@ void KernelMessages::clear() { } int KernelMessages::add(const Common::Point &pt, uint fontColor, uint8 flags, - uint8 abortTimers, uint32 timeout, const Common::String &msg) { + int endTrigger, uint32 timeout, const Common::String &msg) { Scene &scene = _vm->_game->_scene; // Find a free slot @@ -77,7 +77,7 @@ int KernelMessages::add(const Common::Point &pt, uint fontColor, uint8 flags, while ((idx < _entries.size()) && ((_entries[idx]._flags & KMSG_ACTIVE) != 0)) ++idx; if (idx == _entries.size()) { - if (abortTimers == 0) + if (endTrigger == 0) return -1; error("KernelMessages overflow"); @@ -92,7 +92,7 @@ int KernelMessages::add(const Common::Point &pt, uint fontColor, uint8 flags, rec._textDisplayIndex = -1; rec._timeout = timeout; rec._frameTimer = _vm->_game->_priorFrameTimer; - rec._trigger = abortTimers; + rec._trigger = endTrigger; rec._abortMode = _vm->_game->_triggerSetupMode; rec._actionDetails = scene._action._activeAction; @@ -104,10 +104,10 @@ int KernelMessages::add(const Common::Point &pt, uint fontColor, uint8 flags, return idx; } -int KernelMessages::addQuote(int quoteId, int abortTimers, uint32 timeout) { +int KernelMessages::addQuote(int quoteId, int endTrigger, uint32 timeout) { Common::String quoteStr = _vm->_game->getQuote(quoteId); return add(Common::Point(), 0x1110, KMSG_PLAYER_TIMEOUT | KMSG_CENTER_ALIGN, - abortTimers, timeout, quoteStr); + endTrigger, timeout, quoteStr); } void KernelMessages::scrollMessage(int msgIndex, int numTicks, bool quoted) { diff --git a/engines/mads/messages.h b/engines/mads/messages.h index a7411d98d1..22ae0b24b5 100644 --- a/engines/mads/messages.h +++ b/engines/mads/messages.h @@ -99,9 +99,9 @@ public: ~KernelMessages(); void clear(); - int add(const Common::Point &pt, uint fontColor, uint8 flags, uint8 abortTimers, + int add(const Common::Point &pt, uint fontColor, uint8 flags, int endTrigger, uint32 timeout, const Common::String &msg); - int addQuote(int quoteId, int abortTimers, uint32 timeout); + int addQuote(int quoteId, int endTrigger, uint32 timeout); void scrollMessage(int msgIndex, int numTicks, bool quoted); void setSeqIndex(int msgIndex, int seqIndex); void remove(int msgIndex); diff --git a/engines/mads/nebular/nebular_scenes2.cpp b/engines/mads/nebular/nebular_scenes2.cpp index cb22a2312d..9d5e2185e8 100644 --- a/engines/mads/nebular/nebular_scenes2.cpp +++ b/engines/mads/nebular/nebular_scenes2.cpp @@ -165,16 +165,16 @@ void Scene201::enter() { int sepChar = (_globals[kSexOfRex] == SEX_MALE) ? 't' : 'u'; // Guess values. What is the default value used by the compiler? int suffixNum = -1; - int abortTimers = -1; + int endTrigger = -1; switch(_globals[kTeleporterCommand]) { case 1: suffixNum = 3; - abortTimers = 76; + endTrigger = 76; _globals[kTeleporterUnderstood] = true; break; case 2: suffixNum = 1; - abortTimers = 77; + endTrigger = 77; break; case 3: _game._player._visible = true; @@ -183,12 +183,12 @@ void Scene201::enter() { break; case 4: suffixNum = 2; - abortTimers = 78; + endTrigger = 78; break; } _globals[kTeleporterCommand] = 0; if (suffixNum >= 0) - _scene->loadAnimation(formAnimName(sepChar, suffixNum), abortTimers); + _scene->loadAnimation(formAnimName(sepChar, suffixNum), endTrigger); } if ((_scene->_priorSceneId == 202) && (_globals[kMeteorologistStatus] == METEOROLOGIST_PRESENT) && !_scene->_roomChanged) { -- cgit v1.2.3 From d048776ef3658a726e1a06666453b30f27188730 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 8 Mar 2015 20:44:19 -0400 Subject: MADS: Fix walking behind counter in software store --- engines/mads/nebular/nebular_scenes5.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes5.cpp b/engines/mads/nebular/nebular_scenes5.cpp index f520fd5ed0..8be52692c6 100644 --- a/engines/mads/nebular/nebular_scenes5.cpp +++ b/engines/mads/nebular/nebular_scenes5.cpp @@ -1547,7 +1547,9 @@ void Scene507::actions() { _vm->_dialogs->show(50724); else if (_action.isAction(VERB_LOOK, NOUN_WINDOW)) _vm->_dialogs->show(50725); - else if (_action.isAction(VERB_LOOK, NOUN_COUNTER)) { + else if (_action.isAction(NOUN_WALK_BEHIND, NOUN_COUNTER)) { + // WORkAROUND: Empty handling to prevent default "can't do that" dialogs showing + } else if (_action.isAction(VERB_LOOK, NOUN_COUNTER)) { if (_game._objects.isInRoom(OBJ_PENLIGHT)) _vm->_dialogs->show(50728); else -- cgit v1.2.3 From 1d76659da834d59b7a26c59951f6613d384bd532 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 8 Mar 2015 20:46:40 -0400 Subject: MADS: Fix walking behind counter at Sand Bar restaurant --- engines/mads/nebular/nebular_scenes5.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes5.cpp b/engines/mads/nebular/nebular_scenes5.cpp index 8be52692c6..7cdc55e03c 100644 --- a/engines/mads/nebular/nebular_scenes5.cpp +++ b/engines/mads/nebular/nebular_scenes5.cpp @@ -2463,7 +2463,9 @@ void Scene512::actions() { _vm->_dialogs->show(51233); else if (_action.isAction(VERB_LOOK, NOUN_LAMP)) _vm->_dialogs->show(51234); - else if (_action.isAction(VERB_LOOK, NOUN_COUNTER)) + else if (_action.isAction(NOUN_WALK_BEHIND, NOUN_COUNTER)) { + // WORkAROUND: Empty handling to prevent default "can't do that" dialogs showing + } else if (_action.isAction(VERB_LOOK, NOUN_COUNTER)) _vm->_dialogs->show(51235); else if (_action.isAction(VERB_LOOK, NOUN_ICE_CHESTS)) _vm->_dialogs->show(51237); -- cgit v1.2.3 From 6dd6e555133dfee1fa5647bfc9ba5cabc94a5ed9 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 8 Mar 2015 21:15:14 -0400 Subject: MADS: Fix prior conversation list showing when crawling in vents --- engines/mads/user_interface.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/mads/user_interface.cpp b/engines/mads/user_interface.cpp index a53ab31968..bcd409889e 100644 --- a/engines/mads/user_interface.cpp +++ b/engines/mads/user_interface.cpp @@ -410,13 +410,21 @@ void UserInterface::setup(InputMode inputMode) { } void UserInterface::drawTextElements() { - if (_vm->_game->_screenObjects._inputMode) { - drawConversationList(); - } else { + switch (_vm->_game->_screenObjects._inputMode) { + case kInputBuildingSentences: // Draw the actions drawActions(); drawInventoryList(); drawItemVocabList(); + break; + + case kInputConversation: + drawConversationList(); + break; + + case kInputLimitedSentences: + default: + break; } } -- cgit v1.2.3 From 3cb1a6dc553d5f8490728fb9fca39581d17723ed Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 8 Mar 2015 21:25:15 -0400 Subject: MADS: Fix looking at magazine at security station --- engines/mads/nebular/nebular_scenes3.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes3.cpp b/engines/mads/nebular/nebular_scenes3.cpp index 2febbf6bbd..faf21aaa42 100644 --- a/engines/mads/nebular/nebular_scenes3.cpp +++ b/engines/mads/nebular/nebular_scenes3.cpp @@ -3825,7 +3825,7 @@ void Scene320::actions() { else if (_action.isAction(VERB_LOOK, NOUN_DOUGHNUT)) _vm->_dialogs->show(32006); else if (_action.isAction(VERB_LOOK, NOUN_MAGAZINE)) - _vm->_dialogs->show(32006); + _vm->_dialogs->show(32007); else if (_action.isAction(VERB_LOOK, NOUN_PAPER_FOOTBALL)) _vm->_dialogs->show(32008); else if (_action.isAction(VERB_LOOK, NOUN_NEWSPAPER)) -- cgit v1.2.3 From 9ec28cb27f1f637cc407c6b1b50dc87aece0507f Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 8 Mar 2015 21:38:28 -0400 Subject: MADS: Fix trying to walk into corridor from security station --- engines/mads/nebular/nebular_scenes3.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes3.cpp b/engines/mads/nebular/nebular_scenes3.cpp index faf21aaa42..2ea476008f 100644 --- a/engines/mads/nebular/nebular_scenes3.cpp +++ b/engines/mads/nebular/nebular_scenes3.cpp @@ -1749,7 +1749,7 @@ void Scene311::actions() { else if (_checkGuardFl) { _checkGuardFl = false; _scene->_kernelMessages.reset(); - _scene->_kernelMessages.addQuote(0xFA, 120, 0); + _scene->_kernelMessages.addQuote(250, 0, 240); } else if (_action.isAction(VERB_SIT_AT, NOUN_DESK)) _scene->_nextSceneId = 320; else if (_action.isAction(VERB_CLIMB_INTO, NOUN_AIR_VENT)) { -- cgit v1.2.3 From aad048674b3d63c05742ce9091416ad5465cb541 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 8 Mar 2015 22:34:40 -0400 Subject: MADS: Fix unused variable warning --- engines/mads/screen.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/mads/screen.cpp b/engines/mads/screen.cpp index 8db034c467..6199da5925 100644 --- a/engines/mads/screen.cpp +++ b/engines/mads/screen.cpp @@ -685,7 +685,6 @@ void ScreenSurface::panTransition(MSurface &newScreen, byte *palData, int entryS int y1, y2; int startX = 0; int deltaX; - int sizeY; int xAt; int loopStart; // uint32 baseTicks, currentTicks; @@ -712,7 +711,7 @@ void ScreenSurface::panTransition(MSurface &newScreen, byte *palData, int entryS y1 = 0; y2 = size.y - 1; - sizeY = y2 - y1 + 1; +// sizeY = y2 - y1 + 1; if (throughBlack == THROUGH_BLACK2) swapForeground(palData, &paletteMap[0]); -- cgit v1.2.3 From cc0b88cc532d7708e13a6a9e22da2595223b8e49 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 8 Mar 2015 23:40:50 -0400 Subject: MADS: Fix leak of SpriteAsset instances --- engines/mads/sprites.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines') diff --git a/engines/mads/sprites.cpp b/engines/mads/sprites.cpp index aa73fce712..19742e22b0 100644 --- a/engines/mads/sprites.cpp +++ b/engines/mads/sprites.cpp @@ -402,6 +402,7 @@ void SpriteSets::remove(int idx) { (*this)[idx] = nullptr; } else { do { + delete (*this)[size() - 1]; remove_at(size() - 1); } while (size() > 0 && (*this)[size() - 1] == nullptr); } -- cgit v1.2.3 From 43aad22eb2a99717b115fe2d00aaa384779eaa67 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 8 Mar 2015 23:53:10 -0400 Subject: MADS: Fix SceneInfo instance leak when showing dialogs --- engines/mads/dialogs.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines') diff --git a/engines/mads/dialogs.cpp b/engines/mads/dialogs.cpp index c02f027302..158d9693ad 100644 --- a/engines/mads/dialogs.cpp +++ b/engines/mads/dialogs.cpp @@ -430,6 +430,7 @@ void FullScreenDialog::display() { if (_screenId > 0) { SceneInfo *sceneInfo = SceneInfo::init(_vm); sceneInfo->load(_screenId, 0, "", 0, scene._depthSurface, scene._backgroundSurface); + delete sceneInfo; } scene._priorSceneId = priorSceneId; -- cgit v1.2.3 From 05250d14fa8c3b1d2d51066a18d2c96904733590 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 9 Mar 2015 08:56:33 -0400 Subject: MADS: Fix crash picking up bamboo stalk --- engines/mads/nebular/nebular_scenes2.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes2.cpp b/engines/mads/nebular/nebular_scenes2.cpp index 9d5e2185e8..164b943282 100644 --- a/engines/mads/nebular/nebular_scenes2.cpp +++ b/engines/mads/nebular/nebular_scenes2.cpp @@ -3462,6 +3462,7 @@ void Scene209::actions() { case 3: _scene->_sprites.remove(_globals._spriteIndexes[11]); + _scene->_spriteSlots.fullRefresh(true); break; } _action._inProgress = false; -- cgit v1.2.3 From f37a0b215515e5466bd19c8953c4f53ff4823a59 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 9 Mar 2015 18:24:05 -0400 Subject: MADS: Improved fix for picking up plant stalk --- engines/mads/nebular/nebular_scenes2.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes2.cpp b/engines/mads/nebular/nebular_scenes2.cpp index 164b943282..d62497007c 100644 --- a/engines/mads/nebular/nebular_scenes2.cpp +++ b/engines/mads/nebular/nebular_scenes2.cpp @@ -2838,6 +2838,7 @@ void Scene209::enter() { _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('m', 3)); _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('m', 6)); _globals._spriteIndexes[7] = _scene->_sprites.addSprites(formAnimName('m', 8)); + _globals._spriteIndexes[11] = _scene->_sprites.addSprites("*RXMBD_2"); _game.loadQuoteSet(0x82, 0x83, 0x84, 0x9C, 0x97, 0x95, 0x99, 0x9E, 0x98, 0x9B, 0xA0, 0x96, 0x9F, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x91, 0x92, 0x93, 0x94, 0x89, 0x85, 0x8A, 0x86, 0x87, 0x88, 0); @@ -3439,7 +3440,6 @@ void Scene209::actions() { if (_action.isAction(VERB_TAKE, NOUN_PLANT_STALK) && (_game._trigger || _game._objects.isInRoom(OBJ_PLANT_STALK))) { switch (_game._trigger) { case 0: - _globals._spriteIndexes[11] = _scene->_sprites.addSprites("*RXMBD_2"); _game._player._stepEnabled = false; _game._player._visible = false; _globals._sequenceIndexes[11] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[11], false, 3, 2, 0, 0); @@ -3461,8 +3461,6 @@ void Scene209::actions() { break; case 3: - _scene->_sprites.remove(_globals._spriteIndexes[11]); - _scene->_spriteSlots.fullRefresh(true); break; } _action._inProgress = false; -- cgit v1.2.3 From 82faf6b50da5996b1783877a9c2685d8272ffc0e Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 9 Mar 2015 20:02:55 -0400 Subject: MADS: Fix walking to exit in guard room after dropping severed arm --- engines/mads/nebular/nebular_scenes3.cpp | 3 +-- engines/mads/player.cpp | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes3.cpp b/engines/mads/nebular/nebular_scenes3.cpp index 2ea476008f..8f07993e07 100644 --- a/engines/mads/nebular/nebular_scenes3.cpp +++ b/engines/mads/nebular/nebular_scenes3.cpp @@ -4152,7 +4152,7 @@ void Scene352::setup() { void Scene352::putArmDown(bool corridorExit, bool doorwayExit) { switch (_game._trigger) { case 0: - _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 60, _game.getQuote(0xFF)); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0xFF)); _scene->_sequences.addTimer(48, 1); break; @@ -4197,7 +4197,6 @@ void Scene352::putArmDown(bool corridorExit, bool doorwayExit) { case 4: _game._player.walk(Common::Point(116, 107), FACING_NORTH); - _game._player._stepEnabled = true; _mustPutArmDownFl = false; _scene->_sequences.addTimer(180, 5); _leaveRoomFl = true; diff --git a/engines/mads/player.cpp b/engines/mads/player.cpp index 68e0355df9..38e8638415 100644 --- a/engines/mads/player.cpp +++ b/engines/mads/player.cpp @@ -664,7 +664,7 @@ void Player::startMovement() { _deltaDistance = (majorChange == 0) ? 0 : _totalDistance / majorChange; if (_playerPos.x > _targetPos.x) - _pixelAccum = MAX(_posChange.x, _posChange.y); + _pixelAccum = MIN(_posChange.x, _posChange.y); else _pixelAccum = 0; -- cgit v1.2.3 From d23e493b467a24e5d61dcb936b1c2e042c3ae9ce Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 9 Mar 2015 20:35:10 -0400 Subject: MADS: Fix crash if you talk to intern in gurney room too quickly --- engines/mads/nebular/nebular_scenes3.cpp | 6 ++++++ engines/mads/sequence.cpp | 17 +++++++++++++++-- engines/mads/sequence.h | 3 ++- 3 files changed, 23 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes3.cpp b/engines/mads/nebular/nebular_scenes3.cpp index 8f07993e07..0b22aa7720 100644 --- a/engines/mads/nebular/nebular_scenes3.cpp +++ b/engines/mads/nebular/nebular_scenes3.cpp @@ -2581,6 +2581,12 @@ void Scene318::handleInternDialog(int quoteId, int quoteNum, uint32 timeout) { _scene->_kernelMessages.reset(); _internTalkingFl = true; + // WORKAROUND: In case the player launches multiple talk selections with the + // intern before previous ones have finished, take care of removing any + int seqIndex; + while ((seqIndex = _scene->_sequences.findByTrigger(63)) != -1) + _scene->_sequences.remove(seqIndex); + for (int i = 0; i < quoteNum; i++) { _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; _scene->_sequences.addTimer(180, 63); diff --git a/engines/mads/sequence.cpp b/engines/mads/sequence.cpp index 7dbf4cf3be..744e246321 100644 --- a/engines/mads/sequence.cpp +++ b/engines/mads/sequence.cpp @@ -144,7 +144,7 @@ int SequenceList::add(int spriteListIndex, bool flipped, int frameIndex, int tri return seqIndex; } -int SequenceList::addTimer(int timeout, int abortVal) { +int SequenceList::addTimer(int timeout, int endTrigger) { Scene &scene = _vm->_game->_scene; uint seqIndex; for (seqIndex = 0; seqIndex < _entries.size(); ++seqIndex) { @@ -164,7 +164,7 @@ int SequenceList::addTimer(int timeout, int abortVal) { se._entries._count = 0; se._triggerMode = _vm->_game->_triggerSetupMode; se._actionNouns = _vm->_game->_scene._action._activeAction; - addSubEntry(seqIndex, SEQUENCE_TRIGGER_EXPIRE, 0, abortVal); + addSubEntry(seqIndex, SEQUENCE_TRIGGER_EXPIRE, 0, endTrigger); return seqIndex; } @@ -181,6 +181,19 @@ void SequenceList::remove(int seqIndex) { scene._spriteSlots.deleteTimer(seqIndex); } +int SequenceList::findByTrigger(int trigger) { + for (int idx = 0; idx < _entries.size(); ++idx) { + if (_entries[idx]._active) { + for (uint subIdx = 0; subIdx < _entries[idx]._entries._count; ++subIdx) { + if (_entries[idx]._entries._trigger[subIdx] == trigger) + return idx; + } + } + } + + return -1; +} + void SequenceList::setSpriteSlot(int seqIndex, SpriteSlot &spriteSlot) { Scene &scene = _vm->_game->_scene; SequenceEntry &timerEntry = _entries[seqIndex]; diff --git a/engines/mads/sequence.h b/engines/mads/sequence.h index 1555232780..8b236af15e 100644 --- a/engines/mads/sequence.h +++ b/engines/mads/sequence.h @@ -101,8 +101,9 @@ public: int extraTicks, int numTicks, int msgX, int msgY, bool nonFixed, int scale, int depth, int frameInc, SpriteAnimType animType, int numSprites, int frameStart); - int addTimer(int timeout, int abortVal); + int addTimer(int timeout, int endTrigger); void remove(int seqIndex); + int findByTrigger(int trigger); void setSpriteSlot(int seqIndex, SpriteSlot &spriteSlot); bool loadSprites(int seqIndex); void tick(); -- cgit v1.2.3 From b03d46ceeb2c8969fa496298a6bfc8c49b6994f7 Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Tue, 10 Mar 2015 06:39:09 +0100 Subject: MADS: Silence GCC signed/unsigned warnings --- engines/mads/sequence.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/mads/sequence.cpp b/engines/mads/sequence.cpp index 744e246321..ba0111a844 100644 --- a/engines/mads/sequence.cpp +++ b/engines/mads/sequence.cpp @@ -182,9 +182,9 @@ void SequenceList::remove(int seqIndex) { } int SequenceList::findByTrigger(int trigger) { - for (int idx = 0; idx < _entries.size(); ++idx) { + for (uint idx = 0; idx < _entries.size(); ++idx) { if (_entries[idx]._active) { - for (uint subIdx = 0; subIdx < _entries[idx]._entries._count; ++subIdx) { + for (int subIdx = 0; subIdx < _entries[idx]._entries._count; ++subIdx) { if (_entries[idx]._entries._trigger[subIdx] == trigger) return idx; } -- cgit v1.2.3 From 98f77a66519bdf8f8004e1f78ed1822246919b58 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 10 Mar 2015 20:10:55 -0400 Subject: MADS: Fix timer module hotspot remaining active after taking it --- engines/mads/screen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mads/screen.cpp b/engines/mads/screen.cpp index 6199da5925..5076bbb099 100644 --- a/engines/mads/screen.cpp +++ b/engines/mads/screen.cpp @@ -538,7 +538,7 @@ void ScreenObjects::elementHighlighted() { } void ScreenObjects::setActive(ScrCategory category, int descId, bool active) { - for (uint idx = 1; idx < size(); ++idx) { + for (uint idx = 1; idx <= size(); ++idx) { ScreenObject &sObj = (*this)[idx]; if (sObj._category == category && sObj._descId == descId) sObj._active = active; -- cgit v1.2.3 From 4c765121bc0b49a115d2248850d9798303e46853 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 10 Mar 2015 20:18:42 -0400 Subject: MADS: Fix door closing anim when leaving video store --- engines/mads/nebular/nebular_scenes6.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes6.cpp b/engines/mads/nebular/nebular_scenes6.cpp index 11e3ff78b0..7887044804 100644 --- a/engines/mads/nebular/nebular_scenes6.cpp +++ b/engines/mads/nebular/nebular_scenes6.cpp @@ -2574,7 +2574,7 @@ void Scene609::step() { case 62: _scene->_sequences.remove( _globals._sequenceIndexes[2]); - _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0); _scene->_hotspots.activate(NOUN_VIDEO_STORE_DOOR, true); _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 9); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 63); -- cgit v1.2.3 From 0503893f1cd1f3710e65dd43c236112b62ca1ecc Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 10 Mar 2015 20:32:44 -0400 Subject: MADS: Improved fix for giving batteries to Herman --- engines/mads/nebular/globals_nebular.h | 2 +- engines/mads/nebular/nebular_scenes6.cpp | 16 ++++++---------- 2 files changed, 7 insertions(+), 11 deletions(-) (limited to 'engines') diff --git a/engines/mads/nebular/globals_nebular.h b/engines/mads/nebular/globals_nebular.h index ce671f653d..8d0c26d96d 100644 --- a/engines/mads/nebular/globals_nebular.h +++ b/engines/mads/nebular/globals_nebular.h @@ -150,7 +150,7 @@ enum GlobalId { kConvHermit1 = 130, kConvHermit2 = 131, kHasTalkedToHermit = 132, - kExecuted_1_11 = 133, + kHermitWantsBatteries = 133, kHandsetCellStatus = 134, kBeenInVideoStore = 135, kDurafailRecharged = 136, diff --git a/engines/mads/nebular/nebular_scenes6.cpp b/engines/mads/nebular/nebular_scenes6.cpp index 7887044804..0675ce1c6c 100644 --- a/engines/mads/nebular/nebular_scenes6.cpp +++ b/engines/mads/nebular/nebular_scenes6.cpp @@ -3275,8 +3275,7 @@ void Scene611::handleSubDialog1() { // WORKAROUND: Fix bug in the original where the option to give Hermit batteries // would be given before the player even has any batteries - //if (!_game._objects.isInInventory(OBJ_DURAFAIL_CELLS) && !_game._objects.isInInventory(OBJ_PHONE_CELLS)) - // _globals[kExecuted_1_11] = true; + _globals[kHermitWantsBatteries] = true; setDialogNode(1); break; @@ -3968,14 +3967,11 @@ void Scene611::enter() { _scene->_hotspots.activate(NOUN_HERMIT, false); } - /* WORKAROUND: Pretty sure this is a debugging code fragment that should be ignored - if (_globals[kExecuted_1_11]) { - _dialog1.write(0x294, true); - _dialog1.write(0x292, false); - _globals[kExecuted_1_11] = true; - }*/ - if ((_game._objects.isInInventory(OBJ_DURAFAIL_CELLS)) || (_game._objects.isInInventory(OBJ_PHONE_CELLS))) - _dialog1.write(0x294, true); + // WORKAROUND: Fix original adding 'give batteries' option even if you don't have them + if (_globals[kHermitWantsBatteries]) { + if ((_game._objects.isInInventory(OBJ_DURAFAIL_CELLS)) || (_game._objects.isInInventory(OBJ_PHONE_CELLS))) + _dialog1.write(0x294, true); + } if (_duringDialogFl) { _game._player._playerPos = Common::Point(237, 129); -- cgit v1.2.3 From 879e44a2fb548040fdff83b82445ddea43678f32 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 10 Mar 2015 20:51:55 -0400 Subject: MADS: Fix Herman's thanks for batteries speech remaining on-screen --- engines/mads/nebular/nebular_scenes6.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes6.cpp b/engines/mads/nebular/nebular_scenes6.cpp index 0675ce1c6c..bcf7d73bd0 100644 --- a/engines/mads/nebular/nebular_scenes6.cpp +++ b/engines/mads/nebular/nebular_scenes6.cpp @@ -3829,29 +3829,29 @@ void Scene611::displayHermitQuestions(int question) { Common::String curQuote = _game.getQuote(0x2D3); int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); int quotePosX = _defaultDialogPos.x - (width / 2); - _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 3), 0xFDFC, 0, 0, 9999999, curQuote); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 3), 0xFDFC, 0, 0, 800, curQuote); curQuote = _game.getQuote(0x2D4); width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); quotePosX = _defaultDialogPos.x - (width / 2); - _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 17), 0xFDFC, 0, 0, 9999999, curQuote); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 17), 0xFDFC, 0, 0, 800, curQuote); curQuote = _game.getQuote(0x2D5); width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); quotePosX = _defaultDialogPos.x - (width / 2); - _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 9999999, curQuote); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 800, curQuote); curQuote = _game.getQuote(0x2D6); width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); quotePosX = _defaultDialogPos.x - (width / 2); - _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 800, curQuote); curQuote = _game.getQuote(0x2D7); width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); quotePosX = _defaultDialogPos.x - (width / 2); - _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, curQuote); - } - break; + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 800, curQuote); + } + break; case 22: { Common::String curQuote = _game.getQuote(0x2D8); -- cgit v1.2.3 From 01c3e3b9d5dcb9393ddb659cf8f01e5dc771b38f Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 10 Mar 2015 21:04:36 -0400 Subject: MADS: Fix door animations for South Elevator --- engines/mads/nebular/nebular_scenes5.cpp | 2 +- engines/mads/nebular/nebular_scenes7.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes5.cpp b/engines/mads/nebular/nebular_scenes5.cpp index 7cdc55e03c..98efeba82f 100644 --- a/engines/mads/nebular/nebular_scenes5.cpp +++ b/engines/mads/nebular/nebular_scenes5.cpp @@ -2641,7 +2641,7 @@ void Scene513::actions() { _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[4]); _game._player._visible = true; _scene->_sequences.remove(_globals._sequenceIndexes[2]); - _globals._sequenceIndexes[2] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 2); _vm->_sound->command(24); _scene->_kernelMessages.reset(); diff --git a/engines/mads/nebular/nebular_scenes7.cpp b/engines/mads/nebular/nebular_scenes7.cpp index 006b3ca6ec..6e191b2eef 100644 --- a/engines/mads/nebular/nebular_scenes7.cpp +++ b/engines/mads/nebular/nebular_scenes7.cpp @@ -2287,7 +2287,7 @@ void Scene751::step() { case 62: _vm->_sound->command(17); - _globals._sequenceIndexes[1] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[1], false, 5, 1, 0, 0); + _globals._sequenceIndexes[1] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[1], false, 5, 1, 0, 0); _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136)); _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 63); -- cgit v1.2.3 From 0e03995463c7ae2c297066c89f2fb55569be0392 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 10 Mar 2015 21:16:01 -0400 Subject: MADS: Fix display of crack and background in ship --- engines/mads/nebular/nebular_scenes8.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes8.cpp b/engines/mads/nebular/nebular_scenes8.cpp index 24a1855c36..1a8e7efc60 100644 --- a/engines/mads/nebular/nebular_scenes8.cpp +++ b/engines/mads/nebular/nebular_scenes8.cpp @@ -904,10 +904,10 @@ void Scene804::enter() { _game._player._stepEnabled = false; } } else { - if (_globals[kBeamIsUp] == 0) + if (_globals[kBeamIsUp]) _globals._sequenceIndexes[8] = _scene->_sequences.startCycle(_globals._spriteIndexes[8], false, 1); - if (_globals[kWindowFixed] == 0) + if (_globals[kWindowFixed]) _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1); _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); -- cgit v1.2.3 From e18a0af32b77901419865ccc8942c66cbd88e8bd Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 10 Mar 2015 22:17:48 -0400 Subject: MADS: Fix incorrect depth for animation when repairing crack in ship --- engines/mads/nebular/nebular_scenes8.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes8.cpp b/engines/mads/nebular/nebular_scenes8.cpp index 1a8e7efc60..e18dfc634d 100644 --- a/engines/mads/nebular/nebular_scenes8.cpp +++ b/engines/mads/nebular/nebular_scenes8.cpp @@ -904,8 +904,10 @@ void Scene804::enter() { _game._player._stepEnabled = false; } } else { - if (_globals[kBeamIsUp]) + if (_globals[kBeamIsUp]) { _globals._sequenceIndexes[8] = _scene->_sequences.startCycle(_globals._spriteIndexes[8], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 7); + } if (_globals[kWindowFixed]) _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1); -- cgit v1.2.3 From 1e3442ae44e804c17e51d84972092fc459908ece Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 10 Mar 2015 22:54:47 -0400 Subject: MADS: Fix boat hotspot after loading savegame for scene 801 --- engines/mads/nebular/nebular_scenes7.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes7.cpp b/engines/mads/nebular/nebular_scenes7.cpp index 6e191b2eef..96e56b639a 100644 --- a/engines/mads/nebular/nebular_scenes7.cpp +++ b/engines/mads/nebular/nebular_scenes7.cpp @@ -155,10 +155,13 @@ void Scene701::enter() { _globals._sequenceIndexes[6] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[6], false, 20, 0, 0, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 10); break; - case BOAT_TIED: + case BOAT_TIED: { _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1); _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 9); + int idx = _scene->_dynamicHotspots.add(837, 759, _globals._sequenceIndexes[2], Common::Rect()); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(231, 127), FACING_NORTH); break; + } case BOAT_GONE: _scene->_hotspots.activate(NOUN_BOAT, false); break; -- cgit v1.2.3 From 8e3ee9523edb3aa47ad512bef82ce535f69042d9 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 11 Mar 2015 22:10:41 -0400 Subject: MADS: Fix cycling remaining active when ending TextView starts --- engines/mads/scene.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines') diff --git a/engines/mads/scene.cpp b/engines/mads/scene.cpp index a72648f0c9..bbc83a791b 100644 --- a/engines/mads/scene.cpp +++ b/engines/mads/scene.cpp @@ -666,6 +666,7 @@ void Scene::freeCurrentScene() { } _vm->_palette->_paletteUsage.load(nullptr); + _cyclingActive = false; _hotspots.clear(); _backgroundSurface.free(); _depthSurface.free(); -- cgit v1.2.3 From ed33dee7539c6b05f7dba18fb87cdd44c09ba3cd Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 13 Mar 2015 08:43:27 -0400 Subject: MADS: Fix distortions when playing many of the sounds --- engines/mads/nebular/sound_nebular.cpp | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) (limited to 'engines') diff --git a/engines/mads/nebular/sound_nebular.cpp b/engines/mads/nebular/sound_nebular.cpp index d41d0075eb..6412654fd6 100644 --- a/engines/mads/nebular/sound_nebular.cpp +++ b/engines/mads/nebular/sound_nebular.cpp @@ -594,7 +594,7 @@ void ASound::pollActiveChannel() { break; case 8: - chan->_field1D = *++pSrc; + chan->_field1D = (int8)*++pSrc; chan->_pSrc += 2; break; @@ -733,8 +733,8 @@ void ASound::updateChannelState() { resultCheck(); } else { int reg = 0xA0 + _activeChannelNumber; - int vTimes = (_activeChannelPtr->_field4 + _activeChannelPtr->_field1F) / 12; - int vOffset = (_activeChannelPtr->_field4 + _activeChannelPtr->_field1F) % 12; + int vTimes = (byte)(_activeChannelPtr->_field4 + _activeChannelPtr->_field1F) / 12; + int vOffset = (byte)(_activeChannelPtr->_field4 + _activeChannelPtr->_field1F) % 12; int val = _vList1[vOffset] + _activeChannelPtr->_field1D; write2(8, reg, val & 0xFF); @@ -751,17 +751,6 @@ static const int outputIndexes[] = { static const int outputChannels[] = { 0, 1, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20, 21, 0 }; -static const int volumeList[] = { - 0x3F, 0x3F, 0x36, 0x31, 0x2D, 0x2A, 0x28, 0x26, 0x24, 0x22, 0x21, 0x20, 0x1F, 0x1E, 0x1D, 0x1C, - 0x1B, 0x1A, 0x19, 0x19, 0x18, 0x17, 0x17, 0x16, 0x16, 0x15, 0x15, 0x14, 0x14, 0x13, 0x12, 0x12, - 0x11, 0x11, 0x10, 0x10, 0x0F, 0x0F, 0x0E, 0x0E, 0x0D, 0x0D, 0x0C, 0x0C, 0x0B, 0x0B, 0x0A, 0x0A, - 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; void ASound::updateActiveChannel() { int reg = 0x40 + outputChannels[outputIndexes[_activeChannelNumber * 2 + 1]]; @@ -770,13 +759,9 @@ void ASound::updateActiveChannel() { // Note: Original had a whole block not seeming to be used, since the initialisation // sets a variable to 5660h, and doesn't change it, so the branch is never taken - int val = CLIP(newVolume - volumeList[_activeChannelPtr->_fieldD], 0, 63); - val = (63 - val) | portVal; + portVal |= 63 - newVolume; - int val2 = CLIP(newVolume - volumeList[-(_activeChannelPtr->_fieldD - 127)], 0, 63); - val2 = (63 - val2) | portVal; - write2(0, reg, val); - write2(2, reg, val2); + write2(8, reg, portVal); } void ASound::loadSample(int sampleIndex) { -- cgit v1.2.3 From c0df1248b5a73f4b0f02d0712907878aa265dff4 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 13 Mar 2015 21:54:20 -0400 Subject: MADS: Properly handle reloading scenes when closing dialogs --- engines/mads/nebular/dialogs_nebular.cpp | 18 +++++++++++----- engines/mads/nebular/nebular_scenes.cpp | 2 +- engines/mads/nebular/nebular_scenes1.cpp | 28 ++++++++++++------------ engines/mads/nebular/nebular_scenes2.cpp | 28 ++++++++++++------------ engines/mads/nebular/nebular_scenes3.cpp | 37 ++++++++++++++++---------------- engines/mads/nebular/nebular_scenes4.cpp | 20 ++++++++--------- engines/mads/nebular/nebular_scenes5.cpp | 26 +++++++++++----------- engines/mads/nebular/nebular_scenes6.cpp | 20 ++++++++--------- engines/mads/nebular/nebular_scenes7.cpp | 16 +++++++------- engines/mads/nebular/nebular_scenes8.cpp | 6 +++--- engines/mads/scene.h | 2 ++ 11 files changed, 107 insertions(+), 96 deletions(-) (limited to 'engines') diff --git a/engines/mads/nebular/dialogs_nebular.cpp b/engines/mads/nebular/dialogs_nebular.cpp index 23aef6bdb5..6c57c85408 100644 --- a/engines/mads/nebular/dialogs_nebular.cpp +++ b/engines/mads/nebular/dialogs_nebular.cpp @@ -344,7 +344,7 @@ void DialogsNebular::showDialog() { void DialogsNebular::showScummVMSaveDialog() { Nebular::GameNebular &game = *(Nebular::GameNebular *)_vm->_game; - Scene *scene = &(game._scene); + Scene &scene = game._scene; GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true); int slot = dialog->runModalWithCurrentTarget(); @@ -356,24 +356,31 @@ void DialogsNebular::showScummVMSaveDialog() { desc = dialog->createDefaultSaveDescription(slot); } - scene->_spriteSlots.reset(); - scene->loadScene(scene->_currentSceneId, game._aaName, true); - scene->_userInterface.noInventoryAnim(); + scene._spriteSlots.reset(); + scene.loadScene(scene._currentSceneId, game._aaName, true); + scene._userInterface.noInventoryAnim(); game._scene.drawElements(kTransitionFadeIn, false); game.saveGame(slot, desc); } + + // Flag for scene loading that we're returning from a dialog + scene._currentSceneId = RETURNING_FROM_DIALOG; } void DialogsNebular::showScummVMRestoreDialog() { Nebular::GameNebular &game = *(Nebular::GameNebular *)_vm->_game; GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Restore game:"), _("Restore"), false); + Scene &scene = game._scene; int slot = dialog->runModalWithCurrentTarget(); if (slot >= 0) { game._loadGameSlot = slot; - game._scene._currentSceneId = -1; + game._scene._currentSceneId = RETURNING_FROM_LOADING; game._currentSectionNumber = -1; + } else { + // Flag for scene loading that we're returning from a dialog + scene._currentSceneId = RETURNING_FROM_DIALOG; } } @@ -637,6 +644,7 @@ void GameDialog::display() { GameDialog::~GameDialog() { _vm->_screen.resetClipBounds(); + _vm->_game->_scene._currentSceneId = RETURNING_FROM_DIALOG; } void GameDialog::clearLines() { diff --git a/engines/mads/nebular/nebular_scenes.cpp b/engines/mads/nebular/nebular_scenes.cpp index 72073b1c7b..14cf71d0fc 100644 --- a/engines/mads/nebular/nebular_scenes.cpp +++ b/engines/mads/nebular/nebular_scenes.cpp @@ -538,7 +538,7 @@ void SceneTeleporter::teleporterEnter() { _curMessageId = -1; _msgText = "_"; - if (_scene->_priorSceneId == -2) + if (_scene->_priorSceneId == RETURNING_FROM_DIALOG) _scene->_priorSceneId = _globals[kTeleporterDestination]; if (_scene->_priorSceneId < 101) diff --git a/engines/mads/nebular/nebular_scenes1.cpp b/engines/mads/nebular/nebular_scenes1.cpp index d505bb3d4e..dc2eb1f068 100644 --- a/engines/mads/nebular/nebular_scenes1.cpp +++ b/engines/mads/nebular/nebular_scenes1.cpp @@ -188,13 +188,13 @@ void Scene101::enter() { _scene->_hotspots.activate(NOUN_SHIELD_MODULATOR, false); _panelOpened = false; - if (_scene->_priorSceneId != -1) + if (_scene->_priorSceneId != RETURNING_FROM_LOADING) _globals[kNeedToStandUp] = false; - if (_scene->_priorSceneId != -2) + if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) _game._player._playerPos = Common::Point(100, 152); - if ((_scene->_priorSceneId == 112) || ((_scene->_priorSceneId == -2) && _sittingFl )) { + if ((_scene->_priorSceneId == 112) || ((_scene->_priorSceneId == RETURNING_FROM_DIALOG) && _sittingFl )) { _game._player._visible = false; _sittingFl = true; _game._player._playerPos = Common::Point(161, 123); @@ -721,7 +721,7 @@ void Scene102::enter() { _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 70); } else if (_scene->_priorSceneId == 103) _game._player._playerPos = Common::Point(47, 152); - else if (_scene->_priorSceneId != -2) { + else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._facing = FACING_NORTHWEST; _game._player._playerPos = Common::Point(32, 129); } @@ -1342,7 +1342,7 @@ void Scene103::enter() { _scene->_hotspots.activate(362, false); } - if (_scene->_priorSceneId != -2) + if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) _game._player._playerPos = Common::Point(237, 74); if (_scene->_priorSceneId == 102) { @@ -1625,7 +1625,7 @@ void Scene104::enter() { if (_scene->_priorSceneId == 105) _game._player._playerPos = Common::Point(302, 107); - else if (_scene->_priorSceneId != -2) + else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) _game._player._playerPos = Common::Point(160, 134); _loseFl = false; @@ -1847,7 +1847,7 @@ void Scene105::enter() { if (_scene->_priorSceneId == 104) _game._player._playerPos = Common::Point(13, 97); - else if (_scene->_priorSceneId != -2) + else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) _game._player._playerPos = Common::Point(116, 147); _game.loadQuoteSet(0x4A, 0x4B, 0x4C, 0x35, 0x34, 0); @@ -2021,7 +2021,7 @@ void Scene106::enter() { _game._player._stepEnabled = false; _game._player._facing = FACING_EAST; _game._player._playerPos = Common::Point(106, 69); - } else if (_scene->_priorSceneId != -2) { + } else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { if (_scene->_priorSceneId == 107) { _game._player._playerPos = Common::Point(319, 84); _game._player._facing = _game._player._prepareWalkFacing = FACING_WEST; @@ -2240,7 +2240,7 @@ void Scene107::enter() { _game._player._playerPos = Common::Point(132, 47); else if (_scene->_priorSceneId == 106) _game._player._playerPos = Common::Point(20, 91); - else if (_scene->_priorSceneId != -2) + else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) _game._player._playerPos = Common::Point(223, 151); if (((_scene->_priorSceneId == 105) || (_scene->_priorSceneId == 106)) && (_vm->getRandomNumber(1, 3) == 1)) { @@ -2352,7 +2352,7 @@ void Scene108::enter() { if (_scene->_priorSceneId == 107) _game._player._playerPos = Common::Point(138, 58); - else if (_scene->_priorSceneId != -2) + else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) _game._player._playerPos = Common::Point(305, 98); _game.loadQuoteSet(0x4A, 0x4B, 0x4C, 0x35, 0x34, 0); @@ -2459,7 +2459,7 @@ void Scene109::enter() { if (_scene->_priorSceneId == 110) { _game._player._playerPos = Common::Point(248, 38); _globals[kHoovicSated] = 2; - } else if (_scene->_priorSceneId != -2) { + } else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._playerPos = Common::Point(20, 68); _game._player._facing = FACING_EAST; } @@ -2865,7 +2865,7 @@ void Scene110::enter() { _scene->_dynamicHotspots.setPosition(idx, Common::Point(-1, 0), FACING_NONE); idx = _scene->_dynamicHotspots.add(91, 348, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0)); _scene->_dynamicHotspots.setPosition(idx, Common::Point(-1, 0), FACING_NONE); - } else if (_scene->_priorSceneId != -2) { + } else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._playerPos = Common::Point(194, 23); _game._player._facing = FACING_SOUTH; _game._player._visible = false; @@ -3008,7 +3008,7 @@ void Scene111::enter() { _launched2Fl = false; _stampedFl = false; - if ((_scene->_priorSceneId < 201) && (_scene->_priorSceneId != -2)) { + if ((_scene->_priorSceneId < 201) && (_scene->_priorSceneId != RETURNING_FROM_DIALOG)) { _game._player._stepEnabled = false; _game._player._visible = false; _scene->loadAnimation(Resources::formatName(111, 'A', 0, EXT_AA, ""), 70); @@ -3019,7 +3019,7 @@ void Scene111::enter() { _launched2Fl = true; _vm->_sound->command(36); - } else if (_scene->_priorSceneId != -2) { + } else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._playerPos = Common::Point(300, 130); _game._player._facing = FACING_WEST; } diff --git a/engines/mads/nebular/nebular_scenes2.cpp b/engines/mads/nebular/nebular_scenes2.cpp index d62497007c..84910c4de3 100644 --- a/engines/mads/nebular/nebular_scenes2.cpp +++ b/engines/mads/nebular/nebular_scenes2.cpp @@ -152,7 +152,7 @@ void Scene201::enter() { int idx = _scene->_dynamicHotspots.add(NOUN_BIRDS, 209, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0)); _scene->_dynamicHotspots.setPosition(idx, Common::Point(186, 81), FACING_NORTH); - if ((_scene->_priorSceneId == 202) || (_scene->_priorSceneId == -1)) { + if ((_scene->_priorSceneId == 202) || (_scene->_priorSceneId == RETURNING_FROM_LOADING)) { _game._player._playerPos = Common::Point(165, 152); } else { _game._player._playerPos = Common::Point(223, 149); @@ -430,7 +430,7 @@ void Scene202::enter() { if (_scene->_priorSceneId == 201) { _game._player._playerPos = Common::Point(190, 91); _game._player._facing = FACING_SOUTH; - } else if (_scene->_priorSceneId != -2) { + } else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._playerPos = Common::Point(178, 152); _game._player._facing = FACING_NORTH; } @@ -446,7 +446,7 @@ void Scene202::enter() { _game.loadQuoteSet(0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x62, 0x63, 0x64, 0x65, 0x66, 0x61, 0); _activeMsgFl = false; - if (_scene->_priorSceneId == -2) { + if (_scene->_priorSceneId == RETURNING_FROM_DIALOG) { if (_waitingMeteoFl) { _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 1); _game._player._visible = false; @@ -1044,7 +1044,7 @@ void Scene203::enter() { } else if (_scene->_priorSceneId == 209) { _game._player._playerPos = Common::Point(308, 117); _game._player._facing = FACING_WEST; - } else if (_scene->_priorSceneId != -2) { + } else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._playerPos = Common::Point(155, 152); _game._player._facing = FACING_NORTH; } @@ -1222,7 +1222,7 @@ void Scene205::enter() { Common::Rect(195, 99, 264, 134), 13, 2, 0xFDFC, 60, 108, 108, 109, 109, 110, 110, 111, 108, 0); - if (_scene->_priorSceneId != -2) + if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) _game._player._playerPos = Common::Point(99, 152); if (_globals[kSexOfRex] != SEX_MALE) { @@ -1516,7 +1516,7 @@ void Scene207::enter() { } else if (_scene->_priorSceneId == 214) { _game._player._playerPos = Common::Point(164, 117); _game._player._facing = FACING_SOUTH; - } else if (_scene->_priorSceneId != -2) { + } else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._playerPos = Common::Point(305, 131); } @@ -1728,7 +1728,7 @@ void Scene208::enter() { } else if (_scene->_priorSceneId == 209) { _game._player._playerPos = Common::Point(307, 123); _game._player._facing = FACING_WEST; - } else if (_scene->_priorSceneId != -2) { + } else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._playerPos = Common::Point(162, 149); _game._player._facing = FACING_NORTH; } @@ -2856,7 +2856,7 @@ void Scene209::enter() { if (_scene->_priorSceneId == 208) { _game._player._playerPos = Common::Point(11, 121); _game._player._facing = FACING_EAST; - } else if (_scene->_priorSceneId != -2) { + } else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._playerPos = Common::Point(28, 121); _game._player._facing = FACING_SOUTH; } @@ -4173,7 +4173,7 @@ void Scene210::enter() { _game._player._playerPos = Common::Point(168, 128); _game._player._facing = FACING_SOUTH; _globals[kCurtainOpen] = true; - } else if (_scene->_priorSceneId != -2) + } else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) _game._player._playerPos = Common::Point(308, 132); if (!_globals[kCurtainOpen]) { @@ -4210,7 +4210,7 @@ void Scene210::enter() { _twinkleAnimationType = 0; _twinklesCurrentFrame = 0; - if (_scene->_priorSceneId != -2) { + if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _shouldMoveHead = false; _shouldFaceRex = false; _shouldTalk = false; @@ -4647,7 +4647,7 @@ void Scene211::enter() { _game._player._visible = false; _scene->loadAnimation(formAnimName('A', -1), 100); _scene->_activeAnimation->setCurrentFrame(169); - } else if (_scene->_priorSceneId != -2) { + } else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._playerPos = Common::Point(310, 31); _game._player._facing = FACING_SOUTHWEST; } @@ -4905,7 +4905,7 @@ void Scene212::enter() { if (_scene->_priorSceneId == 208) { _game._player._playerPos = Common::Point(195, 85); _game._player._facing = FACING_SOUTH; - } else if (_scene->_priorSceneId != -2) { + } else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._playerPos = Common::Point(67, 117); _game._player._facing = FACING_NORTHEAST; } @@ -5061,7 +5061,7 @@ void Scene214::enter() { _scene->_hotspots.activate(NOUN_BLOWGUN, false); } - if (_scene->_priorSceneId != -2) + if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) _game._player._playerPos = Common::Point(191, 152); sceneEntrySound(); @@ -5257,7 +5257,7 @@ void Scene215::enter() { _game._player._stepEnabled = false; _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); _scene->_sequences.addTimer(120, 70); - } else if (_scene->_priorSceneId != -2) { + } else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._playerPos = Common::Point(204, 152); _game._player._facing = FACING_NORTH; } diff --git a/engines/mads/nebular/nebular_scenes3.cpp b/engines/mads/nebular/nebular_scenes3.cpp index 0b22aa7720..1a477c3bb8 100644 --- a/engines/mads/nebular/nebular_scenes3.cpp +++ b/engines/mads/nebular/nebular_scenes3.cpp @@ -769,7 +769,7 @@ void Scene307::enter() { _dialog2.write(0x11E, true); - if (_scene->_priorSceneId == -2) { + if (_scene->_priorSceneId == RETURNING_FROM_DIALOG) { if (_grateOpenedFl) _vm->_sound->command(10); else @@ -1618,7 +1618,7 @@ void Scene311::enter() { else if (_scene->_priorSceneId == 320) { _game._player._playerPos = Common::Point(129, 113); _game._player._facing = FACING_SOUTH; - } else if (_scene->_priorSceneId != -2) { + } else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._visible = false; _game._player._stepEnabled = false; _scene->loadAnimation(formAnimName('a', -1), 70); @@ -1896,7 +1896,7 @@ void Scene313::enter() { } else if (_scene->_priorSceneId == 388) { _game._player._playerPos = Common::Point(199, 70); _game._player._facing = FACING_WEST; - } else if (_scene->_priorSceneId != -2) { + } else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._playerPos = Common::Point(234, 70); _game._player._facing = FACING_WEST; } @@ -2215,7 +2215,7 @@ void Scene316::enter() { _globals._sequenceIndexes[1] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[spriteIdx], false, 6, 1, 0, 0); _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 2); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 60); - } else if (_scene->_priorSceneId != -2) + } else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) _game._player._playerPos = Common::Point(291, 126); sceneEntrySound(); @@ -2617,7 +2617,7 @@ void Scene318::enter() { if (_scene->_priorSceneId == 357) _game._player._playerPos = Common::Point(15, 110); - else if (_scene->_priorSceneId != -2) + else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) _game._player._playerPos = Common::Point(214, 152); _dialog1.setup(0x47, 0x191, 0x192, 0x193, 0x194, 0x195, 0x196, 0x197, 0x198, 0x199, 0x19A, 0x19B, 0x19C, 0x19D, 0); @@ -2638,7 +2638,7 @@ void Scene318::enter() { _lastFrame = 0; _scene->_hotspots.activate(NOUN_INTERN, false); - if (_scene->_priorSceneId != -2) { + if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _dialogFl = false; _internWalkingFl = false; _counter= 0; @@ -2655,7 +2655,8 @@ void Scene318::enter() { 0x1C8, 0x1C9, 0x1CA, 0x1CB, 0x1CC, 0x1CD, 0x1CE, 0x1CF, 0x1D0, 0x1D1, 0x1D2, 0x1D3, 0x190, 0x19D, 0); - if ((_scene->_priorSceneId== -2) || (((_scene->_priorSceneId == 318) || (_scene->_priorSceneId == -1)) && (!_globals[kAfterHavoc]))) { + if ((_scene->_priorSceneId == RETURNING_FROM_DIALOG) || (((_scene->_priorSceneId == 318) || + (_scene->_priorSceneId == RETURNING_FROM_LOADING)) && (!_globals[kAfterHavoc]))) { if (!_globals[kAfterHavoc]) { _game._player._visible = false; _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('g', -1)); @@ -3119,7 +3120,7 @@ void Scene319::enter() { _dialog2.setup(0x44, 0x171, 0x172, 0x173, 0x174, 0x175, 0x176, 0); _dialog3.setup(0x45, 0x17D, 0x17E, 0x17F, 0x180, 0x181, 0x182, 0x183, 0); - if (_scene->_priorSceneId != -2) { + if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _dialog1.set(0x165, 0x166, 0x167, 0x168, 0); _dialog2.set(0x171, 0x172, 0x173, 0x174, 0); _dialog3.set(0x17D, 0x17E, 0x17F, 0x180, 0); @@ -3142,7 +3143,7 @@ void Scene319::enter() { _scene->loadAnimation(formAnimName('b', 0)); - if (_scene->_priorSceneId != -2) { + if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _animMode = 1; _nextAction1 = 2; _nextAction2 = 2; @@ -3981,7 +3982,7 @@ void Scene351::enter() { if (_scene->_priorSceneId == 352) _game._player._playerPos = Common::Point(148, 152); - else if (_scene->_priorSceneId != -2) { + else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._playerPos = Common::Point(207, 81); _game._player._facing = FACING_NORTH; } @@ -4266,7 +4267,7 @@ void Scene352::enter() { _vaultOpenFl = false; - if (_scene->_priorSceneId != -2) { + if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _mustPutArmDownFl = false; if (!_game._visitedScenes._sceneRevisited) _globals[kHaveYourStuff] = false; @@ -4281,7 +4282,7 @@ void Scene352::enter() { if (_scene->_priorSceneId == 353) _game._player._playerPos = Common::Point(171, 155); - else if (_scene->_priorSceneId != -2) + else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) _game._player._playerPos = Common::Point(116, 107); sceneEntrySound(); @@ -4750,7 +4751,7 @@ void Scene354::enter() { _game._player._facing = FACING_NORTH; } else if (_scene->_priorSceneId == 316) _game._player._playerPos = Common::Point(71, 107); - else if (_scene->_priorSceneId != -2) + else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) _game._player._playerPos = Common::Point(167, 57); sceneEntrySound(); @@ -4817,7 +4818,7 @@ void Scene357::enter() { _game._player._playerPos = Common::Point(298, 142); else if (_scene->_priorSceneId == 313) _game._player._playerPos = Common::Point(127, 101); - else if (_scene->_priorSceneId != -2) + else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) _game._player._playerPos = Common::Point(15, 148); sceneEntrySound(); @@ -4881,7 +4882,7 @@ void Scene358::enter() { if (_scene->_priorSceneId == 357) _game._player._playerPos = Common::Point(305, 142); - else if (_scene->_priorSceneId != -2) + else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) _game._player._playerPos = Common::Point(12, 141); sceneEntrySound(); @@ -4957,7 +4958,7 @@ void Scene359::enter() { if (_scene->_priorSceneId == 358) _game._player._playerPos = Common::Point(301, 141); - else if (_scene->_priorSceneId != -2) + else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) _game._player._playerPos = Common::Point(15, 148); sceneEntrySound(); @@ -5080,7 +5081,7 @@ void Scene360::enter() { if (_scene->_priorSceneId == 359) _game._player._playerPos = Common::Point(304, 143); - else if (_scene->_priorSceneId != -2) + else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) _game._player._playerPos = Common::Point(13, 141); sceneEntrySound(); @@ -5346,7 +5347,7 @@ void Scene361::enter() { else if (_scene->_priorSceneId == 320) { _game._player._playerPos = Common::Point(129, 113); _game._player._facing = FACING_SOUTH; - } else if (_scene->_priorSceneId != -2) + } else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) _game._player._playerPos = Common::Point(13, 145); _game.loadQuoteSet(0xFB, 0xFC, 0); diff --git a/engines/mads/nebular/nebular_scenes4.cpp b/engines/mads/nebular/nebular_scenes4.cpp index 9db597c312..29b17c42c0 100644 --- a/engines/mads/nebular/nebular_scenes4.cpp +++ b/engines/mads/nebular/nebular_scenes4.cpp @@ -113,7 +113,7 @@ void Scene401::setup() { } void Scene401::enter() { - if (_scene->_priorSceneId != -2) + if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) _northFl = false; _timer = 0; @@ -125,7 +125,7 @@ void Scene401::enter() { _game._player._playerPos = Common::Point(149, 90); _game._player._facing = FACING_SOUTH; _northFl = true; - } else if (_scene->_priorSceneId != -2) { + } else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._playerPos = Common::Point(142, 131); _game._player._facing = FACING_NORTH; } @@ -718,7 +718,7 @@ void Scene402::enter() { _roxOnStool = false; _bartenderDialogNode = 1; _conversationFl = false; - } else if (_scene->_priorSceneId != -2) { + } else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._playerPos = Common::Point(160, 150); _game._player._facing = FACING_NORTH; _game._objects.addToInventory(OBJ_CREDIT_CHIP); @@ -2411,7 +2411,7 @@ void Scene405::enter() { } else if (_scene->_priorSceneId == 413) { _game._player._playerPos = Common::Point(284, 109); _game._player._facing = FACING_SOUTH; - } else if (_scene->_priorSceneId != -2) { + } else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._playerPos = Common::Point(23, 123); _game._player._facing = FACING_EAST; } @@ -2587,7 +2587,7 @@ void Scene406::enter() { } else if (_scene->_priorSceneId == 411) { _game._player._playerPos = Common::Point(153, 108); _game._player._facing = FACING_SOUTH; - } else if (_scene->_priorSceneId != -2) { + } else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._playerPos = Common::Point(15, 129); _game._player._facing = FACING_EAST; } @@ -2791,14 +2791,14 @@ void Scene407::setup() { } void Scene407::enter() { - if (_scene->_priorSceneId != -2) + if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) _fromNorth = false; if (_scene->_priorSceneId == 318) { _game._player._playerPos = Common::Point(172, 92); _game._player._facing = FACING_SOUTH; _fromNorth = true; - } else if (_scene->_priorSceneId != -2) { + } else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._playerPos = Common::Point(172, 132); _game._player._facing = FACING_NORTH; } @@ -3118,7 +3118,7 @@ void Scene410::enter() { else _scene->_hotspots.activate(NOUN_CHARGE_CASES, false); - if (_scene->_priorSceneId != -2) { + if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._playerPos = Common::Point(155, 150); _game._player._facing = FACING_NORTH; } @@ -3646,7 +3646,7 @@ void Scene411::enter() { _scene->_dynamicHotspots.setPosition(idx, Common::Point(220, 121), FACING_NORTHEAST); } - if (_scene->_priorSceneId != -2) { + if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._playerPos = Common::Point(60, 146); _game._player._facing = FACING_NORTHEAST; } @@ -4058,7 +4058,7 @@ void Scene413::enter() { _game._player._playerPos = Common::Point(142, 146); _game._player._facing = FACING_NORTH; _game._player._visible = true; - } else if (_scene->_priorSceneId != -2) { + } else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { if (_globals[kSexOfRex] == REX_MALE) { _scene->loadAnimation(Resources::formatName(413, 'd', 1, EXT_AA, ""), 78); _vm->_sound->command(30); diff --git a/engines/mads/nebular/nebular_scenes5.cpp b/engines/mads/nebular/nebular_scenes5.cpp index 98efeba82f..e6ab658eb4 100644 --- a/engines/mads/nebular/nebular_scenes5.cpp +++ b/engines/mads/nebular/nebular_scenes5.cpp @@ -199,7 +199,7 @@ void Scene501::enter() { _game._player._playerPos = Common::Point(317, 102); _game._player._facing = FACING_SOUTHWEST; _scene->_sequences.addTimer(15, 80); - } else if (_scene->_priorSceneId != -2) + } else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) _game._player._playerPos = Common::Point(299, 131); if (_scene->_roomChanged) { @@ -563,7 +563,7 @@ void Scene503::enter() { _scene->_dynamicHotspots.setPosition(_detonatorHotspotId, Common::Point(254, 135), FACING_SOUTH); } - if (_scene->_priorSceneId != -2) { + if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._playerPos = Common::Point(191, 152); _game._player._facing = FACING_NORTHWEST; } @@ -709,7 +709,7 @@ void Scene504::enter() { _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('a', 3)); _carAnimationMode = 1; _scene->loadAnimation(formAnimName('A', -1)); - if ((_scene->_priorSceneId != -2) && (_scene->_priorSceneId != 505)) + if ((_scene->_priorSceneId != RETURNING_FROM_DIALOG) && (_scene->_priorSceneId != 505)) _globals[kHoverCarLocation] = _scene->_priorSceneId; _globals._sequenceIndexes[7] = _scene->_sequences.startCycle(_globals._spriteIndexes[7], false, 1); @@ -912,7 +912,7 @@ void Scene505::enter() { _globals._spriteIndexes[11] = _scene->_sprites.addSprites(formAnimName('t', -1)); _globals._spriteIndexes[12] = _scene->_sprites.addSprites(formAnimName('e', -1)); - if (_scene->_priorSceneId != -2) + if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) _globals._sequenceIndexes[12] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[12], false, 6, 1, 0, 0); _globals._sequenceIndexes[13] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[13], false, 6, 1, 120, 0); @@ -934,7 +934,7 @@ void Scene505::enter() { for (int i = 0; i < 9; i++) { if (_globals[kHoverCarLocation] == _carLocations[i]) { _homeSelectedId = i; - if (_scene->_priorSceneId != -2) + if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) _selectedId = i; } } @@ -1222,7 +1222,7 @@ void Scene506::enter() { _game._player._facing = FACING_SOUTHEAST; _scene->_sequences.addTimer(60, 80); _game._player._stepEnabled = false; - } else if (_scene->_priorSceneId != -2) { + } else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._playerPos = Common::Point(138, 116); _game._player._facing = FACING_NORTHEAST; _game._player._visible = false; @@ -1471,7 +1471,7 @@ void Scene507::enter() { _scene->_dynamicHotspots.setPosition(_penlightHotspotId, Common::Point(233, 152), FACING_SOUTHEAST); } - if (_scene->_priorSceneId != -2) { + if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._playerPos = Common::Point(121, 147); _game._player._facing = FACING_NORTH; } @@ -1630,7 +1630,7 @@ void Scene508::enter() { if (_scene->_priorSceneId == 515) { _game._player._playerPos = Common::Point(57, 116); _game._player._facing = FACING_NORTHEAST; - } else if (_scene->_priorSceneId != -2) { + } else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._playerPos = Common::Point(289, 139); _game._player._facing = FACING_WEST; } @@ -1868,7 +1868,7 @@ void Scene511::enter() { _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('c', 0)); _globals._spriteIndexes[4] = _scene->_sprites.addSprites("*RXCD_6"); - if (_scene->_priorSceneId != -2) + if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) _handingLine = false; if (_globals[kBoatRaised]) { @@ -1923,7 +1923,7 @@ void Scene511::enter() { if (_scene->_priorSceneId == 512) { _game._player._playerPos = Common::Point(60, 112); _game._player._facing = FACING_SOUTHEAST; - } else if (_scene->_priorSceneId != -2) { + } else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._playerPos = Common::Point(55, 152); _game._player._facing = FACING_NORTHWEST; _game._player._visible = false; @@ -2242,7 +2242,7 @@ void Scene512::enter() { } else _scene->_hotspots.activate(NOUN_PADLOCK_KEY, false); - if (_scene->_priorSceneId != -2) { + if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._playerPos = Common::Point(144, 152); _game._player._facing = FACING_NORTHEAST; } @@ -2510,7 +2510,7 @@ void Scene513::enter() { _game._player._facing = FACING_WEST; _game._player._stepEnabled = false; _scene->_sequences.addTimer(15, 80); - } else if (_scene->_priorSceneId != -2) { + } else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._playerPos = Common::Point(63, 149); _game._player._facing = FACING_NORTHEAST; _game._player._visible = false; @@ -2744,7 +2744,7 @@ void Scene551::enter() { if (_scene->_priorSceneId == 501) _game._player._playerPos = Common::Point(18, 130); - else if (_scene->_priorSceneId != -2) { + else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._playerPos = Common::Point(124, 119); _game._player._facing = FACING_NORTH; } diff --git a/engines/mads/nebular/nebular_scenes6.cpp b/engines/mads/nebular/nebular_scenes6.cpp index bcf7d73bd0..046782b772 100644 --- a/engines/mads/nebular/nebular_scenes6.cpp +++ b/engines/mads/nebular/nebular_scenes6.cpp @@ -112,7 +112,7 @@ void Scene601::enter() { _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -2); _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 3); _scene->loadAnimation(formAnimName('R', 1), 70); - } else if (_scene->_priorSceneId != -2) { + } else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._playerPos = Common::Point(229, 129); _game._player._facing = FACING_SOUTHWEST; } @@ -293,7 +293,7 @@ void Scene602::enter() { if (_scene->_priorSceneId == 603) { _game._player._playerPos = Common::Point(228, 126); _game._player._facing = FACING_WEST; - } else if (_scene->_priorSceneId != -2) { + } else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._playerPos = Common::Point(50, 127); _game._player._facing = FACING_EAST; } @@ -585,7 +585,7 @@ void Scene603::enter() { _scene->_dynamicHotspots.setPosition(_noteHotspotId, Common::Point(242, 118), FACING_NORTHEAST); } - if (_scene->_priorSceneId != -2) + if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) _game._player._playerPos = Common::Point(113, 134); sceneEntrySound(); @@ -750,7 +750,7 @@ void Scene604::enter() { _vm->_palette->setEntry(253, 45, 24, 17); _animationActiveFl = false; - if (_scene->_priorSceneId != -2) { + if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._playerPos = Common::Point(72, 149); _game._player._facing = FACING_NORTHEAST; _game._player._visible = false; @@ -1106,7 +1106,7 @@ void Scene607::enter() { if (_scene->_priorSceneId == 608) { _game._player._playerPos = Common::Point(297, 50); _game._player._facing = FACING_SOUTHEAST; - } else if (_scene->_priorSceneId != -2) { + } else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._playerPos = Common::Point(40, 104); _game._player._facing = FACING_SOUTHEAST; _game._player._visible = false; @@ -1778,7 +1778,7 @@ void Scene608::enter() { _vm->_palette->setEntry(252, 63, 44, 30); _vm->_palette->setEntry(253, 63, 20, 22); - if (_scene->_priorSceneId != -2) { + if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._playerPos = Common::Point(46, 132); _game._player._facing = FACING_EAST; if (_game._difficulty == DIFFICULTY_HARD) { @@ -2535,7 +2535,7 @@ void Scene609::enter() { _game._player._facing = FACING_EAST; _scene->_sequences.addTimer(60, 60); _game._player._stepEnabled = false; - } else if (_scene->_priorSceneId != -2) { + } else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._playerPos = Common::Point(86, 136); _game._player._facing = FACING_NORTHEAST; _game._player._visible = false; @@ -2884,7 +2884,7 @@ void Scene610::enter() { if (_scene->_roomChanged && _game._difficulty != DIFFICULTY_EASY) _game._objects.addToInventory(OBJ_PENLIGHT); - if (_scene->_priorSceneId != -2) { + if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._playerPos = Common::Point(175, 152); _game._player._facing = FACING_NORTHWEST; } @@ -3948,7 +3948,7 @@ void Scene611::enter() { _alreadyTalkingFl = false; _startTradingFl = false; - if (_scene->_priorSceneId != -2) { + if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._playerPos = Common::Point(22, 132); _game._player._facing = FACING_EAST; _duringDialogFl = false; @@ -4560,7 +4560,7 @@ void Scene612::enter() { _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, _cycleIndex); _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); - if (_scene->_priorSceneId != -2) { + if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._playerPos = Common::Point(280, 75); _game._player._facing = FACING_SOUTHWEST; _game._player._visible = false; diff --git a/engines/mads/nebular/nebular_scenes7.cpp b/engines/mads/nebular/nebular_scenes7.cpp index 96e56b639a..7be66670d5 100644 --- a/engines/mads/nebular/nebular_scenes7.cpp +++ b/engines/mads/nebular/nebular_scenes7.cpp @@ -194,7 +194,7 @@ void Scene701::enter() { _game._player._stepEnabled = false; _scene->loadAnimation(formAnimName('B', 1), 80); _vm->_sound->command(28); - } else if (_scene->_priorSceneId != -2 && _scene->_priorSceneId != 620) { + } else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG && _scene->_priorSceneId != 620) { _game._player._playerPos = Common::Point(22, 131); _game._player._facing = FACING_EAST; _game._player._stepEnabled = false; @@ -463,7 +463,7 @@ void Scene702::enter() { if (_scene->_priorSceneId == 701) { _game._player._playerPos = Common::Point(13, 145); _game._player._facing = FACING_EAST; - } else if (_scene->_priorSceneId != -2 && _scene->_priorSceneId != 620) { + } else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG && _scene->_priorSceneId != 620) { _game._player._playerPos = Common::Point(289, 138); _game._player.walk(Common::Point(262, 148), FACING_WEST); _game._player._facing = FACING_WEST; @@ -697,7 +697,7 @@ void Scene703::enter() { _monsterMode = 0; _scene->loadAnimation(formAnimName('A', -1)); _scene->_activeAnimation->setCurrentFrame(34); - } else if (_scene->_priorSceneId != -2) { + } else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._stepEnabled = false; _boatDir = 1; if (_globals[kMonsterAlive]) { @@ -1244,7 +1244,7 @@ void Scene704::enter() { _boatDirection = 2; _scene->loadAnimation(formAnimName('A', -1)); _scene->_activeAnimation->setCurrentFrame(36); - } else if (_scene->_priorSceneId != -2) { + } else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._stepEnabled = false; _boatDirection = 1; _scene->loadAnimation(formAnimName('A', -1)); @@ -1570,7 +1570,7 @@ void Scene705::enter() { _globals._sequenceIndexes[3] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[3], false, 9, 1, 0, 0); _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 4); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 71); - } else if (_scene->_priorSceneId != -2) { + } else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._stepEnabled = false; _scene->_sequences.addTimer(1, 80); _vm->_sound->command(28); @@ -1857,7 +1857,7 @@ void Scene706::enter() { if (_scene->_priorSceneId == 707) { _game._player._playerPos = Common::Point(277, 103); _game._player._facing = FACING_SOUTHWEST; - } else if (_scene->_priorSceneId != -2) { + } else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._playerPos = Common::Point(167, 152); _game._player._facing = FACING_NORTH; } @@ -2216,7 +2216,7 @@ void Scene751::enter() { _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, -2); _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(155, 129)); _scene->_sequences.addTimer(15, 70); - } else if (_scene->_priorSceneId != -2) { + } else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._playerPos = Common::Point(22, 131); _game._player._facing = FACING_EAST; _game._player._stepEnabled = false; @@ -2530,7 +2530,7 @@ void Scene752::enter() { if (_scene->_priorSceneId == 751) { _game._player._playerPos = Common::Point(13, 145); _game._player._facing = FACING_EAST; - } else if (_scene->_priorSceneId != -2) { + } else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._playerPos = Common::Point(289, 138); _game._player.walk(Common::Point(262, 148), FACING_WEST); _game._player._facing = FACING_WEST; diff --git a/engines/mads/nebular/nebular_scenes8.cpp b/engines/mads/nebular/nebular_scenes8.cpp index e18dfc634d..8ce559b82b 100644 --- a/engines/mads/nebular/nebular_scenes8.cpp +++ b/engines/mads/nebular/nebular_scenes8.cpp @@ -121,7 +121,7 @@ void Scene801::enter() { _game._player._playerPos = Common::Point(307, 111); _game._player.walk(Common::Point(270, 118), FACING_WEST); _game._player._visible = true; - } else if ((_scene->_priorSceneId != -2) && !_globals[kTeleporterCommand]) { + } else if ((_scene->_priorSceneId != RETURNING_FROM_DIALOG) && !_globals[kTeleporterCommand]) { _game._player._playerPos = Common::Point(8, 117); _game._player.walk(Common::Point(41, 115), FACING_EAST); _game._player._visible = true; @@ -346,7 +346,7 @@ void Scene802::enter() { _game._player._playerPos = Common::Point(303, 119); _game._player._facing = FACING_WEST; - } else if (_scene->_priorSceneId != -2) { + } else if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._playerPos = Common::Point(15, 129); _game._player._facing = FACING_EAST; } @@ -557,7 +557,7 @@ void Scene803::enter() { if (!_globals[kFromCockpit]) { if (!_globals[kReturnFromCut]) { - if (_scene->_priorSceneId != -2) { + if (_scene->_priorSceneId != RETURNING_FROM_DIALOG) { _game._player._playerPos = Common::Point(15, 130); _game._player._facing = FACING_EAST; } diff --git a/engines/mads/scene.h b/engines/mads/scene.h index 05053c3166..5927f4e70f 100644 --- a/engines/mads/scene.h +++ b/engines/mads/scene.h @@ -40,6 +40,8 @@ namespace MADS { +enum { RETURNING_FROM_DIALOG = -2, RETURNING_FROM_LOADING = -1 }; + class Scene { private: /** -- cgit v1.2.3 From 5c834815436014efd1f2b88455d8e44cf28ebc85 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 13 Mar 2015 22:05:21 -0400 Subject: MADS: Action fixes for top of south elevator scene --- engines/mads/nebular/nebular_scenes.h | 1 - engines/mads/nebular/nebular_scenes7.cpp | 8 +++----- 2 files changed, 3 insertions(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes.h b/engines/mads/nebular/nebular_scenes.h index cf33b21aad..8549643ff8 100644 --- a/engines/mads/nebular/nebular_scenes.h +++ b/engines/mads/nebular/nebular_scenes.h @@ -924,7 +924,6 @@ enum Noun { NOUN_WHISKEY = 0x30F, NOUN_ALCOHOL = 0x310, NOUN_RIM = 0x311, - //NOUN_WALK_ALONG = 0x312, NOUN_SUBMERGED_CITY = 0x313, NOUN_GOVERNORS_HOUSE = 0x314, NOUN_RIM_TOWARDS_EAST = 0x315, diff --git a/engines/mads/nebular/nebular_scenes7.cpp b/engines/mads/nebular/nebular_scenes7.cpp index 7be66670d5..b40a8054f7 100644 --- a/engines/mads/nebular/nebular_scenes7.cpp +++ b/engines/mads/nebular/nebular_scenes7.cpp @@ -279,10 +279,8 @@ void Scene701::preActions() { } void Scene701::actions() { - if (_action.isAction(VERB_WALK_ALONG, NOUN_PLATFORM)) - return; - - if (_action.isAction(VERB_LOOK, NOUN_BINOCULARS, NOUN_BUILDING) && _game._objects[OBJ_VASE]._roomNumber == 706) { + if (_action.isAction(VERB_WALK_ALONG, NOUN_PLATFORM)) { + } else if (_action.isAction(VERB_LOOK, NOUN_BINOCULARS, NOUN_BUILDING) && _game._objects[OBJ_VASE]._roomNumber == 706) { switch (_game._trigger) { case 0: _game._player._stepEnabled = false; @@ -418,7 +416,7 @@ void Scene701::actions() { _vm->_dialogs->show(70111); } else if (_action.isAction(VERB_LOOK, NOUN_SUBMERGED_CITY)) _vm->_dialogs->show(70112); - else if (_action.isAction(VERB_LOOK, 0)) + else if (_action.isAction(VERB_LOOK, NOUN_ELEVATOR)) _vm->_dialogs->show(70113); else if (_action.isAction(VERB_LOOK, NOUN_PLATFORM)) _vm->_dialogs->show(70114); -- cgit v1.2.3 From 84702e7d5c646ba757bf6fbfc59986570c43540b Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 13 Mar 2015 22:52:58 -0400 Subject: MADS: Fix text display when opening the Slippery Pig fridge --- engines/mads/nebular/nebular_scenes1.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes1.cpp b/engines/mads/nebular/nebular_scenes1.cpp index dc2eb1f068..0c5888b6ec 100644 --- a/engines/mads/nebular/nebular_scenes1.cpp +++ b/engines/mads/nebular/nebular_scenes1.cpp @@ -906,7 +906,7 @@ void Scene102::actions() { _fridgeFirstOpenFl = false; int quoteId = _vm->getRandomNumber(59, 63); Common::String curQuote = _game.getQuote(quoteId); - int width = _vm->_font->getWidth(curQuote, -1); + int width = _scene->_kernelMessages._talkFont->getWidth(curQuote, -1); _scene->_kernelMessages.reset(); _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; _scene->_kernelMessages.add(Common::Point(210, 60), 0x1110, 0, 73, 120, curQuote); -- cgit v1.2.3 From 4c97e08e33f5a94c62c7ae480d05eae85a6721b6 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 14 Mar 2015 12:50:04 +0200 Subject: MADS: Fix some verbs --- engines/mads/nebular/nebular_scenes.h | 17 +++++++++-------- engines/mads/nebular/nebular_scenes3.cpp | 4 ++-- engines/mads/nebular/nebular_scenes5.cpp | 8 ++++---- 3 files changed, 15 insertions(+), 14 deletions(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes.h b/engines/mads/nebular/nebular_scenes.h index 8549643ff8..db7738f13b 100644 --- a/engines/mads/nebular/nebular_scenes.h +++ b/engines/mads/nebular/nebular_scenes.h @@ -106,6 +106,7 @@ enum Verb { VERB_WALK_UP = 0x227, VERB_WALK_INTO = 0x242, VERB_EXIT = 0x298, + VERB_WALK_BEHIND = 0x2A2, VERB_WALK_ONTO = 0x2B5, VERB_RETURN_TO = 0x2D5, VERB_CLIMB_INTO = 0x2F7, @@ -216,9 +217,9 @@ enum Noun { NOUN_CLEARING_TO_EAST = 0x4B, NOUN_CLEARING_TO_SOUTH = 0x4C, NOUN_CLIFF_FACE = 0x4D, - NOUN_CLIMB_DOWN = 0x4E, - NOUN_CLIMB_THROUGH = 0x4F, - NOUN_CLIMB_UP = 0x50, + //NOUN_CLIMB_DOWN = 0x4E, + //NOUN_CLIMB_THROUGH = 0x4F, + //NOUN_CLIMB_UP = 0x50, NOUN_CLOCK = 0x51, NOUN_CLOSET = 0x52, NOUN_CLOTHESLINE = 0x53, @@ -397,7 +398,7 @@ enum Noun { NOUN_PALM_TREE = 0x100, NOUN_PASSAGE_WAY_TO_SOUTH = 0x101, NOUN_PASSION_PUSS = 0x102, - NOUN_PEER_THROUGH = 0x103, + //NOUN_PEER_THROUGH = 0x103, NOUN_PENCIL = 0x104, NOUN_PENDULOUS_CRAG = 0x105, NOUN_PENLIGHT = 0x106, @@ -812,7 +813,7 @@ enum Noun { NOUN_COUNTER = 0x29F, NOUN_SENSOR = 0x2A0, NOUN_SOFTWARE_INFORMATION = 0x2A1, - NOUN_WALK_BEHIND = 0x2A2, + //NOUN_WALK_BEHIND = 0x2A2, NOUN_BARGAINS = 0x2A3, NOUN_SCAN_LIGHT = 0x2A4, NOUN_OLD_SOFTWARE_STAND = 0x2A5, @@ -831,7 +832,7 @@ enum Noun { //NOUN_GAWK_AT = 0x2B2, NOUN_CORRIDOR_TO_SOUTH = 0x2B3, NOUN_CORRIDOR_TO_NORTH = 0x2B4, - NOUN_WALK_ONTO = 0x2B5, + //NOUN_WALK_ONTO = 0x2B5, NOUN_ROCK_WALL = 0x2B6, NOUN_WOMAN = 0x2B7, NOUN_WOMEN = 0x2B8, @@ -897,7 +898,7 @@ enum Noun { NOUN_YOUR_STUFF = 0x2F4, NOUN_OTHER_STUFF = 0x2F5, NOUN_LAMP = 0x2F6, - NOUN_CLIMB_INTO = 0x2F7, + //NOUN_CLIMB_INTO = 0x2F7, NOUN_LIGHT_BULB = 0x2F8, //NOUN_STEP_INTO = 0x2F9, NOUN_ROOM = 0x2FA, @@ -1056,7 +1057,7 @@ enum Noun { NOUN_PAD_TO_EAST = 0x394, NOUN_PAD_TO_WEST = 0x395, NOUN_TOWER = 0x396, - NOUN_LOOK_OUT = 0x397, + //NOUN_LOOK_OUT = 0x397, NOUN_SERVICE_PANEL = 0x398, NOUN_CRACK = 0x399, NOUN_THROTTLE = 0x39A, diff --git a/engines/mads/nebular/nebular_scenes3.cpp b/engines/mads/nebular/nebular_scenes3.cpp index 1a477c3bb8..d6c7ba1cc7 100644 --- a/engines/mads/nebular/nebular_scenes3.cpp +++ b/engines/mads/nebular/nebular_scenes3.cpp @@ -521,7 +521,7 @@ void Scene307::setup() { setPlayerSpritesPrefix(); setAAName(); _scene->addActiveVocab(NOUN_AIR_VENT); - _scene->addActiveVocab(NOUN_CLIMB_INTO); + _scene->addActiveVocab(VERB_CLIMB_INTO); } void Scene307::handleRexDialog(int quote) { @@ -992,7 +992,7 @@ void Scene307::actions() { _scene->_sequences.remove(_globals._sequenceIndexes[5]); _grateOpenedFl = true; _scene->_hotspots.activate(17, false); - int idx = _scene->_dynamicHotspots.add(17, NOUN_CLIMB_INTO, -1, Common::Rect(117, 67, 117 + 19, 67 + 13)); + int idx = _scene->_dynamicHotspots.add(17, VERB_CLIMB_INTO, -1, Common::Rect(117, 67, 117 + 19, 67 + 13)); int hotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(129, 104), FACING_NORTH); _scene->_dynamicHotspots.setCursor(hotspotId, CURSOR_GO_UP); _game._objects.removeFromInventory(OBJ_SCALPEL, NOWHERE); diff --git a/engines/mads/nebular/nebular_scenes5.cpp b/engines/mads/nebular/nebular_scenes5.cpp index e6ab658eb4..a76edaca67 100644 --- a/engines/mads/nebular/nebular_scenes5.cpp +++ b/engines/mads/nebular/nebular_scenes5.cpp @@ -1547,8 +1547,8 @@ void Scene507::actions() { _vm->_dialogs->show(50724); else if (_action.isAction(VERB_LOOK, NOUN_WINDOW)) _vm->_dialogs->show(50725); - else if (_action.isAction(NOUN_WALK_BEHIND, NOUN_COUNTER)) { - // WORkAROUND: Empty handling to prevent default "can't do that" dialogs showing + else if (_action.isAction(VERB_WALK_BEHIND, NOUN_COUNTER)) { + // WORKAROUND: Empty handling to prevent default "can't do that" dialogs showing } else if (_action.isAction(VERB_LOOK, NOUN_COUNTER)) { if (_game._objects.isInRoom(OBJ_PENLIGHT)) _vm->_dialogs->show(50728); @@ -2463,8 +2463,8 @@ void Scene512::actions() { _vm->_dialogs->show(51233); else if (_action.isAction(VERB_LOOK, NOUN_LAMP)) _vm->_dialogs->show(51234); - else if (_action.isAction(NOUN_WALK_BEHIND, NOUN_COUNTER)) { - // WORkAROUND: Empty handling to prevent default "can't do that" dialogs showing + else if (_action.isAction(VERB_WALK_BEHIND, NOUN_COUNTER)) { + // WORKAROUND: Empty handling to prevent default "can't do that" dialogs showing } else if (_action.isAction(VERB_LOOK, NOUN_COUNTER)) _vm->_dialogs->show(51235); else if (_action.isAction(VERB_LOOK, NOUN_ICE_CHESTS)) -- cgit v1.2.3 From 1f8845e9f433365c3586240b4e395cf888ec770b Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 14 Mar 2015 13:04:46 +0200 Subject: MADS: Fix toggling of game options --- engines/mads/nebular/dialogs_nebular.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mads/nebular/dialogs_nebular.cpp b/engines/mads/nebular/dialogs_nebular.cpp index 6c57c85408..530cf8a785 100644 --- a/engines/mads/nebular/dialogs_nebular.cpp +++ b/engines/mads/nebular/dialogs_nebular.cpp @@ -1142,8 +1142,9 @@ void OptionsDialog::show() { // Reload menu _lineIndex = -1; clearLines(); + _vm->_game->_screenObjects.clear(); + _vm->_game->_scene._spriteSlots.reset(); setLines(); - setClickableLines(); } while (!_vm->shouldQuit() && _selectedLine != 0 && _selectedLine <= 7); // If Done button not pressed, reset settings -- cgit v1.2.3 From 0f02cdb4aa0a0e29bea414583a6db8a5ae389f49 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 14 Mar 2015 10:11:19 -0400 Subject: MADS: Fix crash in stream crossing death, simplify SpriteSets class --- engines/mads/game.cpp | 2 +- engines/mads/player.cpp | 2 +- engines/mads/scene.cpp | 2 +- engines/mads/sprites.cpp | 52 +++++++++++++++++++++++++----------------------- engines/mads/sprites.h | 8 +++++--- 5 files changed, 35 insertions(+), 31 deletions(-) (limited to 'engines') diff --git a/engines/mads/game.cpp b/engines/mads/game.cpp index 74c2a3f416..b601a12c82 100644 --- a/engines/mads/game.cpp +++ b/engines/mads/game.cpp @@ -160,7 +160,7 @@ void Game::gameLoop() { sectionLoop(); _player.releasePlayerSprites(); - assert(_scene._sprites._assetCount == 0); + assert(_scene._sprites.size() == 0); _vm->_palette->unlock(); _vm->_events->waitCursor(); diff --git a/engines/mads/player.cpp b/engines/mads/player.cpp index 38e8638415..f61a5a1592 100644 --- a/engines/mads/player.cpp +++ b/engines/mads/player.cpp @@ -709,7 +709,7 @@ void Player::releasePlayerSprites() { _spritesLoaded = false; _spritesChanged = true; - if (scene._sprites._assetCount > 0) { + if (scene._sprites.size() > 0) { warning("Player::releasePlayerSprites(): leftover sprites remain, clearing list"); scene._sprites.clear(); } diff --git a/engines/mads/scene.cpp b/engines/mads/scene.cpp index bbc83a791b..463d4a62fd 100644 --- a/engines/mads/scene.cpp +++ b/engines/mads/scene.cpp @@ -676,7 +676,7 @@ void Scene::freeCurrentScene() { } void Scene::removeSprites() { - for (int idx = _sprites._assetCount - 1; idx >= _spritesCount; --idx) + for (int idx = _sprites.size() - 1; idx >= _spritesCount; --idx) _sprites.remove(idx); } diff --git a/engines/mads/sprites.cpp b/engines/mads/sprites.cpp index 19742e22b0..6488add86c 100644 --- a/engines/mads/sprites.cpp +++ b/engines/mads/sprites.cpp @@ -368,19 +368,18 @@ SpriteSets::~SpriteSets() { } int SpriteSets::add(SpriteAsset *asset, int idx) { - if (idx) - idx = idx + 49; - else - idx = _assetCount++; + if (idx) { + assert(idx == 1); + delete _uiSprites; + _uiSprites = asset; - if (idx >= (int)size()) - resize(idx + 1); + return SPRITE_SLOTS_MAX_SIZE; + } else { + assert(size() < SPRITE_SLOTS_MAX_SIZE); + push_back(asset); - if ((*this)[idx]) - delete (*this)[idx]; - - (*this)[idx] = asset; - return idx; + return (int)size() - 1; + } } int SpriteSets::addSprites(const Common::String &resName, int flags) { @@ -390,26 +389,29 @@ int SpriteSets::addSprites(const Common::String &resName, int flags) { void SpriteSets::clear() { for (uint i = 0; i < size(); ++i) delete (*this)[i]; - - _assetCount = 0; Common::Array::clear(); + + delete _uiSprites; + _uiSprites = nullptr; } void SpriteSets::remove(int idx) { - if (idx >= 0) { - if (idx < ((int)size() - 1)) { - delete (*this)[idx]; - (*this)[idx] = nullptr; - } else { - do { - delete (*this)[size() - 1]; - remove_at(size() - 1); - } while (size() > 0 && (*this)[size() - 1] == nullptr); - } + if (idx == SPRITE_SLOTS_MAX_SIZE) { + delete _uiSprites; + _uiSprites = nullptr; + } else if (idx >= 0) { + delete (*this)[idx]; - if (idx < 50 && _assetCount > 0) - --_assetCount; + if (idx == ((int)size() - 1)) + remove_at(size() - 1); + else + (*this)[idx] = nullptr; } } +SpriteAsset *&SpriteSets::operator[](int idx) { + return (idx == SPRITE_SLOTS_MAX_SIZE) ? _uiSprites : + Common::Array::operator[](idx); +} + } // End of namespace MADS diff --git a/engines/mads/sprites.h b/engines/mads/sprites.h index 6ea3c9e52e..bb5fdbe964 100644 --- a/engines/mads/sprites.h +++ b/engines/mads/sprites.h @@ -202,12 +202,12 @@ class SpriteSets : public Common::Array { private: MADSEngine *_vm; public: - int _assetCount; - + SpriteAsset *_uiSprites; +public: /** * Constructor */ - SpriteSets(MADSEngine *vm) : _vm(vm), _assetCount(0) {} + SpriteSets(MADSEngine *vm) : _vm(vm), _uiSprites(nullptr) {} /** * Destructor @@ -233,6 +233,8 @@ public: * Remove an asset from the list */ void remove(int idx); + + SpriteAsset *&operator[](int idx); }; } // End of namespace MADS -- cgit v1.2.3 From ff29535074c630987a99f2ac8bab9600ca2da645 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 14 Mar 2015 10:23:45 -0400 Subject: MADS: Fix animation for putting severed arm on scanner --- engines/mads/nebular/nebular_scenes3.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes3.cpp b/engines/mads/nebular/nebular_scenes3.cpp index d6c7ba1cc7..e1540b502b 100644 --- a/engines/mads/nebular/nebular_scenes3.cpp +++ b/engines/mads/nebular/nebular_scenes3.cpp @@ -4496,7 +4496,7 @@ void Scene352::actions() { case 2: _vm->_sound->command(23); _scene->_sequences.remove(_commonSequenceIdx); - _commonSequenceIdx = _scene->_sequences.startPingPongCycle(_commonSpriteIndex, false, 8, 1, 0, 0); + _commonSequenceIdx = _scene->_sequences.addReverseSpriteCycle(_commonSpriteIndex, false, 8, 1, 0, 0); _scene->_sequences.setAnimRange(_commonSequenceIdx, 1, 4); _scene->_sequences.addSubEntry(_commonSequenceIdx, SEQUENCE_TRIGGER_EXPIRE, 0, 3); break; -- cgit v1.2.3 From d47197f1fac36082783c6236552fe64415349a94 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 14 Mar 2015 11:41:27 -0400 Subject: MADS: Fix original bug re-adding disabled hotspots to scene as active --- engines/mads/screen.cpp | 4 +++- engines/mads/screen.h | 2 +- engines/mads/user_interface.cpp | 4 +++- 3 files changed, 7 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/mads/screen.cpp b/engines/mads/screen.cpp index 5076bbb099..c06ff2b7b7 100644 --- a/engines/mads/screen.cpp +++ b/engines/mads/screen.cpp @@ -265,7 +265,7 @@ ScreenObjects::ScreenObjects(MADSEngine *vm) : _vm(vm) { _baseTime = 0; } -void ScreenObjects::add(const Common::Rect &bounds, ScreenMode mode, ScrCategory category, int descId) { +ScreenObject *ScreenObjects::add(const Common::Rect &bounds, ScreenMode mode, ScrCategory category, int descId) { ScreenObject so; so._bounds = bounds; so._category = category; @@ -274,6 +274,8 @@ void ScreenObjects::add(const Common::Rect &bounds, ScreenMode mode, ScrCategory so._active = true; push_back(so); + + return &(*this)[size()]; } void ScreenObjects::check(bool scanFlag) { diff --git a/engines/mads/screen.h b/engines/mads/screen.h index e2462aff18..85c55419ca 100644 --- a/engines/mads/screen.h +++ b/engines/mads/screen.h @@ -167,7 +167,7 @@ public: /** * Add a new item to the list */ - void add(const Common::Rect &bounds, ScreenMode mode, ScrCategory category, int descId); + ScreenObject *add(const Common::Rect &bounds, ScreenMode mode, ScrCategory category, int descId); /** * Check objects on the screen diff --git a/engines/mads/user_interface.cpp b/engines/mads/user_interface.cpp index bcd409889e..0363ae5ef9 100644 --- a/engines/mads/user_interface.cpp +++ b/engines/mads/user_interface.cpp @@ -732,7 +732,9 @@ void UserInterface::loadElements() { _categoryIndexes[CAT_HOTSPOT - 1] = _vm->_game->_screenObjects.size() + 1; for (int hotspotIdx = scene._hotspots.size() - 1; hotspotIdx >= 0; --hotspotIdx) { Hotspot &hs = scene._hotspots[hotspotIdx]; - _vm->_game->_screenObjects.add(hs._bounds, SCREENMODE_VGA, CAT_HOTSPOT, hotspotIdx); + ScreenObject *so = _vm->_game->_screenObjects.add(hs._bounds, SCREENMODE_VGA, + CAT_HOTSPOT, hotspotIdx); + so->_active = hs._active; } } -- cgit v1.2.3 From 561481499d4cb6e1d2a85e5dc35c7c8ff0534e3d Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 14 Mar 2015 11:57:28 -0400 Subject: MADS: Persist gameplay options --- engines/mads/mads.cpp | 19 +++++++++++++++++++ engines/mads/mads.h | 4 ++++ engines/mads/nebular/dialogs_nebular.cpp | 3 +++ 3 files changed, 26 insertions(+) (limited to 'engines') diff --git a/engines/mads/mads.cpp b/engines/mads/mads.cpp index 52a0b40561..a62ad2d7df 100644 --- a/engines/mads/mads.cpp +++ b/engines/mads/mads.cpp @@ -82,6 +82,8 @@ void MADSEngine::initialize() { MSurface::setVm(this); MSprite::setVm(this); + loadOptions(); + Resources::init(this); Conversation::init(this); _debugger = new Debugger(this); @@ -98,6 +100,23 @@ void MADSEngine::initialize() { _screen.empty(); } +void MADSEngine::loadOptions() { + if (ConfMan.hasKey("EasyMouse")) + _easyMouse = ConfMan.getBool("EasyMouse"); + if (ConfMan.hasKey("InvObjectsAnimated")) + _invObjectsAnimated = ConfMan.getBool("InvObjectsAnimated"); + if (ConfMan.hasKey("TextWindowStill")) + _textWindowStill = ConfMan.getBool("TextWindowStill"); +} + +void MADSEngine::saveOptions() { + ConfMan.setBool("EasyMouse", _easyMouse); + ConfMan.setBool("InvObjectsAnimated", _invObjectsAnimated); + ConfMan.setBool("TextWindowStill", _textWindowStill); + + ConfMan.flushToDisk(); +} + Common::Error MADSEngine::run() { initGraphics(MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT, false); initialize(); diff --git a/engines/mads/mads.h b/engines/mads/mads.h index 9a8f2152a1..7cc0ac8bc2 100644 --- a/engines/mads/mads.h +++ b/engines/mads/mads.h @@ -84,6 +84,8 @@ private: * Handles basic initialisation */ void initialize(); + + void loadOptions(); protected: // Engine APIs virtual Common::Error run(); @@ -145,6 +147,8 @@ public: * Handles saving the game via the GMM */ virtual Common::Error saveGameState(int slot, const Common::String &desc); + + void saveOptions(); }; } // End of namespace MADS diff --git a/engines/mads/nebular/dialogs_nebular.cpp b/engines/mads/nebular/dialogs_nebular.cpp index 530cf8a785..1c780c85b7 100644 --- a/engines/mads/nebular/dialogs_nebular.cpp +++ b/engines/mads/nebular/dialogs_nebular.cpp @@ -1117,12 +1117,15 @@ void OptionsDialog::show() { break; case 3: // Interface _vm->_easyMouse = !_vm->_easyMouse; + _vm->saveOptions(); break; case 4: // Inventory _vm->_invObjectsAnimated = !_vm->_invObjectsAnimated; + _vm->saveOptions(); break; case 5: // Text window _vm->_textWindowStill = !_vm->_textWindowStill; + _vm->saveOptions(); break; case 6: // Screen fade if (_vm->_screenFade == SCREEN_FADE_FAST) -- cgit v1.2.3 From a924d4beefc9d82ebe4c5a1880015aa7c97503de Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 14 Mar 2015 12:46:46 -0400 Subject: MADS: Fix hotspot highlighting when easy mouse is off --- engines/mads/events.cpp | 4 ++-- engines/mads/events.h | 2 +- engines/mads/screen.cpp | 6 +++--- engines/mads/user_interface.cpp | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) (limited to 'engines') diff --git a/engines/mads/events.cpp b/engines/mads/events.cpp index 06c6055f01..767f998d81 100644 --- a/engines/mads/events.cpp +++ b/engines/mads/events.cpp @@ -41,7 +41,7 @@ EventsManager::EventsManager(MADSEngine *vm) { _mouseReleased = false; _mouseButtons = 0; _mouseStatus = 0; - _vD2 = 0; + _strokeGoing = 0; _mouseStatusCopy = 0; _mouseMoved = false; _rightMousePressed = false; @@ -266,7 +266,7 @@ void EventsManager::waitForNextFrame() { void EventsManager::initVars() { _mousePos = Common::Point(-1, -1); _mouseStatusCopy = _mouseStatus; - _vD2 = 0; + _strokeGoing = 0; } } // End of namespace MADS diff --git a/engines/mads/events.h b/engines/mads/events.h index 21ef37407b..1a92754f10 100644 --- a/engines/mads/events.h +++ b/engines/mads/events.h @@ -67,7 +67,7 @@ public: byte _mouseButtons; bool _rightMousePressed; int _mouseStatus; - int _vD2; + int _strokeGoing; int _mouseStatusCopy; bool _mouseMoved; Common::Stack _pendingKeys; diff --git a/engines/mads/screen.cpp b/engines/mads/screen.cpp index c06ff2b7b7..3e2fe22611 100644 --- a/engines/mads/screen.cpp +++ b/engines/mads/screen.cpp @@ -308,10 +308,10 @@ void ScreenObjects::check(bool scanFlag) { } //_released = _vm->_events->_mouseReleased; - if (_vm->_events->_vD2 || (_vm->_easyMouse && !_vm->_events->_mouseStatusCopy)) + if (_vm->_events->_mouseButtons || (_vm->_easyMouse && !_vm->_events->_mouseStatusCopy)) scene._userInterface._category = _category; - if (!_vm->_events->_mouseButtons || _vm->_easyMouse) { + if (_vm->_events->_mouseButtons || _vm->_easyMouse) { if (userInterface._category >= CAT_COMMAND && userInterface._category <= CAT_TALK_ENTRY) { elementHighlighted(); } @@ -526,7 +526,7 @@ void ScreenObjects::elementHighlighted() { action._pickedWord = newIndex; if (_category == CAT_INV_LIST || _category == CAT_INV_ANIM) { - if (action._interAwaiting == 1 && newIndex >= 0 && _released && + if (action._interAwaiting == AWAITING_COMMAND && newIndex >= 0 && _released && (!_vm->_events->_mouseReleased || !_vm->_easyMouse)) newIndex = -1; } diff --git a/engines/mads/user_interface.cpp b/engines/mads/user_interface.cpp index 0363ae5ef9..eced2fdb12 100644 --- a/engines/mads/user_interface.cpp +++ b/engines/mads/user_interface.cpp @@ -522,7 +522,7 @@ void UserInterface::updateInventoryScroller() { uint32 timeInc = _scrollbarQuickly ? 100 : 380; if (_vm->_events->_mouseStatus && (_scrollbarMilliTime + timeInc) <= currentMilli) { - _scrollbarQuickly = _vm->_events->_vD2 < 1; + _scrollbarQuickly = _vm->_events->_strokeGoing < 1; _scrollbarMilliTime = currentMilli; // Change the scrollbar and visible inventory list -- cgit v1.2.3 From b39abbfb4955521211847f33bcc133cdd9642fe3 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 14 Mar 2015 14:04:41 -0400 Subject: MADS: Save reverted options if you cancel out of Game Options dialog --- engines/mads/nebular/dialogs_nebular.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'engines') diff --git a/engines/mads/nebular/dialogs_nebular.cpp b/engines/mads/nebular/dialogs_nebular.cpp index 1c780c85b7..10fa28c013 100644 --- a/engines/mads/nebular/dialogs_nebular.cpp +++ b/engines/mads/nebular/dialogs_nebular.cpp @@ -1158,6 +1158,8 @@ void OptionsDialog::show() { _vm->_textWindowStill = prevTextWindowStill; _vm->_screenFade = prevScreenFade; game._storyMode = prevStoryMode; + + _vm->saveOptions(); } } -- cgit v1.2.3 From 1e15c02d1ea56439509926b68b9e393957241e65 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 14 Mar 2015 14:38:22 -0400 Subject: MADS: Fix animation of tying rope to the boat --- engines/mads/animation.cpp | 14 ++++++++++---- engines/mads/animation.h | 5 +++++ engines/mads/nebular/nebular_scenes5.cpp | 9 +++++++-- 3 files changed, 22 insertions(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/mads/animation.cpp b/engines/mads/animation.cpp index 7e616bffbc..bda0bb6876 100644 --- a/engines/mads/animation.cpp +++ b/engines/mads/animation.cpp @@ -436,10 +436,7 @@ void Animation::update() { if (_vm->_game->_scene._frameStartTime < _nextFrameTimer) return; - for (uint idx = 0; idx < scene._spriteSlots.size(); ++idx) { - if (scene._spriteSlots[idx]._seqIndex >= 0x80) - scene._spriteSlots[idx]._flags = IMG_ERASE; - } + eraseSprites(); // Validate the current frame if (_currentFrame >= (int)_miscEntries.size()) { @@ -604,4 +601,13 @@ void Animation::setNextFrameTimer(int frameNumber) { _nextFrameTimer = frameNumber; } +void Animation::eraseSprites() { + Scene &scene = _vm->_game->_scene; + + for (uint idx = 0; idx < scene._spriteSlots.size(); ++idx) { + if (scene._spriteSlots[idx]._seqIndex >= 0x80) + scene._spriteSlots[idx]._flags = IMG_ERASE; + } +} + } // End of namespace MADS diff --git a/engines/mads/animation.h b/engines/mads/animation.h index 8b85a5370d..1c87273e62 100644 --- a/engines/mads/animation.h +++ b/engines/mads/animation.h @@ -219,6 +219,11 @@ public: */ void update(); + /** + * Erases any sprites from the previous animation frame + */ + void eraseSprites(); + void setNextFrameTimer(int frameNumber); int getNextFrameTimer() const { return _nextFrameTimer; } void setCurrentFrame(int frameNumber); diff --git a/engines/mads/nebular/nebular_scenes5.cpp b/engines/mads/nebular/nebular_scenes5.cpp index a76edaca67..2470137b2e 100644 --- a/engines/mads/nebular/nebular_scenes5.cpp +++ b/engines/mads/nebular/nebular_scenes5.cpp @@ -2066,6 +2066,7 @@ void Scene511::actions() { if (_game._trigger == 0) { _game._player._stepEnabled = false; _game._player._visible = false; + _game._player.update(); _lineAnimationMode = 1; _lineAnimationPosition = 1; _lineMoving = true; @@ -2088,7 +2089,8 @@ void Scene511::actions() { } else { _vm->_dialogs->show(51130); } - } else if (_action.isAction(VERB_TIE, NOUN_FISHING_LINE, NOUN_BOAT) || _action.isAction(VERB_ATTACH, NOUN_FISHING_LINE, NOUN_BOAT)) { + } else if (_action.isAction(VERB_TIE, NOUN_FISHING_LINE, NOUN_BOAT) || + _action.isAction(VERB_ATTACH, NOUN_FISHING_LINE, NOUN_BOAT)) { if (_globals[kBoatRaised]) _vm->_dialogs->show(51131); else if (_globals[kLineStatus] == 1) @@ -2106,7 +2108,6 @@ void Scene511::actions() { _scene->_sequences.addTimer(1, 1); else { _game._player._visible = true; - _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; _globals._sequenceIndexes[7] = _scene->_sequences.startCycle(_globals._spriteIndexes[7], false, -2); _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 4); int idx = _scene->_dynamicHotspots.add(NOUN_FISHING_LINE, VERB_WALKTO, _globals._sequenceIndexes[7], Common::Rect(0, 0, 0, 0)); @@ -2116,6 +2117,10 @@ void Scene511::actions() { _lineMoving = true; _globals[kLineStatus] = 3; _game._player._stepEnabled = true; + + if (_scene->_activeAnimation) + _scene->_activeAnimation->eraseSprites(); + _game._player.update(); } } } -- cgit v1.2.3 From fa7dfc396a2ca33e01a0151f63857dd64406502c Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 14 Mar 2015 15:05:42 -0400 Subject: MADS: Fix greeting when talking to cell wall the first time --- engines/mads/nebular/nebular_scenes3.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes3.cpp b/engines/mads/nebular/nebular_scenes3.cpp index e1540b502b..383f5b509f 100644 --- a/engines/mads/nebular/nebular_scenes3.cpp +++ b/engines/mads/nebular/nebular_scenes3.cpp @@ -525,7 +525,7 @@ void Scene307::setup() { } void Scene307::handleRexDialog(int quote) { - Common::String curQuote = _game.getQuote(_action._activeAction._verbId); + Common::String curQuote = _game.getQuote(quote); if (_vm->_font->getWidth(curQuote, _scene->_textSpacing) > 200) { Common::String subQuote1; _game.splitQuote(curQuote, subQuote1, _subQuote2); -- cgit v1.2.3 From 9eb342615c4cdbc1f38374b9a7808dc54bfb7ad9 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 14 Mar 2015 18:34:26 -0400 Subject: MADS: Fix frequently getting endless wait cursor after doctor hits you --- engines/mads/nebular/nebular_scenes3.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes3.cpp b/engines/mads/nebular/nebular_scenes3.cpp index 383f5b509f..4e7781e7a2 100644 --- a/engines/mads/nebular/nebular_scenes3.cpp +++ b/engines/mads/nebular/nebular_scenes3.cpp @@ -3313,7 +3313,7 @@ void Scene319::step() { switch (_game._trigger) { case 70: - case 71: + case 71: { _animMode = 1; _nextAction1 = _nextAction2; _animFrame = 0; @@ -3336,7 +3336,14 @@ void Scene319::step() { _scene->_sequences.updateTimeout(_globals._sequenceIndexes[i], oldIdx); } _scene->_sequences.addSubEntry(_globals._sequenceIndexes[0], SEQUENCE_TRIGGER_EXPIRE, 0, 74); + + // WORKAROUND: This fixes the game sometimes going into an endless waiting + // loop even after the doctor has finished hitting Rex. Note sure if it's due + // to a bug in room script or in the engine, but this at least fixes it + int seqIndex = _scene->_sequences.findByTrigger(2); + _scene->_sequences[seqIndex]._doneFlag = false; break; + } case 72: _vm->_palette->setColorFlags(0xFF, 0, 0); -- cgit v1.2.3 From 97ef41707ab957099b4972bba501479001315e69 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 14 Mar 2015 19:09:44 -0400 Subject: MADS: Hook up sfx/music flags --- engines/mads/detection_tables.h | 4 ++-- engines/mads/mads.cpp | 18 ++++++++++++++++++ engines/mads/mads.h | 6 ++++++ engines/mads/sound.cpp | 5 ++++- 4 files changed, 30 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/mads/detection_tables.h b/engines/mads/detection_tables.h index e68ae380d0..92614ba361 100644 --- a/engines/mads/detection_tables.h +++ b/engines/mads/detection_tables.h @@ -56,7 +56,7 @@ static const MADSGameDescription gameDescriptions[] = { Common::EN_ANY, Common::kPlatformDOS, ADGF_NO_FLAGS, - GUIO1(GUIO_NONE) + GUIO1(GUIO_NOSPEECH) }, GType_RexNebular, 0 @@ -74,7 +74,7 @@ static const MADSGameDescription gameDescriptions[] = { Common::EN_ANY, Common::kPlatformDOS, ADGF_NO_FLAGS, - GUIO1(GUIO_NONE) + GUIO1(GUIO_NOSPEECH) }, GType_RexNebular, 0 diff --git a/engines/mads/mads.cpp b/engines/mads/mads.cpp index a62ad2d7df..761aef3e66 100644 --- a/engines/mads/mads.cpp +++ b/engines/mads/mads.cpp @@ -44,6 +44,7 @@ MADSEngine::MADSEngine(OSystem *syst, const MADSGameDescription *gameDesc) : _textWindowStill = false; _screenFade = SCREEN_FADE_SMOOTH; _musicFlag = true; + _soundFlag = true; _dithering = false; _debugger = nullptr; @@ -107,12 +108,23 @@ void MADSEngine::loadOptions() { _invObjectsAnimated = ConfMan.getBool("InvObjectsAnimated"); if (ConfMan.hasKey("TextWindowStill")) _textWindowStill = ConfMan.getBool("TextWindowStill"); + + if (ConfMan.hasKey("mute") && ConfMan.getBool("mute")) { + _soundFlag = false; + _musicFlag = false; + } else { + _soundFlag = !ConfMan.hasKey("sfx_mute") || !ConfMan.getBool("sfx_mute"); + _musicFlag = !ConfMan.hasGameDomain("music_mute") || !ConfMan.getBool("music_mute"); + } } void MADSEngine::saveOptions() { ConfMan.setBool("EasyMouse", _easyMouse); ConfMan.setBool("InvObjectsAnimated", _invObjectsAnimated); ConfMan.setBool("TextWindowStill", _textWindowStill); + ConfMan.setBool("mute", !_soundFlag && !_musicFlag); + ConfMan.setBool("sfx_mute", !_soundFlag && _musicFlag); + ConfMan.setBool("music_mute", _soundFlag && !_musicFlag); ConfMan.flushToDisk(); } @@ -153,6 +165,12 @@ bool MADSEngine::canSaveGameStateCurrently() { && _events->_cursorId != CURSOR_WAIT; } +void MADSEngine::syncSoundSettings() { + Engine::syncSoundSettings(); + + loadOptions(); +} + /** * Support method that generates a savegame name * @param slot Slot number diff --git a/engines/mads/mads.h b/engines/mads/mads.h index 7cc0ac8bc2..1d641e7c87 100644 --- a/engines/mads/mads.h +++ b/engines/mads/mads.h @@ -106,6 +106,7 @@ public: bool _textWindowStill; ScreenFade _screenFade; bool _musicFlag; + bool _soundFlag; bool _dithering; public: MADSEngine(OSystem *syst, const MADSGameDescription *gameDesc); @@ -148,6 +149,11 @@ public: */ virtual Common::Error saveGameState(int slot, const Common::String &desc); + /** + * Handles updating sound settings after they're changed in the GMM dialog + */ + virtual void syncSoundSettings(); + void saveOptions(); }; diff --git a/engines/mads/sound.cpp b/engines/mads/sound.cpp index fbf217ba0c..1baa169c55 100644 --- a/engines/mads/sound.cpp +++ b/engines/mads/sound.cpp @@ -146,7 +146,10 @@ void SoundManager::command(int commandId, int param) { if (_queuedCommands.size() < 8) _queuedCommands.push(commandId); } else if (_driver) { - _driver->command(commandId, param); + // Note: I don't know any way to identify music commands versus sfx + // commands, so if sfx is mute, then so is music + if (_vm->_soundFlag) + _driver->command(commandId, param); } } -- cgit v1.2.3 From 299bfa3696aaf3c689798faef198d714eb234f4f Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 14 Mar 2015 19:24:56 -0400 Subject: MADS: Fix showing inventory pictures when inventory animating is off --- engines/mads/user_interface.cpp | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) (limited to 'engines') diff --git a/engines/mads/user_interface.cpp b/engines/mads/user_interface.cpp index eced2fdb12..93a555d9c7 100644 --- a/engines/mads/user_interface.cpp +++ b/engines/mads/user_interface.cpp @@ -864,13 +864,13 @@ void UserInterface::loadInventoryAnim(int objectId) { Scene &scene = _vm->_game->_scene; noInventoryAnim(); - if (_vm->_invObjectsAnimated) { - Common::String resName = Common::String::format("*OB%.3dI", objectId); - SpriteAsset *asset = new SpriteAsset(_vm, resName, ASSET_SPINNING_OBJECT); - _invSpritesIndex = scene._sprites.add(asset, 1); - if (_invSpritesIndex >= 0) { - _invFrameNumber = 1; - } + // WORKAROUND: Even in still mode, we now load the animation frames for the + // object, so we can show the first frame as a 'still' + Common::String resName = Common::String::format("*OB%.3dI", objectId); + SpriteAsset *asset = new SpriteAsset(_vm, resName, ASSET_SPINNING_OBJECT); + _invSpritesIndex = scene._sprites.add(asset, 1); + if (_invSpritesIndex >= 0) { + _invFrameNumber = 1; } } @@ -902,10 +902,13 @@ void UserInterface::inventoryAnim() { _invSpritesIndex < 0) return; - // Move to the next frame number in the sequence, resetting if at the end - SpriteAsset *asset = scene._sprites[_invSpritesIndex]; - if (++_invFrameNumber > asset->getCount()) - _invFrameNumber = 1; + // WORKAROUND: Fix still inventory display, which was broken in the original + if (_vm->_invObjectsAnimated) { + // Move to the next frame number in the sequence, resetting if at the end + SpriteAsset *asset = scene._sprites[_invSpritesIndex]; + if (++_invFrameNumber > asset->getCount()) + _invFrameNumber = 1; + } // Loop through the slots list for inventory animation entry for (uint i = 0; i < _uiSlots.size(); ++i) { -- cgit v1.2.3 From d3afff9bc736175b0275d923788198706adc7d78 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 14 Mar 2015 19:30:01 -0400 Subject: MADS: Fix animations erasing sprites on the last frame before transitioning --- engines/mads/animation.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/mads/animation.cpp b/engines/mads/animation.cpp index bda0bb6876..b48491626d 100644 --- a/engines/mads/animation.cpp +++ b/engines/mads/animation.cpp @@ -436,8 +436,6 @@ void Animation::update() { if (_vm->_game->_scene._frameStartTime < _nextFrameTimer) return; - eraseSprites(); - // Validate the current frame if (_currentFrame >= (int)_miscEntries.size()) { // Is the animation allowed to be repeated? @@ -450,6 +448,8 @@ void Animation::update() { } } + eraseSprites(); + // Handle executing any sound command for this frame AnimMiscEntry &misc = _miscEntries[_currentFrame]; if (misc._soundId) -- cgit v1.2.3 From 19a9c068f994d5800a60dff6f14221f03f5d4cc3 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 15 Mar 2015 04:05:06 +0200 Subject: MADS: Hook up all of the remaining options, and add custom game options --- engines/mads/detection.cpp | 63 +++++++++++++++++++++++++++++++- engines/mads/game.h | 3 ++ engines/mads/mads.cpp | 35 +++++++++++++----- engines/mads/nebular/dialogs_nebular.cpp | 24 ++++++------ engines/mads/nebular/game_nebular.h | 3 ++ 5 files changed, 105 insertions(+), 23 deletions(-) (limited to 'engines') diff --git a/engines/mads/detection.cpp b/engines/mads/detection.cpp index 971acde024..ea71fc8539 100644 --- a/engines/mads/detection.cpp +++ b/engines/mads/detection.cpp @@ -29,6 +29,7 @@ #include "common/memstream.h" #include "engines/advancedDetector.h" #include "common/system.h" +#include "common/translation.h" #include "graphics/colormasks.h" #include "graphics/surface.h" #include "mads/events.h" @@ -75,11 +76,71 @@ static const PlainGameDescriptor MADSGames[] = { {0, 0} }; +#define GAMEOPTION_EASY_MOUSE GUIO_GAMEOPTIONS1 +#define GAMEOPTION_ANIMATED_INVENTORY GUIO_GAMEOPTIONS2 +#define GAMEOPTION_ANIMATED_INTERFACE GUIO_GAMEOPTIONS3 +#define GAMEOPTION_NAUGHTY_MODE GUIO_GAMEOPTIONS4 +//#define GAMEOPTION_GRAPHICS_DITHERING GUIO_GAMEOPTIONS5 + #include "mads/detection_tables.h" +static const ADExtraGuiOptionsMap optionsList[] = { + { + GAMEOPTION_EASY_MOUSE, + { + _s("Easy mouse interface"), + _s("Shows object names when hovering the mouse over them"), + "EasyMouse", + true + } + }, + + { + GAMEOPTION_ANIMATED_INVENTORY, + { + _s("Animated inventory items"), + _s("Animated inventory items"), + "InvObjectsAnimated", + true + } + }, + + { + GAMEOPTION_ANIMATED_INTERFACE, + { + _s("Animated game interface"), + _s("Animated game interface"), + "TextWindowAnimated", + true + } + }, + + { + GAMEOPTION_NAUGHTY_MODE, + { + _s("Naughty game mode"), + _s("Naughty game mode"), + "NaughtyMode", + true + } + }, + + /*{ + GAMEOPTION_GRAPHICS_DITHERING, + { + _s("Graphics dithering"), + _s("Graphics dithering"), + "GraphicsDithering", + true + } + },*/ + + AD_EXTRA_GUI_OPTIONS_TERMINATOR +}; + class MADSMetaEngine : public AdvancedMetaEngine { public: - MADSMetaEngine() : AdvancedMetaEngine(MADS::gameDescriptions, sizeof(MADS::MADSGameDescription), MADSGames) { + MADSMetaEngine() : AdvancedMetaEngine(MADS::gameDescriptions, sizeof(MADS::MADSGameDescription), MADSGames, optionsList) { _maxScanDepth = 3; } diff --git a/engines/mads/game.h b/engines/mads/game.h index 66f2580249..d246aa501e 100644 --- a/engines/mads/game.h +++ b/engines/mads/game.h @@ -195,6 +195,9 @@ public: */ virtual void synchronize(Common::Serializer &s, bool phase1); + virtual void setNaughtyMode(bool naughtyMode) {} + virtual bool getNaughtyMode() const { return true; } + // DEPRECATED: ScummVM re-implementation keeps all the quotes loaded, so the methods below are stubs void clearQuotes() {} void loadQuoteRange(int startNum, int endNum) {} diff --git a/engines/mads/mads.cpp b/engines/mads/mads.cpp index 761aef3e66..59d600fbfb 100644 --- a/engines/mads/mads.cpp +++ b/engines/mads/mads.cpp @@ -38,7 +38,7 @@ namespace MADS { MADSEngine::MADSEngine(OSystem *syst, const MADSGameDescription *gameDesc) : _gameDescription(gameDesc), Engine(syst), _randomSource("MADS") { - // Initialize fields + // Initialize game/engine options _easyMouse = true; _invObjectsAnimated = true; _textWindowStill = false; @@ -83,8 +83,6 @@ void MADSEngine::initialize() { MSurface::setVm(this); MSprite::setVm(this); - loadOptions(); - Resources::init(this); Conversation::init(this); _debugger = new Debugger(this); @@ -98,16 +96,14 @@ void MADSEngine::initialize() { _audio = new AudioPlayer(_mixer, getGameID()); _game = Game::init(this); + loadOptions(); + _screen.empty(); } void MADSEngine::loadOptions() { if (ConfMan.hasKey("EasyMouse")) _easyMouse = ConfMan.getBool("EasyMouse"); - if (ConfMan.hasKey("InvObjectsAnimated")) - _invObjectsAnimated = ConfMan.getBool("InvObjectsAnimated"); - if (ConfMan.hasKey("TextWindowStill")) - _textWindowStill = ConfMan.getBool("TextWindowStill"); if (ConfMan.hasKey("mute") && ConfMan.getBool("mute")) { _soundFlag = false; @@ -116,16 +112,37 @@ void MADSEngine::loadOptions() { _soundFlag = !ConfMan.hasKey("sfx_mute") || !ConfMan.getBool("sfx_mute"); _musicFlag = !ConfMan.hasGameDomain("music_mute") || !ConfMan.getBool("music_mute"); } + + if (ConfMan.hasKey("ScreenFade")) + _screenFade = (ScreenFade)ConfMan.getInt("ScreenFade"); + //if (ConfMan.hasKey("GraphicsDithering")) + // _dithering = ConfMan.getBool("GraphicsDithering"); + + if (getGameID() == GType_RexNebular) { + if (ConfMan.hasKey("InvObjectsAnimated")) + _invObjectsAnimated = ConfMan.getBool("InvObjectsAnimated"); + if (ConfMan.hasKey("TextWindowStill")) + _textWindowStill = !ConfMan.getBool("TextWindowAnimated"); + if (ConfMan.hasKey("NaughtyMode")) + _game->setNaughtyMode(ConfMan.getBool("NaughtyMode")); + } } void MADSEngine::saveOptions() { ConfMan.setBool("EasyMouse", _easyMouse); - ConfMan.setBool("InvObjectsAnimated", _invObjectsAnimated); - ConfMan.setBool("TextWindowStill", _textWindowStill); + ConfMan.setInt("ScreenFade", (int)_screenFade); + //ConfMan.setBool("GraphicsDithering", _dithering); + ConfMan.setBool("mute", !_soundFlag && !_musicFlag); ConfMan.setBool("sfx_mute", !_soundFlag && _musicFlag); ConfMan.setBool("music_mute", _soundFlag && !_musicFlag); + if (getGameID() == GType_RexNebular) { + ConfMan.setBool("InvObjectsAnimated", _invObjectsAnimated); + ConfMan.setBool("TextWindowAnimated", !_textWindowStill); + ConfMan.setBool("NaughtyMode", _game->getNaughtyMode()); + } + ConfMan.flushToDisk(); } diff --git a/engines/mads/nebular/dialogs_nebular.cpp b/engines/mads/nebular/dialogs_nebular.cpp index 10fa28c013..0b5e921dcc 100644 --- a/engines/mads/nebular/dialogs_nebular.cpp +++ b/engines/mads/nebular/dialogs_nebular.cpp @@ -1050,12 +1050,11 @@ OptionsDialog::OptionsDialog(MADSEngine *vm) : GameDialog(vm) { int OptionsDialog::getOptionQuote(int option) { Nebular::GameNebular &game = *(Nebular::GameNebular *)_vm->_game; - // TODO: Hook the rest of the options to the current config switch (option) { case 17: // Music - return 24; // 24: ON, 25: OFF + return _vm->_musicFlag ? 24 : 25; // 24: ON, 25: OFF case 18: // Sound - return 26; // 26: ON, 27: OFF + return _vm->_soundFlag ? 26 : 27; // 26: ON, 27: OFF case 19: // Interface return !_vm->_easyMouse ? 28 : 29; // 28: Standard, 29: Easy case 20: // Inventory @@ -1098,6 +1097,7 @@ void OptionsDialog::show() { Nebular::GameNebular &game = *(Nebular::GameNebular *)_vm->_game; // Previous options, restored when cancel is selected + bool prevMusicFlag = _vm->_musicFlag; bool prevEasyMouse = _vm->_easyMouse; bool prevInvObjectsAnimated = _vm->_invObjectsAnimated; bool prevTextWindowStill = _vm->_textWindowStill; @@ -1110,22 +1110,19 @@ void OptionsDialog::show() { switch (_selectedLine) { case 1: // Music - warning("STUB: Music toggle"); + _vm->_musicFlag = _vm->_soundFlag = !_vm->_musicFlag; break; case 2: // Sound - warning("STUB: Sound toggle"); + _vm->_musicFlag = _vm->_soundFlag = !_vm->_musicFlag; break; case 3: // Interface _vm->_easyMouse = !_vm->_easyMouse; - _vm->saveOptions(); break; case 4: // Inventory _vm->_invObjectsAnimated = !_vm->_invObjectsAnimated; - _vm->saveOptions(); break; case 5: // Text window _vm->_textWindowStill = !_vm->_textWindowStill; - _vm->saveOptions(); break; case 6: // Screen fade if (_vm->_screenFade == SCREEN_FADE_FAST) @@ -1150,16 +1147,17 @@ void OptionsDialog::show() { setLines(); } while (!_vm->shouldQuit() && _selectedLine != 0 && _selectedLine <= 7); - // If Done button not pressed, reset settings - if (_selectedLine != 8) { - // Revert all options from the saved ones + if (_selectedLine == 8) { + // OK button, save settings + _vm->saveOptions(); + } else if (_selectedLine == 9) { + // Cancel button, revert all options from the saved ones + _vm->_musicFlag = prevMusicFlag; _vm->_easyMouse = prevEasyMouse; _vm->_invObjectsAnimated = prevInvObjectsAnimated; _vm->_textWindowStill = prevTextWindowStill; _vm->_screenFade = prevScreenFade; game._storyMode = prevStoryMode; - - _vm->saveOptions(); } } diff --git a/engines/mads/nebular/game_nebular.h b/engines/mads/nebular/game_nebular.h index efa21a2e73..1b89d11412 100644 --- a/engines/mads/nebular/game_nebular.h +++ b/engines/mads/nebular/game_nebular.h @@ -131,6 +131,9 @@ public: virtual void step(); virtual void synchronize(Common::Serializer &s, bool phase1); + + virtual void setNaughtyMode(bool naughtyMode) { _storyMode = naughtyMode ? STORYMODE_NAUGHTY : STORYMODE_NICE; } + virtual bool getNaughtyMode() const { return _storyMode == STORYMODE_NAUGHTY; } }; // Section handlers aren't needed in ScummVM implementation -- cgit v1.2.3 From 97ca67ecac3bd4e27cd2ea93c5e88e44722972a3 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 15 Mar 2015 13:45:31 +0200 Subject: MADS: Properly reset the sound flag --- engines/mads/nebular/dialogs_nebular.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mads/nebular/dialogs_nebular.cpp b/engines/mads/nebular/dialogs_nebular.cpp index 0b5e921dcc..4ba5366a60 100644 --- a/engines/mads/nebular/dialogs_nebular.cpp +++ b/engines/mads/nebular/dialogs_nebular.cpp @@ -1152,7 +1152,7 @@ void OptionsDialog::show() { _vm->saveOptions(); } else if (_selectedLine == 9) { // Cancel button, revert all options from the saved ones - _vm->_musicFlag = prevMusicFlag; + _vm->_musicFlag = _vm->_soundFlag = prevMusicFlag; _vm->_easyMouse = prevEasyMouse; _vm->_invObjectsAnimated = prevInvObjectsAnimated; _vm->_textWindowStill = prevTextWindowStill; -- cgit v1.2.3 From 74327cadad47824863f52fdb2b68d093b3a939a6 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 15 Mar 2015 13:47:45 +0200 Subject: MADS: Add custom game options to the ScummVM GUI This should be part of commit 19a9c068f, but it wasn't committed --- engines/mads/detection_tables.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/mads/detection_tables.h b/engines/mads/detection_tables.h index 92614ba361..0a8e98bb31 100644 --- a/engines/mads/detection_tables.h +++ b/engines/mads/detection_tables.h @@ -37,7 +37,7 @@ static const MADSGameDescription gameDescriptions[] = { Common::EN_ANY, Common::kPlatformDOS, ADGF_NO_FLAGS, - GUIO1(GUIO_NONE) + GUIO5(GUIO_NOSPEECH, GAMEOPTION_EASY_MOUSE, GAMEOPTION_ANIMATED_INVENTORY, GAMEOPTION_ANIMATED_INTERFACE, GAMEOPTION_NAUGHTY_MODE) }, GType_RexNebular, 0 @@ -56,7 +56,7 @@ static const MADSGameDescription gameDescriptions[] = { Common::EN_ANY, Common::kPlatformDOS, ADGF_NO_FLAGS, - GUIO1(GUIO_NOSPEECH) + GUIO5(GUIO_NOSPEECH, GAMEOPTION_EASY_MOUSE, GAMEOPTION_ANIMATED_INVENTORY, GAMEOPTION_ANIMATED_INTERFACE, GAMEOPTION_NAUGHTY_MODE) }, GType_RexNebular, 0 @@ -74,7 +74,7 @@ static const MADSGameDescription gameDescriptions[] = { Common::EN_ANY, Common::kPlatformDOS, ADGF_NO_FLAGS, - GUIO1(GUIO_NOSPEECH) + GUIO5(GUIO_NOSPEECH, GAMEOPTION_EASY_MOUSE, GAMEOPTION_ANIMATED_INVENTORY, GAMEOPTION_ANIMATED_INTERFACE, GAMEOPTION_NAUGHTY_MODE) }, GType_RexNebular, 0 @@ -92,7 +92,7 @@ static const MADSGameDescription gameDescriptions[] = { Common::EN_ANY, Common::kPlatformDOS, ADGF_NO_FLAGS, - GUIO1(GUIO_NONE) + GUIO1(GAMEOPTION_EASY_MOUSE) }, GType_Phantom, 0 @@ -110,7 +110,7 @@ static const MADSGameDescription gameDescriptions[] = { Common::EN_ANY, Common::kPlatformDOS, ADGF_NO_FLAGS, - GUIO1(GUIO_NONE) + GUIO1(GAMEOPTION_EASY_MOUSE) }, GType_Dragonsphere, 0 -- cgit v1.2.3 From 9caed13d906b852cd90033a2df304d19f0f0e38c Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 15 Mar 2015 16:18:38 -0400 Subject: MADS: Better handling for removing sprite sets --- engines/mads/sprites.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/mads/sprites.cpp b/engines/mads/sprites.cpp index 6488add86c..67d5e20fe5 100644 --- a/engines/mads/sprites.cpp +++ b/engines/mads/sprites.cpp @@ -402,10 +402,13 @@ void SpriteSets::remove(int idx) { } else if (idx >= 0) { delete (*this)[idx]; - if (idx == ((int)size() - 1)) - remove_at(size() - 1); - else + if (idx < ((int)size() - 1)) { (*this)[idx] = nullptr; + } else { + do { + remove_at(size() - 1); + } while (size() > 0 && (*this)[size() - 1] == nullptr); + } } } -- cgit v1.2.3 From 6d8134f7518a2c368a55cfc49ba0a625a9744645 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 15 Mar 2015 16:20:01 -0400 Subject: MADS: Revert fix for sprites disappearing on last frame of cutscenes The fix that kept the sprites on-screen for the last frame before scene changes in the intro/ending sequences was also causing crashes in-game, where the animation is getting freed before the scene update to remove the sprites was done, so it couldn't get the areas of the screen to refresh --- engines/mads/animation.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/mads/animation.cpp b/engines/mads/animation.cpp index b48491626d..cf02e7b0b5 100644 --- a/engines/mads/animation.cpp +++ b/engines/mads/animation.cpp @@ -436,6 +436,9 @@ void Animation::update() { if (_vm->_game->_scene._frameStartTime < _nextFrameTimer) return; + // Erase any active sprites + eraseSprites(); + // Validate the current frame if (_currentFrame >= (int)_miscEntries.size()) { // Is the animation allowed to be repeated? @@ -448,8 +451,6 @@ void Animation::update() { } } - eraseSprites(); - // Handle executing any sound command for this frame AnimMiscEntry &misc = _miscEntries[_currentFrame]; if (misc._soundId) -- cgit v1.2.3 From 87a9ba5f2f5b9c3cde675c238ce718147417df03 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 15 Mar 2015 16:52:55 -0400 Subject: SHERLOCK: Initial commit --- engines/sherlock/configure.engine | 3 + engines/sherlock/decompress.cpp | 82 +++++++++++++ engines/sherlock/decompress.h | 36 ++++++ engines/sherlock/detection.cpp | 125 ++++++++++++++++++++ engines/sherlock/detection_tables.h | 47 ++++++++ engines/sherlock/graphics.cpp | 45 +++++++ engines/sherlock/graphics.h | 43 +++++++ engines/sherlock/inventory.h | 40 +++++++ engines/sherlock/journal.cpp | 40 +++++++ engines/sherlock/journal.h | 46 ++++++++ engines/sherlock/module.mk | 22 ++++ engines/sherlock/resources.cpp | 219 +++++++++++++++++++++++++++++++++++ engines/sherlock/resources.h | 86 ++++++++++++++ engines/sherlock/room.cpp | 32 +++++ engines/sherlock/room.h | 102 ++++++++++++++++ engines/sherlock/scalpel/scalpel.cpp | 40 +++++++ engines/sherlock/scalpel/scalpel.h | 45 +++++++ engines/sherlock/sherlock.cpp | 81 +++++++++++++ engines/sherlock/sherlock.h | 91 +++++++++++++++ engines/sherlock/sound.h | 39 +++++++ engines/sherlock/sprite.cpp | 142 +++++++++++++++++++++++ engines/sherlock/sprite.h | 56 +++++++++ engines/sherlock/talk.cpp | 30 +++++ engines/sherlock/talk.h | 49 ++++++++ engines/sherlock/tattoo/tattoo.cpp | 38 ++++++ engines/sherlock/tattoo/tattoo.h | 45 +++++++ engines/sherlock/vdaplayer.h | 34 ++++++ 27 files changed, 1658 insertions(+) create mode 100644 engines/sherlock/configure.engine create mode 100644 engines/sherlock/decompress.cpp create mode 100644 engines/sherlock/decompress.h create mode 100644 engines/sherlock/detection.cpp create mode 100644 engines/sherlock/detection_tables.h create mode 100644 engines/sherlock/graphics.cpp create mode 100644 engines/sherlock/graphics.h create mode 100644 engines/sherlock/inventory.h create mode 100644 engines/sherlock/journal.cpp create mode 100644 engines/sherlock/journal.h create mode 100644 engines/sherlock/module.mk create mode 100644 engines/sherlock/resources.cpp create mode 100644 engines/sherlock/resources.h create mode 100644 engines/sherlock/room.cpp create mode 100644 engines/sherlock/room.h create mode 100644 engines/sherlock/scalpel/scalpel.cpp create mode 100644 engines/sherlock/scalpel/scalpel.h create mode 100644 engines/sherlock/sherlock.cpp create mode 100644 engines/sherlock/sherlock.h create mode 100644 engines/sherlock/sound.h create mode 100644 engines/sherlock/sprite.cpp create mode 100644 engines/sherlock/sprite.h create mode 100644 engines/sherlock/talk.cpp create mode 100644 engines/sherlock/talk.h create mode 100644 engines/sherlock/tattoo/tattoo.cpp create mode 100644 engines/sherlock/tattoo/tattoo.h create mode 100644 engines/sherlock/vdaplayer.h (limited to 'engines') diff --git a/engines/sherlock/configure.engine b/engines/sherlock/configure.engine new file mode 100644 index 0000000000..a56129a8f0 --- /dev/null +++ b/engines/sherlock/configure.engine @@ -0,0 +1,3 @@ +# This file is included from the main "configure" script +# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps] +add_engine sherlock "The Lost Files of Sherlock Holmes" no diff --git a/engines/sherlock/decompress.cpp b/engines/sherlock/decompress.cpp new file mode 100644 index 0000000000..61110be840 --- /dev/null +++ b/engines/sherlock/decompress.cpp @@ -0,0 +1,82 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "sherlock/decompress.h" + +namespace Sherlock { + +/** + * Decompresses an LZW compressed resource. If no outSize is specified, it will + * decompress the entire resource. If, however, an explicit size is specified, + * it will decompress only up to that many bytes from the stream starting at + * whatever position it was previously. + */ +Common::SeekableReadStream *decompressLZ(Common::SeekableReadStream &source, int32 outSize) { + if (outSize == -1) { + source.seek(5); + outSize = source.readSint32LE(); + } + + byte lzWindow[4096]; + uint16 lzWindowPos; + uint16 cmd; + + byte *outBuffer = new byte[outSize]; + byte *outBufferEnd = outBuffer + outSize; + Common::MemoryReadStream *outS = new Common::MemoryReadStream(outBuffer, outSize, DisposeAfterUse::YES); + + memset(lzWindow, 0xFF, 0xFEE); + lzWindowPos = 0xFEE; + cmd = 0; + + while (1) { + cmd >>= 1; + if (!(cmd & 0x100)) { + cmd = source.readByte() | 0xFF00; + } + if (cmd & 1) { + byte literal = source.readByte(); + *outBuffer++ = literal; + lzWindow[lzWindowPos] = literal; + lzWindowPos = (lzWindowPos + 1) & 0x0FFF; + } else { + int copyPos, copyLen; + copyPos = source.readByte(); + copyLen = source.readByte(); + copyPos = copyPos | ((copyLen & 0xF0) << 4); + copyLen = (copyLen & 0x0F) + 3; + while (copyLen--) { + byte literal = lzWindow[copyPos]; + copyPos = (copyPos + 1) & 0x0FFF; + *outBuffer++ = literal; + lzWindow[lzWindowPos] = literal; + lzWindowPos = (lzWindowPos + 1) & 0x0FFF; + } + } + if (outBuffer >= outBufferEnd) + break; + } + + return outS; +} + +} // namespace Sherlock diff --git a/engines/sherlock/decompress.h b/engines/sherlock/decompress.h new file mode 100644 index 0000000000..330e018115 --- /dev/null +++ b/engines/sherlock/decompress.h @@ -0,0 +1,36 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef SHERLOCK_DECOMPRESS_H +#define SHERLOCK_DECOMPRESS_H + +#include "common/memstream.h" + +namespace Sherlock { + +#include "common/stream.h" + +Common::SeekableReadStream *decompressLZ(Common::SeekableReadStream &source, int32 outSize = -1); + +} // namespace Sherlock + +#endif diff --git a/engines/sherlock/detection.cpp b/engines/sherlock/detection.cpp new file mode 100644 index 0000000000..f207bb69d9 --- /dev/null +++ b/engines/sherlock/detection.cpp @@ -0,0 +1,125 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "sherlock/sherlock.h" +#include "sherlock/scalpel/scalpel.h" +#include "sherlock/tattoo/tattoo.h" +#include "engines/advancedDetector.h" + +namespace Sherlock { + +#define MAX_SAVES 99 + +struct SherlockGameDescription { + ADGameDescription desc; + + int gameID; + uint32 features; +}; + +uint32 SherlockEngine::getGameID() const { + return _gameDescription->gameID; +} + +uint32 SherlockEngine::getGameFeatures() const { + return _gameDescription->features; +} + +Common::Platform SherlockEngine::getPlatform() const { + return _gameDescription->desc.platform; +} + +} // End of namespace Sherlock + +static const PlainGameDescriptor sherlockGames[] = { + {"sherlock", "The Lost Files of Sherlock Holmes"}, + { "scalpel", "The Case of the Serrated Scalpel" }, + { "rosetattoo", "The Case of the Rose Tattoo" }, + {0, 0} +}; + +#include "sherlock/detection_tables.h" + +class SherlockMetaEngine : public AdvancedMetaEngine { +public: + SherlockMetaEngine() : AdvancedMetaEngine(Sherlock::gameDescriptions, sizeof(Sherlock::gameDescriptions), sherlockGames) {} + + virtual const char *getName() const { + return "Sherlock Engine"; + } + + virtual const char *getOriginalCopyright() const { + return "Sherlock Engine (C) 1992-1996 Mythos Software, 1992-1996 (C) Electronic Arts"; + } + + virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const; + virtual bool hasFeature(MetaEngineFeature f) const; + virtual SaveStateList listSaves(const char *target) const; + virtual int getMaximumSaveSlot() const; + virtual void removeSaveState(const char *target, int slot) const; + SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const; +}; + +bool SherlockMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const { + const Sherlock::SherlockGameDescription *gd = (const Sherlock::SherlockGameDescription *)desc; + if (gd) { + switch (gd->gameID) { + case Sherlock::GType_SerratedScalpel: + *engine = new Sherlock::Scalpel::ScalpelEngine(syst, gd); + break; + case Sherlock::GType_RoseTattoo: + *engine = new Sherlock::Tattoo::TattooEngine(syst, gd); + break; + default: + error("Unknown game"); + break; + } + } + return gd != 0; +} + +bool SherlockMetaEngine::hasFeature(MetaEngineFeature f) const { + return false; +} + +SaveStateList SherlockMetaEngine::listSaves(const char *target) const { + SaveStateList saveList; + return saveList; +} + +int SherlockMetaEngine::getMaximumSaveSlot() const { + return MAX_SAVES; +} + +void SherlockMetaEngine::removeSaveState(const char *target, int slot) const { +} + +SaveStateDescriptor SherlockMetaEngine::querySaveMetaInfos(const char *target, int slot) const { + return SaveStateDescriptor(); +} + + +#if PLUGIN_ENABLED_DYNAMIC(SHERLOCK) +REGISTER_PLUGIN_DYNAMIC(SHERLOCK, PLUGIN_TYPE_ENGINE, SherlockMetaEngine); +#else +REGISTER_PLUGIN_STATIC(SHERLOCK, PLUGIN_TYPE_ENGINE, SherlockMetaEngine); +#endif diff --git a/engines/sherlock/detection_tables.h b/engines/sherlock/detection_tables.h new file mode 100644 index 0000000000..1d7326058e --- /dev/null +++ b/engines/sherlock/detection_tables.h @@ -0,0 +1,47 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +namespace Sherlock { + +static const SherlockGameDescription gameDescriptions[] = { + { + // Case of the Serrated Scalpel - English + { + "scalpel", + 0, + { + { "talk.lib", 0, "ad0c4d6865edf15da4e9204c08815875", 238928 }, + AD_LISTEND + }, + Common::EN_ANY, + Common::kPlatformDOS, + ADGF_NO_FLAGS, + GUIO1(GUIO_NOSPEECH) + }, + GType_SerratedScalpel, + 0 + }, + + { AD_TABLE_END_MARKER, 0, 0 } +}; + +} // End of namespace MADS diff --git a/engines/sherlock/graphics.cpp b/engines/sherlock/graphics.cpp new file mode 100644 index 0000000000..f4a5bf1864 --- /dev/null +++ b/engines/sherlock/graphics.cpp @@ -0,0 +1,45 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "sherlock/graphics.h" + +namespace Sherlock { + +Surface::Surface(uint16 width, uint16 height) { + create(width, height, Graphics::PixelFormat::createFormatCLUT8()); +} + +Surface::~Surface() { + free(); +} + +void Surface::fillRect(int x1, int y1, int x2, int y2, byte color) { + Graphics::Surface::fillRect(Common::Rect(x1, y1, x2, y2), color); +} + +void Surface::drawSprite(int x, int y, SpriteFrame *spriteFrame, bool flipped, bool altFlag) { + + +} + + +} // End of namespace Sherlock diff --git a/engines/sherlock/graphics.h b/engines/sherlock/graphics.h new file mode 100644 index 0000000000..64518a78c6 --- /dev/null +++ b/engines/sherlock/graphics.h @@ -0,0 +1,43 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef SHERLOCK_GRAPHICS_H +#define SHERLOCK_GRAPHICS_H + +#include "common/rect.h" +#include "graphics/surface.h" + +#include "sherlock/sprite.h" + +namespace Sherlock { + +class Surface : public Graphics::Surface { +public: + Surface(uint16 width, uint16 height); + ~Surface(); + void fillRect(int x1, int y1, int x2, int y2, byte color); + void drawSprite(int x, int y, SpriteFrame *spriteFrame, bool flipped = false, bool altFlag = false); +}; + +} // End of namespace Sherlock + +#endif diff --git a/engines/sherlock/inventory.h b/engines/sherlock/inventory.h new file mode 100644 index 0000000000..de4a2d7758 --- /dev/null +++ b/engines/sherlock/inventory.h @@ -0,0 +1,40 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef SHERLOCK_INVENTORY_H +#define SHERLOCK_INVENTORY_H + +#include "common/scummsys.h" + +namespace Sherlock { + +struct InventoryItem { + int stringIndex; + char name[12]; + char description[41]; + char name2[9]; + uint16 value; +}; + +} // End of namespace Sherlock + +#endif diff --git a/engines/sherlock/journal.cpp b/engines/sherlock/journal.cpp new file mode 100644 index 0000000000..ad7df48943 --- /dev/null +++ b/engines/sherlock/journal.cpp @@ -0,0 +1,40 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "sherlock/journal.h" + +namespace Sherlock { + +Journal::Journal() { + // Allow up to 1000 statements + _data.resize(1000); + + // Initialize fields + _count = 0; + _maxPage = 0; + _index = 0; + _sub = 0; + _up = _down = 0; + _page = 0; +} + +} // End of namespace Sherlock diff --git a/engines/sherlock/journal.h b/engines/sherlock/journal.h new file mode 100644 index 0000000000..64158ff123 --- /dev/null +++ b/engines/sherlock/journal.h @@ -0,0 +1,46 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef SHERLOCK_JOURNAL_H +#define SHERLOCK_JOURNAL_H + +#include "common/scummsys.h" +#include "common/array.h" + +namespace Sherlock { + +class Journal { +public: + Common::Array _data; + int _count; + int _maxPage; + int _index; + int _sub; + int _up, _down; + int _page; +public: + Journal(); +}; + +} // End of namespace Sherlock + +#endif diff --git a/engines/sherlock/module.mk b/engines/sherlock/module.mk new file mode 100644 index 0000000000..1dfcb3a5af --- /dev/null +++ b/engines/sherlock/module.mk @@ -0,0 +1,22 @@ +MODULE := engines/sherlock + +MODULE_OBJS = \ + scalpel/scalpel.o \ + tattoo/tattoo.o \ + decompress.o \ + detection.o \ + graphics.o \ + journal.o \ + resources.o \ + room.o \ + sherlock.o \ + sprite.o \ + talk.o + +# This module can be built as a plugin +ifdef BUILD_PLUGINS +PLUGIN := 1 +endif + +# Include common rules +include $(srcdir)/rules.mk diff --git a/engines/sherlock/resources.cpp b/engines/sherlock/resources.cpp new file mode 100644 index 0000000000..e59e65abff --- /dev/null +++ b/engines/sherlock/resources.cpp @@ -0,0 +1,219 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "sherlock/resources.h" +#include "sherlock/decompress.h" +#include "common/debug.h" + +namespace Sherlock { + +Cache::Cache() { +} + +/** + * Returns true if a given file is currently being cached + */ +bool Cache::isCached(const Common::String &filename) const { + return _resources.contains(filename); +} + +/** + * Loads a file into the cache if it's not already present, and returns it. + * If the file is LZW compressed, automatically decompresses it and loads + * the uncompressed version into memory + */ +void Cache::load(const Common::String &filename) { + // First check if the entry already exists + if (_resources.contains(filename)) + return; + + // Allocate a new cache entry + _resources[filename] = CacheEntry(); + CacheEntry &cacheEntry = _resources[filename]; + + // Open the file for reading + Common::File f; + if (!f.open(filename)) + error("Could not read file - %s", filename.c_str()); + + // Check whether the file is compressed + const char LZW_HEADER[5] = { "LZV\x1a" }; + char header[5]; + f.read(header, 5); + bool isCompressed = !strncmp(header, LZW_HEADER, 5); + f.seek(0); + + if (isCompressed) { + // It's compressed, so decompress the file and store it's data in the cache entry + Common::SeekableReadStream *decompressed = decompressLZ(f); + cacheEntry.resize(decompressed->size()); + decompressed->read(&cacheEntry[0], decompressed->size()); + + delete decompressed; + } else { + // It's not, so read the raw data of the file into the cache entry + cacheEntry.resize(f.size()); + f.read(&cacheEntry[0], f.size()); + } + + f.close(); +} + +Common::SeekableReadStream *Cache::get(const Common::String &filename) const { + // Return a memory stream that encapsulates the data + const CacheEntry &cacheEntry = _resources[filename]; + return new Common::MemoryReadStream(&cacheEntry[0], cacheEntry.size()); +} + +/*----------------------------------------------------------------*/ + +Resources::Resources() { + _resourceIndex = -1; + + addToCache("vgs.lib"); + addToCache("talk.lib"); + addToCache("sequence.txt"); + addToCache("journal.txt"); + addToCache("portrait.lib"); +} + + +/** + * Adds the specified file to the cache. If it's a library file, takes care of + * loading it's index for future use + */ +void Resources::addToCache(const Common::String &filename) { + _cache.load(filename); + + // Check to see if the file is a library + Common::SeekableReadStream *stream = load(filename); + uint32 header = stream->readUint32BE(); + if (header == MKTAG('L', 'I', 'B', 26)) + loadLibraryIndex(filename, stream); + + delete stream; +} + +Common::SeekableReadStream *Resources::load(const Common::String &filename) { + // First check if the file is directly in the cache + if (_cache.isCached(filename)) + return _cache.get(filename); + + // Secondly, iterate through any loaded library file looking for a resource + // that has the same name + LibraryIndexes::iterator i; + for (i = _indexes.begin(); i != _indexes.end(); ++i) { + if ((*i)._value.contains(filename)) { + // Get a stream reference to the given library file + Common::SeekableReadStream *stream = load((*i)._key); + LibraryEntry &entry = (*i)._value[filename]; + _resourceIndex = entry._index; + + stream->seek(entry._offset); + Common::SeekableReadStream *resStream = stream->readStream(entry._size); + + delete stream; + return resStream; + } + } + + // At this point, fall back on a physical file with the given name + Common::File f; + if (!f.open(filename)) + error("Could not load file - %s", filename.c_str()); + + Common::SeekableReadStream *stream = f.readStream(f.size()); + f.close(); + + return stream; +} + +/** + * Loads a specific resource from a given library file + */ +Common::SeekableReadStream *Resources::load(const Common::String &filename, const Common::String &libraryFile) { + // Open up the library for access + Common::SeekableReadStream *libStream = load(libraryFile); + + // Check if the library has already had it's index read, and if not, load it + if (!_indexes.contains(libraryFile)) + loadLibraryIndex(libraryFile, libStream); + + // Extract the data for the specified resource and return it + LibraryEntry &entry = _indexes[libraryFile][filename]; + libStream->seek(entry._offset); + Common::SeekableReadStream *stream = libStream->readStream(entry._size); + + delete libStream; + return stream; +} + + +/** + * Reads in the index from a library file, and caches it's index for later use + */ +void Resources::loadLibraryIndex(const Common::String &libFilename, + Common::SeekableReadStream *stream) { + uint32 offset, nextOffset; + + // Create an index entry + _indexes[libFilename] = LibraryIndex(); + LibraryIndex &index = _indexes[libFilename]; + + // Read in the number of resources + stream->seek(4); + int count = stream->readUint16LE(); + + // Loop through reading in the entries + for (int idx = 0; idx < count; ++idx) { + // Read the name of the resource + char resName[13]; + stream->read(resName, 13); + resName[12] = '\0'; + + // Read the offset + offset = stream->readUint32LE(); + + if (idx == (count - 1)) { + nextOffset = stream->size(); + } else { + // Read the size by jumping forward to read the next entry's offset + stream->seek(13, SEEK_CUR); + nextOffset = stream->readUint32LE(); + stream->seek(-17, SEEK_CUR); + } + + // Add the entry to the index + index[resName] = LibraryEntry(idx, offset, nextOffset - offset); + } +} + +/** + * Returns the index of the last loaded resource in it's given library file. + * This will be used primarily when loading talk files, so the engine can + * update the given conversation number in the journal + */ +int Resources::resouceIndex() const { + return _resourceIndex; +} + +} // End of namespace Sherlock diff --git a/engines/sherlock/resources.h b/engines/sherlock/resources.h new file mode 100644 index 0000000000..bfd2eb300c --- /dev/null +++ b/engines/sherlock/resources.h @@ -0,0 +1,86 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef SHERLOCK_RESOURCES_H +#define SHERLOCK_RESOURCES_H + +#include "common/array.h" +#include "common/file.h" +#include "common/hashmap.h" +#include "common/hash-str.h" +#include "common/str.h" +#include "common/stream.h" + +namespace Sherlock { + +typedef Common::Array CacheEntry; +typedef Common::HashMap CacheHash; + +struct LibraryEntry { + uint32 _offset, _size; + int _index; + + LibraryEntry() : _index(0), _offset(0), _size(0) {} + LibraryEntry(int index, uint32 offset, uint32 size) : + _index(index), _offset(offset), _size(size) {} +}; +typedef Common::HashMap LibraryIndex; +typedef Common::HashMap LibraryIndexes; + +class SherlockEngine; + +class Cache { +private: + CacheHash _resources; +public: + Cache(); + + bool isCached(const Common::String &filename) const; + + void load(const Common::String &name); + + Common::SeekableReadStream *get(const Common::String &filename) const; +}; + +class Resources { +private: + Cache _cache; + LibraryIndexes _indexes; + int _resourceIndex; + + void loadLibraryIndex(const Common::String &libFilename, Common::SeekableReadStream *stream); +public: + Resources(); + + void addToCache(const Common::String &filename); + + Common::SeekableReadStream *load(const Common::String &filename); + + Common::SeekableReadStream *load(const Common::String &filename, const Common::String &libraryFile); + + int resouceIndex() const; +}; + + +} // End of namespace Sherlock + +#endif diff --git a/engines/sherlock/room.cpp b/engines/sherlock/room.cpp new file mode 100644 index 0000000000..246a316562 --- /dev/null +++ b/engines/sherlock/room.cpp @@ -0,0 +1,32 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "sherlock/room.h" + +namespace Sherlock { + +Rooms::Rooms() { + for (int roomNum = 0; roomNum < ROOMS_COUNT; ++roomNum) + Common::fill(&_stats[roomNum][0], &_stats[roomNum][9], false); +} + +} // End of namespace Sherlock diff --git a/engines/sherlock/room.h b/engines/sherlock/room.h new file mode 100644 index 0000000000..46755c1a10 --- /dev/null +++ b/engines/sherlock/room.h @@ -0,0 +1,102 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef SHERLOCK_ROOM_H +#define SHERLOCK_ROOM_H + +#include "common/scummsys.h" +#include "sherlock/sprite.h" + +namespace Sherlock { + +#define ROOMS_COUNT 63 + +/* +struct RoomBounds { + int x, y, width, height; +}; + +struct BgshapeSub { + uint16 value; +}; + +struct Bgshape { + char name[12]; + char description[41]; + char *textBufferPtr; + byte *seqBufPtr; + Sprite *sprite; + SpriteFrame *spriteFrame; + byte byte05; + byte seqBigCountFlag; + int16 seqIndex; + int16 canimIndex; + int16 x, y; + int16 xIncr, yIncr, + uint16 status; + int16 x2, y2; + int16 width2, height2; + uint16 word02; + uint16 word03; + byte flag; + byte itemValue; + uint16 word01; + uint16 word05; + uint16 stringIndex; + int16 width, height; + uint16 word04; + byte flagsAndIndex; + uint16 frameCount; + byte spriteFlags; + char string1[50]; + byte byte07; + byte byte01; + byte byte02; + int16 boundsX, boundsY; + byte direction; + byte animIndex; + char string2[50]; + byte byte06; + byte seqByte; + uint16 textBufferOfs; + byte byte03; + uint16 framesCopyCount; + byte byte08; + char string3[51]; + uint16 word06; + uint16 word07; + uint16 word08; + uint16 word09; + BgshapeSub subItems[4]; +}; +*/ +class Rooms { +public: + bool _stats[ROOMS_COUNT][9]; + bool _savedStats[ROOMS_COUNT][9]; +public: + Rooms(); +}; + +} // End of namespace Sherlock + +#endif diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp new file mode 100644 index 0000000000..11b78946f9 --- /dev/null +++ b/engines/sherlock/scalpel/scalpel.cpp @@ -0,0 +1,40 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "sherlock/scalpel/scalpel.h" + +namespace Sherlock { + +namespace Scalpel { + +/** + * Initialises game flags + */ +void ScalpelEngine::initFlags() { + _flags.resize(100 * 8); + _flags[3] = true; // Turn on Alley + _flags[39] = true; // Turn on Baker Street +} + +} // End of namespace Scalpel + +} // End of namespace Scalpel diff --git a/engines/sherlock/scalpel/scalpel.h b/engines/sherlock/scalpel/scalpel.h new file mode 100644 index 0000000000..e9f9aa05a2 --- /dev/null +++ b/engines/sherlock/scalpel/scalpel.h @@ -0,0 +1,45 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef SHERLOCK_SCALPEL_H +#define SHERLOCK_SCALPEL_H + +#include "sherlock/sherlock.h" + +namespace Sherlock { + +namespace Scalpel { + +class ScalpelEngine : public SherlockEngine { +public: + ScalpelEngine(OSystem *syst, const SherlockGameDescription *gameDesc) : + SherlockEngine(syst, gameDesc) {} + virtual ~ScalpelEngine() {} + + virtual void initFlags(); +}; + +} // End of namespace Scalpel + +} // End of namespace Sherlock + +#endif diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp new file mode 100644 index 0000000000..a6ae6e215c --- /dev/null +++ b/engines/sherlock/sherlock.cpp @@ -0,0 +1,81 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "sherlock/sherlock.h" +#include "sherlock/graphics.h" +#include "common/scummsys.h" +#include "common/debug-channels.h" +#include "engines/util.h" + +namespace Sherlock { + +SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gameDesc) : + Engine(syst), _gameDescription(gameDesc) { + _journal = nullptr; + _res = nullptr; + _rooms = nullptr; + _talk = nullptr; +} + + +SherlockEngine::~SherlockEngine() { + delete _journal; + delete _res; + delete _rooms; + delete _talk; +} + +void SherlockEngine::initialize() { + initGraphics(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT, false); + + DebugMan.addDebugChannel(kDebugScript, "scripts", "Script debug level"); + + /* + int midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); + bool native_mt32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32")); + + MidiDriver *driver = MidiDriver::createMidi(midiDriver); + if (native_mt32) + driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); + + _midi = new MidiPlayer(this, driver); + _midi->setGM(true); + _midi->setNativeMT32(native_mt32); + */ + + _journal = new Journal(); + _res = new Resources(); + _rooms = new Rooms(); + _talk = new Talk(); + + initFlags(); +} + +Common::Error SherlockEngine::run() { + initialize(); + + // TODO: The rest of the game + + return Common::kNoError; +} + +} // End of namespace Comet diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h new file mode 100644 index 0000000000..a68650c0a9 --- /dev/null +++ b/engines/sherlock/sherlock.h @@ -0,0 +1,91 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef SHERLOCK_HOLMES_H +#define SHERLOCK_HOLMES_H + +#include "common/scummsys.h" +#include "common/array.h" +#include "common/endian.h" +#include "common/util.h" +#include "common/savefile.h" +#include "common/hash-str.h" +#include "engines/engine.h" +#include "sherlock/journal.h" +#include "sherlock/resources.h" +#include "sherlock/room.h" +#include "sherlock/talk.h" + +namespace Sherlock { + +enum { + kFileTypeHash +}; + +enum { + kDebugScript = 1 << 0 +}; + +enum { + GType_SerratedScalpel = 0, + GType_RoseTattoo = 1 +}; + +#define SHERLOCK_SCREEN_WIDTH 320 +#define SHERLOCK_SCREEN_HEIGHT 200 + +struct SherlockGameDescription; + +class Resource; + +class SherlockEngine : public Engine { +private: + bool detectGame(); + + void initialize(); +public: + const SherlockGameDescription *_gameDescription; + Journal *_journal; + Resources *_res; + Rooms *_rooms; + Talk *_talk; + Common::Array _flags; +public: + SherlockEngine(OSystem *syst, const SherlockGameDescription *gameDesc); + virtual ~SherlockEngine(); + + virtual Common::Error run(); + + virtual void initFlags() = 0; + + int getGameType() const; + uint32 getGameID() const; + uint32 getGameFeatures() const; + Common::Language getLanguage() const; + Common::Platform getPlatform() const; + + Common::String getGameFile(int fileType); +}; + +} // End of namespace Sherlock + +#endif diff --git a/engines/sherlock/sound.h b/engines/sherlock/sound.h new file mode 100644 index 0000000000..f3b34345ef --- /dev/null +++ b/engines/sherlock/sound.h @@ -0,0 +1,39 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef SHERLOCK_SOUND_H +#define SHERLOCK_SOUND_H + +namespace Sherlock { + +class Sound { +public + void playSound(const char *name); + void cacheSound(const char *name, int index); + void playCachedSound(int index); + void clearCache(); + +}; + +} // End of namespace Sherlock + +#endif diff --git a/engines/sherlock/sprite.cpp b/engines/sherlock/sprite.cpp new file mode 100644 index 0000000000..7aa2fdc71b --- /dev/null +++ b/engines/sherlock/sprite.cpp @@ -0,0 +1,142 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "sherlock/sprite.h" +#include "common/debug.h" + +namespace Sherlock { + +/* +struct SpriteFrame { + byte *data; + int width, height; + uint16 flags; + int xofs, yofs; + byte rleMarker; +}; +*/ + +Sprite::Sprite(Common::SeekableReadStream &stream) { + load(stream); +} + +Sprite::~Sprite() { +} + +int Sprite::getFrameCount() { + return _frames.size(); +} + +SpriteFrame *Sprite::getFrame(int index) { + return _frames[index]; +} + +void Sprite::load(Common::SeekableReadStream &stream) { + + while (!stream.eos()) { + + debug("frameNum = %d\n", _frames.size()); + + SpriteFrame *spriteFrame = new SpriteFrame(); + + uint32 startOfs = stream.pos(); + + debug("startOfs = %08X\n", startOfs); + + spriteFrame->frame = NULL; + spriteFrame->width = stream.readUint16LE() + 1; + spriteFrame->height = stream.readUint16LE() + 1; + spriteFrame->flags = stream.readUint16LE(); + stream.readUint16LE(); + + debug("width = %d; height = %d; flags = %04X\n", spriteFrame->width, spriteFrame->height, spriteFrame->flags); + + if (spriteFrame->flags & 0xFF) { + spriteFrame->size = (spriteFrame->width * spriteFrame->height) / 2; + } else if (spriteFrame->flags & 0x0100) { + // this size includes the header size, which we subtract + spriteFrame->size = stream.readUint16LE() - 11; + spriteFrame->rleMarker = stream.readByte(); + } else { + spriteFrame->size = spriteFrame->width * spriteFrame->height; + } + + spriteFrame->data = new byte[spriteFrame->size]; + stream.read(spriteFrame->data, spriteFrame->size); + + decompressFrame(spriteFrame); + + /* + debug("size = %d (%08X)\n", spriteFrame->size, spriteFrame->size); + if (spriteFrame->frame) { + char fn[128]; + sndebug(fn, 128, "%04d.spr", _frames.size()); + FILE *x = fopen(fn, "wb"); + fwrite(spriteFrame->frame->pixels, spriteFrame->frame->w * spriteFrame->frame->h, 1, x); + fclose(x); + } + */ + + _frames.push_back(spriteFrame); + + } + + // debug("Done: %08X\n", stream.pos()); fflush(stdout); + +} + +void Sprite::decompressFrame(SpriteFrame *frame) { + + frame->frame = new Graphics::Surface(); + frame->frame->create(frame->width, frame->height, Graphics::PixelFormat::createFormatCLUT8()); + + if (frame->flags & 0xFF) { + debug("Sprite::decompressFrame() 4-bits/pixel\n"); + debug("TODO\n"); + } else if (frame->flags & 0x0100) { + debug("Sprite::decompressFrame() RLE-compressed; rleMarker = %02X\n", frame->rleMarker); + const byte *src = frame->data; + byte *dst = (byte *)frame->frame->getPixels(); + for (uint16 h = 0; h < frame->height; h++) { + int16 w = frame->width; + while (w > 0) { + if (*src == frame->rleMarker) { + byte rleColor = src[1]; + byte rleCount = src[2]; + src += 3; + w -= rleCount; + while (rleCount--) + *dst++ = rleColor; + } else { + *dst++ = *src++; + w--; + } + } + } + } else { + debug("Sprite::decompressFrame() Uncompressed\n"); + memcpy(frame->data, frame->frame->getPixels(), frame->width * frame->height); + } + +} + +} // End of namespace Sherlock diff --git a/engines/sherlock/sprite.h b/engines/sherlock/sprite.h new file mode 100644 index 0000000000..f56ab588bb --- /dev/null +++ b/engines/sherlock/sprite.h @@ -0,0 +1,56 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef SHERLOCK_SPRITE_H +#define SHERLOCK_SPRITE_H + +#include "common/stream.h" +#include "common/array.h" +#include "graphics/surface.h" + +namespace Sherlock { + +struct SpriteFrame { + byte *data; + uint32 size; + uint16 width, height; + uint16 flags; + int xofs, yofs; + byte rleMarker; + Graphics::Surface *frame; +}; + +class Sprite { +public: + Sprite(Common::SeekableReadStream &stream); + ~Sprite(); + int getFrameCount(); + SpriteFrame *getFrame(int index); +protected: + Common::Array _frames; + void load(Common::SeekableReadStream &stream); + void decompressFrame(SpriteFrame *frame); +}; + +} // End of namespace Sherlock + +#endif diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp new file mode 100644 index 0000000000..3122aff95f --- /dev/null +++ b/engines/sherlock/talk.cpp @@ -0,0 +1,30 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "sherlock/talk.h" + +namespace Sherlock { + +Talk::Talk() { +} + +} // End of namespace Sherlock diff --git a/engines/sherlock/talk.h b/engines/sherlock/talk.h new file mode 100644 index 0000000000..6ffbcdd8d4 --- /dev/null +++ b/engines/sherlock/talk.h @@ -0,0 +1,49 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef SHERLOCK_TALK_H +#define SHERLOCK_TALK_H + +#include "common/scummsys.h" +#include "common/array.h" + +namespace Sherlock { + +struct TalkHistoryEntry { +private: + int _data[2]; +public: + TalkHistoryEntry() { _data[0] = _data[1] = 0; } + + int &operator[](int idx) { return _data[idx]; } +}; + +class Talk { +public: + Common::Array _history; +public: + Talk(); +}; + +} // End of namespace Sherlock + +#endif diff --git a/engines/sherlock/tattoo/tattoo.cpp b/engines/sherlock/tattoo/tattoo.cpp new file mode 100644 index 0000000000..bed6edb3d4 --- /dev/null +++ b/engines/sherlock/tattoo/tattoo.cpp @@ -0,0 +1,38 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "sherlock/tattoo/tattoo.h" + +namespace Sherlock { + +namespace Tattoo { + +/** + * Initialises game flags + */ +void TattooEngine::initFlags() { + _flags.resize(100 * 8); +} + +} // End of namespace Tattoo + +} // End of namespace Scalpel diff --git a/engines/sherlock/tattoo/tattoo.h b/engines/sherlock/tattoo/tattoo.h new file mode 100644 index 0000000000..e2977983f1 --- /dev/null +++ b/engines/sherlock/tattoo/tattoo.h @@ -0,0 +1,45 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef SHERLOCK_TATTOO_H +#define SHERLOCK_TATTOO_H + +#include "sherlock/sherlock.h" + +namespace Sherlock { + +namespace Tattoo { + +class TattooEngine : public SherlockEngine { +public: + TattooEngine(OSystem *syst, const SherlockGameDescription *gameDesc) : + SherlockEngine(syst, gameDesc) {} + virtual ~TattooEngine() {} + + virtual void initFlags(); +}; + +} // End of namespace Tattoo + +} // End of namespace Sherlock + +#endif diff --git a/engines/sherlock/vdaplayer.h b/engines/sherlock/vdaplayer.h new file mode 100644 index 0000000000..9b755606d5 --- /dev/null +++ b/engines/sherlock/vdaplayer.h @@ -0,0 +1,34 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef SHERLOCK_VDAPLAYER_H +#define SHERLOCK_VDAPLAYER_H + +namespace Sherlock { + +class VdaPlayer { + +}; + +} // End of namespace Sherlock + +#endif -- cgit v1.2.3 From eaab373a9687c6d6d3be3983bb77da5a69897a24 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 15 Mar 2015 17:25:21 -0400 Subject: SHERLOCK: Added skeleton Screen class --- engines/sherlock/graphics.cpp | 21 +++++++++++++++++++++ engines/sherlock/graphics.h | 14 ++++++++++++++ engines/sherlock/sherlock.cpp | 3 +++ engines/sherlock/sherlock.h | 2 ++ 4 files changed, 40 insertions(+) (limited to 'engines') diff --git a/engines/sherlock/graphics.cpp b/engines/sherlock/graphics.cpp index f4a5bf1864..695635d2ca 100644 --- a/engines/sherlock/graphics.cpp +++ b/engines/sherlock/graphics.cpp @@ -21,6 +21,8 @@ */ #include "sherlock/graphics.h" +#include "sherlock/sherlock.h" +#include "common/system.h" namespace Sherlock { @@ -41,5 +43,24 @@ void Surface::drawSprite(int x, int y, SpriteFrame *spriteFrame, bool flipped, b } +/*----------------------------------------------------------------*/ + +Screen::Screen(SherlockEngine *vm) : Surface(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT), _vm(vm) { + setFont(1); +} + +void Screen::setFont(int fontNumber) { + _fontNumber = fontNumber; + Common::String fname = Common::String::format("FONT%d.VGS", fontNumber); + Common::SeekableReadStream *stream = _vm->_res->load(fname); + + debug("TODO: Loading font %s, size - %d", fname.c_str(), stream->size()); + + delete stream; +} + +void Screen::update() { + g_system->updateScreen(); +} } // End of namespace Sherlock diff --git a/engines/sherlock/graphics.h b/engines/sherlock/graphics.h index 64518a78c6..fe03e7155d 100644 --- a/engines/sherlock/graphics.h +++ b/engines/sherlock/graphics.h @@ -30,6 +30,8 @@ namespace Sherlock { +class SherlockEngine; + class Surface : public Graphics::Surface { public: Surface(uint16 width, uint16 height); @@ -38,6 +40,18 @@ public: void drawSprite(int x, int y, SpriteFrame *spriteFrame, bool flipped = false, bool altFlag = false); }; +class Screen : public Surface { +private: + SherlockEngine *_vm; + int _fontNumber; +public: + Screen(SherlockEngine *vm); + + void setFont(int fontNumber); + + void update(); +}; + } // End of namespace Sherlock #endif diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index a6ae6e215c..0d55e0ba8d 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -33,6 +33,7 @@ SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gam _journal = nullptr; _res = nullptr; _rooms = nullptr; + _screen = nullptr; _talk = nullptr; } @@ -41,6 +42,7 @@ SherlockEngine::~SherlockEngine() { delete _journal; delete _res; delete _rooms; + delete _screen; delete _talk; } @@ -65,6 +67,7 @@ void SherlockEngine::initialize() { _journal = new Journal(); _res = new Resources(); _rooms = new Rooms(); + _screen = new Screen(this); _talk = new Talk(); initFlags(); diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h index a68650c0a9..4c5f86dd09 100644 --- a/engines/sherlock/sherlock.h +++ b/engines/sherlock/sherlock.h @@ -30,6 +30,7 @@ #include "common/savefile.h" #include "common/hash-str.h" #include "engines/engine.h" +#include "sherlock/graphics.h" #include "sherlock/journal.h" #include "sherlock/resources.h" #include "sherlock/room.h" @@ -67,6 +68,7 @@ public: Journal *_journal; Resources *_res; Rooms *_rooms; + Screen *_screen; Talk *_talk; Common::Array _flags; public: -- cgit v1.2.3 From a6db2fb281fb5842be2d8fc0621922e70ad9668c Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 15 Mar 2015 17:50:10 -0400 Subject: SHERLOCK: Further game setup --- engines/sherlock/room.cpp | 2 ++ engines/sherlock/room.h | 1 + engines/sherlock/scalpel/scalpel.cpp | 8 ++++++-- engines/sherlock/scalpel/scalpel.h | 4 ++-- engines/sherlock/sherlock.cpp | 2 -- engines/sherlock/sherlock.h | 7 ++----- engines/sherlock/tattoo/tattoo.cpp | 7 ------- engines/sherlock/tattoo/tattoo.h | 2 -- 8 files changed, 13 insertions(+), 20 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/room.cpp b/engines/sherlock/room.cpp index 246a316562..9926899953 100644 --- a/engines/sherlock/room.cpp +++ b/engines/sherlock/room.cpp @@ -27,6 +27,8 @@ namespace Sherlock { Rooms::Rooms() { for (int roomNum = 0; roomNum < ROOMS_COUNT; ++roomNum) Common::fill(&_stats[roomNum][0], &_stats[roomNum][9], false); + + _goToRoom = -1; } } // End of namespace Sherlock diff --git a/engines/sherlock/room.h b/engines/sherlock/room.h index 46755c1a10..75800b623a 100644 --- a/engines/sherlock/room.h +++ b/engines/sherlock/room.h @@ -93,6 +93,7 @@ class Rooms { public: bool _stats[ROOMS_COUNT][9]; bool _savedStats[ROOMS_COUNT][9]; + int _goToRoom; public: Rooms(); }; diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp index 11b78946f9..bd8c96f253 100644 --- a/engines/sherlock/scalpel/scalpel.cpp +++ b/engines/sherlock/scalpel/scalpel.cpp @@ -27,14 +27,18 @@ namespace Sherlock { namespace Scalpel { /** - * Initialises game flags + * Game initialization */ -void ScalpelEngine::initFlags() { +void ScalpelEngine::initialize() { _flags.resize(100 * 8); _flags[3] = true; // Turn on Alley _flags[39] = true; // Turn on Baker Street + + // Starting room + _rooms->_goToRoom = 4; } + } // End of namespace Scalpel } // End of namespace Scalpel diff --git a/engines/sherlock/scalpel/scalpel.h b/engines/sherlock/scalpel/scalpel.h index e9f9aa05a2..9001c20456 100644 --- a/engines/sherlock/scalpel/scalpel.h +++ b/engines/sherlock/scalpel/scalpel.h @@ -30,12 +30,12 @@ namespace Sherlock { namespace Scalpel { class ScalpelEngine : public SherlockEngine { +protected: + virtual void initialize(); public: ScalpelEngine(OSystem *syst, const SherlockGameDescription *gameDesc) : SherlockEngine(syst, gameDesc) {} virtual ~ScalpelEngine() {} - - virtual void initFlags(); }; } // End of namespace Scalpel diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index 0d55e0ba8d..13731e2fd8 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -69,8 +69,6 @@ void SherlockEngine::initialize() { _rooms = new Rooms(); _screen = new Screen(this); _talk = new Talk(); - - initFlags(); } Common::Error SherlockEngine::run() { diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h index 4c5f86dd09..172c940c34 100644 --- a/engines/sherlock/sherlock.h +++ b/engines/sherlock/sherlock.h @@ -60,9 +60,8 @@ class Resource; class SherlockEngine : public Engine { private: - bool detectGame(); - - void initialize(); +protected: + virtual void initialize(); public: const SherlockGameDescription *_gameDescription; Journal *_journal; @@ -77,8 +76,6 @@ public: virtual Common::Error run(); - virtual void initFlags() = 0; - int getGameType() const; uint32 getGameID() const; uint32 getGameFeatures() const; diff --git a/engines/sherlock/tattoo/tattoo.cpp b/engines/sherlock/tattoo/tattoo.cpp index bed6edb3d4..57ca5c6e29 100644 --- a/engines/sherlock/tattoo/tattoo.cpp +++ b/engines/sherlock/tattoo/tattoo.cpp @@ -26,13 +26,6 @@ namespace Sherlock { namespace Tattoo { -/** - * Initialises game flags - */ -void TattooEngine::initFlags() { - _flags.resize(100 * 8); -} - } // End of namespace Tattoo } // End of namespace Scalpel diff --git a/engines/sherlock/tattoo/tattoo.h b/engines/sherlock/tattoo/tattoo.h index e2977983f1..f06fa1532d 100644 --- a/engines/sherlock/tattoo/tattoo.h +++ b/engines/sherlock/tattoo/tattoo.h @@ -34,8 +34,6 @@ public: TattooEngine(OSystem *syst, const SherlockGameDescription *gameDesc) : SherlockEngine(syst, gameDesc) {} virtual ~TattooEngine() {} - - virtual void initFlags(); }; } // End of namespace Tattoo -- cgit v1.2.3 From 1452c18ffb21da0d97725c7c982b25992bd75fe8 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 15 Mar 2015 18:42:24 -0400 Subject: SHERLOCK: Added events manager and debugger classes --- engines/sherlock/debugger.cpp | 59 +++++++++++++ engines/sherlock/debugger.h | 45 ++++++++++ engines/sherlock/events.cpp | 167 +++++++++++++++++++++++++++++++++++ engines/sherlock/events.h | 82 +++++++++++++++++ engines/sherlock/graphics.cpp | 4 +- engines/sherlock/graphics.h | 1 + engines/sherlock/module.mk | 2 + engines/sherlock/scalpel/scalpel.cpp | 9 ++ engines/sherlock/scalpel/scalpel.h | 2 + engines/sherlock/sherlock.cpp | 7 +- engines/sherlock/sherlock.h | 4 + engines/sherlock/tattoo/tattoo.cpp | 4 + engines/sherlock/tattoo/tattoo.h | 2 + 13 files changed, 386 insertions(+), 2 deletions(-) create mode 100644 engines/sherlock/debugger.cpp create mode 100644 engines/sherlock/debugger.h create mode 100644 engines/sherlock/events.cpp create mode 100644 engines/sherlock/events.h (limited to 'engines') diff --git a/engines/sherlock/debugger.cpp b/engines/sherlock/debugger.cpp new file mode 100644 index 0000000000..50300322ef --- /dev/null +++ b/engines/sherlock/debugger.cpp @@ -0,0 +1,59 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "sherlock/debugger.h" +#include "sherlock/sherlock.h" + +namespace Sherlock { + +Debugger::Debugger(SherlockEngine *vm) : GUI::Debugger(), _vm(vm) { + registerCmd("continue", WRAP_METHOD(Debugger, cmdExit)); + registerCmd("scene", WRAP_METHOD(Debugger, cmd_scene)); +} + +static int strToInt(const char *s) { + if (!*s) + // No string at all + return 0; + else if (toupper(s[strlen(s) - 1]) != 'H') + // Standard decimal string + return atoi(s); + + // Hexadecimal string + uint tmp = 0; + int read = sscanf(s, "%xh", &tmp); + if (read < 1) + error("strToInt failed on string \"%s\"", s); + return (int)tmp; +} + +bool Debugger::cmd_scene(int argc, const char **argv) { + if (argc != 2) { + debugPrintf("Format: scene \n"); + return true; + } else { + _vm->_rooms->_goToRoom = strToInt(argv[1]); + return false; + } +} + +} // End of namespace Sherlock diff --git a/engines/sherlock/debugger.h b/engines/sherlock/debugger.h new file mode 100644 index 0000000000..8c7291c9e6 --- /dev/null +++ b/engines/sherlock/debugger.h @@ -0,0 +1,45 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef SHERLOCK_DEBUGGER_H +#define SHERLOCK_DEBUGGER_H + +#include "common/scummsys.h" +#include "gui/debugger.h" + +namespace Sherlock { + +class SherlockEngine; + +class Debugger : public GUI::Debugger { +private: + SherlockEngine *_vm; +protected: + bool cmd_scene(int argc, const char **argv); +public: + Debugger(SherlockEngine *vm); + virtual ~Debugger() {} +}; + +} // End of namespace Sherlock + +#endif /* SHERLOCK_DEBUGGER_H */ diff --git a/engines/sherlock/events.cpp b/engines/sherlock/events.cpp new file mode 100644 index 0000000000..7e62dc075b --- /dev/null +++ b/engines/sherlock/events.cpp @@ -0,0 +1,167 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "common/scummsys.h" +#include "common/events.h" +#include "common/system.h" +#include "engines/util.h" +#include "graphics/cursorman.h" +#include "sherlock/sherlock.h" +#include "sherlock/events.h" + +namespace Sherlock { + +EventsManager::EventsManager(SherlockEngine *vm) { + _vm = vm; + _cursorId = CURSOR_NONE; + _frameCounter = 1; + _priorFrameTime = 0; + _mouseClicked = false; + _mouseButtons = 0; +} + +EventsManager::~EventsManager() { +} + +/** + * Set the cursor to show + */ +void EventsManager::setCursor(CursorType cursorId) { + _cursorId = cursorId; + + // TODO: Cursor handling +} + +/** + * Show the mouse cursor + */ +void EventsManager::showCursor() { + CursorMan.showMouse(true); +} + +/** + * Hide the mouse cursor + */ +void EventsManager::hideCursor() { + CursorMan.showMouse(false); +} + +/** + * Returns true if the mouse cursor is visible + */ +bool EventsManager::isCursorVisible() { + return CursorMan.isVisible(); +} + +void EventsManager::pollEvents() { + checkForNextFrameCounter(); + + Common::Event event; + while (g_system->getEventManager()->pollEvent(event)) { + // Handle keypress + switch (event.type) { + case Common::EVENT_QUIT: + case Common::EVENT_RTL: + return; + + case Common::EVENT_KEYDOWN: + // Check for debugger + if (event.kbd.keycode == Common::KEYCODE_d && (event.kbd.flags & Common::KBD_CTRL)) { + // Attach to the debugger + _vm->_debugger->attach(); + _vm->_debugger->onFrame(); + } else { + _pendingKeys.push(event.kbd); + } + return; + case Common::EVENT_KEYUP: + return; + case Common::EVENT_LBUTTONDOWN: + case Common::EVENT_RBUTTONDOWN: + _mouseClicked = true; + return; + case Common::EVENT_LBUTTONUP: + case Common::EVENT_RBUTTONUP: + _mouseClicked = false; + return; + case Common::EVENT_MOUSEMOVE: + _mousePos = event.mouse; + break; + default: + break; + } + } +} + +bool EventsManager::checkForNextFrameCounter() { + // Check for next game frame + uint32 milli = g_system->getMillis(); + if ((milli - _priorFrameTime) >= GAME_FRAME_TIME) { + ++_frameCounter; + _priorFrameTime = milli; + + // Give time to the debugger + _vm->_debugger->onFrame(); + + // Display the frame + _vm->_screen->update(); + + // Signal the ScummVM debugger + _vm->_debugger->onFrame(); + + return true; + } + + return false; +} + +void EventsManager::delay(int cycles) { + uint32 totalMilli = cycles * 1000 / GAME_FRAME_RATE; + uint32 delayEnd = g_system->getMillis() + totalMilli; + + while (!_vm->shouldQuit() && g_system->getMillis() < delayEnd) { + g_system->delayMillis(10); + + pollEvents(); + } +} + +void EventsManager::waitForNextFrame() { + _mouseClicked = false; + _mouseButtons = 0; + + bool mouseClicked = false; + int mouseButtons = 0; + + uint32 frameCtr = getFrameCounter(); + while (!_vm->shouldQuit() && frameCtr == _frameCounter) { + delay(1); + + mouseClicked |= _mouseClicked; + mouseButtons |= _mouseButtons; + } + + _mouseClicked = mouseClicked; + _mouseButtons = mouseButtons; +} + +} // End of namespace MADS diff --git a/engines/sherlock/events.h b/engines/sherlock/events.h new file mode 100644 index 0000000000..4ba30e0bdf --- /dev/null +++ b/engines/sherlock/events.h @@ -0,0 +1,82 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef SHERLOCK_EVENTS_H +#define SHERLOCK_EVENTS_H + +#include "common/scummsys.h" +#include "common/events.h" +#include "common/stack.h" + +namespace Sherlock { + +enum CursorType { CURSOR_NONE = 0 }; + +#define GAME_FRAME_RATE 50 +#define GAME_FRAME_TIME (1000 / GAME_FRAME_RATE) + +class SherlockEngine; + +class EventsManager { +private: + SherlockEngine *_vm; + uint32 _frameCounter; + uint32 _priorFrameTime; + Common::Point _mousePos; + + bool checkForNextFrameCounter(); +public: + CursorType _cursorId; + byte _mouseButtons; + bool _mouseClicked; + Common::Stack _pendingKeys; +public: + EventsManager(SherlockEngine *vm); + ~EventsManager(); + + void setCursor(CursorType cursorId); + + void showCursor(); + + void hideCursor(); + + bool isCursorVisible(); + + void pollEvents(); + + Common::Point mousePos() const { return _mousePos; } + + uint32 getFrameCounter() const { return _frameCounter; } + + bool isKeyPressed() const { return !_pendingKeys.empty(); } + + Common::KeyState getKey() { return _pendingKeys.pop(); } + + void delay(int amount); + + void waitForNextFrame(); + +}; + +} // End of namespace Sherlock + +#endif /* SHERLOCK_EVENTS_H */ diff --git a/engines/sherlock/graphics.cpp b/engines/sherlock/graphics.cpp index 695635d2ca..5c6c94606e 100644 --- a/engines/sherlock/graphics.cpp +++ b/engines/sherlock/graphics.cpp @@ -45,7 +45,9 @@ void Surface::drawSprite(int x, int y, SpriteFrame *spriteFrame, bool flipped, b /*----------------------------------------------------------------*/ -Screen::Screen(SherlockEngine *vm) : Surface(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT), _vm(vm) { +Screen::Screen(SherlockEngine *vm) : Surface(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT), _vm(vm), + _backBuffer1(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT), + _backBuffer2(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT) { setFont(1); } diff --git a/engines/sherlock/graphics.h b/engines/sherlock/graphics.h index fe03e7155d..801b1747ee 100644 --- a/engines/sherlock/graphics.h +++ b/engines/sherlock/graphics.h @@ -44,6 +44,7 @@ class Screen : public Surface { private: SherlockEngine *_vm; int _fontNumber; + Surface _backBuffer1, _backBuffer2; public: Screen(SherlockEngine *vm); diff --git a/engines/sherlock/module.mk b/engines/sherlock/module.mk index 1dfcb3a5af..19ad039262 100644 --- a/engines/sherlock/module.mk +++ b/engines/sherlock/module.mk @@ -4,7 +4,9 @@ MODULE_OBJS = \ scalpel/scalpel.o \ tattoo/tattoo.o \ decompress.o \ + debugger.o \ detection.o \ + events.o \ graphics.o \ journal.o \ resources.o \ diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp index bd8c96f253..1eaf7c91ee 100644 --- a/engines/sherlock/scalpel/scalpel.cpp +++ b/engines/sherlock/scalpel/scalpel.cpp @@ -30,6 +30,8 @@ namespace Scalpel { * Game initialization */ void ScalpelEngine::initialize() { + SherlockEngine::initialize(); + _flags.resize(100 * 8); _flags[3] = true; // Turn on Alley _flags[39] = true; // Turn on Baker Street @@ -38,6 +40,13 @@ void ScalpelEngine::initialize() { _rooms->_goToRoom = 4; } +/** + * Show the opening sequence + */ +void ScalpelEngine::showOpening() { + // TODO +} + } // End of namespace Scalpel diff --git a/engines/sherlock/scalpel/scalpel.h b/engines/sherlock/scalpel/scalpel.h index 9001c20456..6016984e45 100644 --- a/engines/sherlock/scalpel/scalpel.h +++ b/engines/sherlock/scalpel/scalpel.h @@ -32,6 +32,8 @@ namespace Scalpel { class ScalpelEngine : public SherlockEngine { protected: virtual void initialize(); + + virtual void showOpening(); public: ScalpelEngine(OSystem *syst, const SherlockGameDescription *gameDesc) : SherlockEngine(syst, gameDesc) {} diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index 13731e2fd8..cfbbacccf7 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -30,6 +30,7 @@ namespace Sherlock { SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc) { + _debugger = nullptr; _journal = nullptr; _res = nullptr; _rooms = nullptr; @@ -39,6 +40,7 @@ SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gam SherlockEngine::~SherlockEngine() { + delete _debugger; delete _journal; delete _res; delete _rooms; @@ -64,6 +66,7 @@ void SherlockEngine::initialize() { _midi->setNativeMT32(native_mt32); */ + _debugger = new Debugger(this); _journal = new Journal(); _res = new Resources(); _rooms = new Rooms(); @@ -74,7 +77,9 @@ void SherlockEngine::initialize() { Common::Error SherlockEngine::run() { initialize(); - // TODO: The rest of the game + showOpening(); + + // TODO: Rest of game return Common::kNoError; } diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h index 172c940c34..781851db71 100644 --- a/engines/sherlock/sherlock.h +++ b/engines/sherlock/sherlock.h @@ -30,6 +30,7 @@ #include "common/savefile.h" #include "common/hash-str.h" #include "engines/engine.h" +#include "sherlock/debugger.h" #include "sherlock/graphics.h" #include "sherlock/journal.h" #include "sherlock/resources.h" @@ -62,8 +63,11 @@ class SherlockEngine : public Engine { private: protected: virtual void initialize(); + + virtual void showOpening() = 0; public: const SherlockGameDescription *_gameDescription; + Debugger *_debugger; Journal *_journal; Resources *_res; Rooms *_rooms; diff --git a/engines/sherlock/tattoo/tattoo.cpp b/engines/sherlock/tattoo/tattoo.cpp index 57ca5c6e29..b2b45bc310 100644 --- a/engines/sherlock/tattoo/tattoo.cpp +++ b/engines/sherlock/tattoo/tattoo.cpp @@ -26,6 +26,10 @@ namespace Sherlock { namespace Tattoo { +void TattooEngine::showOpening() { + // TODO +} + } // End of namespace Tattoo } // End of namespace Scalpel diff --git a/engines/sherlock/tattoo/tattoo.h b/engines/sherlock/tattoo/tattoo.h index f06fa1532d..6d3ec33967 100644 --- a/engines/sherlock/tattoo/tattoo.h +++ b/engines/sherlock/tattoo/tattoo.h @@ -30,6 +30,8 @@ namespace Sherlock { namespace Tattoo { class TattooEngine : public SherlockEngine { +protected: + virtual void showOpening(); public: TattooEngine(OSystem *syst, const SherlockGameDescription *gameDesc) : SherlockEngine(syst, gameDesc) {} -- cgit v1.2.3 From 7a9514567f44f5a717fcfb1994431e54e06ea148 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 16 Mar 2015 01:41:08 +0200 Subject: MADS: Handle a game bug in scene 604, which prevents game completion --- engines/mads/nebular/nebular_scenes6.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes6.cpp b/engines/mads/nebular/nebular_scenes6.cpp index 046782b772..d94fb17fd4 100644 --- a/engines/mads/nebular/nebular_scenes6.cpp +++ b/engines/mads/nebular/nebular_scenes6.cpp @@ -948,8 +948,14 @@ void Scene604::actions() { _bombMode = 1; if ((_game._difficulty == DIFFICULTY_HARD) || _globals[kWarnedFloodCity]) handleBombActions(); - else if ((_game._objects.isInInventory(OBJ_POLYCEMENT) && _game._objects.isInInventory(OBJ_CHICKEN)) - && ((_globals[kLineStatus] == LINE_TIED) || ((_game._difficulty == DIFFICULTY_EASY) && (!_globals[kBoatRaised])))) + else if ( + (_game._objects.isInInventory(OBJ_POLYCEMENT) && (_game._objects.isInInventory(OBJ_CHICKEN) || _game._objects.isInInventory(OBJ_CHICKEN_BOMB))) + && (_globals[kLineStatus] == LINE_TIED || (_game._difficulty == DIFFICULTY_EASY && !_globals[kBoatRaised])) + ) + // The original can get in an impossible state at this point, if the player has + // combined the chicken with the bomb before placing the timer bomb on the ledge. + // Therefore, we also allow the player to place the bomb if the chicken bomb is + // in the inventory. handleBombActions(); else if (_game._difficulty == DIFFICULTY_EASY) _vm->_dialogs->show(60424); -- cgit v1.2.3 From 92c55e2bb192785e4587e143c9c367213f30233c Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 15 Mar 2015 21:25:07 -0400 Subject: SHERLOCK: Beginning of animation player --- engines/sherlock/animation.cpp | 124 +++++++++++++++++++++++++++++++++++ engines/sherlock/animation.h | 50 ++++++++++++++ engines/sherlock/events.cpp | 20 ++++++ engines/sherlock/events.h | 2 + engines/sherlock/graphics.h | 2 + engines/sherlock/module.mk | 2 + engines/sherlock/scalpel/scalpel.cpp | 34 ++++++++++ engines/sherlock/scalpel/scalpel.h | 5 ++ engines/sherlock/sherlock.cpp | 8 +++ engines/sherlock/sherlock.h | 6 ++ engines/sherlock/sound.cpp | 55 ++++++++++++++++ engines/sherlock/sound.h | 17 ++++- engines/sherlock/vdaplayer.h | 34 ---------- 13 files changed, 322 insertions(+), 37 deletions(-) create mode 100644 engines/sherlock/animation.cpp create mode 100644 engines/sherlock/animation.h create mode 100644 engines/sherlock/sound.cpp delete mode 100644 engines/sherlock/vdaplayer.h (limited to 'engines') diff --git a/engines/sherlock/animation.cpp b/engines/sherlock/animation.cpp new file mode 100644 index 0000000000..52859ce5e4 --- /dev/null +++ b/engines/sherlock/animation.cpp @@ -0,0 +1,124 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "sherlock/animation.h" +#include "sherlock/sherlock.h" +#include "common/algorithm.h" + +namespace Sherlock { + +// The following are a list of filenames played in the prologue that have +// special effects associated with them at specific frames + +#define FRAMES_END 32000 +#define PROLOGUE_NAMES_COUNT 6 +#define TITLE_NAMES_COUNT 7 +static const char *const PROLOGUE_NAMES[6] = { + "subway1", "subway2", "finale2", "suicid", "coff3", "coff4" +}; +static const int PROLOGUE_FRAMES[6][9] = { + { 4, 26, 54, 72, 92, 134, FRAMES_END }, + { 2, 80, 95, 117, 166, FRAMES_END }, + { 1, FRAMES_END }, + { 42, FRAMES_END }, + { FRAMES_END }, + { FRAMES_END } +}; + +// Title animations file list +static const char *const TITLE_NAMES[7] = { + "27pro1", "14note", "coff1", "coff2", "coff3", "coff4", "14kick" +}; + +static const int TITLE_FRAMES[7][9] = { + { 29, 131, FRAMES_END }, + { 55, 80, 95, 117, 166, FRAMES_END }, + { 15, FRAMES_END }, + { 4, 37, 92, FRAMES_END }, + { 2, 43, FRAMES_END }, + { 2, FRAMES_END }, + { 10, 50, FRAMES_END } +}; + +static const int NO_FRAMES = FRAMES_END; + +Animation::Animation(SherlockEngine *vm): _vm(vm) { + _useEpilogue2 = false; +} + +void Animation::playPrologue(const Common::String &filename, int minDelay, int fade, + bool setPalette, int speed) { + // Check for any any sound frames for the given animation + const int *soundFrames = checkForSoundFrames(filename); + + // Strip any extension off of the passed filename and add .vdx suffix + Common::String baseName = filename; + const char *p = strchr(baseName.c_str(), '.'); + if (p) + baseName = Common::String(filename.c_str(), MIN(p - 1, baseName.c_str() + 7)); + + Common::String vdxName = baseName + ".vdx"; + + // Load the animation + Common::SeekableReadStream *stream; + if (!_titleOverride.empty()) + stream = _vm->_res->load(vdxName, _titleOverride); + else if (_useEpilogue2) + stream = _vm->_res->load(vdxName, "epilog2.lib"); + else + stream = _vm->_res->load(vdxName, "epilogoue.lib"); + int resoucreIndex = _vm->_res->resouceIndex(); + + // Load initial image + //Common::String vdaName = baseName + ".vda"; + // TODO + + + delete stream; +} + +/** + * Checks for whether an animation is being played that has associated sound + */ +const int *Animation::checkForSoundFrames(const Common::String &filename) { + const int *frames = &NO_FRAMES; + + if (!_soundOverride.empty()) { + for (int idx = 0; idx < PROLOGUE_NAMES_COUNT; ++idx) { + if (!scumm_stricmp(filename.c_str(), PROLOGUE_NAMES[idx])) { + frames = &PROLOGUE_FRAMES[idx][0]; + break; + } + } + } else { + for (int idx = 0; idx < TITLE_NAMES_COUNT; ++idx) { + if (!scumm_stricmp(filename.c_str(), TITLE_NAMES[idx])) { + frames = &TITLE_FRAMES[idx][0]; + break; + } + } + } + + return frames; +} + +} // End of namespace Sherlock diff --git a/engines/sherlock/animation.h b/engines/sherlock/animation.h new file mode 100644 index 0000000000..bf4429656e --- /dev/null +++ b/engines/sherlock/animation.h @@ -0,0 +1,50 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef SHERLOCK_ANIMATION_H +#define SHERLOCK_ANIMATION_H + +#include "common/scummsys.h" +#include "common/str.h" + +namespace Sherlock { + +class SherlockEngine; + +class Animation { +private: + SherlockEngine *_vm; + + const int *checkForSoundFrames(const Common::String &filename); +public: + Common::String _soundOverride; + Common::String _titleOverride; + bool _useEpilogue2; +public: + Animation(SherlockEngine *vm); + + void playPrologue(const Common::String &filename, int minDelay, int fade, bool setPalette, int speed); +}; + +} // End of namespace Sherlock + +#endif diff --git a/engines/sherlock/events.cpp b/engines/sherlock/events.cpp index 7e62dc075b..fdcf61e46f 100644 --- a/engines/sherlock/events.cpp +++ b/engines/sherlock/events.cpp @@ -72,6 +72,9 @@ bool EventsManager::isCursorVisible() { return CursorMan.isVisible(); } +/** + * Check for any pending events + */ void EventsManager::pollEvents() { checkForNextFrameCounter(); @@ -112,6 +115,9 @@ void EventsManager::pollEvents() { } } +/** + * Check whether it's time to display the next screen frame + */ bool EventsManager::checkForNextFrameCounter() { // Check for next game frame uint32 milli = g_system->getMillis(); @@ -134,6 +140,17 @@ bool EventsManager::checkForNextFrameCounter() { return false; } +/** + * Clear any current keypress or mouse click + */ +void EventsManager::clearEvents() { + _pendingKeys.clear(); + _mouseClicked = false; +} + +/** + * Delay for a given number of frames/cycles + */ void EventsManager::delay(int cycles) { uint32 totalMilli = cycles * 1000 / GAME_FRAME_RATE; uint32 delayEnd = g_system->getMillis() + totalMilli; @@ -145,6 +162,9 @@ void EventsManager::delay(int cycles) { } } +/** + * Wait for the next frame + */ void EventsManager::waitForNextFrame() { _mouseClicked = false; _mouseButtons = 0; diff --git a/engines/sherlock/events.h b/engines/sherlock/events.h index 4ba30e0bdf..26f4ddb2d5 100644 --- a/engines/sherlock/events.h +++ b/engines/sherlock/events.h @@ -71,6 +71,8 @@ public: Common::KeyState getKey() { return _pendingKeys.pop(); } + void clearEvents(); + void delay(int amount); void waitForNextFrame(); diff --git a/engines/sherlock/graphics.h b/engines/sherlock/graphics.h index 801b1747ee..97daaef6e3 100644 --- a/engines/sherlock/graphics.h +++ b/engines/sherlock/graphics.h @@ -30,6 +30,8 @@ namespace Sherlock { +#define PALETTE_SIZE 768 + class SherlockEngine; class Surface : public Graphics::Surface { diff --git a/engines/sherlock/module.mk b/engines/sherlock/module.mk index 19ad039262..7009f49d3f 100644 --- a/engines/sherlock/module.mk +++ b/engines/sherlock/module.mk @@ -3,6 +3,7 @@ MODULE := engines/sherlock MODULE_OBJS = \ scalpel/scalpel.o \ tattoo/tattoo.o \ + animation.o \ decompress.o \ debugger.o \ detection.o \ @@ -12,6 +13,7 @@ MODULE_OBJS = \ resources.o \ room.o \ sherlock.o \ + sound.o \ sprite.o \ talk.o diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp index 1eaf7c91ee..72c5f1dcf3 100644 --- a/engines/sherlock/scalpel/scalpel.cpp +++ b/engines/sherlock/scalpel/scalpel.cpp @@ -21,6 +21,7 @@ */ #include "sherlock/scalpel/scalpel.h" +#include "sherlock/sherlock.h" namespace Sherlock { @@ -44,9 +45,42 @@ void ScalpelEngine::initialize() { * Show the opening sequence */ void ScalpelEngine::showOpening() { + if (!_events->isKeyPressed()) + showCityCutscene(); + if (!_events->isKeyPressed()) + showAlleyCutscene(); + if (!_events->isKeyPressed()) + showStreetCutscene(); + if (!_events->isKeyPressed()) + showOfficeCutscene(); + + _events->clearEvents(); + _sound->stopMusic(); +} + +void ScalpelEngine::showCityCutscene() { + byte palette[PALETTE_SIZE]; + + _sound->playMusic("prolog1.mus"); + _animation->_titleOverride = "title.lib"; + _animation->_soundOverride = "title.snd"; + _animation->playPrologue("26open1", 1, 255, true, 2); + // TODO } +void ScalpelEngine::showAlleyCutscene() { + +} + +void ScalpelEngine::showStreetCutscene() { + +} + +void ScalpelEngine::showOfficeCutscene() { + +} + } // End of namespace Scalpel diff --git a/engines/sherlock/scalpel/scalpel.h b/engines/sherlock/scalpel/scalpel.h index 6016984e45..5da33e1d52 100644 --- a/engines/sherlock/scalpel/scalpel.h +++ b/engines/sherlock/scalpel/scalpel.h @@ -30,6 +30,11 @@ namespace Sherlock { namespace Scalpel { class ScalpelEngine : public SherlockEngine { +private: + void showCityCutscene(); + void showAlleyCutscene(); + void showStreetCutscene(); + void showOfficeCutscene(); protected: virtual void initialize(); diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index cfbbacccf7..a750741ec9 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -30,21 +30,27 @@ namespace Sherlock { SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc) { + _animation = nullptr; _debugger = nullptr; + _events = nullptr; _journal = nullptr; _res = nullptr; _rooms = nullptr; _screen = nullptr; + _sound = nullptr; _talk = nullptr; } SherlockEngine::~SherlockEngine() { + delete _animation; delete _debugger; + delete _events; delete _journal; delete _res; delete _rooms; delete _screen; + delete _sound; delete _talk; } @@ -66,7 +72,9 @@ void SherlockEngine::initialize() { _midi->setNativeMT32(native_mt32); */ + _animation = new Animation(this); _debugger = new Debugger(this); + _events = new EventsManager(this); _journal = new Journal(); _res = new Resources(); _rooms = new Rooms(); diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h index 781851db71..88fbff74f9 100644 --- a/engines/sherlock/sherlock.h +++ b/engines/sherlock/sherlock.h @@ -30,11 +30,14 @@ #include "common/savefile.h" #include "common/hash-str.h" #include "engines/engine.h" +#include "sherlock/animation.h" #include "sherlock/debugger.h" +#include "sherlock/events.h" #include "sherlock/graphics.h" #include "sherlock/journal.h" #include "sherlock/resources.h" #include "sherlock/room.h" +#include "sherlock/sound.h" #include "sherlock/talk.h" namespace Sherlock { @@ -67,11 +70,14 @@ protected: virtual void showOpening() = 0; public: const SherlockGameDescription *_gameDescription; + Animation *_animation; Debugger *_debugger; + EventsManager *_events; Journal *_journal; Resources *_res; Rooms *_rooms; Screen *_screen; + Sound *_sound; Talk *_talk; Common::Array _flags; public: diff --git a/engines/sherlock/sound.cpp b/engines/sherlock/sound.cpp new file mode 100644 index 0000000000..f16dd5a80d --- /dev/null +++ b/engines/sherlock/sound.cpp @@ -0,0 +1,55 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "sherlock/sound.h" + +namespace Sherlock { + +Sound::Sound(SherlockEngine *vm): _vm(vm) { +} + +void Sound::playSound(const Common::String &name) { + // TODO +} + +void Sound::cacheSound(const Common::String &name, int index) { + // TODO +} + +void Sound::playCachedSound(int index) { + // TODO +} + +void Sound::clearCache() { + // TODO +} + +void Sound::playMusic(const Common::String &name) { + // TODO +} + +void Sound::stopMusic() { + // TODO +} + + +} // End of namespace Sherlock diff --git a/engines/sherlock/sound.h b/engines/sherlock/sound.h index f3b34345ef..b1759a9c8e 100644 --- a/engines/sherlock/sound.h +++ b/engines/sherlock/sound.h @@ -23,15 +23,26 @@ #ifndef SHERLOCK_SOUND_H #define SHERLOCK_SOUND_H +#include "common/scummsys.h" +#include "common/str.h" + namespace Sherlock { +class SherlockEngine; + class Sound { -public - void playSound(const char *name); - void cacheSound(const char *name, int index); +private: + SherlockEngine *_vm; +public: + Sound(SherlockEngine *vm); + + void playSound(const Common::String &name); + void cacheSound(const Common::String &name, int index); void playCachedSound(int index); void clearCache(); + void playMusic(const Common::String &name); + void stopMusic(); }; } // End of namespace Sherlock diff --git a/engines/sherlock/vdaplayer.h b/engines/sherlock/vdaplayer.h deleted file mode 100644 index 9b755606d5..0000000000 --- a/engines/sherlock/vdaplayer.h +++ /dev/null @@ -1,34 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#ifndef SHERLOCK_VDAPLAYER_H -#define SHERLOCK_VDAPLAYER_H - -namespace Sherlock { - -class VdaPlayer { - -}; - -} // End of namespace Sherlock - -#endif -- cgit v1.2.3 From 6cfb7169b94e0c3c665d7799584eb8e5a7f337b3 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 15 Mar 2015 23:16:38 -0400 Subject: SHERLOCK: Beginnings of sprite loading for animations --- engines/sherlock/animation.cpp | 17 +++--- engines/sherlock/animation.h | 3 - engines/sherlock/resources.cpp | 2 +- engines/sherlock/resources.h | 2 +- engines/sherlock/scalpel/scalpel.cpp | 4 +- engines/sherlock/sherlock.cpp | 1 + engines/sherlock/sherlock.h | 3 + engines/sherlock/sprite.cpp | 114 ++++++++++++----------------------- engines/sherlock/sprite.h | 27 ++++----- 9 files changed, 67 insertions(+), 106 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/animation.cpp b/engines/sherlock/animation.cpp index 52859ce5e4..3da0201a61 100644 --- a/engines/sherlock/animation.cpp +++ b/engines/sherlock/animation.cpp @@ -22,6 +22,7 @@ #include "sherlock/animation.h" #include "sherlock/sherlock.h" +#include "sherlock/sprite.h" #include "common/algorithm.h" namespace Sherlock { @@ -62,7 +63,6 @@ static const int TITLE_FRAMES[7][9] = { static const int NO_FRAMES = FRAMES_END; Animation::Animation(SherlockEngine *vm): _vm(vm) { - _useEpilogue2 = false; } void Animation::playPrologue(const Common::String &filename, int minDelay, int fade, @@ -80,16 +80,19 @@ void Animation::playPrologue(const Common::String &filename, int minDelay, int f // Load the animation Common::SeekableReadStream *stream; - if (!_titleOverride.empty()) - stream = _vm->_res->load(vdxName, _titleOverride); - else if (_useEpilogue2) + if (!_vm->_titleOverride.empty()) + stream = _vm->_res->load(vdxName, _vm->_titleOverride); + else if (_vm->_useEpilogue2) stream = _vm->_res->load(vdxName, "epilog2.lib"); else stream = _vm->_res->load(vdxName, "epilogoue.lib"); - int resoucreIndex = _vm->_res->resouceIndex(); + int resourceIndex = _vm->_res->resourceIndex(); // Load initial image - //Common::String vdaName = baseName + ".vda"; + Common::String vdaName = baseName + ".vda"; + Common::SeekableReadStream *vdaStream = _vm->_res->load(vdaName); + Sprite sprite(*vdaStream); + // TODO @@ -102,7 +105,7 @@ void Animation::playPrologue(const Common::String &filename, int minDelay, int f const int *Animation::checkForSoundFrames(const Common::String &filename) { const int *frames = &NO_FRAMES; - if (!_soundOverride.empty()) { + if (!_vm->_soundOverride.empty()) { for (int idx = 0; idx < PROLOGUE_NAMES_COUNT; ++idx) { if (!scumm_stricmp(filename.c_str(), PROLOGUE_NAMES[idx])) { frames = &PROLOGUE_FRAMES[idx][0]; diff --git a/engines/sherlock/animation.h b/engines/sherlock/animation.h index bf4429656e..14384cfa28 100644 --- a/engines/sherlock/animation.h +++ b/engines/sherlock/animation.h @@ -36,9 +36,6 @@ private: const int *checkForSoundFrames(const Common::String &filename); public: - Common::String _soundOverride; - Common::String _titleOverride; - bool _useEpilogue2; public: Animation(SherlockEngine *vm); diff --git a/engines/sherlock/resources.cpp b/engines/sherlock/resources.cpp index e59e65abff..47e2046084 100644 --- a/engines/sherlock/resources.cpp +++ b/engines/sherlock/resources.cpp @@ -212,7 +212,7 @@ void Resources::loadLibraryIndex(const Common::String &libFilename, * This will be used primarily when loading talk files, so the engine can * update the given conversation number in the journal */ -int Resources::resouceIndex() const { +int Resources::resourceIndex() const { return _resourceIndex; } diff --git a/engines/sherlock/resources.h b/engines/sherlock/resources.h index bfd2eb300c..edb9bd8ba0 100644 --- a/engines/sherlock/resources.h +++ b/engines/sherlock/resources.h @@ -77,7 +77,7 @@ public: Common::SeekableReadStream *load(const Common::String &filename, const Common::String &libraryFile); - int resouceIndex() const; + int resourceIndex() const; }; diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp index 72c5f1dcf3..0b651bbb69 100644 --- a/engines/sherlock/scalpel/scalpel.cpp +++ b/engines/sherlock/scalpel/scalpel.cpp @@ -62,8 +62,8 @@ void ScalpelEngine::showCityCutscene() { byte palette[PALETTE_SIZE]; _sound->playMusic("prolog1.mus"); - _animation->_titleOverride = "title.lib"; - _animation->_soundOverride = "title.snd"; + _titleOverride = "title.lib"; + _soundOverride = "title.snd"; _animation->playPrologue("26open1", 1, 255, true, 2); // TODO diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index a750741ec9..cb0472feff 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -39,6 +39,7 @@ SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gam _screen = nullptr; _sound = nullptr; _talk = nullptr; + _useEpilogue2 = false; } diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h index 88fbff74f9..b04a14e8ac 100644 --- a/engines/sherlock/sherlock.h +++ b/engines/sherlock/sherlock.h @@ -80,6 +80,9 @@ public: Sound *_sound; Talk *_talk; Common::Array _flags; + Common::String _soundOverride; + Common::String _titleOverride; + bool _useEpilogue2; public: SherlockEngine(OSystem *syst, const SherlockGameDescription *gameDesc); virtual ~SherlockEngine(); diff --git a/engines/sherlock/sprite.cpp b/engines/sherlock/sprite.cpp index 7aa2fdc71b..f686f0b27e 100644 --- a/engines/sherlock/sprite.cpp +++ b/engines/sherlock/sprite.cpp @@ -25,101 +25,61 @@ namespace Sherlock { -/* -struct SpriteFrame { - byte *data; - int width, height; - uint16 flags; - int xofs, yofs; - byte rleMarker; -}; -*/ - Sprite::Sprite(Common::SeekableReadStream &stream) { load(stream); } Sprite::~Sprite() { + for (uint idx = 0; idx < size(); ++idx) + (*this)[idx]._frame.free(); } -int Sprite::getFrameCount() { - return _frames.size(); -} - -SpriteFrame *Sprite::getFrame(int index) { - return _frames[index]; -} - +/** + * Load the data of the sprite + */ void Sprite::load(Common::SeekableReadStream &stream) { - while (!stream.eos()) { - - debug("frameNum = %d\n", _frames.size()); - - SpriteFrame *spriteFrame = new SpriteFrame(); - - uint32 startOfs = stream.pos(); - - debug("startOfs = %08X\n", startOfs); + SpriteFrame frame; - spriteFrame->frame = NULL; - spriteFrame->width = stream.readUint16LE() + 1; - spriteFrame->height = stream.readUint16LE() + 1; - spriteFrame->flags = stream.readUint16LE(); + frame._width = stream.readUint16LE() + 1; + frame._height = stream.readUint16LE() + 1; + frame._flags = stream.readUint16LE(); stream.readUint16LE(); - debug("width = %d; height = %d; flags = %04X\n", spriteFrame->width, spriteFrame->height, spriteFrame->flags); - - if (spriteFrame->flags & 0xFF) { - spriteFrame->size = (spriteFrame->width * spriteFrame->height) / 2; - } else if (spriteFrame->flags & 0x0100) { + if (frame._flags & 0xFF) { + frame._size = (frame._width * frame._height) / 2; + } else if (frame._flags & 0x0100) { // this size includes the header size, which we subtract - spriteFrame->size = stream.readUint16LE() - 11; - spriteFrame->rleMarker = stream.readByte(); + frame._size = stream.readUint16LE() - 11; + frame._rleMarker = stream.readByte(); } else { - spriteFrame->size = spriteFrame->width * spriteFrame->height; + frame._size = frame._width * frame._height; } - spriteFrame->data = new byte[spriteFrame->size]; - stream.read(spriteFrame->data, spriteFrame->size); - - decompressFrame(spriteFrame); + // Load data for frame and decompress it + byte *data = new byte[frame._size]; + stream.read(data, frame._size); + decompressFrame(frame, data); + delete data; - /* - debug("size = %d (%08X)\n", spriteFrame->size, spriteFrame->size); - if (spriteFrame->frame) { - char fn[128]; - sndebug(fn, 128, "%04d.spr", _frames.size()); - FILE *x = fopen(fn, "wb"); - fwrite(spriteFrame->frame->pixels, spriteFrame->frame->w * spriteFrame->frame->h, 1, x); - fclose(x); - } - */ - - _frames.push_back(spriteFrame); - + push_back(frame); } - - // debug("Done: %08X\n", stream.pos()); fflush(stdout); - } -void Sprite::decompressFrame(SpriteFrame *frame) { - - frame->frame = new Graphics::Surface(); - frame->frame->create(frame->width, frame->height, Graphics::PixelFormat::createFormatCLUT8()); - - if (frame->flags & 0xFF) { - debug("Sprite::decompressFrame() 4-bits/pixel\n"); - debug("TODO\n"); - } else if (frame->flags & 0x0100) { - debug("Sprite::decompressFrame() RLE-compressed; rleMarker = %02X\n", frame->rleMarker); - const byte *src = frame->data; - byte *dst = (byte *)frame->frame->getPixels(); - for (uint16 h = 0; h < frame->height; h++) { - int16 w = frame->width; +/** + * Decompress a single frame for the sprite + */ +void Sprite::decompressFrame(SpriteFrame &frame, const byte *src) { + frame._frame.create(frame._width, frame._height, Graphics::PixelFormat::createFormatCLUT8()); + + if (frame._flags & 0xFF) { + debug("TODO: Sprite::decompressFrame() 4-bits/pixel\n"); + } else if (frame._flags & 0x0100) { + byte *dst = (byte *)frame._frame.getPixels(); + for (uint16 h = 0; h < frame._height; ++h) { + int16 w = frame._width; while (w > 0) { - if (*src == frame->rleMarker) { + if (*src == frame._rleMarker) { byte rleColor = src[1]; byte rleCount = src[2]; src += 3; @@ -133,10 +93,10 @@ void Sprite::decompressFrame(SpriteFrame *frame) { } } } else { - debug("Sprite::decompressFrame() Uncompressed\n"); - memcpy(frame->data, frame->frame->getPixels(), frame->width * frame->height); + // Uncompressed frame + Common::copy(src, src + frame._width * frame._height, + (byte *)frame._frame.getPixels()); } - } } // End of namespace Sherlock diff --git a/engines/sherlock/sprite.h b/engines/sherlock/sprite.h index f56ab588bb..1f81cf8071 100644 --- a/engines/sherlock/sprite.h +++ b/engines/sherlock/sprite.h @@ -23,32 +23,29 @@ #ifndef SHERLOCK_SPRITE_H #define SHERLOCK_SPRITE_H -#include "common/stream.h" #include "common/array.h" +#include "common/rect.h" +#include "common/stream.h" #include "graphics/surface.h" namespace Sherlock { struct SpriteFrame { - byte *data; - uint32 size; - uint16 width, height; - uint16 flags; - int xofs, yofs; - byte rleMarker; - Graphics::Surface *frame; + uint32 _size; + uint16 _width, _height; + int _flags; + Common::Point _offset; + byte _rleMarker; + Graphics::Surface _frame; }; -class Sprite { +class Sprite: public Common::Array { +private: + void load(Common::SeekableReadStream &stream); + void decompressFrame(SpriteFrame &frame, const byte *src); public: Sprite(Common::SeekableReadStream &stream); ~Sprite(); - int getFrameCount(); - SpriteFrame *getFrame(int index); -protected: - Common::Array _frames; - void load(Common::SeekableReadStream &stream); - void decompressFrame(SpriteFrame *frame); }; } // End of namespace Sherlock -- cgit v1.2.3 From 02657f5a91bba15c7d494f71d0c975ece7178861 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 16 Mar 2015 00:02:45 -0400 Subject: SHERLOCK: Fix loading of sprite for startup animation --- engines/sherlock/animation.cpp | 2 +- engines/sherlock/sprite.cpp | 47 +++++++++++++++++++++++------------------- engines/sherlock/sprite.h | 6 ++++-- 3 files changed, 31 insertions(+), 24 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/animation.cpp b/engines/sherlock/animation.cpp index 3da0201a61..4111f6f88f 100644 --- a/engines/sherlock/animation.cpp +++ b/engines/sherlock/animation.cpp @@ -91,7 +91,7 @@ void Animation::playPrologue(const Common::String &filename, int minDelay, int f // Load initial image Common::String vdaName = baseName + ".vda"; Common::SeekableReadStream *vdaStream = _vm->_res->load(vdaName); - Sprite sprite(*vdaStream); + Sprite sprite(*vdaStream, true); // TODO diff --git a/engines/sherlock/sprite.cpp b/engines/sherlock/sprite.cpp index f686f0b27e..ee7c8e5019 100644 --- a/engines/sherlock/sprite.cpp +++ b/engines/sherlock/sprite.cpp @@ -25,8 +25,8 @@ namespace Sherlock { -Sprite::Sprite(Common::SeekableReadStream &stream) { - load(stream); +Sprite::Sprite(Common::SeekableReadStream &stream, bool skipPal) { + load(stream, skipPal); } Sprite::~Sprite() { @@ -37,22 +37,26 @@ Sprite::~Sprite() { /** * Load the data of the sprite */ -void Sprite::load(Common::SeekableReadStream &stream) { - while (!stream.eos()) { +void Sprite::load(Common::SeekableReadStream &stream, bool skipPal) { + while (stream.pos() < stream.size()) { SpriteFrame frame; - frame._width = stream.readUint16LE() + 1; frame._height = stream.readUint16LE() + 1; frame._flags = stream.readUint16LE(); stream.readUint16LE(); + if (skipPal) + frame._flags = 0; + if (frame._flags & 0xFF) { + // Nibble packed frame data frame._size = (frame._width * frame._height) / 2; - } else if (frame._flags & 0x0100) { + } else if (frame._flags & RLE_ENCODED) { // this size includes the header size, which we subtract frame._size = stream.readUint16LE() - 11; frame._rleMarker = stream.readByte(); } else { + // Uncompressed data frame._size = frame._width * frame._height; } @@ -74,24 +78,25 @@ void Sprite::decompressFrame(SpriteFrame &frame, const byte *src) { if (frame._flags & 0xFF) { debug("TODO: Sprite::decompressFrame() 4-bits/pixel\n"); - } else if (frame._flags & 0x0100) { + } else if (frame._flags & RLE_ENCODED) { + // RLE encoded byte *dst = (byte *)frame._frame.getPixels(); - for (uint16 h = 0; h < frame._height; ++h) { - int16 w = frame._width; - while (w > 0) { - if (*src == frame._rleMarker) { - byte rleColor = src[1]; - byte rleCount = src[2]; - src += 3; - w -= rleCount; - while (rleCount--) - *dst++ = rleColor; - } else { - *dst++ = *src++; - w--; - } + + int size = frame._width * frame._height; + while (size > 0) { + if (*src == frame._rleMarker) { + byte rleColor = src[1]; + byte rleCount = src[2]; + src += 3; + size -= rleCount; + while (rleCount--) + *dst++ = rleColor; + } else { + *dst++ = *src++; + --size; } } + assert(size == 0); } else { // Uncompressed frame Common::copy(src, src + frame._width * frame._height, diff --git a/engines/sherlock/sprite.h b/engines/sherlock/sprite.h index 1f81cf8071..17566c81bd 100644 --- a/engines/sherlock/sprite.h +++ b/engines/sherlock/sprite.h @@ -30,6 +30,8 @@ namespace Sherlock { +enum { RLE_ENCODED = 0x0100 }; + struct SpriteFrame { uint32 _size; uint16 _width, _height; @@ -41,10 +43,10 @@ struct SpriteFrame { class Sprite: public Common::Array { private: - void load(Common::SeekableReadStream &stream); + void load(Common::SeekableReadStream &stream, bool skipPal); void decompressFrame(SpriteFrame &frame, const byte *src); public: - Sprite(Common::SeekableReadStream &stream); + Sprite(Common::SeekableReadStream &stream, bool skipPal = false); ~Sprite(); }; -- cgit v1.2.3 From b762bebf27ce7c231dd17fc05bc32f72911e6ed5 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 16 Mar 2015 08:07:24 -0400 Subject: SHERLOCK: Implement sprite palette loading and fade out --- engines/sherlock/animation.cpp | 12 ++++++++++++ engines/sherlock/events.cpp | 11 ++++++++++- engines/sherlock/events.h | 4 +++- engines/sherlock/graphics.cpp | 32 ++++++++++++++++++++++++++++++++ engines/sherlock/graphics.h | 7 +++++++ engines/sherlock/sprite.cpp | 17 +++++++++++++++++ engines/sherlock/sprite.h | 3 +++ 7 files changed, 84 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/animation.cpp b/engines/sherlock/animation.cpp index 4111f6f88f..2e9eb294d3 100644 --- a/engines/sherlock/animation.cpp +++ b/engines/sherlock/animation.cpp @@ -67,6 +67,9 @@ Animation::Animation(SherlockEngine *vm): _vm(vm) { void Animation::playPrologue(const Common::String &filename, int minDelay, int fade, bool setPalette, int speed) { + EventsManager &events = *_vm->_events; + Screen &screen = *_vm->_screen; + // Check for any any sound frames for the given animation const int *soundFrames = checkForSoundFrames(filename); @@ -93,6 +96,15 @@ void Animation::playPrologue(const Common::String &filename, int minDelay, int f Common::SeekableReadStream *vdaStream = _vm->_res->load(vdaName); Sprite sprite(*vdaStream, true); + events.delay(minDelay); + if (fade != 0 && fade != 255) + screen.fadeToBlack(); + + if (setPalette) { + if (fade != 255) + screen.setPalette(sprite._palette); + } + // TODO diff --git a/engines/sherlock/events.cpp b/engines/sherlock/events.cpp index fdcf61e46f..4a51c4a5fb 100644 --- a/engines/sherlock/events.cpp +++ b/engines/sherlock/events.cpp @@ -115,6 +115,15 @@ void EventsManager::pollEvents() { } } +/** + * Poll for events and introduce a small delay, to allow the system to + * yield to other running programs + */ +void EventsManager::pollEventsAndWait() { + pollEvents(); + g_system->delayMillis(10); +} + /** * Check whether it's time to display the next screen frame */ @@ -149,7 +158,7 @@ void EventsManager::clearEvents() { } /** - * Delay for a given number of frames/cycles + * Delay for a given number of cycles, where each cycle is 1/60th of a second */ void EventsManager::delay(int cycles) { uint32 totalMilli = cycles * 1000 / GAME_FRAME_RATE; diff --git a/engines/sherlock/events.h b/engines/sherlock/events.h index 26f4ddb2d5..f4e6964ef5 100644 --- a/engines/sherlock/events.h +++ b/engines/sherlock/events.h @@ -31,7 +31,7 @@ namespace Sherlock { enum CursorType { CURSOR_NONE = 0 }; -#define GAME_FRAME_RATE 50 +#define GAME_FRAME_RATE 60 #define GAME_FRAME_TIME (1000 / GAME_FRAME_RATE) class SherlockEngine; @@ -63,6 +63,8 @@ public: void pollEvents(); + void pollEventsAndWait(); + Common::Point mousePos() const { return _mousePos; } uint32 getFrameCounter() const { return _frameCounter; } diff --git a/engines/sherlock/graphics.cpp b/engines/sherlock/graphics.cpp index 5c6c94606e..583389e060 100644 --- a/engines/sherlock/graphics.cpp +++ b/engines/sherlock/graphics.cpp @@ -23,6 +23,7 @@ #include "sherlock/graphics.h" #include "sherlock/sherlock.h" #include "common/system.h" +#include "graphics/palette.h" namespace Sherlock { @@ -65,4 +66,35 @@ void Screen::update() { g_system->updateScreen(); } +void Screen::getPalette(byte palette[PALETTE_SIZE]) { + g_system->getPaletteManager()->grabPalette(palette, 0, PALETTE_COUNT); +} + +void Screen::setPalette(const byte palette[PALETTE_SIZE]) { + g_system->getPaletteManager()->setPalette(palette, 0, PALETTE_COUNT); +} + +void Screen::fadeToBlack() { + const int FADE_AMOUNT = 2; + bool repeatFlag; + byte *srcP; + int count; + byte tempPalette[PALETTE_SIZE]; + + getPalette(tempPalette); + do { + repeatFlag = false; + for (srcP = &tempPalette[0], count = 0; count < PALETTE_SIZE; ++count, ++srcP) { + int v = *srcP; + if (v) { + repeatFlag = true; + *srcP = MAX(*srcP - FADE_AMOUNT, 0); + } + } + + setPalette(tempPalette); + _vm->_events->pollEventsAndWait(); + } while (repeatFlag && !_vm->shouldQuit()); +} + } // End of namespace Sherlock diff --git a/engines/sherlock/graphics.h b/engines/sherlock/graphics.h index 97daaef6e3..0385deebde 100644 --- a/engines/sherlock/graphics.h +++ b/engines/sherlock/graphics.h @@ -31,6 +31,7 @@ namespace Sherlock { #define PALETTE_SIZE 768 +#define PALETTE_COUNT 256 class SherlockEngine; @@ -53,6 +54,12 @@ public: void setFont(int fontNumber); void update(); + + void getPalette(byte palette[PALETTE_SIZE]); + + void setPalette(const byte palette[PALETTE_SIZE]); + + void fadeToBlack(); }; } // End of namespace Sherlock diff --git a/engines/sherlock/sprite.cpp b/engines/sherlock/sprite.cpp index ee7c8e5019..c8d9ab55e3 100644 --- a/engines/sherlock/sprite.cpp +++ b/engines/sherlock/sprite.cpp @@ -21,11 +21,13 @@ */ #include "sherlock/sprite.h" +#include "sherlock/graphics.h" #include "common/debug.h" namespace Sherlock { Sprite::Sprite(Common::SeekableReadStream &stream, bool skipPal) { + Common::fill(&_palette[0], &_palette[PALETTE_SIZE], 0); load(stream, skipPal); } @@ -38,6 +40,8 @@ Sprite::~Sprite() { * Load the data of the sprite */ void Sprite::load(Common::SeekableReadStream &stream, bool skipPal) { + loadPalette(stream); + while (stream.pos() < stream.size()) { SpriteFrame frame; frame._width = stream.readUint16LE() + 1; @@ -70,6 +74,19 @@ void Sprite::load(Common::SeekableReadStream &stream, bool skipPal) { } } +/** + * Gets the palette at the start of the sprite file + */ +void Sprite::loadPalette(Common::SeekableReadStream &stream) { + int v1 = stream.readUint16LE() + 1; + int v2 = stream.readUint16LE() + 1; + int size = v1 * v2; + assert((size - 12) == PALETTE_SIZE); + + stream.seek(4 + 12, SEEK_CUR); + stream.read(&_palette[0], PALETTE_SIZE); +} + /** * Decompress a single frame for the sprite */ diff --git a/engines/sherlock/sprite.h b/engines/sherlock/sprite.h index 17566c81bd..5a510b2548 100644 --- a/engines/sherlock/sprite.h +++ b/engines/sherlock/sprite.h @@ -44,7 +44,10 @@ struct SpriteFrame { class Sprite: public Common::Array { private: void load(Common::SeekableReadStream &stream, bool skipPal); + void loadPalette(Common::SeekableReadStream &stream); void decompressFrame(SpriteFrame &frame, const byte *src); +public: + byte _palette[256 * 3]; public: Sprite(Common::SeekableReadStream &stream, bool skipPal = false); ~Sprite(); -- cgit v1.2.3 From 0ee3f1895f6b6dcf4bbb70ba309fb66d0ca39613 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 16 Mar 2015 22:42:19 -0400 Subject: SHERLOCK: Beginnings of animation sequence loop --- engines/sherlock/animation.cpp | 69 +++++++++++++++++++++++++++++++++--- engines/sherlock/animation.h | 2 +- engines/sherlock/graphics.cpp | 26 ++++++++++++++ engines/sherlock/graphics.h | 2 ++ engines/sherlock/scalpel/scalpel.cpp | 34 +++++++++--------- engines/sherlock/scalpel/scalpel.h | 8 ++--- engines/sherlock/sherlock.cpp | 1 + engines/sherlock/sound.cpp | 10 +++++- engines/sherlock/sound.h | 12 ++++++- engines/sherlock/sprite.cpp | 13 +++---- engines/sherlock/sprite.h | 5 ++- 11 files changed, 145 insertions(+), 37 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/animation.cpp b/engines/sherlock/animation.cpp index 2e9eb294d3..e4ec06b741 100644 --- a/engines/sherlock/animation.cpp +++ b/engines/sherlock/animation.cpp @@ -65,10 +65,13 @@ static const int NO_FRAMES = FRAMES_END; Animation::Animation(SherlockEngine *vm): _vm(vm) { } -void Animation::playPrologue(const Common::String &filename, int minDelay, int fade, +bool Animation::playPrologue(const Common::String &filename, int minDelay, int fade, bool setPalette, int speed) { EventsManager &events = *_vm->_events; Screen &screen = *_vm->_screen; + Sound &sound = *_vm->_sound; + int soundNumber = 0; + sound._playingEpilogue = true; // Check for any any sound frames for the given animation const int *soundFrames = checkForSoundFrames(filename); @@ -89,7 +92,6 @@ void Animation::playPrologue(const Common::String &filename, int minDelay, int f stream = _vm->_res->load(vdxName, "epilog2.lib"); else stream = _vm->_res->load(vdxName, "epilogoue.lib"); - int resourceIndex = _vm->_res->resourceIndex(); // Load initial image Common::String vdaName = baseName + ".vda"; @@ -99,16 +101,75 @@ void Animation::playPrologue(const Common::String &filename, int minDelay, int f events.delay(minDelay); if (fade != 0 && fade != 255) screen.fadeToBlack(); - + fade = 0; //***DEBUG**** if (setPalette) { if (fade != 255) screen.setPalette(sprite._palette); } - // TODO + int frameNumber = 0; + int spriteFrame; + Common::Point pt; + bool skipped = false; + while (!_vm->shouldQuit()) { + spriteFrame = stream->readSint16LE(); + if (spriteFrame != -1) { + if (spriteFrame < 0) { + spriteFrame = ABS(spriteFrame); + pt.x = stream->readUint16LE(); + pt.y = stream->readUint16LE(); + } else { + pt = sprite[spriteFrame]._position; + } + + screen.copyFrom(sprite[spriteFrame]._frame); + events.pollEventsAndWait(); + } else { + if (fade == 255) { + // Gradual fade in + if (screen.equalizePalette(sprite._palette) == 0) + fade = 0; + } + + // Check if we've reached a frame with sound + if (frameNumber++ == *soundFrames) { + ++soundNumber; + ++soundFrames; + Common::String fname = _vm->_soundOverride.empty() ? + Common::String::format("%s%01d", baseName.c_str(), soundNumber) : + Common::String::format("%s%02d", baseName.c_str(), soundNumber); + + if (sound._voicesEnabled) + sound.playSound(fname); + } + + events.delay(speed); + if (stream->readSint16LE() == -2) + // End of animation + break; + stream->seek(-2, SEEK_CUR); + } + if (events.isKeyPressed()) { + Common::KeyState keyState = events.getKey(); + if (keyState.keycode == Common::KEYCODE_ESCAPE || + keyState.keycode == Common::KEYCODE_SPACE) { + skipped = true; + break; + } + } else if (events._mouseClicked) { + skipped = true; + break; + } + } + + events.clearEvents(); + sound.stopSound(); delete stream; + sound._playingEpilogue = false; + + return !skipped && !_vm->shouldQuit(); } /** diff --git a/engines/sherlock/animation.h b/engines/sherlock/animation.h index 14384cfa28..da4c5baad7 100644 --- a/engines/sherlock/animation.h +++ b/engines/sherlock/animation.h @@ -39,7 +39,7 @@ public: public: Animation(SherlockEngine *vm); - void playPrologue(const Common::String &filename, int minDelay, int fade, bool setPalette, int speed); + bool playPrologue(const Common::String &filename, int minDelay, int fade, bool setPalette, int speed); }; } // End of namespace Sherlock diff --git a/engines/sherlock/graphics.cpp b/engines/sherlock/graphics.cpp index 583389e060..f4fe6b6b46 100644 --- a/engines/sherlock/graphics.cpp +++ b/engines/sherlock/graphics.cpp @@ -63,6 +63,7 @@ void Screen::setFont(int fontNumber) { } void Screen::update() { + g_system->copyRectToScreen(getPixels(), this->w, 0, 0, this->w, this->h); g_system->updateScreen(); } @@ -74,6 +75,31 @@ void Screen::setPalette(const byte palette[PALETTE_SIZE]) { g_system->getPaletteManager()->setPalette(palette, 0, PALETTE_COUNT); } +int Screen::equalizePalette(const byte palette[PALETTE_SIZE]) { + int total = 0; + byte tempPalette[PALETTE_SIZE]; + getPalette(tempPalette); + + // For any palette component that doesn't already match the given destination + // palette, change by 1 towards the reference palette component + for (int idx = 0; idx < PALETTE_SIZE; ++idx) { + if (tempPalette[idx] > palette[idx]) + { + --tempPalette[idx]; + ++total; + } else if (tempPalette[idx] < palette[idx]) { + ++tempPalette[idx]; + ++total; + } + } + + if (total > 0) + // Palette changed, so reload it + setPalette(tempPalette); + + return total; +} + void Screen::fadeToBlack() { const int FADE_AMOUNT = 2; bool repeatFlag; diff --git a/engines/sherlock/graphics.h b/engines/sherlock/graphics.h index 0385deebde..c6611db1ce 100644 --- a/engines/sherlock/graphics.h +++ b/engines/sherlock/graphics.h @@ -59,6 +59,8 @@ public: void setPalette(const byte palette[PALETTE_SIZE]); + int equalizePalette(const byte palette[PALETTE_SIZE]); + void fadeToBlack(); }; diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp index 0b651bbb69..90a93de1b1 100644 --- a/engines/sherlock/scalpel/scalpel.cpp +++ b/engines/sherlock/scalpel/scalpel.cpp @@ -45,21 +45,21 @@ void ScalpelEngine::initialize() { * Show the opening sequence */ void ScalpelEngine::showOpening() { - if (!_events->isKeyPressed()) - showCityCutscene(); - if (!_events->isKeyPressed()) - showAlleyCutscene(); - if (!_events->isKeyPressed()) - showStreetCutscene(); - if (!_events->isKeyPressed()) - showOfficeCutscene(); + if (!showCityCutscene()) + return; + if (!showAlleyCutscene()) + return; + if (!showStreetCutscene()) + return; + if (!showOfficeCutscene()) + return; _events->clearEvents(); _sound->stopMusic(); } -void ScalpelEngine::showCityCutscene() { - byte palette[PALETTE_SIZE]; +bool ScalpelEngine::showCityCutscene() { +// byte palette[PALETTE_SIZE]; _sound->playMusic("prolog1.mus"); _titleOverride = "title.lib"; @@ -67,21 +67,21 @@ void ScalpelEngine::showCityCutscene() { _animation->playPrologue("26open1", 1, 255, true, 2); // TODO + return true; } -void ScalpelEngine::showAlleyCutscene() { - +bool ScalpelEngine::showAlleyCutscene() { + return true; } -void ScalpelEngine::showStreetCutscene() { - +bool ScalpelEngine::showStreetCutscene() { + return true; } -void ScalpelEngine::showOfficeCutscene() { - +bool ScalpelEngine::showOfficeCutscene() { + return true; } - } // End of namespace Scalpel } // End of namespace Scalpel diff --git a/engines/sherlock/scalpel/scalpel.h b/engines/sherlock/scalpel/scalpel.h index 5da33e1d52..584bd78a20 100644 --- a/engines/sherlock/scalpel/scalpel.h +++ b/engines/sherlock/scalpel/scalpel.h @@ -31,10 +31,10 @@ namespace Scalpel { class ScalpelEngine : public SherlockEngine { private: - void showCityCutscene(); - void showAlleyCutscene(); - void showStreetCutscene(); - void showOfficeCutscene(); + bool showCityCutscene(); + bool showAlleyCutscene(); + bool showStreetCutscene(); + bool showOfficeCutscene(); protected: virtual void initialize(); diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index cb0472feff..1fba746f8d 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -80,6 +80,7 @@ void SherlockEngine::initialize() { _res = new Resources(); _rooms = new Rooms(); _screen = new Screen(this); + _sound = new Sound(this); _talk = new Talk(); } diff --git a/engines/sherlock/sound.cpp b/engines/sherlock/sound.cpp index f16dd5a80d..0957315a35 100644 --- a/engines/sherlock/sound.cpp +++ b/engines/sherlock/sound.cpp @@ -25,9 +25,13 @@ namespace Sherlock { Sound::Sound(SherlockEngine *vm): _vm(vm) { + _sfxEnabled = true; + _musicEnabled = true; + _voicesEnabled = true; + _playingEpilogue = false; } -void Sound::playSound(const Common::String &name) { +void Sound::playSound(const Common::String &name, WaitType waitType) { // TODO } @@ -43,6 +47,10 @@ void Sound::clearCache() { // TODO } +void Sound::stopSound() { + // TODO +} + void Sound::playMusic(const Common::String &name) { // TODO } diff --git a/engines/sherlock/sound.h b/engines/sherlock/sound.h index b1759a9c8e..7775016c94 100644 --- a/engines/sherlock/sound.h +++ b/engines/sherlock/sound.h @@ -30,16 +30,26 @@ namespace Sherlock { class SherlockEngine; +enum WaitType { + WAIT_RETURN_IMMEDIATELY = 0, WAIT_FINISH = 1, WAIT_KBD_OR_FINISH = 2 +}; + class Sound { private: SherlockEngine *_vm; +public: + bool _sfxEnabled; + bool _musicEnabled; + bool _voicesEnabled; + bool _playingEpilogue; public: Sound(SherlockEngine *vm); - void playSound(const Common::String &name); + void playSound(const Common::String &name, WaitType waitType = WAIT_RETURN_IMMEDIATELY); void cacheSound(const Common::String &name, int index); void playCachedSound(int index); void clearCache(); + void stopSound(); void playMusic(const Common::String &name); void stopMusic(); diff --git a/engines/sherlock/sprite.cpp b/engines/sherlock/sprite.cpp index c8d9ab55e3..9883d078ae 100644 --- a/engines/sherlock/sprite.cpp +++ b/engines/sherlock/sprite.cpp @@ -46,16 +46,16 @@ void Sprite::load(Common::SeekableReadStream &stream, bool skipPal) { SpriteFrame frame; frame._width = stream.readUint16LE() + 1; frame._height = stream.readUint16LE() + 1; - frame._flags = stream.readUint16LE(); - stream.readUint16LE(); + frame._flags = stream.readByte(); + frame._position.x = stream.readUint16LE(); + frame._position.y = stream.readByte(); - if (skipPal) - frame._flags = 0; + frame._rleEncoded = !skipPal && (frame._position.x == 1); if (frame._flags & 0xFF) { // Nibble packed frame data frame._size = (frame._width * frame._height) / 2; - } else if (frame._flags & RLE_ENCODED) { + } else if (frame._rleEncoded) { // this size includes the header size, which we subtract frame._size = stream.readUint16LE() - 11; frame._rleMarker = stream.readByte(); @@ -78,6 +78,7 @@ void Sprite::load(Common::SeekableReadStream &stream, bool skipPal) { * Gets the palette at the start of the sprite file */ void Sprite::loadPalette(Common::SeekableReadStream &stream) { + // Read in the palette int v1 = stream.readUint16LE() + 1; int v2 = stream.readUint16LE() + 1; int size = v1 * v2; @@ -95,7 +96,7 @@ void Sprite::decompressFrame(SpriteFrame &frame, const byte *src) { if (frame._flags & 0xFF) { debug("TODO: Sprite::decompressFrame() 4-bits/pixel\n"); - } else if (frame._flags & RLE_ENCODED) { + } else if (frame._rleEncoded) { // RLE encoded byte *dst = (byte *)frame._frame.getPixels(); diff --git a/engines/sherlock/sprite.h b/engines/sherlock/sprite.h index 5a510b2548..8aedbdb9c5 100644 --- a/engines/sherlock/sprite.h +++ b/engines/sherlock/sprite.h @@ -30,13 +30,12 @@ namespace Sherlock { -enum { RLE_ENCODED = 0x0100 }; - struct SpriteFrame { uint32 _size; uint16 _width, _height; int _flags; - Common::Point _offset; + bool _rleEncoded; + Common::Point _position; byte _rleMarker; Graphics::Surface _frame; }; -- cgit v1.2.3 From cb874522e4fac3108070d5054977696a58ddb510 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 16 Mar 2015 23:38:58 -0400 Subject: SHERLOCK: Implement screen clipping for sprite drawing --- engines/sherlock/animation.cpp | 22 ++++++++++++---------- engines/sherlock/graphics.cpp | 38 ++++++++++++++++++++++++++++++++++++++ engines/sherlock/graphics.h | 6 ++++++ 3 files changed, 56 insertions(+), 10 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/animation.cpp b/engines/sherlock/animation.cpp index e4ec06b741..581971820d 100644 --- a/engines/sherlock/animation.cpp +++ b/engines/sherlock/animation.cpp @@ -101,7 +101,7 @@ bool Animation::playPrologue(const Common::String &filename, int minDelay, int f events.delay(minDelay); if (fade != 0 && fade != 255) screen.fadeToBlack(); - fade = 0; //***DEBUG**** + if (setPalette) { if (fade != 255) screen.setPalette(sprite._palette); @@ -112,19 +112,26 @@ bool Animation::playPrologue(const Common::String &filename, int minDelay, int f Common::Point pt; bool skipped = false; while (!_vm->shouldQuit()) { + // Get the next sprite to display spriteFrame = stream->readSint16LE(); - if (spriteFrame != -1) { + + if (spriteFrame == -2) { + // End of animation reached + break; + } else if (spriteFrame != -1) { + // Read position from either animation stream or the sprite frame itself if (spriteFrame < 0) { - spriteFrame = ABS(spriteFrame); + spriteFrame += 32769; pt.x = stream->readUint16LE(); pt.y = stream->readUint16LE(); } else { pt = sprite[spriteFrame]._position; } - screen.copyFrom(sprite[spriteFrame]._frame); - events.pollEventsAndWait(); + // Draw the sprite + screen.copyFrom(sprite[spriteFrame]._frame, pt); } else { + // No sprite to show for this animation frame if (fade == 255) { // Gradual fade in if (screen.equalizePalette(sprite._palette) == 0) @@ -144,11 +151,6 @@ bool Animation::playPrologue(const Common::String &filename, int minDelay, int f } events.delay(speed); - - if (stream->readSint16LE() == -2) - // End of animation - break; - stream->seek(-2, SEEK_CUR); } if (events.isKeyPressed()) { diff --git a/engines/sherlock/graphics.cpp b/engines/sherlock/graphics.cpp index f4fe6b6b46..fbfd3b7b45 100644 --- a/engines/sherlock/graphics.cpp +++ b/engines/sherlock/graphics.cpp @@ -35,6 +35,44 @@ Surface::~Surface() { free(); } +/** + * Draws a surface into another + */ +void Surface::copyFrom(const Graphics::Surface &src) { + copyFrom(src, Common::Point()); +} + +/** + * Draws a surface at a given position within this surface + */ +void Surface::copyFrom(const Graphics::Surface &src, const Common::Point &pt) { + Common::Rect drawRect(0, 0, src.w, src.h); + Common::Point destPt = pt; + + if (destPt.x < 0) { + drawRect.left += -destPt.x; + destPt.x = 0; + } + if (destPt.y < 0) { + drawRect.top += -destPt.y; + destPt.y = 0; + } + int right = destPt.x + src.w; + if (right > this->w) { + drawRect.right -= (right - this->w); + } + int bottom = destPt.y + src.h; + if (bottom > this->h) { + drawRect.bottom -= (bottom - this->h); + } + + if (drawRect.isValidRect()) { + addDirtyRect(Common::Rect(destPt.x, destPt.y, destPt.x + drawRect.width(), + destPt.y + drawRect.height())); + copyRectToSurface(src, destPt.x, destPt.y, drawRect); + } +} + void Surface::fillRect(int x1, int y1, int x2, int y2, byte color) { Graphics::Surface::fillRect(Common::Rect(x1, y1, x2, y2), color); } diff --git a/engines/sherlock/graphics.h b/engines/sherlock/graphics.h index c6611db1ce..79cffa839a 100644 --- a/engines/sherlock/graphics.h +++ b/engines/sherlock/graphics.h @@ -36,9 +36,15 @@ namespace Sherlock { class SherlockEngine; class Surface : public Graphics::Surface { +protected: + virtual void addDirtyRect(const Common::Rect &r) {} public: Surface(uint16 width, uint16 height); ~Surface(); + + void copyFrom(const Graphics::Surface &src); + void copyFrom(const Graphics::Surface &src, const Common::Point &pt); + void fillRect(int x1, int y1, int x2, int y2, byte color); void drawSprite(int x, int y, SpriteFrame *spriteFrame, bool flipped = false, bool altFlag = false); }; -- cgit v1.2.3 From 4b5cbc58976c1ed2a58c496aeb5f327352fc38a6 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 16 Mar 2015 23:52:08 -0400 Subject: SHERLOCK: Split Screen class into it's own file --- engines/sherlock/graphics.cpp | 84 --------------------------------- engines/sherlock/graphics.h | 29 ------------ engines/sherlock/module.mk | 1 + engines/sherlock/screen.cpp | 107 ++++++++++++++++++++++++++++++++++++++++++ engines/sherlock/screen.h | 61 ++++++++++++++++++++++++ engines/sherlock/sherlock.h | 2 +- engines/sherlock/sprite.cpp | 2 +- 7 files changed, 171 insertions(+), 115 deletions(-) create mode 100644 engines/sherlock/screen.cpp create mode 100644 engines/sherlock/screen.h (limited to 'engines') diff --git a/engines/sherlock/graphics.cpp b/engines/sherlock/graphics.cpp index fbfd3b7b45..23d3b443e8 100644 --- a/engines/sherlock/graphics.cpp +++ b/engines/sherlock/graphics.cpp @@ -77,88 +77,4 @@ void Surface::fillRect(int x1, int y1, int x2, int y2, byte color) { Graphics::Surface::fillRect(Common::Rect(x1, y1, x2, y2), color); } -void Surface::drawSprite(int x, int y, SpriteFrame *spriteFrame, bool flipped, bool altFlag) { - - -} - -/*----------------------------------------------------------------*/ - -Screen::Screen(SherlockEngine *vm) : Surface(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT), _vm(vm), - _backBuffer1(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT), - _backBuffer2(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT) { - setFont(1); -} - -void Screen::setFont(int fontNumber) { - _fontNumber = fontNumber; - Common::String fname = Common::String::format("FONT%d.VGS", fontNumber); - Common::SeekableReadStream *stream = _vm->_res->load(fname); - - debug("TODO: Loading font %s, size - %d", fname.c_str(), stream->size()); - - delete stream; -} - -void Screen::update() { - g_system->copyRectToScreen(getPixels(), this->w, 0, 0, this->w, this->h); - g_system->updateScreen(); -} - -void Screen::getPalette(byte palette[PALETTE_SIZE]) { - g_system->getPaletteManager()->grabPalette(palette, 0, PALETTE_COUNT); -} - -void Screen::setPalette(const byte palette[PALETTE_SIZE]) { - g_system->getPaletteManager()->setPalette(palette, 0, PALETTE_COUNT); -} - -int Screen::equalizePalette(const byte palette[PALETTE_SIZE]) { - int total = 0; - byte tempPalette[PALETTE_SIZE]; - getPalette(tempPalette); - - // For any palette component that doesn't already match the given destination - // palette, change by 1 towards the reference palette component - for (int idx = 0; idx < PALETTE_SIZE; ++idx) { - if (tempPalette[idx] > palette[idx]) - { - --tempPalette[idx]; - ++total; - } else if (tempPalette[idx] < palette[idx]) { - ++tempPalette[idx]; - ++total; - } - } - - if (total > 0) - // Palette changed, so reload it - setPalette(tempPalette); - - return total; -} - -void Screen::fadeToBlack() { - const int FADE_AMOUNT = 2; - bool repeatFlag; - byte *srcP; - int count; - byte tempPalette[PALETTE_SIZE]; - - getPalette(tempPalette); - do { - repeatFlag = false; - for (srcP = &tempPalette[0], count = 0; count < PALETTE_SIZE; ++count, ++srcP) { - int v = *srcP; - if (v) { - repeatFlag = true; - *srcP = MAX(*srcP - FADE_AMOUNT, 0); - } - } - - setPalette(tempPalette); - _vm->_events->pollEventsAndWait(); - } while (repeatFlag && !_vm->shouldQuit()); -} - } // End of namespace Sherlock diff --git a/engines/sherlock/graphics.h b/engines/sherlock/graphics.h index 79cffa839a..1765cf04ae 100644 --- a/engines/sherlock/graphics.h +++ b/engines/sherlock/graphics.h @@ -26,15 +26,8 @@ #include "common/rect.h" #include "graphics/surface.h" -#include "sherlock/sprite.h" - namespace Sherlock { -#define PALETTE_SIZE 768 -#define PALETTE_COUNT 256 - -class SherlockEngine; - class Surface : public Graphics::Surface { protected: virtual void addDirtyRect(const Common::Rect &r) {} @@ -46,28 +39,6 @@ public: void copyFrom(const Graphics::Surface &src, const Common::Point &pt); void fillRect(int x1, int y1, int x2, int y2, byte color); - void drawSprite(int x, int y, SpriteFrame *spriteFrame, bool flipped = false, bool altFlag = false); -}; - -class Screen : public Surface { -private: - SherlockEngine *_vm; - int _fontNumber; - Surface _backBuffer1, _backBuffer2; -public: - Screen(SherlockEngine *vm); - - void setFont(int fontNumber); - - void update(); - - void getPalette(byte palette[PALETTE_SIZE]); - - void setPalette(const byte palette[PALETTE_SIZE]); - - int equalizePalette(const byte palette[PALETTE_SIZE]); - - void fadeToBlack(); }; } // End of namespace Sherlock diff --git a/engines/sherlock/module.mk b/engines/sherlock/module.mk index 7009f49d3f..06186f1504 100644 --- a/engines/sherlock/module.mk +++ b/engines/sherlock/module.mk @@ -12,6 +12,7 @@ MODULE_OBJS = \ journal.o \ resources.o \ room.o \ + screen.o \ sherlock.o \ sound.o \ sprite.o \ diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp new file mode 100644 index 0000000000..d3fe68e367 --- /dev/null +++ b/engines/sherlock/screen.cpp @@ -0,0 +1,107 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "sherlock/screen.h" +#include "sherlock/sherlock.h" +#include "common/system.h" +#include "graphics/palette.h" + +namespace Sherlock { + +Screen::Screen(SherlockEngine *vm) : Surface(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT), _vm(vm), + _backBuffer1(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT), + _backBuffer2(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT) { + setFont(1); +} + +void Screen::setFont(int fontNumber) { + _fontNumber = fontNumber; + Common::String fname = Common::String::format("FONT%d.VGS", fontNumber); + Common::SeekableReadStream *stream = _vm->_res->load(fname); + + debug("TODO: Loading font %s, size - %d", fname.c_str(), stream->size()); + + delete stream; +} + +void Screen::update() { + g_system->copyRectToScreen(getPixels(), this->w, 0, 0, this->w, this->h); + g_system->updateScreen(); +} + +void Screen::getPalette(byte palette[PALETTE_SIZE]) { + g_system->getPaletteManager()->grabPalette(palette, 0, PALETTE_COUNT); +} + +void Screen::setPalette(const byte palette[PALETTE_SIZE]) { + g_system->getPaletteManager()->setPalette(palette, 0, PALETTE_COUNT); +} + +int Screen::equalizePalette(const byte palette[PALETTE_SIZE]) { + int total = 0; + byte tempPalette[PALETTE_SIZE]; + getPalette(tempPalette); + + // For any palette component that doesn't already match the given destination + // palette, change by 1 towards the reference palette component + for (int idx = 0; idx < PALETTE_SIZE; ++idx) { + if (tempPalette[idx] > palette[idx]) + { + --tempPalette[idx]; + ++total; + } else if (tempPalette[idx] < palette[idx]) { + ++tempPalette[idx]; + ++total; + } + } + + if (total > 0) + // Palette changed, so reload it + setPalette(tempPalette); + + return total; +} + +void Screen::fadeToBlack() { + const int FADE_AMOUNT = 2; + bool repeatFlag; + byte *srcP; + int count; + byte tempPalette[PALETTE_SIZE]; + + getPalette(tempPalette); + do { + repeatFlag = false; + for (srcP = &tempPalette[0], count = 0; count < PALETTE_SIZE; ++count, ++srcP) { + int v = *srcP; + if (v) { + repeatFlag = true; + *srcP = MAX(*srcP - FADE_AMOUNT, 0); + } + } + + setPalette(tempPalette); + _vm->_events->pollEventsAndWait(); + } while (repeatFlag && !_vm->shouldQuit()); +} + +} // End of namespace Sherlock diff --git a/engines/sherlock/screen.h b/engines/sherlock/screen.h new file mode 100644 index 0000000000..3d1ad785e6 --- /dev/null +++ b/engines/sherlock/screen.h @@ -0,0 +1,61 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef SHERLOCK_SCREEN_H +#define SHERLOCK_SCREEN_H + +#include "common/rect.h" +#include "graphics/surface.h" + +#include "sherlock/graphics.h" + +namespace Sherlock { + +#define PALETTE_SIZE 768 +#define PALETTE_COUNT 256 + +class SherlockEngine; + +class Screen : public Surface { +private: + SherlockEngine *_vm; + int _fontNumber; + Surface _backBuffer1, _backBuffer2; +public: + Screen(SherlockEngine *vm); + + void setFont(int fontNumber); + + void update(); + + void getPalette(byte palette[PALETTE_SIZE]); + + void setPalette(const byte palette[PALETTE_SIZE]); + + int equalizePalette(const byte palette[PALETTE_SIZE]); + + void fadeToBlack(); +}; + +} // End of namespace Sherlock + +#endif diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h index b04a14e8ac..8d24a78c81 100644 --- a/engines/sherlock/sherlock.h +++ b/engines/sherlock/sherlock.h @@ -33,10 +33,10 @@ #include "sherlock/animation.h" #include "sherlock/debugger.h" #include "sherlock/events.h" -#include "sherlock/graphics.h" #include "sherlock/journal.h" #include "sherlock/resources.h" #include "sherlock/room.h" +#include "sherlock/screen.h" #include "sherlock/sound.h" #include "sherlock/talk.h" diff --git a/engines/sherlock/sprite.cpp b/engines/sherlock/sprite.cpp index 9883d078ae..ca70932155 100644 --- a/engines/sherlock/sprite.cpp +++ b/engines/sherlock/sprite.cpp @@ -21,7 +21,7 @@ */ #include "sherlock/sprite.h" -#include "sherlock/graphics.h" +#include "sherlock/screen.h" #include "common/debug.h" namespace Sherlock { -- cgit v1.2.3 From 59c124aa609bc872ac00175729728bdd825e6f1d Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 17 Mar 2015 00:01:12 -0400 Subject: SHERLOCK: Add dirty rect handling --- engines/sherlock/screen.cpp | 68 ++++++++++++++++++++++++++++++++++++++++++++- engines/sherlock/screen.h | 8 ++++++ 2 files changed, 75 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp index d3fe68e367..6dcb37c448 100644 --- a/engines/sherlock/screen.cpp +++ b/engines/sherlock/screen.cpp @@ -44,8 +44,21 @@ void Screen::setFont(int fontNumber) { } void Screen::update() { - g_system->copyRectToScreen(getPixels(), this->w, 0, 0, this->w, this->h); + // Merge the dirty rects + mergeDirtyRects(); + + // Loop through copying dirty areas to the physical screen + Common::List::iterator i; + for (i = _dirtyRects.begin(); i != _dirtyRects.end(); ++i) { + const Common::Rect &r = *i; + const byte *srcP = (const byte *)getBasePtr(r.left, r.top); + g_system->copyRectToScreen(srcP, this->pitch, r.left, r.top, + r.width(), r.height()); + } + + // Signal the physical screen to update g_system->updateScreen(); + _dirtyRects.clear(); } void Screen::getPalette(byte palette[PALETTE_SIZE]) { @@ -104,4 +117,57 @@ void Screen::fadeToBlack() { } while (repeatFlag && !_vm->shouldQuit()); } +/** + * Adds a rectangle to the list of modified areas of the screen during the + * current frame + */ +void Screen::addDirtyRect(const Common::Rect &r) { + _dirtyRects.push_back(r); + assert(r.isValidRect() && r.width() > 0 && r.height() > 0); +} + +/** + * Merges together overlapping dirty areas of the screen + */ +void Screen::mergeDirtyRects() { + Common::List::iterator rOuter, rInner; + + // Ensure dirty rect list has at least two entries + rOuter = _dirtyRects.begin(); + for (int i = 0; i < 2; ++i, ++rOuter) { + if (rOuter == _dirtyRects.end()) + return; + } + + // Process the dirty rect list to find any rects to merge + for (rOuter = _dirtyRects.begin(); rOuter != _dirtyRects.end(); ++rOuter) { + rInner = rOuter; + while (++rInner != _dirtyRects.end()) { + + if ((*rOuter).intersects(*rInner)) { + // these two rectangles overlap or + // are next to each other - merge them + + unionRectangle(*rOuter, *rOuter, *rInner); + + // remove the inner rect from the list + _dirtyRects.erase(rInner); + + // move back to beginning of list + rInner = rOuter; + } + } + } +} + +/** + * Returns the union of two dirty area rectangles + */ +bool Screen::unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2) { + destRect = src1; + destRect.extend(src2); + + return !destRect.isEmpty(); +} + } // End of namespace Sherlock diff --git a/engines/sherlock/screen.h b/engines/sherlock/screen.h index 3d1ad785e6..62d3944d04 100644 --- a/engines/sherlock/screen.h +++ b/engines/sherlock/screen.h @@ -23,6 +23,7 @@ #ifndef SHERLOCK_SCREEN_H #define SHERLOCK_SCREEN_H +#include "common/list.h" #include "common/rect.h" #include "graphics/surface.h" @@ -40,6 +41,13 @@ private: SherlockEngine *_vm; int _fontNumber; Surface _backBuffer1, _backBuffer2; + Common::List _dirtyRects; + + void mergeDirtyRects(); + + bool unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2); +protected: + virtual void addDirtyRect(const Common::Rect &r); public: Screen(SherlockEngine *vm); -- cgit v1.2.3 From 51989953b616c97db4d3d433fffee2ab8395606b Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 17 Mar 2015 08:12:19 -0400 Subject: SHERLOCK: Implement transparent sprite drawing --- engines/sherlock/animation.cpp | 2 +- engines/sherlock/graphics.cpp | 54 +++++++++++++++++++++++++++++++++++------- engines/sherlock/graphics.h | 4 ++-- 3 files changed, 49 insertions(+), 11 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/animation.cpp b/engines/sherlock/animation.cpp index 581971820d..0e932b6dd2 100644 --- a/engines/sherlock/animation.cpp +++ b/engines/sherlock/animation.cpp @@ -129,7 +129,7 @@ bool Animation::playPrologue(const Common::String &filename, int minDelay, int f } // Draw the sprite - screen.copyFrom(sprite[spriteFrame]._frame, pt); + screen.transBlitFrom(sprite[spriteFrame]._frame, pt); } else { // No sprite to show for this animation frame if (fade == 255) { diff --git a/engines/sherlock/graphics.cpp b/engines/sherlock/graphics.cpp index 23d3b443e8..2bce822707 100644 --- a/engines/sherlock/graphics.cpp +++ b/engines/sherlock/graphics.cpp @@ -35,17 +35,10 @@ Surface::~Surface() { free(); } -/** - * Draws a surface into another - */ -void Surface::copyFrom(const Graphics::Surface &src) { - copyFrom(src, Common::Point()); -} - /** * Draws a surface at a given position within this surface */ -void Surface::copyFrom(const Graphics::Surface &src, const Common::Point &pt) { +void Surface::blitFrom(const Graphics::Surface &src, const Common::Point &pt) { Common::Rect drawRect(0, 0, src.w, src.h); Common::Point destPt = pt; @@ -73,6 +66,51 @@ void Surface::copyFrom(const Graphics::Surface &src, const Common::Point &pt) { } } + +/** +* Draws a surface at a given position within this surface with transparency +*/ +void Surface::transBlitFrom(const Graphics::Surface &src, const Common::Point &pt) { + Common::Rect drawRect(0, 0, src.w, src.h); + Common::Point destPt = pt; + + if (destPt.x < 0) { + drawRect.left += -destPt.x; + destPt.x = 0; + } + if (destPt.y < 0) { + drawRect.top += -destPt.y; + destPt.y = 0; + } + int right = destPt.x + src.w; + if (right > this->w) { + drawRect.right -= (right - this->w); + } + int bottom = destPt.y + src.h; + if (bottom > this->h) { + drawRect.bottom -= (bottom - this->h); + } + + if (!drawRect.isValidRect()) + return; + + addDirtyRect(Common::Rect(destPt.x, destPt.y, destPt.x + drawRect.width(), + destPt.y + drawRect.height())); + + // Draw loop + const int TRANSPARENCY = 0xFF; + for (int yp = 0; yp < drawRect.height(); ++yp) { + const byte *srcP = (const byte *)src.getBasePtr(drawRect.left, drawRect.top + yp); + byte *destP = (byte *)getBasePtr(destPt.x, destPt.y + yp); + + for (int xp = 0; xp < drawRect.width(); ++xp, ++srcP, ++destP) { + if (*srcP != TRANSPARENCY) + *destP = *srcP; + } + } +} + + void Surface::fillRect(int x1, int y1, int x2, int y2, byte color) { Graphics::Surface::fillRect(Common::Rect(x1, y1, x2, y2), color); } diff --git a/engines/sherlock/graphics.h b/engines/sherlock/graphics.h index 1765cf04ae..983a22a790 100644 --- a/engines/sherlock/graphics.h +++ b/engines/sherlock/graphics.h @@ -35,8 +35,8 @@ public: Surface(uint16 width, uint16 height); ~Surface(); - void copyFrom(const Graphics::Surface &src); - void copyFrom(const Graphics::Surface &src, const Common::Point &pt); + void blitFrom(const Graphics::Surface &src, const Common::Point &pt); + void transBlitFrom(const Graphics::Surface &src, const Common::Point &pt); void fillRect(int x1, int y1, int x2, int y2, byte color); }; -- cgit v1.2.3 From ec4319923452bebade836b43a912de06958315a6 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 17 Mar 2015 08:31:29 -0400 Subject: SHERLOCK: Convert 6-bit palettes to 8-bit VGA palettes --- engines/sherlock/screen.cpp | 4 ++-- engines/sherlock/screen.h | 1 + engines/sherlock/sprite.cpp | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp index 6dcb37c448..500abc1197 100644 --- a/engines/sherlock/screen.cpp +++ b/engines/sherlock/screen.cpp @@ -79,10 +79,10 @@ int Screen::equalizePalette(const byte palette[PALETTE_SIZE]) { for (int idx = 0; idx < PALETTE_SIZE; ++idx) { if (tempPalette[idx] > palette[idx]) { - --tempPalette[idx]; + tempPalette[idx] = MAX((int)palette[idx], (int)tempPalette[idx] - 4); ++total; } else if (tempPalette[idx] < palette[idx]) { - ++tempPalette[idx]; + tempPalette[idx] = MIN((int)palette[idx], (int)tempPalette[idx] + 4); ++total; } } diff --git a/engines/sherlock/screen.h b/engines/sherlock/screen.h index 62d3944d04..d244452771 100644 --- a/engines/sherlock/screen.h +++ b/engines/sherlock/screen.h @@ -33,6 +33,7 @@ namespace Sherlock { #define PALETTE_SIZE 768 #define PALETTE_COUNT 256 +#define VGA_COLOR_TRANS(x) ((x) * 255 / 63) class SherlockEngine; diff --git a/engines/sherlock/sprite.cpp b/engines/sherlock/sprite.cpp index ca70932155..be5a0e0d27 100644 --- a/engines/sherlock/sprite.cpp +++ b/engines/sherlock/sprite.cpp @@ -85,7 +85,8 @@ void Sprite::loadPalette(Common::SeekableReadStream &stream) { assert((size - 12) == PALETTE_SIZE); stream.seek(4 + 12, SEEK_CUR); - stream.read(&_palette[0], PALETTE_SIZE); + for (int idx = 0; idx < PALETTE_SIZE; ++idx) + _palette[idx] = VGA_COLOR_TRANS(stream.readByte()); } /** -- cgit v1.2.3 From 62f3f5d14e391cdac0bbfe200cdde2e4773afba4 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 17 Mar 2015 23:09:04 -0400 Subject: SHERLOCK: Remainder of showCityCutscene implemented --- engines/sherlock/animation.cpp | 7 ++- engines/sherlock/events.cpp | 23 +++++++--- engines/sherlock/events.h | 4 +- engines/sherlock/graphics.cpp | 39 ++++++++++++---- engines/sherlock/graphics.h | 6 ++- engines/sherlock/scalpel/scalpel.cpp | 70 ++++++++++++++++++++++++++--- engines/sherlock/screen.cpp | 87 ++++++++++++++++++++++++++++-------- engines/sherlock/screen.h | 11 ++++- engines/sherlock/sherlock.cpp | 3 +- engines/sherlock/sherlock.h | 8 +++- engines/sherlock/sprite.cpp | 37 +++++++++++---- engines/sherlock/sprite.h | 12 ++++- 12 files changed, 246 insertions(+), 61 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/animation.cpp b/engines/sherlock/animation.cpp index 0e932b6dd2..6788cc51d7 100644 --- a/engines/sherlock/animation.cpp +++ b/engines/sherlock/animation.cpp @@ -95,10 +95,9 @@ bool Animation::playPrologue(const Common::String &filename, int minDelay, int f // Load initial image Common::String vdaName = baseName + ".vda"; - Common::SeekableReadStream *vdaStream = _vm->_res->load(vdaName); - Sprite sprite(*vdaStream, true); + Sprite sprite(vdaName, true); - events.delay(minDelay); + events.wait(minDelay); if (fade != 0 && fade != 255) screen.fadeToBlack(); @@ -150,7 +149,7 @@ bool Animation::playPrologue(const Common::String &filename, int minDelay, int f sound.playSound(fname); } - events.delay(speed); + events.wait(speed); } if (events.isKeyPressed()) { diff --git a/engines/sherlock/events.cpp b/engines/sherlock/events.cpp index 4a51c4a5fb..c6c013193c 100644 --- a/engines/sherlock/events.cpp +++ b/engines/sherlock/events.cpp @@ -158,17 +158,26 @@ void EventsManager::clearEvents() { } /** - * Delay for a given number of cycles, where each cycle is 1/60th of a second + * Delay for a given number of game frames, where each frame is 1/60th of a second */ -void EventsManager::delay(int cycles) { - uint32 totalMilli = cycles * 1000 / GAME_FRAME_RATE; - uint32 delayEnd = g_system->getMillis() + totalMilli; +void EventsManager::wait(int numFrames) { + uint32 totalMilli = numFrames * 1000 / GAME_FRAME_RATE; + delay(totalMilli); +} + +bool EventsManager::delay(uint32 time, bool interruptable) { + uint32 delayEnd = g_system->getMillis() + time; while (!_vm->shouldQuit() && g_system->getMillis() < delayEnd) { - g_system->delayMillis(10); + pollEventsAndWait(); - pollEvents(); + if (interruptable && (isKeyPressed() || _mouseClicked)) { + clearEvents(); + return false; + } } + + return true; } /** @@ -183,7 +192,7 @@ void EventsManager::waitForNextFrame() { uint32 frameCtr = getFrameCounter(); while (!_vm->shouldQuit() && frameCtr == _frameCounter) { - delay(1); + pollEventsAndWait(); mouseClicked |= _mouseClicked; mouseButtons |= _mouseButtons; diff --git a/engines/sherlock/events.h b/engines/sherlock/events.h index f4e6964ef5..4493fcdc65 100644 --- a/engines/sherlock/events.h +++ b/engines/sherlock/events.h @@ -75,7 +75,9 @@ public: void clearEvents(); - void delay(int amount); + void wait(int numFrames); + + bool delay(uint32 time, bool interruptable = false); void waitForNextFrame(); diff --git a/engines/sherlock/graphics.cpp b/engines/sherlock/graphics.cpp index 2bce822707..a4990fb6c6 100644 --- a/engines/sherlock/graphics.cpp +++ b/engines/sherlock/graphics.cpp @@ -35,6 +35,13 @@ Surface::~Surface() { free(); } +/** + * Copy a surface into this one + */ +void Surface::blitFrom(const Graphics::Surface &src) { + blitFrom(src, Common::Point(0, 0)); +} + /** * Draws a surface at a given position within this surface */ @@ -59,18 +66,25 @@ void Surface::blitFrom(const Graphics::Surface &src, const Common::Point &pt) { drawRect.bottom -= (bottom - this->h); } - if (drawRect.isValidRect()) { - addDirtyRect(Common::Rect(destPt.x, destPt.y, destPt.x + drawRect.width(), - destPt.y + drawRect.height())); - copyRectToSurface(src, destPt.x, destPt.y, drawRect); - } + if (drawRect.isValidRect()) + blitFrom(src, destPt, drawRect); } +/** + * Draws a sub-section of a surface at a given position within this surface + */ +void Surface::blitFrom(const Graphics::Surface &src, const Common::Point &pt, + const Common::Rect &srcBounds) { + addDirtyRect(Common::Rect(pt.x, pt.y, pt.x + srcBounds.width(), + pt.y + srcBounds.height())); + copyRectToSurface(src, pt.x, pt.y, srcBounds); +} /** * Draws a surface at a given position within this surface with transparency */ -void Surface::transBlitFrom(const Graphics::Surface &src, const Common::Point &pt) { +void Surface::transBlitFrom(const Graphics::Surface &src, const Common::Point &pt, + bool flipped, int overrideColor) { Common::Rect drawRect(0, 0, src.w, src.h); Common::Point destPt = pt; @@ -94,18 +108,25 @@ void Surface::transBlitFrom(const Graphics::Surface &src, const Common::Point &p if (!drawRect.isValidRect()) return; + if (flipped) + drawRect = Common::Rect(src.w - drawRect.right, src.h - drawRect.bottom, + src.w - drawRect.left, src.h - drawRect.top); + addDirtyRect(Common::Rect(destPt.x, destPt.y, destPt.x + drawRect.width(), destPt.y + drawRect.height())); // Draw loop const int TRANSPARENCY = 0xFF; for (int yp = 0; yp < drawRect.height(); ++yp) { - const byte *srcP = (const byte *)src.getBasePtr(drawRect.left, drawRect.top + yp); + const byte *srcP = (const byte *)src.getBasePtr( + flipped ? drawRect.right : drawRect.left, drawRect.top + yp); byte *destP = (byte *)getBasePtr(destPt.x, destPt.y + yp); - for (int xp = 0; xp < drawRect.width(); ++xp, ++srcP, ++destP) { + for (int xp = 0; xp < drawRect.width(); ++xp, ++destP) { if (*srcP != TRANSPARENCY) - *destP = *srcP; + *destP = overrideColor ? overrideColor : *srcP; + + srcP = flipped ? srcP - 1 : srcP + 1; } } } diff --git a/engines/sherlock/graphics.h b/engines/sherlock/graphics.h index 983a22a790..82c48307d7 100644 --- a/engines/sherlock/graphics.h +++ b/engines/sherlock/graphics.h @@ -35,8 +35,12 @@ public: Surface(uint16 width, uint16 height); ~Surface(); + void blitFrom(const Graphics::Surface &src); void blitFrom(const Graphics::Surface &src, const Common::Point &pt); - void transBlitFrom(const Graphics::Surface &src, const Common::Point &pt); + void blitFrom(const Graphics::Surface &src, const Common::Point &pt, + const Common::Rect &srcBounds); + void transBlitFrom(const Graphics::Surface &src, const Common::Point &pt, + bool flipped = false, int overrideColor = 0); void fillRect(int x1, int y1, int x2, int y2, byte color); }; diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp index 90a93de1b1..0e5a3bec34 100644 --- a/engines/sherlock/scalpel/scalpel.cpp +++ b/engines/sherlock/scalpel/scalpel.cpp @@ -59,15 +59,75 @@ void ScalpelEngine::showOpening() { } bool ScalpelEngine::showCityCutscene() { -// byte palette[PALETTE_SIZE]; + byte palette[PALETTE_SIZE]; _sound->playMusic("prolog1.mus"); _titleOverride = "title.lib"; _soundOverride = "title.snd"; - _animation->playPrologue("26open1", 1, 255, true, 2); - - // TODO - return true; + bool finished = _animation->playPrologue("26open1", 1, 255, true, 2); + + if (finished) { + Sprite titleSprites("title2.vgs", true); + _screen->_backBuffer.blitFrom(*_screen); + _screen->_backBuffer2.blitFrom(*_screen); + + // London, England + _screen->_backBuffer.transBlitFrom(titleSprites[0], Common::Point(10, 11)); + _screen->randomTransition(); + finished = _events->delay(1000, true); + + // November, 1888 + if (finished) { + _screen->_backBuffer.transBlitFrom(titleSprites[1], Common::Point(101, 102)); + _screen->randomTransition(); + finished = _events->delay(5000, true); + } + + // Transition out the title + _screen->_backBuffer.blitFrom(_screen->_backBuffer2); + _screen->randomTransition(); + } + + if (finished) + finished = _animation->playPrologue("26open2", 1, 0, false, 2); + + if (finished) { + Sprite titleSprites("title.vgs", true); + _screen->_backBuffer.blitFrom(*_screen); + _screen->_backBuffer2.blitFrom(*_screen); + + // The Lost Files of + _screen->_backBuffer.transBlitFrom(titleSprites[0], Common::Point(75, 6)); + // Sherlock Holmes + _screen->_backBuffer.transBlitFrom(titleSprites[1], Common::Point(34, 21)); + // copyright + _screen->_backBuffer.transBlitFrom(titleSprites[2], Common::Point(4, 190)); + + _screen->verticalTransition(); + finished = _events->delay(4000, true); + + if (finished) { + _screen->_backBuffer.blitFrom(_screen->_backBuffer2); + _screen->randomTransition(); + finished = _events->delay(2000); + } + + if (finished) { + _screen->getPalette(palette); + _screen->fadeToBlack(2); + } + + if (finished) { + // In the alley... + _screen->transBlitFrom(titleSprites[3], Common::Point(72, 51)); + _screen->fadeIn(palette, 3); + finished = _events->delay(3000, true); + } + } + + _titleOverride = ""; + _soundOverride = ""; + return finished; } bool ScalpelEngine::showAlleyCutscene() { diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp index 500abc1197..41cf19e48c 100644 --- a/engines/sherlock/screen.cpp +++ b/engines/sherlock/screen.cpp @@ -28,7 +28,7 @@ namespace Sherlock { Screen::Screen(SherlockEngine *vm) : Surface(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT), _vm(vm), - _backBuffer1(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT), + _backBuffer(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT), _backBuffer2(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT) { setFont(1); } @@ -94,27 +94,30 @@ int Screen::equalizePalette(const byte palette[PALETTE_SIZE]) { return total; } -void Screen::fadeToBlack() { - const int FADE_AMOUNT = 2; - bool repeatFlag; - byte *srcP; - int count; +/** + * Fade out the palette to black + */ +void Screen::fadeToBlack(int speed) { byte tempPalette[PALETTE_SIZE]; + Common::fill(&tempPalette[0], &tempPalette[PALETTE_SIZE], 0); - getPalette(tempPalette); - do { - repeatFlag = false; - for (srcP = &tempPalette[0], count = 0; count < PALETTE_SIZE; ++count, ++srcP) { - int v = *srcP; - if (v) { - repeatFlag = true; - *srcP = MAX(*srcP - FADE_AMOUNT, 0); - } - } + while (equalizePalette(tempPalette)) { + _vm->_events->delay(15 * speed); + } - setPalette(tempPalette); - _vm->_events->pollEventsAndWait(); - } while (repeatFlag && !_vm->shouldQuit()); + setPalette(tempPalette); +} + +/** + * Fade in a given palette + */ +void Screen::fadeIn(const byte palette[PALETTE_SIZE], int speed) { + int count = 50; + while (equalizePalette(palette) && --count) { + _vm->_events->delay(15 * speed); + } + + setPalette(palette); } /** @@ -170,4 +173,50 @@ bool Screen::unionRectangle(Common::Rect &destRect, const Common::Rect &src1, co return !destRect.isEmpty(); } +/** + * Do a random pixel transition in from _backBuffer surface to the screen + */ +void Screen::randomTransition() { + EventsManager &events = *_vm->_events; + + for (int idx = 0; idx <= 65535; ++idx) { + int offset = _vm->getRandomNumber(this->w * this->h); + *((byte *)getPixels() + offset) = *((const byte *)_backBuffer.getPixels() + offset); + + if (idx != 0 && (idx % 100) == 0) { + _dirtyRects.clear(); + addDirtyRect(Common::Rect(0, 0, this->w, this->h)); + events.delay(5); + } + } + + // Make sure everything has been transferred + blitFrom(_backBuffer); +} + +/** + * Transition to the surface from _backBuffer using a vertical transition + */ +void Screen::verticalTransition() { + EventsManager &events = *_vm->_events; + + byte table[SHERLOCK_SCREEN_WIDTH]; + Common::fill(&table[0], &table[SHERLOCK_SCREEN_WIDTH], 0); + + for (int yp = 0; yp < SHERLOCK_SCREEN_HEIGHT; ++yp) { + for (int xp = 0; xp < SHERLOCK_SCREEN_WIDTH; ++xp) { + int temp = (table[xp] >= 197) ? SHERLOCK_SCREEN_HEIGHT - table[xp] : + _vm->getRandomNumber(3) + 1; + + if (temp) { + blitFrom(_backBuffer, Common::Point(xp, table[xp]), + Common::Rect(xp, table[xp], xp + 1, table[xp] + temp)); + table[xp] += temp; + } + } + + events.delay(10); + } +} + } // End of namespace Sherlock diff --git a/engines/sherlock/screen.h b/engines/sherlock/screen.h index d244452771..0c0175d2ed 100644 --- a/engines/sherlock/screen.h +++ b/engines/sherlock/screen.h @@ -41,7 +41,6 @@ class Screen : public Surface { private: SherlockEngine *_vm; int _fontNumber; - Surface _backBuffer1, _backBuffer2; Common::List _dirtyRects; void mergeDirtyRects(); @@ -49,6 +48,8 @@ private: bool unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2); protected: virtual void addDirtyRect(const Common::Rect &r); +public: + Surface _backBuffer, _backBuffer2; public: Screen(SherlockEngine *vm); @@ -62,7 +63,13 @@ public: int equalizePalette(const byte palette[PALETTE_SIZE]); - void fadeToBlack(); + void fadeToBlack(int speed = 2); + + void fadeIn(const byte palette[PALETTE_SIZE], int speed = 2); + + void randomTransition(); + + void verticalTransition(); }; } // End of namespace Sherlock diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index 1fba746f8d..add24cba9f 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -29,7 +29,7 @@ namespace Sherlock { SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gameDesc) : - Engine(syst), _gameDescription(gameDesc) { + Engine(syst), _gameDescription(gameDesc), _randomSource("Sherlock") { _animation = nullptr; _debugger = nullptr; _events = nullptr; @@ -82,6 +82,7 @@ void SherlockEngine::initialize() { _screen = new Screen(this); _sound = new Sound(this); _talk = new Talk(); + Sprite::setVm(this); } Common::Error SherlockEngine::run() { diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h index 8d24a78c81..cedc57a9f8 100644 --- a/engines/sherlock/sherlock.h +++ b/engines/sherlock/sherlock.h @@ -26,9 +26,10 @@ #include "common/scummsys.h" #include "common/array.h" #include "common/endian.h" -#include "common/util.h" -#include "common/savefile.h" #include "common/hash-str.h" +#include "common/random.h" +#include "common/savefile.h" +#include "common/util.h" #include "engines/engine.h" #include "sherlock/animation.h" #include "sherlock/debugger.h" @@ -79,6 +80,7 @@ public: Screen *_screen; Sound *_sound; Talk *_talk; + Common::RandomSource _randomSource; Common::Array _flags; Common::String _soundOverride; Common::String _titleOverride; @@ -96,6 +98,8 @@ public: Common::Platform getPlatform() const; Common::String getGameFile(int fileType); + + int getRandomNumber(int limit) { return _randomSource.getRandomNumber(limit - 1); } }; } // End of namespace Sherlock diff --git a/engines/sherlock/sprite.cpp b/engines/sherlock/sprite.cpp index be5a0e0d27..8a7bb4cf29 100644 --- a/engines/sherlock/sprite.cpp +++ b/engines/sherlock/sprite.cpp @@ -22,10 +22,26 @@ #include "sherlock/sprite.h" #include "sherlock/screen.h" +#include "sherlock/sherlock.h" #include "common/debug.h" namespace Sherlock { +SherlockEngine *Sprite::_vm; + +void Sprite::setVm(SherlockEngine *vm) { + _vm = vm; +} + +Sprite::Sprite(const Common::String &name, bool skipPal) { + Common::SeekableReadStream *stream = _vm->_res->load(name); + + Common::fill(&_palette[0], &_palette[PALETTE_SIZE], 0); + load(*stream, skipPal); + + delete stream; +} + Sprite::Sprite(Common::SeekableReadStream &stream, bool skipPal) { Common::fill(&_palette[0], &_palette[PALETTE_SIZE], 0); load(stream, skipPal); @@ -39,7 +55,7 @@ Sprite::~Sprite() { /** * Load the data of the sprite */ -void Sprite::load(Common::SeekableReadStream &stream, bool skipPal) { +void Sprite::load(Common::SeekableReadStream &stream, bool skipPalette) { loadPalette(stream); while (stream.pos() < stream.size()) { @@ -50,7 +66,7 @@ void Sprite::load(Common::SeekableReadStream &stream, bool skipPal) { frame._position.x = stream.readUint16LE(); frame._position.y = stream.readByte(); - frame._rleEncoded = !skipPal && (frame._position.x == 1); + frame._rleEncoded = !skipPalette && (frame._position.x == 1); if (frame._flags & 0xFF) { // Nibble packed frame data @@ -78,15 +94,20 @@ void Sprite::load(Common::SeekableReadStream &stream, bool skipPal) { * Gets the palette at the start of the sprite file */ void Sprite::loadPalette(Common::SeekableReadStream &stream) { - // Read in the palette + // Check for palette int v1 = stream.readUint16LE() + 1; int v2 = stream.readUint16LE() + 1; int size = v1 * v2; - assert((size - 12) == PALETTE_SIZE); - - stream.seek(4 + 12, SEEK_CUR); - for (int idx = 0; idx < PALETTE_SIZE; ++idx) - _palette[idx] = VGA_COLOR_TRANS(stream.readByte()); + + if ((size - 12) == PALETTE_SIZE) { + // Found palette, so read it in + stream.seek(4 + 12, SEEK_CUR); + for (int idx = 0; idx < PALETTE_SIZE; ++idx) + _palette[idx] = VGA_COLOR_TRANS(stream.readByte()); + } else { + // Not a palette, so rewind to start of frame data for normal frame processing + stream.seek(-4, SEEK_CUR); + } } /** diff --git a/engines/sherlock/sprite.h b/engines/sherlock/sprite.h index 8aedbdb9c5..844013db43 100644 --- a/engines/sherlock/sprite.h +++ b/engines/sherlock/sprite.h @@ -30,6 +30,8 @@ namespace Sherlock { +class SherlockEngine; + struct SpriteFrame { uint32 _size; uint16 _width, _height; @@ -38,18 +40,24 @@ struct SpriteFrame { Common::Point _position; byte _rleMarker; Graphics::Surface _frame; + + operator Graphics::Surface &() { return _frame; } }; class Sprite: public Common::Array { private: - void load(Common::SeekableReadStream &stream, bool skipPal); + static SherlockEngine *_vm; + + void load(Common::SeekableReadStream &stream, bool skipPalette); void loadPalette(Common::SeekableReadStream &stream); void decompressFrame(SpriteFrame &frame, const byte *src); public: byte _palette[256 * 3]; public: - Sprite(Common::SeekableReadStream &stream, bool skipPal = false); + Sprite(const Common::String &name, bool skipPal = false); + Sprite(Common::SeekableReadStream &stream, bool skipPal = false); ~Sprite(); + static void setVm(SherlockEngine *vm); }; } // End of namespace Sherlock -- cgit v1.2.3 From 9a9f569f3b24ae964506895a0b56a35e1aa2eeaf Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Wed, 18 Mar 2015 23:30:32 +0100 Subject: SCI: debugger / fix diskdump + list commands diskdump: support for audio36+sync36 list: always show tuple for audio36+sync36 --- engines/sci/console.cpp | 244 +++++++++++++++++++++++++++++++++--------------- engines/sci/console.h | 2 + 2 files changed, 172 insertions(+), 74 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index a3abf606d0..3f5548aac7 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -660,10 +660,33 @@ bool Console::cmdRegisters(int argc, const char **argv) { return true; } +bool Console::parseResourceNumber36(const char *userParameter, uint16 &resourceNumber, uint32 &resourceTuple) { + int userParameterLen = strlen(userParameter); + + if (userParameterLen != 10) { + debugPrintf("Audio36/Sync36 resource numbers must be specified as RRRNNVVCCS\n"); + debugPrintf("where RRR is the resource number/map\n"); + debugPrintf(" NN is the noun\n"); + debugPrintf(" VV is the verb\n"); + debugPrintf(" CC is the cond\n"); + debugPrintf(" S is the seq\n"); + return false; + } + + // input: RRRNNVVCCS + resourceNumber = strtol(Common::String(userParameter, 3).c_str(), 0, 36); + uint16 noun = strtol(Common::String(userParameter + 3, 2).c_str(), 0, 36); + uint16 verb = strtol(Common::String(userParameter + 5, 2).c_str(), 0, 36); + uint16 cond = strtol(Common::String(userParameter + 7, 2).c_str(), 0, 36); + uint16 seq = strtol(Common::String(userParameter + 9, 1).c_str(), 0, 36); + resourceTuple = ((noun & 0xff) << 24) | ((verb & 0xff) << 16) | ((cond & 0xff) << 8) | (seq & 0xff); + return true; +} + bool Console::cmdDiskDump(int argc, const char **argv) { - int resNumFrom = 0; - int resNumTo = 0; - int resNumCur = 0; + bool resourceAll = false; + uint16 resourceNumber = 0; + uint32 resourceTuple = 0; if (argc != 3) { debugPrintf("Dumps the specified resource to disk as a patch file\n"); @@ -673,42 +696,90 @@ bool Console::cmdDiskDump(int argc, const char **argv) { return true; } + ResourceType resourceType = parseResourceType(argv[1]); + if (resourceType == kResourceTypeInvalid) { + debugPrintf("Resource type '%s' is not valid\n", argv[1]); + return true; + } + if (strcmp(argv[2], "*") == 0) { - resNumFrom = 0; - resNumTo = 65535; + resourceAll = true; } else { - resNumFrom = atoi(argv[2]); - resNumTo = resNumFrom; + switch (resourceType) { + case kResourceTypeAudio36: + case kResourceTypeSync36: + if (!parseResourceNumber36(argv[2], resourceNumber, resourceTuple)) { + return true; + } + break; + default: + resourceNumber = atoi(argv[2]); + break; + } } - ResourceType res = parseResourceType(argv[1]); - - if (res == kResourceTypeInvalid) + if (resourceType == kResourceTypeInvalid) { debugPrintf("Resource type '%s' is not valid\n", argv[1]); - else { - for (resNumCur = resNumFrom; resNumCur <= resNumTo; resNumCur++) { - Resource *resource = _engine->getResMan()->findResource(ResourceId(res, resNumCur), 0); - if (resource) { - char outFileName[50]; - sprintf(outFileName, "%s.%03d", getResourceTypeName(res), resNumCur); - Common::DumpFile *outFile = new Common::DumpFile(); - outFile->open(outFileName); - resource->writeToStream(outFile); - outFile->finalize(); - outFile->close(); - delete outFile; - debugPrintf("Resource %s.%03d (located in %s) has been dumped to disk\n", argv[1], resNumCur, resource->getResourceLocation().c_str()); - } else { - if (resNumFrom == resNumTo) { - debugPrintf("Resource %s.%03d not found\n", argv[1], resNumCur); - } - } + return true; + } + + if (resourceAll) { + // "*" used, dump everything of that type + Common::List resources = _engine->getResMan()->listResources(resourceType, -1); + Common::sort(resources.begin(), resources.end()); + + Common::List::iterator itr; + for (itr = resources.begin(); itr != resources.end(); ++itr) { + resourceNumber = itr->getNumber(); + resourceTuple = itr->getTuple(); + cmdDiskDumpWorker(resourceType, resourceNumber, resourceTuple); } + } else { + // id was given, dump only this resource + cmdDiskDumpWorker(resourceType, resourceNumber, resourceTuple); } return true; } +void Console::cmdDiskDumpWorker(ResourceType resourceType, int resourceNumber, uint32 resourceTuple) { + const char *resourceTypeName = getResourceTypeName(resourceType); + ResourceId resourceId; + Resource *resource = NULL; + char outFileName[50]; + + switch (resourceType) { + case kResourceTypeAudio36: + case kResourceTypeSync36: { + resourceId = ResourceId(resourceType, resourceNumber, resourceTuple); + resource = _engine->getResMan()->findResource(resourceId, 0); + sprintf(outFileName, "%s", resourceId.toPatchNameBase36().c_str()); + // patch filename is: [type:1 char] [map:3 chars] [noun:2 chars] [verb:2 chars] "." [cond: 2 chars] [seq:1 char] + // e.g. "@5EG0000.014" + break; + } + default: + resourceId = ResourceId(resourceType, resourceNumber); + resource = _engine->getResMan()->findResource(resourceId, 0); + sprintf(outFileName, "%s.%03d", resourceTypeName, resourceNumber); + // patch filename is: [resourcetype].[resourcenumber] + // e.g. "Script.0" + break; + } + + if (resource) { + Common::DumpFile *outFile = new Common::DumpFile(); + outFile->open(outFileName); + resource->writeToStream(outFile); + outFile->finalize(); + outFile->close(); + delete outFile; + debugPrintf("Resource %s (located in %s) has been dumped to disk\n", outFileName, resource->getResourceLocation().c_str()); + } else { + debugPrintf("Resource %s not found\n", outFileName); + } +} + bool Console::cmdHexDump(int argc, const char **argv) { if (argc != 3) { debugPrintf("Dumps the specified resource to standard output\n"); @@ -748,6 +819,77 @@ bool Console::cmdResourceId(int argc, const char **argv) { return true; } +bool Console::cmdList(int argc, const char **argv) { + int selectedMapNumber = -1; + Common::List resources; + Common::List::iterator itr; + int displayCount = 0; + int currentMap = -1; + + if (argc < 2) { + debugPrintf("Lists all the resources of a given type\n"); + cmdResourceTypes(argc, argv); + return true; + } + + ResourceType resourceType = parseResourceType(argv[1]); + if (resourceType == kResourceTypeInvalid) { + debugPrintf("Unknown resource type: '%s'\n", argv[1]); + return true; + } + + switch (resourceType) { + case kResourceTypeAudio36: + case kResourceTypeSync36: + if (argc != 3) { + debugPrintf("Please specify map number (-1: all maps)\n"); + return true; + } + selectedMapNumber = atoi(argv[2]); + resources = _engine->getResMan()->listResources(resourceType, selectedMapNumber); + Common::sort(resources.begin(), resources.end()); + + for (itr = resources.begin(); itr != resources.end(); ++itr) { + const uint16 map = itr->getNumber(); + const uint32 resourceTuple = itr->getTuple(); + const uint16 noun = (resourceTuple >> 24) & 0xff; + const uint16 verb = (resourceTuple >> 16) & 0xff; + const uint16 cond = (resourceTuple >> 8) & 0xff; + const uint16 seq = resourceTuple & 0xff; + + if (currentMap != map) { + if (displayCount % 3) + debugPrintf("\n"); + debugPrintf("Map %04x (%i):\n", map, map); + currentMap = map; + displayCount = 0; + } + + if (displayCount % 3 == 0) + debugPrintf(" "); + + debugPrintf("%02x %02x %02x %02x (%3i %3i %3i %3i) ", noun, verb, cond, seq, noun, verb, cond, seq); + + if (++displayCount % 3 == 0) + debugPrintf("\n"); + } + break; + default: + resources = _engine->getResMan()->listResources(resourceType); + Common::sort(resources.begin(), resources.end()); + + for (itr = resources.begin(); itr != resources.end(); ++itr) { + debugPrintf("%8i", itr->getNumber()); + if (++displayCount % 10 == 0) + debugPrintf("\n"); + } + break; + } + + debugPrintf("\n"); + return true; +} + bool Console::cmdDissectScript(int argc, const char **argv) { if (argc != 2) { debugPrintf("Examines a script\n"); @@ -1124,52 +1266,6 @@ bool Console::cmdMapInstrument(int argc, const char **argv) { return true; } -bool Console::cmdList(int argc, const char **argv) { - if (argc < 2) { - debugPrintf("Lists all the resources of a given type\n"); - cmdResourceTypes(argc, argv); - return true; - } - - - ResourceType res = parseResourceType(argv[1]); - if (res == kResourceTypeInvalid) - debugPrintf("Unknown resource type: '%s'\n", argv[1]); - else { - int number = -1; - - if ((res == kResourceTypeAudio36) || (res == kResourceTypeSync36)) { - if (argc != 3) { - debugPrintf("Please specify map number (-1: all maps)\n"); - return true; - } - number = atoi(argv[2]); - } - - Common::List resources = _engine->getResMan()->listResources(res, number); - Common::sort(resources.begin(), resources.end()); - - int cnt = 0; - Common::List::iterator itr; - for (itr = resources.begin(); itr != resources.end(); ++itr) { - if (number == -1) { - debugPrintf("%8i", itr->getNumber()); - if (++cnt % 10 == 0) - debugPrintf("\n"); - } else if (number == (int)itr->getNumber()) { - const uint32 tuple = itr->getTuple(); - debugPrintf("(%3i, %3i, %3i, %3i) ", (tuple >> 24) & 0xff, (tuple >> 16) & 0xff, - (tuple >> 8) & 0xff, tuple & 0xff); - if (++cnt % 4 == 0) - debugPrintf("\n"); - } - } - debugPrintf("\n"); - } - - return true; -} - bool Console::cmdSaveGame(int argc, const char **argv) { if (argc != 2) { debugPrintf("Saves the current game state to the hard disk\n"); diff --git a/engines/sci/console.h b/engines/sci/console.h index c8e99f78f7..6d024082b5 100644 --- a/engines/sci/console.h +++ b/engines/sci/console.h @@ -68,6 +68,7 @@ private: bool cmdSaid(int argc, const char **argv); // Resources bool cmdDiskDump(int argc, const char **argv); + void cmdDiskDumpWorker(ResourceType resourceType, int resourceNumber, uint32 resourceTuple); bool cmdHexDump(int argc, const char **argv); bool cmdResourceId(int argc, const char **argv); bool cmdResourceInfo(int argc, const char **argv); @@ -157,6 +158,7 @@ private: bool cmdViewAccumulatorObject(int argc, const char **argv); bool parseInteger(const char *argument, int &result); + bool parseResourceNumber36(const char *userParameter, uint16 &resourceNumber, uint32 &resourceTuple); void printBasicVarInfo(reg_t variable); -- cgit v1.2.3 From b8ad1ce140c91257ba79fe50f41da34a5a6e74c2 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 18 Mar 2015 19:02:17 -0400 Subject: SHERLOCK: Make random pixel transitions more like the original --- engines/sherlock/events.cpp | 34 ++++++++++++++++++++++++---------- engines/sherlock/screen.cpp | 19 ++++++++++++++----- engines/sherlock/screen.h | 1 + 3 files changed, 39 insertions(+), 15 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/events.cpp b/engines/sherlock/events.cpp index c6c013193c..b2d9fc65e8 100644 --- a/engines/sherlock/events.cpp +++ b/engines/sherlock/events.cpp @@ -166,18 +166,32 @@ void EventsManager::wait(int numFrames) { } bool EventsManager::delay(uint32 time, bool interruptable) { - uint32 delayEnd = g_system->getMillis() + time; - - while (!_vm->shouldQuit() && g_system->getMillis() < delayEnd) { - pollEventsAndWait(); - - if (interruptable && (isKeyPressed() || _mouseClicked)) { - clearEvents(); - return false; + // Different handling for really short versus extended times + if (time < 10) { + // For really short periods, simply delay by the desired amount + pollEvents(); + g_system->delayMillis(time); + bool result = !(interruptable && (isKeyPressed() || _mouseClicked)); + + clearEvents(); + return result; + } else { + // For long periods go into a loop where we delay by 10ms at a time and then + // check for events. This ensures for longer delays that responsiveness is + // maintained + uint32 delayEnd = g_system->getMillis() + time; + + while (!_vm->shouldQuit() && g_system->getMillis() < delayEnd) { + pollEventsAndWait(); + + if (interruptable && (isKeyPressed() || _mouseClicked)) { + clearEvents(); + return false; + } } - } - return true; + return true; + } } /** diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp index 41cf19e48c..7a4d4863ac 100644 --- a/engines/sherlock/screen.cpp +++ b/engines/sherlock/screen.cpp @@ -30,6 +30,7 @@ namespace Sherlock { Screen::Screen(SherlockEngine *vm) : Surface(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT), _vm(vm), _backBuffer(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT), _backBuffer2(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT) { + _transitionSeed = 1; setFont(1); } @@ -178,15 +179,23 @@ bool Screen::unionRectangle(Common::Rect &destRect, const Common::Rect &src1, co */ void Screen::randomTransition() { EventsManager &events = *_vm->_events; + const int TRANSITION_MULTIPLIER = 0x15a4e35; + _dirtyRects.clear(); for (int idx = 0; idx <= 65535; ++idx) { - int offset = _vm->getRandomNumber(this->w * this->h); - *((byte *)getPixels() + offset) = *((const byte *)_backBuffer.getPixels() + offset); + _transitionSeed = _transitionSeed * TRANSITION_MULTIPLIER + 1; + int offset = _transitionSeed & 65535; + + if (offset < (SHERLOCK_SCREEN_WIDTH * SHERLOCK_SCREEN_HEIGHT)) + *((byte *)getPixels() + offset) = *((const byte *)_backBuffer.getPixels() + offset); if (idx != 0 && (idx % 100) == 0) { - _dirtyRects.clear(); - addDirtyRect(Common::Rect(0, 0, this->w, this->h)); - events.delay(5); + // Ensure there's a full screen dirty rect for the next frame update + if (_dirtyRects.empty()) + addDirtyRect(Common::Rect(0, 0, this->w, this->h)); + + events.pollEvents(); + events.delay(1); } } diff --git a/engines/sherlock/screen.h b/engines/sherlock/screen.h index 0c0175d2ed..78ccffc575 100644 --- a/engines/sherlock/screen.h +++ b/engines/sherlock/screen.h @@ -42,6 +42,7 @@ private: SherlockEngine *_vm; int _fontNumber; Common::List _dirtyRects; + uint32 _transitionSeed; void mergeDirtyRects(); -- cgit v1.2.3 From 4009305070f3f8a1a718526b3e00fc9902a9d87e Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 18 Mar 2015 20:29:50 -0400 Subject: MADS: Hook up ScummVM volume control --- engines/mads/mads.cpp | 7 +++++++ engines/mads/nebular/sound_nebular.cpp | 37 +++++++++++++++++++++------------- engines/mads/nebular/sound_nebular.h | 8 +++++++- engines/mads/sound.cpp | 15 ++++++++++++-- engines/mads/sound.h | 6 ++++++ 5 files changed, 56 insertions(+), 17 deletions(-) (limited to 'engines') diff --git a/engines/mads/mads.cpp b/engines/mads/mads.cpp index 59d600fbfb..374e373035 100644 --- a/engines/mads/mads.cpp +++ b/engines/mads/mads.cpp @@ -126,6 +126,13 @@ void MADSEngine::loadOptions() { if (ConfMan.hasKey("NaughtyMode")) _game->setNaughtyMode(ConfMan.getBool("NaughtyMode")); } + + // Note: MADS is weird in that sfx and music are handled by the same driver, + // and the game scripts themselves check for music being enabled before playing + // a "music" sound. Which means we can independantly mute music in ScummVM, but + // otherwise all sound, music and sfx, is controlled by the SFX volume slider. + int soundVolume = MIN(255, ConfMan.getInt("sfx_volume")); + _sound->setVolume(soundVolume); } void MADSEngine::saveOptions() { diff --git a/engines/mads/nebular/sound_nebular.cpp b/engines/mads/nebular/sound_nebular.cpp index 6412654fd6..9716e6d522 100644 --- a/engines/mads/nebular/sound_nebular.cpp +++ b/engines/mads/nebular/sound_nebular.cpp @@ -44,6 +44,7 @@ AdlibChannel::AdlibChannel() { _field4 = 0; _sampleIndex = 0; _volume = 0; + _volumeOffset = 0; _field7 = 0; _field8 = 0; _field9 = 0; @@ -61,7 +62,6 @@ AdlibChannel::AdlibChannel() { _field19 = 0; _soundData = nullptr; _field1D = 0; - _field1E = 0; _field1F = 0; _field20 = 0; @@ -97,6 +97,7 @@ void AdlibChannel::setPtr2(byte *pData) { void AdlibChannel::load(byte *pData) { _ptr1 = _pSrc = _ptr3 = pData; _ptr4 = _soundData = pData; + _volumeOffset = 0; _fieldA = 0xFF; _activeCount = 1; _fieldD = 64; @@ -104,7 +105,7 @@ void AdlibChannel::load(byte *pData) { _field1F = 0; _field2 = _field3 = 0; _volume = _field7 = 0; - _field1D = _field1E = 0; + _field1D = 0; _fieldE = 0; _field9 = 0; _fieldB = 0; @@ -117,7 +118,7 @@ void AdlibChannel::load(byte *pData) { void AdlibChannel::check(byte *nullPtr) { if (_activeCount && _fieldE) { - if (!_field1E) { + if (!_volumeOffset) { _pSrc = nullPtr; _fieldE = 0; } else { @@ -166,6 +167,7 @@ ASound::ASound(Audio::Mixer *mixer, FM_OPL *opl, const Common::String &filename, _samplePtr = nullptr; _frameCounter = 0; _isDisabled = false; + _masterVolume = 255; _v1 = 0; _v2 = 0; _activeChannelNumber = 0; @@ -540,7 +542,7 @@ void ASound::pollActiveChannel() { chan->_field1 = 0; chan->_field2 = chan->_field3 = 0; chan->_volume = chan->_field7 = 0; - chan->_field1D = chan->_field1E = 0; + chan->_field1D = chan->_volumeOffset = 0; chan->_field8 = 0; chan->_field9 = 0; chan->_fieldB = 0; @@ -615,7 +617,7 @@ void ASound::pollActiveChannel() { if (chan->_fieldE) { chan->_pSrc += 2; } else { - chan->_field1E = *pSrc >> 1; + chan->_volumeOffset = *pSrc >> 1; updateFlag = true; chan->_pSrc += 2; } @@ -659,7 +661,7 @@ void ASound::pollActiveChannel() { if (!--chan->_field9) { chan->_field9 = chan->_fieldA; if (chan->_field2) { - int8 newVal = (int8)chan->_field2 + (int8)chan->_field1E; + int8 newVal = (int8)chan->_field2 + (int8)chan->_volumeOffset; if (newVal < 0) { chan->_field9 = 0; newVal = 0; @@ -668,7 +670,7 @@ void ASound::pollActiveChannel() { newVal = 63; } - chan->_field1E = newVal; + chan->_volumeOffset = newVal; updateFlag = true; } } @@ -755,7 +757,8 @@ static const int outputChannels[] = { void ASound::updateActiveChannel() { int reg = 0x40 + outputChannels[outputIndexes[_activeChannelNumber * 2 + 1]]; int portVal = _ports[reg] & 0xFFC0; - int newVolume = CLIP(_activeChannelPtr->_volume + _activeChannelPtr->_field1E, 0, 63); + int newVolume = CLIP(_activeChannelPtr->_volume + _activeChannelPtr->_volumeOffset, 0, 63); + newVolume = newVolume * _masterVolume / 255; // Note: Original had a whole block not seeming to be used, since the initialisation // sets a variable to 5660h, and doesn't change it, so the branch is never taken @@ -857,6 +860,12 @@ int ASound::readBuffer(int16 *buffer, const int numSamples) { return numSamples; } +void ASound::setVolume(int volume) { + _masterVolume = volume; + if (!volume) + command0(); +} + int ASound::command0() { bool isDisabled = _isDisabled; _isDisabled = true; @@ -1014,22 +1023,22 @@ int ASound1::command10() { int ASound1::command11() { command111213(); - _channels[0]._field1E = 0; - _channels[1]._field1E = 0; + _channels[0]._volumeOffset = 0; + _channels[1]._volumeOffset = 0; return 0; } int ASound1::command12() { command111213(); - _channels[0]._field1E = 40; - _channels[1]._field1E = 0; + _channels[0]._volumeOffset = 40; + _channels[1]._volumeOffset = 0; return 0; } int ASound1::command13() { command111213(); - _channels[0]._field1E = 40; - _channels[1]._field1E = 50; + _channels[0]._volumeOffset = 40; + _channels[1]._volumeOffset = 50; return 0; } diff --git a/engines/mads/nebular/sound_nebular.h b/engines/mads/nebular/sound_nebular.h index cfacb211a4..d2fc552eec 100644 --- a/engines/mads/nebular/sound_nebular.h +++ b/engines/mads/nebular/sound_nebular.h @@ -70,7 +70,7 @@ public: int _field19; byte *_soundData; int _field1D; - int _field1E; + int _volumeOffset; int _field1F; // TODO: Only used by asound.003. Figure out usage @@ -146,6 +146,7 @@ class ASound : public Audio::AudioStream { private: Common::List _dataCache; uint16 _randomSeed; + int _masterVolume; /** * Does the initial Adlib initialisation @@ -382,6 +383,11 @@ public: * Return sample rate */ virtual int getRate() const { return 11025; } + + /** + * Set the volume + */ + void setVolume(int volume); }; class ASound1 : public ASound { diff --git a/engines/mads/sound.cpp b/engines/mads/sound.cpp index 1baa169c55..4036ee8112 100644 --- a/engines/mads/sound.cpp +++ b/engines/mads/sound.cpp @@ -36,6 +36,7 @@ SoundManager::SoundManager(MADSEngine *vm, Audio::Mixer *mixer) { _pollSoundEnabled = false; _soundPollFlag = false; _newSoundsPaused = false; + _masterVolume = 255; _opl = OPL::Config::create(); _opl->init(11025); @@ -97,15 +98,18 @@ void SoundManager::init(int sectionNumber) { break; default: _driver = nullptr; - break; + return; } break; default: warning("SoundManager: Unknown game"); _driver = nullptr; - break; + return; } + + // Set volume for newly loaded driver + _driver->setVolume(_masterVolume); } void SoundManager::closeDriver() { @@ -141,6 +145,13 @@ void SoundManager::startQueuedCommands() { } } +void SoundManager::setVolume(int volume) { + _masterVolume = volume; + + if (_driver) + _driver->setVolume(volume); +} + void SoundManager::command(int commandId, int param) { if (_newSoundsPaused) { if (_queuedCommands.size() < 8) diff --git a/engines/mads/sound.h b/engines/mads/sound.h index 72bb21a812..5884323474 100644 --- a/engines/mads/sound.h +++ b/engines/mads/sound.h @@ -43,6 +43,7 @@ private: bool _soundPollFlag; bool _newSoundsPaused; Common::Queue _queuedCommands; + int _masterVolume; public: SoundManager(MADSEngine *vm, Audio::Mixer *mixer); ~SoundManager(); @@ -78,6 +79,11 @@ public: */ void startQueuedCommands(); + /** + * Set the master volume + */ + void setVolume(int volume); + //@{ /** * Executes a command on the sound driver -- cgit v1.2.3 From 2dc355ff6ecbbc3650beecb341ebe4415de20101 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 18 Mar 2015 22:32:41 -0400 Subject: SHERLOCK: Implement Scalpel-specific scene starting --- engines/sherlock/events.cpp | 24 ++++- engines/sherlock/events.h | 10 +- engines/sherlock/resources.cpp | 57 +++++++---- engines/sherlock/resources.h | 3 + engines/sherlock/room.cpp | 2 +- engines/sherlock/room.h | 3 + engines/sherlock/scalpel/scalpel.cpp | 177 +++++++++++++++++++++++++++++++++++ engines/sherlock/scalpel/scalpel.h | 12 ++- engines/sherlock/screen.cpp | 1 + engines/sherlock/screen.h | 1 + engines/sherlock/sherlock.cpp | 16 +++- engines/sherlock/sherlock.h | 4 + engines/sherlock/sound.cpp | 14 +++ engines/sherlock/sound.h | 4 + 14 files changed, 297 insertions(+), 31 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/events.cpp b/engines/sherlock/events.cpp index b2d9fc65e8..1a882eedea 100644 --- a/engines/sherlock/events.cpp +++ b/engines/sherlock/events.cpp @@ -32,7 +32,8 @@ namespace Sherlock { EventsManager::EventsManager(SherlockEngine *vm) { _vm = vm; - _cursorId = CURSOR_NONE; + _cursorSprites = nullptr; + _cursorIndex = -1; _frameCounter = 1; _priorFrameTime = 0; _mouseClicked = false; @@ -40,15 +41,30 @@ EventsManager::EventsManager(SherlockEngine *vm) { } EventsManager::~EventsManager() { + delete _cursorSprites; +} + +/** + * Load a set of cursors from the specified file + */ +void EventsManager::loadCursors(const Common::String &filename) { + hideCursor(); + delete _cursorSprites; + + _cursorSprites = new Sprite(filename); } /** * Set the cursor to show */ -void EventsManager::setCursor(CursorType cursorId) { - _cursorId = cursorId; +void EventsManager::changeCursor(int cursorIndex) { + _cursorIndex = cursorIndex; + + // Set the cursor data + Graphics::Surface &s = (*_cursorSprites)[cursorIndex]; + CursorMan.replaceCursor(s.getPixels(), s.w, s.h, s.w / 2, s.h / 2, 0xff); - // TODO: Cursor handling + showCursor(); } /** diff --git a/engines/sherlock/events.h b/engines/sherlock/events.h index 4493fcdc65..1f7352eeb5 100644 --- a/engines/sherlock/events.h +++ b/engines/sherlock/events.h @@ -26,11 +26,10 @@ #include "common/scummsys.h" #include "common/events.h" #include "common/stack.h" +#include "sherlock/sprite.h" namespace Sherlock { -enum CursorType { CURSOR_NONE = 0 }; - #define GAME_FRAME_RATE 60 #define GAME_FRAME_TIME (1000 / GAME_FRAME_RATE) @@ -42,10 +41,11 @@ private: uint32 _frameCounter; uint32 _priorFrameTime; Common::Point _mousePos; + Sprite *_cursorSprites; bool checkForNextFrameCounter(); public: - CursorType _cursorId; + int _cursorIndex; byte _mouseButtons; bool _mouseClicked; Common::Stack _pendingKeys; @@ -53,7 +53,9 @@ public: EventsManager(SherlockEngine *vm); ~EventsManager(); - void setCursor(CursorType cursorId); + void loadCursors(const Common::String &filename); + + void changeCursor(int cursorIndex); void showCursor(); diff --git a/engines/sherlock/resources.cpp b/engines/sherlock/resources.cpp index 47e2046084..6636ca5be8 100644 --- a/engines/sherlock/resources.cpp +++ b/engines/sherlock/resources.cpp @@ -41,43 +41,57 @@ bool Cache::isCached(const Common::String &filename) const { * If the file is LZW compressed, automatically decompresses it and loads * the uncompressed version into memory */ -void Cache::load(const Common::String &filename) { +void Cache::load(const Common::String &name) { // First check if the entry already exists - if (_resources.contains(filename)) + if (_resources.contains(name)) return; - // Allocate a new cache entry - _resources[filename] = CacheEntry(); - CacheEntry &cacheEntry = _resources[filename]; - // Open the file for reading Common::File f; - if (!f.open(filename)) - error("Could not read file - %s", filename.c_str()); + if (!f.open(name)) + error("Could not read file - %s", name.c_str()); + + load(name, f); + + f.close(); +} + +/** + * Load a cache entry based on a passed stream + */ +void Cache::load(const Common::String &name, Common::SeekableReadStream &stream) { + // First check if the entry already exists + if (_resources.contains(name)) + return; // Check whether the file is compressed const char LZW_HEADER[5] = { "LZV\x1a" }; char header[5]; - f.read(header, 5); + stream.read(header, 5); bool isCompressed = !strncmp(header, LZW_HEADER, 5); - f.seek(0); + stream.seek(0); + + // Allocate a new cache entry + _resources[name] = CacheEntry(); + CacheEntry &cacheEntry = _resources[name]; if (isCompressed) { // It's compressed, so decompress the file and store it's data in the cache entry - Common::SeekableReadStream *decompressed = decompressLZ(f); + Common::SeekableReadStream *decompressed = decompressLZ(stream); cacheEntry.resize(decompressed->size()); decompressed->read(&cacheEntry[0], decompressed->size()); delete decompressed; } else { // It's not, so read the raw data of the file into the cache entry - cacheEntry.resize(f.size()); - f.read(&cacheEntry[0], f.size()); + cacheEntry.resize(stream.size()); + stream.read(&cacheEntry[0], stream.size()); } - - f.close(); } +/** + * Get a file from the cache + */ Common::SeekableReadStream *Cache::get(const Common::String &filename) const { // Return a memory stream that encapsulates the data const CacheEntry &cacheEntry = _resources[filename]; @@ -96,7 +110,6 @@ Resources::Resources() { addToCache("portrait.lib"); } - /** * Adds the specified file to the cache. If it's a library file, takes care of * loading it's index for future use @@ -113,6 +126,18 @@ void Resources::addToCache(const Common::String &filename) { delete stream; } +/** + * Adds a resource from a library file tot he cache + */ +void Resources::addToCache(const Common::String &filename, const Common::String &libFilename) { + // Get the resource + Common::SeekableReadStream *stream = load(filename, libFilename); + + _cache.load(filename, *stream); + + delete stream; +} + Common::SeekableReadStream *Resources::load(const Common::String &filename) { // First check if the file is directly in the cache if (_cache.isCached(filename)) diff --git a/engines/sherlock/resources.h b/engines/sherlock/resources.h index edb9bd8ba0..cd6e60c325 100644 --- a/engines/sherlock/resources.h +++ b/engines/sherlock/resources.h @@ -57,6 +57,7 @@ public: bool isCached(const Common::String &filename) const; void load(const Common::String &name); + void load(const Common::String &name, Common::SeekableReadStream &stream); Common::SeekableReadStream *get(const Common::String &filename) const; }; @@ -72,6 +73,8 @@ public: Resources(); void addToCache(const Common::String &filename); + void addToCache(const Common::String &filename, const Common::String &libFilename); + bool isInCache(const Common::String &filename) const { return _cache.isCached(filename); } Common::SeekableReadStream *load(const Common::String &filename); diff --git a/engines/sherlock/room.cpp b/engines/sherlock/room.cpp index 9926899953..c06d707b40 100644 --- a/engines/sherlock/room.cpp +++ b/engines/sherlock/room.cpp @@ -27,8 +27,8 @@ namespace Sherlock { Rooms::Rooms() { for (int roomNum = 0; roomNum < ROOMS_COUNT; ++roomNum) Common::fill(&_stats[roomNum][0], &_stats[roomNum][9], false); - _goToRoom = -1; + _oldCharPoint = 0; } } // End of namespace Sherlock diff --git a/engines/sherlock/room.h b/engines/sherlock/room.h index 75800b623a..0f2bc56a45 100644 --- a/engines/sherlock/room.h +++ b/engines/sherlock/room.h @@ -94,6 +94,9 @@ public: bool _stats[ROOMS_COUNT][9]; bool _savedStats[ROOMS_COUNT][9]; int _goToRoom; + Common::Point _bigPos; + Common::Point _overPos; + int _oldCharPoint; public: Rooms(); }; diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp index 0e5a3bec34..d691bbd8bb 100644 --- a/engines/sherlock/scalpel/scalpel.cpp +++ b/engines/sherlock/scalpel/scalpel.cpp @@ -27,6 +27,12 @@ namespace Sherlock { namespace Scalpel { +ScalpelEngine::ScalpelEngine(OSystem *syst, const SherlockGameDescription *gameDesc) : + SherlockEngine(syst, gameDesc) { + _tempFadeStyle = 0; + _chessResult = 0; +} + /** * Game initialization */ @@ -131,17 +137,188 @@ bool ScalpelEngine::showCityCutscene() { } bool ScalpelEngine::showAlleyCutscene() { + // TODO return true; } bool ScalpelEngine::showStreetCutscene() { + // TODO return true; } bool ScalpelEngine::showOfficeCutscene() { + // TODO return true; } +int ScalpelEngine::doChessBoard() { + // TODO + return 0; +} + +void ScalpelEngine::playDarts() { + // TODO +} + +/** + * Starting a scene within the game + */ +void ScalpelEngine::startScene() { + if (_rooms->_goToRoom == 100 || _rooms->_goToRoom == 98) { + // Chessboard selection + if (_sound->_musicEnabled) { + if (_sound->loadSong(100)) { + if (_sound->_music) + _sound->startSong(); + } + } + + _rooms->_goToRoom = doChessBoard(); + + _sound->freeSong(); + _hsavedPos = Common::Point(-1, -1); + _hsavedFs = -1; + } + + // Some rooms are prologue cutscenes, rather than normal game scenes. These are: + // 2: Blackwood's capture + // 52: Rescuing Anna + // 53: Moorehead's death / subway train + // 55: Fade out and exit + // 70: Brumwell suicide + switch (_rooms->_goToRoom) { + case 2: + case 52: + case 53: + case 70: + if (_sound->_musicEnabled && _sound->loadSong(_rooms->_goToRoom)) { + if (_sound->_music) + _sound->startSong(); + } + + switch (_rooms->_goToRoom) { + case 2: + // Blackwood's capture + _res->addToCache("final2.vda", "epilogue.lib"); + _res->addToCache("final2.vdx", "epilogue.lib"); + _animation->playPrologue("final1", 1, 3, true, 4); + _animation->playPrologue("final22", 1, 0, false, 4); + break; + + case 52: + // Rescuing Anna + _res->addToCache("finalr2.vda", "epilogue.lib"); + _res->addToCache("finalr2.vdx", "epilogue.lib"); + _res->addToCache("finale1.vda", "epilogue.lib"); + _res->addToCache("finale1.vdx", "epilogue.lib"); + _res->addToCache("finale2.vda", "epilogue.lib"); + _res->addToCache("finale2.vdx", "epilogue.lib"); + _res->addToCache("finale3.vda", "epilogue.lib"); + _res->addToCache("finale3.vdx", "epilogue.lib"); + _res->addToCache("finale4.vda", "EPILOG2.lib"); + _res->addToCache("finale4.vdx", "EPILOG2.lib"); + + _animation->playPrologue("finalr1", 1, 3, true, 4); + _animation->playPrologue("finalr2", 1, 0, false, 4); + + if (!_res->isInCache("finale2.vda")) { + // Finale file isn't cached + _res->addToCache("finale2.vda", "epilogue.lib"); + _res->addToCache("finale2.vdx", "epilogue.lib"); + _res->addToCache("finale3.vda", "epilogue.lib"); + _res->addToCache("finale3.vdx", "epilogue.lib"); + _res->addToCache("finale4.vda", "EPILOG2.lib"); + _res->addToCache("finale4.vdx", "EPILOG2.lib"); + } + + _animation->playPrologue("finale1", 1, 0, false, 4); + _animation->playPrologue("finale2", 1, 0, false, 4); + _animation->playPrologue("finale3", 1, 0, false, 4); + + _useEpilogue2 = true; + _animation->playPrologue("finale4", 1, 0, false, 4); + _useEpilogue2 = false; + break; + + case 53: + // Moorehead's death / subway train + _res->addToCache("SUBWAY2.vda", "epilogue.lib"); + _res->addToCache("SUBWAY2.vdx", "epilogue.lib"); + _res->addToCache("SUBWAY3.vda", "epilogue.lib"); + _res->addToCache("SUBWAY3.vdx", "epilogue.lib"); + + _animation->playPrologue("SUBWAY1", 1, 3, true, 4); + _animation->playPrologue("SUBWAY2", 1, 0, false, 4); + _animation->playPrologue("SUBWAY3", 1, 0, false, 4); + + // Set fading to direct fade temporary so the transition goes quickly. + _tempFadeStyle = _screen->_fadeStyle ? 257 : 256; + _screen->_fadeStyle = false; + break; + + case 70: + // Brumwell suicide + _animation->playPrologue("suicid", 1, 3, true, 4); + break; + default: + break; + } + + // Except for the Moorehead Murder scene, fade to black first + if (_rooms->_goToRoom != 53) { + _events->wait(40); + _screen->fadeToBlack(3); + } + + switch (_rooms->_goToRoom) { + case 52: + _rooms->_goToRoom = 27; // Go to the Lawyer's Office + _rooms->_bigPos = Common::Point(0, 0); // Overland scroll position + _rooms->_overPos = Common::Point(22900 - 600, 9400 + 900); // Overland position + _rooms->_oldCharPoint = 27; + break; + + case 53: + _rooms->_goToRoom = 17; // Go to St. Pancras Station + _rooms->_bigPos = Common::Point(0, 0); // Overland scroll position + _rooms->_overPos = Common::Point(32500 - 600, 3000 + 900); // Overland position + _rooms->_oldCharPoint = 17; + break; + + default: + _rooms->_goToRoom = 4; // Back to Baker st. + _rooms->_bigPos = Common::Point(0, 0); // Overland scroll position + _rooms->_overPos = Common::Point(14500 - 600, 8400 + 900); // Overland position + _rooms->_oldCharPoint = 4; + break; + } + + // Free any song from the previous scene + _sound->freeSong(); + break; + + case 55: + // Exit game + _screen->fadeToBlack(3); + quitGame(); + return; + + default: + break; + } + + _events->loadCursors("rmouse.vgs"); + _events->changeCursor(0); + + if (_rooms->_goToRoom == 99) { + // Chess Board + playDarts(); + _chessResult = _rooms->_goToRoom = 19; // Go back to the bar + } + + _chessResult = _rooms->_goToRoom; +} + } // End of namespace Scalpel } // End of namespace Scalpel diff --git a/engines/sherlock/scalpel/scalpel.h b/engines/sherlock/scalpel/scalpel.h index 584bd78a20..83510064fa 100644 --- a/engines/sherlock/scalpel/scalpel.h +++ b/engines/sherlock/scalpel/scalpel.h @@ -31,17 +31,25 @@ namespace Scalpel { class ScalpelEngine : public SherlockEngine { private: + int _tempFadeStyle; + int _chessResult; + bool showCityCutscene(); bool showAlleyCutscene(); bool showStreetCutscene(); bool showOfficeCutscene(); + + int doChessBoard(); + + void playDarts(); protected: virtual void initialize(); virtual void showOpening(); + + virtual void startScene(); public: - ScalpelEngine(OSystem *syst, const SherlockGameDescription *gameDesc) : - SherlockEngine(syst, gameDesc) {} + ScalpelEngine(OSystem *syst, const SherlockGameDescription *gameDesc); virtual ~ScalpelEngine() {} }; diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp index 7a4d4863ac..0ec5df9c4c 100644 --- a/engines/sherlock/screen.cpp +++ b/engines/sherlock/screen.cpp @@ -31,6 +31,7 @@ Screen::Screen(SherlockEngine *vm) : Surface(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCR _backBuffer(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT), _backBuffer2(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT) { _transitionSeed = 1; + _fadeStyle = false; setFont(1); } diff --git a/engines/sherlock/screen.h b/engines/sherlock/screen.h index 78ccffc575..05fd80a8b7 100644 --- a/engines/sherlock/screen.h +++ b/engines/sherlock/screen.h @@ -51,6 +51,7 @@ protected: virtual void addDirtyRect(const Common::Rect &r); public: Surface _backBuffer, _backBuffer2; + bool _fadeStyle; public: Screen(SherlockEngine *vm); diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index add24cba9f..907f0a5a16 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -40,9 +40,10 @@ SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gam _sound = nullptr; _talk = nullptr; _useEpilogue2 = false; + _hsavedPos = Common::Point(-1, -1); + _hsavedFs = -1; } - SherlockEngine::~SherlockEngine() { delete _animation; delete _debugger; @@ -73,11 +74,11 @@ void SherlockEngine::initialize() { _midi->setNativeMT32(native_mt32); */ + _res = new Resources(); _animation = new Animation(this); _debugger = new Debugger(this); _events = new EventsManager(this); _journal = new Journal(); - _res = new Resources(); _rooms = new Rooms(); _screen = new Screen(this); _sound = new Sound(this); @@ -90,8 +91,15 @@ Common::Error SherlockEngine::run() { showOpening(); - // TODO: Rest of game - + while (!shouldQuit()) { + // Prepare for scene, and handle any game-specific scenes + startScene(); + + // TODO: Implement game and remove this dummy loop + while (!shouldQuit()) + _events->pollEventsAndWait(); + } + return Common::kNoError; } diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h index cedc57a9f8..7906417d7e 100644 --- a/engines/sherlock/sherlock.h +++ b/engines/sherlock/sherlock.h @@ -69,6 +69,8 @@ protected: virtual void initialize(); virtual void showOpening() = 0; + + virtual void startScene() {} public: const SherlockGameDescription *_gameDescription; Animation *_animation; @@ -85,6 +87,8 @@ public: Common::String _soundOverride; Common::String _titleOverride; bool _useEpilogue2; + Common::Point _hsavedPos; + int _hsavedFs; public: SherlockEngine(OSystem *syst, const SherlockGameDescription *gameDesc); virtual ~SherlockEngine(); diff --git a/engines/sherlock/sound.cpp b/engines/sherlock/sound.cpp index 0957315a35..efc1965637 100644 --- a/engines/sherlock/sound.cpp +++ b/engines/sherlock/sound.cpp @@ -29,6 +29,7 @@ Sound::Sound(SherlockEngine *vm): _vm(vm) { _musicEnabled = true; _voicesEnabled = true; _playingEpilogue = false; + _music = false; } void Sound::playSound(const Common::String &name, WaitType waitType) { @@ -59,5 +60,18 @@ void Sound::stopMusic() { // TODO } +int Sound::loadSong(int songNumber) { + // TODO + return 0; +} + +void Sound::startSong() { + // TODO +} + +void Sound::freeSong() { + // TODO +} + } // End of namespace Sherlock diff --git a/engines/sherlock/sound.h b/engines/sherlock/sound.h index 7775016c94..442e908838 100644 --- a/engines/sherlock/sound.h +++ b/engines/sherlock/sound.h @@ -42,6 +42,7 @@ public: bool _musicEnabled; bool _voicesEnabled; bool _playingEpilogue; + bool _music; public: Sound(SherlockEngine *vm); @@ -50,6 +51,9 @@ public: void playCachedSound(int index); void clearCache(); void stopSound(); + int loadSong(int songNumber); + void startSong(); + void freeSong(); void playMusic(const Common::String &name); void stopMusic(); -- cgit v1.2.3 From 5a7ea9318d54bd725dd2493277dc0daf17f8abb4 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 18 Mar 2015 23:01:47 -0400 Subject: SHERLOCK: Refactor Rooms to Scene, added skeletons for Chess and Darts --- engines/sherlock/debugger.cpp | 2 +- engines/sherlock/module.mk | 4 +- engines/sherlock/room.cpp | 34 ----------- engines/sherlock/room.h | 106 ----------------------------------- engines/sherlock/scalpel/chess.cpp | 37 ++++++++++++ engines/sherlock/scalpel/chess.h | 45 +++++++++++++++ engines/sherlock/scalpel/darts.cpp | 36 ++++++++++++ engines/sherlock/scalpel/darts.h | 45 +++++++++++++++ engines/sherlock/scalpel/scalpel.cpp | 69 ++++++++++++----------- engines/sherlock/scalpel/scalpel.h | 10 ++-- engines/sherlock/scene.cpp | 41 ++++++++++++++ engines/sherlock/scene.h | 55 ++++++++++++++++++ engines/sherlock/sherlock.cpp | 8 ++- engines/sherlock/sherlock.h | 4 +- 14 files changed, 310 insertions(+), 186 deletions(-) delete mode 100644 engines/sherlock/room.cpp delete mode 100644 engines/sherlock/room.h create mode 100644 engines/sherlock/scalpel/chess.cpp create mode 100644 engines/sherlock/scalpel/chess.h create mode 100644 engines/sherlock/scalpel/darts.cpp create mode 100644 engines/sherlock/scalpel/darts.h create mode 100644 engines/sherlock/scene.cpp create mode 100644 engines/sherlock/scene.h (limited to 'engines') diff --git a/engines/sherlock/debugger.cpp b/engines/sherlock/debugger.cpp index 50300322ef..1e0716c3d3 100644 --- a/engines/sherlock/debugger.cpp +++ b/engines/sherlock/debugger.cpp @@ -51,7 +51,7 @@ bool Debugger::cmd_scene(int argc, const char **argv) { debugPrintf("Format: scene \n"); return true; } else { - _vm->_rooms->_goToRoom = strToInt(argv[1]); + _vm->_scene->_goToRoom = strToInt(argv[1]); return false; } } diff --git a/engines/sherlock/module.mk b/engines/sherlock/module.mk index 06186f1504..eef27aa0b1 100644 --- a/engines/sherlock/module.mk +++ b/engines/sherlock/module.mk @@ -1,6 +1,8 @@ MODULE := engines/sherlock MODULE_OBJS = \ + scalpel/chess.o \ + scalpel/darts.o \ scalpel/scalpel.o \ tattoo/tattoo.o \ animation.o \ @@ -11,7 +13,7 @@ MODULE_OBJS = \ graphics.o \ journal.o \ resources.o \ - room.o \ + scene.o \ screen.o \ sherlock.o \ sound.o \ diff --git a/engines/sherlock/room.cpp b/engines/sherlock/room.cpp deleted file mode 100644 index c06d707b40..0000000000 --- a/engines/sherlock/room.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "sherlock/room.h" - -namespace Sherlock { - -Rooms::Rooms() { - for (int roomNum = 0; roomNum < ROOMS_COUNT; ++roomNum) - Common::fill(&_stats[roomNum][0], &_stats[roomNum][9], false); - _goToRoom = -1; - _oldCharPoint = 0; -} - -} // End of namespace Sherlock diff --git a/engines/sherlock/room.h b/engines/sherlock/room.h deleted file mode 100644 index 0f2bc56a45..0000000000 --- a/engines/sherlock/room.h +++ /dev/null @@ -1,106 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#ifndef SHERLOCK_ROOM_H -#define SHERLOCK_ROOM_H - -#include "common/scummsys.h" -#include "sherlock/sprite.h" - -namespace Sherlock { - -#define ROOMS_COUNT 63 - -/* -struct RoomBounds { - int x, y, width, height; -}; - -struct BgshapeSub { - uint16 value; -}; - -struct Bgshape { - char name[12]; - char description[41]; - char *textBufferPtr; - byte *seqBufPtr; - Sprite *sprite; - SpriteFrame *spriteFrame; - byte byte05; - byte seqBigCountFlag; - int16 seqIndex; - int16 canimIndex; - int16 x, y; - int16 xIncr, yIncr, - uint16 status; - int16 x2, y2; - int16 width2, height2; - uint16 word02; - uint16 word03; - byte flag; - byte itemValue; - uint16 word01; - uint16 word05; - uint16 stringIndex; - int16 width, height; - uint16 word04; - byte flagsAndIndex; - uint16 frameCount; - byte spriteFlags; - char string1[50]; - byte byte07; - byte byte01; - byte byte02; - int16 boundsX, boundsY; - byte direction; - byte animIndex; - char string2[50]; - byte byte06; - byte seqByte; - uint16 textBufferOfs; - byte byte03; - uint16 framesCopyCount; - byte byte08; - char string3[51]; - uint16 word06; - uint16 word07; - uint16 word08; - uint16 word09; - BgshapeSub subItems[4]; -}; -*/ -class Rooms { -public: - bool _stats[ROOMS_COUNT][9]; - bool _savedStats[ROOMS_COUNT][9]; - int _goToRoom; - Common::Point _bigPos; - Common::Point _overPos; - int _oldCharPoint; -public: - Rooms(); -}; - -} // End of namespace Sherlock - -#endif diff --git a/engines/sherlock/scalpel/chess.cpp b/engines/sherlock/scalpel/chess.cpp new file mode 100644 index 0000000000..95c662dd01 --- /dev/null +++ b/engines/sherlock/scalpel/chess.cpp @@ -0,0 +1,37 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "sherlock/scalpel/chess.h" +#include "sherlock/scalpel/scalpel.h" + +namespace Sherlock { + +namespace Scalpel { + +int Chess::doChessBoard() { + // TODO + return 0; +} + +} // End of namespace Scalpel + +} // End of namespace Scalpel diff --git a/engines/sherlock/scalpel/chess.h b/engines/sherlock/scalpel/chess.h new file mode 100644 index 0000000000..70607472c2 --- /dev/null +++ b/engines/sherlock/scalpel/chess.h @@ -0,0 +1,45 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef SHERLOCK_CHESS_H +#define SHERLOCK_CHESS_H + +namespace Sherlock { + +namespace Scalpel { + +class ScalpelEngine; + +class Chess { +private: + ScalpelEngine *_vm; +public: + Chess(ScalpelEngine *vm) : _vm(vm) {} + + int doChessBoard(); +}; + +} // End of namespace Scalpel + +} // End of namespace Sherlock + +#endif diff --git a/engines/sherlock/scalpel/darts.cpp b/engines/sherlock/scalpel/darts.cpp new file mode 100644 index 0000000000..857ac63f8c --- /dev/null +++ b/engines/sherlock/scalpel/darts.cpp @@ -0,0 +1,36 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "sherlock/scalpel/darts.h" +#include "sherlock/scalpel/scalpel.h" + +namespace Sherlock { + +namespace Scalpel { + +void Darts::playDarts() { + // TODO +} + +} // End of namespace Scalpel + +} // End of namespace Scalpel diff --git a/engines/sherlock/scalpel/darts.h b/engines/sherlock/scalpel/darts.h new file mode 100644 index 0000000000..22164156c9 --- /dev/null +++ b/engines/sherlock/scalpel/darts.h @@ -0,0 +1,45 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef SHERLOCK_DARTS_H +#define SHERLOCK_DARTS_H + +namespace Sherlock { + +namespace Scalpel { + +class ScalpelEngine; + +class Darts { +private: + ScalpelEngine *_vm; +public: + Darts(ScalpelEngine *vm) : _vm(vm) {} + + void playDarts(); +}; + +} // End of namespace Scalpel + +} // End of namespace Sherlock + +#endif diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp index d691bbd8bb..d5f63b9c0d 100644 --- a/engines/sherlock/scalpel/scalpel.cpp +++ b/engines/sherlock/scalpel/scalpel.cpp @@ -29,22 +29,32 @@ namespace Scalpel { ScalpelEngine::ScalpelEngine(OSystem *syst, const SherlockGameDescription *gameDesc) : SherlockEngine(syst, gameDesc) { + _chess = nullptr; + _darts = nullptr; _tempFadeStyle = 0; _chessResult = 0; } +ScalpelEngine::~ScalpelEngine() { + delete _chess; + delete _darts; +} + /** * Game initialization */ void ScalpelEngine::initialize() { SherlockEngine::initialize(); + _chess = new Chess(this); + _darts = new Darts(this); + _flags.resize(100 * 8); _flags[3] = true; // Turn on Alley _flags[39] = true; // Turn on Baker Street - // Starting room - _rooms->_goToRoom = 4; + // Starting scene + _scene->_goToRoom = 4; } /** @@ -151,20 +161,11 @@ bool ScalpelEngine::showOfficeCutscene() { return true; } -int ScalpelEngine::doChessBoard() { - // TODO - return 0; -} - -void ScalpelEngine::playDarts() { - // TODO -} - /** * Starting a scene within the game */ void ScalpelEngine::startScene() { - if (_rooms->_goToRoom == 100 || _rooms->_goToRoom == 98) { + if (_scene->_goToRoom == 100 || _scene->_goToRoom == 98) { // Chessboard selection if (_sound->_musicEnabled) { if (_sound->loadSong(100)) { @@ -173,7 +174,7 @@ void ScalpelEngine::startScene() { } } - _rooms->_goToRoom = doChessBoard(); + _scene->_goToRoom = _chess->doChessBoard(); _sound->freeSong(); _hsavedPos = Common::Point(-1, -1); @@ -186,17 +187,17 @@ void ScalpelEngine::startScene() { // 53: Moorehead's death / subway train // 55: Fade out and exit // 70: Brumwell suicide - switch (_rooms->_goToRoom) { + switch (_scene->_goToRoom) { case 2: case 52: case 53: case 70: - if (_sound->_musicEnabled && _sound->loadSong(_rooms->_goToRoom)) { + if (_sound->_musicEnabled && _sound->loadSong(_scene->_goToRoom)) { if (_sound->_music) _sound->startSong(); } - switch (_rooms->_goToRoom) { + switch (_scene->_goToRoom) { case 2: // Blackwood's capture _res->addToCache("final2.vda", "epilogue.lib"); @@ -265,31 +266,31 @@ void ScalpelEngine::startScene() { } // Except for the Moorehead Murder scene, fade to black first - if (_rooms->_goToRoom != 53) { + if (_scene->_goToRoom != 53) { _events->wait(40); _screen->fadeToBlack(3); } - switch (_rooms->_goToRoom) { + switch (_scene->_goToRoom) { case 52: - _rooms->_goToRoom = 27; // Go to the Lawyer's Office - _rooms->_bigPos = Common::Point(0, 0); // Overland scroll position - _rooms->_overPos = Common::Point(22900 - 600, 9400 + 900); // Overland position - _rooms->_oldCharPoint = 27; + _scene->_goToRoom = 27; // Go to the Lawyer's Office + _scene->_bigPos = Common::Point(0, 0); // Overland scroll position + _scene->_overPos = Common::Point(22900 - 600, 9400 + 900); // Overland position + _scene->_oldCharPoint = 27; break; case 53: - _rooms->_goToRoom = 17; // Go to St. Pancras Station - _rooms->_bigPos = Common::Point(0, 0); // Overland scroll position - _rooms->_overPos = Common::Point(32500 - 600, 3000 + 900); // Overland position - _rooms->_oldCharPoint = 17; + _scene->_goToRoom = 17; // Go to St. Pancras Station + _scene->_bigPos = Common::Point(0, 0); // Overland scroll position + _scene->_overPos = Common::Point(32500 - 600, 3000 + 900); // Overland position + _scene->_oldCharPoint = 17; break; default: - _rooms->_goToRoom = 4; // Back to Baker st. - _rooms->_bigPos = Common::Point(0, 0); // Overland scroll position - _rooms->_overPos = Common::Point(14500 - 600, 8400 + 900); // Overland position - _rooms->_oldCharPoint = 4; + _scene->_goToRoom = 4; // Back to Baker st. + _scene->_bigPos = Common::Point(0, 0); // Overland scroll position + _scene->_overPos = Common::Point(14500 - 600, 8400 + 900); // Overland position + _scene->_oldCharPoint = 4; break; } @@ -310,13 +311,13 @@ void ScalpelEngine::startScene() { _events->loadCursors("rmouse.vgs"); _events->changeCursor(0); - if (_rooms->_goToRoom == 99) { + if (_scene->_goToRoom == 99) { // Chess Board - playDarts(); - _chessResult = _rooms->_goToRoom = 19; // Go back to the bar + _darts->playDarts(); + _chessResult = _scene->_goToRoom = 19; // Go back to the bar } - _chessResult = _rooms->_goToRoom; + _chessResult = _scene->_goToRoom; } } // End of namespace Scalpel diff --git a/engines/sherlock/scalpel/scalpel.h b/engines/sherlock/scalpel/scalpel.h index 83510064fa..b096599ee1 100644 --- a/engines/sherlock/scalpel/scalpel.h +++ b/engines/sherlock/scalpel/scalpel.h @@ -24,6 +24,8 @@ #define SHERLOCK_SCALPEL_H #include "sherlock/sherlock.h" +#include "sherlock/scalpel/chess.h" +#include "sherlock/scalpel/darts.h" namespace Sherlock { @@ -31,6 +33,8 @@ namespace Scalpel { class ScalpelEngine : public SherlockEngine { private: + Chess *_chess; + Darts *_darts; int _tempFadeStyle; int _chessResult; @@ -38,10 +42,6 @@ private: bool showAlleyCutscene(); bool showStreetCutscene(); bool showOfficeCutscene(); - - int doChessBoard(); - - void playDarts(); protected: virtual void initialize(); @@ -50,7 +50,7 @@ protected: virtual void startScene(); public: ScalpelEngine(OSystem *syst, const SherlockGameDescription *gameDesc); - virtual ~ScalpelEngine() {} + virtual ~ScalpelEngine(); }; } // End of namespace Scalpel diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp new file mode 100644 index 0000000000..de351a5561 --- /dev/null +++ b/engines/sherlock/scene.cpp @@ -0,0 +1,41 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "sherlock/scene.h" + +namespace Sherlock { + +Scene::Scene(SherlockEngine *vm): _vm(vm) { + for (int idx = 0; idx < SCENES_COUNT; ++idx) + Common::fill(&_stats[idx][0], &_stats[idx][9], false); + _goToRoom = -1; + _oldCharPoint = 0; + _numExits = 0; + + _controlSprites = new Sprite("menu.all"); +} + +Scene::~Scene() { + delete _controlSprites; +} + +} // End of namespace Sherlock diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h new file mode 100644 index 0000000000..031245b122 --- /dev/null +++ b/engines/sherlock/scene.h @@ -0,0 +1,55 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef SHERLOCK_SCENE_H +#define SHERLOCK_SCENE_H + +#include "common/scummsys.h" +#include "sherlock/sprite.h" + +namespace Sherlock { + +#define SCENES_COUNT 63 + +class SherlockEngine; + +class Scene { +private: + SherlockEngine *_vm; +public: + bool _stats[SCENES_COUNT][9]; + bool _savedStats[SCENES_COUNT][9]; + int _goToRoom; + Common::Point _bigPos; + Common::Point _overPos; + int _oldCharPoint; + Sprite *_controlSprites; + int _numExits; +public: + Scene(SherlockEngine *vm); + + ~Scene(); +}; + +} // End of namespace Sherlock + +#endif diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index 907f0a5a16..8b597df31b 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -35,7 +35,7 @@ SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gam _events = nullptr; _journal = nullptr; _res = nullptr; - _rooms = nullptr; + _scene = nullptr; _screen = nullptr; _sound = nullptr; _talk = nullptr; @@ -50,7 +50,7 @@ SherlockEngine::~SherlockEngine() { delete _events; delete _journal; delete _res; - delete _rooms; + delete _scene; delete _screen; delete _sound; delete _talk; @@ -79,7 +79,7 @@ void SherlockEngine::initialize() { _debugger = new Debugger(this); _events = new EventsManager(this); _journal = new Journal(); - _rooms = new Rooms(); + _scene = new Scene(this); _screen = new Screen(this); _sound = new Sound(this); _talk = new Talk(); @@ -94,6 +94,8 @@ Common::Error SherlockEngine::run() { while (!shouldQuit()) { // Prepare for scene, and handle any game-specific scenes startScene(); + if (shouldQuit()) + break; // TODO: Implement game and remove this dummy loop while (!shouldQuit()) diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h index 7906417d7e..c6023684b4 100644 --- a/engines/sherlock/sherlock.h +++ b/engines/sherlock/sherlock.h @@ -36,7 +36,7 @@ #include "sherlock/events.h" #include "sherlock/journal.h" #include "sherlock/resources.h" -#include "sherlock/room.h" +#include "sherlock/scene.h" #include "sherlock/screen.h" #include "sherlock/sound.h" #include "sherlock/talk.h" @@ -78,7 +78,7 @@ public: EventsManager *_events; Journal *_journal; Resources *_res; - Rooms *_rooms; + Scene *_scene; Screen *_screen; Sound *_sound; Talk *_talk; -- cgit v1.2.3 From 55a94d8fd4bc79c088ecb191f7e639996c6e5127 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Thu, 19 Mar 2015 20:07:01 +0100 Subject: SCI: added workaround for LSL2/Amiga bug #6818 was bug in script (amiga exclusive) --- engines/sci/engine/workarounds.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines') diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index c5730b5345..ed45e294a2 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -268,6 +268,7 @@ const SciWorkaroundEntry kDirLoop_workarounds[] = { // gameID, room,script,lvl, object-name, method-name, call,index, workaround const SciWorkaroundEntry kDisposeScript_workarounds[] = { { GID_LAURABOW, 777, 777, 0, "myStab", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: after the will is signed, parameter 0 is an object - bug #4967 + { GID_LSL2, -1, 54, 0, "rm54", "dispose", -1, 0, { WORKAROUND_IGNORE, 0 } }, // Amiga: room 55, script tries to kDisposeScript an object (does not happen for DOS) - bug #6818 { GID_QFG1, -1, 64, 0, "rm64", "dispose", -1, 0, { WORKAROUND_IGNORE, 0 } }, // when leaving graveyard, parameter 0 is an object { GID_SQ4, 150, 151, 0, "fightScript", "dispose", -1, 0, { WORKAROUND_IGNORE, 0 } }, // during fight with Vohaul, parameter 0 is an object { GID_SQ4, 150, 152, 0, "driveCloseUp", "dispose", -1, 0, { WORKAROUND_IGNORE, 0 } }, // when choosing "beam download", parameter 0 is an object -- cgit v1.2.3 From e73faeee681a904751db28456a1320b74232ce43 Mon Sep 17 00:00:00 2001 From: sylvaintv Date: Thu, 19 Mar 2015 21:42:08 +0100 Subject: TOON: Add options menu - Add options menu when pressing F1 - Add in-game font change --- engines/toon/anim.cpp | 28 ++-- engines/toon/character.cpp | 5 + engines/toon/font.cpp | 6 +- engines/toon/toon.cpp | 362 ++++++++++++++++++++++++++++++++++++++++++++- engines/toon/toon.h | 4 + 5 files changed, 381 insertions(+), 24 deletions(-) (limited to 'engines') diff --git a/engines/toon/anim.cpp b/engines/toon/anim.cpp index ec23fea186..4788ba61a9 100644 --- a/engines/toon/anim.cpp +++ b/engines/toon/anim.cpp @@ -150,10 +150,12 @@ void Animation::drawFrame(Graphics::Surface &surface, int32 frame, int16 xx, int if (_numFrames == 0) return; + int16 dataFrame = frame; + if (_frames[frame]._ref != -1) - frame = _frames[frame]._ref; + dataFrame = _frames[frame]._ref; - if (!_frames[frame]._data) + if (!_frames[dataFrame]._data) return; int16 rectX = _frames[frame]._x2 - _frames[frame]._x1; @@ -194,7 +196,7 @@ void Animation::drawFrame(Graphics::Surface &surface, int32 frame, int16 xx, int return; int32 destPitch = surface.pitch; - uint8 *srcRow = _frames[frame]._data + offsX + (_frames[frame]._x2 - _frames[frame]._x1) * offsY; + uint8 *srcRow = _frames[dataFrame]._data + offsX + (_frames[frame]._x2 - _frames[frame]._x1) * offsY; uint8 *curRow = (uint8 *)surface.getBasePtr(xx + _x1 + _frames[frame]._x1 + offsX, yy + _frames[frame]._y1 + _y1 + offsY); for (int16 y = 0; y < rectY; y++) { uint8 *cur = curRow; @@ -216,8 +218,12 @@ void Animation::drawFrameWithMask(Graphics::Surface &surface, int32 frame, int16 void Animation::drawFrameWithMaskAndScale(Graphics::Surface &surface, int32 frame, int16 xx, int16 yy, int32 zz, Picture *mask, int32 scale) { debugC(5, kDebugAnim, "drawFrameWithMaskAndScale(surface, %d, %d, %d, %d, mask, %d)", frame, xx, yy, zz, scale); + + int16 dataFrame = frame; + if (_frames[frame]._ref != -1) - frame = _frames[frame]._ref; + dataFrame = _frames[frame]._ref; + int16 rectX = _frames[frame]._x2 - _frames[frame]._x1; int16 rectY = _frames[frame]._y2 - _frames[frame]._y1; @@ -235,7 +241,7 @@ void Animation::drawFrameWithMaskAndScale(Graphics::Surface &surface, int32 fram int32 destPitch = surface.pitch; int32 destPitchMask = mask->getWidth(); - uint8 *c = _frames[frame]._data; + uint8 *c = _frames[dataFrame]._data; uint8 *curRow = (uint8 *)surface.getPixels(); uint8 *curRowMask = mask->getDataPtr(); @@ -287,9 +293,6 @@ int16 Animation::getFrameWidth(int32 frame) { if ((frame < 0) || (frame >= _numFrames)) return 0; - if (_frames[frame]._ref != -1) - frame = _frames[frame]._ref; - return _frames[frame]._x2 - _frames[frame]._x1; } @@ -298,9 +301,6 @@ int16 Animation::getFrameHeight(int32 frame) { if (frame < 0 || frame >= _numFrames) return 0; - if (_frames[frame]._ref != -1) - frame = _frames[frame]._ref; - return _frames[frame]._y2 - _frames[frame]._y1; } @@ -323,8 +323,10 @@ void Animation::drawFontFrame(Graphics::Surface &surface, int32 frame, int16 xx, if (_numFrames == 0) return; + int16 dataFrame = frame; + if (_frames[frame]._ref != -1) - frame = _frames[frame]._ref; + dataFrame = _frames[frame]._ref; int16 rectX = _frames[frame]._x2 - _frames[frame]._x1; int16 rectY = _frames[frame]._y2 - _frames[frame]._y1; @@ -345,7 +347,7 @@ void Animation::drawFontFrame(Graphics::Surface &surface, int32 frame, int16 xx, return; int32 destPitch = surface.pitch; - uint8 *c = _frames[frame]._data; + uint8 *c = _frames[dataFrame]._data; uint8 *curRow = (uint8 *)surface.getBasePtr(xx + _x1 + _frames[frame]._x1, yy + _frames[frame]._y1 + _y1); for (int16 y = 0; y < rectY; y++) { unsigned char *cur = curRow; diff --git a/engines/toon/character.cpp b/engines/toon/character.cpp index 686fe99beb..3d7beeeafe 100644 --- a/engines/toon/character.cpp +++ b/engines/toon/character.cpp @@ -226,6 +226,11 @@ bool Character::walkTo(int16 newPosX, int16 newPosY) { } setFacing(getFacingFromDirection(smoothDx, smoothDy)); + if (_currentWalkStamp != localWalkStamp) { + // another walkTo was started in setFacing, we need to cancel this one. + return false; + } + playWalkAnim(0, 0); } diff --git a/engines/toon/font.cpp b/engines/toon/font.cpp index ab941e5de9..9b08e432fc 100644 --- a/engines/toon/font.cpp +++ b/engines/toon/font.cpp @@ -99,7 +99,7 @@ void FontRenderer::renderText(int16 x, int16 y, const Common::String &origText, } else { curChar = textToFont(curChar); _currentFont->drawFontFrame(_vm->getMainSurface(), curChar, curX, curY, _currentFontColor); - curX = curX + _currentFont->getFrameWidth(curChar) - 1; + curX = curX + MAX(_currentFont->getFrameWidth(curChar) - 2, 0); height = MAX(height, _currentFont->getFrameHeight(curChar)); } text++; @@ -138,8 +138,8 @@ void FontRenderer::computeSize(const Common::String &origText, int16 *retX, int1 // really tell how far it will stick out. For now, // assume we only need to take the lower bound into // consideration. - Common::Rect charRect = _currentFont->getFrameRect(curChar); - lastLineHeight = MAX(lastLineHeight, charRect.bottom); + //Common::Rect charRect = _currentFont->getFrameRect(curChar); + lastLineHeight = MAX(lastLineHeight, _currentFont->getHeight()); } text++; } diff --git a/engines/toon/toon.cpp b/engines/toon/toon.cpp index 2f5051c157..ba455dd08c 100644 --- a/engines/toon/toon.cpp +++ b/engines/toon/toon.cpp @@ -210,6 +210,9 @@ void ToonEngine::parseInput() { if (event.kbd.keycode == Common::KEYCODE_s && !hasModifier) { _audioManager->muteSfx(!_audioManager->isSfxMuted()); } + if (event.kbd.keycode == Common::KEYCODE_F1 && !hasModifier && !_gameState->_inMenu) { + showOptions(); + } if (event.kbd.flags & Common::KBD_ALT) { int slotNum = event.kbd.keycode - (event.kbd.keycode >= Common::KEYCODE_KP0 ? Common::KEYCODE_KP0 : Common::KEYCODE_0); @@ -255,7 +258,7 @@ void ToonEngine::parseInput() { } } - if (!_gameState->_inConversation && !_gameState->_mouseHidden && !_gameState->_inInventory) { + if (!_gameState->_inConversation && !_gameState->_mouseHidden && !_gameState->_inInventory && !_gameState->_inMenu) { selectHotspot(); clickEvent(); } @@ -576,7 +579,29 @@ enum MainMenuMasks { MAINMENUMASK_EVERYWHERE = 3 }; -struct MainMenuFile { +enum OptionMenuSelections { + OPTIONMENUHOTSPOT_NONE = 0, + OPTIONMENUHOTSPOT_PLAY = 1, + OPTIONMENUHOTSPOT_QUIT = 2, + OPTIONMENUHOTSPOT_TEXT = 3, + OPTIONMENUHOTSPOT_TEXTSPEED = 4, + OPTIONMENUHOTSPOT_VOLUMESFX = 5, + OPTIONMENUHOTSPOT_VOLUMESFXSLIDER = 6, + OPTIONMENUHOTSPOT_VOLUMEMUSIC = 7, + OPTIONMENUHOTSPOT_VOLUMEMUSICSLIDER = 8, + OPTIONMENUHOTSPOT_VOLUMEVOICE = 9, + OPTIONMENUHOTSPOT_VOLUMEVOICESLIDER = 10, + OPTIONMENUHOTSPOT_SPEAKERBUTTON = 11, + OPTIONMENUHOTSPOT_SPEAKERLEVER = 12, + OPTIONMENUHOTSPOT_VIDEO_MODE = 13, +}; + +enum OptionMenuMasks { + OPTIONMENUMASK_EVERYWHERE = 1, +}; + + +struct MenuFile { int menuMask; int id; const char *animationFile; @@ -584,7 +609,7 @@ struct MainMenuFile { }; #define MAINMENU_ENTRYCOUNT 12 -static const MainMenuFile mainMenuFiles[] = { +static const MenuFile mainMenuFiles[] = { { MAINMENUMASK_BASE, MAINMENUHOTSPOT_START, "STARTBUT.CAF", 0 }, // "Start" button { MAINMENUMASK_BASE, MAINMENUHOTSPOT_INTRO, "INTROBUT.CAF", 0 }, // "Intro" button { MAINMENUMASK_BASE, MAINMENUHOTSPOT_LOADGAME, "LOADBUT.CAF", 0 }, // "Load Game" button @@ -600,7 +625,38 @@ static const MainMenuFile mainMenuFiles[] = { { MAINMENUMASK_HOTKEYS, MAINMENUHOTSPOT_HOTKEYSCLOSE, "HOTKEYS.CAF", 0 } // Hotkeys display - clicking on it will close hotkeys }; -struct MainMenuEntry { +#define OPTIONMENU_ENTRYCOUNT 27 +static const MenuFile optionMenuFiles[] = { + { OPTIONMENUMASK_EVERYWHERE, OPTIONMENUHOTSPOT_PLAY, "PLAYBUTN.CAF", 0 }, // "Start" button + { OPTIONMENUMASK_EVERYWHERE, OPTIONMENUHOTSPOT_QUIT, "QUITBUTN.CAF", 0 }, // "Intro" button + { OPTIONMENUMASK_EVERYWHERE, OPTIONMENUHOTSPOT_VIDEO_MODE, "VIDMODE.CAF", 0 }, // "Start" button + { OPTIONMENUMASK_EVERYWHERE, OPTIONMENUHOTSPOT_TEXTSPEED, "TXTSPEED.CAF", 0 }, // "Intro" button + { OPTIONMENUMASK_EVERYWHERE, OPTIONMENUHOTSPOT_TEXT, "TEXTDIAL.CAF", 0}, // "Intro" button + { OPTIONMENUMASK_EVERYWHERE, OPTIONMENUHOTSPOT_VOLUMESFX, "SFXBUTN.CAF", 0 }, // "Start" button + { OPTIONMENUMASK_EVERYWHERE, OPTIONMENUHOTSPOT_VOLUMESFXSLIDER, "SFXSLDR.CAF", 0 }, // "Intro" button + { OPTIONMENUMASK_EVERYWHERE, OPTIONMENUHOTSPOT_VOLUMEVOICE, "VOICEBTN.CAF", 0 }, // "Start" button + { OPTIONMENUMASK_EVERYWHERE, OPTIONMENUHOTSPOT_VOLUMEVOICESLIDER, "VOICESLD.CAF", 0 }, // "Intro" button + { OPTIONMENUMASK_EVERYWHERE, OPTIONMENUHOTSPOT_VOLUMEMUSIC, "MUSICBTN.CAF", 0 }, // "Start" button + { OPTIONMENUMASK_EVERYWHERE, OPTIONMENUHOTSPOT_VOLUMEMUSICSLIDER, "MUSICSLD.CAF", 0 }, // "Intro" button + { OPTIONMENUMASK_EVERYWHERE, OPTIONMENUHOTSPOT_SPEAKERBUTTON, "XTRABUTN.CAF", 0 }, // "Start" button + { OPTIONMENUMASK_EVERYWHERE, OPTIONMENUHOTSPOT_SPEAKERLEVER, "XTRALEVR.CAF", 0}, // "Intro" button + { OPTIONMENUMASK_EVERYWHERE, OPTIONMENUHOTSPOT_NONE, "ANTENNAL.CAF", 6 }, // "Start" button + { OPTIONMENUMASK_EVERYWHERE, OPTIONMENUHOTSPOT_NONE, "ANTENNAR.CAF", 6 }, // "Intro" button + { OPTIONMENUMASK_EVERYWHERE, OPTIONMENUHOTSPOT_NONE, "BIGREDL.CAF", 6 }, // "Start" button + { OPTIONMENUMASK_EVERYWHERE, OPTIONMENUHOTSPOT_NONE, "BIGREDR.CAF", 6 }, // "Intro" button + { OPTIONMENUMASK_EVERYWHERE, OPTIONMENUHOTSPOT_NONE, "GRIDLTEL.CAF", 6 }, // "Start" button + { OPTIONMENUMASK_EVERYWHERE, OPTIONMENUHOTSPOT_NONE, "GRIDLTER.CAF", 6 }, // "Intro" button + { OPTIONMENUMASK_EVERYWHERE, OPTIONMENUHOTSPOT_NONE, "LSPEAKR.CAF", 0 }, // "Start" button + { OPTIONMENUMASK_EVERYWHERE, OPTIONMENUHOTSPOT_NONE, "RSPEAKR.CAF", 0 }, // "Intro" button + { OPTIONMENUMASK_EVERYWHERE, OPTIONMENUHOTSPOT_NONE, "STARLITL.CAF", 6 }, // "Start" button + { OPTIONMENUMASK_EVERYWHERE, OPTIONMENUHOTSPOT_NONE, "STARLITR.CAF", 6 }, // "Intro" button + { OPTIONMENUMASK_EVERYWHERE, OPTIONMENUHOTSPOT_NONE, "CHASE1.CAF", 6 }, // "Intro" button + { OPTIONMENUMASK_EVERYWHERE, OPTIONMENUHOTSPOT_NONE, "CHASE2.CAF", 6 }, // "Intro" button + { OPTIONMENUMASK_EVERYWHERE, OPTIONMENUHOTSPOT_NONE, "CHASE3.CAF", 6 }, // "Intro" button + { OPTIONMENUMASK_EVERYWHERE, OPTIONMENUHOTSPOT_NONE, "CHASE4.CAF", 6 } // "Intro" button +}; + +struct MenuEntry { int menuMask; int id; Animation *animation; @@ -608,15 +664,291 @@ struct MainMenuEntry { int animateOnFrame; int animateCurFrame; int activeFrame; + bool playOnce; }; +bool ToonEngine::showOptions() { + + storePalette(); + fadeOut(5); + Picture* optionPicture = new Picture(this); + optionPicture->loadPicture("OPTIONS.CPS"); + optionPicture->setupPalette(); + flushPalette(true); + + int16 oldScrollValue = _gameState->_currentScrollValue; + _gameState->_currentScrollValue = 0; + + bool oldMouseHidden = _gameState->_mouseHidden; + _gameState->_mouseHidden = false; + + MenuEntry entries[OPTIONMENU_ENTRYCOUNT]; + + for (int entryNr = 0; entryNr < OPTIONMENU_ENTRYCOUNT; entryNr++) { + entries[entryNr].menuMask = optionMenuFiles[entryNr].menuMask; + entries[entryNr].id = optionMenuFiles[entryNr].id; + entries[entryNr].animation = new Animation(this); + entries[entryNr].animation->loadAnimation(optionMenuFiles[entryNr].animationFile); + if (entries[entryNr].id != OPTIONMENUHOTSPOT_NONE) + entries[entryNr].rect = entries[entryNr].animation->getRect(); + entries[entryNr].animateOnFrame = optionMenuFiles[entryNr].animateOnFrame; + entries[entryNr].animateCurFrame = 0; + entries[entryNr].activeFrame = 0; + entries[entryNr].playOnce = false; + } + + entries[10].activeFrame = _audioManager->_mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType) * (entries[10].animation->_numFrames - 1) / 256; + entries[8].activeFrame = _audioManager->_mixer->getVolumeForSoundType(Audio::Mixer::kSpeechSoundType) * (entries[8].animation->_numFrames - 1) / 256; + entries[6].activeFrame = _audioManager->_mixer->getVolumeForSoundType(Audio::Mixer::kSFXSoundType) * (entries[6].animation->_numFrames - 1) / 256; + + entries[9].activeFrame = _audioManager->isMusicMuted() ? 0 : 3; + entries[7].activeFrame = _audioManager->isVoiceMuted() ? 0 : 3; + entries[5].activeFrame = _audioManager->isSfxMuted() ? 0 : 3; + + entries[2].activeFrame = entries[2].animation->_numFrames - 1; + + if (!_showConversationText) { + entries[4].activeFrame = 4; + } else if (_useAlternativeFont) { + entries[4].activeFrame = 8; + } else { + entries[4].activeFrame = 0; + } + + setCursor(0); + + int menuMask = OPTIONMENUMASK_EVERYWHERE; + int ratioX = 0; + bool doExit = false; + bool exitGame = false; + _gameState->_inMenu = true; + dirtyAllScreen(); + _firstFrame = true; + + while (!doExit) { + + int clickingOn = OPTIONMENUHOTSPOT_NONE; + int clickingOnSprite = 0; + int clickRelease = false; + + while (!clickRelease) { + + if (_dirtyAll) { + optionPicture->draw(*_mainSurface, 0, 0, 0, 0); + addDirtyRect(0, 0, TOON_SCREEN_WIDTH, TOON_SCREEN_HEIGHT); + } else { + optionPicture->drawWithRectList(*_mainSurface, 0, 0, 0, 0, _dirtyRects); + } + clearDirtyRects(); + + for (int entryNr = 0; entryNr < OPTIONMENU_ENTRYCOUNT; entryNr++) { + if (entries[entryNr].menuMask & menuMask) { + if (entries[entryNr].animateOnFrame) { + entries[entryNr].animateCurFrame++; + if (entries[entryNr].animateOnFrame <= entries[entryNr].animateCurFrame) { + entries[entryNr].activeFrame++; + if (entries[entryNr].activeFrame >= entries[entryNr].animation->_numFrames) { + entries[entryNr].activeFrame = 0; + if (entries[entryNr].playOnce) { + entries[entryNr].animateOnFrame = 0; + entries[entryNr].playOnce = false; + } + if (entryNr == 20 && entries[entryNr].animateOnFrame > 0) { + playSFX(-3, 128); + } + } + entries[entryNr].animateCurFrame = 0; + } + } + int32 frameNr = entries[entryNr].activeFrame; + entries[entryNr].animation->drawFrame(*_mainSurface, frameNr, 0, 0); + } + } + + parseInput(); + + copyToVirtualScreen(true); + if (_firstFrame) { + _firstFrame = false; + fadeIn(5); + } + _system->delayMillis(17); + + if (_mouseButton & 1) { + // left mouse button pushed down + clickingOn = OPTIONMENUHOTSPOT_NONE; + for (int entryNr = 0; entryNr < OPTIONMENU_ENTRYCOUNT; entryNr++) { + if (entries[entryNr].menuMask & menuMask) { + if (entries[entryNr].id != OPTIONMENUHOTSPOT_NONE) { + if (entries[entryNr].rect.contains(_mouseX, _mouseY)) { + clickingOn = entries[entryNr].id; + clickingOnSprite = entryNr; + ratioX = (_mouseX - entries[entryNr].rect.left) * 256 / entries[entryNr].rect.width(); + } + } + } + } + } else { + // left mouse button released/not pushed down + if (clickingOn != OPTIONMENUHOTSPOT_NONE) + clickRelease = true; + } + + // handle sliders + if (clickingOn == OPTIONMENUHOTSPOT_VOLUMEMUSICSLIDER) { + entries[clickingOnSprite].activeFrame = ratioX * (entries[clickingOnSprite].animation->_numFrames) / 256; + int vol = entries[clickingOnSprite].activeFrame * 256 / entries[clickingOnSprite].animation->_numFrames; + _audioManager->_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, vol); + } + + if (clickingOn == OPTIONMENUHOTSPOT_VOLUMEVOICESLIDER) { + entries[clickingOnSprite].activeFrame = ratioX * (entries[clickingOnSprite].animation->_numFrames) / 256; + int vol = entries[clickingOnSprite].activeFrame * 256 / entries[clickingOnSprite].animation->_numFrames; + _audioManager->_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, vol); + } + + if (clickingOn == OPTIONMENUHOTSPOT_VOLUMESFXSLIDER) { + entries[clickingOnSprite].activeFrame = ratioX * (entries[clickingOnSprite].animation->_numFrames) / 256; + int vol = entries[clickingOnSprite].activeFrame * 256 / entries[clickingOnSprite].animation->_numFrames; + _audioManager->_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, vol); + } + + if (clickingOn == OPTIONMENUHOTSPOT_TEXTSPEED) { + entries[clickingOnSprite].activeFrame = ratioX * (entries[clickingOnSprite].animation->_numFrames) / 256; + } + + if (clickingOn == OPTIONMENUHOTSPOT_PLAY) { + entries[0].activeFrame = entries[0].animation->_numFrames - 1; + } else { + entries[0].activeFrame = 0; + } + + if (clickingOn == OPTIONMENUHOTSPOT_QUIT) { + entries[1].activeFrame = entries[1].animation->_numFrames - 1; + } else { + entries[1].activeFrame = 0; + } + + if (_shouldQuit) { + clickingOn = OPTIONMENUHOTSPOT_NONE; + clickRelease = true; + doExit = true; + } + } + + if (clickingOn == OPTIONMENUHOTSPOT_VOLUMEMUSIC) { + if (entries[9].activeFrame == 0) { + entries[9].activeFrame = 3; + _audioManager->muteMusic(false); + } else { + entries[9].activeFrame = 0; + _audioManager->muteMusic(true); + } + playSFX(-7, 128); + } + + if (clickingOn == OPTIONMENUHOTSPOT_VOLUMEVOICE) { + if (entries[7].activeFrame == 0) { + entries[7].activeFrame = 3; + _audioManager->muteVoice(false); + } else { + entries[7].activeFrame = 0; + _audioManager->muteVoice(true); + } + playSFX(-7, 128); + } + + if (clickingOn == OPTIONMENUHOTSPOT_VOLUMESFX) { + if (entries[5].activeFrame == 0) { + entries[5].activeFrame = 3; + _audioManager->muteSfx(false); + } else { + entries[5].activeFrame = 0; + _audioManager->muteSfx(true); + } + playSFX(-7, 128); + } + + if (clickingOn == OPTIONMENUHOTSPOT_SPEAKERBUTTON) { + entries[11].animateOnFrame = 4; + entries[11].playOnce = true; + + entries[19].animateOnFrame = 4; + entries[19].playOnce = true; + + playSFX(-10, 128); + _audioManager->playVoice(316, true); + } + + if (clickingOn == OPTIONMENUHOTSPOT_SPEAKERLEVER) { + + entries[12].activeFrame = 1 - entries[12].activeFrame; + if(entries[12].activeFrame == 1) { + entries[20].animateOnFrame = 4; + entries[20].playOnce = false; + playSFX(-3, 128); + } else { + entries[20].playOnce = true; + } + playSFX(-9, 128); + } + + if (clickingOn == OPTIONMENUHOTSPOT_TEXT) { + + if (entries[4].activeFrame == 0) { + _showConversationText = false; + entries[4].activeFrame = 4; + } else if (entries[4].activeFrame == 4) { + _showConversationText = true; + setFont(true); + entries[4].activeFrame = 8; + } else if(entries[4].activeFrame == 8) { + _showConversationText = true; + setFont(false); + entries[4].activeFrame = 0; + } + + playSFX(-9, 128); + } + + // don't allow change to video mode + if (clickingOn == OPTIONMENUHOTSPOT_VIDEO_MODE) { + playSoundWrong(); + } + + if (clickingOn == OPTIONMENUHOTSPOT_PLAY) { + doExit = true; + exitGame = false; + _audioManager->playSFX(10, 128, true); + } + + if (clickingOn == OPTIONMENUHOTSPOT_QUIT) { + doExit = true; + exitGame = true; + _shouldQuit = true; + _audioManager->playSFX(10, 128, true); + } + } + + fadeOut(5); + _gameState->_mouseHidden = oldMouseHidden; + _gameState->_inMenu = false; + _firstFrame = true; + _gameState->_currentScrollValue = oldScrollValue; + + restorePalette(); + dirtyAllScreen(); + + return exitGame; +} + bool ToonEngine::showMainmenu(bool &loadedGame) { Picture *mainmenuPicture = new Picture(this); mainmenuPicture->loadPicture("TITLESCR.CPS"); mainmenuPicture->setupPalette(); flushPalette(false); - MainMenuEntry entries[MAINMENU_ENTRYCOUNT]; + MenuEntry entries[MAINMENU_ENTRYCOUNT]; for (int entryNr = 0; entryNr < MAINMENU_ENTRYCOUNT; entryNr++) { entries[entryNr].menuMask = mainMenuFiles[entryNr].menuMask; @@ -630,7 +962,7 @@ bool ToonEngine::showMainmenu(bool &loadedGame) { entries[entryNr].activeFrame = 0; } - setCursor(1); + setCursor(0); bool doExit = false; bool exitGame = false; @@ -822,6 +1154,7 @@ ToonEngine::ToonEngine(OSystem *syst, const ADGameDescription *gameDescription) _inventoryPicture = NULL; _currentMask = NULL; _showConversationText = true; + _useAlternativeFont = false; _isDemo = _gameDescription->flags & ADGF_DEMO; DebugMan.addDebugChannel(kDebugAnim, "Anim", "Animation debug level"); @@ -1853,6 +2186,17 @@ void ToonEngine::initFonts() { _fontEZ = new Animation(this); _fontEZ->loadAnimation("EZFONT.CAF"); + + setFont(false); +} + +void ToonEngine::setFont(bool alternative) { + if (alternative) { + _currentFont = _fontEZ; + } else { + _currentFont = _fontToon; + } + _useAlternativeFont = alternative; } void ToonEngine::drawInfoLine() { @@ -1870,7 +2214,7 @@ void ToonEngine::drawInfoLine() { } if (infoTool) { _fontRenderer->setFontColor(0xc8, 0xdd, 0xe3); - _fontRenderer->setFont(_fontToon); + _fontRenderer->setFont(_currentFont); _fontRenderer->renderText(320 + _gameState->_currentScrollValue, 398, infoTool, 5); } } @@ -1998,6 +2342,8 @@ int32 ToonEngine::simpleCharacterTalk(int32 dialogid) { _audioManager->playVoice(myId, false); } else { myId = _genericTexts->getId(dialogid - 1000); + if (myId == -1) + return 0; _audioManager->playVoice(myId, true); } @@ -2936,7 +3282,7 @@ Character *ToonEngine::getCharacterById(int32 charId) { void ToonEngine::drawConversationLine() { if (_currentTextLine && _showConversationText) { _fontRenderer->setFontColorByCharacter(_currentTextLineCharacterId); - _fontRenderer->setFont(_fontToon); + _fontRenderer->setFont(_currentFont); _fontRenderer->renderMultiLineText(_currentTextLineX, _currentTextLineY, _currentTextLine, 0); } } diff --git a/engines/toon/toon.h b/engines/toon/toon.h index 6903e5de57..f419d491c6 100644 --- a/engines/toon/toon.h +++ b/engines/toon/toon.h @@ -111,6 +111,7 @@ public: Common::Error run(); GUI::Debugger *getDebugger() { return _console; } bool showMainmenu(bool &loadedGame); + bool showOptions(); void init(); bool loadToonDat(); char **loadTextsVariants(Common::File &in); @@ -122,6 +123,7 @@ public: void parseInput(); void initChapter(); void initFonts(); + void setFont(bool alternative); void loadScene(int32 SceneId, bool forGameLoad = false); void exitScene(); void loadCursor(); @@ -421,6 +423,7 @@ protected: FontRenderer *_fontRenderer; Animation *_fontToon; Animation *_fontEZ; + Animation *_currentFont; AudioManager *_audioManager; @@ -431,6 +434,7 @@ protected: bool _firstFrame; bool _isDemo; bool _showConversationText; + bool _useAlternativeFont; bool _needPaletteFlush; private: ToonConsole *_console; -- cgit v1.2.3 From 15a4371b2d651a382cf077b1e1edef0b21c48685 Mon Sep 17 00:00:00 2001 From: sylvaintv Date: Thu, 19 Mar 2015 22:40:29 +0100 Subject: TOON: Fix bad enum syntax --- engines/toon/toon.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/toon/toon.cpp b/engines/toon/toon.cpp index ba455dd08c..09f865f798 100644 --- a/engines/toon/toon.cpp +++ b/engines/toon/toon.cpp @@ -593,11 +593,11 @@ enum OptionMenuSelections { OPTIONMENUHOTSPOT_VOLUMEVOICESLIDER = 10, OPTIONMENUHOTSPOT_SPEAKERBUTTON = 11, OPTIONMENUHOTSPOT_SPEAKERLEVER = 12, - OPTIONMENUHOTSPOT_VIDEO_MODE = 13, + OPTIONMENUHOTSPOT_VIDEO_MODE = 13 }; enum OptionMenuMasks { - OPTIONMENUMASK_EVERYWHERE = 1, + OPTIONMENUMASK_EVERYWHERE = 1 }; -- cgit v1.2.3 From a02461fcb15da3b2e7e91d9cfb1bca559a1d277b Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 19 Mar 2015 19:49:42 -0400 Subject: SHERLOCK: Refactorings, new Sprite and People classes --- engines/sherlock/animation.cpp | 23 +++--- engines/sherlock/events.cpp | 10 +-- engines/sherlock/events.h | 4 +- engines/sherlock/module.mk | 3 +- engines/sherlock/people.cpp | 73 +++++++++++++++++ engines/sherlock/people.h | 57 ++++++++++++++ engines/sherlock/resources.cpp | 121 ++++++++++++++++++++++++++++ engines/sherlock/resources.h | 29 +++++++ engines/sherlock/scalpel/scalpel.cpp | 16 ++-- engines/sherlock/scene.cpp | 19 ++++- engines/sherlock/scene.h | 13 +++- engines/sherlock/sherlock.cpp | 5 +- engines/sherlock/sherlock.h | 2 + engines/sherlock/sprite.cpp | 147 ----------------------------------- engines/sherlock/sprite.h | 65 ---------------- engines/sherlock/sprites.cpp | 27 +++++++ engines/sherlock/sprites.h | 83 ++++++++++++++++++++ 17 files changed, 451 insertions(+), 246 deletions(-) create mode 100644 engines/sherlock/people.cpp create mode 100644 engines/sherlock/people.h delete mode 100644 engines/sherlock/sprite.cpp delete mode 100644 engines/sherlock/sprite.h create mode 100644 engines/sherlock/sprites.cpp create mode 100644 engines/sherlock/sprites.h (limited to 'engines') diff --git a/engines/sherlock/animation.cpp b/engines/sherlock/animation.cpp index 6788cc51d7..2b12005079 100644 --- a/engines/sherlock/animation.cpp +++ b/engines/sherlock/animation.cpp @@ -22,7 +22,6 @@ #include "sherlock/animation.h" #include "sherlock/sherlock.h" -#include "sherlock/sprite.h" #include "common/algorithm.h" namespace Sherlock { @@ -95,7 +94,7 @@ bool Animation::playPrologue(const Common::String &filename, int minDelay, int f // Load initial image Common::String vdaName = baseName + ".vda"; - Sprite sprite(vdaName, true); + ImageFile images(vdaName, true); events.wait(minDelay); if (fade != 0 && fade != 255) @@ -103,37 +102,37 @@ bool Animation::playPrologue(const Common::String &filename, int minDelay, int f if (setPalette) { if (fade != 255) - screen.setPalette(sprite._palette); + screen.setPalette(images._palette); } int frameNumber = 0; - int spriteFrame; + int imageFrame; Common::Point pt; bool skipped = false; while (!_vm->shouldQuit()) { // Get the next sprite to display - spriteFrame = stream->readSint16LE(); + imageFrame = stream->readSint16LE(); - if (spriteFrame == -2) { + if (imageFrame == -2) { // End of animation reached break; - } else if (spriteFrame != -1) { + } else if (imageFrame != -1) { // Read position from either animation stream or the sprite frame itself - if (spriteFrame < 0) { - spriteFrame += 32769; + if (imageFrame < 0) { + imageFrame += 32769; pt.x = stream->readUint16LE(); pt.y = stream->readUint16LE(); } else { - pt = sprite[spriteFrame]._position; + pt = images[imageFrame]._position; } // Draw the sprite - screen.transBlitFrom(sprite[spriteFrame]._frame, pt); + screen.transBlitFrom(images[imageFrame]._frame, pt); } else { // No sprite to show for this animation frame if (fade == 255) { // Gradual fade in - if (screen.equalizePalette(sprite._palette) == 0) + if (screen.equalizePalette(images._palette) == 0) fade = 0; } diff --git a/engines/sherlock/events.cpp b/engines/sherlock/events.cpp index 1a882eedea..ecdbdbe8d7 100644 --- a/engines/sherlock/events.cpp +++ b/engines/sherlock/events.cpp @@ -32,7 +32,7 @@ namespace Sherlock { EventsManager::EventsManager(SherlockEngine *vm) { _vm = vm; - _cursorSprites = nullptr; + _cursorImages = nullptr; _cursorIndex = -1; _frameCounter = 1; _priorFrameTime = 0; @@ -41,7 +41,7 @@ EventsManager::EventsManager(SherlockEngine *vm) { } EventsManager::~EventsManager() { - delete _cursorSprites; + delete _cursorImages; } /** @@ -49,9 +49,9 @@ EventsManager::~EventsManager() { */ void EventsManager::loadCursors(const Common::String &filename) { hideCursor(); - delete _cursorSprites; + delete _cursorImages; - _cursorSprites = new Sprite(filename); + _cursorImages = new ImageFile(filename); } /** @@ -61,7 +61,7 @@ void EventsManager::changeCursor(int cursorIndex) { _cursorIndex = cursorIndex; // Set the cursor data - Graphics::Surface &s = (*_cursorSprites)[cursorIndex]; + Graphics::Surface &s = (*_cursorImages)[cursorIndex]; CursorMan.replaceCursor(s.getPixels(), s.w, s.h, s.w / 2, s.h / 2, 0xff); showCursor(); diff --git a/engines/sherlock/events.h b/engines/sherlock/events.h index 1f7352eeb5..0fa6bf3a5e 100644 --- a/engines/sherlock/events.h +++ b/engines/sherlock/events.h @@ -26,7 +26,7 @@ #include "common/scummsys.h" #include "common/events.h" #include "common/stack.h" -#include "sherlock/sprite.h" +#include "sherlock/resources.h" namespace Sherlock { @@ -41,7 +41,7 @@ private: uint32 _frameCounter; uint32 _priorFrameTime; Common::Point _mousePos; - Sprite *_cursorSprites; + ImageFile *_cursorImages; bool checkForNextFrameCounter(); public: diff --git a/engines/sherlock/module.mk b/engines/sherlock/module.mk index eef27aa0b1..865b422ef9 100644 --- a/engines/sherlock/module.mk +++ b/engines/sherlock/module.mk @@ -12,12 +12,13 @@ MODULE_OBJS = \ events.o \ graphics.o \ journal.o \ + people.o \ resources.o \ scene.o \ screen.o \ sherlock.o \ sound.o \ - sprite.o \ + sprites.o \ talk.o # This module can be built as a plugin diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp new file mode 100644 index 0000000000..53ccaf5baf --- /dev/null +++ b/engines/sherlock/people.cpp @@ -0,0 +1,73 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "sherlock/people.h" + +namespace Sherlock { + +// Characer animation sequences +static const uint8 CHARACTER_SEQUENCES[MAX_HOLMES_SEQUENCE][MAX_FRAME] = { + { 29, 1, 2, 3, 4, 5, 6, 7, 0 }, // Walk Right + { 22, 1, 2, 3, 4, 5, 6, 7, 0 }, // Walk Down + { 29, 1, 2, 3, 4, 5, 6, 7, 0 }, // Walk Left + { 15, 1, 2, 3, 4, 5, 6, 7, 0 }, // Walk Up + { 42, 1, 2, 3, 4, 5, 0 }, // Goto Stand Right + { 47, 1, 2, 3, 4, 5, 0 }, // Goto Stand Down + { 42, 1, 2, 3, 4, 5, 0 }, // Goto Stand Left + { 36, 1, 0 }, // Goto Stand Up + { 8, 1, 2, 3, 4, 5, 6, 7, 0 }, // Walk Up Right + { 1, 1, 2, 3, 4, 5, 6, 7, 0 }, // Walk Down Right + { 8, 1, 2, 3, 4, 5, 6, 7, 0 }, // Walk Up Left + { 1, 1, 2, 3, 4, 5, 6, 7, 0 }, // Walk Down Left + { 37, 1, 2, 3, 4, 5, 0 }, // Goto Stand Up Right + { 37, 1, 2, 3, 4, 5, 0 }, // Goto Stand Up Left + { 52, 1, 2, 3, 4, 0 }, // Goto Stand Down Right + { 52, 1, 2, 3, 4, 0 } // Goto Stand Down Left +}; + + +People::People(SherlockEngine *vm) : _vm(vm) { +} + +void People::reset() { + Sprite &p = _data[PLAYER]; + + p._description = "Sherlock Holmes!"; + p._type = CHARACTER; + p._position = Common::Point(10000, 11000); + p._sequenceNumber = STOP_DOWNRIGHT; + p._sequences = &CHARACTER_SEQUENCES; + p._spriteFrame = nullptr; + p._frameNumber = 1; + p._movement = Common::Point(0, 0); + p._oldPosition = Common::Point(0, 0); + p._oldSize = Common::Point(0, 0); + p._misc = 0; + p._walkCount = 0; + p._pickUp = ""; + p._allow = 0; + p._noShapeSize = Common::Point(0, 0); + p._goto = Common::Point(0, 0); + p._status = 0; +} + +} // End of namespace Sherlock diff --git a/engines/sherlock/people.h b/engines/sherlock/people.h new file mode 100644 index 0000000000..4ca7f51444 --- /dev/null +++ b/engines/sherlock/people.h @@ -0,0 +1,57 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef SHERLOCK_PEOPLE_H +#define SHERLOCK_PEOPLE_H + +#include "common/scummsys.h" +#include "sherlock/sprites.h" + +namespace Sherlock { + +#define MAX_PEOPLE 2 +#define PLAYER 0 + +// Animation sequence identifiers for characters +enum { + WALK_RIGHT = 0, WALK_DOWN = 1, WALK_LEFT = 2, WALK_UP = 3, STOP_LEFT = 4, + STOP_DOWN = 5, STOP_RIGHT = 6, STOP_UP = 7, WALK_UPRIGHT = 8, + WALK_DOWNRIGHT = 9, WALK_UPLEFT = 10, WALK_DOWNLEFT = 11, + STOP_UPRIGHT = 12, STOP_UPLEFT = 13, STOP_DOWNRIGHT = 14, + STOP_DOWNLEFT = 15, TALK_RIGHT = 6, TALK_LEFT = 4 +}; + +class SherlockEngine; + +class People { +private: + SherlockEngine *_vm; + Sprite _data[MAX_PEOPLE]; +public: + People(SherlockEngine *vm); + + void reset(); +}; + +} // End of namespace Sherlock + +#endif diff --git a/engines/sherlock/resources.cpp b/engines/sherlock/resources.cpp index 6636ca5be8..cdea7bd296 100644 --- a/engines/sherlock/resources.cpp +++ b/engines/sherlock/resources.cpp @@ -22,6 +22,8 @@ #include "sherlock/resources.h" #include "sherlock/decompress.h" +#include "sherlock/screen.h" +#include "sherlock/sherlock.h" #include "common/debug.h" namespace Sherlock { @@ -241,4 +243,123 @@ int Resources::resourceIndex() const { return _resourceIndex; } +/*----------------------------------------------------------------*/ + +SherlockEngine *ImageFile::_vm; + +void ImageFile::setVm(SherlockEngine *vm) { + _vm = vm; +} + +ImageFile::ImageFile(const Common::String &name, bool skipPal) { + Common::SeekableReadStream *stream = _vm->_res->load(name); + + Common::fill(&_palette[0], &_palette[PALETTE_SIZE], 0); + load(*stream, skipPal); + + delete stream; +} + +ImageFile::ImageFile(Common::SeekableReadStream &stream, bool skipPal) { + Common::fill(&_palette[0], &_palette[PALETTE_SIZE], 0); + load(stream, skipPal); +} + +ImageFile::~ImageFile() { + for (uint idx = 0; idx < size(); ++idx) + (*this)[idx]._frame.free(); +} + +/** + * Load the data of the sprite + */ +void ImageFile::load(Common::SeekableReadStream &stream, bool skipPalette) { + loadPalette(stream); + + while (stream.pos() < stream.size()) { + ImageFrame frame; + frame._width = stream.readUint16LE() + 1; + frame._height = stream.readUint16LE() + 1; + frame._flags = stream.readByte(); + frame._position.x = stream.readUint16LE(); + frame._position.y = stream.readByte(); + + frame._rleEncoded = !skipPalette && (frame._position.x == 1); + + if (frame._flags & 0xFF) { + // Nibble packed frame data + frame._size = (frame._width * frame._height) / 2; + } else if (frame._rleEncoded) { + // this size includes the header size, which we subtract + frame._size = stream.readUint16LE() - 11; + frame._rleMarker = stream.readByte(); + } else { + // Uncompressed data + frame._size = frame._width * frame._height; + } + + // Load data for frame and decompress it + byte *data = new byte[frame._size]; + stream.read(data, frame._size); + decompressFrame(frame, data); + delete data; + + push_back(frame); + } +} + +/** + * Gets the palette at the start of the sprite file + */ +void ImageFile::loadPalette(Common::SeekableReadStream &stream) { + // Check for palette + int v1 = stream.readUint16LE() + 1; + int v2 = stream.readUint16LE() + 1; + int size = v1 * v2; + + if ((size - 12) == PALETTE_SIZE) { + // Found palette, so read it in + stream.seek(4 + 12, SEEK_CUR); + for (int idx = 0; idx < PALETTE_SIZE; ++idx) + _palette[idx] = VGA_COLOR_TRANS(stream.readByte()); + } else { + // Not a palette, so rewind to start of frame data for normal frame processing + stream.seek(-4, SEEK_CUR); + } +} + +/** + * Decompress a single frame for the sprite + */ +void ImageFile::decompressFrame(ImageFrame &frame, const byte *src) { + frame._frame.create(frame._width, frame._height, Graphics::PixelFormat::createFormatCLUT8()); + + if (frame._flags & 0xFF) { + error("TODO: ImageFile::decompressFrame() 4-bits/pixel\n"); + } else if (frame._rleEncoded) { + // RLE encoded + byte *dst = (byte *)frame._frame.getPixels(); + + int size = frame._width * frame._height; + while (size > 0) { + if (*src == frame._rleMarker) { + byte rleColor = src[1]; + byte rleCount = src[2]; + src += 3; + size -= rleCount; + while (rleCount--) + *dst++ = rleColor; + } else { + *dst++ = *src++; + --size; + } + } + assert(size == 0); + } else { + // Uncompressed frame + Common::copy(src, src + frame._width * frame._height, + (byte *)frame._frame.getPixels()); + } +} + } // End of namespace Sherlock diff --git a/engines/sherlock/resources.h b/engines/sherlock/resources.h index cd6e60c325..ad9867c523 100644 --- a/engines/sherlock/resources.h +++ b/engines/sherlock/resources.h @@ -27,8 +27,10 @@ #include "common/file.h" #include "common/hashmap.h" #include "common/hash-str.h" +#include "common/rect.h" #include "common/str.h" #include "common/stream.h" +#include "graphics/surface.h" namespace Sherlock { @@ -83,6 +85,33 @@ public: int resourceIndex() const; }; +struct ImageFrame { + uint32 _size; + uint16 _width, _height; + int _flags; + bool _rleEncoded; + Common::Point _position; + byte _rleMarker; + Graphics::Surface _frame; + + operator Graphics::Surface &() { return _frame; } +}; + +class ImageFile : public Common::Array { +private: + static SherlockEngine *_vm; + + void load(Common::SeekableReadStream &stream, bool skipPalette); + void loadPalette(Common::SeekableReadStream &stream); + void decompressFrame(ImageFrame &frame, const byte *src); +public: + byte _palette[256 * 3]; +public: + ImageFile(const Common::String &name, bool skipPal = false); + ImageFile(Common::SeekableReadStream &stream, bool skipPal = false); + ~ImageFile(); + static void setVm(SherlockEngine *vm); +}; } // End of namespace Sherlock diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp index d5f63b9c0d..ca04153594 100644 --- a/engines/sherlock/scalpel/scalpel.cpp +++ b/engines/sherlock/scalpel/scalpel.cpp @@ -83,18 +83,18 @@ bool ScalpelEngine::showCityCutscene() { bool finished = _animation->playPrologue("26open1", 1, 255, true, 2); if (finished) { - Sprite titleSprites("title2.vgs", true); + ImageFile titleImages("title2.vgs", true); _screen->_backBuffer.blitFrom(*_screen); _screen->_backBuffer2.blitFrom(*_screen); // London, England - _screen->_backBuffer.transBlitFrom(titleSprites[0], Common::Point(10, 11)); + _screen->_backBuffer.transBlitFrom(titleImages[0], Common::Point(10, 11)); _screen->randomTransition(); finished = _events->delay(1000, true); // November, 1888 if (finished) { - _screen->_backBuffer.transBlitFrom(titleSprites[1], Common::Point(101, 102)); + _screen->_backBuffer.transBlitFrom(titleImages[1], Common::Point(101, 102)); _screen->randomTransition(); finished = _events->delay(5000, true); } @@ -108,16 +108,16 @@ bool ScalpelEngine::showCityCutscene() { finished = _animation->playPrologue("26open2", 1, 0, false, 2); if (finished) { - Sprite titleSprites("title.vgs", true); + ImageFile titleImages("title.vgs", true); _screen->_backBuffer.blitFrom(*_screen); _screen->_backBuffer2.blitFrom(*_screen); // The Lost Files of - _screen->_backBuffer.transBlitFrom(titleSprites[0], Common::Point(75, 6)); + _screen->_backBuffer.transBlitFrom(titleImages[0], Common::Point(75, 6)); // Sherlock Holmes - _screen->_backBuffer.transBlitFrom(titleSprites[1], Common::Point(34, 21)); + _screen->_backBuffer.transBlitFrom(titleImages[1], Common::Point(34, 21)); // copyright - _screen->_backBuffer.transBlitFrom(titleSprites[2], Common::Point(4, 190)); + _screen->_backBuffer.transBlitFrom(titleImages[2], Common::Point(4, 190)); _screen->verticalTransition(); finished = _events->delay(4000, true); @@ -135,7 +135,7 @@ bool ScalpelEngine::showCityCutscene() { if (finished) { // In the alley... - _screen->transBlitFrom(titleSprites[3], Common::Point(72, 51)); + _screen->transBlitFrom(titleImages[3], Common::Point(72, 51)); _screen->fadeIn(palette, 3); finished = _events->delay(3000, true); } diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index de351a5561..84ef44d7e1 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -30,12 +30,27 @@ Scene::Scene(SherlockEngine *vm): _vm(vm) { _goToRoom = -1; _oldCharPoint = 0; _numExits = 0; + _windowOpen = _infoFlag = false; + _menuMode = _keyboardInput = 0; - _controlSprites = new Sprite("menu.all"); + _controls = nullptr; // new ImageFile("menu.all"); } Scene::~Scene() { - delete _controlSprites; + delete _controls; +} + +void Scene::selectScene() { + // Reset fields + _numExits = 0; + _windowOpen = _infoFlag = false; + _menuMode = _keyboardInput = 0; + _oldKey = _help = _oldHelp = 0; + _oldTemp = _temp = 0; + + // Set up player + + } } // End of namespace Sherlock diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h index 031245b122..f92dfccfad 100644 --- a/engines/sherlock/scene.h +++ b/engines/sherlock/scene.h @@ -24,7 +24,7 @@ #define SHERLOCK_SCENE_H #include "common/scummsys.h" -#include "sherlock/sprite.h" +#include "sherlock/resources.h" namespace Sherlock { @@ -35,6 +35,8 @@ class SherlockEngine; class Scene { private: SherlockEngine *_vm; + + void loadScene(); public: bool _stats[SCENES_COUNT][9]; bool _savedStats[SCENES_COUNT][9]; @@ -42,12 +44,17 @@ public: Common::Point _bigPos; Common::Point _overPos; int _oldCharPoint; - Sprite *_controlSprites; + ImageFile *_controls; int _numExits; + bool _windowOpen, _infoFlag; + int _menuMode, _keyboardInput; + int _oldKey, _help, _oldHelp; + int _oldTemp, _temp; public: Scene(SherlockEngine *vm); - ~Scene(); + + void selectScene(); }; } // End of namespace Sherlock diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index 8b597df31b..a292ee675c 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -74,6 +74,7 @@ void SherlockEngine::initialize() { _midi->setNativeMT32(native_mt32); */ + ImageFile::setVm(this); _res = new Resources(); _animation = new Animation(this); _debugger = new Debugger(this); @@ -83,7 +84,6 @@ void SherlockEngine::initialize() { _screen = new Screen(this); _sound = new Sound(this); _talk = new Talk(); - Sprite::setVm(this); } Common::Error SherlockEngine::run() { @@ -97,6 +97,9 @@ Common::Error SherlockEngine::run() { if (shouldQuit()) break; + // Initialize the scene + _scene->selectScene(); + // TODO: Implement game and remove this dummy loop while (!shouldQuit()) _events->pollEventsAndWait(); diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h index c6023684b4..210e24c320 100644 --- a/engines/sherlock/sherlock.h +++ b/engines/sherlock/sherlock.h @@ -35,6 +35,7 @@ #include "sherlock/debugger.h" #include "sherlock/events.h" #include "sherlock/journal.h" +#include "sherlock/people.h" #include "sherlock/resources.h" #include "sherlock/scene.h" #include "sherlock/screen.h" @@ -77,6 +78,7 @@ public: Debugger *_debugger; EventsManager *_events; Journal *_journal; + People *_people; Resources *_res; Scene *_scene; Screen *_screen; diff --git a/engines/sherlock/sprite.cpp b/engines/sherlock/sprite.cpp deleted file mode 100644 index 8a7bb4cf29..0000000000 --- a/engines/sherlock/sprite.cpp +++ /dev/null @@ -1,147 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "sherlock/sprite.h" -#include "sherlock/screen.h" -#include "sherlock/sherlock.h" -#include "common/debug.h" - -namespace Sherlock { - -SherlockEngine *Sprite::_vm; - -void Sprite::setVm(SherlockEngine *vm) { - _vm = vm; -} - -Sprite::Sprite(const Common::String &name, bool skipPal) { - Common::SeekableReadStream *stream = _vm->_res->load(name); - - Common::fill(&_palette[0], &_palette[PALETTE_SIZE], 0); - load(*stream, skipPal); - - delete stream; -} - -Sprite::Sprite(Common::SeekableReadStream &stream, bool skipPal) { - Common::fill(&_palette[0], &_palette[PALETTE_SIZE], 0); - load(stream, skipPal); -} - -Sprite::~Sprite() { - for (uint idx = 0; idx < size(); ++idx) - (*this)[idx]._frame.free(); -} - -/** - * Load the data of the sprite - */ -void Sprite::load(Common::SeekableReadStream &stream, bool skipPalette) { - loadPalette(stream); - - while (stream.pos() < stream.size()) { - SpriteFrame frame; - frame._width = stream.readUint16LE() + 1; - frame._height = stream.readUint16LE() + 1; - frame._flags = stream.readByte(); - frame._position.x = stream.readUint16LE(); - frame._position.y = stream.readByte(); - - frame._rleEncoded = !skipPalette && (frame._position.x == 1); - - if (frame._flags & 0xFF) { - // Nibble packed frame data - frame._size = (frame._width * frame._height) / 2; - } else if (frame._rleEncoded) { - // this size includes the header size, which we subtract - frame._size = stream.readUint16LE() - 11; - frame._rleMarker = stream.readByte(); - } else { - // Uncompressed data - frame._size = frame._width * frame._height; - } - - // Load data for frame and decompress it - byte *data = new byte[frame._size]; - stream.read(data, frame._size); - decompressFrame(frame, data); - delete data; - - push_back(frame); - } -} - -/** - * Gets the palette at the start of the sprite file - */ -void Sprite::loadPalette(Common::SeekableReadStream &stream) { - // Check for palette - int v1 = stream.readUint16LE() + 1; - int v2 = stream.readUint16LE() + 1; - int size = v1 * v2; - - if ((size - 12) == PALETTE_SIZE) { - // Found palette, so read it in - stream.seek(4 + 12, SEEK_CUR); - for (int idx = 0; idx < PALETTE_SIZE; ++idx) - _palette[idx] = VGA_COLOR_TRANS(stream.readByte()); - } else { - // Not a palette, so rewind to start of frame data for normal frame processing - stream.seek(-4, SEEK_CUR); - } -} - -/** - * Decompress a single frame for the sprite - */ -void Sprite::decompressFrame(SpriteFrame &frame, const byte *src) { - frame._frame.create(frame._width, frame._height, Graphics::PixelFormat::createFormatCLUT8()); - - if (frame._flags & 0xFF) { - debug("TODO: Sprite::decompressFrame() 4-bits/pixel\n"); - } else if (frame._rleEncoded) { - // RLE encoded - byte *dst = (byte *)frame._frame.getPixels(); - - int size = frame._width * frame._height; - while (size > 0) { - if (*src == frame._rleMarker) { - byte rleColor = src[1]; - byte rleCount = src[2]; - src += 3; - size -= rleCount; - while (rleCount--) - *dst++ = rleColor; - } else { - *dst++ = *src++; - --size; - } - } - assert(size == 0); - } else { - // Uncompressed frame - Common::copy(src, src + frame._width * frame._height, - (byte *)frame._frame.getPixels()); - } -} - -} // End of namespace Sherlock diff --git a/engines/sherlock/sprite.h b/engines/sherlock/sprite.h deleted file mode 100644 index 844013db43..0000000000 --- a/engines/sherlock/sprite.h +++ /dev/null @@ -1,65 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#ifndef SHERLOCK_SPRITE_H -#define SHERLOCK_SPRITE_H - -#include "common/array.h" -#include "common/rect.h" -#include "common/stream.h" -#include "graphics/surface.h" - -namespace Sherlock { - -class SherlockEngine; - -struct SpriteFrame { - uint32 _size; - uint16 _width, _height; - int _flags; - bool _rleEncoded; - Common::Point _position; - byte _rleMarker; - Graphics::Surface _frame; - - operator Graphics::Surface &() { return _frame; } -}; - -class Sprite: public Common::Array { -private: - static SherlockEngine *_vm; - - void load(Common::SeekableReadStream &stream, bool skipPalette); - void loadPalette(Common::SeekableReadStream &stream); - void decompressFrame(SpriteFrame &frame, const byte *src); -public: - byte _palette[256 * 3]; -public: - Sprite(const Common::String &name, bool skipPal = false); - Sprite(Common::SeekableReadStream &stream, bool skipPal = false); - ~Sprite(); - static void setVm(SherlockEngine *vm); -}; - -} // End of namespace Sherlock - -#endif diff --git a/engines/sherlock/sprites.cpp b/engines/sherlock/sprites.cpp new file mode 100644 index 0000000000..6e33219309 --- /dev/null +++ b/engines/sherlock/sprites.cpp @@ -0,0 +1,27 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "sherlock/sprites.h" + +namespace Sherlock { + +} // End of namespace Sherlock diff --git a/engines/sherlock/sprites.h b/engines/sherlock/sprites.h new file mode 100644 index 0000000000..631693d815 --- /dev/null +++ b/engines/sherlock/sprites.h @@ -0,0 +1,83 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef SHERLOCK_SPRITES_H +#define SHERLOCK_SPRITES_H + +#include "common/scummsys.h" +#include "common/rect.h" +#include "common/str-array.h" +#include "common/str.h" +#include "sherlock/resources.h" + +namespace Sherlock { + +class SherlockEngine; + +enum ObjectAllow { + ALLOW_MOVEMENT = 1, ALLOW_OPEN = 2, ALLOW_CLOSE = 4 +}; + +enum SpriteType { + INVALID = 0, + CHARACTER = 1, + CURSOR = 2, + STATIC_BG_SHAPE = 3, // Background shape that doesn't animate + ACTIVE_BG_SHAPE = 4, // Background shape that animates + REMOVE = 5, // Object should be removed next frame + NO_SHAPE = 6, // Background object with no shape + HIDDEN = 7, // Hidden backgruond object + HIDE_SHAPE = 8 // Object needs to be hidden +}; + +#define MAX_HOLMES_SEQUENCE 16 +#define MAX_FRAME 30 + +struct Sprite { + Common::String _name; // Name + Common::String _description; // Description + Common::StringArray _examine; // Examine in-depth description + Common::String _pickUp; // Message for if you can't pick up object + + const uint8 (*_sequences)[MAX_HOLMES_SEQUENCE][MAX_FRAME]; // Holds animation sequences + Sprite *_sprites; // Sprite shapes + ImageFrame *_spriteFrame; // Pointer to shape in the sprite + int _walkCount; // Character walk counter + int _allow; // Allowed menu commands - ObjectAllow + int _frameNumber; // Frame number in rame sequence to draw + int _sequenceNumber; // Sequence being used + Common::Point _position; // Current position + Common::Point _movement; // Momvement amount + Common::Point _oldPosition; // Old position + Common::Point _oldSize; // Image's old size + Common::Point _goto; // Walk destination + SpriteType _type; // Type of object + int _pickup; + Common::Point _noShapeSize; // Size of a NO_SHAPE + int _status; // Status: open/closed, moved/not moved + byte _misc; // Miscellaneous use + int _numFrames; // How many frames the object has +}; + +} // End of namespace Sherlock + +#endif -- cgit v1.2.3 From 77a4227aa4915a860accdd761fb9695d390641dd Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 19 Mar 2015 23:31:28 -0400 Subject: SHERLOCK: Added loading of scene objects --- engines/sherlock/module.mk | 2 +- engines/sherlock/objects.cpp | 155 ++++++++++++++++++++++++++++++++++++++ engines/sherlock/objects.h | 166 +++++++++++++++++++++++++++++++++++++++++ engines/sherlock/people.cpp | 2 +- engines/sherlock/people.h | 2 +- engines/sherlock/resources.cpp | 7 ++ engines/sherlock/resources.h | 2 + engines/sherlock/scene.cpp | 127 ++++++++++++++++++++++++++++++- engines/sherlock/scene.h | 35 +++++++++ engines/sherlock/sherlock.cpp | 11 ++- engines/sherlock/sprites.cpp | 27 ------- engines/sherlock/sprites.h | 83 --------------------- 12 files changed, 503 insertions(+), 116 deletions(-) create mode 100644 engines/sherlock/objects.cpp create mode 100644 engines/sherlock/objects.h delete mode 100644 engines/sherlock/sprites.cpp delete mode 100644 engines/sherlock/sprites.h (limited to 'engines') diff --git a/engines/sherlock/module.mk b/engines/sherlock/module.mk index 865b422ef9..dc88ab3f5f 100644 --- a/engines/sherlock/module.mk +++ b/engines/sherlock/module.mk @@ -12,13 +12,13 @@ MODULE_OBJS = \ events.o \ graphics.o \ journal.o \ + objects.o \ people.o \ resources.o \ scene.o \ screen.o \ sherlock.o \ sound.o \ - sprites.o \ talk.o # This module can be built as a plugin diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp new file mode 100644 index 0000000000..2386c00686 --- /dev/null +++ b/engines/sherlock/objects.cpp @@ -0,0 +1,155 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "sherlock/objects.h" + +namespace Sherlock { + +/** + * Reset the data for the sprite + */ +void Sprite::clear() { + _name = ""; + _description = ""; + _examine.clear(); + _pickUp = ""; + _sequences = nullptr; + _images = nullptr; + _imageFrame = nullptr; + _walkCount = 0; + _allow = 0; + _frameNumber = _sequenceNumber = 0; + _position.x = _position.y = 0; + _movement.x = _movement.y = 0; + _oldPosition.x = _oldPosition.y = 0; + _oldSize.x = _oldSize.y = 0; + _goto.x = _goto.y = 0; + _type = INVALID; + _pickUp.clear(); + _noShapeSize.x = _noShapeSize.y = 0; + _status = 0; + _misc = 0; + _numFrames = 0; +} + +/*----------------------------------------------------------------*/ + +void ActionType::synchronize(Common::SeekableReadStream &s) { + char buffer[12]; + + _cAnimNum = s.readByte(); + _cAnimSpeed = s.readByte(); + + for (int idx = 0; idx < 4; ++idx) { + s.read(buffer, 12); + _names[idx] = Common::String(buffer); + } +} + +/*----------------------------------------------------------------*/ + +void UseType::synchronize(Common::SeekableReadStream &s) { + char buffer[12]; + + _cAnimNum = s.readByte(); + _cAnimSpeed = s.readByte(); + + for (int idx = 0; idx < 4; ++idx) { + s.read(buffer, 12); + _names[idx] = Common::String(buffer); + } + + _useFlag = s.readUint16LE(); + _dFlag[0] = s.readUint16LE(); + _lFlag[0] = s.readUint16LE(); + _lFlag[1] = s.readUint16LE(); + + s.read(buffer, 12); + _target = Common::String(buffer); +} + +/*----------------------------------------------------------------*/ + +void Object::synchronize(Common::SeekableReadStream &s) { + char buffer[50]; + + s.read(buffer, 12); + _name = Common::String(buffer); + s.read(buffer, 41); + _description = Common::String(buffer); + + _examine.clear(); + _sequences = nullptr; + _images = nullptr; + _imageFrame = nullptr; + s.seek(16, SEEK_CUR); + + _walkCount = s.readByte(); + _allow = s.readByte(); + _frameNumber = s.readSint16LE(); + _sequenceNumber = s.readSint16LE(); + _position.x = s.readSint16LE(); + _position.y = s.readSint16LE(); + _movement.x = s.readSint16LE(); + _movement.y = s.readSint16LE(); + _type = (SpriteType)s.readUint16LE(); + _oldPosition.x = s.readSint16LE(); + _oldPosition.y = s.readSint16LE(); + _oldSize.x = s.readUint16LE(); + _oldSize.y = s.readUint16LE(); + _goto.x = s.readSint16LE(); + _goto.y = s.readSint16LE(); + + _pickup = s.readByte(); + _defaultCommand = s.readByte(); + _lookFlag = s.readUint16LE(); + _pickupFlag = s.readUint16LE(); + _requiredFlag = s.readUint16LE(); + _noShapeSize.x = s.readUint16LE(); + _noShapeSize.y = s.readUint16LE(); + _status = s.readUint16LE(); + _misc = s.readByte(); + _maxFrames = s.readUint16LE(); + _flags = s.readByte(); + _aOpen.synchronize(s); + _aType = s.readByte(); + _lookFrames = s.readByte(); + _seqcounter = s.readByte(); + _lookPosition.x = s.readUint16LE(); + _lookPosition.y = s.readByte(); + _lookFacing = s.readByte(); + _lookcAnim = s.readByte(); + _aClose.synchronize(s); + _seqStack = s.readByte(); + _seqTo = s.readByte(); + _descOfs = s.readUint16LE(); + _seqcounter2 = s.readByte(); + _seqSize = s.readUint16LE(); + s.skip(1); + _aMove.synchronize(s); + s.skip(8); + + for (int idx = 0; idx < 4; ++idx) + _use[idx].synchronize(s); +} + +} // End of namespace Sherlock diff --git a/engines/sherlock/objects.h b/engines/sherlock/objects.h new file mode 100644 index 0000000000..f730240479 --- /dev/null +++ b/engines/sherlock/objects.h @@ -0,0 +1,166 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef SHERLOCK_OBJECTS_H +#define SHERLOCK_OBJECTS_H + +#include "common/scummsys.h" +#include "common/rect.h" +#include "common/str-array.h" +#include "common/str.h" +#include "sherlock/resources.h" + +namespace Sherlock { + +class SherlockEngine; + +enum ObjectAllow { + ALLOW_MOVEMENT = 1, ALLOW_OPEN = 2, ALLOW_CLOSE = 4 +}; + +enum SpriteType { + INVALID = 0, + CHARACTER = 1, + CURSOR = 2, + STATIC_BG_SHAPE = 3, // Background shape that doesn't animate + ACTIVE_BG_SHAPE = 4, // Background shape that animates + REMOVE = 5, // Object should be removed next frame + NO_SHAPE = 6, // Background object with no shape + HIDDEN = 7, // Hidden backgruond object + HIDE_SHAPE = 8 // Object needs to be hidden +}; + +#define MAX_HOLMES_SEQUENCE 16 +#define MAX_FRAME 30 + +struct Sprite { + Common::String _name; // Name + Common::String _description; // Description + Common::StringArray _examine; // Examine in-depth description + Common::String _pickUp; // Message for if you can't pick up object + + const uint8 (*_sequences)[MAX_HOLMES_SEQUENCE][MAX_FRAME]; // Holds animation sequences + ImageFile *_images; // Sprite images + ImageFrame *_imageFrame; // Pointer to shape in the images + int _walkCount; // Character walk counter + int _allow; // Allowed menu commands - ObjectAllow + int _frameNumber; // Frame number in rame sequence to draw + int _sequenceNumber; // Sequence being used + Common::Point _position; // Current position + Common::Point _movement; // Momvement amount + Common::Point _oldPosition; // Old position + Common::Point _oldSize; // Image's old size + Common::Point _goto; // Walk destination + SpriteType _type; // Type of object + int _pickup; + Common::Point _noShapeSize; // Size of a NO_SHAPE + int _status; // Status: open/closed, moved/not moved + int8 _misc; // Miscellaneous use + int _numFrames; // How many frames the object has + + Sprite() { clear(); } + void clear(); +}; + +struct ActionType { + char _cAnimNum; + char _cAnimSpeed; // if high bit set, play in reverse + Common::String _names[4]; + + void synchronize(Common::SeekableReadStream &s); +}; + +struct UseType { + int _cAnimNum; + int _cAnimSpeed; // if high bit set, play in reverse + Common::String _names[4]; + int _useFlag; // Which flag USE will set (if any) + int _dFlag[1]; + int _lFlag[2]; + Common::String _target; + + void synchronize(Common::SeekableReadStream &s); +}; + +struct Object { + Common::String _name; // Name + Common::String _description; // Description + Common::StringArray _examine; // Examine in-depth description + uint8 (*_sequences)[MAX_HOLMES_SEQUENCE][MAX_FRAME]; // Holds animation sequences + ImageFile *_images; // Sprite images + ImageFrame *_imageFrame; // Pointer to shape in the images + int _walkCount; // Character walk counter + int _allow; // Allowed menu commands - ObjectAllow + int _frameNumber; // Frame number in rame sequence to draw + int _sequenceNumber; // Sequence being used + SpriteType _type; // Object type + Common::Point _position; // Current position + Common::Point _movement; // Momvement amount + Common::Point _oldPosition; // Old position + Common::Point _oldSize; // Image's old size + Common::Point _goto; // Walk destination + + int _pickup; + int _defaultCommand; // Default right-click command + int _lookFlag; // Which flag LOOK will set (if any) + int _pickupFlag; // Which flag PICKUP will set (if any) + int _requiredFlag; // Object will be hidden if not set + Common::Point _noShapeSize; // Size of a NO_SHAPE + int _status; // Status (open/closed, moved/not) + int8 _misc; // Misc field -- use varies with type + int _maxFrames; // Number of frames + int _flags; // Tells if object can be walked behind + ActionType _aOpen; // Holds data for moving object + int _aType; // Tells if this is an object, person, talk, etc. + int _lookFrames; // How many frames to play of the look anim before pausing + int _seqcounter; // How many times this sequence has been executed + Common::Point _lookPosition; // Where to walk when examining object + int _lookFacing; // Direction to face when examining object + int _lookcAnim; + ActionType _aClose; + int _seqStack; // Allows gosubs to return to calling frame + int _seqTo; // Allows 1-5, 8-3 type sequences encoded in 2 bytes + uint _descOfs; // Tells where description starts in DescText + int _seqcounter2; // Counter of calling frame sequence + uint _seqSize; // Tells where description starts + ActionType _aMove; + UseType _use[4]; + + void synchronize(Common::SeekableReadStream &s); +}; + +struct CAnim { + Common::String _name; // Name + int _sequences[MAX_FRAME]; // Animation sequences + Common::Point _position; // Position + int _size; // Size of uncompressed animation + SpriteType _type; + int _flags; // Tells if can be walked behind + Common::Point _goto; // coords holmes should walk to before starting canim + int _sequenceNumber; + Common::Point _teleportPos; // Location Holmes shoul teleport to after + int _teleportS; // playing canim +}; + +} // End of namespace Sherlock + +#endif diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp index 53ccaf5baf..cdb498e5e6 100644 --- a/engines/sherlock/people.cpp +++ b/engines/sherlock/people.cpp @@ -56,7 +56,7 @@ void People::reset() { p._position = Common::Point(10000, 11000); p._sequenceNumber = STOP_DOWNRIGHT; p._sequences = &CHARACTER_SEQUENCES; - p._spriteFrame = nullptr; + p._imageFrame = nullptr; p._frameNumber = 1; p._movement = Common::Point(0, 0); p._oldPosition = Common::Point(0, 0); diff --git a/engines/sherlock/people.h b/engines/sherlock/people.h index 4ca7f51444..3f639a6d44 100644 --- a/engines/sherlock/people.h +++ b/engines/sherlock/people.h @@ -24,7 +24,7 @@ #define SHERLOCK_PEOPLE_H #include "common/scummsys.h" -#include "sherlock/sprites.h" +#include "sherlock/objects.h" namespace Sherlock { diff --git a/engines/sherlock/resources.cpp b/engines/sherlock/resources.cpp index cdea7bd296..66feca6bd5 100644 --- a/engines/sherlock/resources.cpp +++ b/engines/sherlock/resources.cpp @@ -194,6 +194,13 @@ Common::SeekableReadStream *Resources::load(const Common::String &filename, cons return stream; } +/** + * Returns true if the given file exists on disk or in the cache + */ +bool Resources::exists(const Common::String &filename) const { + Common::File f; + return f.exists(filename) || _cache.isCached(filename); +} /** * Reads in the index from a library file, and caches it's index for later use diff --git a/engines/sherlock/resources.h b/engines/sherlock/resources.h index ad9867c523..2f9222c1fd 100644 --- a/engines/sherlock/resources.h +++ b/engines/sherlock/resources.h @@ -82,6 +82,8 @@ public: Common::SeekableReadStream *load(const Common::String &filename, const Common::String &libraryFile); + bool exists(const Common::String &filename) const; + int resourceIndex() const; }; diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 84ef44d7e1..267b02b43c 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -21,9 +21,37 @@ */ #include "sherlock/scene.h" +#include "sherlock/sherlock.h" +#include "sherlock/decompress.h" namespace Sherlock { +void BgFileHeader::synchronize(Common::SeekableReadStream &s) { + _numStructs = s.readUint16LE(); + _numImages = s.readUint16LE(); + _numcAnimations = s.readUint16LE(); + _descSize = s.readUint16LE(); + _seqSize = s.readUint16LE(); + _fill = s.readUint16LE(); +} + +/*----------------------------------------------------------------*/ + +void BgfileheaderInfo::synchronize(Common::SeekableReadStream &s) { + _fSize = s.readUint32LE(); + _maxFrames = s.readByte(); + + char buffer[9]; + s.read(buffer, 9); + _filename = Common::String(buffer); +} + +int _fSize; // How long images are +int _maxFrames; // How many unique frames in object +Common::String _filename; // Filename of object + +/*----------------------------------------------------------------*/ + Scene::Scene(SherlockEngine *vm): _vm(vm) { for (int idx = 0; idx < SCENES_COUNT; ++idx) Common::fill(&_stats[idx][0], &_stats[idx][9], false); @@ -32,6 +60,11 @@ Scene::Scene(SherlockEngine *vm): _vm(vm) { _numExits = 0; _windowOpen = _infoFlag = false; _menuMode = _keyboardInput = 0; + _walkedInScene = false; + _ongoingCans = 0; + _version = 0; + _lzwMode = false; + _invGraphicItems = 0; _controls = nullptr; // new ImageFile("menu.all"); } @@ -48,9 +81,101 @@ void Scene::selectScene() { _oldKey = _help = _oldHelp = 0; _oldTemp = _temp = 0; - // Set up player + // Load the scene + Common::String sceneFile = Common::String::format("res%02d", _goToRoom); + Common::String roomName = Common::String::format("res%02d.rrm", _goToRoom); + _goToRoom = -1; + + loadScene(sceneFile); +} + +/** + * Loads the data associated for a given scene. The .BGD file's format is: + * BGHEADER: Holds an index for the rest of the file + * STRUCTS: The objects for the scene + * IMAGES: The graphic information for the structures + * + * The _misc field of the structures contains the number of the graphic image + * that it should point to after loading; _misc is then set to 0. + */ +void Scene::loadScene(const Common::String &filename) { + bool flag; + + _walkedInScene = false; + _ongoingCans = 0; + + // Reset the list of walkable areas + _roomBounds.clear(); + _roomBounds.push_back(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); + + _descText.clear(); + _comments = ""; + _bgShapes.clear(); + _cAnim.clear(); + _sequenceBuffer.clear(); + + // + // Load background shapes from .rrm + // + + Common::String rrmFile = filename + ".rrm"; + flag = _vm->_res->exists(rrmFile); + if (flag) { + Common::SeekableReadStream *rrmStream = _vm->_res->load(rrmFile); + + rrmStream->seek(39); + _version = rrmStream->readByte(); + _lzwMode = _version == 10; + + // Go to header and read it in + rrmStream->seek(rrmStream->readUint32LE()); + BgFileHeader bgHeader; + bgHeader.synchronize(*rrmStream); + + _cAnim.resize(bgHeader._numcAnimations); + _invGraphicItems = bgHeader._numImages + 1; + + // Read in the shapes header info + Common::Array bgInfo; + bgInfo.resize(bgHeader._numStructs); + + for (uint idx = 0; idx < bgInfo.size(); ++idx) + bgInfo[idx].synchronize(*rrmStream); + + // Initialize the cAnim + for (uint idx = 0; idx < _cAnim.size(); ++idx) { + _cAnim[idx]._position.x = -1; + _cAnim[idx]._goto.x = -1; + _cAnim[idx]._teleportPos.x = -1; + } + + // Read information + Common::SeekableReadStream *infoStream = !_lzwMode ? rrmStream : + decompressLZ(*rrmStream, bgHeader._numImages * 569 + + bgHeader._descSize + bgHeader._seqSize); + + _bgShapes.resize(bgHeader._numStructs); + for (uint idx = 0; idx < _bgShapes.size(); ++idx) + _bgShapes[idx].synchronize(*infoStream); + + if (bgHeader._descSize) { + _descText.resize(bgHeader._descSize); + infoStream->read(&_descText[0], bgHeader._descSize); + } + + if (bgHeader._seqSize) { + _sequenceBuffer.resize(bgHeader._seqSize); + infoStream->read(&_sequenceBuffer[0], bgHeader._seqSize); + } + + if (_lzwMode) + delete infoStream; + // Load shapes + // TODO + delete rrmStream; + } } } // End of namespace Sherlock diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h index f92dfccfad..e216c2bd9d 100644 --- a/engines/sherlock/scene.h +++ b/engines/sherlock/scene.h @@ -24,6 +24,9 @@ #define SHERLOCK_SCENE_H #include "common/scummsys.h" +#include "common/array.h" +#include "common/rect.h" +#include "sherlock/objects.h" #include "sherlock/resources.h" namespace Sherlock { @@ -32,11 +35,32 @@ namespace Sherlock { class SherlockEngine; +struct BgFileHeader { + int _numStructs; + int _numImages; + int _numcAnimations; + int _descSize; + int _seqSize; + int _fill; + + void synchronize(Common::SeekableReadStream &s); +}; + +struct BgfileheaderInfo { + int _fSize; // How long images are + int _maxFrames; // How many unique frames in object + Common::String _filename; // Filename of object + + void synchronize(Common::SeekableReadStream &s); +}; + class Scene { private: SherlockEngine *_vm; void loadScene(); + + void loadScene(const Common::String &filename); public: bool _stats[SCENES_COUNT][9]; bool _savedStats[SCENES_COUNT][9]; @@ -50,6 +74,17 @@ public: int _menuMode, _keyboardInput; int _oldKey, _help, _oldHelp; int _oldTemp, _temp; + bool _walkedInScene; + int _ongoingCans; + int _version; + bool _lzwMode; + int _invGraphicItems; + Common::String _comments; + Common::Array _descText; + Common::Array _roomBounds; + Common::Array _bgShapes; + Common::Array _cAnim; + Common::Array _sequenceBuffer; public: Scene(SherlockEngine *vm); ~Scene(); diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index a292ee675c..a963d0bfe5 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -34,6 +34,7 @@ SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gam _debugger = nullptr; _events = nullptr; _journal = nullptr; + _people = nullptr; _res = nullptr; _scene = nullptr; _screen = nullptr; @@ -49,6 +50,7 @@ SherlockEngine::~SherlockEngine() { delete _debugger; delete _events; delete _journal; + delete _people; delete _res; delete _scene; delete _screen; @@ -80,6 +82,7 @@ void SherlockEngine::initialize() { _debugger = new Debugger(this); _events = new EventsManager(this); _journal = new Journal(); + _people = new People(this); _scene = new Scene(this); _screen = new Screen(this); _sound = new Sound(this); @@ -92,12 +95,16 @@ Common::Error SherlockEngine::run() { showOpening(); while (!shouldQuit()) { - // Prepare for scene, and handle any game-specific scenes + // Prepare for scene, and handle any game-specific scenes. This allows + // for game specific cutscenes or mini-games that aren't standard scenes startScene(); if (shouldQuit()) break; - // Initialize the scene + // Reset the active characters to initially just Sherlock + _people->reset(); + + // Initialize and load the scene. _scene->selectScene(); // TODO: Implement game and remove this dummy loop diff --git a/engines/sherlock/sprites.cpp b/engines/sherlock/sprites.cpp deleted file mode 100644 index 6e33219309..0000000000 --- a/engines/sherlock/sprites.cpp +++ /dev/null @@ -1,27 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "sherlock/sprites.h" - -namespace Sherlock { - -} // End of namespace Sherlock diff --git a/engines/sherlock/sprites.h b/engines/sherlock/sprites.h deleted file mode 100644 index 631693d815..0000000000 --- a/engines/sherlock/sprites.h +++ /dev/null @@ -1,83 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#ifndef SHERLOCK_SPRITES_H -#define SHERLOCK_SPRITES_H - -#include "common/scummsys.h" -#include "common/rect.h" -#include "common/str-array.h" -#include "common/str.h" -#include "sherlock/resources.h" - -namespace Sherlock { - -class SherlockEngine; - -enum ObjectAllow { - ALLOW_MOVEMENT = 1, ALLOW_OPEN = 2, ALLOW_CLOSE = 4 -}; - -enum SpriteType { - INVALID = 0, - CHARACTER = 1, - CURSOR = 2, - STATIC_BG_SHAPE = 3, // Background shape that doesn't animate - ACTIVE_BG_SHAPE = 4, // Background shape that animates - REMOVE = 5, // Object should be removed next frame - NO_SHAPE = 6, // Background object with no shape - HIDDEN = 7, // Hidden backgruond object - HIDE_SHAPE = 8 // Object needs to be hidden -}; - -#define MAX_HOLMES_SEQUENCE 16 -#define MAX_FRAME 30 - -struct Sprite { - Common::String _name; // Name - Common::String _description; // Description - Common::StringArray _examine; // Examine in-depth description - Common::String _pickUp; // Message for if you can't pick up object - - const uint8 (*_sequences)[MAX_HOLMES_SEQUENCE][MAX_FRAME]; // Holds animation sequences - Sprite *_sprites; // Sprite shapes - ImageFrame *_spriteFrame; // Pointer to shape in the sprite - int _walkCount; // Character walk counter - int _allow; // Allowed menu commands - ObjectAllow - int _frameNumber; // Frame number in rame sequence to draw - int _sequenceNumber; // Sequence being used - Common::Point _position; // Current position - Common::Point _movement; // Momvement amount - Common::Point _oldPosition; // Old position - Common::Point _oldSize; // Image's old size - Common::Point _goto; // Walk destination - SpriteType _type; // Type of object - int _pickup; - Common::Point _noShapeSize; // Size of a NO_SHAPE - int _status; // Status: open/closed, moved/not moved - byte _misc; // Miscellaneous use - int _numFrames; // How many frames the object has -}; - -} // End of namespace Sherlock - -#endif -- cgit v1.2.3 From 43381e98197f8adb5ee73f8dc05c81b972fedeae Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 20 Mar 2015 07:54:39 -0400 Subject: SHERLOCK: Further scene loading code --- engines/sherlock/objects.cpp | 38 ++++++++++++++++-- engines/sherlock/objects.h | 19 +++++++-- engines/sherlock/scene.cpp | 95 ++++++++++++++++++++++++++++++++++++++------ engines/sherlock/scene.h | 5 ++- 4 files changed, 136 insertions(+), 21 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index 2386c00686..73e6397b50 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -101,7 +101,10 @@ void Object::synchronize(Common::SeekableReadStream &s) { _sequences = nullptr; _images = nullptr; _imageFrame = nullptr; - s.seek(16, SEEK_CUR); + + s.skip(4); + _sequenceOffset = s.readUint32LE(); + s.seek(8, SEEK_CUR); _walkCount = s.readByte(); _allow = s.readByte(); @@ -133,7 +136,7 @@ void Object::synchronize(Common::SeekableReadStream &s) { _aOpen.synchronize(s); _aType = s.readByte(); _lookFrames = s.readByte(); - _seqcounter = s.readByte(); + _seqCounter = s.readByte(); _lookPosition.x = s.readUint16LE(); _lookPosition.y = s.readByte(); _lookFacing = s.readByte(); @@ -141,7 +144,7 @@ void Object::synchronize(Common::SeekableReadStream &s) { _aClose.synchronize(s); _seqStack = s.readByte(); _seqTo = s.readByte(); - _descOfs = s.readUint16LE(); + _descOffset = s.readUint16LE(); _seqcounter2 = s.readByte(); _seqSize = s.readUint16LE(); s.skip(1); @@ -152,4 +155,33 @@ void Object::synchronize(Common::SeekableReadStream &s) { _use[idx].synchronize(s); } +/*----------------------------------------------------------------*/ + +void CAnim::synchronize(Common::SeekableReadStream &s) { + char buffer[12]; + s.read(buffer, 12); + _name = Common::String(buffer); + + s.read(_sequences, 30); + _position.x = s.readSint16LE(); + _position.y = s.readSint16LE(); + _size = s.readUint32LE(); + _type = (SpriteType)s.readUint16LE(); + _flags = s.readByte(); + _goto.x = s.readSint16LE(); + _goto.y = s.readSint16LE(); + _sequenceNumber = s.readSint16LE(); + _teleportPos.x = s.readSint16LE(); + _teleportPos.y = s.readSint16LE(); + _teleportS = s.readSint16LE(); +} + +/*----------------------------------------------------------------*/ + +InvGraphicType::InvGraphicType() { + _images = nullptr; + _maxFrames = 0; + _filesize = 0; +} + } // End of namespace Sherlock diff --git a/engines/sherlock/objects.h b/engines/sherlock/objects.h index f730240479..31d9520932 100644 --- a/engines/sherlock/objects.h +++ b/engines/sherlock/objects.h @@ -104,8 +104,9 @@ struct UseType { struct Object { Common::String _name; // Name Common::String _description; // Description - Common::StringArray _examine; // Examine in-depth description - uint8 (*_sequences)[MAX_HOLMES_SEQUENCE][MAX_FRAME]; // Holds animation sequences + Common::String _examine; // Examine in-depth description + int _sequenceOffset; + uint8 *_sequences; // Holds animation sequences ImageFile *_images; // Sprite images ImageFrame *_imageFrame; // Pointer to shape in the images int _walkCount; // Character walk counter @@ -132,14 +133,14 @@ struct Object { ActionType _aOpen; // Holds data for moving object int _aType; // Tells if this is an object, person, talk, etc. int _lookFrames; // How many frames to play of the look anim before pausing - int _seqcounter; // How many times this sequence has been executed + int _seqCounter; // How many times this sequence has been executed Common::Point _lookPosition; // Where to walk when examining object int _lookFacing; // Direction to face when examining object int _lookcAnim; ActionType _aClose; int _seqStack; // Allows gosubs to return to calling frame int _seqTo; // Allows 1-5, 8-3 type sequences encoded in 2 bytes - uint _descOfs; // Tells where description starts in DescText + uint _descOffset; // Tells where description starts in DescText int _seqcounter2; // Counter of calling frame sequence uint _seqSize; // Tells where description starts ActionType _aMove; @@ -159,8 +160,18 @@ struct CAnim { int _sequenceNumber; Common::Point _teleportPos; // Location Holmes shoul teleport to after int _teleportS; // playing canim + + void synchronize(Common::SeekableReadStream &s); }; +struct InvGraphicType { + ImageFile *_images; // Object images + int _maxFrames; // How many frames in object + int _filesize; // File size + + InvGraphicType(); +} ; + } // End of namespace Sherlock #endif diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 267b02b43c..ffae6f60c1 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -38,7 +38,7 @@ void BgFileHeader::synchronize(Common::SeekableReadStream &s) { /*----------------------------------------------------------------*/ void BgfileheaderInfo::synchronize(Common::SeekableReadStream &s) { - _fSize = s.readUint32LE(); + _filesize = s.readUint32LE(); _maxFrames = s.readByte(); char buffer[9]; @@ -71,6 +71,15 @@ Scene::Scene(SherlockEngine *vm): _vm(vm) { Scene::~Scene() { delete _controls; + clear(); +} + +/** + * Takes care of clearing any scene data + */ +void Scene::clear() { + for (uint idx = 0; idx < _bgShapes.size(); ++idx) + delete _bgShapes[idx]._images; } void Scene::selectScene() { @@ -108,6 +117,7 @@ void Scene::loadScene(const Common::String &filename) { _roomBounds.clear(); _roomBounds.push_back(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); + clear(); _descText.clear(); _comments = ""; _bgShapes.clear(); @@ -131,8 +141,6 @@ void Scene::loadScene(const Common::String &filename) { rrmStream->seek(rrmStream->readUint32LE()); BgFileHeader bgHeader; bgHeader.synchronize(*rrmStream); - - _cAnim.resize(bgHeader._numcAnimations); _invGraphicItems = bgHeader._numImages + 1; // Read in the shapes header info @@ -142,20 +150,13 @@ void Scene::loadScene(const Common::String &filename) { for (uint idx = 0; idx < bgInfo.size(); ++idx) bgInfo[idx].synchronize(*rrmStream); - // Initialize the cAnim - for (uint idx = 0; idx < _cAnim.size(); ++idx) { - _cAnim[idx]._position.x = -1; - _cAnim[idx]._goto.x = -1; - _cAnim[idx]._teleportPos.x = -1; - } - // Read information Common::SeekableReadStream *infoStream = !_lzwMode ? rrmStream : decompressLZ(*rrmStream, bgHeader._numImages * 569 + bgHeader._descSize + bgHeader._seqSize); - _bgShapes.resize(bgHeader._numStructs); - for (uint idx = 0; idx < _bgShapes.size(); ++idx) + _bgShapes.resize(bgHeader._numStructs + 1); + for (int idx = 0; idx < bgHeader._numStructs; ++idx) _bgShapes[idx].synchronize(*infoStream); if (bgHeader._descSize) { @@ -171,11 +172,79 @@ void Scene::loadScene(const Common::String &filename) { if (_lzwMode) delete infoStream; - // Load shapes + // Set up inv list + _inv.resize(bgHeader._numImages + 1); + for (int idx = 0; idx < bgHeader._numImages; ++idx) { + _inv[idx + 1]._filesize = bgInfo[idx]._filesize; + _inv[idx + 1]._maxFrames = bgInfo[idx]._maxFrames; + + // Read in the image data + Common::SeekableReadStream *imageStream = !_lzwMode ? rrmStream : + decompressLZ(*rrmStream, bgInfo[idx]._filesize); + + _inv[idx + 1]._images = new ImageFile(*imageStream); + + if (_lzwMode) + delete imageStream; + } + + // Set up the bgShapes + for (int idx = 0; idx < bgHeader._numStructs; ++idx) { + _bgShapes[idx]._examine = Common::String(&_descText[_bgShapes[idx]._descOffset]); + _bgShapes[idx]._sequences = &_sequenceBuffer[_bgShapes[idx]._sequenceOffset]; + _bgShapes[idx]._misc = 0; + _bgShapes[idx]._seqCounter = 0; + _bgShapes[idx]._seqcounter2 = 0; + _bgShapes[idx]._seqStack = 0; + _bgShapes[idx]._frameNumber = -1; + _bgShapes[idx]._position = Common::Point(0, 0); + _bgShapes[idx]._oldSize = Common::Point(1, 1); + + _bgShapes[idx]._images = _inv[_bgShapes[idx]._misc]._images; + _bgShapes[idx]._imageFrame = !_bgShapes[idx]._images ? (ImageFrame *)nullptr : + &(*_bgShapes[idx]._images)[0]; + } + + // Set up end of list + _bgShapes[bgHeader._numStructs]._sequences = &_sequenceBuffer[0] + bgHeader._seqSize; + _bgShapes[bgHeader._numStructs]._examine = nullptr; + + // Load in cAnim list + Common::SeekableReadStream *canimStream = !_lzwMode ? rrmStream : + decompressLZ(*rrmStream, 65 * bgHeader._numcAnimations); + + _cAnim.resize(bgHeader._numcAnimations); + for (uint idx = 0; idx < _cAnim.size(); ++idx) + _cAnim[idx].synchronize(*canimStream); + + if (_lzwMode) + delete canimStream; + + // Read in the room bounding areas + int size = rrmStream->readUint16LE(); + Common::SeekableReadStream *boundsStream = !_lzwMode ? rrmStream : + decompressLZ(*rrmStream, size); + + _roomBounds.resize(size / 10); + for (uint idx = 0; idx < _roomBounds.size(); ++idx) { + _roomBounds[idx].left = boundsStream->readSint16LE(); + _roomBounds[idx].top = boundsStream->readSint16LE(); + _roomBounds[idx].setWidth(boundsStream->readSint16LE()); + _roomBounds[idx].setHeight(boundsStream->readSint16LE()); + boundsStream->skip(2); // Skip unused scene number field + } + + if (_lzwMode) + delete boundsStream; + + // Back at version byte, so skip over it + rrmStream->skip(1); + // TODO delete rrmStream; } + } } // End of namespace Sherlock diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h index e216c2bd9d..2280e169b7 100644 --- a/engines/sherlock/scene.h +++ b/engines/sherlock/scene.h @@ -47,7 +47,7 @@ struct BgFileHeader { }; struct BgfileheaderInfo { - int _fSize; // How long images are + int _filesize; // How long images are int _maxFrames; // How many unique frames in object Common::String _filename; // Filename of object @@ -85,10 +85,13 @@ public: Common::Array _bgShapes; Common::Array _cAnim; Common::Array _sequenceBuffer; + Common::Array _inv; public: Scene(SherlockEngine *vm); ~Scene(); + void clear(); + void selectScene(); }; -- cgit v1.2.3 From 84631468561c3df20cfd073d20c35344be4c6f3f Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Fri, 20 Mar 2015 15:30:58 +0100 Subject: SCI: SQ1VGA: added script patch for bug #6816 fixes SQ1VGA Ulence Flats force field generator script glitch --- engines/sci/engine/script_patches.cpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'engines') diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp index 45e0155950..5c0e84fa01 100644 --- a/engines/sci/engine/script_patches.cpp +++ b/engines/sci/engine/script_patches.cpp @@ -2501,6 +2501,29 @@ static const uint16 sq1vgaPatchUlenceFlatsTimepodGfxGlitch[] = { PATCH_END }; +// In Ulence Flats, there is a space ship, that you will use at some point. +// Near that space ship are 2 force field generators. +// When you look at the top of those generators, the game will crash. +// This happens also in Sierra SCI. It's caused by a jump, that goes out of bounds. +// We currently do not know if this was caused by a compiler glitch or if it was a developer error. +// Anyway we patch this glitchy code, so that the game won't crash anymore. +// +// Applies to at least: English Floppy +// Responsible method: radar1::doVerb +// Fixes bug: #6816 +static const uint16 sq1vgaSignatureUlenceFlatsGeneratorGlitch[] = { + SIG_MAGICDWORD, 0x1a, // eq? + 0x30, SIG_UINT16(0xcdf4), // bnt absolute 0xf000 + SIG_END +}; + +static const uint16 sq1vgaPatchUlenceFlatsGeneratorGlitch[] = { + PATCH_ADDTOOFFSET(+1), + 0x32, PATCH_UINT16(0x0000), // jmp 0x0000 (waste bytes) + PATCH_END +}; + +// No documentation for this patch (TODO) static const uint16 sq1vgaSignatureEgoShowsCard[] = { SIG_MAGICDWORD, 0x38, SIG_SELECTOR16(timesShownID), // push "timesShownID" @@ -2625,6 +2648,7 @@ static const uint16 sq1vgaPatchSpiderDroidTiming[] = { // script, description, signature patch static const SciScriptPatcherEntry sq1vgaSignatures[] = { { true, 45, "Ulence Flats: timepod graphic glitch", 1, sq1vgaSignatureUlenceFlatsTimepodGfxGlitch, sq1vgaPatchUlenceFlatsTimepodGfxGlitch }, + { true, 45, "Ulence Flats: force field generator glitch", 1, sq1vgaSignatureUlenceFlatsGeneratorGlitch, sq1vgaPatchUlenceFlatsGeneratorGlitch }, { true, 58, "Sarien armory droid zapping ego first time", 1, sq1vgaSignatureEgoShowsCard, sq1vgaPatchEgoShowsCard }, { true, 704, "spider droid timing issue", 1, sq1vgaSignatureSpiderDroidTiming, sq1vgaPatchSpiderDroidTiming }, SCI_SIGNATUREENTRY_TERMINATOR -- cgit v1.2.3 From 7f9f3051117d0101088c368c925e8f40d909dc6d Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Fri, 20 Mar 2015 16:06:19 +0100 Subject: SCI: improve debug output for signature mismatch dump parameter list to debugger as well --- engines/sci/engine/kernel.cpp | 45 ++++++++++++++++++++++++++----------------- engines/sci/engine/kernel.h | 2 +- engines/sci/engine/vm.cpp | 18 +++++++++++------ 3 files changed, 40 insertions(+), 25 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 2b16bb3d99..bfb7bfcd08 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -432,57 +432,66 @@ static const SignatureDebugType signatureDebugTypeList[] = { { 0, NULL } }; -static void kernelSignatureDebugType(const uint16 type) { +static void kernelSignatureDebugType(Common::String &signatureDetailsStr, const uint16 type) { bool firstPrint = true; const SignatureDebugType *list = signatureDebugTypeList; while (list->typeCheck) { if (type & list->typeCheck) { if (!firstPrint) - debugN(", "); - debugN("%s", list->text); +// debugN(", "); + signatureDetailsStr += ", "; +// debugN("%s", list->text); +// signatureDetailsStr += signatureDetailsStr.format("%s", list->text); + signatureDetailsStr += list->text; firstPrint = false; } list++; } } -// Shows kernel call signature and current arguments for debugging purposes -void Kernel::signatureDebug(const uint16 *sig, int argc, const reg_t *argv) { +// Create string, that holds the details of a kernel call signature and current arguments +// For debugging purposes +void Kernel::signatureDebug(Common::String &signatureDetailsStr, const uint16 *sig, int argc, const reg_t *argv) { int argnr = 0; + + // add ERROR: to debug output + debugN("ERROR:"); + while (*sig || argc) { - debugN("parameter %d: ", argnr++); + // add leading spaces for additional parameters + signatureDetailsStr += signatureDetailsStr.format("parameter %d: ", argnr++); if (argc) { reg_t parameter = *argv; - debugN("%04x:%04x (", PRINT_REG(parameter)); + signatureDetailsStr += signatureDetailsStr.format("%04x:%04x (", PRINT_REG(parameter)); int regType = findRegType(parameter); if (regType) - kernelSignatureDebugType(regType); + kernelSignatureDebugType(signatureDetailsStr, regType); else - debugN("unknown type of %04x:%04x", PRINT_REG(parameter)); - debugN(")"); + signatureDetailsStr += signatureDetailsStr.format("unknown type of %04x:%04x", PRINT_REG(parameter)); + signatureDetailsStr += ")"; argv++; argc--; } else { - debugN("not passed"); + signatureDetailsStr += "not passed"; } if (*sig) { const uint16 signature = *sig; if ((signature & SIG_MAYBE_ANY) == SIG_MAYBE_ANY) { - debugN(", may be any"); + signatureDetailsStr += ", may be any"; } else { - debugN(", should be "); - kernelSignatureDebugType(signature); + signatureDetailsStr += ", should be "; + kernelSignatureDebugType(signatureDetailsStr, signature); } if (signature & SIG_IS_OPTIONAL) - debugN(" (optional)"); + signatureDetailsStr += " (optional)"; if (signature & SIG_NEEDS_MORE) - debugN(" (needs more)"); + signatureDetailsStr += " (needs more)"; if (signature & SIG_MORE_MAY_FOLLOW) - debugN(" (more may follow)"); + signatureDetailsStr += " (more may follow)"; sig++; } - debugN("\n"); + signatureDetailsStr += "\n"; } } diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index a65bcb7df5..57b4d9455b 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -186,7 +186,7 @@ public: bool signatureMatch(const uint16 *sig, int argc, const reg_t *argv); // Prints out debug information in case a signature check fails - void signatureDebug(const uint16 *sig, int argc, const reg_t *argv); + void signatureDebug(Common::String &signatureDetails, const uint16 *sig, int argc, const reg_t *argv); /** * Determines the type of the object indicated by reg. diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 06858540ec..6f02c96de8 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -358,12 +358,15 @@ static void callKernelFunc(EngineState *s, int kernelCallNr, int argc) { SciTrackOriginReply originReply; SciWorkaroundSolution solution = trackOriginAndFindWorkaround(0, kernelCall.workarounds, &originReply); switch (solution.type) { - case WORKAROUND_NONE: - kernel->signatureDebug(kernelCall.signature, argc, argv); - error("[VM] k%s[%x]: signature mismatch via method %s::%s (room %d, script %d, localCall 0x%x)", + case WORKAROUND_NONE: { + Common::String signatureDetailsStr; + kernel->signatureDebug(signatureDetailsStr, kernelCall.signature, argc, argv); + error("\n%s[VM] k%s[%x]: signature mismatch in method %s::%s (room %d, script %d, localCall 0x%x)", + signatureDetailsStr.c_str(), kernelCall.name, kernelCallNr, originReply.objectName.c_str(), originReply.methodName.c_str(), s->currentRoomNumber(), originReply.scriptNr, originReply.localCallOffset); break; + } case WORKAROUND_IGNORE: // don't do kernel call, leave acc alone return; case WORKAROUND_STILLCALL: // call kernel anyway @@ -408,15 +411,18 @@ static void callKernelFunc(EngineState *s, int kernelCallNr, int argc) { SciWorkaroundSolution solution = trackOriginAndFindWorkaround(0, kernelSubCall.workarounds, &originReply); switch (solution.type) { case WORKAROUND_NONE: { - kernel->signatureDebug(kernelSubCall.signature, argc, argv); + Common::String signatureDetailsStr; + kernel->signatureDebug(signatureDetailsStr, kernelSubCall.signature, argc, argv); int callNameLen = strlen(kernelCall.name); if (strncmp(kernelCall.name, kernelSubCall.name, callNameLen) == 0) { const char *subCallName = kernelSubCall.name + callNameLen; - error("[VM] k%s(%s): signature mismatch via method %s::%s (room %d, script %d, localCall %x)", + error("\n%s[VM] k%s(%s): signature mismatch in method %s::%s (room %d, script %d, localCall %x)", + signatureDetailsStr.c_str(), kernelCall.name, subCallName, originReply.objectName.c_str(), originReply.methodName.c_str(), s->currentRoomNumber(), originReply.scriptNr, originReply.localCallOffset); } - error("[VM] k%s: signature mismatch via method %s::%s (room %d, script %d, localCall %x)", + error("\n%s[VM] k%s: signature mismatch in method %s::%s (room %d, script %d, localCall %x)", + signatureDetailsStr.c_str(), kernelSubCall.name, originReply.objectName.c_str(), originReply.methodName.c_str(), s->currentRoomNumber(), originReply.scriptNr, originReply.localCallOffset); break; -- cgit v1.2.3 From 1f65284ada41b7156b5d68507fcdad6255694140 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Fri, 20 Mar 2015 23:58:47 +0100 Subject: SCI: QFG1VGA: added script patch fixes bug #6706 fixes healer's hut buy/steal issue effectively removes 60 tick delay from script --- engines/sci/engine/script_patches.cpp | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'engines') diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp index 5c0e84fa01..b6b9f72996 100644 --- a/engines/sci/engine/script_patches.cpp +++ b/engines/sci/engine/script_patches.cpp @@ -2140,6 +2140,7 @@ static const uint16 qfg1vgaPatchCheetaurDescription[] = { // Local 5 of that room is a timer, that closes the door (object door11). // Setting it to 1 during happyFace::changeState(0) stops door11::doit from // calling goTo6::init, so the whole issue is stopped from happening. +// // Applies to at least: English floppy // Responsible method: happyFace::changeState, door11::doit // Fixes bug #6181 @@ -2166,8 +2167,40 @@ static const uint16 qfg1vgaPatchFunnyRoomFix[] = { PATCH_END }; +// The player is able to buy (and also steal) potions in the healer's hut +// Strangely Sierra delays the actual buy/get potion code for 60 ticks +// Why they did that is unknown. The code is triggered anyway only after +// the relevant dialog boxes are closed. +// +// This delay causes problems in case the user quickly enters the inventory. +// That's why we remove the code related to the delay completely. +// +// Applies to at least: English floppy +// Responsible method: cueItScript::changeState +// Fixes bug #6706 +static const uint16 qfg1vgaSignatureHealerHutNoDelay[] = { + 0x65, 0x14, // aTop 14 (state) + 0x36, // push + 0x3c, // dup + 0x35, 0x00, // ldi 00 + 0x1a, // eq? + 0x31, 0x07, // bnt 07 [-> next state] + SIG_MAGICDWORD, + 0x35, 0x3c, // ldi 3c (60 ticks) + 0x65, 0x20, // aTop ticks + 0x32, // jmp [-> end of method] + SIG_END +}; + +static const uint16 qfg1vgaPatchHealerHutNoDelay[] = { + PATCH_ADDTOOFFSET(+9), + 0x35, 0x01, // ldi 01 (1 tick only, so that execution will resume as soon as dialog box is closed) + PATCH_END +}; + // script, description, signature patch static const SciScriptPatcherEntry qfg1vgaSignatures[] = { + { true, 55, "healer's hut, no delay for buy/steal", 1, qfg1vgaSignatureHealerHutNoDelay, qfg1vgaPatchHealerHutNoDelay }, { true, 215, "fight event issue", 1, qfg1vgaSignatureFightEvents, qfg1vgaPatchFightEvents }, { true, 216, "weapon master event issue", 1, qfg1vgaSignatureFightEvents, qfg1vgaPatchFightEvents }, { true, 814, "window text temp space", 1, qfg1vgaSignatureTempSpace, qfg1vgaPatchTempSpace }, -- cgit v1.2.3 From 4550e8c5ef0429e1c917d455049419871acfabec Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 21 Mar 2015 00:05:22 +0100 Subject: SCI: fix script patch description --- engines/sci/engine/script_patches.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp index b6b9f72996..711078d29c 100644 --- a/engines/sci/engine/script_patches.cpp +++ b/engines/sci/engine/script_patches.cpp @@ -2173,7 +2173,8 @@ static const uint16 qfg1vgaPatchFunnyRoomFix[] = { // the relevant dialog boxes are closed. // // This delay causes problems in case the user quickly enters the inventory. -// That's why we remove the code related to the delay completely. +// That's why we change the amount of ticks to 1, so that the remaining states +// are executed right after the dialog boxes are closed. // // Applies to at least: English floppy // Responsible method: cueItScript::changeState -- cgit v1.2.3 From cf92e540db2d58f243abe595da40a7da4450911f Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 20 Mar 2015 19:44:32 -0400 Subject: SHERLOCK: More scene loading code and support methods --- engines/sherlock/objects.cpp | 37 +++++++- engines/sherlock/objects.h | 26 +++++- engines/sherlock/scene.cpp | 196 ++++++++++++++++++++++++++++++++++++++++-- engines/sherlock/scene.h | 48 ++++++++++- engines/sherlock/screen.cpp | 2 + engines/sherlock/screen.h | 3 + engines/sherlock/sherlock.cpp | 1 + engines/sherlock/sherlock.h | 2 + engines/sherlock/sound.cpp | 4 + engines/sherlock/sound.h | 1 + 10 files changed, 308 insertions(+), 12 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index 73e6397b50..aa9b391f96 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -134,7 +134,7 @@ void Object::synchronize(Common::SeekableReadStream &s) { _maxFrames = s.readUint16LE(); _flags = s.readByte(); _aOpen.synchronize(s); - _aType = s.readByte(); + _aType = (AType)s.readByte(); _lookFrames = s.readByte(); _seqCounter = s.readByte(); _lookPosition.x = s.readUint16LE(); @@ -155,6 +155,41 @@ void Object::synchronize(Common::SeekableReadStream &s) { _use[idx].synchronize(s); } +void Object::toggleHidden() { + if (_type != HIDDEN && _type != HIDE_SHAPE && _type != INVALID) { + if (_seqTo != 0) + _sequences[_frameNumber] = _seqTo + SEQ_TO_CODE + 128; + _seqTo = 0; + + if (_images == nullptr || _images->size() == 0) + // No shape to erase, so flag as hidden + _type = HIDDEN; + else + // Otherwise, flag it to be hidden after it gets erased + _type = HIDE_SHAPE; + } else if (_type != INVALID) { + if (_seqTo != 0) + _sequences[_frameNumber] = _seqTo + SEQ_TO_CODE + 128; + _seqTo = 0; + + _seqCounter = _seqcounter2 = 0; + _seqStack = 0; + _frameNumber = -1; + + if (_images == nullptr || _images->size() == 0) { + _type = NO_SHAPE; + } else { + _type = ACTIVE_BG_SHAPE; + int idx = _sequences[0]; + if (idx >= _maxFrames) + // Turn on: set up first frame + idx = 0; + + _imageFrame = &(*_images)[idx]; + } + } +} + /*----------------------------------------------------------------*/ void CAnim::synchronize(Common::SeekableReadStream &s) { diff --git a/engines/sherlock/objects.h b/engines/sherlock/objects.h index 31d9520932..f3879b1143 100644 --- a/engines/sherlock/objects.h +++ b/engines/sherlock/objects.h @@ -49,9 +49,31 @@ enum SpriteType { HIDE_SHAPE = 8 // Object needs to be hidden }; +enum AType { + OBJECT = 0, + PERSON = 1, + SOLID = 2, + TALK = 3, // Standard talk zone + FLAG_SET = 4, + DELTA = 5, + WALK_AROUND = 6, + TALK_EVERY = 7, // Talk zone that turns on every room visit + TALK_MOVE = 8, // Talk zone that only activates when Holmes moves + PAL_CHANGE = 9, // Changes the palette down so that it gets darker + PAL_CHANGE2 = 10, // Same as PAL_CHANGE, except that it goes up + SCRIPT_ZONE = 11, // If this is clicked in, it is activated + BLANK_ZONE = 12, // This masks out other objects when entered + NOWALK_ZONE = 13 // Player cannot walk here +}; + #define MAX_HOLMES_SEQUENCE 16 #define MAX_FRAME 30 +// code put into sequences to defines 1-10 type seqs +#define SEQ_TO_CODE 67 +#define FLIP_CODE (64 + 128) +#define SOUND_CODE (34 + 128) + struct Sprite { Common::String _name; // Name Common::String _description; // Description @@ -131,7 +153,7 @@ struct Object { int _maxFrames; // Number of frames int _flags; // Tells if object can be walked behind ActionType _aOpen; // Holds data for moving object - int _aType; // Tells if this is an object, person, talk, etc. + AType _aType; // Tells if this is an object, person, talk, etc. int _lookFrames; // How many frames to play of the look anim before pausing int _seqCounter; // How many times this sequence has been executed Common::Point _lookPosition; // Where to walk when examining object @@ -147,6 +169,8 @@ struct Object { UseType _use[4]; void synchronize(Common::SeekableReadStream &s); + + void toggleHidden(); }; struct CAnim { diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index ffae6f60c1..86e347d011 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -46,18 +46,47 @@ void BgfileheaderInfo::synchronize(Common::SeekableReadStream &s) { _filename = Common::String(buffer); } -int _fSize; // How long images are -int _maxFrames; // How many unique frames in object -Common::String _filename; // Filename of object +/*----------------------------------------------------------------*/ + +void Exit::synchronize(Common::SeekableReadStream &s) { + _position.x = s.readSint16LE(); + _position.y = s.readSint16LE(); + _size.x = s.readSint16LE(); + _size.y = s.readSint16LE(); + _scene = s.readSint16LE(); + _allow = s.readSint16LE(); + _people.x = s.readSint16LE(); + _people.y = s.readSint16LE(); + _peopleDir = s.readUint16LE(); +} + +/*----------------------------------------------------------------*/ + +void SceneEntry::synchronize(Common::SeekableReadStream &s) { + _startPosition.x = s.readSint16LE(); + _startPosition.y = s.readSint16LE(); + _startDir = s.readByte(); + _allow = s.readByte(); +} + +void SceneSound::synchronize(Common::SeekableReadStream &s) { + char buffer[9]; + s.read(buffer, 8); + buffer[8] = '\0'; + + _name = Common::String(buffer); + _priority = s.readByte(); +} /*----------------------------------------------------------------*/ Scene::Scene(SherlockEngine *vm): _vm(vm) { for (int idx = 0; idx < SCENES_COUNT; ++idx) Common::fill(&_stats[idx][0], &_stats[idx][9], false); + _currentScene = -1; _goToRoom = -1; + _changes = false; _oldCharPoint = 0; - _numExits = 0; _windowOpen = _infoFlag = false; _menuMode = _keyboardInput = 0; _walkedInScene = false; @@ -66,10 +95,12 @@ Scene::Scene(SherlockEngine *vm): _vm(vm) { _lzwMode = false; _invGraphicItems = 0; + _controlPanel = new ImageFile("controls.vgs"); _controls = nullptr; // new ImageFile("menu.all"); } Scene::~Scene() { + delete _controlPanel; delete _controls; clear(); } @@ -78,13 +109,10 @@ Scene::~Scene() { * Takes care of clearing any scene data */ void Scene::clear() { - for (uint idx = 0; idx < _bgShapes.size(); ++idx) - delete _bgShapes[idx]._images; } void Scene::selectScene() { // Reset fields - _numExits = 0; _windowOpen = _infoFlag = false; _menuMode = _keyboardInput = 0; _oldKey = _help = _oldHelp = 0; @@ -93,6 +121,7 @@ void Scene::selectScene() { // Load the scene Common::String sceneFile = Common::String::format("res%02d", _goToRoom); Common::String roomName = Common::String::format("res%02d.rrm", _goToRoom); + _currentScene = _goToRoom; _goToRoom = -1; loadScene(sceneFile); @@ -108,6 +137,8 @@ void Scene::selectScene() { * that it should point to after loading; _misc is then set to 0. */ void Scene::loadScene(const Common::String &filename) { + Screen &screen = *_vm->_screen; + Sound &sound = *_vm->_sound; bool flag; _walkedInScene = false; @@ -240,11 +271,160 @@ void Scene::loadScene(const Common::String &filename) { // Back at version byte, so skip over it rrmStream->skip(1); - // TODO + // Load the walk directory + for (int idx1 = 0; idx1 < MAX_ZONES; ++idx1) { + for (int idx2 = 0; idx2 < MAX_ZONES; ++idx2) + _walkDirectory[idx1][idx2] = rrmStream->readSint16LE(); + } + + // Read in the walk data + size = rrmStream->readUint16LE(); + Common::SeekableReadStream *walkStream = !_lzwMode ? rrmStream : + decompressLZ(*rrmStream, size); + + _walkData.resize(size); + walkStream->read(&_walkData[0], size); + + if (_lzwMode) + delete walkStream; + + // Read in the exits + int numExits = rrmStream->readByte(); + _exits.resize(numExits); + + for (int idx = 0; idx < numExits; ++idx) + _exits[idx].synchronize(*rrmStream); + + // Read in the entrance + _entrance.synchronize(*rrmStream); + + // Initialize sound list + int numSounds = rrmStream->readByte(); + _sounds.resize(numSounds); + + for (int idx = 0; idx < numSounds; ++idx) + _sounds[idx].synchronize(*rrmStream); + + // If sound is turned on, load the sounds into memory + if (sound._sfxEnabled) { + for (int idx = 0; idx < numSounds; ++idx) { + sound.loadSound(_sounds[idx]._name, _sounds[idx]._priority); + _sounds[idx]._name = ""; + } + } + + // Read in palette + rrmStream->read(screen._cMap, PALETTE_SIZE); + for (int idx = 0; idx < PALETTE_SIZE; ++idx) + screen._cMap[idx] = VGA_COLOR_TRANS(screen._cMap[idx]); + + Common::copy(screen._cMap, screen._cMap + PALETTE_SIZE, screen._sMap); + + // Read in the background + Common::SeekableReadStream *bgStream = !_lzwMode ? rrmStream : + decompressLZ(*rrmStream, SHERLOCK_SCREEN_WIDTH * SHERLOCK_SCENE_HEIGHT); + + bgStream->read(screen._backBuffer.getPixels(), SHERLOCK_SCREEN_WIDTH * SHERLOCK_SCENE_HEIGHT); + + if (_lzwMode) + delete bgStream; + + // Set the palette + screen._backBuffer2.blitFrom(screen._backBuffer); + screen.setPalette(screen._cMap); delete rrmStream; } + // Clear user interface area and draw controls + screen._backBuffer2.fillRect(0, INFO_LINE, SHERLOCK_SCREEN_WIDTH, INFO_LINE + 10, INFO_BLACK); + screen._backBuffer.transBlitFrom((*_controlPanel)[0], Common::Point(0, CONTROLS_Y)); + screen._backBuffer2.transBlitFrom((*_controlPanel)[0], Common::Point(0, CONTROLS_Y)); + + _changes = false; + checkSceneStatus(); + + if (!_vm->_justLoaded) { + for (uint idx = 0; idx < _bgShapes.size(); ++idx) { + if (_bgShapes[idx]._type == HIDDEN && _bgShapes[idx]._aType == TALK_EVERY) + _bgShapes[idx].toggleHidden(); + } + + // Check for TURNON objects + for (uint idx = 0; idx < _bgShapes.size(); ++idx) { + if (_bgShapes[idx]._type == HIDDEN && (_bgShapes[idx]._flags & 0x20)) + _bgShapes[idx].toggleHidden(); + } + + // Check for TURNOFF objects + for (uint idx = 0; idx < _bgShapes.size(); ++idx) { + if (_bgShapes[idx]._type != HIDDEN && (_bgShapes[idx]._flags & 0x40) && + _bgShapes[idx]._type != INVALID) + _bgShapes[idx].toggleHidden(); + } + } + + checkSceneFlags(false); + checkInventory(); + + // TODO +} + +/** + * Set objects to their current persistent state. This includes things such as + * opening or moving them + */ +void Scene::checkSceneStatus() { + if (_stats[_currentScene][8]) { + for (int idx = 0; idx < 8; ++idx) { + int val = _stats[_currentScene][idx]; + + for (int bit = 0; bit < 8; ++bit) { + uint objNumber = idx * 8 + bit; + if (objNumber < _bgShapes.size()) { + Object &obj = _bgShapes[objNumber]; + + if (val & 1) { + // No shape to erase, so flag as hidden + obj._type = HIDDEN; + } else if (obj._images == nullptr || obj._images->size() == 0) { + // No shape + obj._type = NO_SHAPE; + } else { + obj._type = ACTIVE_BG_SHAPE; + } + } else { + // Finished checks + return; + } + + val >>= 1; + } + } + } +} + +/** + * Check the scene's objects against the game flags. If false is passed, + * it means the scene has just been loaded. A value of true means that the scene + * is in use (ie. not just loaded) + */ +void Scene::checkSceneFlags(bool flag) { + int mode = mode ? HIDE_SHAPE : HIDDEN; + + for (uint idx = 0; idx < _bgShapes.size(); ++idx) { + Object &o = _bgShapes[idx]; + // TODO: read_flags calls + } +} + +/** + * Checks scene objects against the player's inventory items. If there are any + * matching names, it means the given item has already been picked up, and should + * be hidden in the scene. + */ +void Scene::checkInventory() { + } } // End of namespace Sherlock diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h index 2280e169b7..ae4fcfdb45 100644 --- a/engines/sherlock/scene.h +++ b/engines/sherlock/scene.h @@ -32,6 +32,10 @@ namespace Sherlock { #define SCENES_COUNT 63 +#define MAX_ZONES 40 +#define INFO_LINE 140 +#define CONTROLS_Y 138 +#define CONTROLS_Y1 151 class SherlockEngine; @@ -54,6 +58,33 @@ struct BgfileheaderInfo { void synchronize(Common::SeekableReadStream &s); }; +struct Exit { + Common::Point _position; + Common::Point _size; + + int _scene; + int _allow; + Common::Point _people; + int _peopleDir; + + void synchronize(Common::SeekableReadStream &s); +}; + +struct SceneEntry { + Common::Point _startPosition; + int _startDir; + int _allow; + + void synchronize(Common::SeekableReadStream &s); +}; + +struct SceneSound { + Common::String _name; + int _priority; + + void synchronize(Common::SeekableReadStream &s); +}; + class Scene { private: SherlockEngine *_vm; @@ -61,15 +92,23 @@ private: void loadScene(); void loadScene(const Common::String &filename); + + void checkSceneStatus(); + + void checkSceneFlags(bool mode); + + void checkInventory(); public: + int _currentScene; + int _goToRoom; + bool _changes; bool _stats[SCENES_COUNT][9]; bool _savedStats[SCENES_COUNT][9]; - int _goToRoom; Common::Point _bigPos; Common::Point _overPos; int _oldCharPoint; ImageFile *_controls; - int _numExits; + ImageFile *_controlPanel; bool _windowOpen, _infoFlag; int _menuMode, _keyboardInput; int _oldKey, _help, _oldHelp; @@ -86,6 +125,11 @@ public: Common::Array _cAnim; Common::Array _sequenceBuffer; Common::Array _inv; + int _walkDirectory[MAX_ZONES][MAX_ZONES]; + Common::Array _walkData; + Common::Array _exits; + SceneEntry _entrance; + Common::Array _sounds; public: Scene(SherlockEngine *vm); ~Scene(); diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp index 0ec5df9c4c..b322b96d6b 100644 --- a/engines/sherlock/screen.cpp +++ b/engines/sherlock/screen.cpp @@ -32,6 +32,8 @@ Screen::Screen(SherlockEngine *vm) : Surface(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCR _backBuffer2(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT) { _transitionSeed = 1; _fadeStyle = false; + Common::fill(&_cMap[0], &_cMap[PALETTE_SIZE], 0); + Common::fill(&_sMap[0], &_sMap[PALETTE_SIZE], 0); setFont(1); } diff --git a/engines/sherlock/screen.h b/engines/sherlock/screen.h index 05fd80a8b7..2c5e585475 100644 --- a/engines/sherlock/screen.h +++ b/engines/sherlock/screen.h @@ -34,6 +34,7 @@ namespace Sherlock { #define PALETTE_SIZE 768 #define PALETTE_COUNT 256 #define VGA_COLOR_TRANS(x) ((x) * 255 / 63) +#define INFO_BLACK 1 class SherlockEngine; @@ -52,6 +53,8 @@ protected: public: Surface _backBuffer, _backBuffer2; bool _fadeStyle; + byte _cMap[PALETTE_SIZE]; + byte _sMap[PALETTE_SIZE]; public: Screen(SherlockEngine *vm); diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index a963d0bfe5..115d9f0130 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -43,6 +43,7 @@ SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gam _useEpilogue2 = false; _hsavedPos = Common::Point(-1, -1); _hsavedFs = -1; + _justLoaded = false; } SherlockEngine::~SherlockEngine() { diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h index 210e24c320..c31416f91e 100644 --- a/engines/sherlock/sherlock.h +++ b/engines/sherlock/sherlock.h @@ -59,6 +59,7 @@ enum { #define SHERLOCK_SCREEN_WIDTH 320 #define SHERLOCK_SCREEN_HEIGHT 200 +#define SHERLOCK_SCENE_HEIGHT 138 struct SherlockGameDescription; @@ -91,6 +92,7 @@ public: bool _useEpilogue2; Common::Point _hsavedPos; int _hsavedFs; + bool _justLoaded; public: SherlockEngine(OSystem *syst, const SherlockGameDescription *gameDesc); virtual ~SherlockEngine(); diff --git a/engines/sherlock/sound.cpp b/engines/sherlock/sound.cpp index efc1965637..61c740ea3f 100644 --- a/engines/sherlock/sound.cpp +++ b/engines/sherlock/sound.cpp @@ -32,6 +32,10 @@ Sound::Sound(SherlockEngine *vm): _vm(vm) { _music = false; } +void Sound::loadSound(const Common::String &name, int priority) { + // TODO +} + void Sound::playSound(const Common::String &name, WaitType waitType) { // TODO } diff --git a/engines/sherlock/sound.h b/engines/sherlock/sound.h index 442e908838..9d323833f1 100644 --- a/engines/sherlock/sound.h +++ b/engines/sherlock/sound.h @@ -46,6 +46,7 @@ public: public: Sound(SherlockEngine *vm); + void loadSound(const Common::String &name, int priority); void playSound(const Common::String &name, WaitType waitType = WAIT_RETURN_IMMEDIATELY); void cacheSound(const Common::String &name, int index); void playCachedSound(int index); -- cgit v1.2.3 From f0ad2f624bddcc031c99a487bff1d5ec89956477 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 20 Mar 2015 22:01:52 -0400 Subject: SHERLOCK: More scene loading, implemented Inventory class --- engines/sherlock/inventory.cpp | 27 ++++++++++ engines/sherlock/inventory.h | 18 +++++-- engines/sherlock/module.mk | 1 + engines/sherlock/objects.cpp | 6 +++ engines/sherlock/objects.h | 3 ++ engines/sherlock/people.cpp | 18 +++++++ engines/sherlock/people.h | 4 ++ engines/sherlock/scalpel/scalpel.cpp | 16 ++++++ engines/sherlock/scene.cpp | 96 ++++++++++++++++++++++++++++++++++-- engines/sherlock/scene.h | 10 ++-- engines/sherlock/sherlock.cpp | 24 +++++++++ engines/sherlock/sherlock.h | 9 ++++ 12 files changed, 218 insertions(+), 14 deletions(-) create mode 100644 engines/sherlock/inventory.cpp (limited to 'engines') diff --git a/engines/sherlock/inventory.cpp b/engines/sherlock/inventory.cpp new file mode 100644 index 0000000000..634e664f5a --- /dev/null +++ b/engines/sherlock/inventory.cpp @@ -0,0 +1,27 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "sherlock/inventory.h" + +namespace Sherlock { + +} // End of namespace Sherlock diff --git a/engines/sherlock/inventory.h b/engines/sherlock/inventory.h index de4a2d7758..dc56e93841 100644 --- a/engines/sherlock/inventory.h +++ b/engines/sherlock/inventory.h @@ -24,15 +24,23 @@ #define SHERLOCK_INVENTORY_H #include "common/scummsys.h" +#include "common/array.h" namespace Sherlock { struct InventoryItem { - int stringIndex; - char name[12]; - char description[41]; - char name2[9]; - uint16 value; + int _requiredFlag; + Common::String _name; + Common::String _description;; + Common::String _examine; + int _lookFlag; +}; + +class Inventory : public Common::Array { +public: + uint _holdings; + + Inventory() : Common::Array(), _holdings(0) {} }; } // End of namespace Sherlock diff --git a/engines/sherlock/module.mk b/engines/sherlock/module.mk index dc88ab3f5f..aa8f495742 100644 --- a/engines/sherlock/module.mk +++ b/engines/sherlock/module.mk @@ -11,6 +11,7 @@ MODULE_OBJS = \ detection.o \ events.o \ graphics.o \ + inventory.o \ journal.o \ objects.o \ people.o \ diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index aa9b391f96..d696954cda 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -51,6 +51,12 @@ void Sprite::clear() { _numFrames = 0; } +void Sprite::setImageFrame() { + // TODO: check this + int imageNumber = (*_sequences)[_sequenceNumber][_frameNumber]; + _imageFrame = &(*_images)[imageNumber]; +} + /*----------------------------------------------------------------*/ void ActionType::synchronize(Common::SeekableReadStream &s) { diff --git a/engines/sherlock/objects.h b/engines/sherlock/objects.h index f3879b1143..d43b70f4e9 100644 --- a/engines/sherlock/objects.h +++ b/engines/sherlock/objects.h @@ -100,7 +100,10 @@ struct Sprite { int _numFrames; // How many frames the object has Sprite() { clear(); } + void clear(); + + void setImageFrame(); }; struct ActionType { diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp index cdb498e5e6..b4bbef2e1a 100644 --- a/engines/sherlock/people.cpp +++ b/engines/sherlock/people.cpp @@ -46,6 +46,12 @@ static const uint8 CHARACTER_SEQUENCES[MAX_HOLMES_SEQUENCE][MAX_FRAME] = { People::People(SherlockEngine *vm) : _vm(vm) { + _walkLoaded = false; +} + +People::~People() { + if (_walkLoaded) + delete _data[PLAYER]._images; } void People::reset() { @@ -70,4 +76,16 @@ void People::reset() { p._status = 0; } +bool People::loadWalk() { + if (_walkLoaded) { + return false; + } else { + _data[PLAYER]._images = new ImageFile("walk.vgs"); + _data[PLAYER].setImageFrame(); + _walkLoaded = true; + + return true; + } +} + } // End of namespace Sherlock diff --git a/engines/sherlock/people.h b/engines/sherlock/people.h index 3f639a6d44..4bdc6a88f0 100644 --- a/engines/sherlock/people.h +++ b/engines/sherlock/people.h @@ -46,10 +46,14 @@ class People { private: SherlockEngine *_vm; Sprite _data[MAX_PEOPLE]; + bool _walkLoaded; public: People(SherlockEngine *vm); + ~People(); void reset(); + + bool loadWalk(); }; } // End of namespace Sherlock diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp index ca04153594..40ca9736d6 100644 --- a/engines/sherlock/scalpel/scalpel.cpp +++ b/engines/sherlock/scalpel/scalpel.cpp @@ -27,6 +27,18 @@ namespace Sherlock { namespace Scalpel { +#define NUM_PLACES 100 +const int MAP_X[NUM_PLACES] = { + 0, 368, 0, 219, 0, 282, 0, 43, 0, 0, 396, 408, 0, 0, 0, 568, 37, 325, + 28, 0, 263, 36, 148, 469, 342, 143, 443, 229, 298, 0, 157, 260, 432, + 174, 0, 351, 0, 528, 0, 136, 0, 0, 0, 555, 165, 0, 506, 0, 0, 344, 0, 0 +}; +const int MAP_Y[NUM_PLACES] = { + 0, 147, 0, 166, 0, 109, 0, 61, 0, 0, 264, 70, 0, 0, 0, 266, 341, 30, 275, + 0, 294, 146, 311, 230, 184, 268, 133, 94, 207, 0, 142, 142, 330, 255, 0, + 37, 0, 70, 0, 116, 0, 0, 0, 50, 21, 0, 303, 0, 0, 229, 0, 0 +}; + ScalpelEngine::ScalpelEngine(OSystem *syst, const SherlockGameDescription *gameDesc) : SherlockEngine(syst, gameDesc) { _chess = nullptr; @@ -53,6 +65,10 @@ void ScalpelEngine::initialize() { _flags[3] = true; // Turn on Alley _flags[39] = true; // Turn on Baker Street + // Load the map co-ordinates for each scene + for (int idx = 0; idx < NUM_PLACES; ++idx) + _map.push_back(Common::Point(MAP_X[idx], MAP_Y[idx])); + // Starting scene _scene->_goToRoom = 4; } diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 86e347d011..4ec5c29134 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -136,7 +136,9 @@ void Scene::selectScene() { * The _misc field of the structures contains the number of the graphic image * that it should point to after loading; _misc is then set to 0. */ -void Scene::loadScene(const Common::String &filename) { +bool Scene::loadScene(const Common::String &filename) { + EventsManager &events = *_vm->_events; + People &people = *_vm->_people; Screen &screen = *_vm->_screen; Sound &sound = *_vm->_sound; bool flag; @@ -367,7 +369,28 @@ void Scene::loadScene(const Common::String &filename) { checkSceneFlags(false); checkInventory(); - // TODO + // Handle starting any music for the scene + if (sound._musicEnabled && sound.loadSong(_currentScene)) { + if (sound._music) + sound.startSong(); + } + + // Load walking images if not already loaded + people.loadWalk(); + + // Transition to the scene and setup entrance co-ordinates and animations + transitionToScene(); + + // Player has not yet walked in this scene + _walkedInScene = false; + + // Reset the position on the overland map + _vm->_oldCharPoint = _currentScene; + _vm->_over.x = _vm->_map[_currentScene].x * 100 - 600; + _vm->_over.y = _vm->_map[_currentScene].y * 100 + 900; + + events.clearEvents(); + return flag; } /** @@ -410,11 +433,55 @@ void Scene::checkSceneStatus() { * is in use (ie. not just loaded) */ void Scene::checkSceneFlags(bool flag) { - int mode = mode ? HIDE_SHAPE : HIDDEN; + SpriteType mode = flag ? HIDE_SHAPE : HIDDEN; for (uint idx = 0; idx < _bgShapes.size(); ++idx) { Object &o = _bgShapes[idx]; - // TODO: read_flags calls + + if (o._requiredFlag) { + if (!_vm->readFlags(_bgShapes[idx]._requiredFlag)) { + // Kill object + if (o._type != HIDDEN && o._type != INVALID) { + if (o._images == nullptr || o._images->size() == 0) + // No shape to erase, so flag as hidden + o._type = HIDDEN; + else + // Flag it as needing to be hidden after first erasing it + o._type = mode; + } + } else if (_bgShapes[idx]._requiredFlag) { + // Restore object + if (o._images == nullptr || o._images->size() == 0) + o._type = NO_SHAPE; + else + o._type = ACTIVE_BG_SHAPE; + } + } + } + + // Check inventory + for (uint idx = 0; idx < _vm->_inventory->_holdings; ++idx) { + InventoryItem &ii = (*_vm->_inventory)[idx]; + if (ii._requiredFlag && !_vm->readFlags(ii._requiredFlag)) { + // Kill object: move it after the active holdings + InventoryItem tempItem = (*_vm->_inventory)[idx]; + _vm->_inventory->insert_at(_vm->_inventory->_holdings, tempItem); + _vm->_inventory->remove_at(idx); + _vm->_inventory->_holdings--; + break; + } + } + + for (uint idx = _vm->_inventory->_holdings; idx < _vm->_inventory->size(); ++idx) { + InventoryItem &ii = (*_vm->_inventory)[idx]; + if (ii._requiredFlag && _vm->readFlags(ii._requiredFlag)) { + // Restore object: move it after the active holdings + InventoryItem tempItem = (*_vm->_inventory)[idx]; + _vm->_inventory->remove_at(idx); + _vm->_inventory->insert_at(_vm->_inventory->_holdings, tempItem); + _vm->_inventory->_holdings++; + break; + } } } @@ -424,7 +491,28 @@ void Scene::checkSceneFlags(bool flag) { * be hidden in the scene. */ void Scene::checkInventory() { + for (uint shapeIdx = 0; shapeIdx < _bgShapes.size(); ++shapeIdx) { + for (uint invIdx = 0; invIdx < _vm->_inventory->size(); ++invIdx) { + if (scumm_stricmp(_bgShapes[shapeIdx]._name.c_str(), + (*_vm->_inventory)[invIdx]._name.c_str()) == 0) { + _bgShapes[shapeIdx]._type = INVALID; + break; + } + } + } +} + +/** + * Set up any entrance co-ordinates or entrance canimations, and then transition + * in the scene + */ +void Scene::transitionToScene() { + const int FS_TRANS[8] = { + STOP_UP, STOP_UPRIGHT, STOP_RIGHT, STOP_DOWNRIGHT, STOP_DOWN, + STOP_DOWNLEFT, STOP_LEFT, STOP_UPLEFT + }; + // TODO } } // End of namespace Sherlock diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h index ae4fcfdb45..d51856b508 100644 --- a/engines/sherlock/scene.h +++ b/engines/sherlock/scene.h @@ -89,15 +89,13 @@ class Scene { private: SherlockEngine *_vm; - void loadScene(); - - void loadScene(const Common::String &filename); + bool loadScene(const Common::String &filename); void checkSceneStatus(); - void checkSceneFlags(bool mode); - void checkInventory(); + + void transitionToScene(); public: int _currentScene; int _goToRoom; @@ -137,6 +135,8 @@ public: void clear(); void selectScene(); + + void checkSceneFlags(bool mode); }; } // End of namespace Sherlock diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index 115d9f0130..65dc6c80a5 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -33,6 +33,7 @@ SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gam _animation = nullptr; _debugger = nullptr; _events = nullptr; + _inventory = nullptr; _journal = nullptr; _people = nullptr; _res = nullptr; @@ -50,6 +51,7 @@ SherlockEngine::~SherlockEngine() { delete _animation; delete _debugger; delete _events; + delete _inventory; delete _journal; delete _people; delete _res; @@ -82,6 +84,7 @@ void SherlockEngine::initialize() { _animation = new Animation(this); _debugger = new Debugger(this); _events = new EventsManager(this); + _inventory = new Inventory(); _journal = new Journal(); _people = new People(this); _scene = new Scene(this); @@ -116,4 +119,25 @@ Common::Error SherlockEngine::run() { return Common::kNoError; } +/** + * Read the state of a global flag + */ +bool SherlockEngine::readFlags(int flagNum) { + bool value = _flags[ABS(flagNum)]; + if (flagNum < 0) + value = !value; + + return value; +} + +/** + * Sets a global flag to either true or false depending on whether the specified + * flag is positive or negative + */ +void SherlockEngine::setFlags(int flagNum) { + _flags[ABS(flagNum)] = flagNum >= 0; + + _scene->checkSceneFlags(true); +} + } // End of namespace Comet diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h index c31416f91e..a8ca9abbfd 100644 --- a/engines/sherlock/sherlock.h +++ b/engines/sherlock/sherlock.h @@ -34,6 +34,7 @@ #include "sherlock/animation.h" #include "sherlock/debugger.h" #include "sherlock/events.h" +#include "sherlock/inventory.h" #include "sherlock/journal.h" #include "sherlock/people.h" #include "sherlock/resources.h" @@ -78,6 +79,7 @@ public: Animation *_animation; Debugger *_debugger; EventsManager *_events; + Inventory *_inventory; Journal *_journal; People *_people; Resources *_res; @@ -93,6 +95,9 @@ public: Common::Point _hsavedPos; int _hsavedFs; bool _justLoaded; + int _oldCharPoint; // Old scene + Common::Point _over; // Old map position + Common::Array _map; // Map locations for each scene public: SherlockEngine(OSystem *syst, const SherlockGameDescription *gameDesc); virtual ~SherlockEngine(); @@ -108,6 +113,10 @@ public: Common::String getGameFile(int fileType); int getRandomNumber(int limit) { return _randomSource.getRandomNumber(limit - 1); } + + bool readFlags(int flagNum); + + void setFlags(int flagNum); }; } // End of namespace Sherlock -- cgit v1.2.3 From 06fbefc7875b37dd531b65c42087e4e6782c03a6 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 21 Mar 2015 09:20:39 -0400 Subject: SHERLOCK: Beginnings of transitionToScene --- engines/sherlock/objects.cpp | 12 ++++ engines/sherlock/objects.h | 6 ++ engines/sherlock/people.cpp | 1 + engines/sherlock/people.h | 13 +++- engines/sherlock/scalpel/scalpel.cpp | 4 +- engines/sherlock/scene.cpp | 117 +++++++++++++++++++++++++++++++++++ engines/sherlock/scene.h | 6 ++ engines/sherlock/sherlock.cpp | 3 +- engines/sherlock/sherlock.h | 3 +- 9 files changed, 157 insertions(+), 8 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index d696954cda..3fc9901a38 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -57,6 +57,18 @@ void Sprite::setImageFrame() { _imageFrame = &(*_images)[imageNumber]; } +void Sprite::adjustSprite(bool onChessboard) { + // TODO +} + +void Sprite::gotoStand() { + // TODO +} + +void Sprite::setWalking() { + // TODO +} + /*----------------------------------------------------------------*/ void ActionType::synchronize(Common::SeekableReadStream &s) { diff --git a/engines/sherlock/objects.h b/engines/sherlock/objects.h index d43b70f4e9..a1bdc5933c 100644 --- a/engines/sherlock/objects.h +++ b/engines/sherlock/objects.h @@ -104,6 +104,12 @@ struct Sprite { void clear(); void setImageFrame(); + + void adjustSprite(bool onChessboard = false); + + void gotoStand(); + + void setWalking(); }; struct ActionType { diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp index b4bbef2e1a..b187b65ad4 100644 --- a/engines/sherlock/people.cpp +++ b/engines/sherlock/people.cpp @@ -47,6 +47,7 @@ static const uint8 CHARACTER_SEQUENCES[MAX_HOLMES_SEQUENCE][MAX_FRAME] = { People::People(SherlockEngine *vm) : _vm(vm) { _walkLoaded = false; + _holmesOn = true; } People::~People() { diff --git a/engines/sherlock/people.h b/engines/sherlock/people.h index 4bdc6a88f0..74a4575af6 100644 --- a/engines/sherlock/people.h +++ b/engines/sherlock/people.h @@ -28,8 +28,13 @@ namespace Sherlock { -#define MAX_PEOPLE 2 -#define PLAYER 0 +// People definitions +enum PeopleId { + PLAYER = 0, + AL = 0, + PEG = 1, + MAX_PEOPLE = 2 +}; // Animation sequence identifiers for characters enum { @@ -47,6 +52,8 @@ private: SherlockEngine *_vm; Sprite _data[MAX_PEOPLE]; bool _walkLoaded; +public: + bool _holmesOn; public: People(SherlockEngine *vm); ~People(); @@ -54,6 +61,8 @@ public: void reset(); bool loadWalk(); + + Sprite &operator[](PeopleId id) { return _data[id]; } }; } // End of namespace Sherlock diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp index 40ca9736d6..2477f2894f 100644 --- a/engines/sherlock/scalpel/scalpel.cpp +++ b/engines/sherlock/scalpel/scalpel.cpp @@ -193,8 +193,8 @@ void ScalpelEngine::startScene() { _scene->_goToRoom = _chess->doChessBoard(); _sound->freeSong(); - _hsavedPos = Common::Point(-1, -1); - _hsavedFs = -1; + _scene->_hsavedPos = Common::Point(-1, -1); + _scene->_hsavedFs = -1; } // Some rooms are prologue cutscenes, rather than normal game scenes. These are: diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 4ec5c29134..8875327dcf 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -94,6 +94,8 @@ Scene::Scene(SherlockEngine *vm): _vm(vm) { _version = 0; _lzwMode = false; _invGraphicItems = 0; + _hsavedPos = Common::Point(-1, -1); + _hsavedFs = -1; _controlPanel = new ImageFile("controls.vgs"); _controls = nullptr; // new ImageFile("menu.all"); @@ -511,8 +513,123 @@ void Scene::transitionToScene() { STOP_UP, STOP_UPRIGHT, STOP_RIGHT, STOP_DOWNRIGHT, STOP_DOWN, STOP_DOWNLEFT, STOP_LEFT, STOP_UPLEFT }; + People &people = *_vm->_people; + + if (_hsavedPos.x < 1) { + // No exit information from last scene-check entrance info + if (_entrance._startPosition.x < 1) { + // No entrance info either, so use defaults + _hsavedPos = Common::Point(16000, 10000); + _hsavedFs = 4; + } else { + // setup entrance info + _hsavedPos = _entrance._startPosition; + _hsavedFs = _entrance._startDir; + } + } else { + // Exit information exists, translate it to real sequence info + // Note: If a savegame was just loaded, then the data is already correct. + // Otherwise, this is a linked scene or entrance info, and must be translated + if (_hsavedFs < 8 && !_vm->_justLoaded) { + _hsavedFs = FS_TRANS[_hsavedFs]; + _hsavedPos.x *= 100; + _hsavedPos.y *= 100; + } + } + + int startcAnimNum = -1; + + if (_hsavedFs < 101) { + // Standard info, so set it + people[PLAYER]._position = _hsavedPos; + people[PLAYER]._sequenceNumber = _hsavedFs; + } else { + // It's canimation information + startcAnimNum = _hsavedFs - 101; + + // Prevent Holmes from being drawn + people[PLAYER]._position = Common::Point(0, 0); + } + + for (uint objIdx = 0; objIdx < _bgShapes.size(); ++objIdx) { + Object &obj = _bgShapes[objIdx]; + + if (obj._aType > 1 && obj._type != INVALID && obj._type != HIDDEN) { + Common::Point topLeft = obj._position; + Common::Point bottomRight; + + if (obj._type != NO_SHAPE) { + topLeft += obj._imageFrame->_position; + bottomRight.x = topLeft.x + obj._imageFrame->_frame.w; + bottomRight.y = topLeft.y + obj._imageFrame->_frame.h; + } else { + bottomRight = topLeft + obj._noShapeSize; + } + + if (Common::Rect(topLeft.x, topLeft.y, bottomRight.x, bottomRight.y).contains( + Common::Point(people[PLAYER]._position.x / 100, people[PLAYER]._position.y / 100))) { + // Current point is already inside box - impact occurred on + // a previous call. So simply do nothing except talk until the + // player is clear of the box + switch (obj._aType) { + case FLAG_SET: + for (int useNum = 0; useNum < 4; ++useNum) { + if (obj._use[useNum]._useFlag) { + if (!_vm->readFlags(obj._use[useNum]._useFlag)) + _vm->setFlags(obj._use[useNum]._useFlag); + } + + if (!_vm->_talkToAbort) { + for (int nameIdx = 0; nameIdx < 4; ++nameIdx) { + toggleObject(obj._use[useNum]._names[nameIdx]); + } + } + } + + obj._type = HIDDEN; + break; + + default: + break; + } + } + } + } + updateBackground(); // TODO } +/** + * Scans through the object list to find one with a matching name, and will + * call toggleHidden with all matches found. Returns the numer of matches found + */ +int Scene::toggleObject(const Common::String &name) { + int count = 0; + + for (uint idx = 0; idx < _bgShapes.size(); ++idx) { + if (scumm_stricmp(name.c_str(), _bgShapes[idx]._name.c_str()) == 0) { + ++count; + _bgShapes[idx].toggleHidden(); + } + } + + return count; +} + +/** + * Update the screen back buffer with all of the scene objects which need + * to be drawn + */ +void Scene::updateBackground() { + People &people = *_vm->_people; + //setDisplayBounds(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT); + + // Update Holmes if he's turned on + if (people._holmesOn) + people[AL].adjustSprite(); + + +} + } // End of namespace Sherlock diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h index d51856b508..5625bb1f5b 100644 --- a/engines/sherlock/scene.h +++ b/engines/sherlock/scene.h @@ -96,6 +96,10 @@ private: void checkInventory(); void transitionToScene(); + + int toggleObject(const Common::String &name); + + void updateBackground(); public: int _currentScene; int _goToRoom; @@ -128,6 +132,8 @@ public: Common::Array _exits; SceneEntry _entrance; Common::Array _sounds; + Common::Point _hsavedPos; + int _hsavedFs; public: Scene(SherlockEngine *vm); ~Scene(); diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index 65dc6c80a5..60e32bda82 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -42,9 +42,8 @@ SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gam _sound = nullptr; _talk = nullptr; _useEpilogue2 = false; - _hsavedPos = Common::Point(-1, -1); - _hsavedFs = -1; _justLoaded = false; + _talkToAbort = false; } SherlockEngine::~SherlockEngine() { diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h index a8ca9abbfd..84b6c48f12 100644 --- a/engines/sherlock/sherlock.h +++ b/engines/sherlock/sherlock.h @@ -92,12 +92,11 @@ public: Common::String _soundOverride; Common::String _titleOverride; bool _useEpilogue2; - Common::Point _hsavedPos; - int _hsavedFs; bool _justLoaded; int _oldCharPoint; // Old scene Common::Point _over; // Old map position Common::Array _map; // Map locations for each scene + bool _talkToAbort; public: SherlockEngine(OSystem *syst, const SherlockGameDescription *gameDesc); virtual ~SherlockEngine(); -- cgit v1.2.3 From b6076dd52458320f39442bc225ef8b0ce531ea51 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 21 Mar 2015 11:24:35 -0400 Subject: SHERLOCK: Implemented setWalking --- engines/sherlock/objects.cpp | 17 ++-- engines/sherlock/objects.h | 18 ++-- engines/sherlock/people.cpp | 204 +++++++++++++++++++++++++++++++++++++++++- engines/sherlock/people.h | 20 ++++- engines/sherlock/scene.cpp | 2 +- engines/sherlock/scene.h | 2 +- engines/sherlock/sherlock.cpp | 15 +--- engines/sherlock/sherlock.h | 1 + 8 files changed, 240 insertions(+), 39 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index 3fc9901a38..63e4bdf621 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -21,9 +21,14 @@ */ #include "sherlock/objects.h" +#include "sherlock/sherlock.h" +#include "sherlock/people.h" +#include "sherlock/scene.h" namespace Sherlock { +SherlockEngine *Sprite::_vm; + /** * Reset the data for the sprite */ @@ -39,7 +44,7 @@ void Sprite::clear() { _allow = 0; _frameNumber = _sequenceNumber = 0; _position.x = _position.y = 0; - _movement.x = _movement.y = 0; + _delta.x = _delta.y = 0; _oldPosition.x = _oldPosition.y = 0; _oldSize.x = _oldSize.y = 0; _goto.x = _goto.y = 0; @@ -57,15 +62,7 @@ void Sprite::setImageFrame() { _imageFrame = &(*_images)[imageNumber]; } -void Sprite::adjustSprite(bool onChessboard) { - // TODO -} - -void Sprite::gotoStand() { - // TODO -} - -void Sprite::setWalking() { +void Sprite::adjustSprite() { // TODO } diff --git a/engines/sherlock/objects.h b/engines/sherlock/objects.h index a1bdc5933c..b1207867e4 100644 --- a/engines/sherlock/objects.h +++ b/engines/sherlock/objects.h @@ -74,7 +74,10 @@ enum AType { #define FLIP_CODE (64 + 128) #define SOUND_CODE (34 + 128) -struct Sprite { +class Sprite { +private: + static SherlockEngine *_vm; +public: Common::String _name; // Name Common::String _description; // Description Common::StringArray _examine; // Examine in-depth description @@ -88,7 +91,7 @@ struct Sprite { int _frameNumber; // Frame number in rame sequence to draw int _sequenceNumber; // Sequence being used Common::Point _position; // Current position - Common::Point _movement; // Momvement amount + Common::Point _delta; // Momvement delta Common::Point _oldPosition; // Old position Common::Point _oldSize; // Image's old size Common::Point _goto; // Walk destination @@ -98,18 +101,15 @@ struct Sprite { int _status; // Status: open/closed, moved/not moved int8 _misc; // Miscellaneous use int _numFrames; // How many frames the object has - +public: Sprite() { clear(); } - + static void setVm(SherlockEngine *vm) { _vm = vm; } + void clear(); void setImageFrame(); - void adjustSprite(bool onChessboard = false); - - void gotoStand(); - - void setWalking(); + void adjustSprite(); }; struct ActionType { diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp index b187b65ad4..998fe4f0cf 100644 --- a/engines/sherlock/people.cpp +++ b/engines/sherlock/people.cpp @@ -21,9 +21,15 @@ */ #include "sherlock/people.h" +#include "sherlock/sherlock.h" namespace Sherlock { +// Walk speeds +#define MWALK_SPEED 2 +#define XWALK_SPEED 4 +#define YWALK_SPEED 1 + // Characer animation sequences static const uint8 CHARACTER_SEQUENCES[MAX_HOLMES_SEQUENCE][MAX_FRAME] = { { 29, 1, 2, 3, 4, 5, 6, 7, 0 }, // Walk Right @@ -45,9 +51,11 @@ static const uint8 CHARACTER_SEQUENCES[MAX_HOLMES_SEQUENCE][MAX_FRAME] = { }; -People::People(SherlockEngine *vm) : _vm(vm) { +People::People(SherlockEngine *vm) : _vm(vm), _player(_data[0]) { _walkLoaded = false; _holmesOn = true; + _oldWalkSequence = -1; + _allowWalkAbort = false; } People::~People() { @@ -65,7 +73,7 @@ void People::reset() { p._sequences = &CHARACTER_SEQUENCES; p._imageFrame = nullptr; p._frameNumber = 1; - p._movement = Common::Point(0, 0); + p._delta = Common::Point(0, 0); p._oldPosition = Common::Point(0, 0); p._oldSize = Common::Point(0, 0); p._misc = 0; @@ -89,4 +97,196 @@ bool People::loadWalk() { } } +/** +* Set the variables for moving a character from one poisition to another +* in a straight line - goAllTheWay must have been previously called to +* check for any obstacles in the path. +*/ +void People::setWalking() { + Scene &scene = *_vm->_scene; + int oldDirection, oldFrame; + Common::Point speed, delta; + int temp; + + // Flag that player has now walked in the scene + scene._walkedInScene = true; + + // Stop any previous walking, since a new dest is being set + _player._walkCount = 0; + oldDirection = _player._sequenceNumber; + oldFrame = _player._frameNumber; + + // Set speed to use horizontal and vertical movement + if (_vm->_onChessboard) { + speed = Common::Point(MWALK_SPEED, MWALK_SPEED); + } else { + speed = Common::Point(XWALK_SPEED, YWALK_SPEED); + } + + // If the player is already close to the given destination that no + // walking is needed, move to the next straight line segment in the + // overall walking route, if there is one + for (;;) { + // Since we want the player to be centered on the destination they + // clicked, but characters draw positions start at their left, move + // the destination half the character width to draw him centered + if (_walkDest.x >= (temp = _player._imageFrame->_frame.w / 2)) + _walkDest.x -= temp; + + delta = Common::Point( + ABS(_player._position.x / 100 - _walkDest.x), + ABS(_player._position.y / 100 - _walkDest.y) + ); + + // If we're ready to move a sufficient distance, that's it. Otherwise, + // move onto the next portion of the walk path, if there is one + if ((delta.x > 3 || delta.y > 0) || _walkTo.empty()) + break; + + // Pop next walk segment off the walk route stack + _walkDest = _walkTo.pop(); + } while (!_vm->shouldQuit()); + + // If a sufficient move is being done, then start the move + if (delta.x > 3 || delta.y) { + // See whether the major movement is horizontal or vertical + if (delta.x >= delta.y) { + // Set the initial frame sequence for the left and right, as well + // as settting the delta x depending on direction + if (_walkDest.x < (_player._position.x / 100)) { + _player._sequenceNumber = _vm->_onChessboard ? MAP_LEFT : WALK_LEFT; + _player._delta.x = speed.x * -100; + } else { + _player._sequenceNumber = _vm->_onChessboard ? MAP_RIGHT : WALK_RIGHT; + _player._delta.x = speed.x * 100; + } + + // See if the x delta is too small to be divided by the speed, since + // this would cause a divide by zero error + if (delta.x >= speed.x) { + // Det the delta y + _player._delta.y = (delta.y * 100) / (delta.x / speed.x); + if (_walkDest.y < (_player._position.y / 100)) + _player._delta.y = -_player._delta.y; + + // Set how many times we should add the delta to the player's position + _player._walkCount = delta.x / speed.x; + } else { + // The delta x was less than the speed (ie. we're really close to + // the destination). So set delta to 0 so the player won't move + _player._delta = Common::Point(0, 0); + _player._position = Common::Point(_walkDest.x * 100, _walkDest.y * 100); + _player._walkCount = 1; + } + + // See if the sequence needs to be changed for diagonal walking + if (_player._delta.y > 150) { + if (!_vm->_onChessboard) { + switch (_player._sequenceNumber) { + case WALK_LEFT: + _player._sequenceNumber = WALK_DOWNLEFT; + break; + case WALK_RIGHT: + _player._sequenceNumber = WALK_DOWNRIGHT; + break; + } + } + } else if (_player._delta.y < -150) { + if (!_vm->_onChessboard) { + switch (_player._sequenceNumber) { + case WALK_LEFT: + _player._sequenceNumber = WALK_UPLEFT; + break; + case WALK_RIGHT: + _player._sequenceNumber = WALK_UPRIGHT; + break; + } + } + } + } else { + // Major movement is vertical, so set the sequence for up and down, + // and set the delta Y depending on the direction + if (_walkDest.y < (_player._position.y / 100)) { + _player._sequenceNumber = WALK_UP; + _player._delta.y = speed.y * -100; + } else { + _player._sequenceNumber = WALK_DOWN; + _player._delta.y = speed.y * 100; + } + + // If we're on the overhead map, set the sequence so we keep moving + // in the same direction + _player._sequenceNumber = (oldDirection == -1) ? MAP_RIGHT : oldDirection; + + // Set the delta x + _player._delta.x = (delta.x * 100) / (delta.y / speed.y); + if (_walkDest.x < (_player._position.x / 100)) + _player._delta.x = -_player._delta.x; + } + } + + // See if the new walk sequence is the same as the old. If it's a new one, + // we need to reset the frame number to zero so it's animation starts at + // it's beginning. Otherwise, if it's the same sequence, we can leave it + // as is, so it keeps the animation going at wherever it was up to + if (_player._sequenceNumber != _oldWalkSequence) + _player._frameNumber = 0; + _oldWalkSequence = _player._sequenceNumber; + + if (!_player._walkCount) + gotoStand(_player); + + // If the sequence is the same as when we started, then Holmes was + // standing still and we're trying to re-stand him, so reset Holmes' + // rame to the old frame number from before it was reset to 0 + if (_player._sequenceNumber == oldDirection) + _player._frameNumber = oldFrame; +} + +/** + * Bring a moving character to a standing position. If the Scalpel chessboard + * is being displayed, then the chraracter will always face down. + */ +void People::gotoStand(Sprite &sprite) { + Scene &scene = *_vm->_scene; + _walkTo.clear(); + sprite._walkCount = 0; + + switch (sprite._sequenceNumber) { + case WALK_UP: + sprite._sequenceNumber = STOP_UP; break; + case WALK_DOWN: + sprite._sequenceNumber = STOP_DOWN; break; + case TALK_LEFT: + case WALK_LEFT: + sprite._sequenceNumber = STOP_LEFT; break; + case TALK_RIGHT: + case WALK_RIGHT: + sprite._sequenceNumber = STOP_RIGHT; break; + case WALK_UPRIGHT: + sprite._sequenceNumber = STOP_UPRIGHT; break; + case WALK_UPLEFT: + sprite._sequenceNumber = STOP_UPLEFT; break; + case WALK_DOWNRIGHT: + sprite._sequenceNumber = STOP_DOWNRIGHT; break; + case WALK_DOWNLEFT: + sprite._sequenceNumber = STOP_DOWNLEFT; break; + default: + break; + } + + // Only restart frame at 0 if the sequence number has changed + if (_oldWalkSequence != -1 || sprite._sequenceNumber == STOP_UP) + sprite._frameNumber = 0; + + if (_vm->_onChessboard) { + sprite._sequenceNumber = 0; + _data[AL]._position.x = (_vm->_map[scene._charPoint].x - 6) * 100; + _data[AL]._position.y = (_vm->_map[scene._charPoint].x + 10) * 100; + } + + _oldWalkSequence = -1; + _allowWalkAbort = true; +} + } // End of namespace Sherlock diff --git a/engines/sherlock/people.h b/engines/sherlock/people.h index 74a4575af6..be9be006e8 100644 --- a/engines/sherlock/people.h +++ b/engines/sherlock/people.h @@ -24,6 +24,7 @@ #define SHERLOCK_PEOPLE_H #include "common/scummsys.h" +#include "common/stack.h" #include "sherlock/objects.h" namespace Sherlock { @@ -39,10 +40,14 @@ enum PeopleId { // Animation sequence identifiers for characters enum { WALK_RIGHT = 0, WALK_DOWN = 1, WALK_LEFT = 2, WALK_UP = 3, STOP_LEFT = 4, - STOP_DOWN = 5, STOP_RIGHT = 6, STOP_UP = 7, WALK_UPRIGHT = 8, + STOP_DOWN = 5, STOP_RIGHT = 6, STOP_UP = 7, WALK_UPRIGHT = 8, WALK_DOWNRIGHT = 9, WALK_UPLEFT = 10, WALK_DOWNLEFT = 11, STOP_UPRIGHT = 12, STOP_UPLEFT = 13, STOP_DOWNRIGHT = 14, - STOP_DOWNLEFT = 15, TALK_RIGHT = 6, TALK_LEFT = 4 + STOP_DOWNLEFT = 15, TALK_RIGHT = 6, TALK_LEFT = 4, +}; +enum { + MAP_UP = 1, MAP_UPRIGHT = 2, MAP_RIGHT = 1, MAP_DOWNRIGHT = 4, + MAP_DOWN = 5, MAP_DOWNLEFT = 6, MAP_LEFT = 2, MAP_UPLEFT = 8 }; class SherlockEngine; @@ -51,18 +56,27 @@ class People { private: SherlockEngine *_vm; Sprite _data[MAX_PEOPLE]; + Sprite &_player; bool _walkLoaded; + int _oldWalkSequence; + bool _allowWalkAbort; public: + Common::Point _walkDest; + Common::Stack _walkTo; bool _holmesOn; public: People(SherlockEngine *vm); ~People(); + Sprite &operator[](PeopleId id) { return _data[id]; } + void reset(); bool loadWalk(); - Sprite &operator[](PeopleId id) { return _data[id]; } + void setWalking(); + + void gotoStand(Sprite &sprite); }; } // End of namespace Sherlock diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 8875327dcf..13db8d9b94 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -86,7 +86,7 @@ Scene::Scene(SherlockEngine *vm): _vm(vm) { _currentScene = -1; _goToRoom = -1; _changes = false; - _oldCharPoint = 0; + _charPoint = _oldCharPoint = 0; _windowOpen = _infoFlag = false; _menuMode = _keyboardInput = 0; _walkedInScene = false; diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h index 5625bb1f5b..a4b94652c8 100644 --- a/engines/sherlock/scene.h +++ b/engines/sherlock/scene.h @@ -108,7 +108,7 @@ public: bool _savedStats[SCENES_COUNT][9]; Common::Point _bigPos; Common::Point _overPos; - int _oldCharPoint; + int _charPoint, _oldCharPoint; ImageFile *_controls; ImageFile *_controlPanel; bool _windowOpen, _infoFlag; diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index 60e32bda82..2787e2b924 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -44,6 +44,7 @@ SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gam _useEpilogue2 = false; _justLoaded = false; _talkToAbort = false; + _onChessboard = false; } SherlockEngine::~SherlockEngine() { @@ -65,20 +66,8 @@ void SherlockEngine::initialize() { DebugMan.addDebugChannel(kDebugScript, "scripts", "Script debug level"); - /* - int midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); - bool native_mt32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32")); - - MidiDriver *driver = MidiDriver::createMidi(midiDriver); - if (native_mt32) - driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); - - _midi = new MidiPlayer(this, driver); - _midi->setGM(true); - _midi->setNativeMT32(native_mt32); - */ - ImageFile::setVm(this); + Sprite::setVm(this); _res = new Resources(); _animation = new Animation(this); _debugger = new Debugger(this); diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h index 84b6c48f12..1607cec974 100644 --- a/engines/sherlock/sherlock.h +++ b/engines/sherlock/sherlock.h @@ -97,6 +97,7 @@ public: Common::Point _over; // Old map position Common::Array _map; // Map locations for each scene bool _talkToAbort; + bool _onChessboard; public: SherlockEngine(OSystem *syst, const SherlockGameDescription *gameDesc); virtual ~SherlockEngine(); -- cgit v1.2.3 From 8f4b4a7bc269bf454ab90d003f1cc55104c175b6 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 21 Mar 2015 13:01:45 -0400 Subject: SHERLOCK: Implemented updateBackground --- engines/sherlock/graphics.cpp | 26 ++++++++-- engines/sherlock/graphics.h | 8 +++- engines/sherlock/objects.cpp | 104 ++++++++++++++++++++++++++++++++++++++-- engines/sherlock/objects.h | 5 ++ engines/sherlock/people.h | 2 + engines/sherlock/scene.cpp | 107 +++++++++++++++++++++++++++++++++++++++--- engines/sherlock/scene.h | 8 +++- engines/sherlock/sherlock.cpp | 3 ++ engines/sherlock/sherlock.h | 3 ++ 9 files changed, 251 insertions(+), 15 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/graphics.cpp b/engines/sherlock/graphics.cpp index a4990fb6c6..8c096e3c72 100644 --- a/engines/sherlock/graphics.cpp +++ b/engines/sherlock/graphics.cpp @@ -27,12 +27,22 @@ namespace Sherlock { -Surface::Surface(uint16 width, uint16 height) { +Surface::Surface(uint16 width, uint16 height): _freePixels(true) { create(width, height, Graphics::PixelFormat::createFormatCLUT8()); } +Surface::Surface(Surface &src, const Common::Rect &r) : _freePixels(false) { + setPixels(src.getBasePtr(r.left, r.top)); + w = r.width(); + h = r.height(); + pitch = src.pitch; + format = Graphics::PixelFormat::createFormatCLUT8(); +} + + Surface::~Surface() { - free(); + if (_freePixels) + free(); } /** @@ -131,9 +141,19 @@ void Surface::transBlitFrom(const Graphics::Surface &src, const Common::Point &p } } - +/** + * Fill a given area of the surface with a given color + */ void Surface::fillRect(int x1, int y1, int x2, int y2, byte color) { Graphics::Surface::fillRect(Common::Rect(x1, y1, x2, y2), color); } +/** + * Return a sub-area of the surface as a new surface object. The surfaces + * are shared in common, so changes in the sub-surface affects the original. + */ +Surface Surface::getSubArea(const Common::Rect &r) { + return Surface(*this, r); +} + } // End of namespace Sherlock diff --git a/engines/sherlock/graphics.h b/engines/sherlock/graphics.h index 82c48307d7..0536c016bf 100644 --- a/engines/sherlock/graphics.h +++ b/engines/sherlock/graphics.h @@ -29,11 +29,15 @@ namespace Sherlock { class Surface : public Graphics::Surface { +private: + bool _freePixels; protected: virtual void addDirtyRect(const Common::Rect &r) {} + + Surface(Surface &src, const Common::Rect &r); public: Surface(uint16 width, uint16 height); - ~Surface(); + ~Surface(); void blitFrom(const Graphics::Surface &src); void blitFrom(const Graphics::Surface &src, const Common::Point &pt); @@ -43,6 +47,8 @@ public: bool flipped = false, int overrideColor = 0); void fillRect(int x1, int y1, int x2, int y2, byte color); + + Surface getSubArea(const Common::Rect &r); }; } // End of namespace Sherlock diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index 63e4bdf621..a12939e787 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -24,9 +24,15 @@ #include "sherlock/sherlock.h" #include "sherlock/people.h" #include "sherlock/scene.h" +#include "common/util.h" namespace Sherlock { +#define UPPER_LIMIT 0 +#define LOWER_LIMIT CONTROLS_Y +#define LEFT_LIMIT 0 +#define RIGHT_LIMIT SHERLOCK_SCREEN_WIDTH + SherlockEngine *Sprite::_vm; /** @@ -56,14 +62,106 @@ void Sprite::clear() { _numFrames = 0; } +/** + * Updates the image frame poiner for the sprite + */ void Sprite::setImageFrame() { - // TODO: check this - int imageNumber = (*_sequences)[_sequenceNumber][_frameNumber]; + int imageNumber = (*_sequences)[_sequenceNumber][_frameNumber] + + (*_sequences)[_sequenceNumber][0] - 2; _imageFrame = &(*_images)[imageNumber]; } +/** + * This adjusts the sprites position, as well as it's animation sequence: + */ void Sprite::adjustSprite() { - // TODO + People &people = *_vm->_people; + Scene &scene = *_vm->_scene; + int checkFrame = _allow ? MAX_FRAME : 32000; + + if (_type == INVALID || (_type == CHARACTER && _vm->_animating)) + return; + + if (!_vm->_talkCounter && _type == CHARACTER && _walkCount) { + // Handle active movement for the sprite + _position += _delta; + --_walkCount; + + if (!_walkCount) { + // If there any points left for the character to walk to along the + // route to a destination, then move to the next point + if (!people._walkTo.empty()) { + people._walkDest = people._walkTo.pop(); + people.setWalking(); + } else { + people.gotoStand(*this); + } + } + } + + if (_type == CHARACTER && !_vm->_onChessboard) { + if ((_position.y / 100) > LOWER_LIMIT) { + _position.y = LOWER_LIMIT * 100; + people.gotoStand(*this); + } + + if ((_position.y / 100) < UPPER_LIMIT) { + _position.y = UPPER_LIMIT * 100; + people.gotoStand(*this); + } + + if ((_position.x / 100) < LEFT_LIMIT) { + _position.x = LEFT_LIMIT * 100; + people.gotoStand(*this); + } + } else if (!_vm->_onChessboard) { + _position.y = CLIP((int)_position.y, UPPER_LIMIT, LOWER_LIMIT); + _position.x = CLIP((int)_position.x, LEFT_LIMIT, RIGHT_LIMIT); + } + + if (!_vm->_onChessboard || (_vm->_slowChess = !_vm->_slowChess)) + ++_frameNumber; + + if ((*_sequences)[_sequenceNumber][_frameNumber] == 0) { + switch (_sequenceNumber) { + case STOP_UP: + case STOP_DOWN: + case STOP_LEFT: + case STOP_RIGHT: + case STOP_UPRIGHT: + case STOP_UPLEFT: + case STOP_DOWNRIGHT: + case STOP_DOWNLEFT: + // We're in a stop sequence, so reset back to the last frame, so + // the character is shown as standing still + --_frameNumber; + break; + + default: + // Move 1 past the first frame - we need to compensate, since we + // already passed the frame increment + _frameNumber = 1; + break; + } + } + + // Update the _imageFrame to point to the new frame's image + setImageFrame(); + + // Check to see if character has entered an exit zone + if (!_walkCount && scene._walkedInScene && scene._goToRoom == -1) { + Common::Rect charRect(_position.x / 100 - 5, _position.y / 100 - 2, + _position.x / 100 + 5, _position.y / 100 + 2); + Exit *exit = scene.checkForExit(charRect); + + if (exit) { + scene._hsavedPos = exit->_people; + scene._hsavedFs = exit->_peopleDir; + + if (scene._hsavedFs > 100 && scene._hsavedPos.x < 1) + scene._hsavedPos.x = 100; + } + } } /*----------------------------------------------------------------*/ diff --git a/engines/sherlock/objects.h b/engines/sherlock/objects.h index b1207867e4..d9f1c7409e 100644 --- a/engines/sherlock/objects.h +++ b/engines/sherlock/objects.h @@ -66,6 +66,11 @@ enum AType { NOWALK_ZONE = 13 // Player cannot walk here }; +// Different levels for sprites to be at +enum { + BEHIND = 0, NORMAL_BEHIND = 1, NORMAL_FORWARD = 2, FORWARD = 3 +}; + #define MAX_HOLMES_SEQUENCE 16 #define MAX_FRAME 30 diff --git a/engines/sherlock/people.h b/engines/sherlock/people.h index be9be006e8..e58fd33ef2 100644 --- a/engines/sherlock/people.h +++ b/engines/sherlock/people.h @@ -70,6 +70,8 @@ public: Sprite &operator[](PeopleId id) { return _data[id]; } + bool isHolmesActive() const { return _walkLoaded && _holmesOn; } + void reset(); bool loadWalk(); diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 13db8d9b94..9fbec6b776 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -49,10 +49,12 @@ void BgfileheaderInfo::synchronize(Common::SeekableReadStream &s) { /*----------------------------------------------------------------*/ void Exit::synchronize(Common::SeekableReadStream &s) { - _position.x = s.readSint16LE(); - _position.y = s.readSint16LE(); - _size.x = s.readSint16LE(); - _size.y = s.readSint16LE(); + int xp = s.readSint16LE(); + int yp = s.readSint16LE(); + int xSize = s.readSint16LE(); + int ySize = s.readSint16LE(); + _bounds = Common::Rect(xp, yp, xp + xSize, yp + ySize); + _scene = s.readSint16LE(); _allow = s.readSint16LE(); _people.x = s.readSint16LE(); @@ -623,13 +625,106 @@ int Scene::toggleObject(const Common::String &name) { */ void Scene::updateBackground() { People &people = *_vm->_people; - //setDisplayBounds(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT); + Screen &screen = *_vm->_screen; + Surface surface = screen._backBuffer.getSubArea( + Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT)); + Sprite &player = people[AL]; // Update Holmes if he's turned on if (people._holmesOn) - people[AL].adjustSprite(); + player.adjustSprite(); + + // Flag the bg shapes which need to be redrawn + checkBgShapes(player._imageFrame, Common::Point(player._position.x / 100, + player._position.y / 100)); + + // Draw all active shapes which are behind the person + for (uint idx = 0; idx < _bgShapes.size(); ++idx) { + if (_bgShapes[idx]._type == ACTIVE_BG_SHAPE && _bgShapes[idx]._misc == BEHIND) + surface.transBlitFrom(_bgShapes[idx]._imageFrame->_frame, + _bgShapes[idx]._position, _bgShapes[idx]._flags & 2); + } + + // Draw all canimations which are behind the person + for (uint idx = 0; idx < _canimShapes.size(); ++idx) { + if (_canimShapes[idx]._type == ACTIVE_BG_SHAPE && _canimShapes[idx]._misc == BEHIND) + surface.transBlitFrom(_canimShapes[idx]._imageFrame->_frame, + _canimShapes[idx]._position, _canimShapes[idx]._flags & 2); + } + + // Draw all active shapes which are normal and behind the person + for (uint idx = 0; idx < _bgShapes.size(); ++idx) { + if (_bgShapes[idx]._type == ACTIVE_BG_SHAPE && _bgShapes[idx]._misc == NORMAL_BEHIND) + surface.transBlitFrom(_bgShapes[idx]._imageFrame->_frame, + _bgShapes[idx]._position, _bgShapes[idx]._flags & 2); + } + + // Draw all canimations which are normal and behind the person + for (uint idx = 0; idx < _canimShapes.size(); ++idx) { + if (_canimShapes[idx]._type == ACTIVE_BG_SHAPE && _canimShapes[idx]._misc == NORMAL_BEHIND) + surface.transBlitFrom(_canimShapes[idx]._imageFrame->_frame, + _canimShapes[idx]._position, _canimShapes[idx]._flags & 2); + } + + // Draw the player if he's active + if (player._type == CHARACTER && people.isHolmesActive()) { + bool flipped = player._sequenceNumber == WALK_LEFT || player._sequenceNumber == STOP_LEFT || + player._sequenceNumber == WALK_UPLEFT || player._sequenceNumber == STOP_UPLEFT || + player._sequenceNumber == WALK_DOWNRIGHT || player._sequenceNumber == STOP_DOWNRIGHT; + + surface.transBlitFrom(player._imageFrame->_frame, + Common::Point(player._position.x / 100, player._position.y / 100), flipped); + } + // Draw all static and active shapes that are NORMAL and are in front of the player + for (uint idx = 0; idx < _bgShapes.size(); ++idx) { + if ((_bgShapes[idx]._type == ACTIVE_BG_SHAPE || _bgShapes[idx]._type == STATIC_BG_SHAPE) && + _bgShapes[idx]._misc == NORMAL_FORWARD) + surface.transBlitFrom(_bgShapes[idx]._imageFrame->_frame, + _bgShapes[idx]._position, _bgShapes[idx]._flags & 2); + } + + // Draw all static and active canimations that are NORMAL and are in front of the player + for (uint idx = 0; idx < _canimShapes.size(); ++idx) { + if ((_canimShapes[idx]._type == ACTIVE_BG_SHAPE || _canimShapes[idx]._type == STATIC_BG_SHAPE) && + _canimShapes[idx]._misc == NORMAL_FORWARD) + surface.transBlitFrom(_canimShapes[idx]._imageFrame->_frame, + _canimShapes[idx]._position, _canimShapes[idx]._flags & 2); + } + + // Draw all static and active shapes that are FORWARD + for (uint idx = 0; idx < _bgShapes.size(); ++idx) { + _bgShapes[idx]._oldPosition = _bgShapes[idx]._position; + _bgShapes[idx]._oldSize = Common::Point(_bgShapes[idx]._imageFrame->_frame.w, + _bgShapes[idx]._imageFrame->_frame.h); + + if ((_bgShapes[idx]._type == ACTIVE_BG_SHAPE || _bgShapes[idx]._type == STATIC_BG_SHAPE) && + _bgShapes[idx]._misc == FORWARD) + surface.transBlitFrom(_bgShapes[idx]._imageFrame->_frame, + _bgShapes[idx]._position, _bgShapes[idx]._flags & 2); + } + + // Draw all static and active canimations that are forward + for (uint idx = 0; idx < _canimShapes.size(); ++idx) { + if ((_canimShapes[idx]._type == ACTIVE_BG_SHAPE || _canimShapes[idx]._type == STATIC_BG_SHAPE) && + _canimShapes[idx]._misc == FORWARD) + surface.transBlitFrom(_canimShapes[idx]._imageFrame->_frame, + _canimShapes[idx]._position, _canimShapes[idx]._flags & 2); + } +} + +Exit *Scene::checkForExit(const Common::Rect &r) { + for (uint idx = 0; idx < _exits.size(); ++idx) { + if (_exits[idx]._bounds.intersects(r)) + return &_exits[idx]; + } + return nullptr; } +void Scene::checkBgShapes(ImageFrame *frame, const Common::Point &pt) { + // TODO +} + + } // End of namespace Sherlock diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h index a4b94652c8..8986b62bf5 100644 --- a/engines/sherlock/scene.h +++ b/engines/sherlock/scene.h @@ -59,8 +59,7 @@ struct BgfileheaderInfo { }; struct Exit { - Common::Point _position; - Common::Point _size; + Common::Rect _bounds; int _scene; int _allow; @@ -100,6 +99,8 @@ private: int toggleObject(const Common::String &name); void updateBackground(); + + void checkBgShapes(ImageFrame *frame, const Common::Point &pt); public: int _currentScene; int _goToRoom; @@ -134,6 +135,7 @@ public: Common::Array _sounds; Common::Point _hsavedPos; int _hsavedFs; + Common::Array _canimShapes; public: Scene(SherlockEngine *vm); ~Scene(); @@ -143,6 +145,8 @@ public: void selectScene(); void checkSceneFlags(bool mode); + + Exit *checkForExit(const Common::Rect &r); }; } // End of namespace Sherlock diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index 2787e2b924..257cbb2cab 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -45,6 +45,9 @@ SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gam _justLoaded = false; _talkToAbort = false; _onChessboard = false; + _slowChess = false; + _animating = false; + _talkCounter = 0; } SherlockEngine::~SherlockEngine() { diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h index 1607cec974..7ce28cfdd7 100644 --- a/engines/sherlock/sherlock.h +++ b/engines/sherlock/sherlock.h @@ -98,6 +98,9 @@ public: Common::Array _map; // Map locations for each scene bool _talkToAbort; bool _onChessboard; + bool _slowChess; + bool _animating; + int _talkCounter; public: SherlockEngine(OSystem *syst, const SherlockGameDescription *gameDesc); virtual ~SherlockEngine(); -- cgit v1.2.3 From 26c51680741882b7ee60a0e24227e6c6918aab0e Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 21 Mar 2015 18:18:12 -0400 Subject: SHERLOCK: Implemented checkObject and some support methods --- engines/sherlock/animation.cpp | 2 +- engines/sherlock/events.cpp | 11 +- engines/sherlock/events.h | 6 +- engines/sherlock/objects.cpp | 170 ++++++++++++++++++++- engines/sherlock/objects.h | 25 ++- engines/sherlock/people.cpp | 5 + engines/sherlock/people.h | 2 + engines/sherlock/resources.cpp | 12 +- engines/sherlock/resources.h | 1 + engines/sherlock/scalpel/scalpel.cpp | 6 +- engines/sherlock/scene.cpp | 285 ++++++++++++++++++++++++++++++++++- engines/sherlock/scene.h | 9 ++ engines/sherlock/sherlock.cpp | 1 + engines/sherlock/sound.cpp | 11 +- engines/sherlock/sound.h | 8 +- 15 files changed, 521 insertions(+), 33 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/animation.cpp b/engines/sherlock/animation.cpp index 2b12005079..a7f91e91cd 100644 --- a/engines/sherlock/animation.cpp +++ b/engines/sherlock/animation.cpp @@ -144,7 +144,7 @@ bool Animation::playPrologue(const Common::String &filename, int minDelay, int f Common::String::format("%s%01d", baseName.c_str(), soundNumber) : Common::String::format("%s%02d", baseName.c_str(), soundNumber); - if (sound._voicesEnabled) + if (sound._voicesOn) sound.playSound(fname); } diff --git a/engines/sherlock/events.cpp b/engines/sherlock/events.cpp index ecdbdbe8d7..69e89e7157 100644 --- a/engines/sherlock/events.cpp +++ b/engines/sherlock/events.cpp @@ -33,7 +33,7 @@ namespace Sherlock { EventsManager::EventsManager(SherlockEngine *vm) { _vm = vm; _cursorImages = nullptr; - _cursorIndex = -1; + _cursorId = INVALID_CURSOR; _frameCounter = 1; _priorFrameTime = 0; _mouseClicked = false; @@ -57,11 +57,14 @@ void EventsManager::loadCursors(const Common::String &filename) { /** * Set the cursor to show */ -void EventsManager::changeCursor(int cursorIndex) { - _cursorIndex = cursorIndex; +void EventsManager::changeCursor(CursorId cursorId) { + if (cursorId == _cursorId) + return; + + _cursorId = cursorId; // Set the cursor data - Graphics::Surface &s = (*_cursorImages)[cursorIndex]; + Graphics::Surface &s = (*_cursorImages)[cursorId]; CursorMan.replaceCursor(s.getPixels(), s.w, s.h, s.w / 2, s.h / 2, 0xff); showCursor(); diff --git a/engines/sherlock/events.h b/engines/sherlock/events.h index 0fa6bf3a5e..8965489e27 100644 --- a/engines/sherlock/events.h +++ b/engines/sherlock/events.h @@ -33,6 +33,8 @@ namespace Sherlock { #define GAME_FRAME_RATE 60 #define GAME_FRAME_TIME (1000 / GAME_FRAME_RATE) +enum CursorId { ARROW = 0, MAGNIFY = 1, WAIT = 2, INVALID_CURSOR = -1 }; + class SherlockEngine; class EventsManager { @@ -45,7 +47,7 @@ private: bool checkForNextFrameCounter(); public: - int _cursorIndex; + CursorId _cursorId; byte _mouseButtons; bool _mouseClicked; Common::Stack _pendingKeys; @@ -55,7 +57,7 @@ public: void loadCursors(const Common::String &filename); - void changeCursor(int cursorIndex); + void changeCursor(CursorId cursorId); void showCursor(); diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index a12939e787..ece96457db 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -77,7 +77,6 @@ void Sprite::setImageFrame() { void Sprite::adjustSprite() { People &people = *_vm->_people; Scene &scene = *_vm->_scene; - int checkFrame = _allow ? MAX_FRAME : 32000; if (_type == INVALID || (_type == CHARACTER && _vm->_animating)) return; @@ -202,6 +201,17 @@ void UseType::synchronize(Common::SeekableReadStream &s) { /*----------------------------------------------------------------*/ +SherlockEngine *Object::_vm; +bool Object::_countCAnimFrames; + +void Object::setVm(SherlockEngine *vm) { + _vm = vm; + _countCAnimFrames = false; +} + +/** + * Load the object data from the passed stream + */ void Object::synchronize(Common::SeekableReadStream &s) { char buffer[50]; @@ -225,8 +235,8 @@ void Object::synchronize(Common::SeekableReadStream &s) { _sequenceNumber = s.readSint16LE(); _position.x = s.readSint16LE(); _position.y = s.readSint16LE(); - _movement.x = s.readSint16LE(); - _movement.y = s.readSint16LE(); + _delta.x = s.readSint16LE(); + _delta.y = s.readSint16LE(); _type = (SpriteType)s.readUint16LE(); _oldPosition.x = s.readSint16LE(); _oldPosition.y = s.readSint16LE(); @@ -268,6 +278,9 @@ void Object::synchronize(Common::SeekableReadStream &s) { _use[idx].synchronize(s); } +/** + * Toggle the type of an object between hidden and active + */ void Object::toggleHidden() { if (_type != HIDDEN && _type != HIDE_SHAPE && _type != INVALID) { if (_seqTo != 0) @@ -303,6 +316,153 @@ void Object::toggleHidden() { } } +/** + * Check the state of the object + */ +void Object::checkObject(Object &o) { + Scene &scene = *_vm->_scene; + Sound &sound = *_vm->_sound; + int checkFrame = _allow ? MAX_FRAME : 32000; + bool codeFound; + + if (_seqTo) { + byte *ptr = &_sequences[_frameNumber]; + if (*ptr == _seqTo) { + // The sequence is completed + *ptr = _seqTo + SEQ_TO_CODE + 128; // Reset to normal + _seqTo = 0; + } else { + // Continue doing sequence + if (*ptr > _seqTo) + *ptr--; + else + *ptr++; + + return; + } + } + + ++_frameNumber; + + do { + // Check for end of sequence + codeFound = checkEndOfSequence(); + + if (_sequences[_frameNumber] >= 128 && _frameNumber < checkFrame) { + codeFound = true; + int v = _sequences[_frameNumber]; + + if (v >= 228) { + // Goto code found + v -= 228; + _seqcounter2 = _seqCounter; + _seqStack = _frameNumber + 1; + setObjSequence(v, false); + } else if (v >= SOUND_CODE && (v <= (SOUND_CODE + 29))) { + codeFound = true; + ++_frameNumber; + v -= SOUND_CODE; + + if (sound._soundOn && !_countCAnimFrames) { + if (!scene._sounds[v - 1]._name.empty() && sound._digitized) + sound.playLoadedSound(v - 1, 0); + } + } else if (v >= FLIP_CODE && v <= (FLIP_CODE + 2)) { + // Flip code + codeFound = true; + ++_frameNumber; + v -= FLIP_CODE; + + // Alter the flipped status + switch (v) { + case 0: + // Clear the flag + _flags &= ~2; + break; + case 1: + // Set the flag + _flags |= 2; + break; + case 2: + // Toggle the flag + _flags ^= 2; + break; + default: + break; + } + } else { + v -= 128; + + // 68-99 is a squence code + if (v > SEQ_TO_CODE) { + byte *p = &_sequences[_frameNumber]; + v -= SEQ_TO_CODE; // # from 1-32 + _seqTo = v; + *p = *(p - 1); + + if (*p > 128) + // If the high bit is set, convert to a real frame + *p -= (byte)(SEQ_TO_CODE - 128); + + if (*p > _seqTo) + *p -= 1; + else + *p += 1; + + // Will be incremented below to return back to original value + --_frameNumber; + v = 0; + } else if (v == 10) { + // Set delta for objects + Common::Point pt(_sequences[_frameNumber + 1], _sequences[_frameNumber + 2]); + if (pt.x > 128) + pt.x = (pt.x - 128) * -1; + else + pt.x--; + + if (pt.y > 128) + pt.y = (pt.y - 128) * -1; + else + pt.y; + + _delta = pt; + _frameNumber += 2; + } else if (v < 4) { + for (int idx = 0; idx < 4; ++idx) { + o.checkNameForCodes(_use[v]._names[idx], nullptr); + } + + if (_use[v]._useFlag) + _vm->setFlags(_use[v]._useFlag); + } + + ++_frameNumber; + } + } + } while (codeFound); +} + +bool Object::checkEndOfSequence() const { + // TODO + return false; +} + +void Object::setObjSequence(int seq, bool wait) { + // TODO +} + +/** +* Checks for codes +* @param name The name to check for codes +* @param messages If provided, any messages to be returned +* @returns 0 if no codes are found, 1 if codes were found +*/ +int Object::checkNameForCodes(const Common::String &name, Common::StringArray *messages) { + + // TODO + return 0; +} + /*----------------------------------------------------------------*/ void CAnim::synchronize(Common::SeekableReadStream &s) { @@ -318,10 +478,10 @@ void CAnim::synchronize(Common::SeekableReadStream &s) { _flags = s.readByte(); _goto.x = s.readSint16LE(); _goto.y = s.readSint16LE(); - _sequenceNumber = s.readSint16LE(); + _gotoDir = s.readSint16LE(); _teleportPos.x = s.readSint16LE(); _teleportPos.y = s.readSint16LE(); - _teleportS = s.readSint16LE(); + _teleportDir = s.readSint16LE(); } /*----------------------------------------------------------------*/ diff --git a/engines/sherlock/objects.h b/engines/sherlock/objects.h index d9f1c7409e..d7442f928f 100644 --- a/engines/sherlock/objects.h +++ b/engines/sherlock/objects.h @@ -137,7 +137,18 @@ struct UseType { void synchronize(Common::SeekableReadStream &s); }; -struct Object { +class Object { +private: + static SherlockEngine *_vm; + + bool checkEndOfSequence() const; + + void setObjSequence(int seq, bool wait); +public: + static bool _countCAnimFrames; + + static void setVm(SherlockEngine *vm); +public: Common::String _name; // Name Common::String _description; // Description Common::String _examine; // Examine in-depth description @@ -151,7 +162,7 @@ struct Object { int _sequenceNumber; // Sequence being used SpriteType _type; // Object type Common::Point _position; // Current position - Common::Point _movement; // Momvement amount + Common::Point _delta; // Momvement amount Common::Point _oldPosition; // Old position Common::Point _oldSize; // Image's old size Common::Point _goto; // Walk destination @@ -185,19 +196,23 @@ struct Object { void synchronize(Common::SeekableReadStream &s); void toggleHidden(); + + void checkObject(Object &o); + + int checkNameForCodes(const Common::String &name, Common::StringArray *messages); }; struct CAnim { Common::String _name; // Name - int _sequences[MAX_FRAME]; // Animation sequences + byte _sequences[MAX_FRAME]; // Animation sequences Common::Point _position; // Position int _size; // Size of uncompressed animation SpriteType _type; int _flags; // Tells if can be walked behind Common::Point _goto; // coords holmes should walk to before starting canim - int _sequenceNumber; + int _gotoDir; Common::Point _teleportPos; // Location Holmes shoul teleport to after - int _teleportS; // playing canim + int _teleportDir; // playing canim void synchronize(Common::SeekableReadStream &s); }; diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp index 998fe4f0cf..43d3422f1a 100644 --- a/engines/sherlock/people.cpp +++ b/engines/sherlock/people.cpp @@ -289,4 +289,9 @@ void People::gotoStand(Sprite &sprite) { _allowWalkAbort = true; } +void People::walkToCoords(const Common::Point &destPos, int destDir) { + // TODO + warning("TODO: walkToCoords"); +} + } // End of namespace Sherlock diff --git a/engines/sherlock/people.h b/engines/sherlock/people.h index e58fd33ef2..d2d7e92512 100644 --- a/engines/sherlock/people.h +++ b/engines/sherlock/people.h @@ -79,6 +79,8 @@ public: void setWalking(); void gotoStand(Sprite &sprite); + + void walkToCoords(const Common::Point &destPos, int destDir); }; } // End of namespace Sherlock diff --git a/engines/sherlock/resources.cpp b/engines/sherlock/resources.cpp index 66feca6bd5..9e25a8dd6e 100644 --- a/engines/sherlock/resources.cpp +++ b/engines/sherlock/resources.cpp @@ -129,7 +129,7 @@ void Resources::addToCache(const Common::String &filename) { } /** - * Adds a resource from a library file tot he cache + * Adds a resource from a library file to the cache */ void Resources::addToCache(const Common::String &filename, const Common::String &libFilename) { // Get the resource @@ -140,6 +140,16 @@ void Resources::addToCache(const Common::String &filename, const Common::String delete stream; } +/** + * Adds a given stream to the cache under the given name + */ +void Resources::addToCache(const Common::String &filename, Common::SeekableReadStream &stream) { + _cache.load(filename, stream); +} + +/** + * Returns a stream for a given file + */ Common::SeekableReadStream *Resources::load(const Common::String &filename) { // First check if the file is directly in the cache if (_cache.isCached(filename)) diff --git a/engines/sherlock/resources.h b/engines/sherlock/resources.h index 2f9222c1fd..1d8c601e77 100644 --- a/engines/sherlock/resources.h +++ b/engines/sherlock/resources.h @@ -76,6 +76,7 @@ public: void addToCache(const Common::String &filename); void addToCache(const Common::String &filename, const Common::String &libFilename); + void addToCache(const Common::String &filename, Common::SeekableReadStream &stream); bool isInCache(const Common::String &filename) const { return _cache.isCached(filename); } Common::SeekableReadStream *load(const Common::String &filename); diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp index 2477f2894f..b8c7661966 100644 --- a/engines/sherlock/scalpel/scalpel.cpp +++ b/engines/sherlock/scalpel/scalpel.cpp @@ -183,7 +183,7 @@ bool ScalpelEngine::showOfficeCutscene() { void ScalpelEngine::startScene() { if (_scene->_goToRoom == 100 || _scene->_goToRoom == 98) { // Chessboard selection - if (_sound->_musicEnabled) { + if (_sound->_musicOn) { if (_sound->loadSong(100)) { if (_sound->_music) _sound->startSong(); @@ -208,7 +208,7 @@ void ScalpelEngine::startScene() { case 52: case 53: case 70: - if (_sound->_musicEnabled && _sound->loadSong(_scene->_goToRoom)) { + if (_sound->_musicOn && _sound->loadSong(_scene->_goToRoom)) { if (_sound->_music) _sound->startSong(); } @@ -325,7 +325,7 @@ void ScalpelEngine::startScene() { } _events->loadCursors("rmouse.vgs"); - _events->changeCursor(0); + _events->changeCursor(ARROW); if (_scene->_goToRoom == 99) { // Chess Board diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 9fbec6b776..8158dfc705 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -98,6 +98,7 @@ Scene::Scene(SherlockEngine *vm): _vm(vm) { _invGraphicItems = 0; _hsavedPos = Common::Point(-1, -1); _hsavedFs = -1; + _cAnimFramePause = 0; _controlPanel = new ImageFile("controls.vgs"); _controls = nullptr; // new ImageFile("menu.all"); @@ -124,7 +125,7 @@ void Scene::selectScene() { // Load the scene Common::String sceneFile = Common::String::format("res%02d", _goToRoom); - Common::String roomName = Common::String::format("res%02d.rrm", _goToRoom); + _rrmName = Common::String::format("res%02d.rrm", _goToRoom); _currentScene = _goToRoom; _goToRoom = -1; @@ -312,7 +313,7 @@ bool Scene::loadScene(const Common::String &filename) { _sounds[idx].synchronize(*rrmStream); // If sound is turned on, load the sounds into memory - if (sound._sfxEnabled) { + if (sound._soundOn) { for (int idx = 0; idx < numSounds; ++idx) { sound.loadSound(_sounds[idx]._name, _sounds[idx]._priority); _sounds[idx]._name = ""; @@ -374,7 +375,7 @@ bool Scene::loadScene(const Common::String &filename) { checkInventory(); // Handle starting any music for the scene - if (sound._musicEnabled && sound.loadSong(_currentScene)) { + if (sound._musicOn && sound.loadSong(_currentScene)) { if (sound._music) sound.startSong(); } @@ -516,6 +517,7 @@ void Scene::transitionToScene() { STOP_DOWNLEFT, STOP_LEFT, STOP_UPLEFT }; People &people = *_vm->_people; + Screen &screen = *_vm->_screen; if (_hsavedPos.x < 1) { // No exit information from last scene-check entrance info @@ -539,7 +541,7 @@ void Scene::transitionToScene() { } } - int startcAnimNum = -1; + int cAnimNum = -1; if (_hsavedFs < 101) { // Standard info, so set it @@ -547,7 +549,7 @@ void Scene::transitionToScene() { people[PLAYER]._sequenceNumber = _hsavedFs; } else { // It's canimation information - startcAnimNum = _hsavedFs - 101; + cAnimNum = _hsavedFs - 101; // Prevent Holmes from being drawn people[PLAYER]._position = Common::Point(0, 0); @@ -599,7 +601,22 @@ void Scene::transitionToScene() { } updateBackground(); - // TODO + + if (screen._fadeStyle) + screen.randomTransition(); + else + screen.blitFrom(screen._backBuffer); + + if (cAnimNum != -1) { + CAnim &c = _cAnim[cAnimNum]; + Common::Point pt = c._position; + + c._position = Common::Point(-1, -1); + people[AL]._position = Common::Point(0, 0); + + startCAnim(cAnimNum, 1); + c._position = pt; + } } /** @@ -722,9 +739,265 @@ Exit *Scene::checkForExit(const Common::Rect &r) { return nullptr; } +/** + * Checks all the background shapes. If a background shape is animating, + * it will flag it as needing to be drawn. If a non-animating shape is + * colliding with another shape, it will also flag it as needing drawing + */ void Scene::checkBgShapes(ImageFrame *frame, const Common::Point &pt) { + // Iterate through the shapes + for (uint idx = 0; idx < _bgShapes.size(); ++idx) { + Object &obj = _bgShapes[idx]; + if (obj._type == STATIC_BG_SHAPE || obj._type == ACTIVE_BG_SHAPE) { + if ((obj._flags & 5) == 1) { + obj._misc = (pt.y < (obj._position.y + obj._imageFrame->_frame.h - 1)) ? + NORMAL_FORWARD : NORMAL_BEHIND; + } else if (!(obj._flags & 1)) { + obj._misc = BEHIND; + } else if (obj._flags & 4) { + obj._misc = FORWARD; + } + } + } + + // Iterate through the canimshapes + for (uint idx = 0; idx < _canimShapes.size(); ++idx) { + Object &obj = _canimShapes[idx]; + if (obj._type == STATIC_BG_SHAPE || obj._type == ACTIVE_BG_SHAPE) { + if ((obj._flags & 5) == 1) { + obj._misc = (pt.y < (obj._position.y + obj._imageFrame->_frame.h - 1)) ? + NORMAL_FORWARD : NORMAL_BEHIND; + } + else if (!(obj._flags & 1)) { + obj._misc = BEHIND; + } + else if (obj._flags & 4) { + obj._misc = FORWARD; + } + } + } +} + +/** + * Attempt to start a canimation sequence. It will load the requisite graphics, and + * then copy the canim object into the _canimShapes array to start the animation. + * + * @param cAnimNum The canim object within the current scene + * @param playRate Play rate. 0 is invalid; 1=normal speed, 2=1/2 speed, etc. + * A negative playRate can also be specified to play the animation in reverse + */ +int Scene::startCAnim(int cAnimNum, int playRate) { + EventsManager &events = *_vm->_events; + People &people = *_vm->_people; + Resources &res = *_vm->_res; + Common::Point tpPos, walkPos; + int tpDir, walkDir; + int tFrames; + int gotoCode = -1; + + // Validation + if (cAnimNum >= (int)_cAnim.size()) + // number out of bounds + return -1; + if (_canimShapes.size() >= 3 || playRate == 0) + // Too many active animations, or invalid play rate + return 0; + + CAnim &cAnim = _cAnim[cAnimNum]; + if (playRate < 0) { + // Reverse direction + walkPos = cAnim._teleportPos; + walkDir = cAnim._teleportDir; + tpPos = cAnim._goto; + tpDir = cAnim._gotoDir; + } else { + // Forward direction + walkPos = cAnim._goto; + walkDir = cAnim._gotoDir; + tpPos = cAnim._teleportPos; + tpDir = cAnim._teleportDir; + } + + events.changeCursor(WAIT); + _canimShapes.push_back(Object()); + Object &cObj = _canimShapes[_canimShapes.size() - 1]; + + if (walkPos.x != -1) { + // Holmes must walk to the walk point before the cAnimation is started + if (people[AL]._position != walkPos) + people.walkToCoords(walkPos, walkDir); + } + + if (_vm->_talkToAbort) + return 1; + + // Copy the canimation into the bgShapes type canimation structure so it can be played + cObj._allow = cAnimNum + 1; // Keep track of the parent structure + cObj._name = _cAnim[cAnimNum]._name; // Copy name + + // Remove any attempt to draw object frame + if (cAnim._type == NO_SHAPE && cAnim._sequences[0] < 100) + cAnim._sequences[0] = 0; + + cObj._sequences = cAnim._sequences; + cObj._images = nullptr; + cObj._position = cAnim._position; + cObj._delta = Common::Point(0, 0); + cObj._type = cAnim._type; + cObj._flags = cAnim._flags; + + cObj._maxFrames = 0; + cObj._frameNumber = -1; + cObj._sequenceNumber = cAnimNum; + cObj._oldPosition = Common::Point(0, 0); + cObj._oldPosition = Common::Point(0, 0); + cObj._goto = Common::Point(0, 0); + cObj._status = 0; + cObj._misc = 0; + cObj._imageFrame = nullptr; + + if (cAnim._name.size() > 0 && cAnim._type != NO_SHAPE) { + if (tpPos.x != -1) + people[AL]._type = REMOVE; + + Common::String fname = cAnim._name + ".vgs"; + if (!res.isInCache(fname)) { + // Set up RRM scene data + Common::SeekableReadStream *rrmStream = res.load(_rrmName); + rrmStream->seek(44 + cAnimNum * 4); + rrmStream->seek(rrmStream->readUint32LE()); + + // Load the canimation into the cache + Common::SeekableReadStream *imgStream = !_lzwMode ? rrmStream : + decompressLZ(*rrmStream, cAnim._size); + res.addToCache(fname, *imgStream); + + if (_lzwMode) + delete imgStream; + + delete rrmStream; + } + + // Now load the resource as an image + cObj._maxFrames = cObj._images->size(); + cObj._images = new ImageFile(fname); + cObj._imageFrame = &(*cObj._images)[0]; + + int frames = 0; + if (playRate < 0) { + // Reverse direction + // Count number of frames + while (cObj._sequences[frames] && frames < MAX_FRAME) + ++frames; + } + else { + // Forward direction + Object::_countCAnimFrames = true; + + while (cObj._type == ACTIVE_BG_SHAPE) { + cObj.checkObject(_bgShapes[0]); + ++frames; + + if (frames >= 1000) + error("CAnim has infinite loop sequence"); + } + + if (frames > 1) + --frames; + + Object::_countCAnimFrames = false; + + cObj._type = cAnim._type; + cObj._frameNumber = -1; + cObj._position = cAnim._position; + cObj._delta = Common::Point(0, 0); + } + + // Return if animation has no frames in it + if (frames == 0) + return -2; + + ++frames; + int repeat = ABS(playRate); + int dir; + + if (playRate < 0) { + // Play in reverse + dir = -2; + cObj._frameNumber = frames - 3; + } else { + dir = 0; + } + + tFrames = frames - 1; + int pauseFrame = (_cAnimFramePause) ? frames - _cAnimFramePause : -1; + + while (--frames) { + if (frames == pauseFrame) + printObjDesc(_cAnimStr, true); + + doBgAnim(); + + // Repeat same frame + int temp = repeat; + while (--temp > 0) { + cObj._frameNumber--; + doBgAnim(); + } + + cObj._frameNumber += dir; + } + + people[AL]._type = CHARACTER; + } + + // Teleport to ending coordinates if necessary + if (tpPos.x != -1) { + people[AL]._position = tpPos; // Place the player + people[AL]._sequenceNumber = tpDir; + people.gotoStand(people[AL]); + } + + if (playRate < 0) + // Reverse direction - set to end sequence + cObj._frameNumber = tFrames - 1; + + if (cObj._frameNumber <= 26) + gotoCode = cObj._sequences[cObj._frameNumber + 3]; + + // Set canim to REMOVE type and free memory + cObj.checkObject(_bgShapes[0]); + + if (gotoCode > 0 && !_vm->_talkToAbort) { + _goToRoom = gotoCode; + + if (_goToRoom < 97 && _vm->_map[_goToRoom].x) { + _overPos = _vm->_map[_goToRoom]; + } + } + + people.loadWalk(); + + if (tpPos.x != -1 && !_vm->_talkToAbort) { + // Teleport to ending coordinates + people[AL]._position = tpPos; + people[AL]._sequenceNumber = tpDir; + + people.gotoStand(people[AL]); + } + + return 1; +} + +void Scene::printObjDesc(const Common::String &str, bool firstTime) { // TODO } +/** + * Animate all objects and people. + */ +void Scene::doBgAnim() { + // TODO +} } // End of namespace Sherlock diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h index 8986b62bf5..06ca2f4c0d 100644 --- a/engines/sherlock/scene.h +++ b/engines/sherlock/scene.h @@ -87,6 +87,9 @@ struct SceneSound { class Scene { private: SherlockEngine *_vm; + Common::String _rrmName; + int _cAnimFramePause; + Common::String _cAnimStr; bool loadScene(const Common::String &filename); @@ -101,6 +104,10 @@ private: void updateBackground(); void checkBgShapes(ImageFrame *frame, const Common::Point &pt); + + int startCAnim(int cAnimNum, int playRate); + + void doBgAnim(); public: int _currentScene; int _goToRoom; @@ -147,6 +154,8 @@ public: void checkSceneFlags(bool mode); Exit *checkForExit(const Common::Rect &r); + + void printObjDesc(const Common::String &str, bool firstTime); }; } // End of namespace Sherlock diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index 257cbb2cab..756be22846 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -70,6 +70,7 @@ void SherlockEngine::initialize() { DebugMan.addDebugChannel(kDebugScript, "scripts", "Script debug level"); ImageFile::setVm(this); + Object::setVm(this); Sprite::setVm(this); _res = new Resources(); _animation = new Animation(this); diff --git a/engines/sherlock/sound.cpp b/engines/sherlock/sound.cpp index 61c740ea3f..0917f83e89 100644 --- a/engines/sherlock/sound.cpp +++ b/engines/sherlock/sound.cpp @@ -25,11 +25,12 @@ namespace Sherlock { Sound::Sound(SherlockEngine *vm): _vm(vm) { - _sfxEnabled = true; - _musicEnabled = true; - _voicesEnabled = true; + _soundOn = true; + _musicOn = true; + _voicesOn = true; _playingEpilogue = false; _music = false; + _digitized = false; } void Sound::loadSound(const Common::String &name, int priority) { @@ -44,6 +45,10 @@ void Sound::cacheSound(const Common::String &name, int index) { // TODO } +void Sound::playLoadedSound(int bufNum, int waitMode) { + // TODO +} + void Sound::playCachedSound(int index) { // TODO } diff --git a/engines/sherlock/sound.h b/engines/sherlock/sound.h index 9d323833f1..b6e645a28f 100644 --- a/engines/sherlock/sound.h +++ b/engines/sherlock/sound.h @@ -38,17 +38,19 @@ class Sound { private: SherlockEngine *_vm; public: - bool _sfxEnabled; - bool _musicEnabled; - bool _voicesEnabled; + bool _soundOn; + bool _musicOn; + bool _voicesOn; bool _playingEpilogue; bool _music; + bool _digitized; public: Sound(SherlockEngine *vm); void loadSound(const Common::String &name, int priority); void playSound(const Common::String &name, WaitType waitType = WAIT_RETURN_IMMEDIATELY); void cacheSound(const Common::String &name, int index); + void playLoadedSound(int bufNum, int waitMode); void playCachedSound(int index); void clearCache(); void stopSound(); -- cgit v1.2.3 From 7f04ea4425bae0ebac7e51d71dc315b965bf94c9 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 21 Mar 2015 20:25:15 -0400 Subject: SHERLOCK: Implemented checkSprite --- engines/sherlock/animation.cpp | 4 +- engines/sherlock/events.cpp | 35 ++++--- engines/sherlock/events.h | 12 ++- engines/sherlock/objects.cpp | 195 ++++++++++++++++++++++++++++++++++- engines/sherlock/objects.h | 4 + engines/sherlock/resources.cpp | 6 +- engines/sherlock/resources.h | 2 +- engines/sherlock/scalpel/scalpel.cpp | 2 +- engines/sherlock/scene.cpp | 80 +++++++++++--- engines/sherlock/scene.h | 29 +++++- engines/sherlock/screen.cpp | 4 +- engines/sherlock/sherlock.cpp | 6 +- engines/sherlock/sherlock.h | 4 +- engines/sherlock/sound.cpp | 3 + engines/sherlock/sound.h | 3 + engines/sherlock/talk.cpp | 9 +- engines/sherlock/talk.h | 10 +- 17 files changed, 355 insertions(+), 53 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/animation.cpp b/engines/sherlock/animation.cpp index a7f91e91cd..9d32746de4 100644 --- a/engines/sherlock/animation.cpp +++ b/engines/sherlock/animation.cpp @@ -66,7 +66,7 @@ Animation::Animation(SherlockEngine *vm): _vm(vm) { bool Animation::playPrologue(const Common::String &filename, int minDelay, int fade, bool setPalette, int speed) { - EventsManager &events = *_vm->_events; + Events &events = *_vm->_events; Screen &screen = *_vm->_screen; Sound &sound = *_vm->_sound; int soundNumber = 0; @@ -123,7 +123,7 @@ bool Animation::playPrologue(const Common::String &filename, int minDelay, int f pt.x = stream->readUint16LE(); pt.y = stream->readUint16LE(); } else { - pt = images[imageFrame]._position; + pt = images[imageFrame]._offset; } // Draw the sprite diff --git a/engines/sherlock/events.cpp b/engines/sherlock/events.cpp index 69e89e7157..1a09f0600e 100644 --- a/engines/sherlock/events.cpp +++ b/engines/sherlock/events.cpp @@ -30,7 +30,7 @@ namespace Sherlock { -EventsManager::EventsManager(SherlockEngine *vm) { +Events::Events(SherlockEngine *vm) { _vm = vm; _cursorImages = nullptr; _cursorId = INVALID_CURSOR; @@ -40,14 +40,14 @@ EventsManager::EventsManager(SherlockEngine *vm) { _mouseButtons = 0; } -EventsManager::~EventsManager() { +Events::~Events() { delete _cursorImages; } /** * Load a set of cursors from the specified file */ -void EventsManager::loadCursors(const Common::String &filename) { +void Events::loadCursors(const Common::String &filename) { hideCursor(); delete _cursorImages; @@ -57,7 +57,7 @@ void EventsManager::loadCursors(const Common::String &filename) { /** * Set the cursor to show */ -void EventsManager::changeCursor(CursorId cursorId) { +void Events::setCursor(CursorId cursorId) { if (cursorId == _cursorId) return; @@ -73,28 +73,35 @@ void EventsManager::changeCursor(CursorId cursorId) { /** * Show the mouse cursor */ -void EventsManager::showCursor() { +void Events::showCursor() { CursorMan.showMouse(true); } /** * Hide the mouse cursor */ -void EventsManager::hideCursor() { +void Events::hideCursor() { CursorMan.showMouse(false); } +/** + * Returns the cursor + */ +CursorId Events::getCursor() const { + return _cursorId; +} + /** * Returns true if the mouse cursor is visible */ -bool EventsManager::isCursorVisible() { +bool Events::isCursorVisible() const { return CursorMan.isVisible(); } /** * Check for any pending events */ -void EventsManager::pollEvents() { +void Events::pollEvents() { checkForNextFrameCounter(); Common::Event event; @@ -138,7 +145,7 @@ void EventsManager::pollEvents() { * Poll for events and introduce a small delay, to allow the system to * yield to other running programs */ -void EventsManager::pollEventsAndWait() { +void Events::pollEventsAndWait() { pollEvents(); g_system->delayMillis(10); } @@ -146,7 +153,7 @@ void EventsManager::pollEventsAndWait() { /** * Check whether it's time to display the next screen frame */ -bool EventsManager::checkForNextFrameCounter() { +bool Events::checkForNextFrameCounter() { // Check for next game frame uint32 milli = g_system->getMillis(); if ((milli - _priorFrameTime) >= GAME_FRAME_TIME) { @@ -171,7 +178,7 @@ bool EventsManager::checkForNextFrameCounter() { /** * Clear any current keypress or mouse click */ -void EventsManager::clearEvents() { +void Events::clearEvents() { _pendingKeys.clear(); _mouseClicked = false; } @@ -179,12 +186,12 @@ void EventsManager::clearEvents() { /** * Delay for a given number of game frames, where each frame is 1/60th of a second */ -void EventsManager::wait(int numFrames) { +void Events::wait(int numFrames) { uint32 totalMilli = numFrames * 1000 / GAME_FRAME_RATE; delay(totalMilli); } -bool EventsManager::delay(uint32 time, bool interruptable) { +bool Events::delay(uint32 time, bool interruptable) { // Different handling for really short versus extended times if (time < 10) { // For really short periods, simply delay by the desired amount @@ -216,7 +223,7 @@ bool EventsManager::delay(uint32 time, bool interruptable) { /** * Wait for the next frame */ -void EventsManager::waitForNextFrame() { +void Events::waitForNextFrame() { _mouseClicked = false; _mouseButtons = 0; diff --git a/engines/sherlock/events.h b/engines/sherlock/events.h index 8965489e27..e939b5768f 100644 --- a/engines/sherlock/events.h +++ b/engines/sherlock/events.h @@ -37,7 +37,7 @@ enum CursorId { ARROW = 0, MAGNIFY = 1, WAIT = 2, INVALID_CURSOR = -1 }; class SherlockEngine; -class EventsManager { +class Events { private: SherlockEngine *_vm; uint32 _frameCounter; @@ -52,18 +52,20 @@ public: bool _mouseClicked; Common::Stack _pendingKeys; public: - EventsManager(SherlockEngine *vm); - ~EventsManager(); + Events(SherlockEngine *vm); + ~Events(); void loadCursors(const Common::String &filename); - void changeCursor(CursorId cursorId); + void setCursor(CursorId cursorId); void showCursor(); void hideCursor(); - bool isCursorVisible(); + CursorId getCursor() const; + + bool isCursorVisible() const; void pollEvents(); diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index ece96457db..5a93ce6869 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -33,6 +33,10 @@ namespace Sherlock { #define LEFT_LIMIT 0 #define RIGHT_LIMIT SHERLOCK_SCREEN_WIDTH +// Distance to walk around WALK_AROUND boxes +#define CLEAR_DIST_X 5 +#define CLEAR_DIST_Y 0 + SherlockEngine *Sprite::_vm; /** @@ -77,11 +81,12 @@ void Sprite::setImageFrame() { void Sprite::adjustSprite() { People &people = *_vm->_people; Scene &scene = *_vm->_scene; + Talk &talk = *_vm->_talk; if (_type == INVALID || (_type == CHARACTER && _vm->_animating)) return; - if (!_vm->_talkCounter && _type == CHARACTER && _walkCount) { + if (!talk._talkCounter && _type == CHARACTER && _walkCount) { // Handle active movement for the sprite _position += _delta; --_walkCount; @@ -163,6 +168,190 @@ void Sprite::adjustSprite() { } } +/** + * Checks the sprite's position to see if it's collided with any special objects + */ +void Sprite::checkSprite() { + Events &events = *_vm->_events; + People &people = *_vm->_people; + Scene &scene = *_vm->_scene; + Screen &screen = *_vm->_screen; + Talk &talk = *_vm->_talk; + Common::Point pt; + Common::Rect objBounds; + Common::Point spritePt(_position.x / 100, _position.y / 100); + + if (!talk._talkCounter && _type == CHARACTER) { + pt = _walkCount ? _position + _delta : _position; + pt.x /= 100; + pt.y /= 100; + + for (uint idx = 0; idx < scene._bgShapes.size() && !talk._talkToAbort; ++idx) { + Object &obj = scene._bgShapes[idx]; + + if (obj._aType > PERSON && _type != INVALID && _type != HIDDEN) { + if (_type == NO_SHAPE) { + objBounds = Common::Rect(_position.x, _position.y, + _position.x + _noShapeSize.x, _position.y + _noShapeSize.y); + } else { + int xp = _position.x + _imageFrame->_offset.x; + int yp = _position.y + _imageFrame->_offset.y; + objBounds = Common::Rect(xp, yp, + xp + _imageFrame->_frame.w, yp + _imageFrame->_frame.h); + } + } + + if (objBounds.contains(pt)) { + if (objBounds.contains(spritePt)) { + // Current point is already inside the the bounds, so impact occurred + // on a previous call. So simply do nothing until we're clear of the box + switch (obj._aType) { + case TALK_MOVE: + if (_walkCount) { + // Holmes is moving + obj._type = HIDDEN; + obj.setFlagsAndToggles(); + talk.talkTo(obj._use[0]._target); + } + break; + + case PAL_CHANGE: + case PAL_CHANGE2: + if (_walkCount) { + int palStart = atoi(obj._use[0]._names[0].c_str()) * 3; + int palLength = atoi(obj._use[0]._names[1].c_str()) * 3; + int templ = atoi(obj._use[0]._names[2].c_str()) * 3; + if (templ == 0) + templ = 100; + + // Ensure only valid palette change data found + if (palLength > 0) { + // Figure out how far into the shape Holmes is so that we + // can figure out what percentage of the original palette + // to set the current palette to + int palPercent = (pt.x - objBounds.left) * 100 / objBounds.width(); + palPercent = palPercent * templ / 100; + if (obj._aType == PAL_CHANGE) + // Invert percentage + palPercent = 100 - palPercent; + + for (int idx = palStart; idx < (palStart + palLength); ++idx) + screen._sMap[idx] = screen._cMap[idx] * palPercent / 100; + + events.pollEvents(); + screen.setPalette(screen._sMap); + } + } + break; + + case TALK: + case TALK_EVERY: + _type = HIDDEN; + obj.setFlagsAndToggles(); + talk.talkTo(obj._use[0]._target); + break; + + default: + break; + } + } else { + // New impact just occurred + switch (obj._aType) { + case BLANK_ZONE: + // A blank zone masks out all other remaining zones underneath it. + // If this zone is hit, exit the outer loop so we do not check anymore + return; + + case SOLID: + case TALK: + // Stop walking + if (obj._aType == TALK) { + obj.setFlagsAndToggles(); + talk.talkTo(obj._use[0]._target); + } else { + people.gotoStand(*this); + } + break; + + case TALK_EVERY: + if (obj._aType == TALK_EVERY) { + obj._type = HIDDEN; + obj.setFlagsAndToggles(); + talk.talkTo(obj._use[0]._target); + } else { + people.gotoStand(*this); + } + break; + + case FLAG_SET: + obj.setFlagsAndToggles(); + obj._type = HIDDEN; + break; + + case WALK_AROUND: + if (objBounds.contains(people._walkTo.top())) { + // Reached zone + people.gotoStand(*this); + } else { + // Destination not within box, walk to best corner + Common::Point walkPos; + + if (spritePt.x >= objBounds.left && spritePt.x < objBounds.right) { + // Impact occurred due to vertical movement. Determine whether to + // travel to the left or right side + if (_delta.x > 0) + // Go to right side + walkPos.x = objBounds.right + CLEAR_DIST_X; + else if (_delta.x < 0) + // Go to left side + walkPos.x = objBounds.left - CLEAR_DIST_X; + else { + // Going straight up or down. So choose best side + if (spritePt.x >= (objBounds.left + objBounds.width() / 2)) + walkPos.x = objBounds.right + CLEAR_DIST_X; + else + walkPos.x = objBounds.left - CLEAR_DIST_X; + } + + walkPos.y = (_delta.y >= 0) ? objBounds.top - CLEAR_DIST_Y : + objBounds.bottom + CLEAR_DIST_Y; + } else { + // Impact occurred due to horizontal movement + if (_delta.y > 0) + // Go to bottom of box + walkPos.y = objBounds.bottom + CLEAR_DIST_Y; + else if (_delta.y < 0) + // Go to top of box + walkPos.y = objBounds.top - CLEAR_DIST_Y; + else { + // Going straight horizontal, so choose best side + if (spritePt.y >= (objBounds.top + objBounds.height() / 2)) + walkPos.y = objBounds.bottom + CLEAR_DIST_Y; + else + walkPos.y = objBounds.top - CLEAR_DIST_Y; + } + + walkPos.x = (_delta.x >= 0) ? objBounds.left - CLEAR_DIST_X : + objBounds.right + CLEAR_DIST_X; + } + + walkPos.x += people[AL]._imageFrame->_frame.w / 2; + people._walkDest = walkPos; + people._walkTo.push(walkPos); + people.setWalking(); + } + break; + + case DELTA: + _position.x += 200; + break; + } + } + } + } + } +} + /*----------------------------------------------------------------*/ void ActionType::synchronize(Common::SeekableReadStream &s) { @@ -463,6 +652,10 @@ int Object::checkNameForCodes(const Common::String &name, Common::StringArray *m return 0; } +void Object::setFlagsAndToggles() { + // TODO +} + /*----------------------------------------------------------------*/ void CAnim::synchronize(Common::SeekableReadStream &s) { diff --git a/engines/sherlock/objects.h b/engines/sherlock/objects.h index d7442f928f..d099718d5b 100644 --- a/engines/sherlock/objects.h +++ b/engines/sherlock/objects.h @@ -115,6 +115,8 @@ public: void setImageFrame(); void adjustSprite(); + + void checkSprite(); }; struct ActionType { @@ -200,6 +202,8 @@ public: void checkObject(Object &o); int checkNameForCodes(const Common::String &name, Common::StringArray *messages); + + void setFlagsAndToggles(); }; struct CAnim { diff --git a/engines/sherlock/resources.cpp b/engines/sherlock/resources.cpp index 9e25a8dd6e..4b087b59b5 100644 --- a/engines/sherlock/resources.cpp +++ b/engines/sherlock/resources.cpp @@ -298,10 +298,10 @@ void ImageFile::load(Common::SeekableReadStream &stream, bool skipPalette) { frame._width = stream.readUint16LE() + 1; frame._height = stream.readUint16LE() + 1; frame._flags = stream.readByte(); - frame._position.x = stream.readUint16LE(); - frame._position.y = stream.readByte(); + frame._offset.x = stream.readUint16LE(); + frame._offset.y = stream.readByte(); - frame._rleEncoded = !skipPalette && (frame._position.x == 1); + frame._rleEncoded = !skipPalette && (frame._offset.x == 1); if (frame._flags & 0xFF) { // Nibble packed frame data diff --git a/engines/sherlock/resources.h b/engines/sherlock/resources.h index 1d8c601e77..ab2eb82a1e 100644 --- a/engines/sherlock/resources.h +++ b/engines/sherlock/resources.h @@ -93,7 +93,7 @@ struct ImageFrame { uint16 _width, _height; int _flags; bool _rleEncoded; - Common::Point _position; + Common::Point _offset; byte _rleMarker; Graphics::Surface _frame; diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp index b8c7661966..bb9c6c0bc2 100644 --- a/engines/sherlock/scalpel/scalpel.cpp +++ b/engines/sherlock/scalpel/scalpel.cpp @@ -325,7 +325,7 @@ void ScalpelEngine::startScene() { } _events->loadCursors("rmouse.vgs"); - _events->changeCursor(ARROW); + _events->setCursor(ARROW); if (_scene->_goToRoom == 99) { // Chess Board diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 8158dfc705..13315b065b 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -90,7 +90,7 @@ Scene::Scene(SherlockEngine *vm): _vm(vm) { _changes = false; _charPoint = _oldCharPoint = 0; _windowOpen = _infoFlag = false; - _menuMode = _keyboardInput = 0; + _keyboardInput = 0; _walkedInScene = false; _ongoingCans = 0; _version = 0; @@ -99,6 +99,9 @@ Scene::Scene(SherlockEngine *vm): _vm(vm) { _hsavedPos = Common::Point(-1, -1); _hsavedFs = -1; _cAnimFramePause = 0; + _menuMode = STD_MODE; + _invMode = INVMODE_0; + _restoreFlag = false; _controlPanel = new ImageFile("controls.vgs"); _controls = nullptr; // new ImageFile("menu.all"); @@ -119,7 +122,8 @@ void Scene::clear() { void Scene::selectScene() { // Reset fields _windowOpen = _infoFlag = false; - _menuMode = _keyboardInput = 0; + _menuMode = STD_MODE; + _keyboardInput = 0; _oldKey = _help = _oldHelp = 0; _oldTemp = _temp = 0; @@ -142,7 +146,7 @@ void Scene::selectScene() { * that it should point to after loading; _misc is then set to 0. */ bool Scene::loadScene(const Common::String &filename) { - EventsManager &events = *_vm->_events; + Events &events = *_vm->_events; People &people = *_vm->_people; Screen &screen = *_vm->_screen; Sound &sound = *_vm->_sound; @@ -512,12 +516,14 @@ void Scene::checkInventory() { * in the scene */ void Scene::transitionToScene() { - const int FS_TRANS[8] = { - STOP_UP, STOP_UPRIGHT, STOP_RIGHT, STOP_DOWNRIGHT, STOP_DOWN, - STOP_DOWNLEFT, STOP_LEFT, STOP_UPLEFT - }; People &people = *_vm->_people; Screen &screen = *_vm->_screen; + Talk &talk = *_vm->_talk; + + const int FS_TRANS[8] = { + STOP_UP, STOP_UPRIGHT, STOP_RIGHT, STOP_DOWNRIGHT, STOP_DOWN, + STOP_DOWNLEFT, STOP_LEFT, STOP_UPLEFT + }; if (_hsavedPos.x < 1) { // No exit information from last scene-check entrance info @@ -563,7 +569,7 @@ void Scene::transitionToScene() { Common::Point bottomRight; if (obj._type != NO_SHAPE) { - topLeft += obj._imageFrame->_position; + topLeft += obj._imageFrame->_offset; bottomRight.x = topLeft.x + obj._imageFrame->_frame.w; bottomRight.y = topLeft.y + obj._imageFrame->_frame.h; } else { @@ -583,7 +589,7 @@ void Scene::transitionToScene() { _vm->setFlags(obj._use[useNum]._useFlag); } - if (!_vm->_talkToAbort) { + if (!talk._talkToAbort) { for (int nameIdx = 0; nameIdx < 4; ++nameIdx) { toggleObject(obj._use[useNum]._names[nameIdx]); } @@ -787,9 +793,10 @@ void Scene::checkBgShapes(ImageFrame *frame, const Common::Point &pt) { * A negative playRate can also be specified to play the animation in reverse */ int Scene::startCAnim(int cAnimNum, int playRate) { - EventsManager &events = *_vm->_events; + Events &events = *_vm->_events; People &people = *_vm->_people; Resources &res = *_vm->_res; + Talk &talk = *_vm->_talk; Common::Point tpPos, walkPos; int tpDir, walkDir; int tFrames; @@ -818,7 +825,7 @@ int Scene::startCAnim(int cAnimNum, int playRate) { tpDir = cAnim._teleportDir; } - events.changeCursor(WAIT); + events.setCursor(WAIT); _canimShapes.push_back(Object()); Object &cObj = _canimShapes[_canimShapes.size() - 1]; @@ -828,7 +835,7 @@ int Scene::startCAnim(int cAnimNum, int playRate) { people.walkToCoords(walkPos, walkDir); } - if (_vm->_talkToAbort) + if (talk._talkToAbort) return 1; // Copy the canimation into the bgShapes type canimation structure so it can be played @@ -968,7 +975,7 @@ int Scene::startCAnim(int cAnimNum, int playRate) { // Set canim to REMOVE type and free memory cObj.checkObject(_bgShapes[0]); - if (gotoCode > 0 && !_vm->_talkToAbort) { + if (gotoCode > 0 && !talk._talkToAbort) { _goToRoom = gotoCode; if (_goToRoom < 97 && _vm->_map[_goToRoom].x) { @@ -978,7 +985,7 @@ int Scene::startCAnim(int cAnimNum, int playRate) { people.loadWalk(); - if (tpPos.x != -1 && !_vm->_talkToAbort) { + if (tpPos.x != -1 && !talk._talkToAbort) { // Teleport to ending coordinates people[AL]._position = tpPos; people[AL]._sequenceNumber = tpDir; @@ -997,6 +1004,51 @@ void Scene::printObjDesc(const Common::String &str, bool firstTime) { * Animate all objects and people. */ void Scene::doBgAnim() { + Events &events = *_vm->_events; + People &people = *_vm->_people; + Screen &screen = *_vm->_screen; + Sound &sound = *_vm->_sound; + Talk &talk = *_vm->_talk; + Surface surface = screen._backBuffer.getSubArea(Common::Rect(0, 0, + SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT)); + int cursorId = events.getCursor(); + Common::Point mousePos = events.mousePos(); + + talk._talkToAbort = false; + + // Animate the mouse cursor + if (cursorId >= WAIT) { + if (++cursorId > (WAIT + 2)) + cursorId = WAIT; + + events.setCursor((CursorId)cursorId); + } + + // Check for setting magnifying glass cursor + if (_menuMode == INV_MODE || _menuMode == USE_MODE || _menuMode == GIVE_MODE) { + if (_invMode == INVMODE_1) { + // Only show Magnifying glass cursor if it's not on the inventory command line + if (mousePos.y < CONTROLS_Y || mousePos.y >(CONTROLS_Y1 + 13)) + events.setCursor(MAGNIFY); + else + events.setCursor(ARROW); + } else { + events.setCursor(ARROW); + } + } + + if (sound._diskSoundPlaying && !*sound._soundIsOn) { + // Loaded sound just finished playing + // TODO: This is horrible.. refactor into the Sound class + delete[] sound._digiBuf; + sound._diskSoundPlaying = false; + } + + if (_restoreFlag) { + if (people[AL]._type == CHARACTER) + people[AL].checkSprite(); + } + // TODO } diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h index 06ca2f4c0d..f48d45c34e 100644 --- a/engines/sherlock/scene.h +++ b/engines/sherlock/scene.h @@ -37,6 +37,30 @@ namespace Sherlock { #define CONTROLS_Y 138 #define CONTROLS_Y1 151 +enum MenuMode { + STD_MODE = 0, + LOOK_MODE = 1, + MOVE_MODE = 2, + TALK_MODE = 3, + PICKUP_MODE = 4, + OPEN_MODE = 5, + CLOSE_MODE = 6, + INV_MODE = 7, + USE_MODE = 8, + GIVE_MODE = 9, + JOURNAL_MODE = 10, + FILES_MODE = 11, + SETUP_MODE = 12 +}; + +enum InvMode { + INVMODE_0 = 0, + INVMODE_1 = 1, + INVMODE_2 = 2, + INVMODE_3 = 3, + INVMODE_255 = 255 +}; + class SherlockEngine; struct BgFileHeader { @@ -90,6 +114,8 @@ private: Common::String _rrmName; int _cAnimFramePause; Common::String _cAnimStr; + MenuMode _menuMode; + InvMode _invMode; bool loadScene(const Common::String &filename); @@ -120,7 +146,7 @@ public: ImageFile *_controls; ImageFile *_controlPanel; bool _windowOpen, _infoFlag; - int _menuMode, _keyboardInput; + int _keyboardInput; int _oldKey, _help, _oldHelp; int _oldTemp, _temp; bool _walkedInScene; @@ -143,6 +169,7 @@ public: Common::Point _hsavedPos; int _hsavedFs; Common::Array _canimShapes; + bool _restoreFlag; public: Scene(SherlockEngine *vm); ~Scene(); diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp index b322b96d6b..e6c11b8cf4 100644 --- a/engines/sherlock/screen.cpp +++ b/engines/sherlock/screen.cpp @@ -181,7 +181,7 @@ bool Screen::unionRectangle(Common::Rect &destRect, const Common::Rect &src1, co * Do a random pixel transition in from _backBuffer surface to the screen */ void Screen::randomTransition() { - EventsManager &events = *_vm->_events; + Events &events = *_vm->_events; const int TRANSITION_MULTIPLIER = 0x15a4e35; _dirtyRects.clear(); @@ -210,7 +210,7 @@ void Screen::randomTransition() { * Transition to the surface from _backBuffer using a vertical transition */ void Screen::verticalTransition() { - EventsManager &events = *_vm->_events; + Events &events = *_vm->_events; byte table[SHERLOCK_SCREEN_WIDTH]; Common::fill(&table[0], &table[SHERLOCK_SCREEN_WIDTH], 0); diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index 756be22846..637660e001 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -43,11 +43,9 @@ SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gam _talk = nullptr; _useEpilogue2 = false; _justLoaded = false; - _talkToAbort = false; _onChessboard = false; _slowChess = false; _animating = false; - _talkCounter = 0; } SherlockEngine::~SherlockEngine() { @@ -75,14 +73,14 @@ void SherlockEngine::initialize() { _res = new Resources(); _animation = new Animation(this); _debugger = new Debugger(this); - _events = new EventsManager(this); + _events = new Events(this); _inventory = new Inventory(); _journal = new Journal(); _people = new People(this); _scene = new Scene(this); _screen = new Screen(this); _sound = new Sound(this); - _talk = new Talk(); + _talk = new Talk(this); } Common::Error SherlockEngine::run() { diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h index 7ce28cfdd7..1c95b10ff3 100644 --- a/engines/sherlock/sherlock.h +++ b/engines/sherlock/sherlock.h @@ -78,7 +78,7 @@ public: const SherlockGameDescription *_gameDescription; Animation *_animation; Debugger *_debugger; - EventsManager *_events; + Events *_events; Inventory *_inventory; Journal *_journal; People *_people; @@ -96,11 +96,9 @@ public: int _oldCharPoint; // Old scene Common::Point _over; // Old map position Common::Array _map; // Map locations for each scene - bool _talkToAbort; bool _onChessboard; bool _slowChess; bool _animating; - int _talkCounter; public: SherlockEngine(OSystem *syst, const SherlockGameDescription *gameDesc); virtual ~SherlockEngine(); diff --git a/engines/sherlock/sound.cpp b/engines/sherlock/sound.cpp index 0917f83e89..e8e433fa84 100644 --- a/engines/sherlock/sound.cpp +++ b/engines/sherlock/sound.cpp @@ -31,6 +31,9 @@ Sound::Sound(SherlockEngine *vm): _vm(vm) { _playingEpilogue = false; _music = false; _digitized = false; + _diskSoundPlaying = false; + _soundIsOn = nullptr; + _digiBuf = nullptr; } void Sound::loadSound(const Common::String &name, int priority) { diff --git a/engines/sherlock/sound.h b/engines/sherlock/sound.h index b6e645a28f..3f32f2724a 100644 --- a/engines/sherlock/sound.h +++ b/engines/sherlock/sound.h @@ -44,6 +44,9 @@ public: bool _playingEpilogue; bool _music; bool _digitized; + bool _diskSoundPlaying; + byte *_soundIsOn; + byte *_digiBuf; public: Sound(SherlockEngine *vm); diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index 3122aff95f..414f3b90a6 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -21,10 +21,17 @@ */ #include "sherlock/talk.h" +#include "sherlock/sherlock.h" namespace Sherlock { -Talk::Talk() { +Talk::Talk(SherlockEngine *vm): _vm(vm) { + _talkCounter = 0; + _talkToAbort = false; +} + +void Talk::talkTo(const Common::String &name) { + // TODO } } // End of namespace Sherlock diff --git a/engines/sherlock/talk.h b/engines/sherlock/talk.h index 6ffbcdd8d4..55a4c0fd69 100644 --- a/engines/sherlock/talk.h +++ b/engines/sherlock/talk.h @@ -37,11 +37,19 @@ public: int &operator[](int idx) { return _data[idx]; } }; +class SherlockEngine; + class Talk { +private: + SherlockEngine *_vm; public: Common::Array _history; + bool _talkToAbort; + int _talkCounter; public: - Talk(); + Talk(SherlockEngine *vm); + + void talkTo(const Common::String &name); }; } // End of namespace Sherlock -- cgit v1.2.3 From ff02c29e9c2f96ed7e36878163b4b22dc8822255 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 22 Mar 2015 00:52:02 -0400 Subject: SHERLOCK: Implemented doBgAnim --- engines/sherlock/objects.cpp | 291 +++++++++++++++++++++++++++-- engines/sherlock/objects.h | 6 +- engines/sherlock/people.cpp | 2 + engines/sherlock/people.h | 3 + engines/sherlock/scalpel/scalpel.cpp | 21 +++ engines/sherlock/scalpel/scalpel.h | 4 + engines/sherlock/scene.cpp | 348 ++++++++++++++++++++++++++++++++++- engines/sherlock/scene.h | 20 +- engines/sherlock/screen.cpp | 63 +++++++ engines/sherlock/screen.h | 12 +- engines/sherlock/sherlock.cpp | 3 +- engines/sherlock/sherlock.h | 4 +- 12 files changed, 751 insertions(+), 26 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index 5a93ce6869..6b681b42e9 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -28,6 +28,8 @@ namespace Sherlock { +#define START_FRAME 0 + #define UPPER_LIMIT 0 #define LOWER_LIMIT CONTROLS_Y #define LEFT_LIMIT 0 @@ -37,6 +39,10 @@ namespace Sherlock { #define CLEAR_DIST_X 5 #define CLEAR_DIST_Y 0 +#define INFO_FOREGROUND 11 +#define INFO_BACKGROUND 1 + + SherlockEngine *Sprite::_vm; /** @@ -83,7 +89,7 @@ void Sprite::adjustSprite() { Scene &scene = *_vm->_scene; Talk &talk = *_vm->_talk; - if (_type == INVALID || (_type == CHARACTER && _vm->_animating)) + if (_type == INVALID || (_type == CHARACTER && scene._animating)) return; if (!talk._talkCounter && _type == CHARACTER && _walkCount) { @@ -457,7 +463,7 @@ void Object::synchronize(Common::SeekableReadStream &s) { _seqStack = s.readByte(); _seqTo = s.readByte(); _descOffset = s.readUint16LE(); - _seqcounter2 = s.readByte(); + _seqCounter2 = s.readByte(); _seqSize = s.readUint16LE(); s.skip(1); _aMove.synchronize(s); @@ -487,7 +493,7 @@ void Object::toggleHidden() { _sequences[_frameNumber] = _seqTo + SEQ_TO_CODE + 128; _seqTo = 0; - _seqCounter = _seqcounter2 = 0; + _seqCounter = _seqCounter2 = 0; _seqStack = 0; _frameNumber = -1; @@ -544,7 +550,7 @@ void Object::checkObject(Object &o) { if (v >= 228) { // Goto code found v -= 228; - _seqcounter2 = _seqCounter; + _seqCounter2 = _seqCounter; _seqStack = _frameNumber + 1; setObjSequence(v, false); } else if (v >= SOUND_CODE && (v <= (SOUND_CODE + 29))) { @@ -631,29 +637,290 @@ void Object::checkObject(Object &o) { } while (codeFound); } -bool Object::checkEndOfSequence() const { - // TODO - return false; +/** + * This will check to see if the object has reached the end of a sequence. + * If it has, it switch to whichever next sequence should be started. + * @returns true if the end of a sequence was reached + */ +bool Object::checkEndOfSequence() { + Screen &screen = *_vm->_screen; + int checkFrame = _allow ? MAX_FRAME : 32000; + bool result = false; + + if (_type == REMOVE || _type == INVALID) + return false; + + if (_sequences[_frameNumber] == 0 || _frameNumber >= checkFrame) { + result = true; + + if (_frameNumber >= (checkFrame - 1)) { + _frameNumber = START_FRAME; + } else { + // Determine next sequence to use + int seq = _sequences[_frameNumber + 1]; + + if (seq == 99) { + --_frameNumber; + screen._backBuffer.transBlitFrom(_imageFrame->_frame, _position); + screen._backBuffer2.transBlitFrom(_imageFrame->_frame, _position); + _type = INVALID; + } else { + setObjSequence(seq, false); + } + } + } + + if (_allow && _frameNumber == 0) { + // canimation just ended + if (_type != NO_SHAPE && _type != REMOVE) { + _type = REMOVE; + + if (!_countCAnimFrames) { + // Save details before shape is removed + _delta.x = _imageFrame->_frame.w; + _delta.y = _imageFrame->_frame.h; + _position = _imageFrame->_offset; + + // Free the images + delete _images; + } + } else { + _type = INVALID; + } + } + + return result; } +/** + * Scans through the sequences array and finds the designated sequence. + * It then sets the frame number of the start of that sequence + */ void Object::setObjSequence(int seq, bool wait) { - // TODO + Scene &scene = *_vm->_scene; + int checkFrame = _allow ? MAX_FRAME : 32000; + + if (seq >= 128) { + // Loop the sequence until the count exceeded + seq -= 128; + + ++_seqCounter; + if (_seqCounter >= seq) { + // Go to next sequence + if (_seqStack) { + _frameNumber = _seqStack; + _seqStack = 0; + _seqCounter = _seqCounter2; + _seqCounter2 = 0; + if (_frameNumber >= checkFrame) + _frameNumber = START_FRAME; + + return; + } + + _frameNumber += 2; + if (_frameNumber >= checkFrame) + _frameNumber = 0; + + _seqCounter = 0; + if (_sequences[_frameNumber] == 0) + seq = _sequences[_frameNumber + 1]; + else + return; + } else { + // Find beginning of sequence + do { + --_frameNumber; + } while (_frameNumber > 0 && _sequences[_frameNumber] != 0); + + if (_frameNumber != 0) + _frameNumber += 2; + + return; + } + } else { + // Reset sequence counter + _seqCounter = 0; + } + + int idx = 0; + int seqCc = 0; + + while (seqCc < seq && idx < checkFrame) { + ++idx; + if (_sequences[idx] == 0) { + ++seqCc; + idx += 2; + } + } + + if (idx >= checkFrame) + idx = 0; + _frameNumber = idx; + + if (wait) { + seqCc = idx; + while (_sequences[idx] != 0) + ++idx; + + idx = idx - seqCc + 2; + for (; idx > 0; --idx) + scene.doBgAnim(); + } } /** * Checks for codes * @param name The name to check for codes -* @param messages If provided, any messages to be returned +* @param messages Provides a lookup list of messages that can be printed * @returns 0 if no codes are found, 1 if codes were found */ int Object::checkNameForCodes(const Common::String &name, Common::StringArray *messages) { + People &people = *_vm->_people; + Scene &scene = *_vm->_scene; + Screen &screen = *_vm->_screen; + Talk &talk = *_vm->_talk; + bool printed = false; + char ch; + const char *p; + + scene.toggleObject(name); + + if (name.hasPrefix("*")) { + // A code was found + printed = true; + ch = toupper(name[1]); + + switch (ch) { + case 'C': + talk.talkTo(name.c_str() + 2); + break; + + case 'T': + case 'B': + case 'F': + case 'W': + // Nothing: action was already done before canimation + break; + + case 'G': + case 'A': { + // G: Have object go somewhere + // A: Add onto existing co-ordinates + Common::String sx(name.c_str() + 2, name.c_str() + 5); + Common::String sy(name.c_str() + 6, name.c_str() + 9); + + if (ch == 'G') + _position = Common::Point(atoi(sx.c_str()), atoi(sy.c_str())); + else + _position += Common::Point(atoi(sx.c_str()), atoi(sy.c_str())); + break; + } + + default: + if (ch >= '0' && ch <= '9') { + scene._goToRoom = atoi(name.c_str() + 1); + + if (scene._goToRoom < 97 && _vm->_map[scene._goToRoom].x) { + _vm->_over.x = _vm->_map[scene._goToRoom].x * 100 - 600; + _vm->_over.y = _vm->_map[scene._goToRoom].y * 100 + 900; + } + + if ((p = strchr(name.c_str(), ',')) != nullptr) { + ++p; + + Common::String s(p, p + 3); + scene._hsavedPos.x = atoi(s.c_str()); + + s = Common::String(p + 3, p + 6); + scene._hsavedPos.y = atoi(s.c_str()); + + s = Common::String(p + 6, p + 9); + scene._hsavedFs = atoi(s.c_str()); + if (scene._hsavedFs == 0) + scene._hsavedFs = 10; + } else if ((p = strchr(name.c_str(), '/')) != nullptr) { + scene._hsavedPos = Common::Point(1, 0); + scene._hsavedFs = 100 + atoi(p + 1); + } + } else { + scene._goToRoom = 100; + } + + people[AL]._position = Common::Point(0, 0); + break; + } + } else if (name.hasPrefix("!")) { + // Message attached to canimation + int messageNum = atoi(name.c_str() + 1); + scene._infoFlag++; + scene.clearInfo(); + screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, INFO_BACKGROUND, + (*messages)[messageNum].c_str()); + _vm->_menuCounter = 25; + } else if (name.hasPrefix("@")) { + // Message attached to canimation + scene._infoFlag++; + scene.clearInfo(); + screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, INFO_BACKGROUND, + "%s", name.c_str() + 1); + printed = true; + _vm->_menuCounter = 25; + } - // TODO - return 0; + return printed; } +/** + * Handle setting any flags associated with the object + */ void Object::setFlagsAndToggles() { - // TODO + Scene &scene = *_vm->_scene; + Talk &talk = *_vm->_talk; + + for (int useIdx = 0; useIdx < 4; ++useIdx) { + if (_use[useIdx]._useFlag) { + if (!_vm->readFlags(_use[useIdx]._useFlag)) + _vm->setFlags(_use[useIdx]._useFlag); + } + + if (_use[useIdx]._cAnimSpeed) { + if (_use[useIdx]._cAnimNum == 0) + // 0 is really a 10 + scene.startCAnim(_use[useIdx]._cAnimNum - 1, _use[useIdx]._cAnimSpeed); + } + + if (!talk._talkToAbort) { + for (int idx = 0; idx < 4; ++idx) + scene.toggleObject(_use[useIdx]._names[idx]); + } + } +} + +/** + * Adjusts the sprite's position and animation sequence, advancing by 1 frame. + * If the end of the sequence is reached, the appropriate action is taken. + */ +void Object::adjustObject() { + if (_type == REMOVE) + return; + + _position += _delta; + + if (_position.y > LOWER_LIMIT) + _position.y = LOWER_LIMIT; + + if (_type != NO_SHAPE) { + int frame = _frameNumber; + if (frame == -1) + frame = 0; + + int imgNum = _sequences[frame]; + if (imgNum > _maxFrames) + imgNum = 1; + + _imageFrame = &(*_images)[imgNum - 1]; + } } /*----------------------------------------------------------------*/ diff --git a/engines/sherlock/objects.h b/engines/sherlock/objects.h index d099718d5b..ee82faf99c 100644 --- a/engines/sherlock/objects.h +++ b/engines/sherlock/objects.h @@ -143,7 +143,7 @@ class Object { private: static SherlockEngine *_vm; - bool checkEndOfSequence() const; + bool checkEndOfSequence(); void setObjSequence(int seq, bool wait); public: @@ -190,7 +190,7 @@ public: int _seqStack; // Allows gosubs to return to calling frame int _seqTo; // Allows 1-5, 8-3 type sequences encoded in 2 bytes uint _descOffset; // Tells where description starts in DescText - int _seqcounter2; // Counter of calling frame sequence + int _seqCounter2; // Counter of calling frame sequence uint _seqSize; // Tells where description starts ActionType _aMove; UseType _use[4]; @@ -204,6 +204,8 @@ public: int checkNameForCodes(const Common::String &name, Common::StringArray *messages); void setFlagsAndToggles(); + + void adjustObject(); }; struct CAnim { diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp index 43d3422f1a..d2fbb3d8c5 100644 --- a/engines/sherlock/people.cpp +++ b/engines/sherlock/people.cpp @@ -56,6 +56,8 @@ People::People(SherlockEngine *vm) : _vm(vm), _player(_data[0]) { _holmesOn = true; _oldWalkSequence = -1; _allowWalkAbort = false; + _portraitLoaded = false; + _clearingThePortrait = false; } People::~People() { diff --git a/engines/sherlock/people.h b/engines/sherlock/people.h index d2d7e92512..7c218671c9 100644 --- a/engines/sherlock/people.h +++ b/engines/sherlock/people.h @@ -64,6 +64,9 @@ public: Common::Point _walkDest; Common::Stack _walkTo; bool _holmesOn; + bool _portraitLoaded; + Object _portrait; + bool _clearingThePortrait; public: People(SherlockEngine *vm); ~People(); diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp index bb9c6c0bc2..1fe1901212 100644 --- a/engines/sherlock/scalpel/scalpel.cpp +++ b/engines/sherlock/scalpel/scalpel.cpp @@ -336,6 +336,27 @@ void ScalpelEngine::startScene() { _chessResult = _scene->_goToRoom; } +/** + * Takes care of clearing the mirror in scene 12, in case anything drew over it + */ +void ScalpelEngine::eraseMirror12() { + // TODO +} + +/** + * Takes care of drawing Holme's reflection onto the mirror in scene 12 + */ +void ScalpelEngine::doMirror12() { + // TODO +} + +/** + * This clears the mirror in scene 12 in case anything messed draw over it + */ +void ScalpelEngine::flushMirror12() { + // TODO +} + } // End of namespace Scalpel } // End of namespace Scalpel diff --git a/engines/sherlock/scalpel/scalpel.h b/engines/sherlock/scalpel/scalpel.h index b096599ee1..2d5deeb882 100644 --- a/engines/sherlock/scalpel/scalpel.h +++ b/engines/sherlock/scalpel/scalpel.h @@ -51,6 +51,10 @@ protected: public: ScalpelEngine(OSystem *syst, const SherlockGameDescription *gameDesc); virtual ~ScalpelEngine(); + + void eraseMirror12(); + void doMirror12(); + void flushMirror12(); }; } // End of namespace Scalpel diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 13315b065b..92a8757fd8 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -22,10 +22,42 @@ #include "sherlock/scene.h" #include "sherlock/sherlock.h" +#include "sherlock/scalpel/scalpel.h" #include "sherlock/decompress.h" namespace Sherlock { +// Main Menu control locations +const int MENU_POINTS[12][4] = { + { 13, 153, 72, 165 }, + { 13, 169, 72, 181 }, + { 13, 185, 72, 197 }, + { 88, 153, 152, 165 }, + { 88, 169, 152, 181 }, + { 88, 185, 152, 197 }, + { 165, 153, 232, 165 }, + { 165, 169, 232, 181 }, + { 165, 185, 233, 197 }, + { 249, 153, 305, 165 }, + { 249, 169, 305, 181 }, + { 249, 185, 305, 197 } +}; + +// Inventory control locations */ +const int INVENTORY_POINTS[8][3] = { + { 4, 50, 28 }, + { 52, 99, 76 }, + { 101, 140, 122 }, + { 142, 187, 165 }, + { 189, 219, 197 }, + { 221, 251, 233 }, + { 253, 283, 265 }, + { 285, 315, 293 } +}; + +/*----------------------------------------------------------------*/ + + void BgFileHeader::synchronize(Common::SeekableReadStream &s) { _numStructs = s.readUint16LE(); _numImages = s.readUint16LE(); @@ -89,7 +121,8 @@ Scene::Scene(SherlockEngine *vm): _vm(vm) { _goToRoom = -1; _changes = false; _charPoint = _oldCharPoint = 0; - _windowOpen = _infoFlag = false; + _windowOpen = false; + _infoFlag = false; _keyboardInput = 0; _walkedInScene = false; _ongoingCans = 0; @@ -102,6 +135,10 @@ Scene::Scene(SherlockEngine *vm): _vm(vm) { _menuMode = STD_MODE; _invMode = INVMODE_0; _restoreFlag = false; + _invLookFlag = false; + _lookHelp = false; + _animating = 0; + _doBgAnimDone = true; _controlPanel = new ImageFile("controls.vgs"); _controls = nullptr; // new ImageFile("menu.all"); @@ -236,7 +273,7 @@ bool Scene::loadScene(const Common::String &filename) { _bgShapes[idx]._sequences = &_sequenceBuffer[_bgShapes[idx]._sequenceOffset]; _bgShapes[idx]._misc = 0; _bgShapes[idx]._seqCounter = 0; - _bgShapes[idx]._seqcounter2 = 0; + _bgShapes[idx]._seqCounter2 = 0; _bgShapes[idx]._seqStack = 0; _bgShapes[idx]._frameNumber = -1; _bgShapes[idx]._position = Common::Point(0, 0); @@ -799,7 +836,7 @@ int Scene::startCAnim(int cAnimNum, int playRate) { Talk &talk = *_vm->_talk; Common::Point tpPos, walkPos; int tpDir, walkDir; - int tFrames; + int tFrames = 0; int gotoCode = -1; // Validation @@ -996,8 +1033,52 @@ int Scene::startCAnim(int cAnimNum, int playRate) { return 1; } +/** + * Print the description of an object + */ void Scene::printObjDesc(const Common::String &str, bool firstTime) { + /* TODO + + Events &events = *_vm->_events; + Screen &screen = *_vm->_screen; + Talk &talk = *_vm->_talk; + int savedSelector; + + if (str.hasPrefix("_")) { + _lookScriptFlag = true; + events.setCursor(MAGNIFY); + savedSelector = _selector; + talk.talkTo(str.c_str() + 1); + _lookScriptFlag = false; + + if (talk._talkToAbort) { + events.setCursor(ARROW); + return; + } + + // Check if looking at an inventory object + if (!_invLookFlag) { + // See if this look was called by a right button click or not + if (!_lookHelp) { + // If it wasn't a right button click, then we need depress + // the look button before we close the window. So save a copy of the + // menu area, and draw the controls onto it + Surface tempSurface((*_controls)[0]._frame->w, (*_controls)[0]._frame->h); + tempSurface.blitFrom(screen._backBuffer2, Common::Point(0, 0), + Common::Rect(MENU_POINTS[0][0], MENU_POINTS[0][1], + MENU_POINTS[0][0] + tempSurface.w, MENU_POINTS[0][1] + tempSurface.h)); + screen._backBuffer2.transBlitFrom((*_controls)[0]._frame, + Common::Point(MENU_POINTS[0][0], MENU_POINTS[0][1])); + + banishWindow(1); + events.setCursor(MAGNIFY); + + } + } + } + // TODO + */ } /** @@ -1047,9 +1128,270 @@ void Scene::doBgAnim() { if (_restoreFlag) { if (people[AL]._type == CHARACTER) people[AL].checkSprite(); + + for (uint idx = 0; idx < _bgShapes.size(); ++idx) { + if (_bgShapes[idx]._type == ACTIVE_BG_SHAPE) + _bgShapes[idx].checkObject(_bgShapes[idx]); + } + + if (people._portraitLoaded && people._portrait._type == ACTIVE_BG_SHAPE) + people._portrait.checkObject(people._portrait); + + for (uint idx = 0; idx < _canimShapes.size(); ++idx) { + if (_canimShapes[idx]._type != INVALID && _canimShapes[idx]._type != REMOVE) + _canimShapes[idx].checkObject(_bgShapes[0]); + } + + if (_currentScene == 12 && _vm->getGameID() == GType_SerratedScalpel) + ((Scalpel::ScalpelEngine *)_vm)->eraseMirror12(); + + // Restore the back buffer from the back buffer 2 in the changed area + Common::Rect bounds(people[AL]._oldPosition.x, people[AL]._oldPosition.y, + people[AL]._oldPosition.x + people[AL]._oldSize.x, + people[AL]._oldPosition.y + people[AL]._oldSize.y); + Common::Point pt(bounds.left, bounds.top); + + if (people[AL]._type == CHARACTER) + screen.restoreBackground(bounds); + else if (people[AL]._type == REMOVE) + screen._backBuffer.blitFrom(screen._backBuffer2, pt, bounds); + + for (uint idx = 0; _bgShapes.size(); ++idx) { + Object &o = _bgShapes[idx]; + if (o._type == ACTIVE_BG_SHAPE || o._type == HIDE_SHAPE || o._type == REMOVE) + screen.restoreBackground(bounds); + } + + if (people._portraitLoaded) + screen.restoreBackground(Common::Rect( + people._portrait._oldPosition.x, people._portrait._oldPosition.y, + people._portrait._oldPosition.x + people._portrait._oldSize.x, + people._portrait._oldPosition.y + people._portrait._oldSize.y + )); + + for (uint idx = 0; idx < _bgShapes.size(); ++idx) { + Object &o = _bgShapes[idx]; + if (o._type == NO_SHAPE && ((o._flags & 1) == 0)) { + // Restore screen area + screen._backBuffer.blitFrom(screen._backBuffer2, o._position, + Common::Rect(o._position.x, o._position.y, + o._position.x + o._noShapeSize.x, o._position.y + o._noShapeSize.y)); + + o._oldPosition = o._position; + o._oldSize = o._noShapeSize; + } + } + + for (uint idx = 0; idx < _canimShapes.size(); ++idx) { + Object &o = _canimShapes[idx]; + if (o._type == ACTIVE_BG_SHAPE || o._type == HIDE_SHAPE || o._type == REMOVE) + screen.restoreBackground(Common::Rect(o._oldPosition.x, o._oldPosition.y, + o._oldPosition.x + o._oldSize.x, o._oldPosition.y + o._oldSize.y)); + } + } + + // + // Update the background objects and canimations + // + + for (uint idx = 0; idx < _bgShapes.size(); ++idx) { + Object &o = _bgShapes[idx]; + if (o._type == ACTIVE_BG_SHAPE || o._type == NO_SHAPE) + o.adjustObject(); } + for (uint idx = 0; idx < _canimShapes.size(); ++idx) { + if (_canimShapes[idx]._type != INVALID) + _canimShapes[idx].adjustObject(); + } + + if (people[AL]._type == CHARACTER && people._holmesOn) + people[AL].adjustSprite(); + + // Flag the bg shapes which need to be redrawn + checkBgShapes(people[AL]._imageFrame, + Common::Point(people[AL]._position.x / 100, people[AL]._position.y / 100)); + + if (_currentScene == 12 && _vm->getGameID() == GType_SerratedScalpel) + ((Scalpel::ScalpelEngine *)_vm)->doMirror12(); + + // Draw all active shapes which are behind the person + for (uint idx = 0; idx < _bgShapes.size(); ++idx) { + Object &o = _bgShapes[idx]; + if (o._type == ACTIVE_BG_SHAPE && o._misc == BEHIND) + screen._backBuffer.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2); + } + + // Draw all canimations which are behind the person + for (uint idx = 0; idx < _canimShapes.size(); ++idx) { + Object &o = _canimShapes[idx]; + if (o._type == ACTIVE_BG_SHAPE && o._misc == BEHIND) { + screen._backBuffer.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2); + } + } + + // Draw all active shapes which are HAPPEN and behind the person + for (uint idx = 0; idx < _bgShapes.size(); ++idx) { + Object &o = _bgShapes[idx]; + if (o._type == ACTIVE_BG_SHAPE && o._misc == NORMAL_BEHIND) + screen._backBuffer.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2); + } + + // Draw all canimations which are NORMAL and behind the person + for (uint idx = 0; idx < _canimShapes.size(); ++idx) { + Object &o = _canimShapes[idx]; + if (o._type == ACTIVE_BG_SHAPE && o._misc == NORMAL_BEHIND) { + screen._backBuffer.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2); + } + } + + // Draw the person if not animating + if (people[AL]._type == CHARACTER && people.isHolmesActive()) { + // If Holmes is too far to the right, move him back so he's on-screen + int xRight = SHERLOCK_SCREEN_WIDTH - 2 - people[AL]._imageFrame->_frame.w; + int tempX = MIN(people[AL]._position.x / 100, xRight); + + bool flipped = people[AL]._frameNumber == WALK_LEFT || people[AL]._frameNumber == STOP_LEFT || + people[AL]._frameNumber == WALK_UPLEFT || people[AL]._frameNumber == STOP_UPLEFT || + people[AL]._frameNumber == WALK_DOWNRIGHT || people[AL]._frameNumber == STOP_DOWNRIGHT; + screen._backBuffer.transBlitFrom(people[AL]._imageFrame->_frame, + Common::Point(tempX, people[AL]._position.y / 100 - people[AL]._imageFrame->_frame.h), flipped); + } + + // Draw all static and active shapes are NORMAL and are in front of the person + for (uint idx = 0; idx < _bgShapes.size(); ++idx) { + Object &o = _bgShapes[idx]; + if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == NORMAL_FORWARD) + screen._backBuffer.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2); + } + + // Draw all static and active canimations that are NORMAL and are in front of the person + for (uint idx = 0; idx < _canimShapes.size(); ++idx) { + Object &o = _canimShapes[idx]; + if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == NORMAL_BEHIND) { + screen._backBuffer.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2); + } + } + + // Draw all static and active shapes that are in front of the person + for (uint idx = 0; idx < _bgShapes.size(); ++idx) { + Object &o = _bgShapes[idx]; + if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == FORWARD) + screen._backBuffer.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2); + } + + // Draw any active portrait + if (people._portraitLoaded && people._portrait._type == ACTIVE_BG_SHAPE) + screen._backBuffer.transBlitFrom(people._portrait._imageFrame->_frame, + people._portrait._position, people._portrait._flags & 2); + + // Draw all static and active canimations that are in front of the person + for (uint idx = 0; idx < _canimShapes.size(); ++idx) { + Object &o = _canimShapes[idx]; + if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == FORWARD) { + screen._backBuffer.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2); + } + } + + // Draw all NO_SHAPE shapes which have flag bit 0 clear + for (uint idx = 0; idx < _bgShapes.size(); ++idx) { + Object &o = _bgShapes[idx]; + if (o._type == NO_SHAPE && (o._flags & 1) == 0) + screen._backBuffer.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2); + } + + // Bring the newly built picture to the screen + if (_animating == 2) { + _animating = 0; + screen.slamRect(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT)); + } else { + if (people[AL]._type != INVALID && ((_goToRoom == -1 || _ongoingCans == 0))) { + if (people[AL]._type == REMOVE) { + screen.slamRect(Common::Rect( + people[AL]._oldPosition.x, people[AL]._oldPosition.y, + people[AL]._oldPosition.x + people[AL]._oldSize.x, + people[AL]._oldPosition.y + people[AL]._oldSize.y + )); + } else { + screen.flushImage(people[AL]._imageFrame, + Common::Point(people[AL]._position.x / 100, people[AL]._position.y / 100), + &people[AL]._oldPosition.x, &people[AL]._oldPosition.y, + &people[AL]._oldSize.x, &people[AL]._oldSize.y); + } + } + + if (_currentScene == 12 && _vm->getGameID() == GType_SerratedScalpel) + ((Scalpel::ScalpelEngine *)_vm)->flushMirror12(); + + for (uint idx = 0; idx < _bgShapes.size(); ++idx) { + Object &o = _bgShapes[idx]; + if ((o._type == ACTIVE_BG_SHAPE || o._type == REMOVE) && _goToRoom == -1) { + screen.flushImage(o._imageFrame, o._position, + &o._oldPosition.x, &o._oldPosition.y, &o._oldSize.x, &o._oldSize.y); + } + } + + if (people._portraitLoaded) { + if (people._portrait._type == REMOVE) + screen.slamRect(Common::Rect( + people._portrait._position.x, people._portrait._position.y, + people._portrait._position.x + people._portrait._delta.x, + people._portrait._position.y + people._portrait._delta.y + )); + else + screen.flushImage(people._portrait._imageFrame, people._portrait._position, + &people._portrait._oldPosition.x, &people._portrait._oldPosition.y, + &people._portrait._oldSize.x, &people._portrait._oldSize.y); + + if (people._portrait._type == REMOVE) + people._portrait._type = INVALID; + } + + if (_goToRoom == -1) { + for (uint idx = 0; idx < _bgShapes.size(); ++idx) { + Object &o = _bgShapes[idx]; + if (o._type == NO_SHAPE && (o._flags & 1) == 0) { + screen.slamArea(o._position.x, o._position.y, o._oldSize.x, o._oldSize.y); + screen.slamArea(o._oldPosition.x, o._oldPosition.y, o._oldSize.x, o._oldSize.y); + } else if (o._type == HIDE_SHAPE) { + screen.flushImage(o._imageFrame, o._position, + &o._oldPosition.x, &o._oldPosition.y, &o._oldSize.x, &o._oldSize.y); + } + } + } + + for (int idx = _canimShapes.size() - 1; idx >= 0; --idx) { + Object &o = _canimShapes[idx]; + if (o._type == REMOVE) { + if (_goToRoom == -1) + screen.slamArea(o._position.x, o._position.y, o._delta.x, o._delta.y); + + _canimShapes.remove_at(idx); + } else if (o._type == ACTIVE_BG_SHAPE) { + screen.flushImage(o._imageFrame, o._position, + &o._oldPosition.x, &o._oldPosition.y, &o._oldSize.x, &o._oldSize.y); + } + } + } + + _restoreFlag = true; + + events.wait(1); + _doBgAnimDone = true; + + // Check if the method was called for calling a portrait, and a talk was + // interrupting it. This talk file would not have been executed at the time, + // since we needed to finish the 'doBgAnim' to finish clearing the portrait + if (people._clearingThePortrait && _vm->_scriptMoreFlag == 3) { + // Reset the flags and call to talk + people._clearingThePortrait = _vm->_scriptMoreFlag = 0; + talk.talkTo(_vm->_scriptName); + } +} + +void Scene::clearInfo() { // TODO } + } // End of namespace Sherlock diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h index f48d45c34e..4b76739402 100644 --- a/engines/sherlock/scene.h +++ b/engines/sherlock/scene.h @@ -116,6 +116,10 @@ private: Common::String _cAnimStr; MenuMode _menuMode; InvMode _invMode; + bool _lookScriptFlag; + int _selector; + bool _invLookFlag; + bool _lookHelp; bool loadScene(const Common::String &filename); @@ -125,15 +129,9 @@ private: void transitionToScene(); - int toggleObject(const Common::String &name); - void updateBackground(); void checkBgShapes(ImageFrame *frame, const Common::Point &pt); - - int startCAnim(int cAnimNum, int playRate); - - void doBgAnim(); public: int _currentScene; int _goToRoom; @@ -170,6 +168,8 @@ public: int _hsavedFs; Common::Array _canimShapes; bool _restoreFlag; + int _animating; + bool _doBgAnimDone; public: Scene(SherlockEngine *vm); ~Scene(); @@ -183,6 +183,14 @@ public: Exit *checkForExit(const Common::Rect &r); void printObjDesc(const Common::String &str, bool firstTime); + + int startCAnim(int cAnimNum, int playRate); + + int toggleObject(const Common::String &name); + + void doBgAnim(); + + void clearInfo(); }; } // End of namespace Sherlock diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp index e6c11b8cf4..f8f1d56e67 100644 --- a/engines/sherlock/screen.cpp +++ b/engines/sherlock/screen.cpp @@ -231,4 +231,67 @@ void Screen::verticalTransition() { } } +/** + * Prints the text passed onto the back buffer at the given position and color. + * The string is then blitted to the screen + */ +void Screen::print(const Common::Point &pt, int fgColor, int bgColor, const char *format, ...) { + // TODO +} + +/** + * Copies a section of the second back buffer into the main back buffer + */ +void Screen::restoreBackground(const Common::Rect &r) { + Common::Rect tempRect = r; + tempRect.clip(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT)); + + if (tempRect.isValidRect()) + _backBuffer.blitFrom(_backBuffer2, Common::Point(tempRect.left, tempRect.top), tempRect); +} + +/** + * Copies a given area to the screen + */ +void Screen::slamArea(int16 xp, int16 yp, int16 w, int16 h) { + slamRect(Common::Rect(xp, yp, xp + w, yp + h)); +} + +/** + * Copies a given area to the screen + */ +void Screen::slamRect(const Common::Rect &r) { + Common::Rect tempRect = r; + tempRect.clip(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); + + if (tempRect.isValidRect()) + blitFrom(_backBuffer, Common::Point(tempRect.left, tempRect.top), tempRect); +} + +/** + * Copy an image from the back buffer to the screen, taking care of both the + * new area covered by the shape as well as the old area, which must be restored + */ +void Screen::flushImage(ImageFrame *frame, const Common::Point &pt, + int16 *xp, int16 *yp, int16 *w, int16 *h) { + Common::Point imgPos = pt + frame->_offset; + Common::Rect newBounds(imgPos.x, imgPos.y, imgPos.x + frame->_frame.w, imgPos.y + frame->_frame.h); + Common::Rect oldBounds(*xp, *yp, *xp + *w, *yp + *h); + + // See if the areas of the old and new overlap, and if so combine the areas + if (newBounds.intersects(oldBounds)) { + newBounds.extend(oldBounds); + slamRect(newBounds); + } else { + // The two areas are independent, so copy them both + slamRect(newBounds); + slamRect(oldBounds); + } + + *xp = newBounds.left; + *yp = newBounds.top; + *w = newBounds.width(); + *h = newBounds.height(); +} + } // End of namespace Sherlock diff --git a/engines/sherlock/screen.h b/engines/sherlock/screen.h index 2c5e585475..87453ba36d 100644 --- a/engines/sherlock/screen.h +++ b/engines/sherlock/screen.h @@ -26,8 +26,8 @@ #include "common/list.h" #include "common/rect.h" #include "graphics/surface.h" - #include "sherlock/graphics.h" +#include "sherlock/resources.h" namespace Sherlock { @@ -75,6 +75,16 @@ public: void randomTransition(); void verticalTransition(); + + void print(const Common::Point &pt, int fgColor, int bgColor, const char *format, ...); + + void restoreBackground(const Common::Rect &r); + + void slamArea(int16 xp, int16 yp, int16 w, int16 h); + void slamRect(const Common::Rect &r); + + void flushImage(ImageFrame *frame, const Common::Point &pt, + int16 *xp, int16 *yp, int16 *w, int16 *h); }; } // End of namespace Sherlock diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index 637660e001..330da6075b 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -45,7 +45,8 @@ SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gam _justLoaded = false; _onChessboard = false; _slowChess = false; - _animating = false; + _menuCounter = 0; + _scriptMoreFlag = 0; } SherlockEngine::~SherlockEngine() { diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h index 1c95b10ff3..92aee9cdc3 100644 --- a/engines/sherlock/sherlock.h +++ b/engines/sherlock/sherlock.h @@ -98,7 +98,9 @@ public: Common::Array _map; // Map locations for each scene bool _onChessboard; bool _slowChess; - bool _animating; + int _menuCounter; + int _scriptMoreFlag; + Common::String _scriptName; public: SherlockEngine(OSystem *syst, const SherlockGameDescription *gameDesc); virtual ~SherlockEngine(); -- cgit v1.2.3 From ec16861ec981eadbcef55454fb67b22502c6c65b Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Sun, 22 Mar 2015 08:14:18 +0100 Subject: ZVISION: Silence Cppcheck warning --- engines/zvision/scripting/actions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/zvision/scripting/actions.cpp b/engines/zvision/scripting/actions.cpp index 21c97e766b..9a8b734e0c 100644 --- a/engines/zvision/scripting/actions.cpp +++ b/engines/zvision/scripting/actions.cpp @@ -1077,7 +1077,7 @@ ActionTtyText::ActionTtyText(ZVision *engine, int32 slotkey, const Common::Strin char filename[64]; int32 x1 = 0, y1 = 0, x2 = 0, y2 = 0; - sscanf(line.c_str(), "%d %d %d %d %64s %u", &x1, &y1, &x2, &y2, filename, &_delay); + sscanf(line.c_str(), "%d %d %d %d %63s %u", &x1, &y1, &x2, &y2, filename, &_delay); _r = Common::Rect(x1, y1, x2, y2); _filename = Common::String(filename); } -- cgit v1.2.3 From d582c8492ce5ef300e24358c80bf0adadcfd11f0 Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Sun, 22 Mar 2015 12:22:30 +0100 Subject: SCUMM: Fix argc check in Cmd_Script() --- engines/scumm/debugger.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/scumm/debugger.cpp b/engines/scumm/debugger.cpp index 2b718b2cfe..0ebea94608 100644 --- a/engines/scumm/debugger.cpp +++ b/engines/scumm/debugger.cpp @@ -256,7 +256,7 @@ bool ScummDebugger::Cmd_Hide(int argc, const char **argv) { bool ScummDebugger::Cmd_Script(int argc, const char** argv) { int scriptnum; - if (argc < 2) { + if (argc < 3) { debugPrintf("Syntax: script \n"); return true; } -- cgit v1.2.3 From 3c77a521dc07a8c0954b11b26dda382817776b9e Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 22 Mar 2015 09:02:31 -0400 Subject: SHERLOCK: Implement main scene loop and more inventory code --- engines/sherlock/debugger.cpp | 2 +- engines/sherlock/graphics.cpp | 7 ++- engines/sherlock/graphics.h | 1 + engines/sherlock/inventory.cpp | 92 ++++++++++++++++++++++++++++++++++++ engines/sherlock/inventory.h | 24 +++++++++- engines/sherlock/objects.cpp | 12 ++--- engines/sherlock/people.cpp | 15 ++++++ engines/sherlock/people.h | 2 + engines/sherlock/scalpel/scalpel.cpp | 31 ++++++------ engines/sherlock/scalpel/scalpel.h | 1 - engines/sherlock/scene.cpp | 72 ++++++++++++++++++++++------ engines/sherlock/scene.h | 6 ++- engines/sherlock/sherlock.cpp | 34 +++++++++++-- engines/sherlock/sherlock.h | 3 ++ engines/sherlock/talk.cpp | 8 ++++ engines/sherlock/talk.h | 4 +- 16 files changed, 267 insertions(+), 47 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/debugger.cpp b/engines/sherlock/debugger.cpp index 1e0716c3d3..b8ac8bef6a 100644 --- a/engines/sherlock/debugger.cpp +++ b/engines/sherlock/debugger.cpp @@ -51,7 +51,7 @@ bool Debugger::cmd_scene(int argc, const char **argv) { debugPrintf("Format: scene \n"); return true; } else { - _vm->_scene->_goToRoom = strToInt(argv[1]); + _vm->_scene->_goToScene = strToInt(argv[1]); return false; } } diff --git a/engines/sherlock/graphics.cpp b/engines/sherlock/graphics.cpp index 8c096e3c72..63988a2f30 100644 --- a/engines/sherlock/graphics.cpp +++ b/engines/sherlock/graphics.cpp @@ -145,7 +145,12 @@ void Surface::transBlitFrom(const Graphics::Surface &src, const Common::Point &p * Fill a given area of the surface with a given color */ void Surface::fillRect(int x1, int y1, int x2, int y2, byte color) { - Graphics::Surface::fillRect(Common::Rect(x1, y1, x2, y2), color); + fillRect(Common::Rect(x1, y1, x2, y2), color); +} + +void Surface::fillRect(const Common::Rect &r, byte color) { + Graphics::Surface::fillRect(r, color); + addDirtyRect(r); } /** diff --git a/engines/sherlock/graphics.h b/engines/sherlock/graphics.h index 0536c016bf..b33495a2b9 100644 --- a/engines/sherlock/graphics.h +++ b/engines/sherlock/graphics.h @@ -47,6 +47,7 @@ public: bool flipped = false, int overrideColor = 0); void fillRect(int x1, int y1, int x2, int y2, byte color); + void fillRect(const Common::Rect &r, byte color); Surface getSubArea(const Common::Rect &r); }; diff --git a/engines/sherlock/inventory.cpp b/engines/sherlock/inventory.cpp index 634e664f5a..cbb69f1041 100644 --- a/engines/sherlock/inventory.cpp +++ b/engines/sherlock/inventory.cpp @@ -21,7 +21,99 @@ */ #include "sherlock/inventory.h" +#include "sherlock/sherlock.h" namespace Sherlock { +Inventory::Inventory(SherlockEngine *vm) : Common::Array(), _vm(vm) { + Common::fill(&_invShapes[0], &_invShapes[MAX_VISIBLE_INVENTORY], (ImageFile *)nullptr); + _invGraphicsLoaded = false; + _invIndex = 0; + _holdings = 0; +} + +Inventory::~Inventory() { + freeGraphics(); +} + +void Inventory::freeInventory() { + freeGraphics(); + + _names.clear(); + _invGraphicsLoaded = false; +} + +/** + * Free any loaded inventory graphics + */ +void Inventory::freeGraphics() { + for (uint idx = 0; idx < MAX_VISIBLE_INVENTORY; ++idx) + delete _invShapes[idx]; + + Common::fill(&_invShapes[0], &_invShapes[MAX_VISIBLE_INVENTORY], (ImageFile *)nullptr); + _invGraphicsLoaded = false; +} + +/** Load the list of names the inventory items correspond to. + */ +void Inventory::loadInv() { + // Exit if the inventory names are already loaded + if (_names.size() > 0) + return; + + // Load the inventory names + Common::SeekableReadStream *stream = _vm->_res->load("invent.txt"); + _names.clear(); + + while (stream->pos() < stream->size()) { + Common::String name; + char c; + while ((c = stream->readByte()) != 0) + name += c; + + _names.push_back(name); + } + + delete stream; +} + +/** + * Load the list of names of graphics for the inventory + */ +void Inventory::loadGraphics() { + if (_invGraphicsLoaded) + return; + + // Default all inventory slots to empty + Common::fill(&_invShapes[0], &_invShapes[MAX_VISIBLE_INVENTORY], (ImageFile *)nullptr); + + for (int idx = _invIndex; (idx < _holdings) && (idx - _invIndex) < 6; ++idx) { + // Get the name of the item to be dispalyed, figure out it's accompanying + // .VGS file with it's picture, and then load it + int invNum = findInv((*this)[idx]._name); + Common::String fName = Common::String::format("item%02d.vgs", invNum); + + _invShapes[idx] = new ImageFile(fName); + } + + _invGraphicsLoaded = true; +} + +/** + * Searches through the list of names that correspond to the inventory items + * and returns the numer that matches the passed name + */ +int Inventory::findInv(const Common::String &name) { + int result = -1; + + for (uint idx = 0; (idx < _holdings) && result == -1; ++idx) { + if (scumm_stricmp(name.c_str(), _names[idx].c_str()) == 0) + result = idx; + } + + if (result == -1) + result = 1; + return result; +} + } // End of namespace Sherlock diff --git a/engines/sherlock/inventory.h b/engines/sherlock/inventory.h index dc56e93841..e561f0318a 100644 --- a/engines/sherlock/inventory.h +++ b/engines/sherlock/inventory.h @@ -25,9 +25,13 @@ #include "common/scummsys.h" #include "common/array.h" +#include "common/str-array.h" +#include "sherlock/resources.h" namespace Sherlock { +#define MAX_VISIBLE_INVENTORY 6 + struct InventoryItem { int _requiredFlag; Common::String _name; @@ -37,10 +41,26 @@ struct InventoryItem { }; class Inventory : public Common::Array { +private: + SherlockEngine *_vm; +public: + ImageFile *_invShapes[MAX_VISIBLE_INVENTORY]; + Common::StringArray _names; + bool _invGraphicsLoaded; + int _invIndex; + int _holdings; + void freeGraphics(); public: - uint _holdings; + Inventory(SherlockEngine *vm); + ~Inventory(); + + void freeInventory(); + + void loadInv(); + + void loadGraphics(); - Inventory() : Common::Array(), _holdings(0) {} + int findInv(const Common::String &name); }; } // End of namespace Sherlock diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index 6b681b42e9..1643bef7b0 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -159,7 +159,7 @@ void Sprite::adjustSprite() { setImageFrame(); // Check to see if character has entered an exit zone - if (!_walkCount && scene._walkedInScene && scene._goToRoom == -1) { + if (!_walkCount && scene._walkedInScene && scene._goToScene == -1) { Common::Rect charRect(_position.x / 100 - 5, _position.y / 100 - 2, _position.x / 100 + 5, _position.y / 100 + 2); Exit *exit = scene.checkForExit(charRect); @@ -819,11 +819,11 @@ int Object::checkNameForCodes(const Common::String &name, Common::StringArray *m default: if (ch >= '0' && ch <= '9') { - scene._goToRoom = atoi(name.c_str() + 1); + scene._goToScene = atoi(name.c_str() + 1); - if (scene._goToRoom < 97 && _vm->_map[scene._goToRoom].x) { - _vm->_over.x = _vm->_map[scene._goToRoom].x * 100 - 600; - _vm->_over.y = _vm->_map[scene._goToRoom].y * 100 + 900; + if (scene._goToScene < 97 && _vm->_map[scene._goToScene].x) { + _vm->_over.x = _vm->_map[scene._goToScene].x * 100 - 600; + _vm->_over.y = _vm->_map[scene._goToScene].y * 100 + 900; } if ((p = strchr(name.c_str(), ',')) != nullptr) { @@ -844,7 +844,7 @@ int Object::checkNameForCodes(const Common::String &name, Common::StringArray *m scene._hsavedFs = 100 + atoi(p + 1); } } else { - scene._goToRoom = 100; + scene._goToScene = 100; } people[AL]._position = Common::Point(0, 0); diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp index d2fbb3d8c5..91689e296c 100644 --- a/engines/sherlock/people.cpp +++ b/engines/sherlock/people.cpp @@ -99,6 +99,21 @@ bool People::loadWalk() { } } +/** + * If the walk data has been loaded, then it will be freed + */ +bool People::freeWalk() { + if (_walkLoaded) { + delete _player._images; + _player._images = nullptr; + + _walkLoaded = false; + return true; + } else { + return false; + } +} + /** * Set the variables for moving a character from one poisition to another * in a straight line - goAllTheWay must have been previously called to diff --git a/engines/sherlock/people.h b/engines/sherlock/people.h index 7c218671c9..de84675e66 100644 --- a/engines/sherlock/people.h +++ b/engines/sherlock/people.h @@ -79,6 +79,8 @@ public: bool loadWalk(); + bool freeWalk(); + void setWalking(); void gotoStand(Sprite &sprite); diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp index 1fe1901212..3ec971895a 100644 --- a/engines/sherlock/scalpel/scalpel.cpp +++ b/engines/sherlock/scalpel/scalpel.cpp @@ -43,7 +43,6 @@ ScalpelEngine::ScalpelEngine(OSystem *syst, const SherlockGameDescription *gameD SherlockEngine(syst, gameDesc) { _chess = nullptr; _darts = nullptr; - _tempFadeStyle = 0; _chessResult = 0; } @@ -70,7 +69,7 @@ void ScalpelEngine::initialize() { _map.push_back(Common::Point(MAP_X[idx], MAP_Y[idx])); // Starting scene - _scene->_goToRoom = 4; + _scene->_goToScene = 4; } /** @@ -181,7 +180,7 @@ bool ScalpelEngine::showOfficeCutscene() { * Starting a scene within the game */ void ScalpelEngine::startScene() { - if (_scene->_goToRoom == 100 || _scene->_goToRoom == 98) { + if (_scene->_goToScene == 100 || _scene->_goToScene == 98) { // Chessboard selection if (_sound->_musicOn) { if (_sound->loadSong(100)) { @@ -190,7 +189,7 @@ void ScalpelEngine::startScene() { } } - _scene->_goToRoom = _chess->doChessBoard(); + _scene->_goToScene = _chess->doChessBoard(); _sound->freeSong(); _scene->_hsavedPos = Common::Point(-1, -1); @@ -203,17 +202,17 @@ void ScalpelEngine::startScene() { // 53: Moorehead's death / subway train // 55: Fade out and exit // 70: Brumwell suicide - switch (_scene->_goToRoom) { + switch (_scene->_goToScene) { case 2: case 52: case 53: case 70: - if (_sound->_musicOn && _sound->loadSong(_scene->_goToRoom)) { + if (_sound->_musicOn && _sound->loadSong(_scene->_goToScene)) { if (_sound->_music) _sound->startSong(); } - switch (_scene->_goToRoom) { + switch (_scene->_goToScene) { case 2: // Blackwood's capture _res->addToCache("final2.vda", "epilogue.lib"); @@ -269,7 +268,7 @@ void ScalpelEngine::startScene() { _animation->playPrologue("SUBWAY3", 1, 0, false, 4); // Set fading to direct fade temporary so the transition goes quickly. - _tempFadeStyle = _screen->_fadeStyle ? 257 : 256; + _scene->_tempFadeStyle = _screen->_fadeStyle ? 257 : 256; _screen->_fadeStyle = false; break; @@ -282,28 +281,28 @@ void ScalpelEngine::startScene() { } // Except for the Moorehead Murder scene, fade to black first - if (_scene->_goToRoom != 53) { + if (_scene->_goToScene != 53) { _events->wait(40); _screen->fadeToBlack(3); } - switch (_scene->_goToRoom) { + switch (_scene->_goToScene) { case 52: - _scene->_goToRoom = 27; // Go to the Lawyer's Office + _scene->_goToScene = 27; // Go to the Lawyer's Office _scene->_bigPos = Common::Point(0, 0); // Overland scroll position _scene->_overPos = Common::Point(22900 - 600, 9400 + 900); // Overland position _scene->_oldCharPoint = 27; break; case 53: - _scene->_goToRoom = 17; // Go to St. Pancras Station + _scene->_goToScene = 17; // Go to St. Pancras Station _scene->_bigPos = Common::Point(0, 0); // Overland scroll position _scene->_overPos = Common::Point(32500 - 600, 3000 + 900); // Overland position _scene->_oldCharPoint = 17; break; default: - _scene->_goToRoom = 4; // Back to Baker st. + _scene->_goToScene = 4; // Back to Baker st. _scene->_bigPos = Common::Point(0, 0); // Overland scroll position _scene->_overPos = Common::Point(14500 - 600, 8400 + 900); // Overland position _scene->_oldCharPoint = 4; @@ -327,13 +326,13 @@ void ScalpelEngine::startScene() { _events->loadCursors("rmouse.vgs"); _events->setCursor(ARROW); - if (_scene->_goToRoom == 99) { + if (_scene->_goToScene == 99) { // Chess Board _darts->playDarts(); - _chessResult = _scene->_goToRoom = 19; // Go back to the bar + _chessResult = _scene->_goToScene = 19; // Go back to the bar } - _chessResult = _scene->_goToRoom; + _chessResult = _scene->_goToScene; } /** diff --git a/engines/sherlock/scalpel/scalpel.h b/engines/sherlock/scalpel/scalpel.h index 2d5deeb882..caf33052aa 100644 --- a/engines/sherlock/scalpel/scalpel.h +++ b/engines/sherlock/scalpel/scalpel.h @@ -35,7 +35,6 @@ class ScalpelEngine : public SherlockEngine { private: Chess *_chess; Darts *_darts; - int _tempFadeStyle; int _chessResult; bool showCityCutscene(); diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 92a8757fd8..e0b5dc1711 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -118,7 +118,7 @@ Scene::Scene(SherlockEngine *vm): _vm(vm) { for (int idx = 0; idx < SCENES_COUNT; ++idx) Common::fill(&_stats[idx][0], &_stats[idx][9], false); _currentScene = -1; - _goToRoom = -1; + _goToScene = -1; _changes = false; _charPoint = _oldCharPoint = 0; _windowOpen = false; @@ -139,6 +139,8 @@ Scene::Scene(SherlockEngine *vm): _vm(vm) { _lookHelp = false; _animating = 0; _doBgAnimDone = true; + _oldLook = 0; + _tempFadeStyle = 0; _controlPanel = new ImageFile("controls.vgs"); _controls = nullptr; // new ImageFile("menu.all"); @@ -156,7 +158,14 @@ Scene::~Scene() { void Scene::clear() { } +/** + * Handles loading the scene specified by _goToScene + */ void Scene::selectScene() { + Events &events = *_vm->_events; + People &people = *_vm->_people; + Screen &screen = *_vm->_screen; + // Reset fields _windowOpen = _infoFlag = false; _menuMode = STD_MODE; @@ -165,12 +174,39 @@ void Scene::selectScene() { _oldTemp = _temp = 0; // Load the scene - Common::String sceneFile = Common::String::format("res%02d", _goToRoom); - _rrmName = Common::String::format("res%02d.rrm", _goToRoom); - _currentScene = _goToRoom; - _goToRoom = -1; + Common::String sceneFile = Common::String::format("res%02d", _goToScene); + _rrmName = Common::String::format("res%02d.rrm", _goToScene); + _currentScene = _goToScene; + _goToScene = -1; loadScene(sceneFile); + + // If the fade style was changed from running amovie, then reset it + if (_tempFadeStyle) { + screen._fadeStyle = _tempFadeStyle; + _tempFadeStyle = 0; + } + + people._walkDest = Common::Point(people[AL]._position.x / 100, + people[AL]._position.y / 100); + + _restoreFlag = true; + events.clearEvents(); + + // If there were any scripst waiting to be run, but were interrupt by a running + // canimation (probably the last scene's exit canim), clear the _scriptMoreFlag + if (_vm->_scriptMoreFlag == 3) + _vm->_scriptMoreFlag = 0; +} + +/** + * Fres all the graphics and other dynamically allocated data for the scene + */ +void Scene::freeScene() { + _vm->_inventory->freeInventory(); + + _roomBounds.clear(); + _canimShapes.clear(); } /** @@ -506,7 +542,7 @@ void Scene::checkSceneFlags(bool flag) { } // Check inventory - for (uint idx = 0; idx < _vm->_inventory->_holdings; ++idx) { + for (int idx = 0; idx < _vm->_inventory->_holdings; ++idx) { InventoryItem &ii = (*_vm->_inventory)[idx]; if (ii._requiredFlag && !_vm->readFlags(ii._requiredFlag)) { // Kill object: move it after the active holdings @@ -1013,10 +1049,10 @@ int Scene::startCAnim(int cAnimNum, int playRate) { cObj.checkObject(_bgShapes[0]); if (gotoCode > 0 && !talk._talkToAbort) { - _goToRoom = gotoCode; + _goToScene = gotoCode; - if (_goToRoom < 97 && _vm->_map[_goToRoom].x) { - _overPos = _vm->_map[_goToRoom]; + if (_goToScene < 97 && _vm->_map[_goToScene].x) { + _overPos = _vm->_map[_goToScene]; } } @@ -1305,7 +1341,7 @@ void Scene::doBgAnim() { _animating = 0; screen.slamRect(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT)); } else { - if (people[AL]._type != INVALID && ((_goToRoom == -1 || _ongoingCans == 0))) { + if (people[AL]._type != INVALID && ((_goToScene == -1 || _ongoingCans == 0))) { if (people[AL]._type == REMOVE) { screen.slamRect(Common::Rect( people[AL]._oldPosition.x, people[AL]._oldPosition.y, @@ -1325,7 +1361,7 @@ void Scene::doBgAnim() { for (uint idx = 0; idx < _bgShapes.size(); ++idx) { Object &o = _bgShapes[idx]; - if ((o._type == ACTIVE_BG_SHAPE || o._type == REMOVE) && _goToRoom == -1) { + if ((o._type == ACTIVE_BG_SHAPE || o._type == REMOVE) && _goToScene == -1) { screen.flushImage(o._imageFrame, o._position, &o._oldPosition.x, &o._oldPosition.y, &o._oldSize.x, &o._oldSize.y); } @@ -1347,7 +1383,7 @@ void Scene::doBgAnim() { people._portrait._type = INVALID; } - if (_goToRoom == -1) { + if (_goToScene == -1) { for (uint idx = 0; idx < _bgShapes.size(); ++idx) { Object &o = _bgShapes[idx]; if (o._type == NO_SHAPE && (o._flags & 1) == 0) { @@ -1363,7 +1399,7 @@ void Scene::doBgAnim() { for (int idx = _canimShapes.size() - 1; idx >= 0; --idx) { Object &o = _canimShapes[idx]; if (o._type == REMOVE) { - if (_goToRoom == -1) + if (_goToScene == -1) screen.slamArea(o._position.x, o._position.y, o._delta.x, o._delta.y); _canimShapes.remove_at(idx); @@ -1389,8 +1425,16 @@ void Scene::doBgAnim() { } } +/** + * Clears the info line of the screen + */ void Scene::clearInfo() { - // TODO + if (_infoFlag) { + _vm->_screen->fillRect(16, INFO_LINE, SHERLOCK_SCREEN_WIDTH - 200, INFO_LINE + 9, + INFO_BLACK); + _infoFlag = false; + _oldLook = -1; + } } diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h index 4b76739402..25c97c097a 100644 --- a/engines/sherlock/scene.h +++ b/engines/sherlock/scene.h @@ -120,6 +120,7 @@ private: int _selector; bool _invLookFlag; bool _lookHelp; + int _oldLook; bool loadScene(const Common::String &filename); @@ -134,7 +135,7 @@ private: void checkBgShapes(ImageFrame *frame, const Common::Point &pt); public: int _currentScene; - int _goToRoom; + int _goToScene; bool _changes; bool _stats[SCENES_COUNT][9]; bool _savedStats[SCENES_COUNT][9]; @@ -170,6 +171,7 @@ public: bool _restoreFlag; int _animating; bool _doBgAnimDone; + int _tempFadeStyle; public: Scene(SherlockEngine *vm); ~Scene(); @@ -178,6 +180,8 @@ public: void selectScene(); + void freeScene(); + void checkSceneFlags(bool mode); Exit *checkForExit(const Common::Rect &r); diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index 330da6075b..e023bf9b16 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -75,7 +75,7 @@ void SherlockEngine::initialize() { _animation = new Animation(this); _debugger = new Debugger(this); _events = new Events(this); - _inventory = new Inventory(); + _inventory = new Inventory(this); _journal = new Journal(); _people = new People(this); _scene = new Scene(this); @@ -102,14 +102,40 @@ Common::Error SherlockEngine::run() { // Initialize and load the scene. _scene->selectScene(); - // TODO: Implement game and remove this dummy loop - while (!shouldQuit()) - _events->pollEventsAndWait(); + // Scene handling loop + sceneLoop(); } return Common::kNoError; } +void SherlockEngine::sceneLoop() { + while (!shouldQuit() && _scene->_goToScene != -1) { + // See if a script needs to be completed from either a goto room code, + // or a script that was interrupted by another script + if (_scriptMoreFlag == 1 || _scriptMoreFlag == 3) + _talk->talkTo(_scriptName); + else + _scriptMoreFlag = 0; + + // Handle any input from the keyboard or mouse + handleInput(); + + if (_scene->_hsavedPos.x == -1) + _scene->doBgAnim(); + } + + _scene->freeScene(); + _talk->freeTalkVars(); + _people->freeWalk(); + +} + +void SherlockEngine::handleInput() { + // TODO +} + + /** * Read the state of a global flag */ diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h index 92aee9cdc3..11bea9bdcd 100644 --- a/engines/sherlock/sherlock.h +++ b/engines/sherlock/sherlock.h @@ -68,6 +68,9 @@ class Resource; class SherlockEngine : public Engine { private: + void sceneLoop(); + + void handleInput(); protected: virtual void initialize(); diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index 414f3b90a6..4c10b7b7ef 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -34,4 +34,12 @@ void Talk::talkTo(const Common::String &name) { // TODO } +/** + * Clear loaded talk data + */ +void Talk::freeTalkVars() { + _statements.clear(); +} + + } // End of namespace Sherlock diff --git a/engines/sherlock/talk.h b/engines/sherlock/talk.h index 55a4c0fd69..fc73994cc6 100644 --- a/engines/sherlock/talk.h +++ b/engines/sherlock/talk.h @@ -43,13 +43,15 @@ class Talk { private: SherlockEngine *_vm; public: - Common::Array _history; + Common::Array _statements; bool _talkToAbort; int _talkCounter; public: Talk(SherlockEngine *vm); void talkTo(const Common::String &name); + + void freeTalkVars(); }; } // End of namespace Sherlock -- cgit v1.2.3 From e444d989bb3470650020cb2c3f0fdb7b2fcab70a Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 22 Mar 2015 09:51:37 -0400 Subject: SHERLOCK: Implemented scene freeing code --- engines/sherlock/inventory.cpp | 2 +- engines/sherlock/objects.cpp | 2 +- engines/sherlock/objects.h | 4 ++-- engines/sherlock/scene.cpp | 42 ++++++++++++++++++++++++++++-------------- engines/sherlock/scene.h | 6 +++--- engines/sherlock/sherlock.cpp | 2 +- engines/sherlock/sherlock.h | 1 + engines/sherlock/sound.cpp | 4 ++++ engines/sherlock/sound.h | 1 + 9 files changed, 42 insertions(+), 22 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/inventory.cpp b/engines/sherlock/inventory.cpp index cbb69f1041..2a277a6331 100644 --- a/engines/sherlock/inventory.cpp +++ b/engines/sherlock/inventory.cpp @@ -106,7 +106,7 @@ void Inventory::loadGraphics() { int Inventory::findInv(const Common::String &name) { int result = -1; - for (uint idx = 0; (idx < _holdings) && result == -1; ++idx) { + for (int idx = 0; (idx < _holdings) && result == -1; ++idx) { if (scumm_stricmp(name.c_str(), _names[idx].c_str()) == 0) result = idx; } diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index 1643bef7b0..bbe2c9d4d2 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -946,7 +946,7 @@ void CAnim::synchronize(Common::SeekableReadStream &s) { /*----------------------------------------------------------------*/ -InvGraphicType::InvGraphicType() { +SceneImage::SceneImage() { _images = nullptr; _maxFrames = 0; _filesize = 0; diff --git a/engines/sherlock/objects.h b/engines/sherlock/objects.h index ee82faf99c..2ac2e16da0 100644 --- a/engines/sherlock/objects.h +++ b/engines/sherlock/objects.h @@ -223,12 +223,12 @@ struct CAnim { void synchronize(Common::SeekableReadStream &s); }; -struct InvGraphicType { +struct SceneImage { ImageFile *_images; // Object images int _maxFrames; // How many frames in object int _filesize; // File size - InvGraphicType(); + SceneImage(); } ; } // End of namespace Sherlock diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index e0b5dc1711..18ccdd4050 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -149,13 +149,7 @@ Scene::Scene(SherlockEngine *vm): _vm(vm) { Scene::~Scene() { delete _controlPanel; delete _controls; - clear(); -} - -/** - * Takes care of clearing any scene data - */ -void Scene::clear() { + freeScene(); } /** @@ -203,10 +197,27 @@ void Scene::selectScene() { * Fres all the graphics and other dynamically allocated data for the scene */ void Scene::freeScene() { + _vm->_talk->freeTalkVars(); _vm->_inventory->freeInventory(); + _vm->_sound->freeSong(); + _vm->_sound->freeLoadedSounds(); + if (!_vm->_loadingSavedGame) + saveSceneStatus(); + else + _vm->_loadingSavedGame = false; + + _sequenceBuffer.clear(); + _descText.clear(); + _walkData.clear(); + _cAnim.clear(); + _bgShapes.clear(); _roomBounds.clear(); _canimShapes.clear(); + + for (uint idx = 0; idx < _images.size(); ++idx) + delete _images[idx]._images; + _images.clear(); } /** @@ -225,6 +236,7 @@ bool Scene::loadScene(const Common::String &filename) { Sound &sound = *_vm->_sound; bool flag; + freeScene(); _walkedInScene = false; _ongoingCans = 0; @@ -232,7 +244,6 @@ bool Scene::loadScene(const Common::String &filename) { _roomBounds.clear(); _roomBounds.push_back(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); - clear(); _descText.clear(); _comments = ""; _bgShapes.clear(); @@ -287,17 +298,17 @@ bool Scene::loadScene(const Common::String &filename) { if (_lzwMode) delete infoStream; - // Set up inv list - _inv.resize(bgHeader._numImages + 1); + // Set up the list of images used by the scene + _images.resize(bgHeader._numImages + 1); for (int idx = 0; idx < bgHeader._numImages; ++idx) { - _inv[idx + 1]._filesize = bgInfo[idx]._filesize; - _inv[idx + 1]._maxFrames = bgInfo[idx]._maxFrames; + _images[idx + 1]._filesize = bgInfo[idx]._filesize; + _images[idx + 1]._maxFrames = bgInfo[idx]._maxFrames; // Read in the image data Common::SeekableReadStream *imageStream = !_lzwMode ? rrmStream : decompressLZ(*rrmStream, bgInfo[idx]._filesize); - _inv[idx + 1]._images = new ImageFile(*imageStream); + _images[idx + 1]._images = new ImageFile(*imageStream); if (_lzwMode) delete imageStream; @@ -315,7 +326,7 @@ bool Scene::loadScene(const Common::String &filename) { _bgShapes[idx]._position = Common::Point(0, 0); _bgShapes[idx]._oldSize = Common::Point(1, 1); - _bgShapes[idx]._images = _inv[_bgShapes[idx]._misc]._images; + _bgShapes[idx]._images = _images[_bgShapes[idx]._misc]._images; _bgShapes[idx]._imageFrame = !_bgShapes[idx]._images ? (ImageFrame *)nullptr : &(*_bgShapes[idx]._images)[0]; } @@ -1437,5 +1448,8 @@ void Scene::clearInfo() { } } +void Scene::saveSceneStatus() { + // TODO +} } // End of namespace Sherlock diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h index 25c97c097a..3cdb20ac0f 100644 --- a/engines/sherlock/scene.h +++ b/engines/sherlock/scene.h @@ -133,6 +133,8 @@ private: void updateBackground(); void checkBgShapes(ImageFrame *frame, const Common::Point &pt); + + void saveSceneStatus(); public: int _currentScene; int _goToScene; @@ -159,7 +161,7 @@ public: Common::Array _bgShapes; Common::Array _cAnim; Common::Array _sequenceBuffer; - Common::Array _inv; + Common::Array _images; int _walkDirectory[MAX_ZONES][MAX_ZONES]; Common::Array _walkData; Common::Array _exits; @@ -176,8 +178,6 @@ public: Scene(SherlockEngine *vm); ~Scene(); - void clear(); - void selectScene(); void freeScene(); diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index e023bf9b16..ad590e3ffd 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -43,6 +43,7 @@ SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gam _talk = nullptr; _useEpilogue2 = false; _justLoaded = false; + _loadingSavedGame = false; _onChessboard = false; _slowChess = false; _menuCounter = 0; @@ -126,7 +127,6 @@ void SherlockEngine::sceneLoop() { } _scene->freeScene(); - _talk->freeTalkVars(); _people->freeWalk(); } diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h index 11bea9bdcd..b84f6d7429 100644 --- a/engines/sherlock/sherlock.h +++ b/engines/sherlock/sherlock.h @@ -96,6 +96,7 @@ public: Common::String _titleOverride; bool _useEpilogue2; bool _justLoaded; + bool _loadingSavedGame; int _oldCharPoint; // Old scene Common::Point _over; // Old map position Common::Array _map; // Map locations for each scene diff --git a/engines/sherlock/sound.cpp b/engines/sherlock/sound.cpp index e8e433fa84..5e7df5607f 100644 --- a/engines/sherlock/sound.cpp +++ b/engines/sherlock/sound.cpp @@ -56,6 +56,10 @@ void Sound::playCachedSound(int index) { // TODO } +void Sound::freeLoadedSounds() { + // TODO +} + void Sound::clearCache() { // TODO } diff --git a/engines/sherlock/sound.h b/engines/sherlock/sound.h index 3f32f2724a..74e8db3611 100644 --- a/engines/sherlock/sound.h +++ b/engines/sherlock/sound.h @@ -55,6 +55,7 @@ public: void cacheSound(const Common::String &name, int index); void playLoadedSound(int bufNum, int waitMode); void playCachedSound(int index); + void freeLoadedSounds(); void clearCache(); void stopSound(); int loadSong(int songNumber); -- cgit v1.2.3 From 840bd862b734d54b18eb505b32ce030da10c934d Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 22 Mar 2015 10:48:28 -0400 Subject: SHERLOCK: Implement ImageFile nibble mode, fixes for scene data loading --- engines/sherlock/objects.cpp | 11 +++++----- engines/sherlock/objects.h | 2 +- engines/sherlock/resources.cpp | 13 +++++++---- engines/sherlock/resources.h | 2 +- engines/sherlock/scene.cpp | 49 ++++++++++++++++++++---------------------- engines/sherlock/scene.h | 2 +- 6 files changed, 40 insertions(+), 39 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index bbe2c9d4d2..7d86c45e15 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -408,12 +408,11 @@ void Object::setVm(SherlockEngine *vm) { * Load the object data from the passed stream */ void Object::synchronize(Common::SeekableReadStream &s) { - char buffer[50]; - + char buffer[12]; s.read(buffer, 12); _name = Common::String(buffer); - s.read(buffer, 41); - _description = Common::String(buffer); + + s.read(_description, 41); _examine.clear(); _sequences = nullptr; @@ -421,8 +420,8 @@ void Object::synchronize(Common::SeekableReadStream &s) { _imageFrame = nullptr; s.skip(4); - _sequenceOffset = s.readUint32LE(); - s.seek(8, SEEK_CUR); + _sequenceOffset = s.readUint16LE(); + s.seek(10, SEEK_CUR); _walkCount = s.readByte(); _allow = s.readByte(); diff --git a/engines/sherlock/objects.h b/engines/sherlock/objects.h index 2ac2e16da0..2a52ec4d33 100644 --- a/engines/sherlock/objects.h +++ b/engines/sherlock/objects.h @@ -152,7 +152,7 @@ public: static void setVm(SherlockEngine *vm); public: Common::String _name; // Name - Common::String _description; // Description + char _description[41]; // Description lines Common::String _examine; // Examine in-depth description int _sequenceOffset; uint8 *_sequences; // Holds animation sequences diff --git a/engines/sherlock/resources.cpp b/engines/sherlock/resources.cpp index 4b087b59b5..3915a4b5d9 100644 --- a/engines/sherlock/resources.cpp +++ b/engines/sherlock/resources.cpp @@ -297,13 +297,13 @@ void ImageFile::load(Common::SeekableReadStream &stream, bool skipPalette) { ImageFrame frame; frame._width = stream.readUint16LE() + 1; frame._height = stream.readUint16LE() + 1; - frame._flags = stream.readByte(); + frame._paletteBase = stream.readByte(); frame._offset.x = stream.readUint16LE(); frame._offset.y = stream.readByte(); frame._rleEncoded = !skipPalette && (frame._offset.x == 1); - if (frame._flags & 0xFF) { + if (frame._paletteBase) { // Nibble packed frame data frame._size = (frame._width * frame._height) / 2; } else if (frame._rleEncoded) { @@ -351,8 +351,13 @@ void ImageFile::loadPalette(Common::SeekableReadStream &stream) { void ImageFile::decompressFrame(ImageFrame &frame, const byte *src) { frame._frame.create(frame._width, frame._height, Graphics::PixelFormat::createFormatCLUT8()); - if (frame._flags & 0xFF) { - error("TODO: ImageFile::decompressFrame() 4-bits/pixel\n"); + if (frame._paletteBase) { + // Nibble-packed + byte *pDest = (byte *)frame._frame.getPixels(); + for (int idx = 0; idx < frame._size; ++idx, ++src) { + *pDest++ = *src & 0xF; + *pDest++ = (*src >> 4); + } } else if (frame._rleEncoded) { // RLE encoded byte *dst = (byte *)frame._frame.getPixels(); diff --git a/engines/sherlock/resources.h b/engines/sherlock/resources.h index ab2eb82a1e..45fda565bc 100644 --- a/engines/sherlock/resources.h +++ b/engines/sherlock/resources.h @@ -91,7 +91,7 @@ public: struct ImageFrame { uint32 _size; uint16 _width, _height; - int _flags; + int _paletteBase; bool _rleEncoded; Common::Point _offset; byte _rleMarker; diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 18ccdd4050..578eba2c24 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -212,7 +212,7 @@ void Scene::freeScene() { _walkData.clear(); _cAnim.clear(); _bgShapes.clear(); - _roomBounds.clear(); + _bounds.clear(); _canimShapes.clear(); for (uint idx = 0; idx < _images.size(); ++idx) @@ -241,8 +241,8 @@ bool Scene::loadScene(const Common::String &filename) { _ongoingCans = 0; // Reset the list of walkable areas - _roomBounds.clear(); - _roomBounds.push_back(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); + _bounds.clear(); + _bounds.push_back(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); _descText.clear(); _comments = ""; @@ -281,7 +281,7 @@ bool Scene::loadScene(const Common::String &filename) { decompressLZ(*rrmStream, bgHeader._numImages * 569 + bgHeader._descSize + bgHeader._seqSize); - _bgShapes.resize(bgHeader._numStructs + 1); + _bgShapes.resize(bgHeader._numStructs); for (int idx = 0; idx < bgHeader._numStructs; ++idx) _bgShapes[idx].synchronize(*infoStream); @@ -305,13 +305,13 @@ bool Scene::loadScene(const Common::String &filename) { _images[idx + 1]._maxFrames = bgInfo[idx]._maxFrames; // Read in the image data - Common::SeekableReadStream *imageStream = !_lzwMode ? rrmStream : - decompressLZ(*rrmStream, bgInfo[idx]._filesize); + Common::SeekableReadStream *imageStream = _lzwMode ? + decompressLZ(*rrmStream, bgInfo[idx]._filesize) : + rrmStream->readStream(bgInfo[idx]._filesize); _images[idx + 1]._images = new ImageFile(*imageStream); - if (_lzwMode) - delete imageStream; + delete imageStream; } // Set up the bgShapes @@ -331,44 +331,41 @@ bool Scene::loadScene(const Common::String &filename) { &(*_bgShapes[idx]._images)[0]; } - // Set up end of list - _bgShapes[bgHeader._numStructs]._sequences = &_sequenceBuffer[0] + bgHeader._seqSize; - _bgShapes[bgHeader._numStructs]._examine = nullptr; - // Load in cAnim list - Common::SeekableReadStream *canimStream = !_lzwMode ? rrmStream : - decompressLZ(*rrmStream, 65 * bgHeader._numcAnimations); + Common::SeekableReadStream *canimStream = _lzwMode ? + decompressLZ(*rrmStream, 65 * bgHeader._numcAnimations) : + rrmStream->readStream(65 * bgHeader._numcAnimations); _cAnim.resize(bgHeader._numcAnimations); for (uint idx = 0; idx < _cAnim.size(); ++idx) _cAnim[idx].synchronize(*canimStream); - if (_lzwMode) - delete canimStream; + delete canimStream; // Read in the room bounding areas int size = rrmStream->readUint16LE(); Common::SeekableReadStream *boundsStream = !_lzwMode ? rrmStream : decompressLZ(*rrmStream, size); - _roomBounds.resize(size / 10); - for (uint idx = 0; idx < _roomBounds.size(); ++idx) { - _roomBounds[idx].left = boundsStream->readSint16LE(); - _roomBounds[idx].top = boundsStream->readSint16LE(); - _roomBounds[idx].setWidth(boundsStream->readSint16LE()); - _roomBounds[idx].setHeight(boundsStream->readSint16LE()); + _bounds.resize(size / 10); + for (uint idx = 0; idx < _bounds.size(); ++idx) { + _bounds[idx].left = boundsStream->readSint16LE(); + _bounds[idx].top = boundsStream->readSint16LE(); + _bounds[idx].setWidth(boundsStream->readSint16LE()); + _bounds[idx].setHeight(boundsStream->readSint16LE()); boundsStream->skip(2); // Skip unused scene number field } if (_lzwMode) delete boundsStream; - // Back at version byte, so skip over it - rrmStream->skip(1); + // Ensure we've reached the path version byte + if (rrmStream->readByte() != 254) + error("Invalid scene path data"); // Load the walk directory - for (int idx1 = 0; idx1 < MAX_ZONES; ++idx1) { - for (int idx2 = 0; idx2 < MAX_ZONES; ++idx2) + for (uint idx1 = 0; idx1 < _bounds.size(); ++idx1) { + for (uint idx2 = 0; idx2 < _bounds.size(); ++idx2) _walkDirectory[idx1][idx2] = rrmStream->readSint16LE(); } diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h index 3cdb20ac0f..a6e4f51b99 100644 --- a/engines/sherlock/scene.h +++ b/engines/sherlock/scene.h @@ -157,7 +157,7 @@ public: int _invGraphicItems; Common::String _comments; Common::Array _descText; - Common::Array _roomBounds; + Common::Array _bounds; Common::Array _bgShapes; Common::Array _cAnim; Common::Array _sequenceBuffer; -- cgit v1.2.3 From 0f424da24b8d5c3399714d56c896e3a46983faac Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 22 Mar 2015 15:44:11 -0400 Subject: SHERLOCK: First game scene is partially showing --- engines/sherlock/objects.h | 3 +++ engines/sherlock/scene.cpp | 14 +++++++------- engines/sherlock/sherlock.cpp | 7 ++++--- 3 files changed, 14 insertions(+), 10 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/objects.h b/engines/sherlock/objects.h index 2a52ec4d33..9e43c087b8 100644 --- a/engines/sherlock/objects.h +++ b/engines/sherlock/objects.h @@ -206,6 +206,9 @@ public: void setFlagsAndToggles(); void adjustObject(); + + int frameWidth() const { return _imageFrame ? _imageFrame->_frame.w : 0; } + int frameHeight() const { return _imageFrame ? _imageFrame->_frame.h : 0; } }; struct CAnim { diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 578eba2c24..5bad8338aa 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -316,6 +316,10 @@ bool Scene::loadScene(const Common::String &filename) { // Set up the bgShapes for (int idx = 0; idx < bgHeader._numStructs; ++idx) { + _bgShapes[idx]._images = _images[_bgShapes[idx]._misc]._images; + _bgShapes[idx]._imageFrame = !_bgShapes[idx]._images ? (ImageFrame *)nullptr : + &(*_bgShapes[idx]._images)[0]; + _bgShapes[idx]._examine = Common::String(&_descText[_bgShapes[idx]._descOffset]); _bgShapes[idx]._sequences = &_sequenceBuffer[_bgShapes[idx]._sequenceOffset]; _bgShapes[idx]._misc = 0; @@ -325,10 +329,6 @@ bool Scene::loadScene(const Common::String &filename) { _bgShapes[idx]._frameNumber = -1; _bgShapes[idx]._position = Common::Point(0, 0); _bgShapes[idx]._oldSize = Common::Point(1, 1); - - _bgShapes[idx]._images = _images[_bgShapes[idx]._misc]._images; - _bgShapes[idx]._imageFrame = !_bgShapes[idx]._images ? (ImageFrame *)nullptr : - &(*_bgShapes[idx]._images)[0]; } // Load in cAnim list @@ -799,8 +799,8 @@ void Scene::updateBackground() { // Draw all static and active shapes that are FORWARD for (uint idx = 0; idx < _bgShapes.size(); ++idx) { _bgShapes[idx]._oldPosition = _bgShapes[idx]._position; - _bgShapes[idx]._oldSize = Common::Point(_bgShapes[idx]._imageFrame->_frame.w, - _bgShapes[idx]._imageFrame->_frame.h); + _bgShapes[idx]._oldSize = Common::Point(_bgShapes[idx].frameWidth(), + _bgShapes[idx].frameHeight()); if ((_bgShapes[idx]._type == ACTIVE_BG_SHAPE || _bgShapes[idx]._type == STATIC_BG_SHAPE) && _bgShapes[idx]._misc == FORWARD) @@ -837,7 +837,7 @@ void Scene::checkBgShapes(ImageFrame *frame, const Common::Point &pt) { Object &obj = _bgShapes[idx]; if (obj._type == STATIC_BG_SHAPE || obj._type == ACTIVE_BG_SHAPE) { if ((obj._flags & 5) == 1) { - obj._misc = (pt.y < (obj._position.y + obj._imageFrame->_frame.h - 1)) ? + obj._misc = (pt.y < (obj._position.y + obj.frameHeight() - 1)) ? NORMAL_FORWARD : NORMAL_BEHIND; } else if (!(obj._flags & 1)) { obj._misc = BEHIND; diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index ad590e3ffd..211c52ea87 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -54,14 +54,14 @@ SherlockEngine::~SherlockEngine() { delete _animation; delete _debugger; delete _events; - delete _inventory; delete _journal; delete _people; - delete _res; delete _scene; delete _screen; delete _sound; delete _talk; + delete _inventory; + delete _res; } void SherlockEngine::initialize() { @@ -111,7 +111,7 @@ Common::Error SherlockEngine::run() { } void SherlockEngine::sceneLoop() { - while (!shouldQuit() && _scene->_goToScene != -1) { + while (!shouldQuit() && _scene->_goToScene == -1) { // See if a script needs to be completed from either a goto room code, // or a script that was interrupted by another script if (_scriptMoreFlag == 1 || _scriptMoreFlag == 3) @@ -133,6 +133,7 @@ void SherlockEngine::sceneLoop() { void SherlockEngine::handleInput() { // TODO + _events->pollEventsAndWait(); } -- cgit v1.2.3 From 61980291bd977b15158a00e9cb97b8887a3d11e9 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 22 Mar 2015 15:49:54 -0400 Subject: SHERLOCK: Disable intro for now --- engines/sherlock/sherlock.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index 211c52ea87..5bb6500cf9 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -88,7 +88,8 @@ void SherlockEngine::initialize() { Common::Error SherlockEngine::run() { initialize(); - showOpening(); + // Temporarily disabled for now +// showOpening(); while (!shouldQuit()) { // Prepare for scene, and handle any game-specific scenes. This allows -- cgit v1.2.3 From 47fb0be0c77485741ca0352e2f2de663a49aede5 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 22 Mar 2015 17:30:06 -0400 Subject: SHERLOCK: Fix loading of player sprites --- engines/sherlock/resources.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sherlock/resources.cpp b/engines/sherlock/resources.cpp index 3915a4b5d9..e499b698c1 100644 --- a/engines/sherlock/resources.cpp +++ b/engines/sherlock/resources.cpp @@ -301,7 +301,7 @@ void ImageFile::load(Common::SeekableReadStream &stream, bool skipPalette) { frame._offset.x = stream.readUint16LE(); frame._offset.y = stream.readByte(); - frame._rleEncoded = !skipPalette && (frame._offset.x == 1); + frame._rleEncoded = !skipPalette && (frame._offset.x & 0xff) == 1; if (frame._paletteBase) { // Nibble packed frame data -- cgit v1.2.3 From b3130796540a727822d429ab122258e8be3db463 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 22 Mar 2015 17:54:16 -0400 Subject: SHERLOCK: Fix positioning of scene sprites --- engines/sherlock/scene.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 5bad8338aa..2133da5056 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -327,7 +327,7 @@ bool Scene::loadScene(const Common::String &filename) { _bgShapes[idx]._seqCounter2 = 0; _bgShapes[idx]._seqStack = 0; _bgShapes[idx]._frameNumber = -1; - _bgShapes[idx]._position = Common::Point(0, 0); + _bgShapes[idx]._oldPosition = Common::Point(0, 0); _bgShapes[idx]._oldSize = Common::Point(1, 1); } -- cgit v1.2.3 From 989d26897436103ff475b9987645b06265076bda Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 22 Mar 2015 18:24:13 -0400 Subject: SHERLOCK: Fix placement of Sherlock --- engines/sherlock/objects.h | 3 +++ engines/sherlock/scene.cpp | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sherlock/objects.h b/engines/sherlock/objects.h index 9e43c087b8..8099c6b74f 100644 --- a/engines/sherlock/objects.h +++ b/engines/sherlock/objects.h @@ -117,6 +117,9 @@ public: void adjustSprite(); void checkSprite(); + + int frameWidth() const { return _imageFrame ? _imageFrame->_frame.w : 0; } + int frameHeight() const { return _imageFrame ? _imageFrame->_frame.h : 0; } }; struct ActionType { diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 2133da5056..9f549b4312 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -777,7 +777,8 @@ void Scene::updateBackground() { player._sequenceNumber == WALK_DOWNRIGHT || player._sequenceNumber == STOP_DOWNRIGHT; surface.transBlitFrom(player._imageFrame->_frame, - Common::Point(player._position.x / 100, player._position.y / 100), flipped); + Common::Point(player._position.x / 100, + player._position.y / 100 - player.frameHeight()), flipped); } // Draw all static and active shapes that are NORMAL and are in front of the player -- cgit v1.2.3 From 73085bf57034adc2dbf5994ce2c6930b416eee7d Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 23 Mar 2015 20:34:34 -0400 Subject: SHERLOCK: Beginnings of UserInterface class --- engines/sherlock/animation.cpp | 4 +- engines/sherlock/events.cpp | 56 ++++--- engines/sherlock/events.h | 14 +- engines/sherlock/module.mk | 3 +- engines/sherlock/objects.cpp | 44 ++++-- engines/sherlock/objects.h | 3 + engines/sherlock/resources.cpp | 2 +- engines/sherlock/scene.cpp | 78 ++++----- engines/sherlock/scene.h | 22 +-- engines/sherlock/screen.h | 4 + engines/sherlock/sherlock.cpp | 15 +- engines/sherlock/sherlock.h | 3 +- engines/sherlock/user_interface.cpp | 306 ++++++++++++++++++++++++++++++++++++ engines/sherlock/user_interface.h | 91 +++++++++++ 14 files changed, 534 insertions(+), 111 deletions(-) create mode 100644 engines/sherlock/user_interface.cpp create mode 100644 engines/sherlock/user_interface.h (limited to 'engines') diff --git a/engines/sherlock/animation.cpp b/engines/sherlock/animation.cpp index 9d32746de4..e1687b5238 100644 --- a/engines/sherlock/animation.cpp +++ b/engines/sherlock/animation.cpp @@ -151,14 +151,14 @@ bool Animation::playPrologue(const Common::String &filename, int minDelay, int f events.wait(speed); } - if (events.isKeyPressed()) { + if (events.kbHit()) { Common::KeyState keyState = events.getKey(); if (keyState.keycode == Common::KEYCODE_ESCAPE || keyState.keycode == Common::KEYCODE_SPACE) { skipped = true; break; } - } else if (events._mouseClicked) { + } else if (events._pressed) { skipped = true; break; } diff --git a/engines/sherlock/events.cpp b/engines/sherlock/events.cpp index 1a09f0600e..a6b3c899cb 100644 --- a/engines/sherlock/events.cpp +++ b/engines/sherlock/events.cpp @@ -36,8 +36,10 @@ Events::Events(SherlockEngine *vm) { _cursorId = INVALID_CURSOR; _frameCounter = 1; _priorFrameTime = 0; - _mouseClicked = false; _mouseButtons = 0; + _pressed = _released = false; + _rightPressed = _rightReleased = false; + _oldButtons = _oldRightButton = false; } Events::~Events() { @@ -125,12 +127,16 @@ void Events::pollEvents() { case Common::EVENT_KEYUP: return; case Common::EVENT_LBUTTONDOWN: + _mouseButtons |= 1; + return; case Common::EVENT_RBUTTONDOWN: - _mouseClicked = true; + _mouseButtons |= 2; return; case Common::EVENT_LBUTTONUP: + _mouseButtons &= ~1; + return; case Common::EVENT_RBUTTONUP: - _mouseClicked = false; + _mouseButtons &= ~2; return; case Common::EVENT_MOUSEMOVE: _mousePos = event.mouse; @@ -180,7 +186,9 @@ bool Events::checkForNextFrameCounter() { */ void Events::clearEvents() { _pendingKeys.clear(); - _mouseClicked = false; + _pressed = _rightPressed = false; + _rightPressed = _rightReleased = false; + _oldButtons = _oldRightButton = false; } /** @@ -197,7 +205,7 @@ bool Events::delay(uint32 time, bool interruptable) { // For really short periods, simply delay by the desired amount pollEvents(); g_system->delayMillis(time); - bool result = !(interruptable && (isKeyPressed() || _mouseClicked)); + bool result = !(interruptable && (kbHit() || _pressed)); clearEvents(); return result; @@ -210,7 +218,7 @@ bool Events::delay(uint32 time, bool interruptable) { while (!_vm->shouldQuit() && g_system->getMillis() < delayEnd) { pollEventsAndWait(); - if (interruptable && (isKeyPressed() || _mouseClicked)) { + if (interruptable && (kbHit() || _pressed)) { clearEvents(); return false; } @@ -221,25 +229,33 @@ bool Events::delay(uint32 time, bool interruptable) { } /** - * Wait for the next frame + * Sets the pressed and released button flags depending on the value passed */ -void Events::waitForNextFrame() { - _mouseClicked = false; - _mouseButtons = 0; - - bool mouseClicked = false; - int mouseButtons = 0; +void Events::setButtonState() { + _released = _rightReleased = false; + if (_mouseButtons & 1) + _pressed = _oldButtons = true; + + if ((_mouseButtons & 1) == 0 && _oldButtons) { + _pressed = _oldButtons = false; + _released = true; + } - uint32 frameCtr = getFrameCounter(); - while (!_vm->shouldQuit() && frameCtr == _frameCounter) { - pollEventsAndWait(); + if (_mouseButtons & 2) + _rightPressed = _oldRightButton = true; - mouseClicked |= _mouseClicked; - mouseButtons |= _mouseButtons; + if ((_mouseButtons & 2) == 0 && _oldRightButton) { + _rightPressed = _oldRightButton = false; + _rightReleased = true; } +} - _mouseClicked = mouseClicked; - _mouseButtons = mouseButtons; +/** + * Checks to see to see if a key or a mouse button is pressed. + */ +bool Events::checkInput() { + setButtonState(); + return kbHit() || _pressed || _released || _rightPressed || _rightReleased; } } // End of namespace MADS diff --git a/engines/sherlock/events.h b/engines/sherlock/events.h index e939b5768f..1c5fbc5be4 100644 --- a/engines/sherlock/events.h +++ b/engines/sherlock/events.h @@ -44,12 +44,17 @@ private: uint32 _priorFrameTime; Common::Point _mousePos; ImageFile *_cursorImages; + int _mouseButtons; bool checkForNextFrameCounter(); public: CursorId _cursorId; - byte _mouseButtons; - bool _mouseClicked; + bool _pressed; + bool _released; + bool _rightPressed; + bool _rightReleased; + bool _oldButtons; + bool _oldRightButton; Common::Stack _pendingKeys; public: Events(SherlockEngine *vm); @@ -75,7 +80,7 @@ public: uint32 getFrameCounter() const { return _frameCounter; } - bool isKeyPressed() const { return !_pendingKeys.empty(); } + bool kbHit() const { return !_pendingKeys.empty(); } Common::KeyState getKey() { return _pendingKeys.pop(); } @@ -85,8 +90,9 @@ public: bool delay(uint32 time, bool interruptable = false); - void waitForNextFrame(); + void setButtonState(); + bool checkInput(); }; } // End of namespace Sherlock diff --git a/engines/sherlock/module.mk b/engines/sherlock/module.mk index aa8f495742..4101769a80 100644 --- a/engines/sherlock/module.mk +++ b/engines/sherlock/module.mk @@ -20,7 +20,8 @@ MODULE_OBJS = \ screen.o \ sherlock.o \ sound.o \ - talk.o + talk.o \ + user_interface.o # This module can be built as a plugin ifdef BUILD_PLUGINS diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index 7d86c45e15..e0a24c5b7d 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -39,10 +39,6 @@ namespace Sherlock { #define CLEAR_DIST_X 5 #define CLEAR_DIST_Y 0 -#define INFO_FOREGROUND 11 -#define INFO_BACKGROUND 1 - - SherlockEngine *Sprite::_vm; /** @@ -779,6 +775,7 @@ int Object::checkNameForCodes(const Common::String &name, Common::StringArray *m Scene &scene = *_vm->_scene; Screen &screen = *_vm->_screen; Talk &talk = *_vm->_talk; + UserInterface &ui = *_vm->_ui; bool printed = false; char ch; const char *p; @@ -852,19 +849,19 @@ int Object::checkNameForCodes(const Common::String &name, Common::StringArray *m } else if (name.hasPrefix("!")) { // Message attached to canimation int messageNum = atoi(name.c_str() + 1); - scene._infoFlag++; - scene.clearInfo(); + ui._infoFlag++; + ui.clearInfo(); screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, INFO_BACKGROUND, (*messages)[messageNum].c_str()); - _vm->_menuCounter = 25; + ui._menuCounter = 25; } else if (name.hasPrefix("@")) { // Message attached to canimation - scene._infoFlag++; - scene.clearInfo(); + ui._infoFlag++; + ui.clearInfo(); screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, INFO_BACKGROUND, "%s", name.c_str() + 1); printed = true; - _vm->_menuCounter = 25; + ui._menuCounter = 25; } return printed; @@ -922,6 +919,33 @@ void Object::adjustObject() { } } +/** + * Returns the current bounds for the sprite + */ +const Common::Rect Object::getNewBounds() const { + Common::Point pt = _position; + if (_imageFrame) + pt += _imageFrame->_offset; + + return Common::Rect(pt.x, pt.y, pt.x + frameWidth(), pt.y + frameHeight()); +} + +/** + * Returns the bounds for a sprite without a shape + */ +const Common::Rect Object::getNoShapeBounds() const { + return Common::Rect(_position.x, _position.y, + _position.x + _noShapeSize.x, _position.y + _noShapeSize.y); +} + +/** + * Returns the old bounsd for the sprite from the previous frame + */ +const Common::Rect Object::getOldBounds() const { + return Common::Rect(_oldPosition.x, _oldPosition.y, + _oldPosition.x + _oldSize.x, _oldPosition.y + _oldSize.y); +} + /*----------------------------------------------------------------*/ void CAnim::synchronize(Common::SeekableReadStream &s) { diff --git a/engines/sherlock/objects.h b/engines/sherlock/objects.h index 8099c6b74f..4944681ab3 100644 --- a/engines/sherlock/objects.h +++ b/engines/sherlock/objects.h @@ -212,6 +212,9 @@ public: int frameWidth() const { return _imageFrame ? _imageFrame->_frame.w : 0; } int frameHeight() const { return _imageFrame ? _imageFrame->_frame.h : 0; } + const Common::Rect getNewBounds() const; + const Common::Rect getNoShapeBounds() const; + const Common::Rect getOldBounds() const; }; struct CAnim { diff --git a/engines/sherlock/resources.cpp b/engines/sherlock/resources.cpp index e499b698c1..878747a63c 100644 --- a/engines/sherlock/resources.cpp +++ b/engines/sherlock/resources.cpp @@ -354,7 +354,7 @@ void ImageFile::decompressFrame(ImageFrame &frame, const byte *src) { if (frame._paletteBase) { // Nibble-packed byte *pDest = (byte *)frame._frame.getPixels(); - for (int idx = 0; idx < frame._size; ++idx, ++src) { + for (uint idx = 0; idx < frame._size; ++idx, ++src) { *pDest++ = *src & 0xF; *pDest++ = (*src >> 4); } diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 9f549b4312..6e09693807 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -27,37 +27,6 @@ namespace Sherlock { -// Main Menu control locations -const int MENU_POINTS[12][4] = { - { 13, 153, 72, 165 }, - { 13, 169, 72, 181 }, - { 13, 185, 72, 197 }, - { 88, 153, 152, 165 }, - { 88, 169, 152, 181 }, - { 88, 185, 152, 197 }, - { 165, 153, 232, 165 }, - { 165, 169, 232, 181 }, - { 165, 185, 233, 197 }, - { 249, 153, 305, 165 }, - { 249, 169, 305, 181 }, - { 249, 185, 305, 197 } -}; - -// Inventory control locations */ -const int INVENTORY_POINTS[8][3] = { - { 4, 50, 28 }, - { 52, 99, 76 }, - { 101, 140, 122 }, - { 142, 187, 165 }, - { 189, 219, 197 }, - { 221, 251, 233 }, - { 253, 283, 265 }, - { 285, 315, 293 } -}; - -/*----------------------------------------------------------------*/ - - void BgFileHeader::synchronize(Common::SeekableReadStream &s) { _numStructs = s.readUint16LE(); _numImages = s.readUint16LE(); @@ -121,8 +90,6 @@ Scene::Scene(SherlockEngine *vm): _vm(vm) { _goToScene = -1; _changes = false; _charPoint = _oldCharPoint = 0; - _windowOpen = false; - _infoFlag = false; _keyboardInput = 0; _walkedInScene = false; _ongoingCans = 0; @@ -132,23 +99,19 @@ Scene::Scene(SherlockEngine *vm): _vm(vm) { _hsavedPos = Common::Point(-1, -1); _hsavedFs = -1; _cAnimFramePause = 0; - _menuMode = STD_MODE; _invMode = INVMODE_0; _restoreFlag = false; _invLookFlag = false; _lookHelp = false; _animating = 0; _doBgAnimDone = true; - _oldLook = 0; _tempFadeStyle = 0; _controlPanel = new ImageFile("controls.vgs"); - _controls = nullptr; // new ImageFile("menu.all"); } Scene::~Scene() { delete _controlPanel; - delete _controls; freeScene(); } @@ -159,10 +122,11 @@ void Scene::selectScene() { Events &events = *_vm->_events; People &people = *_vm->_people; Screen &screen = *_vm->_screen; + UserInterface &ui = *_vm->_ui; // Reset fields - _windowOpen = _infoFlag = false; - _menuMode = STD_MODE; + ui._windowOpen = ui._infoFlag = false; + ui._menuMode = STD_MODE; _keyboardInput = 0; _oldKey = _help = _oldHelp = 0; _oldTemp = _temp = 0; @@ -1135,6 +1099,7 @@ void Scene::doBgAnim() { Screen &screen = *_vm->_screen; Sound &sound = *_vm->_sound; Talk &talk = *_vm->_talk; + UserInterface &ui = *_vm->_ui; Surface surface = screen._backBuffer.getSubArea(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT)); int cursorId = events.getCursor(); @@ -1151,7 +1116,7 @@ void Scene::doBgAnim() { } // Check for setting magnifying glass cursor - if (_menuMode == INV_MODE || _menuMode == USE_MODE || _menuMode == GIVE_MODE) { + if (ui._menuMode == INV_MODE || ui._menuMode == USE_MODE || ui._menuMode == GIVE_MODE) { if (_invMode == INVMODE_1) { // Only show Magnifying glass cursor if it's not on the inventory command line if (mousePos.y < CONTROLS_Y || mousePos.y >(CONTROLS_Y1 + 13)) @@ -1434,20 +1399,33 @@ void Scene::doBgAnim() { } } +void Scene::saveSceneStatus() { + // TODO +} + /** - * Clears the info line of the screen + * Attempts to find a background shape within the passed bounds. If found, + * it will return the shape number, or -1 on failure. */ -void Scene::clearInfo() { - if (_infoFlag) { - _vm->_screen->fillRect(16, INFO_LINE, SHERLOCK_SCREEN_WIDTH - 200, INFO_LINE + 9, - INFO_BLACK); - _infoFlag = false; - _oldLook = -1; +int Scene::findBgShape(const Common::Rect &r) { + if (!_doBgAnimDone) + // New frame hasn't been drawn yet + return -1; + + for (int idx = (int)_bgShapes.size() - 1; idx >= 0; --idx) { + Object &o = _bgShapes[idx]; + if (o._type != INVALID && o._type != NO_SHAPE && o._type != HIDDEN + && o._aType <= PERSON) { + if (r.intersects(o.getNewBounds())) + return idx; + } else if (o._type == NO_SHAPE) { + if (r.intersects(o.getNoShapeBounds())) + return idx; + } } -} -void Scene::saveSceneStatus() { - // TODO + return -1; } + } // End of namespace Sherlock diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h index a6e4f51b99..785ed63106 100644 --- a/engines/sherlock/scene.h +++ b/engines/sherlock/scene.h @@ -37,22 +37,6 @@ namespace Sherlock { #define CONTROLS_Y 138 #define CONTROLS_Y1 151 -enum MenuMode { - STD_MODE = 0, - LOOK_MODE = 1, - MOVE_MODE = 2, - TALK_MODE = 3, - PICKUP_MODE = 4, - OPEN_MODE = 5, - CLOSE_MODE = 6, - INV_MODE = 7, - USE_MODE = 8, - GIVE_MODE = 9, - JOURNAL_MODE = 10, - FILES_MODE = 11, - SETUP_MODE = 12 -}; - enum InvMode { INVMODE_0 = 0, INVMODE_1 = 1, @@ -114,13 +98,11 @@ private: Common::String _rrmName; int _cAnimFramePause; Common::String _cAnimStr; - MenuMode _menuMode; InvMode _invMode; bool _lookScriptFlag; int _selector; bool _invLookFlag; bool _lookHelp; - int _oldLook; bool loadScene(const Common::String &filename); @@ -144,9 +126,7 @@ public: Common::Point _bigPos; Common::Point _overPos; int _charPoint, _oldCharPoint; - ImageFile *_controls; ImageFile *_controlPanel; - bool _windowOpen, _infoFlag; int _keyboardInput; int _oldKey, _help, _oldHelp; int _oldTemp, _temp; @@ -195,6 +175,8 @@ public: void doBgAnim(); void clearInfo(); + + int findBgShape(const Common::Rect &r); }; } // End of namespace Sherlock diff --git a/engines/sherlock/screen.h b/engines/sherlock/screen.h index 87453ba36d..419ae681c2 100644 --- a/engines/sherlock/screen.h +++ b/engines/sherlock/screen.h @@ -34,7 +34,11 @@ namespace Sherlock { #define PALETTE_SIZE 768 #define PALETTE_COUNT 256 #define VGA_COLOR_TRANS(x) ((x) * 255 / 63) + #define INFO_BLACK 1 +#define INFO_FOREGROUND 11 +#define INFO_BACKGROUND 1 + class SherlockEngine; diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index 5bb6500cf9..eea40f33a6 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -41,12 +41,12 @@ SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gam _screen = nullptr; _sound = nullptr; _talk = nullptr; + _ui = nullptr; _useEpilogue2 = false; _justLoaded = false; _loadingSavedGame = false; _onChessboard = false; _slowChess = false; - _menuCounter = 0; _scriptMoreFlag = 0; } @@ -60,6 +60,7 @@ SherlockEngine::~SherlockEngine() { delete _screen; delete _sound; delete _talk; + delete _ui; delete _inventory; delete _res; } @@ -83,6 +84,7 @@ void SherlockEngine::initialize() { _screen = new Screen(this); _sound = new Sound(this); _talk = new Talk(this); + _ui = new UserInterface(this); } Common::Error SherlockEngine::run() { @@ -132,9 +134,18 @@ void SherlockEngine::sceneLoop() { } +/** + * Handle all player input + */ void SherlockEngine::handleInput() { - // TODO + bool personFound; + _events->pollEventsAndWait(); + + // See if a key or mouse button is pressed + _events->setButtonState(); + + _ui->handleInput(); } diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h index b84f6d7429..392f55839e 100644 --- a/engines/sherlock/sherlock.h +++ b/engines/sherlock/sherlock.h @@ -42,6 +42,7 @@ #include "sherlock/screen.h" #include "sherlock/sound.h" #include "sherlock/talk.h" +#include "sherlock/user_interface.h" namespace Sherlock { @@ -90,6 +91,7 @@ public: Screen *_screen; Sound *_sound; Talk *_talk; + UserInterface *_ui; Common::RandomSource _randomSource; Common::Array _flags; Common::String _soundOverride; @@ -102,7 +104,6 @@ public: Common::Array _map; // Map locations for each scene bool _onChessboard; bool _slowChess; - int _menuCounter; int _scriptMoreFlag; Common::String _scriptName; public: diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp new file mode 100644 index 0000000000..d80aaecb54 --- /dev/null +++ b/engines/sherlock/user_interface.cpp @@ -0,0 +1,306 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "sherlock/user_interface.h" +#include "sherlock/sherlock.h" + +namespace Sherlock { + +// Main user interface menu control locations +const int MENU_POINTS[12][4] = { + { 13, 153, 72, 165 }, + { 13, 169, 72, 181 }, + { 13, 185, 72, 197 }, + { 88, 153, 152, 165 }, + { 88, 169, 152, 181 }, + { 88, 185, 152, 197 }, + { 165, 153, 232, 165 }, + { 165, 169, 232, 181 }, + { 165, 185, 233, 197 }, + { 249, 153, 305, 165 }, + { 249, 169, 305, 181 }, + { 249, 185, 305, 197 } +}; + +// Inventory control locations */ +const int INVENTORY_POINTS[8][3] = { + { 4, 50, 28 }, + { 52, 99, 76 }, + { 101, 140, 122 }, + { 142, 187, 165 }, + { 189, 219, 197 }, + { 221, 251, 233 }, + { 253, 283, 265 }, + { 285, 315, 293 } +}; + +const char COMMANDS[13] = "LMTPOCIUGJFS"; + +/*----------------------------------------------------------------*/ + +UserInterface::UserInterface(SherlockEngine *vm) : _vm(vm) { + _bgFound = 0; + _oldBgFound = -1; + _keycode = Common::KEYCODE_INVALID; + _helpStyle = 0; + _menuCounter = 0; + _menuMode = STD_MODE; + _help = _oldHelp = 0; + _lookHelp = 0; + _key = _oldKey = 0; + _temp = _oldTemp = 0; + _invLookFlag = 0; + _windowOpen = false; + _oldLook = false; + _keyboardInput = false; + + _controls = nullptr; // new ImageFile("menu.all"); +} + +UserInterface::~UserInterface() { + delete _controls; +} + +void UserInterface::handleInput() { + Events &events = *_vm->_events; + Scene &scene = *_vm->_scene; + Screen &screen = *_vm->_screen; + + if (_menuCounter) + whileMenuCounter(); + + Common::Point pt = events.mousePos(); + _bgFound = scene.findBgShape(Common::Rect(pt.x, pt.y, pt.x + 1, pt.y + 1)); + _keycode = Common::KEYCODE_INVALID; + + // Check kbd and set the mouse released flag if Enter or space is pressed. + // Otherwise, the pressed key is stored for later use + if (events.kbHit()) { + Common::KeyState keyState = events.getKey(); + + if (keyState.keycode == Common::KEYCODE_x && keyState.flags & Common::KBD_ALT) { + _vm->quitGame(); + return; + } else if (keyState.keycode == Common::KEYCODE_SPACE || + keyState.keycode == Common::KEYCODE_RETURN) { + events._pressed = events._oldButtons = 0; + _keycode = Common::KEYCODE_INVALID; + } + } + + // Do button highlighting check + if (!_vm->_scriptMoreFlag) { // Don't if scripts are running + if (((events._rightPressed || events._rightReleased) && _helpStyle) || + (!_helpStyle && !_menuCounter)) { + // Handle any default commands if we're in STD_MODE + if (_menuMode == STD_MODE) { + if (pt.y < CONTROLS_Y && + (events._rightPressed || (!_helpStyle && !events._released)) && + (_bgFound != -1) && (_bgFound < 1000) && + (scene._bgShapes[_bgFound]._defaultCommand || + scene._bgShapes[_bgFound]._description[0])) { + // If there is no default command, so set it to Look + if (scene._bgShapes[_bgFound]._defaultCommand) + _help = scene._bgShapes[_bgFound]._defaultCommand - 1; + else + _help = 0; + + // Reset 'help' if it is an invalid command + if (_help > 5) + _help = -1; + } else if (pt.y < CONTROLS_Y && + ((events._rightReleased && _helpStyle) || (events._released && !_helpStyle)) && + (_bgFound != -1 && _bgFound < 1000) && + (scene._bgShapes[_bgFound]._defaultCommand || + scene._bgShapes[_bgFound]._description[0])) { + // If there is no default command, set it to Look + if (scene._bgShapes[_bgFound]._defaultCommand) + _menuMode = (MenuMode)scene._bgShapes[_bgFound]._defaultCommand; + else + _menuMode = LOOK_MODE; + events._released = true; + events._pressed = events._oldButtons = false; + _help = _oldHelp = -1; + + if (_menuMode == LOOK_MODE) { + // Set the flag to tell the game that this was a right-click + // call to look and should exit without the look button being pressed + _lookHelp = true; + } + } else { + _help = -1; + } + + // Check if highlighting a different button than last time + if (_help != _oldHelp) { + // If another button was highlighted previously, restore it + if (_oldHelp != -1) + restoreButton(_oldHelp); + + // If we're highlighting a new button, then draw it pressed + if (_help != -1) + depressButton(_help); + + _help = _oldHelp; + } + + if (_bgFound != _oldBgFound) { + _infoFlag = true; + clearInfo(); + + if (_help != -1 && (scene._bgShapes[_bgFound]._description[0] != 32 && + scene._bgShapes[_bgFound]._description[0])) + screen.print(Common::Point(0, INFO_LINE + 1), + INFO_FOREGROUND, INFO_BACKGROUND, "%s", + scene._bgShapes[_bgFound]._description); + } + } else { + // We're not in STD_MODE + // If there isn't a window open, then revert back to STD_MODE + if (!_windowOpen && events._rightReleased) { + // Restore all buttons + for (int idx = 0; idx < 12; ++idx) + restoreButton(idx); + + _menuMode = STD_MODE; + _key = _oldKey = -1; + _temp = _oldTemp = _lookHelp = _invLookFlag = 0; + events.clearEvents(); + } + } + } + } + + // TODO +} + +/** + * Draws the image for a user interface button in the down/pressed state. + */ +void UserInterface::depressButton(int num) { + Screen &screen = *_vm->_screen; + Common::Point pt(MENU_POINTS[num][0], MENU_POINTS[num][1]); + + Graphics::Surface &s = (*_controls)[num]._frame; + screen._backBuffer.transBlitFrom(s, pt); + screen.slamArea(pt.x, pt.y, pt.x + s.w, pt.y + s.h); +} + +/** + * Draws the image for the given user interface button in the up + * (not selected) position + */ +void UserInterface::restoreButton(int num) { + Screen &screen = *_vm->_screen; + Common::Point pt(MENU_POINTS[num][0], MENU_POINTS[num][1]); + + screen._backBuffer.blitFrom(screen._backBuffer2, pt, + Common::Rect(pt.x, pt.y, pt.x + 90, pt.y + 19)); + screen._backBuffer.blitFrom(screen._backBuffer, pt, + Common::Rect(pt.x, pt.y, pt.x + (*_controls)[num]._frame.w, + (*_controls)[num]._frame.h)); + + if (!_menuCounter) { + _infoFlag++; + clearInfo(); + } +} + +/** + * If he mouse button is pressed, then calls depressButton to draw the button + * as pressed; if not, it will show it as released with a call to "restoreButton". + */ +void UserInterface::pushButton(int num) { + Events &events = *_vm->_events; + _oldKey = -1; + + if (!events._released) { + if (_oldHelp != -1) + restoreButton(_oldHelp); + if (_help != -1) + restoreButton(_help); + + depressButton(num); + events.wait(6); + } + + restoreButton(num); +} + +/** + * By the time this method has been called, the graphics for the button change + * have already been drawn. This simply takes care of switching the mode around + * accordingly + */ +void UserInterface::toggleButton(int num) { + Screen &screen = *_vm->_screen; + + if (_menuMode != (num + 1)) { + _menuMode = (MenuMode)(num + 1); + _oldKey = COMMANDS[num]; + _oldTemp = num; + + if (_keyboardInput) { + if (_oldHelp != -1 && _oldHelp != num) + restoreButton(_oldHelp); + if (_help != -1 && _help != num) + restoreButton(_help); + + _keyboardInput = false; + + Graphics::Surface &s = (*_controls)[num]._frame; + Common::Point pt(MENU_POINTS[num][0], MENU_POINTS[num][1]); + screen._backBuffer.transBlitFrom(s, pt); + screen.slamArea(pt.x, pt.y, pt.x + s.w, pt.y + s.h); + } + } else { + _menuMode = STD_MODE; + _oldKey = -1; + restoreButton(num); + } +} + + +/** + * Clears the info line of the screen + */ +void UserInterface::clearInfo() { + if (_infoFlag) { + _vm->_screen->fillRect(16, INFO_LINE, SHERLOCK_SCREEN_WIDTH - 200, INFO_LINE + 9, + INFO_BLACK); + _infoFlag = false; + _oldLook = -1; + } +} + +/** + * Handles counting down whilst checking for input, then clears the info line. + */ +void UserInterface::whileMenuCounter() { + if (!(--_menuCounter) || _vm->_events->checkInput()) { + _menuCounter = 0; + ++_infoFlag; + clearInfo(); + } +} + +} // End of namespace Sherlock diff --git a/engines/sherlock/user_interface.h b/engines/sherlock/user_interface.h new file mode 100644 index 0000000000..4a98a5be89 --- /dev/null +++ b/engines/sherlock/user_interface.h @@ -0,0 +1,91 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef SHERLOCK_UI_H +#define SHERLOCK_UI_H + +#include "common/scummsys.h" +#include "common/events.h" +#include "sherlock/resources.h" + +namespace Sherlock { + +enum MenuMode { + STD_MODE = 0, + LOOK_MODE = 1, + MOVE_MODE = 2, + TALK_MODE = 3, + PICKUP_MODE = 4, + OPEN_MODE = 5, + CLOSE_MODE = 6, + INV_MODE = 7, + USE_MODE = 8, + GIVE_MODE = 9, + JOURNAL_MODE = 10, + FILES_MODE = 11, + SETUP_MODE = 12 +}; + +class SherlockEngine; + +class UserInterface { +private: + SherlockEngine *_vm; + int _bgFound; + int _oldBgFound; + Common::KeyCode _keycode; + int _helpStyle; + int _lookHelp; + int _help, _oldHelp; + int _key, _oldKey; + int _temp, _oldTemp; + int _invLookFlag; + ImageFile *_controls; + int _oldLook; + bool _keyboardInput; +private: + void depressButton(int num); + + void restoreButton(int num); + + void pushButton(int num); + + void toggleButton(int num); +public: + MenuMode _menuMode; + int _menuCounter; + bool _infoFlag; + bool _windowOpen; +public: + UserInterface(SherlockEngine *vm); + ~UserInterface(); + + void handleInput(); + + void clearInfo(); + + void whileMenuCounter(); +}; + +} // End of namespace Sherlock + +#endif -- cgit v1.2.3 From 73de00b72f002c09c173226e85b0f96f35551d10 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 23 Mar 2015 21:52:20 -0400 Subject: SHERLOCK: Implemented UserInterface::handleInput --- engines/sherlock/people.cpp | 4 + engines/sherlock/people.h | 4 +- engines/sherlock/scene.cpp | 22 +++++ engines/sherlock/scene.h | 2 + engines/sherlock/sherlock.cpp | 2 - engines/sherlock/talk.cpp | 4 + engines/sherlock/talk.h | 2 + engines/sherlock/user_interface.cpp | 185 +++++++++++++++++++++++++++++++++++- engines/sherlock/user_interface.h | 16 ++++ 9 files changed, 237 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp index 91689e296c..8a8dcb5245 100644 --- a/engines/sherlock/people.cpp +++ b/engines/sherlock/people.cpp @@ -311,4 +311,8 @@ void People::walkToCoords(const Common::Point &destPos, int destDir) { warning("TODO: walkToCoords"); } +void People::goAllTheWay() { + // TODO +} + } // End of namespace Sherlock diff --git a/engines/sherlock/people.h b/engines/sherlock/people.h index de84675e66..8d1953ee20 100644 --- a/engines/sherlock/people.h +++ b/engines/sherlock/people.h @@ -59,7 +59,6 @@ private: Sprite &_player; bool _walkLoaded; int _oldWalkSequence; - bool _allowWalkAbort; public: Common::Point _walkDest; Common::Stack _walkTo; @@ -67,6 +66,7 @@ public: bool _portraitLoaded; Object _portrait; bool _clearingThePortrait; + bool _allowWalkAbort; public: People(SherlockEngine *vm); ~People(); @@ -86,6 +86,8 @@ public: void gotoStand(Sprite &sprite); void walkToCoords(const Common::Point &destPos, int destDir); + + void goAllTheWay(); }; } // End of namespace Sherlock diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 6e09693807..95e8355957 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -1427,5 +1427,27 @@ int Scene::findBgShape(const Common::Rect &r) { return -1; } +/** + * Checks to see if the given position in the scene belongs to a given zone type. + * If it is, the zone is activated and used just like a TAKL zone or aFLAG_SET zone. + */ +int Scene::checkForZones(const Common::Point &pt, int zoneType) { + int matches = 0; + + for (uint idx = 0; idx < _bgShapes.size(); ++idx) { + Object &o = _bgShapes[idx]; + if ((o._aType == zoneType && o._type != INVALID) && o._type != HIDDEN) { + Common::Rect r = o._type == NO_SHAPE ? o.getNoShapeBounds() : o.getNewBounds(); + + if (r.contains(pt)) { + ++matches; + o.setFlagsAndToggles(); + _vm->_talk->talkTo(o._use[0]._target); + } + } + } + + return matches; +} } // End of namespace Sherlock diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h index 785ed63106..1a9fe7b02c 100644 --- a/engines/sherlock/scene.h +++ b/engines/sherlock/scene.h @@ -177,6 +177,8 @@ public: void clearInfo(); int findBgShape(const Common::Rect &r); + + int checkForZones(const Common::Point &pt, int zoneType); }; } // End of namespace Sherlock diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index eea40f33a6..a9de32972f 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -138,8 +138,6 @@ void SherlockEngine::sceneLoop() { * Handle all player input */ void SherlockEngine::handleInput() { - bool personFound; - _events->pollEventsAndWait(); // See if a key or mouse button is pressed diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index 4c10b7b7ef..ff71d37a2f 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -34,6 +34,10 @@ void Talk::talkTo(const Common::String &name) { // TODO } +void Talk::talk(int objNum) { + // TODO +} + /** * Clear loaded talk data */ diff --git a/engines/sherlock/talk.h b/engines/sherlock/talk.h index fc73994cc6..9359b77e87 100644 --- a/engines/sherlock/talk.h +++ b/engines/sherlock/talk.h @@ -51,6 +51,8 @@ public: void talkTo(const Common::String &name); + void talk(int objNum); + void freeTalkVars(); }; diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index d80aaecb54..5ed5494c5e 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -72,6 +72,8 @@ UserInterface::UserInterface(SherlockEngine *vm) : _vm(vm) { _windowOpen = false; _oldLook = false; _keyboardInput = false; + _invMode = 0; + _pause = false; _controls = nullptr; // new ImageFile("menu.all"); } @@ -82,8 +84,10 @@ UserInterface::~UserInterface() { void UserInterface::handleInput() { Events &events = *_vm->_events; + People &people = *_vm->_people; Scene &scene = *_vm->_scene; Screen &screen = *_vm->_screen; + Talk &talk = *_vm->_talk; if (_menuCounter) whileMenuCounter(); @@ -190,7 +194,146 @@ void UserInterface::handleInput() { } } - // TODO + // Reset the old bgshape number if the mouse button is released, so that + // it can e re-highlighted when we come back here + if ((events._rightReleased && _helpStyle) || (events._released && !_helpStyle)) + _oldBgFound = -1; + + // Do routines that should be done before input processing + switch (_menuMode) { + case LOOK_MODE: + if (!_windowOpen) { + if (events._released && _bgFound >= 0 && _bgFound < 1000) { + if (!scene._bgShapes[_bgFound]._examine.empty()) + examine(); + } else { + lookScreen(pt); + } + } + break; + + case MOVE_MODE: + case OPEN_MODE: + case CLOSE_MODE: + case PICKUP_MODE: + lookScreen(pt); + break; + + case TALK_MODE: + if (!_windowOpen) { + bool personFound; + + if (_bgFound >= 1000) { + personFound = false; + if (!events._released) + lookScreen(pt); + } else { + personFound = scene._bgShapes[_bgFound]._aType == PERSON && _bgFound != -1; + } + + if (events._released && personFound) + talk.talk(_bgFound); + else if (personFound) + lookScreen(pt); + else if (_bgFound < 1000) + clearInfo(); + } + break; + + case USE_MODE: + case GIVE_MODE: + case INV_MODE: + if (_invMode == 1 || _invMode == 2 || _invMode == 3) { + if (pt.y < CONTROLS_Y) + lookInv(); + else + lookScreen(pt); + } + break; + + default: + break; + } + + // + // Do input processing + // + if (events._pressed || events._released || events._rightPressed || + _keycode != Common::KEYCODE_INVALID || _pause) { + if (((events._released && (_helpStyle || _help == -1)) || (events._rightReleased && !_helpStyle)) && + (pt.y <= CONTROLS_Y) && (_menuMode == STD_MODE)) { + // The mouse was clicked in the playing area with no action buttons down. + // Check if the mouse was clicked in a script zone. If it was, + // then execute the script. Otherwise, walk to the given position + if (scene.checkForZones(pt, SCRIPT_ZONE) != 0) { + // Mouse clicked in script zone + events._pressed = events._released = false; + } else { + people._walkDest = pt; + people._allowWalkAbort = false; + people.goAllTheWay(); + } + + if (_oldKey != -1) { + restoreButton(_oldTemp); + _oldKey = -1; + } + } + + // Handle action depending on selected mode + switch (_menuMode) { + case LOOK_MODE: + if (_windowOpen) + doLookControl(); + break; + + case MOVE_MODE: + doMiscControl(ALLOW_MOVEMENT); + break; + + case TALK_MODE: + if (_windowOpen) + doTalkControl(); + break; + + case OPEN_MODE: + doMiscControl(ALLOW_OPEN); + break; + + case CLOSE_MODE: + doMiscControl(ALLOW_CLOSE); + break; + + case PICKUP_MODE: + doPickControl(); + break; + + case USE_MODE: + case GIVE_MODE: + case INV_MODE: + doInvControl(); + break; + + case FILES_MODE: + doEnvControl(); + break; + + default: + break; + } + + // As long as there isn't an open window, do main input processing. + // Windows are opened when in TALK, USE, INV, and GIVE modes + if ((!_windowOpen && !_menuCounter && pt.y > CONTROLS_Y) || + _keycode != Common::KEYCODE_INVALID) { + if (events._pressed || events._released || _pause || + _keycode != Common::KEYCODE_INVALID) + doMainControl(); + } + + if (pt.y < CONTROLS_Y && events._pressed && _oldTemp != (_menuMode - 1) && _oldKey != -1) + restoreButton(_oldTemp); + } } /** @@ -303,4 +446,44 @@ void UserInterface::whileMenuCounter() { } } +void UserInterface::examine() { + // TODO +} + +void UserInterface::lookScreen(const Common::Point &pt) { + // TODO +} + +void UserInterface::lookInv() { + // TODO +} + +void UserInterface::doEnvControl() { + // TODO +} + +void UserInterface::doInvControl() { + // TODO +} + +void UserInterface::doLookControl() { + // TODO +} + +void UserInterface::doMainControl() { + // TODO +} + +void UserInterface::doMiscControl(int allowed) { + // TODO +} + +void UserInterface::doPickControl() { + // TODO +} + +void UserInterface::doTalkControl() { + // TODO +} + } // End of namespace Sherlock diff --git a/engines/sherlock/user_interface.h b/engines/sherlock/user_interface.h index 4a98a5be89..d312ff919c 100644 --- a/engines/sherlock/user_interface.h +++ b/engines/sherlock/user_interface.h @@ -62,6 +62,8 @@ private: ImageFile *_controls; int _oldLook; bool _keyboardInput; + int _invMode; + bool _pause; private: void depressButton(int num); @@ -70,6 +72,20 @@ private: void pushButton(int num); void toggleButton(int num); + + void examine(); + + void lookScreen(const Common::Point &pt); + + void lookInv(); + + void doEnvControl(); + void doInvControl(); + void doLookControl(); + void doMainControl(); + void doMiscControl(int allowed); + void doPickControl(); + void doTalkControl(); public: MenuMode _menuMode; int _menuCounter; -- cgit v1.2.3 From d44a9e3f5a390837ce88b95d6afa2e7a5ee9e26e Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 23 Mar 2015 22:27:07 -0400 Subject: SHERLOCK: Fix loading of user interface controls --- engines/sherlock/resources.cpp | 10 ++++++---- engines/sherlock/user_interface.cpp | 9 ++++++--- 2 files changed, 12 insertions(+), 7 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/resources.cpp b/engines/sherlock/resources.cpp index 878747a63c..1bedbe9b7b 100644 --- a/engines/sherlock/resources.cpp +++ b/engines/sherlock/resources.cpp @@ -300,7 +300,7 @@ void ImageFile::load(Common::SeekableReadStream &stream, bool skipPalette) { frame._paletteBase = stream.readByte(); frame._offset.x = stream.readUint16LE(); frame._offset.y = stream.readByte(); - + frame._rleEncoded = !skipPalette && (frame._offset.x & 0xff) == 1; if (frame._paletteBase) { @@ -332,16 +332,18 @@ void ImageFile::loadPalette(Common::SeekableReadStream &stream) { // Check for palette int v1 = stream.readUint16LE() + 1; int v2 = stream.readUint16LE() + 1; + stream.skip(1); // Skip paletteBase byte + bool rleEncoded = stream.readByte() == 1; int size = v1 * v2; - if ((size - 12) == PALETTE_SIZE) { + if ((size - 12) == PALETTE_SIZE && !rleEncoded) { // Found palette, so read it in - stream.seek(4 + 12, SEEK_CUR); + stream.seek(2 + 12, SEEK_CUR); for (int idx = 0; idx < PALETTE_SIZE; ++idx) _palette[idx] = VGA_COLOR_TRANS(stream.readByte()); } else { // Not a palette, so rewind to start of frame data for normal frame processing - stream.seek(-4, SEEK_CUR); + stream.seek(-6, SEEK_CUR); } } diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index 5ed5494c5e..1cd5b80980 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -75,13 +75,16 @@ UserInterface::UserInterface(SherlockEngine *vm) : _vm(vm) { _invMode = 0; _pause = false; - _controls = nullptr; // new ImageFile("menu.all"); + _controls = new ImageFile("menu.all"); } UserInterface::~UserInterface() { delete _controls; } +/** + * Main input handler for the user interface + */ void UserInterface::handleInput() { Events &events = *_vm->_events; People &people = *_vm->_people; @@ -355,12 +358,12 @@ void UserInterface::depressButton(int num) { void UserInterface::restoreButton(int num) { Screen &screen = *_vm->_screen; Common::Point pt(MENU_POINTS[num][0], MENU_POINTS[num][1]); + Graphics::Surface &frame = (*_controls)[num]._frame; screen._backBuffer.blitFrom(screen._backBuffer2, pt, Common::Rect(pt.x, pt.y, pt.x + 90, pt.y + 19)); screen._backBuffer.blitFrom(screen._backBuffer, pt, - Common::Rect(pt.x, pt.y, pt.x + (*_controls)[num]._frame.w, - (*_controls)[num]._frame.h)); + Common::Rect(pt.x, pt.y, pt.x + frame.w, pt.y + frame.h)); if (!_menuCounter) { _infoFlag++; -- cgit v1.2.3 From f2ee94c0ab646d3efe93e0c782494f5888d7cc36 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 24 Mar 2015 08:35:08 -0400 Subject: SHERLOCK: Implement font drawing --- engines/sherlock/graphics.cpp | 8 +++ engines/sherlock/graphics.h | 3 ++ engines/sherlock/resources.cpp | 5 +- engines/sherlock/screen.cpp | 105 ++++++++++++++++++++++++++++++++---- engines/sherlock/screen.h | 9 ++++ engines/sherlock/user_interface.cpp | 2 +- 6 files changed, 118 insertions(+), 14 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/graphics.cpp b/engines/sherlock/graphics.cpp index 63988a2f30..1a0144bc4b 100644 --- a/engines/sherlock/graphics.cpp +++ b/engines/sherlock/graphics.cpp @@ -90,6 +90,14 @@ void Surface::blitFrom(const Graphics::Surface &src, const Common::Point &pt, copyRectToSurface(src, pt.x, pt.y, srcBounds); } +/** +* Draws an image frame at a given position within this surface with transparency +*/ +void Surface::transBlitFrom(const ImageFrame &src, const Common::Point &pt, + bool flipped, int overrideColor) { + transBlitFrom(src._frame, pt + src._offset, flipped, overrideColor); +} + /** * Draws a surface at a given position within this surface with transparency */ diff --git a/engines/sherlock/graphics.h b/engines/sherlock/graphics.h index b33495a2b9..c380d805b2 100644 --- a/engines/sherlock/graphics.h +++ b/engines/sherlock/graphics.h @@ -25,6 +25,7 @@ #include "common/rect.h" #include "graphics/surface.h" +#include "sherlock/resources.h" namespace Sherlock { @@ -43,6 +44,8 @@ public: void blitFrom(const Graphics::Surface &src, const Common::Point &pt); void blitFrom(const Graphics::Surface &src, const Common::Point &pt, const Common::Rect &srcBounds); + void transBlitFrom(const ImageFrame &src, const Common::Point &pt, + bool flipped = false, int overrideColor = 0); void transBlitFrom(const Graphics::Surface &src, const Common::Point &pt, bool flipped = false, int overrideColor = 0); diff --git a/engines/sherlock/resources.cpp b/engines/sherlock/resources.cpp index 1bedbe9b7b..0d66646286 100644 --- a/engines/sherlock/resources.cpp +++ b/engines/sherlock/resources.cpp @@ -298,10 +298,11 @@ void ImageFile::load(Common::SeekableReadStream &stream, bool skipPalette) { frame._width = stream.readUint16LE() + 1; frame._height = stream.readUint16LE() + 1; frame._paletteBase = stream.readByte(); - frame._offset.x = stream.readUint16LE(); + frame._rleEncoded = stream.readByte() == 1; + frame._offset.x = stream.readByte(); frame._offset.y = stream.readByte(); - frame._rleEncoded = !skipPalette && (frame._offset.x & 0xff) == 1; + frame._rleEncoded = !skipPalette && frame._rleEncoded; if (frame._paletteBase) { // Nibble packed frame data diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp index f8f1d56e67..b1ad280b39 100644 --- a/engines/sherlock/screen.cpp +++ b/engines/sherlock/screen.cpp @@ -23,6 +23,7 @@ #include "sherlock/screen.h" #include "sherlock/sherlock.h" #include "common/system.h" +#include "common/util.h" #include "graphics/palette.h" namespace Sherlock { @@ -32,19 +33,29 @@ Screen::Screen(SherlockEngine *vm) : Surface(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCR _backBuffer2(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT) { _transitionSeed = 1; _fadeStyle = false; + _font = nullptr; + _fontHeight = 0; Common::fill(&_cMap[0], &_cMap[PALETTE_SIZE], 0); Common::fill(&_sMap[0], &_sMap[PALETTE_SIZE], 0); setFont(1); } +Screen::~Screen() { + delete _font; +} + void Screen::setFont(int fontNumber) { _fontNumber = fontNumber; Common::String fname = Common::String::format("FONT%d.VGS", fontNumber); - Common::SeekableReadStream *stream = _vm->_res->load(fname); - debug("TODO: Loading font %s, size - %d", fname.c_str(), stream->size()); + // Discard any previous font and read in new one + delete _font; + _font = new ImageFile(fname); - delete stream; + // Iterate through the frames to find the tallest font character + _fontHeight = 0; + for (uint idx = 0; idx < _font->size(); ++idx) + _fontHeight = MAX((uint16)_fontHeight, (*_font)[idx]._frame.h); } void Screen::update() { @@ -231,14 +242,6 @@ void Screen::verticalTransition() { } } -/** - * Prints the text passed onto the back buffer at the given position and color. - * The string is then blitted to the screen - */ -void Screen::print(const Common::Point &pt, int fgColor, int bgColor, const char *format, ...) { - // TODO -} - /** * Copies a section of the second back buffer into the main back buffer */ @@ -294,4 +297,84 @@ void Screen::flushImage(ImageFrame *frame, const Common::Point &pt, *h = newBounds.height(); } +/** + * Prints the text passed onto the back buffer at the given position and color. + * The string is then blitted to the screen + */ +void Screen::print(const Common::Point &pt, int fgColor, int bgColor, const char *format, ...) { + // Create the string to display + char buffer[100]; + va_list args; + + va_start(args, format); + vsprintf(buffer, format, args); + va_end(args); + Common::String str(buffer); + + // Figure out area to draw text in + Common::Point pos = pt; + int width = stringWidth(str); + pos.y--; // Font is always drawing one line higher + if (!pos.x) + // Center text horizontally + pos.x = (SHERLOCK_SCREEN_WIDTH - width) / 2; + + Common::Rect textBounds(pos.x, pos.y, pos.x + width, pos.y + _fontHeight); + if (textBounds.right > SHERLOCK_SCREEN_WIDTH) + textBounds.moveTo(SHERLOCK_SCREEN_WIDTH - width, textBounds.top); + if (textBounds.bottom > SHERLOCK_SCREEN_HEIGHT) + textBounds.moveTo(textBounds.left, SHERLOCK_SCREEN_HEIGHT - _fontHeight); + + // Write out the string at the given position + writeString(str, Common::Point(textBounds.left, textBounds.top), fgColor); + + // Copy the affected area to the screen + slamRect(textBounds); +} + +/** + * Returns the width of a string in pixels + */ +int Screen::stringWidth(const Common::String &str) { + int width = 0; + + for (const char *c = str.c_str(); *c; ++c) + width += charWidth(*c); + + return width; +} + +/** + * Returns the width of a character in pixels + */ +int Screen::charWidth(char c) { + if (c == ' ') + return 5; + else if (c > ' ' && c <= '~') + return (*_font)[c - 33]._frame.w + 1; + else + return 0; +} + +/** + * Draws the given string into the back buffer using the images stored in _font + */ +void Screen::writeString(const Common::String &str, const Common::Point &pt, int color) { + Common::Point charPos = pt; + + for (const char *c = str.c_str(); *c; ++c) { + if (*c == ' ') + charPos.x += 5; + else { + assert(*c > ' ' && *c <= '~'); + ImageFrame &frame = (*_font)[*c - 33]; + _backBuffer.transBlitFrom(frame, charPos, false, color); + charPos.x += frame._frame.w + 1; + } + } + + addDirtyRect(Common::Rect(pt.x, pt.y, charPos.x, pt.y + _fontHeight)); +} + + } // End of namespace Sherlock diff --git a/engines/sherlock/screen.h b/engines/sherlock/screen.h index 419ae681c2..257eb916b9 100644 --- a/engines/sherlock/screen.h +++ b/engines/sherlock/screen.h @@ -48,10 +48,14 @@ private: int _fontNumber; Common::List _dirtyRects; uint32 _transitionSeed; + ImageFile *_font; + int _fontHeight; void mergeDirtyRects(); bool unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2); + + void writeString(const Common::String &str, const Common::Point &pt, int color); protected: virtual void addDirtyRect(const Common::Rect &r); public: @@ -61,6 +65,7 @@ public: byte _sMap[PALETTE_SIZE]; public: Screen(SherlockEngine *vm); + ~Screen(); void setFont(int fontNumber); @@ -89,6 +94,10 @@ public: void flushImage(ImageFrame *frame, const Common::Point &pt, int16 *xp, int16 *yp, int16 *w, int16 *h); + + int stringWidth(const Common::String &str); + + int charWidth(char c); }; } // End of namespace Sherlock diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index 1cd5b80980..1f201c74b8 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -431,7 +431,7 @@ void UserInterface::toggleButton(int num) { */ void UserInterface::clearInfo() { if (_infoFlag) { - _vm->_screen->fillRect(16, INFO_LINE, SHERLOCK_SCREEN_WIDTH - 200, INFO_LINE + 9, + _vm->_screen->fillRect(16, INFO_LINE, SHERLOCK_SCREEN_WIDTH - 20, INFO_LINE + 9, INFO_BLACK); _infoFlag = false; _oldLook = -1; -- cgit v1.2.3 From 97e58fb0171af885019d997493db33fab9af0091 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 24 Mar 2015 20:14:13 -0400 Subject: SHERLOCK: Fix display of scene hotspots --- engines/sherlock/screen.cpp | 11 ++++++++--- engines/sherlock/screen.h | 2 ++ engines/sherlock/user_interface.cpp | 7 ++++--- 3 files changed, 14 insertions(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp index b1ad280b39..e0eab428a8 100644 --- a/engines/sherlock/screen.cpp +++ b/engines/sherlock/screen.cpp @@ -46,7 +46,7 @@ Screen::~Screen() { void Screen::setFont(int fontNumber) { _fontNumber = fontNumber; - Common::String fname = Common::String::format("FONT%d.VGS", fontNumber); + Common::String fname = Common::String::format("FONT%d.VGS", fontNumber + 1); // Discard any previous font and read in new one delete _font; @@ -372,9 +372,14 @@ void Screen::writeString(const Common::String &str, const Common::Point &pt, int charPos.x += frame._frame.w + 1; } } - - addDirtyRect(Common::Rect(pt.x, pt.y, charPos.x, pt.y + _fontHeight)); } +/** + * Fills an area on the back buffer, and then copies it to the screen + */ +void Screen::bar(const Common::Rect &r, int color) { + _backBuffer.fillRect(r, color); + slamRect(r); +} } // End of namespace Sherlock diff --git a/engines/sherlock/screen.h b/engines/sherlock/screen.h index 257eb916b9..239067b1cc 100644 --- a/engines/sherlock/screen.h +++ b/engines/sherlock/screen.h @@ -98,6 +98,8 @@ public: int stringWidth(const Common::String &str); int charWidth(char c); + + void bar(const Common::Rect &r, int color); }; } // End of namespace Sherlock diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index 1f201c74b8..661604e4bf 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -268,7 +268,8 @@ void UserInterface::handleInput() { // The mouse was clicked in the playing area with no action buttons down. // Check if the mouse was clicked in a script zone. If it was, // then execute the script. Otherwise, walk to the given position - if (scene.checkForZones(pt, SCRIPT_ZONE) != 0) { + if (scene.checkForZones(pt, SCRIPT_ZONE) != 0 || + scene.checkForZones(pt, NOWALK_ZONE) != 0) { // Mouse clicked in script zone events._pressed = events._released = false; } else { @@ -431,8 +432,8 @@ void UserInterface::toggleButton(int num) { */ void UserInterface::clearInfo() { if (_infoFlag) { - _vm->_screen->fillRect(16, INFO_LINE, SHERLOCK_SCREEN_WIDTH - 20, INFO_LINE + 9, - INFO_BLACK); + _vm->_screen->bar(Common::Rect(16, INFO_LINE, SHERLOCK_SCREEN_WIDTH - 20, + INFO_LINE + 9), INFO_BLACK); _infoFlag = false; _oldLook = -1; } -- cgit v1.2.3 From 03a969bd0f696f9a7fa0dc56c47c2b05d28a5a47 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 24 Mar 2015 22:24:45 -0400 Subject: SHERLOCK: Implementing walk code --- engines/sherlock/people.cpp | 127 ++++++++++++++++++++++++++++++++++-- engines/sherlock/people.h | 1 + engines/sherlock/scene.cpp | 56 ++++++++++++---- engines/sherlock/scene.h | 6 +- engines/sherlock/sherlock.cpp | 3 + engines/sherlock/user_interface.cpp | 6 ++ engines/sherlock/user_interface.h | 2 + 7 files changed, 185 insertions(+), 16 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp index 8a8dcb5245..ca840bb5b1 100644 --- a/engines/sherlock/people.cpp +++ b/engines/sherlock/people.cpp @@ -58,6 +58,7 @@ People::People(SherlockEngine *vm) : _vm(vm), _player(_data[0]) { _allowWalkAbort = false; _portraitLoaded = false; _clearingThePortrait = false; + _srcZone = _destZone = 0; } People::~People() { @@ -143,7 +144,7 @@ void People::setWalking() { // If the player is already close to the given destination that no // walking is needed, move to the next straight line segment in the // overall walking route, if there is one - for (;;) { + do { // Since we want the player to be centered on the destination they // clicked, but characters draw positions start at their left, move // the destination half the character width to draw him centered @@ -306,13 +307,131 @@ void People::gotoStand(Sprite &sprite) { _allowWalkAbort = true; } +/** + * Walk to the co-ordinates passed, and then face the given direction + */ void People::walkToCoords(const Common::Point &destPos, int destDir) { - // TODO - warning("TODO: walkToCoords"); + Events &events = *_vm->_events; + Scene &scene = *_vm->_scene; + Talk &talk = *_vm->_talk; + + CursorId oldCursor = events.getCursor(); + events.setCursor(WAIT); + + _walkDest = Common::Point(destPos.x / 100 + 10, destPos.y / 100); + _allowWalkAbort = true; + goAllTheWay(); + + // Keep calling doBgAnim until the walk is done + do { + events.pollEventsAndWait(); + scene.doBgAnim(); + } while (!_vm->shouldQuit() && _player._walkCount); + + if (!talk._talkToAbort) { + // Put player exactly on destination position, and set direction + _player._position = destPos; + _player._sequenceNumber = destDir; + gotoStand(_player); + + // Draw Holmes facing the new direction + scene.doBgAnim(); + + if (!talk._talkToAbort) + events.setCursor(oldCursor); + } } +/** + * Called to set the character walking to the current cursor location. + * It uses the zones and the inter-zone points to determine a series + * of steps to walk to get to that position. + */ void People::goAllTheWay() { - // TODO + Scene &scene = *_vm->_scene; + Common::Point srcPt(_player._position.x / 100 + _player.frameWidth() / 2, + _player._position.y / 100); + + // Get the zone the player is currently in + _srcZone = scene.whichZone(srcPt); + if (_srcZone == -1) + _srcZone = scene.closestZone(srcPt); + + // Get the zone of the destination + _destZone = scene.whichZone(_walkDest); + if (_destZone == -1) { + _destZone = scene.closestZone(_walkDest); + + // The destination isn't in a zone + if (_walkDest.x >= (SHERLOCK_SCREEN_WIDTH - 1)) + _walkDest.x = SHERLOCK_SCREEN_WIDTH - 2; + + // Trace a line between the centroid of the found closest zone to + // the destination, to find the point at which the zone will be left + const Common::Rect &destRect = scene._zones[_destZone]; + const Common::Point destCenter((destRect.left + destRect.right) / 2, + (destRect.top + destRect.bottom) / 2); + const Common::Point delta = _walkDest - destCenter; + Common::Point pt(destCenter.x * 100, destCenter.y * 100); + + // Move along the line until the zone is left + do { + pt += delta; + } while (destRect.contains(pt.x / 100, pt.y / 100)); + + // Set the new walk destination to the last point that was in the + // zone just before it was left + _walkDest = Common::Point((pt.x - delta.x * 2) / 100, + (pt.y - delta.y * 2) / 100); + } + + // Only do a walk if both zones are acceptable + if (_srcZone == -2 || _destZone == -2) + return; + + // If the start and dest zones are the same, walk directly to the dest point + if (_srcZone == _destZone) { + setWalking(); + } else { + // Otherwise a path needs to be formed from the path information + int i = scene._walkDirectory[_srcZone][_destZone]; + + // See if we need to use a reverse path + if (i == -1) + i = scene._walkDirectory[_destZone][_srcZone]; + + int count = scene._walkData[i]; + ++i; + + // See how many points there are between the src and dest zones + if (!count || count == 255) { + // There are none, so just walk to the new zone + setWalking(); + } else { + // There are points, so set up a multi-step path between points + // to reach the given destination + _walkTo.clear(); + + if (scene._walkDirectory[_srcZone][_destZone] != -1) { + for (int idx = 0; idx < count; ++idx, i += 3) { + _walkTo.push(Common::Point(READ_LE_UINT16(&scene._walkData[i]), + scene._walkData[i + 2])); + } + } else { + for (int idx = 0; idx < count; ++idx) + _walkTo.push(Common::Point()); + + for (int idx = count - 1; idx >= 0; --idx, i += 3) { + _walkTo[idx].x = READ_LE_UINT16(&scene._walkData[i]); + _walkTo[idx].y = scene._walkData[i + 2]; + } + } + + // Start walking + _walkDest = _walkTo.top(); + setWalking(); + } + } } } // End of namespace Sherlock diff --git a/engines/sherlock/people.h b/engines/sherlock/people.h index 8d1953ee20..0393528095 100644 --- a/engines/sherlock/people.h +++ b/engines/sherlock/people.h @@ -59,6 +59,7 @@ private: Sprite &_player; bool _walkLoaded; int _oldWalkSequence; + int _srcZone, _destZone; public: Common::Point _walkDest; Common::Stack _walkTo; diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 95e8355957..c5cba1b5cd 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -176,7 +176,7 @@ void Scene::freeScene() { _walkData.clear(); _cAnim.clear(); _bgShapes.clear(); - _bounds.clear(); + _zones.clear(); _canimShapes.clear(); for (uint idx = 0; idx < _images.size(); ++idx) @@ -205,8 +205,8 @@ bool Scene::loadScene(const Common::String &filename) { _ongoingCans = 0; // Reset the list of walkable areas - _bounds.clear(); - _bounds.push_back(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); + _zones.clear(); + _zones.push_back(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); _descText.clear(); _comments = ""; @@ -311,12 +311,12 @@ bool Scene::loadScene(const Common::String &filename) { Common::SeekableReadStream *boundsStream = !_lzwMode ? rrmStream : decompressLZ(*rrmStream, size); - _bounds.resize(size / 10); - for (uint idx = 0; idx < _bounds.size(); ++idx) { - _bounds[idx].left = boundsStream->readSint16LE(); - _bounds[idx].top = boundsStream->readSint16LE(); - _bounds[idx].setWidth(boundsStream->readSint16LE()); - _bounds[idx].setHeight(boundsStream->readSint16LE()); + _zones.resize(size / 10); + for (uint idx = 0; idx < _zones.size(); ++idx) { + _zones[idx].left = boundsStream->readSint16LE(); + _zones[idx].top = boundsStream->readSint16LE(); + _zones[idx].setWidth(boundsStream->readSint16LE()); + _zones[idx].setHeight(boundsStream->readSint16LE()); boundsStream->skip(2); // Skip unused scene number field } @@ -328,8 +328,8 @@ bool Scene::loadScene(const Common::String &filename) { error("Invalid scene path data"); // Load the walk directory - for (uint idx1 = 0; idx1 < _bounds.size(); ++idx1) { - for (uint idx2 = 0; idx2 < _bounds.size(); ++idx2) + for (uint idx1 = 0; idx1 < _zones.size(); ++idx1) { + for (uint idx2 = 0; idx2 < _zones.size(); ++idx2) _walkDirectory[idx1][idx2] = rrmStream->readSint16LE(); } @@ -1450,4 +1450,38 @@ int Scene::checkForZones(const Common::Point &pt, int zoneType) { return matches; } +/** + * Check which zone the the given position is located in. + */ +int Scene::whichZone(const Common::Point &pt) { + for (uint idx = 0; idx < _zones.size(); ++idx) { + if (_zones[idx].contains(pt)) + return idx; + } + + return -1; +} + +/** + * Returns the index of the closest zone to a given point. + */ +int Scene::closestZone(const Common::Point &pt) { + int dist = 1000; + int zone = -1; + + for (uint idx = 0; idx < _zones.size(); ++idx) { + Common::Point zc((_zones[idx].left + _zones[idx].right) / 2, + (_zones[idx].top + _zones[idx].bottom) / 2); + int d = ABS(zc.x - pt.x) + ABS(zc.y - pt.y); + + if (d < dist) { + // Found a closer zone + dist = d; + zone = idx; + } + } + + return zone; +} + } // End of namespace Sherlock diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h index 1a9fe7b02c..1b3a730179 100644 --- a/engines/sherlock/scene.h +++ b/engines/sherlock/scene.h @@ -137,7 +137,7 @@ public: int _invGraphicItems; Common::String _comments; Common::Array _descText; - Common::Array _bounds; + Common::Array _zones; Common::Array _bgShapes; Common::Array _cAnim; Common::Array _sequenceBuffer; @@ -179,6 +179,10 @@ public: int findBgShape(const Common::Rect &r); int checkForZones(const Common::Point &pt, int zoneType); + + int whichZone(const Common::Point &pt); + + int closestZone(const Common::Point &pt); }; } // End of namespace Sherlock diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index a9de32972f..107dee5a41 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -100,6 +100,9 @@ Common::Error SherlockEngine::run() { if (shouldQuit()) break; + // Reset UI flags + _ui->reset(); + // Reset the active characters to initially just Sherlock _people->reset(); diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index 661604e4bf..fc94cc5a5c 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -82,6 +82,12 @@ UserInterface::~UserInterface() { delete _controls; } +void UserInterface::reset() { + _oldKey = -1; + _help = _oldHelp = -1; + _oldTemp = _temp = -1; +} + /** * Main input handler for the user interface */ diff --git a/engines/sherlock/user_interface.h b/engines/sherlock/user_interface.h index d312ff919c..d2ef8942c3 100644 --- a/engines/sherlock/user_interface.h +++ b/engines/sherlock/user_interface.h @@ -95,6 +95,8 @@ public: UserInterface(SherlockEngine *vm); ~UserInterface(); + void reset(); + void handleInput(); void clearInfo(); -- cgit v1.2.3 From fc7f8024beb4e3a0ee2b6def649ca1a3e91fa899 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 25 Mar 2015 08:16:59 -0400 Subject: SHERLOCK: Fixes to scene loading --- engines/sherlock/objects.cpp | 8 ++++---- engines/sherlock/scene.cpp | 8 +++++++- engines/sherlock/screen.cpp | 20 ++++++++++++-------- 3 files changed, 23 insertions(+), 13 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index e0a24c5b7d..cdd397f23c 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -381,10 +381,10 @@ void UseType::synchronize(Common::SeekableReadStream &s) { _names[idx] = Common::String(buffer); } - _useFlag = s.readUint16LE(); - _dFlag[0] = s.readUint16LE(); - _lFlag[0] = s.readUint16LE(); - _lFlag[1] = s.readUint16LE(); + _useFlag = s.readSint16LE(); + _dFlag[0] = s.readSint16LE(); + _lFlag[0] = s.readSint16LE(); + _lFlag[1] = s.readSint16LE(); s.read(buffer, 12); _target = Common::String(buffer); diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index c5cba1b5cd..1b7a1a9cd2 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -601,7 +601,13 @@ void Scene::transitionToScene() { } else { // It's canimation information cAnimNum = _hsavedFs - 101; + } + + // Reset positioning for next load + _hsavedPos = Common::Point(-1, -1); + _hsavedFs = -1; + if (cAnimNum != -1) { // Prevent Holmes from being drawn people[PLAYER]._position = Common::Point(0, 0); } @@ -1166,7 +1172,7 @@ void Scene::doBgAnim() { else if (people[AL]._type == REMOVE) screen._backBuffer.blitFrom(screen._backBuffer2, pt, bounds); - for (uint idx = 0; _bgShapes.size(); ++idx) { + for (uint idx = 0; idx < _bgShapes.size(); ++idx) { Object &o = _bgShapes[idx]; if (o._type == ACTIVE_BG_SHAPE || o._type == HIDE_SHAPE || o._type == REMOVE) screen.restoreBackground(bounds); diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp index e0eab428a8..7c222f3e24 100644 --- a/engines/sherlock/screen.cpp +++ b/engines/sherlock/screen.cpp @@ -246,11 +246,13 @@ void Screen::verticalTransition() { * Copies a section of the second back buffer into the main back buffer */ void Screen::restoreBackground(const Common::Rect &r) { - Common::Rect tempRect = r; - tempRect.clip(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT)); + if (r.width() > 0 && r.height() > 0) { + Common::Rect tempRect = r; + tempRect.clip(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT)); - if (tempRect.isValidRect()) - _backBuffer.blitFrom(_backBuffer2, Common::Point(tempRect.left, tempRect.top), tempRect); + if (tempRect.isValidRect()) + _backBuffer.blitFrom(_backBuffer2, Common::Point(tempRect.left, tempRect.top), tempRect); + } } /** @@ -264,11 +266,13 @@ void Screen::slamArea(int16 xp, int16 yp, int16 w, int16 h) { * Copies a given area to the screen */ void Screen::slamRect(const Common::Rect &r) { - Common::Rect tempRect = r; - tempRect.clip(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); + if (r.width() && r.height() > 0) { + Common::Rect tempRect = r; + tempRect.clip(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); - if (tempRect.isValidRect()) - blitFrom(_backBuffer, Common::Point(tempRect.left, tempRect.top), tempRect); + if (tempRect.isValidRect()) + blitFrom(_backBuffer, Common::Point(tempRect.left, tempRect.top), tempRect); + } } /** -- cgit v1.2.3 From b280d72ab8de6f6fe77d0957de1b651b9fdb264c Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 25 Mar 2015 22:23:53 -0400 Subject: SHERLOCK: Sprite positioning fixes --- engines/sherlock/objects.cpp | 2 +- engines/sherlock/scene.cpp | 5 ++++- engines/sherlock/screen.cpp | 8 ++++++-- engines/sherlock/user_interface.cpp | 6 +++--- 4 files changed, 14 insertions(+), 7 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index cdd397f23c..7e72eff1e9 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -613,7 +613,7 @@ void Object::checkObject(Object &o) { if (pt.y > 128) pt.y = (pt.y - 128) * -1; else - pt.y; + pt.y--; _delta = pt; _frameNumber += 2; diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 1b7a1a9cd2..b00e07a8a7 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -1330,7 +1330,8 @@ void Scene::doBgAnim() { )); } else { screen.flushImage(people[AL]._imageFrame, - Common::Point(people[AL]._position.x / 100, people[AL]._position.y / 100), + Common::Point(people[AL]._position.x / 100, + people[AL]._position.y / 100 - people[AL].frameHeight()), &people[AL]._oldPosition.x, &people[AL]._oldPosition.y, &people[AL]._oldSize.x, &people[AL]._oldSize.y); } @@ -1370,8 +1371,10 @@ void Scene::doBgAnim() { screen.slamArea(o._position.x, o._position.y, o._oldSize.x, o._oldSize.y); screen.slamArea(o._oldPosition.x, o._oldPosition.y, o._oldSize.x, o._oldSize.y); } else if (o._type == HIDE_SHAPE) { + // Hiding shape, so flush it out and mark it as hidden screen.flushImage(o._imageFrame, o._position, &o._oldPosition.x, &o._oldPosition.y, &o._oldSize.x, &o._oldSize.y); + o._type = HIDDEN; } } } diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp index 7c222f3e24..098d43e827 100644 --- a/engines/sherlock/screen.cpp +++ b/engines/sherlock/screen.cpp @@ -287,8 +287,12 @@ void Screen::flushImage(ImageFrame *frame, const Common::Point &pt, // See if the areas of the old and new overlap, and if so combine the areas if (newBounds.intersects(oldBounds)) { - newBounds.extend(oldBounds); - slamRect(newBounds); + Common::Rect mergedBounds = newBounds; + mergedBounds.extend(oldBounds); + mergedBounds.right += 1; + mergedBounds.bottom += 1; + + slamRect(mergedBounds); } else { // The two areas are independent, so copy them both slamRect(newBounds); diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index fc94cc5a5c..b0ac0b169b 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -176,7 +176,7 @@ void UserInterface::handleInput() { _help = _oldHelp; } - if (_bgFound != _oldBgFound) { + if (_bgFound != _oldBgFound || _oldBgFound == -1) { _infoFlag = true; clearInfo(); @@ -438,8 +438,8 @@ void UserInterface::toggleButton(int num) { */ void UserInterface::clearInfo() { if (_infoFlag) { - _vm->_screen->bar(Common::Rect(16, INFO_LINE, SHERLOCK_SCREEN_WIDTH - 20, - INFO_LINE + 9), INFO_BLACK); + _vm->_screen->bar(Common::Rect(16, INFO_LINE, SHERLOCK_SCREEN_WIDTH - 19, + INFO_LINE + 10), INFO_BLACK); _infoFlag = false; _oldLook = -1; } -- cgit v1.2.3 From 94d79c0ed36269fe1c7bbf08871329d166acc2f0 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 25 Mar 2015 22:41:42 -0400 Subject: SHERLOCK: Fix restoring background before drawing new sprites --- engines/sherlock/scene.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index b00e07a8a7..0cb6d7721b 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -1175,7 +1175,7 @@ void Scene::doBgAnim() { for (uint idx = 0; idx < _bgShapes.size(); ++idx) { Object &o = _bgShapes[idx]; if (o._type == ACTIVE_BG_SHAPE || o._type == HIDE_SHAPE || o._type == REMOVE) - screen.restoreBackground(bounds); + screen.restoreBackground(o.getOldBounds()); } if (people._portraitLoaded) -- cgit v1.2.3 From a8350c48e93143dd2d6344efce1b36c4e2eb34be Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 25 Mar 2015 22:56:56 -0400 Subject: SHERLOCK: Fix display of hotspot tooltips --- engines/sherlock/user_interface.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index b0ac0b169b..bcf460a821 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -173,7 +173,7 @@ void UserInterface::handleInput() { if (_help != -1) depressButton(_help); - _help = _oldHelp; + _oldHelp = _help; } if (_bgFound != _oldBgFound || _oldBgFound == -1) { @@ -185,6 +185,8 @@ void UserInterface::handleInput() { screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, INFO_BACKGROUND, "%s", scene._bgShapes[_bgFound]._description); + + _oldBgFound = _bgFound; } } else { // We're not in STD_MODE -- cgit v1.2.3 From 0f52dcc561fbe05816452d2a20b3f09f6cd9e0fa Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 25 Mar 2015 23:07:56 -0400 Subject: SHERLOCK: Highlight default action button when highlighting hotspots --- engines/sherlock/user_interface.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index bcf460a821..df3ac9352c 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -371,8 +371,7 @@ void UserInterface::restoreButton(int num) { screen._backBuffer.blitFrom(screen._backBuffer2, pt, Common::Rect(pt.x, pt.y, pt.x + 90, pt.y + 19)); - screen._backBuffer.blitFrom(screen._backBuffer, pt, - Common::Rect(pt.x, pt.y, pt.x + frame.w, pt.y + frame.h)); + screen.slamArea(pt.x, pt.y, pt.x + frame.w, pt.y + frame.h); if (!_menuCounter) { _infoFlag++; -- cgit v1.2.3 From 5e45abcca4b76955cc0ebcfa54a1b9f9be12bfa0 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 26 Mar 2015 21:40:24 -0400 Subject: SHERLOCK: Implemented printObjectDesc --- engines/sherlock/inventory.cpp | 6 +- engines/sherlock/inventory.h | 4 +- engines/sherlock/objects.cpp | 10 +- engines/sherlock/objects.h | 6 +- engines/sherlock/scene.cpp | 53 +------- engines/sherlock/scene.h | 6 +- engines/sherlock/screen.cpp | 22 +++- engines/sherlock/screen.h | 16 ++- engines/sherlock/user_interface.cpp | 252 +++++++++++++++++++++++++++++++++++- engines/sherlock/user_interface.h | 16 +++ 10 files changed, 316 insertions(+), 75 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/inventory.cpp b/engines/sherlock/inventory.cpp index 2a277a6331..e103213eb5 100644 --- a/engines/sherlock/inventory.cpp +++ b/engines/sherlock/inventory.cpp @@ -36,7 +36,7 @@ Inventory::~Inventory() { freeGraphics(); } -void Inventory::freeInventory() { +void Inventory::freeInv() { freeGraphics(); _names.clear(); @@ -116,4 +116,8 @@ int Inventory::findInv(const Common::String &name) { return result; } +void Inventory::putInv(int slamit) { + // TODO +} + } // End of namespace Sherlock diff --git a/engines/sherlock/inventory.h b/engines/sherlock/inventory.h index e561f0318a..01a325e382 100644 --- a/engines/sherlock/inventory.h +++ b/engines/sherlock/inventory.h @@ -54,13 +54,15 @@ public: Inventory(SherlockEngine *vm); ~Inventory(); - void freeInventory(); + void freeInv(); void loadInv(); void loadGraphics(); int findInv(const Common::String &name); + + void putInv(int slamit); }; } // End of namespace Sherlock diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index 7e72eff1e9..39a9cf8014 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -404,11 +404,11 @@ void Object::setVm(SherlockEngine *vm) { * Load the object data from the passed stream */ void Object::synchronize(Common::SeekableReadStream &s) { - char buffer[12]; + char buffer[41]; s.read(buffer, 12); _name = Common::String(buffer); - - s.read(_description, 41); + s.read(buffer, 41); + _description = Common::String(buffer); _examine.clear(); _sequences = nullptr; @@ -851,14 +851,14 @@ int Object::checkNameForCodes(const Common::String &name, Common::StringArray *m int messageNum = atoi(name.c_str() + 1); ui._infoFlag++; ui.clearInfo(); - screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, INFO_BACKGROUND, + screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, (*messages)[messageNum].c_str()); ui._menuCounter = 25; } else if (name.hasPrefix("@")) { // Message attached to canimation ui._infoFlag++; ui.clearInfo(); - screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, INFO_BACKGROUND, + screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "%s", name.c_str() + 1); printed = true; ui._menuCounter = 25; diff --git a/engines/sherlock/objects.h b/engines/sherlock/objects.h index 4944681ab3..26ad1d3900 100644 --- a/engines/sherlock/objects.h +++ b/engines/sherlock/objects.h @@ -123,8 +123,8 @@ public: }; struct ActionType { - char _cAnimNum; - char _cAnimSpeed; // if high bit set, play in reverse + int8 _cAnimNum; + uint8 _cAnimSpeed; // if high bit set, play in reverse Common::String _names[4]; void synchronize(Common::SeekableReadStream &s); @@ -155,7 +155,7 @@ public: static void setVm(SherlockEngine *vm); public: Common::String _name; // Name - char _description[41]; // Description lines + Common::String _description; // Description lines Common::String _examine; // Examine in-depth description int _sequenceOffset; uint8 *_sequences; // Holds animation sequences diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 0cb6d7721b..6442538794 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -162,7 +162,7 @@ void Scene::selectScene() { */ void Scene::freeScene() { _vm->_talk->freeTalkVars(); - _vm->_inventory->freeInventory(); + _vm->_inventory->freeInv(); _vm->_sound->freeSong(); _vm->_sound->freeLoadedSounds(); @@ -849,6 +849,7 @@ int Scene::startCAnim(int cAnimNum, int playRate) { People &people = *_vm->_people; Resources &res = *_vm->_res; Talk &talk = *_vm->_talk; + UserInterface &ui = *_vm->_ui; Common::Point tpPos, walkPos; int tpDir, walkDir; int tFrames = 0; @@ -993,7 +994,7 @@ int Scene::startCAnim(int cAnimNum, int playRate) { while (--frames) { if (frames == pauseFrame) - printObjDesc(_cAnimStr, true); + ui.printObjectDesc(); doBgAnim(); @@ -1048,54 +1049,6 @@ int Scene::startCAnim(int cAnimNum, int playRate) { return 1; } -/** - * Print the description of an object - */ -void Scene::printObjDesc(const Common::String &str, bool firstTime) { - /* TODO - - Events &events = *_vm->_events; - Screen &screen = *_vm->_screen; - Talk &talk = *_vm->_talk; - int savedSelector; - - if (str.hasPrefix("_")) { - _lookScriptFlag = true; - events.setCursor(MAGNIFY); - savedSelector = _selector; - talk.talkTo(str.c_str() + 1); - _lookScriptFlag = false; - - if (talk._talkToAbort) { - events.setCursor(ARROW); - return; - } - - // Check if looking at an inventory object - if (!_invLookFlag) { - // See if this look was called by a right button click or not - if (!_lookHelp) { - // If it wasn't a right button click, then we need depress - // the look button before we close the window. So save a copy of the - // menu area, and draw the controls onto it - Surface tempSurface((*_controls)[0]._frame->w, (*_controls)[0]._frame->h); - tempSurface.blitFrom(screen._backBuffer2, Common::Point(0, 0), - Common::Rect(MENU_POINTS[0][0], MENU_POINTS[0][1], - MENU_POINTS[0][0] + tempSurface.w, MENU_POINTS[0][1] + tempSurface.h)); - screen._backBuffer2.transBlitFrom((*_controls)[0]._frame, - Common::Point(MENU_POINTS[0][0], MENU_POINTS[0][1])); - - banishWindow(1); - events.setCursor(MAGNIFY); - - } - } - } - - // TODO - */ -} - /** * Animate all objects and people. */ diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h index 1b3a730179..27313e34af 100644 --- a/engines/sherlock/scene.h +++ b/engines/sherlock/scene.h @@ -96,10 +96,7 @@ class Scene { private: SherlockEngine *_vm; Common::String _rrmName; - int _cAnimFramePause; - Common::String _cAnimStr; InvMode _invMode; - bool _lookScriptFlag; int _selector; bool _invLookFlag; bool _lookHelp; @@ -154,6 +151,7 @@ public: int _animating; bool _doBgAnimDone; int _tempFadeStyle; + int _cAnimFramePause; public: Scene(SherlockEngine *vm); ~Scene(); @@ -166,8 +164,6 @@ public: Exit *checkForExit(const Common::Rect &r); - void printObjDesc(const Common::String &str, bool firstTime); - int startCAnim(int cAnimNum, int playRate); int toggleObject(const Common::String &name); diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp index 098d43e827..646802094f 100644 --- a/engines/sherlock/screen.cpp +++ b/engines/sherlock/screen.cpp @@ -309,7 +309,7 @@ void Screen::flushImage(ImageFrame *frame, const Common::Point &pt, * Prints the text passed onto the back buffer at the given position and color. * The string is then blitted to the screen */ -void Screen::print(const Common::Point &pt, int fgColor, int bgColor, const char *format, ...) { +void Screen::print(const Common::Point &pt, int color, const char *format, ...) { // Create the string to display char buffer[100]; va_list args; @@ -334,12 +334,30 @@ void Screen::print(const Common::Point &pt, int fgColor, int bgColor, const char textBounds.moveTo(textBounds.left, SHERLOCK_SCREEN_HEIGHT - _fontHeight); // Write out the string at the given position - writeString(str, Common::Point(textBounds.left, textBounds.top), fgColor); + writeString(str, Common::Point(textBounds.left, textBounds.top), color); // Copy the affected area to the screen slamRect(textBounds); } +/** + * Print a strings onto the back buffer without blitting it to the screen + */ +void Screen::gPrint(const Common::Point &pt, int color, const char *format, ...) { + // Create the string to display + char buffer[100]; + va_list args; + + va_start(args, format); + vsprintf(buffer, format, args); + va_end(args); + Common::String str(buffer); + + // Print the text + writeString(str, pt, color); +} + + /** * Returns the width of a string in pixels */ diff --git a/engines/sherlock/screen.h b/engines/sherlock/screen.h index 239067b1cc..45a50e7e85 100644 --- a/engines/sherlock/screen.h +++ b/engines/sherlock/screen.h @@ -35,10 +35,15 @@ namespace Sherlock { #define PALETTE_COUNT 256 #define VGA_COLOR_TRANS(x) ((x) * 255 / 63) -#define INFO_BLACK 1 -#define INFO_FOREGROUND 11 -#define INFO_BACKGROUND 1 - +enum { + INFO_BLACK = 1, + INFO_FOREGROUND = 11, + INFO_BACKGROUND = 1, + BORDER_COLOR = 237, + INV_FOREGROUND = 14, + INV_BACKGROUND = 1, + COM_FOREGROUND = 15 +}; class SherlockEngine; @@ -85,7 +90,8 @@ public: void verticalTransition(); - void print(const Common::Point &pt, int fgColor, int bgColor, const char *format, ...); + void print(const Common::Point &pt, int color, const char *format, ...); + void gPrint(const Common::Point &pt, int color, const char *format, ...); void restoreBackground(const Common::Rect &r); diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index df3ac9352c..b0388b4e29 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -54,6 +54,8 @@ const int INVENTORY_POINTS[8][3] = { }; const char COMMANDS[13] = "LMTPOCIUGJFS"; +const char *const PRESS_KEY_FOR_MORE = "Press any Key for More."; +const char *const PRESS_KEY_TO_CONTINUE = "Press any Key to Continue."; /*----------------------------------------------------------------*/ @@ -74,6 +76,11 @@ UserInterface::UserInterface(SherlockEngine *vm) : _vm(vm) { _keyboardInput = false; _invMode = 0; _pause = false; + _cNum = 0; + _selector = _oldSelector = -1; + _windowBounds = Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH - 1, + SHERLOCK_SCREEN_HEIGHT - 1); + _windowStyle = 0; _controls = new ImageFile("menu.all"); } @@ -183,8 +190,7 @@ void UserInterface::handleInput() { if (_help != -1 && (scene._bgShapes[_bgFound]._description[0] != 32 && scene._bgShapes[_bgFound]._description[0])) screen.print(Common::Point(0, INFO_LINE + 1), - INFO_FOREGROUND, INFO_BACKGROUND, "%s", - scene._bgShapes[_bgFound]._description); + INFO_FOREGROUND, scene._bgShapes[_bgFound]._description.c_str()); _oldBgFound = _bgFound; } @@ -457,8 +463,53 @@ void UserInterface::whileMenuCounter() { } } +/** + * Creates a text window and uses it to display the in-depth description + * of the highlighted object + */ void UserInterface::examine() { - // TODO + Events &events = *_vm->_events; + Inventory &inv = *_vm->_inventory; + People &people = *_vm->_people; + Scene &scene = *_vm->_scene; + Talk &talk = *_vm->_talk; + Common::Point pt = events.mousePos(); + int canimSpeed; + + if (pt.y < (CONTROLS_Y + 9)) { + Object &obj = scene._bgShapes[_bgFound]; + + if (obj._lookcAnim != 0) { + canimSpeed = ((obj._lookcAnim & 0xe0) >> 5) + 1; + scene._cAnimFramePause = obj._lookFrames; + _cAnimStr = obj._examine; + _cNum = (obj._lookcAnim & 0x1f) - 1; + + scene.startCAnim(_cNum, canimSpeed); + } else if (obj._lookPosition.y != 0) { + // Need to walk to the object to be examined + people.walkToCoords(obj._lookPosition, obj._lookFacing); + } + + if (talk._talkToAbort) { + _cAnimStr = obj._examine; + if (obj._lookFlag) + _vm->setFlags(obj._lookFlag); + } + } else { + // Looking at an inventory item + _cAnimStr = inv[_selector]._examine; + if (inv[_selector]._lookFlag) + _vm->setFlags(inv[_selector]._lookFlag); + } + + if (!talk._talkToAbort) { + if (!scene._cAnimFramePause) + printObjectDesc(_cAnimStr, true); + else + // description was already printed in startCAnimation + scene._cAnimFramePause = 0; + } } void UserInterface::lookScreen(const Common::Point &pt) { @@ -497,4 +548,199 @@ void UserInterface::doTalkControl() { // TODO } + +/** +* Print the description of an object +*/ +void UserInterface::printObjectDesc(const Common::String &str, bool firstTime) { + Events &events = *_vm->_events; + Inventory &inv = *_vm->_inventory; + Screen &screen = *_vm->_screen; + Talk &talk = *_vm->_talk; + int savedSelector; + + if (str.hasPrefix("_")) { + _lookScriptFlag = true; + events.setCursor(MAGNIFY); + savedSelector = _selector; + talk.talkTo(str.c_str() + 1); + _lookScriptFlag = false; + + if (talk._talkToAbort) { + events.setCursor(ARROW); + return; + } + + // Check if looking at an inventory object + if (!_invLookFlag) { + // See if this look was called by a right button click or not + if (!_lookHelp) { + // If it wasn't a right button click, then we need depress + // the look button before we close the window. So save a copy of the + // menu area, and draw the controls onto it + Surface tempSurface((*_controls)[0]._frame.w, (*_controls)[0]._frame.h); + Common::Point pt(MENU_POINTS[0][0], MENU_POINTS[0][1]); + + tempSurface.blitFrom(screen._backBuffer2, Common::Point(0, 0), + Common::Rect(pt.x, pt.y, pt.x + tempSurface.w, pt.y + tempSurface.h)); + screen._backBuffer2.transBlitFrom((*_controls)[0]._frame, pt); + + banishWindow(1); + events.setCursor(MAGNIFY); + _windowBounds.top = CONTROLS_Y1; + _key = _oldKey = COMMANDS[LOOK_MODE - 1]; + _temp = _oldTemp = 0; + _menuMode = LOOK_MODE; + events.clearEvents(); + + screen._backBuffer2.blitFrom(tempSurface, pt); + } else { + events.setCursor(ARROW); + banishWindow(true); + _windowBounds.top = CONTROLS_Y1; + _key = _oldKey = -1; + _temp = _oldTemp = 0; + _menuMode = STD_MODE; + _lookHelp = 0; + events.clearEvents(); + } + } else { + // Looking at an inventory object + _selector = _oldSelector = savedSelector; + + // Reload the inventory graphics and draw the inventory + inv.loadInv(); + inv.putInv(2); + inv.freeInv(); + banishWindow(1); + + _windowBounds.top = CONTROLS_Y1; + _key = _oldKey = COMMANDS[INV_MODE - 1]; + _temp = _oldTemp = 0; + events.clearEvents(); + + _invLookFlag = 0; + _menuMode = INV_MODE; + _windowOpen = true; + } + + return; + } + + if (firstTime) { + // Only draw the border on the first call + _infoFlag = true; + clearInfo(); + + screen.bar(Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, + CONTROLS_Y1 + 10), BORDER_COLOR); + screen.bar(Common::Rect(0, CONTROLS_Y + 10, 1, SHERLOCK_SCREEN_HEIGHT - 1), + BORDER_COLOR); + screen.bar(Common::Rect(SHERLOCK_SCREEN_WIDTH - 2, CONTROLS_Y + 10, + SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR); + screen.bar(Common::Rect(0, SHERLOCK_SCREEN_HEIGHT - 1, SHERLOCK_SCREEN_WIDTH, + SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR); + } + + // Clear background + screen.bar(Common::Rect(2, CONTROLS_Y + 10, SHERLOCK_SCREEN_WIDTH - 2, + SHERLOCK_SCREEN_HEIGHT - 2), INV_BACKGROUND); + + _windowBounds.top = CONTROLS_Y; + events.clearEvents(); + + bool endOfStr = false; + const char *msgP = str.c_str(); + for (int lineNum = 0; lineNum < 5 && !endOfStr; ++lineNum) { + int width = 0; + const char *lineStartP = msgP; + + // Determine how much can be displayed on the line + do { + width += screen.charWidth(*msgP++); + } while (width < 300 && *msgP); + + if (*msgP) + --msgP; + else + endOfStr = true; + + // If the line needs to be wrapped, scan backwards to find + // the end of the previous word as a splitting point + if (width >= 300) { + while (*msgP != ' ') + --msgP; + endOfStr = false; + } + + // Print out the line + Common::String line(lineStartP, msgP); + screen.gPrint(Common::Point(16, CONTROLS_Y + 12 + lineNum * 9), + INV_FOREGROUND, line.c_str()); + } + + // Handle display depending on whether all the message was shown + if (!endOfStr) { + makeButton(Common::Rect(46, CONTROLS_Y, 272, CONTROLS_Y + 10), + (SHERLOCK_SCREEN_WIDTH - screen.stringWidth(PRESS_KEY_FOR_MORE)) / 2, + PRESS_KEY_FOR_MORE); + screen.gPrint(Common::Point((SHERLOCK_SCREEN_WIDTH - + screen.stringWidth(PRESS_KEY_FOR_MORE)) / 2, CONTROLS_Y), + COM_FOREGROUND, "P"); + _descStr = msgP; + } else { + makeButton(Common::Rect(46, CONTROLS_Y, 272, CONTROLS_Y + 10), + (SHERLOCK_SCREEN_WIDTH - screen.stringWidth(PRESS_KEY_TO_CONTINUE)) / 2, + PRESS_KEY_FOR_MORE); + screen.gPrint(Common::Point((SHERLOCK_SCREEN_WIDTH - + screen.stringWidth(PRESS_KEY_TO_CONTINUE)) / 2, CONTROLS_Y), + COM_FOREGROUND, "P"); + _descStr = ""; + } + + if (firstTime) { + if (!_windowStyle) { + screen.slamRect(Common::Rect(0, CONTROLS_Y, + SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); + } + else { + Surface tempSurface(SHERLOCK_SCREEN_WIDTH, + (SHERLOCK_SCREEN_HEIGHT - CONTROLS_Y) + 10); + Common::Rect r(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT); + + tempSurface.blitFrom(screen._backBuffer, Common::Point(0, CONTROLS_Y), r); + screen._backBuffer.blitFrom(screen._backBuffer2, + Common::Point(0, CONTROLS_Y), r); + + summonWindow(); + } + + _selector = _oldSelector = -1; + _windowOpen = true; + } else { + screen.slamRect(Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, + SHERLOCK_SCREEN_HEIGHT)); + } +} + +/** +* Print the previously selected object's decription +*/ +void UserInterface::printObjectDesc() { + printObjectDesc(_cAnimStr, true); +} + +void UserInterface::banishWindow(bool flag) { + // TODO +} + +void UserInterface::makeButton(const Common::Rect &bounds, int textX, + const Common::String &str) { + // TODO +} + +void UserInterface::summonWindow() { + // TODO +} + } // End of namespace Sherlock diff --git a/engines/sherlock/user_interface.h b/engines/sherlock/user_interface.h index d2ef8942c3..98f6cd21ea 100644 --- a/engines/sherlock/user_interface.h +++ b/engines/sherlock/user_interface.h @@ -64,6 +64,13 @@ private: bool _keyboardInput; int _invMode; bool _pause; + int _cNum; + int _selector, _oldSelector; + Common::String _cAnimStr; + bool _lookScriptFlag; + Common::Rect _windowBounds; + Common::String _descStr; + int _windowStyle; private: void depressButton(int num); @@ -86,6 +93,12 @@ private: void doMiscControl(int allowed); void doPickControl(); void doTalkControl(); + + void banishWindow(bool flag); + + void makeButton(const Common::Rect &bounds, int textX, const Common::String &str); + + void summonWindow(); public: MenuMode _menuMode; int _menuCounter; @@ -102,6 +115,9 @@ public: void clearInfo(); void whileMenuCounter(); + + void printObjectDesc(const Common::String &str, bool firstTime); + void printObjectDesc(); }; } // End of namespace Sherlock -- cgit v1.2.3 From 9f21575c564cb1aff07f0265a47af59ce31ec93e Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 26 Mar 2015 23:10:10 -0400 Subject: SHERLOCK: Implemented banishWindow --- engines/sherlock/user_interface.cpp | 97 ++++++++++++++++++++++++++++++++++--- engines/sherlock/user_interface.h | 8 +-- 2 files changed, 94 insertions(+), 11 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index b0388b4e29..8e5cbb68ef 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -649,6 +649,7 @@ void UserInterface::printObjectDesc(const Common::String &str, bool firstTime) { _windowBounds.top = CONTROLS_Y; events.clearEvents(); + // Loop through displaying up to five lines bool endOfStr = false; const char *msgP = str.c_str(); for (int lineNum = 0; lineNum < 5 && !endOfStr; ++lineNum) { @@ -712,7 +713,8 @@ void UserInterface::printObjectDesc(const Common::String &str, bool firstTime) { screen._backBuffer.blitFrom(screen._backBuffer2, Common::Point(0, CONTROLS_Y), r); - summonWindow(); + // Display the window + summonWindow(tempSurface); } _selector = _oldSelector = -1; @@ -730,17 +732,98 @@ void UserInterface::printObjectDesc() { printObjectDesc(_cAnimStr, true); } -void UserInterface::banishWindow(bool flag) { - // TODO -} - void UserInterface::makeButton(const Common::Rect &bounds, int textX, const Common::String &str) { // TODO } -void UserInterface::summonWindow() { - // TODO +/** + * Displays a passed window by gradually displaying it up vertically + */ +void UserInterface::summonWindow(const Surface &bgSurface) { + Events &events = *_vm->_events; + Screen &screen = *_vm->_screen; + + if (_windowOpen) + // A window is already open, so can't open another one + return; + + // Gradually slide up the display of the window + for (int idx = 1; idx <= (SHERLOCK_SCREEN_HEIGHT - CONTROLS_Y); idx += 2) { + screen.blitFrom(bgSurface, Common::Point(0, SHERLOCK_SCREEN_HEIGHT - idx), + Common::Rect(0, 0, bgSurface.w, idx)); + screen.slamRect(Common::Rect(0, SHERLOCK_SCREEN_HEIGHT - idx, + SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); + + events.delay(10); + } + + // Final display of the entire window + screen._backBuffer.blitFrom(bgSurface, Common::Point(0, CONTROLS_Y), + Common::Rect(0, 0, bgSurface.w, bgSurface.h)); + screen.slamArea(0, CONTROLS_Y, bgSurface.w, bgSurface.h); + + _windowOpen = true; +} + +/** + * Close a currently open window + * @param flag 0 = slide old window down, 1 = slide old window up + */ +void UserInterface::banishWindow(bool flag) { + Events &events = *_vm->_events; + Screen &screen = *_vm->_screen; + + if (_windowOpen) { + if (!flag || !_windowStyle) { + // Slide window up + // Only slide the window up if the window style allows it + if (_windowStyle) { + for (int idx = 2; idx < (SHERLOCK_SCREEN_HEIGHT - CONTROLS_Y); idx += 2) { + byte *pSrc = (byte *)screen._backBuffer.getBasePtr(0, CONTROLS_Y); + Common::copy(pSrc, pSrc + (SHERLOCK_SCREEN_HEIGHT - CONTROLS_Y + idx) + * SHERLOCK_SCREEN_WIDTH, pSrc - SHERLOCK_SCREEN_WIDTH * 2); + screen._backBuffer.blitFrom(screen._backBuffer2, + Common::Point(0, CONTROLS_Y), + Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_HEIGHT, CONTROLS_Y + idx)); + + screen.slamArea(0, CONTROLS_Y + idx - 2, SHERLOCK_SCREEN_WIDTH, + SHERLOCK_SCREEN_HEIGHT - CONTROLS_Y - idx + 2); + events.delay(10); + } + + // Restore final two old lines + screen._backBuffer.blitFrom(screen._backBuffer2, + Common::Point(0, SHERLOCK_SCREEN_HEIGHT - 2), + Common::Rect(0, SHERLOCK_SCREEN_HEIGHT - 2, + SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); + screen.slamArea(0, SHERLOCK_SCREEN_HEIGHT - 2, SHERLOCK_SCREEN_WIDTH, 2); + } else { + // Restore old area to completely erase window + screen._backBuffer.blitFrom(screen._backBuffer2, + Common::Point(0, CONTROLS_Y), + Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); + screen.slamRect(Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, + SHERLOCK_SCREEN_HEIGHT)); + } + } else { + for (int idx = SHERLOCK_SCREEN_HEIGHT - 1 - CONTROLS_Y1; idx >= 0; idx -= 2) { + byte *pSrc = (byte *)screen._backBuffer.getBasePtr(0, CONTROLS_Y1 + idx); + byte *pDest = (byte *)screen._backBuffer.getBasePtr(0, CONTROLS_Y1); + + Common::copy(pSrc, pSrc + (SHERLOCK_SCREEN_HEIGHT - CONTROLS_Y1 - idx) + * SHERLOCK_SCREEN_WIDTH, pDest); + screen.slamArea(0, CONTROLS_Y1 + idx, SHERLOCK_SCREEN_WIDTH, + SHERLOCK_SCREEN_HEIGHT - CONTROLS_Y1 - idx); + events.delay(10); + } + } + + _infoFlag = false; + _windowOpen = false; + } + + _menuMode = STD_MODE; } } // End of namespace Sherlock diff --git a/engines/sherlock/user_interface.h b/engines/sherlock/user_interface.h index 98f6cd21ea..291aa1e9d2 100644 --- a/engines/sherlock/user_interface.h +++ b/engines/sherlock/user_interface.h @@ -25,6 +25,7 @@ #include "common/scummsys.h" #include "common/events.h" +#include "sherlock/graphics.h" #include "sherlock/resources.h" namespace Sherlock { @@ -94,11 +95,7 @@ private: void doPickControl(); void doTalkControl(); - void banishWindow(bool flag); - void makeButton(const Common::Rect &bounds, int textX, const Common::String &str); - - void summonWindow(); public: MenuMode _menuMode; int _menuCounter; @@ -118,6 +115,9 @@ public: void printObjectDesc(const Common::String &str, bool firstTime); void printObjectDesc(); + + void summonWindow(const Surface &bgSurface); + void banishWindow(bool flag); }; } // End of namespace Sherlock -- cgit v1.2.3 From 4fad808aad87bc15827eed180f395c04c260e447 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 27 Mar 2015 08:36:04 -0400 Subject: SHERLOCK: Implemented doMainControl --- engines/sherlock/events.cpp | 8 ++ engines/sherlock/events.h | 1 + engines/sherlock/inventory.cpp | 4 + engines/sherlock/inventory.h | 2 + engines/sherlock/user_interface.cpp | 191 +++++++++++++++++++++++++++++++++++- engines/sherlock/user_interface.h | 4 + 6 files changed, 208 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/events.cpp b/engines/sherlock/events.cpp index a6b3c899cb..5c94b7e1ff 100644 --- a/engines/sherlock/events.cpp +++ b/engines/sherlock/events.cpp @@ -191,6 +191,14 @@ void Events::clearEvents() { _oldButtons = _oldRightButton = false; } +/** + * Clear any pending keyboard inputs + */ +void Events::clearKeyboard() { + _pendingKeys.clear(); +} + + /** * Delay for a given number of game frames, where each frame is 1/60th of a second */ diff --git a/engines/sherlock/events.h b/engines/sherlock/events.h index 1c5fbc5be4..c3bdaf5a93 100644 --- a/engines/sherlock/events.h +++ b/engines/sherlock/events.h @@ -85,6 +85,7 @@ public: Common::KeyState getKey() { return _pendingKeys.pop(); } void clearEvents(); + void clearKeyboard(); void wait(int numFrames); diff --git a/engines/sherlock/inventory.cpp b/engines/sherlock/inventory.cpp index e103213eb5..a05ec6f359 100644 --- a/engines/sherlock/inventory.cpp +++ b/engines/sherlock/inventory.cpp @@ -120,4 +120,8 @@ void Inventory::putInv(int slamit) { // TODO } +void Inventory::invent(int flag) { + // TODO +} + } // End of namespace Sherlock diff --git a/engines/sherlock/inventory.h b/engines/sherlock/inventory.h index 01a325e382..6d61378b99 100644 --- a/engines/sherlock/inventory.h +++ b/engines/sherlock/inventory.h @@ -63,6 +63,8 @@ public: int findInv(const Common::String &name); void putInv(int slamit); + + void invent(int flag); }; } // End of namespace Sherlock diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index 8e5cbb68ef..2827e80b78 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -528,12 +528,188 @@ void UserInterface::doInvControl() { // TODO } +/** + * Handles waiting whilst an object's description window is open. + */ void UserInterface::doLookControl() { - // TODO + Events &events = *_vm->_events; + Inventory &inv = *_vm->_inventory; + Screen &screen = *_vm->_screen; + + _key = _oldKey = -1; + _keyboardInput = _keycode != Common::KEYCODE_INVALID; + + if (events._released || events._rightReleased || _keyboardInput) { + // Is an inventory object being looked at? + if (!_invLookFlag) { + // Is there any remaining text to display? + if (!_descStr.empty()) { + printObjectDesc(_descStr, false); + } else if (!_lookHelp) { + // Need to close the window and depress the Look button + Common::Point pt(MENU_POINTS[0][0], MENU_POINTS[0][1]); + Surface tempSurface((*_controls)[0]._frame.w, (*_controls)[0]._frame.h); + tempSurface.blitFrom(screen._backBuffer2, Common::Point(0, 0), + Common::Rect(pt.x, pt.y, pt.x + (*_controls)[0]._frame.w, + pt.y + (*_controls)[1]._frame.h)); + + screen._backBuffer2.blitFrom((*_controls)[0]._frame, pt); + banishWindow(true); + + _windowBounds.top = CONTROLS_Y1; + _key = _oldKey = COMMANDS[LOOK_MODE - 1]; + _temp = _oldTemp = 0; + _menuMode = LOOK_MODE; + events.clearEvents(); + + screen._backBuffer2.blitFrom(tempSurface, pt); + } + } else { + // Looking at an inventory object + // Backup the user interface + Surface tempSurface(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT - CONTROLS_Y1); + tempSurface.blitFrom(screen._backBuffer2, Common::Point(0, 0), + Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); + + inv.invent(128); + banishWindow(true); + + // Restore the ui + screen._backBuffer2.blitFrom(tempSurface, Common::Point(0, CONTROLS_Y1)); + } + + _windowBounds.top = CONTROLS_Y1; + _key = _oldKey = COMMANDS[LOOK_MODE - 1]; + _temp = _oldTemp = 0; + events.clearEvents(); + _invLookFlag = false; + _menuMode = INV_MODE; + _windowOpen = true; + } } +/** + * Handles input until one of the user interface buttons/commands is selected + */ void UserInterface::doMainControl() { - // TODO + Events &events = *_vm->_events; + Inventory &inv = *_vm->_inventory; + Common::Point pt = events.mousePos(); + + if ((events._pressed || events._released) && pt.y > CONTROLS_Y) { + events.clearKeyboard(); + _key = -1; + + // Check whether the mouse is in any of the command areas + for (_temp = 0; (_temp < 12) && (_key == -1); ++_temp) { + Common::Rect r(MENU_POINTS[_temp][0], MENU_POINTS[_temp][1], + MENU_POINTS[_temp][2], MENU_POINTS[_temp][3]); + if (r.contains(pt)) + _key = COMMANDS[_temp]; + } + --_temp; + } else if (_keycode != Common::KEYCODE_INVALID) { + // Keyboard control + _keyboardInput = true; + + if (_keycode >= Common::KEYCODE_a && _keycode <= Common::KEYCODE_z) { + const char *c = strchr(COMMANDS, _keycode); + _temp = !c ? 12 : c - COMMANDS; + } else { + _temp = 12; + } + + if (_temp == 12) + _key = -1; + + if (events._rightPressed) { + _temp = 12; + _key = -1; + } + } else if (!events._released) { + _key = -1; + } + + // Check if the button being pointed to has changed + if (_oldKey != _key && !_windowOpen) { + // Clear the info line + _infoFlag++; + clearInfo(); + + // If there was an old button selected, restore it + if (_oldKey != -1) { + _menuMode = STD_MODE; + restoreButton(_oldTemp); + } + + // If a new button is being pointed to, highlight it + if (_key != -1 && _temp < 12 && !_keyboardInput) + depressButton(_temp); + + // Save the new button selection + _oldKey = _key; + _oldTemp = _temp; + } + + if (!events._pressed && !_windowOpen) { + switch (_key) { + case 'L': + toggleButton(0); + break; + case 'M': + toggleButton(1); + break; + case 'T': + toggleButton(2); + break; + case 'P': + toggleButton(3); + break; + case 'O': + toggleButton(4); + break; + case 'C': + toggleButton(5); + break; + case 'I': + pushButton(6); + _selector = _oldSelector = -1; + _menuMode = INV_MODE; + inv.invent(1); + break; + case 'U': + pushButton(7); + _selector = _oldSelector = -1; + _menuMode = USE_MODE; + inv.invent(2); + break; + case 'G': + pushButton(8); + _selector = _oldSelector = -1; + _menuMode = GIVE_MODE; + inv.invent(3); + break; + case 'J': + pushButton(9); + _menuMode = JOURNAL_MODE; + journalControl(); + break; + case 'F': + pushButton(10); + _menuMode = FILES_MODE; + environment(); + break; + case 'S': + pushButton(11); + _menuMode = SETUP_MODE; + doControls(); + break; + default: + break; + } + + _help = _oldHelp = _oldBgFound = -1; + } } void UserInterface::doMiscControl(int allowed) { @@ -548,6 +724,17 @@ void UserInterface::doTalkControl() { // TODO } +void UserInterface::journalControl() { + // TODO +} + +void UserInterface::environment() { + // TODO +} + +void UserInterface::doControls() { + // TODO +} /** * Print the description of an object diff --git a/engines/sherlock/user_interface.h b/engines/sherlock/user_interface.h index 291aa1e9d2..582d6f87ce 100644 --- a/engines/sherlock/user_interface.h +++ b/engines/sherlock/user_interface.h @@ -94,6 +94,10 @@ private: void doMiscControl(int allowed); void doPickControl(); void doTalkControl(); + void journalControl(); + + void environment(); + void doControls(); void makeButton(const Common::Rect &bounds, int textX, const Common::String &str); public: -- cgit v1.2.3 From 56a854e2292f420a6ab03c65174f9fc0310bc2fa Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 27 Mar 2015 19:52:46 -0400 Subject: SHERLOCK: Fixes for examine dialog display --- engines/sherlock/events.cpp | 2 +- engines/sherlock/scene.cpp | 15 ++++++---- engines/sherlock/scene.h | 1 - engines/sherlock/screen.h | 18 +++++++----- engines/sherlock/user_interface.cpp | 57 ++++++++++++++++++++++++++----------- engines/sherlock/user_interface.h | 5 +++- 6 files changed, 66 insertions(+), 32 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/events.cpp b/engines/sherlock/events.cpp index 5c94b7e1ff..fef22c9301 100644 --- a/engines/sherlock/events.cpp +++ b/engines/sherlock/events.cpp @@ -186,7 +186,7 @@ bool Events::checkForNextFrameCounter() { */ void Events::clearEvents() { _pendingKeys.clear(); - _pressed = _rightPressed = false; + _pressed = _released = false; _rightPressed = _rightReleased = false; _oldButtons = _oldRightButton = false; } diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 6442538794..97f7350ea9 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -106,12 +106,9 @@ Scene::Scene(SherlockEngine *vm): _vm(vm) { _animating = 0; _doBgAnimDone = true; _tempFadeStyle = 0; - - _controlPanel = new ImageFile("controls.vgs"); } Scene::~Scene() { - delete _controlPanel; freeScene(); } @@ -198,6 +195,7 @@ bool Scene::loadScene(const Common::String &filename) { People &people = *_vm->_people; Screen &screen = *_vm->_screen; Sound &sound = *_vm->_sound; + UserInterface &ui = *_vm->_ui; bool flag; freeScene(); @@ -393,9 +391,7 @@ bool Scene::loadScene(const Common::String &filename) { } // Clear user interface area and draw controls - screen._backBuffer2.fillRect(0, INFO_LINE, SHERLOCK_SCREEN_WIDTH, INFO_LINE + 10, INFO_BLACK); - screen._backBuffer.transBlitFrom((*_controlPanel)[0], Common::Point(0, CONTROLS_Y)); - screen._backBuffer2.transBlitFrom((*_controlPanel)[0], Common::Point(0, CONTROLS_Y)); + ui.drawInterface(); _changes = false; checkSceneStatus(); @@ -1074,6 +1070,13 @@ void Scene::doBgAnim() { events.setCursor((CursorId)cursorId); } + if (ui._menuMode == LOOK_MODE) { + if (mousePos.y > CONTROLS_Y1) + events.setCursor(ARROW); + else if (mousePos.y < CONTROLS_Y) + events.setCursor(MAGNIFY); + } + // Check for setting magnifying glass cursor if (ui._menuMode == INV_MODE || ui._menuMode == USE_MODE || ui._menuMode == GIVE_MODE) { if (_invMode == INVMODE_1) { diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h index 27313e34af..007f910b10 100644 --- a/engines/sherlock/scene.h +++ b/engines/sherlock/scene.h @@ -123,7 +123,6 @@ public: Common::Point _bigPos; Common::Point _overPos; int _charPoint, _oldCharPoint; - ImageFile *_controlPanel; int _keyboardInput; int _oldKey, _help, _oldHelp; int _oldTemp, _temp; diff --git a/engines/sherlock/screen.h b/engines/sherlock/screen.h index 45a50e7e85..e8f45f7bba 100644 --- a/engines/sherlock/screen.h +++ b/engines/sherlock/screen.h @@ -36,13 +36,17 @@ namespace Sherlock { #define VGA_COLOR_TRANS(x) ((x) * 255 / 63) enum { - INFO_BLACK = 1, - INFO_FOREGROUND = 11, - INFO_BACKGROUND = 1, - BORDER_COLOR = 237, - INV_FOREGROUND = 14, - INV_BACKGROUND = 1, - COM_FOREGROUND = 15 + INFO_BLACK = 1, + INFO_FOREGROUND = 11, + INFO_BACKGROUND = 1, + BORDER_COLOR = 237, + INV_FOREGROUND = 14, + INV_BACKGROUND = 1, + COMMAND_HIGHLIGHTED = 10, + COMMAND_FOREGROUND = 15, + BUTTON_TOP = 233, + BUTTON_MIDDLE = 244, + BUTTON_BOTTOM = 248 }; class SherlockEngine; diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index 2827e80b78..c15685d82b 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -60,6 +60,8 @@ const char *const PRESS_KEY_TO_CONTINUE = "Press any Key to Continue."; /*----------------------------------------------------------------*/ UserInterface::UserInterface(SherlockEngine *vm) : _vm(vm) { + _controls = new ImageFile("menu.all"); + _controlPanel = new ImageFile("controls.vgs"); _bgFound = 0; _oldBgFound = -1; _keycode = Common::KEYCODE_INVALID; @@ -81,12 +83,11 @@ UserInterface::UserInterface(SherlockEngine *vm) : _vm(vm) { _windowBounds = Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH - 1, SHERLOCK_SCREEN_HEIGHT - 1); _windowStyle = 0; - - _controls = new ImageFile("menu.all"); } UserInterface::~UserInterface() { delete _controls; + delete _controlPanel; } void UserInterface::reset() { @@ -95,6 +96,17 @@ void UserInterface::reset() { _oldTemp = _temp = -1; } +/** + * Draw the user interface onto the screen's back buffers + */ +void UserInterface::drawInterface() { + Screen &screen = *_vm->_screen; + + screen._backBuffer2.fillRect(0, INFO_LINE, SHERLOCK_SCREEN_WIDTH, INFO_LINE + 10, INFO_BLACK); + screen._backBuffer.transBlitFrom((*_controlPanel)[0], Common::Point(0, CONTROLS_Y)); + screen._backBuffer2.transBlitFrom((*_controlPanel)[0], Common::Point(0, CONTROLS_Y)); +} + /** * Main input handler for the user interface */ @@ -137,7 +149,7 @@ void UserInterface::handleInput() { (events._rightPressed || (!_helpStyle && !events._released)) && (_bgFound != -1) && (_bgFound < 1000) && (scene._bgShapes[_bgFound]._defaultCommand || - scene._bgShapes[_bgFound]._description[0])) { + !scene._bgShapes[_bgFound]._description.empty())) { // If there is no default command, so set it to Look if (scene._bgShapes[_bgFound]._defaultCommand) _help = scene._bgShapes[_bgFound]._defaultCommand - 1; @@ -151,7 +163,7 @@ void UserInterface::handleInput() { ((events._rightReleased && _helpStyle) || (events._released && !_helpStyle)) && (_bgFound != -1 && _bgFound < 1000) && (scene._bgShapes[_bgFound]._defaultCommand || - scene._bgShapes[_bgFound]._description[0])) { + !scene._bgShapes[_bgFound]._description.empty())) { // If there is no default command, set it to Look if (scene._bgShapes[_bgFound]._defaultCommand) _menuMode = (MenuMode)scene._bgShapes[_bgFound]._defaultCommand; @@ -491,7 +503,7 @@ void UserInterface::examine() { people.walkToCoords(obj._lookPosition, obj._lookFacing); } - if (talk._talkToAbort) { + if (!talk._talkToAbort) { _cAnimStr = obj._examine; if (obj._lookFlag) _vm->setFlags(obj._lookFlag); @@ -548,11 +560,6 @@ void UserInterface::doLookControl() { } else if (!_lookHelp) { // Need to close the window and depress the Look button Common::Point pt(MENU_POINTS[0][0], MENU_POINTS[0][1]); - Surface tempSurface((*_controls)[0]._frame.w, (*_controls)[0]._frame.h); - tempSurface.blitFrom(screen._backBuffer2, Common::Point(0, 0), - Common::Rect(pt.x, pt.y, pt.x + (*_controls)[0]._frame.w, - pt.y + (*_controls)[1]._frame.h)); - screen._backBuffer2.blitFrom((*_controls)[0]._frame, pt); banishWindow(true); @@ -562,7 +569,8 @@ void UserInterface::doLookControl() { _menuMode = LOOK_MODE; events.clearEvents(); - screen._backBuffer2.blitFrom(tempSurface, pt); + // Restore UI + drawInterface(); } } else { // Looking at an inventory object @@ -865,6 +873,10 @@ void UserInterface::printObjectDesc(const Common::String &str, bool firstTime) { Common::String line(lineStartP, msgP); screen.gPrint(Common::Point(16, CONTROLS_Y + 12 + lineNum * 9), INV_FOREGROUND, line.c_str()); + + if (!endOfStr) + // Start next line at start of the nxet word after space + ++msgP; } // Handle display depending on whether all the message was shown @@ -874,7 +886,7 @@ void UserInterface::printObjectDesc(const Common::String &str, bool firstTime) { PRESS_KEY_FOR_MORE); screen.gPrint(Common::Point((SHERLOCK_SCREEN_WIDTH - screen.stringWidth(PRESS_KEY_FOR_MORE)) / 2, CONTROLS_Y), - COM_FOREGROUND, "P"); + COMMAND_FOREGROUND, "P"); _descStr = msgP; } else { makeButton(Common::Rect(46, CONTROLS_Y, 272, CONTROLS_Y + 10), @@ -882,7 +894,7 @@ void UserInterface::printObjectDesc(const Common::String &str, bool firstTime) { PRESS_KEY_FOR_MORE); screen.gPrint(Common::Point((SHERLOCK_SCREEN_WIDTH - screen.stringWidth(PRESS_KEY_TO_CONTINUE)) / 2, CONTROLS_Y), - COM_FOREGROUND, "P"); + COMMAND_FOREGROUND, "P"); _descStr = ""; } @@ -913,15 +925,28 @@ void UserInterface::printObjectDesc(const Common::String &str, bool firstTime) { } /** -* Print the previously selected object's decription -*/ + * Print the previously selected object's decription + */ void UserInterface::printObjectDesc() { printObjectDesc(_cAnimStr, true); } +/** + * Draws a button for use in the inventory, talk, and examine dialogs. + */ void UserInterface::makeButton(const Common::Rect &bounds, int textX, const Common::String &str) { - // TODO + Screen &screen = *_vm->_screen; + + screen.bar(Common::Rect(bounds.left, bounds.top, bounds.right, bounds.top + 1), BUTTON_TOP); + screen.bar(Common::Rect(bounds.left, bounds.top, bounds.left + 1, bounds.bottom), BUTTON_TOP); + screen.bar(Common::Rect(bounds.right - 1, bounds.top, bounds.right, bounds.bottom), BUTTON_BOTTOM); + screen.bar(Common::Rect(bounds.left + 1, bounds.bottom - 1, bounds.right, bounds.bottom), BUTTON_BOTTOM); + screen.bar(Common::Rect(bounds.left + 1, bounds.top + 1, bounds.right - 1, bounds.bottom - 1), BUTTON_MIDDLE); + + screen.gPrint(Common::Point(textX, bounds.top), COMMAND_HIGHLIGHTED, "%c", str[0]); + screen.gPrint(Common::Point(textX + screen.charWidth(str[0]), bounds.top), + COMMAND_FOREGROUND, "%s", str.c_str() + 1); } /** diff --git a/engines/sherlock/user_interface.h b/engines/sherlock/user_interface.h index 582d6f87ce..f6e0435f48 100644 --- a/engines/sherlock/user_interface.h +++ b/engines/sherlock/user_interface.h @@ -51,6 +51,8 @@ class SherlockEngine; class UserInterface { private: SherlockEngine *_vm; + ImageFile *_controlPanel; + ImageFile *_controls; int _bgFound; int _oldBgFound; Common::KeyCode _keycode; @@ -60,7 +62,6 @@ private: int _key, _oldKey; int _temp, _oldTemp; int _invLookFlag; - ImageFile *_controls; int _oldLook; bool _keyboardInput; int _invMode; @@ -111,6 +112,8 @@ public: void reset(); + void drawInterface(); + void handleInput(); void clearInfo(); -- cgit v1.2.3 From e122b752b7faf6a0307e74523771860367f7227e Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 27 Mar 2015 22:12:37 -0400 Subject: SHERLOCK: Fix scrolling examine window on-screen --- engines/sherlock/screen.cpp | 2 +- engines/sherlock/screen.h | 2 +- engines/sherlock/user_interface.cpp | 40 ++++++++++++++++++++----------------- 3 files changed, 24 insertions(+), 20 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp index 646802094f..def20612b7 100644 --- a/engines/sherlock/screen.cpp +++ b/engines/sherlock/screen.cpp @@ -403,7 +403,7 @@ void Screen::writeString(const Common::String &str, const Common::Point &pt, int /** * Fills an area on the back buffer, and then copies it to the screen */ -void Screen::bar(const Common::Rect &r, int color) { +void Screen::vgaBar(const Common::Rect &r, int color) { _backBuffer.fillRect(r, color); slamRect(r); } diff --git a/engines/sherlock/screen.h b/engines/sherlock/screen.h index e8f45f7bba..acd122e0e9 100644 --- a/engines/sherlock/screen.h +++ b/engines/sherlock/screen.h @@ -109,7 +109,7 @@ public: int charWidth(char c); - void bar(const Common::Rect &r, int color); + void vgaBar(const Common::Rect &r, int color); }; } // End of namespace Sherlock diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index c15685d82b..6af698baa6 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -82,7 +82,7 @@ UserInterface::UserInterface(SherlockEngine *vm) : _vm(vm) { _selector = _oldSelector = -1; _windowBounds = Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH - 1, SHERLOCK_SCREEN_HEIGHT - 1); - _windowStyle = 0; + _windowStyle = 1; // Sliding windows } UserInterface::~UserInterface() { @@ -457,7 +457,7 @@ void UserInterface::toggleButton(int num) { */ void UserInterface::clearInfo() { if (_infoFlag) { - _vm->_screen->bar(Common::Rect(16, INFO_LINE, SHERLOCK_SCREEN_WIDTH - 19, + _vm->_screen->vgaBar(Common::Rect(16, INFO_LINE, SHERLOCK_SCREEN_WIDTH - 19, INFO_LINE + 10), INFO_BLACK); _infoFlag = false; _oldLook = -1; @@ -822,23 +822,24 @@ void UserInterface::printObjectDesc(const Common::String &str, bool firstTime) { return; } + Surface &bb = screen._backBuffer; if (firstTime) { // Only draw the border on the first call _infoFlag = true; clearInfo(); - screen.bar(Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, + bb.fillRect(Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, CONTROLS_Y1 + 10), BORDER_COLOR); - screen.bar(Common::Rect(0, CONTROLS_Y + 10, 1, SHERLOCK_SCREEN_HEIGHT - 1), + bb.fillRect(Common::Rect(0, CONTROLS_Y + 10, 1, SHERLOCK_SCREEN_HEIGHT - 1), BORDER_COLOR); - screen.bar(Common::Rect(SHERLOCK_SCREEN_WIDTH - 2, CONTROLS_Y + 10, + bb.fillRect(Common::Rect(SHERLOCK_SCREEN_WIDTH - 2, CONTROLS_Y + 10, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR); - screen.bar(Common::Rect(0, SHERLOCK_SCREEN_HEIGHT - 1, SHERLOCK_SCREEN_WIDTH, + bb.fillRect(Common::Rect(0, SHERLOCK_SCREEN_HEIGHT - 1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR); } // Clear background - screen.bar(Common::Rect(2, CONTROLS_Y + 10, SHERLOCK_SCREEN_WIDTH - 2, + bb.fillRect(Common::Rect(2, CONTROLS_Y + 10, SHERLOCK_SCREEN_WIDTH - 2, SHERLOCK_SCREEN_HEIGHT - 2), INV_BACKGROUND); _windowBounds.top = CONTROLS_Y; @@ -904,15 +905,17 @@ void UserInterface::printObjectDesc(const Common::String &str, bool firstTime) { SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); } else { + // Extract the window that's been drawn on the back buffer Surface tempSurface(SHERLOCK_SCREEN_WIDTH, - (SHERLOCK_SCREEN_HEIGHT - CONTROLS_Y) + 10); + (SHERLOCK_SCREEN_HEIGHT - CONTROLS_Y)); Common::Rect r(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT); + tempSurface.blitFrom(screen._backBuffer, Common::Point(0, 0), r); - tempSurface.blitFrom(screen._backBuffer, Common::Point(0, CONTROLS_Y), r); + // Remove drawn window with original user interface screen._backBuffer.blitFrom(screen._backBuffer2, Common::Point(0, CONTROLS_Y), r); - // Display the window + // Display the window gradually on-screen summonWindow(tempSurface); } @@ -938,11 +941,12 @@ void UserInterface::makeButton(const Common::Rect &bounds, int textX, const Common::String &str) { Screen &screen = *_vm->_screen; - screen.bar(Common::Rect(bounds.left, bounds.top, bounds.right, bounds.top + 1), BUTTON_TOP); - screen.bar(Common::Rect(bounds.left, bounds.top, bounds.left + 1, bounds.bottom), BUTTON_TOP); - screen.bar(Common::Rect(bounds.right - 1, bounds.top, bounds.right, bounds.bottom), BUTTON_BOTTOM); - screen.bar(Common::Rect(bounds.left + 1, bounds.bottom - 1, bounds.right, bounds.bottom), BUTTON_BOTTOM); - screen.bar(Common::Rect(bounds.left + 1, bounds.top + 1, bounds.right - 1, bounds.bottom - 1), BUTTON_MIDDLE); + Surface &bb = screen._backBuffer; + bb.fillRect(Common::Rect(bounds.left, bounds.top, bounds.right, bounds.top + 1), BUTTON_TOP); + bb.fillRect(Common::Rect(bounds.left, bounds.top, bounds.left + 1, bounds.bottom), BUTTON_TOP); + bb.fillRect(Common::Rect(bounds.right - 1, bounds.top, bounds.right, bounds.bottom), BUTTON_BOTTOM); + bb.fillRect(Common::Rect(bounds.left + 1, bounds.bottom - 1, bounds.right, bounds.bottom), BUTTON_BOTTOM); + bb.fillRect(Common::Rect(bounds.left + 1, bounds.top + 1, bounds.right - 1, bounds.bottom - 1), BUTTON_MIDDLE); screen.gPrint(Common::Point(textX, bounds.top), COMMAND_HIGHLIGHTED, "%c", str[0]); screen.gPrint(Common::Point(textX + screen.charWidth(str[0]), bounds.top), @@ -950,7 +954,7 @@ void UserInterface::makeButton(const Common::Rect &bounds, int textX, } /** - * Displays a passed window by gradually displaying it up vertically + * Displays a passed window by gradually scrolling it vertically on-screen */ void UserInterface::summonWindow(const Surface &bgSurface) { Events &events = *_vm->_events; @@ -961,8 +965,8 @@ void UserInterface::summonWindow(const Surface &bgSurface) { return; // Gradually slide up the display of the window - for (int idx = 1; idx <= (SHERLOCK_SCREEN_HEIGHT - CONTROLS_Y); idx += 2) { - screen.blitFrom(bgSurface, Common::Point(0, SHERLOCK_SCREEN_HEIGHT - idx), + for (int idx = 1; idx <= bgSurface.h; idx += 2) { + screen._backBuffer.blitFrom(bgSurface, Common::Point(0, SHERLOCK_SCREEN_HEIGHT - idx), Common::Rect(0, 0, bgSurface.w, idx)); screen.slamRect(Common::Rect(0, SHERLOCK_SCREEN_HEIGHT - idx, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); -- cgit v1.2.3 From 5b1ad857b7cd0b6065c01e000dfadb80526a1729 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 27 Mar 2015 23:04:49 -0400 Subject: SHERLOCK: Fix for sliding examine dialog off-screen --- engines/sherlock/user_interface.cpp | 45 ++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 16 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index 6af698baa6..61d6c6a76e 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -571,6 +571,14 @@ void UserInterface::doLookControl() { // Restore UI drawInterface(); + } else { + events.setCursor(ARROW); + banishWindow(true); + _windowBounds.top = CONTROLS_Y1; + _key = _oldKey = -1; + _temp = _oldTemp = 0; + _menuMode = STD_MODE; + events.clearEvents(); } } else { // Looking at an inventory object @@ -984,24 +992,28 @@ void UserInterface::summonWindow(const Surface &bgSurface) { /** * Close a currently open window - * @param flag 0 = slide old window down, 1 = slide old window up + * @param flag 0 = slide old window down, 1 = slide prior UI back up */ void UserInterface::banishWindow(bool flag) { Events &events = *_vm->_events; Screen &screen = *_vm->_screen; if (_windowOpen) { - if (!flag || !_windowStyle) { - // Slide window up - // Only slide the window up if the window style allows it + if (flag || !_windowStyle) { + // Slide window down + // Only slide the window if the window style allows it if (_windowStyle) { for (int idx = 2; idx < (SHERLOCK_SCREEN_HEIGHT - CONTROLS_Y); idx += 2) { - byte *pSrc = (byte *)screen._backBuffer.getBasePtr(0, CONTROLS_Y); - Common::copy(pSrc, pSrc + (SHERLOCK_SCREEN_HEIGHT - CONTROLS_Y + idx) - * SHERLOCK_SCREEN_WIDTH, pSrc - SHERLOCK_SCREEN_WIDTH * 2); + // Shift the window down by 2 lines + byte *pSrc = (byte *)screen._backBuffer.getBasePtr(0, CONTROLS_Y + idx - 2); + byte *pSrcEnd = (byte *)screen._backBuffer.getBasePtr(0, SHERLOCK_SCREEN_HEIGHT - 2); + byte *pDest = (byte *)screen._backBuffer.getBasePtr(0, SHERLOCK_SCREEN_HEIGHT); + Common::copy_backward(pSrc, pSrcEnd, pDest); + + // Restore lines from the ui in the secondary back buffer screen._backBuffer.blitFrom(screen._backBuffer2, Common::Point(0, CONTROLS_Y), - Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_HEIGHT, CONTROLS_Y + idx)); + Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, CONTROLS_Y + idx)); screen.slamArea(0, CONTROLS_Y + idx - 2, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT - CONTROLS_Y - idx + 2); @@ -1023,14 +1035,15 @@ void UserInterface::banishWindow(bool flag) { SHERLOCK_SCREEN_HEIGHT)); } } else { - for (int idx = SHERLOCK_SCREEN_HEIGHT - 1 - CONTROLS_Y1; idx >= 0; idx -= 2) { - byte *pSrc = (byte *)screen._backBuffer.getBasePtr(0, CONTROLS_Y1 + idx); - byte *pDest = (byte *)screen._backBuffer.getBasePtr(0, CONTROLS_Y1); - - Common::copy(pSrc, pSrc + (SHERLOCK_SCREEN_HEIGHT - CONTROLS_Y1 - idx) - * SHERLOCK_SCREEN_WIDTH, pDest); - screen.slamArea(0, CONTROLS_Y1 + idx, SHERLOCK_SCREEN_WIDTH, - SHERLOCK_SCREEN_HEIGHT - CONTROLS_Y1 - idx); + // Slide the original user interface up to cover the dialog + for (int idx = 1; idx < (SHERLOCK_SCREEN_HEIGHT - CONTROLS_Y1); idx += 2) { + byte *pSrc = (byte *)screen._backBuffer2.getBasePtr(0, CONTROLS_Y1); + byte *pSrcEnd = (byte *)screen._backBuffer2.getBasePtr(0, CONTROLS_Y1 + idx); + byte *pDest = (byte *)screen._backBuffer.getBasePtr(0, SHERLOCK_SCREEN_HEIGHT - idx); + Common::copy(pSrc, pSrcEnd, pDest); + + screen.slamArea(0, SHERLOCK_SCREEN_HEIGHT - idx, SHERLOCK_SCREEN_WIDTH, + SHERLOCK_SCREEN_HEIGHT); events.delay(10); } } -- cgit v1.2.3 From c047009ee10d8de67ee17088aad4ca131d907a8a Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 27 Mar 2015 23:10:36 -0400 Subject: SHERLOCK: Fix hotspots working again after examining an object --- engines/sherlock/user_interface.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index 61d6c6a76e..54c1f8e0fc 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -580,7 +580,8 @@ void UserInterface::doLookControl() { _menuMode = STD_MODE; events.clearEvents(); } - } else { + } + else { // Looking at an inventory object // Backup the user interface Surface tempSurface(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT - CONTROLS_Y1); @@ -592,15 +593,15 @@ void UserInterface::doLookControl() { // Restore the ui screen._backBuffer2.blitFrom(tempSurface, Common::Point(0, CONTROLS_Y1)); - } - _windowBounds.top = CONTROLS_Y1; - _key = _oldKey = COMMANDS[LOOK_MODE - 1]; - _temp = _oldTemp = 0; - events.clearEvents(); - _invLookFlag = false; - _menuMode = INV_MODE; - _windowOpen = true; + _windowBounds.top = CONTROLS_Y1; + _key = _oldKey = COMMANDS[LOOK_MODE - 1]; + _temp = _oldTemp = 0; + events.clearEvents(); + _invLookFlag = false; + _menuMode = INV_MODE; + _windowOpen = true; + } } } @@ -900,7 +901,7 @@ void UserInterface::printObjectDesc(const Common::String &str, bool firstTime) { } else { makeButton(Common::Rect(46, CONTROLS_Y, 272, CONTROLS_Y + 10), (SHERLOCK_SCREEN_WIDTH - screen.stringWidth(PRESS_KEY_TO_CONTINUE)) / 2, - PRESS_KEY_FOR_MORE); + PRESS_KEY_TO_CONTINUE); screen.gPrint(Common::Point((SHERLOCK_SCREEN_WIDTH - screen.stringWidth(PRESS_KEY_TO_CONTINUE)) / 2, CONTROLS_Y), COMMAND_FOREGROUND, "P"); -- cgit v1.2.3 From 91df82c3e1599a658a7e4897bebf747e0e7fc189 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 27 Mar 2015 23:24:54 -0400 Subject: SHERLOCK: Fix mouse cursor hotspots --- engines/sherlock/events.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sherlock/events.cpp b/engines/sherlock/events.cpp index fef22c9301..d147fe1f4c 100644 --- a/engines/sherlock/events.cpp +++ b/engines/sherlock/events.cpp @@ -67,7 +67,7 @@ void Events::setCursor(CursorId cursorId) { // Set the cursor data Graphics::Surface &s = (*_cursorImages)[cursorId]; - CursorMan.replaceCursor(s.getPixels(), s.w, s.h, s.w / 2, s.h / 2, 0xff); + CursorMan.replaceCursor(s.getPixels(), s.w, s.h, 0, 0, 0xff); showCursor(); } -- cgit v1.2.3 From ebda40038b72fd34673e2a6e8a29b4ec47d1ee54 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 28 Mar 2015 10:32:00 -0400 Subject: SHERLOCK: Add partial on-screen clipping to blitFrom --- engines/sherlock/graphics.cpp | 71 +++++++++++++++++++++++++------------ engines/sherlock/graphics.h | 2 ++ engines/sherlock/user_interface.cpp | 2 +- 3 files changed, 51 insertions(+), 24 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/graphics.cpp b/engines/sherlock/graphics.cpp index 1a0144bc4b..306ff23548 100644 --- a/engines/sherlock/graphics.cpp +++ b/engines/sherlock/graphics.cpp @@ -85,9 +85,15 @@ void Surface::blitFrom(const Graphics::Surface &src, const Common::Point &pt) { */ void Surface::blitFrom(const Graphics::Surface &src, const Common::Point &pt, const Common::Rect &srcBounds) { - addDirtyRect(Common::Rect(pt.x, pt.y, pt.x + srcBounds.width(), - pt.y + srcBounds.height())); - copyRectToSurface(src, pt.x, pt.y, srcBounds); + Common::Rect destRect(pt.x, pt.y, pt.x + srcBounds.width(), + pt.y + srcBounds.height()); + Common::Rect srcRect = srcBounds; + + if (clip(srcRect, destRect)) { + // Surface is at least partially or completely on-screen + addDirtyRect(destRect); + copyRectToSurface(src, destRect.left, destRect.top, srcRect); + } } /** @@ -104,32 +110,18 @@ void Surface::transBlitFrom(const ImageFrame &src, const Common::Point &pt, void Surface::transBlitFrom(const Graphics::Surface &src, const Common::Point &pt, bool flipped, int overrideColor) { Common::Rect drawRect(0, 0, src.w, src.h); - Common::Point destPt = pt; - - if (destPt.x < 0) { - drawRect.left += -destPt.x; - destPt.x = 0; - } - if (destPt.y < 0) { - drawRect.top += -destPt.y; - destPt.y = 0; - } - int right = destPt.x + src.w; - if (right > this->w) { - drawRect.right -= (right - this->w); - } - int bottom = destPt.y + src.h; - if (bottom > this->h) { - drawRect.bottom -= (bottom - this->h); - } - - if (!drawRect.isValidRect()) + Common::Rect destRect(pt.x, pt.y, pt.x + src.w, pt.y + src.h); + + // Clip the display area to on-screen + if (!clip(drawRect, destRect)) + // It's completely off-screen return; if (flipped) drawRect = Common::Rect(src.w - drawRect.right, src.h - drawRect.bottom, src.w - drawRect.left, src.h - drawRect.top); + Common::Point destPt(destRect.left, destRect.top); addDirtyRect(Common::Rect(destPt.x, destPt.y, destPt.x + drawRect.width(), destPt.y + drawRect.height())); @@ -169,4 +161,37 @@ Surface Surface::getSubArea(const Common::Rect &r) { return Surface(*this, r); } +/** + * Clips the given source bounds so the passed destBounds will be entirely on-screen + */ +bool Surface::clip(Common::Rect &srcBounds, Common::Rect &destBounds) { + if (destBounds.left >= this->w || destBounds.top >= this->h || + destBounds.right <= 0 || destBounds.bottom <= 0) + return false; + + // Clip the bounds if necessary to fit on-screen + if (destBounds.right > this->w) { + srcBounds.right -= destBounds.right - this->w; + destBounds.right = this->w; + } + + if (destBounds.bottom > this->h) { + srcBounds.bottom -= destBounds.bottom - this->h; + destBounds.bottom = this->h; + } + + if (destBounds.top < 0) { + srcBounds.top += -destBounds.top; + destBounds.top = 0; + } + + if (destBounds.left < 0) { + srcBounds.left += -destBounds.left; + destBounds.left = 0; + } + + return true; +} + + } // End of namespace Sherlock diff --git a/engines/sherlock/graphics.h b/engines/sherlock/graphics.h index c380d805b2..b54dc1ec37 100644 --- a/engines/sherlock/graphics.h +++ b/engines/sherlock/graphics.h @@ -32,6 +32,8 @@ namespace Sherlock { class Surface : public Graphics::Surface { private: bool _freePixels; + + bool clip(Common::Rect &srcBounds, Common::Rect &destBounds); protected: virtual void addDirtyRect(const Common::Rect &r) {} diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index 54c1f8e0fc..61933cf9f3 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -257,7 +257,7 @@ void UserInterface::handleInput() { if (!events._released) lookScreen(pt); } else { - personFound = scene._bgShapes[_bgFound]._aType == PERSON && _bgFound != -1; + personFound = _bgFound != -1 && scene._bgShapes[_bgFound]._aType == PERSON; } if (events._released && personFound) -- cgit v1.2.3 From 35df6bb7ed44f78548ff7ab6b63fccc4e5b1609f Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 28 Mar 2015 16:28:48 -0400 Subject: SHERLOCK: Implemented doInvControl --- engines/sherlock/inventory.cpp | 12 ++ engines/sherlock/inventory.h | 6 + engines/sherlock/user_interface.cpp | 241 +++++++++++++++++++++++++++++++++++- engines/sherlock/user_interface.h | 9 ++ 4 files changed, 267 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sherlock/inventory.cpp b/engines/sherlock/inventory.cpp index a05ec6f359..75ee364123 100644 --- a/engines/sherlock/inventory.cpp +++ b/engines/sherlock/inventory.cpp @@ -124,4 +124,16 @@ void Inventory::invent(int flag) { // TODO } +void Inventory::invCommands(bool slamIt) { + // TODO +} + +void Inventory::doInvLite(int index, byte color) { + // TODO +} + +void Inventory::doInvJF() { + // TODO +} + } // End of namespace Sherlock diff --git a/engines/sherlock/inventory.h b/engines/sherlock/inventory.h index 6d61378b99..0fa8eb0824 100644 --- a/engines/sherlock/inventory.h +++ b/engines/sherlock/inventory.h @@ -65,6 +65,12 @@ public: void putInv(int slamit); void invent(int flag); + + void invCommands(bool slamIt); + + void doInvLite(int index, byte color); + + void doInvJF(); }; } // End of namespace Sherlock diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index 61933cf9f3..10b13cedbe 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -77,12 +77,14 @@ UserInterface::UserInterface(SherlockEngine *vm) : _vm(vm) { _oldLook = false; _keyboardInput = false; _invMode = 0; + _invIndex = 0; _pause = false; _cNum = 0; _selector = _oldSelector = -1; _windowBounds = Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH - 1, SHERLOCK_SCREEN_HEIGHT - 1); _windowStyle = 1; // Sliding windows + _find = 0; } UserInterface::~UserInterface() { @@ -451,6 +453,10 @@ void UserInterface::toggleButton(int num) { } } +void UserInterface::buttonPrint(const Common::Point &pt, int color, bool slamIt, + const Common::String &str) { + // TODO +} /** * Clears the info line of the screen @@ -536,8 +542,235 @@ void UserInterface::doEnvControl() { // TODO } +/** + * Handle input whilst the inventory is active + */ void UserInterface::doInvControl() { - // TODO + Events &events = *_vm->_events; + Inventory &inv = *_vm->_inventory; + Scene &scene = *_vm->_scene; + Screen &screen = *_vm->_screen; + Talk &talk = *_vm->_talk; + const char INVENTORY_COMMANDS[9] = { "ELUG-+,." }; + int colors[8]; + Common::Point mousePos = events.mousePos(); + + _key = _oldKey = -1; + _keyboardInput = false; + + // Check whether any inventory slot is highlighted + int found = -1; + Common::fill(&colors[0], &colors[8], (int)COMMAND_FOREGROUND); + for (int idx = 0; idx < 8; ++idx) { + Common::Rect r(INVENTORY_POINTS[idx][0], CONTROLS_Y1, + INVENTORY_POINTS[idx][1], CONTROLS_Y1 + 10); + if (r.contains(mousePos)) { + found = idx; + break; + } + } + + if (events._pressed || events._released) { + events.clearKeyboard(); + + if (found != -1) + // If a slot highlighted, set it's color + colors[found] = COMMAND_HIGHLIGHTED; + buttonPrint(Common::Point(INVENTORY_POINTS[0][2], CONTROLS_Y1), + colors[0], true, "Exit"); + + if (found >= 0 && found <= 3) { + buttonPrint(Common::Point(INVENTORY_POINTS[1][2], CONTROLS_Y1), colors[1], true, "Look"); + buttonPrint(Common::Point(INVENTORY_POINTS[2][2], CONTROLS_Y1), colors[1], true, "Use"); + buttonPrint(Common::Point(INVENTORY_POINTS[3][2], CONTROLS_Y1), colors[1], true, "Give"); + _invMode = found; + _selector = -1; + } + + if (_invIndex) { + screen.print(Common::Point(INVENTORY_POINTS[4][2], CONTROLS_Y1 + 1), + colors[4], "^^"); + screen.print(Common::Point(INVENTORY_POINTS[5][2], CONTROLS_Y1 + 1), + colors[5], "^"); + } + + if ((inv._holdings - _invIndex) > 6) { + screen.print(Common::Point(INVENTORY_POINTS[6][2], CONTROLS_Y1 + 1), + colors[6], "^^"); + screen.print(Common::Point(INVENTORY_POINTS[7][2], CONTROLS_Y1 + 1), + colors[7], "^"); + } + + bool flag = false; + if (_invMode == 1 || _invMode == 2 || _invMode == 3) { + Common::Rect r(15, CONTROLS_Y1 + 11, 314, SHERLOCK_SCREEN_HEIGHT - 2); + flag = (_selector < inv._holdings); + } + + if (!flag && mousePos.y >(CONTROLS_Y1 + 11)) + _selector = -1; + } + + if (_keycode != Common::KEYCODE_INVALID) { + _key = toupper(_keycode); + + if (_key == Common::KEYCODE_ESCAPE) + // Escape will also 'E'xit out of inventory display + _key = Common::KEYCODE_e; + + if (_key == 'E' || _key == 'L' || _key == 'U' || _key == 'G' + || _key == '-' || _key == '+') { + int temp = _invMode; + + const char *chP = strchr(INVENTORY_COMMANDS, _key); + _invMode = !chP ? 8 : chP - INVENTORY_COMMANDS; + inv.invCommands(true); + + _invMode = temp; + _keyboardInput = true; + if (_key == 'E') + _invMode = STD_MODE; + _selector = -1; + } else { + _selector = -1; + } + } + + if (_selector != _oldSelector) { + if (_oldSelector != -1) { + // Un-highlight + if (_oldSelector >= _invIndex && _oldSelector < (_invIndex + 6)) + inv.doInvLite(_oldSelector, BUTTON_MIDDLE); + } + + if (_selector != -1) + inv.doInvLite(_selector, 235); + + _oldSelector = _selector; + } + + if (events._released || _keyboardInput) { + if ((!found && events._released) && _key == 'E') { + inv.freeInv(); + _infoFlag = true; + clearInfo(); + banishWindow(false); + _key = -1; + events.clearEvents(); + events.setCursor(ARROW); + } else if ((found == 1 && events._released) || (_key == 'L')) { + _invMode = 1; + } else if ((found == 2 && events._released) || (_key == 'U')) { + _invMode = 2; + } else if ((found == 3 && events._released) || (_key == 'G')) { + _invMode = 3; + } else if (((found == 4 && events._released) || _key == ',') && _invIndex) { + if (_invIndex >= 6) + _invIndex -= 6; + else + _invIndex = 0; + + screen.print(Common::Point(INVENTORY_POINTS[4][2], CONTROLS_Y1 + 1), + COMMAND_HIGHLIGHTED, "^^"); + inv.freeGraphics(); + inv.loadGraphics(); + inv.putInv(1); + inv.invCommands(true); + } else if (((found == 5 && events._released) || _key == '-') && _invIndex) { + --_invIndex; + screen.print(Common::Point(INVENTORY_POINTS[4][2], CONTROLS_Y1 + 1), + COMMAND_HIGHLIGHTED, "^"); + inv.freeGraphics(); + inv.loadGraphics(); + inv.putInv(1); + inv.invCommands(true); + } else if (((found == 6 && events._released) || _key == '+') && (inv._holdings - _invIndex) > 6) { + ++_invIndex; + screen.print(Common::Point(INVENTORY_POINTS[6][2], CONTROLS_Y1 + 1), + COMMAND_HIGHLIGHTED, "_"); + inv.freeGraphics(); + inv.loadGraphics(); + inv.putInv(1); + inv.invCommands(true); + } else if (((found == 7 && events._released) || _key == '.') && (inv._holdings - _invIndex) > 6) { + _invIndex += 6; + if ((inv._holdings - 6) < _invIndex) + _invIndex = inv._holdings - 6; + + screen.print(Common::Point(INVENTORY_POINTS[7][2], CONTROLS_Y1 + 1), + COMMAND_HIGHLIGHTED, "_"); + inv.freeGraphics(); + inv.loadGraphics(); + inv.putInv(1); + inv.invCommands(true); + } else { + // If something is being given, make sure it's to a person + if (_invMode == 3) { + if (_bgFound != -1 && scene._bgShapes[_bgFound]._aType == PERSON) + _find = _bgFound; + else + _find = -1; + } else { + _find = _bgFound; + } + + if ((mousePos.y < CONTROLS_Y1) && (_invMode == 1) && (_find >= 0) && (_find < 1000)) { + if (!scene._bgShapes[_find]._examine.empty() && + scene._bgShapes[_find]._examine[0] >= ' ') + inv.doInvJF(); + } else if (_selector != -1 || _find >= 0) { + // Selector is the inventory object that was clicked on, or selected. + // If it's -1, then no inventory item is highlighted yet. Otherwise, + // an object in the scene has been clicked. + + if (_selector != -1 && _invMode == 1 && mousePos.y >(CONTROLS_Y1 + 11)) + inv.doInvJF(); + + if (talk._talkToAbort) + return; + + // Now check for the Use and Give actions. If inv_mode is 3, + // that means GIVE is in effect, _selector is the object being + // given, and _find is the target. + // The same applies to USE, except if _selector is -1, then USE + // is being tried on an object in the scene without an inventory + // object being highlighted first. + + if ((_invMode == 2 || (_selector != -1 && _invMode == 3)) && _find >= 0) { + events._pressed = events._released = false; + _infoFlag = true; + clearInfo(); + + int temp = _selector; // Save the selector + _selector = -1; + + inv.putInv(1); + _selector = temp; // Restore it + temp = _invMode; + _invMode = -1; + inv.invCommands(true); + + _infoFlag = true; + clearInfo(); + banishWindow(false); + _key = -1; + + inv.freeInv(); + + if (_selector >= 0) + // Use/Give inv object with scene object + checkUseAction(scene._bgShapes[_find]._use[0], inv[_selector]._name, + _muse, _find, temp - 2); + else + // Now inv object has been highlighted + checkUseAction(scene._bgShapes[_find]._use[0], "*SELF", _muse, + _find, temp - 2); + + _selector = _oldSelector = -1; + } + } + } + } } /** @@ -1056,4 +1289,10 @@ void UserInterface::banishWindow(bool flag) { _menuMode = STD_MODE; } +void UserInterface::checkUseAction(UseType &use, const Common::String &invName, + const Common::String &msg, int objNum, int giveMode) { + // TODO +} + + } // End of namespace Sherlock diff --git a/engines/sherlock/user_interface.h b/engines/sherlock/user_interface.h index f6e0435f48..d94b2fadc5 100644 --- a/engines/sherlock/user_interface.h +++ b/engines/sherlock/user_interface.h @@ -26,6 +26,7 @@ #include "common/scummsys.h" #include "common/events.h" #include "sherlock/graphics.h" +#include "sherlock/objects.h" #include "sherlock/resources.h" namespace Sherlock { @@ -65,6 +66,7 @@ private: int _oldLook; bool _keyboardInput; int _invMode; + int _invIndex; bool _pause; int _cNum; int _selector, _oldSelector; @@ -73,6 +75,8 @@ private: Common::Rect _windowBounds; Common::String _descStr; int _windowStyle; + int _find; + Common::String _muse; private: void depressButton(int num); @@ -82,6 +86,8 @@ private: void toggleButton(int num); + void buttonPrint(const Common::Point &pt, int color, bool slamIt, const Common::String &str); + void examine(); void lookScreen(const Common::Point &pt); @@ -101,6 +107,9 @@ private: void doControls(); void makeButton(const Common::Rect &bounds, int textX, const Common::String &str); + + void checkUseAction(UseType &use, const Common::String &invName, const Common::String &msg, + int objNum, int giveMode); public: MenuMode _menuMode; int _menuCounter; -- cgit v1.2.3 From 073b7e075ccac02ecab922e03781b3663c92af6c Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 28 Mar 2015 17:36:46 -0400 Subject: SHERLOCK: Implemented lookScreen --- engines/sherlock/screen.h | 3 +- engines/sherlock/user_interface.cpp | 139 +++++++++++++++++++++++++++++++++++- 2 files changed, 139 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/screen.h b/engines/sherlock/screen.h index acd122e0e9..3ac40263c0 100644 --- a/engines/sherlock/screen.h +++ b/engines/sherlock/screen.h @@ -46,7 +46,8 @@ enum { COMMAND_FOREGROUND = 15, BUTTON_TOP = 233, BUTTON_MIDDLE = 244, - BUTTON_BOTTOM = 248 + BUTTON_BOTTOM = 248, + TALK_FOREGROUND = 12 }; class SherlockEngine; diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index 10b13cedbe..9710c3a74a 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -530,12 +530,147 @@ void UserInterface::examine() { } } +/** + * Print the name of an object in the scene + */ void UserInterface::lookScreen(const Common::Point &pt) { - // TODO + Events &events = *_vm->_events; + Inventory &inv = *_vm->_inventory; + Scene &scene = *_vm->_scene; + Screen &screen = *_vm->_screen; + Common::Point mousePos = events.mousePos(); + int temp; + Common::String tempStr; + int x, width, width1, width2 = 0; + + // Don't display anything for right button command + if ((events._rightPressed || events._rightPressed) && !events._pressed) + return; + + if (mousePos.y < CONTROLS_Y && (temp = _bgFound) != -1) { + if (temp != _oldLook) { + _infoFlag = true; + clearInfo(); + + if (temp < 1000) + tempStr = scene._bgShapes[temp]._description; + else + tempStr = scene._bgShapes[temp - 1000]._description; + + _infoFlag = true; + clearInfo(); + + // Only print description if there is one + if (!tempStr.empty() && tempStr[0] != ' ') { + // If inventory is active and an item is selected for a Use or Give action + if ((_menuMode == INV_MODE || _menuMode == USE_MODE || _menuMode == GIVE_MODE) && + (_invMode == 2 || _invMode == 3)) { + width1 = screen.stringWidth(inv[_selector]._name); + + if (_invMode == 2) { + // Using an object + x = width = screen.stringWidth("Use "); + + if (temp < 1000 && scene._bgShapes[temp]._aType != PERSON) + // It's not a person, so make it lowercase + tempStr.setChar(tolower(tempStr[0]), 0); + + x += screen.stringWidth(tempStr); + + // If we're using an inventory object, add in the width + // of the object name and the " on " + if (_selector != -1) { + x += width1; + width2 = screen.stringWidth(" on "); + x += width2; + } + + // If the line will be too long, keep cutting off characters + // until the string will fit + while (x > 280) { + x -= screen.charWidth(tempStr.lastChar()); + tempStr.deleteLastChar(); + } + + int xStart = (SHERLOCK_SCREEN_HEIGHT - x) / 2; + screen.print(Common::Point(xStart, INFO_LINE + 1), + INFO_FOREGROUND, "Use "); + + if (_selector != -1) { + screen.print(Common::Point(xStart + width, INFO_LINE + 1), + TALK_FOREGROUND, inv[_selector]._name.c_str()); + screen.print(Common::Point(xStart + width + width1, INFO_LINE + 1), + INFO_FOREGROUND, " on "); + screen.print(Common::Point(xStart + width + width1 + width2, INFO_LINE + 1), + INFO_FOREGROUND, tempStr.c_str()); + } else { + screen.print(Common::Point(xStart + width, INFO_LINE + 1), + INFO_FOREGROUND, tempStr.c_str()); + } + } else if (temp >= 0 && temp < 1000 && _selector != -1 && + scene._bgShapes[temp]._aType == PERSON) { + // Giving an object to a person + x = width = screen.stringWidth("Give "); + x += width1; + width2 = screen.stringWidth(" to "); + x += width2; + x += screen.stringWidth(tempStr); + + // Ensure string will fit on-screen + while (x > 280) { + x -= screen.charWidth(tempStr.lastChar()); + tempStr.deleteLastChar(); + } + + int xStart = (SHERLOCK_SCREEN_WIDTH - x) / 2; + screen.print(Common::Point(xStart, INFO_LINE + 1), + INFO_FOREGROUND, "Give "); + screen.print(Common::Point(xStart + width, INFO_LINE + 1), + TALK_FOREGROUND, inv[_selector]._name.c_str()); + screen.print(Common::Point(xStart + width + width1, INFO_LINE + 1), + INFO_FOREGROUND, " to "); + screen.print(Common::Point(xStart + width + width1 + width2, INFO_LINE + 1), + INFO_FOREGROUND, tempStr.c_str()); + } + } else { + screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, tempStr.c_str()); + } + + _infoFlag = true; + _oldLook = temp; + } + } + } else { + clearInfo(); + } } +/** + * Gets the item in the inventory the mouse is on and display's it's description + */ void UserInterface::lookInv() { - // TODO + Events &events = *_vm->_events; + Inventory &inv = *_vm->_inventory; + Screen &screen = *_vm->_screen; + Common::Point mousePos = events.mousePos(); + + if (mousePos.x > 15 && mousePos.x < 314 && mousePos.y > (CONTROLS_Y1 + 11) + && mousePos.y < (SHERLOCK_SCREEN_HEIGHT - 2)) { + int temp = (mousePos.x - 6) / 52 + _invIndex; + if (temp < inv._holdings) { + if (temp < inv._holdings) { + clearInfo(); + screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, + inv[temp]._description.c_str()); + _infoFlag = true; + _oldLook = temp; + } + } else { + clearInfo(); + } + } else { + clearInfo(); + } } void UserInterface::doEnvControl() { -- cgit v1.2.3 From c28416f38ef77eef0858756d0b3265c44ad90216 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 28 Mar 2015 20:13:57 -0400 Subject: SHERLOCK: Change the screen _backBuffer to be a pointer --- engines/sherlock/inventory.cpp | 19 +++++++++++++++++- engines/sherlock/inventory.h | 1 + engines/sherlock/objects.cpp | 2 +- engines/sherlock/scalpel/scalpel.cpp | 18 ++++++++--------- engines/sherlock/scene.cpp | 38 ++++++++++++++++++------------------ engines/sherlock/screen.cpp | 19 +++++++++--------- engines/sherlock/screen.h | 3 ++- engines/sherlock/user_interface.cpp | 34 ++++++++++++++++---------------- 8 files changed, 77 insertions(+), 57 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/inventory.cpp b/engines/sherlock/inventory.cpp index 75ee364123..8eb7ecc1a1 100644 --- a/engines/sherlock/inventory.cpp +++ b/engines/sherlock/inventory.cpp @@ -30,6 +30,7 @@ Inventory::Inventory(SherlockEngine *vm) : Common::Array(), _vm(v _invGraphicsLoaded = false; _invIndex = 0; _holdings = 0; + _oldFlag = 0; } Inventory::~Inventory() { @@ -120,8 +121,24 @@ void Inventory::putInv(int slamit) { // TODO } +/** + * Put the game into inventory mode and open the interface window. + * The flag parameter specifies the mode: + * 0 = plain inventory mode + * 2 = use inventory mode + * 3 = give inventory mode + * 128 = Draw window in the back buffer, but don't display it + */ void Inventory::invent(int flag) { - // TODO + Screen &screen = *_vm->_screen; + _oldFlag = 7; + loadInv(); + + if (flag == 128) { + screen._backBuffer = &screen._backBuffer2; + } + + } void Inventory::invCommands(bool slamIt) { diff --git a/engines/sherlock/inventory.h b/engines/sherlock/inventory.h index 0fa8eb0824..1db91292a5 100644 --- a/engines/sherlock/inventory.h +++ b/engines/sherlock/inventory.h @@ -50,6 +50,7 @@ public: int _invIndex; int _holdings; void freeGraphics(); + int _oldFlag; public: Inventory(SherlockEngine *vm); ~Inventory(); diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index 39a9cf8014..d5d24e72af 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -656,7 +656,7 @@ bool Object::checkEndOfSequence() { if (seq == 99) { --_frameNumber; - screen._backBuffer.transBlitFrom(_imageFrame->_frame, _position); + screen._backBuffer1.transBlitFrom(_imageFrame->_frame, _position); screen._backBuffer2.transBlitFrom(_imageFrame->_frame, _position); _type = INVALID; } else { diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp index 3ec971895a..db59434f85 100644 --- a/engines/sherlock/scalpel/scalpel.cpp +++ b/engines/sherlock/scalpel/scalpel.cpp @@ -99,23 +99,23 @@ bool ScalpelEngine::showCityCutscene() { if (finished) { ImageFile titleImages("title2.vgs", true); - _screen->_backBuffer.blitFrom(*_screen); + _screen->_backBuffer1.blitFrom(*_screen); _screen->_backBuffer2.blitFrom(*_screen); // London, England - _screen->_backBuffer.transBlitFrom(titleImages[0], Common::Point(10, 11)); + _screen->_backBuffer1.transBlitFrom(titleImages[0], Common::Point(10, 11)); _screen->randomTransition(); finished = _events->delay(1000, true); // November, 1888 if (finished) { - _screen->_backBuffer.transBlitFrom(titleImages[1], Common::Point(101, 102)); + _screen->_backBuffer1.transBlitFrom(titleImages[1], Common::Point(101, 102)); _screen->randomTransition(); finished = _events->delay(5000, true); } // Transition out the title - _screen->_backBuffer.blitFrom(_screen->_backBuffer2); + _screen->_backBuffer1.blitFrom(_screen->_backBuffer2); _screen->randomTransition(); } @@ -124,21 +124,21 @@ bool ScalpelEngine::showCityCutscene() { if (finished) { ImageFile titleImages("title.vgs", true); - _screen->_backBuffer.blitFrom(*_screen); + _screen->_backBuffer1.blitFrom(*_screen); _screen->_backBuffer2.blitFrom(*_screen); // The Lost Files of - _screen->_backBuffer.transBlitFrom(titleImages[0], Common::Point(75, 6)); + _screen->_backBuffer1.transBlitFrom(titleImages[0], Common::Point(75, 6)); // Sherlock Holmes - _screen->_backBuffer.transBlitFrom(titleImages[1], Common::Point(34, 21)); + _screen->_backBuffer1.transBlitFrom(titleImages[1], Common::Point(34, 21)); // copyright - _screen->_backBuffer.transBlitFrom(titleImages[2], Common::Point(4, 190)); + _screen->_backBuffer1.transBlitFrom(titleImages[2], Common::Point(4, 190)); _screen->verticalTransition(); finished = _events->delay(4000, true); if (finished) { - _screen->_backBuffer.blitFrom(_screen->_backBuffer2); + _screen->_backBuffer1.blitFrom(_screen->_backBuffer2); _screen->randomTransition(); finished = _events->delay(2000); } diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 97f7350ea9..c3afc4a0d4 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -378,13 +378,13 @@ bool Scene::loadScene(const Common::String &filename) { Common::SeekableReadStream *bgStream = !_lzwMode ? rrmStream : decompressLZ(*rrmStream, SHERLOCK_SCREEN_WIDTH * SHERLOCK_SCENE_HEIGHT); - bgStream->read(screen._backBuffer.getPixels(), SHERLOCK_SCREEN_WIDTH * SHERLOCK_SCENE_HEIGHT); + bgStream->read(screen._backBuffer1.getPixels(), SHERLOCK_SCREEN_WIDTH * SHERLOCK_SCENE_HEIGHT); if (_lzwMode) delete bgStream; - // Set the palette - screen._backBuffer2.blitFrom(screen._backBuffer); + // Backup the image and set the palette + screen._backBuffer2.blitFrom(screen._backBuffer1); screen.setPalette(screen._cMap); delete rrmStream; @@ -658,7 +658,7 @@ void Scene::transitionToScene() { if (screen._fadeStyle) screen.randomTransition(); else - screen.blitFrom(screen._backBuffer); + screen.blitFrom(screen._backBuffer1); if (cAnimNum != -1) { CAnim &c = _cAnim[cAnimNum]; @@ -696,7 +696,7 @@ int Scene::toggleObject(const Common::String &name) { void Scene::updateBackground() { People &people = *_vm->_people; Screen &screen = *_vm->_screen; - Surface surface = screen._backBuffer.getSubArea( + Surface surface = screen._backBuffer1.getSubArea( Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT)); Sprite &player = people[AL]; @@ -1055,7 +1055,7 @@ void Scene::doBgAnim() { Sound &sound = *_vm->_sound; Talk &talk = *_vm->_talk; UserInterface &ui = *_vm->_ui; - Surface surface = screen._backBuffer.getSubArea(Common::Rect(0, 0, + Surface surface = screen._backBuffer1.getSubArea(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT)); int cursorId = events.getCursor(); Common::Point mousePos = events.mousePos(); @@ -1126,7 +1126,7 @@ void Scene::doBgAnim() { if (people[AL]._type == CHARACTER) screen.restoreBackground(bounds); else if (people[AL]._type == REMOVE) - screen._backBuffer.blitFrom(screen._backBuffer2, pt, bounds); + screen._backBuffer1.blitFrom(screen._backBuffer2, pt, bounds); for (uint idx = 0; idx < _bgShapes.size(); ++idx) { Object &o = _bgShapes[idx]; @@ -1145,7 +1145,7 @@ void Scene::doBgAnim() { Object &o = _bgShapes[idx]; if (o._type == NO_SHAPE && ((o._flags & 1) == 0)) { // Restore screen area - screen._backBuffer.blitFrom(screen._backBuffer2, o._position, + screen._backBuffer1.blitFrom(screen._backBuffer2, o._position, Common::Rect(o._position.x, o._position.y, o._position.x + o._noShapeSize.x, o._position.y + o._noShapeSize.y)); @@ -1191,14 +1191,14 @@ void Scene::doBgAnim() { for (uint idx = 0; idx < _bgShapes.size(); ++idx) { Object &o = _bgShapes[idx]; if (o._type == ACTIVE_BG_SHAPE && o._misc == BEHIND) - screen._backBuffer.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2); + screen._backBuffer1.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2); } // Draw all canimations which are behind the person for (uint idx = 0; idx < _canimShapes.size(); ++idx) { Object &o = _canimShapes[idx]; if (o._type == ACTIVE_BG_SHAPE && o._misc == BEHIND) { - screen._backBuffer.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2); + screen._backBuffer1.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2); } } @@ -1206,14 +1206,14 @@ void Scene::doBgAnim() { for (uint idx = 0; idx < _bgShapes.size(); ++idx) { Object &o = _bgShapes[idx]; if (o._type == ACTIVE_BG_SHAPE && o._misc == NORMAL_BEHIND) - screen._backBuffer.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2); + screen._backBuffer1.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2); } // Draw all canimations which are NORMAL and behind the person for (uint idx = 0; idx < _canimShapes.size(); ++idx) { Object &o = _canimShapes[idx]; if (o._type == ACTIVE_BG_SHAPE && o._misc == NORMAL_BEHIND) { - screen._backBuffer.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2); + screen._backBuffer1.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2); } } @@ -1226,7 +1226,7 @@ void Scene::doBgAnim() { bool flipped = people[AL]._frameNumber == WALK_LEFT || people[AL]._frameNumber == STOP_LEFT || people[AL]._frameNumber == WALK_UPLEFT || people[AL]._frameNumber == STOP_UPLEFT || people[AL]._frameNumber == WALK_DOWNRIGHT || people[AL]._frameNumber == STOP_DOWNRIGHT; - screen._backBuffer.transBlitFrom(people[AL]._imageFrame->_frame, + screen._backBuffer1.transBlitFrom(people[AL]._imageFrame->_frame, Common::Point(tempX, people[AL]._position.y / 100 - people[AL]._imageFrame->_frame.h), flipped); } @@ -1234,14 +1234,14 @@ void Scene::doBgAnim() { for (uint idx = 0; idx < _bgShapes.size(); ++idx) { Object &o = _bgShapes[idx]; if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == NORMAL_FORWARD) - screen._backBuffer.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2); + screen._backBuffer1.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2); } // Draw all static and active canimations that are NORMAL and are in front of the person for (uint idx = 0; idx < _canimShapes.size(); ++idx) { Object &o = _canimShapes[idx]; if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == NORMAL_BEHIND) { - screen._backBuffer.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2); + screen._backBuffer1.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2); } } @@ -1249,19 +1249,19 @@ void Scene::doBgAnim() { for (uint idx = 0; idx < _bgShapes.size(); ++idx) { Object &o = _bgShapes[idx]; if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == FORWARD) - screen._backBuffer.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2); + screen._backBuffer1.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2); } // Draw any active portrait if (people._portraitLoaded && people._portrait._type == ACTIVE_BG_SHAPE) - screen._backBuffer.transBlitFrom(people._portrait._imageFrame->_frame, + screen._backBuffer1.transBlitFrom(people._portrait._imageFrame->_frame, people._portrait._position, people._portrait._flags & 2); // Draw all static and active canimations that are in front of the person for (uint idx = 0; idx < _canimShapes.size(); ++idx) { Object &o = _canimShapes[idx]; if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == FORWARD) { - screen._backBuffer.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2); + screen._backBuffer1.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2); } } @@ -1269,7 +1269,7 @@ void Scene::doBgAnim() { for (uint idx = 0; idx < _bgShapes.size(); ++idx) { Object &o = _bgShapes[idx]; if (o._type == NO_SHAPE && (o._flags & 1) == 0) - screen._backBuffer.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2); + screen._backBuffer1.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2); } // Bring the newly built picture to the screen diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp index def20612b7..f1562e2468 100644 --- a/engines/sherlock/screen.cpp +++ b/engines/sherlock/screen.cpp @@ -29,8 +29,9 @@ namespace Sherlock { Screen::Screen(SherlockEngine *vm) : Surface(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT), _vm(vm), - _backBuffer(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT), - _backBuffer2(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT) { + _backBuffer1(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT), + _backBuffer2(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT), + _backBuffer(&_backBuffer1) { _transitionSeed = 1; _fadeStyle = false; _font = nullptr; @@ -201,7 +202,7 @@ void Screen::randomTransition() { int offset = _transitionSeed & 65535; if (offset < (SHERLOCK_SCREEN_WIDTH * SHERLOCK_SCREEN_HEIGHT)) - *((byte *)getPixels() + offset) = *((const byte *)_backBuffer.getPixels() + offset); + *((byte *)getPixels() + offset) = *((const byte *)_backBuffer->getPixels() + offset); if (idx != 0 && (idx % 100) == 0) { // Ensure there's a full screen dirty rect for the next frame update @@ -214,7 +215,7 @@ void Screen::randomTransition() { } // Make sure everything has been transferred - blitFrom(_backBuffer); + blitFrom(_backBuffer1); } /** @@ -232,7 +233,7 @@ void Screen::verticalTransition() { _vm->getRandomNumber(3) + 1; if (temp) { - blitFrom(_backBuffer, Common::Point(xp, table[xp]), + blitFrom(_backBuffer1, Common::Point(xp, table[xp]), Common::Rect(xp, table[xp], xp + 1, table[xp] + temp)); table[xp] += temp; } @@ -251,7 +252,7 @@ void Screen::restoreBackground(const Common::Rect &r) { tempRect.clip(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT)); if (tempRect.isValidRect()) - _backBuffer.blitFrom(_backBuffer2, Common::Point(tempRect.left, tempRect.top), tempRect); + _backBuffer1.blitFrom(_backBuffer2, Common::Point(tempRect.left, tempRect.top), tempRect); } } @@ -271,7 +272,7 @@ void Screen::slamRect(const Common::Rect &r) { tempRect.clip(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); if (tempRect.isValidRect()) - blitFrom(_backBuffer, Common::Point(tempRect.left, tempRect.top), tempRect); + blitFrom(*_backBuffer, Common::Point(tempRect.left, tempRect.top), tempRect); } } @@ -394,7 +395,7 @@ void Screen::writeString(const Common::String &str, const Common::Point &pt, int else { assert(*c > ' ' && *c <= '~'); ImageFrame &frame = (*_font)[*c - 33]; - _backBuffer.transBlitFrom(frame, charPos, false, color); + _backBuffer->transBlitFrom(frame, charPos, false, color); charPos.x += frame._frame.w + 1; } } @@ -404,7 +405,7 @@ void Screen::writeString(const Common::String &str, const Common::Point &pt, int * Fills an area on the back buffer, and then copies it to the screen */ void Screen::vgaBar(const Common::Rect &r, int color) { - _backBuffer.fillRect(r, color); + _backBuffer->fillRect(r, color); slamRect(r); } diff --git a/engines/sherlock/screen.h b/engines/sherlock/screen.h index 3ac40263c0..7d07cfa062 100644 --- a/engines/sherlock/screen.h +++ b/engines/sherlock/screen.h @@ -69,7 +69,8 @@ private: protected: virtual void addDirtyRect(const Common::Rect &r); public: - Surface _backBuffer, _backBuffer2; + Surface _backBuffer1, _backBuffer2; + Surface *_backBuffer; bool _fadeStyle; byte _cMap[PALETTE_SIZE]; byte _sMap[PALETTE_SIZE]; diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index 9710c3a74a..dbc9108212 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -105,7 +105,7 @@ void UserInterface::drawInterface() { Screen &screen = *_vm->_screen; screen._backBuffer2.fillRect(0, INFO_LINE, SHERLOCK_SCREEN_WIDTH, INFO_LINE + 10, INFO_BLACK); - screen._backBuffer.transBlitFrom((*_controlPanel)[0], Common::Point(0, CONTROLS_Y)); + screen._backBuffer1.transBlitFrom((*_controlPanel)[0], Common::Point(0, CONTROLS_Y)); screen._backBuffer2.transBlitFrom((*_controlPanel)[0], Common::Point(0, CONTROLS_Y)); } @@ -376,7 +376,7 @@ void UserInterface::depressButton(int num) { Common::Point pt(MENU_POINTS[num][0], MENU_POINTS[num][1]); Graphics::Surface &s = (*_controls)[num]._frame; - screen._backBuffer.transBlitFrom(s, pt); + screen._backBuffer1.transBlitFrom(s, pt); screen.slamArea(pt.x, pt.y, pt.x + s.w, pt.y + s.h); } @@ -389,7 +389,7 @@ void UserInterface::restoreButton(int num) { Common::Point pt(MENU_POINTS[num][0], MENU_POINTS[num][1]); Graphics::Surface &frame = (*_controls)[num]._frame; - screen._backBuffer.blitFrom(screen._backBuffer2, pt, + screen._backBuffer1.blitFrom(screen._backBuffer2, pt, Common::Rect(pt.x, pt.y, pt.x + 90, pt.y + 19)); screen.slamArea(pt.x, pt.y, pt.x + frame.w, pt.y + frame.h); @@ -443,7 +443,7 @@ void UserInterface::toggleButton(int num) { Graphics::Surface &s = (*_controls)[num]._frame; Common::Point pt(MENU_POINTS[num][0], MENU_POINTS[num][1]); - screen._backBuffer.transBlitFrom(s, pt); + screen._backBuffer1.transBlitFrom(s, pt); screen.slamArea(pt.x, pt.y, pt.x + s.w, pt.y + s.h); } } else { @@ -1199,7 +1199,7 @@ void UserInterface::printObjectDesc(const Common::String &str, bool firstTime) { return; } - Surface &bb = screen._backBuffer; + Surface &bb = *screen._backBuffer; if (firstTime) { // Only draw the border on the first call _infoFlag = true; @@ -1286,10 +1286,10 @@ void UserInterface::printObjectDesc(const Common::String &str, bool firstTime) { Surface tempSurface(SHERLOCK_SCREEN_WIDTH, (SHERLOCK_SCREEN_HEIGHT - CONTROLS_Y)); Common::Rect r(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT); - tempSurface.blitFrom(screen._backBuffer, Common::Point(0, 0), r); + tempSurface.blitFrom(screen._backBuffer1, Common::Point(0, 0), r); // Remove drawn window with original user interface - screen._backBuffer.blitFrom(screen._backBuffer2, + screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(0, CONTROLS_Y), r); // Display the window gradually on-screen @@ -1318,7 +1318,7 @@ void UserInterface::makeButton(const Common::Rect &bounds, int textX, const Common::String &str) { Screen &screen = *_vm->_screen; - Surface &bb = screen._backBuffer; + Surface &bb = *screen._backBuffer; bb.fillRect(Common::Rect(bounds.left, bounds.top, bounds.right, bounds.top + 1), BUTTON_TOP); bb.fillRect(Common::Rect(bounds.left, bounds.top, bounds.left + 1, bounds.bottom), BUTTON_TOP); bb.fillRect(Common::Rect(bounds.right - 1, bounds.top, bounds.right, bounds.bottom), BUTTON_BOTTOM); @@ -1343,7 +1343,7 @@ void UserInterface::summonWindow(const Surface &bgSurface) { // Gradually slide up the display of the window for (int idx = 1; idx <= bgSurface.h; idx += 2) { - screen._backBuffer.blitFrom(bgSurface, Common::Point(0, SHERLOCK_SCREEN_HEIGHT - idx), + screen._backBuffer->blitFrom(bgSurface, Common::Point(0, SHERLOCK_SCREEN_HEIGHT - idx), Common::Rect(0, 0, bgSurface.w, idx)); screen.slamRect(Common::Rect(0, SHERLOCK_SCREEN_HEIGHT - idx, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); @@ -1352,7 +1352,7 @@ void UserInterface::summonWindow(const Surface &bgSurface) { } // Final display of the entire window - screen._backBuffer.blitFrom(bgSurface, Common::Point(0, CONTROLS_Y), + screen._backBuffer->blitFrom(bgSurface, Common::Point(0, CONTROLS_Y), Common::Rect(0, 0, bgSurface.w, bgSurface.h)); screen.slamArea(0, CONTROLS_Y, bgSurface.w, bgSurface.h); @@ -1374,13 +1374,13 @@ void UserInterface::banishWindow(bool flag) { if (_windowStyle) { for (int idx = 2; idx < (SHERLOCK_SCREEN_HEIGHT - CONTROLS_Y); idx += 2) { // Shift the window down by 2 lines - byte *pSrc = (byte *)screen._backBuffer.getBasePtr(0, CONTROLS_Y + idx - 2); - byte *pSrcEnd = (byte *)screen._backBuffer.getBasePtr(0, SHERLOCK_SCREEN_HEIGHT - 2); - byte *pDest = (byte *)screen._backBuffer.getBasePtr(0, SHERLOCK_SCREEN_HEIGHT); + byte *pSrc = (byte *)screen._backBuffer1.getBasePtr(0, CONTROLS_Y + idx - 2); + byte *pSrcEnd = (byte *)screen._backBuffer1.getBasePtr(0, SHERLOCK_SCREEN_HEIGHT - 2); + byte *pDest = (byte *)screen._backBuffer1.getBasePtr(0, SHERLOCK_SCREEN_HEIGHT); Common::copy_backward(pSrc, pSrcEnd, pDest); // Restore lines from the ui in the secondary back buffer - screen._backBuffer.blitFrom(screen._backBuffer2, + screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(0, CONTROLS_Y), Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, CONTROLS_Y + idx)); @@ -1390,14 +1390,14 @@ void UserInterface::banishWindow(bool flag) { } // Restore final two old lines - screen._backBuffer.blitFrom(screen._backBuffer2, + screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(0, SHERLOCK_SCREEN_HEIGHT - 2), Common::Rect(0, SHERLOCK_SCREEN_HEIGHT - 2, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); screen.slamArea(0, SHERLOCK_SCREEN_HEIGHT - 2, SHERLOCK_SCREEN_WIDTH, 2); } else { // Restore old area to completely erase window - screen._backBuffer.blitFrom(screen._backBuffer2, + screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(0, CONTROLS_Y), Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); screen.slamRect(Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, @@ -1408,7 +1408,7 @@ void UserInterface::banishWindow(bool flag) { for (int idx = 1; idx < (SHERLOCK_SCREEN_HEIGHT - CONTROLS_Y1); idx += 2) { byte *pSrc = (byte *)screen._backBuffer2.getBasePtr(0, CONTROLS_Y1); byte *pSrcEnd = (byte *)screen._backBuffer2.getBasePtr(0, CONTROLS_Y1 + idx); - byte *pDest = (byte *)screen._backBuffer.getBasePtr(0, SHERLOCK_SCREEN_HEIGHT - idx); + byte *pDest = (byte *)screen._backBuffer1.getBasePtr(0, SHERLOCK_SCREEN_HEIGHT - idx); Common::copy(pSrc, pSrcEnd, pDest); screen.slamArea(0, SHERLOCK_SCREEN_HEIGHT - idx, SHERLOCK_SCREEN_WIDTH, -- cgit v1.2.3 From 7fec58a57d9c45f7b899f67042af57b54ca80252 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 28 Mar 2015 22:31:18 -0400 Subject: SHERLOCK: Beginnings of inventory display --- engines/sherlock/inventory.cpp | 65 ++++++++++++++++++++- engines/sherlock/inventory.h | 3 +- engines/sherlock/scene.h | 2 - engines/sherlock/screen.cpp | 18 ++++++ engines/sherlock/screen.h | 2 + engines/sherlock/user_interface.cpp | 109 +++++++++++++++++++----------------- engines/sherlock/user_interface.h | 18 ++++-- 7 files changed, 156 insertions(+), 61 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/inventory.cpp b/engines/sherlock/inventory.cpp index 8eb7ecc1a1..c39bba4f5b 100644 --- a/engines/sherlock/inventory.cpp +++ b/engines/sherlock/inventory.cpp @@ -31,6 +31,7 @@ Inventory::Inventory(SherlockEngine *vm) : Common::Array(), _vm(v _invIndex = 0; _holdings = 0; _oldFlag = 0; + _invFlag = 0; } Inventory::~Inventory() { @@ -129,8 +130,11 @@ void Inventory::putInv(int slamit) { * 3 = give inventory mode * 128 = Draw window in the back buffer, but don't display it */ -void Inventory::invent(int flag) { +void Inventory::drawInventory(int flag) { Screen &screen = *_vm->_screen; + UserInterface &ui = *_vm->_ui; + int tempFlag = flag; + _oldFlag = 7; loadInv(); @@ -138,7 +142,64 @@ void Inventory::invent(int flag) { screen._backBuffer = &screen._backBuffer2; } - + // Draw the window background + Surface &bb = *screen._backBuffer; + bb.fillRect(Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH, CONTROLS_Y1 + 10), BORDER_COLOR); + bb.fillRect(Common::Rect(0, CONTROLS_Y1 + 10, 2, SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR); + bb.fillRect(Common::Rect(SHERLOCK_SCREEN_WIDTH - 2, CONTROLS_Y1 + 10, + SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR); + bb.fillRect(Common::Rect(0, SHERLOCK_SCREEN_HEIGHT - 2, SHERLOCK_SCREEN_WIDTH, + SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR); + bb.fillRect(Common::Rect(2, CONTROLS_Y1 + 10, SHERLOCK_SCREEN_WIDTH - 2, SHERLOCK_SCREEN_HEIGHT - 2), + INV_BACKGROUND); + + // Draw the buttons + screen.makeButton(Common::Rect(INVENTORY_POINTS[0][0], CONTROLS_Y1, INVENTORY_POINTS[0][1], + CONTROLS_Y1 + 9), INVENTORY_POINTS[0][2] - screen.stringWidth("Exit") / 2, "Exit"); + screen.makeButton(Common::Rect(INVENTORY_POINTS[1][0], CONTROLS_Y1, INVENTORY_POINTS[1][1], + CONTROLS_Y1 + 9), INVENTORY_POINTS[1][2] - screen.stringWidth("Look") / 2, "Look"); + screen.makeButton(Common::Rect(INVENTORY_POINTS[2][0], CONTROLS_Y1, INVENTORY_POINTS[2][1], + CONTROLS_Y1 + 9), INVENTORY_POINTS[2][2] - screen.stringWidth("Use") / 2, "Use"); + screen.makeButton(Common::Rect(INVENTORY_POINTS[3][0], CONTROLS_Y1, INVENTORY_POINTS[3][1], + CONTROLS_Y1 + 9), INVENTORY_POINTS[3][2] - screen.stringWidth("Give") / 2, "Give"); + screen.makeButton(Common::Rect(INVENTORY_POINTS[4][0], CONTROLS_Y1, INVENTORY_POINTS[4][1], + CONTROLS_Y1 + 9), INVENTORY_POINTS[4][2], "^^"); + screen.makeButton(Common::Rect(INVENTORY_POINTS[5][0], CONTROLS_Y1, INVENTORY_POINTS[5][1], + CONTROLS_Y1 + 9), INVENTORY_POINTS[5][2], "^"); + screen.makeButton(Common::Rect(INVENTORY_POINTS[6][0], CONTROLS_Y1, INVENTORY_POINTS[6][1], + CONTROLS_Y1 + 9), INVENTORY_POINTS[6][2], "_"); + screen.makeButton(Common::Rect(INVENTORY_POINTS[7][0], CONTROLS_Y1, INVENTORY_POINTS[7][1], + CONTROLS_Y1 + 9), INVENTORY_POINTS[7][2], "__"); + + if (tempFlag == 128) + flag = 1; + ui._invMode = flag; + + if (flag) { + ui._oldKey = INVENTORY_COMMANDS[flag]; + _oldFlag = flag; + } else { + ui._oldKey = -1; + _invFlag = 6; + } + + invCommands(0); + putInv(0); + + if (tempFlag != 128) { + if (!ui._windowStyle) { + screen.slamRect(Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); + } else { + ui.summonWindow(false, CONTROLS_Y1); + } + + ui._windowOpen = true; + } else { + // Reset the screen back buffer to the first buffer now that drawing is done + screen._backBuffer = &screen._backBuffer1; + } + + ui._oldUse = -1; } void Inventory::invCommands(bool slamIt) { diff --git a/engines/sherlock/inventory.h b/engines/sherlock/inventory.h index 1db91292a5..7785250e8c 100644 --- a/engines/sherlock/inventory.h +++ b/engines/sherlock/inventory.h @@ -51,6 +51,7 @@ public: int _holdings; void freeGraphics(); int _oldFlag; + int _invFlag; public: Inventory(SherlockEngine *vm); ~Inventory(); @@ -65,7 +66,7 @@ public: void putInv(int slamit); - void invent(int flag); + void drawInventory(int flag); void invCommands(bool slamIt); diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h index 007f910b10..d89a47e560 100644 --- a/engines/sherlock/scene.h +++ b/engines/sherlock/scene.h @@ -34,8 +34,6 @@ namespace Sherlock { #define SCENES_COUNT 63 #define MAX_ZONES 40 #define INFO_LINE 140 -#define CONTROLS_Y 138 -#define CONTROLS_Y1 151 enum InvMode { INVMODE_0 = 0, diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp index f1562e2468..16d590c0f4 100644 --- a/engines/sherlock/screen.cpp +++ b/engines/sherlock/screen.cpp @@ -409,4 +409,22 @@ void Screen::vgaBar(const Common::Rect &r, int color) { slamRect(r); } +/** + * Draws a button for use in the inventory, talk, and examine dialogs. + */ +void Screen::makeButton(const Common::Rect &bounds, int textX, + const Common::String &str) { + + Surface &bb = *_backBuffer; + bb.fillRect(Common::Rect(bounds.left, bounds.top, bounds.right, bounds.top + 1), BUTTON_TOP); + bb.fillRect(Common::Rect(bounds.left, bounds.top, bounds.left + 1, bounds.bottom), BUTTON_TOP); + bb.fillRect(Common::Rect(bounds.right - 1, bounds.top, bounds.right, bounds.bottom), BUTTON_BOTTOM); + bb.fillRect(Common::Rect(bounds.left + 1, bounds.bottom - 1, bounds.right, bounds.bottom), BUTTON_BOTTOM); + bb.fillRect(Common::Rect(bounds.left + 1, bounds.top + 1, bounds.right - 1, bounds.bottom - 1), BUTTON_MIDDLE); + + gPrint(Common::Point(textX, bounds.top), COMMAND_HIGHLIGHTED, "%c", str[0]); + gPrint(Common::Point(textX + charWidth(str[0]), bounds.top), + COMMAND_FOREGROUND, "%s", str.c_str() + 1); +} + } // End of namespace Sherlock diff --git a/engines/sherlock/screen.h b/engines/sherlock/screen.h index 7d07cfa062..f33bbfceab 100644 --- a/engines/sherlock/screen.h +++ b/engines/sherlock/screen.h @@ -112,6 +112,8 @@ public: int charWidth(char c); void vgaBar(const Common::Rect &r, int color); + + void makeButton(const Common::Rect &bounds, int textX, const Common::String &str); }; } // End of namespace Sherlock diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index dbc9108212..a993965429 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -54,6 +54,7 @@ const int INVENTORY_POINTS[8][3] = { }; const char COMMANDS[13] = "LMTPOCIUGJFS"; +const char INVENTORY_COMMANDS[9] = { "ELUG-+,." }; const char *const PRESS_KEY_FOR_MORE = "Press any Key for More."; const char *const PRESS_KEY_TO_CONTINUE = "Press any Key to Continue."; @@ -85,6 +86,7 @@ UserInterface::UserInterface(SherlockEngine *vm) : _vm(vm) { SHERLOCK_SCREEN_HEIGHT - 1); _windowStyle = 1; // Sliding windows _find = 0; + _oldUse = 0; } UserInterface::~UserInterface() { @@ -686,7 +688,6 @@ void UserInterface::doInvControl() { Scene &scene = *_vm->_scene; Screen &screen = *_vm->_screen; Talk &talk = *_vm->_talk; - const char INVENTORY_COMMANDS[9] = { "ELUG-+,." }; int colors[8]; Common::Point mousePos = events.mousePos(); @@ -956,7 +957,7 @@ void UserInterface::doLookControl() { tempSurface.blitFrom(screen._backBuffer2, Common::Point(0, 0), Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); - inv.invent(128); + inv.drawInventory(128); banishWindow(true); // Restore the ui @@ -1060,19 +1061,19 @@ void UserInterface::doMainControl() { pushButton(6); _selector = _oldSelector = -1; _menuMode = INV_MODE; - inv.invent(1); + inv.drawInventory(1); break; case 'U': pushButton(7); _selector = _oldSelector = -1; _menuMode = USE_MODE; - inv.invent(2); + inv.drawInventory(2); break; case 'G': pushButton(8); _selector = _oldSelector = -1; _menuMode = GIVE_MODE; - inv.invent(3); + inv.drawInventory(3); break; case 'J': pushButton(9); @@ -1259,7 +1260,7 @@ void UserInterface::printObjectDesc(const Common::String &str, bool firstTime) { // Handle display depending on whether all the message was shown if (!endOfStr) { - makeButton(Common::Rect(46, CONTROLS_Y, 272, CONTROLS_Y + 10), + screen.makeButton(Common::Rect(46, CONTROLS_Y, 272, CONTROLS_Y + 10), (SHERLOCK_SCREEN_WIDTH - screen.stringWidth(PRESS_KEY_FOR_MORE)) / 2, PRESS_KEY_FOR_MORE); screen.gPrint(Common::Point((SHERLOCK_SCREEN_WIDTH - @@ -1267,7 +1268,7 @@ void UserInterface::printObjectDesc(const Common::String &str, bool firstTime) { COMMAND_FOREGROUND, "P"); _descStr = msgP; } else { - makeButton(Common::Rect(46, CONTROLS_Y, 272, CONTROLS_Y + 10), + screen.makeButton(Common::Rect(46, CONTROLS_Y, 272, CONTROLS_Y + 10), (SHERLOCK_SCREEN_WIDTH - screen.stringWidth(PRESS_KEY_TO_CONTINUE)) / 2, PRESS_KEY_TO_CONTINUE); screen.gPrint(Common::Point((SHERLOCK_SCREEN_WIDTH - @@ -1280,20 +1281,9 @@ void UserInterface::printObjectDesc(const Common::String &str, bool firstTime) { if (!_windowStyle) { screen.slamRect(Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); - } - else { - // Extract the window that's been drawn on the back buffer - Surface tempSurface(SHERLOCK_SCREEN_WIDTH, - (SHERLOCK_SCREEN_HEIGHT - CONTROLS_Y)); - Common::Rect r(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT); - tempSurface.blitFrom(screen._backBuffer1, Common::Point(0, 0), r); - - // Remove drawn window with original user interface - screen._backBuffer1.blitFrom(screen._backBuffer2, - Common::Point(0, CONTROLS_Y), r); - - // Display the window gradually on-screen - summonWindow(tempSurface); + } else { + // Display the window + summonWindow(); } _selector = _oldSelector = -1; @@ -1311,29 +1301,10 @@ void UserInterface::printObjectDesc() { printObjectDesc(_cAnimStr, true); } -/** - * Draws a button for use in the inventory, talk, and examine dialogs. - */ -void UserInterface::makeButton(const Common::Rect &bounds, int textX, - const Common::String &str) { - Screen &screen = *_vm->_screen; - - Surface &bb = *screen._backBuffer; - bb.fillRect(Common::Rect(bounds.left, bounds.top, bounds.right, bounds.top + 1), BUTTON_TOP); - bb.fillRect(Common::Rect(bounds.left, bounds.top, bounds.left + 1, bounds.bottom), BUTTON_TOP); - bb.fillRect(Common::Rect(bounds.right - 1, bounds.top, bounds.right, bounds.bottom), BUTTON_BOTTOM); - bb.fillRect(Common::Rect(bounds.left + 1, bounds.bottom - 1, bounds.right, bounds.bottom), BUTTON_BOTTOM); - bb.fillRect(Common::Rect(bounds.left + 1, bounds.top + 1, bounds.right - 1, bounds.bottom - 1), BUTTON_MIDDLE); - - screen.gPrint(Common::Point(textX, bounds.top), COMMAND_HIGHLIGHTED, "%c", str[0]); - screen.gPrint(Common::Point(textX + screen.charWidth(str[0]), bounds.top), - COMMAND_FOREGROUND, "%s", str.c_str() + 1); -} - /** * Displays a passed window by gradually scrolling it vertically on-screen */ -void UserInterface::summonWindow(const Surface &bgSurface) { +void UserInterface::summonWindow(const Surface &bgSurface, bool slideUp) { Events &events = *_vm->_events; Screen &screen = *_vm->_screen; @@ -1341,34 +1312,68 @@ void UserInterface::summonWindow(const Surface &bgSurface) { // A window is already open, so can't open another one return; - // Gradually slide up the display of the window - for (int idx = 1; idx <= bgSurface.h; idx += 2) { - screen._backBuffer->blitFrom(bgSurface, Common::Point(0, SHERLOCK_SCREEN_HEIGHT - idx), - Common::Rect(0, 0, bgSurface.w, idx)); - screen.slamRect(Common::Rect(0, SHERLOCK_SCREEN_HEIGHT - idx, - SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); + if (slideUp) { + // Gradually slide up the display of the window + for (int idx = 1; idx <= bgSurface.h; idx += 2) { + screen._backBuffer->blitFrom(bgSurface, Common::Point(0, SHERLOCK_SCREEN_HEIGHT - idx), + Common::Rect(0, 0, bgSurface.w, idx)); + screen.slamRect(Common::Rect(0, SHERLOCK_SCREEN_HEIGHT - idx, + SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); - events.delay(10); + events.delay(10); + } + } else { + // Gradually slide down the display of the window + for (int idx = 1; idx <= bgSurface.h; idx += 2) { + screen._backBuffer->blitFrom(bgSurface, + Common::Point(0, SHERLOCK_SCREEN_HEIGHT - bgSurface.h), + Common::Rect(0, bgSurface.h - idx, bgSurface.w, bgSurface.h)); + screen.slamRect(Common::Rect(0, SHERLOCK_SCREEN_HEIGHT - bgSurface.h, + SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT - bgSurface.h + idx)); + + events.delay(10); + } } // Final display of the entire window - screen._backBuffer->blitFrom(bgSurface, Common::Point(0, CONTROLS_Y), + screen._backBuffer->blitFrom(bgSurface, Common::Point(0, + SHERLOCK_SCREEN_HEIGHT - bgSurface.h), Common::Rect(0, 0, bgSurface.w, bgSurface.h)); - screen.slamArea(0, CONTROLS_Y, bgSurface.w, bgSurface.h); + screen.slamArea(0, SHERLOCK_SCREEN_HEIGHT - bgSurface.h, bgSurface.w, bgSurface.h); _windowOpen = true; } +/** + * Slide the window stored in the back buffer onto the screen + */ +void UserInterface::summonWindow(bool slideUp, int height) { + Screen &screen = *_vm->_screen; + + // Extract the window that's been drawn on the back buffer + Surface tempSurface(SHERLOCK_SCREEN_WIDTH, + (SHERLOCK_SCREEN_HEIGHT - height)); + Common::Rect r(0, height, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT); + tempSurface.blitFrom(screen._backBuffer1, Common::Point(0, 0), r); + + // Remove drawn window with original user interface + screen._backBuffer1.blitFrom(screen._backBuffer2, + Common::Point(0, height), r); + + // Display the window gradually on-screen + summonWindow(tempSurface, slideUp); +} + /** * Close a currently open window * @param flag 0 = slide old window down, 1 = slide prior UI back up */ -void UserInterface::banishWindow(bool flag) { +void UserInterface::banishWindow(bool slideUp) { Events &events = *_vm->_events; Screen &screen = *_vm->_screen; if (_windowOpen) { - if (flag || !_windowStyle) { + if (slideUp || !_windowStyle) { // Slide window down // Only slide the window if the window style allows it if (_windowStyle) { diff --git a/engines/sherlock/user_interface.h b/engines/sherlock/user_interface.h index d94b2fadc5..87fd4a5e99 100644 --- a/engines/sherlock/user_interface.h +++ b/engines/sherlock/user_interface.h @@ -31,6 +31,9 @@ namespace Sherlock { +#define CONTROLS_Y 138 +#define CONTROLS_Y1 151 + enum MenuMode { STD_MODE = 0, LOOK_MODE = 1, @@ -47,9 +50,16 @@ enum MenuMode { SETUP_MODE = 12 }; +extern const int MENU_POINTS[12][4]; + +extern const int INVENTORY_POINTS[8][3]; +extern const char INVENTORY_COMMANDS[9]; + class SherlockEngine; +class Inventory; class UserInterface { + friend class Inventory; private: SherlockEngine *_vm; ImageFile *_controlPanel; @@ -77,6 +87,7 @@ private: int _windowStyle; int _find; Common::String _muse; + int _oldUse; private: void depressButton(int num); @@ -106,8 +117,6 @@ private: void environment(); void doControls(); - void makeButton(const Common::Rect &bounds, int textX, const Common::String &str); - void checkUseAction(UseType &use, const Common::String &invName, const Common::String &msg, int objNum, int giveMode); public: @@ -132,8 +141,9 @@ public: void printObjectDesc(const Common::String &str, bool firstTime); void printObjectDesc(); - void summonWindow(const Surface &bgSurface); - void banishWindow(bool flag); + void summonWindow(const Surface &bgSurface, bool slideUp = true); + void summonWindow(bool slideUp = true, int height = CONTROLS_Y); + void banishWindow(bool slideUp = true); }; } // End of namespace Sherlock -- cgit v1.2.3 From 3149ce0204f658e7420f16a151710f43052506f2 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 29 Mar 2015 09:52:23 -0400 Subject: SHERLOCK: Added inventory list and display images in inventory mode --- engines/sherlock/inventory.cpp | 149 ++++++++++++++++++++++++++++++++--- engines/sherlock/inventory.h | 6 +- engines/sherlock/scalpel/scalpel.cpp | 25 ++++++ engines/sherlock/scalpel/scalpel.h | 2 + engines/sherlock/screen.cpp | 47 ++++++++++- engines/sherlock/screen.h | 12 ++- engines/sherlock/user_interface.cpp | 86 ++++++++++---------- engines/sherlock/user_interface.h | 4 - 8 files changed, 262 insertions(+), 69 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/inventory.cpp b/engines/sherlock/inventory.cpp index c39bba4f5b..a7691fc866 100644 --- a/engines/sherlock/inventory.cpp +++ b/engines/sherlock/inventory.cpp @@ -25,6 +25,14 @@ namespace Sherlock { +InventoryItem::InventoryItem(int requiredFlag, const Common::String &name, + const Common::String &description, const Common::String &examine) : + _requiredFlag(requiredFlag), _name(name), _description(description), + _examine(examine), _lookFlag(0) { +} + +/*----------------------------------------------------------------*/ + Inventory::Inventory(SherlockEngine *vm) : Common::Array(), _vm(vm) { Common::fill(&_invShapes[0], &_invShapes[MAX_VISIBLE_INVENTORY], (ImageFile *)nullptr); _invGraphicsLoaded = false; @@ -32,6 +40,7 @@ Inventory::Inventory(SherlockEngine *vm) : Common::Array(), _vm(v _holdings = 0; _oldFlag = 0; _invFlag = 0; + _invMode = 0; } Inventory::~Inventory() { @@ -77,6 +86,8 @@ void Inventory::loadInv() { } delete stream; + + loadGraphics(); } /** @@ -89,11 +100,11 @@ void Inventory::loadGraphics() { // Default all inventory slots to empty Common::fill(&_invShapes[0], &_invShapes[MAX_VISIBLE_INVENTORY], (ImageFile *)nullptr); - for (int idx = _invIndex; (idx < _holdings) && (idx - _invIndex) < 6; ++idx) { + for (int idx = _invIndex; (idx < _holdings) && (idx - _invIndex) < MAX_VISIBLE_INVENTORY; ++idx) { // Get the name of the item to be dispalyed, figure out it's accompanying // .VGS file with it's picture, and then load it int invNum = findInv((*this)[idx]._name); - Common::String fName = Common::String::format("item%02d.vgs", invNum); + Common::String fName = Common::String::format("item%02d.vgs", invNum + 1); _invShapes[idx] = new ImageFile(fName); } @@ -106,20 +117,73 @@ void Inventory::loadGraphics() { * and returns the numer that matches the passed name */ int Inventory::findInv(const Common::String &name) { - int result = -1; - - for (int idx = 0; (idx < _holdings) && result == -1; ++idx) { + for (int idx = 0; idx < size(); ++idx) { if (scumm_stricmp(name.c_str(), _names[idx].c_str()) == 0) - result = idx; + return idx; } - if (result == -1) - result = 1; - return result; + return 1; } -void Inventory::putInv(int slamit) { - // TODO +/** + * Display the character's inventory. The slamIt parameter specifies: + * 0 = Draw it on the back buffer, and don't display it + * 1 = Draw it on the back buffer, and then display it + * 2 = Draw it on the secondary back buffer, and don't display it + */ +void Inventory::putInv(int slamIt) { + Screen &screen = *_vm->_screen; + UserInterface &ui = *_vm->_ui; + + // If an inventory item has disappeared (due to using it or giving it), + // a blank space slot may haave appeared. If so, adjust the inventory + if (_invIndex > 0 && _invIndex > (_holdings - 6)) { + --_invIndex; + freeGraphics(); + loadGraphics(); + } + + if (slamIt != 2) { + screen.makePanel(Common::Rect(6, 163, 54, 197)); + screen.makePanel(Common::Rect(58, 163, 106, 197)); + screen.makePanel(Common::Rect(110, 163, 158, 197)); + screen.makePanel(Common::Rect(162, 163, 210, 197)); + screen.makePanel(Common::Rect(214, 163, 262, 197)); + screen.makePanel(Common::Rect(266, 163, 314, 197)); + } + + // Iterate through displaying up to 6 objects at a time + for (int idx = _invIndex; idx < _holdings && (idx - _invIndex) < MAX_VISIBLE_INVENTORY; ++idx) { + int itemNum = idx - _invIndex; + Surface &bb = slamIt == 2 ? screen._backBuffer2 : screen._backBuffer1; + Common::Rect r(8 + itemNum * 52, 165, 51 + itemNum * 52, 194); + + // Draw the background + if (idx == ui._selector) { + bb.fillRect(r, 235); + } else if (slamIt == 2) { + bb.fillRect(r, BUTTON_MIDDLE); + } + + // Draw the item image + Graphics::Surface &img = (*_invShapes[itemNum])[0]._frame; + bb.transBlitFrom(img, Common::Point(6 + itemNum * 52 + ((47 - img.w) / 2), + 163 + ((33 - img.h) / 2))); + } + + if (slamIt == 1) + screen.slamArea(6, 163, 308, 34); + + if (slamIt != 2) + ui.clearInfo(); + + if (slamIt == 0) { + invCommands(0); + } else if (slamIt == 2) { + screen._backBuffer = &screen._backBuffer2; + invCommands(0); + screen._backBuffer = &screen._backBuffer1; + } } /** @@ -173,7 +237,7 @@ void Inventory::drawInventory(int flag) { if (tempFlag == 128) flag = 1; - ui._invMode = flag; + _invMode = flag; if (flag) { ui._oldKey = INVENTORY_COMMANDS[flag]; @@ -202,8 +266,67 @@ void Inventory::drawInventory(int flag) { ui._oldUse = -1; } +/** + * Prints the line of inventory commands at the top of an inventory window with + * the correct highlighting + */ void Inventory::invCommands(bool slamIt) { - // TODO + Screen &screen = *_vm->_screen; + UserInterface &ui = *_vm->_ui; + + if (slamIt) { + screen.buttonPrint(Common::Point(INVENTORY_POINTS[0][2], CONTROLS_Y1), + _invMode == 0 ? COMMAND_HIGHLIGHTED :COMMAND_FOREGROUND, + true, "Exit"); + screen.buttonPrint(Common::Point(INVENTORY_POINTS[1][2], CONTROLS_Y1), + _invMode == 1 ? COMMAND_HIGHLIGHTED :COMMAND_FOREGROUND, + true, "Look"); + screen.buttonPrint(Common::Point(INVENTORY_POINTS[2][2], CONTROLS_Y1), + _invMode == 2 ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND, + true, "Use"); + screen.buttonPrint(Common::Point(INVENTORY_POINTS[3][2], CONTROLS_Y1), + _invMode == 3 ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND, + true, "Give"); + screen.print(Common::Point(INVENTORY_POINTS[4][2], CONTROLS_Y1 + 1), + _invMode == 0 ? COMMAND_NULL : COMMAND_FOREGROUND, + "^^"); + screen.print(Common::Point(INVENTORY_POINTS[5][2], CONTROLS_Y1 + 1), + _invMode == 0 ? COMMAND_NULL : COMMAND_FOREGROUND, + "^"); + screen.print(Common::Point(INVENTORY_POINTS[6][2], CONTROLS_Y1 + 1), + (_holdings - _invIndex <= 6) ? COMMAND_NULL : COMMAND_FOREGROUND, + "_"); + screen.print(Common::Point(INVENTORY_POINTS[7][2], CONTROLS_Y1 + 1), + (_holdings - _invIndex <= 6) ? COMMAND_NULL : COMMAND_FOREGROUND, + "__"); + if (_invMode != 1) + ui.clearInfo(); + } else { + screen.buttonPrint(Common::Point(INVENTORY_POINTS[0][2], CONTROLS_Y1), + _invMode == 0 ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND, + false, "Exit"); + screen.buttonPrint(Common::Point(INVENTORY_POINTS[1][2], CONTROLS_Y1), + _invMode == 1 ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND, + false, "Look"); + screen.buttonPrint(Common::Point(INVENTORY_POINTS[2][2], CONTROLS_Y1), + _invMode == 2 ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND, + false, "Use"); + screen.buttonPrint(Common::Point(INVENTORY_POINTS[3][2], CONTROLS_Y1), + _invMode == 3 ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND, + false, "Give"); + screen.print(Common::Point(INVENTORY_POINTS[4][2], CONTROLS_Y1), + _invIndex == 0 ? COMMAND_NULL : COMMAND_FOREGROUND, + "^^"); + screen.print(Common::Point(INVENTORY_POINTS[5][2], CONTROLS_Y1), + _invIndex == 0 ? COMMAND_NULL : COMMAND_FOREGROUND, + "^"); + screen.print(Common::Point(INVENTORY_POINTS[6][2], CONTROLS_Y1), + (_holdings - _invIndex < 7) ? COMMAND_NULL : COMMAND_FOREGROUND, + "_"); + screen.print(Common::Point(INVENTORY_POINTS[7][2], CONTROLS_Y1), + (_holdings - _invIndex < 7) ? COMMAND_NULL : COMMAND_FOREGROUND, + "__"); + } } void Inventory::doInvLite(int index, byte color) { diff --git a/engines/sherlock/inventory.h b/engines/sherlock/inventory.h index 7785250e8c..e9a4ba5548 100644 --- a/engines/sherlock/inventory.h +++ b/engines/sherlock/inventory.h @@ -38,6 +38,9 @@ struct InventoryItem { Common::String _description;; Common::String _examine; int _lookFlag; + + InventoryItem(int requiredFlag, const Common::String &name, + const Common::String &description, const Common::String &examine); }; class Inventory : public Common::Array { @@ -47,6 +50,7 @@ public: ImageFile *_invShapes[MAX_VISIBLE_INVENTORY]; Common::StringArray _names; bool _invGraphicsLoaded; + int _invMode; int _invIndex; int _holdings; void freeGraphics(); @@ -64,7 +68,7 @@ public: int findInv(const Common::String &name); - void putInv(int slamit); + void putInv(int slamIt); void drawInventory(int flag); diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp index db59434f85..d226c2e82a 100644 --- a/engines/sherlock/scalpel/scalpel.cpp +++ b/engines/sherlock/scalpel/scalpel.cpp @@ -68,6 +68,9 @@ void ScalpelEngine::initialize() { for (int idx = 0; idx < NUM_PLACES; ++idx) _map.push_back(Common::Point(MAP_X[idx], MAP_Y[idx])); + // Load the inventory + loadInventory(); + // Starting scene _scene->_goToScene = 4; } @@ -176,6 +179,28 @@ bool ScalpelEngine::showOfficeCutscene() { return true; } +void ScalpelEngine::loadInventory() { + Inventory &inv = *_inventory; + + // Initial inventory + inv._holdings = 2; + inv.push_back(InventoryItem(0, "Message", "A message requesting help", "_ITEM03A")); + inv.push_back(InventoryItem(0, "Holmes Card", "A number of business cards", "_ITEM07A")); + + // Potential items + inv.push_back(InventoryItem(95, "Tickets", "Opera Tickets", "_ITEM10A")); + inv.push_back(InventoryItem(138, "Cuff Link", "Cuff Link", "_ITEM04A")); + inv.push_back(InventoryItem(138, "Wire Hook", "Wire Hook", "_ITEM06A")); + inv.push_back(InventoryItem(150, "Note", "Note", "_ITEM13A")); + inv.push_back(InventoryItem(481, "Open Watch", "An open pocket watch", "_ITEM62A")); + inv.push_back(InventoryItem(481, "Paper", "A piece of paper with numbers on it", "_ITEM44A")); + inv.push_back(InventoryItem(532, "Letter", "A letter folded many times", "_ITEM68A")); + inv.push_back(InventoryItem(544, "Tarot", "Tarot Cards", "_ITEM71A")); + inv.push_back(InventoryItem(544, "Ornate Key", "An ornate key", "_ITEM70A")); + inv.push_back(InventoryItem(586, "Pawn ticket", "A pawn ticket", "_ITEM16A")); +}; + + /** * Starting a scene within the game */ diff --git a/engines/sherlock/scalpel/scalpel.h b/engines/sherlock/scalpel/scalpel.h index caf33052aa..34d017e757 100644 --- a/engines/sherlock/scalpel/scalpel.h +++ b/engines/sherlock/scalpel/scalpel.h @@ -41,6 +41,8 @@ private: bool showAlleyCutscene(); bool showStreetCutscene(); bool showOfficeCutscene(); + + void loadInventory(); protected: virtual void initialize(); diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp index 16d590c0f4..a3705b54da 100644 --- a/engines/sherlock/screen.cpp +++ b/engines/sherlock/screen.cpp @@ -310,7 +310,7 @@ void Screen::flushImage(ImageFrame *frame, const Common::Point &pt, * Prints the text passed onto the back buffer at the given position and color. * The string is then blitted to the screen */ -void Screen::print(const Common::Point &pt, int color, const char *format, ...) { +void Screen::print(const Common::Point &pt, byte color, const char *format, ...) { // Create the string to display char buffer[100]; va_list args; @@ -344,7 +344,7 @@ void Screen::print(const Common::Point &pt, int color, const char *format, ...) /** * Print a strings onto the back buffer without blitting it to the screen */ -void Screen::gPrint(const Common::Point &pt, int color, const char *format, ...) { +void Screen::gPrint(const Common::Point &pt, byte color, const char *format, ...) { // Create the string to display char buffer[100]; va_list args; @@ -386,7 +386,7 @@ int Screen::charWidth(char c) { /** * Draws the given string into the back buffer using the images stored in _font */ -void Screen::writeString(const Common::String &str, const Common::Point &pt, int color) { +void Screen::writeString(const Common::String &str, const Common::Point &pt, byte color) { Common::Point charPos = pt; for (const char *c = str.c_str(); *c; ++c) { @@ -427,4 +427,45 @@ void Screen::makeButton(const Common::Rect &bounds, int textX, COMMAND_FOREGROUND, "%s", str.c_str() + 1); } +/** + * Prints an interface command with the first letter highlighted to indicate + * what keyboard shortcut is associated with it + */ +void Screen::buttonPrint(const Common::Point &pt, byte color, bool slamIt, + const Common::String &str) { + int xStart = pt.x - stringWidth(str) / 2; + + if (color == COMMAND_FOREGROUND) { + // First character needs to be highlighted + if (slamIt) { + print(Common::Point(xStart, pt.y + 1), COMMAND_HIGHLIGHTED, "%c", str[0]); + print(Common::Point(xStart + charWidth(str[0]), pt.y + 1), + color, "%s", str.c_str() + 1); + } else { + print(Common::Point(xStart, pt.y), COMMAND_HIGHLIGHTED, "%c", str[0]); + print(Common::Point(xStart + charWidth(str[0]), pt.y), + color, "%s", str.c_str() + 1); + } + } else { + print(Common::Point(xStart, slamIt ? pt.y + 1 : pt.y), COMMAND_HIGHLIGHTED, + "%s", str.c_str()); + } +} + +/** + * Draw a panel in th eback buffer with a raised area effect around the edges + */ +void Screen::makePanel(const Common::Rect &r) { + _backBuffer->fillRect(r, BUTTON_MIDDLE); + _backBuffer->hLine(r.left, r.top, r.right - 2, BUTTON_TOP); + _backBuffer->hLine(r.left + 1, r.top + 1, r.right - 3, BUTTON_TOP); + _backBuffer->vLine(r.left, r.top, r.bottom - 1, BUTTON_TOP); + _backBuffer->vLine(r.left + 1, r.top + 1, r.bottom - 2, BUTTON_TOP); + + _backBuffer->vLine(r.right - 1, r.top, r.bottom - 1, BUTTON_BOTTOM); + _backBuffer->vLine(r.right - 2, r.top + 1, r.bottom - 2, BUTTON_BOTTOM); + _backBuffer->hLine(r.left, r.bottom - 1, r.right - 1, BUTTON_BOTTOM); + _backBuffer->hLine(r.left + 1, r.bottom - 2, r.right - 1, BUTTON_BOTTOM); +} + } // End of namespace Sherlock diff --git a/engines/sherlock/screen.h b/engines/sherlock/screen.h index f33bbfceab..5047d40216 100644 --- a/engines/sherlock/screen.h +++ b/engines/sherlock/screen.h @@ -44,6 +44,8 @@ enum { INV_BACKGROUND = 1, COMMAND_HIGHLIGHTED = 10, COMMAND_FOREGROUND = 15, + COMMAND_BACKGROUND = 4, + COMMAND_NULL = 248, BUTTON_TOP = 233, BUTTON_MIDDLE = 244, BUTTON_BOTTOM = 248, @@ -65,7 +67,7 @@ private: bool unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2); - void writeString(const Common::String &str, const Common::Point &pt, int color); + void writeString(const Common::String &str, const Common::Point &pt, byte color); protected: virtual void addDirtyRect(const Common::Rect &r); public: @@ -96,8 +98,8 @@ public: void verticalTransition(); - void print(const Common::Point &pt, int color, const char *format, ...); - void gPrint(const Common::Point &pt, int color, const char *format, ...); + void print(const Common::Point &pt, byte color, const char *format, ...); + void gPrint(const Common::Point &pt, byte color, const char *format, ...); void restoreBackground(const Common::Rect &r); @@ -114,6 +116,10 @@ public: void vgaBar(const Common::Rect &r, int color); void makeButton(const Common::Rect &bounds, int textX, const Common::String &str); + + void buttonPrint(const Common::Point &pt, byte color, bool slamIt, const Common::String &str); + + void makePanel(const Common::Rect &r); }; } // End of namespace Sherlock diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index a993965429..5e8b3287f0 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -77,8 +77,6 @@ UserInterface::UserInterface(SherlockEngine *vm) : _vm(vm) { _windowOpen = false; _oldLook = false; _keyboardInput = false; - _invMode = 0; - _invIndex = 0; _pause = false; _cNum = 0; _selector = _oldSelector = -1; @@ -116,6 +114,7 @@ void UserInterface::drawInterface() { */ void UserInterface::handleInput() { Events &events = *_vm->_events; + Inventory &inv = *_vm->_inventory; People &people = *_vm->_people; Scene &scene = *_vm->_scene; Screen &screen = *_vm->_screen; @@ -276,7 +275,7 @@ void UserInterface::handleInput() { case USE_MODE: case GIVE_MODE: case INV_MODE: - if (_invMode == 1 || _invMode == 2 || _invMode == 3) { + if (inv._invMode == 1 || inv._invMode == 2 || inv._invMode == 3) { if (pt.y < CONTROLS_Y) lookInv(); else @@ -455,11 +454,6 @@ void UserInterface::toggleButton(int num) { } } -void UserInterface::buttonPrint(const Common::Point &pt, int color, bool slamIt, - const Common::String &str) { - // TODO -} - /** * Clears the info line of the screen */ @@ -566,10 +560,10 @@ void UserInterface::lookScreen(const Common::Point &pt) { if (!tempStr.empty() && tempStr[0] != ' ') { // If inventory is active and an item is selected for a Use or Give action if ((_menuMode == INV_MODE || _menuMode == USE_MODE || _menuMode == GIVE_MODE) && - (_invMode == 2 || _invMode == 3)) { + (inv._invMode == 2 || inv._invMode == 3)) { width1 = screen.stringWidth(inv[_selector]._name); - if (_invMode == 2) { + if (inv._invMode == 2) { // Using an object x = width = screen.stringWidth("Use "); @@ -658,7 +652,7 @@ void UserInterface::lookInv() { if (mousePos.x > 15 && mousePos.x < 314 && mousePos.y > (CONTROLS_Y1 + 11) && mousePos.y < (SHERLOCK_SCREEN_HEIGHT - 2)) { - int temp = (mousePos.x - 6) / 52 + _invIndex; + int temp = (mousePos.x - 6) / 52 + inv._invIndex; if (temp < inv._holdings) { if (temp < inv._holdings) { clearInfo(); @@ -712,25 +706,25 @@ void UserInterface::doInvControl() { if (found != -1) // If a slot highlighted, set it's color colors[found] = COMMAND_HIGHLIGHTED; - buttonPrint(Common::Point(INVENTORY_POINTS[0][2], CONTROLS_Y1), + screen.buttonPrint(Common::Point(INVENTORY_POINTS[0][2], CONTROLS_Y1), colors[0], true, "Exit"); if (found >= 0 && found <= 3) { - buttonPrint(Common::Point(INVENTORY_POINTS[1][2], CONTROLS_Y1), colors[1], true, "Look"); - buttonPrint(Common::Point(INVENTORY_POINTS[2][2], CONTROLS_Y1), colors[1], true, "Use"); - buttonPrint(Common::Point(INVENTORY_POINTS[3][2], CONTROLS_Y1), colors[1], true, "Give"); - _invMode = found; + screen.buttonPrint(Common::Point(INVENTORY_POINTS[1][2], CONTROLS_Y1), colors[1], true, "Look"); + screen.buttonPrint(Common::Point(INVENTORY_POINTS[2][2], CONTROLS_Y1), colors[1], true, "Use"); + screen.buttonPrint(Common::Point(INVENTORY_POINTS[3][2], CONTROLS_Y1), colors[1], true, "Give"); + inv._invMode = found; _selector = -1; } - if (_invIndex) { + if (inv._invIndex) { screen.print(Common::Point(INVENTORY_POINTS[4][2], CONTROLS_Y1 + 1), colors[4], "^^"); screen.print(Common::Point(INVENTORY_POINTS[5][2], CONTROLS_Y1 + 1), colors[5], "^"); } - if ((inv._holdings - _invIndex) > 6) { + if ((inv._holdings - inv._invIndex) > 6) { screen.print(Common::Point(INVENTORY_POINTS[6][2], CONTROLS_Y1 + 1), colors[6], "^^"); screen.print(Common::Point(INVENTORY_POINTS[7][2], CONTROLS_Y1 + 1), @@ -738,7 +732,7 @@ void UserInterface::doInvControl() { } bool flag = false; - if (_invMode == 1 || _invMode == 2 || _invMode == 3) { + if (inv._invMode == 1 || inv._invMode == 2 || inv._invMode == 3) { Common::Rect r(15, CONTROLS_Y1 + 11, 314, SHERLOCK_SCREEN_HEIGHT - 2); flag = (_selector < inv._holdings); } @@ -756,16 +750,16 @@ void UserInterface::doInvControl() { if (_key == 'E' || _key == 'L' || _key == 'U' || _key == 'G' || _key == '-' || _key == '+') { - int temp = _invMode; + int temp = inv._invMode; const char *chP = strchr(INVENTORY_COMMANDS, _key); - _invMode = !chP ? 8 : chP - INVENTORY_COMMANDS; + inv._invMode = !chP ? 8 : chP - INVENTORY_COMMANDS; inv.invCommands(true); - _invMode = temp; + inv._invMode = temp; _keyboardInput = true; if (_key == 'E') - _invMode = STD_MODE; + inv._invMode = STD_MODE; _selector = -1; } else { _selector = -1; @@ -775,7 +769,7 @@ void UserInterface::doInvControl() { if (_selector != _oldSelector) { if (_oldSelector != -1) { // Un-highlight - if (_oldSelector >= _invIndex && _oldSelector < (_invIndex + 6)) + if (_oldSelector >= inv._invIndex && _oldSelector < (inv._invIndex + 6)) inv.doInvLite(_oldSelector, BUTTON_MIDDLE); } @@ -795,16 +789,16 @@ void UserInterface::doInvControl() { events.clearEvents(); events.setCursor(ARROW); } else if ((found == 1 && events._released) || (_key == 'L')) { - _invMode = 1; + inv._invMode = 1; } else if ((found == 2 && events._released) || (_key == 'U')) { - _invMode = 2; + inv._invMode = 2; } else if ((found == 3 && events._released) || (_key == 'G')) { - _invMode = 3; - } else if (((found == 4 && events._released) || _key == ',') && _invIndex) { - if (_invIndex >= 6) - _invIndex -= 6; + inv._invMode = 3; + } else if (((found == 4 && events._released) || _key == ',') && inv._invIndex) { + if (inv._invIndex >= 6) + inv._invIndex -= 6; else - _invIndex = 0; + inv._invIndex = 0; screen.print(Common::Point(INVENTORY_POINTS[4][2], CONTROLS_Y1 + 1), COMMAND_HIGHLIGHTED, "^^"); @@ -812,26 +806,28 @@ void UserInterface::doInvControl() { inv.loadGraphics(); inv.putInv(1); inv.invCommands(true); - } else if (((found == 5 && events._released) || _key == '-') && _invIndex) { - --_invIndex; + } else if (((found == 5 && events._released) || _key == '-') && inv._invIndex) { + --inv._invIndex; screen.print(Common::Point(INVENTORY_POINTS[4][2], CONTROLS_Y1 + 1), COMMAND_HIGHLIGHTED, "^"); inv.freeGraphics(); inv.loadGraphics(); inv.putInv(1); inv.invCommands(true); - } else if (((found == 6 && events._released) || _key == '+') && (inv._holdings - _invIndex) > 6) { - ++_invIndex; + } else if (((found == 6 && events._released) || _key == '+') && + (inv._holdings - inv._invIndex) > 6) { + ++inv._invIndex; screen.print(Common::Point(INVENTORY_POINTS[6][2], CONTROLS_Y1 + 1), COMMAND_HIGHLIGHTED, "_"); inv.freeGraphics(); inv.loadGraphics(); inv.putInv(1); inv.invCommands(true); - } else if (((found == 7 && events._released) || _key == '.') && (inv._holdings - _invIndex) > 6) { - _invIndex += 6; - if ((inv._holdings - 6) < _invIndex) - _invIndex = inv._holdings - 6; + } else if (((found == 7 && events._released) || _key == '.') && + (inv._holdings - inv._invIndex) > 6) { + inv._invIndex += 6; + if ((inv._holdings - 6) < inv._invIndex) + inv._invIndex = inv._holdings - 6; screen.print(Common::Point(INVENTORY_POINTS[7][2], CONTROLS_Y1 + 1), COMMAND_HIGHLIGHTED, "_"); @@ -841,7 +837,7 @@ void UserInterface::doInvControl() { inv.invCommands(true); } else { // If something is being given, make sure it's to a person - if (_invMode == 3) { + if (inv._invMode == 3) { if (_bgFound != -1 && scene._bgShapes[_bgFound]._aType == PERSON) _find = _bgFound; else @@ -850,7 +846,7 @@ void UserInterface::doInvControl() { _find = _bgFound; } - if ((mousePos.y < CONTROLS_Y1) && (_invMode == 1) && (_find >= 0) && (_find < 1000)) { + if ((mousePos.y < CONTROLS_Y1) && (inv._invMode == 1) && (_find >= 0) && (_find < 1000)) { if (!scene._bgShapes[_find]._examine.empty() && scene._bgShapes[_find]._examine[0] >= ' ') inv.doInvJF(); @@ -859,7 +855,7 @@ void UserInterface::doInvControl() { // If it's -1, then no inventory item is highlighted yet. Otherwise, // an object in the scene has been clicked. - if (_selector != -1 && _invMode == 1 && mousePos.y >(CONTROLS_Y1 + 11)) + if (_selector != -1 && inv._invMode == 1 && mousePos.y >(CONTROLS_Y1 + 11)) inv.doInvJF(); if (talk._talkToAbort) @@ -872,7 +868,7 @@ void UserInterface::doInvControl() { // is being tried on an object in the scene without an inventory // object being highlighted first. - if ((_invMode == 2 || (_selector != -1 && _invMode == 3)) && _find >= 0) { + if ((inv._invMode == 2 || (_selector != -1 && inv._invMode == 3)) && _find >= 0) { events._pressed = events._released = false; _infoFlag = true; clearInfo(); @@ -882,8 +878,8 @@ void UserInterface::doInvControl() { inv.putInv(1); _selector = temp; // Restore it - temp = _invMode; - _invMode = -1; + temp = inv._invMode; + inv._invMode = -1; inv.invCommands(true); _infoFlag = true; diff --git a/engines/sherlock/user_interface.h b/engines/sherlock/user_interface.h index 87fd4a5e99..14462d6a34 100644 --- a/engines/sherlock/user_interface.h +++ b/engines/sherlock/user_interface.h @@ -75,8 +75,6 @@ private: int _invLookFlag; int _oldLook; bool _keyboardInput; - int _invMode; - int _invIndex; bool _pause; int _cNum; int _selector, _oldSelector; @@ -97,8 +95,6 @@ private: void toggleButton(int num); - void buttonPrint(const Common::Point &pt, int color, bool slamIt, const Common::String &str); - void examine(); void lookScreen(const Common::Point &pt); -- cgit v1.2.3 From fb0f95172a0395cc6d86f26fea5de2c6a780999a Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 29 Mar 2015 16:21:49 -0400 Subject: MADS: Don't hide sprites bewteen resources in an animation sequence --- engines/mads/menu_views.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'engines') diff --git a/engines/mads/menu_views.cpp b/engines/mads/menu_views.cpp index 5a0c7ee92e..319f5b0f87 100644 --- a/engines/mads/menu_views.cpp +++ b/engines/mads/menu_views.cpp @@ -544,6 +544,7 @@ void AnimationView::doFrame() { scriptDone(); } else { scene._frameStartTime = 0; + scene._spriteSlots.clear(); loadNextResource(); } } else if (_currentAnimation->getCurrentFrame() == 1) { @@ -559,6 +560,10 @@ void AnimationView::doFrame() { ++scene._frameStartTime; _currentAnimation->update(); _redrawFlag = true; + + if (_currentAnimation->freeFlag()) + // We don't want the sprites removed after the last animation frame + scene._spriteSlots.clear(); } } -- cgit v1.2.3 From 478fae2a6ea6d1c896cd9d5454b170889fc8447a Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 29 Mar 2015 22:12:27 -0400 Subject: MADS: Set testing flags for Rex Nebular --- engines/mads/detection_tables.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/mads/detection_tables.h b/engines/mads/detection_tables.h index 0a8e98bb31..faf73996ac 100644 --- a/engines/mads/detection_tables.h +++ b/engines/mads/detection_tables.h @@ -55,7 +55,7 @@ static const MADSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformDOS, - ADGF_NO_FLAGS, + ADGF_TESTING, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EASY_MOUSE, GAMEOPTION_ANIMATED_INVENTORY, GAMEOPTION_ANIMATED_INTERFACE, GAMEOPTION_NAUGHTY_MODE) }, GType_RexNebular, @@ -73,7 +73,7 @@ static const MADSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformDOS, - ADGF_NO_FLAGS, + ADGF_TESTING, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EASY_MOUSE, GAMEOPTION_ANIMATED_INVENTORY, GAMEOPTION_ANIMATED_INTERFACE, GAMEOPTION_NAUGHTY_MODE) }, GType_RexNebular, -- cgit v1.2.3 From 943d0a702fe468f14fb40f73ef68588705488037 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 30 Mar 2015 21:07:01 -0400 Subject: SHERLOCK: Beginnings of talk loading, added skeleton Scripts class --- engines/sherlock/inventory.cpp | 42 ++++-- engines/sherlock/inventory.h | 15 +- engines/sherlock/module.mk | 1 + engines/sherlock/people.h | 13 +- engines/sherlock/scene.cpp | 16 +- engines/sherlock/scene.h | 11 +- engines/sherlock/screen.cpp | 11 ++ engines/sherlock/screen.h | 4 + engines/sherlock/scripts.cpp | 35 +++++ engines/sherlock/scripts.h | 48 ++++++ engines/sherlock/sherlock.cpp | 14 +- engines/sherlock/sherlock.h | 6 +- engines/sherlock/talk.cpp | 291 +++++++++++++++++++++++++++++++++++- engines/sherlock/talk.h | 43 +++++- engines/sherlock/user_interface.cpp | 58 ++++--- engines/sherlock/user_interface.h | 11 +- 16 files changed, 542 insertions(+), 77 deletions(-) create mode 100644 engines/sherlock/scripts.cpp create mode 100644 engines/sherlock/scripts.h (limited to 'engines') diff --git a/engines/sherlock/inventory.cpp b/engines/sherlock/inventory.cpp index a7691fc866..ac37e7c587 100644 --- a/engines/sherlock/inventory.cpp +++ b/engines/sherlock/inventory.cpp @@ -40,7 +40,7 @@ Inventory::Inventory(SherlockEngine *vm) : Common::Array(), _vm(v _holdings = 0; _oldFlag = 0; _invFlag = 0; - _invMode = 0; + _invMode = INVMODE_EXIT; } Inventory::~Inventory() { @@ -117,7 +117,7 @@ void Inventory::loadGraphics() { * and returns the numer that matches the passed name */ int Inventory::findInv(const Common::String &name) { - for (int idx = 0; idx < size(); ++idx) { + for (int idx = 0; idx < (int)size(); ++idx) { if (scumm_stricmp(name.c_str(), _names[idx].c_str()) == 0) return idx; } @@ -219,25 +219,25 @@ void Inventory::drawInventory(int flag) { // Draw the buttons screen.makeButton(Common::Rect(INVENTORY_POINTS[0][0], CONTROLS_Y1, INVENTORY_POINTS[0][1], - CONTROLS_Y1 + 9), INVENTORY_POINTS[0][2] - screen.stringWidth("Exit") / 2, "Exit"); + CONTROLS_Y1 + 10), INVENTORY_POINTS[0][2] - screen.stringWidth("Exit") / 2, "Exit"); screen.makeButton(Common::Rect(INVENTORY_POINTS[1][0], CONTROLS_Y1, INVENTORY_POINTS[1][1], - CONTROLS_Y1 + 9), INVENTORY_POINTS[1][2] - screen.stringWidth("Look") / 2, "Look"); + CONTROLS_Y1 + 10), INVENTORY_POINTS[1][2] - screen.stringWidth("Look") / 2, "Look"); screen.makeButton(Common::Rect(INVENTORY_POINTS[2][0], CONTROLS_Y1, INVENTORY_POINTS[2][1], - CONTROLS_Y1 + 9), INVENTORY_POINTS[2][2] - screen.stringWidth("Use") / 2, "Use"); + CONTROLS_Y1 + 10), INVENTORY_POINTS[2][2] - screen.stringWidth("Use") / 2, "Use"); screen.makeButton(Common::Rect(INVENTORY_POINTS[3][0], CONTROLS_Y1, INVENTORY_POINTS[3][1], - CONTROLS_Y1 + 9), INVENTORY_POINTS[3][2] - screen.stringWidth("Give") / 2, "Give"); + CONTROLS_Y1 + 10), INVENTORY_POINTS[3][2] - screen.stringWidth("Give") / 2, "Give"); screen.makeButton(Common::Rect(INVENTORY_POINTS[4][0], CONTROLS_Y1, INVENTORY_POINTS[4][1], - CONTROLS_Y1 + 9), INVENTORY_POINTS[4][2], "^^"); + CONTROLS_Y1 + 10), INVENTORY_POINTS[4][2], "^^"); screen.makeButton(Common::Rect(INVENTORY_POINTS[5][0], CONTROLS_Y1, INVENTORY_POINTS[5][1], - CONTROLS_Y1 + 9), INVENTORY_POINTS[5][2], "^"); + CONTROLS_Y1 + 10), INVENTORY_POINTS[5][2], "^"); screen.makeButton(Common::Rect(INVENTORY_POINTS[6][0], CONTROLS_Y1, INVENTORY_POINTS[6][1], - CONTROLS_Y1 + 9), INVENTORY_POINTS[6][2], "_"); + CONTROLS_Y1 + 10), INVENTORY_POINTS[6][2], "_"); screen.makeButton(Common::Rect(INVENTORY_POINTS[7][0], CONTROLS_Y1, INVENTORY_POINTS[7][1], - CONTROLS_Y1 + 9), INVENTORY_POINTS[7][2], "__"); + CONTROLS_Y1 + 10), INVENTORY_POINTS[7][2], "__"); if (tempFlag == 128) flag = 1; - _invMode = flag; + _invMode = (InvMode)flag; if (flag) { ui._oldKey = INVENTORY_COMMANDS[flag]; @@ -334,7 +334,25 @@ void Inventory::doInvLite(int index, byte color) { } void Inventory::doInvJF() { - // TODO + Screen &screen = *_vm->_screen; + Talk &talk = *_vm->_talk; + UserInterface &ui = *_vm->_ui; + + ui._invLookFlag = true; + freeInv(); + + ui._infoFlag = true; + ui.clearInfo(); + + screen._backBuffer2.blitFrom(screen._backBuffer1, Common::Point(0, CONTROLS_Y), + Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); + ui.examine(); + + if (!talk._talkToAbort) { + screen._backBuffer2.blitFrom((*ui._controlPanel)[0]._frame, + Common::Point(0, CONTROLS_Y)); + loadInv(); + } } } // End of namespace Sherlock diff --git a/engines/sherlock/inventory.h b/engines/sherlock/inventory.h index e9a4ba5548..3c01dc38da 100644 --- a/engines/sherlock/inventory.h +++ b/engines/sherlock/inventory.h @@ -32,6 +32,19 @@ namespace Sherlock { #define MAX_VISIBLE_INVENTORY 6 +enum InvMode { + INVMODE_EXIT = 0, + INVMODE_LOOK = 1, + INVMODE_USE = 2, + INVMODE_GIVE = 3, + INVMODE_FIRST = 4, + INVMODE_PREVIOUS = 5, + INVMODE_NEXT = 6, + INVMODE_LAST = 7, + INVMODE_INVALID = 8, + INVMODE_USE55 = 255 +}; + struct InventoryItem { int _requiredFlag; Common::String _name; @@ -50,7 +63,7 @@ public: ImageFile *_invShapes[MAX_VISIBLE_INVENTORY]; Common::StringArray _names; bool _invGraphicsLoaded; - int _invMode; + InvMode _invMode; int _invIndex; int _holdings; void freeGraphics(); diff --git a/engines/sherlock/module.mk b/engines/sherlock/module.mk index 4101769a80..a01f9f0f71 100644 --- a/engines/sherlock/module.mk +++ b/engines/sherlock/module.mk @@ -18,6 +18,7 @@ MODULE_OBJS = \ resources.o \ scene.o \ screen.o \ + scripts.o \ sherlock.o \ sound.o \ talk.o \ diff --git a/engines/sherlock/people.h b/engines/sherlock/people.h index 0393528095..6b5c59b1bd 100644 --- a/engines/sherlock/people.h +++ b/engines/sherlock/people.h @@ -52,17 +52,24 @@ enum { class SherlockEngine; +class Person: public Sprite { +public: + Person() : Sprite() {} + + Common::String _portrait; +}; + class People { private: SherlockEngine *_vm; - Sprite _data[MAX_PEOPLE]; - Sprite &_player; + Person _data[MAX_PEOPLE]; bool _walkLoaded; int _oldWalkSequence; int _srcZone, _destZone; public: Common::Point _walkDest; Common::Stack _walkTo; + Person &_player; bool _holmesOn; bool _portraitLoaded; Object _portrait; @@ -72,7 +79,7 @@ public: People(SherlockEngine *vm); ~People(); - Sprite &operator[](PeopleId id) { return _data[id]; } + Person &operator[](PeopleId id) { return _data[id]; } bool isHolmesActive() const { return _walkLoaded && _holmesOn; } diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index c3afc4a0d4..7c66a1dc62 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -99,7 +99,6 @@ Scene::Scene(SherlockEngine *vm): _vm(vm) { _hsavedPos = Common::Point(-1, -1); _hsavedFs = -1; _cAnimFramePause = 0; - _invMode = INVMODE_0; _restoreFlag = false; _invLookFlag = false; _lookHelp = false; @@ -119,6 +118,7 @@ void Scene::selectScene() { Events &events = *_vm->_events; People &people = *_vm->_people; Screen &screen = *_vm->_screen; + Scripts &scripts = *_vm->_scripts; UserInterface &ui = *_vm->_ui; // Reset fields @@ -150,8 +150,8 @@ void Scene::selectScene() { // If there were any scripst waiting to be run, but were interrupt by a running // canimation (probably the last scene's exit canim), clear the _scriptMoreFlag - if (_vm->_scriptMoreFlag == 3) - _vm->_scriptMoreFlag = 0; + if (scripts._scriptMoreFlag == 3) + scripts._scriptMoreFlag = 0; } /** @@ -1050,8 +1050,10 @@ int Scene::startCAnim(int cAnimNum, int playRate) { */ void Scene::doBgAnim() { Events &events = *_vm->_events; + Inventory &inv = *_vm->_inventory; People &people = *_vm->_people; Screen &screen = *_vm->_screen; + Scripts &scripts = *_vm->_scripts; Sound &sound = *_vm->_sound; Talk &talk = *_vm->_talk; UserInterface &ui = *_vm->_ui; @@ -1079,7 +1081,7 @@ void Scene::doBgAnim() { // Check for setting magnifying glass cursor if (ui._menuMode == INV_MODE || ui._menuMode == USE_MODE || ui._menuMode == GIVE_MODE) { - if (_invMode == INVMODE_1) { + if (inv._invMode == INVMODE_LOOK) { // Only show Magnifying glass cursor if it's not on the inventory command line if (mousePos.y < CONTROLS_Y || mousePos.y >(CONTROLS_Y1 + 13)) events.setCursor(MAGNIFY); @@ -1357,10 +1359,10 @@ void Scene::doBgAnim() { // Check if the method was called for calling a portrait, and a talk was // interrupting it. This talk file would not have been executed at the time, // since we needed to finish the 'doBgAnim' to finish clearing the portrait - if (people._clearingThePortrait && _vm->_scriptMoreFlag == 3) { + if (people._clearingThePortrait && scripts._scriptMoreFlag == 3) { // Reset the flags and call to talk - people._clearingThePortrait = _vm->_scriptMoreFlag = 0; - talk.talkTo(_vm->_scriptName); + people._clearingThePortrait = scripts._scriptMoreFlag = 0; + talk.talkTo(scripts._scriptName); } } diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h index d89a47e560..cd64073621 100644 --- a/engines/sherlock/scene.h +++ b/engines/sherlock/scene.h @@ -35,14 +35,6 @@ namespace Sherlock { #define MAX_ZONES 40 #define INFO_LINE 140 -enum InvMode { - INVMODE_0 = 0, - INVMODE_1 = 1, - INVMODE_2 = 2, - INVMODE_3 = 3, - INVMODE_255 = 255 -}; - class SherlockEngine; struct BgFileHeader { @@ -94,9 +86,7 @@ class Scene { private: SherlockEngine *_vm; Common::String _rrmName; - InvMode _invMode; int _selector; - bool _invLookFlag; bool _lookHelp; bool loadScene(const Common::String &filename); @@ -149,6 +139,7 @@ public: bool _doBgAnimDone; int _tempFadeStyle; int _cAnimFramePause; + bool _invLookFlag; public: Scene(SherlockEngine *vm); ~Scene(); diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp index a3705b54da..0eeddf2a5f 100644 --- a/engines/sherlock/screen.cpp +++ b/engines/sherlock/screen.cpp @@ -468,4 +468,15 @@ void Screen::makePanel(const Common::Rect &r) { _backBuffer->hLine(r.left + 1, r.bottom - 2, r.right - 1, BUTTON_BOTTOM); } +void Screen::setDisplayBounds(const Common::Rect &r) { + // TODO: See if needed +} +void Screen::resetDisplayBounds() { + setDisplayBounds(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); +} + +Common::Rect Screen::getDisplayBounds() { + return Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT); +} + } // End of namespace Sherlock diff --git a/engines/sherlock/screen.h b/engines/sherlock/screen.h index 5047d40216..597c47c83a 100644 --- a/engines/sherlock/screen.h +++ b/engines/sherlock/screen.h @@ -120,6 +120,10 @@ public: void buttonPrint(const Common::Point &pt, byte color, bool slamIt, const Common::String &str); void makePanel(const Common::Rect &r); + + void setDisplayBounds(const Common::Rect &r); + void resetDisplayBounds(); + Common::Rect getDisplayBounds(); }; } // End of namespace Sherlock diff --git a/engines/sherlock/scripts.cpp b/engines/sherlock/scripts.cpp new file mode 100644 index 0000000000..ace957bd76 --- /dev/null +++ b/engines/sherlock/scripts.cpp @@ -0,0 +1,35 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "sherlock/scripts.h" +#include "sherlock/sherlock.h" + +namespace Sherlock { + +Scripts::Scripts(SherlockEngine *vm): _vm(vm) { + _scriptMoreFlag = 0; + _scriptSaveIndex = 0; + _scriptSelect = 0; + _abortFlag = false; +} + +} // End of namespace Sherlock diff --git a/engines/sherlock/scripts.h b/engines/sherlock/scripts.h new file mode 100644 index 0000000000..eede1ca103 --- /dev/null +++ b/engines/sherlock/scripts.h @@ -0,0 +1,48 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef SHERLOCK_SCRIPTS_H +#define SHERLOCK_SCRIPTS_H + +#include "common/scummsys.h" +#include "common/array.h" + +namespace Sherlock { + +class SherlockEngine; + +class Scripts { +private: + SherlockEngine *_vm; +public: + int _scriptMoreFlag; + Common::String _scriptName; + int _scriptSaveIndex; + int _scriptSelect; + bool _abortFlag; +public: + Scripts(SherlockEngine *vm); +}; + +} // End of namespace Sherlock + +#endif diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index 107dee5a41..04a9ed54d5 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -39,6 +39,7 @@ SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gam _res = nullptr; _scene = nullptr; _screen = nullptr; + _scripts = nullptr; _sound = nullptr; _talk = nullptr; _ui = nullptr; @@ -47,7 +48,6 @@ SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gam _loadingSavedGame = false; _onChessboard = false; _slowChess = false; - _scriptMoreFlag = 0; } SherlockEngine::~SherlockEngine() { @@ -58,6 +58,7 @@ SherlockEngine::~SherlockEngine() { delete _people; delete _scene; delete _screen; + delete _scripts; delete _sound; delete _talk; delete _ui; @@ -82,6 +83,7 @@ void SherlockEngine::initialize() { _people = new People(this); _scene = new Scene(this); _screen = new Screen(this); + _scripts = new Scripts(this); _sound = new Sound(this); _talk = new Talk(this); _ui = new UserInterface(this); @@ -120,10 +122,10 @@ void SherlockEngine::sceneLoop() { while (!shouldQuit() && _scene->_goToScene == -1) { // See if a script needs to be completed from either a goto room code, // or a script that was interrupted by another script - if (_scriptMoreFlag == 1 || _scriptMoreFlag == 3) - _talk->talkTo(_scriptName); + if (_scripts->_scriptMoreFlag == 1 || _scripts->_scriptMoreFlag == 3) + _talk->talkTo(_scripts->_scriptName); else - _scriptMoreFlag = 0; + _scripts->_scriptMoreFlag = 0; // Handle any input from the keyboard or mouse handleInput(); @@ -171,4 +173,8 @@ void SherlockEngine::setFlags(int flagNum) { _scene->checkSceneFlags(true); } +void SherlockEngine::freeSaveGameList() { + // TODO +} + } // End of namespace Comet diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h index 392f55839e..7b562e0a23 100644 --- a/engines/sherlock/sherlock.h +++ b/engines/sherlock/sherlock.h @@ -40,6 +40,7 @@ #include "sherlock/resources.h" #include "sherlock/scene.h" #include "sherlock/screen.h" +#include "sherlock/scripts.h" #include "sherlock/sound.h" #include "sherlock/talk.h" #include "sherlock/user_interface.h" @@ -89,6 +90,7 @@ public: Resources *_res; Scene *_scene; Screen *_screen; + Scripts *_scripts; Sound *_sound; Talk *_talk; UserInterface *_ui; @@ -104,8 +106,6 @@ public: Common::Array _map; // Map locations for each scene bool _onChessboard; bool _slowChess; - int _scriptMoreFlag; - Common::String _scriptName; public: SherlockEngine(OSystem *syst, const SherlockGameDescription *gameDesc); virtual ~SherlockEngine(); @@ -125,6 +125,8 @@ public: bool readFlags(int flagNum); void setFlags(int flagNum); + + void freeSaveGameList(); }; } // End of namespace Sherlock diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index ff71d37a2f..d67013b60e 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -25,13 +25,238 @@ namespace Sherlock { +/** + * Load the data for a single statement within a talk file + */ +void Statement::synchronize(Common::SeekableReadStream &s, bool voices) { + int length; + + length = s.readUint16LE(); + for (int idx = 0; idx < length; ++idx) + _statement += (char)s.readByte(); + + length = s.readUint16LE(); + for (int idx = 0; idx < length; ++idx) + _reply += (char)s.readByte(); + + // If we don't have digital sound, we'll need to strip out voice commands from reply + if (!voices) { + // Scan for a 140 byte, which indicates playing a sound + for (uint idx = 0; idx < _reply.size(); ++idx) { + if (_reply[idx] == 140) { + // Replace instruction character with a space, and delete the + // rest of the name following it + _reply = Common::String(_reply.c_str(), _reply.c_str() + idx) + " " + + Common::String(_reply.c_str() + 9); + } + } + + // Ensure the last character of the reply is not a space from the prior + // conversion loop, to avoid any issues with the space ever causing a page + // wrap, and ending up displaying another empty page + while (_reply.lastChar() == ' ') + _reply.deleteLastChar(); + } + + length = s.readUint16LE(); + for (int idx = 0; idx < length; ++idx) + _linkFile += (char)s.readByte(); + + length = s.readUint16LE(); + for (int idx = 0; idx < length; ++idx) + _voiceFile += (char)s.readByte(); + + _required.resize(s.readByte()); + _modified.resize(s.readByte()); + + // Read in flag required/modified data + for (uint idx = 0; idx < _required.size(); ++idx) + _required[idx] = s.readUint16LE(); + for (uint idx = 0; idx < _modified.size(); ++idx) + _modified[idx] = s.readUint16LE(); + + _portraitSide = s.readByte(); + _quotient = s.readUint16LE(); +} + +/*----------------------------------------------------------------*/ + Talk::Talk(SherlockEngine *vm): _vm(vm) { _talkCounter = 0; _talkToAbort = false; + _saveSeqNum = 0; + _speaker = 0; + _talkIndex = 0; + _talkTo = 0; } -void Talk::talkTo(const Common::String &name) { - // TODO +/** + * Called when either an NPC initiates a conversation or for inventory item + * descriptions. It opens up a description window similar to how 'talk' does, + * but shows a 'reply' directly instead of waiting for a statement option. + */ +void Talk::talkTo(const Common::String &filename) { + Events &events = *_vm->_events; + Inventory &inv = *_vm->_inventory; + People &people = *_vm->_people; + Scene &scene = *_vm->_scene; + Screen &screen = *_vm->_screen; + Scripts &scripts = *_vm->_scripts; + Talk &talk = *_vm->_talk; + UserInterface &ui = *_vm->_ui; + Common::Rect savedBounds = screen.getDisplayBounds(); + + if (filename.empty()) + // No filename passed, so exit + return; + + // If there any canimations currently running, or a portrait is being cleared, + // save the filename for later executing when the canimation is done + if (scene._ongoingCans || people._clearingThePortrait) { + // Make sure we're not in the middle of a script + if (!scripts._scriptMoreFlag) { + scripts._scriptName = filename; + scripts._scriptSaveIndex = 0; + + // Flag the selection, since we don't yet know which statement yet + scripts._scriptSelect = 100; + scripts._scriptMoreFlag = 3; + } + + return; + } + + // Save the ui mode temporarily and switch to talk mode + int savedMode = ui._menuMode; + ui._menuMode = TALK_MODE; + + // Turn on the Exit option + ui._endKeyActive = true; + + if (people[AL]._walkCount || people._walkTo.size() > 0) { + // Only interrupt if an action if trying to do an action, and not just + // if the player is walking around the scene + if (people._allowWalkAbort) + scripts._abortFlag = true; + + people.gotoStand(people._player); + } + + if (talk._talkToAbort) + return; + + talk.freeTalkVars(); + + // If any sequences have changed in the prior talk file, restore them + if (_savedSequences.size() > 0) { + for (uint idx = 0; idx < _savedSequences.size(); ++idx) { + SavedSequence &ss = _savedSequences[idx]; + for (uint idx2 = 0; idx2 < _savedSequences.size(); ++idx2) + scene._bgShapes[ss._objNum]._sequences[idx2] = ss._sequences[idx2]; + + // Reset the object's frame to the beginning of the sequence + scene._bgShapes[ss._objNum]._frameNumber = 0; + } + } + + while (_sequenceStack.empty()) + pullSequence(); + + // Restore any pressed button + if (!ui._windowOpen && savedMode != STD_MODE) + ui.restoreButton(savedMode - 1); + + // Clear the ui counter so that anything displayed on the info line + // before the window was opened isn't cleared + ui._menuCounter = 0; + + // Close any previous window before starting the talk + if (ui._windowOpen) { + switch (savedMode) { + case LOOK_MODE: + events.setCursor(ARROW); + + if (ui._invLookFlag) { + screen.resetDisplayBounds(); + ui.drawInterface(2); + } + + ui.banishWindow(); + ui._windowBounds.top = CONTROLS_Y1; + ui._temp = ui._oldTemp = ui._lookHelp = 0; + ui._menuMode = STD_MODE; + events._pressed = events._released = events._oldButtons = 0; + ui._invLookFlag = false; + break; + + case TALK_MODE: + if (_speaker < 128) + clearTalking(); + if (_talkCounter) + return; + + // If we were in inventory mode looking at an object, restore the + // back buffers before closing the window, so we get the ui restored + // rather than the inventory again + if (ui._invLookFlag) { + screen.resetDisplayBounds(); + ui.drawInterface(2); + ui._invLookFlag = ui._lookScriptFlag = false; + } + + ui.banishWindow(); + ui._windowBounds.top = CONTROLS_Y1; + scripts._abortFlag = true; + break; + + case INV_MODE: + case USE_MODE: + case GIVE_MODE: + inv.freeInv(); + if (ui._invLookFlag) { + screen.resetDisplayBounds(); + ui.drawInterface(2); + ui._invLookFlag = ui._lookScriptFlag = false; + } + + ui._infoFlag = true; + ui.clearInfo(); + ui.banishWindow(false); + ui._key = -1; + break; + + case FILES_MODE: + ui.banishWindow(true); + ui._windowBounds.top = CONTROLS_Y1; + scripts._abortFlag = true; + break; + + case SETUP_MODE: + ui.banishWindow(true); + ui._windowBounds.top = CONTROLS_Y1; + ui._temp = ui._oldTemp = ui._lookHelp = ui._invLookFlag = false; + ui._menuMode = STD_MODE; + events._pressed = events._released = events._oldButtons = 0; + scripts._abortFlag = true; + break; + } + } + + screen.resetDisplayBounds(); + events._pressed = events._released = false; + loadTalkFile(filename); + ui._selector = ui._oldSelector = ui._key = ui._oldKey = -1; + + // Find the first statement that has the correct flags + int select = -1; + for (uint idx = 0; idx < _statements.size() && select == -1; ++idx) { + /* + if (!_talkMap[idx]) + select = _talkIndex = idx; + */ + } + + // TODOa } void Talk::talk(int objNum) { @@ -45,5 +270,67 @@ void Talk::freeTalkVars() { _statements.clear(); } +void Talk::pullSequence() { + // TODO +} + +/** + * Opens the talk file 'talk.tlk' and searches the index for the specified + * conversation. If found, the data for that conversation is loaded + */ +void Talk::loadTalkFile(const Common::String &filename) { + People &people = *_vm->_people; + Resources &res = *_vm->_res; + Sound &sound = *_vm->_sound; + + // Check for an existing person being talked to + _talkTo = -1; + for (int idx = 0; idx < MAX_PEOPLE; ++idx) { + if (scumm_strnicmp(filename.c_str(), people[(PeopleId)idx]._portrait.c_str(), 4)) { + _talkTo = idx; + break; + } + } + + const char *chP = strchr(filename.c_str(), '.'); + Common::String talkFile = !chP ? filename + ".tlk" : + Common::String(filename.c_str(), chP) + ".tlk"; + + // Open the talk file for reading + Common::SeekableReadStream *talkStream = res.load(talkFile); + talkStream->skip(2); // Skip talk file version num + + _statements.resize(talkStream->readByte()); + for (uint idx = 0; idx < _statements.size(); ++idx) + _statements[idx].synchronize(*talkStream, sound._voicesOn); + + delete talkStream; + setTalkMap(); +} + +void Talk::clearTalking() { + // TODO +} + +/** + * Form a translate table from the loaded statements from a talk file + */ +void Talk::setTalkMap() { + int statementNum = 0; + + for (uint sIdx = 0; sIdx < _statements.size(); ++sIdx) { + Statement &statement = _statements[sIdx]; + + // Set up talk map entry for the statement + bool valid = true; + for (uint idx = 0; idx < statement._required.size(); ++idx) { + if (!_vm->readFlags(statement._required[idx])) + valid = false; + } + + statement._talkMap = valid ? statementNum++ : -1; + } +} + } // End of namespace Sherlock diff --git a/engines/sherlock/talk.h b/engines/sherlock/talk.h index 9359b77e87..6ef4a04b6a 100644 --- a/engines/sherlock/talk.h +++ b/engines/sherlock/talk.h @@ -25,31 +25,58 @@ #include "common/scummsys.h" #include "common/array.h" +#include "common/stream.h" +#include "common/stack.h" namespace Sherlock { -struct TalkHistoryEntry { -private: - int _data[2]; -public: - TalkHistoryEntry() { _data[0] = _data[1] = 0; } +struct SavedSequence { + int _objNum; + Common::Array _sequences; +}; - int &operator[](int idx) { return _data[idx]; } +struct Statement { + Common::String _statement; + Common::String _reply; + Common::String _linkFile; + Common::String _voiceFile; + Common::Array _required; + Common::Array _modified; + int _portraitSide; + int _quotient; + int _talkMap; + + void synchronize(Common::SeekableReadStream &s, bool voices); }; class SherlockEngine; class Talk { + private: SherlockEngine *_vm; + int _saveSeqNum; + Common::Array _savedSequences; + Common::Stack _sequenceStack; + Common::Array _statements; + int _speaker; + int _talkIndex; + int _talkTo; + + void pullSequence(); + + void loadTalkFile(const Common::String &filename); + + void clearTalking(); + + void setTalkMap(); public: - Common::Array _statements; bool _talkToAbort; int _talkCounter; public: Talk(SherlockEngine *vm); - void talkTo(const Common::String &name); + void talkTo(const Common::String &filename); void talk(int objNum); diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index 5e8b3287f0..9fe8a0979f 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -43,14 +43,14 @@ const int MENU_POINTS[12][4] = { // Inventory control locations */ const int INVENTORY_POINTS[8][3] = { - { 4, 50, 28 }, - { 52, 99, 76 }, - { 101, 140, 122 }, - { 142, 187, 165 }, - { 189, 219, 197 }, - { 221, 251, 233 }, - { 253, 283, 265 }, - { 285, 315, 293 } + { 4, 50, 29 }, + { 52, 99, 77 }, + { 101, 140, 123 }, + { 142, 187, 166 }, + { 189, 219, 198 }, + { 221, 251, 234 }, + { 253, 283, 266 }, + { 285, 315, 294 } }; const char COMMANDS[13] = "LMTPOCIUGJFS"; @@ -85,6 +85,7 @@ UserInterface::UserInterface(SherlockEngine *vm) : _vm(vm) { _windowStyle = 1; // Sliding windows _find = 0; _oldUse = 0; + _endKeyActive = true; } UserInterface::~UserInterface() { @@ -101,12 +102,15 @@ void UserInterface::reset() { /** * Draw the user interface onto the screen's back buffers */ -void UserInterface::drawInterface() { +void UserInterface::drawInterface(int bufferNum) { Screen &screen = *_vm->_screen; - screen._backBuffer2.fillRect(0, INFO_LINE, SHERLOCK_SCREEN_WIDTH, INFO_LINE + 10, INFO_BLACK); - screen._backBuffer1.transBlitFrom((*_controlPanel)[0], Common::Point(0, CONTROLS_Y)); - screen._backBuffer2.transBlitFrom((*_controlPanel)[0], Common::Point(0, CONTROLS_Y)); + if (bufferNum & 1) + screen._backBuffer1.transBlitFrom((*_controlPanel)[0], Common::Point(0, CONTROLS_Y)); + if (bufferNum & 2) + screen._backBuffer2.transBlitFrom((*_controlPanel)[0], Common::Point(0, CONTROLS_Y)); + if (bufferNum == 3) + screen._backBuffer2.fillRect(0, INFO_LINE, SHERLOCK_SCREEN_WIDTH, INFO_LINE + 10, INFO_BLACK); } /** @@ -118,6 +122,7 @@ void UserInterface::handleInput() { People &people = *_vm->_people; Scene &scene = *_vm->_scene; Screen &screen = *_vm->_screen; + Scripts &scripts = *_vm->_scripts; Talk &talk = *_vm->_talk; if (_menuCounter) @@ -143,7 +148,7 @@ void UserInterface::handleInput() { } // Do button highlighting check - if (!_vm->_scriptMoreFlag) { // Don't if scripts are running + if (!scripts._scriptMoreFlag) { // Don't if scripts are running if (((events._rightPressed || events._rightReleased) && _helpStyle) || (!_helpStyle && !_menuCounter)) { // Handle any default commands if we're in STD_MODE @@ -276,7 +281,7 @@ void UserInterface::handleInput() { case GIVE_MODE: case INV_MODE: if (inv._invMode == 1 || inv._invMode == 2 || inv._invMode == 3) { - if (pt.y < CONTROLS_Y) + if (pt.y > CONTROLS_Y) lookInv(); else lookScreen(pt); @@ -713,7 +718,7 @@ void UserInterface::doInvControl() { screen.buttonPrint(Common::Point(INVENTORY_POINTS[1][2], CONTROLS_Y1), colors[1], true, "Look"); screen.buttonPrint(Common::Point(INVENTORY_POINTS[2][2], CONTROLS_Y1), colors[1], true, "Use"); screen.buttonPrint(Common::Point(INVENTORY_POINTS[3][2], CONTROLS_Y1), colors[1], true, "Give"); - inv._invMode = found; + inv._invMode = (InvMode)found; _selector = -1; } @@ -734,7 +739,11 @@ void UserInterface::doInvControl() { bool flag = false; if (inv._invMode == 1 || inv._invMode == 2 || inv._invMode == 3) { Common::Rect r(15, CONTROLS_Y1 + 11, 314, SHERLOCK_SCREEN_HEIGHT - 2); - flag = (_selector < inv._holdings); + if (r.contains(mousePos)) { + _selector = (mousePos.x - 6) / 52 + inv._invIndex; + if (_selector < inv._holdings) + flag = true; + } } if (!flag && mousePos.y >(CONTROLS_Y1 + 11)) @@ -753,13 +762,13 @@ void UserInterface::doInvControl() { int temp = inv._invMode; const char *chP = strchr(INVENTORY_COMMANDS, _key); - inv._invMode = !chP ? 8 : chP - INVENTORY_COMMANDS; + inv._invMode = !chP ? INVMODE_INVALID : (InvMode)(chP - INVENTORY_COMMANDS); inv.invCommands(true); - inv._invMode = temp; + inv._invMode = (InvMode)temp; _keyboardInput = true; if (_key == 'E') - inv._invMode = STD_MODE; + inv._invMode = INVMODE_EXIT; _selector = -1; } else { _selector = -1; @@ -789,11 +798,11 @@ void UserInterface::doInvControl() { events.clearEvents(); events.setCursor(ARROW); } else if ((found == 1 && events._released) || (_key == 'L')) { - inv._invMode = 1; + inv._invMode = INVMODE_LOOK; } else if ((found == 2 && events._released) || (_key == 'U')) { - inv._invMode = 2; + inv._invMode = INVMODE_USE; } else if ((found == 3 && events._released) || (_key == 'G')) { - inv._invMode = 3; + inv._invMode = INVMODE_GIVE; } else if (((found == 4 && events._released) || _key == ',') && inv._invIndex) { if (inv._invIndex >= 6) inv._invIndex -= 6; @@ -855,7 +864,8 @@ void UserInterface::doInvControl() { // If it's -1, then no inventory item is highlighted yet. Otherwise, // an object in the scene has been clicked. - if (_selector != -1 && inv._invMode == 1 && mousePos.y >(CONTROLS_Y1 + 11)) + if (_selector != -1 && inv._invMode == INVMODE_LOOK + && mousePos.y >(CONTROLS_Y1 + 11)) inv.doInvJF(); if (talk._talkToAbort) @@ -879,7 +889,7 @@ void UserInterface::doInvControl() { inv.putInv(1); _selector = temp; // Restore it temp = inv._invMode; - inv._invMode = -1; + inv._invMode = INVMODE_USE55; inv.invCommands(true); _infoFlag = true; diff --git a/engines/sherlock/user_interface.h b/engines/sherlock/user_interface.h index 14462d6a34..157900f0aa 100644 --- a/engines/sherlock/user_interface.h +++ b/engines/sherlock/user_interface.h @@ -57,9 +57,11 @@ extern const char INVENTORY_COMMANDS[9]; class SherlockEngine; class Inventory; +class Talk; class UserInterface { friend class Inventory; + friend class Talk; private: SherlockEngine *_vm; ImageFile *_controlPanel; @@ -72,7 +74,6 @@ private: int _help, _oldHelp; int _key, _oldKey; int _temp, _oldTemp; - int _invLookFlag; int _oldLook; bool _keyboardInput; bool _pause; @@ -89,8 +90,6 @@ private: private: void depressButton(int num); - void restoreButton(int num); - void pushButton(int num); void toggleButton(int num); @@ -120,13 +119,15 @@ public: int _menuCounter; bool _infoFlag; bool _windowOpen; + bool _endKeyActive; + int _invLookFlag; public: UserInterface(SherlockEngine *vm); ~UserInterface(); void reset(); - void drawInterface(); + void drawInterface(int bufferNum = 3); void handleInput(); @@ -140,6 +141,8 @@ public: void summonWindow(const Surface &bgSurface, bool slideUp = true); void summonWindow(bool slideUp = true, int height = CONTROLS_Y); void banishWindow(bool slideUp = true); + + void restoreButton(int num); }; } // End of namespace Sherlock -- cgit v1.2.3 From cf4226be45ddea933ef17722eac0f5ccadc7357b Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 31 Mar 2015 07:55:54 -0400 Subject: SHERLOCK: Implemented talkTo --- engines/sherlock/journal.cpp | 4 + engines/sherlock/journal.h | 2 + engines/sherlock/scripts.cpp | 26 +++- engines/sherlock/scripts.h | 20 ++- engines/sherlock/talk.cpp | 241 +++++++++++++++++++++++++++++++----- engines/sherlock/talk.h | 19 ++- engines/sherlock/user_interface.cpp | 10 ++ engines/sherlock/user_interface.h | 2 + 8 files changed, 290 insertions(+), 34 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/journal.cpp b/engines/sherlock/journal.cpp index ad7df48943..34423d2480 100644 --- a/engines/sherlock/journal.cpp +++ b/engines/sherlock/journal.cpp @@ -37,4 +37,8 @@ Journal::Journal() { _page = 0; } +void Journal::record(int converseNum, int statementNum) { + // TODO +} + } // End of namespace Sherlock diff --git a/engines/sherlock/journal.h b/engines/sherlock/journal.h index 64158ff123..87e5a4f8f2 100644 --- a/engines/sherlock/journal.h +++ b/engines/sherlock/journal.h @@ -39,6 +39,8 @@ public: int _page; public: Journal(); + + void record(int converseNum, int statementNum); }; } // End of namespace Sherlock diff --git a/engines/sherlock/scripts.cpp b/engines/sherlock/scripts.cpp index ace957bd76..1da72c976b 100644 --- a/engines/sherlock/scripts.cpp +++ b/engines/sherlock/scripts.cpp @@ -29,7 +29,31 @@ Scripts::Scripts(SherlockEngine *vm): _vm(vm) { _scriptMoreFlag = 0; _scriptSaveIndex = 0; _scriptSelect = 0; - _abortFlag = false; } +void Scripts::doScript(const Common::String &str) { + // TODO +} + +void Scripts::pullSeq() { + // TODO +} + +void Scripts::pushSeq(int speak) { + // TODO +} + +void Scripts::setStillSeq(int speak) { + // TODO +} + +void Scripts::popStack() { + ScriptEntry script = _scriptStack.pop(); + _scriptName = script._name; + _scriptSaveIndex = script._index; + _scriptSelect = script._select; + _scriptMoreFlag = true; +} + + } // End of namespace Sherlock diff --git a/engines/sherlock/scripts.h b/engines/sherlock/scripts.h index eede1ca103..6c23e72fe4 100644 --- a/engines/sherlock/scripts.h +++ b/engines/sherlock/scripts.h @@ -24,23 +24,39 @@ #define SHERLOCK_SCRIPTS_H #include "common/scummsys.h" -#include "common/array.h" +#include "common/stack.h" namespace Sherlock { class SherlockEngine; +struct ScriptEntry { + Common::String _name; + int _index; + int _select; +}; + class Scripts { private: SherlockEngine *_vm; public: + Common::Stack _scriptStack; int _scriptMoreFlag; Common::String _scriptName; int _scriptSaveIndex; int _scriptSelect; - bool _abortFlag; public: Scripts(SherlockEngine *vm); + + void doScript(const Common::String &str); + + void pullSeq(); + + void pushSeq(int speak); + + void setStillSeq(int speak); + + void popStack(); }; } // End of namespace Sherlock diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index d67013b60e..e3c5ebc5e0 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -25,10 +25,14 @@ namespace Sherlock { +#define SFX_COMMAND 140 + +/*----------------------------------------------------------------*/ + /** * Load the data for a single statement within a talk file */ -void Statement::synchronize(Common::SeekableReadStream &s, bool voices) { +void Statement::synchronize(Common::SeekableReadStream &s) { int length; length = s.readUint16LE(); @@ -39,25 +43,6 @@ void Statement::synchronize(Common::SeekableReadStream &s, bool voices) { for (int idx = 0; idx < length; ++idx) _reply += (char)s.readByte(); - // If we don't have digital sound, we'll need to strip out voice commands from reply - if (!voices) { - // Scan for a 140 byte, which indicates playing a sound - for (uint idx = 0; idx < _reply.size(); ++idx) { - if (_reply[idx] == 140) { - // Replace instruction character with a space, and delete the - // rest of the name following it - _reply = Common::String(_reply.c_str(), _reply.c_str() + idx) + " " + - Common::String(_reply.c_str() + 9); - } - } - - // Ensure the last character of the reply is not a space from the prior - // conversion loop, to avoid any issues with the space ever causing a page - // wrap, and ending up displaying another empty page - while (_reply.lastChar() == ' ') - _reply.deleteLastChar(); - } - length = s.readUint16LE(); for (int idx = 0; idx < length; ++idx) _linkFile += (char)s.readByte(); @@ -81,6 +66,12 @@ void Statement::synchronize(Common::SeekableReadStream &s, bool voices) { /*----------------------------------------------------------------*/ +TalkHistoryEntry::TalkHistoryEntry() { + Common::fill(&_data[0], &_data[16], false); +} + +/*----------------------------------------------------------------*/ + Talk::Talk(SherlockEngine *vm): _vm(vm) { _talkCounter = 0; _talkToAbort = false; @@ -88,6 +79,10 @@ Talk::Talk(SherlockEngine *vm): _vm(vm) { _speaker = 0; _talkIndex = 0; _talkTo = 0; + _scriptSelect = 0; + _converseNum = -1; + _talkStealth = 0; + _talkToFlag = -1; } /** @@ -98,6 +93,7 @@ Talk::Talk(SherlockEngine *vm): _vm(vm) { void Talk::talkTo(const Common::String &filename) { Events &events = *_vm->_events; Inventory &inv = *_vm->_inventory; + Journal &journal = *_vm->_journal; People &people = *_vm->_people; Scene &scene = *_vm->_scene; Screen &screen = *_vm->_screen; @@ -105,6 +101,7 @@ void Talk::talkTo(const Common::String &filename) { Talk &talk = *_vm->_talk; UserInterface &ui = *_vm->_ui; Common::Rect savedBounds = screen.getDisplayBounds(); + bool abortFlag = false; if (filename.empty()) // No filename passed, so exit @@ -137,7 +134,7 @@ void Talk::talkTo(const Common::String &filename) { // Only interrupt if an action if trying to do an action, and not just // if the player is walking around the scene if (people._allowWalkAbort) - scripts._abortFlag = true; + abortFlag = true; people.gotoStand(people._player); } @@ -206,7 +203,7 @@ void Talk::talkTo(const Common::String &filename) { ui.banishWindow(); ui._windowBounds.top = CONTROLS_Y1; - scripts._abortFlag = true; + abortFlag = true; break; case INV_MODE: @@ -228,7 +225,7 @@ void Talk::talkTo(const Common::String &filename) { case FILES_MODE: ui.banishWindow(true); ui._windowBounds.top = CONTROLS_Y1; - scripts._abortFlag = true; + abortFlag = true; break; case SETUP_MODE: @@ -237,7 +234,7 @@ void Talk::talkTo(const Common::String &filename) { ui._temp = ui._oldTemp = ui._lookHelp = ui._invLookFlag = false; ui._menuMode = STD_MODE; events._pressed = events._released = events._oldButtons = 0; - scripts._abortFlag = true; + abortFlag = true; break; } } @@ -250,13 +247,161 @@ void Talk::talkTo(const Common::String &filename) { // Find the first statement that has the correct flags int select = -1; for (uint idx = 0; idx < _statements.size() && select == -1; ++idx) { - /* - if (!_talkMap[idx]) + if (_statements[idx]._talkMap == 0) select = _talkIndex = idx; - */ } - // TODOa + if (scripts._scriptMoreFlag && _scriptSelect != 0) + select = _scriptSelect; + + if (select == -1) + error("Couldn't find statement to display"); + + // Add the statement into the journal and talk history + if (_talkTo != -1 && !_talkHistory[_converseNum][select]) + journal.record(_converseNum | 2048, select); + _talkHistory[_converseNum][select] = true; + + // Check if the talk file is meant to be a non-seen comment + if (filename[7] != '*') { + // Should we start in stealth mode? + if (_statements[select]._statement.hasPrefix("^")) { + _talkStealth = 2; + } else { + // Not in stealth mode, so bring up the ui window + _talkStealth = 0; + ++_talkToFlag; + events.setCursor(WAIT); + + ui._windowBounds.top = CONTROLS_Y; + ui._infoFlag = true; + ui.clearInfo(); + } + + // Handle replies until there's no further linked file, + // or the link file isn't a reply first cnversation + for (;;) { + _sequenceStack.clear(); + _scriptSelect = select; + _speaker = _talkTo; + + Statement &statement = _statements[select]; + scripts.doScript(_statements[select]._reply); + + if (_talkToAbort) + return; + + if (!_talkStealth) + ui.clearWindow(); + + if (statement._modified.size() > 0) { + for (uint idx = 0; idx < statement._modified.size(); ++idx) + _vm->setFlags(statement._modified[idx]); + + setTalkMap(); + } + + // Check for a linked file + if (!statement._linkFile.empty() && !scripts._scriptMoreFlag) { + freeTalkVars(); + loadTalkFile(statement._linkFile); + + // Scan for the first valid statement in the newly loaded file + select = -1; + for (uint idx = 0; idx < _statements.size(); ++idx) { + if (_statements[idx]._talkMap == 0) { + select = idx; + break; + } + } + + if (_talkToFlag == 1) + scripts.pullSeq(); + + // Set the stealth mode for the new talk file + Statement &newStatement = _statements[select]; + _talkStealth = newStatement._statement.hasPrefix("^") ? 2 : 0; + + // If the new conversion is a reply first, then we don't need + // to display any choices, since the reply needs to be shown + if (!newStatement._statement.hasPrefix("*") && + !newStatement._statement.hasPrefix("^")) { + _sequenceStack.clear(); + scripts.pushSeq(_talkTo); + scripts.setStillSeq(_talkTo); + _talkIndex = select; + ui._selector = ui._oldSelector = -1; + + if (!ui._windowOpen) { + // Draw the talk interface on the back buffer + drawInterface(); + displayTalk(false); + } else { + displayTalk(true); + } + + byte color = ui._endKeyActive ? COMMAND_FOREGROUND : COMMAND_NULL; + + // If the window is alraedy open, simply draw. Otherwise, do it + // to the back buffer and then summon the window + if (ui._windowOpen) { + screen.buttonPrint(Common::Point(119, CONTROLS_Y), color, true, "Exit"); + } else { + screen.buttonPrint(Common::Point(119, CONTROLS_Y), color, false, "Exit"); + + if (!ui._windowStyle) { + screen.slamRect(Common::Rect(0, CONTROLS_Y, + SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); + } else { + ui.summonWindow(); + } + + ui._windowOpen = true; + } + + // Break out of loop now that we're waiting for player input + events.setCursor(ARROW); + break; + } else { + // Add the statement into the journal and talk history + if (_talkTo != -1 && !_talkHistory[_converseNum][select]) + journal.record(_converseNum | 2048, select); + _talkHistory[_converseNum][select] = true; + + } + + ui._key = ui._oldKey = COMMANDS[TALK_MODE - 1]; + ui._temp = ui._oldTemp = 0; + ui._menuMode = TALK_MODE; + _talkToFlag = 2; + } else { + freeTalkVars(); + + if (!ui._lookScriptFlag) { + ui.banishWindow(); + ui._windowBounds.top = CONTROLS_Y1; + ui._menuMode = STD_MODE; + } + + break; + } + } + } + + _talkStealth = 0; + events._pressed = events._released = events._oldButtons = 0; + events.clearKeyboard(); + + screen.setDisplayBounds(savedBounds); + _talkToAbort = abortFlag; + + // If a script was added to the script stack, restore state so that the + // previous script can continue + if (!scripts._scriptStack.empty()) { + scripts.popStack(); + } + + events.setCursor(ARROW); } void Talk::talk(int objNum) { @@ -302,9 +447,12 @@ void Talk::loadTalkFile(const Common::String &filename) { _statements.resize(talkStream->readByte()); for (uint idx = 0; idx < _statements.size(); ++idx) - _statements[idx].synchronize(*talkStream, sound._voicesOn); + _statements[idx].synchronize(*talkStream); delete talkStream; + + if (!sound._voicesOn) + stripVoiceCommands(); setTalkMap(); } @@ -313,7 +461,33 @@ void Talk::clearTalking() { } /** - * Form a translate table from the loaded statements from a talk file + * Remove any voice commands from a loaded statement list + */ +void Talk::stripVoiceCommands() { + for (uint sIdx = 0; sIdx < _statements.size(); ++sIdx) { + Statement &statement = _statements[sIdx]; + + // Scan for an sound effect byte, which indicates to play a sound + for (uint idx = 0; idx < statement._reply.size(); ++idx) { + if (statement._reply[idx] == SFX_COMMAND) { + // Replace instruction character with a space, and delete the + // rest of the name following it + statement._reply = Common::String(statement._reply.c_str(), + statement._reply.c_str() + idx) + " " + + Common::String(statement._reply.c_str() + 9); + } + } + + // Ensure the last character of the reply is not a space from the prior + // conversion loop, to avoid any issues with the space ever causing a page + // wrap, and ending up displaying another empty page + while (statement._reply.lastChar() == ' ') + statement._reply.deleteLastChar(); + } +} + +/** + * Form a table of the display indexes for statements */ void Talk::setTalkMap() { int statementNum = 0; @@ -332,5 +506,12 @@ void Talk::setTalkMap() { } } +void Talk::drawInterface() { + // TODO +} + +void Talk::displayTalk(bool slamIt) { + // TODO +} } // End of namespace Sherlock diff --git a/engines/sherlock/talk.h b/engines/sherlock/talk.h index 6ef4a04b6a..6557f6eed6 100644 --- a/engines/sherlock/talk.h +++ b/engines/sherlock/talk.h @@ -46,7 +46,14 @@ struct Statement { int _quotient; int _talkMap; - void synchronize(Common::SeekableReadStream &s, bool voices); + void synchronize(Common::SeekableReadStream &s); +}; + +struct TalkHistoryEntry { + bool _data[16]; + + TalkHistoryEntry(); + bool &operator[](int index) { return _data[index]; } }; class SherlockEngine; @@ -59,9 +66,14 @@ private: Common::Array _savedSequences; Common::Stack _sequenceStack; Common::Array _statements; + TalkHistoryEntry _talkHistory[500]; int _speaker; int _talkIndex; int _talkTo; + int _scriptSelect; + int _converseNum; + int _talkStealth; + int _talkToFlag; void pullSequence(); @@ -69,7 +81,10 @@ private: void clearTalking(); + void stripVoiceCommands(); void setTalkMap(); + + void displayTalk(bool slamIt); public: bool _talkToAbort; int _talkCounter; @@ -81,6 +96,8 @@ public: void talk(int objNum); void freeTalkVars(); + + void drawInterface(); }; } // End of namespace Sherlock diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index 9fe8a0979f..74142ab80e 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -471,6 +471,16 @@ void UserInterface::clearInfo() { } } +/** + * Clear any active text window + */ +void UserInterface::clearWindow() { + if (_windowOpen) { + _vm->_screen->vgaBar(Common::Rect(3, CONTROLS_Y + 11, SHERLOCK_SCREEN_WIDTH - 2, + SHERLOCK_SCREEN_HEIGHT - 2), INV_BACKGROUND); + } +} + /** * Handles counting down whilst checking for input, then clears the info line. */ diff --git a/engines/sherlock/user_interface.h b/engines/sherlock/user_interface.h index 157900f0aa..1259bed31b 100644 --- a/engines/sherlock/user_interface.h +++ b/engines/sherlock/user_interface.h @@ -50,6 +50,7 @@ enum MenuMode { SETUP_MODE = 12 }; +extern const char COMMANDS[13]; extern const int MENU_POINTS[12][4]; extern const int INVENTORY_POINTS[8][3]; @@ -132,6 +133,7 @@ public: void handleInput(); void clearInfo(); + void clearWindow(); void whileMenuCounter(); -- cgit v1.2.3 From 0b873d74e0a607ddf460c91fc6e18d04c7fb7b8c Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 31 Mar 2015 08:28:51 -0400 Subject: SHERLOCK: Implemented displayTalk --- engines/sherlock/screen.h | 3 +- engines/sherlock/talk.cpp | 95 ++++++++++++++++++++++++++++++++++++++++++++++- engines/sherlock/talk.h | 8 +++- 3 files changed, 102 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/screen.h b/engines/sherlock/screen.h index 597c47c83a..edc0136471 100644 --- a/engines/sherlock/screen.h +++ b/engines/sherlock/screen.h @@ -49,7 +49,8 @@ enum { BUTTON_TOP = 233, BUTTON_MIDDLE = 244, BUTTON_BOTTOM = 248, - TALK_FOREGROUND = 12 + TALK_FOREGROUND = 12, + TALK_NULL = 16 }; class SherlockEngine; diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index e3c5ebc5e0..e915169903 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -22,6 +22,7 @@ #include "sherlock/talk.h" #include "sherlock/sherlock.h" +#include "sherlock/screen.h" namespace Sherlock { @@ -83,6 +84,7 @@ Talk::Talk(SherlockEngine *vm): _vm(vm) { _converseNum = -1; _talkStealth = 0; _talkToFlag = -1; + _moreTalkDown = _moreTalkUp = false; } /** @@ -405,6 +407,7 @@ void Talk::talkTo(const Common::String &filename) { } void Talk::talk(int objNum) { + // TODO } @@ -510,8 +513,98 @@ void Talk::drawInterface() { // TODO } -void Talk::displayTalk(bool slamIt) { +/** + * Display a list of statements in a window at the bottom of the scren that the + * player can select from. + */ +bool Talk::displayTalk(bool slamIt) { + Screen &screen = *_vm->_screen; + int yp = CONTROLS_Y + 14; + int lineY = -1; + _moreTalkDown = _moreTalkUp = false; + + for (uint idx = 0; idx < _statements.size(); ++idx) { + _statements[idx]._talkPos.top = _statements[idx]._talkPos.bottom = -1; + } + + if (_talkIndex) { + for (uint idx = 0; idx < _statements.size(); ++idx) { + if (_statements[idx]._talkMap != -1) + _moreTalkUp = true; + } + } + + // Display the up arrow if the first option is scrolled off-screen + if (_moreTalkUp) { + if (slamIt) { + screen.print(Common::Point(5, CONTROLS_Y + 13), INV_FOREGROUND, "~"); + screen.buttonPrint(Common::Point(159, CONTROLS_Y), COMMAND_FOREGROUND, true, "Up"); + } else { + screen.gPrint(Common::Point(5, CONTROLS_Y + 12), INV_FOREGROUND, "~"); + screen.buttonPrint(Common::Point(159, CONTROLS_Y), COMMAND_FOREGROUND, false, "Up"); + } + } else { + if (slamIt) { + screen.buttonPrint(Common::Point(159, CONTROLS_Y), COMMAND_NULL, true, "Up"); + screen.vgaBar(Common::Rect(5, CONTROLS_Y + 11, 15, CONTROLS_Y + 22), INV_BACKGROUND); + } else { + screen.buttonPrint(Common::Point(159, CONTROLS_Y), COMMAND_NULL, false, "Up"); + screen._backBuffer1.fillRect(Common::Rect(5, CONTROLS_Y + 11, + 15, CONTROLS_Y + 22), INV_BACKGROUND); + } + } + + // Loop through the statements + bool done = false; + for (uint idx = _talkIndex; idx < _statements.size() && !done; ++idx) { + Statement &statement = _statements[idx]; + + if (statement._talkMap != -1) { + bool flag = _talkHistory[_converseNum][idx]; + lineY = talkLine(idx, statement._talkMap, flag ? TALK_NULL : INV_FOREGROUND, + yp, slamIt); + + if (lineY != -1) { + statement._talkPos.top = yp; + yp = lineY; + statement._talkPos.bottom = yp; + + if (yp == SHERLOCK_SCREEN_HEIGHT) + done = true; + } else { + done = true; + } + } + } + + // Display the down arrow if there are more statements available + if (lineY == -1 || lineY == SHERLOCK_SCREEN_HEIGHT) { + _moreTalkDown = true; + + if (slamIt) { + screen.print(Common::Point(5, 190), INV_FOREGROUND, "|"); + screen.buttonPrint(Common::Point(200, CONTROLS_Y), COMMAND_FOREGROUND, true, "Down"); + } else { + screen.gPrint(Common::Point(5, 189), INV_FOREGROUND, "|"); + screen.buttonPrint(Common::Point(200, CONTROLS_Y), COMMAND_FOREGROUND, false, "Down"); + } + } else { + if (slamIt) { + screen.buttonPrint(Common::Point(200, CONTROLS_Y), COMMAND_NULL, true, "Down"); + screen.vgaBar(Common::Rect(5, 189, 16, 199), INV_BACKGROUND); + } else { + screen.buttonPrint(Common::Point(200, CONTROLS_Y), COMMAND_FOREGROUND, false, "Down"); + screen._backBuffer1.fillRect(Common::Rect(5, 189, 16, 199), INV_BACKGROUND); + } + } + + return done; +} + +int Talk::talkLine(int lineNum, int stateNum, byte color, int lineY, bool slamIt) { // TODO + return 0; } + } // End of namespace Sherlock diff --git a/engines/sherlock/talk.h b/engines/sherlock/talk.h index 6557f6eed6..d44419f9a9 100644 --- a/engines/sherlock/talk.h +++ b/engines/sherlock/talk.h @@ -25,6 +25,7 @@ #include "common/scummsys.h" #include "common/array.h" +#include "common/rect.h" #include "common/stream.h" #include "common/stack.h" @@ -45,6 +46,7 @@ struct Statement { int _portraitSide; int _quotient; int _talkMap; + Common::Rect _talkPos; void synchronize(Common::SeekableReadStream &s); }; @@ -59,7 +61,6 @@ struct TalkHistoryEntry { class SherlockEngine; class Talk { - private: SherlockEngine *_vm; int _saveSeqNum; @@ -74,6 +75,7 @@ private: int _converseNum; int _talkStealth; int _talkToFlag; + bool _moreTalkUp, _moreTalkDown; void pullSequence(); @@ -84,7 +86,9 @@ private: void stripVoiceCommands(); void setTalkMap(); - void displayTalk(bool slamIt); + bool displayTalk(bool slamIt); + + int talkLine(int lineNum, int stateNum, byte color, int lineY, bool slamIt); public: bool _talkToAbort; int _talkCounter; -- cgit v1.2.3 From 87521eb504ddb8f05c6b61cfdaf3c757f5adce64 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 31 Mar 2015 20:16:34 -0400 Subject: SHERLOCK: Implemented talkLine --- engines/sherlock/talk.cpp | 91 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 88 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index e915169903..a84ce7cd70 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -601,10 +601,95 @@ bool Talk::displayTalk(bool slamIt) { return done; } +/** + * Prints a single conversation option in the interface window + */ int Talk::talkLine(int lineNum, int stateNum, byte color, int lineY, bool slamIt) { - // TODO - return 0; -} + Screen &screen = *_vm->_screen; + int idx = lineNum; + Common::String msg, number; + bool numberFlag = false; + + // Get the statement to display as well as optional number prefix + if (idx < 128) { + number = Common::String::format("%d.", stateNum + 1); + numberFlag = true; + } else { + idx -= 128; + } + msg = _statements[idx]._statement; + + // Handle potentially multiple lines needed to display entire statement + const char *lineStartP = msg.c_str(); + int maxWidth = 298 - numberFlag ? 18 : 0; + for (;;) { + // Get as much of the statement as possible will fit on the + Common::String sLine; + const char *lineEndP = lineStartP; + int width = 0; + do { + width += screen.charWidth(*lineEndP); + } while (*++lineEndP && width < maxWidth); + + // Check if we need to wrap the line + if (width >= maxWidth) { + // Work backwards to the prior word's end + while (*--lineEndP != ' ') + ; + + sLine = Common::String(lineStartP, lineEndP++); + } else { + // Can display remainder of the statement on the current line + sLine = Common::String(lineStartP); + } + + + if (lineY <= (SHERLOCK_SCREEN_HEIGHT - 10)) { + // Need to directly display on-screen? + if (slamIt) { + // See if a numer prefix is needed or not + if (numberFlag) { + // Are we drawing the first line? + if (lineStartP == msg.c_str()) { + // We are, so print the number and then the text + screen.print(Common::Point(16, lineY), color, number.c_str()); + } + + // Draw the line with an indent + screen.print(Common::Point(30, lineY), color, sLine.c_str()); + } else { + screen.print(Common::Point(16, lineY), color, sLine.c_str()); + } + } else { + if (numberFlag) { + if (lineStartP == msg.c_str()) { + screen.gPrint(Common::Point(16, lineY - 1), color, number.c_str()); + } + + screen.gPrint(Common::Point(30, lineY - 1), color, sLine.c_str()); + } else { + screen.gPrint(Common::Point(16, lineY - 1), color, sLine.c_str()); + } + } + // Move to next line, if any + lineY += 9; + lineStartP = lineEndP; + + if (!*lineEndP) + break; + } else { + // We're close to the bottom of the screen, so stop display + lineY = -1; + break; + } + } + + if (lineY == -1 && lineStartP != msg.c_str()) + lineY = SHERLOCK_SCREEN_HEIGHT; + + // Return the Y position of the next line to follow this one + return lineY; +} } // End of namespace Sherlock -- cgit v1.2.3 From 54ecf6cda88f6a32b0e12f9fdb2698c540d76bd4 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 31 Mar 2015 20:37:59 -0400 Subject: SHERLOCK: Implemented talk method --- engines/sherlock/talk.cpp | 97 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 96 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index a84ce7cd70..e5d6cea64a 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -406,9 +406,104 @@ void Talk::talkTo(const Common::String &filename) { events.setCursor(ARROW); } +/** + * Main method for handling conversations when a character to talk to has been + * selected. It will make Holmes walk to the person to talk to, draws the + * interface window for the conversation and passes on control to give the + * player a list of options to make a selection from + */ void Talk::talk(int objNum) { + Events &events = *_vm->_events; + People &people = *_vm->_people; + Scene &scene = *_vm->_scene; + Screen &screen = *_vm->_screen; + Scripts &scripts = *_vm->_scripts; + UserInterface &ui = *_vm->_ui; + Object &obj = scene._bgShapes[objNum]; - // TODO + ui._windowBounds.top = CONTROLS_Y; + ui._infoFlag = true; + _speaker = 128; + loadTalkFile(scene._bgShapes[objNum]._name); + + // Find the first statement with the correct flags + int select = -1; + for (uint idx = 0; idx < _statements.size(); ++idx) { + if (_statements[idx]._talkMap == 0) { + select = idx; + break; + } + } + if (select == -1) + error("No entry matched all required flags"); + + // See if the statement is a stealth mode reply + Statement &statement = _statements[select]; + if (statement._statement.hasPrefix("^")) { + _sequenceStack.clear(); + + // Start talk in stealth mode + _talkStealth = 2; + + talkTo(obj._name); + } else if (statement._statement.hasPrefix("*")) { + // Character being spoken to will speak first + _sequenceStack.clear(); + scripts.pushSeq(_talkTo); + scripts.setStillSeq(_talkTo); + + events.setCursor(WAIT); + if (obj._lookPosition.y != 0) + // Need to walk to character first + people.walkToCoords(Common::Point(obj._lookPosition.x, obj._lookPosition.y * 100), + obj._lookFacing); + events.setCursor(ARROW); + + if (_talkToAbort) + talkTo(obj._name); + } else { + // Holmes will be speaking first + _sequenceStack.clear(); + scripts.pushSeq(_talkTo); + scripts.setStillSeq(_talkTo); + + _talkToFlag = false; + events.setCursor(WAIT); + if (obj._lookPosition.y != 0) + // Walk over to person to talk to + people.walkToCoords(Common::Point(obj._lookPosition.x, obj._lookPosition.y * 100), + obj._lookFacing); + events.setCursor(ARROW); + + if (!_talkToAbort) { + // See if walking over triggered a conversation + if (_talkToFlag) { + if (_talkToFlag == 1) { + events.setCursor(ARROW); + // _sequenceStack._count = 1; + scripts.pullSeq(); + } + } else { + drawInterface(); + + events._pressed = events._released = false; + _talkIndex = select; + displayTalk(false); + ui._selector = ui._oldSelector = -1; + + if (!ui._windowStyle) { + screen.slamRect(Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, + SHERLOCK_SCREEN_HEIGHT)); + } else { + ui.summonWindow(); + } + + ui._windowOpen = true; + } + + _talkToFlag = -1; + } + } } /** -- cgit v1.2.3 From 8fa8b14762ce655d0d99782864be927d3c946cba Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 31 Mar 2015 21:30:22 -0400 Subject: SHERLOCK: Implement clearTalking and Talk::drawInterface --- engines/sherlock/people.cpp | 36 ++++++++++++++++++++++++++++++++++++ engines/sherlock/people.h | 4 ++++ engines/sherlock/talk.cpp | 35 +++++++++++++++++++++++++++++------ engines/sherlock/talk.h | 2 -- engines/sherlock/user_interface.h | 2 ++ 5 files changed, 71 insertions(+), 8 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp index ca840bb5b1..8d4fa68117 100644 --- a/engines/sherlock/people.cpp +++ b/engines/sherlock/people.cpp @@ -57,13 +57,16 @@ People::People(SherlockEngine *vm) : _vm(vm), _player(_data[0]) { _oldWalkSequence = -1; _allowWalkAbort = false; _portraitLoaded = false; + _portraitsOn = false; _clearingThePortrait = false; _srcZone = _destZone = 0; + _talkPics = nullptr; } People::~People() { if (_walkLoaded) delete _data[PLAYER]._images; + delete _talkPics; } void People::reset() { @@ -434,4 +437,37 @@ void People::goAllTheWay() { } } +/** + * Turn off any currently active portraits, and removes them from being drawn + */ +void People::clearTalking() { + Scene &scene = *_vm->_scene; + Screen &screen = *_vm->_screen; + Talk &talk = *_vm->_talk; + + if (_portraitsOn) { + Common::Point pt = _portrait._position; + int width, height; + _portrait._imageFrame = _talkPics ? &(*_talkPics)[0] : (ImageFrame *)nullptr; + + // Flag portrait for removal, and save the size of the frame to use erasing it + _portrait._type = REMOVE; + _portrait._delta.x = width = _portrait.frameWidth(); + _portrait._delta.y = height = _portrait.frameHeight(); + + delete _talkPics; + _talkPics = nullptr; + + // Flag to let the talk code know not to interrupt on the next doBgAnim + _clearingThePortrait = true; + scene.doBgAnim(); + _clearingThePortrait = false; + + screen.slamArea(pt.x, pt.y, width, height); + + if (!talk._talkToAbort) + _portraitLoaded = false; + } +} + } // End of namespace Sherlock diff --git a/engines/sherlock/people.h b/engines/sherlock/people.h index 6b5c59b1bd..1c67ff8996 100644 --- a/engines/sherlock/people.h +++ b/engines/sherlock/people.h @@ -66,12 +66,14 @@ private: bool _walkLoaded; int _oldWalkSequence; int _srcZone, _destZone; + ImageFile *_talkPics; public: Common::Point _walkDest; Common::Stack _walkTo; Person &_player; bool _holmesOn; bool _portraitLoaded; + bool _portraitsOn; Object _portrait; bool _clearingThePortrait; bool _allowWalkAbort; @@ -96,6 +98,8 @@ public: void walkToCoords(const Common::Point &destPos, int destDir); void goAllTheWay(); + + void clearTalking(); }; } // End of namespace Sherlock diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index e5d6cea64a..79f9167506 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -190,7 +190,7 @@ void Talk::talkTo(const Common::String &filename) { case TALK_MODE: if (_speaker < 128) - clearTalking(); + people.clearTalking(); if (_talkCounter) return; @@ -554,10 +554,6 @@ void Talk::loadTalkFile(const Common::String &filename) { setTalkMap(); } -void Talk::clearTalking() { - // TODO -} - /** * Remove any voice commands from a loaded statement list */ @@ -604,8 +600,35 @@ void Talk::setTalkMap() { } } +/** + * Draws the interface for conversation display + */ void Talk::drawInterface() { - // TODO + Screen &screen = *_vm->_screen; + Surface &bb = *screen._backBuffer; + + bb.fillRect(Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, CONTROLS_Y1 + 10), BORDER_COLOR); + bb.fillRect(Common::Rect(0, CONTROLS_Y + 10, 2, SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR); + bb.fillRect(Common::Rect(SHERLOCK_SCREEN_WIDTH - 2, CONTROLS_Y + 10, + SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR); + bb.fillRect(Common::Rect(0, SHERLOCK_SCREEN_HEIGHT - 1, SHERLOCK_SCREEN_WIDTH - 2, + SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR); + bb.fillRect(Common::Rect(2, CONTROLS_Y + 10, SHERLOCK_SCREEN_WIDTH - 2, + SHERLOCK_SCREEN_HEIGHT - 2), INV_BACKGROUND); + + if (_talkTo != -1) { + screen.makeButton(Common::Rect(99, CONTROLS_Y, 139, CONTROLS_Y + 10), + 119 - screen.stringWidth("Exit") / 2, "Exit"); + screen.makeButton(Common::Rect(140, CONTROLS_Y, 180, CONTROLS_Y + 10), + 159 - screen.stringWidth("Up"), "Up"); + screen.makeButton(Common::Rect(181, CONTROLS_Y, 221, CONTROLS_Y + 10), + 200 - screen.stringWidth("Down") / 2, "Down"); + } else { + int strWidth = screen.stringWidth(PRESS_KEY_TO_CONTINUE); + screen.makeButton(Common::Rect(46, CONTROLS_Y, 273, CONTROLS_Y + 10), + 160 - strWidth, PRESS_KEY_TO_CONTINUE); + screen.gPrint(Common::Point(160 - strWidth / 2, CONTROLS_Y), COMMAND_FOREGROUND, false, "P"); + } } /** diff --git a/engines/sherlock/talk.h b/engines/sherlock/talk.h index d44419f9a9..dbcdf742b8 100644 --- a/engines/sherlock/talk.h +++ b/engines/sherlock/talk.h @@ -81,8 +81,6 @@ private: void loadTalkFile(const Common::String &filename); - void clearTalking(); - void stripVoiceCommands(); void setTalkMap(); diff --git a/engines/sherlock/user_interface.h b/engines/sherlock/user_interface.h index 1259bed31b..f80fe48b2d 100644 --- a/engines/sherlock/user_interface.h +++ b/engines/sherlock/user_interface.h @@ -55,6 +55,8 @@ extern const int MENU_POINTS[12][4]; extern const int INVENTORY_POINTS[8][3]; extern const char INVENTORY_COMMANDS[9]; +extern const char *const PRESS_KEY_FOR_MORE; +extern const char *const PRESS_KEY_TO_CONTINUE; class SherlockEngine; class Inventory; -- cgit v1.2.3 From 1199cf724c7507fb54a52eea842ac2bcc6864736 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 31 Mar 2015 22:42:57 -0400 Subject: SHERLOCK: Loading for TALK_SEQUENCES and STILL_SEQUENCES Scalpel arrays --- engines/sherlock/people.cpp | 5 ++ engines/sherlock/people.h | 2 + engines/sherlock/scalpel/scalpel.cpp | 145 +++++++++++++++++++++++++++++++++++ engines/sherlock/scripts.cpp | 12 --- engines/sherlock/scripts.h | 6 -- engines/sherlock/talk.cpp | 100 +++++++++++++++++++----- engines/sherlock/talk.h | 27 ++++++- 7 files changed, 257 insertions(+), 40 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp index 8d4fa68117..3da35f2fec 100644 --- a/engines/sherlock/people.cpp +++ b/engines/sherlock/people.cpp @@ -470,4 +470,9 @@ void People::clearTalking() { } } +int People::findSpeaker(int speaker) { + // TODO + return -1; +} + } // End of namespace Sherlock diff --git a/engines/sherlock/people.h b/engines/sherlock/people.h index 1c67ff8996..aa54c67567 100644 --- a/engines/sherlock/people.h +++ b/engines/sherlock/people.h @@ -100,6 +100,8 @@ public: void goAllTheWay(); void clearTalking(); + + int findSpeaker(int speaker); }; } // End of namespace Sherlock diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp index d226c2e82a..0432dc2278 100644 --- a/engines/sherlock/scalpel/scalpel.cpp +++ b/engines/sherlock/scalpel/scalpel.cpp @@ -39,6 +39,148 @@ const int MAP_Y[NUM_PLACES] = { 37, 0, 70, 0, 116, 0, 0, 0, 50, 21, 0, 303, 0, 0, 229, 0, 0 }; +#define MAX_PEOPLE 66 + +const byte STILL_SEQUENCES[MAX_PEOPLE][MAX_TALK_SEQUENCES] = { + { 1, 0, 0 }, // Sherlock Holmes + { 6, 0, 0 }, // Dr. Watson + { 4, 0, 0 }, // Inspector Lestrade + { 2, 0, 0 }, // Constable #1 + { 2, 0, 0 }, // Constable #2 + { 2, 0, 0 }, // Sheila Parker + { 3, 0, 0 }, // Henry Carruthers + { 9, 0, 0 }, // Lesly (flower girl) + { 13, 0, 0 }, // Usher #1 + { 2, 0, 0 }, // Usher #2 + { 4, 0, 0 }, // Fredrick Epstein + { 9, 0, 0 }, // Mrs.Worthington + { 2, 0, 0 }, // Coach + { 8, 0, 0 }, // Player + { 13, 0, 0 }, // Waterboy + { 6, 0, 0 }, // James Sanders + { 1, 0, 0 }, // Belle (perfumerie) + { 20, 0, 0 }, // Cleaning Girl (perfumerie) + { 17, 0, 0 }, // Epstien in the Opera Balcony + { 3, 0, 0 }, // Wiggins + { 2, 0, 0 }, // Paul (Brumwell/Carroway) + { 1, 0, 0 }, // Bartender + { 1, 0, 0 }, // Dirty Drunk + { 1, 0, 0 }, // Shouting Drunk + { 1, 0, 0 }, // Staggering Drunk + { 1, 0, 0 }, // Bouncer + { 6, 0, 0 }, // James Sanders - At Home + { 6, 0, 0 }, // The Coroner + { 1, 0, 0 }, // The Equestrian Shop Keeper + { 1, 0, 0 }, // George Blackwood + { 7, 0, 0 }, // Lars + { 1, 0, 0 }, // Sheila Parker + { 8, 0, 0 }, // Chemist + { 6, 0, 0 }, // Inspector Gregson + { 1, 0, 0 }, // Lawyer + { 1, 0, 0 }, // Mycroft + { 7, 0, 0 }, // Old Sherman + { 1, 0, 0 }, // Stock Boy in Chemist Shop + { 1, 0, 0 }, // Barman + { 1, 0, 0 }, // Dandy Player + { 1, 0, 0 }, // Rough-looking Player + { 1, 0, 0 }, // Spectator + { 1, 0, 0 }, // Robert Hunt + { 3, 0, 0 }, // Violet Secretary + { 1, 0, 0 }, // Pettigrew + { 8, 0, 0 }, // Augie (apple seller) + { 16, 0, 0 }, // Anna Carroway + { 1, 0, 0 }, // Guard + { 8, 0, 0 }, // Antonio Caruso + { 1, 0, 0 }, // Toby the Dog + { 13, 0, 0 }, // Simon Kingsley + { 2, 0, 0 }, // Alfred Tobacco Clerk + { 1, 0, 0 }, // Lady Brumwell + { 1, 0, 0 }, // Madame Rosa + { 1, 0, 0 }, // Lady Brumwell + { 1, 0, 0 }, // Joseph Moorehead + { 5, 0, 0 }, // Mrs. Beale + { 1, 0, 0 }, // Felix the Lion + { 1, 0, 0 }, // Hollingston + { 1, 0, 0 }, // Constable Callaghan + { 2, 0, 0 }, // Sergeant Jeremy Duncan + { 1, 0, 0 }, // Lord Brumwell + { 1, 0, 0 }, // Nigel Jameson + { 1, 0, 0 }, // Jonas (newspaper seller) + { 1, 0, 0 }, // Constable Dugan + { 4, 0, 0 } // Inspector Lestrade (Yard) +}; + +byte TALK_SEQUENCES[MAX_PEOPLE][MAX_TALK_SEQUENCES] = { + { 1, 0, 0 }, // Sherlock Holmes + { 5, 5, 6, 7, 8, 7, 8, 6, 0, 0 }, // Dr. Watson + { 2, 0, 0 }, // Inspector Lestrade + { 1, 0, 0 }, // Constable #1 + { 1, 0, 0 }, // Constable #2 + { 2, 3, 0, 0 }, // Sheila Parker + { 3, 0, 0 }, // Henry Carruthers + { 1, 2, 3, 2, 1, 2, 3, 0, 0 }, // Lesly (flower girl) + { 13, 14, 0, 0 }, // Usher #1 + { 2, 0, 0 }, // Usher #2 + { 1, 2, 3, 4, 3, 4, 3, 2, 0, 0 }, // Fredrick Epstein + { 8, 0, 0 }, // Mrs.Worthington + { 1, 2, 3, 4, 5, 4, 3, 2, 0, 0 }, // Coach + { 7, 8, 0, 0 }, // Player + { 12, 13, 0, 0 }, // Waterboy + { 3, 4, 0, 0 }, // James Sanders + { 4, 5, 0, 0 }, // Belle (perfumerie) + { 14, 15, 16, 17, 18, 19, 20, 20, 20, 0, 0 }, // Cleaning Girl (perfumerie) + { 16, 17, 18, 18, 18, 17, 17, 0, 0 }, // Epstien in the Opera Balcony + { 2, 3, 0, 0 }, // Wiggins + { 1, 2, 0, 0 }, // Paul (Brumwell/Carroway) + { 1, 0, 0 }, // Bartender + { 1, 0, 0 }, // Dirty Drunk + { 1, 0, 0 }, // Shouting Drunk + { 1, 0, 0 }, // Staggering Drunk + { 1, 0, 0 }, // Bouncer + { 5, 6, 0, 0 }, // James Sanders - At Home + { 4, 5, 0, 0 }, // The Coroner + { 1, 0, 0 }, // The Equestrian Shop Keeper + { 1, 0, 0 }, // George Blackwood + { 5, 6, 0, 0 }, // Lars + { 1, 0, 0 }, // Sheila Parker + { 8, 9, 0, 0 }, // Chemist + { 5, 6, 0, 0 }, // Inspector Gregson + { 1, 0, 0 }, // Lawyer + { 1, 0, 0 }, // Mycroft + { 7, 8, 0, 0 }, // Old Sherman + { 1, 0, 0 }, // Stock Boy in Chemist Shop + { 1, 0, 0 }, // Barman + { 1, 0, 0 }, // Dandy Player + { 1, 0, 0 }, // Rough-looking Player + { 1, 0, 0 }, // Spectator + { 1, 0, 0 }, // Robert Hunt + { 3, 4, 0, 0 }, // Violet Secretary + { 1, 0, 0 }, // Pettigrew + { 14, 15, 0, 0 }, // Augie (apple seller) + { 3, 4, 5, 6, 0, 0 }, // Anna Carroway + { 4, 5, 6, 0, 0 }, // Guard + { 7, 8, 0, 0 }, // Antonio Caruso + { 1, 0, 0 }, // Toby the Dog + { 13, 14, 0, 0 }, // Simon Kingsley + { 2, 3, 0, 0 }, // Alfred Tobacco Clerk + { 3, 4, 0, 0 }, // Lady Brumwell + { 1, 30, 0, 0 }, // Madame Rosa + { 3, 4, 0, 0 }, // Lady Brumwell + { 1, 0, 0 }, // Joseph Moorehead + { 14, 15, 16, 17, 18, 19, 20, 0, 0 }, // Mrs. Beale + { 1, 0, 0 }, // Felix the Lion + { 1, 0, 0 }, // Hollingston + { 1, 0, 0 }, // Constable Callaghan + { 1, 1, 2, 2, 0, 0 }, // Sergeant Jeremy Duncan + { 9, 10, 0, 0 }, // Lord Brumwell + { 1, 2, 0, 138, 3, 4, 0, 138, 0, 0 }, // Nigel Jameson + { 1, 8, 0, 0 }, // Jonas (newspaper seller) + { 1, 0, 0 }, // Constable Dugan + { 2, 0, 0 } // Inspector Lestrade (Yard) +}; + +/*----------------------------------------------------------------*/ + ScalpelEngine::ScalpelEngine(OSystem *syst, const SherlockGameDescription *gameDesc) : SherlockEngine(syst, gameDesc) { _chess = nullptr; @@ -71,6 +213,9 @@ void ScalpelEngine::initialize() { // Load the inventory loadInventory(); + // Set up constants used by the talk system + _talk->setSequences(&TALK_SEQUENCES[0][0], &STILL_SEQUENCES[0][0], MAX_PEOPLE); + // Starting scene _scene->_goToScene = 4; } diff --git a/engines/sherlock/scripts.cpp b/engines/sherlock/scripts.cpp index 1da72c976b..d337030bae 100644 --- a/engines/sherlock/scripts.cpp +++ b/engines/sherlock/scripts.cpp @@ -35,18 +35,6 @@ void Scripts::doScript(const Common::String &str) { // TODO } -void Scripts::pullSeq() { - // TODO -} - -void Scripts::pushSeq(int speak) { - // TODO -} - -void Scripts::setStillSeq(int speak) { - // TODO -} - void Scripts::popStack() { ScriptEntry script = _scriptStack.pop(); _scriptName = script._name; diff --git a/engines/sherlock/scripts.h b/engines/sherlock/scripts.h index 6c23e72fe4..6765687bcf 100644 --- a/engines/sherlock/scripts.h +++ b/engines/sherlock/scripts.h @@ -50,12 +50,6 @@ public: void doScript(const Common::String &str); - void pullSeq(); - - void pushSeq(int speak); - - void setStillSeq(int speak); - void popStack(); }; diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index 79f9167506..26c2e523f3 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -73,6 +73,16 @@ TalkHistoryEntry::TalkHistoryEntry() { /*----------------------------------------------------------------*/ +TalkSequences::TalkSequences(const byte *data) { + Common::copy(data, data + MAX_TALK_SEQUENCES, _data); +} + +void TalkSequences::clear() { + Common::fill(&_data[0], &_data[MAX_TALK_SEQUENCES], 0); +} + +/*----------------------------------------------------------------*/ + Talk::Talk(SherlockEngine *vm): _vm(vm) { _talkCounter = 0; _talkToAbort = false; @@ -87,6 +97,15 @@ Talk::Talk(SherlockEngine *vm): _vm(vm) { _moreTalkDown = _moreTalkUp = false; } +void Talk::setSequences(const byte *talkSequences, const byte *stillSequences, int maxPeople) { + for (int idx = 0; idx < maxPeople; ++idx) { + STILL_SEQUENCES.push_back(TalkSequences(stillSequences)); + TALK_SEQUENCES.push_back(TalkSequences(talkSequences)); + stillSequences += MAX_TALK_SEQUENCES; + talkSequences += MAX_TALK_SEQUENCES; + } +} + /** * Called when either an NPC initiates a conversation or for inventory item * descriptions. It opens up a description window similar to how 'talk' does, @@ -158,7 +177,7 @@ void Talk::talkTo(const Common::String &filename) { } } - while (_sequenceStack.empty()) + while (!_sequenceStack.empty()) pullSequence(); // Restore any pressed button @@ -283,7 +302,7 @@ void Talk::talkTo(const Common::String &filename) { // Handle replies until there's no further linked file, // or the link file isn't a reply first cnversation for (;;) { - _sequenceStack.clear(); + clearSequences(); _scriptSelect = select; _speaker = _talkTo; @@ -318,7 +337,7 @@ void Talk::talkTo(const Common::String &filename) { } if (_talkToFlag == 1) - scripts.pullSeq(); + pullSequence(); // Set the stealth mode for the new talk file Statement &newStatement = _statements[select]; @@ -328,9 +347,9 @@ void Talk::talkTo(const Common::String &filename) { // to display any choices, since the reply needs to be shown if (!newStatement._statement.hasPrefix("*") && !newStatement._statement.hasPrefix("^")) { - _sequenceStack.clear(); - scripts.pushSeq(_talkTo); - scripts.setStillSeq(_talkTo); + clearSequences(); + pushSequence(_talkTo); + setStillSeq(_talkTo); _talkIndex = select; ui._selector = ui._oldSelector = -1; @@ -417,7 +436,6 @@ void Talk::talk(int objNum) { People &people = *_vm->_people; Scene &scene = *_vm->_scene; Screen &screen = *_vm->_screen; - Scripts &scripts = *_vm->_scripts; UserInterface &ui = *_vm->_ui; Object &obj = scene._bgShapes[objNum]; @@ -440,7 +458,7 @@ void Talk::talk(int objNum) { // See if the statement is a stealth mode reply Statement &statement = _statements[select]; if (statement._statement.hasPrefix("^")) { - _sequenceStack.clear(); + clearSequences(); // Start talk in stealth mode _talkStealth = 2; @@ -448,9 +466,9 @@ void Talk::talk(int objNum) { talkTo(obj._name); } else if (statement._statement.hasPrefix("*")) { // Character being spoken to will speak first - _sequenceStack.clear(); - scripts.pushSeq(_talkTo); - scripts.setStillSeq(_talkTo); + clearSequences(); + pushSequence(_talkTo); + setStillSeq(_talkTo); events.setCursor(WAIT); if (obj._lookPosition.y != 0) @@ -463,9 +481,9 @@ void Talk::talk(int objNum) { talkTo(obj._name); } else { // Holmes will be speaking first - _sequenceStack.clear(); - scripts.pushSeq(_talkTo); - scripts.setStillSeq(_talkTo); + clearSequences(); + pushSequence(_talkTo); + setStillSeq(_talkTo); _talkToFlag = false; events.setCursor(WAIT); @@ -481,7 +499,7 @@ void Talk::talk(int objNum) { if (_talkToFlag == 1) { events.setCursor(ARROW); // _sequenceStack._count = 1; - scripts.pullSeq(); + pullSequence(); } } else { drawInterface(); @@ -513,10 +531,6 @@ void Talk::freeTalkVars() { _statements.clear(); } -void Talk::pullSequence() { - // TODO -} - /** * Opens the talk file 'talk.tlk' and searches the index for the specified * conversation. If found, the data for that conversation is loaded @@ -810,4 +824,52 @@ int Talk::talkLine(int lineNum, int stateNum, byte color, int lineY, bool slamIt return lineY; } +/** + * Clears the stack of pending object sequences associated with speakers in the scene + */ +void Talk::clearSequences() { + _sequenceStack.clear(); +} + +void Talk::pullSequence() { + // TODO +} + +void Talk::pushSequence(int speak) { + // TODO +} + +/** + * Change the sequence of a background object corresponding to a given speaker. + * The new sequence will display the character as "listening" + */ +void Talk::setStillSeq(int speak) { + People &people = *_vm->_people; + Scene &scene = *_vm->_scene; + + // Don't bother doing anything if no specific speaker is specified + if (speak == -1) + return; + + if (speak) { + int objNum = people.findSpeaker(speak); + if (objNum != -1) { + Object &obj = scene._bgShapes[objNum]; + + if (obj._seqSize < MAX_TALK_SEQUENCES) { + warning("Tried to copy too many still frames"); + } else { + for (uint idx = 0; idx < MAX_TALK_SEQUENCES; ++idx) { + obj._sequences[idx] = STILL_SEQUENCES[speak][idx]; + if (idx > 0 && !TALK_SEQUENCES[speak][idx] && !TALK_SEQUENCES[speak][idx - 1]) + break; + } + + obj._frameNumber = 0; + obj._seqTo = 0; + } + } + } +} + } // End of namespace Sherlock diff --git a/engines/sherlock/talk.h b/engines/sherlock/talk.h index dbcdf742b8..3b02f92bc6 100644 --- a/engines/sherlock/talk.h +++ b/engines/sherlock/talk.h @@ -31,6 +31,8 @@ namespace Sherlock { +#define MAX_TALK_SEQUENCES 11 + struct SavedSequence { int _objNum; Common::Array _sequences; @@ -58,15 +60,28 @@ struct TalkHistoryEntry { bool &operator[](int index) { return _data[index]; } }; +struct TalkSequences { + byte _data[MAX_TALK_SEQUENCES]; + + TalkSequences() { clear(); } + TalkSequences(const byte *data); + + byte &operator[](int idx) { return _data[idx]; } + void clear(); +}; + class SherlockEngine; class Talk { +private: + Common::Array STILL_SEQUENCES; + Common::Array TALK_SEQUENCES; private: SherlockEngine *_vm; int _saveSeqNum; Common::Array _savedSequences; - Common::Stack _sequenceStack; Common::Array _statements; + Common::Stack _sequenceStack; TalkHistoryEntry _talkHistory[500]; int _speaker; int _talkIndex; @@ -77,8 +92,6 @@ private: int _talkToFlag; bool _moreTalkUp, _moreTalkDown; - void pullSequence(); - void loadTalkFile(const Common::String &filename); void stripVoiceCommands(); @@ -92,6 +105,8 @@ public: int _talkCounter; public: Talk(SherlockEngine *vm); + void setSequences(const byte *talkSequences, const byte *stillSequences, + int maxPeople); void talkTo(const Common::String &filename); @@ -100,6 +115,12 @@ public: void freeTalkVars(); void drawInterface(); + + void setStillSeq(int speak); + void clearSequences(); + void pullSequence(); + void pushSequence(int speak); + bool isSequencesEmpty() const { return _sequenceStack.empty(); } }; } // End of namespace Sherlock -- cgit v1.2.3 From 283c6074ad77c0c18c9d1550d7ac7c2443072aec Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 31 Mar 2015 23:21:04 -0400 Subject: SHERLOCK: Implement pushSequence and pullSequence --- engines/sherlock/talk.cpp | 66 ++++++++++++++++++++++++++++++++++++++++------- engines/sherlock/talk.h | 11 +++++--- 2 files changed, 64 insertions(+), 13 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index 26c2e523f3..6596431b8b 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -831,37 +831,83 @@ void Talk::clearSequences() { _sequenceStack.clear(); } +/** + * Pulls a background object sequence from the sequence stack and restore's the + * object's sequence + */ void Talk::pullSequence() { - // TODO + Scene &scene = *_vm->_scene; + + SequenceEntry seq = _sequenceStack.pop(); + if (seq._objNum != -1) { + Object &obj = scene._bgShapes[seq._objNum]; + + if (obj._seqSize < MAX_TALK_SEQUENCES) { + warning("Tried to restore too few frames"); + } else { + for (int idx = 0; idx < MAX_TALK_SEQUENCES; ++idx) + obj._sequences[idx] = seq._sequences[idx]; + + obj._frameNumber = seq._frameNumber; + obj._seqTo = seq._seqTo; + } + } } -void Talk::pushSequence(int speak) { - // TODO +/** + * Push the sequence of a background object that's an NPC that needs to be + * saved onto the sequence stack. + */ +void Talk::pushSequence(int speaker) { + People &people = *_vm->_people; + Scene &scene = *_vm->_scene; + + // Only proceed if a speaker is specified + if (speaker == -1) + return; + + SequenceEntry seqEntry; + if (!speaker) { + seqEntry._objNum = -1; + } else { + seqEntry._objNum = people.findSpeaker(speaker); + + Object &obj = scene._bgShapes[seqEntry._objNum]; + for (uint idx = 0; idx < MAX_TALK_SEQUENCES; ++idx) + seqEntry._sequences.push_back(obj._sequences[idx]); + + seqEntry._frameNumber = obj._frameNumber; + seqEntry._seqTo = obj._seqTo; + } + + _sequenceStack.push(seqEntry); + if (_sequenceStack.size() >= 5) + error("sequence stack overflow"); } /** * Change the sequence of a background object corresponding to a given speaker. * The new sequence will display the character as "listening" */ -void Talk::setStillSeq(int speak) { +void Talk::setStillSeq(int speaker) { People &people = *_vm->_people; Scene &scene = *_vm->_scene; // Don't bother doing anything if no specific speaker is specified - if (speak == -1) + if (speaker == -1) return; - if (speak) { - int objNum = people.findSpeaker(speak); + if (speaker) { + int objNum = people.findSpeaker(speaker); if (objNum != -1) { Object &obj = scene._bgShapes[objNum]; if (obj._seqSize < MAX_TALK_SEQUENCES) { - warning("Tried to copy too many still frames"); + warning("Tried to copy too few still frames"); } else { for (uint idx = 0; idx < MAX_TALK_SEQUENCES; ++idx) { - obj._sequences[idx] = STILL_SEQUENCES[speak][idx]; - if (idx > 0 && !TALK_SEQUENCES[speak][idx] && !TALK_SEQUENCES[speak][idx - 1]) + obj._sequences[idx] = STILL_SEQUENCES[speaker][idx]; + if (idx > 0 && !TALK_SEQUENCES[speaker][idx] && !TALK_SEQUENCES[speaker][idx - 1]) break; } diff --git a/engines/sherlock/talk.h b/engines/sherlock/talk.h index 3b02f92bc6..0cd0a8c638 100644 --- a/engines/sherlock/talk.h +++ b/engines/sherlock/talk.h @@ -38,6 +38,11 @@ struct SavedSequence { Common::Array _sequences; }; +struct SequenceEntry : public SavedSequence { + int _frameNumber; + int _seqTo; +}; + struct Statement { Common::String _statement; Common::String _reply; @@ -80,8 +85,8 @@ private: SherlockEngine *_vm; int _saveSeqNum; Common::Array _savedSequences; + Common::Stack _sequenceStack; Common::Array _statements; - Common::Stack _sequenceStack; TalkHistoryEntry _talkHistory[500]; int _speaker; int _talkIndex; @@ -116,10 +121,10 @@ public: void drawInterface(); - void setStillSeq(int speak); + void setStillSeq(int speaker); void clearSequences(); void pullSequence(); - void pushSequence(int speak); + void pushSequence(int speaker); bool isSequencesEmpty() const { return _sequenceStack.empty(); } }; -- cgit v1.2.3 From c13c02b079d0881b4d1cd205364d043920bab9a5 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 1 Apr 2015 23:12:49 -0400 Subject: SHERLOCK: Implemented loadJournalFile --- engines/sherlock/journal.cpp | 379 +++++++++++++++++++++++++++++++++++++++++- engines/sherlock/journal.h | 30 +++- engines/sherlock/people.h | 1 + engines/sherlock/sherlock.cpp | 2 +- engines/sherlock/talk.h | 8 +- 5 files changed, 412 insertions(+), 8 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/journal.cpp b/engines/sherlock/journal.cpp index 34423d2480..a9eb86bf07 100644 --- a/engines/sherlock/journal.cpp +++ b/engines/sherlock/journal.cpp @@ -21,10 +21,11 @@ */ #include "sherlock/journal.h" +#include "sherlock/sherlock.h" namespace Sherlock { -Journal::Journal() { +Journal::Journal(SherlockEngine *vm): _vm(vm) { // Allow up to 1000 statements _data.resize(1000); @@ -35,10 +36,386 @@ Journal::Journal() { _sub = 0; _up = _down = 0; _page = 0; + _converseNum = -1; + + // Load the journal directory and location names + loadJournalLocations(); } +/** + * Records statements that are said, in the order which they are said. The player + * can then read the journal to review them + */ void Journal::record(int converseNum, int statementNum) { + int saveIndex = _index; + int saveSub = _sub; + + // Record the entry into the list + _data.push_back(JournalEntry(converseNum, statementNum)); + + bool newLines = loadJournalFile(true); + // TODO } +void Journal::loadJournalLocations() { + Resources &res = *_vm->_res; + char c; + + _directory.clear(); + + Common::SeekableReadStream *dir = res.load("talk.lib"); + dir->skip(4); // Skip header + + // Get the numer of entries + _directory.resize(dir->readUint16LE()); + + // Read in each entry + for (uint idx = 0; idx < _directory.size(); ++idx) { + Common::String line; + while ((c = dir->readByte()) != 0) + line += c; + + _directory.push_back(line); + } + + delete dir; + + // Load in the locations stored in journal.txt + Common::SeekableReadStream *loc = res.load("journal.txt"); + + _locations.clear(); + while (loc->pos() < loc->size()) { + Common::String line; + while ((c = loc->readByte()) != '\0') + line += c; + + _locations.push_back(line); + } + + delete loc; +} + +/** + * Loads the description for the current display index in the journal, and then + * word wraps the result to prepare it for being displayed + */ +bool Journal::loadJournalFile(bool alreadyLoaded) { + Inventory &inv = *_vm->_inventory; + People &people = *_vm->_people; + Screen &screen = *_vm->_screen; + Talk &talk = *_vm->_talk; + JournalEntry &journalEntry = _data[_index]; + Statement &statement = talk[journalEntry._statementNum]; + + Common::String dirFilename = _directory[journalEntry._converseNum]; + bool replyOnly = journalEntry._replyOnly; + Common::String locStr(dirFilename.c_str(), dirFilename.c_str() + 4); + int newLocation = atoi(locStr.c_str()); + + // If not flagged as alrady loaded, load the conversation into script variables + if (!alreadyLoaded) { + // See if the file to be used is already loaded + if (journalEntry._converseNum != _converseNum) { + // Nope. Free any previously loaded talk + talk.freeTalkVars(); + + // Find the person being talked to + talk._talkTo = -1; + for (int idx = 0; idx < MAX_PEOPLE; ++idx) { + Common::String portrait = people[idx]._portrait; + Common::String numStr(portrait.c_str(), portrait.c_str() + 4); + + if (locStr == numStr) { + talk._talkTo = idx; + break; + } + } + + // Load the talk file + talk.loadTalkFile(dirFilename); + } + } + + if (talk[0]._statement.hasPrefix("*") || talk[0]._statement.hasPrefix("^")) + replyOnly = true; + + // If this isn't the first journal entry, see if the previous journal entry + // was in the same scene to see if we need to include the scene header + int oldLocation = -1; + if (_index != 0) { + // Get the scene number of the prior journal entry + Common::String priorEntry = _directory[_data[_index - 1]._converseNum]; + oldLocation = atoi(Common::String(priorEntry.c_str() + 4, priorEntry.c_str() + 6).c_str()); + } + + // Start building journal string + Common::String journalString; + + if (newLocation != oldLocation) { + // Add in scene title + journalString = "@" + _locations[newLocation - 1] + ":"; + + // See if title can fit into a single line, or requires splitting on 2 lines + int width = screen.stringWidth(journalString.c_str() + 1); + if (width > 230) { + // Scan backwards from end of title to find a space between a word + // where the width is less than the maximum allowed for the line + const char *lineP = journalString.c_str() + journalString.size() - 1; + while (width > 230 || *lineP != ' ') + width -= screen.charWidth(*lineP--); + + // Split the header into two lines, and add a '@' prefix + // to the second line as well + journalString = Common::String(journalString.c_str(), lineP) + "\n@" + + Common::String(lineP + 1); + } + + // Add a newline at the end of the title + journalString += '\n'; + } + + // If Holmes has something to say first, then take care of it + if (!replyOnly) { + // Handle the grammar + journalString += "Holmes "; + if (talk[journalEntry._statementNum]._statement.hasSuffix("?")) + journalString += "asked "; + else + journalString += "said to "; + + switch (talk._talkTo) { + case 1: + journalString += "me"; + break; + case 2: + journalString += "the Inspector"; + break; + default: + journalString += inv._names[talk._talkTo]; + break; + } + journalString += ", \""; + + // Add the statement + journalString += statement._statement; + } + + // Handle including the reply + bool startOfReply = true; + bool ctrlSpace = false; + bool commentFlag = false; + bool commentJustPrinted = false; + const char *replyP = statement._reply.c_str(); + + while (*replyP) { + char c = *replyP; + + // Is it a control character? + if (c < 128) { + // Nope. Set flag for allowing control coes to insert spaces + ctrlSpace = true; + + // Check for embedded comments + if (c == '{' || c == '}') { + // Comment characters. If we're starting a comment and there's + // already text displayed, add a closing quote + if (c == '{' && !startOfReply && !commentJustPrinted) + journalString += '"'; + + // If a reply isn't just being started, and we didn't just end + // a comment (which would have added a line), add a carriage return + if (!startOfReply && ((!commentJustPrinted && c == '{') || c == '}')) + journalString += '"'; + + // Handle setting or clearing comment state + if (c == '{') { + commentFlag = true; + commentJustPrinted = false; + } else { + commentFlag = false; + commentJustPrinted = true; + } + } else { + if (startOfReply) { + if (!replyOnly) { + journalString += "\"\n"; + + if (talk._talkTo == 1) + journalString += "I replied, \""; + else + journalString += "The reply was, \""; + } else { + if (talk._talkTo == 1) + journalString += "I"; + else if (talk._talkTo == 2) + journalString += "The Inspector"; + else + journalString += inv._names[talk._talkTo]; + + const char *strP = replyP + 1; + char v; + do { + v = *strP++; + } while (v && v < 128 && v != '.' && v != '!' && v != '?'); + + if (v == '?') + journalString += " asked, \""; + else + journalString += " said, \""; + } + + startOfReply = false; + } + + // Copy text from the place until either the reply ends, a comment + // {} block is started, or a control character is encountered + do { + journalString += *replyP++; + } while (*replyP && *replyP < 128 && *replyP != '{' && *replyP != '}'); + + // Move pointer back, since the outer for loop will increment it again + --replyP; + commentJustPrinted = false; + } + } else if (c == 128) { + if (!startOfReply) { + if (!commentFlag && !commentJustPrinted) + journalString += "\"\n"; + + journalString += "Then "; + commentFlag = false; + } else if (!replyOnly) { + journalString += "\"\n"; + } + + startOfReply = false; + c = *++replyP; + + if ((c - 1) == 0) + journalString += "Holmes"; + else if ((c - 1) == 1) + journalString += "I"; + else if ((c - 1) == 2) + journalString += "the Inspector"; + else + journalString += inv._names[c - 1]; + + const char *strP = replyP + 1; + char v; + do { + v = *strP++; + } while (v && v < 128 && v != '.' && v != '!' && v != '?'); + + if (v == '?') + journalString += " asked, \""; + else + journalString += " said, \""; + } else { + // Control code, so move past it and any parameters + ++replyP; + switch (c) { + case 129: // Run canim + case 130: // Assign side + case 131: // Pause with control + case 136: // Pause without control + case 157: // Walk to canimation + // These commands don't have any param + break; + + case 134: // Change sequence + replyP += (replyP[0] & 127) + replyP[2] + 1; + break; + + case 135: // Walk to co-ords + case 154: // Move mouse + replyP += 3; + break; + + case 139: // Set flag + case 143: // If statement + ++replyP; + break; + + case 140: // Play voice file + case 150: // Play prologue + case 153: // Call talk file + replyP += 7; + break; + + case 141: // Toggle object + case 151: // Put item in inventory + case 152: // Set object + case 155: // Info line + case 158: // Delete item from inventory + replyP += *replyP & 127; + break; + + case 149: // Goto scene + replyP += 4; + break; + + case 161: // End of line + journalString += "\n"; + break; + + default: + break; + } + + // Put a space in the output for a control character, unless it's + // immediately coming after another control character + if (ctrlSpace && c != 130 && c != 161 && !commentJustPrinted) { + journalString += " "; + ctrlSpace = false; + } + } + } + + if (!startOfReply && !commentJustPrinted) + journalString += '"'; + + // Finally finished building the journal text. Need to process the text to + // word wrap it to fit on-screen. The resulting lines are stored in the + // _entries array + _entries.clear(); + + while (!journalString.empty()) { + const char *startP = journalString.c_str(); + + // If the first character is a '@' flagging a title line, then move + // past it, so the @ won't be included in the line width calculation + if (*startP == '@') + ++startP; + + // Build up chacters until a full line is found + int width = 0; + const char *endP = startP; + while (width < 230 && *endP && *endP != '\n' && (endP - startP) < 79) + width += screen.charWidth(*endP++); + + // If word wrapping, move back to end of prior word + if (width >= 230 || (endP - startP) >= 79) { + while (*--endP != ' ') + ; + } + + // Add in the line + _entries.push_back(Common::String(startP, endP)); + + // Strip line off from string being processed + journalString = *endP ? Common::String(endP + 1) : ""; + } + + // Add a blank line at the end of the text as long as text was present + if (!startOfReply) { + _entries.push_back(""); + } else { + _entries.clear(); + } + + return _entries.size(); +} + + } // End of namespace Sherlock diff --git a/engines/sherlock/journal.h b/engines/sherlock/journal.h index 87e5a4f8f2..af8d683619 100644 --- a/engines/sherlock/journal.h +++ b/engines/sherlock/journal.h @@ -25,20 +25,44 @@ #include "common/scummsys.h" #include "common/array.h" +#include "common/str-array.h" +#include "common/stream.h" namespace Sherlock { +struct JournalEntry { + int _converseNum; + bool _replyOnly; + int _statementNum; + + JournalEntry() : _converseNum(0), _replyOnly(false), _statementNum(0) {} + JournalEntry(int converseNum, int statementNum, bool replyOnly = false) : + _converseNum(converseNum), _statementNum(statementNum), _replyOnly(replyOnly) {} +}; + +class SherlockEngine; + class Journal { -public: - Common::Array _data; +private: + SherlockEngine *_vm; + Common::Array _data; + Common::StringArray _directory; + Common::StringArray _locations; + Common::StringArray _entries; int _count; int _maxPage; int _index; int _sub; int _up, _down; int _page; + int _converseNum; + + void loadJournalLocations(); + + bool loadJournalFile(bool alreadyLoaded); +public: public: - Journal(); + Journal(SherlockEngine *vm); void record(int converseNum, int statementNum); }; diff --git a/engines/sherlock/people.h b/engines/sherlock/people.h index aa54c67567..a1fad019c8 100644 --- a/engines/sherlock/people.h +++ b/engines/sherlock/people.h @@ -82,6 +82,7 @@ public: ~People(); Person &operator[](PeopleId id) { return _data[id]; } + Person &operator[](int idx) { return _data[idx]; } bool isHolmesActive() const { return _walkLoaded && _holmesOn; } diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index 04a9ed54d5..20a805594e 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -79,7 +79,7 @@ void SherlockEngine::initialize() { _debugger = new Debugger(this); _events = new Events(this); _inventory = new Inventory(this); - _journal = new Journal(); + _journal = new Journal(this); _people = new People(this); _scene = new Scene(this); _screen = new Screen(this); diff --git a/engines/sherlock/talk.h b/engines/sherlock/talk.h index 0cd0a8c638..48cdd2b5b2 100644 --- a/engines/sherlock/talk.h +++ b/engines/sherlock/talk.h @@ -90,15 +90,12 @@ private: TalkHistoryEntry _talkHistory[500]; int _speaker; int _talkIndex; - int _talkTo; int _scriptSelect; int _converseNum; int _talkStealth; int _talkToFlag; bool _moreTalkUp, _moreTalkDown; - void loadTalkFile(const Common::String &filename); - void stripVoiceCommands(); void setTalkMap(); @@ -108,11 +105,14 @@ private: public: bool _talkToAbort; int _talkCounter; + int _talkTo; public: Talk(SherlockEngine *vm); void setSequences(const byte *talkSequences, const byte *stillSequences, int maxPeople); + Statement &operator[](int idx) { return _statements[idx]; } + void talkTo(const Common::String &filename); void talk(int objNum); @@ -121,6 +121,8 @@ public: void drawInterface(); + void loadTalkFile(const Common::String &filename); + void setStillSeq(int speaker); void clearSequences(); void pullSequence(); -- cgit v1.2.3 From 86022c065c1bf7aa67549de602cd6e8933477d74 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 1 Apr 2015 23:19:00 -0400 Subject: SHERLOCK: Implemented Journal::record --- engines/sherlock/journal.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/journal.cpp b/engines/sherlock/journal.cpp index a9eb86bf07..dcddddbbbd 100644 --- a/engines/sherlock/journal.cpp +++ b/engines/sherlock/journal.cpp @@ -52,10 +52,23 @@ void Journal::record(int converseNum, int statementNum) { // Record the entry into the list _data.push_back(JournalEntry(converseNum, statementNum)); + _index = _data.size() - 1; - bool newLines = loadJournalFile(true); + // Load the text for the new entry to get the number of lines it will have + int newLines = loadJournalFile(true); - // TODO + // Restore old state + _index = saveIndex; + _sub = saveSub; + + // If new lines were added to the ournal, update the total number of lines + // the journal continues + if (newLines) { + _maxPage += newLines; + } else { + // No lines in entry, so remove the new entry from the journal + _data.remove_at(_data.size() - 1); + } } void Journal::loadJournalLocations() { -- cgit v1.2.3 From 2c36889ec5312b15a7deba8a19003d9500425cb3 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 2 Apr 2015 08:11:36 -0400 Subject: SHERLOCK: Rename journal fields for clarity --- engines/sherlock/journal.cpp | 24 ++++++++++++------------ engines/sherlock/journal.h | 4 ++-- 2 files changed, 14 insertions(+), 14 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/journal.cpp b/engines/sherlock/journal.cpp index dcddddbbbd..04165cd827 100644 --- a/engines/sherlock/journal.cpp +++ b/engines/sherlock/journal.cpp @@ -27,7 +27,7 @@ namespace Sherlock { Journal::Journal(SherlockEngine *vm): _vm(vm) { // Allow up to 1000 statements - _data.resize(1000); + _journal.resize(1000); // Initialize fields _count = 0; @@ -51,8 +51,8 @@ void Journal::record(int converseNum, int statementNum) { int saveSub = _sub; // Record the entry into the list - _data.push_back(JournalEntry(converseNum, statementNum)); - _index = _data.size() - 1; + _journal.push_back(JournalEntry(converseNum, statementNum)); + _index = _journal.size() - 1; // Load the text for the new entry to get the number of lines it will have int newLines = loadJournalFile(true); @@ -67,7 +67,7 @@ void Journal::record(int converseNum, int statementNum) { _maxPage += newLines; } else { // No lines in entry, so remove the new entry from the journal - _data.remove_at(_data.size() - 1); + _journal.remove_at(_journal.size() - 1); } } @@ -118,7 +118,7 @@ bool Journal::loadJournalFile(bool alreadyLoaded) { People &people = *_vm->_people; Screen &screen = *_vm->_screen; Talk &talk = *_vm->_talk; - JournalEntry &journalEntry = _data[_index]; + JournalEntry &journalEntry = _journal[_index]; Statement &statement = talk[journalEntry._statementNum]; Common::String dirFilename = _directory[journalEntry._converseNum]; @@ -158,7 +158,7 @@ bool Journal::loadJournalFile(bool alreadyLoaded) { int oldLocation = -1; if (_index != 0) { // Get the scene number of the prior journal entry - Common::String priorEntry = _directory[_data[_index - 1]._converseNum]; + Common::String priorEntry = _directory[_journal[_index - 1]._converseNum]; oldLocation = atoi(Common::String(priorEntry.c_str() + 4, priorEntry.c_str() + 6).c_str()); } @@ -390,8 +390,8 @@ bool Journal::loadJournalFile(bool alreadyLoaded) { // Finally finished building the journal text. Need to process the text to // word wrap it to fit on-screen. The resulting lines are stored in the - // _entries array - _entries.clear(); + // _lines array + _lines.clear(); while (!journalString.empty()) { const char *startP = journalString.c_str(); @@ -414,7 +414,7 @@ bool Journal::loadJournalFile(bool alreadyLoaded) { } // Add in the line - _entries.push_back(Common::String(startP, endP)); + _lines.push_back(Common::String(startP, endP)); // Strip line off from string being processed journalString = *endP ? Common::String(endP + 1) : ""; @@ -422,12 +422,12 @@ bool Journal::loadJournalFile(bool alreadyLoaded) { // Add a blank line at the end of the text as long as text was present if (!startOfReply) { - _entries.push_back(""); + _lines.push_back(""); } else { - _entries.clear(); + _lines.clear(); } - return _entries.size(); + return _lines.size(); } diff --git a/engines/sherlock/journal.h b/engines/sherlock/journal.h index af8d683619..4add81d508 100644 --- a/engines/sherlock/journal.h +++ b/engines/sherlock/journal.h @@ -45,10 +45,10 @@ class SherlockEngine; class Journal { private: SherlockEngine *_vm; - Common::Array _data; + Common::Array _journal; Common::StringArray _directory; Common::StringArray _locations; - Common::StringArray _entries; + Common::StringArray _lines; int _count; int _maxPage; int _index; -- cgit v1.2.3 From 8ee021434236b454faf52995fb102322f2e7bd8f Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 2 Apr 2015 08:44:07 -0400 Subject: SHERLOCK: Implemented Inventory::highlight --- engines/sherlock/inventory.cpp | 15 +++++++++++++-- engines/sherlock/inventory.h | 2 +- engines/sherlock/user_interface.cpp | 4 ++-- 3 files changed, 16 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/inventory.cpp b/engines/sherlock/inventory.cpp index ac37e7c587..f7706c9d64 100644 --- a/engines/sherlock/inventory.cpp +++ b/engines/sherlock/inventory.cpp @@ -329,8 +329,19 @@ void Inventory::invCommands(bool slamIt) { } } -void Inventory::doInvLite(int index, byte color) { - // TODO +/** + * Set the highlighting color of a given inventory item + */ +void Inventory::highlight(int index, byte color) { + Screen &screen = *_vm->_screen; + Surface &bb = *screen._backBuffer; + int slot = index - _invIndex; + Graphics::Surface &img = (*_invShapes[slot])[0]._frame; + + bb.fillRect(Common::Rect(8 + slot * 52, 165, (slot + 1) * 52, 194), color); + bb.transBlitFrom(img, Common::Point(6 + slot * 52 + ((47 - img.w) / 2), + 163 + ((33 - img.h) / 2))); + screen.slamArea(8 + slot * 52, 165, 44, 30); } void Inventory::doInvJF() { diff --git a/engines/sherlock/inventory.h b/engines/sherlock/inventory.h index 3c01dc38da..55abc4c960 100644 --- a/engines/sherlock/inventory.h +++ b/engines/sherlock/inventory.h @@ -87,7 +87,7 @@ public: void invCommands(bool slamIt); - void doInvLite(int index, byte color); + void highlight(int index, byte color); void doInvJF(); }; diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index 74142ab80e..6f60049e31 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -789,11 +789,11 @@ void UserInterface::doInvControl() { if (_oldSelector != -1) { // Un-highlight if (_oldSelector >= inv._invIndex && _oldSelector < (inv._invIndex + 6)) - inv.doInvLite(_oldSelector, BUTTON_MIDDLE); + inv.highlight(_oldSelector, BUTTON_MIDDLE); } if (_selector != -1) - inv.doInvLite(_selector, 235); + inv.highlight(_selector, 235); _oldSelector = _selector; } -- cgit v1.2.3 From 9c24ae75909088742aae7b303f80de43cb31a7a6 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 2 Apr 2015 18:30:16 -0400 Subject: SHERLOCK: Implemented Journal::drawInterface --- engines/sherlock/journal.cpp | 81 +++++++++++++++++++++++++++++++++++++ engines/sherlock/journal.h | 6 +++ engines/sherlock/user_interface.cpp | 4 ++ 3 files changed, 91 insertions(+) (limited to 'engines') diff --git a/engines/sherlock/journal.cpp b/engines/sherlock/journal.cpp index 04165cd827..94c6cf69e7 100644 --- a/engines/sherlock/journal.cpp +++ b/engines/sherlock/journal.cpp @@ -25,6 +25,23 @@ namespace Sherlock { +#define JOURNAL_BUTTONS_Y 178 + +// Positioning of buttons in the journal view +const int JOURNAL_POINTS[9][3] = { + { 6, 68, 37 }, + { 69, 131, 100 }, + { 132, 192, 162 }, + { 193, 250, 221 }, + { 251, 313, 281 }, + { 6, 82, 44 }, + { 83, 159, 121 }, + { 160, 236, 198 }, + { 237, 313, 275 } +}; + +/*----------------------------------------------------------------*/ + Journal::Journal(SherlockEngine *vm): _vm(vm) { // Allow up to 1000 statements _journal.resize(1000); @@ -430,5 +447,69 @@ bool Journal::loadJournalFile(bool alreadyLoaded) { return _lines.size(); } +void Journal::drawInterface() { + Resources &res = *_vm->_res; + Screen &screen = *_vm->_screen; + byte palette[PALETTE_SIZE]; + + // Load in the journal background + Common::SeekableReadStream *bg = res.load("journal.lbv"); + bg->read(screen._backBuffer1.getPixels(), SHERLOCK_SCREEN_WIDTH * SHERLOCK_SCREEN_HEIGHT); + bg->read(palette, PALETTE_SIZE); + delete bg; + + // Set the palette and print the title + screen.setPalette(palette); + screen.gPrint(Common::Point(111, 18), BUTTON_BOTTOM, "Watson's Journal"); + screen.gPrint(Common::Point(110, 17), INV_FOREGROUND, "Watson's Journal"); + + // Draw the buttons + screen.makeButton(Common::Rect(JOURNAL_POINTS[0][0], JOURNAL_BUTTONS_Y, + JOURNAL_POINTS[0][1], JOURNAL_BUTTONS_Y + 10), + JOURNAL_POINTS[0][2] - screen.stringWidth("Exit") / 2, "Exit"); + screen.makeButton(Common::Rect(JOURNAL_POINTS[1][0], JOURNAL_BUTTONS_Y, + JOURNAL_POINTS[1][1], JOURNAL_BUTTONS_Y + 10), + JOURNAL_POINTS[1][2] - screen.stringWidth("Back 10") / 2, "Back 10"); + screen.makeButton(Common::Rect(JOURNAL_POINTS[2][0], JOURNAL_BUTTONS_Y, + JOURNAL_POINTS[2][1], JOURNAL_BUTTONS_Y + 10), + JOURNAL_POINTS[2][2] - screen.stringWidth("Up") / 2, "Up"); + screen.makeButton(Common::Rect(JOURNAL_POINTS[3][0], JOURNAL_BUTTONS_Y, + JOURNAL_POINTS[3][1], JOURNAL_BUTTONS_Y + 10), + JOURNAL_POINTS[3][2] - screen.stringWidth("Down") / 2, "Down"); + screen.makeButton(Common::Rect(JOURNAL_POINTS[4][0], JOURNAL_BUTTONS_Y, + JOURNAL_POINTS[4][1], JOURNAL_BUTTONS_Y + 10), + JOURNAL_POINTS[4][2] - screen.stringWidth("Ahead 10") / 2, "Ahead 10"); + screen.makeButton(Common::Rect(JOURNAL_POINTS[5][0], JOURNAL_BUTTONS_Y + 11, + JOURNAL_POINTS[5][1], JOURNAL_BUTTONS_Y + 21), + JOURNAL_POINTS[5][2] - screen.stringWidth("Search") / 2, "Search"); + screen.makeButton(Common::Rect(JOURNAL_POINTS[6][0], JOURNAL_BUTTONS_Y + 11, + JOURNAL_POINTS[6][1], JOURNAL_BUTTONS_Y + 21), + JOURNAL_POINTS[6][2] - screen.stringWidth("First Page") / 2, "First Page"); + screen.makeButton(Common::Rect(JOURNAL_POINTS[7][0], JOURNAL_BUTTONS_Y + 11, + JOURNAL_POINTS[7][1], JOURNAL_BUTTONS_Y + 21), + JOURNAL_POINTS[7][2] - screen.stringWidth("Last Page") / 2, "Last Page"); + screen.makeButton(Common::Rect(JOURNAL_POINTS[8][0], JOURNAL_BUTTONS_Y + 11, + JOURNAL_POINTS[8][1], JOURNAL_BUTTONS_Y + 21), + JOURNAL_POINTS[8][2] - screen.stringWidth("Print Text") / 2, "Print Text"); + + if (_journal.size() == 0) { + _up = _down = 0; + } else { + doJournal(0, 0); + } + + doArrows(); + + // Show the entire screen + screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT); +} + +void Journal::doArrows() { + // TODO +} + +void Journal::doJournal(int direction, int howFar) { + // TODO +} } // End of namespace Sherlock diff --git a/engines/sherlock/journal.h b/engines/sherlock/journal.h index 4add81d508..34d99af0ec 100644 --- a/engines/sherlock/journal.h +++ b/engines/sherlock/journal.h @@ -60,11 +60,17 @@ private: void loadJournalLocations(); bool loadJournalFile(bool alreadyLoaded); + + void doArrows(); + + void doJournal(int direction, int howFar); public: public: Journal(SherlockEngine *vm); void record(int converseNum, int statementNum); + + void drawInterface(); }; } // End of namespace Sherlock diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index 6f60049e31..01b08ffd71 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -1127,6 +1127,10 @@ void UserInterface::doTalkControl() { } void UserInterface::journalControl() { + Journal &journal = *_vm->_journal; + + journal.drawInterface(); + // TODO } -- cgit v1.2.3 From 91774a0aebb0b37010627e448a1ac18169cec07f Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 2 Apr 2015 19:19:36 -0400 Subject: SHERLOCK: Implemented Journal::doButtons --- engines/sherlock/journal.cpp | 24 ++++++++++++++++++++++-- engines/sherlock/journal.h | 2 +- 2 files changed, 23 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/journal.cpp b/engines/sherlock/journal.cpp index 94c6cf69e7..b45d772716 100644 --- a/engines/sherlock/journal.cpp +++ b/engines/sherlock/journal.cpp @@ -51,7 +51,7 @@ Journal::Journal(SherlockEngine *vm): _vm(vm) { _maxPage = 0; _index = 0; _sub = 0; - _up = _down = 0; + _up = _down = false; _page = 0; _converseNum = -1; @@ -504,8 +504,28 @@ void Journal::drawInterface() { screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT); } +/** + * Display the arrows that can be used to scroll up and down pages + */ void Journal::doArrows() { - // TODO + Screen &screen = *_vm->_screen; + byte color; + + color = (_page > 1) ? COMMAND_FOREGROUND : COMMAND_NULL; + screen.buttonPrint(Common::Point(JOURNAL_POINTS[1][2], JOURNAL_BUTTONS_Y), color, false, "Back 10"); + screen.buttonPrint(Common::Point(JOURNAL_POINTS[2][2], JOURNAL_BUTTONS_Y), color, false, "Up"); + + color = _down ? COMMAND_FOREGROUND : COMMAND_NULL; + screen.buttonPrint(Common::Point(JOURNAL_POINTS[3][2], JOURNAL_BUTTONS_Y), color, false, "Down"); + screen.buttonPrint(Common::Point(JOURNAL_POINTS[4][2], JOURNAL_BUTTONS_Y), color, false, "Ahead 10"); + screen.buttonPrint(Common::Point(JOURNAL_POINTS[7][2], JOURNAL_BUTTONS_Y + 11), color, false, "Last Page"); + + color = _journal.size() > 0 ? COMMAND_FOREGROUND : COMMAND_NULL; + screen.buttonPrint(Common::Point(JOURNAL_POINTS[5][2], JOURNAL_BUTTONS_Y + 11), color, false, "Search"); + screen.buttonPrint(Common::Point(JOURNAL_POINTS[8][2], JOURNAL_BUTTONS_Y + 11), color, false, "Print Text"); + + color = _page > 1 ? COMMAND_FOREGROUND : COMMAND_NULL; + screen.buttonPrint(Common::Point(JOURNAL_POINTS[6][2], JOURNAL_BUTTONS_Y + 11), color, false, "First Page"); } void Journal::doJournal(int direction, int howFar) { diff --git a/engines/sherlock/journal.h b/engines/sherlock/journal.h index 34d99af0ec..8ad19dc0e5 100644 --- a/engines/sherlock/journal.h +++ b/engines/sherlock/journal.h @@ -53,7 +53,7 @@ private: int _maxPage; int _index; int _sub; - int _up, _down; + bool _up, _down; int _page; int _converseNum; -- cgit v1.2.3 From 2b1bc8dc3cbcd6c85ee8ba5734154c8e72a38645 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 3 Apr 2015 21:01:06 -0500 Subject: TONY: Add detection for Italian PC Magazine version --- engines/tony/detection_tables.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'engines') diff --git a/engines/tony/detection_tables.h b/engines/tony/detection_tables.h index 28dcaac752..e4a064157b 100644 --- a/engines/tony/detection_tables.h +++ b/engines/tony/detection_tables.h @@ -127,6 +127,22 @@ static const TonyGameDescription gameDescriptions[] = { }, }, + { + // Tony Tough Italian (PC Action magazine) + { + "tony", + 0, + { + { "data1.cab", 0, "42344827407b974af11d60fadbd021b4", 3811 }, + AD_LISTEND + }, + Common::IT_ITA, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + GUIO1(GUIO_NONE) + }, + }, + { // Tony Tough Italian provided by Giovanni Bajo { -- cgit v1.2.3 From 402846aea5e08d774521caaa9bd29531c738a100 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 4 Apr 2015 08:54:19 -0500 Subject: SHERLOCK: Implemented doJournal --- engines/sherlock/journal.cpp | 259 ++++++++++++++++++++++++++++++++++++++++++- engines/sherlock/journal.h | 5 +- engines/sherlock/screen.h | 3 +- 3 files changed, 263 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/journal.cpp b/engines/sherlock/journal.cpp index b45d772716..140b766dca 100644 --- a/engines/sherlock/journal.cpp +++ b/engines/sherlock/journal.cpp @@ -26,6 +26,7 @@ namespace Sherlock { #define JOURNAL_BUTTONS_Y 178 +#define LINES_PER_PAGE 11 // Positioning of buttons in the journal view const int JOURNAL_POINTS[9][3] = { @@ -528,8 +529,262 @@ void Journal::doArrows() { screen.buttonPrint(Common::Point(JOURNAL_POINTS[6][2], JOURNAL_BUTTONS_Y + 11), color, false, "First Page"); } -void Journal::doJournal(int direction, int howFar) { - // TODO +/** + * Displays a page of the journal at the current index + */ +bool Journal::doJournal(int direction, int howFar) { + Events &events = *_vm->_events; + Screen &screen = *_vm->_screen; + int yp = 37; + int startPage = _page; + bool endJournal = false; + bool firstOccurance = false; + bool searchSuccessful = false; + bool endFlag = false; + int lineNum = 0; + int maxLines; + int savedIndex; + int savedSub; + int temp; + bool inc; + const char *matchP; + int width; + + _converseNum = -1; + _down = true; + + do { + // Get the number of lines for the current journal entry + maxLines = loadJournalFile(false); + if (!maxLines) { + // Entry has no text, so it must be a stealth eny. Move onto further journal entries + // until an entry with text is found + if (++_index == (int)_journal.size()) { + endJournal = true; + } else { + _sub = 0; + maxLines = loadJournalFile(false); + } + } + } while (!endJournal && !maxLines); + + // Check if there no further pages with text until the end of the journal + if (endJournal) { + // If moving forward or backwards, clear the page before printing + if (direction) + clearPage(); + + screen.gPrint(Common::Point(235, 21), PEN_COLOR, "Page %d", _page); + return false; + } + + // If the journal page is being changed, set the wait cursor + if (direction) + events.setCursor(WAIT); + + switch (direction) { + case 1: + case 4: + // Move backwards howFar number of lines unless either the start of the journal is reached, + // or a searched for keyword is found + do { + // Animate the glass mouse cursor + int cursorNum = (int)events.getCursor() + 1; + if (cursorNum > (WAIT + 2)) + cursorNum = WAIT; + events.setCursor((CursorId)cursorNum); + + // Move backwards through the journal file a line at a time + if (--_sub < 0) { + do { + if (--_index < 0) { + _index = 0; + _sub = 0; + endJournal = true; + } + else { + maxLines = loadJournalFile(false); + _sub = maxLines - 1; + } + } while (!endJournal && !maxLines); + } + + // If it's search mode, check each line for the given keyword + if (direction >= 3 && maxLines && !endJournal && !searchSuccessful) { + Common::String line = _lines[_sub]; + line.toUppercase(); + if (strstr(line.c_str(), _find.c_str()) != nullptr) { + // Found a match. Reset howFar so that the start of page that the match + // was found on will be displayed + searchSuccessful = true; + howFar = ((lineNum / LINES_PER_PAGE) + 1) * LINES_PER_PAGE; + } + } + + ++lineNum; + } while (lineNum < howFar && !endJournal); + + if (!_index && !_sub) + _page = 1; + else + _page -= howFar / LINES_PER_PAGE; + break; + + case 2: + case 3: + // Move howFar lines ahead unless the end of the journal is reached, + // or a searched for keyword is found + for (temp = 0; (temp < (howFar / LINES_PER_PAGE)) && !endJournal && !searchSuccessful; ++temp) { + // Handle animating mouse cursor + int cursorNum = (int)events.getCursor() + 1; + if (cursorNum >(WAIT + 2)) + cursorNum = WAIT; + events.setCursor((CursorId)cursorNum); + + lineNum = 0; + savedIndex = _index; + savedSub = _sub; + + // Move a single page ahead + do { + // If in search mode, check for keyword + if (direction >= 3 && _page != startPage) { + Common::String line = _lines[_sub]; + line.toUppercase(); + if (strstr(line.c_str(), _find.c_str()) != nullptr) + searchSuccessful = true; + } + + // Move forwards a line at a time, unless search word was found + if (!searchSuccessful) { + if (++_sub == maxLines) { + // Reached end of page + do { + if (++_index == (int)_lines.size()) { + _index = savedIndex; + _sub = savedSub; + maxLines = loadJournalFile(false); + endJournal = true; + } else { + _sub = 0; + maxLines = loadJournalFile(false); + } + } while (!endJournal && !maxLines); + } + + ++lineNum; + } + } while ((lineNum < LINES_PER_PAGE) && !endJournal && !searchSuccessful); + + if (!endJournal && !searchSuccessful) + // Move to next page + ++_page; + + if (searchSuccessful) { + // Search found, so show top of the page it was found on + _index = savedIndex; + _sub = savedSub; + maxLines = loadJournalFile(false); + } + } + break; + + default: + break; + } + + if (direction) { + events.setCursor(ARROW); + clearPage(); + } + + screen.gPrint(Common::Point(235, 21), PEN_COLOR, "Page %d", _page); + + temp = _sub; + savedIndex = _index; + lineNum = 0; + + do { + inc = true; + + // If there wasn't any line to print at the top of the page, we won't need to + // increment the y position + if (_lines[temp].empty() && yp == 37) + inc = false; + + // If there's a searched for keyword in the line, it will need to be highlighted + if (searchSuccessful && firstOccurance) { + // Check if line has the keyword + Common::String line = _lines[temp]; + line.toUppercase(); + if ((matchP = strstr(line.c_str(), _find.c_str())) != nullptr) { + matchP = _lines[temp].c_str() + (matchP - line.c_str()); + firstOccurance = false; + + // Print out the start of the line before the matching keyword + Common::String lineStart(_lines[temp].c_str(), matchP); + if (lineStart.hasPrefix("@")) { + width = screen.stringWidth(lineStart.c_str() + 1); + screen.gPrint(Common::Point(53, yp), 15, "%s", lineStart.c_str() + 1); + } else { + width = screen.stringWidth(lineStart.c_str()); + screen.gPrint(Common::Point(53, yp), PEN_COLOR, lineStart.c_str()); + } + + // Print out the found keyword + Common::String lineMatch(matchP, matchP + _find.size()); + screen.gPrint(Common::Point(53 + width, yp), INV_FOREGROUND, lineMatch.c_str()); + width += screen.stringWidth(lineMatch.c_str()); + + // Print remainder of line + screen.gPrint(Common::Point(53 + width, yp), PEN_COLOR, matchP + _find.size()); + } else if (_lines[temp].hasPrefix("@")) { + screen.gPrint(Common::Point(53, yp), 15, _lines[temp].c_str() + 1); + } else { + screen.gPrint(Common::Point(53, yp), PEN_COLOR, _lines[temp].c_str()); + } + } else { + if (_lines[temp].hasPrefix("@")) { + screen.gPrint(Common::Point(53, yp), 15, _lines[temp].c_str() + 1); + } else { + screen.gPrint(Common::Point(53, yp), PEN_COLOR, _lines[temp].c_str()); + } + } + + if (++temp == maxLines) { + // Move to next page + do { + if (_index < (_journal.size() - 1) && lineNum < (LINES_PER_PAGE - 1)) { + ++_index; + maxLines = loadJournalFile(false); + temp = 0; + } else { + if (_index == (_journal.size() - 1)) + _down = false; + endFlag = true; + } + } while (!endFlag && !maxLines); + } + + if (inc) { + // Move to next line + ++lineNum; + yp += 13; + } + } while (lineNum < LINES_PER_PAGE && !endFlag); + + _index = savedIndex; + _up = _index || _sub; + + return direction >= 3 && searchSuccessful; +} + +/** + * Clears the journal page + */ +void Journal::clearPage() { + // Clear the journal page by redrawing it from scratch + drawInterface(); } } // End of namespace Sherlock diff --git a/engines/sherlock/journal.h b/engines/sherlock/journal.h index 8ad19dc0e5..25f70b0e29 100644 --- a/engines/sherlock/journal.h +++ b/engines/sherlock/journal.h @@ -56,6 +56,7 @@ private: bool _up, _down; int _page; int _converseNum; + Common::String _find; void loadJournalLocations(); @@ -63,7 +64,9 @@ private: void doArrows(); - void doJournal(int direction, int howFar); + bool doJournal(int direction, int howFar); + + void clearPage(); public: public: Journal(SherlockEngine *vm); diff --git a/engines/sherlock/screen.h b/engines/sherlock/screen.h index edc0136471..4e37a7787c 100644 --- a/engines/sherlock/screen.h +++ b/engines/sherlock/screen.h @@ -50,7 +50,8 @@ enum { BUTTON_MIDDLE = 244, BUTTON_BOTTOM = 248, TALK_FOREGROUND = 12, - TALK_NULL = 16 + TALK_NULL = 16, + PEN_COLOR = 250 }; class SherlockEngine; -- cgit v1.2.3 From 005438570492b88a152a7a11e6d4df45687ba0bd Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 4 Apr 2015 17:09:59 -0500 Subject: SHERLOCK: Implement journal event handling --- engines/sherlock/journal.cpp | 392 +++++++++++++++++++++++++++++++++++- engines/sherlock/journal.h | 5 +- engines/sherlock/scene.h | 4 +- engines/sherlock/user_interface.cpp | 43 +++- 4 files changed, 438 insertions(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/journal.cpp b/engines/sherlock/journal.cpp index 140b766dca..b05cc03372 100644 --- a/engines/sherlock/journal.cpp +++ b/engines/sherlock/journal.cpp @@ -41,6 +41,12 @@ const int JOURNAL_POINTS[9][3] = { { 237, 313, 275 } }; +const int SEARCH_POINTS[3][3] = { + { 51, 123, 86 }, + { 124, 196, 159 }, + { 197, 269, 232 } +}; + /*----------------------------------------------------------------*/ Journal::Journal(SherlockEngine *vm): _vm(vm) { @@ -754,12 +760,12 @@ bool Journal::doJournal(int direction, int howFar) { if (++temp == maxLines) { // Move to next page do { - if (_index < (_journal.size() - 1) && lineNum < (LINES_PER_PAGE - 1)) { + if (_index < ((int)_journal.size() - 1) && lineNum < (LINES_PER_PAGE - 1)) { ++_index; maxLines = loadJournalFile(false); temp = 0; } else { - if (_index == (_journal.size() - 1)) + if (_index == ((int)_journal.size() - 1)) _down = false; endFlag = true; } @@ -787,4 +793,386 @@ void Journal::clearPage() { drawInterface(); } +/** + * Handle events whilst the journal is being displayed + */ +bool Journal::handleEvents(int key) { + Events &events = *_vm->_events; + Screen &screen = *_vm->_screen; + bool doneFlag = false; + Common::Point pt = events.mousePos(); + byte color; + enum Button { + BTN_NONE, BTN_EXIT, BTN_BACK10, BTN_UP, BTN_DOWN, BTN_AHEAD110, BTN_SEARCH, + BTN_FIRST_PAGE, BTN_LAST_PAGE, BTN_PRINT_TEXT + }; + Button found = BTN_NONE; + + if (events._pressed || events._released) { + // Exit button + if (pt.x > JOURNAL_POINTS[0][0] && pt.x < JOURNAL_POINTS[0][1] && pt.y >= JOURNAL_BUTTONS_Y && + pt.y < (JOURNAL_BUTTONS_Y + 10)) { + found = BTN_EXIT; + color = COMMAND_HIGHLIGHTED; + } else { + color = COMMAND_FOREGROUND; + } + screen.buttonPrint(Common::Point(JOURNAL_POINTS[1][2], JOURNAL_BUTTONS_Y), color, true, "Exit"); + + // Back 10 button + if (pt.x > JOURNAL_POINTS[1][0] && pt.x < JOURNAL_POINTS[1][1] && pt.y >= JOURNAL_BUTTONS_Y && + pt.y < (JOURNAL_BUTTONS_Y + 10) && _page > 1) { + found = BTN_BACK10; + screen.buttonPrint(Common::Point(JOURNAL_POINTS[1][2], JOURNAL_BUTTONS_Y), COMMAND_HIGHLIGHTED, true, "Back 10"); + } else if (_page > 1) { + screen.buttonPrint(Common::Point(JOURNAL_POINTS[1][2], JOURNAL_BUTTONS_Y), COMMAND_FOREGROUND, true, "Back 10"); + } + + // Up button + if (pt.x > JOURNAL_POINTS[2][0] && pt.x < JOURNAL_POINTS[2][1] && pt.y >= JOURNAL_BUTTONS_Y && + pt.y < (JOURNAL_BUTTONS_Y + 10) && _up) { + found = BTN_UP; + screen.buttonPrint(Common::Point(JOURNAL_POINTS[2][2], JOURNAL_BUTTONS_Y), COMMAND_HIGHLIGHTED, true, "Up"); + } else if (_up) { + screen.buttonPrint(Common::Point(JOURNAL_POINTS[2][2], JOURNAL_BUTTONS_Y), COMMAND_FOREGROUND, true, "Up"); + } + + // Down button + if (pt.x > JOURNAL_POINTS[3][0] && pt.x < JOURNAL_POINTS[3][1] && pt.y >= JOURNAL_BUTTONS_Y && + pt.y < (JOURNAL_BUTTONS_Y + 10) && _down) { + found = BTN_DOWN; + screen.buttonPrint(Common::Point(JOURNAL_POINTS[3][2], JOURNAL_BUTTONS_Y), COMMAND_HIGHLIGHTED, true, "Down"); + } else if (_down) { + screen.buttonPrint(Common::Point(JOURNAL_POINTS[3][2], JOURNAL_BUTTONS_Y), COMMAND_FOREGROUND, true, "Down"); + } + + // Ahead 10 button + if (pt.x > JOURNAL_POINTS[4][0] && pt.x < JOURNAL_POINTS[4][1] && pt.y >= JOURNAL_BUTTONS_Y && + pt.y < (JOURNAL_BUTTONS_Y + 10) && _down) { + found = BTN_AHEAD110; + screen.buttonPrint(Common::Point(JOURNAL_POINTS[4][2], JOURNAL_BUTTONS_Y), COMMAND_HIGHLIGHTED, true, "Ahead 10"); + } else if (_down) { + screen.buttonPrint(Common::Point(JOURNAL_POINTS[4][2], JOURNAL_BUTTONS_Y), COMMAND_FOREGROUND, true, "Ahead 10"); + } + + // Search button + if (pt.x > JOURNAL_POINTS[5][0] && pt.x < JOURNAL_POINTS[5][1] && pt.y >= (JOURNAL_BUTTONS_Y + 11) && + pt.y < (JOURNAL_BUTTONS_Y + 20) && !_journal.empty()) { + found = BTN_SEARCH; + color = COMMAND_HIGHLIGHTED; + } else if (_journal.empty()) { + color = COMMAND_NULL; + } else { + color = COMMAND_FOREGROUND; + } + screen.buttonPrint(Common::Point(JOURNAL_POINTS[5][2], JOURNAL_BUTTONS_Y + 11), color, true, "Search"); + + // First Page button + if (pt.x > JOURNAL_POINTS[6][0] && pt.x < JOURNAL_POINTS[6][1] && pt.y >= (JOURNAL_BUTTONS_Y + 11) && + pt.y < (JOURNAL_BUTTONS_Y + 20) && _up) { + found = BTN_FIRST_PAGE; + color = COMMAND_HIGHLIGHTED; + } else if (_up) { + color = COMMAND_FOREGROUND; + } else { + color = COMMAND_NULL; + } + screen.buttonPrint(Common::Point(JOURNAL_POINTS[6][2], JOURNAL_BUTTONS_Y + 11), color, true, "First Page"); + + // Last Page button + if (pt.x > JOURNAL_POINTS[7][0] && pt.x < JOURNAL_POINTS[7][1] && pt.y >= (JOURNAL_BUTTONS_Y + 11) && + pt.y < (JOURNAL_BUTTONS_Y + 20) && _down) { + found = BTN_LAST_PAGE; + color = COMMAND_HIGHLIGHTED; + } else if (_down) { + color = COMMAND_FOREGROUND; + } else { + color = COMMAND_NULL; + } + screen.buttonPrint(Common::Point(JOURNAL_POINTS[7][2], JOURNAL_BUTTONS_Y + 11), color, true, "Last Page"); + + + // Print Text button + if (pt.x > JOURNAL_POINTS[8][0] && pt.x < JOURNAL_POINTS[8][1] && pt.y >= (JOURNAL_BUTTONS_Y + 11) && + pt.y < (JOURNAL_BUTTONS_Y + 20) && !_journal.empty()) { + found = BTN_PRINT_TEXT; + color = COMMAND_HIGHLIGHTED; + } else if (_journal.empty()) { + color = COMMAND_NULL; + } else { + color = COMMAND_FOREGROUND; + } + screen.buttonPrint(Common::Point(JOURNAL_POINTS[8][2], JOURNAL_BUTTONS_Y + 11), color, true, "Print Text"); + } + + if (found == BTN_EXIT && events._released) + // Exit button pressed + doneFlag = true; + + if (((found == BTN_BACK10 && events._released) || key == 'B') && (_page > 1)) { + // Scrolll up 10 pages + if (_page < 11) + doJournal(1, (_page - 1) * LINES_PER_PAGE); + else + doJournal(1, 10 * LINES_PER_PAGE); + + doArrows(); + screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT); + } + + if (((found == BTN_UP && events._released) || key =='U') && _up) { + // Scroll up + doJournal(1, LINES_PER_PAGE); + doArrows(); + screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT); + } + + if (((found == BTN_DOWN && events._released) || key =='D') && _down) { + // Scroll down + doJournal(2, LINES_PER_PAGE); + doArrows(); + screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT); + } + + if (((found == BTN_AHEAD110 && events._released) || key == 'A') && _down) { + // Scroll down 10 pages + if ((_page + 10) > _maxPage) + doJournal(2, (_maxPage - _page) * LINES_PER_PAGE); + else + doJournal(2, 10 * LINES_PER_PAGE); + + doArrows(); + screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT); + } + + if (((found == BTN_SEARCH && events._released) || key == 'S') && !_journal.empty()) { + screen.buttonPrint(Common::Point(JOURNAL_POINTS[5][2], JOURNAL_BUTTONS_Y + 11), COMMAND_FOREGROUND, true, "Search"); + bool notFound = false; + + int dir; + + do { + if ((dir = getFindName(notFound)) != 0) { + int savedIndex = _index; + int savedSub = _sub; + int savedPage = _page; + + if (doJournal(dir + 2, 1000 * LINES_PER_PAGE) == 0) { + _index = savedIndex; + _sub = savedSub; + _page = savedPage; + + clearPage(); + doJournal(0, 0); + notFound = true; + } else { + doneFlag = true; + } + + doArrows(); + screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT); + } else { + doneFlag = true; + } + } while (!doneFlag); + doneFlag = false; + } + + if (((found == BTN_FIRST_PAGE && events._released) || key == 'F') && _up) { + // First page + _index = _sub = 0; + _up = _down = false; + _page = 1; + + clearPage(); + doJournal(0, 0); + doArrows(); + screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT); + } + + if (((found == BTN_LAST_PAGE && events._released) || key == 'L') && _down) { + // Last page + if ((_page + 10) > _maxPage) + doJournal(2, (_maxPage - _page) * LINES_PER_PAGE); + else + doJournal(2, 1000 * LINES_PER_PAGE); + + doArrows(); + screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT); + } + + events.wait(2); + + return doneFlag; +} + +/** + * Show the search submenu + */ +int Journal::getFindName(bool printError) { + Events &events = *_vm->_events; + Screen &screen = *_vm->_screen; + Talk &talk = *_vm->_talk; + int xp; + int yp = 174; + bool flag = false; + Common::String name; + enum Button { BTN_NONE, BTN_EXIT, BTN_BACKWARD, BTN_FORWARD }; + Button found = BTN_NONE; + int done = 0; + byte color; + + // Draw search panel + screen.makePanel(Common::Rect(6, 171, 313, 199)); + screen.makeButton(Common::Rect(SEARCH_POINTS[0][0], yp, SEARCH_POINTS[0][1], yp + 10), + SEARCH_POINTS[0][2] - screen.stringWidth("Exit") / 2, "Exit"); + screen.makeButton(Common::Rect(SEARCH_POINTS[1][0], yp, SEARCH_POINTS[1][1], yp + 10), + SEARCH_POINTS[1][2] - screen.stringWidth("Backward") / 2, "Backward"); + screen.makeButton(Common::Rect(SEARCH_POINTS[2][0], yp, SEARCH_POINTS[2][1], yp + 10), + SEARCH_POINTS[2][2] - screen.stringWidth("Forward") / 2, "Forward"); + + screen.gPrint(Common::Point(SEARCH_POINTS[0][2] - screen.stringWidth("Exit") / 2, yp), COMMAND_FOREGROUND, "E"); + screen.gPrint(Common::Point(SEARCH_POINTS[1][2] - screen.stringWidth("Backward") / 2, yp), COMMAND_FOREGROUND, "B"); + screen.gPrint(Common::Point(SEARCH_POINTS[2][2] - screen.stringWidth("Forward") / 2, yp), COMMAND_FOREGROUND, "F"); + + screen.fillRect(Common::Rect(12, 185, 307, 186), BUTTON_BOTTOM); + screen.vLine(12, 185, 195, BUTTON_BOTTOM); + screen.hLine(13, 195, 306, BUTTON_TOP); + screen.hLine(306, 186, 195, BUTTON_TOP); + + if (printError) { + screen.gPrint(Common::Point((SHERLOCK_SCREEN_WIDTH - screen.stringWidth("Text Not Found !")) / 2, 185), + INV_FOREGROUND, "Text Not Found !"); + } else if (!_find.empty()) { + // There's already a search term, display it already + screen.gPrint(Common::Point(15, 185), TALK_FOREGROUND, _find.c_str()); + name = _find; + } + + screen.slamArea(6, 171, 307, 28); + + if (printError) { + // Give time for user to see the message + for (int idx = 0; idx < 40 && !_vm->shouldQuit() && !events.kbHit() && !events._released; ++idx) { + events.pollEvents(); + events.setButtonState(); + + events.wait(2); + } + + events.clearKeyboard(); + screen.fillRect(Common::Rect(13, 186, 306, 195), BUTTON_MIDDLE); + + if (!_find.empty()) { + screen.gPrint(Common::Point(15, 185), TALK_FOREGROUND, _find.c_str()); + name = _find; + } + + screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT); + } + + xp = 15 + screen.stringWidth(name); + yp = 186; + + do { + events._released = false; + found = BTN_NONE; + + while (!_vm->shouldQuit() && !events.kbHit() && !events._released) { + found = BTN_NONE; + if (talk._talkToAbort) + return 0; + + // Check if key or mouse button press has occurred + events.setButtonState(); + Common::Point pt = events.mousePos(); + + flag = !flag; + screen.vgaBar(Common::Rect(xp, yp, xp + 8, yp + 9), flag ? INV_FOREGROUND : BUTTON_MIDDLE); + + if (events._pressed || events._released) { + if (pt.x > SEARCH_POINTS[0][0] && pt.x < SEARCH_POINTS[0][1] && pt.y > 174 && pt.y < 183) { + found = BTN_EXIT; + color = COMMAND_HIGHLIGHTED; + } else { + color = COMMAND_FOREGROUND; + } + screen.print(Common::Point(SEARCH_POINTS[0][2] - screen.stringWidth("Exit") / 2, 175), color, "Exit"); + + if (pt.x > SEARCH_POINTS[1][0] && pt.x < SEARCH_POINTS[1][1] && pt.y > 174 && pt.y < 183) { + found = BTN_BACKWARD; + color = COMMAND_HIGHLIGHTED; + } else { + color = COMMAND_FOREGROUND; + } + screen.print(Common::Point(SEARCH_POINTS[1][2] - screen.stringWidth("Backward") / 2, 175), color, "Backward"); + + if (pt.x > SEARCH_POINTS[2][0] && pt.x < SEARCH_POINTS[2][1] && pt.y > 174 && pt.y < 183) { + found = BTN_FORWARD; + color = COMMAND_HIGHLIGHTED; + } else { + color = COMMAND_FOREGROUND; + } + screen.print(Common::Point(SEARCH_POINTS[1][2] - screen.stringWidth("Forward") / 2, 175), color, "Forward"); + } + + events.wait(2); + } + + if (events.kbHit()) { + Common::KeyState keyState = events.getKey(); + + if (keyState.keycode == Common::KEYCODE_BACKSPACE && name.c_str() > 0) { + screen.vgaBar(Common::Rect(xp - screen.charWidth(name.lastChar()), yp, xp + 8, yp + 9), BUTTON_MIDDLE); + xp -= screen.charWidth(name.lastChar()); + screen.vgaBar(Common::Rect(xp, yp, xp + 8, yp + 9), INV_FOREGROUND); + name.deleteLastChar(); + } + + if (keyState.keycode == Common::KEYCODE_RETURN) + done = 1; + + if (keyState.keycode == Common::KEYCODE_ESCAPE) { + screen.vgaBar(Common::Rect(xp, yp, xp + 8, yp + 9), BUTTON_MIDDLE); + done = -1; + } + + if (keyState.keycode >= Common::KEYCODE_SPACE && keyState.keycode <= Common::KEYCODE_z + && keyState.keycode != Common::KEYCODE_AT && name.size() < 50 + && (xp + screen.charWidth(keyState.keycode)) < 296) { + screen.vgaBar(Common::Rect(xp, yp, xp + 8, yp + 9), BUTTON_MIDDLE); + screen.print(Common::Point(xp, yp), TALK_FOREGROUND, "%c", (char)keyState.keycode); + xp += screen.charWidth((char)keyState.keycode); + name += (char)keyState.keycode; + } + } + + if (events._released) { + switch (found) { + case BTN_EXIT: + done = -1; break; + case BTN_BACKWARD: + done = 2; break; + case BTN_FORWARD: + done = 1; break; + default: + break; + } + } + } while (!done); + + if (done != -1) { + _find = name; + } else { + done = 0; + } + + // Redisplay the journal screen + clearPage(); + doJournal(0, 0); + screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT); + + return done; +} + } // End of namespace Sherlock diff --git a/engines/sherlock/journal.h b/engines/sherlock/journal.h index 25f70b0e29..a5fe1e8d94 100644 --- a/engines/sherlock/journal.h +++ b/engines/sherlock/journal.h @@ -67,13 +67,16 @@ private: bool doJournal(int direction, int howFar); void clearPage(); -public: + + int getFindName(bool printError); public: Journal(SherlockEngine *vm); void record(int converseNum, int statementNum); void drawInterface(); + + bool handleEvents(int key); }; } // End of namespace Sherlock diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h index cd64073621..3549325e8e 100644 --- a/engines/sherlock/scene.h +++ b/engines/sherlock/scene.h @@ -97,8 +97,6 @@ private: void transitionToScene(); - void updateBackground(); - void checkBgShapes(ImageFrame *frame, const Common::Point &pt); void saveSceneStatus(); @@ -167,6 +165,8 @@ public: int whichZone(const Common::Point &pt); int closestZone(const Common::Point &pt); + + void updateBackground(); }; } // End of namespace Sherlock diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index 01b08ffd71..289bff814f 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -1127,10 +1127,51 @@ void UserInterface::doTalkControl() { } void UserInterface::journalControl() { + Events &events = *_vm->_events; Journal &journal = *_vm->_journal; - + Scene &scene = *_vm->_scene; + Screen &screen = *_vm->_screen; + int found; + bool doneFlag = false; + + // Draw the journal screen journal.drawInterface(); + // Handle journal events + do { + found = _key = -1; + events.setButtonState(); + + // Handle keypresses + if (events.kbHit()) { + Common::KeyState keyState = events.getKey(); + if (keyState.keycode == Common::KEYCODE_x && (keyState.flags & Common::KBD_ALT)) { + _vm->quitGame(); + return; + } else if (keyState.keycode == Common::KEYCODE_e || keyState.keycode == Common::KEYCODE_ESCAPE) { + doneFlag = true; + } else { + _key = toupper(keyState.keycode); + } + } + + if (!doneFlag) + doneFlag = journal.handleEvents(_key); + } while (!_vm->shouldQuit() && !doneFlag); + + // Finish up + _infoFlag = _keyboardInput = false; + _keycode = Common::KEYCODE_INVALID; + _windowOpen = false; + _windowBounds.top = CONTROLS_Y1; + _key = -1; + + // Reset the palette + screen.setPalette(screen._cMap); + + screen._backBuffer1.blitFrom(screen._backBuffer2); + scene.updateBackground(); + screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT); // TODO } -- cgit v1.2.3 From f238e7563ae62dd5d067432b2cc87b8c154aa40b Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 4 Apr 2015 17:59:33 -0500 Subject: TONY: Revert Italian detection entry --- engines/tony/detection_tables.h | 16 ---------------- 1 file changed, 16 deletions(-) (limited to 'engines') diff --git a/engines/tony/detection_tables.h b/engines/tony/detection_tables.h index e4a064157b..28dcaac752 100644 --- a/engines/tony/detection_tables.h +++ b/engines/tony/detection_tables.h @@ -127,22 +127,6 @@ static const TonyGameDescription gameDescriptions[] = { }, }, - { - // Tony Tough Italian (PC Action magazine) - { - "tony", - 0, - { - { "data1.cab", 0, "42344827407b974af11d60fadbd021b4", 3811 }, - AD_LISTEND - }, - Common::IT_ITA, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - GUIO1(GUIO_NONE) - }, - }, - { // Tony Tough Italian provided by Giovanni Bajo { -- cgit v1.2.3 From a44ab1facc9c1ed8bc1f1ff38876c65f2624a406 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 4 Apr 2015 21:08:15 -0500 Subject: MADS: Fix incorrect depth handling after picking up rebreather --- engines/mads/nebular/nebular_scenes1.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes1.cpp b/engines/mads/nebular/nebular_scenes1.cpp index 0c5888b6ec..047dc1f498 100644 --- a/engines/mads/nebular/nebular_scenes1.cpp +++ b/engines/mads/nebular/nebular_scenes1.cpp @@ -1462,7 +1462,6 @@ void Scene103::actions() { } else if (_action.isAction(VERB_TAKE, NOUN_REBREATHER, 0) && _game._objects.isInRoom(OBJ_REBREATHER)) { switch (_vm->_game->_trigger) { case 0: - _scene->changeVariant(1); _globals._sequenceIndexes[12] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[12], false, 3, 2); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[12]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_SPRITE, 6, 1); -- cgit v1.2.3 From 355fa444caadfc951ba289bf23fc275f949bf36e Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 4 Apr 2015 21:40:21 -0500 Subject: MADS: Fix throwing burger in the different difficulty modes --- engines/mads/nebular/nebular_scenes1.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes1.cpp b/engines/mads/nebular/nebular_scenes1.cpp index 047dc1f498..0a62e375d7 100644 --- a/engines/mads/nebular/nebular_scenes1.cpp +++ b/engines/mads/nebular/nebular_scenes1.cpp @@ -2637,7 +2637,7 @@ void Scene109::actions() { break; case OBJ_BURGER: - _hoovicDifficultFl = (_game._difficulty == DIFFICULTY_EASY); + _hoovicDifficultFl = (_game._difficulty == DIFFICULTY_HARD); _globals._spriteIndexes[8] = _scene->_sprites.addSprites(formAnimName('H', (_hoovicDifficultFl ? 3 : 1))); break; } -- cgit v1.2.3 From ae61f8ba04aca3cbd84c4dd27f9302744246f109 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 4 Apr 2015 22:03:06 -0500 Subject: MADS: Fix wait cursor when leaving crashed ship for the first time --- engines/mads/events.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mads/events.cpp b/engines/mads/events.cpp index 767f998d81..52569af375 100644 --- a/engines/mads/events.cpp +++ b/engines/mads/events.cpp @@ -84,8 +84,8 @@ void EventsManager::waitCursor() { CursorType cursorId = (CursorType)MIN(_cursorSprites->getCount(), (int)CURSOR_WAIT); _newCursorId = cursorId; if (_cursorId != _newCursorId) { - changeCursor(); _cursorId = _newCursorId; + changeCursor(); } } -- cgit v1.2.3 From d6945864ea450cdaa20e5120771e3c497e5515ee Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 4 Apr 2015 22:39:56 -0500 Subject: MADS: Keep Rex's speech on-screen longer when exitting crashed ship --- engines/mads/messages.cpp | 8 +++++--- engines/mads/nebular/nebular_scenes1.cpp | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/mads/messages.cpp b/engines/mads/messages.cpp index 4b105630d6..304c79aa46 100644 --- a/engines/mads/messages.cpp +++ b/engines/mads/messages.cpp @@ -91,7 +91,7 @@ int KernelMessages::add(const Common::Point &pt, uint fontColor, uint8 flags, rec._position = pt; rec._textDisplayIndex = -1; rec._timeout = timeout; - rec._frameTimer = _vm->_game->_priorFrameTimer; + rec._frameTimer = scene._frameStartTime; rec._trigger = endTrigger; rec._abortMode = _vm->_game->_triggerSetupMode; @@ -162,8 +162,10 @@ void KernelMessages::update() { uint32 currentTimer = _vm->_game->_scene._frameStartTime; for (uint i = 0; i < _entries.size() && !_vm->_game->_trigger; ++i) { - KernelMessage &msg = _entries[i]; + if (_vm->_game->_trigger) + break; + KernelMessage &msg = _entries[i]; if (((msg._flags & KMSG_ACTIVE) != 0) && (currentTimer >= msg._frameTimer)) processText(i); } @@ -172,7 +174,7 @@ void KernelMessages::update() { void KernelMessages::processText(int msgIndex) { Scene &scene = _vm->_game->_scene; KernelMessage &msg = _entries[msgIndex]; - uint32 currentTimer = _vm->_game->_priorFrameTimer; + uint32 currentTimer = scene._frameStartTime; bool flag = false; if ((msg._flags & KMSG_EXPIRE) != 0) { diff --git a/engines/mads/nebular/nebular_scenes1.cpp b/engines/mads/nebular/nebular_scenes1.cpp index 0a62e375d7..bcc4fb43d5 100644 --- a/engines/mads/nebular/nebular_scenes1.cpp +++ b/engines/mads/nebular/nebular_scenes1.cpp @@ -2112,9 +2112,9 @@ void Scene106::step() { } if (msgId >= 0) { - int nextAbortVal = _game._trigger + 1; + int nextTrigger = _game._trigger + 1; _scene->_kernelMessages.add(Common::Point(15, _positionY), 0x1110, 0, 0, 360, _game.getQuote(msgId)); - _scene->_sequences.addTimer(150, nextAbortVal); + _scene->_sequences.addTimer(150, nextTrigger); _positionY += 14; } } -- cgit v1.2.3 From cb91e1518a3ba88e378d4e90cbe0d8e99ba4e639 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 4 Apr 2015 22:59:43 -0500 Subject: MADS: Have Rex swim to correct spot when throwing burger or fish --- engines/mads/nebular/nebular_scenes1.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/mads/nebular/nebular_scenes1.cpp b/engines/mads/nebular/nebular_scenes1.cpp index bcc4fb43d5..c9eda08859 100644 --- a/engines/mads/nebular/nebular_scenes1.cpp +++ b/engines/mads/nebular/nebular_scenes1.cpp @@ -2589,8 +2589,8 @@ void Scene109::preActions() { _game._player._walkOffScreenSceneId = 108; if ((_action.isAction(VERB_THROW) || _action.isAction(VERB_GIVE) || _action.isAction(VERB_PUT)) - && (_action.isObject(NOUN_SMALL_HOLE) || _action.isObject(NOUN_TUNNEL)) - && (_action.isObject(NOUN_DEAD_FISH) || _action.isObject(NOUN_STUFFED_FISH) || _action.isObject(NOUN_BURGER))) { + && (_action.isTarget(NOUN_SMALL_HOLE) || _action.isTarget(NOUN_TUNNEL)) + && (_action.isObject(NOUN_DEAD_FISH) || _action.isObject(NOUN_STUFFED_FISH) || _action.isObject(NOUN_BURGER))) { int idx = _game._objects.getIdFromDesc(_action._activeAction._objectNameId); if ((idx >= 0) && _game._objects.isInInventory(idx)) { _game._player._prepareWalkPos = Common::Point(106, 38); -- cgit v1.2.3 From b0c76b3a17a08abed2d35d301cbd69f9bc8efa52 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 5 Apr 2015 07:50:13 -0500 Subject: TONY: Fix disabled ui after capturing guard on Ferris Wheel --- engines/tony/mpal/mpal.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'engines') diff --git a/engines/tony/mpal/mpal.cpp b/engines/tony/mpal/mpal.cpp index c813b354b0..89cc28130d 100644 --- a/engines/tony/mpal/mpal.cpp +++ b/engines/tony/mpal/mpal.cpp @@ -709,6 +709,10 @@ void ActionThread(CORO_PARAM, const void *param) { CORO_SLEEP(1); } + // WORKAROUND: User interface sometimes remaining disabled after capturing guard on Ferris wheel + if (_ctx->item->_nObj == 3601 && _ctx->item->_dwRes == 9) + g_vm->getEngine()->enableInput(); + globalDestroy(_ctx->item); _ctx->item = NULL; -- cgit v1.2.3 From d17dea4afd76cba7280e3ffafd1e78a09430e983 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 5 Apr 2015 14:49:02 -0500 Subject: SHERLOCK: Fix journal initalization and initial calls --- engines/sherlock/journal.cpp | 36 ++++++++++++++++-------------------- engines/sherlock/journal.h | 4 ++-- engines/sherlock/objects.cpp | 14 +++++++------- engines/sherlock/talk.cpp | 15 ++++++++++----- 4 files changed, 35 insertions(+), 34 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/journal.cpp b/engines/sherlock/journal.cpp index b05cc03372..2811c463a2 100644 --- a/engines/sherlock/journal.cpp +++ b/engines/sherlock/journal.cpp @@ -50,9 +50,6 @@ const int SEARCH_POINTS[3][3] = { /*----------------------------------------------------------------*/ Journal::Journal(SherlockEngine *vm): _vm(vm) { - // Allow up to 1000 statements - _journal.resize(1000); - // Initialize fields _count = 0; _maxPage = 0; @@ -70,12 +67,12 @@ Journal::Journal(SherlockEngine *vm): _vm(vm) { * Records statements that are said, in the order which they are said. The player * can then read the journal to review them */ -void Journal::record(int converseNum, int statementNum) { +void Journal::record(int converseNum, int statementNum, bool replyOnly) { int saveIndex = _index; int saveSub = _sub; // Record the entry into the list - _journal.push_back(JournalEntry(converseNum, statementNum)); + _journal.push_back(JournalEntry(converseNum, statementNum, replyOnly)); _index = _journal.size() - 1; // Load the text for the new entry to get the number of lines it will have @@ -108,12 +105,12 @@ void Journal::loadJournalLocations() { _directory.resize(dir->readUint16LE()); // Read in each entry + char buffer[17]; for (uint idx = 0; idx < _directory.size(); ++idx) { - Common::String line; - while ((c = dir->readByte()) != 0) - line += c; + dir->read(buffer, 17); + buffer[16] = '\0'; - _directory.push_back(line); + _directory[idx] = Common::String(buffer); } delete dir; @@ -124,7 +121,7 @@ void Journal::loadJournalLocations() { _locations.clear(); while (loc->pos() < loc->size()) { Common::String line; - while ((c = loc->readByte()) != '\0') + while ((c = loc->readByte()) != 0) line += c; _locations.push_back(line); @@ -137,7 +134,7 @@ void Journal::loadJournalLocations() { * Loads the description for the current display index in the journal, and then * word wraps the result to prepare it for being displayed */ -bool Journal::loadJournalFile(bool alreadyLoaded) { +int Journal::loadJournalFile(bool alreadyLoaded) { Inventory &inv = *_vm->_inventory; People &people = *_vm->_people; Screen &screen = *_vm->_screen; @@ -147,7 +144,7 @@ bool Journal::loadJournalFile(bool alreadyLoaded) { Common::String dirFilename = _directory[journalEntry._converseNum]; bool replyOnly = journalEntry._replyOnly; - Common::String locStr(dirFilename.c_str(), dirFilename.c_str() + 4); + Common::String locStr(dirFilename.c_str() + 4, dirFilename.c_str() + 6); int newLocation = atoi(locStr.c_str()); // If not flagged as alrady loaded, load the conversation into script variables @@ -246,7 +243,7 @@ bool Journal::loadJournalFile(bool alreadyLoaded) { const char *replyP = statement._reply.c_str(); while (*replyP) { - char c = *replyP; + char c = *replyP++; // Is it a control character? if (c < 128) { @@ -264,7 +261,8 @@ bool Journal::loadJournalFile(bool alreadyLoaded) { // a comment (which would have added a line), add a carriage return if (!startOfReply && ((!commentJustPrinted && c == '{') || c == '}')) journalString += '"'; - + startOfReply = false; + // Handle setting or clearing comment state if (c == '{') { commentFlag = true; @@ -290,7 +288,7 @@ bool Journal::loadJournalFile(bool alreadyLoaded) { else journalString += inv._names[talk._talkTo]; - const char *strP = replyP + 1; + const char *strP = replyP; char v; do { v = *strP++; @@ -307,12 +305,11 @@ bool Journal::loadJournalFile(bool alreadyLoaded) { // Copy text from the place until either the reply ends, a comment // {} block is started, or a control character is encountered + journalString += c; do { journalString += *replyP++; } while (*replyP && *replyP < 128 && *replyP != '{' && *replyP != '}'); - // Move pointer back, since the outer for loop will increment it again - --replyP; commentJustPrinted = false; } } else if (c == 128) { @@ -327,7 +324,7 @@ bool Journal::loadJournalFile(bool alreadyLoaded) { } startOfReply = false; - c = *++replyP; + c = *replyP++; if ((c - 1) == 0) journalString += "Holmes"; @@ -338,7 +335,7 @@ bool Journal::loadJournalFile(bool alreadyLoaded) { else journalString += inv._names[c - 1]; - const char *strP = replyP + 1; + const char *strP = replyP; char v; do { v = *strP++; @@ -350,7 +347,6 @@ bool Journal::loadJournalFile(bool alreadyLoaded) { journalString += " said, \""; } else { // Control code, so move past it and any parameters - ++replyP; switch (c) { case 129: // Run canim case 130: // Assign side diff --git a/engines/sherlock/journal.h b/engines/sherlock/journal.h index a5fe1e8d94..894065759b 100644 --- a/engines/sherlock/journal.h +++ b/engines/sherlock/journal.h @@ -60,7 +60,7 @@ private: void loadJournalLocations(); - bool loadJournalFile(bool alreadyLoaded); + int loadJournalFile(bool alreadyLoaded); void doArrows(); @@ -72,7 +72,7 @@ private: public: Journal(SherlockEngine *vm); - void record(int converseNum, int statementNum); + void record(int converseNum, int statementNum, bool replyOnly = false); void drawInterface(); diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index d5d24e72af..e4730ef207 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -191,15 +191,15 @@ void Sprite::checkSprite() { for (uint idx = 0; idx < scene._bgShapes.size() && !talk._talkToAbort; ++idx) { Object &obj = scene._bgShapes[idx]; - if (obj._aType > PERSON && _type != INVALID && _type != HIDDEN) { - if (_type == NO_SHAPE) { - objBounds = Common::Rect(_position.x, _position.y, - _position.x + _noShapeSize.x, _position.y + _noShapeSize.y); + if (obj._aType > PERSON && obj._type != INVALID && obj._type != HIDDEN) { + if (obj._type == NO_SHAPE) { + objBounds = Common::Rect(obj._position.x, obj._position.y, + obj._position.x + obj._noShapeSize.x, obj._position.y + obj._noShapeSize.y); } else { - int xp = _position.x + _imageFrame->_offset.x; - int yp = _position.y + _imageFrame->_offset.y; + int xp = obj._position.x + obj._imageFrame->_offset.x; + int yp = obj._position.y + obj._imageFrame->_offset.y; objBounds = Common::Rect(xp, yp, - xp + _imageFrame->_frame.w, yp + _imageFrame->_frame.h); + xp + obj._imageFrame->_frame.w, yp + obj._imageFrame->_frame.h); } } diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index 6596431b8b..d284ace8b8 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -37,20 +37,24 @@ void Statement::synchronize(Common::SeekableReadStream &s) { int length; length = s.readUint16LE(); - for (int idx = 0; idx < length; ++idx) + for (int idx = 0; idx < length - 1; ++idx) _statement += (char)s.readByte(); + s.readByte(); // Null ending length = s.readUint16LE(); - for (int idx = 0; idx < length; ++idx) + for (int idx = 0; idx < length - 1; ++idx) _reply += (char)s.readByte(); + s.readByte(); // Null ending length = s.readUint16LE(); - for (int idx = 0; idx < length; ++idx) + for (int idx = 0; idx < length - 1; ++idx) _linkFile += (char)s.readByte(); + s.readByte(); // Null ending length = s.readUint16LE(); - for (int idx = 0; idx < length; ++idx) + for (int idx = 0; idx < length - 1; ++idx) _voiceFile += (char)s.readByte(); + s.readByte(); // Null ending _required.resize(s.readByte()); _modified.resize(s.readByte()); @@ -280,7 +284,7 @@ void Talk::talkTo(const Common::String &filename) { // Add the statement into the journal and talk history if (_talkTo != -1 && !_talkHistory[_converseNum][select]) - journal.record(_converseNum | 2048, select); + journal.record(_converseNum, select, true); _talkHistory[_converseNum][select] = true; // Check if the talk file is meant to be a non-seen comment @@ -555,6 +559,7 @@ void Talk::loadTalkFile(const Common::String &filename) { // Open the talk file for reading Common::SeekableReadStream *talkStream = res.load(talkFile); + _converseNum = res.resourceIndex(); talkStream->skip(2); // Skip talk file version num _statements.resize(talkStream->readByte()); -- cgit v1.2.3 From d9168c8fae304c0984b59d142dfc66e04b9fab36 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 5 Apr 2015 15:28:10 -0500 Subject: MADS: Fix placement of blowgun in easy mode --- engines/mads/game.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'engines') diff --git a/engines/mads/game.cpp b/engines/mads/game.cpp index b601a12c82..72d7988c05 100644 --- a/engines/mads/game.cpp +++ b/engines/mads/game.cpp @@ -115,8 +115,6 @@ void Game::run() { _statusFlag = true; while (!_vm->shouldQuit()) { - initializeGlobals(); - if (_loadGameSlot == -1) { startGame(); } -- cgit v1.2.3 From 661542b8c62a618f5d4b8265c8f9fb4d7e58a3a7 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 6 Apr 2015 03:12:15 +0300 Subject: MADS: Implement copy protection screen for Rex --- engines/mads/nebular/dialogs_nebular.cpp | 44 +++++++++++++++++++---- engines/mads/nebular/dialogs_nebular.h | 3 ++ engines/mads/nebular/game_nebular.cpp | 62 +++++++++++++++++--------------- engines/mads/nebular/nebular_scenes8.cpp | 2 +- 4 files changed, 74 insertions(+), 37 deletions(-) (limited to 'engines') diff --git a/engines/mads/nebular/dialogs_nebular.cpp b/engines/mads/nebular/dialogs_nebular.cpp index 4ba5366a60..9388aa2aa5 100644 --- a/engines/mads/nebular/dialogs_nebular.cpp +++ b/engines/mads/nebular/dialogs_nebular.cpp @@ -417,7 +417,7 @@ TextDialog(vm, FONT_INTERFACE, Common::Point(-1, -1), 32) { _hogEntry._pageNum, _hogEntry._lineNum, _hogEntry._wordNum); wordWrap(line); - wordWrap("and type it on the line below (we',27h,'ve even given you"); + wordWrap("and type it on the line below (we've even given you"); wordWrap("first letter as a hint). As soon as you do that, we can get"); wordWrap("right into this really COOL adventure game!\n"); wordWrap("\n"); @@ -428,17 +428,47 @@ TextDialog(vm, FONT_INTERFACE, Common::Point(-1, -1), 32) { void CopyProtectionDialog::show() { draw(); - _vm->_events->showCursor(); - // TODO: Replace with text input - while (!_vm->shouldQuit() && !_vm->_events->isKeyPressed() && - !_vm->_events->_mouseClicked) { - _vm->_events->delay(1); + Common::KeyState curKey; + Common::Rect inputArea(110, 165, 210, 175); + MSurface *origInput = new MSurface(inputArea.width(), inputArea.height()); + _vm->_screen.frameRect(inputArea, TEXTDIALOG_BLACK); + _vm->_screen.copyTo(origInput, inputArea, Common::Point(0, 0)); + _font->setColors(TEXTDIALOG_FE, TEXTDIALOG_FE, TEXTDIALOG_FE, TEXTDIALOG_FE); + _vm->_screen.copyRectToScreen(inputArea); + _vm->_screen.updateScreen(); + + while (!_vm->shouldQuit()) { + while (!_vm->_events->isKeyPressed()) { + _vm->_events->delay(1); + } + + curKey = _vm->_events->getKey(); + + if (curKey.keycode == Common::KEYCODE_RETURN || curKey.keycode == Common::KEYCODE_KP_ENTER) + break; + else if (curKey.keycode == Common::KEYCODE_BACKSPACE) + _textInput.deleteLastChar(); + else if (_textInput.size() < 14) + _textInput += curKey.ascii; + + _vm->_events->_pendingKeys.clear(); + + _vm->_screen.copyFrom(origInput, Common::Rect(0, 0, inputArea.width(), inputArea.height()), Common::Point(inputArea.left, inputArea.top)); + _font->writeString(&_vm->_screen, _textInput, + Common::Point(inputArea.left + 2, inputArea.top + 1), 1); + _vm->_screen.copyRectToScreen(inputArea); + _vm->_screen.updateScreen(); } - _vm->_events->_pendingKeys.clear(); + delete origInput; } +bool CopyProtectionDialog::isCorrectAnswer() { + return _hogEntry._word == _textInput; +} + + bool CopyProtectionDialog::getHogAnusEntry(HOGANUS &entry) { File f; f.open("*HOGANUS.DAT"); diff --git a/engines/mads/nebular/dialogs_nebular.h b/engines/mads/nebular/dialogs_nebular.h index 5dbe4da6f0..0f086f6ec1 100644 --- a/engines/mads/nebular/dialogs_nebular.h +++ b/engines/mads/nebular/dialogs_nebular.h @@ -69,6 +69,7 @@ struct HOGANUS { class CopyProtectionDialog : public TextDialog { private: HOGANUS _hogEntry; + Common::String _textInput; /** * Get a random copy protection entry from the HOGANUS resource @@ -84,6 +85,8 @@ public: * Show the dialog */ virtual void show(); + + bool isCorrectAnswer(); }; class PictureDialog : public TextDialog { diff --git a/engines/mads/nebular/game_nebular.cpp b/engines/mads/nebular/game_nebular.cpp index cde998e66a..ec7c6678e8 100644 --- a/engines/mads/nebular/game_nebular.cpp +++ b/engines/mads/nebular/game_nebular.cpp @@ -45,19 +45,25 @@ GameNebular::GameNebular(MADSEngine *vm) } ProtectionResult GameNebular::checkCopyProtection() { - /* - // DEBUG: Flag copy protection failure - _globals[kCopyProtectFailed] = -1; + //if (!ConfMan.getBool("copy_protection")) + // return PROTECTION_SUCCEED; - if (!ConfMan.getBool("copy_protection")) - return true; + CopyProtectionDialog *dlg; + bool correctAnswer; - * DEBUG: Disabled for now - CopyProtectionDialog *dlg = new CopyProtectionDialog(_vm, false); + dlg = new CopyProtectionDialog(_vm, false); dlg->show(); + correctAnswer = dlg->isCorrectAnswer(); delete dlg; - */ - return PROTECTION_SUCCEED; + + if (!correctAnswer) { + dlg = new CopyProtectionDialog(_vm, true); + dlg->show(); + correctAnswer = dlg->isCorrectAnswer(); + delete dlg; + } + + return correctAnswer ? PROTECTION_SUCCEED : PROTECTION_FAIL; } void GameNebular::startGame() { @@ -91,26 +97,6 @@ void GameNebular::startGame() { checkShowDialog(); _winStatus = 0; - /* - // Check copy protection - ProtectionResult protectionResult = checkCopyProtection(); - switch (protectionResult) { - case PROTECTION_FAIL: - // Copy protection failed - _scene._nextSceneId = 804; - initializeGlobals(); - _globals[kCopyProtectFailed] = true; - return; - case PROTECTION_ESCAPE: - // User escaped out of copy protection dialog - _vm->quitGame(); - return; - default: - // Copy protection check succeeded - break; - } - */ - _sectionNumber = 1; initSection(_sectionNumber); _vm->_events->setCursor(CURSOR_ARROW); @@ -128,6 +114,24 @@ void GameNebular::startGame() { _scene._nextSceneId = 101; initializeGlobals(); + + // Check copy protection + ProtectionResult protectionResult = checkCopyProtection(); + + switch (protectionResult) { + case PROTECTION_FAIL: + // Copy protection failed + _scene._nextSceneId = 804; + _globals[kCopyProtectFailed] = true; + return; + case PROTECTION_ESCAPE: + // User escaped out of copy protection dialog + _vm->quitGame(); + return; + default: + // Copy protection check succeeded + break; + } } void GameNebular::initializeGlobals() { diff --git a/engines/mads/nebular/nebular_scenes8.cpp b/engines/mads/nebular/nebular_scenes8.cpp index 8ce559b82b..5f8417cee1 100644 --- a/engines/mads/nebular/nebular_scenes8.cpp +++ b/engines/mads/nebular/nebular_scenes8.cpp @@ -957,7 +957,7 @@ void Scene804::step() { _globals[kInSpace] = false; _globals[kBeamIsUp] = true; - assert(!_globals[kCopyProtectFailed]); + //assert(!_globals[kCopyProtectFailed]); _game._winStatus = 4; return; } -- cgit v1.2.3 From 900471834987c32b23b3162e2d2f40bbcc2b593d Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 5 Apr 2015 21:35:22 -0500 Subject: SHERLOCK: Fix display of journal --- engines/sherlock/journal.cpp | 12 ++++++++---- engines/sherlock/screen.cpp | 13 +++++++------ 2 files changed, 15 insertions(+), 10 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/journal.cpp b/engines/sherlock/journal.cpp index 2811c463a2..f9c2c54289 100644 --- a/engines/sherlock/journal.cpp +++ b/engines/sherlock/journal.cpp @@ -56,7 +56,7 @@ Journal::Journal(SherlockEngine *vm): _vm(vm) { _index = 0; _sub = 0; _up = _down = false; - _page = 0; + _page = 1; _converseNum = -1; // Load the journal directory and location names @@ -140,7 +140,6 @@ int Journal::loadJournalFile(bool alreadyLoaded) { Screen &screen = *_vm->_screen; Talk &talk = *_vm->_talk; JournalEntry &journalEntry = _journal[_index]; - Statement &statement = talk[journalEntry._statementNum]; Common::String dirFilename = _directory[journalEntry._converseNum]; bool replyOnly = journalEntry._replyOnly; @@ -184,6 +183,7 @@ int Journal::loadJournalFile(bool alreadyLoaded) { } // Start building journal string + Statement &statement = talk[journalEntry._statementNum]; Common::String journalString; if (newLocation != oldLocation) { @@ -260,7 +260,7 @@ int Journal::loadJournalFile(bool alreadyLoaded) { // If a reply isn't just being started, and we didn't just end // a comment (which would have added a line), add a carriage return if (!startOfReply && ((!commentJustPrinted && c == '{') || c == '}')) - journalString += '"'; + journalString += '\n'; startOfReply = false; // Handle setting or clearing comment state @@ -434,7 +434,7 @@ int Journal::loadJournalFile(bool alreadyLoaded) { } // Add in the line - _lines.push_back(Common::String(startP, endP)); + _lines.push_back(Common::String(journalString.c_str(), endP)); // Strip line off from string being processed journalString = *endP ? Common::String(endP + 1) : ""; @@ -461,6 +461,10 @@ void Journal::drawInterface() { bg->read(palette, PALETTE_SIZE); delete bg; + // Translate the palette for display + for (int idx = 0; idx < PALETTE_SIZE; ++idx) + palette[idx] = VGA_COLOR_TRANS(palette[idx]); + // Set the palette and print the title screen.setPalette(palette); screen.gPrint(Common::Point(111, 18), BUTTON_BOTTOM, "Watson's Journal"); diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp index 0eeddf2a5f..a30108118c 100644 --- a/engines/sherlock/screen.cpp +++ b/engines/sherlock/screen.cpp @@ -440,15 +440,16 @@ void Screen::buttonPrint(const Common::Point &pt, byte color, bool slamIt, if (slamIt) { print(Common::Point(xStart, pt.y + 1), COMMAND_HIGHLIGHTED, "%c", str[0]); print(Common::Point(xStart + charWidth(str[0]), pt.y + 1), - color, "%s", str.c_str() + 1); + COMMAND_FOREGROUND, str.c_str() + 1); } else { - print(Common::Point(xStart, pt.y), COMMAND_HIGHLIGHTED, "%c", str[0]); - print(Common::Point(xStart + charWidth(str[0]), pt.y), - color, "%s", str.c_str() + 1); + gPrint(Common::Point(xStart, pt.y), COMMAND_HIGHLIGHTED, "%c", str[0]); + gPrint(Common::Point(xStart + charWidth(str[0]), pt.y), + COMMAND_FOREGROUND, str.c_str() + 1); } + } else if (slamIt) { + print(Common::Point(xStart, pt.y + 1), color, str.c_str()); } else { - print(Common::Point(xStart, slamIt ? pt.y + 1 : pt.y), COMMAND_HIGHLIGHTED, - "%s", str.c_str()); + gPrint(Common::Point(xStart, pt.y), color, str.c_str()); } } -- cgit v1.2.3 From 3ef78ed7e1fccaf6f31f4e317196cace6af577a2 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 5 Apr 2015 22:15:46 -0500 Subject: SHERLOCK: Fix button text for inventory display --- engines/sherlock/inventory.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/inventory.cpp b/engines/sherlock/inventory.cpp index f7706c9d64..e58c4ddac6 100644 --- a/engines/sherlock/inventory.cpp +++ b/engines/sherlock/inventory.cpp @@ -314,16 +314,16 @@ void Inventory::invCommands(bool slamIt) { screen.buttonPrint(Common::Point(INVENTORY_POINTS[3][2], CONTROLS_Y1), _invMode == 3 ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND, false, "Give"); - screen.print(Common::Point(INVENTORY_POINTS[4][2], CONTROLS_Y1), + screen.gPrint(Common::Point(INVENTORY_POINTS[4][2], CONTROLS_Y1), _invIndex == 0 ? COMMAND_NULL : COMMAND_FOREGROUND, "^^"); - screen.print(Common::Point(INVENTORY_POINTS[5][2], CONTROLS_Y1), + screen.gPrint(Common::Point(INVENTORY_POINTS[5][2], CONTROLS_Y1), _invIndex == 0 ? COMMAND_NULL : COMMAND_FOREGROUND, "^"); - screen.print(Common::Point(INVENTORY_POINTS[6][2], CONTROLS_Y1), + screen.gPrint(Common::Point(INVENTORY_POINTS[6][2], CONTROLS_Y1), (_holdings - _invIndex < 7) ? COMMAND_NULL : COMMAND_FOREGROUND, "_"); - screen.print(Common::Point(INVENTORY_POINTS[7][2], CONTROLS_Y1), + screen.gPrint(Common::Point(INVENTORY_POINTS[7][2], CONTROLS_Y1), (_holdings - _invIndex < 7) ? COMMAND_NULL : COMMAND_FOREGROUND, "__"); } -- cgit v1.2.3 From f3251b5bb65bbd4ecee7a0700e1f876987cc7644 Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Mon, 6 Apr 2015 08:29:46 +0200 Subject: MADS: Allow quitting in Rex's copy protection dialog --- engines/mads/nebular/dialogs_nebular.cpp | 5 ++++- engines/mads/nebular/game_nebular.cpp | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/mads/nebular/dialogs_nebular.cpp b/engines/mads/nebular/dialogs_nebular.cpp index 9388aa2aa5..731e7e960d 100644 --- a/engines/mads/nebular/dialogs_nebular.cpp +++ b/engines/mads/nebular/dialogs_nebular.cpp @@ -439,10 +439,13 @@ void CopyProtectionDialog::show() { _vm->_screen.updateScreen(); while (!_vm->shouldQuit()) { - while (!_vm->_events->isKeyPressed()) { + while (!_vm->shouldQuit() && !_vm->_events->isKeyPressed()) { _vm->_events->delay(1); } + if (_vm->shouldQuit()) + break; + curKey = _vm->_events->getKey(); if (curKey.keycode == Common::KEYCODE_RETURN || curKey.keycode == Common::KEYCODE_KP_ENTER) diff --git a/engines/mads/nebular/game_nebular.cpp b/engines/mads/nebular/game_nebular.cpp index ec7c6678e8..c96f1c6df9 100644 --- a/engines/mads/nebular/game_nebular.cpp +++ b/engines/mads/nebular/game_nebular.cpp @@ -56,7 +56,7 @@ ProtectionResult GameNebular::checkCopyProtection() { correctAnswer = dlg->isCorrectAnswer(); delete dlg; - if (!correctAnswer) { + if (!correctAnswer && !_vm->shouldQuit()) { dlg = new CopyProtectionDialog(_vm, true); dlg->show(); correctAnswer = dlg->isCorrectAnswer(); -- cgit v1.2.3 From c8ac76b22bfd676bb72a850a141730022d6d476c Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Mon, 6 Apr 2015 10:42:16 +0200 Subject: MADS: Show first character of the Rex Nebular copy protection word --- engines/mads/nebular/dialogs_nebular.cpp | 35 +++++++++++++++++++------------- 1 file changed, 21 insertions(+), 14 deletions(-) (limited to 'engines') diff --git a/engines/mads/nebular/dialogs_nebular.cpp b/engines/mads/nebular/dialogs_nebular.cpp index 731e7e960d..10715797ed 100644 --- a/engines/mads/nebular/dialogs_nebular.cpp +++ b/engines/mads/nebular/dialogs_nebular.cpp @@ -438,24 +438,31 @@ void CopyProtectionDialog::show() { _vm->_screen.copyRectToScreen(inputArea); _vm->_screen.updateScreen(); + bool firstTime = true; + while (!_vm->shouldQuit()) { - while (!_vm->shouldQuit() && !_vm->_events->isKeyPressed()) { - _vm->_events->delay(1); - } + if (!firstTime) { + while (!_vm->shouldQuit() && !_vm->_events->isKeyPressed()) { + _vm->_events->delay(1); + } - if (_vm->shouldQuit()) - break; + if (_vm->shouldQuit()) + break; - curKey = _vm->_events->getKey(); - - if (curKey.keycode == Common::KEYCODE_RETURN || curKey.keycode == Common::KEYCODE_KP_ENTER) - break; - else if (curKey.keycode == Common::KEYCODE_BACKSPACE) - _textInput.deleteLastChar(); - else if (_textInput.size() < 14) - _textInput += curKey.ascii; + curKey = _vm->_events->getKey(); + + if (curKey.keycode == Common::KEYCODE_RETURN || curKey.keycode == Common::KEYCODE_KP_ENTER) + break; + else if (curKey.keycode == Common::KEYCODE_BACKSPACE) + _textInput.deleteLastChar(); + else if (_textInput.size() < 14) + _textInput += curKey.ascii; - _vm->_events->_pendingKeys.clear(); + _vm->_events->_pendingKeys.clear(); + } else { + firstTime = false; + _textInput = _hogEntry._word[0]; + } _vm->_screen.copyFrom(origInput, Common::Rect(0, 0, inputArea.width(), inputArea.height()), Common::Point(inputArea.left, inputArea.top)); _font->writeString(&_vm->_screen, _textInput, -- cgit v1.2.3 From 07c7f5e31a1f1952ebe583a138352e13e45e0c66 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 7 Apr 2015 20:09:00 -0500 Subject: MADS: Fix crash leaving scene after shooting monkey --- engines/mads/sprites.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mads/sprites.cpp b/engines/mads/sprites.cpp index 67d5e20fe5..bc36b5575a 100644 --- a/engines/mads/sprites.cpp +++ b/engines/mads/sprites.cpp @@ -399,7 +399,7 @@ void SpriteSets::remove(int idx) { if (idx == SPRITE_SLOTS_MAX_SIZE) { delete _uiSprites; _uiSprites = nullptr; - } else if (idx >= 0) { + } else if (idx >= 0 && idx < (int)size()) { delete (*this)[idx]; if (idx < ((int)size() - 1)) { -- cgit v1.2.3 From 49fd689c07be266cf0ad40d3510ac875ac81174c Mon Sep 17 00:00:00 2001 From: Strangerke Date: Wed, 8 Apr 2015 22:55:33 +0200 Subject: SHERLOCK: Implement showAlleyCutscene --- engines/sherlock/scalpel/scalpel.cpp | 38 ++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp index 0432dc2278..954ea12aec 100644 --- a/engines/sherlock/scalpel/scalpel.cpp +++ b/engines/sherlock/scalpel/scalpel.cpp @@ -310,8 +310,42 @@ bool ScalpelEngine::showCityCutscene() { } bool ScalpelEngine::showAlleyCutscene() { - // TODO - return true; + byte palette[PALETTE_SIZE]; + _sound->playMusic("prolog2.mus"); + + _titleOverride = "TITLE.LIB"; + _soundOverride = "TITLE.SND"; + + bool finished = _animation->playPrologue("27PRO1", 1, 3, true, 2); + if (finished) + _animation->playPrologue("27PRO2", 1, 0, false, 2); + + if (finished) { + ImageFile screamImages("SCREAM.LBV", false); + _screen->_backBuffer1.transBlitFrom(screamImages[0], Common::Point(0, 0)); + _screen->_backBuffer2.blitFrom(_screen->_backBuffer1); + finished = _events->delay(6000); + } + + if (finished) + _animation->playPrologue("27PRO3", 1, 0, true, 2); + + if(finished) { + _screen->getPalette(palette); + _screen->fadeToBlack(2); + } + + if(finished) { + ImageFile titleImages("title3.vgs", true); + // "Early the following morning on Baker Street..." + _screen->_backBuffer1.transBlitFrom(titleImages[0], Common::Point(35, 51), false, 0); + _screen->fadeIn(palette, 3); + finished = _events->delay(1000); + } + + _titleOverride = ""; + _soundOverride = ""; + return finished; } bool ScalpelEngine::showStreetCutscene() { -- cgit v1.2.3 From d45d1672137843d028c4ddf63ccf9b62d5d72976 Mon Sep 17 00:00:00 2001 From: Strangerke Date: Thu, 9 Apr 2015 00:12:18 +0200 Subject: SHERLOCK: Fix regression in image loading --- engines/sherlock/resources.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/resources.cpp b/engines/sherlock/resources.cpp index 0d66646286..262832c3c3 100644 --- a/engines/sherlock/resources.cpp +++ b/engines/sherlock/resources.cpp @@ -298,8 +298,8 @@ void ImageFile::load(Common::SeekableReadStream &stream, bool skipPalette) { frame._width = stream.readUint16LE() + 1; frame._height = stream.readUint16LE() + 1; frame._paletteBase = stream.readByte(); - frame._rleEncoded = stream.readByte() == 1; - frame._offset.x = stream.readByte(); + frame._offset.x = stream.readUint16LE(); + frame._rleEncoded = ((frame._offset.x & 0xFF) == 1); frame._offset.y = stream.readByte(); frame._rleEncoded = !skipPalette && frame._rleEncoded; -- cgit v1.2.3 From 47afe424c194d5d4fd1797948b53f999473fe922 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 8 Apr 2015 21:28:24 -0500 Subject: MADS: Don't show protection dialog when exiting directly from main menu --- engines/mads/nebular/game_nebular.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'engines') diff --git a/engines/mads/nebular/game_nebular.cpp b/engines/mads/nebular/game_nebular.cpp index c96f1c6df9..e9a3d0b716 100644 --- a/engines/mads/nebular/game_nebular.cpp +++ b/engines/mads/nebular/game_nebular.cpp @@ -107,6 +107,9 @@ void GameNebular::startGame() { _vm->_dialogs->showDialog(); } while (!_vm->shouldQuit() && _vm->_dialogs->_pendingDialog != DIALOG_NONE); + if (_vm->shouldQuit()) + return; + _priorSectionNumber = 0; _priorSectionNumber = -1; _scene._priorSceneId = 0; -- cgit v1.2.3 From ec999f1cb74dff8c42c69898bb6cbc3823b169dd Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 9 Apr 2015 13:44:39 +0300 Subject: MADS: Plug some memory leaks Surfaces should be freed (to free their inner allocated surface buffers) before being deleted --- engines/mads/game.cpp | 1 + engines/mads/nebular/dialogs_nebular.cpp | 4 +++- engines/mads/scene_data.cpp | 2 ++ engines/mads/sprites.cpp | 4 +++- engines/mads/user_interface.cpp | 1 + 5 files changed, 10 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/mads/game.cpp b/engines/mads/game.cpp index 72d7988c05..3d1c194612 100644 --- a/engines/mads/game.cpp +++ b/engines/mads/game.cpp @@ -100,6 +100,7 @@ Game::~Game() { } delete _saveFile; + _surface->free(); delete _surface; delete _sectionHandler; } diff --git a/engines/mads/nebular/dialogs_nebular.cpp b/engines/mads/nebular/dialogs_nebular.cpp index 10715797ed..5b9942db07 100644 --- a/engines/mads/nebular/dialogs_nebular.cpp +++ b/engines/mads/nebular/dialogs_nebular.cpp @@ -430,7 +430,7 @@ void CopyProtectionDialog::show() { draw(); Common::KeyState curKey; - Common::Rect inputArea(110, 165, 210, 175); + const Common::Rect inputArea(110, 165, 210, 175); MSurface *origInput = new MSurface(inputArea.width(), inputArea.height()); _vm->_screen.frameRect(inputArea, TEXTDIALOG_BLACK); _vm->_screen.copyTo(origInput, inputArea, Common::Point(0, 0)); @@ -471,6 +471,7 @@ void CopyProtectionDialog::show() { _vm->_screen.updateScreen(); } + origInput->free(); delete origInput; } @@ -592,6 +593,7 @@ void PictureDialog::save() { void PictureDialog::restore() { if (_savedSurface) { _savedSurface->copyTo(&_vm->_screen); + _savedSurface->free(); delete _savedSurface; _savedSurface = nullptr; diff --git a/engines/mads/scene_data.cpp b/engines/mads/scene_data.cpp index d0e96be1d7..e594406447 100644 --- a/engines/mads/scene_data.cpp +++ b/engines/mads/scene_data.cpp @@ -451,6 +451,8 @@ void SceneInfo::loadMadsV2Background(int sceneId, const Common::String &resName, fab.decompress(compressedTileData, compressedTileDataSize, (byte*)newTile->getPixels(), tileWidth * tileHeight); tileSet.push_back(TileSetList::value_type(newTile)); + newTile->free(); + delete newTile; delete[] compressedTileData; } diff --git a/engines/mads/sprites.cpp b/engines/mads/sprites.cpp index bc36b5575a..f15d6456d3 100644 --- a/engines/mads/sprites.cpp +++ b/engines/mads/sprites.cpp @@ -347,8 +347,10 @@ void SpriteSlots::drawSprites(MSurface *s) { spr->copyTo(s, Common::Point(xp, yp), sprite->getTransparencyIndex()); // Free sprite if it was a flipped one - if (flipped) + if (flipped) { + spr->free(); delete spr; + } } } } diff --git a/engines/mads/user_interface.cpp b/engines/mads/user_interface.cpp index 93a555d9c7..1e5a1d80d2 100644 --- a/engines/mads/user_interface.cpp +++ b/engines/mads/user_interface.cpp @@ -164,6 +164,7 @@ void UISlots::draw(bool updateFlag, bool delFlag) { MSurface *spr = sprite->flipHorizontal(); userInterface.mergeFrom(spr, spr->getBounds(), slot._position, sprite->getTransparencyIndex()); + spr->free(); delete spr; } else { userInterface.mergeFrom(sprite, sprite->getBounds(), slot._position, -- cgit v1.2.3 From ec03857d7dd7614675b41cfc412be20b733b469a Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 9 Apr 2015 14:08:48 +0300 Subject: MADS: Fix a regression in V2 games --- engines/mads/scene_data.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/mads/scene_data.cpp b/engines/mads/scene_data.cpp index e594406447..e48bcd8c6f 100644 --- a/engines/mads/scene_data.cpp +++ b/engines/mads/scene_data.cpp @@ -451,8 +451,6 @@ void SceneInfo::loadMadsV2Background(int sceneId, const Common::String &resName, fab.decompress(compressedTileData, compressedTileDataSize, (byte*)newTile->getPixels(), tileWidth * tileHeight); tileSet.push_back(TileSetList::value_type(newTile)); - newTile->free(); - delete newTile; delete[] compressedTileData; } @@ -471,6 +469,7 @@ void SceneInfo::loadMadsV2Background(int sceneId, const Common::String &resName, for (int i = 0; i < tileIndex; i++) ++tile; ((*tile).get())->copyTo(&bgSurface, Common::Point(x * tileWidth, y * tileHeight)); + ((*tile).get())->free(); } } tileSet.clear(); -- cgit v1.2.3 From 96e04ab797253bbe853f172ea1d734ebe812d419 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 10 Apr 2015 23:35:26 -0500 Subject: SHERLOCK: Implemented doScript and support methods --- engines/sherlock/animation.cpp | 2 +- engines/sherlock/events.cpp | 8 + engines/sherlock/events.h | 2 + engines/sherlock/inventory.cpp | 112 +++++ engines/sherlock/inventory.h | 9 + engines/sherlock/people.cpp | 2 + engines/sherlock/people.h | 2 + engines/sherlock/scene.cpp | 16 +- engines/sherlock/scripts.cpp | 11 +- engines/sherlock/scripts.h | 6 +- engines/sherlock/sherlock.cpp | 6 +- engines/sherlock/sound.cpp | 7 +- engines/sherlock/sound.h | 4 +- engines/sherlock/talk.cpp | 833 +++++++++++++++++++++++++++++++++++- engines/sherlock/talk.h | 31 +- engines/sherlock/user_interface.cpp | 10 +- 16 files changed, 1002 insertions(+), 59 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/animation.cpp b/engines/sherlock/animation.cpp index e1687b5238..4674151ec7 100644 --- a/engines/sherlock/animation.cpp +++ b/engines/sherlock/animation.cpp @@ -144,7 +144,7 @@ bool Animation::playPrologue(const Common::String &filename, int minDelay, int f Common::String::format("%s%01d", baseName.c_str(), soundNumber) : Common::String::format("%s%02d", baseName.c_str(), soundNumber); - if (sound._voicesOn) + if (sound._voices) sound.playSound(fname); } diff --git a/engines/sherlock/events.cpp b/engines/sherlock/events.cpp index d147fe1f4c..67d09e52b2 100644 --- a/engines/sherlock/events.cpp +++ b/engines/sherlock/events.cpp @@ -100,6 +100,14 @@ bool Events::isCursorVisible() const { return CursorMan.isVisible(); } +/** + * Move the mouse + */ +void Events::moveMouse(const Common::Point &pt) { + g_system->warpMouse(pt.x, pt.y); +} + + /** * Check for any pending events */ diff --git a/engines/sherlock/events.h b/engines/sherlock/events.h index c3bdaf5a93..71f7623002 100644 --- a/engines/sherlock/events.h +++ b/engines/sherlock/events.h @@ -72,6 +72,8 @@ public: bool isCursorVisible() const; + void moveMouse(const Common::Point &pt); + void pollEvents(); void pollEventsAndWait(); diff --git a/engines/sherlock/inventory.cpp b/engines/sherlock/inventory.cpp index e58c4ddac6..0ea85f32fc 100644 --- a/engines/sherlock/inventory.cpp +++ b/engines/sherlock/inventory.cpp @@ -366,4 +366,116 @@ void Inventory::doInvJF() { } } +/** + * Adds a shape from the scene to the player's inventory + */ +int Inventory::putNameInInventory(const Common::String &name) { + Scene &scene = *_vm->_scene; + int matches = 0; + + for (uint idx = 0; idx < scene._bgShapes.size(); ++idx) { + Object &o = scene._bgShapes[idx]; + if (scumm_stricmp(name.c_str(), o._name.c_str()) == 0 && o._type != INVALID) { + putItemInInventory(o); + ++matches; + } + } + + return matches; +} + +/** + * Moves a specified item into the player's inventory If the item has a *PICKUP* use action, + * then the item in the use action are added to the inventory. + */ +int Inventory::putItemInInventory(Object &obj) { + Scene &scene = *_vm->_scene; + int matches = 0; + bool pickupFound = false; + + if (obj._pickupFlag) + _vm->setFlags(obj._pickupFlag); + + for (int useNum = 0; useNum < 4; ++useNum) { + if (scumm_stricmp(obj._use[useNum]._target.c_str(), "*PICKUP*") == 0) { + pickupFound = true; + + for (int namesNum = 0; namesNum < 4; ++namesNum) { + for (uint bgNum = 0; bgNum < scene._bgShapes.size(); ++bgNum) { + Object &bgObj = scene._bgShapes[bgNum]; + if (scumm_stricmp(obj._use[useNum]._names[namesNum].c_str(), bgObj._name.c_str()) == 0) { + copyToInventory(bgObj); + if (bgObj._pickupFlag) + _vm->setFlags(bgObj._pickupFlag); + + if (bgObj._type == ACTIVE_BG_SHAPE || bgObj._type == NO_SHAPE || bgObj._type == HIDE_SHAPE) { + if (bgObj._imageFrame == nullptr || bgObj._frameNumber < 0) + // No shape to erase, so flag as hidden + bgObj._type = INVALID; + else + bgObj._type = REMOVE; + } else if (bgObj._type == HIDDEN) { + bgObj._type = INVALID; + } + + ++matches; + } + } + } + } + } + + if (!pickupFound) { + // No pickup item found, so add the passed item + copyToInventory(obj); + matches = 0; + } + + if (matches == 0) { + if (!pickupFound) + matches = 1; + + if (obj._type == ACTIVE_BG_SHAPE || obj._type == NO_SHAPE || obj._type == HIDE_SHAPE) { + if (obj._imageFrame == nullptr || obj._frameNumber < 0) + // No shape to erase, so flag as hidden + obj._type = INVALID; + else + obj._type = REMOVE; + } else if (obj._type == HIDDEN) { + obj._type = INVALID; + } + } + + return matches; +} + +/** + * Copy the passed object into the inventory + */ +void Inventory::copyToInventory(Object &obj) { + // TODO +} + +/** + * Deletes a specified item from the player's inventory + */ +int Inventory::deleteItemFromInventory(const Common::String &name) { + int invNum = -1; + + for (int idx = 0; idx < (int)size() && invNum == -1; ++idx) { + if (scumm_stricmp(name.c_str(), (*this)[idx]._name.c_str()) == 0) + invNum = idx; + } + + if (invNum == -1) + // Item not present + return 0; + + // Item found, so delete it + remove_at(invNum); + --_holdings; + + return 1; +} + } // End of namespace Sherlock diff --git a/engines/sherlock/inventory.h b/engines/sherlock/inventory.h index 55abc4c960..722692a3b2 100644 --- a/engines/sherlock/inventory.h +++ b/engines/sherlock/inventory.h @@ -26,6 +26,7 @@ #include "common/scummsys.h" #include "common/array.h" #include "common/str-array.h" +#include "sherlock/objects.h" #include "sherlock/resources.h" namespace Sherlock { @@ -59,6 +60,10 @@ struct InventoryItem { class Inventory : public Common::Array { private: SherlockEngine *_vm; + + int putItemInInventory(Object &obj); + + void copyToInventory(Object &obj); public: ImageFile *_invShapes[MAX_VISIBLE_INVENTORY]; Common::StringArray _names; @@ -90,6 +95,10 @@ public: void highlight(int index, byte color); void doInvJF(); + + int putNameInInventory(const Common::String &name); + + int deleteItemFromInventory(const Common::String &name); }; } // End of namespace Sherlock diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp index 3da35f2fec..9319fbb79d 100644 --- a/engines/sherlock/people.cpp +++ b/engines/sherlock/people.cpp @@ -61,6 +61,8 @@ People::People(SherlockEngine *vm) : _vm(vm), _player(_data[0]) { _clearingThePortrait = false; _srcZone = _destZone = 0; _talkPics = nullptr; + _portraitSide = 0; + _speakerFlip = false; } People::~People() { diff --git a/engines/sherlock/people.h b/engines/sherlock/people.h index a1fad019c8..1a846dded1 100644 --- a/engines/sherlock/people.h +++ b/engines/sherlock/people.h @@ -77,6 +77,8 @@ public: Object _portrait; bool _clearingThePortrait; bool _allowWalkAbort; + int _portraitSide; + bool _speakerFlip; public: People(SherlockEngine *vm); ~People(); diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 7c66a1dc62..3d5f566164 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -89,7 +89,8 @@ Scene::Scene(SherlockEngine *vm): _vm(vm) { _currentScene = -1; _goToScene = -1; _changes = false; - _charPoint = _oldCharPoint = 0; + _charPoint = 0; + _oldCharPoint = 39; _keyboardInput = 0; _walkedInScene = false; _ongoingCans = 0; @@ -118,7 +119,7 @@ void Scene::selectScene() { Events &events = *_vm->_events; People &people = *_vm->_people; Screen &screen = *_vm->_screen; - Scripts &scripts = *_vm->_scripts; + Talk &talk = *_vm->_talk; UserInterface &ui = *_vm->_ui; // Reset fields @@ -150,8 +151,8 @@ void Scene::selectScene() { // If there were any scripst waiting to be run, but were interrupt by a running // canimation (probably the last scene's exit canim), clear the _scriptMoreFlag - if (scripts._scriptMoreFlag == 3) - scripts._scriptMoreFlag = 0; + if (talk._scriptMoreFlag == 3) + talk._scriptMoreFlag = 0; } /** @@ -1053,7 +1054,6 @@ void Scene::doBgAnim() { Inventory &inv = *_vm->_inventory; People &people = *_vm->_people; Screen &screen = *_vm->_screen; - Scripts &scripts = *_vm->_scripts; Sound &sound = *_vm->_sound; Talk &talk = *_vm->_talk; UserInterface &ui = *_vm->_ui; @@ -1359,10 +1359,10 @@ void Scene::doBgAnim() { // Check if the method was called for calling a portrait, and a talk was // interrupting it. This talk file would not have been executed at the time, // since we needed to finish the 'doBgAnim' to finish clearing the portrait - if (people._clearingThePortrait && scripts._scriptMoreFlag == 3) { + if (people._clearingThePortrait && talk._scriptMoreFlag == 3) { // Reset the flags and call to talk - people._clearingThePortrait = scripts._scriptMoreFlag = 0; - talk.talkTo(scripts._scriptName); + people._clearingThePortrait = talk._scriptMoreFlag = 0; + talk.talkTo(talk._scriptName); } } diff --git a/engines/sherlock/scripts.cpp b/engines/sherlock/scripts.cpp index d337030bae..02dcfa6f0b 100644 --- a/engines/sherlock/scripts.cpp +++ b/engines/sherlock/scripts.cpp @@ -26,21 +26,16 @@ namespace Sherlock { Scripts::Scripts(SherlockEngine *vm): _vm(vm) { - _scriptMoreFlag = 0; - _scriptSaveIndex = 0; - _scriptSelect = 0; -} -void Scripts::doScript(const Common::String &str) { - // TODO } void Scripts::popStack() { + /* ScriptEntry script = _scriptStack.pop(); _scriptName = script._name; - _scriptSaveIndex = script._index; +// _scriptSaveIndex = script._index; _scriptSelect = script._select; - _scriptMoreFlag = true; + */ } diff --git a/engines/sherlock/scripts.h b/engines/sherlock/scripts.h index 6765687bcf..beea726c8d 100644 --- a/engines/sherlock/scripts.h +++ b/engines/sherlock/scripts.h @@ -40,11 +40,7 @@ class Scripts { private: SherlockEngine *_vm; public: - Common::Stack _scriptStack; - int _scriptMoreFlag; - Common::String _scriptName; - int _scriptSaveIndex; - int _scriptSelect; + public: Scripts(SherlockEngine *vm); diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index 20a805594e..2a1b456b76 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -122,10 +122,10 @@ void SherlockEngine::sceneLoop() { while (!shouldQuit() && _scene->_goToScene == -1) { // See if a script needs to be completed from either a goto room code, // or a script that was interrupted by another script - if (_scripts->_scriptMoreFlag == 1 || _scripts->_scriptMoreFlag == 3) - _talk->talkTo(_scripts->_scriptName); + if (_talk->_scriptMoreFlag == 1 || _talk->_scriptMoreFlag == 3) + _talk->talkTo(_talk->_scriptName); else - _scripts->_scriptMoreFlag = 0; + _talk->_scriptMoreFlag = 0; // Handle any input from the keyboard or mouse handleInput(); diff --git a/engines/sherlock/sound.cpp b/engines/sherlock/sound.cpp index 5e7df5607f..771d5db9d5 100644 --- a/engines/sherlock/sound.cpp +++ b/engines/sherlock/sound.cpp @@ -27,7 +27,8 @@ namespace Sherlock { Sound::Sound(SherlockEngine *vm): _vm(vm) { _soundOn = true; _musicOn = true; - _voicesOn = true; + _speechOn = true; + _voices = 0; _playingEpilogue = false; _music = false; _digitized = false; @@ -89,5 +90,9 @@ void Sound::freeSong() { // TODO } +void Sound::stopSndFuncPtr(int v1, int v2) { + // TODO +} + } // End of namespace Sherlock diff --git a/engines/sherlock/sound.h b/engines/sherlock/sound.h index 74e8db3611..22d5a5c221 100644 --- a/engines/sherlock/sound.h +++ b/engines/sherlock/sound.h @@ -40,7 +40,8 @@ private: public: bool _soundOn; bool _musicOn; - bool _voicesOn; + bool _speechOn; + int _voices; bool _playingEpilogue; bool _music; bool _digitized; @@ -64,6 +65,7 @@ public: void playMusic(const Common::String &name); void stopMusic(); + void stopSndFuncPtr(int v1, int v2); }; } // End of namespace Sherlock diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index d284ace8b8..193c0f9a19 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -26,7 +26,42 @@ namespace Sherlock { -#define SFX_COMMAND 140 +enum { + SWITCH_SPEAKER = 128, + RUN_CANIMATION = 129, + ASSIGN_PORTRAIT_LOCATION = 130, + PAUSE = 131, + REMOVE_PORTRAIT = 132, + CLEAR_WINDOW = 133, + ADJUST_OBJ_SEQUENCE = 134, + WALK_TO_COORDS = 135, + PAUSE_WITHOUT_CONTROL = 136, + BANISH_WINDOW = 137, + SUMMON_WINDOW = 138, + SET_FLAG = 139, + SFX_COMMAND = 140, + TOGGLE_OBJECT = 141, + STEALTH_MODE_ACTIVE = 142, + IF_STATEMENT = 143, + ELSE_STATEMENT = 144, + END_IF_STATEMENT = 145, + STEALTH_MODE_DEACTIVATE = 146, + TURN_HOLMES_OFF = 147, + TURN_HOLMES_ON = 148, + GOTO_SCENE = 149, + PLAY_PROLOGUE = 150, + ADD_ITEM_TO_INVENTORY = 151, + SET_OBJECT = 152, + CALL_TALK_FILE = 153, + MOVE_MOUSE = 154, + DISPLAY_INFO_LINE = 155, + CLEAR_INFO_LINE = 156, + WALK_TO_CANIMATION = 157, + REMOVE_ITEM_FROM_INVENTORY = 158, + ENABLE_END_KEY = 159, + DISABLE_END_KEY = 160, + COMMAND_161 = 161 +}; /*----------------------------------------------------------------*/ @@ -99,6 +134,9 @@ Talk::Talk(SherlockEngine *vm): _vm(vm) { _talkStealth = 0; _talkToFlag = -1; _moreTalkDown = _moreTalkUp = false; + _scriptMoreFlag = 1; + _scriptSaveIndex = -1; + _scriptCurrentIndex = -1; } void Talk::setSequences(const byte *talkSequences, const byte *stillSequences, int maxPeople) { @@ -136,13 +174,13 @@ void Talk::talkTo(const Common::String &filename) { // save the filename for later executing when the canimation is done if (scene._ongoingCans || people._clearingThePortrait) { // Make sure we're not in the middle of a script - if (!scripts._scriptMoreFlag) { - scripts._scriptName = filename; - scripts._scriptSaveIndex = 0; + if (!_scriptMoreFlag) { + _scriptName = filename; + _scriptSaveIndex = 0; // Flag the selection, since we don't yet know which statement yet - scripts._scriptSelect = 100; - scripts._scriptMoreFlag = 3; + _scriptSelect = 100; + _scriptMoreFlag = 3; } return; @@ -172,7 +210,7 @@ void Talk::talkTo(const Common::String &filename) { // If any sequences have changed in the prior talk file, restore them if (_savedSequences.size() > 0) { for (uint idx = 0; idx < _savedSequences.size(); ++idx) { - SavedSequence &ss = _savedSequences[idx]; + SequenceEntry &ss = _savedSequences[idx]; for (uint idx2 = 0; idx2 < _savedSequences.size(); ++idx2) scene._bgShapes[ss._objNum]._sequences[idx2] = ss._sequences[idx2]; @@ -181,7 +219,7 @@ void Talk::talkTo(const Common::String &filename) { } } - while (!_sequenceStack.empty()) + while (!_scriptStack.empty()) pullSequence(); // Restore any pressed button @@ -276,7 +314,7 @@ void Talk::talkTo(const Common::String &filename) { select = _talkIndex = idx; } - if (scripts._scriptMoreFlag && _scriptSelect != 0) + if (_scriptMoreFlag && _scriptSelect != 0) select = _scriptSelect; if (select == -1) @@ -288,7 +326,7 @@ void Talk::talkTo(const Common::String &filename) { _talkHistory[_converseNum][select] = true; // Check if the talk file is meant to be a non-seen comment - if (filename[7] != '*') { + if (filename.size() < 8 || filename[7] != '*') { // Should we start in stealth mode? if (_statements[select]._statement.hasPrefix("^")) { _talkStealth = 2; @@ -305,13 +343,13 @@ void Talk::talkTo(const Common::String &filename) { // Handle replies until there's no further linked file, // or the link file isn't a reply first cnversation - for (;;) { + while (!_vm->shouldQuit()) { clearSequences(); _scriptSelect = select; _speaker = _talkTo; Statement &statement = _statements[select]; - scripts.doScript(_statements[select]._reply); + doScript(_statements[select]._reply); if (_talkToAbort) return; @@ -327,7 +365,7 @@ void Talk::talkTo(const Common::String &filename) { } // Check for a linked file - if (!statement._linkFile.empty() && !scripts._scriptMoreFlag) { + if (!statement._linkFile.empty() && !_scriptMoreFlag) { freeTalkVars(); loadTalkFile(statement._linkFile); @@ -422,7 +460,7 @@ void Talk::talkTo(const Common::String &filename) { // If a script was added to the script stack, restore state so that the // previous script can continue - if (!scripts._scriptStack.empty()) { + if (!_scriptStack.empty()) { scripts.popStack(); } @@ -547,7 +585,7 @@ void Talk::loadTalkFile(const Common::String &filename) { // Check for an existing person being talked to _talkTo = -1; for (int idx = 0; idx < MAX_PEOPLE; ++idx) { - if (scumm_strnicmp(filename.c_str(), people[(PeopleId)idx]._portrait.c_str(), 4)) { + if (!scumm_strnicmp(filename.c_str(), people[(PeopleId)idx]._portrait.c_str(), 4)) { _talkTo = idx; break; } @@ -568,7 +606,7 @@ void Talk::loadTalkFile(const Common::String &filename) { delete talkStream; - if (!sound._voicesOn) + if (!sound._voices) stripVoiceCommands(); setTalkMap(); } @@ -833,7 +871,7 @@ int Talk::talkLine(int lineNum, int stateNum, byte color, int lineY, bool slamIt * Clears the stack of pending object sequences associated with speakers in the scene */ void Talk::clearSequences() { - _sequenceStack.clear(); + _scriptStack.clear(); } /** @@ -843,7 +881,7 @@ void Talk::clearSequences() { void Talk::pullSequence() { Scene &scene = *_vm->_scene; - SequenceEntry seq = _sequenceStack.pop(); + SequenceEntry seq = _scriptStack.pop(); if (seq._objNum != -1) { Object &obj = scene._bgShapes[seq._objNum]; @@ -871,7 +909,7 @@ void Talk::pushSequence(int speaker) { if (speaker == -1) return; - SequenceEntry seqEntry; + ScriptStackEntry seqEntry; if (!speaker) { seqEntry._objNum = -1; } else { @@ -885,9 +923,13 @@ void Talk::pushSequence(int speaker) { seqEntry._seqTo = obj._seqTo; } - _sequenceStack.push(seqEntry); - if (_sequenceStack.size() >= 5) - error("sequence stack overflow"); + _scriptStack.push(seqEntry); + if (_scriptStack.size() >= 5) + error("script stack overflow"); +} + +void Talk::setSequence(int speaker) { + // TODO } /** @@ -923,4 +965,751 @@ void Talk::setStillSeq(int speaker) { } } +/** + * Parses a reply for control codes and display text. The found text is printed within + * the text window, handles delays, animations, and animating portraits. + */ +void Talk::doScript(const Common::String &script) { + Animation &anim = *_vm->_animation; + Events &events = *_vm->_events; + Inventory &inv = *_vm->_inventory; + People &people = *_vm->_people; + Scene &scene = *_vm->_scene; + Screen &screen = *_vm->_screen; + Sound &sound = *_vm->_sound; + UserInterface &ui = *_vm->_ui; + int wait = 0; + bool pauseFlag = false; + bool endStr = false; + int yp = CONTROLS_Y + 12; + int charCount = 0; + int line = 0; + bool noTextYet = true; + bool openTalkWindow = false; + int obj; + int seqCount; + + _saveSeqNum = 0; + + const char *str = script.c_str(); + if (_scriptMoreFlag) { + _scriptMoreFlag = 0; + str = script.c_str() + _scriptSaveIndex; + } + + // Check if the script begins with a Stealh Mode Active command + if (str[0] == STEALTH_MODE_ACTIVE || _talkStealth) { + _talkStealth = 2; + _speaker |= 128; + } else { + pushSequence(_speaker); + ui.clearWindow(); + + // Need to switch speakers? + if (str[0] == SWITCH_SPEAKER) { + _speaker = str[1] - 1; + str += 2; + pullSequence(); + pushSequence(_speaker); + setSequence(_speaker); + } + else { + setSequence(_speaker); + } + + // Assign portrait location? + if (str[0] == ASSIGN_PORTRAIT_LOCATION) { + switch (str[1] & 15) { + case 1: + people._portraitSide = 20; + break; + case 2: + people._portraitSide = 220; + break; + case 3: + people._portraitSide = 120; + break; + default: + break; + + } + + if (str[1] > 15) + people._speakerFlip = true; + str += 2; + } + + // Remove portrait? + if (str[0] == REMOVE_PORTRAIT) { + _speaker = 255; + } + else { + // Nope, so set the first speaker + setTalking(_speaker); + } + } + + do { + Common::String tempString; + wait = 0; + + if (!str[0]) { + endStr = true; + } else if (str[0] == '{') { + // Start of comment, so skip over it + while (*str++ != '}') + ; + } else if (str[0] >= 128) { + // Handle control code + switch (str[0]) { + case SWITCH_SPEAKER: + // Save the current point in the script, since it might be intterupted by + // doing bg anims in the next call, so we need to know where to return to + _scriptCurrentIndex = str - script.c_str(); + + if (!(_speaker & 128)) + clearTalking(); + if (_talkToAbort) + return; + + ui.clearWindow(); + yp = CONTROLS_Y + 12; + charCount = line = 0; + + _speaker = *++str - 1; + setTalking(_speaker); + pullSequence(); + pushSequence(_speaker); + setSequence(_speaker); + break; + + case RUN_CANIMATION: + // Save the current point in the script, since it might be intterupted by + // doing bg anims in the next call, so we need to know where to return to + _scriptCurrentIndex = str - script.c_str(); + scene.startCAnim((str[0] - 1) & 127, 1 + (str[0] & 128)); + if (_talkToAbort) + return; + + // Check if next character is changing side or changing portrait + if (charCount && (str[1] == SWITCH_SPEAKER || str[1] == ASSIGN_PORTRAIT_LOCATION)) + wait = 1; + break; + + case ASSIGN_PORTRAIT_LOCATION: + ++str; + switch (str[0] & 15) { + case 1: + people._portraitSide = 20; + break; + case 2: + people._portraitSide = 220; + break; + case 3: + people._portraitSide = 120; + break; + default: + break; + } + + if (str[0] > 15) + people._speakerFlip = true; + break; + + case PAUSE: + // Pause + charCount = *++str; + wait = pauseFlag = true; + break; + + case REMOVE_PORTRAIT: + // Save the current point in the script, since it might be intterupted by + // doing bg anims in the next call, so we need to know where to return to + _scriptCurrentIndex = str - script.c_str(); + + if (_speaker < 128) + clearTalking(); + pullSequence(); + if (_talkToAbort) + return; + + _speaker |= 128; + break; + + case CLEAR_WINDOW: + ui.clearWindow(); + yp = CONTROLS_Y + 12; + charCount = line = 0; + break; + + case ADJUST_OBJ_SEQUENCE: + // Get the name of the object to adjust + ++str; + for (int idx = 0; idx < (str[0] & 127); ++idx) + tempString += str[idx + 2]; + + // Scan for object + obj = -1; + for (uint idx = 0; idx < scene._bgShapes.size(); ++idx) { + if (scumm_stricmp(tempString.c_str(), scene._bgShapes[idx]._name.c_str()) == 0) + obj = idx; + } + if (obj == -1) + error("Could not find object %s to change", tempString.c_str()); + + // Should the script be overwritten? + if (str[0] > 128) { + // Save the current sequence + _savedSequences.push(SequenceEntry()); + SequenceEntry &seqEntry = _savedSequences.top(); + seqEntry._objNum = obj; + seqEntry._seqTo = scene._bgShapes[obj]._seqTo; + for (uint idx = 0; idx < scene._bgShapes[obj]._seqSize; ++idx) + seqEntry._sequences.push_back(scene._bgShapes[obj]._sequences[idx]); + } + + // Get number of bytes to change + seqCount = str[1]; + str += (str[0] & 127) + 2; + + // Copy in the new sequence + for (int idx = 0; idx < seqCount; ++idx, ++str) + scene._bgShapes[obj]._sequences[idx] = str[0] - 1; + + // Reset object back to beginning of new sequence + scene._bgShapes[obj]._frameNumber = 0; + continue; + + case WALK_TO_COORDS: + // Save the current point in the script, since it might be intterupted by + // doing bg anims in the next call, so we need to know where to return to + _scriptCurrentIndex = str - script.c_str(); + + people.walkToCoords(Common::Point(((str[0] - 1) * 256 + str[1] - 1) * 100, str[2] * 100), str[3] - 1); + if (_talkToAbort) + return; + + str += 3; + break; + + case PAUSE_WITHOUT_CONTROL: + // Save the current point in the script, since it might be intterupted by + // doing bg anims in the next call, so we need to know where to return to + _scriptCurrentIndex = str - script.c_str(); + + for (int idx = 0; idx < (str[0] - 1); ++idx) { + scene.doBgAnim(); + if (_talkToAbort) + return; + + // Check for button press + events.pollEvents(); + events.setButtonState(); + } + break; + + case BANISH_WINDOW: + // Save the current point in the script, since it might be intterupted by + // doing bg anims in the next call, so we need to know where to return to + _scriptCurrentIndex = str - script.c_str(); + + if (!(_speaker & 128)) + clearTalking(); + pullSequence(); + + if (_talkToAbort) + return; + + _speaker |= 128; + ui.banishWindow(); + ui._menuMode = TALK_MODE; + noTextYet = true; + break; + + case SUMMON_WINDOW: + drawInterface(); + events._pressed = events._released = false; + events.clearKeyboard(); + noTextYet = false; + + if (_speaker != -1) { + screen.buttonPrint(Common::Point(119, CONTROLS_Y), COMMAND_NULL, false, "Exit"); + screen.buttonPrint(Common::Point(159, CONTROLS_Y), COMMAND_NULL, false, "Up"); + screen.buttonPrint(Common::Point(200, CONTROLS_Y), COMMAND_NULL, false, "Down"); + } + break; + + case SET_FLAG: { + ++str; + int flag1 = (str[0] - 1) * 256 + str[1] - 1 - (str[1] == 1 ? 1 : 0); + int flag = (flag1 & 0x7fff) * (flag1 >= 0x8000 ? -1 : 1); + _vm->setFlags(flag); + ++str; + break; + } + + case SFX_COMMAND: + ++str; + if (sound._voices) { + for (int idx = 0; idx < 8 && str[idx] != '~'; ++idx) + tempString += str[idx]; + sound.playSound(tempString); + + // Set voices to wait for more + sound._voices = 2; + sound._speechOn = (*sound._soundIsOn); + } + + wait = 1; + str += 7; + break; + + case TOGGLE_OBJECT: + for (int idx = 0; idx < str[0]; ++idx) + tempString += str[idx + 1]; + + scene.toggleObject(tempString); + str += str[0]; + break; + + case STEALTH_MODE_ACTIVE: + _talkStealth = 2; + break; + + case IF_STATEMENT: { + ++str; + int flag = (str[0] - 1) * 256 + str[1] - 1 - (str[1] == 1 ? 1 : 0); + ++str; + wait = 0; + + bool result = flag < 0x8000; + if (_vm->readFlags(flag & 0x7fff) != result) { + do { + ++str; + } while (str[0] && str[0] != ELSE_STATEMENT && str[0] != END_IF_STATEMENT); + + if (!str[0]) + endStr = true; + } + break; + } + + case ELSE_STATEMENT: + // If this is encountered here, it means that a preceeding IF statement was found, + // and evaluated to true. Now all the statements for the true block are finished, + // so skip over the block of code that would have executed if the result was false + wait = 0; + do { + ++str; + } while (str[0] && str[0] != END_IF_STATEMENT); + break; + + case STEALTH_MODE_DEACTIVATE: + _talkStealth = 0; + events.clearKeyboard(); + break; + + case TURN_HOLMES_OFF: + people._holmesOn = false; + break; + + case TURN_HOLMES_ON: + people._holmesOn = true; + break; + + case GOTO_SCENE: + scene._goToScene = str[1] - 1; + + if (scene._goToScene != 100) { + // Not going to the map overview + scene._oldCharPoint = scene._goToScene; + scene._overPos.x = _vm->_map[scene._goToScene].x * 100 - 600; + scene._overPos.y = _vm->_map[scene._goToScene].y * 100 + 900; + + // Run a canimation? + if (str[2] > 100) { + scene._hsavedFs = str[2]; + scene._hsavedPos = Common::Point(160, 100); + } + } + str += 6; + + _scriptMoreFlag = (scene._goToScene == 100) ? 2 : 1; + _scriptSaveIndex = str - script.c_str(); + endStr = true; + wait = 0; + break; + + case PLAY_PROLOGUE: + ++str; + for (int idx = 0; idx < 8 && str[idx] != '~'; ++idx) + tempString += str[idx]; + + anim.playPrologue(tempString, 1, 3, true, 4); + break; + + case ADD_ITEM_TO_INVENTORY: + ++str; + for (int idx = 0; idx < str[0]; ++idx) + tempString += str[idx]; + str += str[0]; + + inv.putNameInInventory(tempString); + break; + + case SET_OBJECT: { + ++str; + for (int idx = 0; idx < (str[0] & 127); ++idx) + tempString += str[idx + 1]; + str += str[0]; + + // Set comparison state according to if we want to hide or unhide + bool state = (str[0] >= 128); + + for (uint idx = 0; idx < scene._bgShapes.size(); ++idx) { + Object &obj = scene._bgShapes[idx]; + if (scumm_stricmp(tempString.c_str(), obj._name.c_str()) == 0) { + // Only toggle the object if it's not in the desired state already + if ((obj._type == HIDDEN && state) || (obj._type != HIDDEN && !state)) + obj.toggleHidden(); + } + } + break; + } + + case CALL_TALK_FILE: + ++str; + for (int idx = 0; idx < 8 && str[idx] != '~'; ++idx) + tempString += str[idx]; + str += 8; + + _scriptCurrentIndex = str - script.c_str(); + + // Save the current script position and new talk file + if (_scriptStack.size() < 10) { + ScriptStackEntry rec; + rec._name = _scriptName; + rec._currentIndex = _scriptCurrentIndex; + rec._select = _scriptSelect; + } else { + error("Script stack overflow"); + } + + _scriptMoreFlag = true; + endStr = true; + wait = 0; + break; + + case MOVE_MOUSE: + // Save the current point in the script, since it might be intterupted by + // doing bg anims in the next call, so we need to know where to return to + _scriptCurrentIndex = str - script.c_str(); + events.moveMouse(Common::Point((str[0] - 1) * 256 + str[1] - 1, str[2])); + if (_talkToAbort) + return; + str += 3; + break; + + case DISPLAY_INFO_LINE: + ++str; + for (int idx = 0; idx < str[0]; ++idx) + tempString += str[idx + 1]; + str += str[0]; + + screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, tempString.c_str()); + break; + + case CLEAR_INFO_LINE: + ui._infoFlag = true; + ui.clearInfo(); + break; + + case WALK_TO_CANIMATION: { + ++str; + int animIndex = str[0] - 1; + + // Save the current point in the script, since it might be intterupted by + // doing bg anims in the next call, so we need to know where to return to + _scriptCurrentIndex = (str + 1) - script.c_str(); + if (_talkToAbort) + return; + break; + } + + case REMOVE_ITEM_FROM_INVENTORY: + ++str; + for (int idx = 0; idx < str[0]; ++idx) + tempString += str[idx + 1]; + str += str[0]; + + inv.deleteItemFromInventory(tempString); + break; + + case ENABLE_END_KEY: + ui._endKeyActive = true; + break; + + case DISABLE_END_KEY: + ui._endKeyActive = false; + break; + + default: + break; + } + + ++str; + } else { + // If the window isn't yet open, draw the window before printing starts + if (!ui._windowOpen && noTextYet) { + noTextYet = false; + drawInterface(); + + if (_talkTo != -1) { + screen.buttonPrint(Common::Point(119, CONTROLS_Y), COMMAND_NULL, false, "Exit"); + screen.buttonPrint(Common::Point(159, CONTROLS_Y), COMMAND_NULL, false, "Up"); + screen.buttonPrint(Common::Point(200, CONTROLS_Y), COMMAND_NULL, false, "Down"); + } + } + + // If it's the first line, display the speaker + if (!line && _speaker >= 0 && _speaker < MAX_PEOPLE) { + // If the window is open, display the name directly on-screen. + // Otherwise, simply draw it on the back buffer + if (ui._windowOpen) { + screen.print(Common::Point(16, yp), TALK_FOREGROUND, inv._names[_speaker & 127].c_str()); + } else { + screen.gPrint(Common::Point(16, yp - 1), TALK_FOREGROUND, inv._names[_speaker & 127].c_str()); + openTalkWindow = true; + } + + yp += 9; + } + + // Find amound of text that will fit on the line + int width = 0, idx = 0; + do { + width += screen.charWidth(str[idx]); + } while (width < 298 && str[idx] && str[idx] != '{' && str[idx] < 128); + + if (str[idx] || width >= 298) { + if (str[idx] < 128 && str[idx] != '{') { + --idx; + --charCount; + } + } else { + endStr = true; + } + + // If word wrap is needed, find the start of the current word + if (width >= 298) { + while (str[idx] != ' ') { + --idx; + --charCount; + } + } + + // Print the line + Common::String lineStr(str, str + idx); + + // If the speaker indicates a description file, print it in yellow + if (_speaker != -1) { + if (ui._windowOpen) { + screen.print(Common::Point(16, yp), INV_FOREGROUND, lineStr.c_str()); + } else { + screen.gPrint(Common::Point(16, yp - 1), INV_FOREGROUND, lineStr.c_str()); + } + } else { + if (ui._windowOpen) { + screen.print(Common::Point(16, yp), COMMAND_FOREGROUND, lineStr.c_str()); + } + else { + screen.gPrint(Common::Point(16, yp - 1), COMMAND_FOREGROUND, lineStr.c_str()); + } + } + + // Move to end of displayed line + str += idx; + + // If line wrap occurred, then move to after the separating space between the words + if (str[0] < 128 && str[0] != '{') + ++str; + + yp += 9; + ++line; + + // Certain different conditions require a wait + if ((line == 4 && str[0] != SFX_COMMAND && str[0] != PAUSE && _speaker != -1) || + (line == 5 && str[0] != PAUSE && _speaker != -1) || + endStr) { + wait = 1; + } + + switch (str[0]) { + case SWITCH_SPEAKER: + case ASSIGN_PORTRAIT_LOCATION: + case BANISH_WINDOW: + case IF_STATEMENT: + case ELSE_STATEMENT: + case END_IF_STATEMENT: + case GOTO_SCENE: + case CALL_TALK_FILE: + wait = 1; + break; + default: + break; + } + } + + // Open window if it wasn't already open, and text has already been printed + if ((openTalkWindow && wait) || (openTalkWindow && str[0] >= 128 && str[0] != COMMAND_161)) { + if (!ui._windowStyle) { + screen.slamRect(Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); + } else { + ui.summonWindow(); + } + + ui._windowOpen = true; + openTalkWindow = false; + } + + if (wait) { + // Save the current point in the script, since it might be intterupted by + // doing bg anims in the next call, so we need to know where to return to + _scriptCurrentIndex = str - script.c_str(); + + // Handling pausing + if (!pauseFlag && charCount < 160) + charCount = 160; + + wait = waitForMore(charCount); + if (wait == -1) + endStr = true; + + // If a key was pressed to finish the window, see if further voice files should be skipped + if (wait >= 0 && wait < 254) { + if (str[0] == SFX_COMMAND) + str += 9; + } + + // Clear the window unless the wait was due to a PAUSE command + if (!pauseFlag && wait != -1 && str[0] != SFX_COMMAND) { + if (!_talkStealth) + ui.clearWindow(); + yp = CONTROLS_Y + 12; + charCount = line = 0; + } + + pauseFlag = false; + } + } while (!_vm->shouldQuit() && !endStr); + + if (wait != -1) { + for (int ssIndex = 0; ssIndex < (int)_savedSequences.size(); ++ssIndex) { + SequenceEntry &seq = _savedSequences[ssIndex]; + Object &obj = scene._bgShapes[seq._objNum]; + + for (uint idx = 0; idx < seq._sequences.size(); ++idx) + obj._sequences[idx] = seq._sequences[idx]; + obj._frameNumber = seq._frameNumber; + obj._seqTo = seq._seqTo; + } + + pullSequence(); + if (_speaker < 128) + clearTalking(); + } +} + +void Talk::clearTalking() { + // TODO +} + +void Talk::setTalking(int speaker) { + // TODO +} + +/** + * When the talk window has been displayed, waits a period of time proportional to + * the amount of text that's been displayed + */ +int Talk::waitForMore(int delay) { + Events &events = *_vm->_events; + People &people = *_vm->_people; + Scene &scene = *_vm->_scene; + Sound &sound = *_vm->_sound; + UserInterface &ui = *_vm->_ui; + CursorId oldCursor = events.getCursor(); + int key2 = 254; + + // Unless we're in stealth mode, show the appropriate cursor + if (!_talkStealth) { + events.setCursor(ui._lookScriptFlag ? MAGNIFY : ARROW); + } + + do { + if (sound._speechOn && !*sound._soundIsOn) + people._portrait._frameNumber = -1; + + scene.doBgAnim(); + + // If talkTo call was done via doBgAnim, abort out of talk quietly + if (_talkToAbort) { + key2 = -1; + events._released = true; + } else { + // See if there's been a button press + events.setButtonState(); + + if (events.kbHit()) { + Common::KeyState keyState = events.getKey(); + if (keyState.keycode >= 32 && keyState.keycode < 128) + key2 = keyState.keycode; + } + + if (_talkStealth) { + key2 = 254; + events._released = false; + } + } + + // Count down the delay + if ((delay > 0 && !ui._invLookFlag && !ui._lookScriptFlag) || _talkStealth) + --delay; + + // If there are voices playing, reset delay so that they keep playing + if (sound._voices == 2 && *sound._soundIsOn) + delay = 0; + } while (!_vm->shouldQuit() && key2 == 254 && (delay || (sound._voices == 2 && *sound._soundIsOn)) + && !events._released && !events._rightReleased); + + // If voices was set 2 to indicate a voice file was place, then reset it back to 1 + if (sound._voices == 2) + sound._voices = 1; + + if (delay > 0 && sound._diskSoundPlaying) + sound.stopSndFuncPtr(0, 0); + + // Adjust _talkStealth mode: + // mode 1 - It was by a pause without stealth being on before the pause, so reset back to 0 + // mode 3 - It was set by a pause with stealth being on before the pause, to set it to active + // mode 0/2 (Inactive/active) No change + switch (_talkStealth) { + case 1: + _talkStealth = 0; + break; + case 2: + _talkStealth = 2; + break; + default: + break; + } + + sound._speechOn = false; + events.setCursor(_talkToAbort ? ARROW : oldCursor); + events._pressed = events._released = false; + + return key2; +} + + } // End of namespace Sherlock diff --git a/engines/sherlock/talk.h b/engines/sherlock/talk.h index 48cdd2b5b2..1b679a47bd 100644 --- a/engines/sherlock/talk.h +++ b/engines/sherlock/talk.h @@ -33,16 +33,19 @@ namespace Sherlock { #define MAX_TALK_SEQUENCES 11 -struct SavedSequence { +struct SequenceEntry { int _objNum; Common::Array _sequences; -}; - -struct SequenceEntry : public SavedSequence { int _frameNumber; int _seqTo; }; +struct ScriptStackEntry : public SequenceEntry { + Common::String _name; + int _currentIndex; + int _select; +}; + struct Statement { Common::String _statement; Common::String _reply; @@ -84,8 +87,8 @@ private: private: SherlockEngine *_vm; int _saveSeqNum; - Common::Array _savedSequences; - Common::Stack _sequenceStack; + Common::Stack _savedSequences; + Common::Stack _scriptStack; Common::Array _statements; TalkHistoryEntry _talkHistory[500]; int _speaker; @@ -95,17 +98,28 @@ private: int _talkStealth; int _talkToFlag; bool _moreTalkUp, _moreTalkDown; - + int _scriptSaveIndex; + int _scriptCurrentIndex; +private: void stripVoiceCommands(); void setTalkMap(); bool displayTalk(bool slamIt); int talkLine(int lineNum, int stateNum, byte color, int lineY, bool slamIt); + + void doScript(const Common::String &script); + + void clearTalking(); + void setTalking(int speaker); + + int waitForMore(int delay); public: bool _talkToAbort; int _talkCounter; int _talkTo; + int _scriptMoreFlag; + Common::String _scriptName; public: Talk(SherlockEngine *vm); void setSequences(const byte *talkSequences, const byte *stillSequences, @@ -127,7 +141,8 @@ public: void clearSequences(); void pullSequence(); void pushSequence(int speaker); - bool isSequencesEmpty() const { return _sequenceStack.empty(); } + void setSequence(int speaker); + bool isSequencesEmpty() const { return _scriptStack.empty(); } }; } // End of namespace Sherlock diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index 289bff814f..88265f6a19 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -122,7 +122,6 @@ void UserInterface::handleInput() { People &people = *_vm->_people; Scene &scene = *_vm->_scene; Screen &screen = *_vm->_screen; - Scripts &scripts = *_vm->_scripts; Talk &talk = *_vm->_talk; if (_menuCounter) @@ -148,7 +147,7 @@ void UserInterface::handleInput() { } // Do button highlighting check - if (!scripts._scriptMoreFlag) { // Don't if scripts are running + if (!talk._scriptMoreFlag) { // Don't if scripts are running if (((events._rightPressed || events._rightReleased) && _helpStyle) || (!_helpStyle && !_menuCounter)) { // Handle any default commands if we're in STD_MODE @@ -532,6 +531,13 @@ void UserInterface::examine() { _vm->setFlags(inv[_selector]._lookFlag); } + if (_invLookFlag) { + // Dont close the inventory window when starting an examine display, since it's + // window will slide up to replace the inventory display + _windowOpen = false; + _menuMode = LOOK_MODE; + } + if (!talk._talkToAbort) { if (!scene._cAnimFramePause) printObjectDesc(_cAnimStr, true); -- cgit v1.2.3 From a5992a08a02d86e33eb9c30dc8c6dd6fcb0bdf77 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Thu, 22 Aug 2013 20:37:16 -0400 Subject: MOHAWK: Run Myst in 8bpp --- engines/mohawk/cursors.cpp | 6 +- engines/mohawk/myst.cpp | 12 ++- engines/mohawk/myst_graphics.cpp | 165 +++++++++++++++++++++++++----------- engines/mohawk/myst_graphics.h | 27 +++--- engines/mohawk/myst_stacks/myst.cpp | 20 +++-- engines/mohawk/video.cpp | 46 +++++++++- engines/mohawk/video.h | 4 + 7 files changed, 205 insertions(+), 75 deletions(-) (limited to 'engines') diff --git a/engines/mohawk/cursors.cpp b/engines/mohawk/cursors.cpp index f1baac02e2..4b66829e6a 100644 --- a/engines/mohawk/cursors.cpp +++ b/engines/mohawk/cursors.cpp @@ -122,7 +122,11 @@ void MystCursorManager::setCursor(uint16 id) { // Myst ME stores some cursors as 24bpp images instead of 8bpp if (surface->format.bytesPerPixel == 1) { CursorMan.replaceCursor(surface->getPixels(), surface->w, surface->h, hotspotX, hotspotY, 0); - CursorMan.replaceCursorPalette(mhkSurface->getPalette(), 0, 256); + + // We're using the screen palette for the original game, but we need + // to use this for any 8bpp cursor in ME. + if (_vm->getFeatures() & GF_ME) + CursorMan.replaceCursorPalette(mhkSurface->getPalette(), 0, 256); } else { Graphics::PixelFormat pixelFormat = g_system->getScreenFormat(); CursorMan.replaceCursor(surface->getPixels(), surface->w, surface->h, hotspotX, hotspotY, pixelFormat.RGBToColor(255, 255, 255), false, &pixelFormat); diff --git a/engines/mohawk/myst.cpp b/engines/mohawk/myst.cpp index 7634e8d88a..b6a6c27329 100644 --- a/engines/mohawk/myst.cpp +++ b/engines/mohawk/myst.cpp @@ -413,7 +413,12 @@ void MohawkEngine_Myst::changeToStack(uint16 stack, uint16 card, uint16 linkSrcS // Fill screen with black and empty cursor _cursor->setCursor(0); - _system->fillScreen(_system->getScreenFormat().RGBToColor(0, 0, 0)); + + if (getFeatures() & GF_ME) + _system->fillScreen(_system->getScreenFormat().RGBToColor(0, 0, 0)); + else + _gfx->clearScreenPalette(); + _system->updateScreen(); _sound->stopSound(); @@ -495,9 +500,10 @@ void MohawkEngine_Myst::changeToStack(uint16 stack, uint16 card, uint16 linkSrcS _cache.clear(); _gfx->clearCache(); - // Play Flyby Entry Movie on Masterpiece Edition. - const char *flyby = 0; if (getFeatures() & GF_ME) { + // Play Flyby Entry Movie on Masterpiece Edition. + const char *flyby = 0; + switch (_curStack) { case kSeleniticStack: flyby = "selenitic flyby"; diff --git a/engines/mohawk/myst_graphics.cpp b/engines/mohawk/myst_graphics.cpp index 9ea9f15444..49f97cca63 100644 --- a/engines/mohawk/myst_graphics.cpp +++ b/engines/mohawk/myst_graphics.cpp @@ -28,6 +28,7 @@ #include "common/system.h" #include "common/textconsole.h" #include "engines/util.h" +#include "graphics/palette.h" #include "image/pict.h" namespace Mohawk { @@ -37,16 +38,20 @@ MystGraphics::MystGraphics(MohawkEngine_Myst* vm) : GraphicsManager(), _vm(vm) { _viewport = Common::Rect(544, 332); - // The original version of Myst could run in 8bpp color too. - // However, it dithered videos to 8bpp and they looked considerably - // worse (than they already did :P). So we're not even going to - // support 8bpp mode in Myst (Myst ME required >8bpp anyway). - initGraphics(_viewport.width(), _viewport.height(), true, NULL); // What an odd screen size! + if (_vm->getFeatures() & GF_ME) { + // High color + initGraphics(_viewport.width(), _viewport.height(), true, NULL); - _pixelFormat = _vm->_system->getScreenFormat(); + if (_vm->_system->getScreenFormat().bytesPerPixel == 1) + error("Myst ME requires greater than 256 colors to run"); + } else { + // Paletted + initGraphics(_viewport.width(), _viewport.height(), true); + setBasePalette(); + setPaletteToScreen(); + } - if (_pixelFormat.bytesPerPixel == 1) - error("Myst requires greater than 256 colors to run"); + _pixelFormat = _vm->_system->getScreenFormat(); // Initialize our buffer _backBuffer = new Graphics::Surface(); @@ -101,7 +106,9 @@ MohawkSurface *MystGraphics::decodeImage(uint16 id) { mhkSurface = new MohawkSurface(pict.getSurface()->convertTo(_pixelFormat)); } else { mhkSurface = _bmpDecoder->decodeImage(dataStream); - mhkSurface->convertToTrueColor(); + + if (_vm->getFeatures() & GF_ME) + mhkSurface->convertToTrueColor(); } assert(mhkSurface); @@ -151,7 +158,8 @@ void MystGraphics::copyImageSectionToScreen(uint16 image, Common::Rect src, Comm } void MystGraphics::copyImageSectionToBackBuffer(uint16 image, Common::Rect src, Common::Rect dest) { - Graphics::Surface *surface = findImage(image)->getSurface(); + MohawkSurface *mhkSurface = findImage(image); + Graphics::Surface *surface = mhkSurface->getSurface(); // Make sure the image is bottom aligned in the dest rect dest.top = dest.bottom - MIN(surface->h, dest.height()); @@ -190,6 +198,13 @@ void MystGraphics::copyImageSectionToBackBuffer(uint16 image, Common::Rect src, for (uint16 i = 0; i < height; i++) memcpy(_backBuffer->getBasePtr(dest.left, i + dest.top), surface->getBasePtr(src.left, top + i), width * surface->format.bytesPerPixel); + + if (!(_vm->getFeatures() & GF_ME)) { + // Make sure the palette is set + assert(mhkSurface->getPalette()); + memcpy(_palette + 10 * 3, mhkSurface->getPalette() + 10 * 3, (256 - 10 * 2) * 3); + setPaletteToScreen(); + } } void MystGraphics::copyImageToScreen(uint16 image, Common::Rect dest) { @@ -419,12 +434,16 @@ void MystGraphics::transitionDissolve(Common::Rect rect, uint step) { for (uint16 x = rect.left; x < rect.right; x++) { if (linePattern[x % 4]) { - if (_pixelFormat.bytesPerPixel == 2) { - uint16 *dst = (uint16 *)screen->getBasePtr(x, y); - *dst = *(const uint16 *)_backBuffer->getBasePtr(x, y); - } else { - uint32 *dst = (uint32 *)screen->getBasePtr(x, y); - *dst = *(const uint32 *)_backBuffer->getBasePtr(x, y); + switch (_pixelFormat.bytesPerPixel) { + case 1: + *((byte *)screen->getBasePtr(x, y)) = *((const byte *)_backBuffer->getBasePtr(x, y)); + break; + case 2: + *((uint16 *)screen->getBasePtr(x, y)) = *((const uint16 *)_backBuffer->getBasePtr(x, y)); + break; + case 4: + *((uint32 *)screen->getBasePtr(x, y)) = *((const uint32 *)_backBuffer->getBasePtr(x, y)); + break; } } } @@ -588,11 +607,11 @@ void MystGraphics::drawRect(Common::Rect rect, RectState state) { Graphics::Surface *screen = _vm->_system->lockScreen(); if (state == kRectEnabled) - screen->frameRect(rect, _pixelFormat.RGBToColor(0, 255, 0)); + screen->frameRect(rect, (_vm->getFeatures() & GF_ME) ? _pixelFormat.RGBToColor(0, 255, 0) : 250); else if (state == kRectUnreachable) - screen->frameRect(rect, _pixelFormat.RGBToColor(0, 0, 255)); + screen->frameRect(rect, (_vm->getFeatures() & GF_ME) ? _pixelFormat.RGBToColor(0, 0, 255) : 252); else - screen->frameRect(rect, _pixelFormat.RGBToColor(255, 0, 0)); + screen->frameRect(rect, (_vm->getFeatures() & GF_ME) ? _pixelFormat.RGBToColor(255, 0, 0) : 249); _vm->_system->unlockScreen(); } @@ -629,50 +648,94 @@ void MystGraphics::simulatePreviousDrawDelay(const Common::Rect &dest) { _nextAllowedDrawTime = time + _constantDrawDelay + dest.height() * dest.width() / _proportionalDrawDelay; } -void MystGraphics::copyBackBufferToScreenWithSaturation(int16 saturation) { - Graphics::Surface *screen = _vm->_system->lockScreen(); +void MystGraphics::fadeToBlack() { + // This is only for the demo + assert(!(_vm->getFeatures() & GF_ME)); - for (uint16 y = 0; y < _viewport.height(); y++) - for (uint16 x = 0; x < _viewport.width(); x++) { - uint32 color; - uint8 r, g, b; + // Linear fade in 64 steps + for (int i = 63; i >= 0; i--) { + byte palette[256 * 3]; + byte *src = _palette; + byte *dst = palette; - if (_pixelFormat.bytesPerPixel == 2) - color = *(const uint16 *)_backBuffer->getBasePtr(x, y); - else - color = *(const uint32 *)_backBuffer->getBasePtr(x, y); + for (uint j = 0; j < sizeof(palette); j++) + *dst++ = *src++ * i / 64; - _pixelFormat.colorToRGB(color, r, g, b); + _vm->_system->getPaletteManager()->setPalette(palette, 0, 256); + _vm->_system->updateScreen(); + } +} - r = CLIP((int16)r - saturation, 0, 255); - g = CLIP((int16)g - saturation, 0, 255); - b = CLIP((int16)b - saturation, 0, 255); +void MystGraphics::fadeFromBlack() { + // This is only for the demo + assert(!(_vm->getFeatures() & GF_ME)); - color = _pixelFormat.RGBToColor(r, g, b); + copyBackBufferToScreen(_viewport); - if (_pixelFormat.bytesPerPixel == 2) { - uint16 *dst = (uint16 *)screen->getBasePtr(x, y); - *dst = color; - } else { - uint32 *dst = (uint32 *)screen->getBasePtr(x, y); - *dst = color; - } - } + // Linear fade in 64 steps + for (int i = 0; i < 64; i++) { + byte palette[256 * 3]; + byte *src = _palette; + byte *dst = palette; - _vm->_system->unlockScreen(); + for (uint j = 0; j < sizeof(palette); j++) + *dst++ = *src++ * i / 64; + + _vm->_system->getPaletteManager()->setPalette(palette, 0, 256); + _vm->_system->updateScreen(); + } + + // Set the full palette + _vm->_system->getPaletteManager()->setPalette(_palette, 0, 256); _vm->_system->updateScreen(); } -void MystGraphics::fadeToBlack() { - for (int16 i = 0; i < 256; i += 32) { - copyBackBufferToScreenWithSaturation(i); - } +void MystGraphics::clearScreenPalette() { + // Set the palette to all black + byte palette[256 * 3]; + memset(palette, 0, sizeof(palette)); + _vm->_system->getPaletteManager()->setPalette(palette, 0, 256); } -void MystGraphics::fadeFromBlack() { - for (int16 i = 256; i >= 0; i -= 32) { - copyBackBufferToScreenWithSaturation(i); - } +void MystGraphics::setBasePalette() { + // Entries [0, 9] of the palette + static const byte lowPalette[] = { + 0xFF, 0xFF, 0xFF, + 0x80, 0x00, 0x00, + 0x00, 0x80, 0x00, + 0x80, 0x80, 0x00, + 0x00, 0x00, 0x80, + 0x80, 0x00, 0x80, + 0x00, 0x80, 0x80, + 0xC0, 0xC0, 0xC0, + 0xC0, 0xDC, 0xC0, + 0xA6, 0xCA, 0xF0 + }; + + // Entries [246, 255] of the palette + static const byte highPalette[] = { + 0xFF, 0xFB, 0xF0, + 0xA0, 0xA0, 0xA4, + 0x80, 0x80, 0x80, + 0xFF, 0x00, 0x00, + 0x00, 0xFF, 0x00, + 0xFF, 0xFF, 0x00, + 0x00, 0x00, 0xFF, + 0xFF, 0x00, 0xFF, + 0x00, 0xFF, 0xFF, + 0x00, 0x00, 0x00 + }; + + // Note that 0 and 255 are different from normal Windows. + // Myst seems to hack that to white, resp. black (probably for Mac compat). + + memcpy(_palette, lowPalette, sizeof(lowPalette)); + memset(_palette + sizeof(lowPalette), 0, sizeof(_palette) - sizeof(lowPalette) - sizeof(highPalette)); + memcpy(_palette + sizeof(_palette) - sizeof(highPalette), highPalette, sizeof(highPalette)); +} + +void MystGraphics::setPaletteToScreen() { + _vm->_system->getPaletteManager()->setPalette(_palette, 0, 256); } } // End of namespace Mohawk diff --git a/engines/mohawk/myst_graphics.h b/engines/mohawk/myst_graphics.h index 1f70320bf6..6281c94cc8 100644 --- a/engines/mohawk/myst_graphics.h +++ b/engines/mohawk/myst_graphics.h @@ -40,7 +40,7 @@ enum RectState { class MystGraphics : public GraphicsManager { public: - MystGraphics(MohawkEngine_Myst*); + MystGraphics(MohawkEngine_Myst *vm); ~MystGraphics(); void copyImageSectionToScreen(uint16 image, Common::Rect src, Common::Rect dest); @@ -55,18 +55,15 @@ public: void fadeToBlack(); void fadeFromBlack(); + void clearScreenPalette(); + void setBasePalette(); + void setPaletteToScreen(); + const byte *getPalette() const { return _palette; } + protected: MohawkSurface *decodeImage(uint16 id); MohawkEngine *getVM() { return (MohawkEngine *)_vm; } - void simulatePreviousDrawDelay(const Common::Rect &dest); - void copyBackBufferToScreenWithSaturation(int16 saturation); - void transitionDissolve(Common::Rect rect, uint step); - void transitionSlideToLeft(Common::Rect rect, uint16 steps, uint16 delay); - void transitionSlideToRight(Common::Rect rect, uint16 steps, uint16 delay); - void transitionSlideToTop(Common::Rect rect, uint16 steps, uint16 delay); - void transitionSlideToBottom(Common::Rect rect, uint16 steps, uint16 delay); - void transitionPartialToRight(Common::Rect rect, uint32 width, uint32 steps); - void transitionPartialToLeft(Common::Rect rect, uint32 width, uint32 steps); + private: MohawkEngine_Myst *_vm; MystBitmap *_bmpDecoder; @@ -74,11 +71,21 @@ private: Graphics::Surface *_backBuffer; Graphics::PixelFormat _pixelFormat; Common::Rect _viewport; + byte _palette[256 * 3]; int _enableDrawingTimeSimulation; uint32 _nextAllowedDrawTime; static const uint _constantDrawDelay = 10; // ms static const uint _proportionalDrawDelay = 500; // pixels per ms + + void simulatePreviousDrawDelay(const Common::Rect &dest); + void transitionDissolve(Common::Rect rect, uint step); + void transitionSlideToLeft(Common::Rect rect, uint16 steps, uint16 delay); + void transitionSlideToRight(Common::Rect rect, uint16 steps, uint16 delay); + void transitionSlideToTop(Common::Rect rect, uint16 steps, uint16 delay); + void transitionSlideToBottom(Common::Rect rect, uint16 steps, uint16 delay); + void transitionPartialToRight(Common::Rect rect, uint32 width, uint32 steps); + void transitionPartialToLeft(Common::Rect rect, uint32 width, uint32 steps); }; } // End of namespace Mohawk diff --git a/engines/mohawk/myst_stacks/myst.cpp b/engines/mohawk/myst_stacks/myst.cpp index c500df5ad3..ca6e7c0ee5 100644 --- a/engines/mohawk/myst_stacks/myst.cpp +++ b/engines/mohawk/myst_stacks/myst.cpp @@ -3201,13 +3201,21 @@ Common::Point Myst::towerRotationMapComputeCoords(const Common::Point ¢er, u } void Myst::towerRotationMapDrawLine(const Common::Point ¢er, const Common::Point &end) { - Graphics::PixelFormat pf = _vm->_system->getScreenFormat(); - uint32 color = 0; + uint32 color; - if (!_towerRotationOverSpot) - color = pf.RGBToColor(0xFF, 0xFF, 0xFF); // White - else - color = pf.RGBToColor(0xFF, 0, 0); // Red + if (_vm->getFeatures() & GF_ME) { + Graphics::PixelFormat pf = _vm->_system->getScreenFormat(); + + if (!_towerRotationOverSpot) + color = pf.RGBToColor(0xFF, 0xFF, 0xFF); // White + else + color = pf.RGBToColor(0xFF, 0, 0); // Red + } else { + if (!_towerRotationOverSpot) + color = 0x00; // White + else + color = 0xF9; // Red + } const Common::Rect rect = Common::Rect(106, 42, 459, 273); diff --git a/engines/mohawk/video.cpp b/engines/mohawk/video.cpp index cebb72e24f..ca38f22b7a 100644 --- a/engines/mohawk/video.cpp +++ b/engines/mohawk/video.cpp @@ -53,6 +53,8 @@ bool VideoEntry::endOfVideo() { } VideoManager::VideoManager(MohawkEngine* vm) : _vm(vm) { + // Set dithering enabled, if required + _enableDither = _vm->getGameType() == GType_MYST && !(_vm->getFeatures() & GF_ME); } VideoManager::~VideoManager() { @@ -230,16 +232,23 @@ bool VideoManager::updateMovies() { Graphics::PixelFormat pixelFormat = _vm->_system->getScreenFormat(); if (frame->format != pixelFormat) { - // We don't support downconverting to 8bpp - if (pixelFormat.bytesPerPixel == 1) - error("Cannot convert high color video frame to 8bpp"); + // We don't support downconverting to 8bpp without having + // support in the codec. Set _enableDither if shows up. + if (pixelFormat.bytesPerPixel == 1) { + warning("Cannot convert high color video frame to 8bpp"); + delete _videoStreams[i].video; + _videoStreams[i].clear(); + continue; + } // Convert to the current screen format convertedFrame = frame->convertTo(pixelFormat, _videoStreams[i]->getPalette()); frame = convertedFrame; } else if (pixelFormat.bytesPerPixel == 1 && _videoStreams[i]->hasDirtyPalette()) { // Set the palette when running in 8bpp mode only - _vm->_system->getPaletteManager()->setPalette(_videoStreams[i]->getPalette(), 0, 256); + // Don't do this for Myst, which has its own per-stack handling + if (_vm->getGameType() != GType_MYST) + _vm->_system->getPaletteManager()->setPalette(_videoStreams[i]->getPalette(), 0, 256); } // Clip the width/height to make sure we stay on the screen (Myst does this a few times) @@ -394,6 +403,9 @@ VideoHandle VideoManager::createVideoHandle(uint16 id, uint16 x, uint16 y, bool entry.loop = loop; entry.enabled = true; + // Enable dither if necessary + checkEnableDither(entry); + entry->start(); // Search for any deleted videos so we can take a formerly used slot @@ -431,6 +443,10 @@ VideoHandle VideoManager::createVideoHandle(const Common::String &filename, uint } entry->loadStream(file); + + // Enable dither if necessary + checkEnableDither(entry); + entry->setVolume(volume); entry->start(); @@ -551,4 +567,26 @@ void VideoManager::pauseMovie(VideoHandle handle, bool pause) { _videoStreams[handle]->pauseVideo(pause); } +void VideoManager::checkEnableDither(VideoEntry &entry) { + // If we're not dithering, bail out + if (!_enableDither) + return; + + // Ignore any video which is already 8bpp + if (entry->getPixelFormat().bytesPerPixel == 1) + return; + + // Set the palette + byte palette[256 * 3]; + g_system->getPaletteManager()->grabPalette(palette, 0, 256); + entry->setDitheringPalette(palette); + + if (entry->getPixelFormat().bytesPerPixel != 1) { + if (entry.filename.empty()) + error("Failed to set dither for video %d", entry.id); + else + error("Failed to set dither for video %s", entry.filename.c_str()); + } +} + } // End of namespace Mohawk diff --git a/engines/mohawk/video.h b/engines/mohawk/video.h index 43181e3e6c..deb09afe6b 100644 --- a/engines/mohawk/video.h +++ b/engines/mohawk/video.h @@ -124,6 +124,10 @@ private: VideoHandle createVideoHandle(uint16 id, uint16 x, uint16 y, bool loop, uint16 volume = 0xff); VideoHandle createVideoHandle(const Common::String &filename, uint16 x, uint16 y, bool loop, byte volume = 0xff); + + // Dithering control + bool _enableDither; + void checkEnableDither(VideoEntry &entry); }; } // End of namespace Mohawk -- cgit v1.2.3 From 3323af355dd081428c114c4b15b4abc7307115c0 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Sat, 11 Apr 2015 15:31:20 -0400 Subject: MOHAWK: Allow Myst to compile without RGB colors --- engines/mohawk/configure.engine | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mohawk/configure.engine b/engines/mohawk/configure.engine index fa9d15cffc..47402c4560 100644 --- a/engines/mohawk/configure.engine +++ b/engines/mohawk/configure.engine @@ -3,4 +3,4 @@ add_engine mohawk "Mohawk" yes "cstime myst riven" "Living Books" add_engine cstime "Where in Time is Carmen Sandiego?" no add_engine riven "Riven: The Sequel to Myst" no "" "" "16bit" -add_engine myst "Myst" no "" "" "16bit" +add_engine myst "Myst" no -- cgit v1.2.3 From dd63cef93efce72b300c99a6a8b9415a111c2b82 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 11 Apr 2015 15:38:31 -0500 Subject: MADS: Fix memory leak in Dialog class --- engines/mads/dialogs.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines') diff --git a/engines/mads/dialogs.cpp b/engines/mads/dialogs.cpp index 158d9693ad..7f0b02bc65 100644 --- a/engines/mads/dialogs.cpp +++ b/engines/mads/dialogs.cpp @@ -43,6 +43,7 @@ Dialog::Dialog(MADSEngine *vm) } Dialog::~Dialog() { + delete _savedSurface; } void Dialog::save() { -- cgit v1.2.3 From 797506eff79126e60ec97e8377b5a6d632769564 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Sat, 11 Apr 2015 16:05:50 -0400 Subject: SWORD25: Use fabs for absolute value of doubles --- engines/sword25/util/double_serialization.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sword25/util/double_serialization.cpp b/engines/sword25/util/double_serialization.cpp index 73da296e40..13fa42b6be 100644 --- a/engines/sword25/util/double_serialization.cpp +++ b/engines/sword25/util/double_serialization.cpp @@ -33,7 +33,7 @@ SerializedDouble encodeDouble(double value) { double significand = frexp(value, &exponent); // Shift the the first part of the significand into the integer range - double shiftedsignificandPart = ldexp(abs(significand), 32); + double shiftedsignificandPart = ldexp(fabs(significand), 32); uint32 significandOne = uint32(floor(shiftedsignificandPart)); // Shift the remainder of the significand into the integer range -- cgit v1.2.3 From ddf170de4a33fac4cac3093bf6dd97d253216092 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Sat, 11 Apr 2015 16:11:21 -0400 Subject: ZVISION: Silence gcc warnings --- engines/zvision/graphics/effects/fog.cpp | 6 ++--- engines/zvision/graphics/effects/wave.cpp | 2 +- engines/zvision/graphics/render_manager.cpp | 4 ++-- .../zvision/scripting/effects/distort_effect.cpp | 2 +- engines/zvision/scripting/effects/music_effect.cpp | 2 +- engines/zvision/scripting/menu.cpp | 26 +++++++++++----------- engines/zvision/text/truetype_font.cpp | 8 +++---- 7 files changed, 25 insertions(+), 25 deletions(-) (limited to 'engines') diff --git a/engines/zvision/graphics/effects/fog.cpp b/engines/zvision/graphics/effects/fog.cpp index 32a01915d3..7b65f60f24 100644 --- a/engines/zvision/graphics/effects/fog.cpp +++ b/engines/zvision/graphics/effects/fog.cpp @@ -142,9 +142,9 @@ void FogFx::update() { for (uint8 i = 0; i < 31; i++) { float perc = (float)i / 31.0; - uint8 cr = (float)_r * perc; - uint8 cg = (float)_g * perc; - uint8 cb = (float)_b * perc; + uint8 cr = (uint8)((float)_r * perc); + uint8 cg = (uint8)((float)_g * perc); + uint8 cb = (uint8)((float)_b * perc); _colorMap[i] = _engine->_resourcePixelFormat.RGBToColor(cr << 3, cg << 3, cb << 3); } } diff --git a/engines/zvision/graphics/effects/wave.cpp b/engines/zvision/graphics/effects/wave.cpp index cec631611b..d2887b3112 100644 --- a/engines/zvision/graphics/effects/wave.cpp +++ b/engines/zvision/graphics/effects/wave.cpp @@ -54,7 +54,7 @@ WaveFx::WaveFx(ZVision *engine, uint32 key, Common::Rect region, bool ported, in int16 dx = (x - quarterWidth); int16 dy = (y - quarterHeight); - _ampls[i][x + y * _halfWidth] = ampl * sin(sqrt(dx * dx / (float)centerX + dy * dy / (float)centerY) / (-waveln * 3.1415926) + phase); + _ampls[i][x + y * _halfWidth] = (int8)(ampl * sin(sqrt(dx * dx / (float)centerX + dy * dy / (float)centerY) / (-waveln * 3.1415926) + phase)); } phase += spd; } diff --git a/engines/zvision/graphics/render_manager.cpp b/engines/zvision/graphics/render_manager.cpp index 3772d5909e..ce0a02a1ad 100644 --- a/engines/zvision/graphics/render_manager.cpp +++ b/engines/zvision/graphics/render_manager.cpp @@ -1108,7 +1108,7 @@ void RenderManager::updateRotation() { int16 newPosition = startPosition + _velocity; int16 screenHeight = getBkgSize().y; - int16 tiltGap = _renderTable.getTiltGap(); + int16 tiltGap = (int16)_renderTable.getTiltGap(); if (newPosition >= (screenHeight - tiltGap)) newPosition = screenHeight - tiltGap; @@ -1143,7 +1143,7 @@ void RenderManager::checkBorders() { int16 newPosition = startPosition; int16 screenHeight = getBkgSize().y; - int16 tiltGap = _renderTable.getTiltGap(); + int16 tiltGap = (int16)_renderTable.getTiltGap(); if (newPosition >= (screenHeight - tiltGap)) newPosition = screenHeight - tiltGap; diff --git a/engines/zvision/scripting/effects/distort_effect.cpp b/engines/zvision/scripting/effects/distort_effect.cpp index 78c4a1b9a8..113b5d048d 100644 --- a/engines/zvision/scripting/effects/distort_effect.cpp +++ b/engines/zvision/scripting/effects/distort_effect.cpp @@ -52,7 +52,7 @@ DistortNode::DistortNode(ZVision *engine, uint32 key, int16 speed, float startAn _diffLinScale = endLineScale - startLineScale; _frmSpeed = (float)speed / 15.0; - _frames = ceil((5.0 - _frmSpeed * 2.0) / _frmSpeed); + _frames = (int)ceil((5.0 - _frmSpeed * 2.0) / _frmSpeed); if (_frames <= 0) _frames = 1; diff --git a/engines/zvision/scripting/effects/music_effect.cpp b/engines/zvision/scripting/effects/music_effect.cpp index ad3c0f6d22..e3fdc96dba 100644 --- a/engines/zvision/scripting/effects/music_effect.cpp +++ b/engines/zvision/scripting/effects/music_effect.cpp @@ -140,7 +140,7 @@ bool MusicNode::process(uint32 deltaTimeInMillis) { if (_crossfadeTime > 0) { if ((int32)deltaTimeInMillis > _crossfadeTime) deltaTimeInMillis = _crossfadeTime; - _newvol += floor(((float)(_crossfadeTarget - _newvol) / (float)_crossfadeTime)) * (float)deltaTimeInMillis; + _newvol += (int)(floor(((float)(_crossfadeTarget - _newvol) / (float)_crossfadeTime)) * (float)deltaTimeInMillis); _crossfadeTime -= deltaTimeInMillis; } else { _crossfade = false; diff --git a/engines/zvision/scripting/menu.cpp b/engines/zvision/scripting/menu.cpp index 16aa57e3ae..e7775cbe3f 100644 --- a/engines/zvision/scripting/menu.cpp +++ b/engines/zvision/scripting/menu.cpp @@ -50,9 +50,9 @@ MenuZGI::MenuZGI(ZVision *engine) : scrolled[0] = false; scrolled[1] = false; scrolled[2] = false; - scrollPos[0] = 0.0; - scrollPos[1] = 0.0; - scrollPos[2] = 0.0; + scrollPos[0] = 0; + scrollPos[1] = 0; + scrollPos[2] = 0; mouseOnItem = -1; redraw = false; clean = false; @@ -361,11 +361,11 @@ void MenuZGI::process(uint32 deltatime) { if (scrl == 0) scrl = 1.0; - scrollPos [kMenuItem] += scrl; + scrollPos[kMenuItem] += (int)scrl; if (scrollPos[kMenuItem] >= 0) { scrolled[kMenuItem] = true; - scrollPos [kMenuItem] = 0; + scrollPos[kMenuItem] = 0; } } if (redraw) { @@ -430,11 +430,11 @@ void MenuZGI::process(uint32 deltatime) { if (scrl == 0) scrl = 1.0; - scrollPos [kMenuMagic] += scrl; + scrollPos[kMenuMagic] += (int)scrl; if (scrollPos[kMenuMagic] >= 600) { scrolled[kMenuMagic] = true; - scrollPos [kMenuMagic] = 600; + scrollPos[kMenuMagic] = 600; } } if (redraw) { @@ -495,11 +495,11 @@ void MenuZGI::process(uint32 deltatime) { if (scrl == 0) scrl = 1.0; - scrollPos [kMenuMain] += scrl; + scrollPos[kMenuMain] += (int)scrl; if (scrollPos[kMenuMain] >= 0) { scrolled[kMenuMain] = true; - scrollPos [kMenuMain] = 0; + scrollPos[kMenuMain] = 0; } } if (redraw) { @@ -553,7 +553,7 @@ MenuNemesis::MenuNemesis(ZVision *engine) : MenuHandler(engine) { inmenu = false; scrolled = false; - scrollPos = 0.0; + scrollPos = 0; mouseOnItem = -1; redraw = false; delay = 0; @@ -696,7 +696,7 @@ void MenuNemesis::process(uint32 deltatime) { if (scrl == 0) scrl = 1.0; - scrollPos += scrl; + scrollPos += (int)scrl; redraw = true; } @@ -743,10 +743,10 @@ void MenuNemesis::process(uint32 deltatime) { if (scrl == 0) scrl = 1.0; - Common::Rect cl(64, 32 + scrollPos - scrl, 64 + 512, 32 + scrollPos + 1); + Common::Rect cl(64, (int16)(32 + scrollPos - scrl), 64 + 512, 32 + scrollPos + 1); _engine->getRenderManager()->clearMenuSurface(cl); - scrollPos -= scrl; + scrollPos -= (int)scrl; redraw = true; } else scrollPos = -32; diff --git a/engines/zvision/text/truetype_font.cpp b/engines/zvision/text/truetype_font.cpp index 7ad8d6db61..acb053ea8d 100644 --- a/engines/zvision/text/truetype_font.cpp +++ b/engines/zvision/text/truetype_font.cpp @@ -199,12 +199,12 @@ void StyledTTFont::drawChar(Graphics::Surface *dst, byte chr, int x, int y, uint if (_font) { _font->drawChar(dst, chr, x, y, color); if (_style & TTF_STYLE_UNDERLINE) { - int16 pos = floor(_font->getFontHeight() * 0.87); + int16 pos = (int16)floor(_font->getFontHeight() * 0.87); int thk = MAX((int)(_font->getFontHeight() * 0.05), 1); dst->fillRect(Common::Rect(x, y + pos, x + _font->getCharWidth(chr), y + pos + thk), color); } if (_style & TTF_STYLE_STRIKETHROUGH) { - int16 pos = floor(_font->getFontHeight() * 0.60); + int16 pos = (int16)floor(_font->getFontHeight() * 0.60); int thk = MAX((int)(_font->getFontHeight() * 0.05), 1); dst->fillRect(Common::Rect(x, y + pos, x + _font->getCharWidth(chr), y + pos + thk), color); } @@ -216,7 +216,7 @@ void StyledTTFont::drawString(Graphics::Surface *dst, const Common::String &str, Common::U32String u32str = convertUtf8ToUtf32(str); _font->drawString(dst, u32str, x, y, w, color, align); if (_style & TTF_STYLE_UNDERLINE) { - int16 pos = floor(_font->getFontHeight() * 0.87); + int16 pos = (int16)floor(_font->getFontHeight() * 0.87); int16 wd = MIN(_font->getStringWidth(u32str), w); int16 stX = x; if (align == Graphics::kTextAlignCenter) @@ -229,7 +229,7 @@ void StyledTTFont::drawString(Graphics::Surface *dst, const Common::String &str, dst->fillRect(Common::Rect(stX, y + pos, stX + wd, y + pos + thk), color); } if (_style & TTF_STYLE_STRIKETHROUGH) { - int16 pos = floor(_font->getFontHeight() * 0.60); + int16 pos = (int16)floor(_font->getFontHeight() * 0.60); int16 wd = MIN(_font->getStringWidth(u32str), w); int16 stX = x; if (align == Graphics::kTextAlignCenter) -- cgit v1.2.3 From 0d4d8e878cfba4ea9c32dc46e4923886df95395c Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 11 Apr 2015 16:52:19 -0500 Subject: SHERLOCK: Implemented stubbed talk and inventory methods --- engines/sherlock/inventory.cpp | 10 +- engines/sherlock/inventory.h | 1 + engines/sherlock/people.cpp | 223 ++++++++++++++++++++++++++++++++++++++++- engines/sherlock/people.h | 10 +- engines/sherlock/talk.cpp | 59 +++++++---- engines/sherlock/talk.h | 3 - 6 files changed, 276 insertions(+), 30 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/inventory.cpp b/engines/sherlock/inventory.cpp index 0ea85f32fc..9eedac7c6a 100644 --- a/engines/sherlock/inventory.cpp +++ b/engines/sherlock/inventory.cpp @@ -453,7 +453,15 @@ int Inventory::putItemInInventory(Object &obj) { * Copy the passed object into the inventory */ void Inventory::copyToInventory(Object &obj) { - // TODO + InventoryItem invItem; + invItem._name = obj._name; + invItem._description = obj._description; + invItem._examine = obj._examine; + invItem._lookFlag = obj._lookFlag; + invItem._requiredFlag = obj._requiredFlag; + + insert_at(_holdings, invItem); + ++_holdings; } /** diff --git a/engines/sherlock/inventory.h b/engines/sherlock/inventory.h index 722692a3b2..436d2bc18d 100644 --- a/engines/sherlock/inventory.h +++ b/engines/sherlock/inventory.h @@ -53,6 +53,7 @@ struct InventoryItem { Common::String _examine; int _lookFlag; + InventoryItem() : _requiredFlag(0), _lookFlag(0) {} InventoryItem(int requiredFlag, const Common::String &name, const Common::String &description, const Common::String &examine); }; diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp index 9319fbb79d..5c7f9ef506 100644 --- a/engines/sherlock/people.cpp +++ b/engines/sherlock/people.cpp @@ -50,6 +50,145 @@ static const uint8 CHARACTER_SEQUENCES[MAX_HOLMES_SEQUENCE][MAX_FRAME] = { { 52, 1, 2, 3, 4, 0 } // Goto Stand Down Left }; +const char PORTRAITS[MAX_PEOPLE][5] = { + { "HOLM" }, // Sherlock Holmes + { "WATS" }, // Dr. Watson + { "LEST" }, // Inspector Lestrade + { "CON1" }, // Constable O'Brien + { "CON2" }, // Constable Lewis + { "SHEI" }, // Sheila Parker + { "HENR" }, // Henry Carruthers + { "LESL" }, // Lesley (flower girl) + { "USH1" }, // Usher #1 + { "USH2" }, // Usher #2 + { "FRED" }, // Fredrick Epstein + { "WORT" }, // Mrs. Worthington + { "COAC" }, // Coach + { "PLAY" }, // Player + { "WBOY" }, // Tim (Waterboy) + { "JAME" }, // James Sanders + { "BELL" }, // Belle (perfumerie) + { "GIRL" }, // Cleaning Girl (perfumerie) + { "EPST" }, // Epstien in the Opera Balcony + { "WIGG" }, // Wiggins + { "PAUL" }, // Paul (Brumwell / Carroway) + { "BART" }, // Bartender + { "DIRT" }, // Dirty Drunk + { "SHOU" }, // Shouting Drunk + { "STAG" }, // Staggering Drunk + { "BOUN" }, // Bouncer + { "SAND" }, // James Sanders - At Home + { "CORO" }, // The Coroner + { "EQUE" }, // The Equestrian Shop Keeper + { "GEOR" }, // George Blackwood + { "LARS" }, // Lars + { "PARK" }, // Sheila Parker (happy) + { "CHEM" }, // Chemist + { "GREG" }, // Inspector Gregson + { "LAWY" }, // Jacob Farthington Lawyer + { "MYCR" }, // Mycroft + { "SHER" }, // Old Sherman + { "CHMB" }, // Richard Chemist Stock boy + { "BARM" }, // Barman + { "DAND" }, // Dandy Player + { "ROUG" }, // Rough-looking Player + { "SPEC" }, // Spectator + { "HUNT" }, // Robert Hunt + { "VIOL" }, // Violet Secretary + { "PETT" }, // Pettigrew + { "APPL" }, // Augie (apple seller) + { "ANNA" }, // Anna Carroway + { "GUAR" }, // Guard + { "ANTO" }, // Antonio Caruso + { "TOBY" }, // Toby the Dog + { "KING" }, // Simon Kingsley + { "ALFR" }, // Alfred Tobacco Clerk + { "LADY" }, // Lady Brumwell + { "ROSA" }, // Madame Rosa + { "LADB" }, // Lady Brumwell + { "MOOR" }, // Joseph Moorehead + { "BEAL" }, // Mrs. Beale + { "LION" }, // Felix the Lion + { "HOLL" }, // Hollingston + { "CALL" }, // Constable Callaghan + { "JERE" }, // Sergeant Jeremy Duncan + { "LORD" }, // Lord Brumwell + { "NIGE" }, // Nigel Jameson + { "JONA" }, // Jonas (newspaper seller) + { "DUGA" }, // Constable Dugan + { "INSP" } // Inspector Lestrade (Scotland Yard) +}; + +const char *const NAMES[MAX_PEOPLE] = { + "Sherlock Holmes", + "Dr. Watson", + "Inspector Lestrade", + "Constable O'Brien", + "Constable Lewis", + "Sheila Parker", + "Henry Carruthers", + "Lesley", + "An Usher", + "An Usher", + "Fredrick Epstein", + "Mrs. Worthington", + "The Coach", + "A Player", + "Tim", + "James Sanders", + "Belle", + "Cleaning Girl", + "Fredrick Epstein", + "Wiggins", + "Paul", + "The Bartender", + "A Dirty Drunk", + "A Shouting Drunk", + "A Staggering Drunk", + "The Bouncer", + "James Sanders", + "The Coroner", + "Reginald Snipes", + "George Blackwood", + "Lars", + "Sheila Parker", + "The Chemist", + "Inspector Gregson", + "Jacob Farthington", + "Mycroft", + "Old Sherman", + "Richard", + "The Barman", + "A Dandy Player", + "A Rough-looking Player", + "A Spectator", + "Robert Hunt", + "Violet", + "Pettigrew", + "Augie", + "Anna Carroway", + "A Guard", + "Antonio Caruso", + "Toby the Dog", + "Simon Kingsley", + "Alfred", + "Lady Brumwell", + "Madame Rosa", + "Lady Brumwell", + "Joseph Moorehead", + "Mrs. Beale", + "Felix", + "Hollingston", + "Constable Callaghan", + "Sergeant Duncan", + "Lord Brumwell", + "Nigel Jaimeson", + "Jonas", + "Constable Dugan", + "Inspector Lestrade" +}; + +/*----------------------------------------------------------------*/ People::People(SherlockEngine *vm) : _vm(vm), _player(_data[0]) { _walkLoaded = false; @@ -63,6 +202,7 @@ People::People(SherlockEngine *vm) : _vm(vm), _player(_data[0]) { _talkPics = nullptr; _portraitSide = 0; _speakerFlip = false; + _holmesFlip = false; } People::~People() { @@ -439,6 +579,27 @@ void People::goAllTheWay() { } } +/** + * Finds the scene background object corresponding to a specified speaker + */ +int People::findSpeaker(int speaker) { + Scene &scene = *_vm->_scene; + + for (int idx = 0; idx < (int)scene._bgShapes.size(); ++idx) { + Object &obj = scene._bgShapes[idx]; + + if (obj._type == ACTIVE_BG_SHAPE) { + Common::String name(obj._name.c_str(), obj._name.c_str() + 4); + + if (scumm_stricmp(PORTRAITS[speaker], name.c_str()) == 0 + && obj._name[4] >= '0' && obj._name[4] <= '9') + return idx - 1; + } + } + + return -1; +} + /** * Turn off any currently active portraits, and removes them from being drawn */ @@ -472,9 +633,65 @@ void People::clearTalking() { } } -int People::findSpeaker(int speaker) { - // TODO - return -1; +/** + * Setup the data for an animating speaker portrait at the top of the screen + */ +void People::setTalking(int speaker) { + Resources &res = *_vm->_res; + + // If no speaker is specified, then we can exit immediately + if (speaker == -1) + return; + + if (_portraitsOn) { + delete _talkPics; + _talkPics = new ImageFile("portrait.lib"); + + // Load portrait sequences + Common::SeekableReadStream *stream = res.load("sequence.txt"); + stream->seek(speaker * MAX_FRAME); + + int idx = 0; + do { + _portrait._sequences[idx] = stream->readByte(); + ++idx; + } while (idx < 2 || _portrait._sequences[idx - 2] || _portrait._sequences[idx - 1]); + + delete stream; + + _portrait._maxFrames = idx; + _portrait._frameNumber = 0; + _portrait._sequenceNumber = 0; + _portrait._images = _talkPics; + _portrait._imageFrame = &(*_talkPics)[0]; + _portrait._position = Common::Point(_portraitSide, 10); + _portrait._delta = Common::Point(0, 0); + _portrait._oldPosition = Common::Point(0, 0); + _portrait._goto = Common::Point(0, 0); + _portrait._flags = 5; + _portrait._status = 0; + _portrait._misc = 0; + _portrait._allow = 0; + _portrait._type = ACTIVE_BG_SHAPE; + _portrait._name = " "; + _portrait._description = " "; + _portrait._examine = " "; + _portrait._walkCount = 0; + + if (_holmesFlip || _speakerFlip) { + _portrait._flags |= 2; + + _holmesFlip = false; + _speakerFlip = false; + } + + if (_portraitSide == 20) + _portraitSide = 220; + else + _portraitSide = 20; + + _portraitLoaded = true; + } } } // End of namespace Sherlock diff --git a/engines/sherlock/people.h b/engines/sherlock/people.h index 1a846dded1..bec078d11e 100644 --- a/engines/sherlock/people.h +++ b/engines/sherlock/people.h @@ -34,7 +34,7 @@ enum PeopleId { PLAYER = 0, AL = 0, PEG = 1, - MAX_PEOPLE = 2 + MAX_PEOPLE = 66 }; // Animation sequence identifiers for characters @@ -66,8 +66,8 @@ private: bool _walkLoaded; int _oldWalkSequence; int _srcZone, _destZone; - ImageFile *_talkPics; public: + ImageFile *_talkPics; Common::Point _walkDest; Common::Stack _walkTo; Person &_player; @@ -79,6 +79,7 @@ public: bool _allowWalkAbort; int _portraitSide; bool _speakerFlip; + bool _holmesFlip; public: People(SherlockEngine *vm); ~People(); @@ -102,9 +103,10 @@ public: void goAllTheWay(); - void clearTalking(); - int findSpeaker(int speaker); + + void clearTalking(); + void setTalking(int speaker); }; } // End of namespace Sherlock diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index 193c0f9a19..c97f2a0646 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -161,7 +161,6 @@ void Talk::talkTo(const Common::String &filename) { Scene &scene = *_vm->_scene; Screen &screen = *_vm->_screen; Scripts &scripts = *_vm->_scripts; - Talk &talk = *_vm->_talk; UserInterface &ui = *_vm->_ui; Common::Rect savedBounds = screen.getDisplayBounds(); bool abortFlag = false; @@ -202,10 +201,10 @@ void Talk::talkTo(const Common::String &filename) { people.gotoStand(people._player); } - if (talk._talkToAbort) + if (_talkToAbort) return; - talk.freeTalkVars(); + freeTalkVars(); // If any sequences have changed in the prior talk file, restore them if (_savedSequences.size() > 0) { @@ -928,8 +927,36 @@ void Talk::pushSequence(int speaker) { error("script stack overflow"); } +/** + * Change the sequence of the scene background object associated with the current speaker. + */ void Talk::setSequence(int speaker) { - // TODO + People &people = *_vm->_people; + Scene &scene = *_vm->_scene; + + // If no speaker is specified, then nothing needs to be done + if (speaker != -1) + return; + + if (speaker) { + int objNum = people.findSpeaker(speaker); + if (objNum != -1) { + Object &obj = scene._bgShapes[objNum]; + + if (obj._seqSize < MAX_TALK_SEQUENCES) { + warning("Tried to copy too many talk frames"); + } else { + for (int idx = 0; idx < MAX_TALK_SEQUENCES; ++idx) { + obj._sequences[idx] = TALK_SEQUENCES[speaker][idx]; + if (idx > 0 && !TALK_SEQUENCES[speaker][idx] && !TALK_SEQUENCES[speaker][idx - 1]) + return; + + obj._frameNumber = 0; + obj._sequenceNumber = 0; + } + } + } + } } /** @@ -1045,7 +1072,7 @@ void Talk::doScript(const Common::String &script) { } else { // Nope, so set the first speaker - setTalking(_speaker); + people.setTalking(_speaker); } } @@ -1068,7 +1095,7 @@ void Talk::doScript(const Common::String &script) { _scriptCurrentIndex = str - script.c_str(); if (!(_speaker & 128)) - clearTalking(); + people.clearTalking(); if (_talkToAbort) return; @@ -1077,7 +1104,7 @@ void Talk::doScript(const Common::String &script) { charCount = line = 0; _speaker = *++str - 1; - setTalking(_speaker); + people.setTalking(_speaker); pullSequence(); pushSequence(_speaker); setSequence(_speaker); @@ -1128,7 +1155,7 @@ void Talk::doScript(const Common::String &script) { _scriptCurrentIndex = str - script.c_str(); if (_speaker < 128) - clearTalking(); + people.clearTalking(); pullSequence(); if (_talkToAbort) return; @@ -1214,7 +1241,7 @@ void Talk::doScript(const Common::String &script) { _scriptCurrentIndex = str - script.c_str(); if (!(_speaker & 128)) - clearTalking(); + people.clearTalking(); pullSequence(); if (_talkToAbort) @@ -1426,11 +1453,13 @@ void Talk::doScript(const Common::String &script) { case WALK_TO_CANIMATION: { ++str; - int animIndex = str[0] - 1; + CAnim &anim = scene._cAnim[str[0] - 1]; // Save the current point in the script, since it might be intterupted by // doing bg anims in the next call, so we need to know where to return to _scriptCurrentIndex = (str + 1) - script.c_str(); + + people.walkToCoords(anim._goto, anim._gotoDir); if (_talkToAbort) return; break; @@ -1616,18 +1645,10 @@ void Talk::doScript(const Common::String &script) { pullSequence(); if (_speaker < 128) - clearTalking(); + people.clearTalking(); } } -void Talk::clearTalking() { - // TODO -} - -void Talk::setTalking(int speaker) { - // TODO -} - /** * When the talk window has been displayed, waits a period of time proportional to * the amount of text that's been displayed diff --git a/engines/sherlock/talk.h b/engines/sherlock/talk.h index 1b679a47bd..1a7dd587da 100644 --- a/engines/sherlock/talk.h +++ b/engines/sherlock/talk.h @@ -110,9 +110,6 @@ private: void doScript(const Common::String &script); - void clearTalking(); - void setTalking(int speaker); - int waitForMore(int delay); public: bool _talkToAbort; -- cgit v1.2.3 From 0f0321eb43fa321319805db8264601d0f2646282 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 11 Apr 2015 17:50:07 -0500 Subject: SHERLOCK: Fix startup initialization --- engines/sherlock/talk.cpp | 9 +++++++-- engines/sherlock/user_interface.cpp | 2 ++ 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index c97f2a0646..ec3f67bd84 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -134,7 +134,7 @@ Talk::Talk(SherlockEngine *vm): _vm(vm) { _talkStealth = 0; _talkToFlag = -1; _moreTalkDown = _moreTalkUp = false; - _scriptMoreFlag = 1; + _scriptMoreFlag = false; _scriptSaveIndex = -1; _scriptCurrentIndex = -1; } @@ -683,7 +683,7 @@ void Talk::drawInterface() { int strWidth = screen.stringWidth(PRESS_KEY_TO_CONTINUE); screen.makeButton(Common::Rect(46, CONTROLS_Y, 273, CONTROLS_Y + 10), 160 - strWidth, PRESS_KEY_TO_CONTINUE); - screen.gPrint(Common::Point(160 - strWidth / 2, CONTROLS_Y), COMMAND_FOREGROUND, false, "P"); + screen.gPrint(Common::Point(160 - strWidth / 2, CONTROLS_Y), COMMAND_FOREGROUND, "P"); } } @@ -880,6 +880,9 @@ void Talk::clearSequences() { void Talk::pullSequence() { Scene &scene = *_vm->_scene; + if (_scriptStack.empty()) + return; + SequenceEntry seq = _scriptStack.pop(); if (seq._objNum != -1) { Object &obj = scene._bgShapes[seq._objNum]; @@ -1518,6 +1521,8 @@ void Talk::doScript(const Common::String &script) { int width = 0, idx = 0; do { width += screen.charWidth(str[idx]); + ++idx; + ++charCount; } while (width < 298 && str[idx] && str[idx] != '{' && str[idx] < 128); if (str[idx] || width >= 298) { diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index 88265f6a19..2b808a085a 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -86,6 +86,8 @@ UserInterface::UserInterface(SherlockEngine *vm) : _vm(vm) { _find = 0; _oldUse = 0; _endKeyActive = true; + _lookScriptFlag = false; + _infoFlag = false; } UserInterface::~UserInterface() { -- cgit v1.2.3 From 461d5c64f27c2cf86890a9ba8d7df8a63f6278e7 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 11 Apr 2015 23:42:11 -0500 Subject: SHERLOCK: Fixes for opening door --- engines/sherlock/objects.cpp | 40 ++++++-- engines/sherlock/objects.h | 8 +- engines/sherlock/people.h | 15 ++- engines/sherlock/scene.cpp | 15 ++- engines/sherlock/talk.cpp | 2 +- engines/sherlock/user_interface.cpp | 197 +++++++++++++++++++++++++++++++++++- engines/sherlock/user_interface.h | 1 + 7 files changed, 254 insertions(+), 24 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index e4730ef207..dc57322bd4 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -248,7 +248,7 @@ void Sprite::checkSprite() { case TALK: case TALK_EVERY: - _type = HIDDEN; + obj._type = HIDDEN; obj.setFlagsAndToggles(); talk.talkTo(obj._use[0]._target); break; @@ -400,6 +400,36 @@ void Object::setVm(SherlockEngine *vm) { _countCAnimFrames = false; } +Object::Object() { + _sequenceOffset = 0; + _sequences = nullptr; + _images = nullptr; + _imageFrame = nullptr; + _walkCount = 0; + _allow = 0; + _frameNumber = 0; + _sequenceNumber = 0; + _type = INVALID; + _pickup = 0; + _defaultCommand = 0; + _lookFlag = 0; + _pickupFlag = 0; + _requiredFlag = 0; + _status = 0; + _misc = 0; + _maxFrames = 0; + _flags = 0; + _lookFrames = 0; + _seqCounter = 0; + _lookFacing = 0; + _lookcAnim = 0; + _seqStack = 0; + _seqTo = 0; + _descOffset = 0; + _seqCounter2 = 0; + _seqSize = 0; +} + /** * Load the object data from the passed stream */ @@ -770,7 +800,7 @@ void Object::setObjSequence(int seq, bool wait) { * @param messages Provides a lookup list of messages that can be printed * @returns 0 if no codes are found, 1 if codes were found */ -int Object::checkNameForCodes(const Common::String &name, Common::StringArray *messages) { +int Object::checkNameForCodes(const Common::String &name, const char *const messages[]) { People &people = *_vm->_people; Scene &scene = *_vm->_scene; Screen &screen = *_vm->_screen; @@ -851,15 +881,13 @@ int Object::checkNameForCodes(const Common::String &name, Common::StringArray *m int messageNum = atoi(name.c_str() + 1); ui._infoFlag++; ui.clearInfo(); - screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, - (*messages)[messageNum].c_str()); + screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, messages[messageNum]); ui._menuCounter = 25; } else if (name.hasPrefix("@")) { // Message attached to canimation ui._infoFlag++; ui.clearInfo(); - screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, - "%s", name.c_str() + 1); + screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, name.c_str() + 1); printed = true; ui._menuCounter = 25; } diff --git a/engines/sherlock/objects.h b/engines/sherlock/objects.h index 26ad1d3900..2c642b5a58 100644 --- a/engines/sherlock/objects.h +++ b/engines/sherlock/objects.h @@ -34,7 +34,7 @@ namespace Sherlock { class SherlockEngine; enum ObjectAllow { - ALLOW_MOVEMENT = 1, ALLOW_OPEN = 2, ALLOW_CLOSE = 4 + ALLOW_MOVE = 1, ALLOW_OPEN = 2, ALLOW_CLOSE = 4 }; enum SpriteType { @@ -122,6 +122,8 @@ public: int frameHeight() const { return _imageFrame ? _imageFrame->_frame.h : 0; } }; +enum { REVERSE_DIRECTION = 0x80 }; + struct ActionType { int8 _cAnimNum; uint8 _cAnimSpeed; // if high bit set, play in reverse @@ -198,13 +200,15 @@ public: ActionType _aMove; UseType _use[4]; + Object(); + void synchronize(Common::SeekableReadStream &s); void toggleHidden(); void checkObject(Object &o); - int checkNameForCodes(const Common::String &name, Common::StringArray *messages); + int checkNameForCodes(const Common::String &name, const char *const messages[]); void setFlagsAndToggles(); diff --git a/engines/sherlock/people.h b/engines/sherlock/people.h index bec078d11e..ba870d041d 100644 --- a/engines/sherlock/people.h +++ b/engines/sherlock/people.h @@ -34,7 +34,8 @@ enum PeopleId { PLAYER = 0, AL = 0, PEG = 1, - MAX_PEOPLE = 66 + NUM_OF_PEOPLE = 2, // Holmes and Watson + MAX_PEOPLE = 66 // Total of all NPCs }; // Animation sequence identifiers for characters @@ -62,7 +63,7 @@ public: class People { private: SherlockEngine *_vm; - Person _data[MAX_PEOPLE]; + Person _data[NUM_OF_PEOPLE]; bool _walkLoaded; int _oldWalkSequence; int _srcZone, _destZone; @@ -84,8 +85,14 @@ public: People(SherlockEngine *vm); ~People(); - Person &operator[](PeopleId id) { return _data[id]; } - Person &operator[](int idx) { return _data[idx]; } + Person &operator[](PeopleId id) { + assert(id < NUM_OF_PEOPLE); + return _data[id]; + } + Person &operator[](int idx) { + assert(idx < NUM_OF_PEOPLE); + return _data[idx]; + } bool isHolmesActive() const { return _walkLoaded && _holmesOn; } diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 3d5f566164..1cad2506e5 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -314,8 +314,8 @@ bool Scene::loadScene(const Common::String &filename) { for (uint idx = 0; idx < _zones.size(); ++idx) { _zones[idx].left = boundsStream->readSint16LE(); _zones[idx].top = boundsStream->readSint16LE(); - _zones[idx].setWidth(boundsStream->readSint16LE()); - _zones[idx].setHeight(boundsStream->readSint16LE()); + _zones[idx].setWidth(boundsStream->readSint16LE() + 1); + _zones[idx].setHeight(boundsStream->readSint16LE() + 1); boundsStream->skip(2); // Skip unused scene number field } @@ -925,20 +925,18 @@ int Scene::startCAnim(int cAnimNum, int playRate) { rrmStream->seek(rrmStream->readUint32LE()); // Load the canimation into the cache - Common::SeekableReadStream *imgStream = !_lzwMode ? rrmStream : + Common::SeekableReadStream *imgStream = !_lzwMode ? rrmStream->readStream(cAnim._size) : decompressLZ(*rrmStream, cAnim._size); res.addToCache(fname, *imgStream); - if (_lzwMode) - delete imgStream; - + delete imgStream; delete rrmStream; } // Now load the resource as an image - cObj._maxFrames = cObj._images->size(); cObj._images = new ImageFile(fname); cObj._imageFrame = &(*cObj._images)[0]; + cObj._maxFrames = cObj._images->size(); int frames = 0; if (playRate < 0) { @@ -946,8 +944,7 @@ int Scene::startCAnim(int cAnimNum, int playRate) { // Count number of frames while (cObj._sequences[frames] && frames < MAX_FRAME) ++frames; - } - else { + } else { // Forward direction Object::_countCAnimFrames = true; diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index ec3f67bd84..281b6b4672 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -583,7 +583,7 @@ void Talk::loadTalkFile(const Common::String &filename) { // Check for an existing person being talked to _talkTo = -1; - for (int idx = 0; idx < MAX_PEOPLE; ++idx) { + for (int idx = 0; idx < NUM_OF_PEOPLE; ++idx) { if (!scumm_strnicmp(filename.c_str(), people[(PeopleId)idx]._portrait.c_str(), 4)) { _talkTo = idx; break; diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index 2b808a085a..ebbe00ffbc 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -58,6 +58,25 @@ const char INVENTORY_COMMANDS[9] = { "ELUG-+,." }; const char *const PRESS_KEY_FOR_MORE = "Press any Key for More."; const char *const PRESS_KEY_TO_CONTINUE = "Press any Key to Continue."; +const char *const MOPEN[] = { + "This cannot be opened", "It is already open", "It is locked", "Wait for Watson", " ", "." +}; +const char *const MCLOSE[] = { + "This cannot be closed", "It is already closed", "The safe door is in the way" +}; +const char *const MMOVE[] = { + "This cannot be moved", "It is bolted to the floor", "It is too heavy", "The other crate is in the way" +}; +const char *const MPICK[] = { + "Nothing of interest here", "It is bolted down", "It is too big to carry", "It is too heavy", + "I think a girl would be more your type", "Those flowers belong to Penny", "She's far too young for you!", + "I think a girl would be more your type!", "Government property for official use only" +}; +const char *const MUSE[] = { + "You can't do that", "It had no effect", "You can't reach it", "OK, the door looks bigger! Happy?", + "Doors don't smoke" +}; + /*----------------------------------------------------------------*/ UserInterface::UserInterface(SherlockEngine *vm) : _vm(vm) { @@ -327,7 +346,7 @@ void UserInterface::handleInput() { break; case MOVE_MODE: - doMiscControl(ALLOW_MOVEMENT); + doMiscControl(ALLOW_MOVE); break; case TALK_MODE: @@ -1122,8 +1141,56 @@ void UserInterface::doMainControl() { } } +/** + * Handles the input for the MOVE, OPEN, and CLOSE commands + */ void UserInterface::doMiscControl(int allowed) { - // TODO + Events &events = *_vm->_events; + Scene &scene = *_vm->_scene; + Talk &talk = *_vm->_talk; + + if (events._released) { + _temp = _bgFound; + if (_bgFound != -1) { + // Only allow pointing to objects, not people + if (_bgFound < 1000) { + events.clearEvents(); + Object &obj = scene._bgShapes[_bgFound]; + + switch (allowed) { + case ALLOW_OPEN: + checkAction(obj._aOpen, MOPEN, _temp); + if (_menuMode && !talk._talkToAbort) { + _menuMode = STD_MODE; + restoreButton(OPEN_MODE - 1); + _key = _oldKey = -1; + } + break; + + case ALLOW_CLOSE: + checkAction(obj._aClose, MCLOSE, _temp); + if (_menuMode != TALK_MODE && !talk._talkToAbort) { + _menuMode = STD_MODE; + restoreButton(CLOSE_MODE - 1); + _key = _oldKey = -1; + } + break; + + case ALLOW_MOVE: + checkAction(obj._aMove, MMOVE, _temp); + if (_menuMode != TALK_MODE && !talk._talkToAbort) { + _menuMode = STD_MODE; + restoreButton(MOVE_MODE - 1); + _key = _oldKey = -1; + } + break; + + default: + break; + } + } + } + } } void UserInterface::doPickControl() { @@ -1503,5 +1570,131 @@ void UserInterface::checkUseAction(UseType &use, const Common::String &invName, // TODO } +/** + * Called for OPEN, CLOSE, and MOVE actions are being done + */ +void UserInterface::checkAction(ActionType &action, const char *const messages[], int objNum) { + Events &events = *_vm->_events; + People &people = *_vm->_people; + Scene &scene = *_vm->_scene; + Screen &screen = *_vm->_screen; + Talk &talk = *_vm->_talk; + bool printed = false; + bool doCAnim = true; + int cAnimNum; + Common::Point pt(-1, -1); + int dir = -1; + + if (objNum >= 1000) + // Ignore actions done on characters + return; + Object &obj = scene._bgShapes[objNum]; + + if (action._cAnimNum == 0) + // Really a 10 + cAnimNum = 9; + else + cAnimNum = action._cAnimNum - 1; + CAnim &anim = scene._cAnim[cAnimNum]; + + if (action._cAnimNum != 99) { + if (action._cAnimSpeed & REVERSE_DIRECTION) { + pt = anim._teleportPos; + dir = anim._teleportDir; + } else { + pt = anim._goto; + dir = anim._gotoDir; + } + } + + if (action._cAnimSpeed) { + // Has a value, so do action + // Show wait cursor whilst walking to object and doing action + events.setCursor(WAIT); + + for (int nameIdx = 0; nameIdx < 4; ++nameIdx) { + if (action._names[nameIdx].hasPrefix("*") && toupper(action._names[nameIdx][1]) == 'W') { + if (obj.checkNameForCodes(Common::String(action._names[nameIdx].c_str() + 2), messages)) { + if (!talk._talkToAbort) + printed = true; + } + } + } + + for (int nameIdx = 0; nameIdx < 4; ++nameIdx) { + if (action._names[nameIdx].hasPrefix("*")) { + char ch = toupper(action._names[nameIdx][1]); + + if (ch == 'T' || ch == 'B') { + printed = true; + if (pt.x != -1) + // Holmes needs to walk to object before the action is done + people.walkToCoords(pt, dir); + + if (!talk._talkToAbort) { + // Ensure Holmes is on the exact intended location + people[AL]._position = pt; + people[AL]._sequenceNumber = dir; + people.gotoStand(people[AL]); + + talk.talkTo(action._names[nameIdx] + 2); + if (ch == 'T') + doCAnim = false; + } + } + } + } + + if (doCAnim && !talk._talkToAbort) { + if (pt.x != -1) + // Holmes needs to walk to object before the action is done + people.walkToCoords(pt, dir); + } + + for (int nameIdx = 0; nameIdx < 4; ++nameIdx) { + if (action._names[nameIdx].hasPrefix("*") && toupper(action._names[nameIdx][1]) == 'F') { + if (obj.checkNameForCodes(action._names[nameIdx].c_str() + 2, messages)) { + if (!talk._talkToAbort) + printed = true; + } + } + } + + if (doCAnim && !talk._talkToAbort && action._cAnimNum != 99) + scene.startCAnim(cAnimNum, action._cAnimSpeed); + + if (!talk._talkToAbort) { + for (int nameIdx = 0; nameIdx < 4 && !talk._talkToAbort; ++nameIdx) { + if (obj.checkNameForCodes(action._names[nameIdx], messages)) { + if (!talk._talkToAbort) + printed = true; + } + } + + // Unless we're leaving the scene, print a "Done" message unless the printed flag has been set + if (scene._goToScene != 1 && !printed && !talk._talkToAbort) { + _infoFlag = true; + clearInfo(); + screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, messages[action._cAnimNum]); + + // Set how long to show the message + _menuCounter = 30; + } + } + } else { + // Invalid action, to print error message + _infoFlag = true; + clearInfo(); + screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, messages[action._cAnimNum]); + _infoFlag = true; + + // Set how long to show the message + _menuCounter = 30; + } + + // Reset cursor back to arrow + events.setCursor(ARROW); +} + } // End of namespace Sherlock diff --git a/engines/sherlock/user_interface.h b/engines/sherlock/user_interface.h index f80fe48b2d..9b104465cf 100644 --- a/engines/sherlock/user_interface.h +++ b/engines/sherlock/user_interface.h @@ -117,6 +117,7 @@ private: void checkUseAction(UseType &use, const Common::String &invName, const Common::String &msg, int objNum, int giveMode); + void checkAction(ActionType &action, const char *const messages[], int objNum); public: MenuMode _menuMode; int _menuCounter; -- cgit v1.2.3 From 454b6a2bbe38a4540769ad5cf51290b7a19524e4 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 12 Apr 2015 11:06:25 -0500 Subject: SHERLOCK: Implemented pick up code --- engines/sherlock/inventory.h | 3 +- engines/sherlock/objects.cpp | 91 +++++++++++++++++++++++++++++++++++++ engines/sherlock/objects.h | 2 + engines/sherlock/user_interface.cpp | 27 ++++++++++- engines/sherlock/user_interface.h | 1 + 5 files changed, 121 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/inventory.h b/engines/sherlock/inventory.h index 436d2bc18d..4e426beaf4 100644 --- a/engines/sherlock/inventory.h +++ b/engines/sherlock/inventory.h @@ -62,8 +62,6 @@ class Inventory : public Common::Array { private: SherlockEngine *_vm; - int putItemInInventory(Object &obj); - void copyToInventory(Object &obj); public: ImageFile *_invShapes[MAX_VISIBLE_INVENTORY]; @@ -98,6 +96,7 @@ public: void doInvJF(); int putNameInInventory(const Common::String &name); + int putItemInInventory(Object &obj); int deleteItemFromInventory(const Common::String &name); }; diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index dc57322bd4..cab35f9634 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -947,6 +947,97 @@ void Object::adjustObject() { } } +/** + * Handles trying to pick up an object. If allowed, plays an y necessary animation for picking + * up the item, and then adds it to the player's inventory + */ +int Object::pickUpObject(const char *const messages[]) { + Inventory &inv = *_vm->_inventory; + People &people = *_vm->_people; + Scene &scene = *_vm->_scene; + Screen &screen = *_vm->_screen; + Talk &talk = *_vm->_talk; + UserInterface &ui = *_vm->_ui; + int pickup = _pickup & 0x7f; + bool printed = false; + bool takeFlag = true; + int numObjects = 0; + int message; + + if (pickup == 99) { + for (int idx = 0; idx < 4 && !talk._talkToAbort; ++idx) { + if (checkNameForCodes(_use[0]._names[idx], nullptr)) { + if (!talk._talkToAbort) + printed = true; + } + } + + return 0; + } + + if (!pickup || (pickup > 50 && pickup <= 80)) { + int message = _pickup; + if (message > 50) + message -= 50; + + ++ui._infoFlag; + ui.clearInfo(); + screen.print(Common::Point(0, INFO_LINE + 1), INFO_LINE, messages[message]); + ui._menuCounter = 30; + } else { + // Pick it up + if ((_pickup & 0x80) == 0) { + // Play an animation + if (pickup > 80) { + takeFlag = false; // Don't pick it up + scene.startCAnim(pickup - 81, 1); + if (_pickupFlag) + _vm->setFlags(_pickupFlag); + } else { + scene.startCAnim(pickup - 1, 1); + if (!talk._talkToAbort) { + // Erase the shape + _type = _type == NO_SHAPE ? INVALID : REMOVE; + } + } + + if (talk._talkToAbort) + return 0; + } else { + // Play generic pickup sequence + // Original moved cursor position here + people.goAllTheWay(); + ui._menuCounter = 25; + ui._temp1 = 1; + } + + for (int idx = 0; idx < 4 && !talk._talkToAbort; ++idx) { + if (checkNameForCodes(_use[0]._names[idx], nullptr)) { + if (!talk._talkToAbort) + printed = true; + } + } + if (talk._talkToAbort) + return 0; + + // Add the item to the player's inventory + if (takeFlag) + numObjects = inv.putItemInInventory(*this); + + if (!printed) { + ui._infoFlag++; + ui.clearInfo(); + + Common::String itemName = _description; + itemName.setChar(tolower(itemName[0]), 0); + screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "Picked up %s", itemName.c_str()); + ui._menuCounter = 25; + } + } + + return numObjects; +} + /** * Returns the current bounds for the sprite */ diff --git a/engines/sherlock/objects.h b/engines/sherlock/objects.h index 2c642b5a58..534ed66643 100644 --- a/engines/sherlock/objects.h +++ b/engines/sherlock/objects.h @@ -214,6 +214,8 @@ public: void adjustObject(); + int pickUpObject(const char *const messages[]); + int frameWidth() const { return _imageFrame ? _imageFrame->_frame.w : 0; } int frameHeight() const { return _imageFrame ? _imageFrame->_frame.h : 0; } const Common::Rect getNewBounds() const; diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index ebbe00ffbc..9104c761a0 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -92,6 +92,7 @@ UserInterface::UserInterface(SherlockEngine *vm) : _vm(vm) { _lookHelp = 0; _key = _oldKey = 0; _temp = _oldTemp = 0; + _temp1 = 0; _invLookFlag = 0; _windowOpen = false; _oldLook = false; @@ -711,6 +712,9 @@ void UserInterface::lookInv() { } } +/** + * Handles input when the file list window is being displayed + */ void UserInterface::doEnvControl() { // TODO } @@ -1193,8 +1197,29 @@ void UserInterface::doMiscControl(int allowed) { } } +/** + * Handles input for picking up items + */ void UserInterface::doPickControl() { - // TODO + Events &events = *_vm->_events; + Scene &scene = *_vm->_scene; + + if (events._released) { + if ((_temp = _bgFound) != -1) { + events.clearEvents(); + + // Don't allow characters to be picked up + if (_bgFound < 1000) { + scene._bgShapes[_bgFound].pickUpObject(MPICK); + + if (_menuMode != TALK_MODE) { + _key = _oldKey = -1; + _menuMode = STD_MODE; + restoreButton(PICKUP_MODE - 1); + } + } + } + } } void UserInterface::doTalkControl() { diff --git a/engines/sherlock/user_interface.h b/engines/sherlock/user_interface.h index 9b104465cf..c4a07abc76 100644 --- a/engines/sherlock/user_interface.h +++ b/engines/sherlock/user_interface.h @@ -125,6 +125,7 @@ public: bool _windowOpen; bool _endKeyActive; int _invLookFlag; + int _temp1; public: UserInterface(SherlockEngine *vm); ~UserInterface(); -- cgit v1.2.3 From c9890cbacc7bf6a1216cadf6eddc04832f0ebbe4 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 12 Apr 2015 17:55:55 -0500 Subject: SHERLOCK: Implementing event handling for talk display --- engines/sherlock/people.cpp | 1 + engines/sherlock/people.h | 1 + engines/sherlock/talk.h | 4 +- engines/sherlock/user_interface.cpp | 254 +++++++++++++++++++++++++++++++++++- 4 files changed, 258 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp index 5c7f9ef506..e6a4eeed0f 100644 --- a/engines/sherlock/people.cpp +++ b/engines/sherlock/people.cpp @@ -203,6 +203,7 @@ People::People(SherlockEngine *vm) : _vm(vm), _player(_data[0]) { _portraitSide = 0; _speakerFlip = false; _holmesFlip = false; + _homesQuotient = 0; } People::~People() { diff --git a/engines/sherlock/people.h b/engines/sherlock/people.h index ba870d041d..601fe6006b 100644 --- a/engines/sherlock/people.h +++ b/engines/sherlock/people.h @@ -81,6 +81,7 @@ public: int _portraitSide; bool _speakerFlip; bool _holmesFlip; + int _homesQuotient; public: People(SherlockEngine *vm); ~People(); diff --git a/engines/sherlock/talk.h b/engines/sherlock/talk.h index 1a7dd587da..c4b5fe46d2 100644 --- a/engines/sherlock/talk.h +++ b/engines/sherlock/talk.h @@ -79,8 +79,10 @@ struct TalkSequences { }; class SherlockEngine; +class UserInterface; class Talk { + friend class UserInterface; private: Common::Array STILL_SEQUENCES; Common::Array TALK_SEQUENCES; @@ -97,7 +99,6 @@ private: int _converseNum; int _talkStealth; int _talkToFlag; - bool _moreTalkUp, _moreTalkDown; int _scriptSaveIndex; int _scriptCurrentIndex; private: @@ -117,6 +118,7 @@ public: int _talkTo; int _scriptMoreFlag; Common::String _scriptName; + bool _moreTalkUp, _moreTalkDown; public: Talk(SherlockEngine *vm); void setSequences(const byte *talkSequences, const byte *stillSequences, diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index 9104c761a0..70f284c359 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -1222,8 +1222,260 @@ void UserInterface::doPickControl() { } } +/** + * Handles input when in talk mode. It highlights the buttons and available statements, + * and handles allowing the user to click on them + */ void UserInterface::doTalkControl() { - // TODO + Events &events = *_vm->_events; + Journal &journal = *_vm->_journal; + People &people = *_vm->_people; + Screen &screen = *_vm->_screen; + Sound &sound = *_vm->_sound; + Talk &talk = *_vm->_talk; + UserInterface &ui = *_vm->_ui; + Common::Point mousePos = events.mousePos(); + int select; + + _key = _oldKey = -1; + _keyboardInput = false; + + if (events._pressed || events._released) { + events.clearKeyboard(); + + // Handle button printing + if (mousePos.x > 99 && mousePos.x < 138 && mousePos.y > CONTROLS_Y && mousePos.y < (CONTROLS_Y + 10) && !_endKeyActive) + screen.buttonPrint(Common::Point(119, CONTROLS_Y), COMMAND_HIGHLIGHTED, true, "Exit"); + else if (_endKeyActive) + screen.buttonPrint(Common::Point(119, CONTROLS_Y), COMMAND_FOREGROUND, true, "Exit"); + + if (mousePos.x > 140 && mousePos.x < 170 && mousePos.y > CONTROLS_Y && mousePos.y < (CONTROLS_Y + 10) && talk._moreTalkUp) + screen.buttonPrint(Common::Point(159, CONTROLS_Y), COMMAND_HIGHLIGHTED, true, "Up"); + else if (talk._moreTalkUp) + screen.buttonPrint(Common::Point(159, CONTROLS_Y), COMMAND_FOREGROUND, true, "Up"); + + if (mousePos.x > 181&& mousePos.x < 220 && mousePos.y > CONTROLS_Y && mousePos.y < (CONTROLS_Y + 10) && talk._moreTalkDown) + screen.buttonPrint(Common::Point(200, CONTROLS_Y), COMMAND_HIGHLIGHTED, true, "Down"); + else if (talk._moreTalkDown) + screen.buttonPrint(Common::Point(200, CONTROLS_Y), COMMAND_FOREGROUND, true, "Down"); + + bool found = false; + for (_selector = talk._talkIndex; _selector < (int)talk._statements.size() && !found; ++_selector) { + if (mousePos.y > talk._statements[_selector]._talkPos.top && + mousePos.y < talk._statements[_selector]._talkPos.bottom) + found = true; + } + --_selector; + if (!found) + _selector = -1; + } + + if (_keycode != Common::KEYCODE_INVALID) { + _key = toupper(_keycode); + if (_key == Common::KEYCODE_ESCAPE) + _key = 'E'; + + // Check for number press indicating reply line + if (_key >= '1' && _key <= ('1' + (int)talk._statements.size() - 1)) { + for (uint idx = 0; idx < talk._statements.size(); ++idx) { + if (talk._statements[idx]._talkMap == (_key - '1')) { + // Found the given statement + _selector = idx; + _key = -1; + _keyboardInput = true; + break; + } + } + } else if (_key == 'E' || _key == 'U' || _key == 'D') { + _keyboardInput = true; + } else { + _selector = -1; + } + } + + if (_selector != _oldSelector) { + // Remove highlighting from previous line, if any + if (_oldSelector != -1) { + if (!((talk._talkHistory[talk._converseNum][_oldSelector] >> (_oldSelector & 7)) & 1)) + talk.talkLine(_oldSelector, talk._statements[_oldSelector]._talkMap, INV_FOREGROUND, + talk._statements[_oldSelector]._talkPos.top, true); + else + talk.talkLine(_oldSelector, talk._statements[_oldSelector]._talkMap, TALK_NULL, + talk._statements[_oldSelector]._talkPos.top, true); + } + + // Add highlighting to new line, if any + if (_selector != -1) + talk.talkLine(_selector, talk._statements[_selector]._talkMap, TALK_FOREGROUND, + talk._statements[_selector]._talkPos.top, true); + } + + if (events._released || _keyboardInput) { + if (_endKeyActive && ((mousePos.x > 99 && mousePos.y > CONTROLS_Y && mousePos.y < (CONTROLS_Y + 10) + && talk._moreTalkUp && events._released) || _key == 'E')) { + talk.freeTalkVars(); + talk.pullSequence(); + banishWindow(); + _windowBounds.top = CONTROLS_Y1; + } else if ((mousePos.x > 140 && mousePos.x < 179 && mousePos.y > CONTROLS_Y && mousePos.y < (CONTROLS_Y + 10) + && talk._moreTalkUp && events._released) || (talk._moreTalkUp && _key == 'U')) { + while (talk._statements[--talk._talkIndex]._talkMap == -1) + ; + screen._backBuffer1.fillRect(Common::Rect(5, CONTROLS_Y + 11, SHERLOCK_SCREEN_WIDTH - 2, + SHERLOCK_SCREEN_HEIGHT - 1), INV_BACKGROUND); + talk.displayTalk(false); + + screen.slamRect(Common::Rect(5, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH - 5, SHERLOCK_SCREEN_HEIGHT - 2)); + } else if ((mousePos.x > 181 && mousePos.x < 220 && mousePos.y > CONTROLS_Y && mousePos.y < (CONTROLS_Y + 10) + && talk._moreTalkDown && events._released) || (talk._moreTalkDown && _key == 'D')) { + do { + ++talk._talkIndex; + } while (talk._talkIndex < (int)talk._statements.size() && talk._statements[talk._talkIndex]._talkMap == -1); + + screen._backBuffer1.fillRect(Common::Rect(5, CONTROLS_Y + 11, SHERLOCK_SCREEN_WIDTH - 2, + SHERLOCK_SCREEN_HEIGHT - 1), INV_BACKGROUND); + talk.displayTalk(false); + + screen.slamRect(Common::Rect(5, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH - 5, SHERLOCK_SCREEN_HEIGHT - 2)); + } else if (_selector != -1) { + screen.buttonPrint(Common::Point(119, CONTROLS_Y), COMMAND_NULL, true, "Exit"); + screen.buttonPrint(Common::Point(159, CONTROLS_Y), COMMAND_NULL, true, "Up"); + screen.buttonPrint(Common::Point(200, CONTROLS_Y), COMMAND_NULL, true, "Down"); + + // If the reply is new, add it to the journal + if (!talk._talkHistory[talk._converseNum][_selector]) { + journal.record(talk._converseNum, _selector); + + // Add any Holmes point to Holmes' total, if any + if (talk._statements[_selector]._quotient) + people._homesQuotient += talk._statements[_selector]._quotient; + } + + // Flag the response as having been used + talk._talkHistory[talk._converseNum][_selector] = true; + + clearWindow(); + screen.print(Common::Point(16, CONTROLS_Y + 12), TALK_FOREGROUND, "Sherlock Holmes"); + talk.talkLine(_selector + 128, talk._statements[_selector]._talkMap, COMMAND_FOREGROUND, CONTROLS_Y + 21, true); + + switch (talk._statements[_selector]._portraitSide & 3) { + case 0: + case 1: + people._portraitSide = 20; + break; + case 2: + people._portraitSide = 220; + break; + case 3: + people._portraitSide = 120; + break; + } + + // Check for flipping Holmes + if (talk._statements[_selector]._portraitSide & REVERSE_DIRECTION) + people._holmesFlip = true; + + talk._speaker = 0; + people.setTalking(0); + + if (!talk._statements[_selector]._voiceFile.empty() && sound._voices) { + sound.playSound(talk._statements[_selector]._voiceFile); + + // Set voices as an indicator for waiting + sound._voices = 2; + sound._speechOn = *sound._soundIsOn; + } else { + sound._speechOn = false; + } + + // Set the _scriptCurrentIndex so if the statement is irrupted, the entire + // reply will be shown when it's restarted + talk._scriptCurrentIndex = 0; + talk.waitForMore(talk._statements[_selector]._statement.size()); + if (talk._talkToAbort) + return; + + people.clearTalking(); + if (talk._talkToAbort) + return; + + while (!_vm->shouldQuit()) { + talk._scriptSelect = _selector; + talk._speaker = talk._talkTo; + talk.doScript(talk._statements[_selector]._reply); + + if (!talk._talkToAbort) { + if (!talk._talkStealth) + clearWindow(); + + if (!talk._statements[_selector]._modified.empty()) { + for (uint idx = 0; idx < talk._statements[_selector]._modified.size(); ++idx) { + _vm->setFlags(talk._statements[_selector]._modified[idx]); + } + + talk.setTalkMap(); + } + + // Check for another linked talk file + Common::String linkFilename = talk._statements[_selector]._linkFile; + if (!linkFilename.empty() && !talk._scriptMoreFlag) { + talk.freeTalkVars(); + talk.loadTalkFile(linkFilename); + + // Find the first new statement + select = _selector = _oldSelector = -1; + for (uint idx = 0; idx < talk._statements.size() && select == -1; ++idx) { + if (!talk._statements[idx]._talkMap) + select = talk._talkIndex = idx; + } + + // See if the new statement is a stealth reply + talk._talkStealth = talk._statements[select]._statement.hasPrefix("^") ? 2 : 0; + + // Is the new talk file a standard file, reply first file, or a stealth file + if (!talk._statements[select]._statement.hasPrefix("*") && + !talk._statements[select]._statement.hasPrefix("^")) { + // Not a reply first file, so display the new selections + if (_endKeyActive) + screen.buttonPrint(Common::Point(119, CONTROLS_Y), COMMAND_FOREGROUND, true, "Exit"); + else + screen.buttonPrint(Common::Point(119, CONTROLS_Y), COMMAND_NULL, true, "Exit"); + + talk.displayTalk(true); + events.setCursor(ARROW); + break; + } else { + _selector = select; + + if (!talk._talkHistory[talk._converseNum][_selector]) + journal.record(talk._converseNum, _selector); + + talk._talkHistory[talk._converseNum][_selector] = true; + } + } else { + talk.freeTalkVars(); + talk.pullSequence(); + banishWindow(); + _windowBounds.top = CONTROLS_Y1; + break; + } + } else { + break; + } + } + + events._pressed = events._released = false; + events._oldButtons = 0; + talk._talkStealth = 0; + + // If a script was pushed onto the script stack, restore it + if (!talk._scriptStack.empty()) { + SequenceEntry seqEntry = talk._scriptStack.pop(); +// talk._scriptName = seqEntry. + // TODO + } + } + } } void UserInterface::journalControl() { -- cgit v1.2.3 From e8e095aa2ad7f3914b3b8dd4826c2d13e35b1163 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 12 Apr 2015 19:11:34 -0500 Subject: SHERLOCK: Fix mixups with sequence stack and script stack --- engines/sherlock/talk.cpp | 6 +++--- engines/sherlock/talk.h | 3 ++- engines/sherlock/user_interface.cpp | 8 ++++---- 3 files changed, 9 insertions(+), 8 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index 281b6b4672..a40d3ace2d 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -883,7 +883,7 @@ void Talk::pullSequence() { if (_scriptStack.empty()) return; - SequenceEntry seq = _scriptStack.pop(); + SequenceEntry seq = _sequenceStack.pop(); if (seq._objNum != -1) { Object &obj = scene._bgShapes[seq._objNum]; @@ -911,7 +911,7 @@ void Talk::pushSequence(int speaker) { if (speaker == -1) return; - ScriptStackEntry seqEntry; + SequenceEntry seqEntry; if (!speaker) { seqEntry._objNum = -1; } else { @@ -925,7 +925,7 @@ void Talk::pushSequence(int speaker) { seqEntry._seqTo = obj._seqTo; } - _scriptStack.push(seqEntry); + _sequenceStack.push(seqEntry); if (_scriptStack.size() >= 5) error("script stack overflow"); } diff --git a/engines/sherlock/talk.h b/engines/sherlock/talk.h index c4b5fe46d2..bf4f12675c 100644 --- a/engines/sherlock/talk.h +++ b/engines/sherlock/talk.h @@ -40,7 +40,7 @@ struct SequenceEntry { int _seqTo; }; -struct ScriptStackEntry : public SequenceEntry { +struct ScriptStackEntry { Common::String _name; int _currentIndex; int _select; @@ -90,6 +90,7 @@ private: SherlockEngine *_vm; int _saveSeqNum; Common::Stack _savedSequences; + Common::Stack _sequenceStack; Common::Stack _scriptStack; Common::Array _statements; TalkHistoryEntry _talkHistory[500]; diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index 70f284c359..e20813822e 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -1233,7 +1233,6 @@ void UserInterface::doTalkControl() { Screen &screen = *_vm->_screen; Sound &sound = *_vm->_sound; Talk &talk = *_vm->_talk; - UserInterface &ui = *_vm->_ui; Common::Point mousePos = events.mousePos(); int select; @@ -1470,9 +1469,10 @@ void UserInterface::doTalkControl() { // If a script was pushed onto the script stack, restore it if (!talk._scriptStack.empty()) { - SequenceEntry seqEntry = talk._scriptStack.pop(); -// talk._scriptName = seqEntry. - // TODO + ScriptStackEntry stackEntry = talk._scriptStack.pop(); + talk._scriptName = stackEntry._name; + talk._scriptSaveIndex = stackEntry._currentIndex; + talk._scriptSelect = stackEntry._select; } } } -- cgit v1.2.3 From d521ece7cb46ade23cdb2d342a0537716dd11400 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Sun, 12 Apr 2015 20:13:47 -0400 Subject: MOHAWK: Set dithering on any original Myst video Fixes display of the library "swirl" video --- engines/mohawk/video.cpp | 4 ---- 1 file changed, 4 deletions(-) (limited to 'engines') diff --git a/engines/mohawk/video.cpp b/engines/mohawk/video.cpp index ca38f22b7a..3f27e4a1a4 100644 --- a/engines/mohawk/video.cpp +++ b/engines/mohawk/video.cpp @@ -572,10 +572,6 @@ void VideoManager::checkEnableDither(VideoEntry &entry) { if (!_enableDither) return; - // Ignore any video which is already 8bpp - if (entry->getPixelFormat().bytesPerPixel == 1) - return; - // Set the palette byte palette[256 * 3]; g_system->getPaletteManager()->grabPalette(palette, 0, 256); -- cgit v1.2.3 From cf878316ea66e75b715f8467ff82594fa3a32604 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 12 Apr 2015 23:20:22 -0500 Subject: SHERLOCK: Implement settings window code --- engines/sherlock/screen.h | 2 + engines/sherlock/sherlock.cpp | 5 + engines/sherlock/sherlock.h | 4 + engines/sherlock/user_interface.cpp | 317 +++++++++++++++++++++++++++++++++++- engines/sherlock/user_interface.h | 13 ++ 5 files changed, 340 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sherlock/screen.h b/engines/sherlock/screen.h index 4e37a7787c..2cfd7c8a88 100644 --- a/engines/sherlock/screen.h +++ b/engines/sherlock/screen.h @@ -126,6 +126,8 @@ public: void setDisplayBounds(const Common::Rect &r); void resetDisplayBounds(); Common::Rect getDisplayBounds(); + + int fontNumber() const { return _fontNumber; } }; } // End of namespace Sherlock diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index 2a1b456b76..72c072b640 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -48,6 +48,7 @@ SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gam _loadingSavedGame = false; _onChessboard = false; _slowChess = false; + _keyPadSpeed = 0; } SherlockEngine::~SherlockEngine() { @@ -177,4 +178,8 @@ void SherlockEngine::freeSaveGameList() { // TODO } +void SherlockEngine::saveConfig() { + // TODO +} + } // End of namespace Comet diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h index 7b562e0a23..ef10cd2d47 100644 --- a/engines/sherlock/sherlock.h +++ b/engines/sherlock/sherlock.h @@ -106,6 +106,8 @@ public: Common::Array _map; // Map locations for each scene bool _onChessboard; bool _slowChess; + bool _joystick; + int _keyPadSpeed; public: SherlockEngine(OSystem *syst, const SherlockGameDescription *gameDesc); virtual ~SherlockEngine(); @@ -127,6 +129,8 @@ public: void setFlags(int flagNum); void freeSaveGameList(); + + void saveConfig(); }; } // End of namespace Sherlock diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index e20813822e..651844fd66 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -53,6 +53,23 @@ const int INVENTORY_POINTS[8][3] = { { 285, 315, 294 } }; +const int SETUP_POINTS[12][4] = { + { 4, 154, 101, 53 }, // Exit + { 4, 165, 101, 53 }, // Music Toggle + { 219, 165, 316, 268 }, // Voice Toggle + { 103, 165, 217, 160 }, // Sound Effects Toggle + { 219, 154, 316, 268 }, // Help Button Left/Right + { 103, 154, 217, 160 }, // New Font Style + { 4, 187, 101, 53 }, // Joystick Toggle + { 103, 187, 217, 160 }, // Calibrate Joystick + { 219, 176, 316, 268 }, // Fade Style + { 103, 176, 217, 160 }, // Window Open Style + { 4, 176, 101, 53 }, // Portraits Toggle + { 219, 187, 316, 268 } // Key Pad Accel. Toggle +}; + + + const char COMMANDS[13] = "LMTPOCIUGJFS"; const char INVENTORY_COMMANDS[9] = { "ELUG-+,." }; const char *const PRESS_KEY_FOR_MORE = "Press any Key for More."; @@ -77,6 +94,162 @@ const char *const MUSE[] = { "Doors don't smoke" }; +const char *const SETUP_STRS0[2] = { "off", "on" }; +const char *const SETUP_STRS1[2] = { "Directly", "by Pixel" }; +const char *const SETUP_STRS2[2] = { "Left", "Right" }; +const char *const SETUP_STRS3[2] = { "Appear", "Slide" }; +const char *const SETUP_STRS4[2] = { "Slow", "Fast" }; +const char *const SETUP_STRS5[2] = { "Left", "Right" }; +const char *const SETUP_NAMES[12] = { + "Exit", "M", "V", "S", "B", "New Font Style", "J", "Calibrate Joystick", "F", "W", "P", "K" +}; + +/*----------------------------------------------------------------*/ + +/** + * Draws the interface for the settings window + */ +void Settings::drawInteface(bool flag) { + People &people = *_vm->_people; + Screen &screen = *_vm->_screen; + Sound &sound = *_vm->_sound; + UserInterface &ui = *_vm->_ui; + Common::String tempStr; + + if (!flag) { + screen._backBuffer1.fillRect(Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH, CONTROLS_Y1 + 1), BORDER_COLOR); + screen._backBuffer1.fillRect(Common::Rect(0, CONTROLS_Y1 + 1, 2, SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR); + screen._backBuffer1.fillRect(Common::Rect(SHERLOCK_SCREEN_WIDTH - 2, CONTROLS_Y1 + 1, SHERLOCK_SCREEN_WIDTH, + SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR); + screen._backBuffer1.hLine(0, SHERLOCK_SCREEN_HEIGHT - 1, SHERLOCK_SCREEN_WIDTH - 1, BORDER_COLOR); + screen._backBuffer1.fillRect(Common::Rect(2, CONTROLS_Y1 + 1, SHERLOCK_SCREEN_WIDTH - 2, + SHERLOCK_SCREEN_HEIGHT - 2), INV_BACKGROUND); + } + + screen.makeButton(Common::Rect(SETUP_POINTS[0][0], SETUP_POINTS[0][1], SETUP_POINTS[0][2], SETUP_POINTS[0][1] + 10), + SETUP_POINTS[0][3] - screen.stringWidth("Exit") / 2, "Exit"); + + tempStr = Common::String::format("Music %s", SETUP_STRS0[sound._music]); + screen.makeButton(Common::Rect(SETUP_POINTS[1][0], SETUP_POINTS[1][1], SETUP_POINTS[1][2], SETUP_POINTS[1][1] + 10), + SETUP_POINTS[1][3] - screen.stringWidth(tempStr) / 2, tempStr); + + tempStr = Common::String::format("Voices %s", SETUP_STRS0[sound._voices]); + screen.makeButton(Common::Rect(SETUP_POINTS[2][0], SETUP_POINTS[2][1], SETUP_POINTS[2][2], SETUP_POINTS[2][1] + 10), + SETUP_POINTS[2][3] - screen.stringWidth(tempStr) / 2, tempStr); + + tempStr = Common::String::format("Sound Effects %s", SETUP_STRS0[sound._digitized]); + screen.makeButton(Common::Rect(SETUP_POINTS[3][0], SETUP_POINTS[3][1], SETUP_POINTS[3][2], SETUP_POINTS[3][1] + 10), + SETUP_POINTS[3][3] - screen.stringWidth(tempStr) / 2, tempStr); + + tempStr = Common::String::format("Auto Help %s", SETUP_STRS5[ui._helpStyle]); + screen.makeButton(Common::Rect(SETUP_POINTS[4][0], SETUP_POINTS[4][1], SETUP_POINTS[4][2], SETUP_POINTS[4][1] + 10), + SETUP_POINTS[4][3] - screen.stringWidth(tempStr) / 2, tempStr); + screen.makeButton(Common::Rect(SETUP_POINTS[5][0], SETUP_POINTS[5][1], SETUP_POINTS[5][2], SETUP_POINTS[5][1] + 10), + SETUP_POINTS[5][3] - screen.stringWidth("New Font Style") / 2, "New Font Style"); + tempStr = Common::String::format("Joystick %s", SETUP_STRS0[_vm->_joystick ? 1 : 0]); + screen.makeButton(Common::Rect(SETUP_POINTS[6][0], SETUP_POINTS[6][1], SETUP_POINTS[6][2], SETUP_POINTS[6][1] + 10), + SETUP_POINTS[6][3] - screen.stringWidth(tempStr) / 2, tempStr); + screen.makeButton(Common::Rect(SETUP_POINTS[7][0], SETUP_POINTS[7][1], SETUP_POINTS[7][2], SETUP_POINTS[7][1] + 10), + SETUP_POINTS[7][3] - screen.stringWidth("Calibrate Joystick") / 2, "Calibrate Joystick"); + + tempStr = Common::String::format("Fade %s", screen._fadeStyle ? "by Pixel" : "Directly"); + screen.makeButton(Common::Rect(SETUP_POINTS[8][0], SETUP_POINTS[8][1], SETUP_POINTS[8][2], SETUP_POINTS[8][1] + 10), + SETUP_POINTS[8][3] - screen.stringWidth(tempStr) / 2, tempStr); + + tempStr = Common::String::format("Windows %s", ui._windowStyle ? "Slide" : "Appear"); + screen.makeButton(Common::Rect(SETUP_POINTS[9][0], SETUP_POINTS[9][1], SETUP_POINTS[9][2], SETUP_POINTS[9][1] + 10), + SETUP_POINTS[9][3] - screen.stringWidth(tempStr) / 2, tempStr); + + tempStr = Common::String::format("Portraits %s", SETUP_STRS0[people._portraitsOn]); + screen.makeButton(Common::Rect(SETUP_POINTS[10][0], SETUP_POINTS[10][1], SETUP_POINTS[10][2], SETUP_POINTS[10][1] + 10), + SETUP_POINTS[10][3] - screen.stringWidth(tempStr) / 2, tempStr); + tempStr = Common::String::format("Key Pad %s", _vm->_keyPadSpeed ? "Fast" : "Slow"); + + screen.makeButton(Common::Rect(SETUP_POINTS[11][0], SETUP_POINTS[11][1], SETUP_POINTS[11][2], SETUP_POINTS[11][1] + 10), + SETUP_POINTS[11][3] - screen.stringWidth(tempStr) / 2, tempStr); + + // Show the window immediately, or slide it on-screen + if (!flag) { + if (!ui._windowStyle) { + screen.slamRect(Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); + } else { + ui.summonWindow(true, CONTROLS_Y1); + } + + ui._windowOpen = true; + } else { + screen.slamRect(Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); + } +} + +int Settings::drawButtons(const Common::Point &pt, int key) { + Events &events = *_vm->_events; + People &people = *_vm->_people; + Screen &screen = *_vm->_screen; + Sound &sound = *_vm->_sound; + UserInterface &ui = *_vm->_ui; + int found = -1; + byte color; + Common::String tempStr; + + for (int idx = 0; idx < 12; ++idx) { + if ((pt.x > SETUP_POINTS[idx][0] && pt.x < SETUP_POINTS[idx][2] && pt.y > SETUP_POINTS[idx][1] + && pt.y < (SETUP_POINTS[idx][1] + 10) && (events._released || events._released)) + || (key == SETUP_NAMES[idx][0])) { + found = idx; + color = COMMAND_HIGHLIGHTED; + } else { + color = COMMAND_FOREGROUND; + } + + // Print the button text + switch (idx) { + case 1: + tempStr = Common::String::format("Music %s", SETUP_STRS0[sound._music]); + screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr); + break; + case 2: + tempStr = Common::String::format("Voices %s", SETUP_STRS0[sound._voices]); + screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr); + break; + case 3: + tempStr = Common::String::format("Sound Effects %s", SETUP_STRS0[sound._digitized]); + screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr); + break; + case 4: + tempStr = Common::String::format("Auto Help %s", SETUP_STRS2[ui._helpStyle]); + screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr); + break; + case 6: + tempStr = Common::String::format("Joystick %s", SETUP_STRS0[_vm->_joystick]); + screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr); + break; + case 8: + tempStr = Common::String::format("Fade %s", SETUP_STRS1[screen._fadeStyle]); + screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr); + break; + case 9: + tempStr = Common::String::format("Windows %s", SETUP_STRS3[ui._windowStyle]); + screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr); + break; + case 10: + tempStr = Common::String::format("Portraits %s", SETUP_STRS0[people._portraitsOn]); + screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr); + break; + case 11: + tempStr = Common::String::format("Key Pad %s", SETUP_STRS4[_vm->_keyPadSpeed]); + screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr); + break; + default: + screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, SETUP_NAMES[idx]); + break; + } + } + + return found; +} + + /*----------------------------------------------------------------*/ UserInterface::UserInterface(SherlockEngine *vm) : _vm(vm) { @@ -1531,8 +1704,150 @@ void UserInterface::environment() { // TODO } +/** + * Handles input when the settings window is being shown + */ void UserInterface::doControls() { - // TODO + Events &events = *_vm->_events; + People &people = *_vm->_people; + Scene &scene = *_vm->_scene; + Screen &screen = *_vm->_screen; + Sound &sound = *_vm->_sound; + Talk &talk = *_vm->_talk; + UserInterface &ui = *_vm->_ui; + int found; + byte color; + bool updateConfig = false; + + Settings settings(_vm); + settings.drawInteface(false); + + do { + if (_menuCounter) + whileMenuCounter(); + + found = -1; + _key = -1; + + scene.doBgAnim(); + if (talk._talkToAbort) + return; + + events.setButtonState(); + Common::Point pt = events.mousePos(); + + if (events._pressed || events._released || events.kbHit()) { + clearInfo(); + _key = -1; + + if (events.kbHit()) { + Common::KeyState keyState = events.getKey(); + _key = toupper(keyState.keycode); + + if (_key == Common::KEYCODE_RETURN || _key == Common::KEYCODE_SPACE) { + events._pressed = false; + events._oldButtons = 0; + _keycode = Common::KEYCODE_INVALID; + events._released = true; + } + } + + // Handle highlighting button under mouse + found = settings.drawButtons(pt, _key); + } + + if ((found == 0 && events._released) || (_key == 'E' || _key == Common::KEYCODE_ESCAPE)) + // Exit + break; + + if ((found == 1 && events._released) || _key == 'M') { + // Toggle music + if (sound._music) { + sound.stopSound(); + sound._music = false; + } else { + sound._music = true; + sound.startSong(); + } + + updateConfig = true; + settings.drawInteface(true); + } + + if ((found == 2 && events._released) || _key == 'V') { + sound._voices = !sound._voices; + updateConfig = true; + settings.drawInteface(true); + } + + if ((found == 3 && events._released) || _key == 'S') { + // Toggle sound effects + sound._digitized = !sound._digitized; + updateConfig = true; + settings.drawInteface(true); + } + + if ((found == 4 && events._released) || _key == 'A') { + // Help button style + ui._helpStyle ^= 1; + updateConfig = true; + settings.drawInteface(true); + } + + if ((found == 5 && events._released) || _key == 'N') { + // New font style + screen.setFont((screen.fontNumber() + 1) & 3); + } + + if ((found == 6 && events._released) || _key == 'J') { + // Toggle joystick + _vm->_joystick = !_vm->_joystick; + updateConfig = true; + settings.drawInteface(true); + } + + if ((found == 7 && events._released) || _key == 'C') { + // Calibrate joystick - No implementation in ScummVM + } + + if ((found == 8 && events._released) || _key == 'F') { + // Toggle fade style + screen._fadeStyle = !screen._fadeStyle; + updateConfig = true; + settings.drawInteface(true); + } + + if ((found == 9 && events._released) || _key == 'W') { + // Window style + ui._windowStyle ^= 1; + updateConfig = true; + settings.drawInteface(true); + } + + if ((found == 10 && events._released) || _key == 'P') { + // Toggle portraits being shown + people._portraitsOn = !people._portraitsOn; + updateConfig = true; + settings.drawInteface(true); + } + + if ((found == 11 && events._released) || _key == 'K') { + // Toggle keypad acceleration speed + _vm->_keyPadSpeed ^= 1; + updateConfig = true; + settings.drawInteface(true); + } + } while (!_vm->shouldQuit()); + + banishWindow(); + + if (updateConfig) + _vm->saveConfig(); + + _keycode = Common::KEYCODE_INVALID; + _keyboardInput = false; + _windowBounds.top = CONTROLS_Y1; + _key = -1; } /** diff --git a/engines/sherlock/user_interface.h b/engines/sherlock/user_interface.h index c4a07abc76..eaa8a3654b 100644 --- a/engines/sherlock/user_interface.h +++ b/engines/sherlock/user_interface.h @@ -61,9 +61,22 @@ extern const char *const PRESS_KEY_TO_CONTINUE; class SherlockEngine; class Inventory; class Talk; +class UserInterface; + +class Settings { +private: + SherlockEngine *_vm; +public: + Settings(SherlockEngine *vm) : _vm() {} + + void drawInteface(bool flag); + + int drawButtons(const Common::Point &pt, int key); +}; class UserInterface { friend class Inventory; + friend class Settings; friend class Talk; private: SherlockEngine *_vm; -- cgit v1.2.3 From 537f33d9cf60fffdd473ae3cd32e2abffc9cb24f Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 13 Apr 2015 18:08:20 +0200 Subject: SCI: script patch for qfg3 hero export bug #6807 --- engines/sci/engine/script_patches.cpp | 64 +++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) (limited to 'engines') diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp index 711078d29c..6d5b49f441 100644 --- a/engines/sci/engine/script_patches.cpp +++ b/engines/sci/engine/script_patches.cpp @@ -2344,12 +2344,76 @@ static const uint16 qfg3PatchWooDialogAlt[] = { PATCH_END }; +// When exporting characters at the end of Quest for Glory 3, the underlying +// code has issues with values, that are above 9999. +// For further study: https://github.com/Blazingstix/QFGImporter/blob/master/QFGImporter/QFGImporter/QFG3.txt +// +// If a value is above 9999, parts or even the whole character file will get corrupted. +// +// We are fixing the code because of that. We are patching code, that is calculating the checksum +// and add extra code to lower such values to 9999. +// +// Applies to at least: English, French, German, Italian, Spanish floppy +// Responsible method: saveHero::changeState +// Fixes bug #6807 +static const uint16 qfg3SignatureExportChar[] = { + 0x35, SIG_ADDTOOFFSET(+1), // ldi 00 / ldi 01 (2 loops, we patch both) + 0xa5, 0x00, // sat temp[0] [contains index to data] + 0x8d, 0x00, // lst temp[0] + SIG_MAGICDWORD, + 0x35, 0x2c, // ldi 2c + 0x22, // lt? [index above or equal 2Ch (44d)? + 0x31, 0x23, // bnt [exit loop] + // from this point it's actually useless code, maybe a sci compiler bug + 0x8d, 0x00, // lst temp[0] + 0x35, 0x01, // ldi 01 + 0x02, // add + 0x9b, 0x00, // lsli local[0] ---------- load local[0 + ACC] onto stack + 0x8d, 0x00, // lst temp[0] + 0x35, 0x01, // ldi 01 + 0x02, // add + 0xb3, 0x00, // sali local[0] ---------- save stack to local[0 + ACC] + // end of useless code + 0x8b, SIG_ADDTOOFFSET(+1), // lsl local[36h/37h] ---- load local[36h/37h] onto stack + 0x8d, 0x00, // lst temp[0] + 0x35, 0x01, // ldi 01 + 0x02, // add + 0x93, 0x00, // lali local[0] ---------- load local[0 + ACC] into ACC + 0x02, // add -------------------- add ACC + stack and put into ACC + 0xa3, SIG_ADDTOOFFSET(+1), // sal local[36h/37h] ---- save ACC to local[36h/37h] + 0x8d, 0x00, // lst temp[0] ------------ temp[0] to stack + 0x35, 0x02, // ldi 02 + 0x02, // add -------------------- add 2 to stack + 0xa5, 0x00, // sat temp[0] ------------ save ACC to temp[0] + 0x33, 0xd6, // jmp [loop] + SIG_END +}; + +static const uint16 qfg3PatchExportChar[] = { + PATCH_ADDTOOFFSET(+11), + 0x85, 0x00, // lat temp[0] + 0x9b, 0x01, // lsli local[0] + 1 ------ load local[ ACC + 1] onto stack + 0x3c, // dup + 0x34, PATCH_UINT16(0x2710), // ldi 2710h (10000d) + 0x2c, // ult? ------------------- is value smaller than 10000? + 0x2f, 0x0a, // bt [jump over] + 0x3a, // toss + 0x38, PATCH_UINT16(0x270f), // pushi 270fh (9999d) + 0x3c, // dup + 0x85, 0x00, // lat temp[0] + 0xba, PATCH_UINT16(0x0001), // ssli local[0] + 1 ------ save stack to local[ ACC + 1] (UINT16 to waste 1 byte) + // jump offset + 0x83, PATCH_GETORIGINALBYTE(+26), // lal local[37h/36h] ---- load local[37h/36h] into ACC + 0x02, // add -------------------- add local[37h/36h] + data value + PATCH_END +}; // script, description, signature patch static const SciScriptPatcherEntry qfg3Signatures[] = { { true, 944, "import dialog continuous calls", 1, qfg3SignatureImportDialog, qfg3PatchImportDialog }, { true, 440, "dialog crash when asking about Woo", 1, qfg3SignatureWooDialog, qfg3PatchWooDialog }, { true, 440, "dialog crash when asking about Woo", 1, qfg3SignatureWooDialogAlt, qfg3PatchWooDialogAlt }, + { true, 52, "export character save bug", 2, qfg3SignatureExportChar, qfg3PatchExportChar }, SCI_SIGNATUREENTRY_TERMINATOR }; -- cgit v1.2.3 From 3483799959926d130bcabc1da7e424501a6ef173 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 13 Apr 2015 18:26:12 +0200 Subject: SCI: add french qfg3 export filename for fix Sierra translator translated the filename --- engines/sci/engine/kgraphics.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index ee2249bd9d..7d24dd861f 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -955,8 +955,9 @@ reg_t kDrawControl(EngineState *s, int argc, reg_t *argv) { reg_t textReference = readSelector(s->_segMan, controlObject, SELECTOR(text)); if (!textReference.isNull()) { Common::String text = s->_segMan->getString(textReference); - if ((text == "a:hq1_hero.sav") || (text == "a:glory1.sav") || (text == "a:glory2.sav") || (text == "a:glory3.sav")) { + if ((text == "a:hq1_hero.sav") || (text == "a:glory1.sav") || (text == "a:glory2.sav") || (text == "a:glory3.sav") || (text == "a:gloire3.sauv")) { // Remove "a:" from hero quest / quest for glory export default filenames + // The french version of Quest For Glory 3 uses "gloire3.sauv". It seems a translator translated the filename. text.deleteChar(0); text.deleteChar(0); s->_segMan->strcpy(textReference, text.c_str()); -- cgit v1.2.3 From 3be28b495dbedc3a94b366edd6178cbf0941cc77 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 13 Apr 2015 20:10:35 -0500 Subject: SHERLOCK: Implemented checkUseAction --- engines/sherlock/user_interface.cpp | 105 +++++++++++++++++++++++++++++++++--- engines/sherlock/user_interface.h | 3 +- 2 files changed, 98 insertions(+), 10 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index 651844fd66..dc87cf130c 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -1115,12 +1115,10 @@ void UserInterface::doInvControl() { if (_selector >= 0) // Use/Give inv object with scene object - checkUseAction(scene._bgShapes[_find]._use[0], inv[_selector]._name, - _muse, _find, temp - 2); + checkUseAction(&scene._bgShapes[_find]._use[0], inv[_selector]._name, MUSE, _find, temp - 2); else // Now inv object has been highlighted - checkUseAction(scene._bgShapes[_find]._use[0], "*SELF", _muse, - _find, temp - 2); + checkUseAction(&scene._bgShapes[_find]._use[0], "*SELF", MUSE, _find, temp - 2); _selector = _oldSelector = -1; } @@ -1716,7 +1714,6 @@ void UserInterface::doControls() { Talk &talk = *_vm->_talk; UserInterface &ui = *_vm->_ui; int found; - byte color; bool updateConfig = false; Settings settings(_vm); @@ -2157,9 +2154,101 @@ void UserInterface::banishWindow(bool slideUp) { _menuMode = STD_MODE; } -void UserInterface::checkUseAction(UseType &use, const Common::String &invName, - const Common::String &msg, int objNum, int giveMode) { - // TODO +/** + * Checks to see whether a USE action is valid on the given object + */ +void UserInterface::checkUseAction(const UseType *use, const Common::String &invName, + const char *const messages[], int objNum, int giveMode) { + Events &events = *_vm->_events; + Inventory &inv = *_vm->_inventory; + Scene &scene = *_vm->_scene; + Screen &screen = *_vm->_screen; + Talk &talk = *_vm->_talk; + bool printed = messages == nullptr; + + if (objNum >= 1000) { + // Holmes was specified, so do nothing + _infoFlag = true; + clearInfo(); + _infoFlag = true; + + // Display error message + _menuCounter = 30; + screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "You can't do that to yourself."); + return; + } + + // Scan for target item + int targetNum = -1; + if (giveMode) { + for (int idx = 0; idx < 4 && targetNum == -1; ++idx) { + if ((scumm_stricmp(use[idx]._target.c_str(), "*GIVE*") == 0 || scumm_stricmp(use[idx]._target.c_str(), "*GIVEP*") == 0) + && scumm_stricmp(use[idx]._names[0].c_str(), invName.c_str()) == 0) { + // Found a match + targetNum = idx; + if (scumm_stricmp(use[idx]._target.c_str(), "*GIVE*") == 0) + inv.deleteItemFromInventory(invName); + } + } + } else { + for (int idx = 0; idx < 4 && targetNum == -1; ++idx) { + if (scumm_stricmp(use[idx]._target.c_str(), invName.c_str()) == 0) + targetNum = idx; + } + } + + if (targetNum != -1) { + // Found a target, so do the action + const UseType &action = use[targetNum]; + int messageNum = action._cAnimNum; + + events.setCursor(WAIT); + + if (action._useFlag) + _vm->setFlags(action._useFlag); + + if (action._cAnimNum != 99) { + if (action._cAnimNum == 0) + scene.startCAnim(9, action._cAnimSpeed); + else + scene.startCAnim(action._cAnimNum - 1, action._cAnimSpeed); + } + + if (!talk._talkToAbort) { + Object &obj = scene._bgShapes[objNum]; + for (int idx = 0; idx < 4 && !talk._talkToAbort; ++idx) { + if (obj.checkNameForCodes(action._names[idx], messages)) { + if (!talk._talkToAbort) + printed = true; + } + } + + // Print "Done..." as an ending, unless flagged for leaving scene or otherwise flagged + if (scene._goToScene != 1 && !printed && !talk._talkToAbort) { + _infoFlag++; + clearInfo(); + screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "Done..."); + _menuCounter = 25; + } + } + } else { + // Couldn't find target, so print error + _infoFlag = true; + clearInfo(); + + if (giveMode) { + screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "No, thank you."); + } else if (messages == nullptr) { + screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "You can't do that."); + } else { + screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, messages[0]); + } + + _infoFlag = true; + _menuCounter = 30; + } + + events.setCursor(ARROW); } /** diff --git a/engines/sherlock/user_interface.h b/engines/sherlock/user_interface.h index eaa8a3654b..23aca4e536 100644 --- a/engines/sherlock/user_interface.h +++ b/engines/sherlock/user_interface.h @@ -101,7 +101,6 @@ private: Common::String _descStr; int _windowStyle; int _find; - Common::String _muse; int _oldUse; private: void depressButton(int num); @@ -128,7 +127,7 @@ private: void environment(); void doControls(); - void checkUseAction(UseType &use, const Common::String &invName, const Common::String &msg, + void checkUseAction(const UseType *use, const Common::String &invName, const char *const messages[], int objNum, int giveMode); void checkAction(ActionType &action, const char *const messages[], int objNum); public: -- cgit v1.2.3 From 38b6aa70a82fb05ee7e1581a239e054a9d304827 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 13 Apr 2015 22:55:07 -0500 Subject: SHERLOCK: Fixes for talk setup and portrait loading --- engines/sherlock/objects.cpp | 1 - engines/sherlock/people.cpp | 8 ++++++-- engines/sherlock/people.h | 3 +++ engines/sherlock/sound.cpp | 6 +++--- engines/sherlock/talk.cpp | 35 ++++++++++++++++++----------------- engines/sherlock/user_interface.cpp | 3 +-- 6 files changed, 31 insertions(+), 25 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index cab35f9634..4cf26a3ad7 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -962,7 +962,6 @@ int Object::pickUpObject(const char *const messages[]) { bool printed = false; bool takeFlag = true; int numObjects = 0; - int message; if (pickup == 99) { for (int idx = 0; idx < 4 && !talk._talkToAbort; ++idx) { diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp index e6a4eeed0f..5dd50e7e94 100644 --- a/engines/sherlock/people.cpp +++ b/engines/sherlock/people.cpp @@ -196,7 +196,7 @@ People::People(SherlockEngine *vm) : _vm(vm), _player(_data[0]) { _oldWalkSequence = -1; _allowWalkAbort = false; _portraitLoaded = false; - _portraitsOn = false; + _portraitsOn = true; _clearingThePortrait = false; _srcZone = _destZone = 0; _talkPics = nullptr; @@ -204,12 +204,15 @@ People::People(SherlockEngine *vm) : _vm(vm), _player(_data[0]) { _speakerFlip = false; _holmesFlip = false; _homesQuotient = 0; + + _portrait._sequences = new byte[32]; } People::~People() { if (_walkLoaded) delete _data[PLAYER]._images; delete _talkPics; + delete[] _portrait._sequences; } void People::reset() { @@ -646,7 +649,8 @@ void People::setTalking(int speaker) { if (_portraitsOn) { delete _talkPics; - _talkPics = new ImageFile("portrait.lib"); + Common::String filename = Common::String::format("%s.vgs", PORTRAITS[speaker]); + _talkPics = new ImageFile(filename); // Load portrait sequences Common::SeekableReadStream *stream = res.load("sequence.txt"); diff --git a/engines/sherlock/people.h b/engines/sherlock/people.h index 601fe6006b..593b516ee6 100644 --- a/engines/sherlock/people.h +++ b/engines/sherlock/people.h @@ -51,6 +51,9 @@ enum { MAP_DOWN = 5, MAP_DOWNLEFT = 6, MAP_LEFT = 2, MAP_UPLEFT = 8 }; +extern const char *const NAMES[MAX_PEOPLE]; +extern const char PORTRAITS[MAX_PEOPLE][5]; + class SherlockEngine; class Person: public Sprite { diff --git a/engines/sherlock/sound.cpp b/engines/sherlock/sound.cpp index 771d5db9d5..c3e50a8be2 100644 --- a/engines/sherlock/sound.cpp +++ b/engines/sherlock/sound.cpp @@ -25,9 +25,9 @@ namespace Sherlock { Sound::Sound(SherlockEngine *vm): _vm(vm) { - _soundOn = true; - _musicOn = true; - _speechOn = true; + _soundOn = false; + _musicOn = false; + _speechOn = false; _voices = 0; _playingEpilogue = false; _music = false; diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index a40d3ace2d..279e6de69a 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -96,9 +96,9 @@ void Statement::synchronize(Common::SeekableReadStream &s) { // Read in flag required/modified data for (uint idx = 0; idx < _required.size(); ++idx) - _required[idx] = s.readUint16LE(); + _required[idx] = s.readSint16LE(); for (uint idx = 0; idx < _modified.size(); ++idx) - _modified[idx] = s.readUint16LE(); + _modified[idx] = s.readSint16LE(); _portraitSide = s.readByte(); _quotient = s.readUint16LE(); @@ -583,8 +583,8 @@ void Talk::loadTalkFile(const Common::String &filename) { // Check for an existing person being talked to _talkTo = -1; - for (int idx = 0; idx < NUM_OF_PEOPLE; ++idx) { - if (!scumm_strnicmp(filename.c_str(), people[(PeopleId)idx]._portrait.c_str(), 4)) { + for (int idx = 0; idx < MAX_PEOPLE; ++idx) { + if (!scumm_strnicmp(filename.c_str(), PORTRAITS[idx], 4)) { _talkTo = idx; break; } @@ -1036,7 +1036,7 @@ void Talk::doScript(const Common::String &script) { ui.clearWindow(); // Need to switch speakers? - if (str[0] == SWITCH_SPEAKER) { + if ((byte)str[0] == SWITCH_SPEAKER) { _speaker = str[1] - 1; str += 2; pullSequence(); @@ -1048,7 +1048,7 @@ void Talk::doScript(const Common::String &script) { } // Assign portrait location? - if (str[0] == ASSIGN_PORTRAIT_LOCATION) { + if ((byte)str[0] == ASSIGN_PORTRAIT_LOCATION) { switch (str[1] & 15) { case 1: people._portraitSide = 20; @@ -1083,15 +1083,16 @@ void Talk::doScript(const Common::String &script) { Common::String tempString; wait = 0; - if (!str[0]) { + byte c = (byte)str[0]; + if (!c) { endStr = true; - } else if (str[0] == '{') { + } else if (c == '{') { // Start of comment, so skip over it while (*str++ != '}') ; - } else if (str[0] >= 128) { + } else if (c >= 128) { // Handle control code - switch (str[0]) { + switch (c) { case SWITCH_SPEAKER: // Save the current point in the script, since it might be intterupted by // doing bg anims in the next call, so we need to know where to return to @@ -1157,7 +1158,7 @@ void Talk::doScript(const Common::String &script) { // doing bg anims in the next call, so we need to know where to return to _scriptCurrentIndex = str - script.c_str(); - if (_speaker < 128) + if (_speaker >= 0 && _speaker < 128) people.clearTalking(); pullSequence(); if (_talkToAbort) @@ -1508,9 +1509,9 @@ void Talk::doScript(const Common::String &script) { // If the window is open, display the name directly on-screen. // Otherwise, simply draw it on the back buffer if (ui._windowOpen) { - screen.print(Common::Point(16, yp), TALK_FOREGROUND, inv._names[_speaker & 127].c_str()); + screen.print(Common::Point(16, yp), TALK_FOREGROUND, NAMES[_speaker & 127]); } else { - screen.gPrint(Common::Point(16, yp - 1), TALK_FOREGROUND, inv._names[_speaker & 127].c_str()); + screen.gPrint(Common::Point(16, yp - 1), TALK_FOREGROUND, NAMES[_speaker & 127]); openTalkWindow = true; } @@ -1523,10 +1524,10 @@ void Talk::doScript(const Common::String &script) { width += screen.charWidth(str[idx]); ++idx; ++charCount; - } while (width < 298 && str[idx] && str[idx] != '{' && str[idx] < 128); + } while (width < 298 && str[idx] && str[idx] != '{' && (byte)str[idx] < 128); if (str[idx] || width >= 298) { - if (str[idx] < 128 && str[idx] != '{') { + if ((byte)str[idx] < 128 && str[idx] != '{') { --idx; --charCount; } @@ -1565,7 +1566,7 @@ void Talk::doScript(const Common::String &script) { str += idx; // If line wrap occurred, then move to after the separating space between the words - if (str[0] < 128 && str[0] != '{') + if ((byte)str[0] < 128 && str[0] != '{') ++str; yp += 9; @@ -1578,7 +1579,7 @@ void Talk::doScript(const Common::String &script) { wait = 1; } - switch (str[0]) { + switch ((byte)str[0]) { case SWITCH_SPEAKER: case ASSIGN_PORTRAIT_LOCATION: case BANISH_WINDOW: diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index dc87cf130c..43ae76f94b 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -2200,7 +2200,6 @@ void UserInterface::checkUseAction(const UseType *use, const Common::String &inv if (targetNum != -1) { // Found a target, so do the action const UseType &action = use[targetNum]; - int messageNum = action._cAnimNum; events.setCursor(WAIT); @@ -2318,7 +2317,7 @@ void UserInterface::checkAction(ActionType &action, const char *const messages[] people[AL]._sequenceNumber = dir; people.gotoStand(people[AL]); - talk.talkTo(action._names[nameIdx] + 2); + talk.talkTo(action._names[nameIdx].c_str() + 2); if (ch == 'T') doCAnim = false; } -- cgit v1.2.3 From 97d3df3c9e7faa4b9925765c4612d341848cf08c Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 13 Apr 2015 23:37:39 -0500 Subject: SHERLOCK: Fix for animating chracter portraits when talking --- engines/sherlock/scene.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'engines') diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 1cad2506e5..8a6681b5e0 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -1171,6 +1171,9 @@ void Scene::doBgAnim() { o.adjustObject(); } + if (people._portraitLoaded && people._portrait._type == ACTIVE_BG_SHAPE) + people._portrait.adjustObject(); + for (uint idx = 0; idx < _canimShapes.size(); ++idx) { if (_canimShapes[idx]._type != INVALID) _canimShapes[idx].adjustObject(); -- cgit v1.2.3 From fb32222177a89c7a6701fa359131cb06ff15cbda Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Tue, 14 Apr 2015 14:59:55 +0200 Subject: SCI: add workaround for Hoyle 4 Euchre (bug 6602) --- engines/sci/engine/workarounds.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines') diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index ed45e294a2..998d7cc041 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -96,6 +96,7 @@ const SciWorkaroundEntry uninitializedReadWorkarounds[] = { { GID_HOYLE4, 300, 300, 0, "", "export 2", 0x1d4d, 0, { WORKAROUND_FAKE, 0 } }, // after passing around cards in hearts { GID_HOYLE4, 400, 400, 1, "GinHand", "calcRuns", -1, 4, { WORKAROUND_FAKE, 0 } }, // sometimes while playing Gin Rummy (e.g. when knocking and placing a card) - bug #5665 { GID_HOYLE4, 500, 17, 1, "Character", "say", -1, 504, { WORKAROUND_FAKE, 0 } }, // sometimes while playing Cribbage (e.g. when the opponent says "Last Card") - bug #5662 + { GID_HOYLE4, 800, 870, 0, "EuchreStrategy", "thinkLead", -1, 0, { WORKAROUND_FAKE, 0 } }, // while playing Euchre, happens at least on 2nd or 3rd turn - bug #6602 { GID_HOYLE4, -1, 937, 0, "IconBar", "dispatchEvent", -1, 408, { WORKAROUND_FAKE, 0 } }, // pressing ENTER on scoreboard while mouse is not on OK button, may not happen all the time - bug #6603 { GID_ISLANDBRAIN, 100, 937, 0, "IconBar", "dispatchEvent", -1, 58, { WORKAROUND_FAKE, 0 } }, // when using ENTER at the startup menu - bug #5241 { GID_ISLANDBRAIN, 140, 140, 0, "piece", "init", -1, 3, { WORKAROUND_FAKE, 1 } }, // first puzzle right at the start, some initialization variable. bnt is done on it, and it should be non-0 -- cgit v1.2.3 From c58325b519371064348b747c957a89d009ac12ba Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 14 Apr 2015 19:53:03 -0500 Subject: SHERLOCK: Fix scene transition --- engines/sherlock/objects.cpp | 28 ++++++++++++++-------------- engines/sherlock/scene.cpp | 10 +++++++--- 2 files changed, 21 insertions(+), 17 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index 4cf26a3ad7..ca1bdfb2c5 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -693,24 +693,24 @@ bool Object::checkEndOfSequence() { setObjSequence(seq, false); } } - } - if (_allow && _frameNumber == 0) { - // canimation just ended - if (_type != NO_SHAPE && _type != REMOVE) { - _type = REMOVE; + if (_allow && _frameNumber == 0) { + // canimation just ended + if (_type != NO_SHAPE && _type != REMOVE) { + _type = REMOVE; - if (!_countCAnimFrames) { - // Save details before shape is removed - _delta.x = _imageFrame->_frame.w; - _delta.y = _imageFrame->_frame.h; - _position = _imageFrame->_offset; + if (!_countCAnimFrames) { + // Save details before shape is removed + _delta.x = _imageFrame->_frame.w; + _delta.y = _imageFrame->_frame.h; + _position = _imageFrame->_offset; - // Free the images - delete _images; + // Free the images + delete _images; + } + } else { + _type = INVALID; } - } else { - _type = INVALID; } } diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 8a6681b5e0..1ce2183af1 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -663,13 +663,13 @@ void Scene::transitionToScene() { if (cAnimNum != -1) { CAnim &c = _cAnim[cAnimNum]; - Common::Point pt = c._position; + Common::Point pt = c._goto; - c._position = Common::Point(-1, -1); + c._goto = Common::Point(-1, -1); people[AL]._position = Common::Point(0, 0); startCAnim(cAnimNum, 1); - c._position = pt; + c._goto = pt; } } @@ -875,7 +875,9 @@ int Scene::startCAnim(int cAnimNum, int playRate) { tpDir = cAnim._teleportDir; } + CursorId oldCursor = events.getCursor(); events.setCursor(WAIT); + _canimShapes.push_back(Object()); Object &cObj = _canimShapes[_canimShapes.size() - 1]; @@ -1040,6 +1042,8 @@ int Scene::startCAnim(int cAnimNum, int playRate) { people.gotoStand(people[AL]); } + events.setCursor(oldCursor); + return 1; } -- cgit v1.2.3 From f4af9fdbfd4531fd59c9f51785d573f6a128639e Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 14 Apr 2015 20:14:09 -0500 Subject: SHERLOCK: Fix word-wrap of talk options --- engines/sherlock/talk.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index 279e6de69a..49e0677b80 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -795,7 +795,7 @@ int Talk::talkLine(int lineNum, int stateNum, byte color, int lineY, bool slamIt // Handle potentially multiple lines needed to display entire statement const char *lineStartP = msg.c_str(); - int maxWidth = 298 - numberFlag ? 18 : 0; + int maxWidth = 298 - (numberFlag ? 18 : 0); for (;;) { // Get as much of the statement as possible will fit on the Common::String sLine; -- cgit v1.2.3 From b14debc20769c7c6e8b0d5fb1d189e319e5ad6e4 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 14 Apr 2015 20:30:02 -0500 Subject: SHERLOCK: Fix talking to Watson when he's sitting down --- engines/sherlock/talk.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index 49e0677b80..73bf9b5fb3 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -591,8 +591,8 @@ void Talk::loadTalkFile(const Common::String &filename) { } const char *chP = strchr(filename.c_str(), '.'); - Common::String talkFile = !chP ? filename + ".tlk" : - Common::String(filename.c_str(), chP) + ".tlk"; + Common::String talkFile = chP ? Common::String(filename.c_str(), chP) + ".tlk" : + Common::String(filename.c_str(), filename.c_str() + 7) + ".tlk"; // Open the talk file for reading Common::SeekableReadStream *talkStream = res.load(talkFile); -- cgit v1.2.3 From 460a84e68f4a633b52a8654f93cdd81a2f3521e4 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 14 Apr 2015 21:24:24 -0500 Subject: SHERLOCK: Fix stopping Watson from moving when talking to him --- engines/sherlock/people.cpp | 2 +- engines/sherlock/talk.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp index 5dd50e7e94..cc26339bde 100644 --- a/engines/sherlock/people.cpp +++ b/engines/sherlock/people.cpp @@ -597,7 +597,7 @@ int People::findSpeaker(int speaker) { if (scumm_stricmp(PORTRAITS[speaker], name.c_str()) == 0 && obj._name[4] >= '0' && obj._name[4] <= '9') - return idx - 1; + return idx; } } diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index 73bf9b5fb3..ef64edd66b 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -880,7 +880,7 @@ void Talk::clearSequences() { void Talk::pullSequence() { Scene &scene = *_vm->_scene; - if (_scriptStack.empty()) + if (_sequenceStack.empty()) return; SequenceEntry seq = _sequenceStack.pop(); -- cgit v1.2.3 From 5b97d581f655eed747a33a69ff7cb5bfe79763fd Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 14 Apr 2015 22:41:18 -0500 Subject: SHERLOCK: Fix horizontal flipping of Holmes when walking left --- engines/sherlock/scene.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 1ce2183af1..46ddbc425f 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -1229,9 +1229,9 @@ void Scene::doBgAnim() { int xRight = SHERLOCK_SCREEN_WIDTH - 2 - people[AL]._imageFrame->_frame.w; int tempX = MIN(people[AL]._position.x / 100, xRight); - bool flipped = people[AL]._frameNumber == WALK_LEFT || people[AL]._frameNumber == STOP_LEFT || - people[AL]._frameNumber == WALK_UPLEFT || people[AL]._frameNumber == STOP_UPLEFT || - people[AL]._frameNumber == WALK_DOWNRIGHT || people[AL]._frameNumber == STOP_DOWNRIGHT; + bool flipped = people[AL]._sequenceNumber == WALK_LEFT || people[AL]._sequenceNumber == STOP_LEFT || + people[AL]._sequenceNumber == WALK_UPLEFT || people[AL]._sequenceNumber == STOP_UPLEFT || + people[AL]._sequenceNumber == WALK_DOWNRIGHT || people[AL]._sequenceNumber == STOP_DOWNRIGHT; screen._backBuffer1.transBlitFrom(people[AL]._imageFrame->_frame, Common::Point(tempX, people[AL]._position.y / 100 - people[AL]._imageFrame->_frame.h), flipped); } -- cgit v1.2.3 From a830d7732537a913aa29ae4a4bc10e80e79dbc82 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 15 Apr 2015 07:49:10 -0500 Subject: SHERLOCK: Refactored out Scripts class --- engines/sherlock/module.mk | 1 - engines/sherlock/scripts.cpp | 42 --------------------------------- engines/sherlock/scripts.h | 54 ------------------------------------------- engines/sherlock/sherlock.cpp | 3 --- engines/sherlock/sherlock.h | 2 -- engines/sherlock/talk.cpp | 14 +++++++---- engines/sherlock/talk.h | 2 ++ 7 files changed, 12 insertions(+), 106 deletions(-) delete mode 100644 engines/sherlock/scripts.cpp delete mode 100644 engines/sherlock/scripts.h (limited to 'engines') diff --git a/engines/sherlock/module.mk b/engines/sherlock/module.mk index a01f9f0f71..4101769a80 100644 --- a/engines/sherlock/module.mk +++ b/engines/sherlock/module.mk @@ -18,7 +18,6 @@ MODULE_OBJS = \ resources.o \ scene.o \ screen.o \ - scripts.o \ sherlock.o \ sound.o \ talk.o \ diff --git a/engines/sherlock/scripts.cpp b/engines/sherlock/scripts.cpp deleted file mode 100644 index 02dcfa6f0b..0000000000 --- a/engines/sherlock/scripts.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "sherlock/scripts.h" -#include "sherlock/sherlock.h" - -namespace Sherlock { - -Scripts::Scripts(SherlockEngine *vm): _vm(vm) { - -} - -void Scripts::popStack() { - /* - ScriptEntry script = _scriptStack.pop(); - _scriptName = script._name; -// _scriptSaveIndex = script._index; - _scriptSelect = script._select; - */ -} - - -} // End of namespace Sherlock diff --git a/engines/sherlock/scripts.h b/engines/sherlock/scripts.h deleted file mode 100644 index beea726c8d..0000000000 --- a/engines/sherlock/scripts.h +++ /dev/null @@ -1,54 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#ifndef SHERLOCK_SCRIPTS_H -#define SHERLOCK_SCRIPTS_H - -#include "common/scummsys.h" -#include "common/stack.h" - -namespace Sherlock { - -class SherlockEngine; - -struct ScriptEntry { - Common::String _name; - int _index; - int _select; -}; - -class Scripts { -private: - SherlockEngine *_vm; -public: - -public: - Scripts(SherlockEngine *vm); - - void doScript(const Common::String &str); - - void popStack(); -}; - -} // End of namespace Sherlock - -#endif diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index 72c072b640..c65a70a20f 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -39,7 +39,6 @@ SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gam _res = nullptr; _scene = nullptr; _screen = nullptr; - _scripts = nullptr; _sound = nullptr; _talk = nullptr; _ui = nullptr; @@ -59,7 +58,6 @@ SherlockEngine::~SherlockEngine() { delete _people; delete _scene; delete _screen; - delete _scripts; delete _sound; delete _talk; delete _ui; @@ -84,7 +82,6 @@ void SherlockEngine::initialize() { _people = new People(this); _scene = new Scene(this); _screen = new Screen(this); - _scripts = new Scripts(this); _sound = new Sound(this); _talk = new Talk(this); _ui = new UserInterface(this); diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h index ef10cd2d47..ec8e0c3148 100644 --- a/engines/sherlock/sherlock.h +++ b/engines/sherlock/sherlock.h @@ -40,7 +40,6 @@ #include "sherlock/resources.h" #include "sherlock/scene.h" #include "sherlock/screen.h" -#include "sherlock/scripts.h" #include "sherlock/sound.h" #include "sherlock/talk.h" #include "sherlock/user_interface.h" @@ -90,7 +89,6 @@ public: Resources *_res; Scene *_scene; Screen *_screen; - Scripts *_scripts; Sound *_sound; Talk *_talk; UserInterface *_ui; diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index ef64edd66b..ee1e6201d2 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -160,7 +160,6 @@ void Talk::talkTo(const Common::String &filename) { People &people = *_vm->_people; Scene &scene = *_vm->_scene; Screen &screen = *_vm->_screen; - Scripts &scripts = *_vm->_scripts; UserInterface &ui = *_vm->_ui; Common::Rect savedBounds = screen.getDisplayBounds(); bool abortFlag = false; @@ -459,9 +458,7 @@ void Talk::talkTo(const Common::String &filename) { // If a script was added to the script stack, restore state so that the // previous script can continue - if (!_scriptStack.empty()) { - scripts.popStack(); - } + popStack(); events.setCursor(ARROW); } @@ -1738,5 +1735,14 @@ int Talk::waitForMore(int delay) { return key2; } +void Talk::popStack() { + if (!_scriptStack.empty()) { + ScriptStackEntry scriptEntry = _scriptStack.pop(); + _scriptName = scriptEntry._name; + _scriptSaveIndex = scriptEntry._currentIndex; + _scriptSelect = scriptEntry._select; + _scriptMoreFlag = true; + } +} } // End of namespace Sherlock diff --git a/engines/sherlock/talk.h b/engines/sherlock/talk.h index bf4f12675c..4a33f2f557 100644 --- a/engines/sherlock/talk.h +++ b/engines/sherlock/talk.h @@ -143,6 +143,8 @@ public: void pushSequence(int speaker); void setSequence(int speaker); bool isSequencesEmpty() const { return _scriptStack.empty(); } + + void popStack(); }; } // End of namespace Sherlock -- cgit v1.2.3 From 17bf9e7f547d1893fbafb77dcc6703b21eca52c6 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 15 Apr 2015 08:22:40 -0500 Subject: SHERLOCK: Refactored Chess class to be Map class --- engines/sherlock/map.cpp | 46 +++++++++++++++++++++++++++++++ engines/sherlock/map.h | 52 ++++++++++++++++++++++++++++++++++++ engines/sherlock/module.mk | 2 +- engines/sherlock/objects.cpp | 7 ++--- engines/sherlock/people.cpp | 5 ++-- engines/sherlock/scalpel/chess.cpp | 37 ------------------------- engines/sherlock/scalpel/chess.h | 45 ------------------------------- engines/sherlock/scalpel/scalpel.cpp | 14 ++++------ engines/sherlock/scalpel/scalpel.h | 4 +-- engines/sherlock/scene.cpp | 10 ++++--- engines/sherlock/sherlock.cpp | 3 +++ engines/sherlock/sherlock.h | 3 ++- engines/sherlock/talk.cpp | 6 ++--- 13 files changed, 126 insertions(+), 108 deletions(-) create mode 100644 engines/sherlock/map.cpp create mode 100644 engines/sherlock/map.h delete mode 100644 engines/sherlock/scalpel/chess.cpp delete mode 100644 engines/sherlock/scalpel/chess.h (limited to 'engines') diff --git a/engines/sherlock/map.cpp b/engines/sherlock/map.cpp new file mode 100644 index 0000000000..8257c16a38 --- /dev/null +++ b/engines/sherlock/map.cpp @@ -0,0 +1,46 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "sherlock/map.h" + +namespace Sherlock { + +Map::Map(SherlockEngine *vm): _vm(vm) { +} + +/** + * Loads the list of points for locations on the map for each scene + */ +void Map::loadPoints(int count, const int *xList, const int *yList) { + for (int idx = 0; idx < count; ++idx, ++xList, ++yList) { + _points.push_back(Common::Point(*xList, *yList)); + } +} + +/** + * Show the map + */ +int Map::show() { + return 0; +} + +} // End of namespace Sherlock diff --git a/engines/sherlock/map.h b/engines/sherlock/map.h new file mode 100644 index 0000000000..88f2b75805 --- /dev/null +++ b/engines/sherlock/map.h @@ -0,0 +1,52 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef SHERLOCK_MAP_H +#define SHERLOCK_MAP_H + +#include "common/scummsys.h" +#include "common/array.h" +#include "common/rect.h" +#include "common/str.h" + +namespace Sherlock { + +class SherlockEngine; + +class Map { +private: + SherlockEngine *_vm; + Common::Array _points; // Map locations for each scene +public: +public: + Map(SherlockEngine *vm); + + const Common::Point &operator[](int idx) { return _points[idx]; } + + void loadPoints(int count, const int *xList, const int *yList); + + int show(); +}; + +} // End of namespace Sherlock + +#endif diff --git a/engines/sherlock/module.mk b/engines/sherlock/module.mk index 4101769a80..171f704a1e 100644 --- a/engines/sherlock/module.mk +++ b/engines/sherlock/module.mk @@ -1,7 +1,6 @@ MODULE := engines/sherlock MODULE_OBJS = \ - scalpel/chess.o \ scalpel/darts.o \ scalpel/scalpel.o \ tattoo/tattoo.o \ @@ -13,6 +12,7 @@ MODULE_OBJS = \ graphics.o \ inventory.o \ journal.o \ + map.o \ objects.o \ people.o \ resources.o \ diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index ca1bdfb2c5..82daa90a38 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -801,6 +801,7 @@ void Object::setObjSequence(int seq, bool wait) { * @returns 0 if no codes are found, 1 if codes were found */ int Object::checkNameForCodes(const Common::String &name, const char *const messages[]) { + Map &map = *_vm->_map; People &people = *_vm->_people; Scene &scene = *_vm->_scene; Screen &screen = *_vm->_screen; @@ -847,9 +848,9 @@ int Object::checkNameForCodes(const Common::String &name, const char *const mess if (ch >= '0' && ch <= '9') { scene._goToScene = atoi(name.c_str() + 1); - if (scene._goToScene < 97 && _vm->_map[scene._goToScene].x) { - _vm->_over.x = _vm->_map[scene._goToScene].x * 100 - 600; - _vm->_over.y = _vm->_map[scene._goToScene].y * 100 + 900; + if (scene._goToScene < 97 && map[scene._goToScene].x) { + _vm->_over.x = map[scene._goToScene].x * 100 - 600; + _vm->_over.y = map[scene._goToScene].y * 100 + 900; } if ((p = strchr(name.c_str(), ',')) != nullptr) { diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp index cc26339bde..d22c08f625 100644 --- a/engines/sherlock/people.cpp +++ b/engines/sherlock/people.cpp @@ -415,6 +415,7 @@ void People::setWalking() { * is being displayed, then the chraracter will always face down. */ void People::gotoStand(Sprite &sprite) { + Map &map = *_vm->_map; Scene &scene = *_vm->_scene; _walkTo.clear(); sprite._walkCount = 0; @@ -448,8 +449,8 @@ void People::gotoStand(Sprite &sprite) { if (_vm->_onChessboard) { sprite._sequenceNumber = 0; - _data[AL]._position.x = (_vm->_map[scene._charPoint].x - 6) * 100; - _data[AL]._position.y = (_vm->_map[scene._charPoint].x + 10) * 100; + _data[AL]._position.x = (map[scene._charPoint].x - 6) * 100; + _data[AL]._position.y = (map[scene._charPoint].x + 10) * 100; } _oldWalkSequence = -1; diff --git a/engines/sherlock/scalpel/chess.cpp b/engines/sherlock/scalpel/chess.cpp deleted file mode 100644 index 95c662dd01..0000000000 --- a/engines/sherlock/scalpel/chess.cpp +++ /dev/null @@ -1,37 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "sherlock/scalpel/chess.h" -#include "sherlock/scalpel/scalpel.h" - -namespace Sherlock { - -namespace Scalpel { - -int Chess::doChessBoard() { - // TODO - return 0; -} - -} // End of namespace Scalpel - -} // End of namespace Scalpel diff --git a/engines/sherlock/scalpel/chess.h b/engines/sherlock/scalpel/chess.h deleted file mode 100644 index 70607472c2..0000000000 --- a/engines/sherlock/scalpel/chess.h +++ /dev/null @@ -1,45 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#ifndef SHERLOCK_CHESS_H -#define SHERLOCK_CHESS_H - -namespace Sherlock { - -namespace Scalpel { - -class ScalpelEngine; - -class Chess { -private: - ScalpelEngine *_vm; -public: - Chess(ScalpelEngine *vm) : _vm(vm) {} - - int doChessBoard(); -}; - -} // End of namespace Scalpel - -} // End of namespace Sherlock - -#endif diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp index 954ea12aec..0742d05366 100644 --- a/engines/sherlock/scalpel/scalpel.cpp +++ b/engines/sherlock/scalpel/scalpel.cpp @@ -183,13 +183,11 @@ byte TALK_SEQUENCES[MAX_PEOPLE][MAX_TALK_SEQUENCES] = { ScalpelEngine::ScalpelEngine(OSystem *syst, const SherlockGameDescription *gameDesc) : SherlockEngine(syst, gameDesc) { - _chess = nullptr; _darts = nullptr; - _chessResult = 0; + _mapResult = 0; } ScalpelEngine::~ScalpelEngine() { - delete _chess; delete _darts; } @@ -199,7 +197,6 @@ ScalpelEngine::~ScalpelEngine() { void ScalpelEngine::initialize() { SherlockEngine::initialize(); - _chess = new Chess(this); _darts = new Darts(this); _flags.resize(100 * 8); @@ -207,8 +204,7 @@ void ScalpelEngine::initialize() { _flags[39] = true; // Turn on Baker Street // Load the map co-ordinates for each scene - for (int idx = 0; idx < NUM_PLACES; ++idx) - _map.push_back(Common::Point(MAP_X[idx], MAP_Y[idx])); + _map->loadPoints(NUM_PLACES, &MAP_X[0], &MAP_Y[0]); // Load the inventory loadInventory(); @@ -393,7 +389,7 @@ void ScalpelEngine::startScene() { } } - _scene->_goToScene = _chess->doChessBoard(); + _scene->_goToScene = _map->show(); _sound->freeSong(); _scene->_hsavedPos = Common::Point(-1, -1); @@ -533,10 +529,10 @@ void ScalpelEngine::startScene() { if (_scene->_goToScene == 99) { // Chess Board _darts->playDarts(); - _chessResult = _scene->_goToScene = 19; // Go back to the bar + _mapResult = _scene->_goToScene = 19; // Go back to the bar } - _chessResult = _scene->_goToScene; + _mapResult = _scene->_goToScene; } /** diff --git a/engines/sherlock/scalpel/scalpel.h b/engines/sherlock/scalpel/scalpel.h index 34d017e757..aa00acab84 100644 --- a/engines/sherlock/scalpel/scalpel.h +++ b/engines/sherlock/scalpel/scalpel.h @@ -24,7 +24,6 @@ #define SHERLOCK_SCALPEL_H #include "sherlock/sherlock.h" -#include "sherlock/scalpel/chess.h" #include "sherlock/scalpel/darts.h" namespace Sherlock { @@ -33,9 +32,8 @@ namespace Scalpel { class ScalpelEngine : public SherlockEngine { private: - Chess *_chess; Darts *_darts; - int _chessResult; + int _mapResult; bool showCityCutscene(); bool showAlleyCutscene(); diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 46ddbc425f..575523bc45 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -193,6 +193,7 @@ void Scene::freeScene() { */ bool Scene::loadScene(const Common::String &filename) { Events &events = *_vm->_events; + Map &map = *_vm->_map; People &people = *_vm->_people; Screen &screen = *_vm->_screen; Sound &sound = *_vm->_sound; @@ -437,8 +438,8 @@ bool Scene::loadScene(const Common::String &filename) { // Reset the position on the overland map _vm->_oldCharPoint = _currentScene; - _vm->_over.x = _vm->_map[_currentScene].x * 100 - 600; - _vm->_over.y = _vm->_map[_currentScene].y * 100 + 900; + _vm->_over.x = map[_currentScene].x * 100 - 600; + _vm->_over.y = map[_currentScene].y * 100 + 900; events.clearEvents(); return flag; @@ -843,6 +844,7 @@ void Scene::checkBgShapes(ImageFrame *frame, const Common::Point &pt) { */ int Scene::startCAnim(int cAnimNum, int playRate) { Events &events = *_vm->_events; + Map &map = *_vm->_map; People &people = *_vm->_people; Resources &res = *_vm->_res; Talk &talk = *_vm->_talk; @@ -1027,8 +1029,8 @@ int Scene::startCAnim(int cAnimNum, int playRate) { if (gotoCode > 0 && !talk._talkToAbort) { _goToScene = gotoCode; - if (_goToScene < 97 && _vm->_map[_goToScene].x) { - _overPos = _vm->_map[_goToScene]; + if (_goToScene < 97 && map[_goToScene].x) { + _overPos = map[_goToScene]; } } diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index c65a70a20f..632e388642 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -35,6 +35,7 @@ SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gam _events = nullptr; _inventory = nullptr; _journal = nullptr; + _map = nullptr; _people = nullptr; _res = nullptr; _scene = nullptr; @@ -55,6 +56,7 @@ SherlockEngine::~SherlockEngine() { delete _debugger; delete _events; delete _journal; + delete _map; delete _people; delete _scene; delete _screen; @@ -78,6 +80,7 @@ void SherlockEngine::initialize() { _debugger = new Debugger(this); _events = new Events(this); _inventory = new Inventory(this); + _map = new Map(this); _journal = new Journal(this); _people = new People(this); _scene = new Scene(this); diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h index ec8e0c3148..42e2cf8b38 100644 --- a/engines/sherlock/sherlock.h +++ b/engines/sherlock/sherlock.h @@ -36,6 +36,7 @@ #include "sherlock/events.h" #include "sherlock/inventory.h" #include "sherlock/journal.h" +#include "sherlock/map.h" #include "sherlock/people.h" #include "sherlock/resources.h" #include "sherlock/scene.h" @@ -85,6 +86,7 @@ public: Events *_events; Inventory *_inventory; Journal *_journal; + Map *_map; People *_people; Resources *_res; Scene *_scene; @@ -101,7 +103,6 @@ public: bool _loadingSavedGame; int _oldCharPoint; // Old scene Common::Point _over; // Old map position - Common::Array _map; // Map locations for each scene bool _onChessboard; bool _slowChess; bool _joystick; diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index ee1e6201d2..158cae38a9 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -574,7 +574,6 @@ void Talk::freeTalkVars() { * conversation. If found, the data for that conversation is loaded */ void Talk::loadTalkFile(const Common::String &filename) { - People &people = *_vm->_people; Resources &res = *_vm->_res; Sound &sound = *_vm->_sound; @@ -1000,6 +999,7 @@ void Talk::doScript(const Common::String &script) { Animation &anim = *_vm->_animation; Events &events = *_vm->_events; Inventory &inv = *_vm->_inventory; + Map &map = *_vm->_map; People &people = *_vm->_people; Scene &scene = *_vm->_scene; Screen &screen = *_vm->_screen; @@ -1351,8 +1351,8 @@ void Talk::doScript(const Common::String &script) { if (scene._goToScene != 100) { // Not going to the map overview scene._oldCharPoint = scene._goToScene; - scene._overPos.x = _vm->_map[scene._goToScene].x * 100 - 600; - scene._overPos.y = _vm->_map[scene._goToScene].y * 100 + 900; + scene._overPos.x = map[scene._goToScene].x * 100 - 600; + scene._overPos.y = map[scene._goToScene].y * 100 + 900; // Run a canimation? if (str[2] > 100) { -- cgit v1.2.3 From cb8e40c116ba23293cbf5f30b45da7c24892753c Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Thu, 16 Apr 2015 01:26:23 +0200 Subject: SCI: QFG3 fix priority of chief in hut bug #5173 this is a script issue and also happens in Sierra's SCI. Gets solved by script patch. --- engines/sci/engine/script.cpp | 6 +++--- engines/sci/engine/script_patches.cpp | 36 +++++++++++++++++++++++++++++++---- 2 files changed, 35 insertions(+), 7 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index 2fe1aba975..88becc82cc 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -136,9 +136,6 @@ void Script::load(int script_nr, ResourceManager *resMan, ScriptPatcher *scriptP assert(_bufSize >= script->size); memcpy(_buf, script->data, script->size); - // Check scripts for matching signatures and patch those, if found - scriptPatcher->processScript(_nr, _buf, script->size); - if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1) { Resource *heap = resMan->findResource(ResourceId(kResourceTypeHeap, _nr), 0); assert(heap != 0); @@ -149,6 +146,9 @@ void Script::load(int script_nr, ResourceManager *resMan, ScriptPatcher *scriptP memcpy(_heapStart, heap->data, heap->size); } + // Check scripts (+ possibly SCI 1.1 heap) for matching signatures and patch those, if found + scriptPatcher->processScript(_nr, _buf, _bufSize); + if (getSciVersion() <= SCI_VERSION_1_LATE) { _exportTable = (const uint16 *)findBlockSCI0(SCI_OBJ_EXPORTS); if (_exportTable) { diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp index 6d5b49f441..48b1292d1b 100644 --- a/engines/sci/engine/script_patches.cpp +++ b/engines/sci/engine/script_patches.cpp @@ -2408,12 +2408,40 @@ static const uint16 qfg3PatchExportChar[] = { PATCH_END }; +// The chief in his hut (room 640) is not drawn using the correct priority, +// which results in a graphical glitch. This is a game bug and also happens +// in Sierra's SCI. We adjust priority accordingly to fix it. +// +// Applies to at least: English, French, German, Italian, Spanish floppy +// Responsible method: heap in script 640 +// Fixes bug #5173 +static const uint16 qfg3SignatureChiefPriority[] = { + SIG_MAGICDWORD, + SIG_UINT16(0x0002), // yStep 0x0002 + SIG_UINT16(0x0281), // view 0x0281 + SIG_UINT16(0x0000), // loop 0x0000 + SIG_UINT16(0x0000), // cel 0x0000 + SIG_UINT16(0x0000), // priority 0x0000 + SIG_UINT16(0x0000), // underbits 0x0000 + SIG_UINT16(0x1000), // signal 0x1000 + SIG_END +}; + +static const uint16 qfg3PatchChiefPriority[] = { + PATCH_ADDTOOFFSET(+8), + PATCH_UINT16(0x000A), // new priority 0x000A (10d) + PATCH_ADDTOOFFSET(+2), + PATCH_UINT16(0x1010), // signal 0x1010 (set fixed priority flag) + PATCH_END +}; + // script, description, signature patch static const SciScriptPatcherEntry qfg3Signatures[] = { - { true, 944, "import dialog continuous calls", 1, qfg3SignatureImportDialog, qfg3PatchImportDialog }, - { true, 440, "dialog crash when asking about Woo", 1, qfg3SignatureWooDialog, qfg3PatchWooDialog }, - { true, 440, "dialog crash when asking about Woo", 1, qfg3SignatureWooDialogAlt, qfg3PatchWooDialogAlt }, - { true, 52, "export character save bug", 2, qfg3SignatureExportChar, qfg3PatchExportChar }, + { true, 944, "import dialog continuous calls", 1, qfg3SignatureImportDialog, qfg3PatchImportDialog }, + { true, 440, "dialog crash when asking about Woo", 1, qfg3SignatureWooDialog, qfg3PatchWooDialog }, + { true, 440, "dialog crash when asking about Woo", 1, qfg3SignatureWooDialogAlt, qfg3PatchWooDialogAlt }, + { true, 52, "export character save bug", 2, qfg3SignatureExportChar, qfg3PatchExportChar }, + { true, 640, "chief in hut priority fix", 1, qfg3SignatureChiefPriority, qfg3PatchChiefPriority }, SCI_SIGNATUREENTRY_TERMINATOR }; -- cgit v1.2.3 From 6a1eee88cfbc0f362bb4a2c058ece310e966ca84 Mon Sep 17 00:00:00 2001 From: Kirben Date: Thu, 16 Apr 2015 14:36:34 +1000 Subject: SCUMM: Add file prefixes used by Italian versions of several HE games. --- engines/scumm/detection_tables.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'engines') diff --git a/engines/scumm/detection_tables.h b/engines/scumm/detection_tables.h index 6eab5c752f..d42a7251d9 100644 --- a/engines/scumm/detection_tables.h +++ b/engines/scumm/detection_tables.h @@ -812,6 +812,7 @@ static const GameFilenamePattern gameFilenamesTable[] = { { "pajama3", "PyjamaHG", kGenHEPC, Common::FR_FRA, UNK, 0 }, { "pajama3", "PyjamaSKS", kGenHEPC, Common::DE_DEU, UNK, 0 }, { "pajama3", "PyjamaSKS", kGenHEMac, Common::DE_DEU, Common::kPlatformMacintosh, 0 }, + { "pajama3", "SamLDM", kGenHEPC, Common::IT_ITA, Common::kPlatformWindows, 0 }, { "pajama3", "UKPajamaEAT", kGenHEPC, Common::RU_RUS, UNK, 0 }, { "puttcircus", "puttcircus", kGenHEPC, UNK_LANG, UNK, 0 }, @@ -830,6 +831,7 @@ static const GameFilenamePattern gameFilenamesTable[] = { { "puttrace", "500demo", kGenHEPC, Common::NL_NLD, Common::kPlatformWindows, 0 }, { "puttrace", "course", kGenHEPC, Common::FR_FRA, UNK, 0 }, { "puttrace", "CourseDemo", kGenHEPC, Common::FR_FRA, UNK, 0 }, + { "puttrace", "GasGasEG", kGenHEPC, Common::IT_ITA, Common::kPlatformWindows, 0 }, { "puttrace", "racedemo", kGenHEPC, UNK_LANG, Common::kPlatformWindows, 0 }, { "puttrace", "RaceDemo", kGenHEMac, UNK_LANG, Common::kPlatformMacintosh, 0 }, { "puttrace", "Rennen", kGenHEPC, Common::DE_DEU, UNK, 0 }, @@ -926,6 +928,7 @@ static const GameFilenamePattern gameFilenamesTable[] = { { "spyfox2", "Sf2demo", kGenHEMac, UNK_LANG, Common::kPlatformMacintosh, 0 }, { "spyfox2", "Spy Fox 2", kGenHEMac, UNK_LANG, Common::kPlatformMacintosh, 0 }, { "spyfox2", "Spy Fox 2 - Demo", kGenHEMac, UNK_LANG, Common::kPlatformMacintosh, 0 }, + { "spyfox2", "SPyFoxMCR", kGenHEPC, Common::IT_ITA, Common::kPlatformWindows, 0 }, { "spyfox2", "SpyFoxOR", kGenHEPC, Common::DE_DEU, UNK, 0 }, { "spyfox2", "SpyFoxOR", kGenHEMac, Common::DE_DEU, Common::kPlatformMacintosh, 0 }, { "spyfox2", "SPYFoxORE", kGenHEPC, Common::FR_FRA, UNK, 0 }, -- cgit v1.2.3 From da19822e373bf134049b6b415f2f19bf2e1e343b Mon Sep 17 00:00:00 2001 From: Kirben Date: Thu, 16 Apr 2015 14:46:40 +1000 Subject: SCUMM: Add md5 checksums for Italian versions of several HE games. --- engines/scumm/scumm-md5.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/scumm/scumm-md5.h b/engines/scumm/scumm-md5.h index 5be18fb990..bc3548c150 100644 --- a/engines/scumm/scumm-md5.h +++ b/engines/scumm/scumm-md5.h @@ -1,5 +1,5 @@ /* - This file was generated by the md5table tool on Sun Dec 7 23:09:10 2014 + This file was generated by the md5table tool on Thu Apr 16 04:45:24 2015 DO NOT EDIT MANUALLY! */ @@ -27,6 +27,7 @@ static const MD5Table md5table[] = { { "0557df19f046a84c2fdc63507c6616cb", "farm", "HE 72", "Demo", -1, Common::NL_NLD, Common::kPlatformWindows }, { "055ffe4f47753e47594ac67823220c54", "puttrace", "HE 99", "", -1, Common::DE_DEU, Common::kPlatformUnknown }, { "057c9b456dedcc4d71b991a3072a20b3", "monkey", "SEGA", "", 9465, Common::JA_JPN, Common::kPlatformSegaCD }, + { "05d3143827ab4f5d2521a1a47dab8ff2", "puttrace", "HE 98", "", -1, Common::IT_ITA, Common::kPlatformUnknown }, { "06b187468113f9ae5a400b148a847fac", "atlantis", "Floppy", "Floppy", 12075, Common::EN_ANY, Common::kPlatformMacintosh }, { "06c3cf4f31daad8b1cd93153491db9e6", "pajama3", "", "", 79382, Common::NL_NLD, Common::kPlatformUnknown }, { "07433205acdca3bc553d0e731588b35f", "airport", "", "", -1, Common::EN_ANY, Common::kPlatformWindows }, @@ -164,6 +165,7 @@ static const MD5Table md5table[] = { { "3686cf8f89e102ececf4366e1d2c8126", "monkey2", "", "", 11135, Common::EN_ANY, Common::kPlatformDOS }, { "36a6750e03fb505fc19fc2bf3e4dbe91", "pajama2", "", "Demo", 58749, Common::EN_ANY, Common::kPlatformUnknown }, { "3769b56c9a22f5521d74525ee459f88d", "puttrace", "HE 99", "Demo", 13108, Common::DE_DEU, Common::kPlatformWindows }, + { "3785fd25f7e02b5782bfc5072d8f77c8", "spyfox2", "", "", -1, Common::IT_ITA, Common::kPlatformUnknown }, { "37aed3f91c1ef959e0bd265f9b13781f", "pajama", "HE 100", "Updated", -1, Common::EN_USA, Common::kPlatformUnknown }, { "37f56ceb13e401a7ac7d9e6b37fecaf7", "loom", "EGA", "EGA", 5748, Common::EN_ANY, Common::kPlatformDOS }, { "37ff1b308999c4cca7319edfcc1280a0", "puttputt", "HE 70", "Demo", 8269, Common::EN_ANY, Common::kPlatformWindows }, @@ -376,6 +378,7 @@ static const MD5Table md5table[] = { { "8368f552b1e3eba559f8d559bcc4cadb", "freddi3", "", "", -1, Common::UNK_LANG, Common::kPlatformUnknown }, { "839a658f7d22de00787ebc945348cdb6", "dog", "", "", 19681, Common::DE_DEU, Common::kPlatformWindows }, { "83cedbe26aa8b58988e984e3d34cac8e", "freddi3", "HE 99", "", -1, Common::DE_DEU, Common::kPlatformUnknown }, + { "83e7a9205567dceb456ee35eeaf26ffa", "pajama3", "", "", -1, Common::IT_ITA, Common::kPlatformUnknown }, { "84e3c23a49ded8a6f9197735c8eb3de7", "PuttTime", "HE 85", "", -1, Common::DE_DEU, Common::kPlatformWindows }, { "8539c0ff89868e55a08e652ac44daaae", "water", "HE 98.5", "", -1, Common::NL_NLD, Common::kPlatformUnknown }, { "861e59ed72a1cd0e6d454f7ee7e2bf3d", "comi", "", "", -1, Common::RU_RUS, Common::kPlatformWindows }, -- cgit v1.2.3 From 9ba234c0e09c4fc034ddd82f82483e10e2470dec Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 16 Apr 2015 17:32:11 -0500 Subject: SHERLOCK: Implemented Map::show method --- engines/sherlock/events.cpp | 10 +- engines/sherlock/events.h | 1 + engines/sherlock/map.cpp | 271 +++++++++++++++++++++++++++++++++++++++++++- engines/sherlock/map.h | 32 +++++- 4 files changed, 309 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/events.cpp b/engines/sherlock/events.cpp index 67d09e52b2..79fe1b58d4 100644 --- a/engines/sherlock/events.cpp +++ b/engines/sherlock/events.cpp @@ -67,9 +67,15 @@ void Events::setCursor(CursorId cursorId) { // Set the cursor data Graphics::Surface &s = (*_cursorImages)[cursorId]; - CursorMan.replaceCursor(s.getPixels(), s.w, s.h, 0, 0, 0xff); - showCursor(); + setCursor(s); +} + +/** + * Set the cursor to show from a passed frame + */ +void Events::setCursor(const Graphics::Surface &src) { + CursorMan.replaceCursor(src.getPixels(), src.w, src.h, 0, 0, 0xff); } /** diff --git a/engines/sherlock/events.h b/engines/sherlock/events.h index 71f7623002..ccf6eb1c59 100644 --- a/engines/sherlock/events.h +++ b/engines/sherlock/events.h @@ -63,6 +63,7 @@ public: void loadCursors(const Common::String &filename); void setCursor(CursorId cursorId); + void setCursor(const Graphics::Surface &src); void showCursor(); diff --git a/engines/sherlock/map.cpp b/engines/sherlock/map.cpp index 8257c16a38..aae8d683c0 100644 --- a/engines/sherlock/map.cpp +++ b/engines/sherlock/map.cpp @@ -21,10 +21,20 @@ */ #include "sherlock/map.h" +#include "sherlock/sherlock.h" namespace Sherlock { -Map::Map(SherlockEngine *vm): _vm(vm) { +Map::Map(SherlockEngine *vm): _vm(vm), _topLine(SHERLOCK_SCREEN_WIDTH, 12) { + _shapes = nullptr; + _iconShapes = nullptr; + _point = 0; + _placesShown = false; + _charPoint = -1; + for (int idx = 0; idx < 3; ++idx) + Common::fill(&_sequences[idx][0], &_sequences[idx][MAX_FRAME], 0); + + loadData(); } /** @@ -36,11 +46,268 @@ void Map::loadPoints(int count, const int *xList, const int *yList) { } } +/** + * Load data needed for the map + */ +void Map::loadData() { + // Load the list of location names + Common::SeekableReadStream *txtStream = _vm->_res->load("chess.txt"); + char c; + + while (txtStream->pos() < txtStream->size()) { + Common::String line; + while ((c = txtStream->readByte()) != '\0') + line += c; + + _locationNames.push_back(line); + } + + delete txtStream; + + // Load the path data + Common::SeekableReadStream *pathStream = _vm->_res->load("chess.pth"); + + _paths.resize(31); + for (uint idx = 0; idx < _paths.size(); ++idx) { + _paths[idx].resize(_paths.size()); + + for (uint idx2 = 0; idx2 < _paths.size(); ++idx2) + _paths[idx][idx2] = pathStream->readSint16LE(); + } + + // Load in the path point information + _pathPoints.resize(416); + for (uint idx = 0; idx < _pathPoints.size(); ++idx) + _pathPoints[idx] = pathStream->readSint16LE(); + + delete pathStream; +} + /** * Show the map */ int Map::show() { - return 0; + Events &events = *_vm->_events; + People &people = *_vm->_people; + Scene &scene = *_vm->_scene; + Screen &screen = *_vm->_screen; + Common::Point lDrawn(-1, -1); + bool changed = false, exitFlag = false; + bool drawMap = true; + + // Set font and custom cursor for the map + int oldFont = screen.fontNumber(); + screen.setFont(0); + + ImageFile mapCursors("omouse.vgs"); + events.setCursor(mapCursors[0]); + + // Load the entire map + ImageFile bigMap("bigmap.vgs"); + + // Load need sprites + setupSprites(); + + screen._backBuffer1.blitFrom(bigMap[1], Common::Point(-_bigPos.x, -_bigPos.y)); + screen._backBuffer1.blitFrom(bigMap[2], Common::Point(-_bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y)); + screen._backBuffer1.blitFrom(bigMap[3], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, -_bigPos.y)); + screen._backBuffer1.blitFrom(bigMap[4], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y)); + + _point = -1; + people[AL]._position = _lDrawnPos = _overPos; + + // Show place icons + showPlaces(); + saveTopLine(); + _placesShown = true; + + // Keep looping until either a location is picked, or the game is ended + while (!_vm->shouldQuit() && !exitFlag) { + events.pollEventsAndWait(); + events.setButtonState(); + + // Keyboard handling + if (events.kbHit()) { + Common::KeyState keyState = events.getKey(); + + if (keyState.keycode == Common::KEYCODE_RETURN || keyState.keycode == Common::KEYCODE_SPACE) { + // Both space and enter simulate a mouse release + events._pressed = false; + events._released = true; + events._oldButtons = 0; + } + } + + // Ignore scrolling attempts until the screen is drawn + if (!drawMap) { + Common::Point pt = events.mousePos(); + + // Check for vertical map scrolling + if ((pt.y > (SHERLOCK_SCREEN_HEIGHT - 10) && _bigPos.y < 200) || (pt.y < 10 && _bigPos.y > 0)) { + if (pt.y > (SHERLOCK_SCREEN_HEIGHT - 10)) + _bigPos.y += 10; + else + _bigPos.y -= 10; + + changed = true; + } + + // Check for horizontal map scrolling + if ((pt.x > (SHERLOCK_SCREEN_WIDTH - 10) && _bigPos.x < 315) || (pt.x < 10 && _bigPos.x > 0)) { + if (pt.x > (SHERLOCK_SCREEN_WIDTH - 10)) + _bigPos.x += 15; + else + _bigPos.x -= 15; + + changed = true; + } + } + + if (changed) { + // Map has scrolled, so redraw new map view + changed = false; + + screen._backBuffer1.blitFrom(bigMap[1], Common::Point(-_bigPos.x, -_bigPos.y)); + screen._backBuffer1.blitFrom(bigMap[2], Common::Point(-_bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y)); + screen._backBuffer1.blitFrom(bigMap[3], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, -_bigPos.y)); + screen._backBuffer1.blitFrom(bigMap[4], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y)); + + showPlaces(); + _placesShown = false; + + saveTopLine(); + _savedPos.x = -1; + updateMap(true); + } else if (!drawMap) { + if (!_placesShown) { + showPlaces(); + _placesShown = true; + } + + updateMap(false); + } + + if ((events._released || events._rightReleased) && _point != -1) { + if (people[AL]._walkCount == 0) { + _charPoint = _point; + walkTheStreets(); + + events.setCursor(mapCursors[1]); + } + } + + // Check if a scene has beeen selected and we've finished "moving" to it + if (people[AL]._walkCount == 0) { + if (_charPoint >= 1 && _charPoint < (int)_points.size()) + exitFlag = true; + } + + if (drawMap) { + drawMap = false; + + if (screen._fadeStyle) + screen.randomTransition(); + else + screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT); + } + + // Wait for a frame + events.wait(1); + } + + freeSprites(); + _overPos = people[AL]._position; + + // Reset font and cursor + screen.setFont(oldFont); + events.setCursor(ARROW); + + return _charPoint; +} + +/** + * Load and initialize all the sprites that are needed for the map display + */ +void Map::setupSprites() { + People &people = *_vm->_people; + Scene &scene = *_vm->_scene; + typedef byte Sequences[16][MAX_FRAME]; + _savedPos.x = -1; + + _shapes = new ImageFile("mapicon.vgs"); + _iconShapes = new ImageFile("overicon.vgs"); + + Person &p = people[AL]; + p._description = " "; + p._type = CHARACTER; + p._position = Common::Point(12400, 5000); + p._sequenceNumber = 0; + p._sequences = (Sequences *)&_sequences; + p._images = _shapes; + p._imageFrame = nullptr; + p._frameNumber = 0; + p._delta = Common::Point(0, 0); + p._oldSize = Common::Point(0, 0); + p._oldSize = Common::Point(0, 0); + p._misc = 0; + p._walkCount = 0; + p._allow = 0; + p._noShapeSize = Common::Point(0, 0); + p._goto = Common::Point(28000, 15000); + p._status = 0; + p.setImageFrame(); + + scene._bgShapes.clear(); +} + +/** + * Free the sprites and data used by the map + */ +void Map::freeSprites() { + delete _shapes; + delete _iconShapes; +} + +/** + * Draws an icon for every place that's currently known + */ +void Map::showPlaces() { + Screen &screen = *_vm->_screen; + + for (uint idx = 0; idx < _points.size(); ++idx) { + const Common::Point &pt = _points[idx]; + + if (pt.x != 0 && pt.y != 0) { + if (pt.x >= _bigPos.x && (pt.x - _bigPos.x) < SHERLOCK_SCREEN_WIDTH + && pt.y >= _bigPos.y && (pt.y - _bigPos.y) < SHERLOCK_SCREEN_HEIGHT) { + if (_vm->readFlags(idx)) { + screen._backBuffer1.transBlitFrom((*_iconShapes)[idx], + Common::Point(pt.x - _bigPos.x - 6, pt.y - _bigPos.y - 12)); + } + } + } + } +} + +/** + * Makes a copy of the top rows of the screen that are used to display location names + */ +void Map::saveTopLine() { + _topLine.blitFrom(_vm->_screen->_backBuffer1, Common::Point(0, 0), Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, 12)); +} + +/** + * Update all on-screen sprites to account for any scrolling of the map + */ +void Map::updateMap(bool flushScreen) { + // TODO +} + +/** + * Handle moving icon for player from their previous location on the map to a destination location + */ +void Map::walkTheStreets() { + // TODO } } // End of namespace Sherlock diff --git a/engines/sherlock/map.h b/engines/sherlock/map.h index 88f2b75805..32051d60b7 100644 --- a/engines/sherlock/map.h +++ b/engines/sherlock/map.h @@ -27,6 +27,9 @@ #include "common/array.h" #include "common/rect.h" #include "common/str.h" +#include "common/str-array.h" +#include "sherlock/graphics.h" +#include "sherlock/objects.h" namespace Sherlock { @@ -36,7 +39,34 @@ class Map { private: SherlockEngine *_vm; Common::Array _points; // Map locations for each scene -public: + Common::StringArray _locationNames; + Common::Array< Common::Array > _paths; + Common::Array _pathPoints; + Common::Point _savedPos; + Common::Point _savedSize; + Surface _topLine; + ImageFile *_shapes; + ImageFile *_iconShapes; + byte _sequences[3][MAX_FRAME]; + Common::Point _bigPos; + Common::Point _overPos; + Common::Point _lDrawnPos; + int _point; + bool _placesShown; + int _charPoint; +private: + void loadData(); + + void setupSprites(); + void freeSprites(); + + void showPlaces(); + + void saveTopLine(); + + void updateMap(bool flushScreen); + + void walkTheStreets(); public: Map(SherlockEngine *vm); -- cgit v1.2.3 From 19142ef58a3e632b31a87a99b817e261f47c1bc4 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 17 Apr 2015 00:07:31 -0500 Subject: SHERLOCK: Implement map icon drawing/restoring --- engines/sherlock/graphics.cpp | 13 ++++- engines/sherlock/graphics.h | 2 + engines/sherlock/map.cpp | 116 ++++++++++++++++++++++++++++++++++++++---- engines/sherlock/map.h | 7 +++ 4 files changed, 126 insertions(+), 12 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/graphics.cpp b/engines/sherlock/graphics.cpp index 306ff23548..6e986c839b 100644 --- a/engines/sherlock/graphics.cpp +++ b/engines/sherlock/graphics.cpp @@ -28,7 +28,7 @@ namespace Sherlock { Surface::Surface(uint16 width, uint16 height): _freePixels(true) { - create(width, height, Graphics::PixelFormat::createFormatCLUT8()); + create(width, height); } Surface::Surface(Surface &src, const Common::Rect &r) : _freePixels(false) { @@ -39,12 +39,23 @@ Surface::Surface(Surface &src, const Common::Rect &r) : _freePixels(false) { format = Graphics::PixelFormat::createFormatCLUT8(); } +Surface::Surface() : _freePixels(false) { +} Surface::~Surface() { if (_freePixels) free(); } +void Surface::create(uint16 width, uint16 height) { + if (_freePixels) + free(); + + Graphics::Surface::create(width, height, Graphics::PixelFormat::createFormatCLUT8()); + _freePixels = true; +} + + /** * Copy a surface into this one */ diff --git a/engines/sherlock/graphics.h b/engines/sherlock/graphics.h index b54dc1ec37..85f3ba8c40 100644 --- a/engines/sherlock/graphics.h +++ b/engines/sherlock/graphics.h @@ -40,8 +40,10 @@ protected: Surface(Surface &src, const Common::Rect &r); public: Surface(uint16 width, uint16 height); + Surface(); ~Surface(); + void create(uint16 width, uint16 height); void blitFrom(const Graphics::Surface &src); void blitFrom(const Graphics::Surface &src, const Common::Point &pt); void blitFrom(const Graphics::Surface &src, const Common::Point &pt, diff --git a/engines/sherlock/map.cpp b/engines/sherlock/map.cpp index aae8d683c0..fa3bf99cab 100644 --- a/engines/sherlock/map.cpp +++ b/engines/sherlock/map.cpp @@ -26,11 +26,14 @@ namespace Sherlock { Map::Map(SherlockEngine *vm): _vm(vm), _topLine(SHERLOCK_SCREEN_WIDTH, 12) { + _mapCursors = nullptr; _shapes = nullptr; _iconShapes = nullptr; _point = 0; _placesShown = false; _charPoint = -1; + _cursorIndex = -1; + _drawMap = false; for (int idx = 0; idx < 3; ++idx) Common::fill(&_sequences[idx][0], &_sequences[idx][MAX_FRAME], 0); @@ -89,19 +92,14 @@ void Map::loadData() { int Map::show() { Events &events = *_vm->_events; People &people = *_vm->_people; - Scene &scene = *_vm->_scene; Screen &screen = *_vm->_screen; Common::Point lDrawn(-1, -1); bool changed = false, exitFlag = false; - bool drawMap = true; // Set font and custom cursor for the map int oldFont = screen.fontNumber(); screen.setFont(0); - ImageFile mapCursors("omouse.vgs"); - events.setCursor(mapCursors[0]); - // Load the entire map ImageFile bigMap("bigmap.vgs"); @@ -113,6 +111,7 @@ int Map::show() { screen._backBuffer1.blitFrom(bigMap[3], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, -_bigPos.y)); screen._backBuffer1.blitFrom(bigMap[4], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y)); + _drawMap = true; _point = -1; people[AL]._position = _lDrawnPos = _overPos; @@ -139,7 +138,7 @@ int Map::show() { } // Ignore scrolling attempts until the screen is drawn - if (!drawMap) { + if (!_drawMap) { Common::Point pt = events.mousePos(); // Check for vertical map scrolling @@ -178,7 +177,7 @@ int Map::show() { saveTopLine(); _savedPos.x = -1; updateMap(true); - } else if (!drawMap) { + } else if (!_drawMap) { if (!_placesShown) { showPlaces(); _placesShown = true; @@ -192,7 +191,8 @@ int Map::show() { _charPoint = _point; walkTheStreets(); - events.setCursor(mapCursors[1]); + _cursorIndex = 1; + events.setCursor((*_mapCursors)[_cursorIndex]); } } @@ -202,8 +202,8 @@ int Map::show() { exitFlag = true; } - if (drawMap) { - drawMap = false; + if (_drawMap) { + _drawMap = false; if (screen._fadeStyle) screen.randomTransition(); @@ -229,11 +229,16 @@ int Map::show() { * Load and initialize all the sprites that are needed for the map display */ void Map::setupSprites() { + Events &events = *_vm->_events; People &people = *_vm->_people; Scene &scene = *_vm->_scene; typedef byte Sequences[16][MAX_FRAME]; _savedPos.x = -1; + _mapCursors = new ImageFile("omouse.vgs"); + _cursorIndex = 0; + events.setCursor((*_mapCursors)[_cursorIndex]); + _shapes = new ImageFile("mapicon.vgs"); _iconShapes = new ImageFile("overicon.vgs"); @@ -264,6 +269,7 @@ void Map::setupSprites() { * Free the sprites and data used by the map */ void Map::freeSprites() { + delete _mapCursors; delete _shapes; delete _iconShapes; } @@ -300,7 +306,49 @@ void Map::saveTopLine() { * Update all on-screen sprites to account for any scrolling of the map */ void Map::updateMap(bool flushScreen) { - // TODO + Events &events = *_vm->_events; + People &people = *_vm->_people; + Screen &screen = *_vm->_screen; + Common::Point osPos = _savedPos; + Common::Point osSize = _savedSize; + Common::Point hPos; + + if (_cursorIndex >= 1) { + if (++_cursorIndex > (1 + 8)) + _cursorIndex = 1; + + events.setCursor((*_mapCursors)[_cursorIndex]); + } + + if (!_drawMap && !flushScreen) + restoreIcon(); + else + _savedPos.x = -1; + + people[AL].adjustSprite(); + + _lDrawnPos.x = hPos.x = people[AL]._position.x / 100 - _bigPos.x; + _lDrawnPos.y = hPos.y = people[AL]._position.y / 100 - people[AL].frameHeight() - _bigPos.y; + + // Draw the person icon + saveIcon(people[AL]._imageFrame, hPos); + if (people[AL]._sequenceNumber == MAP_DOWNLEFT || people[AL]._sequenceNumber == MAP_LEFT + || people[AL]._sequenceNumber == MAP_UPLEFT) + screen._backBuffer1.transBlitFrom(people[AL]._imageFrame->_frame, hPos, true); + else + screen._backBuffer1.transBlitFrom(people[AL]._imageFrame->_frame, hPos, false); + + if (flushScreen) { + screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT); + } else if (!_drawMap) { + if (hPos.x > 0 && hPos.y >= 0 && hPos.x < SHERLOCK_SCREEN_WIDTH && hPos.y < SHERLOCK_SCREEN_HEIGHT) + screen.flushImage(people[AL]._imageFrame, Common::Point(people[AL]._position.x / 100 - _bigPos.x, + people[AL]._position.y / 100 - people[AL].frameHeight() - _bigPos.y), + &people[AL]._oldPosition.x, &people[AL]._oldPosition.y, &people[AL]._oldSize.x, &people[AL]._oldSize.y); + + if (osPos.x != -1) + screen.slamArea(osPos.x, osPos.y, osSize.x, osSize.y); + } } /** @@ -310,4 +358,50 @@ void Map::walkTheStreets() { // TODO } +/** + * Save the area under the player's icon + */ +void Map::saveIcon(ImageFrame *src, const Common::Point &pt) { + Screen &screen = *_vm->_screen; + Common::Point size(src->_width, src->_height); + Common::Point pos = pt; + + if (pos.x < 0) { + size.x += pos.x; + pos.x = 0; + } + + if (pos.y < 0) { + size.y += pos.y; + pos.y = 0; + } + + if ((pos.x + size.x) > SHERLOCK_SCREEN_WIDTH) + size.x -= (pos.x + size.x) - SHERLOCK_SCREEN_WIDTH; + + if ((pos.y + size.y) > SHERLOCK_SCREEN_HEIGHT) + size.y -= (pos.y + size.y) - SHERLOCK_SCREEN_HEIGHT; + + if (size.x < 1 || size.y < 1 || pos.x >= SHERLOCK_SCREEN_WIDTH || pos.y >= SHERLOCK_SCREEN_HEIGHT || _drawMap) { + // Flag as the area not needing to be saved + _savedPos.x = -1; + return; + } + + _iconSave.create(size.x, size.y); + _iconSave.blitFrom(screen._backBuffer1, Common::Point(0, 0), + Common::Rect(pos.x, pos.y, pos.x + size.x, pos.y + size.y)); +} + +/** + * Restore the area under the player's icon + */ +void Map::restoreIcon() { + Screen &screen = *_vm->_screen; + + if (_savedPos.x >= 0 && _savedPos.y >= 0 && _savedPos.x <= SHERLOCK_SCREEN_WIDTH + && _savedPos.y < SHERLOCK_SCREEN_HEIGHT) + screen._backBuffer1.blitFrom(_iconSave, _savedPos); +} + } // End of namespace Sherlock diff --git a/engines/sherlock/map.h b/engines/sherlock/map.h index 32051d60b7..653d8c0084 100644 --- a/engines/sherlock/map.h +++ b/engines/sherlock/map.h @@ -45,6 +45,7 @@ private: Common::Point _savedPos; Common::Point _savedSize; Surface _topLine; + ImageFile *_mapCursors; ImageFile *_shapes; ImageFile *_iconShapes; byte _sequences[3][MAX_FRAME]; @@ -54,6 +55,9 @@ private: int _point; bool _placesShown; int _charPoint; + int _cursorIndex; + bool _drawMap; + Surface _iconSave; private: void loadData(); @@ -67,6 +71,9 @@ private: void updateMap(bool flushScreen); void walkTheStreets(); + + void saveIcon(ImageFrame *src, const Common::Point &pt); + void restoreIcon(); public: Map(SherlockEngine *vm); -- cgit v1.2.3 From 64009f9384a376c79717c86713ddfb0e88366084 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Fri, 17 Apr 2015 21:19:36 +0200 Subject: SCI: add kq6 Sneak Peaks CD demo bug #6824 --- engines/sci/detection_tables.h | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'engines') diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h index 32d1a58765..312069025b 100644 --- a/engines/sci/detection_tables.h +++ b/engines/sci/detection_tables.h @@ -1552,6 +1552,17 @@ static const struct ADGameDescription SciGameDescriptions[] = { AD_LISTEND}, Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // King's Quest 6 - English DOS Playable CD "Sneak Peaks" Demo (first island fully playable) + // (supplied by KQ5 G5 in bug report #6824) + // Executable scanning reports "1.cfs.158 Not a release version", VERSION file reports "1.000.000" + // SCI interpreter version ??? + {"kq6", "Demo/CD", { + {"resource.000", 0, "233394a5f33b475ae5975e7e9a420865", 8345598}, + {"resource.map", 0, "eb9e177281b7cde188dc0d83194cd365", 8960}, + {"resource.msg", 0, "3cf5de44de36191f109d425b8450efc8", 259510}, + AD_LISTEND}, + Common::EN_ANY, Common::kPlatformDOS, ADGF_CD | ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // King's Quest 6 - English DOS Floppy // SCI interpreter version 1.001.054 {"kq6", "", { -- cgit v1.2.3 From 882b1c218fedf5ea45d81524f405df1178080e7a Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Fri, 17 Apr 2015 23:40:12 +0200 Subject: SCI: patch qfg2 import bug for 1.102 and below this patches the known character type import bug (which made all imported characters a fighter) --- engines/sci/engine/script_patches.cpp | 52 +++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp index 48b1292d1b..44ceb15f63 100644 --- a/engines/sci/engine/script_patches.cpp +++ b/engines/sci/engine/script_patches.cpp @@ -2245,9 +2245,57 @@ static const uint16 qfg2PatchImportDialog[] = { PATCH_END }; -// script, description, signature patch +// Quest For Glory 2 character import doesn't properly set the character type +// in versions 1.102 and below, which makes all importerted characters a fighter. +// +// Sierra released an official patch. However the fix is really easy to +// implement on our side, so we also patch the flaw in here in case we find it. +// +// The version released on GOG is 1.102 without this patch applied, so us +// patching it is quite useful. +// +// Applies to at least: English Floppy +// Responsible method: importHero::changeState +// Fixes bug: inside versions 1.102 and below +static const uint16 qfg2SignatureImportCharType[] = { + 0x35, 0x04, // ldi 04 + 0x90, SIG_UINT16(0x023b), // lagi global[23Bh] + 0x02, // add + 0x36, // push + 0x35, 0x04, // ldi 04 + 0x08, // div + 0x36, // push + 0x35, 0x0d, // ldi 0D + 0xb0, SIG_UINT16(0x023b), // sagi global[023Bh] + 0x8b, 0x1f, // lsl local[1Fh] + 0x35, 0x05, // ldi 05 + SIG_MAGICDWORD, + 0xb0, SIG_UINT16(0x0150), // sagi global[0150h] + 0x8b, 0x02, // lsl local[02h] + SIG_END +}; + +static const uint16 qfg2PatchImportCharType[] = { + 0x80, PATCH_UINT16(0x023f), // lag global[23Fh] <-- patched to save 2 bytes + 0x02, // add + 0x36, // push + 0x35, 0x04, // ldi 04 + 0x08, // div + 0x36, // push + 0xa8, SIG_UINT16(0x0248), // ssg global[0248h] <-- patched to save 2 bytes + 0x8b, 0x1f, // lsl local[1Fh] + 0xa8, SIG_UINT16(0x0155), // ssg global[0155h] <-- patched to save 2 bytes + // new code, directly from the official sierra patch file + 0x83, 0x01, // lal local[01h] + 0xa1, 0xbb, // sag global[BBh] + 0xa1, 0x73, // sag global[73h] + PATCH_END +}; + +// script, description, signature patch static const SciScriptPatcherEntry qfg2Signatures[] = { - { true, 944, "import dialog continuous calls", 1, qfg2SignatureImportDialog, qfg2PatchImportDialog }, + { true, 805, "import character type fix", 1, qfg2SignatureImportCharType, qfg2PatchImportCharType }, + { true, 944, "import dialog continuous calls", 1, qfg2SignatureImportDialog, qfg2PatchImportDialog }, SCI_SIGNATUREENTRY_TERMINATOR }; -- cgit v1.2.3 From e75367ab3bfa75d1e08b107511f468086f8c3112 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Fri, 17 Apr 2015 23:48:18 +0200 Subject: SCI: sort qfg import files alphabetically --- engines/sci/engine/file.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'engines') diff --git a/engines/sci/engine/file.cpp b/engines/sci/engine/file.cpp index 2ba7d15ac0..623caec856 100644 --- a/engines/sci/engine/file.cpp +++ b/engines/sci/engine/file.cpp @@ -252,6 +252,9 @@ void DirSeeker::addAsVirtualFiles(Common::String title, Common::String fileMask) Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager(); Common::StringArray foundFiles = saveFileMan->listSavefiles(fileMask); if (!foundFiles.empty()) { + // Sort all filenames alphabetically + Common::sort(foundFiles.begin(), foundFiles.end()); + _files.push_back(title); _virtualFiles.push_back(""); Common::StringArray::iterator it; -- cgit v1.2.3 From 8e3f537019647874e12c9c4a1a90a2e004479102 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 18 Apr 2015 09:28:18 +0200 Subject: SCI: QfG3 fix importing QfG1 character files character type was always imported as fighter was never fixed by Sierra --- engines/sci/engine/script_patches.cpp | 36 ++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp index 44ceb15f63..b704a1c4b3 100644 --- a/engines/sci/engine/script_patches.cpp +++ b/engines/sci/engine/script_patches.cpp @@ -2456,6 +2456,31 @@ static const uint16 qfg3PatchExportChar[] = { PATCH_END }; +// Quest for Glory 3 doesn't properly import the character type of Quest for Glory 1 character files. +// This issue was never addressed. It's caused by Sierra reading data directly from the local +// area, which is only set by Quest For Glory 2 import data, instead of reading the properly set global variable. +// +// We fix it, by also directly setting the local variable. +// +// Applies to at least: English, French, German, Italian, Spanish floppy +// Responsible method: importHero::changeState(4) +static const uint16 qfg3SignatureImportQfG1Char[] = { + SIG_MAGICDWORD, + 0x82, SIG_UINT16(0x0238), // lal local[0x0238] + 0xa0, SIG_UINT16(0x016a), // sag global[0x016a] + 0xa1, 0x7d, // sag global[0x7d] + 0x35, 0x01, // ldi 01 + 0x99, 0xfb, // lsgi global[0xfb] + SIG_END +}; + +static const uint16 qfg3PatchImportQfG1Char[] = { + PATCH_ADDTOOFFSET(+8), + 0xa3, 0x01, // sal 01 -> also set local[01] + 0x89, 0xfc, // lsg global[0xFD] -> save 2 bytes + PATCH_END +}; + // The chief in his hut (room 640) is not drawn using the correct priority, // which results in a graphical glitch. This is a game bug and also happens // in Sierra's SCI. We adjust priority accordingly to fix it. @@ -2483,12 +2508,13 @@ static const uint16 qfg3PatchChiefPriority[] = { PATCH_END }; -// script, description, signature patch +// script, description, signature patch static const SciScriptPatcherEntry qfg3Signatures[] = { - { true, 944, "import dialog continuous calls", 1, qfg3SignatureImportDialog, qfg3PatchImportDialog }, - { true, 440, "dialog crash when asking about Woo", 1, qfg3SignatureWooDialog, qfg3PatchWooDialog }, - { true, 440, "dialog crash when asking about Woo", 1, qfg3SignatureWooDialogAlt, qfg3PatchWooDialogAlt }, - { true, 52, "export character save bug", 2, qfg3SignatureExportChar, qfg3PatchExportChar }, + { true, 944, "import dialog continuous calls", 1, qfg3SignatureImportDialog, qfg3PatchImportDialog }, + { true, 440, "dialog crash when asking about Woo", 1, qfg3SignatureWooDialog, qfg3PatchWooDialog }, + { true, 440, "dialog crash when asking about Woo", 1, qfg3SignatureWooDialogAlt, qfg3PatchWooDialogAlt }, + { true, 52, "export character save bug", 2, qfg3SignatureExportChar, qfg3PatchExportChar }, + { true, 54, "import character from QfG1 bug", 1, qfg3SignatureImportQfG1Char, qfg3PatchImportQfG1Char }, { true, 640, "chief in hut priority fix", 1, qfg3SignatureChiefPriority, qfg3PatchChiefPriority }, SCI_SIGNATUREENTRY_TERMINATOR }; -- cgit v1.2.3 From e24c8f1e877ca6b1c399e310ac0d3c2fd7ae4043 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 18 Apr 2015 12:10:26 +0200 Subject: SCI: add uninitialized read workaround qfg3 rm140 for French, German, Italian and Spanish versions --- engines/sci/engine/workarounds.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'engines') diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index 998d7cc041..bfc6cbb64a 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -162,6 +162,10 @@ const SciWorkaroundEntry uninitializedReadWorkarounds[] = { { GID_QFG2, -1, 700, 0, NULL, "showSign", -1, 10, { WORKAROUND_FAKE, 0 } }, // Occurs sometimes when reading a sign in Raseir, Shapeir et al - bugs #5627, #5635 { GID_QFG3, 510, 510, 0, "awardPrize", "changeState", -1, 0, { WORKAROUND_FAKE, 1 } }, // Simbani warrior challenge, after throwing the spears and retrieving the ring - bug #5277. Must be non-zero, otherwise the prize is awarded twice - bug #6160 { GID_QFG3, 140, 140, 0, "rm140", "init", 0x1008, 0, { WORKAROUND_FAKE, 0 } }, // when importing a character and selecting the previous profession - bug #5163 + { GID_QFG3, 140, 140, 0, "rm140", "init", 0x11e4, 0, { WORKAROUND_FAKE, 0 } }, // when importing ... in the French version + { GID_QFG3, 140, 140, 0, "rm140", "init", 0x10f2, 0, { WORKAROUND_FAKE, 0 } }, // when importing ... in the German version + { GID_QFG3, 140, 140, 0, "rm140", "init", 0x11e3, 0, { WORKAROUND_FAKE, 0 } }, // when importing ... in the Italian version + { GID_QFG3, 140, 140, 0, "rm140", "init", 0x123d, 0, { WORKAROUND_FAKE, 0 } }, // when importing ... in the Spanish version { GID_QFG3, 330, 330, -1, "Teller", "doChild", -1, -1, { WORKAROUND_FAKE, 0 } }, // when talking to King Rajah about "Rajah" (bug #5033, temp 1) or "Tarna" (temp 0), or when clicking on yourself and saying "Greet" (bug #5148, temp 1) { GID_QFG3, 700, 700, -1, "monsterIsDead", "changeState", -1, 0, { WORKAROUND_FAKE, 0 } }, // in the jungle, after winning any fight, bug #5169 { GID_QFG3, 470, 470, -1, "rm470", "notify", -1, 0, { WORKAROUND_FAKE, 0 } }, // closing the character screen in the Simbani village in the room with the bridge, bug #5165 -- cgit v1.2.3 From c78cf88766849402f4de40fa972bce06dfdcb0d9 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 18 Apr 2015 13:28:35 +0200 Subject: SCI: sq4 russian: added all workarounds manually and removed generic workaround, which ignores all objectnames. --- engines/sci/engine/workarounds.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index bfc6cbb64a..c6bd9aedc9 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -192,8 +192,11 @@ const SciWorkaroundEntry uninitializedReadWorkarounds[] = { { GID_SQ4, -1, 398, 0, "showBox", "changeState", -1, 0, { WORKAROUND_FAKE, 0 } }, // CD: called when rummaging in Software Excess bargain bin { GID_SQ4, -1, 928, -1, "Narrator", "startText", -1, 1000, { WORKAROUND_FAKE, 1 } }, // CD: happens in the options dialog and in-game when speech and subtitles are used simultaneously { GID_SQ4, -1, 708, -1, "exitBut", "doVerb", -1, 0, { WORKAROUND_FAKE, 0 } }, // Floppy: happens, when looking at the "close" button in the sq4 hintbook - bug #6447 + { GID_SQ4, -1, 708, -1, "", "doVerb", -1, 0, { WORKAROUND_FAKE, 0 } }, // Floppy: happens, when looking at the "close" button... in Russian version - bug #5573 { GID_SQ4, -1, 708, -1, "prevBut", "doVerb", -1, 0, { WORKAROUND_FAKE, 0 } }, // Floppy: happens, when looking at the "previous" button in the sq4 hintbook - bug #6447 + { GID_SQ4, -1, 708, -1, "\xA8\xE6\xE3 \xAD\xA0\xA7\xA0\xA4.", "doVerb", -1, 0, { WORKAROUND_FAKE, 0 } }, // Floppy: happens, when looking at the "previous" button... in Russian version - bug #5573 { GID_SQ4, -1, 708, -1, "nextBut", "doVerb", -1, 0, { WORKAROUND_FAKE, 0 } }, // Floppy: happens, when looking at the "next" button in the sq4 hintbook - bug #6447 + { GID_SQ4, -1, 708, -1, ".", "doVerb", -1, 0, { WORKAROUND_FAKE, 0 } }, // Floppy: happens, when looking at the "next" button... in Russian version - bug #5573 { GID_SQ5, 201, 201, 0, "buttonPanel", "doVerb", -1, 0, { WORKAROUND_FAKE, 1 } }, // when looking at the orange or red button - bug #5112 { GID_SQ6, -1, 0, 0, "SQ6", "init", -1, 2, { WORKAROUND_FAKE, 0 } }, // Demo and full version: called when the game starts (demo: room 0, full: room 100) { GID_SQ6, -1, 64950, -1, "Feature", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // called when pressing "Start game" in the main menu, when entering the Orion's Belt bar (room 300), and perhaps other places @@ -277,6 +280,7 @@ const SciWorkaroundEntry kDisposeScript_workarounds[] = { { GID_QFG1, -1, 64, 0, "rm64", "dispose", -1, 0, { WORKAROUND_IGNORE, 0 } }, // when leaving graveyard, parameter 0 is an object { GID_SQ4, 150, 151, 0, "fightScript", "dispose", -1, 0, { WORKAROUND_IGNORE, 0 } }, // during fight with Vohaul, parameter 0 is an object { GID_SQ4, 150, 152, 0, "driveCloseUp", "dispose", -1, 0, { WORKAROUND_IGNORE, 0 } }, // when choosing "beam download", parameter 0 is an object + { GID_SQ4, 150, 152, 0, "", "dispose", -1, 0, { WORKAROUND_IGNORE, 0 } }, // when choosing "beam download"... in Russian version - bug #5573 SCI_WORKAROUNDENTRY_TERMINATOR }; @@ -301,7 +305,7 @@ const SciWorkaroundEntry kGetAngle_workarounds[] = { // gameID, room,script,lvl, object-name, method-name, call,index, workaround const SciWorkaroundEntry kFindKey_workarounds[] = { { GID_ECOQUEST2, 100, 999, 0, "myList", "contains", -1, 0, { WORKAROUND_FAKE, 0 } }, // When Noah Greene gives Adam the Ecorder, and just before the game gives a demonstration, a null reference to a list is passed - bug #4987 - { GID_HOYLE4, 300, 999, 0, "Piles", "contains", -1, 0, { WORKAROUND_FAKE, 0 } }, // When passing the three cards in Hearts, a null reference to a list is passed - bug #5664 + { GID_HOYLE4, 300, 999, 0, "Piles", "contains", -1, 0, { WORKAROUND_FAKE, 0 } }, // When passing the three cards in Hearts, a null reference to a list is passed - bug #5664 SCI_WORKAROUNDENTRY_TERMINATOR }; @@ -346,12 +350,17 @@ const SciWorkaroundEntry kGraphFillBoxAny_workarounds[] = { // gameID, room,script,lvl, object-name, method-name, call,index, workaround const SciWorkaroundEntry kGraphRedrawBox_workarounds[] = { { GID_SQ4, 405, 405, 0, "swimAfterEgo", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air - accidental additional parameter specified + { GID_SQ4, 405, 405, 0, "", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air... Russian version - bug #5573 { GID_SQ4, 406, 406, 0, "egoFollowed", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // FLOPPY: when getting shot by the police - accidental additional parameter specified { GID_SQ4, 406, 406, 0, "swimAndShoot", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air - accidental additional parameter specified + { GID_SQ4, 406, 406, 0, "", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air... Russian version - bug #5573 (is for both egoFollowed and swimAndShoot) { GID_SQ4, 410, 410, 0, "swimAfterEgo", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air - accidental additional parameter specified + { GID_SQ4, 410, 410, 0, "", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air... Russian version - bug #5573 { GID_SQ4, 411, 411, 0, "swimAndShoot", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air - accidental additional parameter specified + { GID_SQ4, 411, 411, 0, "", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air... Russian version - bug #5573 { GID_SQ4, 150, 150, 0, "laserScript", "changeState", 0xb2, 0, { WORKAROUND_STILLCALL, 0 } }, // when visiting the pedestral where Roger Jr. is trapped, before trashing the brain icon in the programming chapter, accidental additional parameter specified - bug #5479 { GID_SQ4, 150, 150, 0, "laserScript", "changeState", 0x16, 0, { WORKAROUND_STILLCALL, 0 } }, // same as above, for the German version - bug #5527 + { GID_SQ4, 150, 150, 0, "", "changeState", 0x16, 0, { WORKAROUND_STILLCALL, 0 } }, // same as above, for the Russian version - bug #5573 { GID_SQ4, -1, 704, 0, "shootEgo", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // When shot by Droid in Super Computer Maze (Rooms 500, 505, 510...) - accidental additional parameter specified { GID_KQ5, -1, 981, 0, "myWindow", "dispose", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // Happens in the floppy version, when closing any dialog box, accidental additional parameter specified - bug #5031 { GID_KQ5, -1, 995, 0, "invW", "doit", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // Happens in the floppy version, when closing the inventory window, accidental additional parameter specified @@ -508,12 +517,6 @@ SciWorkaroundSolution trackOriginAndFindWorkaround(int index, const SciWorkaroun bool objectNameMatches = (workaround->objectName == NULL) || (workaround->objectName == g_sci->getSciLanguageString(searchObjectName, K_LANG_ENGLISH)); - // Special case: in the fanmade Russian translation of SQ4, all - // of the object names have been deleted or renamed to Russian, - // thus we disable checking of the object name. Fixes bug #5573. - if (g_sci->getLanguage() == Common::RU_RUS && g_sci->getGameId() == GID_SQ4) - objectNameMatches = true; - if (workaround->gameId == gameId && ((workaround->scriptNr == -1) || (workaround->scriptNr == curScriptNr)) && ((workaround->roomNr == -1) || (workaround->roomNr == curRoomNumber)) -- cgit v1.2.3 From 38444d6024870d31656c911b2af1512a1cd6281a Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 18 Apr 2015 22:18:57 +0200 Subject: SCI: add signatures for workaround local-calls instead of using hardcoded offsets, we can now use regular script patcher signatures. only 1 qfg3 workaround has been migrated, the others will follow. --- engines/sci/engine/script_patches.cpp | 190 +++++----- engines/sci/engine/script_patches.h | 9 +- engines/sci/engine/workarounds.cpp | 689 ++++++++++++++++++---------------- engines/sci/engine/workarounds.h | 1 + 4 files changed, 475 insertions(+), 414 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp index b704a1c4b3..e88aa98f42 100644 --- a/engines/sci/engine/script_patches.cpp +++ b/engines/sci/engine/script_patches.cpp @@ -2924,6 +2924,7 @@ ScriptPatcher::ScriptPatcher() { _selectorIdTable[selectorNr] = -1; _runtimeTable = NULL; + _isMacSci11 = false; } ScriptPatcher::~ScriptPatcher() { @@ -2932,7 +2933,7 @@ ScriptPatcher::~ScriptPatcher() { } // will actually patch previously found signature area -void ScriptPatcher::applyPatch(const SciScriptPatcherEntry *patchEntry, byte *scriptData, const uint32 scriptSize, int32 signatureOffset, const bool isMacSci11) { +void ScriptPatcher::applyPatch(const SciScriptPatcherEntry *patchEntry, byte *scriptData, const uint32 scriptSize, int32 signatureOffset) { const uint16 *patchData = patchEntry->patchData; byte orgData[PATCH_VALUELIMIT]; int32 offset = signatureOffset; @@ -2996,7 +2997,7 @@ void ScriptPatcher::applyPatch(const SciScriptPatcherEntry *patchEntry, byte *sc default: byte1 = 0; byte2 = 0; } - if (!isMacSci11) { + if (!_isMacSci11) { scriptData[offset++] = byte1; scriptData[offset++] = byte2; } else { @@ -3023,8 +3024,94 @@ void ScriptPatcher::applyPatch(const SciScriptPatcherEntry *patchEntry, byte *sc } } +bool ScriptPatcher::verifySignature(uint32 byteOffset, const uint16 *signatureData, const char *signatureDescription, const byte *scriptData, const uint32 scriptSize) { + uint16 sigSelector = 0; + + uint16 sigWord = *signatureData; + while (sigWord != SIG_END) { + uint16 sigCommand = sigWord & SIG_COMMANDMASK; + uint16 sigValue = sigWord & SIG_VALUEMASK; + switch (sigCommand) { + case SIG_CODE_ADDTOOFFSET: { + // add value to offset + byteOffset += sigValue; + break; + } + case SIG_CODE_UINT16: + case SIG_CODE_SELECTOR16: { + if ((byteOffset + 1) < scriptSize) { + byte byte1; + byte byte2; + + switch (sigCommand) { + case SIG_CODE_UINT16: { + byte1 = sigValue & SIG_BYTEMASK; + signatureData++; sigWord = *signatureData; + if (sigWord & SIG_COMMANDMASK) + error("Script-Patcher: signature inconsistent\nFaulty signature: '%s'", signatureDescription); + byte2 = sigWord & SIG_BYTEMASK; + break; + } + case SIG_CODE_SELECTOR16: { + sigSelector = _selectorIdTable[sigValue]; + byte1 = sigSelector & 0xFF; + byte2 = sigSelector >> 8; + break; + } + default: + byte1 = 0; byte2 = 0; + } + if (!_isMacSci11) { + if ((scriptData[byteOffset] != byte1) || (scriptData[byteOffset + 1] != byte2)) + sigWord = SIG_MISMATCH; + } else { + // SCI1.1+ on macintosh had uint16s in script in BE-order + if ((scriptData[byteOffset] != byte2) || (scriptData[byteOffset + 1] != byte1)) + sigWord = SIG_MISMATCH; + } + byteOffset += 2; + } else { + sigWord = SIG_MISMATCH; + } + break; + } + case SIG_CODE_SELECTOR8: { + if (byteOffset < scriptSize) { + sigSelector = _selectorIdTable[sigValue]; + if (sigSelector & 0xFF00) + error("Script-Patcher: 8 bit selector required, game uses 16 bit selector\nFaulty signature: '%s'", signatureDescription); + if (scriptData[byteOffset] != (sigSelector & 0xFF)) + sigWord = SIG_MISMATCH; + byteOffset++; + } else { + sigWord = SIG_MISMATCH; // out of bounds + } + break; + } + case SIG_CODE_BYTE: + if (byteOffset < scriptSize) { + if (scriptData[byteOffset] != sigWord) + sigWord = SIG_MISMATCH; + byteOffset++; + } else { + sigWord = SIG_MISMATCH; // out of bounds + } + } + + if (sigWord == SIG_MISMATCH) + break; + + signatureData++; + sigWord = *signatureData; + } + + if (sigWord == SIG_END) // signature fully matched? + return true; + return false; +} + // will return -1 if no match was found, otherwise an offset to the start of the signature match -int32 ScriptPatcher::findSignature(const SciScriptPatcherEntry *patchEntry, SciScriptPatcherRuntimeEntry *runtimeEntry, const byte *scriptData, const uint32 scriptSize, const bool isMacSci11) { +int32 ScriptPatcher::findSignature(const SciScriptPatcherEntry *patchEntry, SciScriptPatcherRuntimeEntry *runtimeEntry, const byte *scriptData, const uint32 scriptSize) { if (scriptSize < 4) // we need to find a DWORD, so less than 4 bytes is not okay return -1; @@ -3036,89 +3123,8 @@ int32 ScriptPatcher::findSignature(const SciScriptPatcherEntry *patchEntry, SciS if (magicDWord == READ_UINT32(scriptData + DWordOffset)) { // magic DWORD found, check if actual signature matches uint32 offset = DWordOffset + runtimeEntry->magicOffset; - uint32 byteOffset = offset; - const uint16 *signatureData = patchEntry->signatureData; - uint16 sigSelector = 0; - - uint16 sigWord = *signatureData; - while (sigWord != SIG_END) { - uint16 sigCommand = sigWord & SIG_COMMANDMASK; - uint16 sigValue = sigWord & SIG_VALUEMASK; - switch (sigCommand) { - case SIG_CODE_ADDTOOFFSET: { - // add value to offset - byteOffset += sigValue; - break; - } - case SIG_CODE_UINT16: - case SIG_CODE_SELECTOR16: { - if ((byteOffset + 1) < scriptSize) { - byte byte1; - byte byte2; - - switch (sigCommand) { - case SIG_CODE_UINT16: { - byte1 = sigValue & SIG_BYTEMASK; - signatureData++; sigWord = *signatureData; - if (sigWord & SIG_COMMANDMASK) - error("Script-Patcher: signature inconsistent\nFaulty patch: '%s'", patchEntry->description); - byte2 = sigWord & SIG_BYTEMASK; - break; - } - case SIG_CODE_SELECTOR16: { - sigSelector = _selectorIdTable[sigValue]; - byte1 = sigSelector & 0xFF; - byte2 = sigSelector >> 8; - break; - } - default: - byte1 = 0; byte2 = 0; - } - if (!isMacSci11) { - if ((scriptData[byteOffset] != byte1) || (scriptData[byteOffset + 1] != byte2)) - sigWord = SIG_MISMATCH; - } else { - // SCI1.1+ on macintosh had uint16s in script in BE-order - if ((scriptData[byteOffset] != byte2) || (scriptData[byteOffset + 1] != byte1)) - sigWord = SIG_MISMATCH; - } - byteOffset += 2; - } else { - sigWord = SIG_MISMATCH; - } - break; - } - case SIG_CODE_SELECTOR8: { - if (byteOffset < scriptSize) { - sigSelector = _selectorIdTable[sigValue]; - if (sigSelector & 0xFF00) - error("Script-Patcher: 8 bit selector required, game uses 16 bit selector\nFaulty patch: '%s'", patchEntry->description); - if (scriptData[byteOffset] != (sigSelector & 0xFF)) - sigWord = SIG_MISMATCH; - byteOffset++; - } else { - sigWord = SIG_MISMATCH; // out of bounds - } - break; - } - case SIG_CODE_BYTE: - if (byteOffset < scriptSize) { - if (scriptData[byteOffset] != sigWord) - sigWord = SIG_MISMATCH; - byteOffset++; - } else { - sigWord = SIG_MISMATCH; // out of bounds - } - } - - if (sigWord == SIG_MISMATCH) - break; - - signatureData++; - sigWord = *signatureData; - } - if (sigWord == SIG_END) // signature fully matched? + if (verifySignature(offset, patchEntry->signatureData, patchEntry->description, scriptData, scriptSize)) return offset; } DWordOffset++; @@ -3129,7 +3135,7 @@ int32 ScriptPatcher::findSignature(const SciScriptPatcherEntry *patchEntry, SciS // This method calculates the magic DWORD for each entry in the signature table // and it also initializes the selector table for selectors used in the signatures/patches of the current game -void ScriptPatcher::initSignature(const SciScriptPatcherEntry *patchTable, bool isMacSci11) { +void ScriptPatcher::initSignature(const SciScriptPatcherEntry *patchTable) { const SciScriptPatcherEntry *curEntry = patchTable; SciScriptPatcherRuntimeEntry *curRuntimeEntry; Selector curSelector = -1; @@ -3197,7 +3203,7 @@ void ScriptPatcher::initSignature(const SciScriptPatcherEntry *patchTable, bool curData++; curWord = *curData; if (curWord & SIG_COMMANDMASK) error("Script-Patcher: signature entry inconsistent\nFaulty patch: '%s'", curEntry->description); - if (!isMacSci11) { + if (!_isMacSci11) { byte1 = curValue; byte2 = curWord & SIG_BYTEMASK; } else { @@ -3212,7 +3218,7 @@ void ScriptPatcher::initSignature(const SciScriptPatcherEntry *patchTable, bool curSelector = g_sci->getKernel()->findSelector(selectorNameTable[curValue]); _selectorIdTable[curValue] = curSelector; } - if (!isMacSci11) { + if (!_isMacSci11) { byte1 = curSelector & 0x00FF; byte2 = curSelector >> 8; } else { @@ -3374,7 +3380,7 @@ void ScriptPatcher::processScript(uint16 scriptNr, byte *scriptData, const uint3 } if (signatureTable) { - bool isMacSci11 = (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_1_1); + _isMacSci11 = (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_1_1); if (!_runtimeTable) { // Abort, in case selectors are not yet initialized (happens for games w/o selector-dictionary) @@ -3382,7 +3388,7 @@ void ScriptPatcher::processScript(uint16 scriptNr, byte *scriptData, const uint3 return; // signature table needs to get initialized (Magic DWORD set, selector table set) - initSignature(signatureTable, isMacSci11); + initSignature(signatureTable); // Do additional game-specific initialization switch (gameId) { @@ -3417,11 +3423,11 @@ void ScriptPatcher::processScript(uint16 scriptNr, byte *scriptData, const uint3 int32 foundOffset = 0; int16 applyCount = curEntry->applyCount; do { - foundOffset = findSignature(curEntry, curRuntimeEntry, scriptData, scriptSize, isMacSci11); + foundOffset = findSignature(curEntry, curRuntimeEntry, scriptData, scriptSize); if (foundOffset != -1) { // found, so apply the patch debugC(kDebugLevelScriptPatcher, "Script-Patcher: '%s' on script %d offset %d", curEntry->description, scriptNr, foundOffset); - applyPatch(curEntry, scriptData, scriptSize, foundOffset, isMacSci11); + applyPatch(curEntry, scriptData, scriptSize, foundOffset); } applyCount--; } while ((foundOffset != -1) && (applyCount)); diff --git a/engines/sci/engine/script_patches.h b/engines/sci/engine/script_patches.h index 7023ef327e..d15fce321b 100644 --- a/engines/sci/engine/script_patches.h +++ b/engines/sci/engine/script_patches.h @@ -74,7 +74,6 @@ struct SciScriptPatcherEntry { const uint16 *patchData; }; -//#define SCI_SIGNATUREENTRY_TERMINATOR { false, 0, NULL, 0, 0, 0, NULL, NULL } #define SCI_SIGNATUREENTRY_TERMINATOR { false, 0, NULL, 0, NULL, NULL } struct SciScriptPatcherRuntimeEntry { @@ -92,15 +91,17 @@ public: ~ScriptPatcher(); void processScript(uint16 scriptNr, byte *scriptData, const uint32 scriptSize); + bool verifySignature(uint32 byteOffset, const uint16 *signatureData, const char *signatureDescription, const byte *scriptData, const uint32 scriptSize); private: - void initSignature(const SciScriptPatcherEntry *patchTable, bool isMacSci11); + void initSignature(const SciScriptPatcherEntry *patchTable); void enablePatch(const SciScriptPatcherEntry *patchTable, const char *searchDescription); - int32 findSignature(const SciScriptPatcherEntry *patchEntry, SciScriptPatcherRuntimeEntry *runtimeEntry, const byte *scriptData, const uint32 scriptSize, bool isMacSci11); - void applyPatch(const SciScriptPatcherEntry *patchEntry, byte *scriptData, const uint32 scriptSize, int32 signatureOffset, bool isMacSci11); + int32 findSignature(const SciScriptPatcherEntry *patchEntry, SciScriptPatcherRuntimeEntry *runtimeEntry, const byte *scriptData, const uint32 scriptSize); + void applyPatch(const SciScriptPatcherEntry *patchEntry, byte *scriptData, const uint32 scriptSize, int32 signatureOffset); Selector *_selectorIdTable; SciScriptPatcherRuntimeEntry *_runtimeTable; + bool _isMacSci11; }; } // End of namespace Sci diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index c6bd9aedc9..9ae6537000 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -24,441 +24,455 @@ #include "sci/engine/object.h" #include "sci/engine/state.h" #include "sci/engine/vm.h" +#include "sci/engine/script_patches.h" #include "sci/engine/workarounds.h" -#define SCI_WORKAROUNDENTRY_TERMINATOR { (SciGameId)0, -1, -1, 0, NULL, NULL, -1, 0, { WORKAROUND_NONE, 0 } } +#define SCI_WORKAROUNDENTRY_TERMINATOR { (SciGameId)0, -1, -1, 0, NULL, NULL, -1, NULL, 0, { WORKAROUND_NONE, 0 } } namespace Sci { -// gameID, room,script,lvl, object-name, method-name, call,index, workaround +// Attention: +// To identify local-call-subroutines code signatures are used. +// Offsets change a lot between different versions of games, especially between different language releases. +// That's why it isn't good to hardcode the offsets of those subroutines. +// +// Those signatures are just like the script patcher signatures (for further study: engine\script_patches.cpp) +// However you may NOT use command SIG_SELECTOR8 nor SIG_SELECTOR16 atm. Proper support for those may be added later. + +// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround const SciWorkaroundEntry arithmeticWorkarounds[] = { - { GID_CAMELOT, 92, 92, 0, "endingCartoon2", "changeState", 0x20d, 0, { WORKAROUND_FAKE, 0 } }, // op_lai: during the ending, sub gets called with no parameters, uses parameter 1 which is theGrail in this case - bug #5237 - { GID_ECOQUEST2, 100, 0, 0, "Rain", "points", 0xcc6, 0, { WORKAROUND_FAKE, 0 } }, // op_or: when giving the papers to the customs officer, gets called against a pointer instead of a number - bug #4939 - { GID_ECOQUEST2, 100, 0, 0, "Rain", "points", 0xce0, 0, { WORKAROUND_FAKE, 0 } }, // Same as above, for the Spanish version - bug #5750 - { GID_FANMADE, 516, 983, 0, "Wander", "setTarget", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_mul: The Legend of the Lost Jewel Demo (fan made): called with object as second parameter when attacked by insects - bug #5124 - { GID_GK1, 800,64992, 0, "Fwd", "doit", -1, 0, { WORKAROUND_FAKE, 1 } }, // op_gt: when Mosely finds Gabriel and Grace near the end of the game, compares the Grooper object with 7 - { GID_HOYLE4, 700, -1, 1, "Code", "doit", -1, 0, { WORKAROUND_FAKE, 1 } }, // op_add: while bidding in Bridge, an object ("Bid") is added to an object in another segment ("hand3") - { GID_ICEMAN, 199, 977, 0, "Grooper", "doit", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_add: While dancing with the girl - { GID_MOTHERGOOSE256, -1, 999, 0, "Event", "new", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_and: constantly during the game (SCI1 version) - { GID_MOTHERGOOSE256, -1, 4, 0, "rm004", "doit", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_or: when going north and reaching the castle (rooms 4 and 37) - bug #5101 - { GID_MOTHERGOOSEHIRES,90, 90, 0, "newGameButton", "select", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_ge: MUMG Deluxe, when selecting "New Game" in the main menu. It tries to compare an integer with a list. Needs to return false for the game to continue. - { GID_PHANTASMAGORIA, 902, 0, 0, "", "export 7", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_shr: when starting a chapter in Phantasmagoria - { GID_QFG1VGA, 301, 928, 0, "Blink", "init", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_div: when entering the inn, gets called with 1 parameter, but 2nd parameter is used for div which happens to be an object - { GID_QFG2, 200, 200, 0, "astro", "messages", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_lsi: when getting asked for your name by the astrologer - bug #5152 - { GID_QFG3, 780, 999, 0, "", "export 6", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_add: trying to talk to yourself at the top of the giant tree - bug #6692 - { GID_QFG4, 710,64941, 0, "RandCycle", "doit", -1, 0, { WORKAROUND_FAKE, 1 } }, // op_gt: when the tentacle appears in the third room of the caves - SCI_WORKAROUNDENTRY_TERMINATOR -}; - -// gameID, room,script,lvl, object-name, method-name, call,index, workaround + { GID_CAMELOT, 92, 92, 0, "endingCartoon2", "changeState", 0x20d, NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_lai: during the ending, sub gets called with no parameters, uses parameter 1 which is theGrail in this case - bug #5237 + { GID_ECOQUEST2, 100, 0, 0, "Rain", "points", 0xcc6, NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_or: when giving the papers to the customs officer, gets called against a pointer instead of a number - bug #4939 + { GID_ECOQUEST2, 100, 0, 0, "Rain", "points", 0xce0, NULL, 0, { WORKAROUND_FAKE, 0 } }, // Same as above, for the Spanish version - bug #5750 + { GID_FANMADE, 516, 983, 0, "Wander", "setTarget", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_mul: The Legend of the Lost Jewel Demo (fan made): called with object as second parameter when attacked by insects - bug #5124 + { GID_GK1, 800,64992, 0, "Fwd", "doit", -1, NULL, 0, { WORKAROUND_FAKE, 1 } }, // op_gt: when Mosely finds Gabriel and Grace near the end of the game, compares the Grooper object with 7 + { GID_HOYLE4, 700, -1, 1, "Code", "doit", -1, NULL, 0, { WORKAROUND_FAKE, 1 } }, // op_add: while bidding in Bridge, an object ("Bid") is added to an object in another segment ("hand3") + { GID_ICEMAN, 199, 977, 0, "Grooper", "doit", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_add: While dancing with the girl + { GID_MOTHERGOOSE256, -1, 999, 0, "Event", "new", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_and: constantly during the game (SCI1 version) + { GID_MOTHERGOOSE256, -1, 4, 0, "rm004", "doit", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_or: when going north and reaching the castle (rooms 4 and 37) - bug #5101 + { GID_MOTHERGOOSEHIRES,90, 90, 0, "newGameButton", "select", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_ge: MUMG Deluxe, when selecting "New Game" in the main menu. It tries to compare an integer with a list. Needs to return false for the game to continue. + { GID_PHANTASMAGORIA, 902, 0, 0, "", "export 7", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_shr: when starting a chapter in Phantasmagoria + { GID_QFG1VGA, 301, 928, 0, "Blink", "init", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_div: when entering the inn, gets called with 1 parameter, but 2nd parameter is used for div which happens to be an object + { GID_QFG2, 200, 200, 0, "astro", "messages", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_lsi: when getting asked for your name by the astrologer - bug #5152 + { GID_QFG3, 780, 999, 0, "", "export 6", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_add: trying to talk to yourself at the top of the giant tree - bug #6692 + { GID_QFG4, 710,64941, 0, "RandCycle", "doit", -1, NULL, 0, { WORKAROUND_FAKE, 1 } }, // op_gt: when the tentacle appears in the third room of the caves + SCI_WORKAROUNDENTRY_TERMINATOR +}; + +// QfG3: rm140::init subcall +static const uint16 sig_uninitread_qfg3_1[] = { + 0x3f, 0x01, // link 01 + 0x89, 0x7d, // lsg global[7Dh] + 0x35, 0x03, // ldi 03 + SIG_END +}; + +// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround const SciWorkaroundEntry uninitializedReadWorkarounds[] = { - { GID_CAMELOT, 40, 40, 0, "Rm40", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // when looking at the ground at the pool of Siloam - bug #6401 - { GID_CASTLEBRAIN, 280, 280, 0, "programmer", "dispatchEvent", -1, 0, { WORKAROUND_FAKE, 0xf } }, // pressing 'q' on the computer screen in the robot room, and closing the help dialog that pops up (bug #5143). Moves the cursor to the view with the ID returned (in this case, the robot hand) - { GID_CNICK_KQ, -1, 0, 1, "Character", "say", -1, -1, { WORKAROUND_FAKE, 0 } }, // checkers/backgammon, like in hoyle 3 - temps 504 and 505 - bug #6255 - { GID_CNICK_KQ, -1, 700, 0, "gcWindow", "open", -1, -1, { WORKAROUND_FAKE, 0 } }, // when entering the control menu, like in hoyle 3 - { GID_CNICK_KQ, 300, 303, 0, "theDoubleCube", "", -1, 5, { WORKAROUND_FAKE, 0 } }, // while playing backgammon with doubling enabled - bug #6426 (same as the theDoubleCube::make workaround for Hoyle 3) - { GID_CNICK_KQ, 300, 303, 0, "theDoubleCube", "", -1, 9, { WORKAROUND_FAKE, 0 } }, // when accepting a double, while playing backgammon with doubling enabled (same as the theDoubleCube::accept workaround for Hoyle 3) - { GID_CNICK_LAURABOW, -1, 0, 1, "Character", "say", -1, -1, { WORKAROUND_FAKE, 0 } }, // Yatch, like in hoyle 3 - temps 504 and 505 - bug #6424 - { GID_CNICK_LAURABOW, -1, 700, 0, NULL, "open", -1, -1, { WORKAROUND_FAKE, 0 } }, // when entering control menu - bug #6423 (same as the gcWindow workaround for Hoyle 3) - { GID_CNICK_LAURABOW,100, 100, 0, NULL, "", -1, 1, { WORKAROUND_FAKE, 0 } }, // while playing domino - bug #6429 (same as the dominoHand2 workaround for Hoyle 3) - { GID_CNICK_LAURABOW,100, 110, 0, NULL, "doit", -1, -1, { WORKAROUND_FAKE, 0 } }, // when changing the "Dominoes per hand" setting - bug #6430 - { GID_CNICK_LONGBOW, 0, 0, 0, "RH Budget", "init", -1, 1, { WORKAROUND_FAKE, 0 } }, // when starting the game - { GID_ECOQUEST, -1, -1, 0, NULL, "doVerb", -1, 0, { WORKAROUND_FAKE, 0 } }, // almost clicking anywhere triggers this in almost all rooms - { GID_FANMADE, 516, 979, 0, "", "export 0", -1, 20, { WORKAROUND_FAKE, 0 } }, // Happens in Grotesteing after the logos - { GID_FANMADE, 528, 990, 0, "GDialog", "doit", -1, 4, { WORKAROUND_FAKE, 0 } }, // Happens in Cascade Quest when closing the glossary - bug #5116 - { GID_FANMADE, 488, 1, 0, "RoomScript", "doit", 0x1f17, 1, { WORKAROUND_FAKE, 0 } }, // Happens in Ocean Battle while playing - bug #5335 - { GID_FREDDYPHARKAS, -1, 24, 0, "gcWin", "open", -1, 5, { WORKAROUND_FAKE, 0xf } }, // is used as priority for game menu - { GID_FREDDYPHARKAS, -1, 31, 0, "quitWin", "open", -1, 5, { WORKAROUND_FAKE, 0xf } }, // is used as priority for game menu - { GID_FREDDYPHARKAS, 540, 540, 0, "WaverCode", "init", -1, -1, { WORKAROUND_FAKE, 0 } }, // Gun pratice mini-game - bug #5232 - { GID_GK1, -1, 64950, -1, "Feature", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // sometimes when walk-clicking - { GID_GK2, -1, 11, 0, "", "export 10", -1, 3, { WORKAROUND_FAKE, 0 } }, // called when the game starts - { GID_GK2, -1, 11, 0, "", "export 10", -1, 4, { WORKAROUND_FAKE, 0 } }, // called during the game - { GID_HOYLE1, 4, 104, 0, "GinRummyCardList", "calcRuns", -1, 4, { WORKAROUND_FAKE, 0 } }, // Gin Rummy / right when the game starts - { GID_HOYLE1, 5, 204, 0, "tableau", "checkRuns", -1, 2, { WORKAROUND_FAKE, 0 } }, // Cribbage / during the game - { GID_HOYLE1, 3, 16, 0, "", "export 0", 0x37c, 3, { WORKAROUND_FAKE, 0 } }, // Hearts / during the game - bug #5299 - { GID_HOYLE1, -1, 997, 0, "MenuBar", "doit", -1, 0, { WORKAROUND_FAKE, 0 } }, // When changing game speed settings - bug #5512 - { GID_HOYLE3, -1, 0, 1, "Character", "say", -1, -1, { WORKAROUND_FAKE, 0 } }, // when starting checkers or dominoes, first time a character says something - temps 504 and 505 - { GID_HOYLE3, -1, 700, 0, "gcWindow", "open", -1, -1, { WORKAROUND_FAKE, 0 } }, // when entering control menu - { GID_HOYLE3, 100, 100, 0, "dominoHand2", "cue", -1, 1, { WORKAROUND_FAKE, 0 } }, // while playing domino - bug #5042 - { GID_HOYLE3, 100, 110, 0, "OKButton", "doit", -1, -1, { WORKAROUND_FAKE, 0 } }, // when changing the "Dominoes per hand" setting - bug #6430 - { GID_HOYLE3, 300, 303, 0, "theDoubleCube", "make", -1, 5, { WORKAROUND_FAKE, 0 } }, // while playing backgammon with doubling enabled - { GID_HOYLE3, 300, 303, 0, "theDoubleCube", "accept", -1, 9, { WORKAROUND_FAKE, 0 } }, // when accepting a double, while playing backgammon with doubling enabled - { GID_HOYLE4, -1, 0, 0, NULL, "open", -1, -1, { WORKAROUND_FAKE, 0 } }, // when selecting "Control" from the menu (temp vars 0-3) - bug #5132 - { GID_HOYLE4, 910, 18, 0, NULL, "init", -1, 0, { WORKAROUND_FAKE, 0 } }, // during tutorial - bug #5213 - { GID_HOYLE4, 910, 910, 0, NULL, "setup", -1, 3, { WORKAROUND_FAKE, 0 } }, // when selecting "Tutorial" from the main menu - bug #5132 - { GID_HOYLE4, 700, 700, 1, "BridgeHand", "calcQTS", -1, 3, { WORKAROUND_FAKE, 0 } }, // when placing a bid in bridge (always) - { GID_HOYLE4, 700, 710, 1, "BridgeStrategyPlay", "checkSplitTops", -1, 10, { WORKAROUND_FAKE, 0 } }, // while playing bridge, objects LeadReturn_Trump, SecondSeat_Trump, ThirdSeat_Trump and others - bug #5794 - { GID_HOYLE4, 700, -1, 1, "BridgeDefense", "think", -1, -1, { WORKAROUND_FAKE, 0 } }, // sometimes while playing bridge, temp var 3, 17 and others, objects LeadReturn_Trump, ThirdSeat_Trump and others - { GID_HOYLE4, 700, 730, 1, "BridgeDefense", "beatTheirBest", -1, 3, { WORKAROUND_FAKE, 0 } }, // rarely while playing bridge - { GID_HOYLE4, 700, -1, 1, "Code", "doit", -1, -1, { WORKAROUND_FAKE, 0 } }, // when placing a bid in bridge (always), temp var 11, 24, 27, 46, 75, objects compete_tree, compwe_tree, other1_tree, b1 - bugs #5663 and #5794 - { GID_HOYLE4, 700, 921, 0, "Print", "addEdit", -1, 0, { WORKAROUND_FAKE, 118 } }, // when saving the game (may also occur in other situations) - bug #6601, bug #6614 - { GID_HOYLE4, 700, 921, 0, "Print", "addEdit", -1, 1, { WORKAROUND_FAKE, 1 } }, // see above, Text-control saves its coordinates to temp[0] and temp[1], Edit-control adjusts to those uninitialized temps, who by accident were left over from the Text-control - { GID_HOYLE4, 300, 300, 0, "", "export 2", 0x1d4d, 0, { WORKAROUND_FAKE, 0 } }, // after passing around cards in hearts - { GID_HOYLE4, 400, 400, 1, "GinHand", "calcRuns", -1, 4, { WORKAROUND_FAKE, 0 } }, // sometimes while playing Gin Rummy (e.g. when knocking and placing a card) - bug #5665 - { GID_HOYLE4, 500, 17, 1, "Character", "say", -1, 504, { WORKAROUND_FAKE, 0 } }, // sometimes while playing Cribbage (e.g. when the opponent says "Last Card") - bug #5662 - { GID_HOYLE4, 800, 870, 0, "EuchreStrategy", "thinkLead", -1, 0, { WORKAROUND_FAKE, 0 } }, // while playing Euchre, happens at least on 2nd or 3rd turn - bug #6602 - { GID_HOYLE4, -1, 937, 0, "IconBar", "dispatchEvent", -1, 408, { WORKAROUND_FAKE, 0 } }, // pressing ENTER on scoreboard while mouse is not on OK button, may not happen all the time - bug #6603 - { GID_ISLANDBRAIN, 100, 937, 0, "IconBar", "dispatchEvent", -1, 58, { WORKAROUND_FAKE, 0 } }, // when using ENTER at the startup menu - bug #5241 - { GID_ISLANDBRAIN, 140, 140, 0, "piece", "init", -1, 3, { WORKAROUND_FAKE, 1 } }, // first puzzle right at the start, some initialization variable. bnt is done on it, and it should be non-0 - { GID_ISLANDBRAIN, 200, 268, 0, "anElement", "select", -1, 0, { WORKAROUND_FAKE, 0 } }, // elements puzzle, gets used before super TextIcon - { GID_JONES, 1, 232, 0, "weekendText", "draw", 0x3d3, 0, { WORKAROUND_FAKE, 0 } }, // jones/cd only - gets called during the game - { GID_JONES, 1, 255, 0, "", "export 0", -1, -1, { WORKAROUND_FAKE, 0 } }, // jones/cd only - called when a game ends, temps 13 and 14 - { GID_JONES, 764, 255, 0, "", "export 0", -1, -1, { WORKAROUND_FAKE, 0 } }, // jones/ega&vga only - called when the game starts, temps 13 and 14 - //{ GID_KQ5, -1, 0, 0, "", "export 29", -1, 3, { WORKAROUND_FAKE, 0xf } }, // called when playing harp for the harpies or when aborting dialog in toy shop, is used for kDoAudio - bug #4961 + { GID_CAMELOT, 40, 40, 0, "Rm40", "handleEvent", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // when looking at the ground at the pool of Siloam - bug #6401 + { GID_CASTLEBRAIN, 280, 280, 0, "programmer", "dispatchEvent", -1, NULL, 0, { WORKAROUND_FAKE, 0xf } }, // pressing 'q' on the computer screen in the robot room, and closing the help dialog that pops up (bug #5143). Moves the cursor to the view with the ID returned (in this case, the robot hand) + { GID_CNICK_KQ, -1, 0, 1, "Character", "say", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // checkers/backgammon, like in hoyle 3 - temps 504 and 505 - bug #6255 + { GID_CNICK_KQ, -1, 700, 0, "gcWindow", "open", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // when entering the control menu, like in hoyle 3 + { GID_CNICK_KQ, 300, 303, 0, "theDoubleCube", "", -1, NULL, 5, { WORKAROUND_FAKE, 0 } }, // while playing backgammon with doubling enabled - bug #6426 (same as the theDoubleCube::make workaround for Hoyle 3) + { GID_CNICK_KQ, 300, 303, 0, "theDoubleCube", "", -1, NULL, 9, { WORKAROUND_FAKE, 0 } }, // when accepting a double, while playing backgammon with doubling enabled (same as the theDoubleCube::accept workaround for Hoyle 3) + { GID_CNICK_LAURABOW, -1, 0, 1, "Character", "say", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // Yatch, like in hoyle 3 - temps 504 and 505 - bug #6424 + { GID_CNICK_LAURABOW, -1, 700, 0, NULL, "open", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // when entering control menu - bug #6423 (same as the gcWindow workaround for Hoyle 3) + { GID_CNICK_LAURABOW,100, 100, 0, NULL, "", -1, NULL, 1, { WORKAROUND_FAKE, 0 } }, // while playing domino - bug #6429 (same as the dominoHand2 workaround for Hoyle 3) + { GID_CNICK_LAURABOW,100, 110, 0, NULL, "doit", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // when changing the "Dominoes per hand" setting - bug #6430 + { GID_CNICK_LONGBOW, 0, 0, 0, "RH Budget", "init", -1, NULL, 1, { WORKAROUND_FAKE, 0 } }, // when starting the game + { GID_ECOQUEST, -1, -1, 0, NULL, "doVerb", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // almost clicking anywhere triggers this in almost all rooms + { GID_FANMADE, 516, 979, 0, "", "export 0", -1, NULL, 20, { WORKAROUND_FAKE, 0 } }, // Happens in Grotesteing after the logos + { GID_FANMADE, 528, 990, 0, "GDialog", "doit", -1, NULL, 4, { WORKAROUND_FAKE, 0 } }, // Happens in Cascade Quest when closing the glossary - bug #5116 + { GID_FANMADE, 488, 1, 0, "RoomScript", "doit", 0x1f17, NULL, 1, { WORKAROUND_FAKE, 0 } }, // Happens in Ocean Battle while playing - bug #5335 + { GID_FREDDYPHARKAS, -1, 24, 0, "gcWin", "open", -1, NULL, 5, { WORKAROUND_FAKE, 0xf } }, // is used as priority for game menu + { GID_FREDDYPHARKAS, -1, 31, 0, "quitWin", "open", -1, NULL, 5, { WORKAROUND_FAKE, 0xf } }, // is used as priority for game menu + { GID_FREDDYPHARKAS, 540, 540, 0, "WaverCode", "init", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // Gun pratice mini-game - bug #5232 + { GID_GK1, -1, 64950, -1, "Feature", "handleEvent", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // sometimes when walk-clicking + { GID_GK2, -1, 11, 0, "", "export 10", -1, NULL, 3, { WORKAROUND_FAKE, 0 } }, // called when the game starts + { GID_GK2, -1, 11, 0, "", "export 10", -1, NULL, 4, { WORKAROUND_FAKE, 0 } }, // called during the game + { GID_HOYLE1, 4, 104, 0, "GinRummyCardList", "calcRuns", -1, NULL, 4, { WORKAROUND_FAKE, 0 } }, // Gin Rummy / right when the game starts + { GID_HOYLE1, 5, 204, 0, "tableau", "checkRuns", -1, NULL, 2, { WORKAROUND_FAKE, 0 } }, // Cribbage / during the game + { GID_HOYLE1, 3, 16, 0, "", "export 0", 0x37c, NULL, 3, { WORKAROUND_FAKE, 0 } }, // Hearts / during the game - bug #5299 + { GID_HOYLE1, -1, 997, 0, "MenuBar", "doit", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // When changing game speed settings - bug #5512 + { GID_HOYLE3, -1, 0, 1, "Character", "say", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // when starting checkers or dominoes, first time a character says something - temps 504 and 505 + { GID_HOYLE3, -1, 700, 0, "gcWindow", "open", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // when entering control menu + { GID_HOYLE3, 100, 100, 0, "dominoHand2", "cue", -1, NULL, 1, { WORKAROUND_FAKE, 0 } }, // while playing domino - bug #5042 + { GID_HOYLE3, 100, 110, 0, "OKButton", "doit", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // when changing the "Dominoes per hand" setting - bug #6430 + { GID_HOYLE3, 300, 303, 0, "theDoubleCube", "make", -1, NULL, 5, { WORKAROUND_FAKE, 0 } }, // while playing backgammon with doubling enabled + { GID_HOYLE3, 300, 303, 0, "theDoubleCube", "accept", -1, NULL, 9, { WORKAROUND_FAKE, 0 } }, // when accepting a double, while playing backgammon with doubling enabled + { GID_HOYLE4, -1, 0, 0, NULL, "open", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // when selecting "Control" from the menu (temp vars 0-3) - bug #5132 + { GID_HOYLE4, 910, 18, 0, NULL, "init", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // during tutorial - bug #5213 + { GID_HOYLE4, 910, 910, 0, NULL, "setup", -1, NULL, 3, { WORKAROUND_FAKE, 0 } }, // when selecting "Tutorial" from the main menu - bug #5132 + { GID_HOYLE4, 700, 700, 1, "BridgeHand", "calcQTS", -1, NULL, 3, { WORKAROUND_FAKE, 0 } }, // when placing a bid in bridge (always) + { GID_HOYLE4, 700, 710, 1, "BridgeStrategyPlay", "checkSplitTops", -1, NULL, 10, { WORKAROUND_FAKE, 0 } }, // while playing bridge, objects LeadReturn_Trump, SecondSeat_Trump, ThirdSeat_Trump and others - bug #5794 + { GID_HOYLE4, 700, -1, 1, "BridgeDefense", "think", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // sometimes while playing bridge, temp var 3, 17 and others, objects LeadReturn_Trump, ThirdSeat_Trump and others + { GID_HOYLE4, 700, 730, 1, "BridgeDefense", "beatTheirBest", -1, NULL, 3, { WORKAROUND_FAKE, 0 } }, // rarely while playing bridge + { GID_HOYLE4, 700, -1, 1, "Code", "doit", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // when placing a bid in bridge (always), temp var 11, 24, 27, 46, 75, objects compete_tree, compwe_tree, other1_tree, b1 - bugs #5663 and #5794 + { GID_HOYLE4, 700, 921, 0, "Print", "addEdit", -1, NULL, 0, { WORKAROUND_FAKE, 118 } }, // when saving the game (may also occur in other situations) - bug #6601, bug #6614 + { GID_HOYLE4, 700, 921, 0, "Print", "addEdit", -1, NULL, 1, { WORKAROUND_FAKE, 1 } }, // see above, Text-control saves its coordinates to temp[0] and temp[1], Edit-control adjusts to those uninitialized temps, who by accident were left over from the Text-control + { GID_HOYLE4, 300, 300, 0, "", "export 2", 0x1d4d, NULL, 0, { WORKAROUND_FAKE, 0 } }, // after passing around cards in hearts + { GID_HOYLE4, 400, 400, 1, "GinHand", "calcRuns", -1, NULL, 4, { WORKAROUND_FAKE, 0 } }, // sometimes while playing Gin Rummy (e.g. when knocking and placing a card) - bug #5665 + { GID_HOYLE4, 500, 17, 1, "Character", "say", -1, NULL, 504, { WORKAROUND_FAKE, 0 } }, // sometimes while playing Cribbage (e.g. when the opponent says "Last Card") - bug #5662 + { GID_HOYLE4, 800, 870, 0, "EuchreStrategy", "thinkLead", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // while playing Euchre, happens at least on 2nd or 3rd turn - bug #6602 + { GID_HOYLE4, -1, 937, 0, "IconBar", "dispatchEvent", -1, NULL, 408, { WORKAROUND_FAKE, 0 } }, // pressing ENTER on scoreboard while mouse is not on OK button, may not happen all the time - bug #6603 + { GID_ISLANDBRAIN, 100, 937, 0, "IconBar", "dispatchEvent", -1, NULL, 58, { WORKAROUND_FAKE, 0 } }, // when using ENTER at the startup menu - bug #5241 + { GID_ISLANDBRAIN, 140, 140, 0, "piece", "init", -1, NULL, 3, { WORKAROUND_FAKE, 1 } }, // first puzzle right at the start, some initialization variable. bnt is done on it, and it should be non-0 + { GID_ISLANDBRAIN, 200, 268, 0, "anElement", "select", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // elements puzzle, gets used before super TextIcon + { GID_JONES, 1, 232, 0, "weekendText", "draw", 0x3d3, NULL, 0, { WORKAROUND_FAKE, 0 } }, // jones/cd only - gets called during the game + { GID_JONES, 1, 255, 0, "", "export 0", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // jones/cd only - called when a game ends, temps 13 and 14 + { GID_JONES, 764, 255, 0, "", "export 0", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // jones/ega&vga only - called when the game starts, temps 13 and 14 + //{ GID_KQ5, -1, 0, 0, "", "export 29", -1, NULL, 3, { WORKAROUND_FAKE, 0xf } }, // called when playing harp for the harpies or when aborting dialog in toy shop, is used for kDoAudio - bug #4961 // ^^ shouldn't be needed anymore, we got a script patch instead (kq5PatchCdHarpyVolume) - { GID_KQ5, 25, 25, 0, "rm025", "doit", -1, 0, { WORKAROUND_FAKE, 0 } }, // inside witch forest, when going to the room where the walking rock is - { GID_KQ5, 55, 55, 0, "helpScript", "doit", -1, 0, { WORKAROUND_FAKE, 0 } }, // when giving the tambourine to the monster in the labyrinth (only happens at one of the locations) - bug #5198 - { GID_KQ5, -1, 755, 0, "gcWin", "open", -1, -1, { WORKAROUND_FAKE, 0 } }, // when entering control menu in the FM-Towns version - { GID_KQ6, -1, 30, 0, "rats", "changeState", -1, -1, { WORKAROUND_FAKE, 0 } }, // rats in the catacombs (temps 1 - 5) - bugs #4958, #4998, #5017 - { GID_KQ6, 210, 210, 0, "rm210", "scriptCheck", -1, 0, { WORKAROUND_FAKE, 1 } }, // using inventory in that room - bug #4953 - { GID_KQ6, 500, 500, 0, "rm500", "init", -1, 0, { WORKAROUND_FAKE, 0 } }, // going to island of the beast - { GID_KQ6, 520, 520, 0, "rm520", "init", -1, 0, { WORKAROUND_FAKE, 0 } }, // going to boiling water trap on beast isle - { GID_KQ6, -1, 903, 0, "controlWin", "open", -1, 4, { WORKAROUND_FAKE, 0 } }, // when opening the controls window (save, load etc) - { GID_KQ6, -1, 907, 0, "tomato", "doVerb", -1, 2, { WORKAROUND_FAKE, 0 } }, // when looking at the rotten tomato in the inventory - bug #5331 - { GID_KQ6, -1, 928, 0, NULL, "startText", -1, 0, { WORKAROUND_FAKE, 0 } }, // gets caused by Text+Audio support (see script patcher) - { GID_KQ7, -1, 64996, 0, "User", "handleEvent", -1, 1, { WORKAROUND_FAKE, 0 } }, // called when pushing a keyboard key - { GID_LAURABOW, 37, 0, 0, "CB1", "doit", -1, 1, { WORKAROUND_FAKE, 0 } }, // when going up the stairs - bug #5084 - { GID_LAURABOW, -1, 967, 0, "myIcon", "cycle", -1, 1, { WORKAROUND_FAKE, 0 } }, // having any portrait conversation coming up - initial bug #4971 - { GID_LAURABOW2, -1, 24, 0, "gcWin", "open", -1, 5, { WORKAROUND_FAKE, 0xf } }, // is used as priority for game menu - { GID_LAURABOW2, -1, 21, 0, "dropCluesCode", "doit", -1, 1, { WORKAROUND_FAKE, 0x7fff } }, // when asking some questions (e.g. the reporter about the burglary, or the policeman about Ziggy). Must be big, as the game scripts perform lt on it and start deleting journal entries - bugs #4979, #5026 - { GID_LAURABOW2, -1, 90, 1, "MuseumActor", "init", -1, 6, { WORKAROUND_FAKE, 0 } }, // Random actors in museum - bug #5197 - { GID_LAURABOW2, 240, 240, 0, "sSteveAnimates", "changeState", -1, 0, { WORKAROUND_FAKE, 0 } }, // Steve Dorian's idle animation at the docks - bug #5028 - { GID_LAURABOW2, -1, 928, 0, NULL, "startText", -1, 0, { WORKAROUND_FAKE, 0 } }, // gets caused by Text+Audio support (see script patcher) - { GID_LONGBOW, -1, 0, 0, "Longbow", "restart", -1, 0, { WORKAROUND_FAKE, 0 } }, // When canceling a restart game - bug #5244 - { GID_LONGBOW, -1, 213, 0, "clear", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // When giving an answer using the druid hand sign code in any room - { GID_LONGBOW, -1, 213, 0, "letter", "handleEvent", 0xa8, 1, { WORKAROUND_FAKE, 0 } }, // When using the druid hand sign code in any room - bug #5035 - { GID_LSL1, 250, 250, 0, "increase", "handleEvent", -1, 2, { WORKAROUND_FAKE, 0 } }, // casino, playing game, increasing bet - { GID_LSL1, 720, 720, 0, "rm720", "init", -1, 0, { WORKAROUND_FAKE, 0 } }, // age check room - { GID_LSL2, 38, 38, 0, "cloudScript", "changeState", -1, 1, { WORKAROUND_FAKE, 0 } }, // entering the room in the middle deck of the ship - bug #5034 - { GID_LSL3, 340, 340, 0, "ComicScript", "changeState", -1, -1, { WORKAROUND_FAKE, 0 } }, // right after entering the 3 ethnic groups inside comedy club (temps 200, 201, 202, 203) - { GID_LSL3, -1, 997, 0, "TheMenuBar", "handleEvent", -1, 1, { WORKAROUND_FAKE, 0xf } }, // when setting volume the first time, this temp is used to set volume on entry (normally it would have been initialized to 's') - { GID_LSL6, 820, 82, 0, "", "export 0", -1, -1, { WORKAROUND_FAKE, 0 } }, // when touching the electric fence - bug #5103 - { GID_LSL6, -1, 85, 0, "washcloth", "doVerb", -1, 0, { WORKAROUND_FAKE, 0 } }, // washcloth in inventory - { GID_LSL6, -1, 928, -1, "Narrator", "startText", -1, 0, { WORKAROUND_FAKE, 0 } }, // used by various objects that are even translated in foreign versions, that's why we use the base-class - { GID_LSL6HIRES, 0, 85, 0, "LL6Inv", "init", -1, 0, { WORKAROUND_FAKE, 0 } }, // on startup - { GID_LSL6HIRES, -1, 64950, 1, "Feature", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // at least when entering swimming pool area - { GID_LSL6HIRES, -1, 64964, 0, "DPath", "init", -1, 1, { WORKAROUND_FAKE, 0 } }, // during the game - { GID_MOTHERGOOSE256, -1, 0, 0, "MG", "doit", -1, 5, { WORKAROUND_FAKE, 0 } }, // SCI1.1: When moving the cursor all the way to the left during the game - bug #5224 - { GID_MOTHERGOOSE256, -1, 992, 0, "AIPath", "init", -1, 0, { WORKAROUND_FAKE, 0 } }, // Happens in the demo and full version. In the demo, it happens when walking two screens from mother goose's house to the north. In the full version, it happens in rooms 7 and 23 - bug #5269 - { GID_MOTHERGOOSE256, 90, 90, 0, "introScript", "changeState", -1, 65, { WORKAROUND_FAKE, 0 } }, // SCI1(CD): At the very end, after the game is completed and restarted - bug #5626 - { GID_MOTHERGOOSE256, 94, 94, 0, "sunrise", "changeState", -1, 367, { WORKAROUND_FAKE, 0 } }, // At the very end, after the game is completed - bug #5294 - { GID_MOTHERGOOSEHIRES,-1,64950, 1, "Feature", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // right when clicking on a child at the start and probably also later - { GID_MOTHERGOOSEHIRES,-1,64950, 1, "View", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // see above - { GID_PEPPER, -1, 894, 0, "Package", "doVerb", -1, 3, { WORKAROUND_FAKE, 0 } }, // using the hand on the book in the inventory - bug #5154 - { GID_PEPPER, 150, 928, 0, "Narrator", "startText", -1, 0, { WORKAROUND_FAKE, 0 } }, // happens during the non-interactive demo of Pepper - { GID_PQ4, -1, 25, 0, "iconToggle", "select", -1, 1, { WORKAROUND_FAKE, 0 } }, // when toggling the icon bar to auto-hide or not - { GID_PQSWAT, -1, 64950, 0, "View", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // Using the menu in the beginning - { GID_QFG1, -1, 210, 0, "Encounter", "init", 0xbd0, 0, { WORKAROUND_FAKE, 0 } }, // hq1: going to the brigands hideout - { GID_QFG1, -1, 210, 0, "Encounter", "init", 0xbe4, 0, { WORKAROUND_FAKE, 0 } }, // qfg1: going to the brigands hideout - { GID_QFG1VGA, 16, 16, 0, "lassoFailed", "changeState", -1, -1, { WORKAROUND_FAKE, 0 } }, // qfg1vga: casting the "fetch" spell in the screen with the flowers, temps 0 and 1 - bug #5309 - { GID_QFG1VGA, -1, 210, 0, "Encounter", "init", 0xcee, 0, { WORKAROUND_FAKE, 0 } }, // qfg1vga: going to the brigands hideout - bug #5515 - { GID_QFG1VGA, -1, 210, 0, "Encounter", "init", 0xce7, 0, { WORKAROUND_FAKE, 0 } }, // qfg1vga: going to room 92 - { GID_QFG2, -1, 71, 0, "theInvSheet", "doit", -1, 1, { WORKAROUND_FAKE, 0 } }, // accessing the inventory - { GID_QFG2, -1, 701, -1, "Alley", "at", -1, 0, { WORKAROUND_FAKE, 0 } }, // when walking inside the alleys in the town - bug #5019 & #5106 - { GID_QFG2, -1, 990, 0, "Restore", "doit", -1, 364, { WORKAROUND_FAKE, 0 } }, // when pressing enter in restore dialog w/o any saved games present - { GID_QFG2, 260, 260, 0, "abdulS", "changeState",0x2d22, -1, { WORKAROUND_FAKE, 0 } }, // During the thief's first mission (in the house), just before Abdul is about to enter the house (where you have to hide in the wardrobe), bug #5153, temps 1 and 2 - { GID_QFG2, 260, 260, 0, "jabbarS", "changeState",0x2d22, -1, { WORKAROUND_FAKE, 0 } }, // During the thief's first mission (in the house), just before Jabbar is about to enter the house (where you have to hide in the wardrobe), bug #5164, temps 1 and 2 - { GID_QFG2, 500, 500, 0, "lightNextCandleS", "changeState", -1, -1, { WORKAROUND_FAKE, 0 } }, // Inside the last room, while Ad Avis performs the ritual to summon the genie - bug #5566 - { GID_QFG2, -1, 700, 0, NULL, "showSign", -1, 10, { WORKAROUND_FAKE, 0 } }, // Occurs sometimes when reading a sign in Raseir, Shapeir et al - bugs #5627, #5635 - { GID_QFG3, 510, 510, 0, "awardPrize", "changeState", -1, 0, { WORKAROUND_FAKE, 1 } }, // Simbani warrior challenge, after throwing the spears and retrieving the ring - bug #5277. Must be non-zero, otherwise the prize is awarded twice - bug #6160 - { GID_QFG3, 140, 140, 0, "rm140", "init", 0x1008, 0, { WORKAROUND_FAKE, 0 } }, // when importing a character and selecting the previous profession - bug #5163 - { GID_QFG3, 140, 140, 0, "rm140", "init", 0x11e4, 0, { WORKAROUND_FAKE, 0 } }, // when importing ... in the French version - { GID_QFG3, 140, 140, 0, "rm140", "init", 0x10f2, 0, { WORKAROUND_FAKE, 0 } }, // when importing ... in the German version - { GID_QFG3, 140, 140, 0, "rm140", "init", 0x11e3, 0, { WORKAROUND_FAKE, 0 } }, // when importing ... in the Italian version - { GID_QFG3, 140, 140, 0, "rm140", "init", 0x123d, 0, { WORKAROUND_FAKE, 0 } }, // when importing ... in the Spanish version - { GID_QFG3, 330, 330, -1, "Teller", "doChild", -1, -1, { WORKAROUND_FAKE, 0 } }, // when talking to King Rajah about "Rajah" (bug #5033, temp 1) or "Tarna" (temp 0), or when clicking on yourself and saying "Greet" (bug #5148, temp 1) - { GID_QFG3, 700, 700, -1, "monsterIsDead", "changeState", -1, 0, { WORKAROUND_FAKE, 0 } }, // in the jungle, after winning any fight, bug #5169 - { GID_QFG3, 470, 470, -1, "rm470", "notify", -1, 0, { WORKAROUND_FAKE, 0 } }, // closing the character screen in the Simbani village in the room with the bridge, bug #5165 - { GID_QFG3, 490, 490, -1, "computersMove", "changeState", -1, 0, { WORKAROUND_FAKE, 0 } }, // when finishing awari game, bug #5167 - { GID_QFG3, 490, 490, -1, "computersMove", "changeState", 0xf53, 4, { WORKAROUND_FAKE, 0 } }, // also when finishing awari game - { GID_QFG3, 851, 32, -1, "ProjObj", "doit", -1, 1, { WORKAROUND_FAKE, 0 } }, // near the end, when throwing the spear of death, bug #5282 - { GID_QFG4, -1, 15, -1, "charInitScreen", "dispatchEvent", -1, 5, { WORKAROUND_FAKE, 0 } }, // floppy version, when viewing the character screen - { GID_QFG4, -1, 64917, -1, "controlPlane", "setBitmap", -1, 3, { WORKAROUND_FAKE, 0 } }, // floppy version, when entering the game menu - { GID_QFG4, -1, 64917, -1, "Plane", "setBitmap", -1, 3, { WORKAROUND_FAKE, 0 } }, // floppy version, happens sometimes in fight scenes - { GID_QFG4, 520, 64950, 0, "fLake2", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // CD version, at the lake, when meeting the Rusalka and attempting to leave - { GID_QFG4, 800, 64950, 0, "View", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // CD version, in the room with the spider pillar, when climbing on the pillar - { GID_RAMA, 12, 64950, -1, "InterfaceFeature", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // Demo, right when it starts - { GID_RAMA, 12, 64950, -1, "hiliteOptText", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // Demo, right when it starts - { GID_RAMA, 12, 64950, -1, "View", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // Demo, right when it starts - { GID_SHIVERS, -1, 952, 0, "SoundManager", "stop", -1, 2, { WORKAROUND_FAKE, 0 } }, // Just after Sierra logo - { GID_SHIVERS, -1, 64950, 0, "Feature", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // When clicking on the locked door at the beginning - { GID_SHIVERS, -1, 64950, 0, "View", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // When clicking on the gargoyle eye at the beginning - { GID_SHIVERS, 20311, 64964, 0, "DPath", "init", -1, 1, { WORKAROUND_FAKE, 0 } }, // Just after door puzzle is solved and the metal balls start to roll - { GID_SHIVERS, 29260, 29260, 0, "spMars", "handleEvent", -1, 4, { WORKAROUND_FAKE, 0 } }, // When clicking mars after seeing fortune to align earth etc... - { GID_SHIVERS, 29260, 29260, 0, "spVenus", "handleEvent", -1, 4, { WORKAROUND_FAKE, 0 } }, // When clicking venus after seeing fortune to align earth etc... - { GID_SQ1, 103, 103, 0, "hand", "internalEvent", -1, -1, { WORKAROUND_FAKE, 0 } }, // Spanish (and maybe early versions?) only: when moving cursor over input pad, temps 1 and 2 - { GID_SQ1, -1, 703, 0, "", "export 1", -1, 0, { WORKAROUND_FAKE, 0 } }, // sub that's called from several objects while on sarien battle cruiser - { GID_SQ1, -1, 703, 0, "firePulsar", "changeState", 0x18a, 0, { WORKAROUND_FAKE, 0 } }, // export 1, but called locally (when shooting at aliens) - { GID_SQ4, -1, 398, 0, "showBox", "changeState", -1, 0, { WORKAROUND_FAKE, 0 } }, // CD: called when rummaging in Software Excess bargain bin - { GID_SQ4, -1, 928, -1, "Narrator", "startText", -1, 1000, { WORKAROUND_FAKE, 1 } }, // CD: happens in the options dialog and in-game when speech and subtitles are used simultaneously - { GID_SQ4, -1, 708, -1, "exitBut", "doVerb", -1, 0, { WORKAROUND_FAKE, 0 } }, // Floppy: happens, when looking at the "close" button in the sq4 hintbook - bug #6447 - { GID_SQ4, -1, 708, -1, "", "doVerb", -1, 0, { WORKAROUND_FAKE, 0 } }, // Floppy: happens, when looking at the "close" button... in Russian version - bug #5573 - { GID_SQ4, -1, 708, -1, "prevBut", "doVerb", -1, 0, { WORKAROUND_FAKE, 0 } }, // Floppy: happens, when looking at the "previous" button in the sq4 hintbook - bug #6447 - { GID_SQ4, -1, 708, -1, "\xA8\xE6\xE3 \xAD\xA0\xA7\xA0\xA4.", "doVerb", -1, 0, { WORKAROUND_FAKE, 0 } }, // Floppy: happens, when looking at the "previous" button... in Russian version - bug #5573 - { GID_SQ4, -1, 708, -1, "nextBut", "doVerb", -1, 0, { WORKAROUND_FAKE, 0 } }, // Floppy: happens, when looking at the "next" button in the sq4 hintbook - bug #6447 - { GID_SQ4, -1, 708, -1, ".", "doVerb", -1, 0, { WORKAROUND_FAKE, 0 } }, // Floppy: happens, when looking at the "next" button... in Russian version - bug #5573 - { GID_SQ5, 201, 201, 0, "buttonPanel", "doVerb", -1, 0, { WORKAROUND_FAKE, 1 } }, // when looking at the orange or red button - bug #5112 - { GID_SQ6, -1, 0, 0, "SQ6", "init", -1, 2, { WORKAROUND_FAKE, 0 } }, // Demo and full version: called when the game starts (demo: room 0, full: room 100) - { GID_SQ6, -1, 64950, -1, "Feature", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // called when pressing "Start game" in the main menu, when entering the Orion's Belt bar (room 300), and perhaps other places - { GID_SQ6, -1, 64964, 0, "DPath", "init", -1, 1, { WORKAROUND_FAKE, 0 } }, // during the game - { GID_TORIN, -1, 64017, 0, "oFlags", "clear", -1, 0, { WORKAROUND_FAKE, 0 } }, // entering Torin's home in the French version - SCI_WORKAROUNDENTRY_TERMINATOR -}; - -// gameID, room,script,lvl, object-name, method-name, call,index, workaround + { GID_KQ5, 25, 25, 0, "rm025", "doit", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // inside witch forest, when going to the room where the walking rock is + { GID_KQ5, 55, 55, 0, "helpScript", "doit", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // when giving the tambourine to the monster in the labyrinth (only happens at one of the locations) - bug #5198 + { GID_KQ5, -1, 755, 0, "gcWin", "open", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // when entering control menu in the FM-Towns version + { GID_KQ6, -1, 30, 0, "rats", "changeState", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // rats in the catacombs (temps 1 - 5) - bugs #4958, #4998, #5017 + { GID_KQ6, 210, 210, 0, "rm210", "scriptCheck", -1, NULL, 0, { WORKAROUND_FAKE, 1 } }, // using inventory in that room - bug #4953 + { GID_KQ6, 500, 500, 0, "rm500", "init", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // going to island of the beast + { GID_KQ6, 520, 520, 0, "rm520", "init", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // going to boiling water trap on beast isle + { GID_KQ6, -1, 903, 0, "controlWin", "open", -1, NULL, 4, { WORKAROUND_FAKE, 0 } }, // when opening the controls window (save, load etc) + { GID_KQ6, -1, 907, 0, "tomato", "doVerb", -1, NULL, 2, { WORKAROUND_FAKE, 0 } }, // when looking at the rotten tomato in the inventory - bug #5331 + { GID_KQ6, -1, 928, 0, NULL, "startText", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // gets caused by Text+Audio support (see script patcher) + { GID_KQ7, -1, 64996, 0, "User", "handleEvent", -1, NULL, 1, { WORKAROUND_FAKE, 0 } }, // called when pushing a keyboard key + { GID_LAURABOW, 37, 0, 0, "CB1", "doit", -1, NULL, 1, { WORKAROUND_FAKE, 0 } }, // when going up the stairs - bug #5084 + { GID_LAURABOW, -1, 967, 0, "myIcon", "cycle", -1, NULL, 1, { WORKAROUND_FAKE, 0 } }, // having any portrait conversation coming up - initial bug #4971 + { GID_LAURABOW2, -1, 24, 0, "gcWin", "open", -1, NULL, 5, { WORKAROUND_FAKE, 0xf } }, // is used as priority for game menu + { GID_LAURABOW2, -1, 21, 0, "dropCluesCode", "doit", -1, NULL, 1, { WORKAROUND_FAKE, 0x7fff } }, // when asking some questions (e.g. the reporter about the burglary, or the policeman about Ziggy). Must be big, as the game scripts perform lt on it and start deleting journal entries - bugs #4979, #5026 + { GID_LAURABOW2, -1, 90, 1, "MuseumActor", "init", -1, NULL, 6, { WORKAROUND_FAKE, 0 } }, // Random actors in museum - bug #5197 + { GID_LAURABOW2, 240, 240, 0, "sSteveAnimates", "changeState", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // Steve Dorian's idle animation at the docks - bug #5028 + { GID_LAURABOW2, -1, 928, 0, NULL, "startText", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // gets caused by Text+Audio support (see script patcher) + { GID_LONGBOW, -1, 0, 0, "Longbow", "restart", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // When canceling a restart game - bug #5244 + { GID_LONGBOW, -1, 213, 0, "clear", "handleEvent", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // When giving an answer using the druid hand sign code in any room + { GID_LONGBOW, -1, 213, 0, "letter", "handleEvent", 0xa8, NULL, 1, { WORKAROUND_FAKE, 0 } }, // When using the druid hand sign code in any room - bug #5035 + { GID_LSL1, 250, 250, 0, "increase", "handleEvent", -1, NULL, 2, { WORKAROUND_FAKE, 0 } }, // casino, playing game, increasing bet + { GID_LSL1, 720, 720, 0, "rm720", "init", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // age check room + { GID_LSL2, 38, 38, 0, "cloudScript", "changeState", -1, NULL, 1, { WORKAROUND_FAKE, 0 } }, // entering the room in the middle deck of the ship - bug #5034 + { GID_LSL3, 340, 340, 0, "ComicScript", "changeState", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // right after entering the 3 ethnic groups inside comedy club (temps 200, 201, 202, 203) + { GID_LSL3, -1, 997, 0, "TheMenuBar", "handleEvent", -1, NULL, 1, { WORKAROUND_FAKE, 0xf } }, // when setting volume the first time, this temp is used to set volume on entry (normally it would have been initialized to 's') + { GID_LSL6, 820, 82, 0, "", "export 0", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // when touching the electric fence - bug #5103 + { GID_LSL6, -1, 85, 0, "washcloth", "doVerb", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // washcloth in inventory + { GID_LSL6, -1, 928, -1, "Narrator", "startText", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // used by various objects that are even translated in foreign versions, that's why we use the base-class + { GID_LSL6HIRES, 0, 85, 0, "LL6Inv", "init", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // on startup + { GID_LSL6HIRES, -1, 64950, 1, "Feature", "handleEvent", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // at least when entering swimming pool area + { GID_LSL6HIRES, -1, 64964, 0, "DPath", "init", -1, NULL, 1, { WORKAROUND_FAKE, 0 } }, // during the game + { GID_MOTHERGOOSE256, -1, 0, 0, "MG", "doit", -1, NULL, 5, { WORKAROUND_FAKE, 0 } }, // SCI1.1: When moving the cursor all the way to the left during the game - bug #5224 + { GID_MOTHERGOOSE256, -1, 992, 0, "AIPath", "init", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // Happens in the demo and full version. In the demo, it happens when walking two screens from mother goose's house to the north. In the full version, it happens in rooms 7 and 23 - bug #5269 + { GID_MOTHERGOOSE256, 90, 90, 0, "introScript", "changeState", -1, NULL, 65, { WORKAROUND_FAKE, 0 } }, // SCI1(CD): At the very end, after the game is completed and restarted - bug #5626 + { GID_MOTHERGOOSE256, 94, 94, 0, "sunrise", "changeState", -1, NULL, 367, { WORKAROUND_FAKE, 0 } }, // At the very end, after the game is completed - bug #5294 + { GID_MOTHERGOOSEHIRES,-1,64950, 1, "Feature", "handleEvent", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // right when clicking on a child at the start and probably also later + { GID_MOTHERGOOSEHIRES,-1,64950, 1, "View", "handleEvent", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // see above + { GID_PEPPER, -1, 894, 0, "Package", "doVerb", -1, NULL, 3, { WORKAROUND_FAKE, 0 } }, // using the hand on the book in the inventory - bug #5154 + { GID_PEPPER, 150, 928, 0, "Narrator", "startText", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // happens during the non-interactive demo of Pepper + { GID_PQ4, -1, 25, 0, "iconToggle", "select", -1, NULL, 1, { WORKAROUND_FAKE, 0 } }, // when toggling the icon bar to auto-hide or not + { GID_PQSWAT, -1, 64950, 0, "View", "handleEvent", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // Using the menu in the beginning + { GID_QFG1, -1, 210, 0, "Encounter", "init", 0xbd0, NULL, 0, { WORKAROUND_FAKE, 0 } }, // hq1: going to the brigands hideout + { GID_QFG1, -1, 210, 0, "Encounter", "init", 0xbe4, NULL, 0, { WORKAROUND_FAKE, 0 } }, // qfg1: going to the brigands hideout + { GID_QFG1VGA, 16, 16, 0, "lassoFailed", "changeState", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // qfg1vga: casting the "fetch" spell in the screen with the flowers, temps 0 and 1 - bug #5309 + { GID_QFG1VGA, -1, 210, 0, "Encounter", "init", 0xcee, NULL, 0, { WORKAROUND_FAKE, 0 } }, // qfg1vga: going to the brigands hideout - bug #5515 + { GID_QFG1VGA, -1, 210, 0, "Encounter", "init", 0xce7, NULL, 0, { WORKAROUND_FAKE, 0 } }, // qfg1vga: going to room 92 + { GID_QFG2, -1, 71, 0, "theInvSheet", "doit", -1, NULL, 1, { WORKAROUND_FAKE, 0 } }, // accessing the inventory + { GID_QFG2, -1, 701, -1, "Alley", "at", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // when walking inside the alleys in the town - bug #5019 & #5106 + { GID_QFG2, -1, 990, 0, "Restore", "doit", -1, NULL, 364, { WORKAROUND_FAKE, 0 } }, // when pressing enter in restore dialog w/o any saved games present + { GID_QFG2, 260, 260, 0, "abdulS", "changeState",0x2d22, NULL, -1, { WORKAROUND_FAKE, 0 } }, // During the thief's first mission (in the house), just before Abdul is about to enter the house (where you have to hide in the wardrobe), bug #5153, temps 1 and 2 + { GID_QFG2, 260, 260, 0, "jabbarS", "changeState",0x2d22, NULL, -1, { WORKAROUND_FAKE, 0 } }, // During the thief's first mission (in the house), just before Jabbar is about to enter the house (where you have to hide in the wardrobe), bug #5164, temps 1 and 2 + { GID_QFG2, 500, 500, 0, "lightNextCandleS", "changeState", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // Inside the last room, while Ad Avis performs the ritual to summon the genie - bug #5566 + { GID_QFG2, -1, 700, 0, NULL, "showSign", -1, NULL, 10, { WORKAROUND_FAKE, 0 } }, // Occurs sometimes when reading a sign in Raseir, Shapeir et al - bugs #5627, #5635 + { GID_QFG3, 510, 510, 0, "awardPrize", "changeState", -1, NULL, 0, { WORKAROUND_FAKE, 1 } }, // Simbani warrior challenge, after throwing the spears and retrieving the ring - bug #5277. Must be non-zero, otherwise the prize is awarded twice - bug #6160 + { GID_QFG3, 140, 140, 0, "rm140", "init", -1, sig_uninitread_qfg3_1, 0, { WORKAROUND_FAKE, 0 } }, // when importing a character and selecting the previous profession - bug #5163 + { GID_QFG3, 330, 330, -1, "Teller", "doChild", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // when talking to King Rajah about "Rajah" (bug #5033, temp 1) or "Tarna" (temp 0), or when clicking on yourself and saying "Greet" (bug #5148, temp 1) + { GID_QFG3, 700, 700, -1, "monsterIsDead", "changeState", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // in the jungle, after winning any fight, bug #5169 + { GID_QFG3, 470, 470, -1, "rm470", "notify", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // closing the character screen in the Simbani village in the room with the bridge, bug #5165 + { GID_QFG3, 490, 490, -1, "computersMove", "changeState", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // when finishing awari game, bug #5167 + { GID_QFG3, 490, 490, -1, "computersMove", "changeState", 0xf53, NULL, 4, { WORKAROUND_FAKE, 0 } }, // also when finishing awari game + { GID_QFG3, 851, 32, -1, "ProjObj", "doit", -1, NULL, 1, { WORKAROUND_FAKE, 0 } }, // near the end, when throwing the spear of death, bug #5282 + { GID_QFG4, -1, 15, -1, "charInitScreen", "dispatchEvent", -1, NULL, 5, { WORKAROUND_FAKE, 0 } }, // floppy version, when viewing the character screen + { GID_QFG4, -1, 64917, -1, "controlPlane", "setBitmap", -1, NULL, 3, { WORKAROUND_FAKE, 0 } }, // floppy version, when entering the game menu + { GID_QFG4, -1, 64917, -1, "Plane", "setBitmap", -1, NULL, 3, { WORKAROUND_FAKE, 0 } }, // floppy version, happens sometimes in fight scenes + { GID_QFG4, 520, 64950, 0, "fLake2", "handleEvent", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // CD version, at the lake, when meeting the Rusalka and attempting to leave + { GID_QFG4, 800, 64950, 0, "View", "handleEvent", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // CD version, in the room with the spider pillar, when climbing on the pillar + { GID_RAMA, 12, 64950, -1, "InterfaceFeature", "handleEvent", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // Demo, right when it starts + { GID_RAMA, 12, 64950, -1, "hiliteOptText", "handleEvent", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // Demo, right when it starts + { GID_RAMA, 12, 64950, -1, "View", "handleEvent", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // Demo, right when it starts + { GID_SHIVERS, -1, 952, 0, "SoundManager", "stop", -1, NULL, 2, { WORKAROUND_FAKE, 0 } }, // Just after Sierra logo + { GID_SHIVERS, -1, 64950, 0, "Feature", "handleEvent", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // When clicking on the locked door at the beginning + { GID_SHIVERS, -1, 64950, 0, "View", "handleEvent", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // When clicking on the gargoyle eye at the beginning + { GID_SHIVERS, 20311, 64964, 0, "DPath", "init", -1, NULL, 1, { WORKAROUND_FAKE, 0 } }, // Just after door puzzle is solved and the metal balls start to roll + { GID_SHIVERS, 29260, 29260, 0, "spMars", "handleEvent", -1, NULL, 4, { WORKAROUND_FAKE, 0 } }, // When clicking mars after seeing fortune to align earth etc... + { GID_SHIVERS, 29260, 29260, 0, "spVenus", "handleEvent", -1, NULL, 4, { WORKAROUND_FAKE, 0 } }, // When clicking venus after seeing fortune to align earth etc... + { GID_SQ1, 103, 103, 0, "hand", "internalEvent", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // Spanish (and maybe early versions?) only: when moving cursor over input pad, temps 1 and 2 + { GID_SQ1, -1, 703, 0, "", "export 1", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // sub that's called from several objects while on sarien battle cruiser + { GID_SQ1, -1, 703, 0, "firePulsar", "changeState", 0x18a, NULL, 0, { WORKAROUND_FAKE, 0 } }, // export 1, but called locally (when shooting at aliens) + { GID_SQ4, -1, 398, 0, "showBox", "changeState", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // CD: called when rummaging in Software Excess bargain bin + { GID_SQ4, -1, 928, -1, "Narrator", "startText", -1, NULL, 1000, { WORKAROUND_FAKE, 1 } }, // CD: happens in the options dialog and in-game when speech and subtitles are used simultaneously + { GID_SQ4, -1, 708, -1, "exitBut", "doVerb", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // Floppy: happens, when looking at the "close" button in the sq4 hintbook - bug #6447 + { GID_SQ4, -1, 708, -1, "", "doVerb", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // Floppy: happens, when looking at the "close" button... in Russian version - bug #5573 + { GID_SQ4, -1, 708, -1, "prevBut", "doVerb", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // Floppy: happens, when looking at the "previous" button in the sq4 hintbook - bug #6447 + { GID_SQ4, -1, 708, -1, "\xA8\xE6\xE3 \xAD\xA0\xA7\xA0\xA4.", "doVerb", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // Floppy: happens, when looking at the "previous" button... in Russian version - bug #5573 + { GID_SQ4, -1, 708, -1, "nextBut", "doVerb", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // Floppy: happens, when looking at the "next" button in the sq4 hintbook - bug #6447 + { GID_SQ4, -1, 708, -1, ".", "doVerb", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // Floppy: happens, when looking at the "next" button... in Russian version - bug #5573 + { GID_SQ5, 201, 201, 0, "buttonPanel", "doVerb", -1, NULL, 0, { WORKAROUND_FAKE, 1 } }, // when looking at the orange or red button - bug #5112 + { GID_SQ6, -1, 0, 0, "SQ6", "init", -1, NULL, 2, { WORKAROUND_FAKE, 0 } }, // Demo and full version: called when the game starts (demo: room 0, full: room 100) + { GID_SQ6, -1, 64950, -1, "Feature", "handleEvent", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // called when pressing "Start game" in the main menu, when entering the Orion's Belt bar (room 300), and perhaps other places + { GID_SQ6, -1, 64964, 0, "DPath", "init", -1, NULL, 1, { WORKAROUND_FAKE, 0 } }, // during the game + { GID_TORIN, -1, 64017, 0, "oFlags", "clear", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // entering Torin's home in the French version + SCI_WORKAROUNDENTRY_TERMINATOR +}; + +// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround const SciWorkaroundEntry kAbs_workarounds[] = { - { GID_HOYLE1, 1, 1, 0, "room1", "doit", -1, 0, { WORKAROUND_FAKE, 0x3e9 } }, // crazy eights - called with objects instead of integers - { GID_HOYLE1, 2, 2, 0, "room2", "doit", -1, 0, { WORKAROUND_FAKE, 0x3e9 } }, // old maid - called with objects instead of integers - { GID_HOYLE1, 3, 3, 0, "room3", "doit", -1, 0, { WORKAROUND_FAKE, 0x3e9 } }, // hearts - called with objects instead of integers - { GID_QFG1VGA, -1, -1, 0, NULL, "doit", -1, 0, { WORKAROUND_FAKE, 0x3e9 } }, // when the game is patched with the NRS patch - { GID_QFG3 , -1, -1, 0, NULL, "doit", -1, 0, { WORKAROUND_FAKE, 0x3e9 } }, // when the game is patched with the NRS patch - bugs #6042, #6043 + { GID_HOYLE1, 1, 1, 0, "room1", "doit", -1, NULL, 0, { WORKAROUND_FAKE, 0x3e9 } }, // crazy eights - called with objects instead of integers + { GID_HOYLE1, 2, 2, 0, "room2", "doit", -1, NULL, 0, { WORKAROUND_FAKE, 0x3e9 } }, // old maid - called with objects instead of integers + { GID_HOYLE1, 3, 3, 0, "room3", "doit", -1, NULL, 0, { WORKAROUND_FAKE, 0x3e9 } }, // hearts - called with objects instead of integers + { GID_QFG1VGA, -1, -1, 0, NULL, "doit", -1, NULL, 0, { WORKAROUND_FAKE, 0x3e9 } }, // when the game is patched with the NRS patch + { GID_QFG3 , -1, -1, 0, NULL, "doit", -1, NULL, 0, { WORKAROUND_FAKE, 0x3e9 } }, // when the game is patched with the NRS patch - bugs #6042, #6043 SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call,index, workaround +// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround const SciWorkaroundEntry kCelHigh_workarounds[] = { - { GID_KQ5, -1, 255, 0, "deathIcon", "setSize", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // english floppy: when getting beaten up in the inn and probably more, called with 2nd parameter as object - bug #5049 - { GID_PQ2, -1, 255, 0, "DIcon", "setSize", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // when showing picture within windows, called with 2nd/3rd parameters as objects - { GID_SQ1, 1, 255, 0, "DIcon", "setSize", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // DEMO: Called with 2nd/3rd parameters as objects when clicking on the menu - bug #5012 - { GID_FANMADE, -1, 979, 0, "DIcon", "setSize", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // In The Gem Scenario and perhaps other fanmade games, this is called with 2nd/3rd parameters as objects - bug #5144 + { GID_KQ5, -1, 255, 0, "deathIcon", "setSize", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // english floppy: when getting beaten up in the inn and probably more, called with 2nd parameter as object - bug #5049 + { GID_PQ2, -1, 255, 0, "DIcon", "setSize", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // when showing picture within windows, called with 2nd/3rd parameters as objects + { GID_SQ1, 1, 255, 0, "DIcon", "setSize", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // DEMO: Called with 2nd/3rd parameters as objects when clicking on the menu - bug #5012 + { GID_FANMADE, -1, 979, 0, "DIcon", "setSize", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // In The Gem Scenario and perhaps other fanmade games, this is called with 2nd/3rd parameters as objects - bug #5144 SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call,index, workaround +// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround const SciWorkaroundEntry kCelWide_workarounds[] = { - { GID_KQ5, -1, 255, 0, "deathIcon", "setSize", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // english floppy: when getting beaten up in the inn and probably more, called with 2nd parameter as object - bug #5049 - { GID_PQ2, -1, 255, 0, "DIcon", "setSize", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // when showing picture within windows, called with 2nd/3rd parameters as objects - { GID_SQ1, 1, 255, 0, "DIcon", "setSize", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // DEMO: Called with 2nd/3rd parameters as objects when clicking on the menu - bug #5012 - { GID_FANMADE, -1, 979, 0, "DIcon", "setSize", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // In The Gem Scenario and perhaps other fanmade games, this is called with 2nd/3rd parameters as objects - bug #5144 + { GID_KQ5, -1, 255, 0, "deathIcon", "setSize", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // english floppy: when getting beaten up in the inn and probably more, called with 2nd parameter as object - bug #5049 + { GID_PQ2, -1, 255, 0, "DIcon", "setSize", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // when showing picture within windows, called with 2nd/3rd parameters as objects + { GID_SQ1, 1, 255, 0, "DIcon", "setSize", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // DEMO: Called with 2nd/3rd parameters as objects when clicking on the menu - bug #5012 + { GID_FANMADE, -1, 979, 0, "DIcon", "setSize", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // In The Gem Scenario and perhaps other fanmade games, this is called with 2nd/3rd parameters as objects - bug #5144 SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call,index, workaround +// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround const SciWorkaroundEntry kDeleteKey_workarounds[] = { - { GID_HOYLE4, 300, 999, 0, "handleEventList", "delete", -1, 0, { WORKAROUND_IGNORE, 0 } }, // restarting hearts, while tray is shown - bug #6604 - { GID_HOYLE4, 500, 999, 0, "handleEventList", "delete", -1, 0, { WORKAROUND_IGNORE, 0 } }, // restarting cribbage, while tray is shown - bug #6604 - { GID_HOYLE4, 975, 999, 0, "handleEventList", "delete", -1, 0, { WORKAROUND_IGNORE, 0 } }, // going back to gamelist from hearts/cribbage, while tray is shown - bug #6604 + { GID_HOYLE4, 300, 999, 0, "handleEventList", "delete", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // restarting hearts, while tray is shown - bug #6604 + { GID_HOYLE4, 500, 999, 0, "handleEventList", "delete", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // restarting cribbage, while tray is shown - bug #6604 + { GID_HOYLE4, 975, 999, 0, "handleEventList", "delete", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // going back to gamelist from hearts/cribbage, while tray is shown - bug #6604 SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call,index, workaround +// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround const SciWorkaroundEntry kDeviceInfo_workarounds[] = { - { GID_FANMADE, -1, 994, 1, "Game", "save", 0xd1c, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games, this is called with one parameter for CurDevice (Cascade Quest) - { GID_FANMADE, -1, 994, 1, "Game", "save", 0xe55, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games, this is called with one parameter for CurDevice (Demo Quest) - { GID_FANMADE, -1, 994, 1, "Game", "save", 0xe57, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games, this is called with one parameter for CurDevice (I Want My C64 Back) - { GID_FANMADE, -1, 994, 0, "Black", "save", 0xa, 0, { WORKAROUND_IGNORE, 0 } }, // In fanmade games, this is called with one parameter for CurDevice (Black Cauldron Remake) - { GID_FANMADE, -1, 994, 1, "Game", "save", 0xe5c, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games, this is called with one parameter for CurDevice (Most of them) - { GID_FANMADE, -1, 994, 1, "Game", "restore", 0xd1c, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games, this is called with one parameter for CurDevice (Cascade Quest) - { GID_FANMADE, -1, 994, 1, "Game", "restore", 0xe55, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games, this is called with one parameter for CurDevice (Demo Quest) - { GID_FANMADE, -1, 994, 1, "Game", "restore", 0xe57, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games, this is called with one parameter for CurDevice (I Want My C64 Back) - { GID_FANMADE, -1, 994, 1, "Game", "restore", 0xe5c, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games, this is called with one parameter for CurDevice (Most of them) + { GID_FANMADE, -1, 994, 1, "Game", "save", 0xd1c, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games, this is called with one parameter for CurDevice (Cascade Quest) + { GID_FANMADE, -1, 994, 1, "Game", "save", 0xe55, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games, this is called with one parameter for CurDevice (Demo Quest) + { GID_FANMADE, -1, 994, 1, "Game", "save", 0xe57, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games, this is called with one parameter for CurDevice (I Want My C64 Back) + { GID_FANMADE, -1, 994, 0, "Black", "save", 0xa, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // In fanmade games, this is called with one parameter for CurDevice (Black Cauldron Remake) + { GID_FANMADE, -1, 994, 1, "Game", "save", 0xe5c, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games, this is called with one parameter for CurDevice (Most of them) + { GID_FANMADE, -1, 994, 1, "Game", "restore", 0xd1c, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games, this is called with one parameter for CurDevice (Cascade Quest) + { GID_FANMADE, -1, 994, 1, "Game", "restore", 0xe55, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games, this is called with one parameter for CurDevice (Demo Quest) + { GID_FANMADE, -1, 994, 1, "Game", "restore", 0xe57, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games, this is called with one parameter for CurDevice (I Want My C64 Back) + { GID_FANMADE, -1, 994, 1, "Game", "restore", 0xe5c, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games, this is called with one parameter for CurDevice (Most of them) SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call,index, workaround +// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround const SciWorkaroundEntry kDisplay_workarounds[] = { - { GID_ISLANDBRAIN, 300, 300, 0, "geneDude", "show", -1, 0, { WORKAROUND_IGNORE, 0 } }, // when looking at the gene explanation chart - a parameter is an object - { GID_PQ2, 23, 23, 0, "rm23Script", "elements", 0x4ae, 0, { WORKAROUND_IGNORE, 0 } }, // when looking at the 2nd page of pate's file - 0x75 as id - { GID_PQ2, 23, 23, 0, "rm23Script", "elements", 0x4c1, 0, { WORKAROUND_IGNORE, 0 } }, // when looking at the 2nd page of pate's file - 0x75 as id (another pq2 version, bug #5223) - { GID_QFG1, 11, 11, 0, "battle", "", -1, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: When entering battle, 0x75 as id - { GID_SQ4, 397, 0, 0, "", "export 12", -1, 0, { WORKAROUND_IGNORE, 0 } }, // FLOPPY: when going into the computer store - bug #5227 - { GID_SQ4, 391, 391, 0, "doCatalog", "mode", 0x84, 0, { WORKAROUND_IGNORE, 0 } }, // CD: clicking on catalog in roboter sale - a parameter is an object - { GID_SQ4, 391, 391, 0, "choosePlug", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // CD: ordering connector in roboter sale - a parameter is an object + { GID_ISLANDBRAIN, 300, 300, 0, "geneDude", "show", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // when looking at the gene explanation chart - a parameter is an object + { GID_PQ2, 23, 23, 0, "rm23Script", "elements", 0x4ae, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // when looking at the 2nd page of pate's file - 0x75 as id + { GID_PQ2, 23, 23, 0, "rm23Script", "elements", 0x4c1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // when looking at the 2nd page of pate's file - 0x75 as id (another pq2 version, bug #5223) + { GID_QFG1, 11, 11, 0, "battle", "", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: When entering battle, 0x75 as id + { GID_SQ4, 397, 0, 0, "", "export 12", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // FLOPPY: when going into the computer store - bug #5227 + { GID_SQ4, 391, 391, 0, "doCatalog", "mode", 0x84, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // CD: clicking on catalog in roboter sale - a parameter is an object + { GID_SQ4, 391, 391, 0, "choosePlug", "changeState", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // CD: ordering connector in roboter sale - a parameter is an object SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call,index, workaround +// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround const SciWorkaroundEntry kDirLoop_workarounds[] = { - { GID_KQ4, 4, 992, 0, "Avoid", "doit", -1, 0, { WORKAROUND_IGNORE, 0 } }, // when the ogre catches you in front of his house, second parameter points to the same object as the first parameter, instead of being an integer (the angle) - bug #5217 + { GID_KQ4, 4, 992, 0, "Avoid", "doit", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // when the ogre catches you in front of his house, second parameter points to the same object as the first parameter, instead of being an integer (the angle) - bug #5217 SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call,index, workaround +// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround const SciWorkaroundEntry kDisposeScript_workarounds[] = { - { GID_LAURABOW, 777, 777, 0, "myStab", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: after the will is signed, parameter 0 is an object - bug #4967 - { GID_LSL2, -1, 54, 0, "rm54", "dispose", -1, 0, { WORKAROUND_IGNORE, 0 } }, // Amiga: room 55, script tries to kDisposeScript an object (does not happen for DOS) - bug #6818 - { GID_QFG1, -1, 64, 0, "rm64", "dispose", -1, 0, { WORKAROUND_IGNORE, 0 } }, // when leaving graveyard, parameter 0 is an object - { GID_SQ4, 150, 151, 0, "fightScript", "dispose", -1, 0, { WORKAROUND_IGNORE, 0 } }, // during fight with Vohaul, parameter 0 is an object - { GID_SQ4, 150, 152, 0, "driveCloseUp", "dispose", -1, 0, { WORKAROUND_IGNORE, 0 } }, // when choosing "beam download", parameter 0 is an object - { GID_SQ4, 150, 152, 0, "", "dispose", -1, 0, { WORKAROUND_IGNORE, 0 } }, // when choosing "beam download"... in Russian version - bug #5573 + { GID_LAURABOW, 777, 777, 0, "myStab", "changeState", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: after the will is signed, parameter 0 is an object - bug #4967 + { GID_LSL2, -1, 54, 0, "rm54", "dispose", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // Amiga: room 55, script tries to kDisposeScript an object (does not happen for DOS) - bug #6818 + { GID_QFG1, -1, 64, 0, "rm64", "dispose", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // when leaving graveyard, parameter 0 is an object + { GID_SQ4, 150, 151, 0, "fightScript", "dispose", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // during fight with Vohaul, parameter 0 is an object + { GID_SQ4, 150, 152, 0, "driveCloseUp", "dispose", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // when choosing "beam download", parameter 0 is an object + { GID_SQ4, 150, 152, 0, "", "dispose", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // when choosing "beam download"... in Russian version - bug #5573 SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call,index, workaround +// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround const SciWorkaroundEntry kDoSoundFade_workarounds[] = { - { GID_KQ5, 213, 989, 0, "globalSound3", "fade", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // english floppy: when bandits leave the secret temple, parameter 4 is an object - bug #5078 - { GID_KQ6, 105, 989, 0, "globalSound", "fade", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // floppy: during intro, parameter 4 is an object - { GID_KQ6, 460, 989, 0, "globalSound2", "fade", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // after pulling the black widow's web on the isle of wonder, parameter 4 is an object - bug #4954 - { GID_QFG4, -1, 64989, 0, "longSong", "fade", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // CD version: many places, parameter 4 is an object (longSong) - { GID_SQ5, 800, 989, 0, "sq5Music1", "fade", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // when cutting the wrong part of Goliath with the laser - bug #6341 + { GID_KQ5, 213, 989, 0, "globalSound3", "fade", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // english floppy: when bandits leave the secret temple, parameter 4 is an object - bug #5078 + { GID_KQ6, 105, 989, 0, "globalSound", "fade", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // floppy: during intro, parameter 4 is an object + { GID_KQ6, 460, 989, 0, "globalSound2", "fade", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // after pulling the black widow's web on the isle of wonder, parameter 4 is an object - bug #4954 + { GID_QFG4, -1, 64989, 0, "longSong", "fade", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // CD version: many places, parameter 4 is an object (longSong) + { GID_SQ5, 800, 989, 0, "sq5Music1", "fade", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // when cutting the wrong part of Goliath with the laser - bug #6341 SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call,index, workaround +// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround const SciWorkaroundEntry kGetAngle_workarounds[] = { - { GID_FANMADE, 516, 992, 0, "Motion", "init", -1, 0, { WORKAROUND_FAKE, 0 } }, // The Legend of the Lost Jewel Demo (fan made): called with third/fourth parameters as objects - { GID_KQ6, -1, 752, 0, "throwDazzle", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // room 740/790 after the Genie is exposed in the Palace (short and long ending), it starts shooting lightning bolts around. An extra 5th parameter is passed - bug #4959 & #5203 - { GID_SQ1, -1, 927, 0, "PAvoider", "doit", -1, 0, { WORKAROUND_FAKE, 0 } }, // all rooms in Ulence Flats after getting the Pilot Droid: called with a single parameter when the droid is in Roger's path - bug #6016 + { GID_FANMADE, 516, 992, 0, "Motion", "init", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // The Legend of the Lost Jewel Demo (fan made): called with third/fourth parameters as objects + { GID_KQ6, -1, 752, 0, "throwDazzle", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // room 740/790 after the Genie is exposed in the Palace (short and long ending), it starts shooting lightning bolts around. An extra 5th parameter is passed - bug #4959 & #5203 + { GID_SQ1, -1, 927, 0, "PAvoider", "doit", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // all rooms in Ulence Flats after getting the Pilot Droid: called with a single parameter when the droid is in Roger's path - bug #6016 SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call,index, workaround +// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround const SciWorkaroundEntry kFindKey_workarounds[] = { - { GID_ECOQUEST2, 100, 999, 0, "myList", "contains", -1, 0, { WORKAROUND_FAKE, 0 } }, // When Noah Greene gives Adam the Ecorder, and just before the game gives a demonstration, a null reference to a list is passed - bug #4987 - { GID_HOYLE4, 300, 999, 0, "Piles", "contains", -1, 0, { WORKAROUND_FAKE, 0 } }, // When passing the three cards in Hearts, a null reference to a list is passed - bug #5664 + { GID_ECOQUEST2, 100, 999, 0, "myList", "contains", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // When Noah Greene gives Adam the Ecorder, and just before the game gives a demonstration, a null reference to a list is passed - bug #4987 + { GID_HOYLE4, 300, 999, 0, "Piles", "contains", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // When passing the three cards in Hearts, a null reference to a list is passed - bug #5664 SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call,index, workaround +// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround const SciWorkaroundEntry kGraphDrawLine_workarounds[] = { - { GID_ISLANDBRAIN, 300, 300, 0, "dudeViewer", "show", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // when looking at the gene explanation chart, gets called with 1 extra parameter - { GID_SQ1, 43, 43, 0, "someoneDied", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // when ordering beer, gets called with 1 extra parameter - { GID_SQ1, 71, 71, 0, "destroyXenon", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // during the Xenon destruction cutscene (which results in death), gets called with 1 extra parameter - bug #5176 - { GID_SQ1, 53, 53, 0, "blastEgo", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // when Roger is found and zapped by the cleaning robot, gets called with 1 extra parameter - bug #5177 + { GID_ISLANDBRAIN, 300, 300, 0, "dudeViewer", "show", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // when looking at the gene explanation chart, gets called with 1 extra parameter + { GID_SQ1, 43, 43, 0, "someoneDied", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // when ordering beer, gets called with 1 extra parameter + { GID_SQ1, 71, 71, 0, "destroyXenon", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // during the Xenon destruction cutscene (which results in death), gets called with 1 extra parameter - bug #5176 + { GID_SQ1, 53, 53, 0, "blastEgo", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // when Roger is found and zapped by the cleaning robot, gets called with 1 extra parameter - bug #5177 SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call,index, workaround +// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround const SciWorkaroundEntry kGraphSaveBox_workarounds[] = { - { GID_CASTLEBRAIN, 420, 427, 0, "alienIcon", "select", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // when selecting a card during the alien card game, gets called with 1 extra parameter - { GID_ISLANDBRAIN, 290, 291, 0, "upElevator", "changeState",0x201f, 0, { WORKAROUND_STILLCALL, 0 } }, // when testing in the elevator puzzle, gets called with 1 argument less - 15 is on stack - bug #4943 - { GID_ISLANDBRAIN, 290, 291, 0, "downElevator", "changeState",0x201f, 0, { WORKAROUND_STILLCALL, 0 } }, // see above - { GID_ISLANDBRAIN, 290, 291, 0, "correctElevator", "changeState",0x201f, 0, { WORKAROUND_STILLCALL, 0 } }, // see above (when testing the correct solution) - { GID_PQ3, 202, 202, 0, "MapEdit", "movePt", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // when plotting crimes, gets called with 2 extra parameters - bug #5099 + { GID_CASTLEBRAIN, 420, 427, 0, "alienIcon", "select", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // when selecting a card during the alien card game, gets called with 1 extra parameter + { GID_ISLANDBRAIN, 290, 291, 0, "upElevator", "changeState",0x201f, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // when testing in the elevator puzzle, gets called with 1 argument less - 15 is on stack - bug #4943 + { GID_ISLANDBRAIN, 290, 291, 0, "downElevator", "changeState",0x201f, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // see above + { GID_ISLANDBRAIN, 290, 291, 0, "correctElevator", "changeState",0x201f, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // see above (when testing the correct solution) + { GID_PQ3, 202, 202, 0, "MapEdit", "movePt", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // when plotting crimes, gets called with 2 extra parameters - bug #5099 SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call,index, workaround +// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround const SciWorkaroundEntry kGraphRestoreBox_workarounds[] = { - { GID_LSL6, -1, 86, 0, "LL6Inv", "hide", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // happens during the game, gets called with 1 extra parameter + { GID_LSL6, -1, 86, 0, "LL6Inv", "hide", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // happens during the game, gets called with 1 extra parameter SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call,index, workaround +// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround const SciWorkaroundEntry kGraphFillBoxForeground_workarounds[] = { - { GID_LSL6, -1, 0, 0, "LSL6", "hideControls", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // happens when giving the bungee key to merrily (room 240) and at least in room 650 too - gets called with additional 5th parameter + { GID_LSL6, -1, 0, 0, "LSL6", "hideControls", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // happens when giving the bungee key to merrily (room 240) and at least in room 650 too - gets called with additional 5th parameter SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call,index, workaround +// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround const SciWorkaroundEntry kGraphFillBoxAny_workarounds[] = { - { GID_ECOQUEST2, 100, 333, 0, "showEcorder", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // necessary workaround for our ecorder script patch, because there isn't enough space to patch the function - { GID_SQ4, -1, 818, 0, "iconTextSwitch", "show", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // CD: game menu "text/speech" display - parameter 5 is missing, but the right color number is on the stack + { GID_ECOQUEST2, 100, 333, 0, "showEcorder", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // necessary workaround for our ecorder script patch, because there isn't enough space to patch the function + { GID_SQ4, -1, 818, 0, "iconTextSwitch", "show", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // CD: game menu "text/speech" display - parameter 5 is missing, but the right color number is on the stack SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call,index, workaround +// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround const SciWorkaroundEntry kGraphRedrawBox_workarounds[] = { - { GID_SQ4, 405, 405, 0, "swimAfterEgo", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air - accidental additional parameter specified - { GID_SQ4, 405, 405, 0, "", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air... Russian version - bug #5573 - { GID_SQ4, 406, 406, 0, "egoFollowed", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // FLOPPY: when getting shot by the police - accidental additional parameter specified - { GID_SQ4, 406, 406, 0, "swimAndShoot", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air - accidental additional parameter specified - { GID_SQ4, 406, 406, 0, "", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air... Russian version - bug #5573 (is for both egoFollowed and swimAndShoot) - { GID_SQ4, 410, 410, 0, "swimAfterEgo", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air - accidental additional parameter specified - { GID_SQ4, 410, 410, 0, "", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air... Russian version - bug #5573 - { GID_SQ4, 411, 411, 0, "swimAndShoot", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air - accidental additional parameter specified - { GID_SQ4, 411, 411, 0, "", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air... Russian version - bug #5573 - { GID_SQ4, 150, 150, 0, "laserScript", "changeState", 0xb2, 0, { WORKAROUND_STILLCALL, 0 } }, // when visiting the pedestral where Roger Jr. is trapped, before trashing the brain icon in the programming chapter, accidental additional parameter specified - bug #5479 - { GID_SQ4, 150, 150, 0, "laserScript", "changeState", 0x16, 0, { WORKAROUND_STILLCALL, 0 } }, // same as above, for the German version - bug #5527 - { GID_SQ4, 150, 150, 0, "", "changeState", 0x16, 0, { WORKAROUND_STILLCALL, 0 } }, // same as above, for the Russian version - bug #5573 - { GID_SQ4, -1, 704, 0, "shootEgo", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // When shot by Droid in Super Computer Maze (Rooms 500, 505, 510...) - accidental additional parameter specified - { GID_KQ5, -1, 981, 0, "myWindow", "dispose", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // Happens in the floppy version, when closing any dialog box, accidental additional parameter specified - bug #5031 - { GID_KQ5, -1, 995, 0, "invW", "doit", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // Happens in the floppy version, when closing the inventory window, accidental additional parameter specified - { GID_KQ5, -1, 995, 0, "", "export 0", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // Happens in the floppy version, when opening the gem pouch, accidental additional parameter specified - bug #5138 - { GID_KQ5, -1, 403, 0, "KQ5Window", "dispose", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // Happens in the FM Towns version when closing any dialog box, accidental additional parameter specified - SCI_WORKAROUNDENTRY_TERMINATOR -}; - -// gameID, room,script,lvl, object-name, method-name, call,index, workaround + { GID_SQ4, 405, 405, 0, "swimAfterEgo", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air - accidental additional parameter specified + { GID_SQ4, 405, 405, 0, "", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air... Russian version - bug #5573 + { GID_SQ4, 406, 406, 0, "egoFollowed", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // FLOPPY: when getting shot by the police - accidental additional parameter specified + { GID_SQ4, 406, 406, 0, "swimAndShoot", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air - accidental additional parameter specified + { GID_SQ4, 406, 406, 0, "", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air... Russian version - bug #5573 (is for both egoFollowed and swimAndShoot) + { GID_SQ4, 410, 410, 0, "swimAfterEgo", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air - accidental additional parameter specified + { GID_SQ4, 410, 410, 0, "", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air... Russian version - bug #5573 + { GID_SQ4, 411, 411, 0, "swimAndShoot", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air - accidental additional parameter specified + { GID_SQ4, 411, 411, 0, "", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air... Russian version - bug #5573 + { GID_SQ4, 150, 150, 0, "laserScript", "changeState", 0xb2, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // when visiting the pedestral where Roger Jr. is trapped, before trashing the brain icon in the programming chapter, accidental additional parameter specified - bug #5479 + { GID_SQ4, 150, 150, 0, "laserScript", "changeState", 0x16, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // same as above, for the German version - bug #5527 + { GID_SQ4, 150, 150, 0, "", "changeState", 0x16, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // same as above, for the Russian version - bug #5573 + { GID_SQ4, -1, 704, 0, "shootEgo", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // When shot by Droid in Super Computer Maze (Rooms 500, 505, 510...) - accidental additional parameter specified + { GID_KQ5, -1, 981, 0, "myWindow", "dispose", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // Happens in the floppy version, when closing any dialog box, accidental additional parameter specified - bug #5031 + { GID_KQ5, -1, 995, 0, "invW", "doit", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // Happens in the floppy version, when closing the inventory window, accidental additional parameter specified + { GID_KQ5, -1, 995, 0, "", "export 0", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // Happens in the floppy version, when opening the gem pouch, accidental additional parameter specified - bug #5138 + { GID_KQ5, -1, 403, 0, "KQ5Window", "dispose", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // Happens in the FM Towns version when closing any dialog box, accidental additional parameter specified + SCI_WORKAROUNDENTRY_TERMINATOR +}; + +// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround const SciWorkaroundEntry kGraphUpdateBox_workarounds[] = { - { GID_ECOQUEST2, 100, 333, 0, "showEcorder", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // necessary workaround for our ecorder script patch, because there isn't enough space to patch the function - { GID_PQ3, 202, 202, 0, "MapEdit", "addPt", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // when plotting crimes, gets called with 2 extra parameters - bug #5099 - { GID_PQ3, 202, 202, 0, "MapEdit", "movePt", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // when plotting crimes, gets called with 2 extra parameters - bug #5099 - { GID_PQ3, 202, 202, 0, "MapEdit", "dispose", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // when plotting crimes, gets called with 2 extra parameters + { GID_ECOQUEST2, 100, 333, 0, "showEcorder", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // necessary workaround for our ecorder script patch, because there isn't enough space to patch the function + { GID_PQ3, 202, 202, 0, "MapEdit", "addPt", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // when plotting crimes, gets called with 2 extra parameters - bug #5099 + { GID_PQ3, 202, 202, 0, "MapEdit", "movePt", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // when plotting crimes, gets called with 2 extra parameters - bug #5099 + { GID_PQ3, 202, 202, 0, "MapEdit", "dispose", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // when plotting crimes, gets called with 2 extra parameters SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call,index, workaround +// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround const SciWorkaroundEntry kIsObject_workarounds[] = { - { GID_GK1, 50, 999, 0, "List", "eachElementDo", -1, 0, { WORKAROUND_FAKE, 0 } }, // GK1 demo, when asking Grace for messages it gets called with an invalid parameter (type "error") - bug #4950 - { GID_ISLANDBRAIN, -1, 999, 0, "List", "eachElementDo", -1, 0, { WORKAROUND_FAKE, 0 } }, // when going to the game options, choosing "Info" and selecting anything from the list, gets called with an invalid parameter (type "error") - bug #4989 - { GID_QFG3, -1, 999, 0, "List", "eachElementDo", -1, 0, { WORKAROUND_FAKE, 0 } }, // when asking for something, gets called with type error parameter + { GID_GK1, 50, 999, 0, "List", "eachElementDo", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // GK1 demo, when asking Grace for messages it gets called with an invalid parameter (type "error") - bug #4950 + { GID_ISLANDBRAIN, -1, 999, 0, "List", "eachElementDo", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // when going to the game options, choosing "Info" and selecting anything from the list, gets called with an invalid parameter (type "error") - bug #4989 + { GID_QFG3, -1, 999, 0, "List", "eachElementDo", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // when asking for something, gets called with type error parameter SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call,index, workaround +// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround const SciWorkaroundEntry kMemory_workarounds[] = { - { GID_LAURABOW2, -1, 999, 0, "", "export 6", -1, 0, { WORKAROUND_FAKE, 0 } }, // during the intro, when exiting the train (room 160), talking to Mr. Augustini, etc. - bug #4944 - { GID_SQ1, -1, 999, 0, "", "export 6", -1, 0, { WORKAROUND_FAKE, 0 } }, // during walking Roger around Ulence Flats - bug #6017 + { GID_LAURABOW2, -1, 999, 0, "", "export 6", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // during the intro, when exiting the train (room 160), talking to Mr. Augustini, etc. - bug #4944 + { GID_SQ1, -1, 999, 0, "", "export 6", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // during walking Roger around Ulence Flats - bug #6017 SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call,index, workaround +// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround const SciWorkaroundEntry kMoveCursor_workarounds[] = { - { GID_KQ5, -1, 937, 0, "IconBar", "handleEvent", -1, 0, { WORKAROUND_IGNORE, 0 } }, // when pressing escape to open the menu, gets called with one parameter instead of 2 - bug #5575 + { GID_KQ5, -1, 937, 0, "IconBar", "handleEvent", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // when pressing escape to open the menu, gets called with one parameter instead of 2 - bug #5575 SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call,index, workaround +// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround const SciWorkaroundEntry kNewWindow_workarounds[] = { - { GID_ECOQUEST, -1, 981, 0, "SysWindow", "open", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // EcoQuest 1 demo uses an in-between interpreter from SCI1 to SCI1.1. It's SCI1.1, but uses the SCI1 semantics for this call - bug #4976 + { GID_ECOQUEST, -1, 981, 0, "SysWindow", "open", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // EcoQuest 1 demo uses an in-between interpreter from SCI1 to SCI1.1. It's SCI1.1, but uses the SCI1 semantics for this call - bug #4976 SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call,index, workaround +// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround const SciWorkaroundEntry kReadNumber_workarounds[] = { - { GID_CNICK_LAURABOW,100, 101, 0, "dominoes.opt", "doit", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // When dominoes.opt is present, the game scripts call kReadNumber with an extra integer parameter - bug #6425 - { GID_HOYLE3, 100, 101, 0, "dominoes.opt", "doit", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // When dominoes.opt is present, the game scripts call kReadNumber with an extra integer parameter - bug #6425 + { GID_CNICK_LAURABOW,100, 101, 0, "dominoes.opt", "doit", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // When dominoes.opt is present, the game scripts call kReadNumber with an extra integer parameter - bug #6425 + { GID_HOYLE3, 100, 101, 0, "dominoes.opt", "doit", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // When dominoes.opt is present, the game scripts call kReadNumber with an extra integer parameter - bug #6425 SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call,index, workaround +// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround const SciWorkaroundEntry kPaletteUnsetFlag_workarounds[] = { - { GID_QFG4, 100, 100, 0, "doMovie", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // after the Sierra logo, no flags are passed, thus the call is meaningless - bug #4947 + { GID_QFG4, 100, 100, 0, "doMovie", "changeState", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // after the Sierra logo, no flags are passed, thus the call is meaningless - bug #4947 SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call,index, workaround +// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround const SciWorkaroundEntry kSetCursor_workarounds[] = { - { GID_KQ5, -1, 768, 0, "KQCursor", "init", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // CD: gets called with 4 additional "900d" parameters + { GID_KQ5, -1, 768, 0, "KQCursor", "init", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // CD: gets called with 4 additional "900d" parameters SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call,index, workaround +// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround const SciWorkaroundEntry kSetPort_workarounds[] = { - { GID_LSL6, 740, 740, 0, "rm740", "drawPic", -1, 0, { WORKAROUND_IGNORE, 0 } }, // ending scene, is called with additional 3 (!) parameters - { GID_QFG3, 830, 830, 0, "portalOpens", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // when the portal appears during the end, gets called with 4 parameters - bug #5174 + { GID_LSL6, 740, 740, 0, "rm740", "drawPic", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // ending scene, is called with additional 3 (!) parameters + { GID_QFG3, 830, 830, 0, "portalOpens", "changeState", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // when the portal appears during the end, gets called with 4 parameters - bug #5174 SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call,index, workaround +// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround const SciWorkaroundEntry kStrAt_workarounds[] = { - { GID_CASTLEBRAIN, 220, 220, 0, "robotJokes", "animateOnce", -1, 0, { WORKAROUND_FAKE, 0 } }, // when trying to view the terminal at the end of the maze without having collected any robot jokes - bug #5127 - { GID_ISLANDBRAIN, 300, 310, 0, "childBreed", "changeState",0x1c7c, 0, { WORKAROUND_FAKE, 0 } }, // when clicking Breed to get the second-generation cyborg hybrid (Standard difficulty), the two parameters are swapped - bug #5088 + { GID_CASTLEBRAIN, 220, 220, 0, "robotJokes", "animateOnce", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // when trying to view the terminal at the end of the maze without having collected any robot jokes - bug #5127 + { GID_ISLANDBRAIN, 300, 310, 0, "childBreed", "changeState",0x1c7c, NULL, 0, { WORKAROUND_FAKE, 0 } }, // when clicking Breed to get the second-generation cyborg hybrid (Standard difficulty), the two parameters are swapped - bug #5088 SCI_WORKAROUNDENTRY_TERMINATOR }; +// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround const SciWorkaroundEntry kStrCpy_workarounds[] = { - { GID_MOTHERGOOSE, 23, 23, 0, "talkScript", "changeState", -1, 0, { WORKAROUND_FAKE, 0 } }, // when talking to the girl in scene 23, there's no destination parameter (script bug - wrong instruction order). The original source is used directly afterwards in kDisplay, to show the girl's text - bug #6485 + { GID_MOTHERGOOSE, 23, 23, 0, "talkScript", "changeState", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // when talking to the girl in scene 23, there's no destination parameter (script bug - wrong instruction order). The original source is used directly afterwards in kDisplay, to show the girl's text - bug #6485 SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call,index, workaround +// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround const SciWorkaroundEntry kStrLen_workarounds[] = { - { GID_QFG2, 210, 2, 0, "", "export 21", 0xdeb, 0, { WORKAROUND_FAKE, 0 } }, // When saying something incorrect at the WIT, an integer is passed instead of a reference - bug #5489 + { GID_QFG2, 210, 2, 0, "", "export 21", 0xdeb, NULL, 0, { WORKAROUND_FAKE, 0 } }, // When saying something incorrect at the WIT, an integer is passed instead of a reference - bug #5489 SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call,index, workaround +// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround const SciWorkaroundEntry kUnLoad_workarounds[] = { - { GID_ECOQUEST, 380, 61, 0, "gotIt", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // CD version: after talking to the dolphin the first time, a 3rd parameter is passed by accident - { GID_ECOQUEST, 380, 69, 0, "lookAtBlackBoard", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // German version, when closing the blackboard closeup in the dolphin room, a 3rd parameter is passed by accident - bug #5483 - { GID_LAURABOW2, -1, -1, 0, "sCartoon", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: during the intro, a 3rd parameter is passed by accident - bug #4966 - { GID_LSL6, 130, 130, 0, "recruitLarryScr", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // during intro, a 3rd parameter is passed by accident - { GID_LSL6, 740, 740, 0, "showCartoon", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // during ending, 4 additional parameters are passed by accident - { GID_LSL6HIRES, 130, 130, 0, "recruitLarryScr", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // during intro, a 3rd parameter is passed by accident - { GID_SQ1, 43, 303, 0, "slotGuy", "dispose", -1, 0, { WORKAROUND_IGNORE, 0 } }, // when leaving ulence flats bar, parameter 1 is not passed - script error - { GID_QFG4, -1, 110, 0, "dreamer", "dispose", -1, 0, { WORKAROUND_IGNORE, 0 } }, // during the dream sequence, a 3rd parameter is passed by accident + { GID_ECOQUEST, 380, 61, 0, "gotIt", "changeState", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // CD version: after talking to the dolphin the first time, a 3rd parameter is passed by accident + { GID_ECOQUEST, 380, 69, 0, "lookAtBlackBoard", "changeState", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // German version, when closing the blackboard closeup in the dolphin room, a 3rd parameter is passed by accident - bug #5483 + { GID_LAURABOW2, -1, -1, 0, "sCartoon", "changeState", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: during the intro, a 3rd parameter is passed by accident - bug #4966 + { GID_LSL6, 130, 130, 0, "recruitLarryScr", "changeState", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // during intro, a 3rd parameter is passed by accident + { GID_LSL6, 740, 740, 0, "showCartoon", "changeState", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // during ending, 4 additional parameters are passed by accident + { GID_LSL6HIRES, 130, 130, 0, "recruitLarryScr", "changeState", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // during intro, a 3rd parameter is passed by accident + { GID_SQ1, 43, 303, 0, "slotGuy", "dispose", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // when leaving ulence flats bar, parameter 1 is not passed - script error + { GID_QFG4, -1, 110, 0, "dreamer", "dispose", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // during the dream sequence, a 3rd parameter is passed by accident SCI_WORKAROUNDENTRY_TERMINATOR }; @@ -476,8 +490,9 @@ SciWorkaroundSolution trackOriginAndFindWorkaround(int index, const SciWorkaroun ExecStack *lastCall = state->xs; const Script *localScript = state->_segMan->getScriptIfLoaded(lastCall->local_segment); int curScriptNr = localScript->getScriptNumber(); + int curLocalCallOffset = lastCall->debugLocalCallOffset; - if (lastCall->debugLocalCallOffset != -1) { + if (curLocalCallOffset != -1) { // if lastcall was actually a local call search back for a real call Common::List::const_iterator callIterator = state->_executionStack.end(); while (callIterator != state->_executionStack.begin()) { @@ -509,13 +524,18 @@ SciWorkaroundSolution trackOriginAndFindWorkaround(int index, const SciWorkaroun // Search if there is a workaround for this one const SciWorkaroundEntry *workaround; int16 inheritanceLevel = 0; - Common::String searchObjectName = curObjectName; + Common::String searchObjectName = g_sci->getSciLanguageString(curObjectName, K_LANG_ENGLISH); reg_t searchObject = lastCall->sendp; + const byte *curScriptPtr = NULL; + uint32 curScriptSize = 0; + do { workaround = workaroundList; while (workaround->methodName) { bool objectNameMatches = (workaround->objectName == NULL) || - (workaround->objectName == g_sci->getSciLanguageString(searchObjectName, K_LANG_ENGLISH)); + (workaround->objectName == searchObjectName); + bool localCallMatches = (workaround->localCallOffset == curLocalCallOffset) || + (workaround->localCallSignature); // soon to be obsolete if (workaround->gameId == gameId && ((workaround->scriptNr == -1) || (workaround->scriptNr == curScriptNr)) @@ -523,10 +543,43 @@ SciWorkaroundSolution trackOriginAndFindWorkaround(int index, const SciWorkaroun && ((workaround->inheritanceLevel == -1) || (workaround->inheritanceLevel == inheritanceLevel)) && objectNameMatches && workaround->methodName == g_sci->getSciLanguageString(curMethodName, K_LANG_ENGLISH) - && workaround->localCallOffset == lastCall->debugLocalCallOffset + && localCallMatches // soon to be obsolete && ((workaround->index == -1) || (workaround->index == index))) { // Workaround found - return workaround->newValue; + if ((workaround->localCallSignature) || (curLocalCallOffset != -1)) { + // local call signature found and/or subcall was made + if ((workaround->localCallSignature) && (lastCall->debugLocalCallOffset)) { + // local call signature found and subcall was made -> check signature accordingly + if (!curScriptPtr) { + // get script data + int segmentId = g_sci->getEngineState()->_segMan->getScriptSegment(curScriptNr); + SegmentObj *segmentObj = NULL; + if (segmentId) { + segmentObj = g_sci->getEngineState()->_segMan->getScriptIfLoaded(segmentId); + } + if (!segmentObj) { + workaround++; + continue; + } + Script *scriptObj = (Script *)segmentObj; + curScriptPtr = scriptObj->getBuf(); + curScriptSize = scriptObj->getScriptSize(); + } + + // now actually check for signature match + if (g_sci->getScriptPatcher()->verifySignature(curLocalCallOffset, workaround->localCallSignature, "workaround signature", curScriptPtr, curScriptSize)) { + return workaround->newValue; + } + + } else { + // mismatch, so workaround doesn't match + workaround++; + continue; + } + } else { + // no localcalls involved -> workaround matches + return workaround->newValue; + } } workaround++; } diff --git a/engines/sci/engine/workarounds.h b/engines/sci/engine/workarounds.h index 9cad618481..25dd2bbc8a 100644 --- a/engines/sci/engine/workarounds.h +++ b/engines/sci/engine/workarounds.h @@ -61,6 +61,7 @@ struct SciWorkaroundEntry { const char *objectName; const char *methodName; int localCallOffset; + const uint16 *localCallSignature; int index; SciWorkaroundSolution newValue; }; -- cgit v1.2.3 From 4efaab40150386004d33d3c3c15e263027168865 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 18 Apr 2015 22:57:51 +0200 Subject: SCI: workaround sig Island Of Dr. Brain migrated --- engines/sci/engine/workarounds.cpp | 47 ++++++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 10 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index 9ae6537000..cc77fba8ec 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -59,7 +59,10 @@ const SciWorkaroundEntry arithmeticWorkarounds[] = { SCI_WORKAROUNDENTRY_TERMINATOR }; -// QfG3: rm140::init subcall +// Game: Quest for Glory 3 +// Calling method: rm140::init +// Subroutine offset: English 0x1008 (script 140) +// Applies to at least: English, French, German, Italian, Spanish PC floppy static const uint16 sig_uninitread_qfg3_1[] = { 0x3f, 0x01, // link 01 0x89, 0x7d, // lsg global[7Dh] @@ -331,13 +334,25 @@ const SciWorkaroundEntry kGraphDrawLine_workarounds[] = { SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround +// Game: Island of Dr. Brain +// Calling method: upElevator::changeState, downElevator::changeState, correctElevator::changeState +// Subroutine offset: 0x201f (script 291) +// Applies to at least: English PC floppy +static const uint16 sig_kGraphSaveBox_ibrain_1[] = { + 0x3f, 0x01, // link 01 + 0x87, 0x01, // lap param[1] + 0x30, SIG_UINT16(0x0043), // bnt [...] + 0x76, // push0 + SIG_END +}; + +// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround const SciWorkaroundEntry kGraphSaveBox_workarounds[] = { - { GID_CASTLEBRAIN, 420, 427, 0, "alienIcon", "select", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // when selecting a card during the alien card game, gets called with 1 extra parameter - { GID_ISLANDBRAIN, 290, 291, 0, "upElevator", "changeState",0x201f, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // when testing in the elevator puzzle, gets called with 1 argument less - 15 is on stack - bug #4943 - { GID_ISLANDBRAIN, 290, 291, 0, "downElevator", "changeState",0x201f, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // see above - { GID_ISLANDBRAIN, 290, 291, 0, "correctElevator", "changeState",0x201f, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // see above (when testing the correct solution) - { GID_PQ3, 202, 202, 0, "MapEdit", "movePt", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // when plotting crimes, gets called with 2 extra parameters - bug #5099 + { GID_CASTLEBRAIN, 420, 427, 0, "alienIcon", "select", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // when selecting a card during the alien card game, gets called with 1 extra parameter + { GID_ISLANDBRAIN, 290, 291, 0, "upElevator", "changeState",-1, sig_kGraphSaveBox_ibrain_1, 0, { WORKAROUND_STILLCALL, 0 } }, // when testing in the elevator puzzle, gets called with 1 argument less - 15 is on stack - bug #4943 + { GID_ISLANDBRAIN, 290, 291, 0, "downElevator", "changeState",-1, sig_kGraphSaveBox_ibrain_1, 0, { WORKAROUND_STILLCALL, 0 } }, // see above + { GID_ISLANDBRAIN, 290, 291, 0, "correctElevator", "changeState",-1, sig_kGraphSaveBox_ibrain_1, 0, { WORKAROUND_STILLCALL, 0 } }, // see above (when testing the correct solution) + { GID_PQ3, 202, 202, 0, "MapEdit", "movePt", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // when plotting crimes, gets called with 2 extra parameters - bug #5099 SCI_WORKAROUNDENTRY_TERMINATOR }; @@ -444,10 +459,22 @@ const SciWorkaroundEntry kSetPort_workarounds[] = { SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround +// Game: Island of Dr. Brain +// Calling method: childBreed::changeState +// Subroutine offset: 0x1c7c (script 310) +// Applies to at least: English PC floppy +static const uint16 sig_kStrAt_ibrain_1[] = { + 0x3f, 0x16, // link 16 + 0x78, // push1 + 0x8f, 0x01, // lsp param[1] + 0x43, // callk StrLen + SIG_END +}; + +// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround const SciWorkaroundEntry kStrAt_workarounds[] = { - { GID_CASTLEBRAIN, 220, 220, 0, "robotJokes", "animateOnce", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // when trying to view the terminal at the end of the maze without having collected any robot jokes - bug #5127 - { GID_ISLANDBRAIN, 300, 310, 0, "childBreed", "changeState",0x1c7c, NULL, 0, { WORKAROUND_FAKE, 0 } }, // when clicking Breed to get the second-generation cyborg hybrid (Standard difficulty), the two parameters are swapped - bug #5088 + { GID_CASTLEBRAIN, 220, 220, 0, "robotJokes", "animateOnce", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // when trying to view the terminal at the end of the maze without having collected any robot jokes - bug #5127 + { GID_ISLANDBRAIN, 300, 310, 0, "childBreed", "changeState",-1, sig_kStrAt_ibrain_1, 0, { WORKAROUND_FAKE, 0 } }, // when clicking Breed to get the second-generation cyborg hybrid (Standard difficulty), the two parameters are swapped - bug #5088 SCI_WORKAROUNDENTRY_TERMINATOR }; -- cgit v1.2.3 From 83c6e1543e556ac6f5f91a38508575747b70fcad Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 18 Apr 2015 23:13:11 +0200 Subject: SCI: add debug level for workarounds It's called "Workarounds" --- engines/sci/engine/workarounds.cpp | 7 ++++++- engines/sci/sci.cpp | 1 + engines/sci/sci.h | 3 ++- 3 files changed, 9 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index cc77fba8ec..4999664d7a 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -555,6 +555,7 @@ SciWorkaroundSolution trackOriginAndFindWorkaround(int index, const SciWorkaroun reg_t searchObject = lastCall->sendp; const byte *curScriptPtr = NULL; uint32 curScriptSize = 0; + bool matched = false; do { workaround = workaroundList; @@ -595,7 +596,7 @@ SciWorkaroundSolution trackOriginAndFindWorkaround(int index, const SciWorkaroun // now actually check for signature match if (g_sci->getScriptPatcher()->verifySignature(curLocalCallOffset, workaround->localCallSignature, "workaround signature", curScriptPtr, curScriptSize)) { - return workaround->newValue; + matched = true; } } else { @@ -605,6 +606,10 @@ SciWorkaroundSolution trackOriginAndFindWorkaround(int index, const SciWorkaroun } } else { // no localcalls involved -> workaround matches + matched = true; + } + if (matched) { + debugC(kDebugLevelWorkarounds, "Workaround: '%s:%s' in script %d", workaround->objectName, workaround->methodName, curScriptNr); return workaround->newValue; } } diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 60a1271b89..d07ab435ff 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -114,6 +114,7 @@ SciEngine::SciEngine(OSystem *syst, const ADGameDescription *desc, SciGameId gam DebugMan.addDebugChannel(kDebugLevelVM, "VM", "VM debugging"); DebugMan.addDebugChannel(kDebugLevelScripts, "Scripts", "Notifies when scripts are unloaded"); DebugMan.addDebugChannel(kDebugLevelScriptPatcher, "ScriptPatcher", "Notifies when scripts are patched"); + DebugMan.addDebugChannel(kDebugLevelWorkarounds, "Workarounds", "Notifies when workarounds are triggered"); DebugMan.addDebugChannel(kDebugLevelGC, "GC", "Garbage Collector debugging"); DebugMan.addDebugChannel(kDebugLevelResMan, "ResMan", "Resource manager debugging"); DebugMan.addDebugChannel(kDebugLevelOnStartup, "OnStartup", "Enter debugger at start of game"); diff --git a/engines/sci/sci.h b/engines/sci/sci.h index 4928fd1b4e..c6813aa07c 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -105,7 +105,8 @@ enum kDebugLevels { kDebugLevelResMan = 1 << 19, kDebugLevelOnStartup = 1 << 20, kDebugLevelDebugMode = 1 << 21, - kDebugLevelScriptPatcher = 1 << 22 + kDebugLevelScriptPatcher = 1 << 22, + kDebugLevelWorkarounds = 1 << 23 }; enum SciGameId { -- cgit v1.2.3 From d6000c927b7a0d29a1eaca70df81e1ae7b07e99f Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 18 Apr 2015 23:40:00 +0200 Subject: SCI: workaround sig Quest for Glory 2 migrated --- engines/sci/engine/workarounds.cpp | 39 +++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index 4999664d7a..27b9697230 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -59,6 +59,19 @@ const SciWorkaroundEntry arithmeticWorkarounds[] = { SCI_WORKAROUNDENTRY_TERMINATOR }; +// Game: Quest for Glory 2 +// Calling method: abdulS::changeState, jabbarS::changeState +// Subroutine offset: English 0x2d22 (script 260) +// Applies to at least: English PC floppy +static const uint16 sig_uninitread_qfg2_1[] = { + 0x3f, 0x03, // link 03 + 0x39, 0x3b, // pushi 3Bh + 0x76, // push0 + 0x81, 0x00, // lag global[0] + 0x4a, 0x04, // send 04 + SIG_END +}; + // Game: Quest for Glory 3 // Calling method: rm140::init // Subroutine offset: English 0x1008 (script 140) @@ -176,8 +189,8 @@ const SciWorkaroundEntry uninitializedReadWorkarounds[] = { { GID_QFG2, -1, 71, 0, "theInvSheet", "doit", -1, NULL, 1, { WORKAROUND_FAKE, 0 } }, // accessing the inventory { GID_QFG2, -1, 701, -1, "Alley", "at", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // when walking inside the alleys in the town - bug #5019 & #5106 { GID_QFG2, -1, 990, 0, "Restore", "doit", -1, NULL, 364, { WORKAROUND_FAKE, 0 } }, // when pressing enter in restore dialog w/o any saved games present - { GID_QFG2, 260, 260, 0, "abdulS", "changeState",0x2d22, NULL, -1, { WORKAROUND_FAKE, 0 } }, // During the thief's first mission (in the house), just before Abdul is about to enter the house (where you have to hide in the wardrobe), bug #5153, temps 1 and 2 - { GID_QFG2, 260, 260, 0, "jabbarS", "changeState",0x2d22, NULL, -1, { WORKAROUND_FAKE, 0 } }, // During the thief's first mission (in the house), just before Jabbar is about to enter the house (where you have to hide in the wardrobe), bug #5164, temps 1 and 2 + { GID_QFG2, 260, 260, 0, "abdulS", "changeState",-1, sig_uninitread_qfg2_1, -1, { WORKAROUND_FAKE, 0 } }, // During the thief's first mission (in the house), just before Abdul is about to enter the house (where you have to hide in the wardrobe), bug #5153, temps 1 and 2 + { GID_QFG2, 260, 260, 0, "jabbarS", "changeState",-1, sig_uninitread_qfg2_1, -1, { WORKAROUND_FAKE, 0 } }, // During the thief's first mission (in the house), just before Jabbar is about to enter the house (where you have to hide in the wardrobe), bug #5164, temps 1 and 2 { GID_QFG2, 500, 500, 0, "lightNextCandleS", "changeState", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // Inside the last room, while Ad Avis performs the ritual to summon the genie - bug #5566 { GID_QFG2, -1, 700, 0, NULL, "showSign", -1, NULL, 10, { WORKAROUND_FAKE, 0 } }, // Occurs sometimes when reading a sign in Raseir, Shapeir et al - bugs #5627, #5635 { GID_QFG3, 510, 510, 0, "awardPrize", "changeState", -1, NULL, 0, { WORKAROUND_FAKE, 1 } }, // Simbani warrior challenge, after throwing the spears and retrieving the ring - bug #5277. Must be non-zero, otherwise the prize is awarded twice - bug #6160 @@ -251,9 +264,9 @@ const SciWorkaroundEntry kCelWide_workarounds[] = { // gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround const SciWorkaroundEntry kDeleteKey_workarounds[] = { - { GID_HOYLE4, 300, 999, 0, "handleEventList", "delete", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // restarting hearts, while tray is shown - bug #6604 - { GID_HOYLE4, 500, 999, 0, "handleEventList", "delete", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // restarting cribbage, while tray is shown - bug #6604 - { GID_HOYLE4, 975, 999, 0, "handleEventList", "delete", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // going back to gamelist from hearts/cribbage, while tray is shown - bug #6604 + { GID_HOYLE4, 300, 999, 0, "handleEventList", "delete", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // restarting hearts, while tray is shown - bug #6604 + { GID_HOYLE4, 500, 999, 0, "handleEventList", "delete", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // restarting cribbage, while tray is shown - bug #6604 + { GID_HOYLE4, 975, 999, 0, "handleEventList", "delete", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // going back to gamelist from hearts/cribbage, while tray is shown - bug #6604 SCI_WORKAROUNDENTRY_TERMINATOR }; @@ -484,9 +497,21 @@ const SciWorkaroundEntry kStrCpy_workarounds[] = { SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround +// Game: Quest for Glory 2 +// Calling method: export 21 of script 2 +// Subroutine offset: English 0x0deb (script 2) +// Applies to at least: English PC floppy +static const uint16 sig_kStrLen_qfg2_1[] = { + 0x3f, 0x04, // link 04 + 0x78, // push1 + 0x8f, 0x02, // lsp param[2] + 0x43, // callk StrLen + SIG_END +}; + +// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround const SciWorkaroundEntry kStrLen_workarounds[] = { - { GID_QFG2, 210, 2, 0, "", "export 21", 0xdeb, NULL, 0, { WORKAROUND_FAKE, 0 } }, // When saying something incorrect at the WIT, an integer is passed instead of a reference - bug #5489 + { GID_QFG2, 210, 2, 0, "", "export 21", -1, sig_kStrLen_qfg2_1, 0, { WORKAROUND_FAKE, 0 } }, // When saying something incorrect at the WIT, an integer is passed instead of a reference - bug #5489 SCI_WORKAROUNDENTRY_TERMINATOR }; -- cgit v1.2.3 From cf9fa4bd4012208208addb7b9705d41acbc93382 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 18 Apr 2015 23:57:48 +0200 Subject: SCI: workaround sig Quest for Glory 1 EGA migrated --- engines/sci/engine/workarounds.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index 27b9697230..e368d124ed 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -59,6 +59,21 @@ const SciWorkaroundEntry arithmeticWorkarounds[] = { SCI_WORKAROUNDENTRY_TERMINATOR }; +// Game: Quest for Glory 1 / Hero's Quest 1 +// Calling method: Encounter::init +// Subroutine offset: English Hero's Quest 0x0bd0, English Quest for Glory 1 0x0be4 (script 210) +// Applies to at least: English PC floppy (Hero's Quest, Quest For Glory 1), Japanese PC-9801 floppy +static const uint16 sig_uninitread_qfg1_1[] = { + 0x3f, 0x02, // link 02 + 0x87, 0x00, // lap param[0] + 0x30, SIG_UINT16(0x000c), // bnt [...] + 0x87, 0x01, // lap param[1] + 0x30, SIG_UINT16(0x0007), // bnt [...] + 0x87, 0x01, // lap param[1] + 0xa5, 0x01, // sat temp[1] + SIG_END +}; + // Game: Quest for Glory 2 // Calling method: abdulS::changeState, jabbarS::changeState // Subroutine offset: English 0x2d22 (script 260) @@ -181,8 +196,7 @@ const SciWorkaroundEntry uninitializedReadWorkarounds[] = { { GID_PEPPER, 150, 928, 0, "Narrator", "startText", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // happens during the non-interactive demo of Pepper { GID_PQ4, -1, 25, 0, "iconToggle", "select", -1, NULL, 1, { WORKAROUND_FAKE, 0 } }, // when toggling the icon bar to auto-hide or not { GID_PQSWAT, -1, 64950, 0, "View", "handleEvent", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // Using the menu in the beginning - { GID_QFG1, -1, 210, 0, "Encounter", "init", 0xbd0, NULL, 0, { WORKAROUND_FAKE, 0 } }, // hq1: going to the brigands hideout - { GID_QFG1, -1, 210, 0, "Encounter", "init", 0xbe4, NULL, 0, { WORKAROUND_FAKE, 0 } }, // qfg1: going to the brigands hideout + { GID_QFG1, -1, 210, 0, "Encounter", "init", -1, sig_uninitread_qfg1_1, 0, { WORKAROUND_FAKE, 0 } }, // qfg1/hq1: going to the brigands hideout { GID_QFG1VGA, 16, 16, 0, "lassoFailed", "changeState", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // qfg1vga: casting the "fetch" spell in the screen with the flowers, temps 0 and 1 - bug #5309 { GID_QFG1VGA, -1, 210, 0, "Encounter", "init", 0xcee, NULL, 0, { WORKAROUND_FAKE, 0 } }, // qfg1vga: going to the brigands hideout - bug #5515 { GID_QFG1VGA, -1, 210, 0, "Encounter", "init", 0xce7, NULL, 0, { WORKAROUND_FAKE, 0 } }, // qfg1vga: going to room 92 -- cgit v1.2.3 From 4122cdc1305d293a700714ea13fce0eda6f6c5ee Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 19 Apr 2015 11:32:52 +0200 Subject: SCI: workaround sig Eco Quest 2 migrated --- engines/sci/engine/workarounds.cpp | 47 ++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 17 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index e368d124ed..2fc05ab76b 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -39,23 +39,36 @@ namespace Sci { // Those signatures are just like the script patcher signatures (for further study: engine\script_patches.cpp) // However you may NOT use command SIG_SELECTOR8 nor SIG_SELECTOR16 atm. Proper support for those may be added later. -// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround +// Game: Eco Quest 2 +// Calling method: Rain::points +// Subroutine offset: English 0x0cc6, Spanish 0x0ce0 (script 0) +// Applies to at least: English PC floppy, Spanish PC floppy +static const uint16 sig_arithmetic_ecoq2_1[] = { + 0x8f, 0x01, // lsp param[1] + 0x35, 0x10, // ldi 10h + 0x08, // div + 0x99, 0x6e, // lsgi global[6Eh] + 0x38, SIG_UINT16(0x8000), // pushi 8000h + 0x8f, 0x01, // lsp param[1] + SIG_END +}; + +// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround const SciWorkaroundEntry arithmeticWorkarounds[] = { - { GID_CAMELOT, 92, 92, 0, "endingCartoon2", "changeState", 0x20d, NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_lai: during the ending, sub gets called with no parameters, uses parameter 1 which is theGrail in this case - bug #5237 - { GID_ECOQUEST2, 100, 0, 0, "Rain", "points", 0xcc6, NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_or: when giving the papers to the customs officer, gets called against a pointer instead of a number - bug #4939 - { GID_ECOQUEST2, 100, 0, 0, "Rain", "points", 0xce0, NULL, 0, { WORKAROUND_FAKE, 0 } }, // Same as above, for the Spanish version - bug #5750 - { GID_FANMADE, 516, 983, 0, "Wander", "setTarget", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_mul: The Legend of the Lost Jewel Demo (fan made): called with object as second parameter when attacked by insects - bug #5124 - { GID_GK1, 800,64992, 0, "Fwd", "doit", -1, NULL, 0, { WORKAROUND_FAKE, 1 } }, // op_gt: when Mosely finds Gabriel and Grace near the end of the game, compares the Grooper object with 7 - { GID_HOYLE4, 700, -1, 1, "Code", "doit", -1, NULL, 0, { WORKAROUND_FAKE, 1 } }, // op_add: while bidding in Bridge, an object ("Bid") is added to an object in another segment ("hand3") - { GID_ICEMAN, 199, 977, 0, "Grooper", "doit", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_add: While dancing with the girl - { GID_MOTHERGOOSE256, -1, 999, 0, "Event", "new", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_and: constantly during the game (SCI1 version) - { GID_MOTHERGOOSE256, -1, 4, 0, "rm004", "doit", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_or: when going north and reaching the castle (rooms 4 and 37) - bug #5101 - { GID_MOTHERGOOSEHIRES,90, 90, 0, "newGameButton", "select", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_ge: MUMG Deluxe, when selecting "New Game" in the main menu. It tries to compare an integer with a list. Needs to return false for the game to continue. - { GID_PHANTASMAGORIA, 902, 0, 0, "", "export 7", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_shr: when starting a chapter in Phantasmagoria - { GID_QFG1VGA, 301, 928, 0, "Blink", "init", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_div: when entering the inn, gets called with 1 parameter, but 2nd parameter is used for div which happens to be an object - { GID_QFG2, 200, 200, 0, "astro", "messages", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_lsi: when getting asked for your name by the astrologer - bug #5152 - { GID_QFG3, 780, 999, 0, "", "export 6", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_add: trying to talk to yourself at the top of the giant tree - bug #6692 - { GID_QFG4, 710,64941, 0, "RandCycle", "doit", -1, NULL, 0, { WORKAROUND_FAKE, 1 } }, // op_gt: when the tentacle appears in the third room of the caves + { GID_CAMELOT, 92, 92, 0, "endingCartoon2", "changeState", 0x20d, NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_lai: during the ending, sub gets called with no parameters, uses parameter 1 which is theGrail in this case - bug #5237 + { GID_ECOQUEST2, 100, 0, 0, "Rain", "points", -1, sig_arithmetic_ecoq2_1, 0, { WORKAROUND_FAKE, 0 } }, // op_or: when giving the papers to the customs officer, gets called against a pointer instead of a number - bug #4939, Spanish version - bug #5750 + { GID_FANMADE, 516, 983, 0, "Wander", "setTarget", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_mul: The Legend of the Lost Jewel Demo (fan made): called with object as second parameter when attacked by insects - bug #5124 + { GID_GK1, 800,64992, 0, "Fwd", "doit", -1, NULL, 0, { WORKAROUND_FAKE, 1 } }, // op_gt: when Mosely finds Gabriel and Grace near the end of the game, compares the Grooper object with 7 + { GID_HOYLE4, 700, -1, 1, "Code", "doit", -1, NULL, 0, { WORKAROUND_FAKE, 1 } }, // op_add: while bidding in Bridge, an object ("Bid") is added to an object in another segment ("hand3") + { GID_ICEMAN, 199, 977, 0, "Grooper", "doit", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_add: While dancing with the girl + { GID_MOTHERGOOSE256, -1, 999, 0, "Event", "new", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_and: constantly during the game (SCI1 version) + { GID_MOTHERGOOSE256, -1, 4, 0, "rm004", "doit", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_or: when going north and reaching the castle (rooms 4 and 37) - bug #5101 + { GID_MOTHERGOOSEHIRES,90, 90, 0, "newGameButton", "select", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_ge: MUMG Deluxe, when selecting "New Game" in the main menu. It tries to compare an integer with a list. Needs to return false for the game to continue. + { GID_PHANTASMAGORIA, 902, 0, 0, "", "export 7", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_shr: when starting a chapter in Phantasmagoria + { GID_QFG1VGA, 301, 928, 0, "Blink", "init", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_div: when entering the inn, gets called with 1 parameter, but 2nd parameter is used for div which happens to be an object + { GID_QFG2, 200, 200, 0, "astro", "messages", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_lsi: when getting asked for your name by the astrologer - bug #5152 + { GID_QFG3, 780, 999, 0, "", "export 6", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_add: trying to talk to yourself at the top of the giant tree - bug #6692 + { GID_QFG4, 710,64941, 0, "RandCycle", "doit", -1, NULL, 0, { WORKAROUND_FAKE, 1 } }, // op_gt: when the tentacle appears in the third room of the caves SCI_WORKAROUNDENTRY_TERMINATOR }; @@ -648,7 +661,7 @@ SciWorkaroundSolution trackOriginAndFindWorkaround(int index, const SciWorkaroun matched = true; } if (matched) { - debugC(kDebugLevelWorkarounds, "Workaround: '%s:%s' in script %d", workaround->objectName, workaround->methodName, curScriptNr); + debugC(kDebugLevelWorkarounds, "Workaround: '%s:%s' in script %d, localcall %x", workaround->objectName, workaround->methodName, curScriptNr, curLocalCallOffset); return workaround->newValue; } } -- cgit v1.2.3 From bbf9c83ebf8ab6f27519a0d1cb4d4c747a16e985 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 19 Apr 2015 11:50:01 +0200 Subject: SCI: workaround sig eco quest 2 update sig also works on french version + sig extended --- engines/sci/engine/workarounds.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index 2fc05ab76b..cafca0a2db 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -41,8 +41,8 @@ namespace Sci { // Game: Eco Quest 2 // Calling method: Rain::points -// Subroutine offset: English 0x0cc6, Spanish 0x0ce0 (script 0) -// Applies to at least: English PC floppy, Spanish PC floppy +// Subroutine offset: English 0x0cc6, French/Spanish 0x0ce0 (script 0) +// Applies to at least: English/French/Spanish PC floppy static const uint16 sig_arithmetic_ecoq2_1[] = { 0x8f, 0x01, // lsp param[1] 0x35, 0x10, // ldi 10h @@ -50,6 +50,11 @@ static const uint16 sig_arithmetic_ecoq2_1[] = { 0x99, 0x6e, // lsgi global[6Eh] 0x38, SIG_UINT16(0x8000), // pushi 8000h 0x8f, 0x01, // lsp param[1] + 0x35, 0x10, // ldi 10h + 0x0a, // mod + 0x0c, // shr + 0x14, // or + 0x36, // push SIG_END }; -- cgit v1.2.3 From 629f6a4208828e27e808155af24037b720e268b3 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 19 Apr 2015 13:09:10 +0200 Subject: SCI: workaround sig Quest for Glory 1 VGA migrated --- engines/sci/engine/workarounds.cpp | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index cafca0a2db..52ddb2912a 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -92,6 +92,22 @@ static const uint16 sig_uninitread_qfg1_1[] = { SIG_END }; +// Game: Quest for Glory 1 VGA +// Calling method: Encounter::init +// Subroutine offset: English w/o patch 0x0cee, w/ patch 0x0ce7 (script 210) +// Applies to at least: English PC floppy +static const uint16 sig_uninitread_qfg1vga_1[] = { + 0x3f, 0x02, // link 02 + 0x87, 0x00, // lap param[0] + 0x31, 0x0b, // bnt [...] + 0x87, 0x01, // lap param[1] + 0x31, 0x07, // bnt [...] + 0x87, 0x01, // lap param[1] + 0xa5, 0x01, // sat temp[1] + // following jump is different for patched and unpatched game + SIG_END +}; + // Game: Quest for Glory 2 // Calling method: abdulS::changeState, jabbarS::changeState // Subroutine offset: English 0x2d22 (script 260) @@ -216,8 +232,7 @@ const SciWorkaroundEntry uninitializedReadWorkarounds[] = { { GID_PQSWAT, -1, 64950, 0, "View", "handleEvent", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // Using the menu in the beginning { GID_QFG1, -1, 210, 0, "Encounter", "init", -1, sig_uninitread_qfg1_1, 0, { WORKAROUND_FAKE, 0 } }, // qfg1/hq1: going to the brigands hideout { GID_QFG1VGA, 16, 16, 0, "lassoFailed", "changeState", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // qfg1vga: casting the "fetch" spell in the screen with the flowers, temps 0 and 1 - bug #5309 - { GID_QFG1VGA, -1, 210, 0, "Encounter", "init", 0xcee, NULL, 0, { WORKAROUND_FAKE, 0 } }, // qfg1vga: going to the brigands hideout - bug #5515 - { GID_QFG1VGA, -1, 210, 0, "Encounter", "init", 0xce7, NULL, 0, { WORKAROUND_FAKE, 0 } }, // qfg1vga: going to room 92 + { GID_QFG1VGA, -1, 210, 0, "Encounter", "init", -1, sig_uninitread_qfg1vga_1, 0, { WORKAROUND_FAKE, 0 } }, // qfg1vga: going to the brigands hideout - bug #5515 { GID_QFG2, -1, 71, 0, "theInvSheet", "doit", -1, NULL, 1, { WORKAROUND_FAKE, 0 } }, // accessing the inventory { GID_QFG2, -1, 701, -1, "Alley", "at", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // when walking inside the alleys in the town - bug #5019 & #5106 { GID_QFG2, -1, 990, 0, "Restore", "doit", -1, NULL, 364, { WORKAROUND_FAKE, 0 } }, // when pressing enter in restore dialog w/o any saved games present -- cgit v1.2.3 From 270fbf2d6a706f526d765890f48d42db98e43969 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 19 Apr 2015 13:40:01 +0200 Subject: SCI: workaround sig Quest for Glory 3 migrated --- engines/sci/engine/workarounds.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index 52ddb2912a..5a03b35171 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -132,6 +132,21 @@ static const uint16 sig_uninitread_qfg3_1[] = { SIG_END }; +// Game: Quest for Glory 3 +// Calling method: computersMove::changeState +// Subroutine offset: English/etc. 0x0f53 (script 490) +// Applies to at least: English, French, German, Italian, Spanish PC floppy +static const uint16 sig_uninitread_qfg3_2[] = { + 0x3f, 0x1d, // link 1Dh + 0x35, 0x01, // ldi 01 + 0xa5, 0x18, // sat temp[18h] + 0x35, 0xce, // ldi CEh + 0xa5, 0x19, // sat temp[19h] + 0x35, 0x00, // ldi 00 + 0xa5, 0x00, // sat temp[0] + SIG_END +}; + // gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround const SciWorkaroundEntry uninitializedReadWorkarounds[] = { { GID_CAMELOT, 40, 40, 0, "Rm40", "handleEvent", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // when looking at the ground at the pool of Siloam - bug #6401 @@ -246,7 +261,7 @@ const SciWorkaroundEntry uninitializedReadWorkarounds[] = { { GID_QFG3, 700, 700, -1, "monsterIsDead", "changeState", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // in the jungle, after winning any fight, bug #5169 { GID_QFG3, 470, 470, -1, "rm470", "notify", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // closing the character screen in the Simbani village in the room with the bridge, bug #5165 { GID_QFG3, 490, 490, -1, "computersMove", "changeState", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // when finishing awari game, bug #5167 - { GID_QFG3, 490, 490, -1, "computersMove", "changeState", 0xf53, NULL, 4, { WORKAROUND_FAKE, 0 } }, // also when finishing awari game + { GID_QFG3, 490, 490, -1, "computersMove", "changeState",-1, sig_uninitread_qfg3_2, 4, { WORKAROUND_FAKE, 0 } }, // also when finishing awari game { GID_QFG3, 851, 32, -1, "ProjObj", "doit", -1, NULL, 1, { WORKAROUND_FAKE, 0 } }, // near the end, when throwing the spear of death, bug #5282 { GID_QFG4, -1, 15, -1, "charInitScreen", "dispatchEvent", -1, NULL, 5, { WORKAROUND_FAKE, 0 } }, // floppy version, when viewing the character screen { GID_QFG4, -1, 64917, -1, "controlPlane", "setBitmap", -1, NULL, 3, { WORKAROUND_FAKE, 0 } }, // floppy version, when entering the game menu -- cgit v1.2.3 From 062c535d1b0afbad79b6191468d7d70f68fe9443 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 19 Apr 2015 15:49:43 +0200 Subject: SCI: workaround sig pq2/demo:lb+hq1 migrated - also kDisplay cleanup, removed dummy opcodes - workarounds should be used instead - fixed hq1 workaround entry, it seems we are able to read vocabulary now --- engines/sci/engine/workarounds.cpp | 35 ++++++++++++++++++++++++++++------- engines/sci/graphics/paint16.cpp | 19 ------------------- 2 files changed, 28 insertions(+), 26 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index 5a03b35171..ebf587183c 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -346,15 +346,36 @@ const SciWorkaroundEntry kDeviceInfo_workarounds[] = { SCI_WORKAROUNDENTRY_TERMINATOR }; +// Game: Police Quest 2 +// Calling method: rm23Script::elements +// Subroutine offset: English 1.001.000: 0x04ae, English 1.002.011: 0x04ca, Japanese: 0x04eb (script 23) +// Applies to at least: English PC floppy, Japanese PC-9801 +static const uint16 sig_kDisplay_pq2_1[] = { + 0x35, 0x00, // ldi 00 + 0xa3, 0x09, // sal local[9] + 0x35, 0x01, // ldi 01 + 0xa3, 0x0a, // sal local[0Ah] + 0x38, SIG_ADDTOOFFSET(+2), // pushi selector[drawPic] TODO: implement selectors + 0x7a, // push2 + 0x39, 0x5a, // pushi 5Ah + 0x7a, // push2 + 0x81, 0x02, // lag global[2] + 0x4a, 0x08, // send 08 + SIG_END +}; + // gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround const SciWorkaroundEntry kDisplay_workarounds[] = { - { GID_ISLANDBRAIN, 300, 300, 0, "geneDude", "show", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // when looking at the gene explanation chart - a parameter is an object - { GID_PQ2, 23, 23, 0, "rm23Script", "elements", 0x4ae, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // when looking at the 2nd page of pate's file - 0x75 as id - { GID_PQ2, 23, 23, 0, "rm23Script", "elements", 0x4c1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // when looking at the 2nd page of pate's file - 0x75 as id (another pq2 version, bug #5223) - { GID_QFG1, 11, 11, 0, "battle", "", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: When entering battle, 0x75 as id - { GID_SQ4, 397, 0, 0, "", "export 12", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // FLOPPY: when going into the computer store - bug #5227 - { GID_SQ4, 391, 391, 0, "doCatalog", "mode", 0x84, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // CD: clicking on catalog in roboter sale - a parameter is an object - { GID_SQ4, 391, 391, 0, "choosePlug", "changeState", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // CD: ordering connector in roboter sale - a parameter is an object + { GID_ISLANDBRAIN, 300, 300, 0, "geneDude", "show", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // when looking at the gene explanation chart - a parameter is an object + { GID_LONGBOW, 95, 95, 0, "countDown", "changeState", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: during title screen "Robin Hood! Your bow is needed" + { GID_LONGBOW, 220, 220, 0, "moveOn", "changeState", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: during second room "Outwit and outfight..." + { GID_LONGBOW, 210, 210, 0, "mama", "changeState", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: during third room "Fall under the spell..." + { GID_LONGBOW, 320, 320, 0, "flyin", "changeState", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: during fourth room "Conspiracies, love..." + { GID_PQ2, 23, 23, 0, "rm23Script", "elements", -1, sig_kDisplay_pq2_1, 0, { WORKAROUND_IGNORE, 0 } }, // when looking at the 2nd page of pate's file - 0x75 as id - bug #5223 + { GID_QFG1, 11, 11, 0, "battle", "init", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: When entering battle, 0x75 as id + { GID_SQ4, 397, 0, 0, "", "export 12", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // FLOPPY: when going into the computer store - bug #5227 + { GID_SQ4, 391, 391, 0, "doCatalog", "mode", 0x84, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // CD: clicking on catalog in roboter sale - a parameter is an object + { GID_SQ4, 391, 391, 0, "choosePlug", "changeState", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // CD: ordering connector in roboter sale - a parameter is an object SCI_WORKAROUNDENTRY_TERMINATOR }; diff --git a/engines/sci/graphics/paint16.cpp b/engines/sci/graphics/paint16.cpp index f80703e14d..6004e9ce7a 100644 --- a/engines/sci/graphics/paint16.cpp +++ b/engines/sci/graphics/paint16.cpp @@ -471,9 +471,6 @@ void GfxPaint16::kernelGraphRedrawBox(Common::Rect rect) { #define SCI_DISPLAY_WIDTH 106 #define SCI_DISPLAY_SAVEUNDER 107 #define SCI_DISPLAY_RESTOREUNDER 108 -#define SCI_DISPLAY_DUMMY1 114 -#define SCI_DISPLAY_DUMMY2 115 -#define SCI_DISPLAY_DUMMY3 117 #define SCI_DISPLAY_DONTSHOWBITS 121 reg_t GfxPaint16::kernelDisplay(const char *text, uint16 languageSplitter, int argc, reg_t *argv) { @@ -543,22 +540,6 @@ reg_t GfxPaint16::kernelDisplay(const char *text, uint16 languageSplitter, int a bRedraw = 0; break; - // The following three dummy calls are not supported by the Sierra SCI - // interpreter, but are erroneously called in some game scripts. - case SCI_DISPLAY_DUMMY1: // Longbow demo (all rooms) and QFG1 EGA demo (room 11) - case SCI_DISPLAY_DUMMY2: // Longbow demo (all rooms) - case SCI_DISPLAY_DUMMY3: // QFG1 EGA demo (room 11) and PQ2 (room 23) - if (!(g_sci->getGameId() == GID_LONGBOW && g_sci->isDemo()) && - !(g_sci->getGameId() == GID_QFG1 && g_sci->isDemo()) && - !(g_sci->getGameId() == GID_PQ2)) - error("Unknown kDisplay argument %d", displayArg.getOffset()); - - if (displayArg.getOffset() == SCI_DISPLAY_DUMMY2) { - if (!argc) - error("No parameter left for kDisplay(115)"); - argc--; argv++; - } - break; default: SciTrackOriginReply originReply; SciWorkaroundSolution solution = trackOriginAndFindWorkaround(0, kDisplay_workarounds, &originReply); -- cgit v1.2.3 From 76fa1a0c6fa38339e28450581bf8562bb4840d40 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 19 Apr 2015 16:18:44 +0200 Subject: SCI: workaround sig Conquests of Longbow migrated --- engines/sci/engine/workarounds.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index ebf587183c..b591ea2b79 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -77,6 +77,18 @@ const SciWorkaroundEntry arithmeticWorkarounds[] = { SCI_WORKAROUNDENTRY_TERMINATOR }; +// Game: Conquests of the Longbow +// Calling method: letter::handleEvent +// Subroutine offset: English 0x00a8 (script 213) +// Applies to at least: English PC floppy, English Amiga floppy +static const uint16 sig_uninitread_longbow_1[] = { + 0x3f, 0x02, // link 02 + 0x35, 0x00, // ldi 00 + 0xa5, 0x00, // sat temp[0] + 0x8d, 0x00, // lst temp[0] + SIG_END +}; + // Game: Quest for Glory 1 / Hero's Quest 1 // Calling method: Encounter::init // Subroutine offset: English Hero's Quest 0x0bd0, English Quest for Glory 1 0x0be4 (script 210) @@ -223,7 +235,7 @@ const SciWorkaroundEntry uninitializedReadWorkarounds[] = { { GID_LAURABOW2, -1, 928, 0, NULL, "startText", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // gets caused by Text+Audio support (see script patcher) { GID_LONGBOW, -1, 0, 0, "Longbow", "restart", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // When canceling a restart game - bug #5244 { GID_LONGBOW, -1, 213, 0, "clear", "handleEvent", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // When giving an answer using the druid hand sign code in any room - { GID_LONGBOW, -1, 213, 0, "letter", "handleEvent", 0xa8, NULL, 1, { WORKAROUND_FAKE, 0 } }, // When using the druid hand sign code in any room - bug #5035 + { GID_LONGBOW, -1, 213, 0, "letter", "handleEvent",-1,sig_uninitread_longbow_1, 1, { WORKAROUND_FAKE, 0 } }, // When using the druid hand sign code in any room - bug #5035 { GID_LSL1, 250, 250, 0, "increase", "handleEvent", -1, NULL, 2, { WORKAROUND_FAKE, 0 } }, // casino, playing game, increasing bet { GID_LSL1, 720, 720, 0, "rm720", "init", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // age check room { GID_LSL2, 38, 38, 0, "cloudScript", "changeState", -1, NULL, 1, { WORKAROUND_FAKE, 0 } }, // entering the room in the middle deck of the ship - bug #5034 -- cgit v1.2.3 From b8838d9bffa3cb4ff2a8ded41311dbae6cfde968 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 19 Apr 2015 17:24:27 +0200 Subject: SCI: workaround sig Conquests of Camelot migrated --- engines/sci/engine/workarounds.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index b591ea2b79..9fb40c54a4 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -39,6 +39,20 @@ namespace Sci { // Those signatures are just like the script patcher signatures (for further study: engine\script_patches.cpp) // However you may NOT use command SIG_SELECTOR8 nor SIG_SELECTOR16 atm. Proper support for those may be added later. +// Game: Conquests of Camelot +// Calling method: endingCartoon2::changeState +// Subroutine offset: English 0x020d (script 92) +// Applies to at least: English PC floppy +static const uint16 sig_arithmetic_camelot_1[] = { + 0x83, 0x32, // lal local[32h] + 0x30, SIG_UINT16(0x001d), // bnt [...] + 0x7a, // push2 + 0x39, 0x08, // pushi 08 + 0x36, // push + 0x43, // callk Graph + SIG_END +}; + // Game: Eco Quest 2 // Calling method: Rain::points // Subroutine offset: English 0x0cc6, French/Spanish 0x0ce0 (script 0) @@ -60,7 +74,7 @@ static const uint16 sig_arithmetic_ecoq2_1[] = { // gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround const SciWorkaroundEntry arithmeticWorkarounds[] = { - { GID_CAMELOT, 92, 92, 0, "endingCartoon2", "changeState", 0x20d, NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_lai: during the ending, sub gets called with no parameters, uses parameter 1 which is theGrail in this case - bug #5237 + { GID_CAMELOT, 92, 92, 0, "endingCartoon2", "changeState",-1,sig_arithmetic_camelot_1, 0, { WORKAROUND_FAKE, 0 } }, // op_lai: during the ending, sub gets called with no parameters, uses parameter 1 which is theGrail in this case - bug #5237 { GID_ECOQUEST2, 100, 0, 0, "Rain", "points", -1, sig_arithmetic_ecoq2_1, 0, { WORKAROUND_FAKE, 0 } }, // op_or: when giving the papers to the customs officer, gets called against a pointer instead of a number - bug #4939, Spanish version - bug #5750 { GID_FANMADE, 516, 983, 0, "Wander", "setTarget", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_mul: The Legend of the Lost Jewel Demo (fan made): called with object as second parameter when attacked by insects - bug #5124 { GID_GK1, 800,64992, 0, "Fwd", "doit", -1, NULL, 0, { WORKAROUND_FAKE, 1 } }, // op_gt: when Mosely finds Gabriel and Grace near the end of the game, compares the Grooper object with 7 @@ -79,7 +93,7 @@ const SciWorkaroundEntry arithmeticWorkarounds[] = { // Game: Conquests of the Longbow // Calling method: letter::handleEvent -// Subroutine offset: English 0x00a8 (script 213) +// Subroutine offset: English PC/Amiga 0x00a8 (script 213) // Applies to at least: English PC floppy, English Amiga floppy static const uint16 sig_uninitread_longbow_1[] = { 0x3f, 0x02, // link 02 -- cgit v1.2.3 From 8f5d65d0f11289bd4b2595ea4ad08b5d2344b133 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 19 Apr 2015 18:28:54 +0200 Subject: SCI: workaround sig Space Quest 4 migrated --- engines/sci/engine/workarounds.cpp | 62 ++++++++++++++++++++++++++------------ 1 file changed, 43 insertions(+), 19 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index 9fb40c54a4..e7b9429bbe 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -390,6 +390,19 @@ static const uint16 sig_kDisplay_pq2_1[] = { SIG_END }; +// Game: Space Quest 4 +// Calling method: doCatalog::mode +// Subroutine offset: English PC CD: 0x0084 (script 391) +// Applies to at least: English PC CD +static const uint16 sig_kDisplay_sq4_1[] = { + 0x38, SIG_UINT16(0x0187), // pushi 0187h (drawPic) + 0x78, // push1 + 0x38, SIG_UINT16(0x0189), // pushi 0189h (reflectPosn) + 0x81, 0x02, // lag global[2] + 0x4a, 0x06, // send 06 + SIG_END +}; + // gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround const SciWorkaroundEntry kDisplay_workarounds[] = { { GID_ISLANDBRAIN, 300, 300, 0, "geneDude", "show", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // when looking at the gene explanation chart - a parameter is an object @@ -400,7 +413,7 @@ const SciWorkaroundEntry kDisplay_workarounds[] = { { GID_PQ2, 23, 23, 0, "rm23Script", "elements", -1, sig_kDisplay_pq2_1, 0, { WORKAROUND_IGNORE, 0 } }, // when looking at the 2nd page of pate's file - 0x75 as id - bug #5223 { GID_QFG1, 11, 11, 0, "battle", "init", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: When entering battle, 0x75 as id { GID_SQ4, 397, 0, 0, "", "export 12", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // FLOPPY: when going into the computer store - bug #5227 - { GID_SQ4, 391, 391, 0, "doCatalog", "mode", 0x84, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // CD: clicking on catalog in roboter sale - a parameter is an object + { GID_SQ4, 391, 391, 0, "doCatalog", "mode", -1, sig_kDisplay_sq4_1, 0, { WORKAROUND_IGNORE, 0 } }, // CD: clicking on catalog in roboter sale - a parameter is an object { GID_SQ4, 391, 391, 0, "choosePlug", "changeState", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // CD: ordering connector in roboter sale - a parameter is an object SCI_WORKAROUNDENTRY_TERMINATOR }; @@ -497,25 +510,36 @@ const SciWorkaroundEntry kGraphFillBoxAny_workarounds[] = { SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround +// Game: Space Quest 4 +// Calling method: laserScript::changeState +// Subroutine offset: English/German/French/Russian PC floppy, Japanese PC-9801: 0x0016, English PC CD: 0x00b2 (script 150) +// Applies to at least: English/German/French/Russian PC floppy, English PC CD, Japanese PC-9801 +static const uint16 sig_kGraphRedrawBox_sq4_1[] = { + 0x3f, 0x07, // link 07 + 0x39, SIG_ADDTOOFFSET(+1), // pushi 2Ah for PC floppy, pushi 27h for PC CD + 0x76, // push0 + 0x72, // lofsa laserSound + SIG_END +}; + +// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround const SciWorkaroundEntry kGraphRedrawBox_workarounds[] = { - { GID_SQ4, 405, 405, 0, "swimAfterEgo", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air - accidental additional parameter specified - { GID_SQ4, 405, 405, 0, "", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air... Russian version - bug #5573 - { GID_SQ4, 406, 406, 0, "egoFollowed", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // FLOPPY: when getting shot by the police - accidental additional parameter specified - { GID_SQ4, 406, 406, 0, "swimAndShoot", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air - accidental additional parameter specified - { GID_SQ4, 406, 406, 0, "", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air... Russian version - bug #5573 (is for both egoFollowed and swimAndShoot) - { GID_SQ4, 410, 410, 0, "swimAfterEgo", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air - accidental additional parameter specified - { GID_SQ4, 410, 410, 0, "", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air... Russian version - bug #5573 - { GID_SQ4, 411, 411, 0, "swimAndShoot", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air - accidental additional parameter specified - { GID_SQ4, 411, 411, 0, "", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air... Russian version - bug #5573 - { GID_SQ4, 150, 150, 0, "laserScript", "changeState", 0xb2, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // when visiting the pedestral where Roger Jr. is trapped, before trashing the brain icon in the programming chapter, accidental additional parameter specified - bug #5479 - { GID_SQ4, 150, 150, 0, "laserScript", "changeState", 0x16, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // same as above, for the German version - bug #5527 - { GID_SQ4, 150, 150, 0, "", "changeState", 0x16, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // same as above, for the Russian version - bug #5573 - { GID_SQ4, -1, 704, 0, "shootEgo", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // When shot by Droid in Super Computer Maze (Rooms 500, 505, 510...) - accidental additional parameter specified - { GID_KQ5, -1, 981, 0, "myWindow", "dispose", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // Happens in the floppy version, when closing any dialog box, accidental additional parameter specified - bug #5031 - { GID_KQ5, -1, 995, 0, "invW", "doit", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // Happens in the floppy version, when closing the inventory window, accidental additional parameter specified - { GID_KQ5, -1, 995, 0, "", "export 0", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // Happens in the floppy version, when opening the gem pouch, accidental additional parameter specified - bug #5138 - { GID_KQ5, -1, 403, 0, "KQ5Window", "dispose", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // Happens in the FM Towns version when closing any dialog box, accidental additional parameter specified + { GID_SQ4, 405, 405, 0, "swimAfterEgo", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air - accidental additional parameter specified + { GID_SQ4, 405, 405, 0, "", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air... Russian version - bug #5573 + { GID_SQ4, 406, 406, 0, "egoFollowed", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // FLOPPY: when getting shot by the police - accidental additional parameter specified + { GID_SQ4, 406, 406, 0, "swimAndShoot", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air - accidental additional parameter specified + { GID_SQ4, 406, 406, 0, "", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air... Russian version - bug #5573 (is for both egoFollowed and swimAndShoot) + { GID_SQ4, 410, 410, 0, "swimAfterEgo", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air - accidental additional parameter specified + { GID_SQ4, 410, 410, 0, "", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air... Russian version - bug #5573 + { GID_SQ4, 411, 411, 0, "swimAndShoot", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air - accidental additional parameter specified + { GID_SQ4, 411, 411, 0, "", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air... Russian version - bug #5573 + { GID_SQ4, 150, 150, 0, "laserScript", "changeState", -1, sig_kGraphRedrawBox_sq4_1, 0, { WORKAROUND_STILLCALL, 0 } }, // when visiting the pedestral where Roger Jr. is trapped, before trashing the brain icon in the programming chapter, accidental additional parameter specified - bug #5479, German - bug #5527 + { GID_SQ4, 150, 150, 0, "", "changeState", -1, sig_kGraphRedrawBox_sq4_1, 0, { WORKAROUND_STILLCALL, 0 } }, // same as above, for the Russian version - bug #5573 + { GID_SQ4, -1, 704, 0, "shootEgo", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // When shot by Droid in Super Computer Maze (Rooms 500, 505, 510...) - accidental additional parameter specified + { GID_KQ5, -1, 981, 0, "myWindow", "dispose", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // Happens in the floppy version, when closing any dialog box, accidental additional parameter specified - bug #5031 + { GID_KQ5, -1, 995, 0, "invW", "doit", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // Happens in the floppy version, when closing the inventory window, accidental additional parameter specified + { GID_KQ5, -1, 995, 0, "", "export 0", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // Happens in the floppy version, when opening the gem pouch, accidental additional parameter specified - bug #5138 + { GID_KQ5, -1, 403, 0, "KQ5Window", "dispose", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // Happens in the FM Towns version when closing any dialog box, accidental additional parameter specified SCI_WORKAROUNDENTRY_TERMINATOR }; -- cgit v1.2.3 From 9e887fe184e2b9b3806ca54833ed8f66a5ef2b78 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 19 Apr 2015 19:08:16 +0200 Subject: SCI: workaround sig for fanmade games kDeviceInfo --- engines/sci/engine/workarounds.cpp | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index e7b9429bbe..85de92992a 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -358,17 +358,34 @@ const SciWorkaroundEntry kDeleteKey_workarounds[] = { SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround +// Game: Fan-Made games (SCI Studio) +// Calling method: Game::save, Game::restore +// Subroutine offset: Al Pond 2: 0x0e5c (ldi 0001) +// Black Cauldron: 0x000a (ldi 01) +// Cascade Quest: 0x0d1c (ldi 0001) +// Demo Quest: 0x0e55 (ldi 0001) +// I want my C64 back: 0x0e57 (ldi 0001) +// Applies to at least: games listed above +static const uint16 sig_kDeviceInfo_Fanmade_1[] = { + 0x3f, 0x79, // link 79h + 0x34, SIG_UINT16(0x0001), // ldi 0001 + 0xa5, 0x00, // sat temp[0] + SIG_END +}; +static const uint16 sig_kDeviceInfo_Fanmade_2[] = { + 0x3f, 0x79, // link 79h + 0x35, 0x01, // ldi 01 + 0xa5, 0x00, // sat temp[0] + SIG_END +}; + +// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround const SciWorkaroundEntry kDeviceInfo_workarounds[] = { - { GID_FANMADE, -1, 994, 1, "Game", "save", 0xd1c, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games, this is called with one parameter for CurDevice (Cascade Quest) - { GID_FANMADE, -1, 994, 1, "Game", "save", 0xe55, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games, this is called with one parameter for CurDevice (Demo Quest) - { GID_FANMADE, -1, 994, 1, "Game", "save", 0xe57, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games, this is called with one parameter for CurDevice (I Want My C64 Back) - { GID_FANMADE, -1, 994, 0, "Black", "save", 0xa, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // In fanmade games, this is called with one parameter for CurDevice (Black Cauldron Remake) - { GID_FANMADE, -1, 994, 1, "Game", "save", 0xe5c, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games, this is called with one parameter for CurDevice (Most of them) - { GID_FANMADE, -1, 994, 1, "Game", "restore", 0xd1c, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games, this is called with one parameter for CurDevice (Cascade Quest) - { GID_FANMADE, -1, 994, 1, "Game", "restore", 0xe55, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games, this is called with one parameter for CurDevice (Demo Quest) - { GID_FANMADE, -1, 994, 1, "Game", "restore", 0xe57, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games, this is called with one parameter for CurDevice (I Want My C64 Back) - { GID_FANMADE, -1, 994, 1, "Game", "restore", 0xe5c, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games, this is called with one parameter for CurDevice (Most of them) + { GID_FANMADE, -1, 994, 1, "Game", "save", -1, sig_kDeviceInfo_Fanmade_1, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games (SCI Studio), this is called with one parameter for CurDevice LDI 01 variant + { GID_FANMADE, -1, 994, 1, "Game", "save", -1, sig_kDeviceInfo_Fanmade_2, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games (SCI Studio), this is called with one parameter for CurDevice LDI 0001 variant + { GID_FANMADE, -1, 994, 0, "Black", "save", -1, sig_kDeviceInfo_Fanmade_1, 0, { WORKAROUND_IGNORE, 0 } }, // In fanmade games (SCI Studio), this is called with one parameter for CurDevice (Black Cauldron Remake) + { GID_FANMADE, -1, 994, 1, "Game", "restore", -1, sig_kDeviceInfo_Fanmade_1, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games (SCI Studio), this is called with one parameter for CurDevice LDI 01 variant + { GID_FANMADE, -1, 994, 1, "Game", "restore", -1, sig_kDeviceInfo_Fanmade_2, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games (SCI Studio), this is called with one parameter for CurDevice LDI 0001 variant SCI_WORKAROUNDENTRY_TERMINATOR }; -- cgit v1.2.3 From d70e4ee3f18aefca0424921e53a785a57225403e Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 19 Apr 2015 19:24:21 +0200 Subject: SCI: workaround sig Space Quest 1 migrated --- engines/sci/engine/workarounds.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index 85de92992a..99bf1de7f9 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -173,6 +173,19 @@ static const uint16 sig_uninitread_qfg3_2[] = { SIG_END }; +// Game: Space Quest 1 +// Calling method: firePulsar::changeState +// Subroutine offset: English 0x018a (script 703) +// Applies to at least: English PC floppy, English Amiga floppy +static const uint16 sig_uninitread_sq1_1[] = { + 0x3f, 0x01, // link 01 + 0x38, SIG_ADDTOOFFSET(+2), // pushi 0242 (selector egoStatus) + 0x76, // push0 + 0x72, SIG_ADDTOOFFSET(+2), // lofsa DeltaurRegion + 0x4a, 0x04, // send 04 + SIG_END +}; + // gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround const SciWorkaroundEntry uninitializedReadWorkarounds[] = { { GID_CAMELOT, 40, 40, 0, "Rm40", "handleEvent", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // when looking at the ground at the pool of Siloam - bug #6401 @@ -305,7 +318,7 @@ const SciWorkaroundEntry uninitializedReadWorkarounds[] = { { GID_SHIVERS, 29260, 29260, 0, "spVenus", "handleEvent", -1, NULL, 4, { WORKAROUND_FAKE, 0 } }, // When clicking venus after seeing fortune to align earth etc... { GID_SQ1, 103, 103, 0, "hand", "internalEvent", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // Spanish (and maybe early versions?) only: when moving cursor over input pad, temps 1 and 2 { GID_SQ1, -1, 703, 0, "", "export 1", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // sub that's called from several objects while on sarien battle cruiser - { GID_SQ1, -1, 703, 0, "firePulsar", "changeState", 0x18a, NULL, 0, { WORKAROUND_FAKE, 0 } }, // export 1, but called locally (when shooting at aliens) + { GID_SQ1, -1, 703, 0, "firePulsar", "changeState",-1, sig_uninitread_sq1_1, 0, { WORKAROUND_FAKE, 0 } }, // export 1, but called locally (when shooting at aliens) { GID_SQ4, -1, 398, 0, "showBox", "changeState", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // CD: called when rummaging in Software Excess bargain bin { GID_SQ4, -1, 928, -1, "Narrator", "startText", -1, NULL, 1000, { WORKAROUND_FAKE, 1 } }, // CD: happens in the options dialog and in-game when speech and subtitles are used simultaneously { GID_SQ4, -1, 708, -1, "exitBut", "doVerb", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // Floppy: happens, when looking at the "close" button in the sq4 hintbook - bug #6447 -- cgit v1.2.3 From 9376b9db88af68770fba86bbd21c310014fc97e4 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 19 Apr 2015 19:44:10 +0200 Subject: SCI: workaround sig Hoyle 4 migrated --- engines/sci/engine/workarounds.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index 99bf1de7f9..e27396469d 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -91,6 +91,17 @@ const SciWorkaroundEntry arithmeticWorkarounds[] = { SCI_WORKAROUNDENTRY_TERMINATOR }; +// Game: Hoyle 4 +// Calling method: export 2 +// Subroutine offset: 0x1d4d (script 300) +// Applies to at least: English PC floppy +static const uint16 sig_uninitread_hoyle4_1[] = { + 0x3f, 0x01, // link 01 + 0x39, 0x40, // pushi 40h + 0x78, // push1 + SIG_END +}; + // Game: Conquests of the Longbow // Calling method: letter::handleEvent // Subroutine offset: English PC/Amiga 0x00a8 (script 213) @@ -229,7 +240,7 @@ const SciWorkaroundEntry uninitializedReadWorkarounds[] = { { GID_HOYLE4, 700, -1, 1, "Code", "doit", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // when placing a bid in bridge (always), temp var 11, 24, 27, 46, 75, objects compete_tree, compwe_tree, other1_tree, b1 - bugs #5663 and #5794 { GID_HOYLE4, 700, 921, 0, "Print", "addEdit", -1, NULL, 0, { WORKAROUND_FAKE, 118 } }, // when saving the game (may also occur in other situations) - bug #6601, bug #6614 { GID_HOYLE4, 700, 921, 0, "Print", "addEdit", -1, NULL, 1, { WORKAROUND_FAKE, 1 } }, // see above, Text-control saves its coordinates to temp[0] and temp[1], Edit-control adjusts to those uninitialized temps, who by accident were left over from the Text-control - { GID_HOYLE4, 300, 300, 0, "", "export 2", 0x1d4d, NULL, 0, { WORKAROUND_FAKE, 0 } }, // after passing around cards in hearts + { GID_HOYLE4, 300, 300, 0, "", "export 2", -1, sig_uninitread_hoyle4_1, 0, { WORKAROUND_FAKE, 0 } }, // after passing around cards in hearts { GID_HOYLE4, 400, 400, 1, "GinHand", "calcRuns", -1, NULL, 4, { WORKAROUND_FAKE, 0 } }, // sometimes while playing Gin Rummy (e.g. when knocking and placing a card) - bug #5665 { GID_HOYLE4, 500, 17, 1, "Character", "say", -1, NULL, 504, { WORKAROUND_FAKE, 0 } }, // sometimes while playing Cribbage (e.g. when the opponent says "Last Card") - bug #5662 { GID_HOYLE4, 800, 870, 0, "EuchreStrategy", "thinkLead", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // while playing Euchre, happens at least on 2nd or 3rd turn - bug #6602 -- cgit v1.2.3 From 2043103232706772b19196d49efb48fbe5c3808d Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 19 Apr 2015 19:53:29 +0200 Subject: SCI: workaround sig Hoyle 1 migrated --- engines/sci/engine/workarounds.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index e27396469d..3c07d94def 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -91,6 +91,18 @@ const SciWorkaroundEntry arithmeticWorkarounds[] = { SCI_WORKAROUNDENTRY_TERMINATOR }; +// Game: Hoyle 1 +// Calling method: export 0 +// Subroutine offset: 0x037c (script 16) +// Applies to at least: English PC floppy +static const uint16 sig_uninitread_hoyle1_1[] = { + 0x3f, 0x05, // link 05 + 0x78, // push1 + 0x76, // push0 + 0x40, // call [...] + SIG_END +}; + // Game: Hoyle 4 // Calling method: export 2 // Subroutine offset: 0x1d4d (script 300) @@ -222,7 +234,7 @@ const SciWorkaroundEntry uninitializedReadWorkarounds[] = { { GID_GK2, -1, 11, 0, "", "export 10", -1, NULL, 4, { WORKAROUND_FAKE, 0 } }, // called during the game { GID_HOYLE1, 4, 104, 0, "GinRummyCardList", "calcRuns", -1, NULL, 4, { WORKAROUND_FAKE, 0 } }, // Gin Rummy / right when the game starts { GID_HOYLE1, 5, 204, 0, "tableau", "checkRuns", -1, NULL, 2, { WORKAROUND_FAKE, 0 } }, // Cribbage / during the game - { GID_HOYLE1, 3, 16, 0, "", "export 0", 0x37c, NULL, 3, { WORKAROUND_FAKE, 0 } }, // Hearts / during the game - bug #5299 + { GID_HOYLE1, 3, 16, 0, "", "export 0", -1, sig_uninitread_hoyle1_1, 3, { WORKAROUND_FAKE, 0 } }, // Hearts / during the game - bug #5299 { GID_HOYLE1, -1, 997, 0, "MenuBar", "doit", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // When changing game speed settings - bug #5512 { GID_HOYLE3, -1, 0, 1, "Character", "say", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // when starting checkers or dominoes, first time a character says something - temps 504 and 505 { GID_HOYLE3, -1, 700, 0, "gcWindow", "open", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // when entering control menu -- cgit v1.2.3 From 4a9f2fb1c4711f86fd1c5aa11fb8e8e1eb8974c4 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 19 Apr 2015 20:05:16 +0200 Subject: SCI: workaround sig Jones in the fast lane migrated --- engines/sci/engine/workarounds.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index 3c07d94def..36218051e7 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -114,6 +114,18 @@ static const uint16 sig_uninitread_hoyle4_1[] = { SIG_END }; +// Game: Jones in the fast lane +// Calling method: weekendText::draw +// Subroutine offset: 0x03d3 (script 232) +// Applies to at least: English PC CD +static const uint16 sig_uninitread_jones_1[] = { + 0x3f, 0x02, // link 02 + 0x8d, 0x00, // lst temp[0] + 0x35, 0x01, // ldi 01 + 0x22, // lt? + SIG_END +}; + // Game: Conquests of the Longbow // Calling method: letter::handleEvent // Subroutine offset: English PC/Amiga 0x00a8 (script 213) @@ -260,7 +272,7 @@ const SciWorkaroundEntry uninitializedReadWorkarounds[] = { { GID_ISLANDBRAIN, 100, 937, 0, "IconBar", "dispatchEvent", -1, NULL, 58, { WORKAROUND_FAKE, 0 } }, // when using ENTER at the startup menu - bug #5241 { GID_ISLANDBRAIN, 140, 140, 0, "piece", "init", -1, NULL, 3, { WORKAROUND_FAKE, 1 } }, // first puzzle right at the start, some initialization variable. bnt is done on it, and it should be non-0 { GID_ISLANDBRAIN, 200, 268, 0, "anElement", "select", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // elements puzzle, gets used before super TextIcon - { GID_JONES, 1, 232, 0, "weekendText", "draw", 0x3d3, NULL, 0, { WORKAROUND_FAKE, 0 } }, // jones/cd only - gets called during the game + { GID_JONES, 1, 232, 0, "weekendText", "draw", -1, sig_uninitread_jones_1, 0, { WORKAROUND_FAKE, 0 } }, // jones/cd only - gets called during the game { GID_JONES, 1, 255, 0, "", "export 0", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // jones/cd only - called when a game ends, temps 13 and 14 { GID_JONES, 764, 255, 0, "", "export 0", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // jones/ega&vga only - called when the game starts, temps 13 and 14 //{ GID_KQ5, -1, 0, 0, "", "export 29", -1, NULL, 3, { WORKAROUND_FAKE, 0xf } }, // called when playing harp for the harpies or when aborting dialog in toy shop, is used for kDoAudio - bug #4961 -- cgit v1.2.3 From 34260a2cdd1f8a7509460df5bdf0a88b8e711840 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 19 Apr 2015 20:25:12 +0200 Subject: SCI: workaround sig fanmade Ocean Battle migrated --- engines/sci/engine/workarounds.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index 36218051e7..b6cd33dd1c 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -91,6 +91,16 @@ const SciWorkaroundEntry arithmeticWorkarounds[] = { SCI_WORKAROUNDENTRY_TERMINATOR }; +// Game: Fan-Made "Ocean Battle" +// Calling method: RoomScript::doit +// Subroutine offset: 0x1f17 +// Applies to at least: Ocean Battle +static const uint16 sig_uninitread_fanmade_1[] = { + 0x3f, 0x04, // link 04 + 0x88, SIG_UINT16(0x023b), // lsg global[23Bh] + SIG_END +}; + // Game: Hoyle 1 // Calling method: export 0 // Subroutine offset: 0x037c (script 16) @@ -237,7 +247,7 @@ const SciWorkaroundEntry uninitializedReadWorkarounds[] = { { GID_ECOQUEST, -1, -1, 0, NULL, "doVerb", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // almost clicking anywhere triggers this in almost all rooms { GID_FANMADE, 516, 979, 0, "", "export 0", -1, NULL, 20, { WORKAROUND_FAKE, 0 } }, // Happens in Grotesteing after the logos { GID_FANMADE, 528, 990, 0, "GDialog", "doit", -1, NULL, 4, { WORKAROUND_FAKE, 0 } }, // Happens in Cascade Quest when closing the glossary - bug #5116 - { GID_FANMADE, 488, 1, 0, "RoomScript", "doit", 0x1f17, NULL, 1, { WORKAROUND_FAKE, 0 } }, // Happens in Ocean Battle while playing - bug #5335 + { GID_FANMADE, 488, 1, 0, "RoomScript", "doit", -1, sig_uninitread_fanmade_1, 1, { WORKAROUND_FAKE, 0 } }, // Happens in Ocean Battle while playing - bug #5335 { GID_FREDDYPHARKAS, -1, 24, 0, "gcWin", "open", -1, NULL, 5, { WORKAROUND_FAKE, 0xf } }, // is used as priority for game menu { GID_FREDDYPHARKAS, -1, 31, 0, "quitWin", "open", -1, NULL, 5, { WORKAROUND_FAKE, 0xf } }, // is used as priority for game menu { GID_FREDDYPHARKAS, 540, 540, 0, "WaverCode", "init", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // Gun pratice mini-game - bug #5232 -- cgit v1.2.3 From d8c732c2a1f16ddf4f189f856b0bdd0f9ad149c3 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 19 Apr 2015 20:46:07 +0200 Subject: SCI: workaround sig cleanup old and now obsolete localCallOffset removed --- engines/sci/engine/workarounds.cpp | 607 ++++++++++++++++++------------------- engines/sci/engine/workarounds.h | 1 - 2 files changed, 302 insertions(+), 306 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index b6cd33dd1c..71ba7d05a4 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -27,7 +27,7 @@ #include "sci/engine/script_patches.h" #include "sci/engine/workarounds.h" -#define SCI_WORKAROUNDENTRY_TERMINATOR { (SciGameId)0, -1, -1, 0, NULL, NULL, -1, NULL, 0, { WORKAROUND_NONE, 0 } } +#define SCI_WORKAROUNDENTRY_TERMINATOR { (SciGameId)0, -1, -1, 0, NULL, NULL, NULL, 0, { WORKAROUND_NONE, 0 } } namespace Sci { @@ -72,22 +72,22 @@ static const uint16 sig_arithmetic_ecoq2_1[] = { SIG_END }; -// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround +// gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround const SciWorkaroundEntry arithmeticWorkarounds[] = { - { GID_CAMELOT, 92, 92, 0, "endingCartoon2", "changeState",-1,sig_arithmetic_camelot_1, 0, { WORKAROUND_FAKE, 0 } }, // op_lai: during the ending, sub gets called with no parameters, uses parameter 1 which is theGrail in this case - bug #5237 - { GID_ECOQUEST2, 100, 0, 0, "Rain", "points", -1, sig_arithmetic_ecoq2_1, 0, { WORKAROUND_FAKE, 0 } }, // op_or: when giving the papers to the customs officer, gets called against a pointer instead of a number - bug #4939, Spanish version - bug #5750 - { GID_FANMADE, 516, 983, 0, "Wander", "setTarget", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_mul: The Legend of the Lost Jewel Demo (fan made): called with object as second parameter when attacked by insects - bug #5124 - { GID_GK1, 800,64992, 0, "Fwd", "doit", -1, NULL, 0, { WORKAROUND_FAKE, 1 } }, // op_gt: when Mosely finds Gabriel and Grace near the end of the game, compares the Grooper object with 7 - { GID_HOYLE4, 700, -1, 1, "Code", "doit", -1, NULL, 0, { WORKAROUND_FAKE, 1 } }, // op_add: while bidding in Bridge, an object ("Bid") is added to an object in another segment ("hand3") - { GID_ICEMAN, 199, 977, 0, "Grooper", "doit", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_add: While dancing with the girl - { GID_MOTHERGOOSE256, -1, 999, 0, "Event", "new", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_and: constantly during the game (SCI1 version) - { GID_MOTHERGOOSE256, -1, 4, 0, "rm004", "doit", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_or: when going north and reaching the castle (rooms 4 and 37) - bug #5101 - { GID_MOTHERGOOSEHIRES,90, 90, 0, "newGameButton", "select", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_ge: MUMG Deluxe, when selecting "New Game" in the main menu. It tries to compare an integer with a list. Needs to return false for the game to continue. - { GID_PHANTASMAGORIA, 902, 0, 0, "", "export 7", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_shr: when starting a chapter in Phantasmagoria - { GID_QFG1VGA, 301, 928, 0, "Blink", "init", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_div: when entering the inn, gets called with 1 parameter, but 2nd parameter is used for div which happens to be an object - { GID_QFG2, 200, 200, 0, "astro", "messages", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_lsi: when getting asked for your name by the astrologer - bug #5152 - { GID_QFG3, 780, 999, 0, "", "export 6", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_add: trying to talk to yourself at the top of the giant tree - bug #6692 - { GID_QFG4, 710,64941, 0, "RandCycle", "doit", -1, NULL, 0, { WORKAROUND_FAKE, 1 } }, // op_gt: when the tentacle appears in the third room of the caves + { GID_CAMELOT, 92, 92, 0, "endingCartoon2", "changeState", sig_arithmetic_camelot_1, 0, { WORKAROUND_FAKE, 0 } }, // op_lai: during the ending, sub gets called with no parameters, uses parameter 1 which is theGrail in this case - bug #5237 + { GID_ECOQUEST2, 100, 0, 0, "Rain", "points", sig_arithmetic_ecoq2_1, 0, { WORKAROUND_FAKE, 0 } }, // op_or: when giving the papers to the customs officer, gets called against a pointer instead of a number - bug #4939, Spanish version - bug #5750 + { GID_FANMADE, 516, 983, 0, "Wander", "setTarget", NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_mul: The Legend of the Lost Jewel Demo (fan made): called with object as second parameter when attacked by insects - bug #5124 + { GID_GK1, 800,64992, 0, "Fwd", "doit", NULL, 0, { WORKAROUND_FAKE, 1 } }, // op_gt: when Mosely finds Gabriel and Grace near the end of the game, compares the Grooper object with 7 + { GID_HOYLE4, 700, -1, 1, "Code", "doit", NULL, 0, { WORKAROUND_FAKE, 1 } }, // op_add: while bidding in Bridge, an object ("Bid") is added to an object in another segment ("hand3") + { GID_ICEMAN, 199, 977, 0, "Grooper", "doit", NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_add: While dancing with the girl + { GID_MOTHERGOOSE256, -1, 999, 0, "Event", "new", NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_and: constantly during the game (SCI1 version) + { GID_MOTHERGOOSE256, -1, 4, 0, "rm004", "doit", NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_or: when going north and reaching the castle (rooms 4 and 37) - bug #5101 + { GID_MOTHERGOOSEHIRES,90, 90, 0, "newGameButton", "select", NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_ge: MUMG Deluxe, when selecting "New Game" in the main menu. It tries to compare an integer with a list. Needs to return false for the game to continue. + { GID_PHANTASMAGORIA, 902, 0, 0, "", "export 7", NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_shr: when starting a chapter in Phantasmagoria + { GID_QFG1VGA, 301, 928, 0, "Blink", "init", NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_div: when entering the inn, gets called with 1 parameter, but 2nd parameter is used for div which happens to be an object + { GID_QFG2, 200, 200, 0, "astro", "messages", NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_lsi: when getting asked for your name by the astrologer - bug #5152 + { GID_QFG3, 780, 999, 0, "", "export 6", NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_add: trying to talk to yourself at the top of the giant tree - bug #6692 + { GID_QFG4, 710,64941, 0, "RandCycle", "doit", NULL, 0, { WORKAROUND_FAKE, 1 } }, // op_gt: when the tentacle appears in the third room of the caves SCI_WORKAROUNDENTRY_TERMINATOR }; @@ -231,188 +231,188 @@ static const uint16 sig_uninitread_sq1_1[] = { SIG_END }; -// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround +// gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround const SciWorkaroundEntry uninitializedReadWorkarounds[] = { - { GID_CAMELOT, 40, 40, 0, "Rm40", "handleEvent", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // when looking at the ground at the pool of Siloam - bug #6401 - { GID_CASTLEBRAIN, 280, 280, 0, "programmer", "dispatchEvent", -1, NULL, 0, { WORKAROUND_FAKE, 0xf } }, // pressing 'q' on the computer screen in the robot room, and closing the help dialog that pops up (bug #5143). Moves the cursor to the view with the ID returned (in this case, the robot hand) - { GID_CNICK_KQ, -1, 0, 1, "Character", "say", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // checkers/backgammon, like in hoyle 3 - temps 504 and 505 - bug #6255 - { GID_CNICK_KQ, -1, 700, 0, "gcWindow", "open", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // when entering the control menu, like in hoyle 3 - { GID_CNICK_KQ, 300, 303, 0, "theDoubleCube", "", -1, NULL, 5, { WORKAROUND_FAKE, 0 } }, // while playing backgammon with doubling enabled - bug #6426 (same as the theDoubleCube::make workaround for Hoyle 3) - { GID_CNICK_KQ, 300, 303, 0, "theDoubleCube", "", -1, NULL, 9, { WORKAROUND_FAKE, 0 } }, // when accepting a double, while playing backgammon with doubling enabled (same as the theDoubleCube::accept workaround for Hoyle 3) - { GID_CNICK_LAURABOW, -1, 0, 1, "Character", "say", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // Yatch, like in hoyle 3 - temps 504 and 505 - bug #6424 - { GID_CNICK_LAURABOW, -1, 700, 0, NULL, "open", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // when entering control menu - bug #6423 (same as the gcWindow workaround for Hoyle 3) - { GID_CNICK_LAURABOW,100, 100, 0, NULL, "", -1, NULL, 1, { WORKAROUND_FAKE, 0 } }, // while playing domino - bug #6429 (same as the dominoHand2 workaround for Hoyle 3) - { GID_CNICK_LAURABOW,100, 110, 0, NULL, "doit", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // when changing the "Dominoes per hand" setting - bug #6430 - { GID_CNICK_LONGBOW, 0, 0, 0, "RH Budget", "init", -1, NULL, 1, { WORKAROUND_FAKE, 0 } }, // when starting the game - { GID_ECOQUEST, -1, -1, 0, NULL, "doVerb", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // almost clicking anywhere triggers this in almost all rooms - { GID_FANMADE, 516, 979, 0, "", "export 0", -1, NULL, 20, { WORKAROUND_FAKE, 0 } }, // Happens in Grotesteing after the logos - { GID_FANMADE, 528, 990, 0, "GDialog", "doit", -1, NULL, 4, { WORKAROUND_FAKE, 0 } }, // Happens in Cascade Quest when closing the glossary - bug #5116 - { GID_FANMADE, 488, 1, 0, "RoomScript", "doit", -1, sig_uninitread_fanmade_1, 1, { WORKAROUND_FAKE, 0 } }, // Happens in Ocean Battle while playing - bug #5335 - { GID_FREDDYPHARKAS, -1, 24, 0, "gcWin", "open", -1, NULL, 5, { WORKAROUND_FAKE, 0xf } }, // is used as priority for game menu - { GID_FREDDYPHARKAS, -1, 31, 0, "quitWin", "open", -1, NULL, 5, { WORKAROUND_FAKE, 0xf } }, // is used as priority for game menu - { GID_FREDDYPHARKAS, 540, 540, 0, "WaverCode", "init", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // Gun pratice mini-game - bug #5232 - { GID_GK1, -1, 64950, -1, "Feature", "handleEvent", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // sometimes when walk-clicking - { GID_GK2, -1, 11, 0, "", "export 10", -1, NULL, 3, { WORKAROUND_FAKE, 0 } }, // called when the game starts - { GID_GK2, -1, 11, 0, "", "export 10", -1, NULL, 4, { WORKAROUND_FAKE, 0 } }, // called during the game - { GID_HOYLE1, 4, 104, 0, "GinRummyCardList", "calcRuns", -1, NULL, 4, { WORKAROUND_FAKE, 0 } }, // Gin Rummy / right when the game starts - { GID_HOYLE1, 5, 204, 0, "tableau", "checkRuns", -1, NULL, 2, { WORKAROUND_FAKE, 0 } }, // Cribbage / during the game - { GID_HOYLE1, 3, 16, 0, "", "export 0", -1, sig_uninitread_hoyle1_1, 3, { WORKAROUND_FAKE, 0 } }, // Hearts / during the game - bug #5299 - { GID_HOYLE1, -1, 997, 0, "MenuBar", "doit", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // When changing game speed settings - bug #5512 - { GID_HOYLE3, -1, 0, 1, "Character", "say", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // when starting checkers or dominoes, first time a character says something - temps 504 and 505 - { GID_HOYLE3, -1, 700, 0, "gcWindow", "open", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // when entering control menu - { GID_HOYLE3, 100, 100, 0, "dominoHand2", "cue", -1, NULL, 1, { WORKAROUND_FAKE, 0 } }, // while playing domino - bug #5042 - { GID_HOYLE3, 100, 110, 0, "OKButton", "doit", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // when changing the "Dominoes per hand" setting - bug #6430 - { GID_HOYLE3, 300, 303, 0, "theDoubleCube", "make", -1, NULL, 5, { WORKAROUND_FAKE, 0 } }, // while playing backgammon with doubling enabled - { GID_HOYLE3, 300, 303, 0, "theDoubleCube", "accept", -1, NULL, 9, { WORKAROUND_FAKE, 0 } }, // when accepting a double, while playing backgammon with doubling enabled - { GID_HOYLE4, -1, 0, 0, NULL, "open", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // when selecting "Control" from the menu (temp vars 0-3) - bug #5132 - { GID_HOYLE4, 910, 18, 0, NULL, "init", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // during tutorial - bug #5213 - { GID_HOYLE4, 910, 910, 0, NULL, "setup", -1, NULL, 3, { WORKAROUND_FAKE, 0 } }, // when selecting "Tutorial" from the main menu - bug #5132 - { GID_HOYLE4, 700, 700, 1, "BridgeHand", "calcQTS", -1, NULL, 3, { WORKAROUND_FAKE, 0 } }, // when placing a bid in bridge (always) - { GID_HOYLE4, 700, 710, 1, "BridgeStrategyPlay", "checkSplitTops", -1, NULL, 10, { WORKAROUND_FAKE, 0 } }, // while playing bridge, objects LeadReturn_Trump, SecondSeat_Trump, ThirdSeat_Trump and others - bug #5794 - { GID_HOYLE4, 700, -1, 1, "BridgeDefense", "think", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // sometimes while playing bridge, temp var 3, 17 and others, objects LeadReturn_Trump, ThirdSeat_Trump and others - { GID_HOYLE4, 700, 730, 1, "BridgeDefense", "beatTheirBest", -1, NULL, 3, { WORKAROUND_FAKE, 0 } }, // rarely while playing bridge - { GID_HOYLE4, 700, -1, 1, "Code", "doit", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // when placing a bid in bridge (always), temp var 11, 24, 27, 46, 75, objects compete_tree, compwe_tree, other1_tree, b1 - bugs #5663 and #5794 - { GID_HOYLE4, 700, 921, 0, "Print", "addEdit", -1, NULL, 0, { WORKAROUND_FAKE, 118 } }, // when saving the game (may also occur in other situations) - bug #6601, bug #6614 - { GID_HOYLE4, 700, 921, 0, "Print", "addEdit", -1, NULL, 1, { WORKAROUND_FAKE, 1 } }, // see above, Text-control saves its coordinates to temp[0] and temp[1], Edit-control adjusts to those uninitialized temps, who by accident were left over from the Text-control - { GID_HOYLE4, 300, 300, 0, "", "export 2", -1, sig_uninitread_hoyle4_1, 0, { WORKAROUND_FAKE, 0 } }, // after passing around cards in hearts - { GID_HOYLE4, 400, 400, 1, "GinHand", "calcRuns", -1, NULL, 4, { WORKAROUND_FAKE, 0 } }, // sometimes while playing Gin Rummy (e.g. when knocking and placing a card) - bug #5665 - { GID_HOYLE4, 500, 17, 1, "Character", "say", -1, NULL, 504, { WORKAROUND_FAKE, 0 } }, // sometimes while playing Cribbage (e.g. when the opponent says "Last Card") - bug #5662 - { GID_HOYLE4, 800, 870, 0, "EuchreStrategy", "thinkLead", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // while playing Euchre, happens at least on 2nd or 3rd turn - bug #6602 - { GID_HOYLE4, -1, 937, 0, "IconBar", "dispatchEvent", -1, NULL, 408, { WORKAROUND_FAKE, 0 } }, // pressing ENTER on scoreboard while mouse is not on OK button, may not happen all the time - bug #6603 - { GID_ISLANDBRAIN, 100, 937, 0, "IconBar", "dispatchEvent", -1, NULL, 58, { WORKAROUND_FAKE, 0 } }, // when using ENTER at the startup menu - bug #5241 - { GID_ISLANDBRAIN, 140, 140, 0, "piece", "init", -1, NULL, 3, { WORKAROUND_FAKE, 1 } }, // first puzzle right at the start, some initialization variable. bnt is done on it, and it should be non-0 - { GID_ISLANDBRAIN, 200, 268, 0, "anElement", "select", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // elements puzzle, gets used before super TextIcon - { GID_JONES, 1, 232, 0, "weekendText", "draw", -1, sig_uninitread_jones_1, 0, { WORKAROUND_FAKE, 0 } }, // jones/cd only - gets called during the game - { GID_JONES, 1, 255, 0, "", "export 0", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // jones/cd only - called when a game ends, temps 13 and 14 - { GID_JONES, 764, 255, 0, "", "export 0", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // jones/ega&vga only - called when the game starts, temps 13 and 14 - //{ GID_KQ5, -1, 0, 0, "", "export 29", -1, NULL, 3, { WORKAROUND_FAKE, 0xf } }, // called when playing harp for the harpies or when aborting dialog in toy shop, is used for kDoAudio - bug #4961 + { GID_CAMELOT, 40, 40, 0, "Rm40", "handleEvent", NULL, 0, { WORKAROUND_FAKE, 0 } }, // when looking at the ground at the pool of Siloam - bug #6401 + { GID_CASTLEBRAIN, 280, 280, 0, "programmer", "dispatchEvent", NULL, 0, { WORKAROUND_FAKE, 0xf } }, // pressing 'q' on the computer screen in the robot room, and closing the help dialog that pops up (bug #5143). Moves the cursor to the view with the ID returned (in this case, the robot hand) + { GID_CNICK_KQ, -1, 0, 1, "Character", "say", NULL, -1, { WORKAROUND_FAKE, 0 } }, // checkers/backgammon, like in hoyle 3 - temps 504 and 505 - bug #6255 + { GID_CNICK_KQ, -1, 700, 0, "gcWindow", "open", NULL, -1, { WORKAROUND_FAKE, 0 } }, // when entering the control menu, like in hoyle 3 + { GID_CNICK_KQ, 300, 303, 0, "theDoubleCube", "", NULL, 5, { WORKAROUND_FAKE, 0 } }, // while playing backgammon with doubling enabled - bug #6426 (same as the theDoubleCube::make workaround for Hoyle 3) + { GID_CNICK_KQ, 300, 303, 0, "theDoubleCube", "", NULL, 9, { WORKAROUND_FAKE, 0 } }, // when accepting a double, while playing backgammon with doubling enabled (same as the theDoubleCube::accept workaround for Hoyle 3) + { GID_CNICK_LAURABOW, -1, 0, 1, "Character", "say", NULL, -1, { WORKAROUND_FAKE, 0 } }, // Yatch, like in hoyle 3 - temps 504 and 505 - bug #6424 + { GID_CNICK_LAURABOW, -1, 700, 0, NULL, "open", NULL, -1, { WORKAROUND_FAKE, 0 } }, // when entering control menu - bug #6423 (same as the gcWindow workaround for Hoyle 3) + { GID_CNICK_LAURABOW,100, 100, 0, NULL, "", NULL, 1, { WORKAROUND_FAKE, 0 } }, // while playing domino - bug #6429 (same as the dominoHand2 workaround for Hoyle 3) + { GID_CNICK_LAURABOW,100, 110, 0, NULL, "doit", NULL, -1, { WORKAROUND_FAKE, 0 } }, // when changing the "Dominoes per hand" setting - bug #6430 + { GID_CNICK_LONGBOW, 0, 0, 0, "RH Budget", "init", NULL, 1, { WORKAROUND_FAKE, 0 } }, // when starting the game + { GID_ECOQUEST, -1, -1, 0, NULL, "doVerb", NULL, 0, { WORKAROUND_FAKE, 0 } }, // almost clicking anywhere triggers this in almost all rooms + { GID_FANMADE, 516, 979, 0, "", "export 0", NULL, 20, { WORKAROUND_FAKE, 0 } }, // Happens in Grotesteing after the logos + { GID_FANMADE, 528, 990, 0, "GDialog", "doit", NULL, 4, { WORKAROUND_FAKE, 0 } }, // Happens in Cascade Quest when closing the glossary - bug #5116 + { GID_FANMADE, 488, 1, 0, "RoomScript", "doit", sig_uninitread_fanmade_1, 1, { WORKAROUND_FAKE, 0 } }, // Happens in Ocean Battle while playing - bug #5335 + { GID_FREDDYPHARKAS, -1, 24, 0, "gcWin", "open", NULL, 5, { WORKAROUND_FAKE, 0xf } }, // is used as priority for game menu + { GID_FREDDYPHARKAS, -1, 31, 0, "quitWin", "open", NULL, 5, { WORKAROUND_FAKE, 0xf } }, // is used as priority for game menu + { GID_FREDDYPHARKAS, 540, 540, 0, "WaverCode", "init", NULL, -1, { WORKAROUND_FAKE, 0 } }, // Gun pratice mini-game - bug #5232 + { GID_GK1, -1, 64950, -1, "Feature", "handleEvent", NULL, 0, { WORKAROUND_FAKE, 0 } }, // sometimes when walk-clicking + { GID_GK2, -1, 11, 0, "", "export 10", NULL, 3, { WORKAROUND_FAKE, 0 } }, // called when the game starts + { GID_GK2, -1, 11, 0, "", "export 10", NULL, 4, { WORKAROUND_FAKE, 0 } }, // called during the game + { GID_HOYLE1, 4, 104, 0, "GinRummyCardList", "calcRuns", NULL, 4, { WORKAROUND_FAKE, 0 } }, // Gin Rummy / right when the game starts + { GID_HOYLE1, 5, 204, 0, "tableau", "checkRuns", NULL, 2, { WORKAROUND_FAKE, 0 } }, // Cribbage / during the game + { GID_HOYLE1, 3, 16, 0, "", "export 0", sig_uninitread_hoyle1_1, 3, { WORKAROUND_FAKE, 0 } }, // Hearts / during the game - bug #5299 + { GID_HOYLE1, -1, 997, 0, "MenuBar", "doit", NULL, 0, { WORKAROUND_FAKE, 0 } }, // When changing game speed settings - bug #5512 + { GID_HOYLE3, -1, 0, 1, "Character", "say", NULL, -1, { WORKAROUND_FAKE, 0 } }, // when starting checkers or dominoes, first time a character says something - temps 504 and 505 + { GID_HOYLE3, -1, 700, 0, "gcWindow", "open", NULL, -1, { WORKAROUND_FAKE, 0 } }, // when entering control menu + { GID_HOYLE3, 100, 100, 0, "dominoHand2", "cue", NULL, 1, { WORKAROUND_FAKE, 0 } }, // while playing domino - bug #5042 + { GID_HOYLE3, 100, 110, 0, "OKButton", "doit", NULL, -1, { WORKAROUND_FAKE, 0 } }, // when changing the "Dominoes per hand" setting - bug #6430 + { GID_HOYLE3, 300, 303, 0, "theDoubleCube", "make", NULL, 5, { WORKAROUND_FAKE, 0 } }, // while playing backgammon with doubling enabled + { GID_HOYLE3, 300, 303, 0, "theDoubleCube", "accept", NULL, 9, { WORKAROUND_FAKE, 0 } }, // when accepting a double, while playing backgammon with doubling enabled + { GID_HOYLE4, -1, 0, 0, NULL, "open", NULL, -1, { WORKAROUND_FAKE, 0 } }, // when selecting "Control" from the menu (temp vars 0-3) - bug #5132 + { GID_HOYLE4, 910, 18, 0, NULL, "init", NULL, 0, { WORKAROUND_FAKE, 0 } }, // during tutorial - bug #5213 + { GID_HOYLE4, 910, 910, 0, NULL, "setup", NULL, 3, { WORKAROUND_FAKE, 0 } }, // when selecting "Tutorial" from the main menu - bug #5132 + { GID_HOYLE4, 700, 700, 1, "BridgeHand", "calcQTS", NULL, 3, { WORKAROUND_FAKE, 0 } }, // when placing a bid in bridge (always) + { GID_HOYLE4, 700, 710, 1, "BridgeStrategyPlay", "checkSplitTops", NULL, 10, { WORKAROUND_FAKE, 0 } }, // while playing bridge, objects LeadReturn_Trump, SecondSeat_Trump, ThirdSeat_Trump and others - bug #5794 + { GID_HOYLE4, 700, -1, 1, "BridgeDefense", "think", NULL, -1, { WORKAROUND_FAKE, 0 } }, // sometimes while playing bridge, temp var 3, 17 and others, objects LeadReturn_Trump, ThirdSeat_Trump and others + { GID_HOYLE4, 700, 730, 1, "BridgeDefense", "beatTheirBest", NULL, 3, { WORKAROUND_FAKE, 0 } }, // rarely while playing bridge + { GID_HOYLE4, 700, -1, 1, "Code", "doit", NULL, -1, { WORKAROUND_FAKE, 0 } }, // when placing a bid in bridge (always), temp var 11, 24, 27, 46, 75, objects compete_tree, compwe_tree, other1_tree, b1 - bugs #5663 and #5794 + { GID_HOYLE4, 700, 921, 0, "Print", "addEdit", NULL, 0, { WORKAROUND_FAKE, 118 } }, // when saving the game (may also occur in other situations) - bug #6601, bug #6614 + { GID_HOYLE4, 700, 921, 0, "Print", "addEdit", NULL, 1, { WORKAROUND_FAKE, 1 } }, // see above, Text-control saves its coordinates to temp[0] and temp[1], Edit-control adjusts to those uninitialized temps, who by accident were left over from the Text-control + { GID_HOYLE4, 300, 300, 0, "", "export 2", sig_uninitread_hoyle4_1, 0, { WORKAROUND_FAKE, 0 } }, // after passing around cards in hearts + { GID_HOYLE4, 400, 400, 1, "GinHand", "calcRuns", NULL, 4, { WORKAROUND_FAKE, 0 } }, // sometimes while playing Gin Rummy (e.g. when knocking and placing a card) - bug #5665 + { GID_HOYLE4, 500, 17, 1, "Character", "say", NULL, 504, { WORKAROUND_FAKE, 0 } }, // sometimes while playing Cribbage (e.g. when the opponent says "Last Card") - bug #5662 + { GID_HOYLE4, 800, 870, 0, "EuchreStrategy", "thinkLead", NULL, 0, { WORKAROUND_FAKE, 0 } }, // while playing Euchre, happens at least on 2nd or 3rd turn - bug #6602 + { GID_HOYLE4, -1, 937, 0, "IconBar", "dispatchEvent", NULL, 408, { WORKAROUND_FAKE, 0 } }, // pressing ENTER on scoreboard while mouse is not on OK button, may not happen all the time - bug #6603 + { GID_ISLANDBRAIN, 100, 937, 0, "IconBar", "dispatchEvent", NULL, 58, { WORKAROUND_FAKE, 0 } }, // when using ENTER at the startup menu - bug #5241 + { GID_ISLANDBRAIN, 140, 140, 0, "piece", "init", NULL, 3, { WORKAROUND_FAKE, 1 } }, // first puzzle right at the start, some initialization variable. bnt is done on it, and it should be non-0 + { GID_ISLANDBRAIN, 200, 268, 0, "anElement", "select", NULL, 0, { WORKAROUND_FAKE, 0 } }, // elements puzzle, gets used before super TextIcon + { GID_JONES, 1, 232, 0, "weekendText", "draw", sig_uninitread_jones_1, 0, { WORKAROUND_FAKE, 0 } }, // jones/cd only - gets called during the game + { GID_JONES, 1, 255, 0, "", "export 0", NULL, -1, { WORKAROUND_FAKE, 0 } }, // jones/cd only - called when a game ends, temps 13 and 14 + { GID_JONES, 764, 255, 0, "", "export 0", NULL, -1, { WORKAROUND_FAKE, 0 } }, // jones/ega&vga only - called when the game starts, temps 13 and 14 + //{ GID_KQ5, -1, 0, 0, "", "export 29", NULL, 3, { WORKAROUND_FAKE, 0xf } }, // called when playing harp for the harpies or when aborting dialog in toy shop, is used for kDoAudio - bug #4961 // ^^ shouldn't be needed anymore, we got a script patch instead (kq5PatchCdHarpyVolume) - { GID_KQ5, 25, 25, 0, "rm025", "doit", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // inside witch forest, when going to the room where the walking rock is - { GID_KQ5, 55, 55, 0, "helpScript", "doit", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // when giving the tambourine to the monster in the labyrinth (only happens at one of the locations) - bug #5198 - { GID_KQ5, -1, 755, 0, "gcWin", "open", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // when entering control menu in the FM-Towns version - { GID_KQ6, -1, 30, 0, "rats", "changeState", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // rats in the catacombs (temps 1 - 5) - bugs #4958, #4998, #5017 - { GID_KQ6, 210, 210, 0, "rm210", "scriptCheck", -1, NULL, 0, { WORKAROUND_FAKE, 1 } }, // using inventory in that room - bug #4953 - { GID_KQ6, 500, 500, 0, "rm500", "init", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // going to island of the beast - { GID_KQ6, 520, 520, 0, "rm520", "init", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // going to boiling water trap on beast isle - { GID_KQ6, -1, 903, 0, "controlWin", "open", -1, NULL, 4, { WORKAROUND_FAKE, 0 } }, // when opening the controls window (save, load etc) - { GID_KQ6, -1, 907, 0, "tomato", "doVerb", -1, NULL, 2, { WORKAROUND_FAKE, 0 } }, // when looking at the rotten tomato in the inventory - bug #5331 - { GID_KQ6, -1, 928, 0, NULL, "startText", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // gets caused by Text+Audio support (see script patcher) - { GID_KQ7, -1, 64996, 0, "User", "handleEvent", -1, NULL, 1, { WORKAROUND_FAKE, 0 } }, // called when pushing a keyboard key - { GID_LAURABOW, 37, 0, 0, "CB1", "doit", -1, NULL, 1, { WORKAROUND_FAKE, 0 } }, // when going up the stairs - bug #5084 - { GID_LAURABOW, -1, 967, 0, "myIcon", "cycle", -1, NULL, 1, { WORKAROUND_FAKE, 0 } }, // having any portrait conversation coming up - initial bug #4971 - { GID_LAURABOW2, -1, 24, 0, "gcWin", "open", -1, NULL, 5, { WORKAROUND_FAKE, 0xf } }, // is used as priority for game menu - { GID_LAURABOW2, -1, 21, 0, "dropCluesCode", "doit", -1, NULL, 1, { WORKAROUND_FAKE, 0x7fff } }, // when asking some questions (e.g. the reporter about the burglary, or the policeman about Ziggy). Must be big, as the game scripts perform lt on it and start deleting journal entries - bugs #4979, #5026 - { GID_LAURABOW2, -1, 90, 1, "MuseumActor", "init", -1, NULL, 6, { WORKAROUND_FAKE, 0 } }, // Random actors in museum - bug #5197 - { GID_LAURABOW2, 240, 240, 0, "sSteveAnimates", "changeState", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // Steve Dorian's idle animation at the docks - bug #5028 - { GID_LAURABOW2, -1, 928, 0, NULL, "startText", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // gets caused by Text+Audio support (see script patcher) - { GID_LONGBOW, -1, 0, 0, "Longbow", "restart", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // When canceling a restart game - bug #5244 - { GID_LONGBOW, -1, 213, 0, "clear", "handleEvent", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // When giving an answer using the druid hand sign code in any room - { GID_LONGBOW, -1, 213, 0, "letter", "handleEvent",-1,sig_uninitread_longbow_1, 1, { WORKAROUND_FAKE, 0 } }, // When using the druid hand sign code in any room - bug #5035 - { GID_LSL1, 250, 250, 0, "increase", "handleEvent", -1, NULL, 2, { WORKAROUND_FAKE, 0 } }, // casino, playing game, increasing bet - { GID_LSL1, 720, 720, 0, "rm720", "init", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // age check room - { GID_LSL2, 38, 38, 0, "cloudScript", "changeState", -1, NULL, 1, { WORKAROUND_FAKE, 0 } }, // entering the room in the middle deck of the ship - bug #5034 - { GID_LSL3, 340, 340, 0, "ComicScript", "changeState", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // right after entering the 3 ethnic groups inside comedy club (temps 200, 201, 202, 203) - { GID_LSL3, -1, 997, 0, "TheMenuBar", "handleEvent", -1, NULL, 1, { WORKAROUND_FAKE, 0xf } }, // when setting volume the first time, this temp is used to set volume on entry (normally it would have been initialized to 's') - { GID_LSL6, 820, 82, 0, "", "export 0", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // when touching the electric fence - bug #5103 - { GID_LSL6, -1, 85, 0, "washcloth", "doVerb", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // washcloth in inventory - { GID_LSL6, -1, 928, -1, "Narrator", "startText", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // used by various objects that are even translated in foreign versions, that's why we use the base-class - { GID_LSL6HIRES, 0, 85, 0, "LL6Inv", "init", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // on startup - { GID_LSL6HIRES, -1, 64950, 1, "Feature", "handleEvent", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // at least when entering swimming pool area - { GID_LSL6HIRES, -1, 64964, 0, "DPath", "init", -1, NULL, 1, { WORKAROUND_FAKE, 0 } }, // during the game - { GID_MOTHERGOOSE256, -1, 0, 0, "MG", "doit", -1, NULL, 5, { WORKAROUND_FAKE, 0 } }, // SCI1.1: When moving the cursor all the way to the left during the game - bug #5224 - { GID_MOTHERGOOSE256, -1, 992, 0, "AIPath", "init", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // Happens in the demo and full version. In the demo, it happens when walking two screens from mother goose's house to the north. In the full version, it happens in rooms 7 and 23 - bug #5269 - { GID_MOTHERGOOSE256, 90, 90, 0, "introScript", "changeState", -1, NULL, 65, { WORKAROUND_FAKE, 0 } }, // SCI1(CD): At the very end, after the game is completed and restarted - bug #5626 - { GID_MOTHERGOOSE256, 94, 94, 0, "sunrise", "changeState", -1, NULL, 367, { WORKAROUND_FAKE, 0 } }, // At the very end, after the game is completed - bug #5294 - { GID_MOTHERGOOSEHIRES,-1,64950, 1, "Feature", "handleEvent", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // right when clicking on a child at the start and probably also later - { GID_MOTHERGOOSEHIRES,-1,64950, 1, "View", "handleEvent", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // see above - { GID_PEPPER, -1, 894, 0, "Package", "doVerb", -1, NULL, 3, { WORKAROUND_FAKE, 0 } }, // using the hand on the book in the inventory - bug #5154 - { GID_PEPPER, 150, 928, 0, "Narrator", "startText", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // happens during the non-interactive demo of Pepper - { GID_PQ4, -1, 25, 0, "iconToggle", "select", -1, NULL, 1, { WORKAROUND_FAKE, 0 } }, // when toggling the icon bar to auto-hide or not - { GID_PQSWAT, -1, 64950, 0, "View", "handleEvent", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // Using the menu in the beginning - { GID_QFG1, -1, 210, 0, "Encounter", "init", -1, sig_uninitread_qfg1_1, 0, { WORKAROUND_FAKE, 0 } }, // qfg1/hq1: going to the brigands hideout - { GID_QFG1VGA, 16, 16, 0, "lassoFailed", "changeState", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // qfg1vga: casting the "fetch" spell in the screen with the flowers, temps 0 and 1 - bug #5309 - { GID_QFG1VGA, -1, 210, 0, "Encounter", "init", -1, sig_uninitread_qfg1vga_1, 0, { WORKAROUND_FAKE, 0 } }, // qfg1vga: going to the brigands hideout - bug #5515 - { GID_QFG2, -1, 71, 0, "theInvSheet", "doit", -1, NULL, 1, { WORKAROUND_FAKE, 0 } }, // accessing the inventory - { GID_QFG2, -1, 701, -1, "Alley", "at", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // when walking inside the alleys in the town - bug #5019 & #5106 - { GID_QFG2, -1, 990, 0, "Restore", "doit", -1, NULL, 364, { WORKAROUND_FAKE, 0 } }, // when pressing enter in restore dialog w/o any saved games present - { GID_QFG2, 260, 260, 0, "abdulS", "changeState",-1, sig_uninitread_qfg2_1, -1, { WORKAROUND_FAKE, 0 } }, // During the thief's first mission (in the house), just before Abdul is about to enter the house (where you have to hide in the wardrobe), bug #5153, temps 1 and 2 - { GID_QFG2, 260, 260, 0, "jabbarS", "changeState",-1, sig_uninitread_qfg2_1, -1, { WORKAROUND_FAKE, 0 } }, // During the thief's first mission (in the house), just before Jabbar is about to enter the house (where you have to hide in the wardrobe), bug #5164, temps 1 and 2 - { GID_QFG2, 500, 500, 0, "lightNextCandleS", "changeState", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // Inside the last room, while Ad Avis performs the ritual to summon the genie - bug #5566 - { GID_QFG2, -1, 700, 0, NULL, "showSign", -1, NULL, 10, { WORKAROUND_FAKE, 0 } }, // Occurs sometimes when reading a sign in Raseir, Shapeir et al - bugs #5627, #5635 - { GID_QFG3, 510, 510, 0, "awardPrize", "changeState", -1, NULL, 0, { WORKAROUND_FAKE, 1 } }, // Simbani warrior challenge, after throwing the spears and retrieving the ring - bug #5277. Must be non-zero, otherwise the prize is awarded twice - bug #6160 - { GID_QFG3, 140, 140, 0, "rm140", "init", -1, sig_uninitread_qfg3_1, 0, { WORKAROUND_FAKE, 0 } }, // when importing a character and selecting the previous profession - bug #5163 - { GID_QFG3, 330, 330, -1, "Teller", "doChild", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // when talking to King Rajah about "Rajah" (bug #5033, temp 1) or "Tarna" (temp 0), or when clicking on yourself and saying "Greet" (bug #5148, temp 1) - { GID_QFG3, 700, 700, -1, "monsterIsDead", "changeState", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // in the jungle, after winning any fight, bug #5169 - { GID_QFG3, 470, 470, -1, "rm470", "notify", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // closing the character screen in the Simbani village in the room with the bridge, bug #5165 - { GID_QFG3, 490, 490, -1, "computersMove", "changeState", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // when finishing awari game, bug #5167 - { GID_QFG3, 490, 490, -1, "computersMove", "changeState",-1, sig_uninitread_qfg3_2, 4, { WORKAROUND_FAKE, 0 } }, // also when finishing awari game - { GID_QFG3, 851, 32, -1, "ProjObj", "doit", -1, NULL, 1, { WORKAROUND_FAKE, 0 } }, // near the end, when throwing the spear of death, bug #5282 - { GID_QFG4, -1, 15, -1, "charInitScreen", "dispatchEvent", -1, NULL, 5, { WORKAROUND_FAKE, 0 } }, // floppy version, when viewing the character screen - { GID_QFG4, -1, 64917, -1, "controlPlane", "setBitmap", -1, NULL, 3, { WORKAROUND_FAKE, 0 } }, // floppy version, when entering the game menu - { GID_QFG4, -1, 64917, -1, "Plane", "setBitmap", -1, NULL, 3, { WORKAROUND_FAKE, 0 } }, // floppy version, happens sometimes in fight scenes - { GID_QFG4, 520, 64950, 0, "fLake2", "handleEvent", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // CD version, at the lake, when meeting the Rusalka and attempting to leave - { GID_QFG4, 800, 64950, 0, "View", "handleEvent", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // CD version, in the room with the spider pillar, when climbing on the pillar - { GID_RAMA, 12, 64950, -1, "InterfaceFeature", "handleEvent", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // Demo, right when it starts - { GID_RAMA, 12, 64950, -1, "hiliteOptText", "handleEvent", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // Demo, right when it starts - { GID_RAMA, 12, 64950, -1, "View", "handleEvent", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // Demo, right when it starts - { GID_SHIVERS, -1, 952, 0, "SoundManager", "stop", -1, NULL, 2, { WORKAROUND_FAKE, 0 } }, // Just after Sierra logo - { GID_SHIVERS, -1, 64950, 0, "Feature", "handleEvent", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // When clicking on the locked door at the beginning - { GID_SHIVERS, -1, 64950, 0, "View", "handleEvent", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // When clicking on the gargoyle eye at the beginning - { GID_SHIVERS, 20311, 64964, 0, "DPath", "init", -1, NULL, 1, { WORKAROUND_FAKE, 0 } }, // Just after door puzzle is solved and the metal balls start to roll - { GID_SHIVERS, 29260, 29260, 0, "spMars", "handleEvent", -1, NULL, 4, { WORKAROUND_FAKE, 0 } }, // When clicking mars after seeing fortune to align earth etc... - { GID_SHIVERS, 29260, 29260, 0, "spVenus", "handleEvent", -1, NULL, 4, { WORKAROUND_FAKE, 0 } }, // When clicking venus after seeing fortune to align earth etc... - { GID_SQ1, 103, 103, 0, "hand", "internalEvent", -1, NULL, -1, { WORKAROUND_FAKE, 0 } }, // Spanish (and maybe early versions?) only: when moving cursor over input pad, temps 1 and 2 - { GID_SQ1, -1, 703, 0, "", "export 1", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // sub that's called from several objects while on sarien battle cruiser - { GID_SQ1, -1, 703, 0, "firePulsar", "changeState",-1, sig_uninitread_sq1_1, 0, { WORKAROUND_FAKE, 0 } }, // export 1, but called locally (when shooting at aliens) - { GID_SQ4, -1, 398, 0, "showBox", "changeState", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // CD: called when rummaging in Software Excess bargain bin - { GID_SQ4, -1, 928, -1, "Narrator", "startText", -1, NULL, 1000, { WORKAROUND_FAKE, 1 } }, // CD: happens in the options dialog and in-game when speech and subtitles are used simultaneously - { GID_SQ4, -1, 708, -1, "exitBut", "doVerb", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // Floppy: happens, when looking at the "close" button in the sq4 hintbook - bug #6447 - { GID_SQ4, -1, 708, -1, "", "doVerb", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // Floppy: happens, when looking at the "close" button... in Russian version - bug #5573 - { GID_SQ4, -1, 708, -1, "prevBut", "doVerb", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // Floppy: happens, when looking at the "previous" button in the sq4 hintbook - bug #6447 - { GID_SQ4, -1, 708, -1, "\xA8\xE6\xE3 \xAD\xA0\xA7\xA0\xA4.", "doVerb", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // Floppy: happens, when looking at the "previous" button... in Russian version - bug #5573 - { GID_SQ4, -1, 708, -1, "nextBut", "doVerb", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // Floppy: happens, when looking at the "next" button in the sq4 hintbook - bug #6447 - { GID_SQ4, -1, 708, -1, ".", "doVerb", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // Floppy: happens, when looking at the "next" button... in Russian version - bug #5573 - { GID_SQ5, 201, 201, 0, "buttonPanel", "doVerb", -1, NULL, 0, { WORKAROUND_FAKE, 1 } }, // when looking at the orange or red button - bug #5112 - { GID_SQ6, -1, 0, 0, "SQ6", "init", -1, NULL, 2, { WORKAROUND_FAKE, 0 } }, // Demo and full version: called when the game starts (demo: room 0, full: room 100) - { GID_SQ6, -1, 64950, -1, "Feature", "handleEvent", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // called when pressing "Start game" in the main menu, when entering the Orion's Belt bar (room 300), and perhaps other places - { GID_SQ6, -1, 64964, 0, "DPath", "init", -1, NULL, 1, { WORKAROUND_FAKE, 0 } }, // during the game - { GID_TORIN, -1, 64017, 0, "oFlags", "clear", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // entering Torin's home in the French version - SCI_WORKAROUNDENTRY_TERMINATOR -}; - -// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround + { GID_KQ5, 25, 25, 0, "rm025", "doit", NULL, 0, { WORKAROUND_FAKE, 0 } }, // inside witch forest, when going to the room where the walking rock is + { GID_KQ5, 55, 55, 0, "helpScript", "doit", NULL, 0, { WORKAROUND_FAKE, 0 } }, // when giving the tambourine to the monster in the labyrinth (only happens at one of the locations) - bug #5198 + { GID_KQ5, -1, 755, 0, "gcWin", "open", NULL, -1, { WORKAROUND_FAKE, 0 } }, // when entering control menu in the FM-Towns version + { GID_KQ6, -1, 30, 0, "rats", "changeState", NULL, -1, { WORKAROUND_FAKE, 0 } }, // rats in the catacombs (temps 1 - 5) - bugs #4958, #4998, #5017 + { GID_KQ6, 210, 210, 0, "rm210", "scriptCheck", NULL, 0, { WORKAROUND_FAKE, 1 } }, // using inventory in that room - bug #4953 + { GID_KQ6, 500, 500, 0, "rm500", "init", NULL, 0, { WORKAROUND_FAKE, 0 } }, // going to island of the beast + { GID_KQ6, 520, 520, 0, "rm520", "init", NULL, 0, { WORKAROUND_FAKE, 0 } }, // going to boiling water trap on beast isle + { GID_KQ6, -1, 903, 0, "controlWin", "open", NULL, 4, { WORKAROUND_FAKE, 0 } }, // when opening the controls window (save, load etc) + { GID_KQ6, -1, 907, 0, "tomato", "doVerb", NULL, 2, { WORKAROUND_FAKE, 0 } }, // when looking at the rotten tomato in the inventory - bug #5331 + { GID_KQ6, -1, 928, 0, NULL, "startText", NULL, 0, { WORKAROUND_FAKE, 0 } }, // gets caused by Text+Audio support (see script patcher) + { GID_KQ7, -1, 64996, 0, "User", "handleEvent", NULL, 1, { WORKAROUND_FAKE, 0 } }, // called when pushing a keyboard key + { GID_LAURABOW, 37, 0, 0, "CB1", "doit", NULL, 1, { WORKAROUND_FAKE, 0 } }, // when going up the stairs - bug #5084 + { GID_LAURABOW, -1, 967, 0, "myIcon", "cycle", NULL, 1, { WORKAROUND_FAKE, 0 } }, // having any portrait conversation coming up - initial bug #4971 + { GID_LAURABOW2, -1, 24, 0, "gcWin", "open", NULL, 5, { WORKAROUND_FAKE, 0xf } }, // is used as priority for game menu + { GID_LAURABOW2, -1, 21, 0, "dropCluesCode", "doit", NULL, 1, { WORKAROUND_FAKE, 0x7fff } }, // when asking some questions (e.g. the reporter about the burglary, or the policeman about Ziggy). Must be big, as the game scripts perform lt on it and start deleting journal entries - bugs #4979, #5026 + { GID_LAURABOW2, -1, 90, 1, "MuseumActor", "init", NULL, 6, { WORKAROUND_FAKE, 0 } }, // Random actors in museum - bug #5197 + { GID_LAURABOW2, 240, 240, 0, "sSteveAnimates", "changeState", NULL, 0, { WORKAROUND_FAKE, 0 } }, // Steve Dorian's idle animation at the docks - bug #5028 + { GID_LAURABOW2, -1, 928, 0, NULL, "startText", NULL, 0, { WORKAROUND_FAKE, 0 } }, // gets caused by Text+Audio support (see script patcher) + { GID_LONGBOW, -1, 0, 0, "Longbow", "restart", NULL, 0, { WORKAROUND_FAKE, 0 } }, // When canceling a restart game - bug #5244 + { GID_LONGBOW, -1, 213, 0, "clear", "handleEvent", NULL, 0, { WORKAROUND_FAKE, 0 } }, // When giving an answer using the druid hand sign code in any room + { GID_LONGBOW, -1, 213, 0, "letter", "handleEvent", sig_uninitread_longbow_1, 1, { WORKAROUND_FAKE, 0 } }, // When using the druid hand sign code in any room - bug #5035 + { GID_LSL1, 250, 250, 0, "increase", "handleEvent", NULL, 2, { WORKAROUND_FAKE, 0 } }, // casino, playing game, increasing bet + { GID_LSL1, 720, 720, 0, "rm720", "init", NULL, 0, { WORKAROUND_FAKE, 0 } }, // age check room + { GID_LSL2, 38, 38, 0, "cloudScript", "changeState", NULL, 1, { WORKAROUND_FAKE, 0 } }, // entering the room in the middle deck of the ship - bug #5034 + { GID_LSL3, 340, 340, 0, "ComicScript", "changeState", NULL, -1, { WORKAROUND_FAKE, 0 } }, // right after entering the 3 ethnic groups inside comedy club (temps 200, 201, 202, 203) + { GID_LSL3, -1, 997, 0, "TheMenuBar", "handleEvent", NULL, 1, { WORKAROUND_FAKE, 0xf } }, // when setting volume the first time, this temp is used to set volume on entry (normally it would have been initialized to 's') + { GID_LSL6, 820, 82, 0, "", "export 0", NULL, -1, { WORKAROUND_FAKE, 0 } }, // when touching the electric fence - bug #5103 + { GID_LSL6, -1, 85, 0, "washcloth", "doVerb", NULL, 0, { WORKAROUND_FAKE, 0 } }, // washcloth in inventory + { GID_LSL6, -1, 928, -1, "Narrator", "startText", NULL, 0, { WORKAROUND_FAKE, 0 } }, // used by various objects that are even translated in foreign versions, that's why we use the base-class + { GID_LSL6HIRES, 0, 85, 0, "LL6Inv", "init", NULL, 0, { WORKAROUND_FAKE, 0 } }, // on startup + { GID_LSL6HIRES, -1, 64950, 1, "Feature", "handleEvent", NULL, 0, { WORKAROUND_FAKE, 0 } }, // at least when entering swimming pool area + { GID_LSL6HIRES, -1, 64964, 0, "DPath", "init", NULL, 1, { WORKAROUND_FAKE, 0 } }, // during the game + { GID_MOTHERGOOSE256, -1, 0, 0, "MG", "doit", NULL, 5, { WORKAROUND_FAKE, 0 } }, // SCI1.1: When moving the cursor all the way to the left during the game - bug #5224 + { GID_MOTHERGOOSE256, -1, 992, 0, "AIPath", "init", NULL, 0, { WORKAROUND_FAKE, 0 } }, // Happens in the demo and full version. In the demo, it happens when walking two screens from mother goose's house to the north. In the full version, it happens in rooms 7 and 23 - bug #5269 + { GID_MOTHERGOOSE256, 90, 90, 0, "introScript", "changeState", NULL, 65, { WORKAROUND_FAKE, 0 } }, // SCI1(CD): At the very end, after the game is completed and restarted - bug #5626 + { GID_MOTHERGOOSE256, 94, 94, 0, "sunrise", "changeState", NULL, 367, { WORKAROUND_FAKE, 0 } }, // At the very end, after the game is completed - bug #5294 + { GID_MOTHERGOOSEHIRES,-1,64950, 1, "Feature", "handleEvent", NULL, 0, { WORKAROUND_FAKE, 0 } }, // right when clicking on a child at the start and probably also later + { GID_MOTHERGOOSEHIRES,-1,64950, 1, "View", "handleEvent", NULL, 0, { WORKAROUND_FAKE, 0 } }, // see above + { GID_PEPPER, -1, 894, 0, "Package", "doVerb", NULL, 3, { WORKAROUND_FAKE, 0 } }, // using the hand on the book in the inventory - bug #5154 + { GID_PEPPER, 150, 928, 0, "Narrator", "startText", NULL, 0, { WORKAROUND_FAKE, 0 } }, // happens during the non-interactive demo of Pepper + { GID_PQ4, -1, 25, 0, "iconToggle", "select", NULL, 1, { WORKAROUND_FAKE, 0 } }, // when toggling the icon bar to auto-hide or not + { GID_PQSWAT, -1, 64950, 0, "View", "handleEvent", NULL, 0, { WORKAROUND_FAKE, 0 } }, // Using the menu in the beginning + { GID_QFG1, -1, 210, 0, "Encounter", "init", sig_uninitread_qfg1_1, 0, { WORKAROUND_FAKE, 0 } }, // qfg1/hq1: going to the brigands hideout + { GID_QFG1VGA, 16, 16, 0, "lassoFailed", "changeState", NULL, -1, { WORKAROUND_FAKE, 0 } }, // qfg1vga: casting the "fetch" spell in the screen with the flowers, temps 0 and 1 - bug #5309 + { GID_QFG1VGA, -1, 210, 0, "Encounter", "init", sig_uninitread_qfg1vga_1, 0, { WORKAROUND_FAKE, 0 } }, // qfg1vga: going to the brigands hideout - bug #5515 + { GID_QFG2, -1, 71, 0, "theInvSheet", "doit", NULL, 1, { WORKAROUND_FAKE, 0 } }, // accessing the inventory + { GID_QFG2, -1, 701, -1, "Alley", "at", NULL, 0, { WORKAROUND_FAKE, 0 } }, // when walking inside the alleys in the town - bug #5019 & #5106 + { GID_QFG2, -1, 990, 0, "Restore", "doit", NULL, 364, { WORKAROUND_FAKE, 0 } }, // when pressing enter in restore dialog w/o any saved games present + { GID_QFG2, 260, 260, 0, "abdulS", "changeState", sig_uninitread_qfg2_1, -1, { WORKAROUND_FAKE, 0 } }, // During the thief's first mission (in the house), just before Abdul is about to enter the house (where you have to hide in the wardrobe), bug #5153, temps 1 and 2 + { GID_QFG2, 260, 260, 0, "jabbarS", "changeState", sig_uninitread_qfg2_1, -1, { WORKAROUND_FAKE, 0 } }, // During the thief's first mission (in the house), just before Jabbar is about to enter the house (where you have to hide in the wardrobe), bug #5164, temps 1 and 2 + { GID_QFG2, 500, 500, 0, "lightNextCandleS", "changeState", NULL, -1, { WORKAROUND_FAKE, 0 } }, // Inside the last room, while Ad Avis performs the ritual to summon the genie - bug #5566 + { GID_QFG2, -1, 700, 0, NULL, "showSign", NULL, 10, { WORKAROUND_FAKE, 0 } }, // Occurs sometimes when reading a sign in Raseir, Shapeir et al - bugs #5627, #5635 + { GID_QFG3, 510, 510, 0, "awardPrize", "changeState", NULL, 0, { WORKAROUND_FAKE, 1 } }, // Simbani warrior challenge, after throwing the spears and retrieving the ring - bug #5277. Must be non-zero, otherwise the prize is awarded twice - bug #6160 + { GID_QFG3, 140, 140, 0, "rm140", "init", sig_uninitread_qfg3_1, 0, { WORKAROUND_FAKE, 0 } }, // when importing a character and selecting the previous profession - bug #5163 + { GID_QFG3, 330, 330, -1, "Teller", "doChild", NULL, -1, { WORKAROUND_FAKE, 0 } }, // when talking to King Rajah about "Rajah" (bug #5033, temp 1) or "Tarna" (temp 0), or when clicking on yourself and saying "Greet" (bug #5148, temp 1) + { GID_QFG3, 700, 700, -1, "monsterIsDead", "changeState", NULL, 0, { WORKAROUND_FAKE, 0 } }, // in the jungle, after winning any fight, bug #5169 + { GID_QFG3, 470, 470, -1, "rm470", "notify", NULL, 0, { WORKAROUND_FAKE, 0 } }, // closing the character screen in the Simbani village in the room with the bridge, bug #5165 + { GID_QFG3, 490, 490, -1, "computersMove", "changeState", NULL, 0, { WORKAROUND_FAKE, 0 } }, // when finishing awari game, bug #5167 + { GID_QFG3, 490, 490, -1, "computersMove", "changeState", sig_uninitread_qfg3_2, 4, { WORKAROUND_FAKE, 0 } }, // also when finishing awari game + { GID_QFG3, 851, 32, -1, "ProjObj", "doit", NULL, 1, { WORKAROUND_FAKE, 0 } }, // near the end, when throwing the spear of death, bug #5282 + { GID_QFG4, -1, 15, -1, "charInitScreen", "dispatchEvent", NULL, 5, { WORKAROUND_FAKE, 0 } }, // floppy version, when viewing the character screen + { GID_QFG4, -1, 64917, -1, "controlPlane", "setBitmap", NULL, 3, { WORKAROUND_FAKE, 0 } }, // floppy version, when entering the game menu + { GID_QFG4, -1, 64917, -1, "Plane", "setBitmap", NULL, 3, { WORKAROUND_FAKE, 0 } }, // floppy version, happens sometimes in fight scenes + { GID_QFG4, 520, 64950, 0, "fLake2", "handleEvent", NULL, 0, { WORKAROUND_FAKE, 0 } }, // CD version, at the lake, when meeting the Rusalka and attempting to leave + { GID_QFG4, 800, 64950, 0, "View", "handleEvent", NULL, 0, { WORKAROUND_FAKE, 0 } }, // CD version, in the room with the spider pillar, when climbing on the pillar + { GID_RAMA, 12, 64950, -1, "InterfaceFeature", "handleEvent", NULL, 0, { WORKAROUND_FAKE, 0 } }, // Demo, right when it starts + { GID_RAMA, 12, 64950, -1, "hiliteOptText", "handleEvent", NULL, 0, { WORKAROUND_FAKE, 0 } }, // Demo, right when it starts + { GID_RAMA, 12, 64950, -1, "View", "handleEvent", NULL, 0, { WORKAROUND_FAKE, 0 } }, // Demo, right when it starts + { GID_SHIVERS, -1, 952, 0, "SoundManager", "stop", NULL, 2, { WORKAROUND_FAKE, 0 } }, // Just after Sierra logo + { GID_SHIVERS, -1, 64950, 0, "Feature", "handleEvent", NULL, 0, { WORKAROUND_FAKE, 0 } }, // When clicking on the locked door at the beginning + { GID_SHIVERS, -1, 64950, 0, "View", "handleEvent", NULL, 0, { WORKAROUND_FAKE, 0 } }, // When clicking on the gargoyle eye at the beginning + { GID_SHIVERS, 20311, 64964, 0, "DPath", "init", NULL, 1, { WORKAROUND_FAKE, 0 } }, // Just after door puzzle is solved and the metal balls start to roll + { GID_SHIVERS, 29260, 29260, 0, "spMars", "handleEvent", NULL, 4, { WORKAROUND_FAKE, 0 } }, // When clicking mars after seeing fortune to align earth etc... + { GID_SHIVERS, 29260, 29260, 0, "spVenus", "handleEvent", NULL, 4, { WORKAROUND_FAKE, 0 } }, // When clicking venus after seeing fortune to align earth etc... + { GID_SQ1, 103, 103, 0, "hand", "internalEvent", NULL, -1, { WORKAROUND_FAKE, 0 } }, // Spanish (and maybe early versions?) only: when moving cursor over input pad, temps 1 and 2 + { GID_SQ1, -1, 703, 0, "", "export 1", NULL, 0, { WORKAROUND_FAKE, 0 } }, // sub that's called from several objects while on sarien battle cruiser + { GID_SQ1, -1, 703, 0, "firePulsar", "changeState", sig_uninitread_sq1_1, 0, { WORKAROUND_FAKE, 0 } }, // export 1, but called locally (when shooting at aliens) + { GID_SQ4, -1, 398, 0, "showBox", "changeState", NULL, 0, { WORKAROUND_FAKE, 0 } }, // CD: called when rummaging in Software Excess bargain bin + { GID_SQ4, -1, 928, -1, "Narrator", "startText", NULL, 1000, { WORKAROUND_FAKE, 1 } }, // CD: happens in the options dialog and in-game when speech and subtitles are used simultaneously + { GID_SQ4, -1, 708, -1, "exitBut", "doVerb", NULL, 0, { WORKAROUND_FAKE, 0 } }, // Floppy: happens, when looking at the "close" button in the sq4 hintbook - bug #6447 + { GID_SQ4, -1, 708, -1, "", "doVerb", NULL, 0, { WORKAROUND_FAKE, 0 } }, // Floppy: happens, when looking at the "close" button... in Russian version - bug #5573 + { GID_SQ4, -1, 708, -1, "prevBut", "doVerb", NULL, 0, { WORKAROUND_FAKE, 0 } }, // Floppy: happens, when looking at the "previous" button in the sq4 hintbook - bug #6447 + { GID_SQ4, -1, 708, -1, "\xA8\xE6\xE3 \xAD\xA0\xA7\xA0\xA4.", "doVerb", NULL, 0, { WORKAROUND_FAKE, 0 } }, // Floppy: happens, when looking at the "previous" button... in Russian version - bug #5573 + { GID_SQ4, -1, 708, -1, "nextBut", "doVerb", NULL, 0, { WORKAROUND_FAKE, 0 } }, // Floppy: happens, when looking at the "next" button in the sq4 hintbook - bug #6447 + { GID_SQ4, -1, 708, -1, ".", "doVerb", NULL, 0, { WORKAROUND_FAKE, 0 } }, // Floppy: happens, when looking at the "next" button... in Russian version - bug #5573 + { GID_SQ5, 201, 201, 0, "buttonPanel", "doVerb", NULL, 0, { WORKAROUND_FAKE, 1 } }, // when looking at the orange or red button - bug #5112 + { GID_SQ6, -1, 0, 0, "SQ6", "init", NULL, 2, { WORKAROUND_FAKE, 0 } }, // Demo and full version: called when the game starts (demo: room 0, full: room 100) + { GID_SQ6, -1, 64950, -1, "Feature", "handleEvent", NULL, 0, { WORKAROUND_FAKE, 0 } }, // called when pressing "Start game" in the main menu, when entering the Orion's Belt bar (room 300), and perhaps other places + { GID_SQ6, -1, 64964, 0, "DPath", "init", NULL, 1, { WORKAROUND_FAKE, 0 } }, // during the game + { GID_TORIN, -1, 64017, 0, "oFlags", "clear", NULL, 0, { WORKAROUND_FAKE, 0 } }, // entering Torin's home in the French version + SCI_WORKAROUNDENTRY_TERMINATOR +}; + +// gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround const SciWorkaroundEntry kAbs_workarounds[] = { - { GID_HOYLE1, 1, 1, 0, "room1", "doit", -1, NULL, 0, { WORKAROUND_FAKE, 0x3e9 } }, // crazy eights - called with objects instead of integers - { GID_HOYLE1, 2, 2, 0, "room2", "doit", -1, NULL, 0, { WORKAROUND_FAKE, 0x3e9 } }, // old maid - called with objects instead of integers - { GID_HOYLE1, 3, 3, 0, "room3", "doit", -1, NULL, 0, { WORKAROUND_FAKE, 0x3e9 } }, // hearts - called with objects instead of integers - { GID_QFG1VGA, -1, -1, 0, NULL, "doit", -1, NULL, 0, { WORKAROUND_FAKE, 0x3e9 } }, // when the game is patched with the NRS patch - { GID_QFG3 , -1, -1, 0, NULL, "doit", -1, NULL, 0, { WORKAROUND_FAKE, 0x3e9 } }, // when the game is patched with the NRS patch - bugs #6042, #6043 + { GID_HOYLE1, 1, 1, 0, "room1", "doit", NULL, 0, { WORKAROUND_FAKE, 0x3e9 } }, // crazy eights - called with objects instead of integers + { GID_HOYLE1, 2, 2, 0, "room2", "doit", NULL, 0, { WORKAROUND_FAKE, 0x3e9 } }, // old maid - called with objects instead of integers + { GID_HOYLE1, 3, 3, 0, "room3", "doit", NULL, 0, { WORKAROUND_FAKE, 0x3e9 } }, // hearts - called with objects instead of integers + { GID_QFG1VGA, -1, -1, 0, NULL, "doit", NULL, 0, { WORKAROUND_FAKE, 0x3e9 } }, // when the game is patched with the NRS patch + { GID_QFG3 , -1, -1, 0, NULL, "doit", NULL, 0, { WORKAROUND_FAKE, 0x3e9 } }, // when the game is patched with the NRS patch - bugs #6042, #6043 SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround +// gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround const SciWorkaroundEntry kCelHigh_workarounds[] = { - { GID_KQ5, -1, 255, 0, "deathIcon", "setSize", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // english floppy: when getting beaten up in the inn and probably more, called with 2nd parameter as object - bug #5049 - { GID_PQ2, -1, 255, 0, "DIcon", "setSize", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // when showing picture within windows, called with 2nd/3rd parameters as objects - { GID_SQ1, 1, 255, 0, "DIcon", "setSize", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // DEMO: Called with 2nd/3rd parameters as objects when clicking on the menu - bug #5012 - { GID_FANMADE, -1, 979, 0, "DIcon", "setSize", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // In The Gem Scenario and perhaps other fanmade games, this is called with 2nd/3rd parameters as objects - bug #5144 + { GID_KQ5, -1, 255, 0, "deathIcon", "setSize", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // english floppy: when getting beaten up in the inn and probably more, called with 2nd parameter as object - bug #5049 + { GID_PQ2, -1, 255, 0, "DIcon", "setSize", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // when showing picture within windows, called with 2nd/3rd parameters as objects + { GID_SQ1, 1, 255, 0, "DIcon", "setSize", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // DEMO: Called with 2nd/3rd parameters as objects when clicking on the menu - bug #5012 + { GID_FANMADE, -1, 979, 0, "DIcon", "setSize", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // In The Gem Scenario and perhaps other fanmade games, this is called with 2nd/3rd parameters as objects - bug #5144 SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround +// gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround const SciWorkaroundEntry kCelWide_workarounds[] = { - { GID_KQ5, -1, 255, 0, "deathIcon", "setSize", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // english floppy: when getting beaten up in the inn and probably more, called with 2nd parameter as object - bug #5049 - { GID_PQ2, -1, 255, 0, "DIcon", "setSize", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // when showing picture within windows, called with 2nd/3rd parameters as objects - { GID_SQ1, 1, 255, 0, "DIcon", "setSize", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // DEMO: Called with 2nd/3rd parameters as objects when clicking on the menu - bug #5012 - { GID_FANMADE, -1, 979, 0, "DIcon", "setSize", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // In The Gem Scenario and perhaps other fanmade games, this is called with 2nd/3rd parameters as objects - bug #5144 + { GID_KQ5, -1, 255, 0, "deathIcon", "setSize", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // english floppy: when getting beaten up in the inn and probably more, called with 2nd parameter as object - bug #5049 + { GID_PQ2, -1, 255, 0, "DIcon", "setSize", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // when showing picture within windows, called with 2nd/3rd parameters as objects + { GID_SQ1, 1, 255, 0, "DIcon", "setSize", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // DEMO: Called with 2nd/3rd parameters as objects when clicking on the menu - bug #5012 + { GID_FANMADE, -1, 979, 0, "DIcon", "setSize", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // In The Gem Scenario and perhaps other fanmade games, this is called with 2nd/3rd parameters as objects - bug #5144 SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround +// gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround const SciWorkaroundEntry kDeleteKey_workarounds[] = { - { GID_HOYLE4, 300, 999, 0, "handleEventList", "delete", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // restarting hearts, while tray is shown - bug #6604 - { GID_HOYLE4, 500, 999, 0, "handleEventList", "delete", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // restarting cribbage, while tray is shown - bug #6604 - { GID_HOYLE4, 975, 999, 0, "handleEventList", "delete", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // going back to gamelist from hearts/cribbage, while tray is shown - bug #6604 + { GID_HOYLE4, 300, 999, 0, "handleEventList", "delete", NULL, 0, { WORKAROUND_IGNORE, 0 } }, // restarting hearts, while tray is shown - bug #6604 + { GID_HOYLE4, 500, 999, 0, "handleEventList", "delete", NULL, 0, { WORKAROUND_IGNORE, 0 } }, // restarting cribbage, while tray is shown - bug #6604 + { GID_HOYLE4, 975, 999, 0, "handleEventList", "delete", NULL, 0, { WORKAROUND_IGNORE, 0 } }, // going back to gamelist from hearts/cribbage, while tray is shown - bug #6604 SCI_WORKAROUNDENTRY_TERMINATOR }; @@ -437,13 +437,13 @@ static const uint16 sig_kDeviceInfo_Fanmade_2[] = { SIG_END }; -// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround +// gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround const SciWorkaroundEntry kDeviceInfo_workarounds[] = { - { GID_FANMADE, -1, 994, 1, "Game", "save", -1, sig_kDeviceInfo_Fanmade_1, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games (SCI Studio), this is called with one parameter for CurDevice LDI 01 variant - { GID_FANMADE, -1, 994, 1, "Game", "save", -1, sig_kDeviceInfo_Fanmade_2, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games (SCI Studio), this is called with one parameter for CurDevice LDI 0001 variant - { GID_FANMADE, -1, 994, 0, "Black", "save", -1, sig_kDeviceInfo_Fanmade_1, 0, { WORKAROUND_IGNORE, 0 } }, // In fanmade games (SCI Studio), this is called with one parameter for CurDevice (Black Cauldron Remake) - { GID_FANMADE, -1, 994, 1, "Game", "restore", -1, sig_kDeviceInfo_Fanmade_1, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games (SCI Studio), this is called with one parameter for CurDevice LDI 01 variant - { GID_FANMADE, -1, 994, 1, "Game", "restore", -1, sig_kDeviceInfo_Fanmade_2, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games (SCI Studio), this is called with one parameter for CurDevice LDI 0001 variant + { GID_FANMADE, -1, 994, 1, "Game", "save", sig_kDeviceInfo_Fanmade_1, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games (SCI Studio), this is called with one parameter for CurDevice LDI 01 variant + { GID_FANMADE, -1, 994, 1, "Game", "save", sig_kDeviceInfo_Fanmade_2, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games (SCI Studio), this is called with one parameter for CurDevice LDI 0001 variant + { GID_FANMADE, -1, 994, 0, "Black", "save", sig_kDeviceInfo_Fanmade_1, 0, { WORKAROUND_IGNORE, 0 } }, // In fanmade games (SCI Studio), this is called with one parameter for CurDevice (Black Cauldron Remake) + { GID_FANMADE, -1, 994, 1, "Game", "restore", sig_kDeviceInfo_Fanmade_1, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games (SCI Studio), this is called with one parameter for CurDevice LDI 01 variant + { GID_FANMADE, -1, 994, 1, "Game", "restore", sig_kDeviceInfo_Fanmade_2, 0, { WORKAROUND_STILLCALL, 0 } }, // In fanmade games (SCI Studio), this is called with one parameter for CurDevice LDI 0001 variant SCI_WORKAROUNDENTRY_TERMINATOR }; @@ -478,69 +478,69 @@ static const uint16 sig_kDisplay_sq4_1[] = { SIG_END }; -// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround +// gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround const SciWorkaroundEntry kDisplay_workarounds[] = { - { GID_ISLANDBRAIN, 300, 300, 0, "geneDude", "show", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // when looking at the gene explanation chart - a parameter is an object - { GID_LONGBOW, 95, 95, 0, "countDown", "changeState", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: during title screen "Robin Hood! Your bow is needed" - { GID_LONGBOW, 220, 220, 0, "moveOn", "changeState", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: during second room "Outwit and outfight..." - { GID_LONGBOW, 210, 210, 0, "mama", "changeState", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: during third room "Fall under the spell..." - { GID_LONGBOW, 320, 320, 0, "flyin", "changeState", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: during fourth room "Conspiracies, love..." - { GID_PQ2, 23, 23, 0, "rm23Script", "elements", -1, sig_kDisplay_pq2_1, 0, { WORKAROUND_IGNORE, 0 } }, // when looking at the 2nd page of pate's file - 0x75 as id - bug #5223 - { GID_QFG1, 11, 11, 0, "battle", "init", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: When entering battle, 0x75 as id - { GID_SQ4, 397, 0, 0, "", "export 12", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // FLOPPY: when going into the computer store - bug #5227 - { GID_SQ4, 391, 391, 0, "doCatalog", "mode", -1, sig_kDisplay_sq4_1, 0, { WORKAROUND_IGNORE, 0 } }, // CD: clicking on catalog in roboter sale - a parameter is an object - { GID_SQ4, 391, 391, 0, "choosePlug", "changeState", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // CD: ordering connector in roboter sale - a parameter is an object + { GID_ISLANDBRAIN, 300, 300, 0, "geneDude", "show", NULL, 0, { WORKAROUND_IGNORE, 0 } }, // when looking at the gene explanation chart - a parameter is an object + { GID_LONGBOW, 95, 95, 0, "countDown", "changeState", NULL, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: during title screen "Robin Hood! Your bow is needed" + { GID_LONGBOW, 220, 220, 0, "moveOn", "changeState", NULL, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: during second room "Outwit and outfight..." + { GID_LONGBOW, 210, 210, 0, "mama", "changeState", NULL, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: during third room "Fall under the spell..." + { GID_LONGBOW, 320, 320, 0, "flyin", "changeState", NULL, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: during fourth room "Conspiracies, love..." + { GID_PQ2, 23, 23, 0, "rm23Script", "elements", sig_kDisplay_pq2_1, 0, { WORKAROUND_IGNORE, 0 } }, // when looking at the 2nd page of pate's file - 0x75 as id - bug #5223 + { GID_QFG1, 11, 11, 0, "battle", "init", NULL, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: When entering battle, 0x75 as id + { GID_SQ4, 397, 0, 0, "", "export 12", NULL, 0, { WORKAROUND_IGNORE, 0 } }, // FLOPPY: when going into the computer store - bug #5227 + { GID_SQ4, 391, 391, 0, "doCatalog", "mode", sig_kDisplay_sq4_1, 0, { WORKAROUND_IGNORE, 0 } }, // CD: clicking on catalog in roboter sale - a parameter is an object + { GID_SQ4, 391, 391, 0, "choosePlug", "changeState", NULL, 0, { WORKAROUND_IGNORE, 0 } }, // CD: ordering connector in roboter sale - a parameter is an object SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround +// gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround const SciWorkaroundEntry kDirLoop_workarounds[] = { - { GID_KQ4, 4, 992, 0, "Avoid", "doit", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // when the ogre catches you in front of his house, second parameter points to the same object as the first parameter, instead of being an integer (the angle) - bug #5217 + { GID_KQ4, 4, 992, 0, "Avoid", "doit", NULL, 0, { WORKAROUND_IGNORE, 0 } }, // when the ogre catches you in front of his house, second parameter points to the same object as the first parameter, instead of being an integer (the angle) - bug #5217 SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround +// gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround const SciWorkaroundEntry kDisposeScript_workarounds[] = { - { GID_LAURABOW, 777, 777, 0, "myStab", "changeState", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: after the will is signed, parameter 0 is an object - bug #4967 - { GID_LSL2, -1, 54, 0, "rm54", "dispose", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // Amiga: room 55, script tries to kDisposeScript an object (does not happen for DOS) - bug #6818 - { GID_QFG1, -1, 64, 0, "rm64", "dispose", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // when leaving graveyard, parameter 0 is an object - { GID_SQ4, 150, 151, 0, "fightScript", "dispose", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // during fight with Vohaul, parameter 0 is an object - { GID_SQ4, 150, 152, 0, "driveCloseUp", "dispose", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // when choosing "beam download", parameter 0 is an object - { GID_SQ4, 150, 152, 0, "", "dispose", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // when choosing "beam download"... in Russian version - bug #5573 + { GID_LAURABOW, 777, 777, 0, "myStab", "changeState", NULL, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: after the will is signed, parameter 0 is an object - bug #4967 + { GID_LSL2, -1, 54, 0, "rm54", "dispose", NULL, 0, { WORKAROUND_IGNORE, 0 } }, // Amiga: room 55, script tries to kDisposeScript an object (does not happen for DOS) - bug #6818 + { GID_QFG1, -1, 64, 0, "rm64", "dispose", NULL, 0, { WORKAROUND_IGNORE, 0 } }, // when leaving graveyard, parameter 0 is an object + { GID_SQ4, 150, 151, 0, "fightScript", "dispose", NULL, 0, { WORKAROUND_IGNORE, 0 } }, // during fight with Vohaul, parameter 0 is an object + { GID_SQ4, 150, 152, 0, "driveCloseUp", "dispose", NULL, 0, { WORKAROUND_IGNORE, 0 } }, // when choosing "beam download", parameter 0 is an object + { GID_SQ4, 150, 152, 0, "", "dispose", NULL, 0, { WORKAROUND_IGNORE, 0 } }, // when choosing "beam download"... in Russian version - bug #5573 SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround +// gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround const SciWorkaroundEntry kDoSoundFade_workarounds[] = { - { GID_KQ5, 213, 989, 0, "globalSound3", "fade", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // english floppy: when bandits leave the secret temple, parameter 4 is an object - bug #5078 - { GID_KQ6, 105, 989, 0, "globalSound", "fade", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // floppy: during intro, parameter 4 is an object - { GID_KQ6, 460, 989, 0, "globalSound2", "fade", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // after pulling the black widow's web on the isle of wonder, parameter 4 is an object - bug #4954 - { GID_QFG4, -1, 64989, 0, "longSong", "fade", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // CD version: many places, parameter 4 is an object (longSong) - { GID_SQ5, 800, 989, 0, "sq5Music1", "fade", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // when cutting the wrong part of Goliath with the laser - bug #6341 + { GID_KQ5, 213, 989, 0, "globalSound3", "fade", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // english floppy: when bandits leave the secret temple, parameter 4 is an object - bug #5078 + { GID_KQ6, 105, 989, 0, "globalSound", "fade", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // floppy: during intro, parameter 4 is an object + { GID_KQ6, 460, 989, 0, "globalSound2", "fade", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // after pulling the black widow's web on the isle of wonder, parameter 4 is an object - bug #4954 + { GID_QFG4, -1, 64989, 0, "longSong", "fade", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // CD version: many places, parameter 4 is an object (longSong) + { GID_SQ5, 800, 989, 0, "sq5Music1", "fade", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // when cutting the wrong part of Goliath with the laser - bug #6341 SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround +// gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround const SciWorkaroundEntry kGetAngle_workarounds[] = { - { GID_FANMADE, 516, 992, 0, "Motion", "init", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // The Legend of the Lost Jewel Demo (fan made): called with third/fourth parameters as objects - { GID_KQ6, -1, 752, 0, "throwDazzle", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // room 740/790 after the Genie is exposed in the Palace (short and long ending), it starts shooting lightning bolts around. An extra 5th parameter is passed - bug #4959 & #5203 - { GID_SQ1, -1, 927, 0, "PAvoider", "doit", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // all rooms in Ulence Flats after getting the Pilot Droid: called with a single parameter when the droid is in Roger's path - bug #6016 + { GID_FANMADE, 516, 992, 0, "Motion", "init", NULL, 0, { WORKAROUND_FAKE, 0 } }, // The Legend of the Lost Jewel Demo (fan made): called with third/fourth parameters as objects + { GID_KQ6, -1, 752, 0, "throwDazzle", "changeState", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // room 740/790 after the Genie is exposed in the Palace (short and long ending), it starts shooting lightning bolts around. An extra 5th parameter is passed - bug #4959 & #5203 + { GID_SQ1, -1, 927, 0, "PAvoider", "doit", NULL, 0, { WORKAROUND_FAKE, 0 } }, // all rooms in Ulence Flats after getting the Pilot Droid: called with a single parameter when the droid is in Roger's path - bug #6016 SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround +// gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround const SciWorkaroundEntry kFindKey_workarounds[] = { - { GID_ECOQUEST2, 100, 999, 0, "myList", "contains", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // When Noah Greene gives Adam the Ecorder, and just before the game gives a demonstration, a null reference to a list is passed - bug #4987 - { GID_HOYLE4, 300, 999, 0, "Piles", "contains", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // When passing the three cards in Hearts, a null reference to a list is passed - bug #5664 + { GID_ECOQUEST2, 100, 999, 0, "myList", "contains", NULL, 0, { WORKAROUND_FAKE, 0 } }, // When Noah Greene gives Adam the Ecorder, and just before the game gives a demonstration, a null reference to a list is passed - bug #4987 + { GID_HOYLE4, 300, 999, 0, "Piles", "contains", NULL, 0, { WORKAROUND_FAKE, 0 } }, // When passing the three cards in Hearts, a null reference to a list is passed - bug #5664 SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround +// gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround const SciWorkaroundEntry kGraphDrawLine_workarounds[] = { - { GID_ISLANDBRAIN, 300, 300, 0, "dudeViewer", "show", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // when looking at the gene explanation chart, gets called with 1 extra parameter - { GID_SQ1, 43, 43, 0, "someoneDied", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // when ordering beer, gets called with 1 extra parameter - { GID_SQ1, 71, 71, 0, "destroyXenon", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // during the Xenon destruction cutscene (which results in death), gets called with 1 extra parameter - bug #5176 - { GID_SQ1, 53, 53, 0, "blastEgo", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // when Roger is found and zapped by the cleaning robot, gets called with 1 extra parameter - bug #5177 + { GID_ISLANDBRAIN, 300, 300, 0, "dudeViewer", "show", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // when looking at the gene explanation chart, gets called with 1 extra parameter + { GID_SQ1, 43, 43, 0, "someoneDied", "changeState", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // when ordering beer, gets called with 1 extra parameter + { GID_SQ1, 71, 71, 0, "destroyXenon", "changeState", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // during the Xenon destruction cutscene (which results in death), gets called with 1 extra parameter - bug #5176 + { GID_SQ1, 53, 53, 0, "blastEgo", "changeState", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // when Roger is found and zapped by the cleaning robot, gets called with 1 extra parameter - bug #5177 SCI_WORKAROUNDENTRY_TERMINATOR }; @@ -556,32 +556,32 @@ static const uint16 sig_kGraphSaveBox_ibrain_1[] = { SIG_END }; -// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround +// gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround const SciWorkaroundEntry kGraphSaveBox_workarounds[] = { - { GID_CASTLEBRAIN, 420, 427, 0, "alienIcon", "select", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // when selecting a card during the alien card game, gets called with 1 extra parameter - { GID_ISLANDBRAIN, 290, 291, 0, "upElevator", "changeState",-1, sig_kGraphSaveBox_ibrain_1, 0, { WORKAROUND_STILLCALL, 0 } }, // when testing in the elevator puzzle, gets called with 1 argument less - 15 is on stack - bug #4943 - { GID_ISLANDBRAIN, 290, 291, 0, "downElevator", "changeState",-1, sig_kGraphSaveBox_ibrain_1, 0, { WORKAROUND_STILLCALL, 0 } }, // see above - { GID_ISLANDBRAIN, 290, 291, 0, "correctElevator", "changeState",-1, sig_kGraphSaveBox_ibrain_1, 0, { WORKAROUND_STILLCALL, 0 } }, // see above (when testing the correct solution) - { GID_PQ3, 202, 202, 0, "MapEdit", "movePt", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // when plotting crimes, gets called with 2 extra parameters - bug #5099 + { GID_CASTLEBRAIN, 420, 427, 0, "alienIcon", "select", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // when selecting a card during the alien card game, gets called with 1 extra parameter + { GID_ISLANDBRAIN, 290, 291, 0, "upElevator", "changeState", sig_kGraphSaveBox_ibrain_1, 0, { WORKAROUND_STILLCALL, 0 } }, // when testing in the elevator puzzle, gets called with 1 argument less - 15 is on stack - bug #4943 + { GID_ISLANDBRAIN, 290, 291, 0, "downElevator", "changeState", sig_kGraphSaveBox_ibrain_1, 0, { WORKAROUND_STILLCALL, 0 } }, // see above + { GID_ISLANDBRAIN, 290, 291, 0, "correctElevator", "changeState", sig_kGraphSaveBox_ibrain_1, 0, { WORKAROUND_STILLCALL, 0 } }, // see above (when testing the correct solution) + { GID_PQ3, 202, 202, 0, "MapEdit", "movePt", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // when plotting crimes, gets called with 2 extra parameters - bug #5099 SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround +// gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround const SciWorkaroundEntry kGraphRestoreBox_workarounds[] = { - { GID_LSL6, -1, 86, 0, "LL6Inv", "hide", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // happens during the game, gets called with 1 extra parameter + { GID_LSL6, -1, 86, 0, "LL6Inv", "hide", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // happens during the game, gets called with 1 extra parameter SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround +// gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround const SciWorkaroundEntry kGraphFillBoxForeground_workarounds[] = { - { GID_LSL6, -1, 0, 0, "LSL6", "hideControls", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // happens when giving the bungee key to merrily (room 240) and at least in room 650 too - gets called with additional 5th parameter + { GID_LSL6, -1, 0, 0, "LSL6", "hideControls", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // happens when giving the bungee key to merrily (room 240) and at least in room 650 too - gets called with additional 5th parameter SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround +// gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround const SciWorkaroundEntry kGraphFillBoxAny_workarounds[] = { - { GID_ECOQUEST2, 100, 333, 0, "showEcorder", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // necessary workaround for our ecorder script patch, because there isn't enough space to patch the function - { GID_SQ4, -1, 818, 0, "iconTextSwitch", "show", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // CD: game menu "text/speech" display - parameter 5 is missing, but the right color number is on the stack + { GID_ECOQUEST2, 100, 333, 0, "showEcorder", "changeState", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // necessary workaround for our ecorder script patch, because there isn't enough space to patch the function + { GID_SQ4, -1, 818, 0, "iconTextSwitch", "show", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // CD: game menu "text/speech" display - parameter 5 is missing, but the right color number is on the stack SCI_WORKAROUNDENTRY_TERMINATOR }; @@ -597,86 +597,86 @@ static const uint16 sig_kGraphRedrawBox_sq4_1[] = { SIG_END }; -// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround +// gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround const SciWorkaroundEntry kGraphRedrawBox_workarounds[] = { - { GID_SQ4, 405, 405, 0, "swimAfterEgo", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air - accidental additional parameter specified - { GID_SQ4, 405, 405, 0, "", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air... Russian version - bug #5573 - { GID_SQ4, 406, 406, 0, "egoFollowed", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // FLOPPY: when getting shot by the police - accidental additional parameter specified - { GID_SQ4, 406, 406, 0, "swimAndShoot", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air - accidental additional parameter specified - { GID_SQ4, 406, 406, 0, "", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air... Russian version - bug #5573 (is for both egoFollowed and swimAndShoot) - { GID_SQ4, 410, 410, 0, "swimAfterEgo", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air - accidental additional parameter specified - { GID_SQ4, 410, 410, 0, "", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air... Russian version - bug #5573 - { GID_SQ4, 411, 411, 0, "swimAndShoot", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air - accidental additional parameter specified - { GID_SQ4, 411, 411, 0, "", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air... Russian version - bug #5573 - { GID_SQ4, 150, 150, 0, "laserScript", "changeState", -1, sig_kGraphRedrawBox_sq4_1, 0, { WORKAROUND_STILLCALL, 0 } }, // when visiting the pedestral where Roger Jr. is trapped, before trashing the brain icon in the programming chapter, accidental additional parameter specified - bug #5479, German - bug #5527 - { GID_SQ4, 150, 150, 0, "", "changeState", -1, sig_kGraphRedrawBox_sq4_1, 0, { WORKAROUND_STILLCALL, 0 } }, // same as above, for the Russian version - bug #5573 - { GID_SQ4, -1, 704, 0, "shootEgo", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // When shot by Droid in Super Computer Maze (Rooms 500, 505, 510...) - accidental additional parameter specified - { GID_KQ5, -1, 981, 0, "myWindow", "dispose", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // Happens in the floppy version, when closing any dialog box, accidental additional parameter specified - bug #5031 - { GID_KQ5, -1, 995, 0, "invW", "doit", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // Happens in the floppy version, when closing the inventory window, accidental additional parameter specified - { GID_KQ5, -1, 995, 0, "", "export 0", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // Happens in the floppy version, when opening the gem pouch, accidental additional parameter specified - bug #5138 - { GID_KQ5, -1, 403, 0, "KQ5Window", "dispose", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // Happens in the FM Towns version when closing any dialog box, accidental additional parameter specified - SCI_WORKAROUNDENTRY_TERMINATOR -}; - -// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround + { GID_SQ4, 405, 405, 0, "swimAfterEgo", "changeState", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air - accidental additional parameter specified + { GID_SQ4, 405, 405, 0, "", "changeState", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air... Russian version - bug #5573 + { GID_SQ4, 406, 406, 0, "egoFollowed", "changeState", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // FLOPPY: when getting shot by the police - accidental additional parameter specified + { GID_SQ4, 406, 406, 0, "swimAndShoot", "changeState", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air - accidental additional parameter specified + { GID_SQ4, 406, 406, 0, "", "changeState", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air... Russian version - bug #5573 (is for both egoFollowed and swimAndShoot) + { GID_SQ4, 410, 410, 0, "swimAfterEgo", "changeState", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air - accidental additional parameter specified + { GID_SQ4, 410, 410, 0, "", "changeState", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air... Russian version - bug #5573 + { GID_SQ4, 411, 411, 0, "swimAndShoot", "changeState", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air - accidental additional parameter specified + { GID_SQ4, 411, 411, 0, "", "changeState", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air... Russian version - bug #5573 + { GID_SQ4, 150, 150, 0, "laserScript", "changeState", sig_kGraphRedrawBox_sq4_1, 0, { WORKAROUND_STILLCALL, 0 } }, // when visiting the pedestral where Roger Jr. is trapped, before trashing the brain icon in the programming chapter, accidental additional parameter specified - bug #5479, German - bug #5527 + { GID_SQ4, 150, 150, 0, "", "changeState", sig_kGraphRedrawBox_sq4_1, 0, { WORKAROUND_STILLCALL, 0 } }, // same as above, for the Russian version - bug #5573 + { GID_SQ4, -1, 704, 0, "shootEgo", "changeState", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // When shot by Droid in Super Computer Maze (Rooms 500, 505, 510...) - accidental additional parameter specified + { GID_KQ5, -1, 981, 0, "myWindow", "dispose", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // Happens in the floppy version, when closing any dialog box, accidental additional parameter specified - bug #5031 + { GID_KQ5, -1, 995, 0, "invW", "doit", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // Happens in the floppy version, when closing the inventory window, accidental additional parameter specified + { GID_KQ5, -1, 995, 0, "", "export 0", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // Happens in the floppy version, when opening the gem pouch, accidental additional parameter specified - bug #5138 + { GID_KQ5, -1, 403, 0, "KQ5Window", "dispose", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // Happens in the FM Towns version when closing any dialog box, accidental additional parameter specified + SCI_WORKAROUNDENTRY_TERMINATOR +}; + +// gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround const SciWorkaroundEntry kGraphUpdateBox_workarounds[] = { - { GID_ECOQUEST2, 100, 333, 0, "showEcorder", "changeState", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // necessary workaround for our ecorder script patch, because there isn't enough space to patch the function - { GID_PQ3, 202, 202, 0, "MapEdit", "addPt", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // when plotting crimes, gets called with 2 extra parameters - bug #5099 - { GID_PQ3, 202, 202, 0, "MapEdit", "movePt", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // when plotting crimes, gets called with 2 extra parameters - bug #5099 - { GID_PQ3, 202, 202, 0, "MapEdit", "dispose", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // when plotting crimes, gets called with 2 extra parameters + { GID_ECOQUEST2, 100, 333, 0, "showEcorder", "changeState", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // necessary workaround for our ecorder script patch, because there isn't enough space to patch the function + { GID_PQ3, 202, 202, 0, "MapEdit", "addPt", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // when plotting crimes, gets called with 2 extra parameters - bug #5099 + { GID_PQ3, 202, 202, 0, "MapEdit", "movePt", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // when plotting crimes, gets called with 2 extra parameters - bug #5099 + { GID_PQ3, 202, 202, 0, "MapEdit", "dispose", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // when plotting crimes, gets called with 2 extra parameters SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround +// gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround const SciWorkaroundEntry kIsObject_workarounds[] = { - { GID_GK1, 50, 999, 0, "List", "eachElementDo", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // GK1 demo, when asking Grace for messages it gets called with an invalid parameter (type "error") - bug #4950 - { GID_ISLANDBRAIN, -1, 999, 0, "List", "eachElementDo", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // when going to the game options, choosing "Info" and selecting anything from the list, gets called with an invalid parameter (type "error") - bug #4989 - { GID_QFG3, -1, 999, 0, "List", "eachElementDo", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // when asking for something, gets called with type error parameter + { GID_GK1, 50, 999, 0, "List", "eachElementDo", NULL, 0, { WORKAROUND_FAKE, 0 } }, // GK1 demo, when asking Grace for messages it gets called with an invalid parameter (type "error") - bug #4950 + { GID_ISLANDBRAIN, -1, 999, 0, "List", "eachElementDo", NULL, 0, { WORKAROUND_FAKE, 0 } }, // when going to the game options, choosing "Info" and selecting anything from the list, gets called with an invalid parameter (type "error") - bug #4989 + { GID_QFG3, -1, 999, 0, "List", "eachElementDo", NULL, 0, { WORKAROUND_FAKE, 0 } }, // when asking for something, gets called with type error parameter SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround +// gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround const SciWorkaroundEntry kMemory_workarounds[] = { - { GID_LAURABOW2, -1, 999, 0, "", "export 6", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // during the intro, when exiting the train (room 160), talking to Mr. Augustini, etc. - bug #4944 - { GID_SQ1, -1, 999, 0, "", "export 6", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // during walking Roger around Ulence Flats - bug #6017 + { GID_LAURABOW2, -1, 999, 0, "", "export 6", NULL, 0, { WORKAROUND_FAKE, 0 } }, // during the intro, when exiting the train (room 160), talking to Mr. Augustini, etc. - bug #4944 + { GID_SQ1, -1, 999, 0, "", "export 6", NULL, 0, { WORKAROUND_FAKE, 0 } }, // during walking Roger around Ulence Flats - bug #6017 SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround +// gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround const SciWorkaroundEntry kMoveCursor_workarounds[] = { - { GID_KQ5, -1, 937, 0, "IconBar", "handleEvent", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // when pressing escape to open the menu, gets called with one parameter instead of 2 - bug #5575 + { GID_KQ5, -1, 937, 0, "IconBar", "handleEvent", NULL, 0, { WORKAROUND_IGNORE, 0 } }, // when pressing escape to open the menu, gets called with one parameter instead of 2 - bug #5575 SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround +// gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround const SciWorkaroundEntry kNewWindow_workarounds[] = { - { GID_ECOQUEST, -1, 981, 0, "SysWindow", "open", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // EcoQuest 1 demo uses an in-between interpreter from SCI1 to SCI1.1. It's SCI1.1, but uses the SCI1 semantics for this call - bug #4976 + { GID_ECOQUEST, -1, 981, 0, "SysWindow", "open", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // EcoQuest 1 demo uses an in-between interpreter from SCI1 to SCI1.1. It's SCI1.1, but uses the SCI1 semantics for this call - bug #4976 SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround +// gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround const SciWorkaroundEntry kReadNumber_workarounds[] = { - { GID_CNICK_LAURABOW,100, 101, 0, "dominoes.opt", "doit", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // When dominoes.opt is present, the game scripts call kReadNumber with an extra integer parameter - bug #6425 - { GID_HOYLE3, 100, 101, 0, "dominoes.opt", "doit", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // When dominoes.opt is present, the game scripts call kReadNumber with an extra integer parameter - bug #6425 + { GID_CNICK_LAURABOW,100, 101, 0, "dominoes.opt", "doit", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // When dominoes.opt is present, the game scripts call kReadNumber with an extra integer parameter - bug #6425 + { GID_HOYLE3, 100, 101, 0, "dominoes.opt", "doit", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // When dominoes.opt is present, the game scripts call kReadNumber with an extra integer parameter - bug #6425 SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround +// gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround const SciWorkaroundEntry kPaletteUnsetFlag_workarounds[] = { - { GID_QFG4, 100, 100, 0, "doMovie", "changeState", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // after the Sierra logo, no flags are passed, thus the call is meaningless - bug #4947 + { GID_QFG4, 100, 100, 0, "doMovie", "changeState", NULL, 0, { WORKAROUND_IGNORE, 0 } }, // after the Sierra logo, no flags are passed, thus the call is meaningless - bug #4947 SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround +// gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround const SciWorkaroundEntry kSetCursor_workarounds[] = { - { GID_KQ5, -1, 768, 0, "KQCursor", "init", -1, NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // CD: gets called with 4 additional "900d" parameters + { GID_KQ5, -1, 768, 0, "KQCursor", "init", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // CD: gets called with 4 additional "900d" parameters SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround +// gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround const SciWorkaroundEntry kSetPort_workarounds[] = { - { GID_LSL6, 740, 740, 0, "rm740", "drawPic", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // ending scene, is called with additional 3 (!) parameters - { GID_QFG3, 830, 830, 0, "portalOpens", "changeState", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // when the portal appears during the end, gets called with 4 parameters - bug #5174 + { GID_LSL6, 740, 740, 0, "rm740", "drawPic", NULL, 0, { WORKAROUND_IGNORE, 0 } }, // ending scene, is called with additional 3 (!) parameters + { GID_QFG3, 830, 830, 0, "portalOpens", "changeState", NULL, 0, { WORKAROUND_IGNORE, 0 } }, // when the portal appears during the end, gets called with 4 parameters - bug #5174 SCI_WORKAROUNDENTRY_TERMINATOR }; @@ -692,16 +692,16 @@ static const uint16 sig_kStrAt_ibrain_1[] = { SIG_END }; -// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround +// gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround const SciWorkaroundEntry kStrAt_workarounds[] = { - { GID_CASTLEBRAIN, 220, 220, 0, "robotJokes", "animateOnce", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // when trying to view the terminal at the end of the maze without having collected any robot jokes - bug #5127 - { GID_ISLANDBRAIN, 300, 310, 0, "childBreed", "changeState",-1, sig_kStrAt_ibrain_1, 0, { WORKAROUND_FAKE, 0 } }, // when clicking Breed to get the second-generation cyborg hybrid (Standard difficulty), the two parameters are swapped - bug #5088 + { GID_CASTLEBRAIN, 220, 220, 0, "robotJokes", "animateOnce", NULL, 0, { WORKAROUND_FAKE, 0 } }, // when trying to view the terminal at the end of the maze without having collected any robot jokes - bug #5127 + { GID_ISLANDBRAIN, 300, 310, 0, "childBreed", "changeState", sig_kStrAt_ibrain_1, 0, { WORKAROUND_FAKE, 0 } }, // when clicking Breed to get the second-generation cyborg hybrid (Standard difficulty), the two parameters are swapped - bug #5088 SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround +// gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround const SciWorkaroundEntry kStrCpy_workarounds[] = { - { GID_MOTHERGOOSE, 23, 23, 0, "talkScript", "changeState", -1, NULL, 0, { WORKAROUND_FAKE, 0 } }, // when talking to the girl in scene 23, there's no destination parameter (script bug - wrong instruction order). The original source is used directly afterwards in kDisplay, to show the girl's text - bug #6485 + { GID_MOTHERGOOSE, 23, 23, 0, "talkScript", "changeState", NULL, 0, { WORKAROUND_FAKE, 0 } }, // when talking to the girl in scene 23, there's no destination parameter (script bug - wrong instruction order). The original source is used directly afterwards in kDisplay, to show the girl's text - bug #6485 SCI_WORKAROUNDENTRY_TERMINATOR }; @@ -717,22 +717,22 @@ static const uint16 sig_kStrLen_qfg2_1[] = { SIG_END }; -// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround +// gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround const SciWorkaroundEntry kStrLen_workarounds[] = { - { GID_QFG2, 210, 2, 0, "", "export 21", -1, sig_kStrLen_qfg2_1, 0, { WORKAROUND_FAKE, 0 } }, // When saying something incorrect at the WIT, an integer is passed instead of a reference - bug #5489 + { GID_QFG2, 210, 2, 0, "", "export 21", sig_kStrLen_qfg2_1, 0, { WORKAROUND_FAKE, 0 } }, // When saying something incorrect at the WIT, an integer is passed instead of a reference - bug #5489 SCI_WORKAROUNDENTRY_TERMINATOR }; -// gameID, room,script,lvl, object-name, method-name, call, callSig, index, workaround +// gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround const SciWorkaroundEntry kUnLoad_workarounds[] = { - { GID_ECOQUEST, 380, 61, 0, "gotIt", "changeState", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // CD version: after talking to the dolphin the first time, a 3rd parameter is passed by accident - { GID_ECOQUEST, 380, 69, 0, "lookAtBlackBoard", "changeState", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // German version, when closing the blackboard closeup in the dolphin room, a 3rd parameter is passed by accident - bug #5483 - { GID_LAURABOW2, -1, -1, 0, "sCartoon", "changeState", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: during the intro, a 3rd parameter is passed by accident - bug #4966 - { GID_LSL6, 130, 130, 0, "recruitLarryScr", "changeState", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // during intro, a 3rd parameter is passed by accident - { GID_LSL6, 740, 740, 0, "showCartoon", "changeState", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // during ending, 4 additional parameters are passed by accident - { GID_LSL6HIRES, 130, 130, 0, "recruitLarryScr", "changeState", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // during intro, a 3rd parameter is passed by accident - { GID_SQ1, 43, 303, 0, "slotGuy", "dispose", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // when leaving ulence flats bar, parameter 1 is not passed - script error - { GID_QFG4, -1, 110, 0, "dreamer", "dispose", -1, NULL, 0, { WORKAROUND_IGNORE, 0 } }, // during the dream sequence, a 3rd parameter is passed by accident + { GID_ECOQUEST, 380, 61, 0, "gotIt", "changeState", NULL, 0, { WORKAROUND_IGNORE, 0 } }, // CD version: after talking to the dolphin the first time, a 3rd parameter is passed by accident + { GID_ECOQUEST, 380, 69, 0, "lookAtBlackBoard", "changeState", NULL, 0, { WORKAROUND_IGNORE, 0 } }, // German version, when closing the blackboard closeup in the dolphin room, a 3rd parameter is passed by accident - bug #5483 + { GID_LAURABOW2, -1, -1, 0, "sCartoon", "changeState", NULL, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: during the intro, a 3rd parameter is passed by accident - bug #4966 + { GID_LSL6, 130, 130, 0, "recruitLarryScr", "changeState", NULL, 0, { WORKAROUND_IGNORE, 0 } }, // during intro, a 3rd parameter is passed by accident + { GID_LSL6, 740, 740, 0, "showCartoon", "changeState", NULL, 0, { WORKAROUND_IGNORE, 0 } }, // during ending, 4 additional parameters are passed by accident + { GID_LSL6HIRES, 130, 130, 0, "recruitLarryScr", "changeState", NULL, 0, { WORKAROUND_IGNORE, 0 } }, // during intro, a 3rd parameter is passed by accident + { GID_SQ1, 43, 303, 0, "slotGuy", "dispose", NULL, 0, { WORKAROUND_IGNORE, 0 } }, // when leaving ulence flats bar, parameter 1 is not passed - script error + { GID_QFG4, -1, 110, 0, "dreamer", "dispose", NULL, 0, { WORKAROUND_IGNORE, 0 } }, // during the dream sequence, a 3rd parameter is passed by accident SCI_WORKAROUNDENTRY_TERMINATOR }; @@ -795,8 +795,6 @@ SciWorkaroundSolution trackOriginAndFindWorkaround(int index, const SciWorkaroun while (workaround->methodName) { bool objectNameMatches = (workaround->objectName == NULL) || (workaround->objectName == searchObjectName); - bool localCallMatches = (workaround->localCallOffset == curLocalCallOffset) || - (workaround->localCallSignature); // soon to be obsolete if (workaround->gameId == gameId && ((workaround->scriptNr == -1) || (workaround->scriptNr == curScriptNr)) @@ -804,7 +802,6 @@ SciWorkaroundSolution trackOriginAndFindWorkaround(int index, const SciWorkaroun && ((workaround->inheritanceLevel == -1) || (workaround->inheritanceLevel == inheritanceLevel)) && objectNameMatches && workaround->methodName == g_sci->getSciLanguageString(curMethodName, K_LANG_ENGLISH) - && localCallMatches // soon to be obsolete && ((workaround->index == -1) || (workaround->index == index))) { // Workaround found if ((workaround->localCallSignature) || (curLocalCallOffset != -1)) { diff --git a/engines/sci/engine/workarounds.h b/engines/sci/engine/workarounds.h index 25dd2bbc8a..46059a175c 100644 --- a/engines/sci/engine/workarounds.h +++ b/engines/sci/engine/workarounds.h @@ -60,7 +60,6 @@ struct SciWorkaroundEntry { int16 inheritanceLevel; const char *objectName; const char *methodName; - int localCallOffset; const uint16 *localCallSignature; int index; SciWorkaroundSolution newValue; -- cgit v1.2.3 From 6777785cdf5dee85fff62e08ec43ce963bb71b41 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 19 Apr 2015 20:48:23 +0200 Subject: SCI: workaround sig cleanup 2 --- engines/sci/engine/workarounds.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index 71ba7d05a4..b33457606e 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -629,9 +629,9 @@ const SciWorkaroundEntry kGraphUpdateBox_workarounds[] = { // gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround const SciWorkaroundEntry kIsObject_workarounds[] = { - { GID_GK1, 50, 999, 0, "List", "eachElementDo", NULL, 0, { WORKAROUND_FAKE, 0 } }, // GK1 demo, when asking Grace for messages it gets called with an invalid parameter (type "error") - bug #4950 - { GID_ISLANDBRAIN, -1, 999, 0, "List", "eachElementDo", NULL, 0, { WORKAROUND_FAKE, 0 } }, // when going to the game options, choosing "Info" and selecting anything from the list, gets called with an invalid parameter (type "error") - bug #4989 - { GID_QFG3, -1, 999, 0, "List", "eachElementDo", NULL, 0, { WORKAROUND_FAKE, 0 } }, // when asking for something, gets called with type error parameter + { GID_GK1, 50, 999, 0, "List", "eachElementDo", NULL, 0, { WORKAROUND_FAKE, 0 } }, // GK1 demo, when asking Grace for messages it gets called with an invalid parameter (type "error") - bug #4950 + { GID_ISLANDBRAIN, -1, 999, 0, "List", "eachElementDo", NULL, 0, { WORKAROUND_FAKE, 0 } }, // when going to the game options, choosing "Info" and selecting anything from the list, gets called with an invalid parameter (type "error") - bug #4989 + { GID_QFG3, -1, 999, 0, "List", "eachElementDo", NULL, 0, { WORKAROUND_FAKE, 0 } }, // when asking for something, gets called with type error parameter SCI_WORKAROUNDENTRY_TERMINATOR }; -- cgit v1.2.3 From bfb86a99db6358043a4c16371c5a927411b4e8cb Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 20 Apr 2015 01:07:54 -0500 Subject: SHERLOCK: Map path walking, beginnings of darts game --- engines/sherlock/map.cpp | 74 ++++++- engines/sherlock/map.h | 19 +- engines/sherlock/scalpel/darts.cpp | 385 +++++++++++++++++++++++++++++++++++ engines/sherlock/scalpel/darts.h | 33 ++- engines/sherlock/scalpel/scalpel.cpp | 8 +- 5 files changed, 504 insertions(+), 15 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/map.cpp b/engines/sherlock/map.cpp index fa3bf99cab..6fd169f43a 100644 --- a/engines/sherlock/map.cpp +++ b/engines/sherlock/map.cpp @@ -31,7 +31,7 @@ Map::Map(SherlockEngine *vm): _vm(vm), _topLine(SHERLOCK_SCREEN_WIDTH, 12) { _iconShapes = nullptr; _point = 0; _placesShown = false; - _charPoint = -1; + _charPoint = _oldCharPoint = -1; _cursorIndex = -1; _drawMap = false; for (int idx = 0; idx < 3; ++idx) @@ -43,9 +43,9 @@ Map::Map(SherlockEngine *vm): _vm(vm), _topLine(SHERLOCK_SCREEN_WIDTH, 12) { /** * Loads the list of points for locations on the map for each scene */ -void Map::loadPoints(int count, const int *xList, const int *yList) { - for (int idx = 0; idx < count; ++idx, ++xList, ++yList) { - _points.push_back(Common::Point(*xList, *yList)); +void Map::loadPoints(int count, const int *xList, const int *yList, const int *transList) { + for (int idx = 0; idx < count; ++idx, ++xList, ++yList, ++transList) { + _points.push_back(MapEntry(*xList, *yList, *transList)); } } @@ -79,9 +79,11 @@ void Map::loadData() { } // Load in the path point information - _pathPoints.resize(416); - for (uint idx = 0; idx < _pathPoints.size(); ++idx) - _pathPoints[idx] = pathStream->readSint16LE(); + _pathPoints.resize(208); + for (uint idx = 0; idx < _pathPoints.size(); ++idx) { + _pathPoints[idx].x = pathStream->readSint16LE(); + _pathPoints[idx].y = pathStream->readSint16LE(); + } delete pathStream; } @@ -302,6 +304,14 @@ void Map::saveTopLine() { _topLine.blitFrom(_vm->_screen->_backBuffer1, Common::Point(0, 0), Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, 12)); } +/** + * Erases anything shown in the top line by restoring the previously saved original map background + */ +void Map::eraseTopLine() { + Screen &screen = *_vm->_screen; + screen.blitFrom(_topLine, Common::Point(0, 0)); +} + /** * Update all on-screen sprites to account for any scrolling of the map */ @@ -355,7 +365,55 @@ void Map::updateMap(bool flushScreen) { * Handle moving icon for player from their previous location on the map to a destination location */ void Map::walkTheStreets() { - // TODO + People &people = *_vm->_people; + bool reversePath = false; + Common::Array tempPath; + + // Get indexes into the path lists for the start and destination scenes + int start = _points[_oldCharPoint]._translate; + int dest = _points[_charPoint]._translate; + + // Get pointer to start of path + const int *ptr = &_paths[start][dest]; + + // Check for any intermediate points between the two locations + if (*ptr || _charPoint > 50 || _oldCharPoint > 50) { + people[AL]._sequenceNumber = -1; + + if (_charPoint == 51 || _oldCharPoint == 51) { + people.setWalking(); + } else { + // Check for moving the path backwards or forwards + if (*ptr == 255) { + reversePath = true; + SWAP(start, dest); + ptr = &_paths[start][dest]; + } + + do { + int idx = *ptr++; + tempPath.push_back(_pathPoints[idx - 1] + Common::Point(4, 4)); + } while (*ptr != 254); + + // Load up the path to use + people._walkTo.clear(); + + if (!reversePath) { + people._walkTo = tempPath; + people._walkDest = tempPath[0]; + } else { + for (int idx = 0; idx < ((int)tempPath.size() - 1); ++idx) + people._walkTo.push(tempPath[idx]); + people._walkDest = tempPath[tempPath.size() - 1]; + } + + people._walkDest.x += 12; + people._walkDest.y += 6; + people.setWalking(); + } + } else { + people[AL]._walkCount = 0; + } } /** diff --git a/engines/sherlock/map.h b/engines/sherlock/map.h index 653d8c0084..f324160bce 100644 --- a/engines/sherlock/map.h +++ b/engines/sherlock/map.h @@ -35,13 +35,21 @@ namespace Sherlock { class SherlockEngine; +struct MapEntry : Common::Point { + int _translate; + + MapEntry() : Common::Point(), _translate(-1) {} + + MapEntry(int x, int y, int translate) : Common::Point(x, y), _translate(translate) {} +}; + class Map { private: SherlockEngine *_vm; - Common::Array _points; // Map locations for each scene + Common::Array _points; // Map locations for each scene Common::StringArray _locationNames; Common::Array< Common::Array > _paths; - Common::Array _pathPoints; + Common::Array _pathPoints; Common::Point _savedPos; Common::Point _savedSize; Surface _topLine; @@ -54,7 +62,7 @@ private: Common::Point _lDrawnPos; int _point; bool _placesShown; - int _charPoint; + int _charPoint, _oldCharPoint; int _cursorIndex; bool _drawMap; Surface _iconSave; @@ -67,6 +75,7 @@ private: void showPlaces(); void saveTopLine(); + void eraseTopLine(); void updateMap(bool flushScreen); @@ -77,9 +86,9 @@ private: public: Map(SherlockEngine *vm); - const Common::Point &operator[](int idx) { return _points[idx]; } + const MapEntry &operator[](int idx) { return _points[idx]; } - void loadPoints(int count, const int *xList, const int *yList); + void loadPoints(int count, const int *xList, const int *yList, const int *transList); int show(); }; diff --git a/engines/sherlock/scalpel/darts.cpp b/engines/sherlock/scalpel/darts.cpp index 857ac63f8c..c975cb1086 100644 --- a/engines/sherlock/scalpel/darts.cpp +++ b/engines/sherlock/scalpel/darts.cpp @@ -27,10 +27,395 @@ namespace Sherlock { namespace Scalpel { +enum { + STATUS_INFO_X = 218, + STATUS_INFO_Y = 53, + DART_INFO_X = 218, + DART_INFO_Y = 103, + DARTBARHX = 35, + DARTHORIZY = 190, + DARTBARVX = 1, + DARTHEIGHTY = 25, + DARTBARSIZE = 150, + DART_BAR_FORE = 8 +}; + +enum { + DART_COL_FORE = 5, + PLAYER_COLOR = 11 +}; + +const char *const OPPONENT_NAMES[5] = { + "Skipper", "Willy", "Micky", "Tom", "Bartender" +}; + +/*----------------------------------------------------------------*/ + +Darts::Darts(ScalpelEngine *vm) : _vm(vm) { + _dartImages = nullptr; + _level = 0; + _computerPlayer = 1; + _playerDartMode = false; + _dartScore1 = _dartScore2 = 0; + _roundNumber = 0; + _playerDartMode = false; + _roundScore = 0; + _oldDartButtons = 0; +} + +/** + * Main method for playing darts game + */ void Darts::playDarts() { + Screen &screen = *_vm->_screen; + int score, roundStartScore; + int playerNumber = 0; + int lastDart; + + // Change the font + int oldFont = screen.fontNumber(); + screen.setFont(4); + + loadDarts(); + initDarts(); + + do { + roundStartScore = score = playerNumber == 0 ? _dartScore1 : _dartScore2; + + // Show player details + showNames(playerNumber); + showStatus(playerNumber); + _roundScore = 0; + + for (int idx = 0; idx < 3; ++idx) { + // Throw a single dart + if (_computerPlayer == 1) + lastDart = throwDart(idx + 1, playerNumber * 2); + else if (_computerPlayer == 2) + lastDart = throwDart(idx + 1, playerNumber + 1); + else + lastDart = throwDart(idx + 1, 0); + + score -= lastDart; + _roundScore += lastDart; + + + } + + // todo + } while (!_vm->shouldQuit()); + // TODO } +/** + * Load the graphics needed for the dart game + */ +void Darts::loadDarts() { + Screen &screen = *_vm->_screen; + + _dartImages = new ImageFile("darts.vgs"); + screen._backBuffer1.blitFrom((*_dartImages)[1], Common::Point(0, 0)); + screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT); +} + +/** + * Initializes the variables needed for the dart game + */ +void Darts::initDarts() { + _dartScore1 = _dartScore2 = 301; + _roundNumber = 1; + + if (_level == 9) { + // No computer players + _computerPlayer = 0; + _level = 0; + } else if (_level == 8) { + _level = _vm->getRandomNumber(3); + _computerPlayer = 2; + } else { + // Check flags for opponents + for (int idx = 0; idx < 4; ++idx) { + if (_vm->readFlags(314 + idx)) + _level = idx; + } + } + + _opponent = OPPONENT_NAMES[_level]; +} + +/** + * Show the player names + */ +void Darts::showNames(int playerNum) { + Screen &screen = *_vm->_screen; + byte color = playerNum == 0 ? PLAYER_COLOR : DART_COL_FORE; + + // Print Holmes first + if (playerNum == 0) + screen.print(Common::Point(STATUS_INFO_X, STATUS_INFO_Y), PLAYER_COLOR + 3, "Holmes"); + else + screen.print(Common::Point(STATUS_INFO_X, STATUS_INFO_Y), color, "Holmes"); + + screen._backBuffer1.fillRect(Common::Rect(STATUS_INFO_X, STATUS_INFO_Y + 10, + STATUS_INFO_X + 31, STATUS_INFO_Y + 12), color); + screen.slamArea(STATUS_INFO_X, STATUS_INFO_Y + 10, 31, 12); + + // Second player + color = playerNum == 1 ? PLAYER_COLOR : DART_COL_FORE; + + if (playerNum != 0) + screen.print(Common::Point(STATUS_INFO_X + 50, STATUS_INFO_Y + 10), PLAYER_COLOR + 3, + _opponent.c_str()); + else + screen.print(Common::Point(STATUS_INFO_X + 50, STATUS_INFO_Y + 10), color, + _opponent.c_str()); + + screen._backBuffer1.fillRect(Common::Rect(STATUS_INFO_X + 50, STATUS_INFO_Y + 10, + STATUS_INFO_Y + 81, STATUS_INFO_Y + 12), color); + screen.slamArea(STATUS_INFO_X + 50, STATUS_INFO_Y + 10, 81, 12); + + // Make a copy of the back buffer to the secondary one + screen._backBuffer2.blitFrom(screen._backBuffer1); +} + +/** + * Show the player score and game status + */ +void Darts::showStatus(int playerNum) { + Screen &screen = *_vm->_screen; + byte color; + + screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(STATUS_INFO_X, STATUS_INFO_Y + 10), + Common::Rect(STATUS_INFO_X, STATUS_INFO_Y + 10, SHERLOCK_SCREEN_WIDTH, STATUS_INFO_Y + 38)); + + color = (playerNum == 0) ? PLAYER_COLOR : DART_COL_FORE; + screen.print(Common::Point(STATUS_INFO_X + 6, STATUS_INFO_Y + 13), color, "%d", _dartScore1); + + color = (playerNum == 1) ? PLAYER_COLOR : DART_COL_FORE; + screen.print(Common::Point(STATUS_INFO_X + 56, STATUS_INFO_Y + 13), color, "%d", _dartScore2); + screen.print(Common::Point(STATUS_INFO_X, STATUS_INFO_Y + 25), PLAYER_COLOR, "Round: %d", _roundNumber); + screen.print(Common::Point(STATUS_INFO_X, STATUS_INFO_Y + 35), PLAYER_COLOR, "Turn Total: %d", _roundScore); + screen.slamRect(Common::Rect(STATUS_INFO_X, STATUS_INFO_Y + 10, SHERLOCK_SCREEN_WIDTH, STATUS_INFO_Y + 48)); +} + +/** + * Throws a single dart. + * @param dartNum Dart number + * @param computer 0 = Player, 1 = 1st player computer, 2 = 2nd player computer + * @returns Score for what dart hit + */ +int Darts::throwDart(int dartNum, int computer) { + Events &events = *_vm->_events; + Screen &screen = *_vm->_screen; + Common::Point targetNum; + int width, height; + + events.clearKeyboard(); + + erasePowerBars(); + screen.print(Common::Point(DART_INFO_X, DART_INFO_Y), DART_COL_FORE, "Dart # %d", dartNum); + + if (!computer) { + screen.print(Common::Point(DART_INFO_X, DART_INFO_Y + 10), DART_COL_FORE, "Hit a key"); + screen.print(Common::Point(DART_INFO_X, DART_INFO_Y + 18), DART_COL_FORE, "to start"); + } + + if (!computer) { + while (!_vm->shouldQuit() && !dartHit()) + ; + } else { + events.delay(10); + } + + screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(DART_INFO_X, DART_INFO_Y - 1), + Common::Rect(DART_INFO_X, DART_INFO_Y - 1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); + screen.slamRect(Common::Rect(DART_INFO_X, DART_INFO_Y - 1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); + + // If it's a computer player, choose a dart destination + if (computer) + targetNum = getComputerDartDest(computer - 1); + + width = doPowerBar(Common::Point(DARTBARHX, DARTHORIZY), DART_BAR_FORE, targetNum.x, 0); + height = 101 - doPowerBar(Common::Point(DARTBARVX, DARTHEIGHTY), DART_BAR_FORE, targetNum.y, 0); + + // For human players, slight y adjustment + if (computer == 0) + height = 2; + + // Copy the bars to the secondary back buffer + screen._backBuffer2.blitFrom(screen._backBuffer1, Common::Point(DARTBARHX - 1, DARTHORIZY - 1), + Common::Rect(DARTBARHX - 1, DARTHORIZY - 1, DARTBARHX + DARTBARSIZE + 3, DARTHORIZY + 10)); + screen._backBuffer2.blitFrom(screen._backBuffer1, Common::Point(DARTBARVX - 1, DARTHEIGHTY - 1), + Common::Rect(DARTBARVX - 1, DARTHEIGHTY - 1, DARTBARVX + 11, DARTHEIGHTY + DARTBARSIZE + 3)); + + // Convert to relative range from -49 to 150 + height -= 50; + width -= 50; + + Common::Point dartPos(111 + width * 2, 99 + height * 2); + drawDartThrow(dartPos); + + return dartScore(dartPos); +} + +/** + * Draw a dart moving towards the board + */ +void Darts::drawDartThrow(const Common::Point &pt) { + // TODO +} + +/** + * Erases the power bars + */ +void Darts::erasePowerBars() { + Screen &screen = *_vm->_screen; + + screen._backBuffer1.fillRect(Common::Rect(DARTBARHX, DARTHORIZY, DARTBARHX + DARTBARSIZE, DARTHORIZY + 10), 0); + screen._backBuffer1.fillRect(Common::Rect(DARTBARVX, DARTHEIGHTY, DARTBARVX + 10, DARTHEIGHTY + DARTBARSIZE), 0); + screen._backBuffer1.transBlitFrom((*_dartImages)[3], Common::Point(DARTBARHX - 1, DARTHORIZY - 1)); + screen._backBuffer1.transBlitFrom((*_dartImages)[4], Common::Point(DARTBARVX - 1, DARTHEIGHTY - 1)); + screen.slamArea(DARTBARHX - 1, DARTHORIZY - 1, DARTBARSIZE + 3, 11); + screen.slamArea(DARTBARVX - 1, DARTHEIGHTY - 1, 11, DARTBARSIZE + 3); +} + +/** + * Show a gradually incrementing incrementing power that bar. If goToPower is provided, it will + * increment to that power level ignoring all keyboard input (ie. for computer throws). + * Otherwise, it will increment until either a key/mouse button is pressed, or it reaches the end + */ +int Darts::doPowerBar(const Common::Point &pt, byte color, int goToPower, int orientation) { + // TODO + return 0; +} + +/** + * Returns true if a mouse button or key is pressed. + */ +bool Darts::dartHit() { + Events &events = *_vm->_events; + + if (events.kbHit()) { + events.clearKeyboard(); + return true; + } + + events.setButtonState(); + return events._pressed && !_oldDartButtons; +} + +/** + * Return the score of the given location on the dart-board + */ +int Darts::dartScore(const Common::Point &pt) { + // TODO + return 0; +} + +/** + * Calculates where a computer player is trying to throw their dart, and choose the actual + * point that was hit with some margin of error + */ +Common::Point Darts::getComputerDartDest(int playerNum) { + Common::Point target; + int aim; + int score = playerNum == 0 ? _dartScore1 : _dartScore2; + + if (score > 50) { + // Aim for the bullseye + target.x = target.y = 76; + + if (_level <= 1 && _vm->getRandomNumber(1) == 1) { + // Introduce margin of error + target.x += _vm->getRandomNumber(21) - 10; + target.y += _vm->getRandomNumber(21) - 10; + } + } else { + aim = score; + + bool done; + Common::Point pt; + do { + done = findNumberOnBoard(aim, pt); + --aim; + } while (!done); + + target.x = 75 + ((target.x - 75) * 20 / 27); + target.y = 75 + ((target.y - 75) * 2 / 3); + } + + // Pick a level of accuracy. The higher the level, the more accurate their throw will be + int accuracy = _vm->getRandomNumber(10) + _level * 2; + + if (accuracy <= 2) { + target.x += _vm->getRandomNumber(71) - 35; + target.y += _vm->getRandomNumber(71) - 35; + } else if (accuracy <= 4) { + target.x += _vm->getRandomNumber(51) - 25; + target.y += _vm->getRandomNumber(51) - 25; + } else if (accuracy <= 6) { + target.x += _vm->getRandomNumber(31) - 15; + target.y += _vm->getRandomNumber(31) - 15; + } else if (accuracy <= 8) { + target.x += _vm->getRandomNumber(21) - 10; + target.y += _vm->getRandomNumber(21) - 10; + } else if (accuracy <= 10) { + target.x += _vm->getRandomNumber(11) - 5; + target.y += _vm->getRandomNumber(11) - 5; + } + + if (target.x < 1) + target.x = 1; + if (target.y < 1) + target.y = 1; + + return target; +} + +/** + * Returns the center position for the area of the dartboard with a given number + */ +bool Darts::findNumberOnBoard(int aim, Common::Point &pt) { + ImageFrame &board = (*_dartImages)[2]; + + // Scan board image for the special "center" pixels + bool done = false; + for (int yp = 0; yp < 132 && !done; ++yp) { + const byte *srcP = (const byte *)board._frame.getBasePtr(0, yp); + for (int xp = 0; xp < 147 && !done; ++xp, ++srcP) { + int score = *srcP; + + // Check for match + if (score == aim) { + done = true; + + // Aim at non-double/triple numbers where possible + if (aim < 21) { + pt.x = xp + 5; + pt.y = yp + 5; + + score = *(const byte *)board._frame.getBasePtr(xp + 10, yp + 10); + if (score != aim) + // Not aiming at non-double/triple number yet + done = false; + } else { + // Aiming at a double or triple + pt.x = xp + 3; + pt.y = yp + 3; + } + } + } + } + + if (aim == 3) + pt.x += 15; + pt.y = 132 - pt.y; + + return done; +} + + } // End of namespace Scalpel } // End of namespace Scalpel diff --git a/engines/sherlock/scalpel/darts.h b/engines/sherlock/scalpel/darts.h index 22164156c9..2fbdc3d7e2 100644 --- a/engines/sherlock/scalpel/darts.h +++ b/engines/sherlock/scalpel/darts.h @@ -23,6 +23,8 @@ #ifndef SHERLOCK_DARTS_H #define SHERLOCK_DARTS_H +#include "sherlock/resources.h" + namespace Sherlock { namespace Scalpel { @@ -32,8 +34,37 @@ class ScalpelEngine; class Darts { private: ScalpelEngine *_vm; + ImageFile *_dartImages; + int _dartScore1, _dartScore2; + int _roundNumber; + int _level; + int _computerPlayer; + Common::String _opponent; + bool _playerDartMode; + int _roundScore; + int _oldDartButtons; + + void loadDarts(); + void initDarts(); + + void showNames(int playerNum); + void showStatus(int playerNum); + + int throwDart(int dartNum, int computer); + void drawDartThrow(const Common::Point &pt); + + void erasePowerBars(); + int doPowerBar(const Common::Point &pt, byte color, int goToPower, int orientation); + + bool dartHit(); + int dartScore(const Common::Point &pt); + + Common::Point getComputerDartDest(int playerNum); + + bool findNumberOnBoard(int aim, Common::Point &pt); + public: - Darts(ScalpelEngine *vm) : _vm(vm) {} + Darts(ScalpelEngine *vm); void playDarts(); }; diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp index 0742d05366..eba6626c53 100644 --- a/engines/sherlock/scalpel/scalpel.cpp +++ b/engines/sherlock/scalpel/scalpel.cpp @@ -39,6 +39,12 @@ const int MAP_Y[NUM_PLACES] = { 37, 0, 70, 0, 116, 0, 0, 0, 50, 21, 0, 303, 0, 0, 229, 0, 0 }; +int MAP_TRANSLATE[NUM_PLACES] = { + 0, 0, 0, 1, 0, 2, 0, 3, 4, 0, 4, 6, 0, 0, 0, 8, 9, 10, 11, 0, 12, 13, 14, 7, + 15, 16, 17, 18, 19, 0, 20, 21, 22, 23, 0, 24, 0, 25, 0, 26, 0, 0, 0, 27, + 28, 0, 29, 0, 0, 30, 0 +}; + #define MAX_PEOPLE 66 const byte STILL_SEQUENCES[MAX_PEOPLE][MAX_TALK_SEQUENCES] = { @@ -204,7 +210,7 @@ void ScalpelEngine::initialize() { _flags[39] = true; // Turn on Baker Street // Load the map co-ordinates for each scene - _map->loadPoints(NUM_PLACES, &MAP_X[0], &MAP_Y[0]); + _map->loadPoints(NUM_PLACES, &MAP_X[0], &MAP_Y[0], &MAP_TRANSLATE[0]); // Load the inventory loadInventory(); -- cgit v1.2.3 From 6a1b12b797c51bdc51c71db67e2df4e8de6281e0 Mon Sep 17 00:00:00 2001 From: Strangerke Date: Mon, 20 Apr 2015 23:47:34 +0200 Subject: SHERLOCK: Add some more code for the intro --- engines/sherlock/scalpel/scalpel.cpp | 92 ++++++++++++++++++++++++++++++++---- engines/sherlock/scalpel/scalpel.h | 1 + engines/sherlock/sound.cpp | 3 +- engines/sherlock/sound.h | 2 +- 4 files changed, 87 insertions(+), 11 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp index eba6626c53..4e49a6b4d3 100644 --- a/engines/sherlock/scalpel/scalpel.cpp +++ b/engines/sherlock/scalpel/scalpel.cpp @@ -249,8 +249,8 @@ bool ScalpelEngine::showCityCutscene() { if (finished) { ImageFile titleImages("title2.vgs", true); - _screen->_backBuffer1.blitFrom(*_screen); - _screen->_backBuffer2.blitFrom(*_screen); + _screen->_backBuffer1.copyFrom(*_screen); + _screen->_backBuffer2.copyFrom(*_screen); // London, England _screen->_backBuffer1.transBlitFrom(titleImages[0], Common::Point(10, 11)); @@ -274,8 +274,8 @@ bool ScalpelEngine::showCityCutscene() { if (finished) { ImageFile titleImages("title.vgs", true); - _screen->_backBuffer1.blitFrom(*_screen); - _screen->_backBuffer2.blitFrom(*_screen); + _screen->_backBuffer1.copyFrom(*_screen); + _screen->_backBuffer2.copyFrom(*_screen); // The Lost Files of _screen->_backBuffer1.transBlitFrom(titleImages[0], Common::Point(75, 6)); @@ -320,7 +320,7 @@ bool ScalpelEngine::showAlleyCutscene() { bool finished = _animation->playPrologue("27PRO1", 1, 3, true, 2); if (finished) - _animation->playPrologue("27PRO2", 1, 0, false, 2); + finished = _animation->playPrologue("27PRO2", 1, 0, false, 2); if (finished) { ImageFile screamImages("SCREAM.LBV", false); @@ -330,7 +330,7 @@ bool ScalpelEngine::showAlleyCutscene() { } if (finished) - _animation->playPrologue("27PRO3", 1, 0, true, 2); + finished = _animation->playPrologue("27PRO3", 1, 0, true, 2); if(finished) { _screen->getPalette(palette); @@ -351,13 +351,87 @@ bool ScalpelEngine::showAlleyCutscene() { } bool ScalpelEngine::showStreetCutscene() { - // TODO + _titleOverride = "TITLE.LIB"; + _soundOverride = "TITLE.SND"; + + _sound->playMusic("PROLOG3.MUS"); + + bool finished = _animation->playPrologue("14KICK", 1, 3, true, 2); + + if (finished) + finished = _animation->playPrologue("14NOTE", 1, 0, false, 2); + + _titleOverride = ""; + _soundOverride = ""; + return finished; +} + +bool ScalpelEngine::scrollCredits() { + _titleOverride = "TITLE.LIB"; + ImageFile creditsImages("credits.vgs", true); + + _screen->_backBuffer1.copyFrom(*_screen->_backBuffer); + + for(int i = 0; i < 600 && !_events->kbHit(); i++) { + _screen->_backBuffer1.copyFrom(*_screen->_backBuffer); + if (i < 200) + _screen->transBlitFrom(creditsImages[0], Common::Point(10, -i), false, 0); + if (i > 0 && i < 400) + _screen->transBlitFrom(creditsImages[1], Common::Point(10, 200 - i), false, 0); + if (i > 200) + _screen->transBlitFrom(creditsImages[2], Common::Point(10, 400 - i), false, 0); + + warning("TODO: Use VideoBlockMove"); +// videoblockmove(SCREEN, BACKBUFFER, 0, 0, 320, 10); +// videoblockmove(SCREEN, BACKBUFFER, 0, 190, 320, 10); + + _events->delay(100); + } + + _titleOverride = ""; return true; } bool ScalpelEngine::showOfficeCutscene() { - // TODO - return true; + _sound->playMusic("PROLOG4.MUS"); + _titleOverride = "TITLE2.LIB"; + _soundOverride = "TITLE.SND"; + + bool finished = _animation->playPrologue("COFF1", 1, 3, true, 3); + if (finished) + finished = _animation->playPrologue("COFF2", 1, 0, false, 3); + if (finished) { + warning("TODO: ShowLBV(""NOTE.LBV"");"); + if (_sound->_voices) { + finished = _sound->playSound("NOTE1", WAIT_KBD_OR_FINISH); + if (finished) + finished = _sound->playSound("NOTE2", WAIT_KBD_OR_FINISH); + if (finished) + finished = _sound->playSound("NOTE3", WAIT_KBD_OR_FINISH); + if (finished) + finished = _sound->playSound("NOTE4", WAIT_KBD_OR_FINISH); + } else + finished = _events->delay(19000); + + _events->clearEvents(); + finished = _events->delay(500); + } + + if (finished) + finished = _animation->playPrologue("COFF3", 1, 0, true, 3); + + if (finished) + finished = _animation->playPrologue("COFF4", 1, 0, false, 3); + + if (finished) + finished = scrollCredits(); + + if (finished) + _screen->fadeToBlack(3); + + _titleOverride = ""; + _soundOverride = ""; + return finished; } void ScalpelEngine::loadInventory() { diff --git a/engines/sherlock/scalpel/scalpel.h b/engines/sherlock/scalpel/scalpel.h index aa00acab84..194bf5413e 100644 --- a/engines/sherlock/scalpel/scalpel.h +++ b/engines/sherlock/scalpel/scalpel.h @@ -39,6 +39,7 @@ private: bool showAlleyCutscene(); bool showStreetCutscene(); bool showOfficeCutscene(); + bool scrollCredits(); void loadInventory(); protected: diff --git a/engines/sherlock/sound.cpp b/engines/sherlock/sound.cpp index c3e50a8be2..600618b570 100644 --- a/engines/sherlock/sound.cpp +++ b/engines/sherlock/sound.cpp @@ -41,8 +41,9 @@ void Sound::loadSound(const Common::String &name, int priority) { // TODO } -void Sound::playSound(const Common::String &name, WaitType waitType) { +bool Sound::playSound(const Common::String &name, WaitType waitType) { // TODO + return true; } void Sound::cacheSound(const Common::String &name, int index) { diff --git a/engines/sherlock/sound.h b/engines/sherlock/sound.h index 22d5a5c221..6adc22c01c 100644 --- a/engines/sherlock/sound.h +++ b/engines/sherlock/sound.h @@ -52,7 +52,7 @@ public: Sound(SherlockEngine *vm); void loadSound(const Common::String &name, int priority); - void playSound(const Common::String &name, WaitType waitType = WAIT_RETURN_IMMEDIATELY); + bool playSound(const Common::String &name, WaitType waitType = WAIT_RETURN_IMMEDIATELY); void cacheSound(const Common::String &name, int index); void playLoadedSound(int bufNum, int waitMode); void playCachedSound(int index); -- cgit v1.2.3 From 7e1e0ed3ac7ca8b3233503476162c1ca1e79e0a8 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 21 Apr 2015 01:12:16 -0500 Subject: SHERLOCK: More darts game logic --- engines/sherlock/scalpel/darts.cpp | 203 ++++++++++++++++++++++++++++++++++--- engines/sherlock/scalpel/darts.h | 6 +- engines/sherlock/sound.cpp | 3 + engines/sherlock/sound.h | 1 + 4 files changed, 197 insertions(+), 16 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/scalpel/darts.cpp b/engines/sherlock/scalpel/darts.cpp index c975cb1086..c3f2c478d7 100644 --- a/engines/sherlock/scalpel/darts.cpp +++ b/engines/sherlock/scalpel/darts.cpp @@ -67,6 +67,7 @@ Darts::Darts(ScalpelEngine *vm) : _vm(vm) { * Main method for playing darts game */ void Darts::playDarts() { + Events &events = *_vm->_events; Screen &screen = *_vm->_screen; int score, roundStartScore; int playerNumber = 0; @@ -79,6 +80,7 @@ void Darts::playDarts() { loadDarts(); initDarts(); + bool done = false; do { roundStartScore = score = playerNumber == 0 ? _dartScore1 : _dartScore2; @@ -99,13 +101,81 @@ void Darts::playDarts() { score -= lastDart; _roundScore += lastDart; + screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(DART_INFO_X, DART_INFO_Y - 1), + Common::Rect(DART_INFO_X, DART_INFO_Y - 1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); + screen.print(Common::Point(DART_INFO_X, DART_INFO_Y), DART_COL_FORE, "Dart # %d", idx + 1); + screen.print(Common::Point(DART_INFO_X, DART_INFO_Y + 10), DART_COL_FORE, "Scored %d points", lastDart); + + if (score != 0 && playerNumber == 0) + screen.print(Common::Point(DART_INFO_X, DART_INFO_Y + 30), DART_COL_FORE, "Press a key"); + + if (score == 0) { + // Some-one has won + screen.print(Common::Point(DART_INFO_X, DART_INFO_Y + 20), PLAYER_COLOR, "GAME OVER!"); + + if (playerNumber == 0) { + screen.print(Common::Point(DART_INFO_X, DART_INFO_Y + 30), PLAYER_COLOR, "Holmes Wins!"); + if (_level < 4) + setFlagsForDarts(318 + _level); + } else { + screen.print(Common::Point(DART_INFO_X, DART_INFO_Y + 30), PLAYER_COLOR, "%s Wins!", _opponent.c_str()); + } + + screen.print(Common::Point(DART_INFO_X, DART_INFO_Y + 4), DART_COL_FORE, "Press a key"); + + idx = 10; + done = true; + } else if (score < 0) { + screen.print(Common::Point(DART_INFO_X, DART_INFO_Y + 20), PLAYER_COLOR, "BUSTED!"); + + idx = 10; + score = roundStartScore; + } + + if (playerNumber == 0) + _dartScore1 = score; + else + _dartScore2 = score; + + showStatus(playerNumber); + events.clearKeyboard(); + if ((playerNumber == 0 && _computerPlayer == 1) || _computerPlayer == 0 || done) { + int dartKey; + while (!(dartKey = dartHit()) && !_vm->shouldQuit()) + events.delay(10); + + if (dartKey == Common::KEYCODE_ESCAPE) { + idx = 10; + done = true; + } + } else { + events.wait(20); + } + + screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(DART_INFO_X, DART_INFO_Y - 1), + Common::Rect(DART_INFO_X, DART_INFO_Y - 1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); + screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT); } - // todo - } while (!_vm->shouldQuit()); + playerNumber ^= 1; + if (!playerNumber) + ++_roundNumber; + + done |= _vm->shouldQuit(); - // TODO + if (!done) { + screen._backBuffer2.blitFrom((*_dartImages)[1], Common::Point(0, 0)); + screen._backBuffer1.blitFrom(screen._backBuffer2); + screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT); + } + } while (!done); + + closeDarts(); + screen.fadeToBlack(); + + // Restore font + screen.setFont(oldFont); } /** @@ -144,6 +214,14 @@ void Darts::initDarts() { _opponent = OPPONENT_NAMES[_level]; } +/** + * Frees the images used by the dart game + */ +void Darts::closeDarts() { + delete _dartImages; + _dartImages = nullptr; +} + /** * Show the player names */ @@ -236,8 +314,8 @@ int Darts::throwDart(int dartNum, int computer) { if (computer) targetNum = getComputerDartDest(computer - 1); - width = doPowerBar(Common::Point(DARTBARHX, DARTHORIZY), DART_BAR_FORE, targetNum.x, 0); - height = 101 - doPowerBar(Common::Point(DARTBARVX, DARTHEIGHTY), DART_BAR_FORE, targetNum.y, 0); + width = doPowerBar(Common::Point(DARTBARHX, DARTHORIZY), DART_BAR_FORE, targetNum.x, false); + height = 101 - doPowerBar(Common::Point(DARTBARVX, DARTHEIGHTY), DART_BAR_FORE, targetNum.y, true); // For human players, slight y adjustment if (computer == 0) @@ -263,7 +341,43 @@ int Darts::throwDart(int dartNum, int computer) { * Draw a dart moving towards the board */ void Darts::drawDartThrow(const Common::Point &pt) { - // TODO + Events &events = *_vm->_events; + Screen &screen = *_vm->_screen; + Common::Point pos(pt.x, pt.y + 2); + Common::Rect oldDrawBounds; + int delta = 9; + + for (int idx = 5; idx < 24; ++idx) { + Graphics::Surface &frame = (*_dartImages)[idx]._frame; + + // Adjust draw position for animating dart + if (idx < 14) + pos.y -= delta--; + else if (idx == 14) + delta = 1; + else + pos.y += delta++; + + // Draw the dart + Common::Point drawPos(pos.x - frame.w / 2, pos.y - frame.h); + screen._backBuffer1.transBlitFrom(frame, drawPos); + screen.slamArea(drawPos.x, drawPos.y, frame.w, frame.h); + + // Handle erasing old dart + if (!oldDrawBounds.isEmpty()) + screen.slamRect(oldDrawBounds); + + oldDrawBounds = Common::Rect(drawPos.x, drawPos.y, drawPos.x + frame.w, drawPos.y + frame.h); + if (idx != 23) + screen._backBuffer1.blitFrom(screen._backBuffer2, drawPos, oldDrawBounds); + + events.wait(2); + } + + // Draw dart in final "stuck to board" form + screen._backBuffer1.transBlitFrom((*_dartImages)[23], Common::Point(oldDrawBounds.left, oldDrawBounds.top)); + screen._backBuffer2.transBlitFrom((*_dartImages)[23], Common::Point(oldDrawBounds.left, oldDrawBounds.top)); + screen.slamRect(oldDrawBounds); } /** @@ -285,32 +399,86 @@ void Darts::erasePowerBars() { * increment to that power level ignoring all keyboard input (ie. for computer throws). * Otherwise, it will increment until either a key/mouse button is pressed, or it reaches the end */ -int Darts::doPowerBar(const Common::Point &pt, byte color, int goToPower, int orientation) { - // TODO - return 0; +int Darts::doPowerBar(const Common::Point &pt, byte color, int goToPower, bool isVertical) { + Events &events = *_vm->_events; + Screen &screen = *_vm->_screen; + Sound &sound = *_vm->_sound; + bool done; + int idx = 0; + + events.clearEvents(); + if (sound._musicOn) + sound.waitTimerRoland(10); + else + events.delay(100); + + // Display loop + do { + done = _vm->shouldQuit() || idx >= DARTBARSIZE; + + if (idx == (goToPower - 1)) + // Reached target power for a computer player + done = true; + else if (goToPower == 0) { + // Check for pres + if (dartHit()) + done = true; + } + + if (isVertical) { + screen._backBuffer1.hLine(pt.x, pt.y + DARTBARSIZE - 1 - idx, pt.x + 8, color); + screen._backBuffer1.transBlitFrom((*_dartImages)[4], Common::Point(pt.x - 1, pt.y - 1)); + screen.slamArea(pt.x, pt.y + DARTBARSIZE - 1 - idx, 8, 2); + } else { + screen._backBuffer1.vLine(pt.x + idx, pt.y, pt.y + 8, color); + screen._backBuffer1.transBlitFrom((*_dartImages)[3], Common::Point(pt.x - 1, pt.y - 1)); + screen.slamArea(pt.x + idx, pt.y, 1, 8); + } + + if (sound._musicOn) { + if (!(idx % 3)) + sound.waitTimerRoland(1); + } else { + if (!(idx % 8)) + events.wait(1); + } + + ++idx; + } while (!done); + + return MIN(idx * 100 / DARTBARSIZE, 100); } /** * Returns true if a mouse button or key is pressed. */ -bool Darts::dartHit() { +int Darts::dartHit() { Events &events = *_vm->_events; if (events.kbHit()) { + Common::KeyState keyState = events.getKey(); + events.clearKeyboard(); - return true; + return keyState.keycode; } events.setButtonState(); - return events._pressed && !_oldDartButtons; + return events._pressed && !_oldDartButtons ? 1 : 0; } /** * Return the score of the given location on the dart-board */ int Darts::dartScore(const Common::Point &pt) { - // TODO - return 0; + Common::Point pos(pt.x - 37, pt.y - 33); + + if (pos.x < 0 || pos.y < 0 || pos.x >= 147 || pt.y >= 132) + // Not on the board + return 0; + + // On board, so get the score from the pixel at that position + int score = *(const byte *)(*_dartImages)[2]._frame.getBasePtr(pos.x, pos.y); + return score; } /** @@ -415,6 +583,13 @@ bool Darts::findNumberOnBoard(int aim, Common::Point &pt) { return done; } +/** + * Set a global flag to 0 or 1 depending on whether the passed flag is negative or positive. + * @remarks We don't use the global setFlags method because we don't want to check scene flags + */ +void Darts::setFlagsForDarts(int flagNum) { + _vm->_flags[ABS(flagNum)] = flagNum >= 0; +} } // End of namespace Scalpel diff --git a/engines/sherlock/scalpel/darts.h b/engines/sherlock/scalpel/darts.h index 2fbdc3d7e2..a6c8cdba6d 100644 --- a/engines/sherlock/scalpel/darts.h +++ b/engines/sherlock/scalpel/darts.h @@ -46,6 +46,7 @@ private: void loadDarts(); void initDarts(); + void closeDarts(); void showNames(int playerNum); void showStatus(int playerNum); @@ -54,15 +55,16 @@ private: void drawDartThrow(const Common::Point &pt); void erasePowerBars(); - int doPowerBar(const Common::Point &pt, byte color, int goToPower, int orientation); + int doPowerBar(const Common::Point &pt, byte color, int goToPower, bool isVertical); - bool dartHit(); + int dartHit(); int dartScore(const Common::Point &pt); Common::Point getComputerDartDest(int playerNum); bool findNumberOnBoard(int aim, Common::Point &pt); + void setFlagsForDarts(int flagNum); public: Darts(ScalpelEngine *vm); diff --git a/engines/sherlock/sound.cpp b/engines/sherlock/sound.cpp index 600618b570..1a6472a9e9 100644 --- a/engines/sherlock/sound.cpp +++ b/engines/sherlock/sound.cpp @@ -95,5 +95,8 @@ void Sound::stopSndFuncPtr(int v1, int v2) { // TODO } +void Sound::waitTimerRoland(uint time) { + // TODO +} } // End of namespace Sherlock diff --git a/engines/sherlock/sound.h b/engines/sherlock/sound.h index 6adc22c01c..28de692109 100644 --- a/engines/sherlock/sound.h +++ b/engines/sherlock/sound.h @@ -66,6 +66,7 @@ public: void playMusic(const Common::String &name); void stopMusic(); void stopSndFuncPtr(int v1, int v2); + void waitTimerRoland(uint time); }; } // End of namespace Sherlock -- cgit v1.2.3 From 6d2bde38ec883f00b9e4254f869e6349b21e0d28 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 21 Apr 2015 01:26:47 -0500 Subject: SHERLOCK: Fix display of cursor --- engines/sherlock/events.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines') diff --git a/engines/sherlock/events.cpp b/engines/sherlock/events.cpp index 79fe1b58d4..1a827eda3b 100644 --- a/engines/sherlock/events.cpp +++ b/engines/sherlock/events.cpp @@ -76,6 +76,7 @@ void Events::setCursor(CursorId cursorId) { */ void Events::setCursor(const Graphics::Surface &src) { CursorMan.replaceCursor(src.getPixels(), src.w, src.h, 0, 0, 0xff); + showCursor(); } /** -- cgit v1.2.3 From a81686b0e1108fc5e9cac79e8e5890ad8c0f8c23 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 21 Apr 2015 02:06:24 -0500 Subject: SHERLOCK: Fix Setup dialog button handling --- engines/sherlock/sherlock.h | 1 - engines/sherlock/user_interface.cpp | 18 +++++++++++------- engines/sherlock/user_interface.h | 2 +- 3 files changed, 12 insertions(+), 9 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h index 42e2cf8b38..67c7a2864d 100644 --- a/engines/sherlock/sherlock.h +++ b/engines/sherlock/sherlock.h @@ -105,7 +105,6 @@ public: Common::Point _over; // Old map position bool _onChessboard; bool _slowChess; - bool _joystick; int _keyPadSpeed; public: SherlockEngine(OSystem *syst, const SherlockGameDescription *gameDesc); diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index 43ae76f94b..3ab705e26c 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -146,7 +146,8 @@ void Settings::drawInteface(bool flag) { SETUP_POINTS[4][3] - screen.stringWidth(tempStr) / 2, tempStr); screen.makeButton(Common::Rect(SETUP_POINTS[5][0], SETUP_POINTS[5][1], SETUP_POINTS[5][2], SETUP_POINTS[5][1] + 10), SETUP_POINTS[5][3] - screen.stringWidth("New Font Style") / 2, "New Font Style"); - tempStr = Common::String::format("Joystick %s", SETUP_STRS0[_vm->_joystick ? 1 : 0]); + + tempStr = Common::String::format("Joystick %s", SETUP_STRS0[0]); screen.makeButton(Common::Rect(SETUP_POINTS[6][0], SETUP_POINTS[6][1], SETUP_POINTS[6][2], SETUP_POINTS[6][1] + 10), SETUP_POINTS[6][3] - screen.stringWidth(tempStr) / 2, tempStr); screen.makeButton(Common::Rect(SETUP_POINTS[7][0], SETUP_POINTS[7][1], SETUP_POINTS[7][2], SETUP_POINTS[7][1] + 10), @@ -221,7 +222,7 @@ int Settings::drawButtons(const Common::Point &pt, int key) { screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr); break; case 6: - tempStr = Common::String::format("Joystick %s", SETUP_STRS0[_vm->_joystick]); + tempStr = Common::String::format("Joystick %s", SETUP_STRS0[0]); screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr); break; case 8: @@ -1793,16 +1794,19 @@ void UserInterface::doControls() { if ((found == 5 && events._released) || _key == 'N') { // New font style - screen.setFont((screen.fontNumber() + 1) & 3); - } + int fontNum = screen.fontNumber() + 1; + if (fontNum == 3) + fontNum = 0; - if ((found == 6 && events._released) || _key == 'J') { - // Toggle joystick - _vm->_joystick = !_vm->_joystick; + screen.setFont(fontNum); updateConfig = true; settings.drawInteface(true); } + if ((found == 6 && events._released) || _key == 'J') { + // Toggle joystick - not implemented under ScummVM + } + if ((found == 7 && events._released) || _key == 'C') { // Calibrate joystick - No implementation in ScummVM } diff --git a/engines/sherlock/user_interface.h b/engines/sherlock/user_interface.h index 23aca4e536..211287c372 100644 --- a/engines/sherlock/user_interface.h +++ b/engines/sherlock/user_interface.h @@ -67,7 +67,7 @@ class Settings { private: SherlockEngine *_vm; public: - Settings(SherlockEngine *vm) : _vm() {} + Settings(SherlockEngine *vm) : _vm(vm) {} void drawInteface(bool flag); -- cgit v1.2.3 From 6fe65dc719f69c3a3cd3a90426e148972716037f Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 21 Apr 2015 03:48:21 -0500 Subject: SHERLOCK: Beginnins of SaveManager class --- engines/sherlock/detection.cpp | 8 +- engines/sherlock/module.mk | 1 + engines/sherlock/saveload.cpp | 183 +++++++++++++++++++++++++++++++++++++++++ engines/sherlock/saveload.h | 74 +++++++++++++++++ 4 files changed, 261 insertions(+), 5 deletions(-) create mode 100644 engines/sherlock/saveload.cpp create mode 100644 engines/sherlock/saveload.h (limited to 'engines') diff --git a/engines/sherlock/detection.cpp b/engines/sherlock/detection.cpp index f207bb69d9..7d9db96e77 100644 --- a/engines/sherlock/detection.cpp +++ b/engines/sherlock/detection.cpp @@ -21,14 +21,13 @@ */ #include "sherlock/sherlock.h" +#include "sherlock/saveload.h" #include "sherlock/scalpel/scalpel.h" #include "sherlock/tattoo/tattoo.h" #include "engines/advancedDetector.h" namespace Sherlock { -#define MAX_SAVES 99 - struct SherlockGameDescription { ADGameDescription desc; @@ -102,12 +101,11 @@ bool SherlockMetaEngine::hasFeature(MetaEngineFeature f) const { } SaveStateList SherlockMetaEngine::listSaves(const char *target) const { - SaveStateList saveList; - return saveList; + return Sherlock::SaveManager(nullptr, "").getSavegameList(target); } int SherlockMetaEngine::getMaximumSaveSlot() const { - return MAX_SAVES; + return NUM_SAVEGAME_SLOTS; } void SherlockMetaEngine::removeSaveState(const char *target, int slot) const { diff --git a/engines/sherlock/module.mk b/engines/sherlock/module.mk index 171f704a1e..44ba63f1e2 100644 --- a/engines/sherlock/module.mk +++ b/engines/sherlock/module.mk @@ -16,6 +16,7 @@ MODULE_OBJS = \ objects.o \ people.o \ resources.o \ + saveload.o \ scene.o \ screen.o \ sherlock.o \ diff --git a/engines/sherlock/saveload.cpp b/engines/sherlock/saveload.cpp new file mode 100644 index 0000000000..54995e056a --- /dev/null +++ b/engines/sherlock/saveload.cpp @@ -0,0 +1,183 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "sherlock/saveload.h" +#include "sherlock/graphics.h" +#include "sherlock/sherlock.h" +#include "common/system.h" +#include "graphics/scaler.h" +#include "graphics/thumbnail.h" + +namespace Sherlock { + +SaveManager::SaveManager(SherlockEngine *vm, const Common::String &target) : + _vm(vm), _target(target) { + _saveThumb = nullptr; +} + +SaveManager::~SaveManager() { + if (_saveThumb) { + _saveThumb->free(); + delete _saveThumb; + } +} + +/** + * Shows the in-game dialog interface for loading and saving games + */ +void SaveManager::show() { + createSavegameList(); + + // TODO +} + +/** + * Build up a savegame list, with empty slots given an explicit Empty message + */ +void SaveManager::createSavegameList() { + _savegames.clear(); + for (int idx = 0; idx < NUM_SAVEGAME_SLOTS; ++idx) + _savegames.push_back("-EMPTY"); + + SaveStateList saveList = getSavegameList(_target); + for (uint idx = 0; idx < saveList.size(); ++idx) + _savegames[saveList[idx].getSaveSlot()] = saveList[idx].getDescription(); +} + +/** + * Load a list of savegames + */ +SaveStateList SaveManager::getSavegameList(const Common::String &target) { + Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); + Common::StringArray filenames; + Common::String saveDesc; + Common::String pattern = Common::String::format("%s.0??", target.c_str()); + SherlockSavegameHeader header; + + filenames = saveFileMan->listSavefiles(pattern); + sort(filenames.begin(), filenames.end()); // Sort to get the files in numerical order + + SaveStateList saveList; + for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) { + const char *ext = strrchr(file->c_str(), '.'); + int slot = ext ? atoi(ext + 1) : -1; + + if (slot >= 0 && slot < NUM_SAVEGAME_SLOTS) { + Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(*file); + + if (in) { + readSavegameHeader(in, header); + saveList.push_back(SaveStateDescriptor(slot, header._saveName)); + + header._thumbnail->free(); + delete header._thumbnail; + delete in; + } + } + } + + return saveList; +} + +const char *const SAVEGAME_STR = "SHLK"; +#define SAVEGAME_STR_SIZE 4 + +bool SaveManager::readSavegameHeader(Common::InSaveFile *in, SherlockSavegameHeader &header) { + char saveIdentBuffer[SAVEGAME_STR_SIZE + 1]; + header._thumbnail = nullptr; + + // Validate the header Id + in->read(saveIdentBuffer, SAVEGAME_STR_SIZE + 1); + if (strncmp(saveIdentBuffer, SAVEGAME_STR, SAVEGAME_STR_SIZE)) + return false; + + header._version = in->readByte(); + if (header._version > SHERLOCK_SAVEGAME_VERSION) + return false; + + // Read in the string + header._saveName.clear(); + char ch; + while ((ch = (char)in->readByte()) != '\0') header._saveName += ch; + + // Get the thumbnail + header._thumbnail = Graphics::loadThumbnail(*in); + if (!header._thumbnail) + return false; + + // Read in save date/time + header._year = in->readSint16LE(); + header._month = in->readSint16LE(); + header._day = in->readSint16LE(); + header._hour = in->readSint16LE(); + header._minute = in->readSint16LE(); + header._totalFrames = in->readUint32LE(); + + return true; +} + +void SaveManager::writeSavegameHeader(Common::OutSaveFile *out, SherlockSavegameHeader &header) { + // Write out a savegame header + out->write(SAVEGAME_STR, SAVEGAME_STR_SIZE + 1); + + out->writeByte(SHERLOCK_SAVEGAME_VERSION); + + // Write savegame name + out->write(header._saveName.c_str(), header._saveName.size()); + out->writeByte('\0'); + + // Handle the thumbnail. If there's already one set by the game, create one + if (!_saveThumb) + createThumbnail(); + Graphics::saveThumbnail(*out, *_saveThumb); + + _saveThumb->free(); + delete _saveThumb; + _saveThumb = nullptr; + + // Write out the save date/time + TimeDate td; + g_system->getTimeAndDate(td); + out->writeSint16LE(td.tm_year + 1900); + out->writeSint16LE(td.tm_mon + 1); + out->writeSint16LE(td.tm_mday); + out->writeSint16LE(td.tm_hour); + out->writeSint16LE(td.tm_min); + out->writeUint32LE(_vm->_events->getFrameCounter()); +} + +/** + * Creates a thumbnail for the current on-screen contents + */ +void SaveManager::createThumbnail() { + if (_saveThumb) { + _saveThumb->free(); + delete _saveThumb; + } + + uint8 thumbPalette[PALETTE_SIZE]; + _vm->_screen->getPalette(thumbPalette); + _saveThumb = new Graphics::Surface(); + ::createThumbnail(_saveThumb, (const byte *)_vm->_screen->getPixels(), SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT, thumbPalette); +} + +} // End of namespace Sherlock diff --git a/engines/sherlock/saveload.h b/engines/sherlock/saveload.h new file mode 100644 index 0000000000..a0f1da4041 --- /dev/null +++ b/engines/sherlock/saveload.h @@ -0,0 +1,74 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef SHERLOCK_SAVELOAD_H +#define SHERLOCK_SAVELOAD_H + +#include "common/scummsys.h" +#include "common/savefile.h" +#include "common/str-array.h" +#include "engines/savestate.h" +#include "graphics/surface.h" + +namespace Sherlock { + +#define NUM_SAVEGAME_SLOTS 99 +#define SHERLOCK_SAVEGAME_VERSION 1 + +struct SherlockSavegameHeader { + uint8 _version; + Common::String _saveName; + Graphics::Surface *_thumbnail; + int _year, _month, _day; + int _hour, _minute; + int _totalFrames; +}; + +class SherlockEngine; + +class SaveManager { +private: + SherlockEngine *_vm; + Common::String _target; + Common::StringArray _savegames; + Graphics::Surface *_saveThumb; + + void createSavegameList(); +public: + SaveManager(SherlockEngine *vm, const Common::String &target); + ~SaveManager(); + + void show(); + + void createThumbnail(); + + static SaveStateList getSavegameList(const Common::String &target); + + void writeSavegameHeader(Common::OutSaveFile *out, SherlockSavegameHeader &header); + + static bool readSavegameHeader(Common::InSaveFile *in, SherlockSavegameHeader &header); + +}; + +} // End of namespace Sherlock + +#endif -- cgit v1.2.3 From 09014d5b96b625f7691bbda3ded24dfa386863d5 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Tue, 21 Apr 2015 14:42:55 +0200 Subject: SCI: fix bug in new workaround sig code --- engines/sci/engine/workarounds.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index b33457606e..c5d85b8c5b 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -804,9 +804,9 @@ SciWorkaroundSolution trackOriginAndFindWorkaround(int index, const SciWorkaroun && workaround->methodName == g_sci->getSciLanguageString(curMethodName, K_LANG_ENGLISH) && ((workaround->index == -1) || (workaround->index == index))) { // Workaround found - if ((workaround->localCallSignature) || (curLocalCallOffset != -1)) { + if ((workaround->localCallSignature) || (curLocalCallOffset >= 0)) { // local call signature found and/or subcall was made - if ((workaround->localCallSignature) && (lastCall->debugLocalCallOffset)) { + if ((workaround->localCallSignature) && (curLocalCallOffset >= 0)) { // local call signature found and subcall was made -> check signature accordingly if (!curScriptPtr) { // get script data -- cgit v1.2.3 From cfcaba92841d17a265e028d95ff61b289beccbca Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Tue, 21 Apr 2015 14:55:05 +0200 Subject: SCI: kDoBresen adjustments for SCI<=1_EGA, thx wjp --- engines/sci/engine/kmovement.cpp | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kmovement.cpp b/engines/sci/engine/kmovement.cpp index 51d49eea9f..9b83dbc52d 100644 --- a/engines/sci/engine/kmovement.cpp +++ b/engines/sci/engine/kmovement.cpp @@ -305,12 +305,23 @@ reg_t kDoBresen(EngineState *s, int argc, reg_t *argv) { for (uint i = 0; i < clientVarNum; ++i) clientBackup[i] = clientObject->getVariable(i); - if (mover_xAxis) { - if (ABS(mover_x - client_x) < ABS(mover_dx)) - completed = true; + if ((getSciVersion() <= SCI_VERSION_1_EGA_ONLY)) { + if (mover_xAxis) { + if (ABS(mover_x - client_x) < ABS(mover_dx)) + completed = true; + } else { + if (ABS(mover_y - client_y) < ABS(mover_dy)) + completed = true; + } } else { - if (ABS(mover_y - client_y) < ABS(mover_dy)) - completed = true; + // SCI1EARLY+ code + if (mover_xAxis) { + if (ABS(mover_x - client_x) <= ABS(mover_dx)) + completed = true; + } else { + if (ABS(mover_y - client_y) <= ABS(mover_dy)) + completed = true; + } } if (completed) { client_x = mover_x; @@ -336,10 +347,10 @@ reg_t kDoBresen(EngineState *s, int argc, reg_t *argv) { bool collision = false; reg_t cantBeHere = NULL_REG; + // adding this here for hoyle 3 to get happy. CantBeHere is a dummy in hoyle 3 and acc is != 0 so we would + // get a collision otherwise. Resetting the result was always done in SSCI + s->r_acc = NULL_REG; if (SELECTOR(cantBeHere) != -1) { - // adding this here for hoyle 3 to get happy. CantBeHere is a dummy in hoyle 3 and acc is != 0 so we would - // get a collision otherwise - s->r_acc = NULL_REG; invokeSelector(s, client, SELECTOR(cantBeHere), argc, argv); if (!s->r_acc.isNull()) collision = true; -- cgit v1.2.3 From 31860163709b12a38856fc017a217eb5e32610a7 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 21 Apr 2015 18:25:06 -0500 Subject: SHERLOCK: Implemented save game dialog event handling --- engines/sherlock/detection.cpp | 23 ++- engines/sherlock/saveload.cpp | 185 +++++++++++++++++++- engines/sherlock/saveload.h | 23 ++- engines/sherlock/sherlock.cpp | 3 + engines/sherlock/sherlock.h | 2 + engines/sherlock/user_interface.cpp | 325 ++++++++++++++++++++++++++++++++++-- engines/sherlock/user_interface.h | 3 +- 7 files changed, 540 insertions(+), 24 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/detection.cpp b/engines/sherlock/detection.cpp index 7d9db96e77..bb66cee7df 100644 --- a/engines/sherlock/detection.cpp +++ b/engines/sherlock/detection.cpp @@ -24,6 +24,7 @@ #include "sherlock/saveload.h" #include "sherlock/scalpel/scalpel.h" #include "sherlock/tattoo/tattoo.h" +#include "common/system.h" #include "engines/advancedDetector.h" namespace Sherlock { @@ -105,13 +106,33 @@ SaveStateList SherlockMetaEngine::listSaves(const char *target) const { } int SherlockMetaEngine::getMaximumSaveSlot() const { - return NUM_SAVEGAME_SLOTS; + return MAX_SAVEGAME_SLOTS; } void SherlockMetaEngine::removeSaveState(const char *target, int slot) const { + Common::String filename = Common::String::format("%s.%03d", target, slot); + g_system->getSavefileManager()->removeSavefile(filename); } SaveStateDescriptor SherlockMetaEngine::querySaveMetaInfos(const char *target, int slot) const { + Common::String filename = Common::String::format("%s.%03d", target, slot); + Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading(filename); + + if (f) { + Sherlock::SherlockSavegameHeader header; + Sherlock::SaveManager::readSavegameHeader(f, header); + delete f; + + // Create the return descriptor + SaveStateDescriptor desc(slot, header._saveName); + desc.setThumbnail(header._thumbnail); + desc.setSaveDate(header._year, header._month, header._day); + desc.setSaveTime(header._hour, header._minute); + desc.setPlayTime(header._totalFrames * GAME_FRAME_TIME); + + return desc; + } + return SaveStateDescriptor(); } diff --git a/engines/sherlock/saveload.cpp b/engines/sherlock/saveload.cpp index 54995e056a..78c86c836e 100644 --- a/engines/sherlock/saveload.cpp +++ b/engines/sherlock/saveload.cpp @@ -29,9 +29,21 @@ namespace Sherlock { +const int ENV_POINTS[6][3] = { + { 41, 80, 61 }, // Exit + { 81, 120, 101 }, // Load + { 121, 160, 141 }, // Save + { 161, 200, 181 }, // Up + { 201, 240, 221 }, // Down + { 241, 280, 261 } // Quit +}; + +/*----------------------------------------------------------------*/ + SaveManager::SaveManager(SherlockEngine *vm, const Common::String &target) : _vm(vm), _target(target) { _saveThumb = nullptr; + _envMode = SAVEMODE_NONE; } SaveManager::~SaveManager() { @@ -44,23 +56,80 @@ SaveManager::~SaveManager() { /** * Shows the in-game dialog interface for loading and saving games */ -void SaveManager::show() { +void SaveManager::drawInterface() { + Screen &screen = *_vm->_screen; + UserInterface &ui = *_vm->_ui; + + // Create a list of savegame slots createSavegameList(); - // TODO + screen._backBuffer1.fillRect(Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, CONTROLS_Y + 10), BORDER_COLOR); + screen._backBuffer1.fillRect(Common::Rect(0, CONTROLS_Y + 10, 2, SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR); + screen._backBuffer1.fillRect(Common::Rect(318, CONTROLS_Y + 10, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR); + screen._backBuffer1.fillRect(Common::Rect(0, 199, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR); + screen._backBuffer1.fillRect(Common::Rect(2, CONTROLS_Y + 10, SHERLOCK_SCREEN_WIDTH - 2, SHERLOCK_SCREEN_HEIGHT - 2), INV_BACKGROUND); + + screen.makeButton(Common::Rect(ENV_POINTS[0][0], CONTROLS_Y, ENV_POINTS[0][1], CONTROLS_Y + 10), + ENV_POINTS[0][2] - screen.stringWidth("Exit") / 2, "Exit"); + screen.makeButton(Common::Rect(ENV_POINTS[1][0], CONTROLS_Y, ENV_POINTS[1][1], CONTROLS_Y + 10), + ENV_POINTS[1][2] - screen.stringWidth("Load") / 2, "Load"); + screen.makeButton(Common::Rect(ENV_POINTS[2][0], CONTROLS_Y, ENV_POINTS[2][1], CONTROLS_Y + 10), + ENV_POINTS[2][2] - screen.stringWidth("Save") / 2, "Save"); + screen.makeButton(Common::Rect(ENV_POINTS[3][0], CONTROLS_Y, ENV_POINTS[3][1], CONTROLS_Y + 10), + ENV_POINTS[3][2] - screen.stringWidth("Up") / 2, "Up"); + screen.makeButton(Common::Rect(ENV_POINTS[4][0], CONTROLS_Y, ENV_POINTS[4][1], CONTROLS_Y + 10), + ENV_POINTS[4][2] - screen.stringWidth("Down") / 2, "Down"); + screen.makeButton(Common::Rect(ENV_POINTS[5][0], CONTROLS_Y, ENV_POINTS[5][1], CONTROLS_Y + 10), + ENV_POINTS[5][2] - screen.stringWidth("Quit") / 2, "Quit"); + + if (!_savegameIndex) + screen.buttonPrint(Common::Point(ENV_POINTS[3][2], CONTROLS_Y), COMMAND_NULL, 0, "Up"); + + if (_savegameIndex == MAX_SAVEGAME_SLOTS - 5) + screen.buttonPrint(Common::Point(ENV_POINTS[4][2], CONTROLS_Y), COMMAND_NULL, 0, "Down"); + + for (int idx = _savegameIndex; idx < _savegameIndex + 5; ++idx) + { + screen.gPrint(Common::Point(6, CONTROLS_Y + 11 + (idx - _savegameIndex) * 10), + INV_FOREGROUND, "%d.", idx + 1); + screen.gPrint(Common::Point(24, CONTROLS_Y + 11 + (idx - _savegameIndex) * 10), + INV_FOREGROUND, "%s", _savegames[idx]); + } + + if (!ui._windowStyle) { + screen.slamRect(Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); + } else { + ui.summonWindow(); + } + + _envMode = SAVEMODE_NONE; } /** * Build up a savegame list, with empty slots given an explicit Empty message */ void SaveManager::createSavegameList() { + Screen &screen = *_vm->_screen; + _savegames.clear(); - for (int idx = 0; idx < NUM_SAVEGAME_SLOTS; ++idx) + for (int idx = 0; idx < MAX_SAVEGAME_SLOTS; ++idx) _savegames.push_back("-EMPTY"); SaveStateList saveList = getSavegameList(_target); for (uint idx = 0; idx < saveList.size(); ++idx) _savegames[saveList[idx].getSaveSlot()] = saveList[idx].getDescription(); + + // Ensure the names will fit on the screen + for (uint idx = 0; idx < _savegames.size(); ++idx) { + int width = screen.stringWidth(_savegames[idx]) + 24; + if (width > 308) { + // It won't fit in, so remove characters until it does + do { + width -= screen.charWidth(_savegames[idx].lastChar()); + _savegames[idx].deleteLastChar(); + } while (width > 300); + } + } } /** @@ -81,7 +150,7 @@ SaveStateList SaveManager::getSavegameList(const Common::String &target) { const char *ext = strrchr(file->c_str(), '.'); int slot = ext ? atoi(ext + 1) : -1; - if (slot >= 0 && slot < NUM_SAVEGAME_SLOTS) { + if (slot >= 0 && slot < MAX_SAVEGAME_SLOTS) { Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(*file); if (in) { @@ -101,6 +170,9 @@ SaveStateList SaveManager::getSavegameList(const Common::String &target) { const char *const SAVEGAME_STR = "SHLK"; #define SAVEGAME_STR_SIZE 4 +/** + * Read in the header information for a savegame + */ bool SaveManager::readSavegameHeader(Common::InSaveFile *in, SherlockSavegameHeader &header) { char saveIdentBuffer[SAVEGAME_STR_SIZE + 1]; header._thumbnail = nullptr; @@ -135,6 +207,9 @@ bool SaveManager::readSavegameHeader(Common::InSaveFile *in, SherlockSavegameHea return true; } +/** + * Write out the header information for a savegame + */ void SaveManager::writeSavegameHeader(Common::OutSaveFile *out, SherlockSavegameHeader &header) { // Write out a savegame header out->write(SAVEGAME_STR, SAVEGAME_STR_SIZE + 1); @@ -180,4 +255,106 @@ void SaveManager::createThumbnail() { ::createThumbnail(_saveThumb, (const byte *)_vm->_screen->getPixels(), SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT, thumbPalette); } +/** + * Return the index of the button the mouse is over, if any + */ +int SaveManager::getHighlightedButton() const { + Common::Point pt = _vm->_events->mousePos(); + + for (int idx = 0; idx < 6; ++idx) { + if (pt.x > ENV_POINTS[idx][0] && pt.x < ENV_POINTS[idx][1] && pt.y > CONTROLS_Y + && pt.y < (CONTROLS_Y + 10)) + return idx; + } + + return -1; +} + +/** + * Handle highlighting buttons + */ +void SaveManager::highlightButtons(int btnIndex) { + Screen &screen = *_vm->_screen; + byte color = (btnIndex == 0) ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND; + + screen.buttonPrint(Common::Point(ENV_POINTS[0][2], CONTROLS_Y), color, 1, "Exit"); + + if ((btnIndex == 1) || ((_envMode == 1) && (btnIndex != 2))) + screen.buttonPrint(Common::Point(ENV_POINTS[1][2], CONTROLS_Y), COMMAND_HIGHLIGHTED, true, "Load"); + else + screen.buttonPrint(Common::Point(ENV_POINTS[1][2], CONTROLS_Y), COMMAND_FOREGROUND, true, "Load"); + + if ((btnIndex == 2) || ((_envMode == 2) && (btnIndex != 1))) + screen.buttonPrint(Common::Point(ENV_POINTS[2][2], CONTROLS_Y), COMMAND_HIGHLIGHTED, true, "Save"); + else + screen.buttonPrint(Common::Point(ENV_POINTS[2][2], CONTROLS_Y), COMMAND_FOREGROUND, true, "Save"); + + if (btnIndex == 3 && _savegameIndex) + screen.buttonPrint(Common::Point(ENV_POINTS[3][2], CONTROLS_Y), COMMAND_HIGHLIGHTED, true, "Up"); + else + if (_savegameIndex) + screen.buttonPrint(Common::Point(ENV_POINTS[3][2], CONTROLS_Y), COMMAND_FOREGROUND, true, "Up"); + + if ((btnIndex == 4) && (_savegameIndex < MAX_SAVEGAME_SLOTS - 5)) + screen.buttonPrint(Common::Point(ENV_POINTS[4][2], CONTROLS_Y), COMMAND_HIGHLIGHTED, true, "Down"); + else if (_savegameIndex < (MAX_SAVEGAME_SLOTS - 5)) + screen.buttonPrint(Common::Point(ENV_POINTS[4][2], CONTROLS_Y), COMMAND_FOREGROUND, true, "Down"); + + color = (btnIndex == 5) ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND; + screen.buttonPrint(Common::Point(ENV_POINTS[5][2], CONTROLS_Y), color, 1, "Quit"); +} + +/** + * Load the game in the specified slot + */ +void SaveManager::loadGame(int slot) { + // TODO +} + +/** + * Save the game in the specified slot with the given name + */ +void SaveManager::saveGame(int slot, const Common::String &name) { + // TODO +} + +/** + * Make sure that the selected savegame is on-screen + */ +bool SaveManager::checkGameOnScreen(int slot) { + Screen &screen = *_vm->_screen; + + // Check if it's already on-screen + if (slot != -1 && (slot < _savegameIndex || slot >= (_savegameIndex + 5))) { + _savegameIndex = slot; + + screen._backBuffer1.fillRect(Common::Rect(3, CONTROLS_Y + 11, SHERLOCK_SCREEN_WIDTH - 2, + SHERLOCK_SCREEN_HEIGHT - 1), INV_BACKGROUND); + + for (int idx = _savegameIndex; idx < (_savegameIndex + 5); ++idx) { + screen.gPrint(Common::Point(6, CONTROLS_Y + 11 + (idx - _savegameIndex) * 10), + INV_FOREGROUND, "%d.", idx + 1); + screen.gPrint(Common::Point(24, CONTROLS_Y + 11 + (idx - _savegameIndex) * 10), + INV_FOREGROUND, "%s", _savegames[idx].c_str()); + } + + screen.slamRect(Common::Rect(3, CONTROLS_Y + 11, 318, SHERLOCK_SCREEN_HEIGHT)); + + byte color = !_savegameIndex ? COMMAND_NULL : COMMAND_FOREGROUND; + screen.buttonPrint(Common::Point(ENV_POINTS[3][2], CONTROLS_Y), color, 1, "Up"); + + color = (_savegameIndex == (MAX_SAVEGAME_SLOTS - 5)) ? COMMAND_NULL : COMMAND_FOREGROUND; + screen.buttonPrint(Common::Point(ENV_POINTS[4][2], CONTROLS_Y), color, 1, "Down"); + + return true; + } + + return false; +} + +bool SaveManager::getFilename(int slot) { + // TODO + return false; +} + } // End of namespace Sherlock diff --git a/engines/sherlock/saveload.h b/engines/sherlock/saveload.h index a0f1da4041..20ce4e6067 100644 --- a/engines/sherlock/saveload.h +++ b/engines/sherlock/saveload.h @@ -31,9 +31,13 @@ namespace Sherlock { -#define NUM_SAVEGAME_SLOTS 99 +#define MAX_SAVEGAME_SLOTS 99 #define SHERLOCK_SAVEGAME_VERSION 1 +enum SaveMode { SAVEMODE_NONE = 0, SAVEMODE_LOAD = 1, SAVEMODE_SAVE = 2 }; + +extern const int ENV_POINTS[6][3]; + struct SherlockSavegameHeader { uint8 _version; Common::String _saveName; @@ -49,15 +53,18 @@ class SaveManager { private: SherlockEngine *_vm; Common::String _target; - Common::StringArray _savegames; Graphics::Surface *_saveThumb; void createSavegameList(); +public: + Common::StringArray _savegames; + int _savegameIndex; + SaveMode _envMode; public: SaveManager(SherlockEngine *vm, const Common::String &target); ~SaveManager(); - void show(); + void drawInterface(); void createThumbnail(); @@ -67,6 +74,16 @@ public: static bool readSavegameHeader(Common::InSaveFile *in, SherlockSavegameHeader &header); + int getHighlightedButton() const; + + void highlightButtons(int btnIndex); + + void loadGame(int slot); + void saveGame(int slot, const Common::String &name); + + bool checkGameOnScreen(int slot); + + bool getFilename(int slot); }; } // End of namespace Sherlock diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index 632e388642..d0744c4775 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -38,6 +38,7 @@ SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gam _map = nullptr; _people = nullptr; _res = nullptr; + _saves = nullptr; _scene = nullptr; _screen = nullptr; _sound = nullptr; @@ -58,6 +59,7 @@ SherlockEngine::~SherlockEngine() { delete _journal; delete _map; delete _people; + delete _saves; delete _scene; delete _screen; delete _sound; @@ -83,6 +85,7 @@ void SherlockEngine::initialize() { _map = new Map(this); _journal = new Journal(this); _people = new People(this); + _saves = new SaveManager(this, _targetName); _scene = new Scene(this); _screen = new Screen(this); _sound = new Sound(this); diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h index 67c7a2864d..20afb6f0e3 100644 --- a/engines/sherlock/sherlock.h +++ b/engines/sherlock/sherlock.h @@ -39,6 +39,7 @@ #include "sherlock/map.h" #include "sherlock/people.h" #include "sherlock/resources.h" +#include "sherlock/saveload.h" #include "sherlock/scene.h" #include "sherlock/screen.h" #include "sherlock/sound.h" @@ -89,6 +90,7 @@ public: Map *_map; People *_people; Resources *_res; + SaveManager *_saves; Scene *_scene; Screen *_screen; Sound *_sound; diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index 3ab705e26c..c8cd300b5e 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -65,15 +65,15 @@ const int SETUP_POINTS[12][4] = { { 219, 176, 316, 268 }, // Fade Style { 103, 176, 217, 160 }, // Window Open Style { 4, 176, 101, 53 }, // Portraits Toggle - { 219, 187, 316, 268 } // Key Pad Accel. Toggle + { 219, 187, 316, 268 } // _key Pad Accel. Toggle }; const char COMMANDS[13] = "LMTPOCIUGJFS"; const char INVENTORY_COMMANDS[9] = { "ELUG-+,." }; -const char *const PRESS_KEY_FOR_MORE = "Press any Key for More."; -const char *const PRESS_KEY_TO_CONTINUE = "Press any Key to Continue."; +const char *const PRESS_KEY_FOR_MORE = "Press any _key for More."; +const char *const PRESS_KEY_TO_CONTINUE = "Press any _key to Continue."; const char *const MOPEN[] = { "This cannot be opened", "It is already open", "It is locked", "Wait for Watson", " ", "." @@ -164,7 +164,7 @@ void Settings::drawInteface(bool flag) { tempStr = Common::String::format("Portraits %s", SETUP_STRS0[people._portraitsOn]); screen.makeButton(Common::Rect(SETUP_POINTS[10][0], SETUP_POINTS[10][1], SETUP_POINTS[10][2], SETUP_POINTS[10][1] + 10), SETUP_POINTS[10][3] - screen.stringWidth(tempStr) / 2, tempStr); - tempStr = Common::String::format("Key Pad %s", _vm->_keyPadSpeed ? "Fast" : "Slow"); + tempStr = Common::String::format("_key Pad %s", _vm->_keyPadSpeed ? "Fast" : "Slow"); screen.makeButton(Common::Rect(SETUP_POINTS[11][0], SETUP_POINTS[11][1], SETUP_POINTS[11][2], SETUP_POINTS[11][1] + 10), SETUP_POINTS[11][3] - screen.stringWidth(tempStr) / 2, tempStr); @@ -183,7 +183,7 @@ void Settings::drawInteface(bool flag) { } } -int Settings::drawButtons(const Common::Point &pt, int key) { +int Settings::drawButtons(const Common::Point &pt, int _key) { Events &events = *_vm->_events; People &people = *_vm->_people; Screen &screen = *_vm->_screen; @@ -196,7 +196,7 @@ int Settings::drawButtons(const Common::Point &pt, int key) { for (int idx = 0; idx < 12; ++idx) { if ((pt.x > SETUP_POINTS[idx][0] && pt.x < SETUP_POINTS[idx][2] && pt.y > SETUP_POINTS[idx][1] && pt.y < (SETUP_POINTS[idx][1] + 10) && (events._released || events._released)) - || (key == SETUP_NAMES[idx][0])) { + || (_key == SETUP_NAMES[idx][0])) { found = idx; color = COMMAND_HIGHLIGHTED; } else { @@ -238,7 +238,7 @@ int Settings::drawButtons(const Common::Point &pt, int key) { screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr); break; case 11: - tempStr = Common::String::format("Key Pad %s", SETUP_STRS4[_vm->_keyPadSpeed]); + tempStr = Common::String::format("_key Pad %s", SETUP_STRS4[_vm->_keyPadSpeed]); screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr); break; default: @@ -328,7 +328,7 @@ void UserInterface::handleInput() { _keycode = Common::KEYCODE_INVALID; // Check kbd and set the mouse released flag if Enter or space is pressed. - // Otherwise, the pressed key is stored for later use + // Otherwise, the pressed _key is stored for later use if (events.kbHit()) { Common::KeyState keyState = events.getKey(); @@ -890,7 +890,304 @@ void UserInterface::lookInv() { * Handles input when the file list window is being displayed */ void UserInterface::doEnvControl() { - // TODO + Events &events = *_vm->_events; + SaveManager &saves = *_vm->_saves; + Scene &scene = *_vm->_scene; + Screen &screen = *_vm->_screen; + Talk &talk = *_vm->_talk; + Common::Point mousePos = events.mousePos(); + static const char ENV_COMMANDS[7] = "ELSUDQ"; + byte color; + + _key = _oldKey = -1; + _keyboardInput = false; + int found = saves.getHighlightedButton(); + + if (events._pressed || events._released) + { + events.clearKeyboard(); + + // Check for a filename entry being highlighted + int found1 = 0; + if ((events._pressed || events._released) && mousePos.y > (CONTROLS_Y + 10)) + { + for (_selector = 0; (_selector < 5) && !found1; ++_selector) + if (mousePos.y > (CONTROLS_Y + 11 + _selector * 10) && mousePos.y < (CONTROLS_Y + 21 + _selector * 10)) + found1 = 1; + + if (_selector + saves._savegameIndex - 1 < MAX_SAVEGAME_SLOTS + (saves._envMode != 1)) + _selector = _selector + saves._savegameIndex - 1; + else + _selector = -1; + + if (!found1) + _selector = -1; + } + + // Handle selecting buttons, if any + saves.highlightButtons(found); + + if (found == 0 || found == 5) + saves._envMode = SAVEMODE_NONE; + } + + if (_keycode) { + _key = toupper(_keycode); + + // Escape _key will close the dialog + if (_key == Common::KEYCODE_ESCAPE) + _key = 'E'; + + if (_key == 'E' || _key == 'L' || _key == 'S' || _key == 'U' || _key == 'D' || _key == 'Q') { + const char *chP = strchr(ENV_COMMANDS, _key); + int btnIndex = !chP ? -1 : chP - ENV_COMMANDS; + saves.highlightButtons(btnIndex); + _keyboardInput = true; + + if (_key == 'E' || _key == 'Q') { + saves._envMode = SAVEMODE_NONE; + } else if (_key >= '1' && _key <= '9') { + _keyboardInput = true; + _selector = _key - '1'; + if (_selector >= MAX_SAVEGAME_SLOTS + (saves._envMode == 1 ? 0 : 1)) + _selector = -1; + + if (saves.checkGameOnScreen(_selector)) + _oldSelector = _selector; + } else { + _selector = -1; + } + } + } + + if (_selector != _oldSelector) { + if (_oldSelector != -1 && _oldSelector >= saves._savegameIndex && _oldSelector < (saves._savegameIndex + 5)) { + screen.print(Common::Point(6, CONTROLS_Y + 12 + (_oldSelector - saves._savegameIndex) * 10), + INV_FOREGROUND, 0, "%d.", _oldSelector + 1); + screen.print(Common::Point(24, CONTROLS_Y + 12 + (_oldSelector - saves._savegameIndex) * 10), + INV_FOREGROUND, 0, "%s", saves._savegames[_oldSelector]); + } + + if (_selector != -1) { + screen.print(Common::Point(6, CONTROLS_Y + 12 + (_selector - saves._savegameIndex) * 10), + TALK_FOREGROUND, 0, "%d.", _selector + 1); + screen.print(Common::Point(24, CONTROLS_Y + 12 + (_selector - saves._savegameIndex) * 10), + TALK_FOREGROUND, 0, "%s", saves._savegames[_selector]); + } + + _oldSelector = _selector; + } + + if (events._released || _keyboardInput) { + if ((found == 0 && events._released) || _key == 'E') { + banishWindow(); + _windowBounds.top = CONTROLS_Y1; + + events._pressed = events._released = _keyboardInput = false; + _keycode = Common::KEYCODE_INVALID; + } else if ((found == 1 && events._released) || _key == 'L') { + saves._envMode = SAVEMODE_LOAD; + if (_selector != -1) { + saves.loadGame(_selector + 1); + } + } else if ((found == 2 && events._released) || _key == 'S') { + saves._envMode = SAVEMODE_SAVE; + if (_selector != -1) { + if (saves.checkGameOnScreen(_selector)) + _oldSelector = _selector; + + if (saves.getFilename(_selector)) { + saves.saveGame(_selector + 1, saves._savegames[_selector]); + + banishWindow(1); + _windowBounds.top = CONTROLS_Y1; + _key = _oldKey = -1; + _keycode = Common::KEYCODE_INVALID; + _keyboardInput = false; + } else { + if (!talk._talkToAbort) { + screen._backBuffer1.fillRect(Common::Rect(6, CONTROLS_Y + 11 + (_selector - saves._savegameIndex) * 10, + SHERLOCK_SCREEN_WIDTH - 2, CONTROLS_Y + 20 + (_selector - saves._savegameIndex) * 10), INV_BACKGROUND); + screen.gPrint(Common::Point(6, CONTROLS_Y + 11 + (_selector - saves._savegameIndex) * 10), INV_FOREGROUND, + "%d.", _selector + 1); + screen.gPrint(Common::Point(24, CONTROLS_Y + 11 + (_selector - saves._savegameIndex) * 10), INV_FOREGROUND, + "%s", saves._savegames[_selector]); + + screen.slamArea(6, CONTROLS_Y + 11 + (_selector - saves._savegameIndex) * 10, 311, 10); + _selector = _oldSelector = -1; + } + } + } + } else if (((found == 3 && events._released) || _key == 'U') && saves._savegameIndex) { + bool moreKeys; + do { + saves._savegameIndex--; + screen._backBuffer1.fillRect(Common::Rect(3, CONTROLS_Y + 11, SHERLOCK_SCREEN_WIDTH - 2, + SHERLOCK_SCREEN_HEIGHT - 1), INV_BACKGROUND); + + for (int idx = saves._savegameIndex; idx < (saves._savegameIndex + 5); ++idx) { + color = INV_FOREGROUND; + if (idx == _selector && idx >= saves._savegameIndex && idx < (saves._savegameIndex + 5)) + color = TALK_FOREGROUND; + + screen.gPrint(Common::Point(6, CONTROLS_Y + 11 + (idx - saves._savegameIndex) * 10), color, "%d.", idx + 1); + screen.gPrint(Common::Point(24, CONTROLS_Y + 11 + (idx - saves._savegameIndex) * 10), color, "%s", saves._savegames[idx]); + } + + screen.slamRect(Common::Rect(3, CONTROLS_Y + 11, SHERLOCK_SCREEN_WIDTH - 2, SHERLOCK_SCREEN_HEIGHT)); + + color = !saves._savegameIndex ? COMMAND_NULL : COMMAND_FOREGROUND; + screen.buttonPrint(Common::Point(ENV_POINTS[3][2], CONTROLS_Y), color, true, "Up"); + color = (saves._savegameIndex == MAX_SAVEGAME_SLOTS - 5) ? COMMAND_NULL : COMMAND_FOREGROUND; + screen.buttonPrint(Common::Point(ENV_POINTS[4][2], CONTROLS_Y), color, true, "Down"); + + // Check for there are more pending U keys pressed + moreKeys = false; + if (events.kbHit()) { + Common::KeyState keyState = events.getKey(); + + _key = toupper(keyState.keycode); + moreKeys = _key == 'U'; + } + } while ((saves._savegameIndex) && moreKeys); + } else if (((found == 4 && events._released) || _key == 'D') && saves._savegameIndex < (MAX_SAVEGAME_SLOTS - 5)) { + bool moreKeys; + do { + saves._savegameIndex++; + screen._backBuffer1.fillRect(Common::Rect(3, CONTROLS_Y + 11, SHERLOCK_SCREEN_WIDTH - 2, + SHERLOCK_SCREEN_HEIGHT - 1), INV_BACKGROUND); + + for (int idx = saves._savegameIndex; idx < (saves._savegameIndex + 5); ++idx) { + if (idx == _selector && idx >= saves._savegameIndex && idx < (saves._savegameIndex + 5)) + color = TALK_FOREGROUND; + else + color = INV_FOREGROUND; + + screen.gPrint(Common::Point(6, CONTROLS_Y + 11 + (idx - saves._savegameIndex) * 10), color, + "%d.", idx + 1); + screen.gPrint(Common::Point(24, CONTROLS_Y + 11 + (idx - saves._savegameIndex) * 10), color, + "%s", saves._savegames[idx]); + } + + screen.slamRect(Common::Rect(3, CONTROLS_Y + 11, SHERLOCK_SCREEN_WIDTH - 2, SHERLOCK_SCREEN_HEIGHT)); + + color = (!saves._savegameIndex) ? COMMAND_NULL : COMMAND_FOREGROUND; + screen.buttonPrint(Common::Point(ENV_POINTS[3][2], CONTROLS_Y), color, true, "Up"); + + color = (saves._savegameIndex == MAX_SAVEGAME_SLOTS - 5) ? COMMAND_NULL : COMMAND_FOREGROUND; + screen.buttonPrint(Common::Point(ENV_POINTS[4][2], CONTROLS_Y), color, true, "Down"); + + // Check for there are more pending D keys pressed + moreKeys = false; + if (events.kbHit()) { + Common::KeyState keyState; + _key = toupper(keyState.keycode); + + moreKeys = _key == 'D'; + } + } while (saves._savegameIndex < (MAX_SAVEGAME_SLOTS - 5) && moreKeys); + } else if ((found == 5 && events._released) || _key == 'Q') { + clearWindow(); + screen.print(Common::Point(0, CONTROLS_Y + 20), INV_FOREGROUND, "Are you sure you wish to Quit ?"); + screen.vgaBar(Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, CONTROLS_Y + 10), BORDER_COLOR); + + screen.makeButton(Common::Rect(112, CONTROLS_Y, 150, CONTROLS_Y + 10), 136 - screen.stringWidth("Yes") / 2, "Yes"); + screen.makeButton(Common::Rect(161, CONTROLS_Y, 209, CONTROLS_Y + 10), 184 - screen.stringWidth("No") / 2, "No"); + screen.slamArea(112, CONTROLS_Y, 97, 10); + + do { + scene.doBgAnim(); + + if (talk._talkToAbort) + return; + + events.pollEventsAndWait(); + events.setButtonState(); + if (events.kbHit()) { + Common::KeyState keyState = events.getKey(); + _key = toupper(keyState.keycode); + + if (_key == 'X' && (keyState.flags & Common::KBD_ALT) != 0) { + _vm->quitGame(); + events.pollEvents(); + return; + } + + if (_key == Common::KEYCODE_ESCAPE) + _key = 'N'; + + if (_key == Common::KEYCODE_RETURN || _key == Common::KEYCODE_SPACE) { + events._pressed = false; + events._released = true; + events._oldButtons = 0; + _keycode = Common::KEYCODE_INVALID; + } + } + + if (events._pressed || events._released) { + if (mousePos.x > 112 && mousePos.x < 159 && mousePos.y > CONTROLS_Y && mousePos.y < (CONTROLS_Y + 9)) + color = COMMAND_HIGHLIGHTED; + else + color = COMMAND_FOREGROUND; + screen.buttonPrint(Common::Point(136, CONTROLS_Y), color, true, "Yes"); + + if (mousePos.x > 161 && mousePos.x < 208 && mousePos.y > CONTROLS_Y && mousePos.y < (CONTROLS_Y + 9)) + color = COMMAND_HIGHLIGHTED; + else + color = COMMAND_FOREGROUND; + screen.buttonPrint(Common::Point(184, CONTROLS_Y), color, true, "No"); + } + + if (mousePos.x > 112 && mousePos.x < 159 && mousePos.y > CONTROLS_Y && mousePos.y < (CONTROLS_Y + 9) && events._released) + _key = 'Y'; + + if (mousePos.x > 161 && mousePos.x < 208 && mousePos.y > CONTROLS_Y && mousePos.y < (CONTROLS_Y + 9) && events._released) + _key = 'N'; + } while (!_vm->shouldQuit() && _key != 'Y' && _key != 'N'); + + if (_key == 'Y') { + _vm->quitGame(); + events.pollEvents(); + return; + } else { + screen.buttonPrint(Common::Point(184, CONTROLS_Y), COMMAND_HIGHLIGHTED, true, "No"); + banishWindow(1); + _windowBounds.top = CONTROLS_Y1; + _key = -1; + } + } else { + if (_selector != -1) { + // Are we already in Load mode? + if (saves._envMode == SAVEMODE_LOAD) { + saves.loadGame(_selector + 1); + } else if (saves._envMode == SAVEMODE_SAVE || _selector == MAX_SAVEGAME_SLOTS) { + // We're alreaady in save mode, or pointed to an empty save slot + if (saves.checkGameOnScreen(_selector)) + _oldSelector = _selector; + + if (saves.getFilename(_selector)) { + saves.saveGame(_selector + 1, saves._savegames[_selector]); + banishWindow(); + _windowBounds.top = CONTROLS_Y1; + _key = _oldKey = -1; + _keycode = Common::KEYCODE_INVALID; + _keyboardInput = false; + } else { + if (!talk._talkToAbort) { + screen._backBuffer1.fillRect(Common::Rect(6, CONTROLS_Y + 11 + (_selector - saves._savegameIndex) * 10, + 317, CONTROLS_Y + 20 + (_selector - saves._savegameIndex) * 10), INV_BACKGROUND); + screen.gPrint(Common::Point(6, CONTROLS_Y + 11 + (_selector - saves._savegameIndex) * 10), + INV_FOREGROUND, 0, "%d.", _selector + 1); + screen.gPrint(Common::Point(24, CONTROLS_Y + 11 + (_selector - saves._savegameIndex) * 10), + INV_FOREGROUND, 0, "%s", saves._savegames[_selector]); + screen.slamArea(6, CONTROLS_Y + 11 + (_selector - saves._savegameIndex) * 10, 311, 10); + _selector = _oldSelector = -1; + } + } + } + } + } + } } /** @@ -1199,6 +1496,7 @@ void UserInterface::doLookControl() { void UserInterface::doMainControl() { Events &events = *_vm->_events; Inventory &inv = *_vm->_inventory; + SaveManager &saves = *_vm->_saves; Common::Point pt = events.mousePos(); if ((events._pressed || events._released) && pt.y > CONTROLS_Y) { @@ -1302,7 +1600,10 @@ void UserInterface::doMainControl() { case 'F': pushButton(10); _menuMode = FILES_MODE; - environment(); + saves.drawInterface(); + + _selector = _oldSelector = -1; + _windowOpen = true; break; case 'S': pushButton(11); @@ -1699,10 +2000,6 @@ void UserInterface::journalControl() { // TODO } -void UserInterface::environment() { - // TODO -} - /** * Handles input when the settings window is being shown */ diff --git a/engines/sherlock/user_interface.h b/engines/sherlock/user_interface.h index 211287c372..12470357e5 100644 --- a/engines/sherlock/user_interface.h +++ b/engines/sherlock/user_interface.h @@ -99,7 +99,6 @@ private: bool _lookScriptFlag; Common::Rect _windowBounds; Common::String _descStr; - int _windowStyle; int _find; int _oldUse; private: @@ -124,7 +123,6 @@ private: void doTalkControl(); void journalControl(); - void environment(); void doControls(); void checkUseAction(const UseType *use, const Common::String &invName, const char *const messages[], @@ -138,6 +136,7 @@ public: bool _endKeyActive; int _invLookFlag; int _temp1; + int _windowStyle; public: UserInterface(SherlockEngine *vm); ~UserInterface(); -- cgit v1.2.3 From 0984405a0dbe718522117507d7c75dc619c586a8 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 21 Apr 2015 22:51:03 -0500 Subject: SHERLOCK: Implement savegame synchronization --- engines/sherlock/inventory.cpp | 20 +++++++++++ engines/sherlock/inventory.h | 3 ++ engines/sherlock/journal.cpp | 31 ++++++++++++++++ engines/sherlock/journal.h | 5 +++ engines/sherlock/people.cpp | 13 ++++++- engines/sherlock/people.h | 5 ++- engines/sherlock/saveload.cpp | 71 +++++++++++++++++++++++++++++++++++-- engines/sherlock/saveload.h | 6 ++++ engines/sherlock/scene.cpp | 61 +++++++++++++++++++------------ engines/sherlock/scene.h | 5 ++- engines/sherlock/screen.cpp | 10 ++++++ engines/sherlock/screen.h | 3 ++ engines/sherlock/sherlock.cpp | 10 +++++- engines/sherlock/sherlock.h | 3 +- engines/sherlock/talk.cpp | 12 +++++++ engines/sherlock/talk.h | 6 +++- engines/sherlock/user_interface.cpp | 2 +- 17 files changed, 234 insertions(+), 32 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/inventory.cpp b/engines/sherlock/inventory.cpp index 9eedac7c6a..3ba6f9d2bd 100644 --- a/engines/sherlock/inventory.cpp +++ b/engines/sherlock/inventory.cpp @@ -486,4 +486,24 @@ int Inventory::deleteItemFromInventory(const Common::String &name) { return 1; } +/** + * Synchronize the data for a savegame + */ +void Inventory::synchronize(Common::Serializer &s) { + s.syncAsSint16LE(_holdings); + + uint count = size(); + s.syncAsUint16LE(count); + if (s.isLoading()) { + resize(count); + + // Reset inventory back to start + _invIndex = 0; + } + + for (uint idx = 0; idx < size(); ++idx) { + // TODO + } +} + } // End of namespace Sherlock diff --git a/engines/sherlock/inventory.h b/engines/sherlock/inventory.h index 4e426beaf4..bccdc9336e 100644 --- a/engines/sherlock/inventory.h +++ b/engines/sherlock/inventory.h @@ -25,6 +25,7 @@ #include "common/scummsys.h" #include "common/array.h" +#include "common/serializer.h" #include "common/str-array.h" #include "sherlock/objects.h" #include "sherlock/resources.h" @@ -99,6 +100,8 @@ public: int putItemInInventory(Object &obj); int deleteItemFromInventory(const Common::String &name); + + void synchronize(Common::Serializer &s); }; } // End of namespace Sherlock diff --git a/engines/sherlock/journal.cpp b/engines/sherlock/journal.cpp index f9c2c54289..15d3a07c75 100644 --- a/engines/sherlock/journal.cpp +++ b/engines/sherlock/journal.cpp @@ -1175,4 +1175,35 @@ int Journal::getFindName(bool printError) { return done; } +/** + * Reset viewing position to the start of the journal + */ +void Journal::resetPosition() { + _index = _sub = _up = _down = 0; + _page = 1; +} + +/** + * Synchronize the data for a savegame + */ +void Journal::synchronize(Common::Serializer &s) { + s.syncAsSint16LE(_count); + s.syncAsSint16LE(_index); + s.syncAsSint16LE(_sub); + s.syncAsSint16LE(_page); + s.syncAsSint16LE(_maxPage); + + int journalCount = _journal.size(); + if (s.isLoading()) + _journal.resize(journalCount); + + for (uint idx = 0; idx < _journal.size(); ++idx) { + JournalEntry &je = _journal[idx]; + + s.syncAsSint16LE(je._converseNum); + s.syncAsByte(je._replyOnly); + s.syncAsSint16LE(je._statementNum); + } +} + } // End of namespace Sherlock diff --git a/engines/sherlock/journal.h b/engines/sherlock/journal.h index 894065759b..9db4b28665 100644 --- a/engines/sherlock/journal.h +++ b/engines/sherlock/journal.h @@ -25,6 +25,7 @@ #include "common/scummsys.h" #include "common/array.h" +#include "common/serializer.h" #include "common/str-array.h" #include "common/stream.h" @@ -77,6 +78,10 @@ public: void drawInterface(); bool handleEvents(int key); + + void resetPosition(); + + void synchronize(Common::Serializer &s); }; } // End of namespace Sherlock diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp index d22c08f625..86c560a1d9 100644 --- a/engines/sherlock/people.cpp +++ b/engines/sherlock/people.cpp @@ -203,7 +203,7 @@ People::People(SherlockEngine *vm) : _vm(vm), _player(_data[0]) { _portraitSide = 0; _speakerFlip = false; _holmesFlip = false; - _homesQuotient = 0; + _holmesQuotient = 0; _portrait._sequences = new byte[32]; } @@ -700,4 +700,15 @@ void People::setTalking(int speaker) { } } +/** + * Synchronize the data for a savegame + */ +void People::synchronize(Common::Serializer &s) { + s.syncAsByte(_holmesOn); + s.syncAsSint16LE(_data[AL]._position.x); + s.syncAsSint16LE(_data[AL]._position.y); + s.syncAsSint16LE(_data[AL]._sequenceNumber); + s.syncAsSint16LE(_holmesQuotient); +} + } // End of namespace Sherlock diff --git a/engines/sherlock/people.h b/engines/sherlock/people.h index 593b516ee6..94f1d05c0d 100644 --- a/engines/sherlock/people.h +++ b/engines/sherlock/people.h @@ -24,6 +24,7 @@ #define SHERLOCK_PEOPLE_H #include "common/scummsys.h" +#include "common/serializer.h" #include "common/stack.h" #include "sherlock/objects.h" @@ -84,7 +85,7 @@ public: int _portraitSide; bool _speakerFlip; bool _holmesFlip; - int _homesQuotient; + int _holmesQuotient; public: People(SherlockEngine *vm); ~People(); @@ -118,6 +119,8 @@ public: void clearTalking(); void setTalking(int speaker); + + void synchronize(Common::Serializer &s); }; } // End of namespace Sherlock diff --git a/engines/sherlock/saveload.cpp b/engines/sherlock/saveload.cpp index 78c86c836e..0cdf1d228f 100644 --- a/engines/sherlock/saveload.cpp +++ b/engines/sherlock/saveload.cpp @@ -44,6 +44,7 @@ SaveManager::SaveManager(SherlockEngine *vm, const Common::String &target) : _vm(vm), _target(target) { _saveThumb = nullptr; _envMode = SAVEMODE_NONE; + _justLoaded = false; } SaveManager::~SaveManager() { @@ -308,14 +309,80 @@ void SaveManager::highlightButtons(int btnIndex) { * Load the game in the specified slot */ void SaveManager::loadGame(int slot) { - // TODO + Common::InSaveFile *saveFile = g_system->getSavefileManager()->openForLoading( + generateSaveName(slot)); + Common::Serializer s(saveFile, nullptr); + + // Load the savaegame header + SherlockSavegameHeader header; + if (!readSavegameHeader(saveFile, header)) + error("Invalid savegame"); + + if (header._thumbnail) { + header._thumbnail->free(); + delete header._thumbnail; + } + + // Synchronize the savegame data + synchronize(s); + + delete saveFile; } /** * Save the game in the specified slot with the given name */ void SaveManager::saveGame(int slot, const Common::String &name) { - // TODO + Common::OutSaveFile *out = g_system->getSavefileManager()->openForSaving( + generateSaveName(slot)); + + SherlockSavegameHeader header; + header._saveName = name; + writeSavegameHeader(out, header); + + Common::Serializer s(nullptr, out); + synchronize(s); + + out->finalize(); + delete out; +} + +/** + * Support method that generates a savegame name + * @param slot Slot number + */ +Common::String SaveManager::generateSaveName(int slot) { + return Common::String::format("%s.%03d", _target.c_str(), slot); +} + +/** + * Synchronize the data for a savegame + */ +void SaveManager::synchronize(Common::Serializer &s) { + Journal &journal = *_vm->_journal; + People &people = *_vm->_people; + Scene &scene = *_vm->_scene; + Screen &screen = *_vm->_screen; + Talk &talk = *_vm->_talk; + + int oldFont = screen.fontNumber(); + + journal.synchronize(s); + people.synchronize(s); + scene.synchronize(s); + screen.synchronize(s); + talk.synchronize(s); + _vm->synchronize(s); + + if (screen.fontNumber() != oldFont) + journal.resetPosition(); + /* + char room_flags[MAX_ROOMS * 9]; + + */ + + _vm->_loadingSavedGame = true; + _justLoaded = true; } /** diff --git a/engines/sherlock/saveload.h b/engines/sherlock/saveload.h index 20ce4e6067..0dad6256ca 100644 --- a/engines/sherlock/saveload.h +++ b/engines/sherlock/saveload.h @@ -25,6 +25,7 @@ #include "common/scummsys.h" #include "common/savefile.h" +#include "common/serializer.h" #include "common/str-array.h" #include "engines/savestate.h" #include "graphics/surface.h" @@ -56,10 +57,15 @@ private: Graphics::Surface *_saveThumb; void createSavegameList(); + + Common::String generateSaveName(int slot); + + void synchronize(Common::Serializer &s); public: Common::StringArray _savegames; int _savegameIndex; SaveMode _envMode; + bool _justLoaded; public: SaveManager(SherlockEngine *vm, const Common::String &target); ~SaveManager(); diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 575523bc45..4671dbdade 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -85,7 +85,7 @@ void SceneSound::synchronize(Common::SeekableReadStream &s) { Scene::Scene(SherlockEngine *vm): _vm(vm) { for (int idx = 0; idx < SCENES_COUNT; ++idx) - Common::fill(&_stats[idx][0], &_stats[idx][9], false); + Common::fill(&_sceneStats[idx][0], &_sceneStats[idx][65], false); _currentScene = -1; _goToScene = -1; _changes = false; @@ -195,6 +195,7 @@ bool Scene::loadScene(const Common::String &filename) { Events &events = *_vm->_events; Map &map = *_vm->_map; People &people = *_vm->_people; + SaveManager &saves = *_vm->_saves; Screen &screen = *_vm->_screen; Sound &sound = *_vm->_sound; UserInterface &ui = *_vm->_ui; @@ -398,7 +399,7 @@ bool Scene::loadScene(const Common::String &filename) { _changes = false; checkSceneStatus(); - if (!_vm->_justLoaded) { + if (!saves._justLoaded) { for (uint idx = 0; idx < _bgShapes.size(); ++idx) { if (_bgShapes[idx]._type == HIDDEN && _bgShapes[idx]._aType == TALK_EVERY) _bgShapes[idx].toggleHidden(); @@ -450,30 +451,25 @@ bool Scene::loadScene(const Common::String &filename) { * opening or moving them */ void Scene::checkSceneStatus() { - if (_stats[_currentScene][8]) { - for (int idx = 0; idx < 8; ++idx) { - int val = _stats[_currentScene][idx]; + if (_sceneStats[_currentScene][65]) { + for (uint idx = 0; idx < 64; ++idx) { + int val = _sceneStats[_currentScene][idx]; - for (int bit = 0; bit < 8; ++bit) { - uint objNumber = idx * 8 + bit; - if (objNumber < _bgShapes.size()) { - Object &obj = _bgShapes[objNumber]; + if (idx < _bgShapes.size()) { + Object &obj = _bgShapes[idx]; - if (val & 1) { - // No shape to erase, so flag as hidden - obj._type = HIDDEN; - } else if (obj._images == nullptr || obj._images->size() == 0) { - // No shape - obj._type = NO_SHAPE; - } else { - obj._type = ACTIVE_BG_SHAPE; - } + if (val & 1) { + // No shape to erase, so flag as hidden + obj._type = HIDDEN; + } else if (obj._images == nullptr || obj._images->size() == 0) { + // No shape + obj._type = NO_SHAPE; } else { - // Finished checks - return; + obj._type = ACTIVE_BG_SHAPE; } - - val >>= 1; + } else { + // Finished checks + return; } } } @@ -560,6 +556,7 @@ void Scene::checkInventory() { */ void Scene::transitionToScene() { People &people = *_vm->_people; + SaveManager &saves = *_vm->_saves; Screen &screen = *_vm->_screen; Talk &talk = *_vm->_talk; @@ -583,7 +580,7 @@ void Scene::transitionToScene() { // Exit information exists, translate it to real sequence info // Note: If a savegame was just loaded, then the data is already correct. // Otherwise, this is a linked scene or entrance info, and must be translated - if (_hsavedFs < 8 && !_vm->_justLoaded) { + if (_hsavedFs < 8 && !saves._justLoaded) { _hsavedFs = FS_TRANS[_hsavedFs]; _hsavedPos.x *= 100; _hsavedPos.y *= 100; @@ -1457,4 +1454,22 @@ int Scene::closestZone(const Common::Point &pt) { return zone; } +/** + * Synchronize the data for a savegame + */ +void Scene::synchronize(Common::Serializer &s) { + s.syncAsSint16LE(_bigPos.x); + s.syncAsSint16LE(_bigPos.y); + s.syncAsSint16LE(_overPos.x); + s.syncAsSint16LE(_overPos.y); + s.syncAsSint16LE(_oldCharPoint); + s.syncAsSint16LE(_goToScene); + + for (int sceneNum = 0; sceneNum < SCENES_COUNT; ++sceneNum) { + for (int flag = 0; flag < 65; ++flag) { + s.syncAsByte(_sceneStats[sceneNum][flag]); + } + } +} + } // End of namespace Sherlock diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h index 3549325e8e..cc01fa92ab 100644 --- a/engines/sherlock/scene.h +++ b/engines/sherlock/scene.h @@ -26,6 +26,7 @@ #include "common/scummsys.h" #include "common/array.h" #include "common/rect.h" +#include "common/serializer.h" #include "sherlock/objects.h" #include "sherlock/resources.h" @@ -104,7 +105,7 @@ public: int _currentScene; int _goToScene; bool _changes; - bool _stats[SCENES_COUNT][9]; + bool _sceneStats[SCENES_COUNT][65]; bool _savedStats[SCENES_COUNT][9]; Common::Point _bigPos; Common::Point _overPos; @@ -167,6 +168,8 @@ public: int closestZone(const Common::Point &pt); void updateBackground(); + + void synchronize(Common::Serializer &s); }; } // End of namespace Sherlock diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp index a30108118c..3c9a10e4a1 100644 --- a/engines/sherlock/screen.cpp +++ b/engines/sherlock/screen.cpp @@ -480,4 +480,14 @@ Common::Rect Screen::getDisplayBounds() { return Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT); } +/** + * Synchronize the data for a savegame + */ +void Screen::synchronize(Common::Serializer &s) { + int fontNumber = _fontNumber; + s.syncAsByte(fontNumber); + if (s.isLoading()) + setFont(fontNumber); +} + } // End of namespace Sherlock diff --git a/engines/sherlock/screen.h b/engines/sherlock/screen.h index 2cfd7c8a88..a8bdc53b5a 100644 --- a/engines/sherlock/screen.h +++ b/engines/sherlock/screen.h @@ -25,6 +25,7 @@ #include "common/list.h" #include "common/rect.h" +#include "common/serializer.h" #include "graphics/surface.h" #include "sherlock/graphics.h" #include "sherlock/resources.h" @@ -128,6 +129,8 @@ public: Common::Rect getDisplayBounds(); int fontNumber() const { return _fontNumber; } + + void synchronize(Common::Serializer &s); }; } // End of namespace Sherlock diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index d0744c4775..bc7b545719 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -45,7 +45,6 @@ SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gam _talk = nullptr; _ui = nullptr; _useEpilogue2 = false; - _justLoaded = false; _loadingSavedGame = false; _onChessboard = false; _slowChess = false; @@ -185,4 +184,13 @@ void SherlockEngine::saveConfig() { // TODO } + +/** + * Synchronize the data for a savegame + */ +void SherlockEngine::synchronize(Common::Serializer &s) { + for (uint idx = 0; idx < _flags.size(); ++idx) + s.syncAsByte(_flags[idx]); +} + } // End of namespace Comet diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h index 20afb6f0e3..48850fff06 100644 --- a/engines/sherlock/sherlock.h +++ b/engines/sherlock/sherlock.h @@ -101,7 +101,6 @@ public: Common::String _soundOverride; Common::String _titleOverride; bool _useEpilogue2; - bool _justLoaded; bool _loadingSavedGame; int _oldCharPoint; // Old scene Common::Point _over; // Old map position @@ -131,6 +130,8 @@ public: void freeSaveGameList(); void saveConfig(); + + void synchronize(Common::Serializer &s); }; } // End of namespace Sherlock diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index 158cae38a9..6740e89efc 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -1745,4 +1745,16 @@ void Talk::popStack() { } } +/** + * Synchronize the data for a savegame + */ +void Talk::synchronize(Common::Serializer &s) { + for (int idx = 0; idx < MAX_TALK_FILES; ++idx) { + TalkHistoryEntry &he = _talkHistory[idx]; + + for (int flag = 0; flag < 16; ++flag) + s.syncAsByte(he._data[flag]); + } +} + } // End of namespace Sherlock diff --git a/engines/sherlock/talk.h b/engines/sherlock/talk.h index 4a33f2f557..620a986454 100644 --- a/engines/sherlock/talk.h +++ b/engines/sherlock/talk.h @@ -26,12 +26,14 @@ #include "common/scummsys.h" #include "common/array.h" #include "common/rect.h" +#include "common/serializer.h" #include "common/stream.h" #include "common/stack.h" namespace Sherlock { #define MAX_TALK_SEQUENCES 11 +#define MAX_TALK_FILES 500 struct SequenceEntry { int _objNum; @@ -93,7 +95,7 @@ private: Common::Stack _sequenceStack; Common::Stack _scriptStack; Common::Array _statements; - TalkHistoryEntry _talkHistory[500]; + TalkHistoryEntry _talkHistory[MAX_TALK_FILES]; int _speaker; int _talkIndex; int _scriptSelect; @@ -145,6 +147,8 @@ public: bool isSequencesEmpty() const { return _scriptStack.empty(); } void popStack(); + + void synchronize(Common::Serializer &s); }; } // End of namespace Sherlock diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index c8cd300b5e..f7f387e9ad 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -1820,7 +1820,7 @@ void UserInterface::doTalkControl() { // Add any Holmes point to Holmes' total, if any if (talk._statements[_selector]._quotient) - people._homesQuotient += talk._statements[_selector]._quotient; + people._holmesQuotient += talk._statements[_selector]._quotient; } // Flag the response as having been used -- cgit v1.2.3 From e08520cca94f33cb69ee8058cb08e400e5443016 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 22 Apr 2015 02:32:25 -0500 Subject: SHERLOCK: Fix Files saves listing and save name entry --- engines/sherlock/saveload.cpp | 96 +++++++++++++++++++++++++++++++++++-- engines/sherlock/user_interface.cpp | 17 ++++--- 2 files changed, 102 insertions(+), 11 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/saveload.cpp b/engines/sherlock/saveload.cpp index 0cdf1d228f..57a4a65b21 100644 --- a/engines/sherlock/saveload.cpp +++ b/engines/sherlock/saveload.cpp @@ -45,6 +45,7 @@ SaveManager::SaveManager(SherlockEngine *vm, const Common::String &target) : _saveThumb = nullptr; _envMode = SAVEMODE_NONE; _justLoaded = false; + _savegameIndex = 0; } SaveManager::~SaveManager() { @@ -94,7 +95,7 @@ void SaveManager::drawInterface() { screen.gPrint(Common::Point(6, CONTROLS_Y + 11 + (idx - _savegameIndex) * 10), INV_FOREGROUND, "%d.", idx + 1); screen.gPrint(Common::Point(24, CONTROLS_Y + 11 + (idx - _savegameIndex) * 10), - INV_FOREGROUND, "%s", _savegames[idx]); + INV_FOREGROUND, "%s", _savegames[idx].c_str()); } if (!ui._windowStyle) { @@ -114,7 +115,7 @@ void SaveManager::createSavegameList() { _savegames.clear(); for (int idx = 0; idx < MAX_SAVEGAME_SLOTS; ++idx) - _savegames.push_back("-EMPTY"); + _savegames.push_back("-EMPTY-"); SaveStateList saveList = getSavegameList(_target); for (uint idx = 0; idx < saveList.size(); ++idx) @@ -420,8 +421,95 @@ bool SaveManager::checkGameOnScreen(int slot) { } bool SaveManager::getFilename(int slot) { - // TODO - return false; + Events &events = *_vm->_events; + Scene &scene = *_vm->_scene; + Screen &screen = *_vm->_screen; + Talk &talk = *_vm->_talk; + int xp, yp; + bool flag = false; + + screen.buttonPrint(Common::Point(ENV_POINTS[0][2], CONTROLS_Y), COMMAND_NULL, true, "Exit"); + screen.buttonPrint(Common::Point(ENV_POINTS[1][2], CONTROLS_Y), COMMAND_NULL, true, "Load"); + screen.buttonPrint(Common::Point(ENV_POINTS[2][2], CONTROLS_Y), COMMAND_NULL, true, "Save"); + screen.buttonPrint(Common::Point(ENV_POINTS[3][2], CONTROLS_Y), COMMAND_NULL, true, "Up"); + screen.buttonPrint(Common::Point(ENV_POINTS[4][2], CONTROLS_Y), COMMAND_NULL, true, "Down"); + screen.buttonPrint(Common::Point(ENV_POINTS[5][2], CONTROLS_Y), COMMAND_NULL, true, "Quit"); + + Common::String saveName = _savegames[slot]; + if (scumm_stricmp(saveName.c_str(), "-EMPTY-") == 0) { + // It's an empty slot, so start off with an empty save name + saveName = ""; + + yp = CONTROLS_Y + 12 + (slot - _savegameIndex) * 10; + screen.vgaBar(Common::Rect(24, yp, 85, yp + 9), INV_BACKGROUND); + } + + screen.print(Common::Point(6, CONTROLS_Y + 12 + (slot - _savegameIndex) * 10), TALK_FOREGROUND, "%d.", slot + 1); + screen.print(Common::Point(24, CONTROLS_Y + 12 + (slot - _savegameIndex) * 10), TALK_FOREGROUND, "%s", saveName.c_str()); + xp = 24 + screen.stringWidth(saveName); + yp = CONTROLS_Y + 12 + (slot - _savegameIndex) * 10; + + int done = 0; + do { + while (!_vm->shouldQuit() && !events.kbHit()) { + scene.doBgAnim(); + + if (talk._talkToAbort) + return false; + + // Allow event processing + events.pollEventsAndWait(); + events.setButtonState(); + + flag = !flag; + if (flag) + screen.vgaBar(Common::Rect(xp, yp - 1, xp + 8, yp + 9), INV_FOREGROUND); + else + screen.vgaBar(Common::Rect(xp, yp - 1, xp + 8, yp + 9), INV_BACKGROUND); + } + if (_vm->shouldQuit()) + return false; + + // Get the next keypress + Common::KeyState keyState = events.getKey(); + + if (keyState.keycode == Common::KEYCODE_BACKSPACE && saveName.size() > 0) { + // Delete character of save name + screen.vgaBar(Common::Rect(xp - screen.charWidth(saveName.lastChar()), yp - 1, + xp + 8, yp + 9), INV_BACKGROUND); + xp -= screen.charWidth(saveName.lastChar()); + screen.vgaBar(Common::Rect(xp, yp - 1, xp + 8, yp + 9), INV_FOREGROUND); + saveName.deleteLastChar(); + } + + if (keyState.keycode == Common::KEYCODE_RETURN) + done = 1; + + if (keyState.keycode == Common::KEYCODE_ESCAPE) { + screen.vgaBar(Common::Rect(xp, yp - 1, xp + 8, yp + 9), INV_BACKGROUND); + done = -1; + } + + if (keyState.keycode >= ' ' && keyState.keycode <= 'z' && saveName.size() < 50 + && (xp + screen.charWidth(keyState.keycode)) < 308) { + screen.vgaBar(Common::Rect(xp, yp - 1, xp + 8, yp + 9), INV_BACKGROUND); + screen.print(Common::Point(xp, yp), TALK_FOREGROUND, "%c", (char)keyState.keycode); + xp += screen.charWidth((char)keyState.keycode); + screen.vgaBar(Common::Rect(xp, yp - 1, xp + 8, yp + 9), INV_FOREGROUND); + saveName += (char)keyState.keycode; + } + } while (!done); + + if (done == 1) { + // Enter key perssed + _savegames[slot] = saveName; + } else { + done = 0; + _envMode = SAVEMODE_NONE; + highlightButtons(-1); + } + + return done == 1; } } // End of namespace Sherlock diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index f7f387e9ad..f95277df91 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -331,13 +331,16 @@ void UserInterface::handleInput() { // Otherwise, the pressed _key is stored for later use if (events.kbHit()) { Common::KeyState keyState = events.getKey(); + _keycode = keyState.keycode; if (keyState.keycode == Common::KEYCODE_x && keyState.flags & Common::KBD_ALT) { _vm->quitGame(); + events.pollEvents(); return; } else if (keyState.keycode == Common::KEYCODE_SPACE || keyState.keycode == Common::KEYCODE_RETURN) { - events._pressed = events._oldButtons = 0; + events._pressed = false; + events._oldButtons = 0; _keycode = Common::KEYCODE_INVALID; } } @@ -963,16 +966,16 @@ void UserInterface::doEnvControl() { if (_selector != _oldSelector) { if (_oldSelector != -1 && _oldSelector >= saves._savegameIndex && _oldSelector < (saves._savegameIndex + 5)) { screen.print(Common::Point(6, CONTROLS_Y + 12 + (_oldSelector - saves._savegameIndex) * 10), - INV_FOREGROUND, 0, "%d.", _oldSelector + 1); + INV_FOREGROUND, "%d.", _oldSelector + 1); screen.print(Common::Point(24, CONTROLS_Y + 12 + (_oldSelector - saves._savegameIndex) * 10), - INV_FOREGROUND, 0, "%s", saves._savegames[_oldSelector]); + INV_FOREGROUND, "%s", saves._savegames[_oldSelector]); } if (_selector != -1) { screen.print(Common::Point(6, CONTROLS_Y + 12 + (_selector - saves._savegameIndex) * 10), - TALK_FOREGROUND, 0, "%d.", _selector + 1); + TALK_FOREGROUND, "%d.", _selector + 1); screen.print(Common::Point(24, CONTROLS_Y + 12 + (_selector - saves._savegameIndex) * 10), - TALK_FOREGROUND, 0, "%s", saves._savegames[_selector]); + TALK_FOREGROUND, "%s", saves._savegames[_selector].c_str()); } _oldSelector = _selector; @@ -1031,7 +1034,7 @@ void UserInterface::doEnvControl() { color = TALK_FOREGROUND; screen.gPrint(Common::Point(6, CONTROLS_Y + 11 + (idx - saves._savegameIndex) * 10), color, "%d.", idx + 1); - screen.gPrint(Common::Point(24, CONTROLS_Y + 11 + (idx - saves._savegameIndex) * 10), color, "%s", saves._savegames[idx]); + screen.gPrint(Common::Point(24, CONTROLS_Y + 11 + (idx - saves._savegameIndex) * 10), color, "%s", saves._savegames[idx].c_str()); } screen.slamRect(Common::Rect(3, CONTROLS_Y + 11, SHERLOCK_SCREEN_WIDTH - 2, SHERLOCK_SCREEN_HEIGHT)); @@ -1066,7 +1069,7 @@ void UserInterface::doEnvControl() { screen.gPrint(Common::Point(6, CONTROLS_Y + 11 + (idx - saves._savegameIndex) * 10), color, "%d.", idx + 1); screen.gPrint(Common::Point(24, CONTROLS_Y + 11 + (idx - saves._savegameIndex) * 10), color, - "%s", saves._savegames[idx]); + "%s", saves._savegames[idx].c_str()); } screen.slamRect(Common::Rect(3, CONTROLS_Y + 11, SHERLOCK_SCREEN_WIDTH - 2, SHERLOCK_SCREEN_HEIGHT)); -- cgit v1.2.3 From 27938653a5cd05856da88142f52de44f30e26eef Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 22 Apr 2015 04:44:55 -0500 Subject: SHERLOCK: Further fixes for entering savegame names --- engines/sherlock/events.cpp | 12 ++++++++++++ engines/sherlock/events.h | 2 +- engines/sherlock/saveload.cpp | 18 +++++++++++++----- engines/sherlock/user_interface.cpp | 10 +++++----- engines/sherlock/user_interface.h | 2 +- 5 files changed, 32 insertions(+), 12 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/events.cpp b/engines/sherlock/events.cpp index 1a827eda3b..f7b473ff7a 100644 --- a/engines/sherlock/events.cpp +++ b/engines/sherlock/events.cpp @@ -196,6 +196,18 @@ bool Events::checkForNextFrameCounter() { return false; } +/** + * Get a pending keypress + */ +Common::KeyState Events::getKey() { + Common::KeyState keyState = _pendingKeys.pop(); + if ((keyState.flags & Common::KBD_SHIFT) != 0) + keyState.ascii = toupper(keyState.ascii); + + return keyState; +} + + /** * Clear any current keypress or mouse click */ diff --git a/engines/sherlock/events.h b/engines/sherlock/events.h index ccf6eb1c59..015c39580d 100644 --- a/engines/sherlock/events.h +++ b/engines/sherlock/events.h @@ -85,7 +85,7 @@ public: bool kbHit() const { return !_pendingKeys.empty(); } - Common::KeyState getKey() { return _pendingKeys.pop(); } + Common::KeyState getKey(); void clearEvents(); void clearKeyboard(); diff --git a/engines/sherlock/saveload.cpp b/engines/sherlock/saveload.cpp index 57a4a65b21..cd7627a768 100644 --- a/engines/sherlock/saveload.cpp +++ b/engines/sherlock/saveload.cpp @@ -118,8 +118,11 @@ void SaveManager::createSavegameList() { _savegames.push_back("-EMPTY-"); SaveStateList saveList = getSavegameList(_target); - for (uint idx = 0; idx < saveList.size(); ++idx) - _savegames[saveList[idx].getSaveSlot()] = saveList[idx].getDescription(); + for (uint idx = 0; idx < saveList.size(); ++idx) { + int slot = saveList[idx].getSaveSlot() - 1; + if (slot >= 0 && slot < MAX_SAVEGAME_SLOTS) + _savegames[slot] = saveList[idx].getDescription(); + } // Ensure the names will fit on the screen for (uint idx = 0; idx < _savegames.size(); ++idx) { @@ -312,6 +315,9 @@ void SaveManager::highlightButtons(int btnIndex) { void SaveManager::loadGame(int slot) { Common::InSaveFile *saveFile = g_system->getSavefileManager()->openForLoading( generateSaveName(slot)); + if (!saveFile) + return; + Common::Serializer s(saveFile, nullptr); // Load the savaegame header @@ -492,11 +498,13 @@ bool SaveManager::getFilename(int slot) { if (keyState.keycode >= ' ' && keyState.keycode <= 'z' && saveName.size() < 50 && (xp + screen.charWidth(keyState.keycode)) < 308) { + char c = (char)keyState.ascii; + screen.vgaBar(Common::Rect(xp, yp - 1, xp + 8, yp + 9), INV_BACKGROUND); - screen.print(Common::Point(xp, yp), TALK_FOREGROUND, "%c", (char)keyState.keycode); - xp += screen.charWidth((char)keyState.keycode); + screen.print(Common::Point(xp, yp), TALK_FOREGROUND, "%c", c); + xp += screen.charWidth(c); screen.vgaBar(Common::Rect(xp, yp - 1, xp + 8, yp + 9), INV_FOREGROUND); - saveName += (char)keyState.keycode; + saveName += c; } } while (!done); diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index f95277df91..cb10606562 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -331,7 +331,7 @@ void UserInterface::handleInput() { // Otherwise, the pressed _key is stored for later use if (events.kbHit()) { Common::KeyState keyState = events.getKey(); - _keycode = keyState.keycode; + _keycode = keyState.ascii; if (keyState.keycode == Common::KEYCODE_x && keyState.flags & Common::KBD_ALT) { _vm->quitGame(); @@ -968,7 +968,7 @@ void UserInterface::doEnvControl() { screen.print(Common::Point(6, CONTROLS_Y + 12 + (_oldSelector - saves._savegameIndex) * 10), INV_FOREGROUND, "%d.", _oldSelector + 1); screen.print(Common::Point(24, CONTROLS_Y + 12 + (_oldSelector - saves._savegameIndex) * 10), - INV_FOREGROUND, "%s", saves._savegames[_oldSelector]); + INV_FOREGROUND, "%s", saves._savegames[_oldSelector].c_str()); } if (_selector != -1) { @@ -1014,7 +1014,7 @@ void UserInterface::doEnvControl() { screen.gPrint(Common::Point(6, CONTROLS_Y + 11 + (_selector - saves._savegameIndex) * 10), INV_FOREGROUND, "%d.", _selector + 1); screen.gPrint(Common::Point(24, CONTROLS_Y + 11 + (_selector - saves._savegameIndex) * 10), INV_FOREGROUND, - "%s", saves._savegames[_selector]); + "%s", saves._savegames[_selector].c_str()); screen.slamArea(6, CONTROLS_Y + 11 + (_selector - saves._savegameIndex) * 10, 311, 10); _selector = _oldSelector = -1; @@ -1180,9 +1180,9 @@ void UserInterface::doEnvControl() { screen._backBuffer1.fillRect(Common::Rect(6, CONTROLS_Y + 11 + (_selector - saves._savegameIndex) * 10, 317, CONTROLS_Y + 20 + (_selector - saves._savegameIndex) * 10), INV_BACKGROUND); screen.gPrint(Common::Point(6, CONTROLS_Y + 11 + (_selector - saves._savegameIndex) * 10), - INV_FOREGROUND, 0, "%d.", _selector + 1); + INV_FOREGROUND, "%d.", _selector + 1); screen.gPrint(Common::Point(24, CONTROLS_Y + 11 + (_selector - saves._savegameIndex) * 10), - INV_FOREGROUND, 0, "%s", saves._savegames[_selector]); + INV_FOREGROUND, "%s", saves._savegames[_selector].c_str()); screen.slamArea(6, CONTROLS_Y + 11 + (_selector - saves._savegameIndex) * 10, 311, 10); _selector = _oldSelector = -1; } diff --git a/engines/sherlock/user_interface.h b/engines/sherlock/user_interface.h index 12470357e5..99612b218b 100644 --- a/engines/sherlock/user_interface.h +++ b/engines/sherlock/user_interface.h @@ -84,7 +84,7 @@ private: ImageFile *_controls; int _bgFound; int _oldBgFound; - Common::KeyCode _keycode; + int _keycode; int _helpStyle; int _lookHelp; int _help, _oldHelp; -- cgit v1.2.3 From 0fc29972804c12ad9b051574a6e0588ff2b065ee Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 22 Apr 2015 05:06:13 -0500 Subject: SHERLOCK: Fixes for saving and restoring games --- engines/sherlock/events.cpp | 1 + engines/sherlock/scene.cpp | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sherlock/events.cpp b/engines/sherlock/events.cpp index f7b473ff7a..f83219d7d2 100644 --- a/engines/sherlock/events.cpp +++ b/engines/sherlock/events.cpp @@ -54,6 +54,7 @@ void Events::loadCursors(const Common::String &filename) { delete _cursorImages; _cursorImages = new ImageFile(filename); + _cursorId = INVALID_CURSOR; } /** diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 4671dbdade..316b8739b1 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -1463,7 +1463,11 @@ void Scene::synchronize(Common::Serializer &s) { s.syncAsSint16LE(_overPos.x); s.syncAsSint16LE(_overPos.y); s.syncAsSint16LE(_oldCharPoint); - s.syncAsSint16LE(_goToScene); + + if (s.isSaving()) + s.syncAsSint16LE(_currentScene); + else + s.syncAsSint16LE(_goToScene); for (int sceneNum = 0; sceneNum < SCENES_COUNT; ++sceneNum) { for (int flag = 0; flag < 65; ++flag) { -- cgit v1.2.3 From 8b0e8cd505eebf199aa9888ce65012f1574b1233 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 22 Apr 2015 06:25:04 -0500 Subject: SHERLOCK: Hook up savegames to launcher --- engines/sherlock/detection.cpp | 13 +++++++++---- engines/sherlock/journal.cpp | 1 + engines/sherlock/saveload.cpp | 4 ++-- engines/sherlock/saveload.h | 4 ++-- engines/sherlock/sherlock.cpp | 18 ++++++++++++++++-- engines/sherlock/sherlock.h | 1 + 6 files changed, 31 insertions(+), 10 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/detection.cpp b/engines/sherlock/detection.cpp index bb66cee7df..5d217bd1c5 100644 --- a/engines/sherlock/detection.cpp +++ b/engines/sherlock/detection.cpp @@ -98,7 +98,12 @@ bool SherlockMetaEngine::createInstance(OSystem *syst, Engine **engine, const AD } bool SherlockMetaEngine::hasFeature(MetaEngineFeature f) const { - return false; + return + (f == kSupportsListSaves) || + (f == kSupportsLoadingDuringStartup) || + (f == kSupportsDeleteSave) || + (f == kSavesSupportMetaInfo) || + (f == kSavesSupportThumbnail); } SaveStateList SherlockMetaEngine::listSaves(const char *target) const { @@ -109,13 +114,13 @@ int SherlockMetaEngine::getMaximumSaveSlot() const { return MAX_SAVEGAME_SLOTS; } -void SherlockMetaEngine::removeSaveState(const char *target, int slot) const { - Common::String filename = Common::String::format("%s.%03d", target, slot); +void SherlockMetaEngine::removeSaveState(const char *target, int slot) const { + Common::String filename = Sherlock::SaveManager(nullptr, target).generateSaveName(slot); g_system->getSavefileManager()->removeSavefile(filename); } SaveStateDescriptor SherlockMetaEngine::querySaveMetaInfos(const char *target, int slot) const { - Common::String filename = Common::String::format("%s.%03d", target, slot); + Common::String filename = Sherlock::SaveManager(nullptr, target).generateSaveName(slot); Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading(filename); if (f) { diff --git a/engines/sherlock/journal.cpp b/engines/sherlock/journal.cpp index 15d3a07c75..18edec8c73 100644 --- a/engines/sherlock/journal.cpp +++ b/engines/sherlock/journal.cpp @@ -1194,6 +1194,7 @@ void Journal::synchronize(Common::Serializer &s) { s.syncAsSint16LE(_maxPage); int journalCount = _journal.size(); + s.syncAsUint16LE(journalCount); if (s.isLoading()) _journal.resize(journalCount); diff --git a/engines/sherlock/saveload.cpp b/engines/sherlock/saveload.cpp index cd7627a768..207eff1ab4 100644 --- a/engines/sherlock/saveload.cpp +++ b/engines/sherlock/saveload.cpp @@ -318,8 +318,6 @@ void SaveManager::loadGame(int slot) { if (!saveFile) return; - Common::Serializer s(saveFile, nullptr); - // Load the savaegame header SherlockSavegameHeader header; if (!readSavegameHeader(saveFile, header)) @@ -331,6 +329,7 @@ void SaveManager::loadGame(int slot) { } // Synchronize the savegame data + Common::Serializer s(saveFile, nullptr); synchronize(s); delete saveFile; @@ -347,6 +346,7 @@ void SaveManager::saveGame(int slot, const Common::String &name) { header._saveName = name; writeSavegameHeader(out, header); + // Synchronize the savegame data Common::Serializer s(nullptr, out); synchronize(s); diff --git a/engines/sherlock/saveload.h b/engines/sherlock/saveload.h index 0dad6256ca..0865fd3856 100644 --- a/engines/sherlock/saveload.h +++ b/engines/sherlock/saveload.h @@ -58,8 +58,6 @@ private: void createSavegameList(); - Common::String generateSaveName(int slot); - void synchronize(Common::Serializer &s); public: Common::StringArray _savegames; @@ -76,6 +74,8 @@ public: static SaveStateList getSavegameList(const Common::String &target); + Common::String generateSaveName(int slot); + void writeSavegameHeader(Common::OutSaveFile *out, SherlockSavegameHeader &header); static bool readSavegameHeader(Common::InSaveFile *in, SherlockSavegameHeader &header); diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index bc7b545719..cd5d48033a 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -23,6 +23,7 @@ #include "sherlock/sherlock.h" #include "sherlock/graphics.h" #include "common/scummsys.h" +#include "common/config-manager.h" #include "common/debug-channels.h" #include "engines/util.h" @@ -49,6 +50,7 @@ SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gam _onChessboard = false; _slowChess = false; _keyPadSpeed = 0; + _loadGameSlot = -1; } SherlockEngine::~SherlockEngine() { @@ -95,8 +97,20 @@ void SherlockEngine::initialize() { Common::Error SherlockEngine::run() { initialize(); - // Temporarily disabled for now -// showOpening(); + // If requested, load a savegame instead of showing the intro + if (ConfMan.hasKey("save_slot")) { + int saveSlot = ConfMan.getInt("save_slot"); + if (saveSlot >= 1 && saveSlot <= MAX_SAVEGAME_SLOTS) + _loadGameSlot = saveSlot; + } + + if (_loadGameSlot != -1) { + _saves->loadGame(_loadGameSlot); + _loadGameSlot = -1; + } else { + // Temporarily disabled for now + // showOpening(); + } while (!shouldQuit()) { // Prepare for scene, and handle any game-specific scenes. This allows diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h index 48850fff06..09e969884c 100644 --- a/engines/sherlock/sherlock.h +++ b/engines/sherlock/sherlock.h @@ -107,6 +107,7 @@ public: bool _onChessboard; bool _slowChess; int _keyPadSpeed; + int _loadGameSlot; public: SherlockEngine(OSystem *syst, const SherlockGameDescription *gameDesc); virtual ~SherlockEngine(); -- cgit v1.2.3 From acf0b01ad80acb54992a36c0123f3c951e2200e3 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 22 Apr 2015 07:08:01 -0500 Subject: SHERLOCK: Hook up saving and loading via GMM --- engines/sherlock/detection.cpp | 7 +++++++ engines/sherlock/saveload.cpp | 4 ---- engines/sherlock/sherlock.cpp | 43 ++++++++++++++++++++++++++++++++++++------ engines/sherlock/sherlock.h | 10 ++++++++-- 4 files changed, 52 insertions(+), 12 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/detection.cpp b/engines/sherlock/detection.cpp index 5d217bd1c5..c4d1c65fd5 100644 --- a/engines/sherlock/detection.cpp +++ b/engines/sherlock/detection.cpp @@ -106,6 +106,13 @@ bool SherlockMetaEngine::hasFeature(MetaEngineFeature f) const { (f == kSavesSupportThumbnail); } +bool Sherlock::SherlockEngine::hasFeature(EngineFeature f) const { + return + (f == kSupportsRTL) || + (f == kSupportsLoadingDuringRuntime) || + (f == kSupportsSavingDuringRuntime); +} + SaveStateList SherlockMetaEngine::listSaves(const char *target) const { return Sherlock::SaveManager(nullptr, "").getSavegameList(target); } diff --git a/engines/sherlock/saveload.cpp b/engines/sherlock/saveload.cpp index 207eff1ab4..7610c42d8c 100644 --- a/engines/sherlock/saveload.cpp +++ b/engines/sherlock/saveload.cpp @@ -383,10 +383,6 @@ void SaveManager::synchronize(Common::Serializer &s) { if (screen.fontNumber() != oldFont) journal.resetPosition(); - /* - char room_flags[MAX_ROOMS * 9]; - - */ _vm->_loadingSavedGame = true; _justLoaded = true; diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index cd5d48033a..518a7aa86b 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -51,6 +51,7 @@ SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gam _slowChess = false; _keyPadSpeed = 0; _loadGameSlot = -1; + _canLoadSave = false; } SherlockEngine::~SherlockEngine() { @@ -147,8 +148,11 @@ void SherlockEngine::sceneLoop() { // Handle any input from the keyboard or mouse handleInput(); - if (_scene->_hsavedPos.x == -1) + if (_scene->_hsavedPos.x == -1) { + _canLoadSave = true; _scene->doBgAnim(); + _canLoadSave = false; + } } _scene->freeScene(); @@ -160,7 +164,9 @@ void SherlockEngine::sceneLoop() { * Handle all player input */ void SherlockEngine::handleInput() { + _canLoadSave = true; _events->pollEventsAndWait(); + _canLoadSave = false; // See if a key or mouse button is pressed _events->setButtonState(); @@ -190,15 +196,10 @@ void SherlockEngine::setFlags(int flagNum) { _scene->checkSceneFlags(true); } -void SherlockEngine::freeSaveGameList() { - // TODO -} - void SherlockEngine::saveConfig() { // TODO } - /** * Synchronize the data for a savegame */ @@ -207,4 +208,34 @@ void SherlockEngine::synchronize(Common::Serializer &s) { s.syncAsByte(_flags[idx]); } +/** + * Returns true if a savegame can be loaded + */ +bool SherlockEngine::canLoadGameStateCurrently() { + return _canLoadSave; +} + +/** + * Returns true if the game can be saved + */ +bool SherlockEngine::canSaveGameStateCurrently() { + return _canLoadSave; +} + +/** + * Called by the GMM to load a savegame + */ +Common::Error SherlockEngine::loadGameState(int slot) { + _saves->loadGame(slot); + return Common::kNoError; +} + +/** + * Called by the GMM to save the game + */ +Common::Error SherlockEngine::saveGameState(int slot, const Common::String &desc) { + _saves->saveGame(slot, desc); + return Common::kNoError; +} + } // End of namespace Comet diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h index 09e969884c..916c9cd253 100644 --- a/engines/sherlock/sherlock.h +++ b/engines/sherlock/sherlock.h @@ -80,6 +80,8 @@ protected: virtual void showOpening() = 0; virtual void startScene() {} + + virtual bool hasFeature(EngineFeature f) const; public: const SherlockGameDescription *_gameDescription; Animation *_animation; @@ -108,12 +110,18 @@ public: bool _slowChess; int _keyPadSpeed; int _loadGameSlot; + bool _canLoadSave; public: SherlockEngine(OSystem *syst, const SherlockGameDescription *gameDesc); virtual ~SherlockEngine(); virtual Common::Error run(); + virtual bool canLoadGameStateCurrently(); + virtual bool canSaveGameStateCurrently(); + virtual Common::Error loadGameState(int slot); + virtual Common::Error saveGameState(int slot, const Common::String &desc); + int getGameType() const; uint32 getGameID() const; uint32 getGameFeatures() const; @@ -128,8 +136,6 @@ public: void setFlags(int flagNum); - void freeSaveGameList(); - void saveConfig(); void synchronize(Common::Serializer &s); -- cgit v1.2.3 From 4f04f90a97965e278f5cbda6fbbd36fa493655cb Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 22 Apr 2015 07:14:49 -0500 Subject: SHERLOCK: Fix thumbnails for savegames made via in-game files dialog --- engines/sherlock/user_interface.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'engines') diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index cb10606562..a3631c577d 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -1603,6 +1603,12 @@ void UserInterface::doMainControl() { case 'F': pushButton(10); _menuMode = FILES_MODE; + + // Create a thumbnail of the current screen before the files dialog is shown, in case + // the user saves the game + saves.createThumbnail(); + + // Display the dialog saves.drawInterface(); _selector = _oldSelector = -1; -- cgit v1.2.3 From 214cd61afd6ab60f749263a54127dfbd629147dd Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 22 Apr 2015 17:23:14 -0500 Subject: SHERLOCK: Fixes for multi-point walking routes --- engines/sherlock/map.cpp | 6 ++++-- engines/sherlock/objects.cpp | 2 +- engines/sherlock/people.cpp | 18 +++++++++--------- engines/sherlock/people.h | 4 ++-- 4 files changed, 16 insertions(+), 14 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/map.cpp b/engines/sherlock/map.cpp index 6fd169f43a..6fff48a1d3 100644 --- a/engines/sherlock/map.cpp +++ b/engines/sherlock/map.cpp @@ -399,8 +399,10 @@ void Map::walkTheStreets() { people._walkTo.clear(); if (!reversePath) { - people._walkTo = tempPath; - people._walkDest = tempPath[0]; + for (int idx = 0; idx < (int)tempPath.size(); ++idx) + people._walkTo.push(tempPath[idx]); + + people._walkDest = tempPath.front(); } else { for (int idx = 0; idx < ((int)tempPath.size() - 1); ++idx) people._walkTo.push(tempPath[idx]); diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index 82daa90a38..ec8bb4f551 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -291,7 +291,7 @@ void Sprite::checkSprite() { break; case WALK_AROUND: - if (objBounds.contains(people._walkTo.top())) { + if (objBounds.contains(people._walkTo.front())) { // Reached zone people.gotoStand(*this); } else { diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp index 86c560a1d9..0212be69b2 100644 --- a/engines/sherlock/people.cpp +++ b/engines/sherlock/people.cpp @@ -554,7 +554,7 @@ void People::goAllTheWay() { ++i; // See how many points there are between the src and dest zones - if (!count || count == 255) { + if (!count || count == -1) { // There are none, so just walk to the new zone setWalking(); } else { @@ -563,22 +563,22 @@ void People::goAllTheWay() { _walkTo.clear(); if (scene._walkDirectory[_srcZone][_destZone] != -1) { - for (int idx = 0; idx < count; ++idx, i += 3) { + i += 3 * (count - 1); + for (int idx = 0; idx < count; ++idx, i -= 3) { _walkTo.push(Common::Point(READ_LE_UINT16(&scene._walkData[i]), scene._walkData[i + 2])); } } else { - for (int idx = 0; idx < count; ++idx) - _walkTo.push(Common::Point()); - - for (int idx = count - 1; idx >= 0; --idx, i += 3) { - _walkTo[idx].x = READ_LE_UINT16(&scene._walkData[i]); - _walkTo[idx].y = scene._walkData[i + 2]; + for (int idx = 0; idx < count; ++idx, i += 3) { + _walkTo.push(Common::Point(READ_LE_UINT16(&scene._walkData[i]), scene._walkData[i + 2])); } } + // Final position + _walkTo.push(_walkDest); + // Start walking - _walkDest = _walkTo.top(); + _walkDest = _walkTo.pop(); setWalking(); } } diff --git a/engines/sherlock/people.h b/engines/sherlock/people.h index 94f1d05c0d..8a7476a33a 100644 --- a/engines/sherlock/people.h +++ b/engines/sherlock/people.h @@ -25,7 +25,7 @@ #include "common/scummsys.h" #include "common/serializer.h" -#include "common/stack.h" +#include "common/queue.h" #include "sherlock/objects.h" namespace Sherlock { @@ -74,7 +74,7 @@ private: public: ImageFile *_talkPics; Common::Point _walkDest; - Common::Stack _walkTo; + Common::Queue _walkTo; Person &_player; bool _holmesOn; bool _portraitLoaded; -- cgit v1.2.3 From 0a4b722b5d348ba38ab4161cac06597506cbe6cf Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 22 Apr 2015 17:36:50 -0500 Subject: SHERLOCK: Fix leaving scenes via exit zones --- engines/sherlock/objects.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index ec8bb4f551..a1ead2c437 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -161,11 +161,15 @@ void Sprite::adjustSprite() { Exit *exit = scene.checkForExit(charRect); if (exit) { - scene._hsavedPos = exit->_people; - scene._hsavedFs = exit->_peopleDir; + scene._goToScene = exit->_scene; - if (scene._hsavedFs > 100 && scene._hsavedPos.x < 1) - scene._hsavedPos.x = 100; + if (exit->_people.x != 0) { + scene._hsavedPos = exit->_people; + scene._hsavedFs = exit->_peopleDir; + + if (scene._hsavedFs > 100 && scene._hsavedPos.x < 1) + scene._hsavedPos.x = 100; + } } } } -- cgit v1.2.3 From afbc333696c11a5a10bd6aa1061eded92836c751 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 22 Apr 2015 18:41:40 -0500 Subject: SHERLOCK: Fix display of overhead map --- engines/sherlock/map.cpp | 33 +++++++++++++++++++++------------ engines/sherlock/map.h | 3 ++- engines/sherlock/scalpel/scalpel.cpp | 11 +++++++++-- 3 files changed, 32 insertions(+), 15 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/map.cpp b/engines/sherlock/map.cpp index 6fff48a1d3..e07dedf7dd 100644 --- a/engines/sherlock/map.cpp +++ b/engines/sherlock/map.cpp @@ -34,7 +34,7 @@ Map::Map(SherlockEngine *vm): _vm(vm), _topLine(SHERLOCK_SCREEN_WIDTH, 12) { _charPoint = _oldCharPoint = -1; _cursorIndex = -1; _drawMap = false; - for (int idx = 0; idx < 3; ++idx) + for (int idx = 0; idx < MAX_HOLMES_SEQUENCE; ++idx) Common::fill(&_sequences[idx][0], &_sequences[idx][MAX_FRAME], 0); loadData(); @@ -49,6 +49,15 @@ void Map::loadPoints(int count, const int *xList, const int *yList, const int *t } } +/** + * Load the sequence data for player icon animations + */ +void Map::loadSequences(int count, const byte *seq) { + for (int idx = 0; idx < count; ++idx, seq += MAX_FRAME) + Common::copy(seq, seq + MAX_FRAME, &_sequences[idx][0]); +} + + /** * Load data needed for the map */ @@ -108,10 +117,10 @@ int Map::show() { // Load need sprites setupSprites(); - screen._backBuffer1.blitFrom(bigMap[1], Common::Point(-_bigPos.x, -_bigPos.y)); - screen._backBuffer1.blitFrom(bigMap[2], Common::Point(-_bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y)); - screen._backBuffer1.blitFrom(bigMap[3], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, -_bigPos.y)); - screen._backBuffer1.blitFrom(bigMap[4], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y)); + screen._backBuffer1.blitFrom(bigMap[0], Common::Point(-_bigPos.x, -_bigPos.y)); + screen._backBuffer1.blitFrom(bigMap[1], Common::Point(-_bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y)); + screen._backBuffer1.blitFrom(bigMap[2], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, -_bigPos.y)); + screen._backBuffer1.blitFrom(bigMap[3], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y)); _drawMap = true; _point = -1; @@ -168,10 +177,10 @@ int Map::show() { // Map has scrolled, so redraw new map view changed = false; - screen._backBuffer1.blitFrom(bigMap[1], Common::Point(-_bigPos.x, -_bigPos.y)); - screen._backBuffer1.blitFrom(bigMap[2], Common::Point(-_bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y)); - screen._backBuffer1.blitFrom(bigMap[3], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, -_bigPos.y)); - screen._backBuffer1.blitFrom(bigMap[4], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y)); + screen._backBuffer1.blitFrom(bigMap[0], Common::Point(-_bigPos.x, -_bigPos.y)); + screen._backBuffer1.blitFrom(bigMap[1], Common::Point(-_bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y)); + screen._backBuffer1.blitFrom(bigMap[2], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, -_bigPos.y)); + screen._backBuffer1.blitFrom(bigMap[3], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y)); showPlaces(); _placesShown = false; @@ -249,7 +258,7 @@ void Map::setupSprites() { p._type = CHARACTER; p._position = Common::Point(12400, 5000); p._sequenceNumber = 0; - p._sequences = (Sequences *)&_sequences; + p._sequences = &_sequences; p._images = _shapes; p._imageFrame = nullptr; p._frameNumber = 0; @@ -283,13 +292,13 @@ void Map::showPlaces() { Screen &screen = *_vm->_screen; for (uint idx = 0; idx < _points.size(); ++idx) { - const Common::Point &pt = _points[idx]; + const MapEntry &pt = _points[idx]; if (pt.x != 0 && pt.y != 0) { if (pt.x >= _bigPos.x && (pt.x - _bigPos.x) < SHERLOCK_SCREEN_WIDTH && pt.y >= _bigPos.y && (pt.y - _bigPos.y) < SHERLOCK_SCREEN_HEIGHT) { if (_vm->readFlags(idx)) { - screen._backBuffer1.transBlitFrom((*_iconShapes)[idx], + screen._backBuffer1.transBlitFrom((*_iconShapes)[pt._translate], Common::Point(pt.x - _bigPos.x - 6, pt.y - _bigPos.y - 12)); } } diff --git a/engines/sherlock/map.h b/engines/sherlock/map.h index f324160bce..5b63fe768c 100644 --- a/engines/sherlock/map.h +++ b/engines/sherlock/map.h @@ -56,7 +56,7 @@ private: ImageFile *_mapCursors; ImageFile *_shapes; ImageFile *_iconShapes; - byte _sequences[3][MAX_FRAME]; + byte _sequences[MAX_HOLMES_SEQUENCE][MAX_FRAME]; Common::Point _bigPos; Common::Point _overPos; Common::Point _lDrawnPos; @@ -89,6 +89,7 @@ public: const MapEntry &operator[](int idx) { return _points[idx]; } void loadPoints(int count, const int *xList, const int *yList, const int *transList); + void loadSequences(int count, const byte *seq); int show(); }; diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp index 4e49a6b4d3..2ca9f80c42 100644 --- a/engines/sherlock/scalpel/scalpel.cpp +++ b/engines/sherlock/scalpel/scalpel.cpp @@ -39,12 +39,18 @@ const int MAP_Y[NUM_PLACES] = { 37, 0, 70, 0, 116, 0, 0, 0, 50, 21, 0, 303, 0, 0, 229, 0, 0 }; -int MAP_TRANSLATE[NUM_PLACES] = { +const int MAP_TRANSLATE[NUM_PLACES] = { 0, 0, 0, 1, 0, 2, 0, 3, 4, 0, 4, 6, 0, 0, 0, 8, 9, 10, 11, 0, 12, 13, 14, 7, 15, 16, 17, 18, 19, 0, 20, 21, 22, 23, 0, 24, 0, 25, 0, 26, 0, 0, 0, 27, 28, 0, 29, 0, 0, 30, 0 }; +const byte MAP_SEQUENCES[3][MAX_FRAME] = { + { 1, 1, 2, 3, 4, 0 }, // Overview Still + { 5, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 0 }, + { 5, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 0 } +}; + #define MAX_PEOPLE 66 const byte STILL_SEQUENCES[MAX_PEOPLE][MAX_TALK_SEQUENCES] = { @@ -209,8 +215,9 @@ void ScalpelEngine::initialize() { _flags[3] = true; // Turn on Alley _flags[39] = true; // Turn on Baker Street - // Load the map co-ordinates for each scene + // Load the map co-ordinates for each scene and sequence data _map->loadPoints(NUM_PLACES, &MAP_X[0], &MAP_Y[0], &MAP_TRANSLATE[0]); + _map->loadSequences(3, &MAP_SEQUENCES[0][0]); // Load the inventory loadInventory(); -- cgit v1.2.3 From 1ae176f3eb2e392d400095d734895728f0a5eabc Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 22 Apr 2015 19:44:57 -0500 Subject: SHERLOCK: Fix display of location names on overhead map --- engines/sherlock/map.cpp | 74 ++++++++++++++++++++++++++++++++++++++++++++++++ engines/sherlock/map.h | 3 ++ 2 files changed, 77 insertions(+) (limited to 'engines') diff --git a/engines/sherlock/map.cpp b/engines/sherlock/map.cpp index e07dedf7dd..b89b4b29fa 100644 --- a/engines/sherlock/map.cpp +++ b/engines/sherlock/map.cpp @@ -113,6 +113,7 @@ int Map::show() { // Load the entire map ImageFile bigMap("bigmap.vgs"); + screen.setPalette(bigMap._palette); // Load need sprites setupSprites(); @@ -194,6 +195,10 @@ int Map::show() { _placesShown = true; } + if (_cursorIndex == 0) { + Common::Point pt = events.mousePos(); + highlightIcon(Common::Point(pt.x - 4 + _bigPos.x, pt.y + _bigPos.y)); + } updateMap(false); } @@ -321,6 +326,34 @@ void Map::eraseTopLine() { screen.blitFrom(_topLine, Common::Point(0, 0)); } +/** + * Prints the name of the specified icon + */ +void Map::showPlaceName(int idx, bool highlighted) { + People &people = *_vm->_people; + Screen &screen = *_vm->_screen; + + Common::String name = _locationNames[idx]; + int width = screen.stringWidth(name); + + if (!_cursorIndex) { + saveIcon(people[AL]._imageFrame, _lDrawnPos); + + bool flipped = people[AL]._sequenceNumber == MAP_DOWNLEFT || people[AL]._sequenceNumber == MAP_LEFT + || people[AL]._sequenceNumber == MAP_UPLEFT; + screen._backBuffer1.transBlitFrom(people[AL]._imageFrame->_frame, _lDrawnPos, flipped); + } + + if (highlighted) { + int xp = (SHERLOCK_SCREEN_WIDTH - screen.stringWidth(name)) / 2; + screen.gPrint(Common::Point(xp + 2, 2), 0, name.c_str()); + screen.gPrint(Common::Point(xp + 1, 1), 0, name.c_str()); + screen.gPrint(Common::Point(xp, 0), 12, name.c_str()); + + screen.slamArea(xp, 0, screen.stringWidth(name) + 2, 15); + } +} + /** * Update all on-screen sprites to account for any scrolling of the map */ @@ -473,4 +506,45 @@ void Map::restoreIcon() { screen._backBuffer1.blitFrom(_iconSave, _savedPos); } +/** + * Handles highlighting map icons, showing their names + */ +void Map::highlightIcon(const Common::Point &pt) { + int oldPoint = _point; + + // Iterate through the icon list + bool done = false; + for (uint idx = 0; idx < _points.size(); ++idx) { + const MapEntry &entry = _points[idx]; + + // Check whether the mouse is over a given icon + if (entry.x != 0 && entry.y != 0) { + if (Common::Rect(entry.x - 8, entry.y - 8, entry.x + 9, entry.y + 9).contains(pt)) { + done = true; + + if (_point != idx && _vm->readFlags(idx)) { + // Changed to a new valid (visible) location + eraseTopLine(); + showPlaceName(idx, true); + _point = idx; + } + } + } + } + + if (!done) { + // No icon was highlighted + if (_point != -1) { + // No longer highlighting previously highlighted icon, so erase it + showPlaceName(_point, false); + eraseTopLine(); + } + + _point = -1; + } else if (oldPoint != -1 && oldPoint != _point) { + showPlaceName(oldPoint, false); + eraseTopLine(); + } +} + } // End of namespace Sherlock diff --git a/engines/sherlock/map.h b/engines/sherlock/map.h index 5b63fe768c..752137e0ba 100644 --- a/engines/sherlock/map.h +++ b/engines/sherlock/map.h @@ -76,6 +76,7 @@ private: void saveTopLine(); void eraseTopLine(); + void showPlaceName(int idx, bool highlighted); void updateMap(bool flushScreen); @@ -83,6 +84,8 @@ private: void saveIcon(ImageFrame *src, const Common::Point &pt); void restoreIcon(); + + void highlightIcon(const Common::Point &pt); public: Map(SherlockEngine *vm); -- cgit v1.2.3 From 02e604ce8c2b0a4f136a6d0815b55046c58ad92d Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 22 Apr 2015 19:59:27 -0500 Subject: SHERLOCK: Fix display of Holmes' icon on overhead map --- engines/sherlock/map.cpp | 25 +++++++++++++++---------- engines/sherlock/map.h | 3 ++- engines/sherlock/objects.cpp | 7 ++++--- engines/sherlock/people.cpp | 13 +++++++------ engines/sherlock/sherlock.cpp | 1 - engines/sherlock/sherlock.h | 1 - 6 files changed, 28 insertions(+), 22 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/map.cpp b/engines/sherlock/map.cpp index b89b4b29fa..5173e0296e 100644 --- a/engines/sherlock/map.cpp +++ b/engines/sherlock/map.cpp @@ -26,14 +26,15 @@ namespace Sherlock { Map::Map(SherlockEngine *vm): _vm(vm), _topLine(SHERLOCK_SCREEN_WIDTH, 12) { + _active = false; _mapCursors = nullptr; _shapes = nullptr; _iconShapes = nullptr; _point = 0; _placesShown = false; - _charPoint = _oldCharPoint = -1; _cursorIndex = -1; _drawMap = false; + _overPos = Common::Point(13000, 12600); for (int idx = 0; idx < MAX_HOLMES_SEQUENCE; ++idx) Common::fill(&_sequences[idx][0], &_sequences[idx][MAX_FRAME], 0); @@ -103,9 +104,11 @@ void Map::loadData() { int Map::show() { Events &events = *_vm->_events; People &people = *_vm->_people; + Scene &scene = *_vm->_scene; Screen &screen = *_vm->_screen; Common::Point lDrawn(-1, -1); bool changed = false, exitFlag = false; + _active = true; // Set font and custom cursor for the map int oldFont = screen.fontNumber(); @@ -204,7 +207,7 @@ int Map::show() { if ((events._released || events._rightReleased) && _point != -1) { if (people[AL]._walkCount == 0) { - _charPoint = _point; + scene._charPoint = _point; walkTheStreets(); _cursorIndex = 1; @@ -214,7 +217,7 @@ int Map::show() { // Check if a scene has beeen selected and we've finished "moving" to it if (people[AL]._walkCount == 0) { - if (_charPoint >= 1 && _charPoint < (int)_points.size()) + if (scene._charPoint >= 1 && scene._charPoint < (int)_points.size()) exitFlag = true; } @@ -238,7 +241,8 @@ int Map::show() { screen.setFont(oldFont); events.setCursor(ARROW); - return _charPoint; + _active = false; + return scene._charPoint; } /** @@ -350,7 +354,7 @@ void Map::showPlaceName(int idx, bool highlighted) { screen.gPrint(Common::Point(xp + 1, 1), 0, name.c_str()); screen.gPrint(Common::Point(xp, 0), 12, name.c_str()); - screen.slamArea(xp, 0, screen.stringWidth(name) + 2, 15); + screen.slamArea(xp, 0, width + 2, 15); } } @@ -408,21 +412,22 @@ void Map::updateMap(bool flushScreen) { */ void Map::walkTheStreets() { People &people = *_vm->_people; + Scene &scene = *_vm->_scene; bool reversePath = false; Common::Array tempPath; // Get indexes into the path lists for the start and destination scenes - int start = _points[_oldCharPoint]._translate; - int dest = _points[_charPoint]._translate; + int start = _points[scene._oldCharPoint]._translate; + int dest = _points[scene._charPoint]._translate; // Get pointer to start of path const int *ptr = &_paths[start][dest]; // Check for any intermediate points between the two locations - if (*ptr || _charPoint > 50 || _oldCharPoint > 50) { + if (*ptr || scene._charPoint > 50 || scene._oldCharPoint > 50) { people[AL]._sequenceNumber = -1; - if (_charPoint == 51 || _oldCharPoint == 51) { + if (scene._charPoint == 51 || scene._oldCharPoint == 51) { people.setWalking(); } else { // Check for moving the path backwards or forwards @@ -514,7 +519,7 @@ void Map::highlightIcon(const Common::Point &pt) { // Iterate through the icon list bool done = false; - for (uint idx = 0; idx < _points.size(); ++idx) { + for (int idx = 0; idx < (int)_points.size(); ++idx) { const MapEntry &entry = _points[idx]; // Check whether the mouse is over a given icon diff --git a/engines/sherlock/map.h b/engines/sherlock/map.h index 752137e0ba..da55a5e383 100644 --- a/engines/sherlock/map.h +++ b/engines/sherlock/map.h @@ -62,7 +62,6 @@ private: Common::Point _lDrawnPos; int _point; bool _placesShown; - int _charPoint, _oldCharPoint; int _cursorIndex; bool _drawMap; Surface _iconSave; @@ -86,6 +85,8 @@ private: void restoreIcon(); void highlightIcon(const Common::Point &pt); +public: + bool _active; public: Map(SherlockEngine *vm); diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index a1ead2c437..e5c6f847fb 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -81,6 +81,7 @@ void Sprite::setImageFrame() { * This adjusts the sprites position, as well as it's animation sequence: */ void Sprite::adjustSprite() { + Map &map = *_vm->_map; People &people = *_vm->_people; Scene &scene = *_vm->_scene; Talk &talk = *_vm->_talk; @@ -105,7 +106,7 @@ void Sprite::adjustSprite() { } } - if (_type == CHARACTER && !_vm->_onChessboard) { + if (_type == CHARACTER && !map._active) { if ((_position.y / 100) > LOWER_LIMIT) { _position.y = LOWER_LIMIT * 100; people.gotoStand(*this); @@ -120,12 +121,12 @@ void Sprite::adjustSprite() { _position.x = LEFT_LIMIT * 100; people.gotoStand(*this); } - } else if (!_vm->_onChessboard) { + } else if (!map._active) { _position.y = CLIP((int)_position.y, UPPER_LIMIT, LOWER_LIMIT); _position.x = CLIP((int)_position.x, LEFT_LIMIT, RIGHT_LIMIT); } - if (!_vm->_onChessboard || (_vm->_slowChess = !_vm->_slowChess)) + if (!map._active || (_vm->_slowChess = !_vm->_slowChess)) ++_frameNumber; if ((*_sequences)[_sequenceNumber][_frameNumber] == 0) { diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp index 0212be69b2..d247109a28 100644 --- a/engines/sherlock/people.cpp +++ b/engines/sherlock/people.cpp @@ -270,6 +270,7 @@ bool People::freeWalk() { * check for any obstacles in the path. */ void People::setWalking() { + Map &map = *_vm->_map; Scene &scene = *_vm->_scene; int oldDirection, oldFrame; Common::Point speed, delta; @@ -284,7 +285,7 @@ void People::setWalking() { oldFrame = _player._frameNumber; // Set speed to use horizontal and vertical movement - if (_vm->_onChessboard) { + if (map._active) { speed = Common::Point(MWALK_SPEED, MWALK_SPEED); } else { speed = Common::Point(XWALK_SPEED, YWALK_SPEED); @@ -321,10 +322,10 @@ void People::setWalking() { // Set the initial frame sequence for the left and right, as well // as settting the delta x depending on direction if (_walkDest.x < (_player._position.x / 100)) { - _player._sequenceNumber = _vm->_onChessboard ? MAP_LEFT : WALK_LEFT; + _player._sequenceNumber = map._active ? MAP_LEFT : WALK_LEFT; _player._delta.x = speed.x * -100; } else { - _player._sequenceNumber = _vm->_onChessboard ? MAP_RIGHT : WALK_RIGHT; + _player._sequenceNumber = map._active ? MAP_RIGHT : WALK_RIGHT; _player._delta.x = speed.x * 100; } @@ -348,7 +349,7 @@ void People::setWalking() { // See if the sequence needs to be changed for diagonal walking if (_player._delta.y > 150) { - if (!_vm->_onChessboard) { + if (!map._active) { switch (_player._sequenceNumber) { case WALK_LEFT: _player._sequenceNumber = WALK_DOWNLEFT; @@ -359,7 +360,7 @@ void People::setWalking() { } } } else if (_player._delta.y < -150) { - if (!_vm->_onChessboard) { + if (!map._active) { switch (_player._sequenceNumber) { case WALK_LEFT: _player._sequenceNumber = WALK_UPLEFT; @@ -447,7 +448,7 @@ void People::gotoStand(Sprite &sprite) { if (_oldWalkSequence != -1 || sprite._sequenceNumber == STOP_UP) sprite._frameNumber = 0; - if (_vm->_onChessboard) { + if (map._active) { sprite._sequenceNumber = 0; _data[AL]._position.x = (map[scene._charPoint].x - 6) * 100; _data[AL]._position.y = (map[scene._charPoint].x + 10) * 100; diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index 518a7aa86b..d880257406 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -47,7 +47,6 @@ SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gam _ui = nullptr; _useEpilogue2 = false; _loadingSavedGame = false; - _onChessboard = false; _slowChess = false; _keyPadSpeed = 0; _loadGameSlot = -1; diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h index 916c9cd253..ce126c0dcc 100644 --- a/engines/sherlock/sherlock.h +++ b/engines/sherlock/sherlock.h @@ -106,7 +106,6 @@ public: bool _loadingSavedGame; int _oldCharPoint; // Old scene Common::Point _over; // Old map position - bool _onChessboard; bool _slowChess; int _keyPadSpeed; int _loadGameSlot; -- cgit v1.2.3 From e24ae07a90ccd0139112d5c086d49173834fa4a1 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 22 Apr 2015 21:11:26 -0500 Subject: SHERLOCK: Fix map path loading --- engines/sherlock/map.cpp | 60 +++++++++++++++++++++++++++++++++----------- engines/sherlock/map.h | 12 ++++++++- engines/sherlock/objects.cpp | 2 +- 3 files changed, 57 insertions(+), 17 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/map.cpp b/engines/sherlock/map.cpp index 5173e0296e..0864997dff 100644 --- a/engines/sherlock/map.cpp +++ b/engines/sherlock/map.cpp @@ -25,6 +25,33 @@ namespace Sherlock { +/** + * Load the data for the paths between locations on the map + */ +void MapPaths::load(int numLocations, Common::SeekableReadStream &s) { + _numLocations = numLocations; + _paths.resize(_numLocations * _numLocations); + + for (int idx = 0; idx < (numLocations * numLocations); ++idx) { + Common::Array &path = _paths[idx]; + int v; + + do { + v = s.readByte(); + path.push_back(v); + } while (v && v < 254); + } +} + +/** + * Get the path between two locations on the map + */ +const byte *MapPaths::getPath(int srcLocation, int destLocation) { + return &_paths[srcLocation * _numLocations + destLocation][0]; +} + +/*----------------------------------------------------------------*/ + Map::Map(SherlockEngine *vm): _vm(vm), _topLine(SHERLOCK_SCREEN_WIDTH, 12) { _active = false; _mapCursors = nullptr; @@ -80,15 +107,10 @@ void Map::loadData() { // Load the path data Common::SeekableReadStream *pathStream = _vm->_res->load("chess.pth"); - _paths.resize(31); - for (uint idx = 0; idx < _paths.size(); ++idx) { - _paths[idx].resize(_paths.size()); + // Get routes between different locations on the map + _paths.load(31, *pathStream); - for (uint idx2 = 0; idx2 < _paths.size(); ++idx2) - _paths[idx][idx2] = pathStream->readSint16LE(); - } - - // Load in the path point information + // Load in the co-ordinates that the paths refer to _pathPoints.resize(208); for (uint idx = 0; idx < _pathPoints.size(); ++idx) { _pathPoints[idx].x = pathStream->readSint16LE(); @@ -207,9 +229,13 @@ int Map::show() { if ((events._released || events._rightReleased) && _point != -1) { if (people[AL]._walkCount == 0) { + people._walkDest = _points[_point] + Common::Point(4, 9); scene._charPoint = _point; + + // Start walking to selected location walkTheStreets(); + // Show wait cursor _cursorIndex = 1; events.setCursor((*_mapCursors)[_cursorIndex]); } @@ -373,7 +399,7 @@ void Map::updateMap(bool flushScreen) { if (++_cursorIndex > (1 + 8)) _cursorIndex = 1; - events.setCursor((*_mapCursors)[_cursorIndex]); + events.setCursor((*_mapCursors)[(_cursorIndex + 1) / 2]); } if (!_drawMap && !flushScreen) @@ -421,26 +447,30 @@ void Map::walkTheStreets() { int dest = _points[scene._charPoint]._translate; // Get pointer to start of path - const int *ptr = &_paths[start][dest]; + const byte *path = _paths.getPath(start, dest); + + // Add in destination position + people._walkTo.clear(); + people._walkTo.push(people._walkDest); // Check for any intermediate points between the two locations - if (*ptr || scene._charPoint > 50 || scene._oldCharPoint > 50) { + if (path[0] || scene._charPoint > 50 || scene._oldCharPoint > 50) { people[AL]._sequenceNumber = -1; if (scene._charPoint == 51 || scene._oldCharPoint == 51) { people.setWalking(); } else { // Check for moving the path backwards or forwards - if (*ptr == 255) { + if (path[0] == 255) { reversePath = true; SWAP(start, dest); - ptr = &_paths[start][dest]; + path = _paths.getPath(start, dest); } do { - int idx = *ptr++; + int idx = *path++; tempPath.push_back(_pathPoints[idx - 1] + Common::Point(4, 4)); - } while (*ptr != 254); + } while (*path != 254); // Load up the path to use people._walkTo.clear(); diff --git a/engines/sherlock/map.h b/engines/sherlock/map.h index da55a5e383..a91e7ae968 100644 --- a/engines/sherlock/map.h +++ b/engines/sherlock/map.h @@ -43,12 +43,22 @@ struct MapEntry : Common::Point { MapEntry(int x, int y, int translate) : Common::Point(x, y), _translate(translate) {} }; +class MapPaths { +private: + int _numLocations; + Common::Array< Common::Array > _paths; +public: + void load(int numLocations, Common::SeekableReadStream &s); + + const byte *getPath(int srcLocation, int destLocation); +}; + class Map { private: SherlockEngine *_vm; Common::Array _points; // Map locations for each scene Common::StringArray _locationNames; - Common::Array< Common::Array > _paths; + MapPaths _paths; Common::Array _pathPoints; Common::Point _savedPos; Common::Point _savedSize; diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index e5c6f847fb..262006b3b1 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -474,7 +474,7 @@ void Object::synchronize(Common::SeekableReadStream &s) { _defaultCommand = s.readByte(); _lookFlag = s.readUint16LE(); _pickupFlag = s.readUint16LE(); - _requiredFlag = s.readUint16LE(); + _requiredFlag = s.readSint16LE(); _noShapeSize.x = s.readUint16LE(); _noShapeSize.y = s.readUint16LE(); _status = s.readUint16LE(); -- cgit v1.2.3 From 179ef7adb2c7dd0eb790a58748ad374ce92b898d Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Thu, 23 Apr 2015 18:54:07 +0200 Subject: SCI: fix Camelot save on map screen bug #6744 don't put restored script windows into _windowList[] --- engines/sci/engine/savegame.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 61f8058e45..d146cba204 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -772,10 +772,17 @@ void GfxPorts::saveLoadWithSerializer(Common::Serializer &s) { if (window->counterTillFree) { _freeCounter++; } else { - if (window->wndStyle & SCI_WINDOWMGR_STYLE_TOPMOST) - _windowList.push_front(window); - else - _windowList.push_back(window); + // we don't put the saved script windows into _windowList[], so that they aren't used + // by kernel functions. This is important and would cause issues otherwise. + // see Conquests of Camelot - bug #6744 - when saving on the map screen (room 103), + // restoring would result in a black window in place + // where the area name was displayed before + // In Sierra's SCI the behaviour is identical to us + // Sierra's SCI won't show those windows after restoring + // If this should cause issues in another game, we would have to add a flag to simply + // avoid any drawing operations for such windows + // We still have to restore script windows, because for example Conquests of Camelot + // will immediately delete windows, that were created before saving the game. } windowCount--; -- cgit v1.2.3 From ecaa4c26c953524bdf34fa55cfdf6c55af129bc4 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 24 Apr 2015 00:53:19 -0500 Subject: SHERLOCK: Fix pathfinding for movement on map screen --- engines/sherlock/map.cpp | 20 +++++++++----------- engines/sherlock/people.cpp | 4 +++- 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/map.cpp b/engines/sherlock/map.cpp index 0864997dff..6e9982eb62 100644 --- a/engines/sherlock/map.cpp +++ b/engines/sherlock/map.cpp @@ -263,9 +263,8 @@ int Map::show() { freeSprites(); _overPos = people[AL]._position; - // Reset font and cursor + // Reset font screen.setFont(oldFont); - events.setCursor(ARROW); _active = false; return scene._charPoint; @@ -451,7 +450,7 @@ void Map::walkTheStreets() { // Add in destination position people._walkTo.clear(); - people._walkTo.push(people._walkDest); + Common::Point destPos = people._walkDest; // Check for any intermediate points between the two locations if (path[0] || scene._charPoint > 50 || scene._oldCharPoint > 50) { @@ -475,24 +474,23 @@ void Map::walkTheStreets() { // Load up the path to use people._walkTo.clear(); - if (!reversePath) { - for (int idx = 0; idx < (int)tempPath.size(); ++idx) + if (reversePath) { + for (int idx = (int)tempPath.size() - 1; idx >= 0; --idx) people._walkTo.push(tempPath[idx]); - - people._walkDest = tempPath.front(); } else { - for (int idx = 0; idx < ((int)tempPath.size() - 1); ++idx) + for (int idx = 0; idx < (int)tempPath.size(); ++idx) people._walkTo.push(tempPath[idx]); - people._walkDest = tempPath[tempPath.size() - 1]; } - people._walkDest.x += 12; - people._walkDest.y += 6; + people._walkDest = people._walkTo.pop() + Common::Point(12, 6); people.setWalking(); } } else { people[AL]._walkCount = 0; } + + // Store the final destination icon position + people._walkTo.push(destPos); } /** diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp index d247109a28..e126757231 100644 --- a/engines/sherlock/people.cpp +++ b/engines/sherlock/people.cpp @@ -389,7 +389,9 @@ void People::setWalking() { // Set the delta x _player._delta.x = (delta.x * 100) / (delta.y / speed.y); if (_walkDest.x < (_player._position.x / 100)) - _player._delta.x = -_player._delta.x; + _player._delta.x = -_player._delta.x;; + + _player._walkCount = delta.y / speed.y; } } -- cgit v1.2.3 From a5edfcc3f5e59a8bb68b6bcbc8d7b6ce72ec633a Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 24 Apr 2015 01:35:51 -0500 Subject: SHERLOCK: Fix restoring background as player icon moves on map --- engines/sherlock/map.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/map.cpp b/engines/sherlock/map.cpp index 6e9982eb62..c3a5ba7b17 100644 --- a/engines/sherlock/map.cpp +++ b/engines/sherlock/map.cpp @@ -286,7 +286,7 @@ void Map::setupSprites() { _shapes = new ImageFile("mapicon.vgs"); _iconShapes = new ImageFile("overicon.vgs"); - + _iconSave.create((*_shapes)[4]._width, (*_shapes)[4]._height); Person &p = people[AL]; p._description = " "; p._type = CHARACTER; @@ -317,6 +317,7 @@ void Map::freeSprites() { delete _mapCursors; delete _shapes; delete _iconShapes; + _iconSave.free(); } /** @@ -523,9 +524,11 @@ void Map::saveIcon(ImageFrame *src, const Common::Point &pt) { return; } - _iconSave.create(size.x, size.y); + assert(size.x <= _iconSave.w && size.y <= _iconSave.h); _iconSave.blitFrom(screen._backBuffer1, Common::Point(0, 0), Common::Rect(pos.x, pos.y, pos.x + size.x, pos.y + size.y)); + _savedPos = pos; + _savedSize = size; } /** @@ -536,7 +539,7 @@ void Map::restoreIcon() { if (_savedPos.x >= 0 && _savedPos.y >= 0 && _savedPos.x <= SHERLOCK_SCREEN_WIDTH && _savedPos.y < SHERLOCK_SCREEN_HEIGHT) - screen._backBuffer1.blitFrom(_iconSave, _savedPos); + screen._backBuffer1.blitFrom(_iconSave, _savedPos, Common::Rect(0, 0, _savedSize.x, _savedSize.y)); } /** -- cgit v1.2.3 From e2b233e0bb62e14fcf454cda74966dd5df071654 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 24 Apr 2015 01:47:25 -0500 Subject: SHERLOCK: Fix button display in talk dialog --- engines/sherlock/talk.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index 6740e89efc..3eeb0f0af5 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -672,7 +672,7 @@ void Talk::drawInterface() { screen.makeButton(Common::Rect(99, CONTROLS_Y, 139, CONTROLS_Y + 10), 119 - screen.stringWidth("Exit") / 2, "Exit"); screen.makeButton(Common::Rect(140, CONTROLS_Y, 180, CONTROLS_Y + 10), - 159 - screen.stringWidth("Up"), "Up"); + 159 - screen.stringWidth("Up") / 2, "Up"); screen.makeButton(Common::Rect(181, CONTROLS_Y, 221, CONTROLS_Y + 10), 200 - screen.stringWidth("Down") / 2, "Down"); } else { -- cgit v1.2.3 From 572ad464901eedfd20ab5a35149e669f4bcac64a Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 24 Apr 2015 02:17:59 -0500 Subject: SHERLOCK: Fix talk sequences being incorrectly started --- engines/sherlock/objects.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index 262006b3b1..888c34fa04 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -195,17 +195,17 @@ void Sprite::checkSprite() { for (uint idx = 0; idx < scene._bgShapes.size() && !talk._talkToAbort; ++idx) { Object &obj = scene._bgShapes[idx]; + if (obj._aType <= PERSON || obj._type == INVALID || obj._type == HIDDEN) + continue; - if (obj._aType > PERSON && obj._type != INVALID && obj._type != HIDDEN) { - if (obj._type == NO_SHAPE) { - objBounds = Common::Rect(obj._position.x, obj._position.y, - obj._position.x + obj._noShapeSize.x, obj._position.y + obj._noShapeSize.y); - } else { - int xp = obj._position.x + obj._imageFrame->_offset.x; - int yp = obj._position.y + obj._imageFrame->_offset.y; - objBounds = Common::Rect(xp, yp, - xp + obj._imageFrame->_frame.w, yp + obj._imageFrame->_frame.h); - } + if (obj._type == NO_SHAPE) { + objBounds = Common::Rect(obj._position.x, obj._position.y, + obj._position.x + obj._noShapeSize.x, obj._position.y + obj._noShapeSize.y); + } else { + int xp = obj._position.x + obj._imageFrame->_offset.x; + int yp = obj._position.y + obj._imageFrame->_offset.y; + objBounds = Common::Rect(xp, yp, + xp + obj._imageFrame->_frame.w, yp + obj._imageFrame->_frame.h); } if (objBounds.contains(pt)) { -- cgit v1.2.3 From 79a3db42e1d9809facdd551f71744656073c1eb9 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 24 Apr 2015 02:29:18 -0500 Subject: SHERLOCK: Fix 'Press any key' interface messages --- engines/sherlock/user_interface.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index a3631c577d..690eba2c84 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -72,8 +72,8 @@ const int SETUP_POINTS[12][4] = { const char COMMANDS[13] = "LMTPOCIUGJFS"; const char INVENTORY_COMMANDS[9] = { "ELUG-+,." }; -const char *const PRESS_KEY_FOR_MORE = "Press any _key for More."; -const char *const PRESS_KEY_TO_CONTINUE = "Press any _key to Continue."; +const char *const PRESS_KEY_FOR_MORE = "Press any Key for More."; +const char *const PRESS_KEY_TO_CONTINUE = "Press any Key to Continue."; const char *const MOPEN[] = { "This cannot be opened", "It is already open", "It is locked", "Wait for Watson", " ", "." -- cgit v1.2.3 From ecd50997ddaaf4c8ac648ecdb8bea1177f128610 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 24 Apr 2015 04:00:46 -0500 Subject: SHERLOCK: Fix Sherlock disappearing when walking to examine objects --- engines/sherlock/user_interface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index 690eba2c84..903b1e6002 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -715,7 +715,7 @@ void UserInterface::examine() { scene.startCAnim(_cNum, canimSpeed); } else if (obj._lookPosition.y != 0) { // Need to walk to the object to be examined - people.walkToCoords(obj._lookPosition, obj._lookFacing); + people.walkToCoords(Common::Point(obj._lookPosition.x, obj._lookPosition.y * 100), obj._lookFacing); } if (!talk._talkToAbort) { -- cgit v1.2.3 From 51eb601f8393876a4ff847a5f4ff9068acd66fc8 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 24 Apr 2015 05:12:30 -0500 Subject: SHERLOCK: Fix loading/handling of sprite offsets --- engines/sherlock/objects.cpp | 4 ++-- engines/sherlock/resources.cpp | 4 ++-- engines/sherlock/scene.cpp | 53 +++++++++++++++++++----------------------- 3 files changed, 28 insertions(+), 33 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index 888c34fa04..9e92b95532 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -691,8 +691,8 @@ bool Object::checkEndOfSequence() { if (seq == 99) { --_frameNumber; - screen._backBuffer1.transBlitFrom(_imageFrame->_frame, _position); - screen._backBuffer2.transBlitFrom(_imageFrame->_frame, _position); + screen._backBuffer1.transBlitFrom(*_imageFrame, _position); + screen._backBuffer2.transBlitFrom(*_imageFrame, _position); _type = INVALID; } else { setObjSequence(seq, false); diff --git a/engines/sherlock/resources.cpp b/engines/sherlock/resources.cpp index 262832c3c3..0d66646286 100644 --- a/engines/sherlock/resources.cpp +++ b/engines/sherlock/resources.cpp @@ -298,8 +298,8 @@ void ImageFile::load(Common::SeekableReadStream &stream, bool skipPalette) { frame._width = stream.readUint16LE() + 1; frame._height = stream.readUint16LE() + 1; frame._paletteBase = stream.readByte(); - frame._offset.x = stream.readUint16LE(); - frame._rleEncoded = ((frame._offset.x & 0xFF) == 1); + frame._rleEncoded = stream.readByte() == 1; + frame._offset.x = stream.readByte(); frame._offset.y = stream.readByte(); frame._rleEncoded = !skipPalette && frame._rleEncoded; diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 316b8739b1..e5d9fc611f 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -710,29 +710,27 @@ void Scene::updateBackground() { // Draw all active shapes which are behind the person for (uint idx = 0; idx < _bgShapes.size(); ++idx) { if (_bgShapes[idx]._type == ACTIVE_BG_SHAPE && _bgShapes[idx]._misc == BEHIND) - surface.transBlitFrom(_bgShapes[idx]._imageFrame->_frame, - _bgShapes[idx]._position, _bgShapes[idx]._flags & 2); + surface.transBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position, _bgShapes[idx]._flags & 2); } // Draw all canimations which are behind the person for (uint idx = 0; idx < _canimShapes.size(); ++idx) { if (_canimShapes[idx]._type == ACTIVE_BG_SHAPE && _canimShapes[idx]._misc == BEHIND) - surface.transBlitFrom(_canimShapes[idx]._imageFrame->_frame, + surface.transBlitFrom(*_canimShapes[idx]._imageFrame, _canimShapes[idx]._position, _canimShapes[idx]._flags & 2); } // Draw all active shapes which are normal and behind the person for (uint idx = 0; idx < _bgShapes.size(); ++idx) { if (_bgShapes[idx]._type == ACTIVE_BG_SHAPE && _bgShapes[idx]._misc == NORMAL_BEHIND) - surface.transBlitFrom(_bgShapes[idx]._imageFrame->_frame, - _bgShapes[idx]._position, _bgShapes[idx]._flags & 2); + surface.transBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position, _bgShapes[idx]._flags & 2); } // Draw all canimations which are normal and behind the person for (uint idx = 0; idx < _canimShapes.size(); ++idx) { if (_canimShapes[idx]._type == ACTIVE_BG_SHAPE && _canimShapes[idx]._misc == NORMAL_BEHIND) - surface.transBlitFrom(_canimShapes[idx]._imageFrame->_frame, - _canimShapes[idx]._position, _canimShapes[idx]._flags & 2); + surface.transBlitFrom(*_canimShapes[idx]._imageFrame, _canimShapes[idx]._position, + _canimShapes[idx]._flags & 2); } // Draw the player if he's active @@ -741,25 +739,23 @@ void Scene::updateBackground() { player._sequenceNumber == WALK_UPLEFT || player._sequenceNumber == STOP_UPLEFT || player._sequenceNumber == WALK_DOWNRIGHT || player._sequenceNumber == STOP_DOWNRIGHT; - surface.transBlitFrom(player._imageFrame->_frame, - Common::Point(player._position.x / 100, - player._position.y / 100 - player.frameHeight()), flipped); + surface.transBlitFrom(*player._imageFrame, Common::Point(player._position.x / 100, + player._position.y / 100 - player.frameHeight()), flipped); } // Draw all static and active shapes that are NORMAL and are in front of the player for (uint idx = 0; idx < _bgShapes.size(); ++idx) { if ((_bgShapes[idx]._type == ACTIVE_BG_SHAPE || _bgShapes[idx]._type == STATIC_BG_SHAPE) && _bgShapes[idx]._misc == NORMAL_FORWARD) - surface.transBlitFrom(_bgShapes[idx]._imageFrame->_frame, - _bgShapes[idx]._position, _bgShapes[idx]._flags & 2); + surface.transBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position, _bgShapes[idx]._flags & 2); } // Draw all static and active canimations that are NORMAL and are in front of the player for (uint idx = 0; idx < _canimShapes.size(); ++idx) { if ((_canimShapes[idx]._type == ACTIVE_BG_SHAPE || _canimShapes[idx]._type == STATIC_BG_SHAPE) && _canimShapes[idx]._misc == NORMAL_FORWARD) - surface.transBlitFrom(_canimShapes[idx]._imageFrame->_frame, - _canimShapes[idx]._position, _canimShapes[idx]._flags & 2); + surface.transBlitFrom(*_canimShapes[idx]._imageFrame, _canimShapes[idx]._position, + _canimShapes[idx]._flags & 2); } // Draw all static and active shapes that are FORWARD @@ -770,16 +766,15 @@ void Scene::updateBackground() { if ((_bgShapes[idx]._type == ACTIVE_BG_SHAPE || _bgShapes[idx]._type == STATIC_BG_SHAPE) && _bgShapes[idx]._misc == FORWARD) - surface.transBlitFrom(_bgShapes[idx]._imageFrame->_frame, - _bgShapes[idx]._position, _bgShapes[idx]._flags & 2); + surface.transBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position, _bgShapes[idx]._flags & 2); } // Draw all static and active canimations that are forward for (uint idx = 0; idx < _canimShapes.size(); ++idx) { if ((_canimShapes[idx]._type == ACTIVE_BG_SHAPE || _canimShapes[idx]._type == STATIC_BG_SHAPE) && _canimShapes[idx]._misc == FORWARD) - surface.transBlitFrom(_canimShapes[idx]._imageFrame->_frame, - _canimShapes[idx]._position, _canimShapes[idx]._flags & 2); + surface.transBlitFrom(*_canimShapes[idx]._imageFrame, _canimShapes[idx]._position, + _canimShapes[idx]._flags & 2); } } @@ -1196,14 +1191,14 @@ void Scene::doBgAnim() { for (uint idx = 0; idx < _bgShapes.size(); ++idx) { Object &o = _bgShapes[idx]; if (o._type == ACTIVE_BG_SHAPE && o._misc == BEHIND) - screen._backBuffer1.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2); + screen._backBuffer1.transBlitFrom(*o._imageFrame, o._position, o._flags & 2); } // Draw all canimations which are behind the person for (uint idx = 0; idx < _canimShapes.size(); ++idx) { Object &o = _canimShapes[idx]; if (o._type == ACTIVE_BG_SHAPE && o._misc == BEHIND) { - screen._backBuffer1.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2); + screen._backBuffer1.transBlitFrom(*o._imageFrame, o._position, o._flags & 2); } } @@ -1211,14 +1206,14 @@ void Scene::doBgAnim() { for (uint idx = 0; idx < _bgShapes.size(); ++idx) { Object &o = _bgShapes[idx]; if (o._type == ACTIVE_BG_SHAPE && o._misc == NORMAL_BEHIND) - screen._backBuffer1.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2); + screen._backBuffer1.transBlitFrom(*o._imageFrame, o._position, o._flags & 2); } // Draw all canimations which are NORMAL and behind the person for (uint idx = 0; idx < _canimShapes.size(); ++idx) { Object &o = _canimShapes[idx]; if (o._type == ACTIVE_BG_SHAPE && o._misc == NORMAL_BEHIND) { - screen._backBuffer1.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2); + screen._backBuffer1.transBlitFrom(*o._imageFrame, o._position, o._flags & 2); } } @@ -1231,7 +1226,7 @@ void Scene::doBgAnim() { bool flipped = people[AL]._sequenceNumber == WALK_LEFT || people[AL]._sequenceNumber == STOP_LEFT || people[AL]._sequenceNumber == WALK_UPLEFT || people[AL]._sequenceNumber == STOP_UPLEFT || people[AL]._sequenceNumber == WALK_DOWNRIGHT || people[AL]._sequenceNumber == STOP_DOWNRIGHT; - screen._backBuffer1.transBlitFrom(people[AL]._imageFrame->_frame, + screen._backBuffer1.transBlitFrom(*people[AL]._imageFrame, Common::Point(tempX, people[AL]._position.y / 100 - people[AL]._imageFrame->_frame.h), flipped); } @@ -1239,14 +1234,14 @@ void Scene::doBgAnim() { for (uint idx = 0; idx < _bgShapes.size(); ++idx) { Object &o = _bgShapes[idx]; if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == NORMAL_FORWARD) - screen._backBuffer1.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2); + screen._backBuffer1.transBlitFrom(*o._imageFrame, o._position, o._flags & 2); } // Draw all static and active canimations that are NORMAL and are in front of the person for (uint idx = 0; idx < _canimShapes.size(); ++idx) { Object &o = _canimShapes[idx]; if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == NORMAL_BEHIND) { - screen._backBuffer1.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2); + screen._backBuffer1.transBlitFrom(*o._imageFrame, o._position, o._flags & 2); } } @@ -1254,19 +1249,19 @@ void Scene::doBgAnim() { for (uint idx = 0; idx < _bgShapes.size(); ++idx) { Object &o = _bgShapes[idx]; if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == FORWARD) - screen._backBuffer1.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2); + screen._backBuffer1.transBlitFrom(*o._imageFrame, o._position, o._flags & 2); } // Draw any active portrait if (people._portraitLoaded && people._portrait._type == ACTIVE_BG_SHAPE) - screen._backBuffer1.transBlitFrom(people._portrait._imageFrame->_frame, + screen._backBuffer1.transBlitFrom(*people._portrait._imageFrame, people._portrait._position, people._portrait._flags & 2); // Draw all static and active canimations that are in front of the person for (uint idx = 0; idx < _canimShapes.size(); ++idx) { Object &o = _canimShapes[idx]; if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == FORWARD) { - screen._backBuffer1.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2); + screen._backBuffer1.transBlitFrom(*o._imageFrame, o._position, o._flags & 2); } } @@ -1274,7 +1269,7 @@ void Scene::doBgAnim() { for (uint idx = 0; idx < _bgShapes.size(); ++idx) { Object &o = _bgShapes[idx]; if (o._type == NO_SHAPE && (o._flags & 1) == 0) - screen._backBuffer1.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2); + screen._backBuffer1.transBlitFrom(*o._imageFrame, o._position, o._flags & 2); } // Bring the newly built picture to the screen -- cgit v1.2.3 From 817217c225475e5908bd3e7f3cfe1076df10ac8d Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Fri, 24 Apr 2015 18:25:58 +0200 Subject: SCI: qfg1vga script patch 4 stag dagger bug #6135 fixes animation issue when throwing a dagger at white stag in room 77 --- engines/sci/engine/script_patches.cpp | 82 ++++++++++++++++++++++++++++++++--- 1 file changed, 77 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp index e88aa98f42..03bf4387b7 100644 --- a/engines/sci/engine/script_patches.cpp +++ b/engines/sci/engine/script_patches.cpp @@ -94,6 +94,7 @@ static const char *const selectorNameTable[] = { "deskSarg", // Gabriel Knight "localize", // Freddy Pharkas "put", // Police Quest 1 VGA + "say", // Quest For Glory 1 VGA "solvePuzzle", // Quest For Glory 3 "timesShownID", // Space Quest 1 VGA "startText", // King's Quest 6 CD / Laura Bow 2 CD for audio+text support @@ -119,6 +120,7 @@ enum ScriptPatcherSelectors { SELECTOR_deskSarg, SELECTOR_localize, SELECTOR_put, + SELECTOR_say, SELECTOR_solvePuzzle, SELECTOR_timesShownID, SELECTOR_startText, @@ -2116,7 +2118,7 @@ static const uint16 qfg1vgaSignatureCheetaurDescription[] = { 0x34, SIG_UINT16(0x01b8), // ldi 01b8 0x1a, // eq? 0x31, 0x16, // bnt 16 - 0x38, SIG_UINT16(0x0127), // pushi 0127 + 0x38, SIG_SELECTOR16(say), // pushi 0127h (selector "say") 0x39, 0x06, // pushi 06 0x39, 0x03, // pushi 03 0x78, // push1 @@ -2199,17 +2201,87 @@ static const uint16 qfg1vgaPatchHealerHutNoDelay[] = { PATCH_END }; +// When following the white stag, you can actually enter the 2nd room from the mushroom/fairy location, +// which results in ego entering from the top. When you then throw a dagger at the stag, one animation +// frame will stay on screen, because of a script bug. +// +// Applies to at least: English floppy, Mac floppy +// Responsible method: stagHurt::changeState +// Fixes bug #6135 +static const uint16 qfg1vgaSignatureWhiteStagDagger[] = { + 0x87, 0x01, // lap param[1] + 0x65, 0x14, // aTop state + 0x36, // push + 0x3c, // dup + 0x35, 0x00, // ldi 0 + 0x1a, // eq? + 0x31, 0x16, // bnt [next parameter check] + 0x76, // push0 + 0x45, 0x02, 0x00, // callb export 2 from script 0, 0 + SIG_MAGICDWORD, + 0x38, SIG_SELECTOR16(say), // pushi 0127h (selector "say") + 0x39, 0x05, // pushi 05 + 0x39, 0x03, // pushi 03 + 0x39, 0x51, // pushi 51h + 0x76, // push0 + 0x76, // push0 + 0x7c, // pushSelf + 0x81, 0x5b, // lag global[5Bh] -> qg1Messager + 0x4a, 0x0e, // send 0Eh -> qg1Messager::say(3, 51h, 0, 0, stagHurt) + 0x33, 0x12, // jmp -> [ret] + 0x3c, // dup + 0x35, 0x01, // ldi 1 + 0x1a, // eq? + 0x31, 0x0c, // bnt [ret] + 0x38, // pushi... + SIG_ADDTOOFFSET(+11), + 0x3a, // toss + 0x48, // ret + SIG_END +}; + +static const uint16 qfg1vgaPatchWhiteStagDagger[] = { + PATCH_ADDTOOFFSET(+4), + 0x2f, 0x05, // bt [next check] (state != 0) + // state = 0 code + 0x35, 0x01, // ldi 1 + 0x65, 0x1a, // aTop cycles + 0x48, // ret + 0x36, // push + 0x35, 0x01, // ldi 1 + 0x1a, // eq? + 0x31, 0x16, // bnt [state = 2 code] + // state = 1 code + 0x76, // push0 + 0x45, 0x02, 0x00, // callb export 2 from script 0, 0 + 0x38, PATCH_SELECTOR16(say), // pushi 0127h (selector "say") + 0x39, 0x05, // pushi 05 + 0x39, 0x03, // pushi 03 + 0x39, 0x51, // pushi 51h + 0x76, // push0 + 0x76, // push0 + 0x7c, // pushSelf + 0x81, 0x5b, // lag global[5Bh] -> qg1Messager + 0x4a, 0x0e, // send 0Eh -> qg1Messager::say(3, 51h, 0, 0, stagHurt) + 0x48, // ret + // state = 2 code + PATCH_ADDTOOFFSET(+13), + 0x48, // ret (remove toss) + PATCH_END +}; + // script, description, signature patch static const SciScriptPatcherEntry qfg1vgaSignatures[] = { + { true, 41, "moving to castle gate", 1, qfg1vgaSignatureMoveToCastleGate, qfg1vgaPatchMoveToCastleGate }, { true, 55, "healer's hut, no delay for buy/steal", 1, qfg1vgaSignatureHealerHutNoDelay, qfg1vgaPatchHealerHutNoDelay }, + { true, 77, "white stag dagger throw animation glitch", 1, qfg1vgaSignatureWhiteStagDagger, qfg1vgaPatchWhiteStagDagger }, + { true, 96, "funny room script bug fixed", 1, qfg1vgaSignatureFunnyRoomFix, qfg1vgaPatchFunnyRoomFix }, + { true, 210, "cheetaur description fixed", 1, qfg1vgaSignatureCheetaurDescription, qfg1vgaPatchCheetaurDescription }, { true, 215, "fight event issue", 1, qfg1vgaSignatureFightEvents, qfg1vgaPatchFightEvents }, { true, 216, "weapon master event issue", 1, qfg1vgaSignatureFightEvents, qfg1vgaPatchFightEvents }, + { true, 331, "moving to crusher", 1, qfg1vgaSignatureMoveToCrusher, qfg1vgaPatchMoveToCrusher }, { true, 814, "window text temp space", 1, qfg1vgaSignatureTempSpace, qfg1vgaPatchTempSpace }, { true, 814, "dialog header offset", 3, qfg1vgaSignatureDialogHeader, qfg1vgaPatchDialogHeader }, - { true, 331, "moving to crusher", 1, qfg1vgaSignatureMoveToCrusher, qfg1vgaPatchMoveToCrusher }, - { true, 41, "moving to castle gate", 1, qfg1vgaSignatureMoveToCastleGate, qfg1vgaPatchMoveToCastleGate }, - { true, 210, "cheetaur description fixed", 1, qfg1vgaSignatureCheetaurDescription, qfg1vgaPatchCheetaurDescription }, - { true, 96, "funny room script bug fixed", 1, qfg1vgaSignatureFunnyRoomFix, qfg1vgaPatchFunnyRoomFix }, SCI_SIGNATUREENTRY_TERMINATOR }; -- cgit v1.2.3 From 5e1588e5cc9030c611609df23941609c68df4b65 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 24 Apr 2015 17:25:37 -0500 Subject: SHERLOCK: Fix display of look description dialogs --- engines/sherlock/talk.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index 3eeb0f0af5..0ac1bbd6aa 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -678,7 +678,7 @@ void Talk::drawInterface() { } else { int strWidth = screen.stringWidth(PRESS_KEY_TO_CONTINUE); screen.makeButton(Common::Rect(46, CONTROLS_Y, 273, CONTROLS_Y + 10), - 160 - strWidth, PRESS_KEY_TO_CONTINUE); + 160 - strWidth / 2, PRESS_KEY_TO_CONTINUE); screen.gPrint(Common::Point(160 - strWidth / 2, CONTROLS_Y), COMMAND_FOREGROUND, "P"); } } @@ -913,12 +913,14 @@ void Talk::pushSequence(int speaker) { } else { seqEntry._objNum = people.findSpeaker(speaker); - Object &obj = scene._bgShapes[seqEntry._objNum]; - for (uint idx = 0; idx < MAX_TALK_SEQUENCES; ++idx) - seqEntry._sequences.push_back(obj._sequences[idx]); + if (seqEntry._objNum != -1) { + Object &obj = scene._bgShapes[seqEntry._objNum]; + for (uint idx = 0; idx < MAX_TALK_SEQUENCES; ++idx) + seqEntry._sequences.push_back(obj._sequences[idx]); - seqEntry._frameNumber = obj._frameNumber; - seqEntry._seqTo = obj._seqTo; + seqEntry._frameNumber = obj._frameNumber; + seqEntry._seqTo = obj._seqTo; + } } _sequenceStack.push(seqEntry); @@ -1549,13 +1551,14 @@ void Talk::doScript(const Common::String &script) { screen.print(Common::Point(16, yp), INV_FOREGROUND, lineStr.c_str()); } else { screen.gPrint(Common::Point(16, yp - 1), INV_FOREGROUND, lineStr.c_str()); + openTalkWindow = true; } } else { if (ui._windowOpen) { screen.print(Common::Point(16, yp), COMMAND_FOREGROUND, lineStr.c_str()); - } - else { + } else { screen.gPrint(Common::Point(16, yp - 1), COMMAND_FOREGROUND, lineStr.c_str()); + openTalkWindow = true; } } -- cgit v1.2.3 From 6eb51c3d50e5134c4054f9652624fe61d772b004 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 24 Apr 2015 17:27:23 -0500 Subject: SHERLOCK: Formatting fixes --- engines/sherlock/objects.cpp | 4 ++-- engines/sherlock/talk.cpp | 6 ++---- engines/sherlock/user_interface.cpp | 3 +-- 3 files changed, 5 insertions(+), 8 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index 9e92b95532..78b6cda2d3 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -309,10 +309,10 @@ void Sprite::checkSprite() { if (_delta.x > 0) // Go to right side walkPos.x = objBounds.right + CLEAR_DIST_X; - else if (_delta.x < 0) + else if (_delta.x < 0) { // Go to left side walkPos.x = objBounds.left - CLEAR_DIST_X; - else { + } else { // Going straight up or down. So choose best side if (spritePt.x >= (objBounds.left + objBounds.width() / 2)) walkPos.x = objBounds.right + CLEAR_DIST_X; diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index 0ac1bbd6aa..9be2b035d4 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -1041,8 +1041,7 @@ void Talk::doScript(const Common::String &script) { pullSequence(); pushSequence(_speaker); setSequence(_speaker); - } - else { + } else { setSequence(_speaker); } @@ -1071,8 +1070,7 @@ void Talk::doScript(const Common::String &script) { // Remove portrait? if (str[0] == REMOVE_PORTRAIT) { _speaker = 255; - } - else { + } else { // Nope, so set the first speaker people.setTalking(_speaker); } diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index 903b1e6002..a2a356127c 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -1468,8 +1468,7 @@ void UserInterface::doLookControl() { _menuMode = STD_MODE; events.clearEvents(); } - } - else { + } else { // Looking at an inventory object // Backup the user interface Surface tempSurface(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT - CONTROLS_Y1); -- cgit v1.2.3 From 930600c85740012db40a11eb06b02b0c78356529 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 24 Apr 2015 17:47:58 -0500 Subject: SHERLOCK: Implement saving scene status when saving game or leaving scene --- engines/sherlock/scene.cpp | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index e5d9fc611f..3ecc7be422 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -451,7 +451,7 @@ bool Scene::loadScene(const Common::String &filename) { * opening or moving them */ void Scene::checkSceneStatus() { - if (_sceneStats[_currentScene][65]) { + if (_sceneStats[_currentScene][64]) { for (uint idx = 0; idx < 64; ++idx) { int val = _sceneStats[_currentScene][idx]; @@ -475,6 +475,23 @@ void Scene::checkSceneStatus() { } } +/** + * Restores objects to the correct status. This ensures that things like being opened or moved + * will remain the same on future visits to the scene + */ +void Scene::saveSceneStatus() { + // Flag any objects for the scene that have been altered + int count = MIN((int)_bgShapes.size(), 64); + for (int idx = 0; idx < count; ++idx) { + Object &obj = _bgShapes[idx]; + _sceneStats[_currentScene][idx] = obj._type == HIDDEN || obj._type == REMOVE + || obj._type == HIDE_SHAPE || obj._type == INVALID; + } + + // Flag scene as having been visited + _sceneStats[_currentScene][64] = true; +} + /** * Check the scene's objects against the game flags. If false is passed, * it means the scene has just been loaded. A value of true means that the scene @@ -1364,10 +1381,6 @@ void Scene::doBgAnim() { } } -void Scene::saveSceneStatus() { - // TODO -} - /** * Attempts to find a background shape within the passed bounds. If found, * it will return the shape number, or -1 on failure. @@ -1453,6 +1466,9 @@ int Scene::closestZone(const Common::Point &pt) { * Synchronize the data for a savegame */ void Scene::synchronize(Common::Serializer &s) { + if (s.isSaving()) + saveSceneStatus(); + s.syncAsSint16LE(_bigPos.x); s.syncAsSint16LE(_bigPos.y); s.syncAsSint16LE(_overPos.x); -- cgit v1.2.3 From 3cf1afb459e29747461e21ba7db971a9c72fc9ff Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 24 Apr 2015 20:26:33 -0500 Subject: SHERLOCK: Fix minor gfx glitch when sliding up closing dialogs --- engines/sherlock/user_interface.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index a2a356127c..12af04d608 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -1304,7 +1304,7 @@ void UserInterface::doInvControl() { } if (events._released || _keyboardInput) { - if ((!found && events._released) && _key == 'E') { + if ((found == 0 && events._released) || _key == 'E') { inv.freeInv(); _infoFlag = true; clearInfo(); @@ -2454,6 +2454,11 @@ void UserInterface::banishWindow(bool slideUp) { SHERLOCK_SCREEN_HEIGHT); events.delay(10); } + + // Show entire final area + screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(0, CONTROLS_Y1), + Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); + screen.slamRect(Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); } _infoFlag = false; -- cgit v1.2.3 From 55404f01d60fb4bb454ceb8e9289debbadda8470 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 24 Apr 2015 20:59:30 -0500 Subject: SHERLOCK: Fix talk dialog buttons --- engines/sherlock/talk.cpp | 8 ++++---- engines/sherlock/user_interface.cpp | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index 9be2b035d4..2ad70dabed 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -698,13 +698,13 @@ bool Talk::displayTalk(bool slamIt) { } if (_talkIndex) { - for (uint idx = 0; idx < _statements.size(); ++idx) { + for (int idx = 0; idx < _talkIndex && !_moreTalkUp; ++idx) { if (_statements[idx]._talkMap != -1) _moreTalkUp = true; } } - // Display the up arrow if the first option is scrolled off-screen + // Display the up arrow and enable Up button if the first option is scrolled off-screen if (_moreTalkUp) { if (slamIt) { screen.print(Common::Point(5, CONTROLS_Y + 13), INV_FOREGROUND, "~"); @@ -747,7 +747,7 @@ bool Talk::displayTalk(bool slamIt) { } } - // Display the down arrow if there are more statements available + // Display the down arrow and enable down button if there are more statements available down off-screen if (lineY == -1 || lineY == SHERLOCK_SCREEN_HEIGHT) { _moreTalkDown = true; @@ -763,7 +763,7 @@ bool Talk::displayTalk(bool slamIt) { screen.buttonPrint(Common::Point(200, CONTROLS_Y), COMMAND_NULL, true, "Down"); screen.vgaBar(Common::Rect(5, 189, 16, 199), INV_BACKGROUND); } else { - screen.buttonPrint(Common::Point(200, CONTROLS_Y), COMMAND_FOREGROUND, false, "Down"); + screen.buttonPrint(Common::Point(200, CONTROLS_Y), COMMAND_NULL, false, "Down"); screen._backBuffer1.fillRect(Common::Rect(5, 189, 16, 199), INV_BACKGROUND); } } diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index 12af04d608..176b1bc42b 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -1791,14 +1791,14 @@ void UserInterface::doTalkControl() { } if (events._released || _keyboardInput) { - if (_endKeyActive && ((mousePos.x > 99 && mousePos.y > CONTROLS_Y && mousePos.y < (CONTROLS_Y + 10) - && talk._moreTalkUp && events._released) || _key == 'E')) { + if (((Common::Rect(99, CONTROLS_Y, 138, CONTROLS_Y + 10).contains(mousePos) && events._released) + || _key == 'E') && _endKeyActive) { talk.freeTalkVars(); talk.pullSequence(); banishWindow(); _windowBounds.top = CONTROLS_Y1; - } else if ((mousePos.x > 140 && mousePos.x < 179 && mousePos.y > CONTROLS_Y && mousePos.y < (CONTROLS_Y + 10) - && talk._moreTalkUp && events._released) || (talk._moreTalkUp && _key == 'U')) { + } else if (((Common::Rect(140, CONTROLS_Y, 179, CONTROLS_Y + 10).contains(mousePos) && events._released) + || _key == 'U') && talk._moreTalkUp) { while (talk._statements[--talk._talkIndex]._talkMap == -1) ; screen._backBuffer1.fillRect(Common::Rect(5, CONTROLS_Y + 11, SHERLOCK_SCREEN_WIDTH - 2, @@ -1806,8 +1806,8 @@ void UserInterface::doTalkControl() { talk.displayTalk(false); screen.slamRect(Common::Rect(5, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH - 5, SHERLOCK_SCREEN_HEIGHT - 2)); - } else if ((mousePos.x > 181 && mousePos.x < 220 && mousePos.y > CONTROLS_Y && mousePos.y < (CONTROLS_Y + 10) - && talk._moreTalkDown && events._released) || (talk._moreTalkDown && _key == 'D')) { + } else if (((Common::Rect(181, CONTROLS_Y, 220, CONTROLS_Y + 10).contains(mousePos) && events._released) + || _key == 'D') && talk._moreTalkDown) { do { ++talk._talkIndex; } while (talk._talkIndex < (int)talk._statements.size() && talk._statements[talk._talkIndex]._talkMap == -1); -- cgit v1.2.3 From 8fa2d48f1f00b4be5e04c305db2a5340e4480d89 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 24 Apr 2015 21:12:05 -0500 Subject: SHERLOCK: Fix crash when entering backstage area --- engines/sherlock/journal.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sherlock/journal.cpp b/engines/sherlock/journal.cpp index 18edec8c73..bb1fc9a883 100644 --- a/engines/sherlock/journal.cpp +++ b/engines/sherlock/journal.cpp @@ -286,7 +286,7 @@ int Journal::loadJournalFile(bool alreadyLoaded) { else if (talk._talkTo == 2) journalString += "The Inspector"; else - journalString += inv._names[talk._talkTo]; + journalString += NAMES[talk._talkTo]; const char *strP = replyP; char v; -- cgit v1.2.3 From c92b3b5c71666797eb6d26008ebbfd88d69573c3 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 24 Apr 2015 22:12:15 -0500 Subject: SHERLOCK: Fix paging in the journal --- engines/sherlock/journal.cpp | 66 +++++++++++++++++++++++--------------------- engines/sherlock/journal.h | 4 +-- 2 files changed, 37 insertions(+), 33 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/journal.cpp b/engines/sherlock/journal.cpp index bb1fc9a883..e3d4e1b7a3 100644 --- a/engines/sherlock/journal.cpp +++ b/engines/sherlock/journal.cpp @@ -136,7 +136,6 @@ void Journal::loadJournalLocations() { */ int Journal::loadJournalFile(bool alreadyLoaded) { Inventory &inv = *_vm->_inventory; - People &people = *_vm->_people; Screen &screen = *_vm->_screen; Talk &talk = *_vm->_talk; JournalEntry &journalEntry = _journal[_index]; @@ -156,7 +155,7 @@ int Journal::loadJournalFile(bool alreadyLoaded) { // Find the person being talked to talk._talkTo = -1; for (int idx = 0; idx < MAX_PEOPLE; ++idx) { - Common::String portrait = people[idx]._portrait; + Common::String portrait = PORTRAITS[idx]; Common::String numStr(portrait.c_str(), portrait.c_str() + 4); if (locStr == numStr) { @@ -243,7 +242,7 @@ int Journal::loadJournalFile(bool alreadyLoaded) { const char *replyP = statement._reply.c_str(); while (*replyP) { - char c = *replyP++; + byte c = *replyP++; // Is it a control character? if (c < 128) { @@ -288,7 +287,7 @@ int Journal::loadJournalFile(bool alreadyLoaded) { else journalString += NAMES[talk._talkTo]; - const char *strP = replyP; + const char *strP = replyP + 1; char v; do { v = *strP++; @@ -354,6 +353,7 @@ int Journal::loadJournalFile(bool alreadyLoaded) { case 136: // Pause without control case 157: // Walk to canimation // These commands don't have any param + ++replyP; break; case 134: // Change sequence @@ -450,7 +450,10 @@ int Journal::loadJournalFile(bool alreadyLoaded) { return _lines.size(); } -void Journal::drawInterface() { +/** + * Draw the journal frame + */ +void Journal::drawJournal() { Resources &res = *_vm->_res; Screen &screen = *_vm->_screen; byte palette[PALETTE_SIZE]; @@ -471,33 +474,42 @@ void Journal::drawInterface() { screen.gPrint(Common::Point(110, 17), INV_FOREGROUND, "Watson's Journal"); // Draw the buttons - screen.makeButton(Common::Rect(JOURNAL_POINTS[0][0], JOURNAL_BUTTONS_Y, - JOURNAL_POINTS[0][1], JOURNAL_BUTTONS_Y + 10), + screen.makeButton(Common::Rect(JOURNAL_POINTS[0][0], JOURNAL_BUTTONS_Y, + JOURNAL_POINTS[0][1], JOURNAL_BUTTONS_Y + 10), JOURNAL_POINTS[0][2] - screen.stringWidth("Exit") / 2, "Exit"); - screen.makeButton(Common::Rect(JOURNAL_POINTS[1][0], JOURNAL_BUTTONS_Y, - JOURNAL_POINTS[1][1], JOURNAL_BUTTONS_Y + 10), + screen.makeButton(Common::Rect(JOURNAL_POINTS[1][0], JOURNAL_BUTTONS_Y, + JOURNAL_POINTS[1][1], JOURNAL_BUTTONS_Y + 10), JOURNAL_POINTS[1][2] - screen.stringWidth("Back 10") / 2, "Back 10"); - screen.makeButton(Common::Rect(JOURNAL_POINTS[2][0], JOURNAL_BUTTONS_Y, - JOURNAL_POINTS[2][1], JOURNAL_BUTTONS_Y + 10), + screen.makeButton(Common::Rect(JOURNAL_POINTS[2][0], JOURNAL_BUTTONS_Y, + JOURNAL_POINTS[2][1], JOURNAL_BUTTONS_Y + 10), JOURNAL_POINTS[2][2] - screen.stringWidth("Up") / 2, "Up"); - screen.makeButton(Common::Rect(JOURNAL_POINTS[3][0], JOURNAL_BUTTONS_Y, - JOURNAL_POINTS[3][1], JOURNAL_BUTTONS_Y + 10), + screen.makeButton(Common::Rect(JOURNAL_POINTS[3][0], JOURNAL_BUTTONS_Y, + JOURNAL_POINTS[3][1], JOURNAL_BUTTONS_Y + 10), JOURNAL_POINTS[3][2] - screen.stringWidth("Down") / 2, "Down"); - screen.makeButton(Common::Rect(JOURNAL_POINTS[4][0], JOURNAL_BUTTONS_Y, + screen.makeButton(Common::Rect(JOURNAL_POINTS[4][0], JOURNAL_BUTTONS_Y, JOURNAL_POINTS[4][1], JOURNAL_BUTTONS_Y + 10), JOURNAL_POINTS[4][2] - screen.stringWidth("Ahead 10") / 2, "Ahead 10"); - screen.makeButton(Common::Rect(JOURNAL_POINTS[5][0], JOURNAL_BUTTONS_Y + 11, + screen.makeButton(Common::Rect(JOURNAL_POINTS[5][0], JOURNAL_BUTTONS_Y + 11, JOURNAL_POINTS[5][1], JOURNAL_BUTTONS_Y + 21), JOURNAL_POINTS[5][2] - screen.stringWidth("Search") / 2, "Search"); - screen.makeButton(Common::Rect(JOURNAL_POINTS[6][0], JOURNAL_BUTTONS_Y + 11, + screen.makeButton(Common::Rect(JOURNAL_POINTS[6][0], JOURNAL_BUTTONS_Y + 11, JOURNAL_POINTS[6][1], JOURNAL_BUTTONS_Y + 21), JOURNAL_POINTS[6][2] - screen.stringWidth("First Page") / 2, "First Page"); - screen.makeButton(Common::Rect(JOURNAL_POINTS[7][0], JOURNAL_BUTTONS_Y + 11, + screen.makeButton(Common::Rect(JOURNAL_POINTS[7][0], JOURNAL_BUTTONS_Y + 11, JOURNAL_POINTS[7][1], JOURNAL_BUTTONS_Y + 21), JOURNAL_POINTS[7][2] - screen.stringWidth("Last Page") / 2, "Last Page"); - screen.makeButton(Common::Rect(JOURNAL_POINTS[8][0], JOURNAL_BUTTONS_Y + 11, + screen.makeButton(Common::Rect(JOURNAL_POINTS[8][0], JOURNAL_BUTTONS_Y + 11, JOURNAL_POINTS[8][1], JOURNAL_BUTTONS_Y + 21), JOURNAL_POINTS[8][2] - screen.stringWidth("Print Text") / 2, "Print Text"); +} + +/** + * Display the journal + */ +void Journal::drawInterface() { + Screen &screen = *_vm->_screen; + + drawJournal(); if (_journal.size() == 0) { _up = _down = 0; @@ -578,7 +590,7 @@ bool Journal::doJournal(int direction, int howFar) { if (endJournal) { // If moving forward or backwards, clear the page before printing if (direction) - clearPage(); + drawJournal(); screen.gPrint(Common::Point(235, 21), PEN_COLOR, "Page %d", _page); return false; @@ -701,7 +713,7 @@ bool Journal::doJournal(int direction, int howFar) { if (direction) { events.setCursor(ARROW); - clearPage(); + drawJournal(); } screen.gPrint(Common::Point(235, 21), PEN_COLOR, "Page %d", _page); @@ -785,14 +797,6 @@ bool Journal::doJournal(int direction, int howFar) { return direction >= 3 && searchSuccessful; } -/** - * Clears the journal page - */ -void Journal::clearPage() { - // Clear the journal page by redrawing it from scratch - drawInterface(); -} - /** * Handle events whilst the journal is being displayed */ @@ -962,7 +966,7 @@ bool Journal::handleEvents(int key) { _sub = savedSub; _page = savedPage; - clearPage(); + drawJournal(); doJournal(0, 0); notFound = true; } else { @@ -984,7 +988,7 @@ bool Journal::handleEvents(int key) { _up = _down = false; _page = 1; - clearPage(); + drawJournal(); doJournal(0, 0); doArrows(); screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT); @@ -1168,7 +1172,7 @@ int Journal::getFindName(bool printError) { } // Redisplay the journal screen - clearPage(); + drawJournal(); doJournal(0, 0); screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT); diff --git a/engines/sherlock/journal.h b/engines/sherlock/journal.h index 9db4b28665..a67e0e51e2 100644 --- a/engines/sherlock/journal.h +++ b/engines/sherlock/journal.h @@ -67,9 +67,9 @@ private: bool doJournal(int direction, int howFar); - void clearPage(); - int getFindName(bool printError); + + void drawJournal(); public: Journal(SherlockEngine *vm); -- cgit v1.2.3 From baeca76b028ff846ce14bad4575984324fd4c999 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 25 Apr 2015 03:05:51 -0500 Subject: SHERLOCK: Fix crash displaying journal contents for Lestrade --- engines/sherlock/journal.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/journal.cpp b/engines/sherlock/journal.cpp index e3d4e1b7a3..1891419acf 100644 --- a/engines/sherlock/journal.cpp +++ b/engines/sherlock/journal.cpp @@ -248,6 +248,7 @@ int Journal::loadJournalFile(bool alreadyLoaded) { if (c < 128) { // Nope. Set flag for allowing control coes to insert spaces ctrlSpace = true; + assert(c >= ' '); // Check for embedded comments if (c == '{' || c == '}') { @@ -307,7 +308,7 @@ int Journal::loadJournalFile(bool alreadyLoaded) { journalString += c; do { journalString += *replyP++; - } while (*replyP && *replyP < 128 && *replyP != '{' && *replyP != '}'); + } while (*replyP && (byte)*replyP < 128 && *replyP != '{' && *replyP != '}'); commentJustPrinted = false; } @@ -323,16 +324,16 @@ int Journal::loadJournalFile(bool alreadyLoaded) { } startOfReply = false; - c = *replyP++; + c = *replyP++ - 1; - if ((c - 1) == 0) + if (c == 0) journalString += "Holmes"; - else if ((c - 1) == 1) + else if (c == 1) journalString += "I"; - else if ((c - 1) == 2) + else if (c == 2) journalString += "the Inspector"; else - journalString += inv._names[c - 1]; + journalString += NAMES[c]; const char *strP = replyP; char v; @@ -352,7 +353,7 @@ int Journal::loadJournalFile(bool alreadyLoaded) { case 131: // Pause with control case 136: // Pause without control case 157: // Walk to canimation - // These commands don't have any param + // These commands have a single parameter ++replyP; break; @@ -821,7 +822,7 @@ bool Journal::handleEvents(int key) { } else { color = COMMAND_FOREGROUND; } - screen.buttonPrint(Common::Point(JOURNAL_POINTS[1][2], JOURNAL_BUTTONS_Y), color, true, "Exit"); + screen.buttonPrint(Common::Point(JOURNAL_POINTS[0][2], JOURNAL_BUTTONS_Y), color, true, "Exit"); // Back 10 button if (pt.x > JOURNAL_POINTS[1][0] && pt.x < JOURNAL_POINTS[1][1] && pt.y >= JOURNAL_BUTTONS_Y && -- cgit v1.2.3 From c6286ec4bd88a4c8a5dc0b5934f8c3241ab2d237 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 25 Apr 2015 03:14:35 -0500 Subject: SHERLOCK: Journal paging fix --- engines/sherlock/journal.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sherlock/journal.cpp b/engines/sherlock/journal.cpp index 1891419acf..91148a2694 100644 --- a/engines/sherlock/journal.cpp +++ b/engines/sherlock/journal.cpp @@ -679,7 +679,7 @@ bool Journal::doJournal(int direction, int howFar) { if (++_sub == maxLines) { // Reached end of page do { - if (++_index == (int)_lines.size()) { + if (++_index == _count) { _index = savedIndex; _sub = savedSub; maxLines = loadJournalFile(false); -- cgit v1.2.3 From eb91c01cf160984f52edf5ba1da3f5db1e2a6519 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 25 Apr 2015 03:19:08 -0500 Subject: SHERLOCK: Fix paging to end of journal --- engines/sherlock/journal.cpp | 4 +--- engines/sherlock/journal.h | 1 - 2 files changed, 1 insertion(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/journal.cpp b/engines/sherlock/journal.cpp index 91148a2694..46114cd746 100644 --- a/engines/sherlock/journal.cpp +++ b/engines/sherlock/journal.cpp @@ -51,7 +51,6 @@ const int SEARCH_POINTS[3][3] = { Journal::Journal(SherlockEngine *vm): _vm(vm) { // Initialize fields - _count = 0; _maxPage = 0; _index = 0; _sub = 0; @@ -679,7 +678,7 @@ bool Journal::doJournal(int direction, int howFar) { if (++_sub == maxLines) { // Reached end of page do { - if (++_index == _count) { + if (++_index == (int)_journal.size()) { _index = savedIndex; _sub = savedSub; maxLines = loadJournalFile(false); @@ -1192,7 +1191,6 @@ void Journal::resetPosition() { * Synchronize the data for a savegame */ void Journal::synchronize(Common::Serializer &s) { - s.syncAsSint16LE(_count); s.syncAsSint16LE(_index); s.syncAsSint16LE(_sub); s.syncAsSint16LE(_page); diff --git a/engines/sherlock/journal.h b/engines/sherlock/journal.h index a67e0e51e2..2ef0f94492 100644 --- a/engines/sherlock/journal.h +++ b/engines/sherlock/journal.h @@ -50,7 +50,6 @@ private: Common::StringArray _directory; Common::StringArray _locations; Common::StringArray _lines; - int _count; int _maxPage; int _index; int _sub; -- cgit v1.2.3 From 2379824e32fd0cb49e3f2b6c997cb6070f0b0393 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 25 Apr 2015 04:42:15 -0500 Subject: SHERLOCK: Fix saving and display of inventory items --- engines/sherlock/inventory.cpp | 19 +++++++++++++++++-- engines/sherlock/inventory.h | 4 +++- engines/sherlock/journal.cpp | 3 +-- engines/sherlock/saveload.cpp | 2 ++ 4 files changed, 23 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/inventory.cpp b/engines/sherlock/inventory.cpp index 3ba6f9d2bd..808429f643 100644 --- a/engines/sherlock/inventory.cpp +++ b/engines/sherlock/inventory.cpp @@ -31,6 +31,17 @@ InventoryItem::InventoryItem(int requiredFlag, const Common::String &name, _examine(examine), _lookFlag(0) { } +/** + * Synchronize the data for an inventory item + */ +void InventoryItem::synchronize(Common::Serializer &s) { + s.syncAsSint16LE(_requiredFlag); + s.syncAsSint16LE(_lookFlag); + s.syncString(_name); + s.syncString(_description); + s.syncString(_examine); +} + /*----------------------------------------------------------------*/ Inventory::Inventory(SherlockEngine *vm) : Common::Array(), _vm(vm) { @@ -47,6 +58,9 @@ Inventory::~Inventory() { freeGraphics(); } +/** + * Free inventory data + */ void Inventory::freeInv() { freeGraphics(); @@ -117,7 +131,7 @@ void Inventory::loadGraphics() { * and returns the numer that matches the passed name */ int Inventory::findInv(const Common::String &name) { - for (int idx = 0; idx < (int)size(); ++idx) { + for (int idx = 0; idx < (int)_names.size(); ++idx) { if (scumm_stricmp(name.c_str(), _names[idx].c_str()) == 0) return idx; } @@ -502,7 +516,8 @@ void Inventory::synchronize(Common::Serializer &s) { } for (uint idx = 0; idx < size(); ++idx) { - // TODO + (*this)[idx].synchronize(s); + } } diff --git a/engines/sherlock/inventory.h b/engines/sherlock/inventory.h index bccdc9336e..0dafdddde9 100644 --- a/engines/sherlock/inventory.h +++ b/engines/sherlock/inventory.h @@ -57,16 +57,18 @@ struct InventoryItem { InventoryItem() : _requiredFlag(0), _lookFlag(0) {} InventoryItem(int requiredFlag, const Common::String &name, const Common::String &description, const Common::String &examine); + + void synchronize(Common::Serializer &s); }; class Inventory : public Common::Array { private: SherlockEngine *_vm; + Common::StringArray _names; void copyToInventory(Object &obj); public: ImageFile *_invShapes[MAX_VISIBLE_INVENTORY]; - Common::StringArray _names; bool _invGraphicsLoaded; InvMode _invMode; int _invIndex; diff --git a/engines/sherlock/journal.cpp b/engines/sherlock/journal.cpp index 46114cd746..ffda25a533 100644 --- a/engines/sherlock/journal.cpp +++ b/engines/sherlock/journal.cpp @@ -134,7 +134,6 @@ void Journal::loadJournalLocations() { * word wraps the result to prepare it for being displayed */ int Journal::loadJournalFile(bool alreadyLoaded) { - Inventory &inv = *_vm->_inventory; Screen &screen = *_vm->_screen; Talk &talk = *_vm->_talk; JournalEntry &journalEntry = _journal[_index]; @@ -224,7 +223,7 @@ int Journal::loadJournalFile(bool alreadyLoaded) { journalString += "the Inspector"; break; default: - journalString += inv._names[talk._talkTo]; + journalString += NAMES[talk._talkTo]; break; } journalString += ", \""; diff --git a/engines/sherlock/saveload.cpp b/engines/sherlock/saveload.cpp index 7610c42d8c..a694e21b28 100644 --- a/engines/sherlock/saveload.cpp +++ b/engines/sherlock/saveload.cpp @@ -366,6 +366,7 @@ Common::String SaveManager::generateSaveName(int slot) { * Synchronize the data for a savegame */ void SaveManager::synchronize(Common::Serializer &s) { + Inventory &inv = *_vm->_inventory; Journal &journal = *_vm->_journal; People &people = *_vm->_people; Scene &scene = *_vm->_scene; @@ -374,6 +375,7 @@ void SaveManager::synchronize(Common::Serializer &s) { int oldFont = screen.fontNumber(); + inv.synchronize(s); journal.synchronize(s); people.synchronize(s); scene.synchronize(s); -- cgit v1.2.3 From b8e12bbd88dba43cd397aca151eddb47d2ce761a Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 25 Apr 2015 05:11:07 -0500 Subject: SHERLOCK: Fix setting scene flags when leaving a scene --- engines/sherlock/scene.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 3ecc7be422..3f551ef5ba 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -129,6 +129,9 @@ void Scene::selectScene() { _oldKey = _help = _oldHelp = 0; _oldTemp = _temp = 0; + // Free any previous scene + freeScene(); + // Load the scene Common::String sceneFile = Common::String::format("res%02d", _goToScene); _rrmName = Common::String::format("res%02d.rrm", _goToScene); @@ -201,7 +204,6 @@ bool Scene::loadScene(const Common::String &filename) { UserInterface &ui = *_vm->_ui; bool flag; - freeScene(); _walkedInScene = false; _ongoingCans = 0; @@ -453,12 +455,12 @@ bool Scene::loadScene(const Common::String &filename) { void Scene::checkSceneStatus() { if (_sceneStats[_currentScene][64]) { for (uint idx = 0; idx < 64; ++idx) { - int val = _sceneStats[_currentScene][idx]; + bool flag = _sceneStats[_currentScene][idx]; if (idx < _bgShapes.size()) { Object &obj = _bgShapes[idx]; - if (val & 1) { + if (flag) { // No shape to erase, so flag as hidden obj._type = HIDDEN; } else if (obj._images == nullptr || obj._images->size() == 0) { -- cgit v1.2.3 From 35368ce8a81cba7a2921a4e14036fa21290f663c Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 25 Apr 2015 05:52:04 -0500 Subject: SHERLOCK: Fixes and cleanup for checkObject --- engines/sherlock/objects.cpp | 8 ++++---- engines/sherlock/objects.h | 2 +- engines/sherlock/scene.cpp | 10 +++++----- 3 files changed, 10 insertions(+), 10 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index 78b6cda2d3..6231c9abc7 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -544,7 +544,7 @@ void Object::toggleHidden() { /** * Check the state of the object */ -void Object::checkObject(Object &o) { +void Object::checkObject() { Scene &scene = *_vm->_scene; Sound &sound = *_vm->_sound; int checkFrame = _allow ? MAX_FRAME : 32000; @@ -559,9 +559,9 @@ void Object::checkObject(Object &o) { } else { // Continue doing sequence if (*ptr > _seqTo) - *ptr--; + *ptr -= 1; else - *ptr++; + *ptr += 1; return; } @@ -654,7 +654,7 @@ void Object::checkObject(Object &o) { _frameNumber += 2; } else if (v < 4) { for (int idx = 0; idx < 4; ++idx) { - o.checkNameForCodes(_use[v]._names[idx], nullptr); + checkNameForCodes(_use[v]._names[idx], nullptr); } if (_use[v]._useFlag) diff --git a/engines/sherlock/objects.h b/engines/sherlock/objects.h index 534ed66643..2b2472fbbf 100644 --- a/engines/sherlock/objects.h +++ b/engines/sherlock/objects.h @@ -206,7 +206,7 @@ public: void toggleHidden(); - void checkObject(Object &o); + void checkObject(); int checkNameForCodes(const Common::String &name, const char *const messages[]); diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 3f551ef5ba..16bb8daecf 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -964,7 +964,7 @@ int Scene::startCAnim(int cAnimNum, int playRate) { Object::_countCAnimFrames = true; while (cObj._type == ACTIVE_BG_SHAPE) { - cObj.checkObject(_bgShapes[0]); + cObj.checkObject(); ++frames; if (frames >= 1000) @@ -1035,7 +1035,7 @@ int Scene::startCAnim(int cAnimNum, int playRate) { gotoCode = cObj._sequences[cObj._frameNumber + 3]; // Set canim to REMOVE type and free memory - cObj.checkObject(_bgShapes[0]); + cObj.checkObject(); if (gotoCode > 0 && !talk._talkToAbort) { _goToScene = gotoCode; @@ -1119,15 +1119,15 @@ void Scene::doBgAnim() { for (uint idx = 0; idx < _bgShapes.size(); ++idx) { if (_bgShapes[idx]._type == ACTIVE_BG_SHAPE) - _bgShapes[idx].checkObject(_bgShapes[idx]); + _bgShapes[idx].checkObject(); } if (people._portraitLoaded && people._portrait._type == ACTIVE_BG_SHAPE) - people._portrait.checkObject(people._portrait); + people._portrait.checkObject(); for (uint idx = 0; idx < _canimShapes.size(); ++idx) { if (_canimShapes[idx]._type != INVALID && _canimShapes[idx]._type != REMOVE) - _canimShapes[idx].checkObject(_bgShapes[0]); + _canimShapes[idx].checkObject(); } if (_currentScene == 12 && _vm->getGameID() == GType_SerratedScalpel) -- cgit v1.2.3 From f4ce7851f849f37851831c3888337feb532425ca Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 25 Apr 2015 20:06:59 +0200 Subject: SCI: script patch for sq4cd, walk in bug #5468 walk right up in the first room, only for SQ4 CD --- engines/sci/engine/script_patches.cpp | 44 ++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp index 03bf4387b7..b4844e3e7e 100644 --- a/engines/sci/engine/script_patches.cpp +++ b/engines/sci/engine/script_patches.cpp @@ -2647,6 +2647,47 @@ static const uint16 sq4FloppyPatchThrowStuffAtSequelPoliceBug[] = { PATCH_END }; +// Right at the start of Space Quest 4 CD, when walking up in the first room, ego will +// immediately walk down just after entering the upper room. +// +// This is caused by the scripts setting ego's vertical coordinate to 189 (BDh), which is the +// trigger in rooms to walk to the room below it. Sometimes this isn't triggered, because +// the scripts also initiate a motion to vertical coordinate 188 (BCh). When you lower the game's speed, +// this bug normally always triggers. And it triggers of course also in the original interpreter. +// +// It doesn't happen in PC floppy, because nsRect is not the same as in CD. +// +// We fix it by setting ego's vertical coordinate to 188 and we also initiate a motion to 187. +// +// Applies to at least: English PC CD +// Responsible method: rm045::doit +// Fixes bug: #5468 +static const uint16 sq4CdSignatureWalkInFromBelowRoom45[] = { + 0x76, // push0 + SIG_MAGICDWORD, + 0x78, // push1 + 0x38, SIG_UINT16(0x00bd), // pushi 00BDh + 0x38, SIG_ADDTOOFFSET(+2), // pushi [setMotion selector] + 0x39, 0x03, // pushi 3 + 0x51, SIG_ADDTOOFFSET(+1), // class [MoveTo] + 0x36, // push + 0x78, // push1 + 0x76, // push0 + 0x81, 0x00, // lag global[0] + 0x4a, 0x04, // send 04 -> get ego::x + 0x36, // push + 0x38, SIG_UINT16(0x00bc), // pushi 00BCh + SIG_END +}; + +static const uint16 sq4CdPatchWalkInFromBelowRoom45[] = { + PATCH_ADDTOOFFSET(+2), + 0x38, PATCH_UINT16(0x00bc), // pushi 00BCh + PATCH_ADDTOOFFSET(+15), + 0x38, PATCH_UINT16(0x00bb), // pushi 00BBh + PATCH_END +}; + // The scripts in SQ4CD support simultaneous playing of speech and subtitles, // but this was not available as an option. The following two patches enable // this functionality in the game's GUI options dialog. @@ -2741,8 +2782,9 @@ static const uint16 sq4CdPatchTextOptions[] = { static const SciScriptPatcherEntry sq4Signatures[] = { { true, 298, "Floppy: endless flight", 1, sq4FloppySignatureEndlessFlight, sq4FloppyPatchEndlessFlight }, { true, 700, "Floppy: throw stuff at sequel police bug", 1, sq4FloppySignatureThrowStuffAtSequelPoliceBug, sq4FloppyPatchThrowStuffAtSequelPoliceBug }, - { true, 818, "CD: Speech and subtitles option", 1, sq4CdSignatureTextOptions, sq4CdPatchTextOptions }, + { true, 45, "CD: walk in from below for room 45 fix", 1, sq4CdSignatureWalkInFromBelowRoom45, sq4CdPatchWalkInFromBelowRoom45 }, { true, 0, "CD: Babble icon speech and subtitles fix", 1, sq4CdSignatureBabbleIcon, sq4CdPatchBabbleIcon }, + { true, 818, "CD: Speech and subtitles option", 1, sq4CdSignatureTextOptions, sq4CdPatchTextOptions }, { true, 818, "CD: Speech and subtitles option button", 1, sq4CdSignatureTextOptionsButton, sq4CdPatchTextOptionsButton }, SCI_SIGNATUREENTRY_TERMINATOR }; -- cgit v1.2.3 From 53f9dac75ef0c0c22c513068eaccf8c96457a438 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 25 Apr 2015 22:42:20 +0200 Subject: SCI: script patch qfg2 saurus freeze - bug #5156 getting back on saurus in the desert by typing command "ride" freezes the game. This patch fixes the issue. Attention: difficult bug to fix, may cause issues --- engines/sci/engine/script_patches.cpp | 44 +++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) (limited to 'engines') diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp index b4844e3e7e..173641f7ee 100644 --- a/engines/sci/engine/script_patches.cpp +++ b/engines/sci/engine/script_patches.cpp @@ -95,6 +95,7 @@ static const char *const selectorNameTable[] = { "localize", // Freddy Pharkas "put", // Police Quest 1 VGA "say", // Quest For Glory 1 VGA + "contains", // Quest For Glory 2 "solvePuzzle", // Quest For Glory 3 "timesShownID", // Space Quest 1 VGA "startText", // King's Quest 6 CD / Laura Bow 2 CD for audio+text support @@ -121,6 +122,7 @@ enum ScriptPatcherSelectors { SELECTOR_localize, SELECTOR_put, SELECTOR_say, + SELECTOR_contains, SELECTOR_solvePuzzle, SELECTOR_timesShownID, SELECTOR_startText, @@ -2286,6 +2288,47 @@ static const SciScriptPatcherEntry qfg1vgaSignatures[] = { }; // =========================================================================== + +// This is a very complicated bug. +// When the player encounters an enemy in the desert while riding a saurus and later +// tries to get back on it by entering "ride", the game will not give control back +// to the player. +// +// This is caused by script mountSaurus getting triggered twice. +// Once by entering the command "ride" and then a second time by a proximity check. +// +// Both are calling mountSaurus::init() in script 20, this one disables controls +// then mountSaurus::changeState() from script 660 is triggered +// mountSaurus::changeState(5) finally calls mountSaurus::dispose(), which is also in script 20 +// which finally re-enables controls +// +// A fix is difficult to implement. The code in script 20 is generic and used by multiple objects +// That's why I have decided to change the responsible globals (66h and A1h) during mountSaurus::changeState(5) +// +// This fix could cause issues in case there is a cutscene, that contains ego getting on a saurus and +// requires controls not getting re-enabled after getting back up on the saurus. +// +// Applies to at least: English PC Floppy, English Amiga Floppy +// Responsible method: mountSaurus::changeState(), mountSaurus::init(), mountSaurus::dispose() +// Fixes bug: #5156 +static const uint16 qfg2SignatureSaurusFreeze[] = { + 0x3c, // dup + 0x35, 0x05, // ldi 5 + SIG_MAGICDWORD, + 0x1a, // eq? + 0x30, SIG_UINT16(0x004e), // bnt [ret] + 0x39, SIG_SELECTOR8(contains), // pushi [selector contains] + 0x78, // push1 + SIG_END +}; + +static const uint16 qfg2PatchSaurusFreeze[] = { + 0x35, 0x01, // ldi 1 + 0xa1, 0x66, // sag 66h + 0xa0, SIG_UINT16(0x00a1), // sag 00A1h + PATCH_END +}; + // Script 944 in QFG2 contains the FileSelector system class, used in the // character import screen. This gets incorrectly called constantly, whenever // the user clicks on a button in order to refresh the file list. This was @@ -2366,6 +2409,7 @@ static const uint16 qfg2PatchImportCharType[] = { // script, description, signature patch static const SciScriptPatcherEntry qfg2Signatures[] = { + { true, 660, "getting back on saurus freeze fix", 1, qfg2SignatureSaurusFreeze, qfg2PatchSaurusFreeze }, { true, 805, "import character type fix", 1, qfg2SignatureImportCharType, qfg2PatchImportCharType }, { true, 944, "import dialog continuous calls", 1, qfg2SignatureImportDialog, qfg2PatchImportDialog }, SCI_SIGNATUREENTRY_TERMINATOR -- cgit v1.2.3 From 4c03e4b699916a9b9fe71afffaf41c283045216e Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Sun, 26 Apr 2015 00:43:53 +0200 Subject: SCI: Stop processing in kGetEvent after loading getSciEvent can trigger the main ScummVM menu, which can trigger loading a game, which will invalidate the game state that kGetEvent is operating on. Other kernel functions may still have the same problem, and a better solution may be necessary. --- engines/sci/engine/kevent.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'engines') diff --git a/engines/sci/engine/kevent.cpp b/engines/sci/engine/kevent.cpp index cb81da2279..dfa29bd047 100644 --- a/engines/sci/engine/kevent.cpp +++ b/engines/sci/engine/kevent.cpp @@ -74,6 +74,11 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) { curEvent = g_sci->getEventManager()->getSciEvent(mask); + // Aborted during getSciEvent (e.g., due to loading a game from the + // ScummVM menu), so return immediately + if (s->abortScriptProcessing) + return NULL_REG; + // For a real event we use its associated mouse position mousePos = curEvent.mousePos; #ifdef ENABLE_SCI32 -- cgit v1.2.3 From 21b138add24e9b95e70adb267c35268de0f828d1 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Sun, 26 Apr 2015 00:50:00 +0200 Subject: Revert "SCI: Hopefully fix bug #3565505 - "SCI : crash when loading a savegame"" This reverts commit 76ff4c700166d69b416dae324ee616ab57265c34. It was intended to fix bug #6136, but only worked around the actual problem in some cases. See 4c03e4b699916a9b9fe71afffaf41c283045216e. --- engines/sci/detection.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp index 85ff1c0062..e572e8ec7f 100644 --- a/engines/sci/detection.cpp +++ b/engines/sci/detection.cpp @@ -834,16 +834,12 @@ Common::Error SciEngine::saveGameState(int slot, const Common::String &desc) { return Common::kNoError; } -// Before enabling the load option in the ScummVM menu, the main game loop must -// have run at least once. When the game loop runs, kGameIsRestarting is invoked, -// thus the speed throttler is initialized. Hopefully fixes bug #3565505. - bool SciEngine::canLoadGameStateCurrently() { - return !_gamestate->executionStackBase && (_gamestate->_throttleLastTime > 0 || _gamestate->_throttleTrigger); + return !_gamestate->executionStackBase; } bool SciEngine::canSaveGameStateCurrently() { - return !_gamestate->executionStackBase && (_gamestate->_throttleLastTime > 0 || _gamestate->_throttleTrigger); + return !_gamestate->executionStackBase; } } // End of namespace Sci -- cgit v1.2.3 From 95f25329379482555c6b1e3181fc737b80f53b40 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 25 Apr 2015 18:37:45 -0500 Subject: SHERLOCK: Disable joystick buttons in Setup dialog, since it isn't supported --- engines/sherlock/user_interface.cpp | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index 176b1bc42b..53151ece55 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -147,11 +147,16 @@ void Settings::drawInteface(bool flag) { screen.makeButton(Common::Rect(SETUP_POINTS[5][0], SETUP_POINTS[5][1], SETUP_POINTS[5][2], SETUP_POINTS[5][1] + 10), SETUP_POINTS[5][3] - screen.stringWidth("New Font Style") / 2, "New Font Style"); - tempStr = Common::String::format("Joystick %s", SETUP_STRS0[0]); + // WORKAROUND: We don't support the joystick in ScummVM, so draw the next two buttons as disabled + tempStr = "Joystick Off"; screen.makeButton(Common::Rect(SETUP_POINTS[6][0], SETUP_POINTS[6][1], SETUP_POINTS[6][2], SETUP_POINTS[6][1] + 10), SETUP_POINTS[6][3] - screen.stringWidth(tempStr) / 2, tempStr); + screen.buttonPrint(Common::Point(SETUP_POINTS[6][3], SETUP_POINTS[6][1]), COMMAND_NULL, false, tempStr); + + tempStr = "Calibrate Joystick"; screen.makeButton(Common::Rect(SETUP_POINTS[7][0], SETUP_POINTS[7][1], SETUP_POINTS[7][2], SETUP_POINTS[7][1] + 10), - SETUP_POINTS[7][3] - screen.stringWidth("Calibrate Joystick") / 2, "Calibrate Joystick"); + SETUP_POINTS[7][3] - screen.stringWidth(tempStr) / 2, tempStr); + screen.buttonPrint(Common::Point(SETUP_POINTS[7][3], SETUP_POINTS[7][1]), COMMAND_NULL, false, tempStr); tempStr = Common::String::format("Fade %s", screen._fadeStyle ? "by Pixel" : "Directly"); screen.makeButton(Common::Rect(SETUP_POINTS[8][0], SETUP_POINTS[8][1], SETUP_POINTS[8][2], SETUP_POINTS[8][1] + 10), @@ -164,7 +169,7 @@ void Settings::drawInteface(bool flag) { tempStr = Common::String::format("Portraits %s", SETUP_STRS0[people._portraitsOn]); screen.makeButton(Common::Rect(SETUP_POINTS[10][0], SETUP_POINTS[10][1], SETUP_POINTS[10][2], SETUP_POINTS[10][1] + 10), SETUP_POINTS[10][3] - screen.stringWidth(tempStr) / 2, tempStr); - tempStr = Common::String::format("_key Pad %s", _vm->_keyPadSpeed ? "Fast" : "Slow"); + tempStr = Common::String::format("Key Pad %s", _vm->_keyPadSpeed ? "Fast" : "Slow"); screen.makeButton(Common::Rect(SETUP_POINTS[11][0], SETUP_POINTS[11][1], SETUP_POINTS[11][2], SETUP_POINTS[11][1] + 10), SETUP_POINTS[11][3] - screen.stringWidth(tempStr) / 2, tempStr); @@ -222,8 +227,12 @@ int Settings::drawButtons(const Common::Point &pt, int _key) { screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr); break; case 6: - tempStr = Common::String::format("Joystick %s", SETUP_STRS0[0]); - screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr); + tempStr = "Joystick Off"; + screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), COMMAND_NULL, true, tempStr); + break; + case 7: + tempStr = "Calibrate Joystick"; + screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), COMMAND_NULL, true, tempStr); break; case 8: tempStr = Common::String::format("Fade %s", SETUP_STRS1[screen._fadeStyle]); @@ -238,7 +247,7 @@ int Settings::drawButtons(const Common::Point &pt, int _key) { screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr); break; case 11: - tempStr = Common::String::format("_key Pad %s", SETUP_STRS4[_vm->_keyPadSpeed]); + tempStr = Common::String::format("Key Pad %s", SETUP_STRS4[_vm->_keyPadSpeed]); screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr); break; default: -- cgit v1.2.3 From 1e4c6abfa3ed3df2bd33f774eddfd5e1a389b9fc Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 25 Apr 2015 21:53:50 -0500 Subject: SHERLOCK: Fix checkSceneFlags incorrectly restoring hidden objects --- engines/sherlock/scene.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 16bb8daecf..60e7b6d369 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -516,7 +516,7 @@ void Scene::checkSceneFlags(bool flag) { // Flag it as needing to be hidden after first erasing it o._type = mode; } - } else if (_bgShapes[idx]._requiredFlag) { + } else if (_bgShapes[idx]._requiredFlag > 0) { // Restore object if (o._images == nullptr || o._images->size() == 0) o._type = NO_SHAPE; -- cgit v1.2.3 From a95170d243df415e58b93e46bf9e23b068729954 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 25 Apr 2015 23:44:50 -0500 Subject: SHERLOCK: Fix Watson not appearing in backstage scene --- engines/sherlock/scene.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines') diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 60e7b6d369..ea7d517301 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -438,6 +438,7 @@ bool Scene::loadScene(const Common::String &filename) { // Player has not yet walked in this scene _walkedInScene = false; + saves._justLoaded = false; // Reset the position on the overland map _vm->_oldCharPoint = _currentScene; -- cgit v1.2.3 From 15a4a942bb6ed708b2ea15bcbb33da66cae292ac Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 26 Apr 2015 00:38:19 -0500 Subject: SHERLOCK: Fix RUN_CANIMATION talk opcode --- engines/sherlock/talk.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index 2ad70dabed..4e7e4de2d0 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -1114,7 +1114,8 @@ void Talk::doScript(const Common::String &script) { case RUN_CANIMATION: // Save the current point in the script, since it might be intterupted by // doing bg anims in the next call, so we need to know where to return to - _scriptCurrentIndex = str - script.c_str(); + ++str; + _scriptCurrentIndex = (str + 1) - script.c_str(); scene.startCAnim((str[0] - 1) & 127, 1 + (str[0] & 128)); if (_talkToAbort) return; -- cgit v1.2.3 From 841a8df09943d77601d1b44c63a2b0c5a531e468 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 26 Apr 2015 02:08:43 -0500 Subject: SHERLOCK: Fix Sherlock disappearing when giving sedative --- engines/sherlock/objects.cpp | 3 +++ engines/sherlock/scene.cpp | 8 +++++--- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index 6231c9abc7..e66f2a68bd 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -424,6 +424,9 @@ Object::Object() { _misc = 0; _maxFrames = 0; _flags = 0; + _aOpen._cAnimNum = 0; + _aOpen._cAnimSpeed = 0; + _aType = OBJECT; _lookFrames = 0; _seqCounter = 0; _lookFacing = 0; diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index ea7d517301..d9161e25c0 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -892,9 +892,6 @@ int Scene::startCAnim(int cAnimNum, int playRate) { CursorId oldCursor = events.getCursor(); events.setCursor(WAIT); - _canimShapes.push_back(Object()); - Object &cObj = _canimShapes[_canimShapes.size() - 1]; - if (walkPos.x != -1) { // Holmes must walk to the walk point before the cAnimation is started if (people[AL]._position != walkPos) @@ -904,6 +901,10 @@ int Scene::startCAnim(int cAnimNum, int playRate) { if (talk._talkToAbort) return 1; + // Add new anim shape entry for displaying the animationo + _canimShapes.push_back(Object()); + Object &cObj = _canimShapes[_canimShapes.size() - 1]; + // Copy the canimation into the bgShapes type canimation structure so it can be played cObj._allow = cAnimNum + 1; // Keep track of the parent structure cObj._name = _cAnim[cAnimNum]._name; // Copy name @@ -1304,6 +1305,7 @@ void Scene::doBgAnim() { people[AL]._oldPosition.x + people[AL]._oldSize.x, people[AL]._oldPosition.y + people[AL]._oldSize.y )); + people[AL]._type = INVALID; } else { screen.flushImage(people[AL]._imageFrame, Common::Point(people[AL]._position.x / 100, -- cgit v1.2.3 From bfba28c33591afe8ce2f7f42de49935029bb4d62 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 26 Apr 2015 09:08:46 +0200 Subject: SCI: implement delayed restore via ScummVM menu will delay restoring a saved game until the next kGetEvent or kWait also implement aborting playback for kPortrait and kShowMovie --- engines/sci/detection.cpp | 4 ++++ engines/sci/engine/kevent.cpp | 14 ++++++++------ engines/sci/engine/kgraphics.cpp | 7 +++++++ engines/sci/engine/kvideo.cpp | 2 ++ engines/sci/engine/savegame.cpp | 17 +++++++++++++++++ engines/sci/engine/savegame.h | 4 +++- engines/sci/engine/state.cpp | 4 ++++ engines/sci/engine/state.h | 4 ++++ engines/sci/graphics/portrait.cpp | 3 ++- 9 files changed, 51 insertions(+), 8 deletions(-) (limited to 'engines') diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp index e572e8ec7f..604aa476a2 100644 --- a/engines/sci/detection.cpp +++ b/engines/sci/detection.cpp @@ -791,6 +791,10 @@ void SciMetaEngine::removeSaveState(const char *target, int slot) const { } Common::Error SciEngine::loadGameState(int slot) { + _gamestate->_delayedRestoreGameId = slot; + _gamestate->_delayedRestoreGame = true; + return Common::kNoError; + Common::String fileName = Common::String::format("%s.%03d", _targetName.c_str(), slot); Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager(); Common::SeekableReadStream *in = saveFileMan->openForLoading(fileName); diff --git a/engines/sci/engine/kevent.cpp b/engines/sci/engine/kevent.cpp index dfa29bd047..8e16e0a07a 100644 --- a/engines/sci/engine/kevent.cpp +++ b/engines/sci/engine/kevent.cpp @@ -24,9 +24,10 @@ #include "sci/sci.h" #include "sci/engine/features.h" -#include "sci/engine/state.h" -#include "sci/engine/selector.h" #include "sci/engine/kernel.h" +#include "sci/engine/savegame.h" +#include "sci/engine/selector.h" +#include "sci/engine/state.h" #include "sci/console.h" #include "sci/debug.h" // for g_debug_simulated_key #include "sci/event.h" @@ -71,13 +72,14 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) { g_debug_simulated_key = 0; return make_reg(0, 1); } - + curEvent = g_sci->getEventManager()->getSciEvent(mask); - // Aborted during getSciEvent (e.g., due to loading a game from the - // ScummVM menu), so return immediately - if (s->abortScriptProcessing) + if (s->_delayedRestoreGame) { + // delayed restore game from ScummVM menu got triggered + gamestate_delayedrestore(s); return NULL_REG; + } // For a real event we use its associated mouse position mousePos = curEvent.mousePos; diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 7d24dd861f..8b790e6a58 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -32,6 +32,7 @@ #include "sci/event.h" #include "sci/resource.h" #include "sci/engine/features.h" +#include "sci/engine/savegame.h" #include "sci/engine/state.h" #include "sci/engine/selector.h" #include "sci/engine/kernel.h" @@ -400,6 +401,12 @@ reg_t kWait(EngineState *s, int argc, reg_t *argv) { s->wait(sleep_time); + if (s->_delayedRestoreGame) { + // delayed restore game from ScummVM menu got triggered + gamestate_delayedrestore(s); + return NULL_REG; + } + return s->r_acc; } diff --git a/engines/sci/engine/kvideo.cpp b/engines/sci/engine/kvideo.cpp index 319469cb08..f925111fc9 100644 --- a/engines/sci/engine/kvideo.cpp +++ b/engines/sci/engine/kvideo.cpp @@ -123,6 +123,8 @@ void playVideo(Video::VideoDecoder *videoDecoder, VideoState videoState) { if ((event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE) || event.type == Common::EVENT_LBUTTONUP) skipVideo = true; } + if (g_sci->getEngineState()->_delayedRestoreGame) + skipVideo = true; g_system->delayMillis(10); } diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index d146cba204..d89170ab22 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -20,6 +20,7 @@ * */ +#include "common/savefile.h" #include "common/stream.h" #include "common/system.h" #include "common/func.h" @@ -872,6 +873,22 @@ bool gamestate_save(EngineState *s, Common::WriteStream *fh, const Common::Strin extern void showScummVMDialog(const Common::String &message); +void gamestate_delayedrestore(EngineState *s) { + Common::String fileName = g_sci->getSavegameName(s->_delayedRestoreGameId); + Common::SeekableReadStream *in = g_sci->getSaveFileManager()->openForLoading(fileName); + + if (in) { + // found a savegame file + gamestate_restore(s, in); + delete in; + if (s->r_acc != make_reg(0, 1)) { + return; + } + } + + error("Restoring gamestate '%s' failed", fileName.c_str()); +} + void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { SavegameMetadata meta; diff --git a/engines/sci/engine/savegame.h b/engines/sci/engine/savegame.h index 7f482ed0a1..5512b90fa8 100644 --- a/engines/sci/engine/savegame.h +++ b/engines/sci/engine/savegame.h @@ -74,7 +74,6 @@ struct SavegameMetadata { uint16 script0Size; }; - /** * Saves a game state to the hard disk in a portable way. * @param s The state to save @@ -84,6 +83,9 @@ struct SavegameMetadata { */ bool gamestate_save(EngineState *s, Common::WriteStream *save, const Common::String &savename, const Common::String &version); +// does a delayed saved game restore, used by ScummVM game menu - see detection.cpp / SciEngine::loadGameState() +void gamestate_delayedrestore(EngineState *s); + /** * Restores a game state from a directory. * @param s An older state from the same game diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index 527c8f0ae0..417d98e2e2 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -92,6 +92,10 @@ void EngineState::reset(bool isRestoring) { abortScriptProcessing = kAbortNone; } + // reset delayed restore game functionality + _delayedRestoreGame = false; + _delayedRestoreGameId = 0; + executionStackBase = 0; _executionStackPosChanged = false; stack_base = 0; diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h index ecc8cb7dfe..e7499e66c9 100644 --- a/engines/sci/engine/state.h +++ b/engines/sci/engine/state.h @@ -131,6 +131,10 @@ public: VirtualIndexFile *_virtualIndexFile; #endif + // see detection.cpp / SciEngine::loadGameState() + bool _delayedRestoreGame; // boolean, that triggers delayed restore (triggered by ScummVM menu) + int _delayedRestoreGameId; // the saved game id, that it supposed to get restored (triggered by ScummVM menu) + uint _chosenQfGImportItem; // Remembers the item selected in QfG import rooms bool _cursorWorkaroundActive; // Refer to GfxCursor::setPosition() diff --git a/engines/sci/graphics/portrait.cpp b/engines/sci/graphics/portrait.cpp index 3311f47022..cb425f3be9 100644 --- a/engines/sci/graphics/portrait.cpp +++ b/engines/sci/graphics/portrait.cpp @@ -317,7 +317,8 @@ void Portrait::doit(Common::Point position, uint16 resourceId, uint16 noun, uint curEvent = _event->getSciEvent(SCI_EVENT_ANY); if (curEvent.type == SCI_EVENT_MOUSE_PRESS || (curEvent.type == SCI_EVENT_KEYBOARD && curEvent.data == SCI_KEY_ESC) || - g_sci->getEngineState()->abortScriptProcessing == kAbortQuitGame) + g_sci->getEngineState()->abortScriptProcessing == kAbortQuitGame || + g_sci->getEngineState()->_delayedRestoreGame) userAbort = true; curPosition = _audio->getAudioPosition(); } while ((curPosition != -1) && (curPosition < timerPosition) && (!userAbort)); -- cgit v1.2.3 From 5a7dbc3666b29a4bde5673fe20a85e68d02b6c56 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 26 Apr 2015 09:10:25 +0200 Subject: SCI: remove unused code in SciEngine::loadGameState() --- engines/sci/detection.cpp | 17 ----------------- 1 file changed, 17 deletions(-) (limited to 'engines') diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp index 604aa476a2..9a41127f6d 100644 --- a/engines/sci/detection.cpp +++ b/engines/sci/detection.cpp @@ -794,23 +794,6 @@ Common::Error SciEngine::loadGameState(int slot) { _gamestate->_delayedRestoreGameId = slot; _gamestate->_delayedRestoreGame = true; return Common::kNoError; - - Common::String fileName = Common::String::format("%s.%03d", _targetName.c_str(), slot); - Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager(); - Common::SeekableReadStream *in = saveFileMan->openForLoading(fileName); - - if (in) { - // found a savegame file - gamestate_restore(_gamestate, in); - delete in; - } - - if (_gamestate->r_acc != make_reg(0, 1)) { - return Common::kNoError; - } else { - warning("Restoring gamestate '%s' failed", fileName.c_str()); - return Common::kUnknownError; - } } Common::Error SciEngine::saveGameState(int slot, const Common::String &desc) { -- cgit v1.2.3 From 6a13dad7ef844ffd5e5174b337cf7e4ad272c80b Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 26 Apr 2015 03:07:13 -0500 Subject: SHERLOCK: Fix TOGGLE_OBJECT talk opcode --- engines/sherlock/talk.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines') diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index 4e7e4de2d0..d81f98cac7 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -1294,6 +1294,7 @@ void Talk::doScript(const Common::String &script) { break; case TOGGLE_OBJECT: + ++str; for (int idx = 0; idx < str[0]; ++idx) tempString += str[idx + 1]; -- cgit v1.2.3 From d7a8d701641600b896622f8b7abb728c4b4cc266 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 26 Apr 2015 03:20:01 -0500 Subject: SHERLOCK: Fix missing increments from various talk opcodes --- engines/sherlock/talk.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'engines') diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index d81f98cac7..b45139db4e 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -1212,6 +1212,7 @@ void Talk::doScript(const Common::String &script) { case WALK_TO_COORDS: // Save the current point in the script, since it might be intterupted by // doing bg anims in the next call, so we need to know where to return to + ++str; _scriptCurrentIndex = str - script.c_str(); people.walkToCoords(Common::Point(((str[0] - 1) * 256 + str[1] - 1) * 100, str[2] * 100), str[3] - 1); @@ -1224,6 +1225,7 @@ void Talk::doScript(const Common::String &script) { case PAUSE_WITHOUT_CONTROL: // Save the current point in the script, since it might be intterupted by // doing bg anims in the next call, so we need to know where to return to + ++str; _scriptCurrentIndex = str - script.c_str(); for (int idx = 0; idx < (str[0] - 1); ++idx) { @@ -1433,6 +1435,7 @@ void Talk::doScript(const Common::String &script) { case MOVE_MOUSE: // Save the current point in the script, since it might be intterupted by // doing bg anims in the next call, so we need to know where to return to + ++str; _scriptCurrentIndex = str - script.c_str(); events.moveMouse(Common::Point((str[0] - 1) * 256 + str[1] - 1, str[2])); if (_talkToAbort) -- cgit v1.2.3 From 9044dd49dc2debd1c7d1fa4ea991320a1072235e Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 26 Apr 2015 03:45:28 -0500 Subject: SHERLOCK: Fix closing closet in Backstage scene --- engines/sherlock/objects.cpp | 4 ++++ engines/sherlock/objects.h | 4 ++-- engines/sherlock/user_interface.cpp | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index e66f2a68bd..8c8d90579c 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -366,6 +366,8 @@ void ActionType::synchronize(Common::SeekableReadStream &s) { _cAnimNum = s.readByte(); _cAnimSpeed = s.readByte(); + if (_cAnimSpeed & 0x80) + _cAnimSpeed = -(_cAnimSpeed & 0x7f); for (int idx = 0; idx < 4; ++idx) { s.read(buffer, 12); @@ -380,6 +382,8 @@ void UseType::synchronize(Common::SeekableReadStream &s) { _cAnimNum = s.readByte(); _cAnimSpeed = s.readByte(); + if (_cAnimSpeed & 0x80) + _cAnimSpeed = -(_cAnimSpeed & 0x7f); for (int idx = 0; idx < 4; ++idx) { s.read(buffer, 12); diff --git a/engines/sherlock/objects.h b/engines/sherlock/objects.h index 2b2472fbbf..80b0b9d9f3 100644 --- a/engines/sherlock/objects.h +++ b/engines/sherlock/objects.h @@ -125,8 +125,8 @@ public: enum { REVERSE_DIRECTION = 0x80 }; struct ActionType { - int8 _cAnimNum; - uint8 _cAnimSpeed; // if high bit set, play in reverse + int _cAnimNum; + int _cAnimSpeed; // if high bit set, play in reverse Common::String _names[4]; void synchronize(Common::SeekableReadStream &s); diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index 53151ece55..c623896c85 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -2678,7 +2678,7 @@ void UserInterface::checkAction(ActionType &action, const char *const messages[] if (scene._goToScene != 1 && !printed && !talk._talkToAbort) { _infoFlag = true; clearInfo(); - screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, messages[action._cAnimNum]); + screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "Done..."); // Set how long to show the message _menuCounter = 30; -- cgit v1.2.3 From 0c68c0a53ac2ffb5837ca2eada00af7f371bc7c9 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 26 Apr 2015 04:33:24 -0500 Subject: SHERLOCK: Fix inventory display when player has more than 6 items --- engines/sherlock/inventory.cpp | 6 +++--- engines/sherlock/user_interface.cpp | 31 ++++++++++++------------------- 2 files changed, 15 insertions(+), 22 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/inventory.cpp b/engines/sherlock/inventory.cpp index 808429f643..798531ea14 100644 --- a/engines/sherlock/inventory.cpp +++ b/engines/sherlock/inventory.cpp @@ -120,7 +120,7 @@ void Inventory::loadGraphics() { int invNum = findInv((*this)[idx]._name); Common::String fName = Common::String::format("item%02d.vgs", invNum + 1); - _invShapes[idx] = new ImageFile(fName); + _invShapes[idx - _invIndex] = new ImageFile(fName); } _invGraphicsLoaded = true; @@ -302,10 +302,10 @@ void Inventory::invCommands(bool slamIt) { _invMode == 3 ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND, true, "Give"); screen.print(Common::Point(INVENTORY_POINTS[4][2], CONTROLS_Y1 + 1), - _invMode == 0 ? COMMAND_NULL : COMMAND_FOREGROUND, + _invIndex == 0 ? COMMAND_NULL : COMMAND_FOREGROUND, "^^"); screen.print(Common::Point(INVENTORY_POINTS[5][2], CONTROLS_Y1 + 1), - _invMode == 0 ? COMMAND_NULL : COMMAND_FOREGROUND, + _invIndex == 0 ? COMMAND_NULL : COMMAND_FOREGROUND, "^"); screen.print(Common::Point(INVENTORY_POINTS[6][2], CONTROLS_Y1 + 1), (_holdings - _invIndex <= 6) ? COMMAND_NULL : COMMAND_FOREGROUND, diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index c623896c85..7a581ca63b 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -1247,17 +1247,13 @@ void UserInterface::doInvControl() { } if (inv._invIndex) { - screen.print(Common::Point(INVENTORY_POINTS[4][2], CONTROLS_Y1 + 1), - colors[4], "^^"); - screen.print(Common::Point(INVENTORY_POINTS[5][2], CONTROLS_Y1 + 1), - colors[5], "^"); + screen.print(Common::Point(INVENTORY_POINTS[4][2], CONTROLS_Y1 + 1), colors[4], "^^"); + screen.print(Common::Point(INVENTORY_POINTS[5][2], CONTROLS_Y1 + 1), colors[5], "^"); } if ((inv._holdings - inv._invIndex) > 6) { - screen.print(Common::Point(INVENTORY_POINTS[6][2], CONTROLS_Y1 + 1), - colors[6], "^^"); - screen.print(Common::Point(INVENTORY_POINTS[7][2], CONTROLS_Y1 + 1), - colors[7], "^"); + screen.print(Common::Point(INVENTORY_POINTS[6][2], CONTROLS_Y1 + 1), colors[6], "_"); + screen.print(Common::Point(INVENTORY_POINTS[7][2], CONTROLS_Y1 + 1), colors[7], "__"); } bool flag = false; @@ -1339,31 +1335,28 @@ void UserInterface::doInvControl() { inv.loadGraphics(); inv.putInv(1); inv.invCommands(true); - } else if (((found == 5 && events._released) || _key == '-') && inv._invIndex) { + } else if (((found == 5 && events._released) || _key == Common::KEYCODE_MINUS + || _key == Common::KEYCODE_KP_MINUS) && inv._invIndex > 0) { --inv._invIndex; - screen.print(Common::Point(INVENTORY_POINTS[4][2], CONTROLS_Y1 + 1), - COMMAND_HIGHLIGHTED, "^"); + screen.print(Common::Point(INVENTORY_POINTS[4][2], CONTROLS_Y1 + 1), COMMAND_HIGHLIGHTED, "^"); inv.freeGraphics(); inv.loadGraphics(); inv.putInv(1); inv.invCommands(true); - } else if (((found == 6 && events._released) || _key == '+') && - (inv._holdings - inv._invIndex) > 6) { + } else if (((found == 6 && events._released) || _key == Common::KEYCODE_PLUS + || _key == Common::KEYCODE_KP_PLUS) && (inv._holdings - inv._invIndex) > 6) { ++inv._invIndex; - screen.print(Common::Point(INVENTORY_POINTS[6][2], CONTROLS_Y1 + 1), - COMMAND_HIGHLIGHTED, "_"); + screen.print(Common::Point(INVENTORY_POINTS[6][2], CONTROLS_Y1 + 1), COMMAND_HIGHLIGHTED, "_"); inv.freeGraphics(); inv.loadGraphics(); inv.putInv(1); inv.invCommands(true); - } else if (((found == 7 && events._released) || _key == '.') && - (inv._holdings - inv._invIndex) > 6) { + } else if (((found == 7 && events._released) || _key == '.') && (inv._holdings - inv._invIndex) > 6) { inv._invIndex += 6; if ((inv._holdings - 6) < inv._invIndex) inv._invIndex = inv._holdings - 6; - screen.print(Common::Point(INVENTORY_POINTS[7][2], CONTROLS_Y1 + 1), - COMMAND_HIGHLIGHTED, "_"); + screen.print(Common::Point(INVENTORY_POINTS[7][2], CONTROLS_Y1 + 1), COMMAND_HIGHLIGHTED, "_"); inv.freeGraphics(); inv.loadGraphics(); inv.putInv(1); -- cgit v1.2.3 From 250b3c1a30acba5770f214edaf14bc288065acd9 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 26 Apr 2015 04:52:31 -0500 Subject: SHERLOCK: Fix handling of talk opcodes in journal loading --- engines/sherlock/journal.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/journal.cpp b/engines/sherlock/journal.cpp index ffda25a533..255662f71c 100644 --- a/engines/sherlock/journal.cpp +++ b/engines/sherlock/journal.cpp @@ -356,23 +356,23 @@ int Journal::loadJournalFile(bool alreadyLoaded) { break; case 134: // Change sequence - replyP += (replyP[0] & 127) + replyP[2] + 1; + replyP += (replyP[0] & 127) + replyP[2] + 2; break; case 135: // Walk to co-ords case 154: // Move mouse - replyP += 3; + replyP += 4; break; case 139: // Set flag case 143: // If statement - ++replyP; + replyP += 2; break; case 140: // Play voice file case 150: // Play prologue case 153: // Call talk file - replyP += 7; + replyP += 8; break; case 141: // Toggle object @@ -380,11 +380,11 @@ int Journal::loadJournalFile(bool alreadyLoaded) { case 152: // Set object case 155: // Info line case 158: // Delete item from inventory - replyP += *replyP & 127; + replyP += (*replyP & 127) + 1; break; case 149: // Goto scene - replyP += 4; + replyP += 5; break; case 161: // End of line -- cgit v1.2.3 From fd8cab4ffd38574fd255bd8f6335238ceb19bba8 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 26 Apr 2015 06:22:25 -0500 Subject: SHERLOCK: Fix casting of data in talk opcode handling --- engines/sherlock/talk.cpp | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index b45139db4e..fafd9ce201 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -1027,7 +1027,7 @@ void Talk::doScript(const Common::String &script) { } // Check if the script begins with a Stealh Mode Active command - if (str[0] == STEALTH_MODE_ACTIVE || _talkStealth) { + if ((byte)str[0] == STEALTH_MODE_ACTIVE || _talkStealth) { _talkStealth = 2; _speaker |= 128; } else { @@ -1068,7 +1068,7 @@ void Talk::doScript(const Common::String &script) { } // Remove portrait? - if (str[0] == REMOVE_PORTRAIT) { + if ((byte)str[0] == REMOVE_PORTRAIT) { _speaker = 255; } else { // Nope, so set the first speaker @@ -1116,12 +1116,12 @@ void Talk::doScript(const Common::String &script) { // doing bg anims in the next call, so we need to know where to return to ++str; _scriptCurrentIndex = (str + 1) - script.c_str(); - scene.startCAnim((str[0] - 1) & 127, 1 + (str[0] & 128)); + scene.startCAnim(((byte)str[0] - 1) & 127, 1 + ((byte)str[0] & 128)); if (_talkToAbort) return; // Check if next character is changing side or changing portrait - if (charCount && (str[1] == SWITCH_SPEAKER || str[1] == ASSIGN_PORTRAIT_LOCATION)) + if (charCount && ((byte)str[1] == SWITCH_SPEAKER || (byte)str[1] == ASSIGN_PORTRAIT_LOCATION)) wait = 1; break; @@ -1215,7 +1215,8 @@ void Talk::doScript(const Common::String &script) { ++str; _scriptCurrentIndex = str - script.c_str(); - people.walkToCoords(Common::Point(((str[0] - 1) * 256 + str[1] - 1) * 100, str[2] * 100), str[3] - 1); + people.walkToCoords(Common::Point((((byte)str[0] - 1) * 256 + (byte)str[1] - 1) * 100, + (byte)str[2] * 100), str[3] - 1); if (_talkToAbort) return; @@ -1272,7 +1273,7 @@ void Talk::doScript(const Common::String &script) { case SET_FLAG: { ++str; - int flag1 = (str[0] - 1) * 256 + str[1] - 1 - (str[1] == 1 ? 1 : 0); + int flag1 = ((byte)str[0] - 1) * 256 + (byte)str[1] - 1 - (str[1] == 1 ? 1 : 0); int flag = (flag1 & 0x7fff) * (flag1 >= 0x8000 ? -1 : 1); _vm->setFlags(flag); ++str; @@ -1310,7 +1311,7 @@ void Talk::doScript(const Common::String &script) { case IF_STATEMENT: { ++str; - int flag = (str[0] - 1) * 256 + str[1] - 1 - (str[1] == 1 ? 1 : 0); + int flag = ((byte)str[0] - 1) * 256 + (byte)str[1] - 1 - (str[1] == 1 ? 1 : 0); ++str; wait = 0; @@ -1396,7 +1397,7 @@ void Talk::doScript(const Common::String &script) { str += str[0]; // Set comparison state according to if we want to hide or unhide - bool state = (str[0] >= 128); + bool state = ((byte)str[0] >= 128); for (uint idx = 0; idx < scene._bgShapes.size(); ++idx) { Object &obj = scene._bgShapes[idx]; @@ -1437,7 +1438,7 @@ void Talk::doScript(const Common::String &script) { // doing bg anims in the next call, so we need to know where to return to ++str; _scriptCurrentIndex = str - script.c_str(); - events.moveMouse(Common::Point((str[0] - 1) * 256 + str[1] - 1, str[2])); + events.moveMouse(Common::Point(((byte)str[0] - 1) * 256 + (byte)str[1] - 1, str[2])); if (_talkToAbort) return; str += 3; @@ -1599,7 +1600,7 @@ void Talk::doScript(const Common::String &script) { } // Open window if it wasn't already open, and text has already been printed - if ((openTalkWindow && wait) || (openTalkWindow && str[0] >= 128 && str[0] != COMMAND_161)) { + if ((openTalkWindow && wait) || (openTalkWindow && (byte)str[0] >= 128 && (byte)str[0] != COMMAND_161)) { if (!ui._windowStyle) { screen.slamRect(Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); } else { @@ -1625,12 +1626,12 @@ void Talk::doScript(const Common::String &script) { // If a key was pressed to finish the window, see if further voice files should be skipped if (wait >= 0 && wait < 254) { - if (str[0] == SFX_COMMAND) + if ((byte)str[0] == SFX_COMMAND) str += 9; } // Clear the window unless the wait was due to a PAUSE command - if (!pauseFlag && wait != -1 && str[0] != SFX_COMMAND) { + if (!pauseFlag && wait != -1 && (byte)str[0] != SFX_COMMAND) { if (!_talkStealth) ui.clearWindow(); yp = CONTROLS_Y + 12; -- cgit v1.2.3 From 5f53b9255eb2799906c324ff0e2ad096092a5dec Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 26 Apr 2015 15:29:02 +0200 Subject: SCI: restore: reset ports before loading memory otherwise we could free hunk space of the loaded saved game --- engines/sci/engine/savegame.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index d89170ab22..e0c2833572 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -728,9 +728,7 @@ void GfxPalette::saveLoadWithSerializer(Common::Serializer &s) { } void GfxPorts::saveLoadWithSerializer(Common::Serializer &s) { - if (s.isLoading()) - reset(); // remove all script generated windows - + // reset() is called directly way earlier in gamestate_restore() if (s.getVersion() >= 27) { uint windowCount = 0; uint id = PORTS_FIRSTSCRIPTWINDOWID; @@ -925,6 +923,13 @@ void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { // We don't need the thumbnail here, so just read it and discard it Graphics::skipThumbnail(*fh); + // reset ports as one of the first things we do, because that may free() some hunk memory + // and we don't want to do that after we read in the saved game hunk memory + if (ser.isLoading()) { + if (g_sci->_gfxPorts) + g_sci->_gfxPorts->reset(); + } + s->reset(true); s->saveLoadWithSerializer(ser); // FIXME: Error handling? -- cgit v1.2.3 From 031b9b8ced1007545099e0e6285ea4bbe1d3e97f Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 26 Apr 2015 15:50:12 +0200 Subject: SCI: restore: clear screen when restoring primarily to clear kPortrait graphics in kq6 when restoring during portrait animation --- engines/sci/engine/savegame.cpp | 7 ++++++- engines/sci/graphics/screen.cpp | 12 ++++++++++++ engines/sci/graphics/screen.h | 1 + 3 files changed, 19 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index e0c2833572..3d934410c3 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -41,6 +41,7 @@ #include "sci/graphics/helpers.h" #include "sci/graphics/palette.h" #include "sci/graphics/ports.h" +#include "sci/graphics/screen.h" #include "sci/parser/vocabulary.h" #include "sci/sound/audio.h" #include "sci/sound/music.h" @@ -923,11 +924,15 @@ void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { // We don't need the thumbnail here, so just read it and discard it Graphics::skipThumbnail(*fh); - // reset ports as one of the first things we do, because that may free() some hunk memory + // reset ports is one of the first things we do, because that may free() some hunk memory // and we don't want to do that after we read in the saved game hunk memory if (ser.isLoading()) { + // reset ports if (g_sci->_gfxPorts) g_sci->_gfxPorts->reset(); + // clear screen + if (g_sci->_gfxScreen) + g_sci->_gfxScreen->clear(); } s->reset(true); diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp index 5a3b30f7ef..dfcb5dbc14 100644 --- a/engines/sci/graphics/screen.cpp +++ b/engines/sci/graphics/screen.cpp @@ -251,6 +251,18 @@ GfxScreen::~GfxScreen() { free(_displayScreen); } +// should not used regulary, only meant for restore game +void GfxScreen::clear() { + // reset all screen data + memset(_visualScreen, 0, _pixels); + memset(_priorityScreen, 0, _pixels); + memset(_controlScreen, 0, _pixels); + memset(_displayScreen, 0, _displayPixels); + memset(&_ditheredPicColors, 0, sizeof(_ditheredPicColors)); + _fontIsUpscaled = false; + copyToScreen(); +} + void GfxScreen::copyToScreen() { g_system->copyRectToScreen(_activeScreen, _displayWidth, 0, 0, _displayWidth, _displayHeight); } diff --git a/engines/sci/graphics/screen.h b/engines/sci/graphics/screen.h index 766e32614a..587d2ef3bc 100644 --- a/engines/sci/graphics/screen.h +++ b/engines/sci/graphics/screen.h @@ -76,6 +76,7 @@ public: byte getColorWhite() { return _colorWhite; } byte getColorDefaultVectorData() { return _colorDefaultVectorData; } + void clear(); void copyToScreen(); void copyFromScreen(byte *buffer); void kernelSyncWithFramebuffer(); -- cgit v1.2.3 From 0ca3fd645406a44f272ccc77abbc143523918701 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 26 Apr 2015 16:38:34 -0500 Subject: SHERLOCK: Fix SET_FLAG talk opcode --- engines/sherlock/talk.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index fafd9ce201..c605f9a7e9 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -1274,7 +1274,7 @@ void Talk::doScript(const Common::String &script) { case SET_FLAG: { ++str; int flag1 = ((byte)str[0] - 1) * 256 + (byte)str[1] - 1 - (str[1] == 1 ? 1 : 0); - int flag = (flag1 & 0x7fff) * (flag1 >= 0x8000 ? -1 : 1); + int flag = (flag1 & 0x3fff) * (flag1 >= 0x4000 ? -1 : 1); _vm->setFlags(flag); ++str; break; -- cgit v1.2.3 From 488ac579d7cd037dfe5c71cf20a878cf5ecdfe18 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 26 Apr 2015 17:26:22 -0500 Subject: SHERLOCK: Fix checking single character star action names --- engines/sherlock/objects.cpp | 2 +- engines/sherlock/user_interface.cpp | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index 8c8d90579c..49f64c85b0 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -828,7 +828,7 @@ int Object::checkNameForCodes(const Common::String &name, const char *const mess if (name.hasPrefix("*")) { // A code was found printed = true; - ch = toupper(name[1]); + ch = (name == "*") ? 0 : toupper(name[1]); switch (ch) { case 'C': diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index 7a581ca63b..ed3debe2fc 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -2609,7 +2609,8 @@ void UserInterface::checkAction(ActionType &action, const char *const messages[] events.setCursor(WAIT); for (int nameIdx = 0; nameIdx < 4; ++nameIdx) { - if (action._names[nameIdx].hasPrefix("*") && toupper(action._names[nameIdx][1]) == 'W') { + if (action._names[nameIdx].hasPrefix("*") && action._names[nameIdx].size() >= 2 + && toupper(action._names[nameIdx][1]) == 'W') { if (obj.checkNameForCodes(Common::String(action._names[nameIdx].c_str() + 2), messages)) { if (!talk._talkToAbort) printed = true; @@ -2618,7 +2619,7 @@ void UserInterface::checkAction(ActionType &action, const char *const messages[] } for (int nameIdx = 0; nameIdx < 4; ++nameIdx) { - if (action._names[nameIdx].hasPrefix("*")) { + if (action._names[nameIdx].hasPrefix("*") && action._names[nameIdx].size() >= 2) { char ch = toupper(action._names[nameIdx][1]); if (ch == 'T' || ch == 'B') { @@ -2648,7 +2649,8 @@ void UserInterface::checkAction(ActionType &action, const char *const messages[] } for (int nameIdx = 0; nameIdx < 4; ++nameIdx) { - if (action._names[nameIdx].hasPrefix("*") && toupper(action._names[nameIdx][1]) == 'F') { + if (action._names[nameIdx].hasPrefix("*") && action._names[nameIdx].size() >= 2 + && toupper(action._names[nameIdx][1]) == 'F') { if (obj.checkNameForCodes(action._names[nameIdx].c_str() + 2, messages)) { if (!talk._talkToAbort) printed = true; -- cgit v1.2.3 From f3bd61607017fe0ef0f5143e6ad8dbdb4743b246 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 26 Apr 2015 18:07:52 -0500 Subject: SHERLOCK: Fix character positioning after loading savegames --- engines/sherlock/objects.cpp | 22 +++++++++++----------- engines/sherlock/people.cpp | 13 ++++++++++--- engines/sherlock/people.h | 2 ++ engines/sherlock/scalpel/scalpel.cpp | 4 ++-- engines/sherlock/scene.cpp | 34 +++++++++++++++++----------------- engines/sherlock/scene.h | 2 -- engines/sherlock/sherlock.cpp | 2 +- engines/sherlock/talk.cpp | 4 ++-- 8 files changed, 45 insertions(+), 38 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index 49f64c85b0..7341fc3b30 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -165,11 +165,11 @@ void Sprite::adjustSprite() { scene._goToScene = exit->_scene; if (exit->_people.x != 0) { - scene._hsavedPos = exit->_people; - scene._hsavedFs = exit->_peopleDir; + people._hSavedPos = exit->_people; + people._hSavedFacing = exit->_peopleDir; - if (scene._hsavedFs > 100 && scene._hsavedPos.x < 1) - scene._hsavedPos.x = 100; + if (people._hSavedFacing > 100 && people._hSavedPos.x < 1) + people._hSavedPos.x = 100; } } } @@ -869,18 +869,18 @@ int Object::checkNameForCodes(const Common::String &name, const char *const mess ++p; Common::String s(p, p + 3); - scene._hsavedPos.x = atoi(s.c_str()); + people._hSavedPos.x = atoi(s.c_str()); s = Common::String(p + 3, p + 6); - scene._hsavedPos.y = atoi(s.c_str()); + people._hSavedPos.y = atoi(s.c_str()); s = Common::String(p + 6, p + 9); - scene._hsavedFs = atoi(s.c_str()); - if (scene._hsavedFs == 0) - scene._hsavedFs = 10; + people._hSavedFacing = atoi(s.c_str()); + if (people._hSavedFacing == 0) + people._hSavedFacing = 10; } else if ((p = strchr(name.c_str(), '/')) != nullptr) { - scene._hsavedPos = Common::Point(1, 0); - scene._hsavedFs = 100 + atoi(p + 1); + people._hSavedPos = Common::Point(1, 0); + people._hSavedFacing = 100 + atoi(p + 1); } } else { scene._goToScene = 100; diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp index e126757231..43e1fa046b 100644 --- a/engines/sherlock/people.cpp +++ b/engines/sherlock/people.cpp @@ -204,6 +204,8 @@ People::People(SherlockEngine *vm) : _vm(vm), _player(_data[0]) { _speakerFlip = false; _holmesFlip = false; _holmesQuotient = 0; + _hSavedPos = Common::Point(-1, -1); + _hSavedFacing = -1; _portrait._sequences = new byte[32]; } @@ -708,10 +710,15 @@ void People::setTalking(int speaker) { */ void People::synchronize(Common::Serializer &s) { s.syncAsByte(_holmesOn); - s.syncAsSint16LE(_data[AL]._position.x); - s.syncAsSint16LE(_data[AL]._position.y); - s.syncAsSint16LE(_data[AL]._sequenceNumber); + s.syncAsSint16LE(_player._position.x); + s.syncAsSint16LE(_player._position.y); + s.syncAsSint16LE(_player._sequenceNumber); s.syncAsSint16LE(_holmesQuotient); + + if (s.isLoading()) { + _hSavedPos = _player._position; + _hSavedFacing = _player._sequenceNumber; + } } } // End of namespace Sherlock diff --git a/engines/sherlock/people.h b/engines/sherlock/people.h index 8a7476a33a..f1ed3496a1 100644 --- a/engines/sherlock/people.h +++ b/engines/sherlock/people.h @@ -74,6 +74,8 @@ private: public: ImageFile *_talkPics; Common::Point _walkDest; + Common::Point _hSavedPos; + int _hSavedFacing; Common::Queue _walkTo; Person &_player; bool _holmesOn; diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp index 2ca9f80c42..65ca61b09f 100644 --- a/engines/sherlock/scalpel/scalpel.cpp +++ b/engines/sherlock/scalpel/scalpel.cpp @@ -479,8 +479,8 @@ void ScalpelEngine::startScene() { _scene->_goToScene = _map->show(); _sound->freeSong(); - _scene->_hsavedPos = Common::Point(-1, -1); - _scene->_hsavedFs = -1; + _people->_hSavedPos = Common::Point(-1, -1); + _people->_hSavedFacing = -1; } // Some rooms are prologue cutscenes, rather than normal game scenes. These are: diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index d9161e25c0..2d0f6fd751 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -97,8 +97,6 @@ Scene::Scene(SherlockEngine *vm): _vm(vm) { _version = 0; _lzwMode = false; _invGraphicItems = 0; - _hsavedPos = Common::Point(-1, -1); - _hsavedFs = -1; _cAnimFramePause = 0; _restoreFlag = false; _invLookFlag = false; @@ -579,48 +577,50 @@ void Scene::transitionToScene() { SaveManager &saves = *_vm->_saves; Screen &screen = *_vm->_screen; Talk &talk = *_vm->_talk; + Common::Point &hSavedPos = people._hSavedPos; + int &hSavedFacing = people._hSavedFacing; const int FS_TRANS[8] = { STOP_UP, STOP_UPRIGHT, STOP_RIGHT, STOP_DOWNRIGHT, STOP_DOWN, STOP_DOWNLEFT, STOP_LEFT, STOP_UPLEFT }; - if (_hsavedPos.x < 1) { + if (hSavedPos.x < 1) { // No exit information from last scene-check entrance info if (_entrance._startPosition.x < 1) { // No entrance info either, so use defaults - _hsavedPos = Common::Point(16000, 10000); - _hsavedFs = 4; + hSavedPos = Common::Point(16000, 10000); + hSavedFacing = 4; } else { // setup entrance info - _hsavedPos = _entrance._startPosition; - _hsavedFs = _entrance._startDir; + hSavedPos = _entrance._startPosition; + hSavedFacing = _entrance._startDir; } } else { // Exit information exists, translate it to real sequence info // Note: If a savegame was just loaded, then the data is already correct. // Otherwise, this is a linked scene or entrance info, and must be translated - if (_hsavedFs < 8 && !saves._justLoaded) { - _hsavedFs = FS_TRANS[_hsavedFs]; - _hsavedPos.x *= 100; - _hsavedPos.y *= 100; + if (hSavedFacing < 8 && !saves._justLoaded) { + hSavedFacing = FS_TRANS[hSavedFacing]; + hSavedPos.x *= 100; + hSavedPos.y *= 100; } } int cAnimNum = -1; - if (_hsavedFs < 101) { + if (hSavedFacing < 101) { // Standard info, so set it - people[PLAYER]._position = _hsavedPos; - people[PLAYER]._sequenceNumber = _hsavedFs; + people[PLAYER]._position = hSavedPos; + people[PLAYER]._sequenceNumber = hSavedFacing; } else { // It's canimation information - cAnimNum = _hsavedFs - 101; + cAnimNum = hSavedFacing - 101; } // Reset positioning for next load - _hsavedPos = Common::Point(-1, -1); - _hsavedFs = -1; + hSavedPos = Common::Point(-1, -1); + hSavedFacing = -1; if (cAnimNum != -1) { // Prevent Holmes from being drawn diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h index cc01fa92ab..892163a2f6 100644 --- a/engines/sherlock/scene.h +++ b/engines/sherlock/scene.h @@ -130,8 +130,6 @@ public: Common::Array _exits; SceneEntry _entrance; Common::Array _sounds; - Common::Point _hsavedPos; - int _hsavedFs; Common::Array _canimShapes; bool _restoreFlag; int _animating; diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index d880257406..406b796fc9 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -147,7 +147,7 @@ void SherlockEngine::sceneLoop() { // Handle any input from the keyboard or mouse handleInput(); - if (_scene->_hsavedPos.x == -1) { + if (_people->_hSavedPos.x == -1) { _canLoadSave = true; _scene->doBgAnim(); _canLoadSave = false; diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index c605f9a7e9..0793552846 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -1361,8 +1361,8 @@ void Talk::doScript(const Common::String &script) { // Run a canimation? if (str[2] > 100) { - scene._hsavedFs = str[2]; - scene._hsavedPos = Common::Point(160, 100); + people._hSavedFacing = (byte)str[2]; + people._hSavedPos = Common::Point(160, 100); } } str += 6; -- cgit v1.2.3 From 65eb390ead25c54b1e3c547f3e189a7ccb73becb Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 26 Apr 2015 18:29:20 -0500 Subject: SHERLOCK: Cleanup and moving of map variables into Map class --- engines/sherlock/map.cpp | 29 +++++++++++++++++++++-------- engines/sherlock/map.h | 8 ++++++-- engines/sherlock/objects.cpp | 4 ++-- engines/sherlock/people.cpp | 5 ++--- engines/sherlock/saveload.cpp | 2 ++ engines/sherlock/scalpel/scalpel.cpp | 18 +++++++++--------- engines/sherlock/scene.cpp | 18 +++++------------- engines/sherlock/scene.h | 3 --- engines/sherlock/sherlock.h | 2 -- engines/sherlock/talk.cpp | 6 +++--- 10 files changed, 50 insertions(+), 45 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/map.cpp b/engines/sherlock/map.cpp index c3a5ba7b17..5865f34fa0 100644 --- a/engines/sherlock/map.cpp +++ b/engines/sherlock/map.cpp @@ -62,6 +62,9 @@ Map::Map(SherlockEngine *vm): _vm(vm), _topLine(SHERLOCK_SCREEN_WIDTH, 12) { _cursorIndex = -1; _drawMap = false; _overPos = Common::Point(13000, 12600); + _charPoint = 0; + _oldCharPoint = 39; + for (int idx = 0; idx < MAX_HOLMES_SEQUENCE; ++idx) Common::fill(&_sequences[idx][0], &_sequences[idx][MAX_FRAME], 0); @@ -126,7 +129,6 @@ void Map::loadData() { int Map::show() { Events &events = *_vm->_events; People &people = *_vm->_people; - Scene &scene = *_vm->_scene; Screen &screen = *_vm->_screen; Common::Point lDrawn(-1, -1); bool changed = false, exitFlag = false; @@ -230,7 +232,7 @@ int Map::show() { if ((events._released || events._rightReleased) && _point != -1) { if (people[AL]._walkCount == 0) { people._walkDest = _points[_point] + Common::Point(4, 9); - scene._charPoint = _point; + _charPoint = _point; // Start walking to selected location walkTheStreets(); @@ -243,7 +245,7 @@ int Map::show() { // Check if a scene has beeen selected and we've finished "moving" to it if (people[AL]._walkCount == 0) { - if (scene._charPoint >= 1 && scene._charPoint < (int)_points.size()) + if (_charPoint >= 1 && _charPoint < (int)_points.size()) exitFlag = true; } @@ -267,7 +269,7 @@ int Map::show() { screen.setFont(oldFont); _active = false; - return scene._charPoint; + return _charPoint; } /** @@ -443,8 +445,8 @@ void Map::walkTheStreets() { Common::Array tempPath; // Get indexes into the path lists for the start and destination scenes - int start = _points[scene._oldCharPoint]._translate; - int dest = _points[scene._charPoint]._translate; + int start = _points[_oldCharPoint]._translate; + int dest = _points[_charPoint]._translate; // Get pointer to start of path const byte *path = _paths.getPath(start, dest); @@ -454,10 +456,10 @@ void Map::walkTheStreets() { Common::Point destPos = people._walkDest; // Check for any intermediate points between the two locations - if (path[0] || scene._charPoint > 50 || scene._oldCharPoint > 50) { + if (path[0] || _charPoint > 50 || _oldCharPoint > 50) { people[AL]._sequenceNumber = -1; - if (scene._charPoint == 51 || scene._oldCharPoint == 51) { + if (_charPoint == 51 || _oldCharPoint == 51) { people.setWalking(); } else { // Check for moving the path backwards or forwards @@ -583,4 +585,15 @@ void Map::highlightIcon(const Common::Point &pt) { } } +/** +* Synchronize the data for a savegame +*/ +void Map::synchronize(Common::Serializer &s) { + s.syncAsSint16LE(_bigPos.x); + s.syncAsSint16LE(_bigPos.y); + s.syncAsSint16LE(_overPos.x); + s.syncAsSint16LE(_overPos.y); + s.syncAsSint16LE(_oldCharPoint); +} + } // End of namespace Sherlock diff --git a/engines/sherlock/map.h b/engines/sherlock/map.h index a91e7ae968..564ae73691 100644 --- a/engines/sherlock/map.h +++ b/engines/sherlock/map.h @@ -26,6 +26,7 @@ #include "common/scummsys.h" #include "common/array.h" #include "common/rect.h" +#include "common/serializer.h" #include "common/str.h" #include "common/str-array.h" #include "sherlock/graphics.h" @@ -67,8 +68,6 @@ private: ImageFile *_shapes; ImageFile *_iconShapes; byte _sequences[MAX_HOLMES_SEQUENCE][MAX_FRAME]; - Common::Point _bigPos; - Common::Point _overPos; Common::Point _lDrawnPos; int _point; bool _placesShown; @@ -97,6 +96,9 @@ private: void highlightIcon(const Common::Point &pt); public: bool _active; + Common::Point _overPos; + Common::Point _bigPos; + int _charPoint, _oldCharPoint; public: Map(SherlockEngine *vm); @@ -106,6 +108,8 @@ public: void loadSequences(int count, const byte *seq); int show(); + + void synchronize(Common::Serializer &s); }; } // End of namespace Sherlock diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index 7341fc3b30..62a1a35f4a 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -861,8 +861,8 @@ int Object::checkNameForCodes(const Common::String &name, const char *const mess scene._goToScene = atoi(name.c_str() + 1); if (scene._goToScene < 97 && map[scene._goToScene].x) { - _vm->_over.x = map[scene._goToScene].x * 100 - 600; - _vm->_over.y = map[scene._goToScene].y * 100 + 900; + map._overPos.x = map[scene._goToScene].x * 100 - 600; + map._overPos.y = map[scene._goToScene].y * 100 + 900; } if ((p = strchr(name.c_str(), ',')) != nullptr) { diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp index 43e1fa046b..2eff1a0973 100644 --- a/engines/sherlock/people.cpp +++ b/engines/sherlock/people.cpp @@ -421,7 +421,6 @@ void People::setWalking() { */ void People::gotoStand(Sprite &sprite) { Map &map = *_vm->_map; - Scene &scene = *_vm->_scene; _walkTo.clear(); sprite._walkCount = 0; @@ -454,8 +453,8 @@ void People::gotoStand(Sprite &sprite) { if (map._active) { sprite._sequenceNumber = 0; - _data[AL]._position.x = (map[scene._charPoint].x - 6) * 100; - _data[AL]._position.y = (map[scene._charPoint].x + 10) * 100; + _player._position.x = (map[map._charPoint].x - 6) * 100; + _player._position.y = (map[map._charPoint].x + 10) * 100; } _oldWalkSequence = -1; diff --git a/engines/sherlock/saveload.cpp b/engines/sherlock/saveload.cpp index a694e21b28..86a4e8417a 100644 --- a/engines/sherlock/saveload.cpp +++ b/engines/sherlock/saveload.cpp @@ -368,6 +368,7 @@ Common::String SaveManager::generateSaveName(int slot) { void SaveManager::synchronize(Common::Serializer &s) { Inventory &inv = *_vm->_inventory; Journal &journal = *_vm->_journal; + Map &map = *_vm->_map; People &people = *_vm->_people; Scene &scene = *_vm->_scene; Screen &screen = *_vm->_screen; @@ -378,6 +379,7 @@ void SaveManager::synchronize(Common::Serializer &s) { inv.synchronize(s); journal.synchronize(s); people.synchronize(s); + map.synchronize(s); scene.synchronize(s); screen.synchronize(s); talk.synchronize(s); diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp index 65ca61b09f..89e042d382 100644 --- a/engines/sherlock/scalpel/scalpel.cpp +++ b/engines/sherlock/scalpel/scalpel.cpp @@ -576,23 +576,23 @@ void ScalpelEngine::startScene() { switch (_scene->_goToScene) { case 52: _scene->_goToScene = 27; // Go to the Lawyer's Office - _scene->_bigPos = Common::Point(0, 0); // Overland scroll position - _scene->_overPos = Common::Point(22900 - 600, 9400 + 900); // Overland position - _scene->_oldCharPoint = 27; + _map->_bigPos = Common::Point(0, 0); // Overland scroll position + _map->_overPos = Common::Point(22900 - 600, 9400 + 900); // Overland position + _map->_oldCharPoint = 27; break; case 53: _scene->_goToScene = 17; // Go to St. Pancras Station - _scene->_bigPos = Common::Point(0, 0); // Overland scroll position - _scene->_overPos = Common::Point(32500 - 600, 3000 + 900); // Overland position - _scene->_oldCharPoint = 17; + _map->_bigPos = Common::Point(0, 0); // Overland scroll position + _map->_overPos = Common::Point(32500 - 600, 3000 + 900); // Overland position + _map->_oldCharPoint = 17; break; default: _scene->_goToScene = 4; // Back to Baker st. - _scene->_bigPos = Common::Point(0, 0); // Overland scroll position - _scene->_overPos = Common::Point(14500 - 600, 8400 + 900); // Overland position - _scene->_oldCharPoint = 4; + _map->_bigPos = Common::Point(0, 0); // Overland scroll position + _map->_overPos = Common::Point(14500 - 600, 8400 + 900); // Overland position + _map->_oldCharPoint = 4; break; } diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 2d0f6fd751..7c31788a2f 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -89,8 +89,6 @@ Scene::Scene(SherlockEngine *vm): _vm(vm) { _currentScene = -1; _goToScene = -1; _changes = false; - _charPoint = 0; - _oldCharPoint = 39; _keyboardInput = 0; _walkedInScene = false; _ongoingCans = 0; @@ -438,10 +436,10 @@ bool Scene::loadScene(const Common::String &filename) { _walkedInScene = false; saves._justLoaded = false; - // Reset the position on the overland map - _vm->_oldCharPoint = _currentScene; - _vm->_over.x = map[_currentScene].x * 100 - 600; - _vm->_over.y = map[_currentScene].y * 100 + 900; + // Reset the previous map location and position on overhead map + map._oldCharPoint = _currentScene; + map._overPos.x = map[_currentScene].x * 100 - 600; + map._overPos.y = map[_currentScene].y * 100 + 900; events.clearEvents(); return flag; @@ -1043,7 +1041,7 @@ int Scene::startCAnim(int cAnimNum, int playRate) { _goToScene = gotoCode; if (_goToScene < 97 && map[_goToScene].x) { - _overPos = map[_goToScene]; + map._overPos = map[_goToScene]; } } @@ -1474,12 +1472,6 @@ void Scene::synchronize(Common::Serializer &s) { if (s.isSaving()) saveSceneStatus(); - s.syncAsSint16LE(_bigPos.x); - s.syncAsSint16LE(_bigPos.y); - s.syncAsSint16LE(_overPos.x); - s.syncAsSint16LE(_overPos.y); - s.syncAsSint16LE(_oldCharPoint); - if (s.isSaving()) s.syncAsSint16LE(_currentScene); else diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h index 892163a2f6..159f281bdf 100644 --- a/engines/sherlock/scene.h +++ b/engines/sherlock/scene.h @@ -107,9 +107,6 @@ public: bool _changes; bool _sceneStats[SCENES_COUNT][65]; bool _savedStats[SCENES_COUNT][9]; - Common::Point _bigPos; - Common::Point _overPos; - int _charPoint, _oldCharPoint; int _keyboardInput; int _oldKey, _help, _oldHelp; int _oldTemp, _temp; diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h index ce126c0dcc..921559183d 100644 --- a/engines/sherlock/sherlock.h +++ b/engines/sherlock/sherlock.h @@ -104,8 +104,6 @@ public: Common::String _titleOverride; bool _useEpilogue2; bool _loadingSavedGame; - int _oldCharPoint; // Old scene - Common::Point _over; // Old map position bool _slowChess; int _keyPadSpeed; int _loadGameSlot; diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index 0793552846..94779ae760 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -1355,9 +1355,9 @@ void Talk::doScript(const Common::String &script) { if (scene._goToScene != 100) { // Not going to the map overview - scene._oldCharPoint = scene._goToScene; - scene._overPos.x = map[scene._goToScene].x * 100 - 600; - scene._overPos.y = map[scene._goToScene].y * 100 + 900; + map._oldCharPoint = scene._goToScene; + map._overPos.x = map[scene._goToScene].x * 100 - 600; + map._overPos.y = map[scene._goToScene].y * 100 + 900; // Run a canimation? if (str[2] > 100) { -- cgit v1.2.3 From d51173cd114e3dacabf7bfa6053f484512ad3514 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 26 Apr 2015 20:09:59 -0500 Subject: SHERLOCK: Fix map not displaying second time it's called --- engines/sherlock/map.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sherlock/map.cpp b/engines/sherlock/map.cpp index 5865f34fa0..b0cf246e52 100644 --- a/engines/sherlock/map.cpp +++ b/engines/sherlock/map.cpp @@ -88,7 +88,6 @@ void Map::loadSequences(int count, const byte *seq) { Common::copy(seq, seq + MAX_FRAME, &_sequences[idx][0]); } - /** * Load data needed for the map */ @@ -151,6 +150,7 @@ int Map::show() { screen._backBuffer1.blitFrom(bigMap[3], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y)); _drawMap = true; + _charPoint = -1; _point = -1; people[AL]._position = _lDrawnPos = _overPos; -- cgit v1.2.3 From 8ec6e58f67e9dd6d0f7243d284497524280f7532 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 26 Apr 2015 20:28:49 -0500 Subject: SHERLOCK: Fix color for picking up messages --- engines/sherlock/objects.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index 62a1a35f4a..f662d00aed 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -994,7 +994,7 @@ int Object::pickUpObject(const char *const messages[]) { ++ui._infoFlag; ui.clearInfo(); - screen.print(Common::Point(0, INFO_LINE + 1), INFO_LINE, messages[message]); + screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, messages[message]); ui._menuCounter = 30; } else { // Pick it up -- cgit v1.2.3 From 3d483400698526a79fe31ac440bb2c410889f85f Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 26 Apr 2015 21:15:33 -0500 Subject: SHERLOCK: Fix using items from inventory dialog --- engines/sherlock/user_interface.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index ed3debe2fc..97f6cfd63a 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -766,7 +766,7 @@ void UserInterface::lookScreen(const Common::Point &pt) { Common::Point mousePos = events.mousePos(); int temp; Common::String tempStr; - int x, width, width1, width2 = 0; + int x, width; // Don't display anything for right button command if ((events._rightPressed || events._rightPressed) && !events._pressed) @@ -790,7 +790,7 @@ void UserInterface::lookScreen(const Common::Point &pt) { // If inventory is active and an item is selected for a Use or Give action if ((_menuMode == INV_MODE || _menuMode == USE_MODE || _menuMode == GIVE_MODE) && (inv._invMode == 2 || inv._invMode == 3)) { - width1 = screen.stringWidth(inv[_selector]._name); + int width1 = 0, width2 = 0; if (inv._invMode == 2) { // Using an object @@ -805,6 +805,7 @@ void UserInterface::lookScreen(const Common::Point &pt) { // If we're using an inventory object, add in the width // of the object name and the " on " if (_selector != -1) { + width1 = screen.stringWidth(inv[_selector]._name); x += width1; width2 = screen.stringWidth(" on "); x += width2; @@ -835,6 +836,7 @@ void UserInterface::lookScreen(const Common::Point &pt) { } else if (temp >= 0 && temp < 1000 && _selector != -1 && scene._bgShapes[temp]._aType == PERSON) { // Giving an object to a person + width1 = screen.stringWidth(inv[_selector]._name); x = width = screen.stringWidth("Give "); x += width1; width2 = screen.stringWidth(" to "); @@ -1235,13 +1237,12 @@ void UserInterface::doInvControl() { if (found != -1) // If a slot highlighted, set it's color colors[found] = COMMAND_HIGHLIGHTED; - screen.buttonPrint(Common::Point(INVENTORY_POINTS[0][2], CONTROLS_Y1), - colors[0], true, "Exit"); + screen.buttonPrint(Common::Point(INVENTORY_POINTS[0][2], CONTROLS_Y1), colors[0], true, "Exit"); if (found >= 0 && found <= 3) { screen.buttonPrint(Common::Point(INVENTORY_POINTS[1][2], CONTROLS_Y1), colors[1], true, "Look"); - screen.buttonPrint(Common::Point(INVENTORY_POINTS[2][2], CONTROLS_Y1), colors[1], true, "Use"); - screen.buttonPrint(Common::Point(INVENTORY_POINTS[3][2], CONTROLS_Y1), colors[1], true, "Give"); + screen.buttonPrint(Common::Point(INVENTORY_POINTS[2][2], CONTROLS_Y1), colors[2], true, "Use"); + screen.buttonPrint(Common::Point(INVENTORY_POINTS[3][2], CONTROLS_Y1), colors[3], true, "Give"); inv._invMode = (InvMode)found; _selector = -1; } -- cgit v1.2.3 From 3a8aa6956812d8e69c6b5e1021ba5c05e3fe0b0b Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 26 Apr 2015 23:31:29 -0500 Subject: SHERLOCK: Fixes for using flower on lab table --- engines/sherlock/scene.cpp | 4 ++++ engines/sherlock/talk.cpp | 3 ++- engines/sherlock/user_interface.cpp | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 7c31788a2f..7b885a2cb9 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -953,6 +953,8 @@ int Scene::startCAnim(int cAnimNum, int playRate) { cObj._imageFrame = &(*cObj._images)[0]; cObj._maxFrames = cObj._images->size(); + ++_ongoingCans; + int frames = 0; if (playRate < 0) { // Reverse direction @@ -1362,6 +1364,8 @@ void Scene::doBgAnim() { screen.slamArea(o._position.x, o._position.y, o._delta.x, o._delta.y); _canimShapes.remove_at(idx); + if (_ongoingCans > 0) + --_ongoingCans; } else if (o._type == ACTIVE_BG_SHAPE) { screen.flushImage(o._imageFrame, o._position, &o._oldPosition.x, &o._oldPosition.y, &o._oldSize.x, &o._oldSize.y); diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index 94779ae760..ea2cb16252 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -312,7 +312,8 @@ void Talk::talkTo(const Common::String &filename) { select = _talkIndex = idx; } - if (_scriptMoreFlag && _scriptSelect != 0) + // If there's a pending automatic selection to be made, then use it + if (_scriptMoreFlag && _scriptSelect != 100) select = _scriptSelect; if (select == -1) diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index 97f6cfd63a..e4d7255774 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -818,7 +818,7 @@ void UserInterface::lookScreen(const Common::Point &pt) { tempStr.deleteLastChar(); } - int xStart = (SHERLOCK_SCREEN_HEIGHT - x) / 2; + int xStart = (SHERLOCK_SCREEN_WIDTH - x) / 2; screen.print(Common::Point(xStart, INFO_LINE + 1), INFO_FOREGROUND, "Use "); -- cgit v1.2.3 From 80fba27cb372c052a912e23595fcd201fd688acf Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 27 Apr 2015 02:18:57 -0500 Subject: SHERLOCK: Fix analysing flower on lab table --- engines/sherlock/scene.cpp | 3 +++ engines/sherlock/talk.cpp | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 7b885a2cb9..f6fe8c8671 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -1014,6 +1014,9 @@ int Scene::startCAnim(int cAnimNum, int playRate) { while (--temp > 0) { cObj._frameNumber--; doBgAnim(); + + if (_vm->shouldQuit()) + return 0; } cObj._frameNumber += dir; diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index ea2cb16252..427be09cc3 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -1117,7 +1117,7 @@ void Talk::doScript(const Common::String &script) { // doing bg anims in the next call, so we need to know where to return to ++str; _scriptCurrentIndex = (str + 1) - script.c_str(); - scene.startCAnim(((byte)str[0] - 1) & 127, 1 + ((byte)str[0] & 128)); + scene.startCAnim(((byte)str[0] - 1) & 127, ((byte)str[0] & 128) ? -1 : 1); if (_talkToAbort) return; -- cgit v1.2.3 From a2e1f4cb76a6629f53a7f03c8b9bc2efa5f701e6 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 27 Apr 2015 02:29:34 -0500 Subject: SHERLOCK: Fix using items within the scene --- engines/sherlock/user_interface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index e4d7255774..b12094638c 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -1422,7 +1422,7 @@ void UserInterface::doInvControl() { checkUseAction(&scene._bgShapes[_find]._use[0], inv[_selector]._name, MUSE, _find, temp - 2); else // Now inv object has been highlighted - checkUseAction(&scene._bgShapes[_find]._use[0], "*SELF", MUSE, _find, temp - 2); + checkUseAction(&scene._bgShapes[_find]._use[0], "*SELF*", MUSE, _find, temp - 2); _selector = _oldSelector = -1; } -- cgit v1.2.3 From f7f405eadb355089b17bb7d146b0e06da04f27e2 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 27 Apr 2015 04:40:19 -0500 Subject: SHERLOCK: Further fixes for analysing flower on lab table --- engines/sherlock/talk.cpp | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index 427be09cc3..29bfff8674 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -134,7 +134,7 @@ Talk::Talk(SherlockEngine *vm): _vm(vm) { _talkStealth = 0; _talkToFlag = -1; _moreTalkDown = _moreTalkUp = false; - _scriptMoreFlag = false; + _scriptMoreFlag = 0; _scriptSaveIndex = -1; _scriptCurrentIndex = -1; } @@ -217,7 +217,7 @@ void Talk::talkTo(const Common::String &filename) { } } - while (!_scriptStack.empty()) + while (!_sequenceStack.empty()) pullSequence(); // Restore any pressed button @@ -578,6 +578,9 @@ void Talk::loadTalkFile(const Common::String &filename) { Resources &res = *_vm->_res; Sound &sound = *_vm->_sound; + // Save a copy of the talk filename + _scriptName = filename; + // Check for an existing person being talked to _talkTo = -1; for (int idx = 0; idx < MAX_PEOPLE; ++idx) { @@ -867,7 +870,7 @@ int Talk::talkLine(int lineNum, int stateNum, byte color, int lineY, bool slamIt * Clears the stack of pending object sequences associated with speakers in the scene */ void Talk::clearSequences() { - _scriptStack.clear(); + _sequenceStack.clear(); } /** @@ -1385,7 +1388,7 @@ void Talk::doScript(const Common::String &script) { case ADD_ITEM_TO_INVENTORY: ++str; for (int idx = 0; idx < str[0]; ++idx) - tempString += str[idx]; + tempString += str[idx + 1]; str += str[0]; inv.putNameInInventory(tempString); @@ -1420,16 +1423,24 @@ void Talk::doScript(const Common::String &script) { _scriptCurrentIndex = str - script.c_str(); // Save the current script position and new talk file - if (_scriptStack.size() < 10) { - ScriptStackEntry rec; - rec._name = _scriptName; - rec._currentIndex = _scriptCurrentIndex; - rec._select = _scriptSelect; + if (_scriptStack.size() < 9) { + ScriptStackEntry rec1; + rec1._name = _scriptName; + rec1._currentIndex = _scriptCurrentIndex; + rec1._select = _scriptSelect; + _scriptStack.push(rec1); + + // Push the new talk file onto the stack + ScriptStackEntry rec2; + rec2._name = tempString; + rec2._currentIndex = 0; + rec2._select = 100; + _scriptStack.push(rec2); } else { error("Script stack overflow"); } - _scriptMoreFlag = true; + _scriptMoreFlag = 1; endStr = true; wait = 0; break; @@ -1655,7 +1666,7 @@ void Talk::doScript(const Common::String &script) { } pullSequence(); - if (_speaker < 128) + if (_speaker >= 0 && _speaker < 128) people.clearTalking(); } } @@ -1749,7 +1760,7 @@ void Talk::popStack() { _scriptName = scriptEntry._name; _scriptSaveIndex = scriptEntry._currentIndex; _scriptSelect = scriptEntry._select; - _scriptMoreFlag = true; + _scriptMoreFlag = 1; } } -- cgit v1.2.3 From 7be410621e9fbc61ff4ec715044afaa79aa54717 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 27 Apr 2015 04:51:16 -0500 Subject: SHERLOCK: Fixes for giving flower to Wiggins --- engines/sherlock/talk.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index 29bfff8674..ed09ddde9c 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -365,8 +365,9 @@ void Talk::talkTo(const Common::String &filename) { // Check for a linked file if (!statement._linkFile.empty() && !_scriptMoreFlag) { + Common::String linkFilename = statement._linkFile; freeTalkVars(); - loadTalkFile(statement._linkFile); + loadTalkFile(linkFilename); // Scan for the first valid statement in the newly loaded file select = -1; @@ -427,7 +428,7 @@ void Talk::talkTo(const Common::String &filename) { } else { // Add the statement into the journal and talk history if (_talkTo != -1 && !_talkHistory[_converseNum][select]) - journal.record(_converseNum | 2048, select); + journal.record(_converseNum, select, true); _talkHistory[_converseNum][select] = true; } -- cgit v1.2.3 From 139bdec3ba3811e1dec00527caaba0d5c3fedcaa Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 27 Apr 2015 18:21:41 +0200 Subject: SCI: immediate restore now uses delayed restore instead of the old hackish method --- engines/sci/sci.cpp | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) (limited to 'engines') diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index d07ab435ff..668ad053cc 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -282,25 +282,13 @@ Common::Error SciEngine::run() { // Check whether loading a savestate was requested int directSaveSlotLoading = ConfMan.getInt("save_slot"); if (directSaveSlotLoading >= 0) { - // call GameObject::play (like normally) - initStackBaseWithSelector(SELECTOR(play)); - // We set this, so that the game automatically quit right after init - _gamestate->variables[VAR_GLOBAL][4] = TRUE_REG; + _gamestate->_delayedRestoreGame = true; + _gamestate->_delayedRestoreGameId = directSaveSlotLoading; // Jones only initializes its menus when restarting/restoring, thus set // the gameIsRestarting flag here before initializing. Fixes bug #6536. if (g_sci->getGameId() == GID_JONES) _gamestate->gameIsRestarting = GAMEISRESTARTING_RESTORE; - - _gamestate->_executionStackPosChanged = false; - run_vm(_gamestate); - - // As soon as we get control again, actually restore the game - reg_t restoreArgv[2] = { NULL_REG, make_reg(0, directSaveSlotLoading) }; // special call (argv[0] is NULL) - kRestoreGame(_gamestate, 2, restoreArgv); - - // this indirectly calls GameObject::init, which will setup menu, text font/color codes etc. - // without this games would be pretty badly broken } // Show any special warnings for buggy scripts with severe game bugs, -- cgit v1.2.3 From 02dd8cffcc9e649c1cfc5bbcb5d2517c63f6f321 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 27 Apr 2015 20:50:37 +0200 Subject: SCI: move SCI32 plane clear to gamestate_restore() --- engines/sci/engine/savegame.cpp | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 3d934410c3..8fca7eabca 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -134,13 +134,6 @@ void SegManager::saveLoadWithSerializer(Common::Serializer &s) { // Reset _scriptSegMap, to be restored below _scriptSegMap.clear(); - -#ifdef ENABLE_SCI32 - // Clear any planes/screen items currently showing so they - // don't show up after the load. - if (getSciVersion() >= SCI_VERSION_2) - g_sci->_gfxFrameout->clear(); -#endif } s.skip(4, VER(14), VER(18)); // OBSOLETE: Used to be _exportsAreWide @@ -926,14 +919,17 @@ void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { // reset ports is one of the first things we do, because that may free() some hunk memory // and we don't want to do that after we read in the saved game hunk memory - if (ser.isLoading()) { - // reset ports - if (g_sci->_gfxPorts) - g_sci->_gfxPorts->reset(); - // clear screen - if (g_sci->_gfxScreen) - g_sci->_gfxScreen->clear(); - } + if (g_sci->_gfxPorts) + g_sci->_gfxPorts->reset(); + // clear screen + if (g_sci->_gfxScreen) + g_sci->_gfxScreen->clear(); +#ifdef ENABLE_SCI32 + // Also clear any SCI32 planes/screen items currently showing so they + // don't show up after the load. + if (getSciVersion() >= SCI_VERSION_2) + g_sci->_gfxFrameout->clear(); +#endif s->reset(true); s->saveLoadWithSerializer(ser); // FIXME: Error handling? -- cgit v1.2.3 From 34a7ec7cdfe6b2eae699968afa28f2f75ee3126c Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 28 Apr 2015 21:35:20 -1000 Subject: SHERLOCK: Fix icon disappearing when moving to Covent Gradens on map Co-ordinates in Sherlock are frequently multiplied by 100. Thus, on the overland map, the values can go up to 64000, which overflows the signed 16-bit values allowed by the standard Common::Point class --- engines/sherlock/map.h | 6 +++--- engines/sherlock/objects.cpp | 2 +- engines/sherlock/objects.h | 23 +++++++++++++++++++++-- 3 files changed, 25 insertions(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/map.h b/engines/sherlock/map.h index 564ae73691..435ca8d5d7 100644 --- a/engines/sherlock/map.h +++ b/engines/sherlock/map.h @@ -68,7 +68,7 @@ private: ImageFile *_shapes; ImageFile *_iconShapes; byte _sequences[MAX_HOLMES_SEQUENCE][MAX_FRAME]; - Common::Point _lDrawnPos; + Point32 _lDrawnPos; int _point; bool _placesShown; int _cursorIndex; @@ -96,8 +96,8 @@ private: void highlightIcon(const Common::Point &pt); public: bool _active; - Common::Point _overPos; - Common::Point _bigPos; + Point32 _overPos; + Point32 _bigPos; int _charPoint, _oldCharPoint; public: Map(SherlockEngine *vm); diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index f662d00aed..d9cc38e55f 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -184,7 +184,7 @@ void Sprite::checkSprite() { Scene &scene = *_vm->_scene; Screen &screen = *_vm->_screen; Talk &talk = *_vm->_talk; - Common::Point pt; + Point32 pt; Common::Rect objBounds; Common::Point spritePt(_position.x / 100, _position.y / 100); diff --git a/engines/sherlock/objects.h b/engines/sherlock/objects.h index 80b0b9d9f3..e2b53ec541 100644 --- a/engines/sherlock/objects.h +++ b/engines/sherlock/objects.h @@ -79,6 +79,25 @@ enum { #define FLIP_CODE (64 + 128) #define SOUND_CODE (34 + 128) +class Point32 { +public: + int x; + int y; + + Point32() : x(0), y(0) {} + Point32(int x1, int y1) : x(x1), y(y1) {} + Point32(const Common::Point &pt) : x(pt.x), y(pt.y) {} + + bool operator==(const Point32 &p) const { return x == p.x && y == p.y; } + bool operator!=(const Point32 &p) const { return x != p.x || y != p.y; } + Point32 operator+(const Point32 &delta) const { return Point32(x + delta.x, y + delta.y); } + Point32 operator-(const Point32 &delta) const { return Point32(x - delta.x, y - delta.y); } + operator Common::Point() { return Common::Point(x, y); } + + void operator+=(const Point32 &delta) { x += delta.x; y += delta.y; } + void operator-=(const Point32 &delta) { x -= delta.x; y -= delta.y; } +}; + class Sprite { private: static SherlockEngine *_vm; @@ -95,8 +114,8 @@ public: int _allow; // Allowed menu commands - ObjectAllow int _frameNumber; // Frame number in rame sequence to draw int _sequenceNumber; // Sequence being used - Common::Point _position; // Current position - Common::Point _delta; // Momvement delta + Point32 _position; // Current position + Point32 _delta; // Momvement delta Common::Point _oldPosition; // Old position Common::Point _oldSize; // Image's old size Common::Point _goto; // Walk destination -- cgit v1.2.3 From 4b53d6a54b121e20d6bd4bfb6f1851b120817101 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 29 Apr 2015 18:02:08 -1000 Subject: SHERLOCK: Fixes for darts minigame --- engines/sherlock/events.cpp | 1 + engines/sherlock/scalpel/darts.cpp | 76 +++++++++++++++++++++--------------- engines/sherlock/scalpel/darts.h | 4 +- engines/sherlock/scalpel/scalpel.cpp | 2 +- 4 files changed, 49 insertions(+), 34 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/events.cpp b/engines/sherlock/events.cpp index f83219d7d2..f7cbdd301e 100644 --- a/engines/sherlock/events.cpp +++ b/engines/sherlock/events.cpp @@ -214,6 +214,7 @@ Common::KeyState Events::getKey() { */ void Events::clearEvents() { _pendingKeys.clear(); + _mouseButtons = 0; _pressed = _released = false; _rightPressed = _rightReleased = false; _oldButtons = _oldRightButton = false; diff --git a/engines/sherlock/scalpel/darts.cpp b/engines/sherlock/scalpel/darts.cpp index c3f2c478d7..0f3c36420e 100644 --- a/engines/sherlock/scalpel/darts.cpp +++ b/engines/sherlock/scalpel/darts.cpp @@ -60,7 +60,7 @@ Darts::Darts(ScalpelEngine *vm) : _vm(vm) { _roundNumber = 0; _playerDartMode = false; _roundScore = 0; - _oldDartButtons = 0; + _oldDartButtons = false; } /** @@ -75,7 +75,7 @@ void Darts::playDarts() { // Change the font int oldFont = screen.fontNumber(); - screen.setFont(4); + screen.setFont(2); loadDarts(); initDarts(); @@ -89,6 +89,9 @@ void Darts::playDarts() { showStatus(playerNumber); _roundScore = 0; + if (_vm->shouldQuit()) + return; + for (int idx = 0; idx < 3; ++idx) { // Throw a single dart if (_computerPlayer == 1) @@ -165,7 +168,7 @@ void Darts::playDarts() { done |= _vm->shouldQuit(); if (!done) { - screen._backBuffer2.blitFrom((*_dartImages)[1], Common::Point(0, 0)); + screen._backBuffer2.blitFrom((*_dartImages)[0], Common::Point(0, 0)); screen._backBuffer1.blitFrom(screen._backBuffer2); screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT); } @@ -185,7 +188,9 @@ void Darts::loadDarts() { Screen &screen = *_vm->_screen; _dartImages = new ImageFile("darts.vgs"); - screen._backBuffer1.blitFrom((*_dartImages)[1], Common::Point(0, 0)); + screen.setPalette(_dartImages->_palette); + + screen._backBuffer1.blitFrom((*_dartImages)[0], Common::Point(0, 0)); screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT); } @@ -223,7 +228,7 @@ void Darts::closeDarts() { } /** - * Show the player names + * Show the names of the people playing, Holmes and his opponent */ void Darts::showNames(int playerNum) { Screen &screen = *_vm->_screen; @@ -243,14 +248,14 @@ void Darts::showNames(int playerNum) { color = playerNum == 1 ? PLAYER_COLOR : DART_COL_FORE; if (playerNum != 0) - screen.print(Common::Point(STATUS_INFO_X + 50, STATUS_INFO_Y + 10), PLAYER_COLOR + 3, + screen.print(Common::Point(STATUS_INFO_X + 50, STATUS_INFO_Y), PLAYER_COLOR + 3, _opponent.c_str()); else - screen.print(Common::Point(STATUS_INFO_X + 50, STATUS_INFO_Y + 10), color, + screen.print(Common::Point(STATUS_INFO_X + 50, STATUS_INFO_Y), color, _opponent.c_str()); screen._backBuffer1.fillRect(Common::Rect(STATUS_INFO_X + 50, STATUS_INFO_Y + 10, - STATUS_INFO_Y + 81, STATUS_INFO_Y + 12), color); + STATUS_INFO_X + 81, STATUS_INFO_Y + 12), color); screen.slamArea(STATUS_INFO_X + 50, STATUS_INFO_Y + 10, 81, 12); // Make a copy of the back buffer to the secondary one @@ -264,8 +269,9 @@ void Darts::showStatus(int playerNum) { Screen &screen = *_vm->_screen; byte color; + // Copy scoring screen from secondary back buffer. This will erase any previously displayed status/score info screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(STATUS_INFO_X, STATUS_INFO_Y + 10), - Common::Rect(STATUS_INFO_X, STATUS_INFO_Y + 10, SHERLOCK_SCREEN_WIDTH, STATUS_INFO_Y + 38)); + Common::Rect(STATUS_INFO_X, STATUS_INFO_Y + 10, SHERLOCK_SCREEN_WIDTH, STATUS_INFO_Y + 48)); color = (playerNum == 0) ? PLAYER_COLOR : DART_COL_FORE; screen.print(Common::Point(STATUS_INFO_X + 6, STATUS_INFO_Y + 13), color, "%d", _dartScore1); @@ -306,6 +312,9 @@ int Darts::throwDart(int dartNum, int computer) { events.delay(10); } + if (_vm->shouldQuit()) + return 0; + screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(DART_INFO_X, DART_INFO_Y - 1), Common::Rect(DART_INFO_X, DART_INFO_Y - 1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); screen.slamRect(Common::Rect(DART_INFO_X, DART_INFO_Y - 1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); @@ -319,15 +328,16 @@ int Darts::throwDart(int dartNum, int computer) { // For human players, slight y adjustment if (computer == 0) - height = 2; + height += 2; - // Copy the bars to the secondary back buffer + // Copy the bars to the secondary back buffer so that they remain fixed at their selected values + // whilst the dart is being animated at being thrown at the board screen._backBuffer2.blitFrom(screen._backBuffer1, Common::Point(DARTBARHX - 1, DARTHORIZY - 1), Common::Rect(DARTBARHX - 1, DARTHORIZY - 1, DARTBARHX + DARTBARSIZE + 3, DARTHORIZY + 10)); screen._backBuffer2.blitFrom(screen._backBuffer1, Common::Point(DARTBARVX - 1, DARTHEIGHTY - 1), Common::Rect(DARTBARVX - 1, DARTHEIGHTY - 1, DARTBARVX + 11, DARTHEIGHTY + DARTBARSIZE + 3)); - // Convert to relative range from -49 to 150 + // Convert height and width to relative range of -50 to 50, where 0,0 is the exact centre of the board height -= 50; width -= 50; @@ -347,13 +357,13 @@ void Darts::drawDartThrow(const Common::Point &pt) { Common::Rect oldDrawBounds; int delta = 9; - for (int idx = 5; idx < 24; ++idx) { + for (int idx = 4; idx < 23; ++idx) { Graphics::Surface &frame = (*_dartImages)[idx]._frame; // Adjust draw position for animating dart - if (idx < 14) + if (idx < 13) pos.y -= delta--; - else if (idx == 14) + else if (idx == 13) delta = 1; else pos.y += delta++; @@ -363,20 +373,19 @@ void Darts::drawDartThrow(const Common::Point &pt) { screen._backBuffer1.transBlitFrom(frame, drawPos); screen.slamArea(drawPos.x, drawPos.y, frame.w, frame.h); - // Handle erasing old dart + // Handle erasing old dart strs if (!oldDrawBounds.isEmpty()) screen.slamRect(oldDrawBounds); oldDrawBounds = Common::Rect(drawPos.x, drawPos.y, drawPos.x + frame.w, drawPos.y + frame.h); - if (idx != 23) - screen._backBuffer1.blitFrom(screen._backBuffer2, drawPos, oldDrawBounds); + screen._backBuffer1.blitFrom(screen._backBuffer2, drawPos, oldDrawBounds); events.wait(2); } // Draw dart in final "stuck to board" form - screen._backBuffer1.transBlitFrom((*_dartImages)[23], Common::Point(oldDrawBounds.left, oldDrawBounds.top)); - screen._backBuffer2.transBlitFrom((*_dartImages)[23], Common::Point(oldDrawBounds.left, oldDrawBounds.top)); + screen._backBuffer1.transBlitFrom((*_dartImages)[22], Common::Point(oldDrawBounds.left, oldDrawBounds.top)); + screen._backBuffer2.transBlitFrom((*_dartImages)[22], Common::Point(oldDrawBounds.left, oldDrawBounds.top)); screen.slamRect(oldDrawBounds); } @@ -388,8 +397,8 @@ void Darts::erasePowerBars() { screen._backBuffer1.fillRect(Common::Rect(DARTBARHX, DARTHORIZY, DARTBARHX + DARTBARSIZE, DARTHORIZY + 10), 0); screen._backBuffer1.fillRect(Common::Rect(DARTBARVX, DARTHEIGHTY, DARTBARVX + 10, DARTHEIGHTY + DARTBARSIZE), 0); - screen._backBuffer1.transBlitFrom((*_dartImages)[3], Common::Point(DARTBARHX - 1, DARTHORIZY - 1)); - screen._backBuffer1.transBlitFrom((*_dartImages)[4], Common::Point(DARTBARVX - 1, DARTHEIGHTY - 1)); + screen._backBuffer1.transBlitFrom((*_dartImages)[2], Common::Point(DARTBARHX - 1, DARTHORIZY - 1)); + screen._backBuffer1.transBlitFrom((*_dartImages)[3], Common::Point(DARTBARVX - 1, DARTHEIGHTY - 1)); screen.slamArea(DARTBARHX - 1, DARTHORIZY - 1, DARTBARSIZE + 3, 11); screen.slamArea(DARTBARVX - 1, DARTHEIGHTY - 1, 11, DARTBARSIZE + 3); } @@ -427,11 +436,11 @@ int Darts::doPowerBar(const Common::Point &pt, byte color, int goToPower, bool i if (isVertical) { screen._backBuffer1.hLine(pt.x, pt.y + DARTBARSIZE - 1 - idx, pt.x + 8, color); - screen._backBuffer1.transBlitFrom((*_dartImages)[4], Common::Point(pt.x - 1, pt.y - 1)); + screen._backBuffer1.transBlitFrom((*_dartImages)[3], Common::Point(pt.x - 1, pt.y - 1)); screen.slamArea(pt.x, pt.y + DARTBARSIZE - 1 - idx, 8, 2); } else { screen._backBuffer1.vLine(pt.x + idx, pt.y, pt.y + 8, color); - screen._backBuffer1.transBlitFrom((*_dartImages)[3], Common::Point(pt.x - 1, pt.y - 1)); + screen._backBuffer1.transBlitFrom((*_dartImages)[2], Common::Point(pt.x - 1, pt.y - 1)); screen.slamArea(pt.x + idx, pt.y, 1, 8); } @@ -452,18 +461,23 @@ int Darts::doPowerBar(const Common::Point &pt, byte color, int goToPower, bool i /** * Returns true if a mouse button or key is pressed. */ -int Darts::dartHit() { +bool Darts::dartHit() { Events &events = *_vm->_events; - if (events.kbHit()) { - Common::KeyState keyState = events.getKey(); + // Process pending events + events.pollEventsAndWait(); + if (events.kbHit()) { + // Key was pressed, so discard it and return true events.clearKeyboard(); - return keyState.keycode; + return true; } + _oldDartButtons = events._pressed; events.setButtonState(); - return events._pressed && !_oldDartButtons ? 1 : 0; + + // Only return true if the mouse button is newly pressed + return (events._pressed && !_oldDartButtons) ? 1 : 0; } /** @@ -477,7 +491,7 @@ int Darts::dartScore(const Common::Point &pt) { return 0; // On board, so get the score from the pixel at that position - int score = *(const byte *)(*_dartImages)[2]._frame.getBasePtr(pos.x, pos.y); + int score = *(const byte *)(*_dartImages)[1]._frame.getBasePtr(pos.x, pos.y); return score; } @@ -545,7 +559,7 @@ Common::Point Darts::getComputerDartDest(int playerNum) { * Returns the center position for the area of the dartboard with a given number */ bool Darts::findNumberOnBoard(int aim, Common::Point &pt) { - ImageFrame &board = (*_dartImages)[2]; + ImageFrame &board = (*_dartImages)[1]; // Scan board image for the special "center" pixels bool done = false; diff --git a/engines/sherlock/scalpel/darts.h b/engines/sherlock/scalpel/darts.h index a6c8cdba6d..50be572067 100644 --- a/engines/sherlock/scalpel/darts.h +++ b/engines/sherlock/scalpel/darts.h @@ -42,7 +42,7 @@ private: Common::String _opponent; bool _playerDartMode; int _roundScore; - int _oldDartButtons; + bool _oldDartButtons; void loadDarts(); void initDarts(); @@ -57,7 +57,7 @@ private: void erasePowerBars(); int doPowerBar(const Common::Point &pt, byte color, int goToPower, bool isVertical); - int dartHit(); + bool dartHit(); int dartScore(const Common::Point &pt); Common::Point getComputerDartDest(int playerNum); diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp index 89e042d382..627a8b7b7f 100644 --- a/engines/sherlock/scalpel/scalpel.cpp +++ b/engines/sherlock/scalpel/scalpel.cpp @@ -614,7 +614,7 @@ void ScalpelEngine::startScene() { _events->setCursor(ARROW); if (_scene->_goToScene == 99) { - // Chess Board + // Darts Board minigame _darts->playDarts(); _mapResult = _scene->_goToScene = 19; // Go back to the bar } -- cgit v1.2.3 From 0ef0b4570a861d117c27b5f72af991506814820c Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 29 Apr 2015 18:11:35 -1000 Subject: SHERLOCK: Minor bugfix and cleanup for dartScore --- engines/sherlock/scalpel/darts.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/scalpel/darts.cpp b/engines/sherlock/scalpel/darts.cpp index 0f3c36420e..476a3071c5 100644 --- a/engines/sherlock/scalpel/darts.cpp +++ b/engines/sherlock/scalpel/darts.cpp @@ -485,13 +485,14 @@ bool Darts::dartHit() { */ int Darts::dartScore(const Common::Point &pt) { Common::Point pos(pt.x - 37, pt.y - 33); + Graphics::Surface &scoreImg = (*_dartImages)[1]._frame; - if (pos.x < 0 || pos.y < 0 || pos.x >= 147 || pt.y >= 132) + if (pos.x < 0 || pos.y < 0 || pos.x >= scoreImg.w || pos.y >= scoreImg.h) // Not on the board return 0; // On board, so get the score from the pixel at that position - int score = *(const byte *)(*_dartImages)[1]._frame.getBasePtr(pos.x, pos.y); + int score = *(const byte *)scoreImg.getBasePtr(pos.x, pos.y); return score; } -- cgit v1.2.3 From e3881ccbb90cb7e650ba1e7d47e6c7dfe5133fdd Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 29 Apr 2015 21:12:56 -1000 Subject: SHERLOCK: Fix display of place names on overhead map --- engines/sherlock/map.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sherlock/map.cpp b/engines/sherlock/map.cpp index b0cf246e52..a807d52f91 100644 --- a/engines/sherlock/map.cpp +++ b/engines/sherlock/map.cpp @@ -355,7 +355,8 @@ void Map::saveTopLine() { */ void Map::eraseTopLine() { Screen &screen = *_vm->_screen; - screen.blitFrom(_topLine, Common::Point(0, 0)); + screen._backBuffer1.blitFrom(_topLine, Common::Point(0, 0)); + screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, _topLine.h); } /** -- cgit v1.2.3 From ef4ec4cde3ec15d7370ef739e4fa6d863e7ccee5 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 29 Apr 2015 21:24:34 -1000 Subject: SHERLOCK: Fix moving crates in Tabacco Shop --- engines/sherlock/user_interface.cpp | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index b12094638c..b0b0d15b5c 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -2592,16 +2592,22 @@ void UserInterface::checkAction(ActionType &action, const char *const messages[] cAnimNum = 9; else cAnimNum = action._cAnimNum - 1; - CAnim &anim = scene._cAnim[cAnimNum]; - + if (action._cAnimNum != 99) { - if (action._cAnimSpeed & REVERSE_DIRECTION) { - pt = anim._teleportPos; - dir = anim._teleportDir; - } else { - pt = anim._goto; - dir = anim._gotoDir; + CAnim &anim = scene._cAnim[cAnimNum]; + + if (action._cAnimNum != 99) { + if (action._cAnimSpeed & REVERSE_DIRECTION) { + pt = anim._teleportPos; + dir = anim._teleportDir; + } else { + pt = anim._goto; + dir = anim._gotoDir; + } } + } else { + pt = Common::Point(-1, -1); + dir = -1; } if (action._cAnimSpeed) { -- cgit v1.2.3 From f34b9a59b52460cae64d526cf9d9eccba922e376 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 29 Apr 2015 21:38:06 -1000 Subject: SHERLOCK: Fix Sherlock gliding when walking vertically --- engines/sherlock/people.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp index 2eff1a0973..ed6e0607bd 100644 --- a/engines/sherlock/people.cpp +++ b/engines/sherlock/people.cpp @@ -386,7 +386,9 @@ void People::setWalking() { // If we're on the overhead map, set the sequence so we keep moving // in the same direction - _player._sequenceNumber = (oldDirection == -1) ? MAP_RIGHT : oldDirection; + if (map._active) { + _player._sequenceNumber = (oldDirection == -1) ? MAP_RIGHT : oldDirection; + } // Set the delta x _player._delta.x = (delta.x * 100) / (delta.y / speed.y); -- cgit v1.2.3 From aba28c4737d8534d160ed0ada17c6c109c0e7b4c Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 29 Apr 2015 21:41:49 -1000 Subject: SHERLOCK: Move _slowChess to Map _frameChangeFlag --- engines/sherlock/map.cpp | 1 + engines/sherlock/map.h | 1 + engines/sherlock/objects.cpp | 2 +- engines/sherlock/sherlock.cpp | 1 - engines/sherlock/sherlock.h | 1 - 5 files changed, 3 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/map.cpp b/engines/sherlock/map.cpp index a807d52f91..5ff27a9709 100644 --- a/engines/sherlock/map.cpp +++ b/engines/sherlock/map.cpp @@ -64,6 +64,7 @@ Map::Map(SherlockEngine *vm): _vm(vm), _topLine(SHERLOCK_SCREEN_WIDTH, 12) { _overPos = Common::Point(13000, 12600); _charPoint = 0; _oldCharPoint = 39; + _frameChangeFlag = false; for (int idx = 0; idx < MAX_HOLMES_SEQUENCE; ++idx) Common::fill(&_sequences[idx][0], &_sequences[idx][MAX_FRAME], 0); diff --git a/engines/sherlock/map.h b/engines/sherlock/map.h index 435ca8d5d7..e4c6655db9 100644 --- a/engines/sherlock/map.h +++ b/engines/sherlock/map.h @@ -99,6 +99,7 @@ public: Point32 _overPos; Point32 _bigPos; int _charPoint, _oldCharPoint; + bool _frameChangeFlag; public: Map(SherlockEngine *vm); diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index d9cc38e55f..04c7599b6d 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -126,7 +126,7 @@ void Sprite::adjustSprite() { _position.x = CLIP((int)_position.x, LEFT_LIMIT, RIGHT_LIMIT); } - if (!map._active || (_vm->_slowChess = !_vm->_slowChess)) + if (!map._active || (map._frameChangeFlag = !map._frameChangeFlag)) ++_frameNumber; if ((*_sequences)[_sequenceNumber][_frameNumber] == 0) { diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index 406b796fc9..a8d3d9a535 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -47,7 +47,6 @@ SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gam _ui = nullptr; _useEpilogue2 = false; _loadingSavedGame = false; - _slowChess = false; _keyPadSpeed = 0; _loadGameSlot = -1; _canLoadSave = false; diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h index 921559183d..3f0779421c 100644 --- a/engines/sherlock/sherlock.h +++ b/engines/sherlock/sherlock.h @@ -104,7 +104,6 @@ public: Common::String _titleOverride; bool _useEpilogue2; bool _loadingSavedGame; - bool _slowChess; int _keyPadSpeed; int _loadGameSlot; bool _canLoadSave; -- cgit v1.2.3 From 21d17357540d3a45522684467d2259dca7cf20db Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 29 Apr 2015 22:12:59 -1000 Subject: SHERLOCK: Fix script byte casting in journal loading --- engines/sherlock/journal.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/journal.cpp b/engines/sherlock/journal.cpp index 255662f71c..b9669d209e 100644 --- a/engines/sherlock/journal.cpp +++ b/engines/sherlock/journal.cpp @@ -240,7 +240,7 @@ int Journal::loadJournalFile(bool alreadyLoaded) { const char *replyP = statement._reply.c_str(); while (*replyP) { - byte c = *replyP++; + byte c = (byte)*replyP++; // Is it a control character? if (c < 128) { @@ -289,7 +289,7 @@ int Journal::loadJournalFile(bool alreadyLoaded) { const char *strP = replyP + 1; char v; do { - v = *strP++; + v = (byte)*strP++; } while (v && v < 128 && v != '.' && v != '!' && v != '?'); if (v == '?') @@ -334,9 +334,9 @@ int Journal::loadJournalFile(bool alreadyLoaded) { journalString += NAMES[c]; const char *strP = replyP; - char v; + byte v; do { - v = *strP++; + v = (byte)*strP++; } while (v && v < 128 && v != '.' && v != '!' && v != '?'); if (v == '?') @@ -356,7 +356,7 @@ int Journal::loadJournalFile(bool alreadyLoaded) { break; case 134: // Change sequence - replyP += (replyP[0] & 127) + replyP[2] + 2; + replyP += ((byte)replyP[0] & 127) + (byte)replyP[2] + 2; break; case 135: // Walk to co-ords @@ -380,7 +380,7 @@ int Journal::loadJournalFile(bool alreadyLoaded) { case 152: // Set object case 155: // Info line case 158: // Delete item from inventory - replyP += (*replyP & 127) + 1; + replyP += ((byte)*replyP & 127) + 1; break; case 149: // Goto scene -- cgit v1.2.3 From 6d32c570d0f4ac956059a450581d46ce0d75ad97 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 29 Apr 2015 22:56:07 -1000 Subject: SHERLOCK: Fix journal loading change sequence opcode --- engines/sherlock/journal.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sherlock/journal.cpp b/engines/sherlock/journal.cpp index b9669d209e..c30b4683d9 100644 --- a/engines/sherlock/journal.cpp +++ b/engines/sherlock/journal.cpp @@ -356,7 +356,7 @@ int Journal::loadJournalFile(bool alreadyLoaded) { break; case 134: // Change sequence - replyP += ((byte)replyP[0] & 127) + (byte)replyP[2] + 2; + replyP += ((byte)replyP[0] & 127) + (byte)replyP[1] + 2; break; case 135: // Walk to co-ords -- cgit v1.2.3 From 7ca3b75805eb404ad7f5ae01ba3000593e8eaf36 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 29 Apr 2015 23:17:51 -1000 Subject: SHERLOCK: Fix clicking in script zones starting the script --- engines/sherlock/objects.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'engines') diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index 04c7599b6d..f353844774 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -924,6 +924,8 @@ void Object::setFlagsAndToggles() { if (_use[useIdx]._cAnimSpeed) { if (_use[useIdx]._cAnimNum == 0) // 0 is really a 10 + scene.startCAnim(9, _use[useIdx]._cAnimSpeed); + else scene.startCAnim(_use[useIdx]._cAnimNum - 1, _use[useIdx]._cAnimSpeed); } -- cgit v1.2.3 From 56f43eff10a038a67954cd4ccc6990bb70fa6740 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 30 Apr 2015 10:24:18 -1000 Subject: SHERLOCK: Fix loading scenes with initially hidden objects --- engines/sherlock/scene.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'engines') diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index f6fe8c8671..1d00e9d23d 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -414,6 +414,9 @@ bool Scene::loadScene(const Common::String &filename) { if (_bgShapes[idx]._type != HIDDEN && (_bgShapes[idx]._flags & 0x40) && _bgShapes[idx]._type != INVALID) _bgShapes[idx].toggleHidden(); + if (_bgShapes[idx]._type == HIDE_SHAPE) + // Hiding isn't needed, since objects aren't drawn yet + _bgShapes[idx]._type = HIDDEN; } } -- cgit v1.2.3 From 00fd812028c6aaa9b2ec05963a66a23dabbd33ba Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 30 Apr 2015 11:23:31 -1000 Subject: SHERLOCK: Properly restrict scene drawing to scene area --- engines/sherlock/graphics.cpp | 8 ------- engines/sherlock/graphics.h | 2 -- engines/sherlock/map.cpp | 1 - engines/sherlock/scene.cpp | 53 ++++++++++++++++++++++--------------------- engines/sherlock/screen.cpp | 26 ++++++++++++++++++--- engines/sherlock/screen.h | 1 + 6 files changed, 51 insertions(+), 40 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/graphics.cpp b/engines/sherlock/graphics.cpp index 6e986c839b..6fd046e458 100644 --- a/engines/sherlock/graphics.cpp +++ b/engines/sherlock/graphics.cpp @@ -164,14 +164,6 @@ void Surface::fillRect(const Common::Rect &r, byte color) { addDirtyRect(r); } -/** - * Return a sub-area of the surface as a new surface object. The surfaces - * are shared in common, so changes in the sub-surface affects the original. - */ -Surface Surface::getSubArea(const Common::Rect &r) { - return Surface(*this, r); -} - /** * Clips the given source bounds so the passed destBounds will be entirely on-screen */ diff --git a/engines/sherlock/graphics.h b/engines/sherlock/graphics.h index 85f3ba8c40..80b692130c 100644 --- a/engines/sherlock/graphics.h +++ b/engines/sherlock/graphics.h @@ -55,8 +55,6 @@ public: void fillRect(int x1, int y1, int x2, int y2, byte color); void fillRect(const Common::Rect &r, byte color); - - Surface getSubArea(const Common::Rect &r); }; } // End of namespace Sherlock diff --git a/engines/sherlock/map.cpp b/engines/sherlock/map.cpp index 5ff27a9709..f572e3771a 100644 --- a/engines/sherlock/map.cpp +++ b/engines/sherlock/map.cpp @@ -442,7 +442,6 @@ void Map::updateMap(bool flushScreen) { */ void Map::walkTheStreets() { People &people = *_vm->_people; - Scene &scene = *_vm->_scene; bool reversePath = false; Common::Array tempPath; diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 1d00e9d23d..50e62b7ba5 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -716,10 +716,11 @@ int Scene::toggleObject(const Common::String &name) { void Scene::updateBackground() { People &people = *_vm->_people; Screen &screen = *_vm->_screen; - Surface surface = screen._backBuffer1.getSubArea( - Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT)); Sprite &player = people[AL]; + // Restrict drawing window + screen.setDisplayBounds(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT)); + // Update Holmes if he's turned on if (people._holmesOn) player.adjustSprite(); @@ -731,26 +732,26 @@ void Scene::updateBackground() { // Draw all active shapes which are behind the person for (uint idx = 0; idx < _bgShapes.size(); ++idx) { if (_bgShapes[idx]._type == ACTIVE_BG_SHAPE && _bgShapes[idx]._misc == BEHIND) - surface.transBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position, _bgShapes[idx]._flags & 2); + screen._backBuffer->transBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position, _bgShapes[idx]._flags & 2); } // Draw all canimations which are behind the person for (uint idx = 0; idx < _canimShapes.size(); ++idx) { if (_canimShapes[idx]._type == ACTIVE_BG_SHAPE && _canimShapes[idx]._misc == BEHIND) - surface.transBlitFrom(*_canimShapes[idx]._imageFrame, + screen._backBuffer->transBlitFrom(*_canimShapes[idx]._imageFrame, _canimShapes[idx]._position, _canimShapes[idx]._flags & 2); } // Draw all active shapes which are normal and behind the person for (uint idx = 0; idx < _bgShapes.size(); ++idx) { if (_bgShapes[idx]._type == ACTIVE_BG_SHAPE && _bgShapes[idx]._misc == NORMAL_BEHIND) - surface.transBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position, _bgShapes[idx]._flags & 2); + screen._backBuffer->transBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position, _bgShapes[idx]._flags & 2); } // Draw all canimations which are normal and behind the person for (uint idx = 0; idx < _canimShapes.size(); ++idx) { if (_canimShapes[idx]._type == ACTIVE_BG_SHAPE && _canimShapes[idx]._misc == NORMAL_BEHIND) - surface.transBlitFrom(*_canimShapes[idx]._imageFrame, _canimShapes[idx]._position, + screen._backBuffer->transBlitFrom(*_canimShapes[idx]._imageFrame, _canimShapes[idx]._position, _canimShapes[idx]._flags & 2); } @@ -760,7 +761,7 @@ void Scene::updateBackground() { player._sequenceNumber == WALK_UPLEFT || player._sequenceNumber == STOP_UPLEFT || player._sequenceNumber == WALK_DOWNRIGHT || player._sequenceNumber == STOP_DOWNRIGHT; - surface.transBlitFrom(*player._imageFrame, Common::Point(player._position.x / 100, + screen._backBuffer->transBlitFrom(*player._imageFrame, Common::Point(player._position.x / 100, player._position.y / 100 - player.frameHeight()), flipped); } @@ -768,14 +769,14 @@ void Scene::updateBackground() { for (uint idx = 0; idx < _bgShapes.size(); ++idx) { if ((_bgShapes[idx]._type == ACTIVE_BG_SHAPE || _bgShapes[idx]._type == STATIC_BG_SHAPE) && _bgShapes[idx]._misc == NORMAL_FORWARD) - surface.transBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position, _bgShapes[idx]._flags & 2); + screen._backBuffer->transBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position, _bgShapes[idx]._flags & 2); } // Draw all static and active canimations that are NORMAL and are in front of the player for (uint idx = 0; idx < _canimShapes.size(); ++idx) { if ((_canimShapes[idx]._type == ACTIVE_BG_SHAPE || _canimShapes[idx]._type == STATIC_BG_SHAPE) && _canimShapes[idx]._misc == NORMAL_FORWARD) - surface.transBlitFrom(*_canimShapes[idx]._imageFrame, _canimShapes[idx]._position, + screen._backBuffer->transBlitFrom(*_canimShapes[idx]._imageFrame, _canimShapes[idx]._position, _canimShapes[idx]._flags & 2); } @@ -787,14 +788,14 @@ void Scene::updateBackground() { if ((_bgShapes[idx]._type == ACTIVE_BG_SHAPE || _bgShapes[idx]._type == STATIC_BG_SHAPE) && _bgShapes[idx]._misc == FORWARD) - surface.transBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position, _bgShapes[idx]._flags & 2); + screen._backBuffer->transBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position, _bgShapes[idx]._flags & 2); } // Draw all static and active canimations that are forward for (uint idx = 0; idx < _canimShapes.size(); ++idx) { if ((_canimShapes[idx]._type == ACTIVE_BG_SHAPE || _canimShapes[idx]._type == STATIC_BG_SHAPE) && _canimShapes[idx]._misc == FORWARD) - surface.transBlitFrom(*_canimShapes[idx]._imageFrame, _canimShapes[idx]._position, + screen._backBuffer->transBlitFrom(*_canimShapes[idx]._imageFrame, _canimShapes[idx]._position, _canimShapes[idx]._flags & 2); } } @@ -1079,8 +1080,8 @@ void Scene::doBgAnim() { Sound &sound = *_vm->_sound; Talk &talk = *_vm->_talk; UserInterface &ui = *_vm->_ui; - Surface surface = screen._backBuffer1.getSubArea(Common::Rect(0, 0, - SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT)); + + screen.setDisplayBounds(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT)); int cursorId = events.getCursor(); Common::Point mousePos = events.mousePos(); @@ -1150,7 +1151,7 @@ void Scene::doBgAnim() { if (people[AL]._type == CHARACTER) screen.restoreBackground(bounds); else if (people[AL]._type == REMOVE) - screen._backBuffer1.blitFrom(screen._backBuffer2, pt, bounds); + screen._backBuffer->blitFrom(screen._backBuffer2, pt, bounds); for (uint idx = 0; idx < _bgShapes.size(); ++idx) { Object &o = _bgShapes[idx]; @@ -1169,7 +1170,7 @@ void Scene::doBgAnim() { Object &o = _bgShapes[idx]; if (o._type == NO_SHAPE && ((o._flags & 1) == 0)) { // Restore screen area - screen._backBuffer1.blitFrom(screen._backBuffer2, o._position, + screen._backBuffer->blitFrom(screen._backBuffer2, o._position, Common::Rect(o._position.x, o._position.y, o._position.x + o._noShapeSize.x, o._position.y + o._noShapeSize.y)); @@ -1218,14 +1219,14 @@ void Scene::doBgAnim() { for (uint idx = 0; idx < _bgShapes.size(); ++idx) { Object &o = _bgShapes[idx]; if (o._type == ACTIVE_BG_SHAPE && o._misc == BEHIND) - screen._backBuffer1.transBlitFrom(*o._imageFrame, o._position, o._flags & 2); + screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & 2); } // Draw all canimations which are behind the person for (uint idx = 0; idx < _canimShapes.size(); ++idx) { Object &o = _canimShapes[idx]; if (o._type == ACTIVE_BG_SHAPE && o._misc == BEHIND) { - screen._backBuffer1.transBlitFrom(*o._imageFrame, o._position, o._flags & 2); + screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & 2); } } @@ -1233,14 +1234,14 @@ void Scene::doBgAnim() { for (uint idx = 0; idx < _bgShapes.size(); ++idx) { Object &o = _bgShapes[idx]; if (o._type == ACTIVE_BG_SHAPE && o._misc == NORMAL_BEHIND) - screen._backBuffer1.transBlitFrom(*o._imageFrame, o._position, o._flags & 2); + screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & 2); } // Draw all canimations which are NORMAL and behind the person for (uint idx = 0; idx < _canimShapes.size(); ++idx) { Object &o = _canimShapes[idx]; if (o._type == ACTIVE_BG_SHAPE && o._misc == NORMAL_BEHIND) { - screen._backBuffer1.transBlitFrom(*o._imageFrame, o._position, o._flags & 2); + screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & 2); } } @@ -1253,7 +1254,7 @@ void Scene::doBgAnim() { bool flipped = people[AL]._sequenceNumber == WALK_LEFT || people[AL]._sequenceNumber == STOP_LEFT || people[AL]._sequenceNumber == WALK_UPLEFT || people[AL]._sequenceNumber == STOP_UPLEFT || people[AL]._sequenceNumber == WALK_DOWNRIGHT || people[AL]._sequenceNumber == STOP_DOWNRIGHT; - screen._backBuffer1.transBlitFrom(*people[AL]._imageFrame, + screen._backBuffer->transBlitFrom(*people[AL]._imageFrame, Common::Point(tempX, people[AL]._position.y / 100 - people[AL]._imageFrame->_frame.h), flipped); } @@ -1261,14 +1262,14 @@ void Scene::doBgAnim() { for (uint idx = 0; idx < _bgShapes.size(); ++idx) { Object &o = _bgShapes[idx]; if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == NORMAL_FORWARD) - screen._backBuffer1.transBlitFrom(*o._imageFrame, o._position, o._flags & 2); + screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & 2); } // Draw all static and active canimations that are NORMAL and are in front of the person for (uint idx = 0; idx < _canimShapes.size(); ++idx) { Object &o = _canimShapes[idx]; if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == NORMAL_BEHIND) { - screen._backBuffer1.transBlitFrom(*o._imageFrame, o._position, o._flags & 2); + screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & 2); } } @@ -1276,19 +1277,19 @@ void Scene::doBgAnim() { for (uint idx = 0; idx < _bgShapes.size(); ++idx) { Object &o = _bgShapes[idx]; if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == FORWARD) - screen._backBuffer1.transBlitFrom(*o._imageFrame, o._position, o._flags & 2); + screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & 2); } // Draw any active portrait if (people._portraitLoaded && people._portrait._type == ACTIVE_BG_SHAPE) - screen._backBuffer1.transBlitFrom(*people._portrait._imageFrame, + screen._backBuffer->transBlitFrom(*people._portrait._imageFrame, people._portrait._position, people._portrait._flags & 2); // Draw all static and active canimations that are in front of the person for (uint idx = 0; idx < _canimShapes.size(); ++idx) { Object &o = _canimShapes[idx]; if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == FORWARD) { - screen._backBuffer1.transBlitFrom(*o._imageFrame, o._position, o._flags & 2); + screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & 2); } } @@ -1296,7 +1297,7 @@ void Scene::doBgAnim() { for (uint idx = 0; idx < _bgShapes.size(); ++idx) { Object &o = _bgShapes[idx]; if (o._type == NO_SHAPE && (o._flags & 1) == 0) - screen._backBuffer1.transBlitFrom(*o._imageFrame, o._position, o._flags & 2); + screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & 2); } // Bring the newly built picture to the screen diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp index 3c9a10e4a1..66590c3ada 100644 --- a/engines/sherlock/screen.cpp +++ b/engines/sherlock/screen.cpp @@ -39,6 +39,10 @@ Screen::Screen(SherlockEngine *vm) : Surface(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCR Common::fill(&_cMap[0], &_cMap[PALETTE_SIZE], 0); Common::fill(&_sMap[0], &_sMap[PALETTE_SIZE], 0); setFont(1); + + // Set dummy surface used for restricted scene drawing + _sceneSurface.format = Graphics::PixelFormat::createFormatCLUT8(); + _sceneSurface.pitch = SHERLOCK_SCREEN_WIDTH; } Screen::~Screen() { @@ -469,15 +473,31 @@ void Screen::makePanel(const Common::Rect &r) { _backBuffer->hLine(r.left + 1, r.bottom - 2, r.right - 1, BUTTON_BOTTOM); } +/** + * Sets the active back buffer pointer to a restricted sub-area of the first back buffer + */ void Screen::setDisplayBounds(const Common::Rect &r) { - // TODO: See if needed + assert(r.left == 0 && r.top == 0); + _sceneSurface.setPixels(_backBuffer1.getPixels()); + _sceneSurface.w = r.width(); + _sceneSurface.h = r.height(); + + _backBuffer = &_sceneSurface; } + +/** + * Resets the active buffer pointer to point back to the full first back buffer + */ void Screen::resetDisplayBounds() { - setDisplayBounds(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); + _backBuffer = &_backBuffer1; } +/** + * Return the size of the current display window + */ Common::Rect Screen::getDisplayBounds() { - return Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT); + return (_backBuffer == &_sceneSurface) ? Common::Rect(0, 0, _sceneSurface.w, _sceneSurface.h) : + Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT); } /** diff --git a/engines/sherlock/screen.h b/engines/sherlock/screen.h index a8bdc53b5a..bbfba1c575 100644 --- a/engines/sherlock/screen.h +++ b/engines/sherlock/screen.h @@ -65,6 +65,7 @@ private: uint32 _transitionSeed; ImageFile *_font; int _fontHeight; + Surface _sceneSurface; void mergeDirtyRects(); -- cgit v1.2.3 From 50da2a2dd8ff6be1f634bd6d9f2b8d54bf059b9d Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 30 Apr 2015 12:21:11 -1000 Subject: SHERLOCK: Fix display of item descriptions --- engines/sherlock/scene.cpp | 4 ++++ engines/sherlock/talk.cpp | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 50e62b7ba5..487688f3a5 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -798,6 +798,8 @@ void Scene::updateBackground() { screen._backBuffer->transBlitFrom(*_canimShapes[idx]._imageFrame, _canimShapes[idx]._position, _canimShapes[idx]._flags & 2); } + + screen.resetDisplayBounds(); } Exit *Scene::checkForExit(const Common::Rect &r) { @@ -1082,6 +1084,7 @@ void Scene::doBgAnim() { UserInterface &ui = *_vm->_ui; screen.setDisplayBounds(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT)); + int cursorId = events.getCursor(); Common::Point mousePos = events.mousePos(); @@ -1384,6 +1387,7 @@ void Scene::doBgAnim() { events.wait(1); _doBgAnimDone = true; + screen.resetDisplayBounds(); // Check if the method was called for calling a portrait, and a talk was // interrupting it. This talk file would not have been executed at the time, diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index ed09ddde9c..b4dde2e6b0 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -455,7 +455,11 @@ void Talk::talkTo(const Common::String &filename) { events._pressed = events._released = events._oldButtons = 0; events.clearKeyboard(); - screen.setDisplayBounds(savedBounds); + if (savedBounds.bottom == SHERLOCK_SCREEN_HEIGHT) + screen.resetDisplayBounds(); + else + screen.setDisplayBounds(savedBounds); + _talkToAbort = abortFlag; // If a script was added to the script stack, restore state so that the -- cgit v1.2.3 From 329f6d744cf1aa002f013be0e5b0af62873598e2 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 30 Apr 2015 12:51:46 -1000 Subject: SHERLOCK: Fix DISPLAY_INFO_LINE talk opcode --- engines/sherlock/talk.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines') diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index b4dde2e6b0..7686df2944 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -1468,6 +1468,7 @@ void Talk::doScript(const Common::String &script) { str += str[0]; screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, tempString.c_str()); + ui._menuCounter = 30; break; case CLEAR_INFO_LINE: -- cgit v1.2.3 From d57cb94752c8c833c06bc1ef531f53587ab1df55 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 30 Apr 2015 15:01:15 -1000 Subject: SHERLOCK: Fix picking up pail at docks --- engines/sherlock/talk.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index 7686df2944..5a36303b21 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -1403,7 +1403,7 @@ void Talk::doScript(const Common::String &script) { ++str; for (int idx = 0; idx < (str[0] & 127); ++idx) tempString += str[idx + 1]; - str += str[0]; + str += str[0] & 127; // Set comparison state according to if we want to hide or unhide bool state = ((byte)str[0] >= 128); -- cgit v1.2.3 From c4008703d1c20afac1ce60a37fc85b9cd2bba0f8 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 30 Apr 2015 15:04:08 -1000 Subject: SHERLOCK: More descriptive comment for talkTo --- engines/sherlock/talk.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index 5a36303b21..de99fe0e88 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -149,9 +149,12 @@ void Talk::setSequences(const byte *talkSequences, const byte *stillSequences, i } /** - * Called when either an NPC initiates a conversation or for inventory item - * descriptions. It opens up a description window similar to how 'talk' does, - * but shows a 'reply' directly instead of waiting for a statement option. + * Called whenever a conversation or item script needs to be run. For standard conversations, + * it opens up a description window similar to how 'talk' does, but shows a 'reply' directly + * instead of waiting for a statement option. + * @remarks It seems that at some point, all item scripts were set up to use this as well. + * In their case, the conversation display is simply suppressed, and control is passed on to + * doScript to implement whatever action is required. */ void Talk::talkTo(const Common::String &filename) { Events &events = *_vm->_events; -- cgit v1.2.3 From 862d63c2a6c8b55bd472809508ba119ca41397dd Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 30 Apr 2015 15:20:48 -1000 Subject: SHERLOCK: Partial fix for Blackwell capture cutscene --- engines/sherlock/animation.cpp | 4 ++-- engines/sherlock/scalpel/scalpel.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/animation.cpp b/engines/sherlock/animation.cpp index 4674151ec7..810c0ecc34 100644 --- a/engines/sherlock/animation.cpp +++ b/engines/sherlock/animation.cpp @@ -90,7 +90,7 @@ bool Animation::playPrologue(const Common::String &filename, int minDelay, int f else if (_vm->_useEpilogue2) stream = _vm->_res->load(vdxName, "epilog2.lib"); else - stream = _vm->_res->load(vdxName, "epilogoue.lib"); + stream = _vm->_res->load(vdxName, "epilogue.lib"); // Load initial image Common::String vdaName = baseName + ".vda"; @@ -127,7 +127,7 @@ bool Animation::playPrologue(const Common::String &filename, int minDelay, int f } // Draw the sprite - screen.transBlitFrom(images[imageFrame]._frame, pt); + screen.transBlitFrom(images[imageFrame], pt); } else { // No sprite to show for this animation frame if (fade == 255) { diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp index 627a8b7b7f..488a4de772 100644 --- a/engines/sherlock/scalpel/scalpel.cpp +++ b/engines/sherlock/scalpel/scalpel.cpp @@ -505,7 +505,7 @@ void ScalpelEngine::startScene() { _res->addToCache("final2.vda", "epilogue.lib"); _res->addToCache("final2.vdx", "epilogue.lib"); _animation->playPrologue("final1", 1, 3, true, 4); - _animation->playPrologue("final22", 1, 0, false, 4); + _animation->playPrologue("final2", 1, 0, false, 4); break; case 52: -- cgit v1.2.3 From e25fbfa8e4a2e6ca2ef187630479151107f8ff19 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 30 Apr 2015 15:38:13 -1000 Subject: SHERLOCK: Fix initial entry conversation with coroner at morgue --- engines/sherlock/objects.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index f353844774..3dc50e61b1 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -200,12 +200,12 @@ void Sprite::checkSprite() { if (obj._type == NO_SHAPE) { objBounds = Common::Rect(obj._position.x, obj._position.y, - obj._position.x + obj._noShapeSize.x, obj._position.y + obj._noShapeSize.y); + obj._position.x + obj._noShapeSize.x + 1, obj._position.y + obj._noShapeSize.y + 1); } else { int xp = obj._position.x + obj._imageFrame->_offset.x; int yp = obj._position.y + obj._imageFrame->_offset.y; objBounds = Common::Rect(xp, yp, - xp + obj._imageFrame->_frame.w, yp + obj._imageFrame->_frame.h); + xp + obj._imageFrame->_frame.w + 1, yp + obj._imageFrame->_frame.h + 1); } if (objBounds.contains(pt)) { -- cgit v1.2.3 From 8e4ccdbd2c5ea543d648ef46300837c3c43ee705 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 30 Apr 2015 15:46:30 -1000 Subject: SHERLOCK: Fix trying to move items that can't be --- engines/sherlock/user_interface.cpp | 59 +++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 29 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index b0b0d15b5c..30d79aa1c9 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -2585,32 +2585,42 @@ void UserInterface::checkAction(ActionType &action, const char *const messages[] if (objNum >= 1000) // Ignore actions done on characters return; - Object &obj = scene._bgShapes[objNum]; - if (action._cAnimNum == 0) - // Really a 10 - cAnimNum = 9; - else - cAnimNum = action._cAnimNum - 1; - - if (action._cAnimNum != 99) { - CAnim &anim = scene._cAnim[cAnimNum]; + if (!action._cAnimSpeed) { + // Invalid action, to print error message + _infoFlag = true; + clearInfo(); + screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, messages[action._cAnimNum]); + _infoFlag = true; + + // Set how long to show the message + _menuCounter = 30; + } else { + Object &obj = scene._bgShapes[objNum]; + if (action._cAnimNum == 0) + // Really a 10 + cAnimNum = 9; + else + cAnimNum = action._cAnimNum - 1; + if (action._cAnimNum != 99) { - if (action._cAnimSpeed & REVERSE_DIRECTION) { - pt = anim._teleportPos; - dir = anim._teleportDir; - } else { - pt = anim._goto; - dir = anim._gotoDir; + CAnim &anim = scene._cAnim[cAnimNum]; + + if (action._cAnimNum != 99) { + if (action._cAnimSpeed & REVERSE_DIRECTION) { + pt = anim._teleportPos; + dir = anim._teleportDir; + } else { + pt = anim._goto; + dir = anim._gotoDir; + } } + } else { + pt = Common::Point(-1, -1); + dir = -1; } - } else { - pt = Common::Point(-1, -1); - dir = -1; - } - if (action._cAnimSpeed) { // Has a value, so do action // Show wait cursor whilst walking to object and doing action events.setCursor(WAIT); @@ -2686,15 +2696,6 @@ void UserInterface::checkAction(ActionType &action, const char *const messages[] _menuCounter = 30; } } - } else { - // Invalid action, to print error message - _infoFlag = true; - clearInfo(); - screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, messages[action._cAnimNum]); - _infoFlag = true; - - // Set how long to show the message - _menuCounter = 30; } // Reset cursor back to arrow -- cgit v1.2.3 From e37cf9c4d0d33c0b0ba9eb7bb842b49205baac4b Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 30 Apr 2015 16:00:08 -1000 Subject: SHERLOCK: Fix talking to Gregson at morgue --- engines/sherlock/talk.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index de99fe0e88..3320beb30c 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -524,7 +524,7 @@ void Talk::talk(int objNum) { obj._lookFacing); events.setCursor(ARROW); - if (_talkToAbort) + if (!_talkToAbort) talkTo(obj._name); } else { // Holmes will be speaking first -- cgit v1.2.3 From e332565119b7efe85ba91fd601f994997912481f Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 30 Apr 2015 16:59:36 -1000 Subject: SHERLOCK: Fix Gregson disappearing at Morgue --- engines/sherlock/talk.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index 3320beb30c..eb5c763106 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -1406,10 +1406,10 @@ void Talk::doScript(const Common::String &script) { ++str; for (int idx = 0; idx < (str[0] & 127); ++idx) tempString += str[idx + 1]; - str += str[0] & 127; // Set comparison state according to if we want to hide or unhide bool state = ((byte)str[0] >= 128); + str += str[0] & 127; for (uint idx = 0; idx < scene._bgShapes.size(); ++idx) { Object &obj = scene._bgShapes[idx]; -- cgit v1.2.3 From 2bc1d2badc79ba2d49ebc225731d602938f7d49e Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 30 Apr 2015 17:55:58 -1000 Subject: SHERLOCK: Fix showing corpse portraits in Morgue --- engines/sherlock/scene.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 487688f3a5..3cc84936b0 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -1271,7 +1271,7 @@ void Scene::doBgAnim() { // Draw all static and active canimations that are NORMAL and are in front of the person for (uint idx = 0; idx < _canimShapes.size(); ++idx) { Object &o = _canimShapes[idx]; - if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == NORMAL_BEHIND) { + if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == NORMAL_FORWARD) { screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & 2); } } -- cgit v1.2.3 From d811e4a9ff48426b01f199db8f24b00e679592d5 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 30 Apr 2015 20:44:19 -1000 Subject: SHERLOCK: Fix color of talk response text --- engines/sherlock/talk.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index eb5c763106..2c59876e84 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -1573,9 +1573,9 @@ void Talk::doScript(const Common::String &script) { // If the speaker indicates a description file, print it in yellow if (_speaker != -1) { if (ui._windowOpen) { - screen.print(Common::Point(16, yp), INV_FOREGROUND, lineStr.c_str()); + screen.print(Common::Point(16, yp), COMMAND_FOREGROUND, lineStr.c_str()); } else { - screen.gPrint(Common::Point(16, yp - 1), INV_FOREGROUND, lineStr.c_str()); + screen.gPrint(Common::Point(16, yp - 1), COMMAND_FOREGROUND, lineStr.c_str()); openTalkWindow = true; } } else { -- cgit v1.2.3 From 821040deaaa4dabf160795e96cb223ba192a87d3 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 30 Apr 2015 21:00:48 -1000 Subject: SHERLOCK: Fix blank talk windows sometimes remaining open --- engines/sherlock/talk.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index 2c59876e84..ed8092c03e 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -1159,7 +1159,7 @@ void Talk::doScript(const Common::String &script) { case PAUSE: // Pause - charCount = *++str; + charCount = (byte)*++str; wait = pauseFlag = true; break; @@ -1598,8 +1598,8 @@ void Talk::doScript(const Common::String &script) { ++line; // Certain different conditions require a wait - if ((line == 4 && str[0] != SFX_COMMAND && str[0] != PAUSE && _speaker != -1) || - (line == 5 && str[0] != PAUSE && _speaker != -1) || + if ((line == 4 && (byte)str[0] != SFX_COMMAND && (byte)str[0] != PAUSE && _speaker != -1) || + (line == 5 && (byte)str[0] != PAUSE && _speaker != -1) || endStr) { wait = 1; } -- cgit v1.2.3 From 56f8d54e5133ecdc6e6cceda27202bf6ba7e26fd Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 30 Apr 2015 21:07:33 -1000 Subject: SHERLOCK: Use script opcode constants in journal loading --- engines/sherlock/journal.cpp | 40 ++++++++++++++++++++-------------------- engines/sherlock/talk.cpp | 41 +---------------------------------------- engines/sherlock/talk.h | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 60 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/journal.cpp b/engines/sherlock/journal.cpp index c30b4683d9..be76756bdd 100644 --- a/engines/sherlock/journal.cpp +++ b/engines/sherlock/journal.cpp @@ -346,48 +346,48 @@ int Journal::loadJournalFile(bool alreadyLoaded) { } else { // Control code, so move past it and any parameters switch (c) { - case 129: // Run canim - case 130: // Assign side - case 131: // Pause with control - case 136: // Pause without control - case 157: // Walk to canimation + case RUN_CANIMATION: + case ASSIGN_PORTRAIT_LOCATION: + case PAUSE: + case PAUSE_WITHOUT_CONTROL: + case WALK_TO_CANIMATION: // These commands have a single parameter ++replyP; break; - case 134: // Change sequence + case ADJUST_OBJ_SEQUENCE: replyP += ((byte)replyP[0] & 127) + (byte)replyP[1] + 2; break; - case 135: // Walk to co-ords - case 154: // Move mouse + case WALK_TO_COORDS: + case MOVE_MOUSE: replyP += 4; break; - case 139: // Set flag - case 143: // If statement + case SET_FLAG: + case IF_STATEMENT: replyP += 2; break; - case 140: // Play voice file - case 150: // Play prologue - case 153: // Call talk file + case SFX_COMMAND: + case PLAY_PROLOGUE: + case CALL_TALK_FILE: replyP += 8; break; - case 141: // Toggle object - case 151: // Put item in inventory - case 152: // Set object - case 155: // Info line - case 158: // Delete item from inventory + case TOGGLE_OBJECT: + case ADD_ITEM_TO_INVENTORY: + case SET_OBJECT: + case DISPLAY_INFO_LINE: + case REMOVE_ITEM_FROM_INVENTORY: replyP += ((byte)*replyP & 127) + 1; break; - case 149: // Goto scene + case GOTO_SCENE: replyP += 5; break; - case 161: // End of line + case CARRIAGE_RETURN: journalString += "\n"; break; diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index ed8092c03e..fb16995d2b 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -26,45 +26,6 @@ namespace Sherlock { -enum { - SWITCH_SPEAKER = 128, - RUN_CANIMATION = 129, - ASSIGN_PORTRAIT_LOCATION = 130, - PAUSE = 131, - REMOVE_PORTRAIT = 132, - CLEAR_WINDOW = 133, - ADJUST_OBJ_SEQUENCE = 134, - WALK_TO_COORDS = 135, - PAUSE_WITHOUT_CONTROL = 136, - BANISH_WINDOW = 137, - SUMMON_WINDOW = 138, - SET_FLAG = 139, - SFX_COMMAND = 140, - TOGGLE_OBJECT = 141, - STEALTH_MODE_ACTIVE = 142, - IF_STATEMENT = 143, - ELSE_STATEMENT = 144, - END_IF_STATEMENT = 145, - STEALTH_MODE_DEACTIVATE = 146, - TURN_HOLMES_OFF = 147, - TURN_HOLMES_ON = 148, - GOTO_SCENE = 149, - PLAY_PROLOGUE = 150, - ADD_ITEM_TO_INVENTORY = 151, - SET_OBJECT = 152, - CALL_TALK_FILE = 153, - MOVE_MOUSE = 154, - DISPLAY_INFO_LINE = 155, - CLEAR_INFO_LINE = 156, - WALK_TO_CANIMATION = 157, - REMOVE_ITEM_FROM_INVENTORY = 158, - ENABLE_END_KEY = 159, - DISABLE_END_KEY = 160, - COMMAND_161 = 161 -}; - -/*----------------------------------------------------------------*/ - /** * Load the data for a single statement within a talk file */ @@ -1621,7 +1582,7 @@ void Talk::doScript(const Common::String &script) { } // Open window if it wasn't already open, and text has already been printed - if ((openTalkWindow && wait) || (openTalkWindow && (byte)str[0] >= 128 && (byte)str[0] != COMMAND_161)) { + if ((openTalkWindow && wait) || (openTalkWindow && (byte)str[0] >= 128 && (byte)str[0] != CARRIAGE_RETURN)) { if (!ui._windowStyle) { screen.slamRect(Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); } else { diff --git a/engines/sherlock/talk.h b/engines/sherlock/talk.h index 620a986454..d545d31351 100644 --- a/engines/sherlock/talk.h +++ b/engines/sherlock/talk.h @@ -35,6 +35,43 @@ namespace Sherlock { #define MAX_TALK_SEQUENCES 11 #define MAX_TALK_FILES 500 +enum { + SWITCH_SPEAKER = 128, + RUN_CANIMATION = 129, + ASSIGN_PORTRAIT_LOCATION = 130, + PAUSE = 131, + REMOVE_PORTRAIT = 132, + CLEAR_WINDOW = 133, + ADJUST_OBJ_SEQUENCE = 134, + WALK_TO_COORDS = 135, + PAUSE_WITHOUT_CONTROL = 136, + BANISH_WINDOW = 137, + SUMMON_WINDOW = 138, + SET_FLAG = 139, + SFX_COMMAND = 140, + TOGGLE_OBJECT = 141, + STEALTH_MODE_ACTIVE = 142, + IF_STATEMENT = 143, + ELSE_STATEMENT = 144, + END_IF_STATEMENT = 145, + STEALTH_MODE_DEACTIVATE = 146, + TURN_HOLMES_OFF = 147, + TURN_HOLMES_ON = 148, + GOTO_SCENE = 149, + PLAY_PROLOGUE = 150, + ADD_ITEM_TO_INVENTORY = 151, + SET_OBJECT = 152, + CALL_TALK_FILE = 153, + MOVE_MOUSE = 154, + DISPLAY_INFO_LINE = 155, + CLEAR_INFO_LINE = 156, + WALK_TO_CANIMATION = 157, + REMOVE_ITEM_FROM_INVENTORY = 158, + ENABLE_END_KEY = 159, + DISABLE_END_KEY = 160, + CARRIAGE_RETURN = 161 +}; + struct SequenceEntry { int _objNum; Common::Array _sequences; -- cgit v1.2.3 From 9117083e0ab8f329a93bcae647d9da78ec212738 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 30 Apr 2015 21:21:59 -1000 Subject: SHERLOCK: Fix crash in Equestrian shop --- engines/sherlock/user_interface.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index 30d79aa1c9..e7e7981966 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -414,8 +414,8 @@ void UserInterface::handleInput() { _infoFlag = true; clearInfo(); - if (_help != -1 && (scene._bgShapes[_bgFound]._description[0] != 32 && - scene._bgShapes[_bgFound]._description[0])) + if (_help != -1 && !scene._bgShapes[_bgFound]._description.empty() + && scene._bgShapes[_bgFound]._description[0] != ' ') screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, scene._bgShapes[_bgFound]._description.c_str()); -- cgit v1.2.3 From d32eb9a70f5c44b16d1262f5d0d62a09d8e893d3 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 30 Apr 2015 21:31:18 -1000 Subject: SHERLOCK: Simplify all the castings of char to byte in Talk and Journal --- engines/sherlock/journal.cpp | 18 +++++----- engines/sherlock/talk.cpp | 78 +++++++++++++++++++++++--------------------- 2 files changed, 49 insertions(+), 47 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/journal.cpp b/engines/sherlock/journal.cpp index be76756bdd..67cff15218 100644 --- a/engines/sherlock/journal.cpp +++ b/engines/sherlock/journal.cpp @@ -237,10 +237,10 @@ int Journal::loadJournalFile(bool alreadyLoaded) { bool ctrlSpace = false; bool commentFlag = false; bool commentJustPrinted = false; - const char *replyP = statement._reply.c_str(); + const byte *replyP = (const byte *)statement._reply.c_str(); while (*replyP) { - byte c = (byte)*replyP++; + byte c = *replyP++; // Is it a control character? if (c < 128) { @@ -286,10 +286,10 @@ int Journal::loadJournalFile(bool alreadyLoaded) { else journalString += NAMES[talk._talkTo]; - const char *strP = replyP + 1; + const byte *strP = replyP + 1; char v; do { - v = (byte)*strP++; + v = *strP++; } while (v && v < 128 && v != '.' && v != '!' && v != '?'); if (v == '?') @@ -306,7 +306,7 @@ int Journal::loadJournalFile(bool alreadyLoaded) { journalString += c; do { journalString += *replyP++; - } while (*replyP && (byte)*replyP < 128 && *replyP != '{' && *replyP != '}'); + } while (*replyP && *replyP < 128 && *replyP != '{' && *replyP != '}'); commentJustPrinted = false; } @@ -333,10 +333,10 @@ int Journal::loadJournalFile(bool alreadyLoaded) { else journalString += NAMES[c]; - const char *strP = replyP; + const byte *strP = replyP; byte v; do { - v = (byte)*strP++; + v = *strP++; } while (v && v < 128 && v != '.' && v != '!' && v != '?'); if (v == '?') @@ -356,7 +356,7 @@ int Journal::loadJournalFile(bool alreadyLoaded) { break; case ADJUST_OBJ_SEQUENCE: - replyP += ((byte)replyP[0] & 127) + (byte)replyP[1] + 2; + replyP += (replyP[0] & 127) + replyP[1] + 2; break; case WALK_TO_COORDS: @@ -380,7 +380,7 @@ int Journal::loadJournalFile(bool alreadyLoaded) { case SET_OBJECT: case DISPLAY_INFO_LINE: case REMOVE_ITEM_FROM_INVENTORY: - replyP += ((byte)*replyP & 127) + 1; + replyP += (*replyP & 127) + 1; break; case GOTO_SCENE: diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index fb16995d2b..9e75f4ecc8 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -993,14 +993,16 @@ void Talk::doScript(const Common::String &script) { _saveSeqNum = 0; - const char *str = script.c_str(); + const byte *scriptStart = (const byte *)script.c_str(); + const byte *str = scriptStart; + if (_scriptMoreFlag) { _scriptMoreFlag = 0; - str = script.c_str() + _scriptSaveIndex; + str = scriptStart + _scriptSaveIndex; } // Check if the script begins with a Stealh Mode Active command - if ((byte)str[0] == STEALTH_MODE_ACTIVE || _talkStealth) { + if (str[0] == STEALTH_MODE_ACTIVE || _talkStealth) { _talkStealth = 2; _speaker |= 128; } else { @@ -1008,7 +1010,7 @@ void Talk::doScript(const Common::String &script) { ui.clearWindow(); // Need to switch speakers? - if ((byte)str[0] == SWITCH_SPEAKER) { + if (str[0] == SWITCH_SPEAKER) { _speaker = str[1] - 1; str += 2; pullSequence(); @@ -1019,7 +1021,7 @@ void Talk::doScript(const Common::String &script) { } // Assign portrait location? - if ((byte)str[0] == ASSIGN_PORTRAIT_LOCATION) { + if (str[0] == ASSIGN_PORTRAIT_LOCATION) { switch (str[1] & 15) { case 1: people._portraitSide = 20; @@ -1041,7 +1043,7 @@ void Talk::doScript(const Common::String &script) { } // Remove portrait? - if ((byte)str[0] == REMOVE_PORTRAIT) { + if (str[0] == REMOVE_PORTRAIT) { _speaker = 255; } else { // Nope, so set the first speaker @@ -1053,7 +1055,7 @@ void Talk::doScript(const Common::String &script) { Common::String tempString; wait = 0; - byte c = (byte)str[0]; + byte c = str[0]; if (!c) { endStr = true; } else if (c == '{') { @@ -1066,7 +1068,7 @@ void Talk::doScript(const Common::String &script) { case SWITCH_SPEAKER: // Save the current point in the script, since it might be intterupted by // doing bg anims in the next call, so we need to know where to return to - _scriptCurrentIndex = str - script.c_str(); + _scriptCurrentIndex = str - scriptStart; if (!(_speaker & 128)) people.clearTalking(); @@ -1088,13 +1090,13 @@ void Talk::doScript(const Common::String &script) { // Save the current point in the script, since it might be intterupted by // doing bg anims in the next call, so we need to know where to return to ++str; - _scriptCurrentIndex = (str + 1) - script.c_str(); - scene.startCAnim(((byte)str[0] - 1) & 127, ((byte)str[0] & 128) ? -1 : 1); + _scriptCurrentIndex = (str + 1) - scriptStart; + scene.startCAnim((str[0] - 1) & 127, (str[0] & 128) ? -1 : 1); if (_talkToAbort) return; // Check if next character is changing side or changing portrait - if (charCount && ((byte)str[1] == SWITCH_SPEAKER || (byte)str[1] == ASSIGN_PORTRAIT_LOCATION)) + if (charCount && (str[1] == SWITCH_SPEAKER || str[1] == ASSIGN_PORTRAIT_LOCATION)) wait = 1; break; @@ -1120,14 +1122,14 @@ void Talk::doScript(const Common::String &script) { case PAUSE: // Pause - charCount = (byte)*++str; + charCount = *++str; wait = pauseFlag = true; break; case REMOVE_PORTRAIT: // Save the current point in the script, since it might be intterupted by // doing bg anims in the next call, so we need to know where to return to - _scriptCurrentIndex = str - script.c_str(); + _scriptCurrentIndex = str - scriptStart; if (_speaker >= 0 && _speaker < 128) people.clearTalking(); @@ -1186,10 +1188,10 @@ void Talk::doScript(const Common::String &script) { // Save the current point in the script, since it might be intterupted by // doing bg anims in the next call, so we need to know where to return to ++str; - _scriptCurrentIndex = str - script.c_str(); + _scriptCurrentIndex = str - scriptStart; - people.walkToCoords(Common::Point((((byte)str[0] - 1) * 256 + (byte)str[1] - 1) * 100, - (byte)str[2] * 100), str[3] - 1); + people.walkToCoords(Common::Point(((str[0] - 1) * 256 + str[1] - 1) * 100, + str[2] * 100), str[3] - 1); if (_talkToAbort) return; @@ -1200,7 +1202,7 @@ void Talk::doScript(const Common::String &script) { // Save the current point in the script, since it might be intterupted by // doing bg anims in the next call, so we need to know where to return to ++str; - _scriptCurrentIndex = str - script.c_str(); + _scriptCurrentIndex = str - scriptStart; for (int idx = 0; idx < (str[0] - 1); ++idx) { scene.doBgAnim(); @@ -1216,7 +1218,7 @@ void Talk::doScript(const Common::String &script) { case BANISH_WINDOW: // Save the current point in the script, since it might be intterupted by // doing bg anims in the next call, so we need to know where to return to - _scriptCurrentIndex = str - script.c_str(); + _scriptCurrentIndex = str - scriptStart; if (!(_speaker & 128)) people.clearTalking(); @@ -1246,7 +1248,7 @@ void Talk::doScript(const Common::String &script) { case SET_FLAG: { ++str; - int flag1 = ((byte)str[0] - 1) * 256 + (byte)str[1] - 1 - (str[1] == 1 ? 1 : 0); + int flag1 = (str[0] - 1) * 256 + str[1] - 1 - (str[1] == 1 ? 1 : 0); int flag = (flag1 & 0x3fff) * (flag1 >= 0x4000 ? -1 : 1); _vm->setFlags(flag); ++str; @@ -1284,7 +1286,7 @@ void Talk::doScript(const Common::String &script) { case IF_STATEMENT: { ++str; - int flag = ((byte)str[0] - 1) * 256 + (byte)str[1] - 1 - (str[1] == 1 ? 1 : 0); + int flag = (str[0] - 1) * 256 + str[1] - 1 - (str[1] == 1 ? 1 : 0); ++str; wait = 0; @@ -1334,14 +1336,14 @@ void Talk::doScript(const Common::String &script) { // Run a canimation? if (str[2] > 100) { - people._hSavedFacing = (byte)str[2]; + people._hSavedFacing = str[2]; people._hSavedPos = Common::Point(160, 100); } } str += 6; _scriptMoreFlag = (scene._goToScene == 100) ? 2 : 1; - _scriptSaveIndex = str - script.c_str(); + _scriptSaveIndex = str - scriptStart; endStr = true; wait = 0; break; @@ -1369,7 +1371,7 @@ void Talk::doScript(const Common::String &script) { tempString += str[idx + 1]; // Set comparison state according to if we want to hide or unhide - bool state = ((byte)str[0] >= 128); + bool state = (str[0] >= 128); str += str[0] & 127; for (uint idx = 0; idx < scene._bgShapes.size(); ++idx) { @@ -1389,7 +1391,7 @@ void Talk::doScript(const Common::String &script) { tempString += str[idx]; str += 8; - _scriptCurrentIndex = str - script.c_str(); + _scriptCurrentIndex = str - scriptStart; // Save the current script position and new talk file if (_scriptStack.size() < 9) { @@ -1418,8 +1420,8 @@ void Talk::doScript(const Common::String &script) { // Save the current point in the script, since it might be intterupted by // doing bg anims in the next call, so we need to know where to return to ++str; - _scriptCurrentIndex = str - script.c_str(); - events.moveMouse(Common::Point(((byte)str[0] - 1) * 256 + (byte)str[1] - 1, str[2])); + _scriptCurrentIndex = str - scriptStart; + events.moveMouse(Common::Point((str[0] - 1) * 256 + str[1] - 1, str[2])); if (_talkToAbort) return; str += 3; @@ -1446,7 +1448,7 @@ void Talk::doScript(const Common::String &script) { // Save the current point in the script, since it might be intterupted by // doing bg anims in the next call, so we need to know where to return to - _scriptCurrentIndex = (str + 1) - script.c_str(); + _scriptCurrentIndex = (str + 1) - scriptStart; people.walkToCoords(anim._goto, anim._gotoDir); if (_talkToAbort) @@ -1509,10 +1511,10 @@ void Talk::doScript(const Common::String &script) { width += screen.charWidth(str[idx]); ++idx; ++charCount; - } while (width < 298 && str[idx] && str[idx] != '{' && (byte)str[idx] < 128); + } while (width < 298 && str[idx] && str[idx] != '{' && str[idx] < 128); if (str[idx] || width >= 298) { - if ((byte)str[idx] < 128 && str[idx] != '{') { + if (str[idx] < 128 && str[idx] != '{') { --idx; --charCount; } @@ -1529,7 +1531,7 @@ void Talk::doScript(const Common::String &script) { } // Print the line - Common::String lineStr(str, str + idx); + Common::String lineStr((const char *)str, (const char *)str + idx); // If the speaker indicates a description file, print it in yellow if (_speaker != -1) { @@ -1552,20 +1554,20 @@ void Talk::doScript(const Common::String &script) { str += idx; // If line wrap occurred, then move to after the separating space between the words - if ((byte)str[0] < 128 && str[0] != '{') + if (str[0] < 128 && str[0] != '{') ++str; yp += 9; ++line; // Certain different conditions require a wait - if ((line == 4 && (byte)str[0] != SFX_COMMAND && (byte)str[0] != PAUSE && _speaker != -1) || - (line == 5 && (byte)str[0] != PAUSE && _speaker != -1) || + if ((line == 4 && str[0] != SFX_COMMAND && str[0] != PAUSE && _speaker != -1) || + (line == 5 && str[0] != PAUSE && _speaker != -1) || endStr) { wait = 1; } - switch ((byte)str[0]) { + switch (str[0]) { case SWITCH_SPEAKER: case ASSIGN_PORTRAIT_LOCATION: case BANISH_WINDOW: @@ -1582,7 +1584,7 @@ void Talk::doScript(const Common::String &script) { } // Open window if it wasn't already open, and text has already been printed - if ((openTalkWindow && wait) || (openTalkWindow && (byte)str[0] >= 128 && (byte)str[0] != CARRIAGE_RETURN)) { + if ((openTalkWindow && wait) || (openTalkWindow && str[0] >= 128 && str[0] != CARRIAGE_RETURN)) { if (!ui._windowStyle) { screen.slamRect(Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); } else { @@ -1596,7 +1598,7 @@ void Talk::doScript(const Common::String &script) { if (wait) { // Save the current point in the script, since it might be intterupted by // doing bg anims in the next call, so we need to know where to return to - _scriptCurrentIndex = str - script.c_str(); + _scriptCurrentIndex = str - scriptStart; // Handling pausing if (!pauseFlag && charCount < 160) @@ -1608,12 +1610,12 @@ void Talk::doScript(const Common::String &script) { // If a key was pressed to finish the window, see if further voice files should be skipped if (wait >= 0 && wait < 254) { - if ((byte)str[0] == SFX_COMMAND) + if (str[0] == SFX_COMMAND) str += 9; } // Clear the window unless the wait was due to a PAUSE command - if (!pauseFlag && wait != -1 && (byte)str[0] != SFX_COMMAND) { + if (!pauseFlag && wait != -1 && str[0] != SFX_COMMAND) { if (!_talkStealth) ui.clearWindow(); yp = CONTROLS_Y + 12; -- cgit v1.2.3 From 9d99f1ebe726785beb0b3053b3cdc60a0fd64894 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 30 Apr 2015 21:46:12 -1000 Subject: SHERLOCK: Fix looking at items with multiple pages of description --- engines/sherlock/talk.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index 9e75f4ecc8..da72125f72 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -1562,7 +1562,7 @@ void Talk::doScript(const Common::String &script) { // Certain different conditions require a wait if ((line == 4 && str[0] != SFX_COMMAND && str[0] != PAUSE && _speaker != -1) || - (line == 5 && str[0] != PAUSE && _speaker != -1) || + (line == 5 && str[0] != PAUSE && _speaker == -1) || endStr) { wait = 1; } -- cgit v1.2.3 From 24a36d610685b2024e864138224cc61e09f4ae16 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 30 Apr 2015 22:11:29 -1000 Subject: SHERLOCK: Fix crash loading scene 42, which didn't have any canimations --- engines/sherlock/scene.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 3cc84936b0..ec7831820a 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -295,16 +295,19 @@ bool Scene::loadScene(const Common::String &filename) { } // Load in cAnim list - Common::SeekableReadStream *canimStream = _lzwMode ? - decompressLZ(*rrmStream, 65 * bgHeader._numcAnimations) : - rrmStream->readStream(65 * bgHeader._numcAnimations); + _cAnim.clear(); + if (bgHeader._numcAnimations) { + Common::SeekableReadStream *canimStream = _lzwMode ? + decompressLZ(*rrmStream, 65 * bgHeader._numcAnimations) : + rrmStream->readStream(65 * bgHeader._numcAnimations); - _cAnim.resize(bgHeader._numcAnimations); - for (uint idx = 0; idx < _cAnim.size(); ++idx) - _cAnim[idx].synchronize(*canimStream); + _cAnim.resize(bgHeader._numcAnimations); + for (uint idx = 0; idx < _cAnim.size(); ++idx) + _cAnim[idx].synchronize(*canimStream); + + delete canimStream; + } - delete canimStream; - // Read in the room bounding areas int size = rrmStream->readUint16LE(); Common::SeekableReadStream *boundsStream = !_lzwMode ? rrmStream : -- cgit v1.2.3 From ac642fdfb3689612f6efb263cc89419c55f019fa Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 30 Apr 2015 23:16:03 -1000 Subject: SHERLOCK: Implement custom mirror logic for scene 12 --- engines/sherlock/scalpel/scalpel.cpp | 85 ++++++++++++++++++++++++++++++++++-- 1 file changed, 82 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp index 488a4de772..69bafa8d67 100644 --- a/engines/sherlock/scalpel/scalpel.cpp +++ b/engines/sherlock/scalpel/scalpel.cpp @@ -626,21 +626,100 @@ void ScalpelEngine::startScene() { * Takes care of clearing the mirror in scene 12, in case anything drew over it */ void ScalpelEngine::eraseMirror12() { - // TODO + Common::Point pt((*_people)[AL]._position.x / 100, (*_people)[AL]._position.y / 100); + + // If player is in range of the mirror, then restore background from the secondary back buffer + if (Common::Rect(70, 100, 200, 200).contains(pt)) { + _screen->_backBuffer1.blitFrom(_screen->_backBuffer2, Common::Point(137, 18), + Common::Rect(137, 18, 184, 74)); + } } /** * Takes care of drawing Holme's reflection onto the mirror in scene 12 */ void ScalpelEngine::doMirror12() { - // TODO + People &people = *_people; + Common::Point pt((*_people)[AL]._position.x / 100, (*_people)[AL]._position.y / 100); + int frameNum = (*people[AL]._sequences)[people[AL]._sequenceNumber][people[AL]._frameNumber] + + (*people[AL]._sequences)[people[AL]._sequenceNumber][0] - 2; + + switch ((*_people)[AL]._sequenceNumber) { + case WALK_DOWN: + frameNum -= 7; + break; + case WALK_UP: + frameNum += 7; + break; + case WALK_DOWNRIGHT: + frameNum += 7; + break; + case WALK_UPRIGHT: + frameNum -= 7; + break; + case WALK_DOWNLEFT: + frameNum += 7; + break; + case WALK_UPLEFT: + frameNum -= 7; + break; + case STOP_DOWN: + frameNum -= 10; + break; + case STOP_UP: + frameNum += 11; + break; + case STOP_DOWNRIGHT: + frameNum -= 15; + break; + case STOP_DOWNLEFT: + frameNum -= 15; + break; + case STOP_UPRIGHT: + case STOP_UPLEFT: + frameNum += 15; + if (frameNum == 55) + frameNum = 54; + break; + default: + break; + } + + if (Common::Rect(80, 100, 145, 138).contains(pt)) { + // Get the frame of Sherlock to draw + ImageFrame &imageFrame = (*people[AL]._images)[frameNum]; + + // Draw the mirror image of Holmes + bool flipped = people[AL]._sequenceNumber == WALK_LEFT || people[AL]._sequenceNumber == STOP_LEFT + || people[AL]._sequenceNumber == WALK_UPRIGHT || people[AL]._sequenceNumber == STOP_UPRIGHT + || people[AL]._sequenceNumber == WALK_DOWNLEFT || people[AL]._sequenceNumber == STOP_DOWNLEFT; + _screen->transBlitFrom(imageFrame, pt + Common::Point(38, imageFrame._frame.h - 25), flipped); + + // Redraw the mirror borders to prevent the drawn image of Holmes from appearing outside of the mirror + _screen->_backBuffer1.blitFrom(_screen->_backBuffer2, Common::Point(114, 18), + Common::Rect(114, 18, 137, 114)); + _screen->_backBuffer1.blitFrom(_screen->_backBuffer2, Common::Point(137, 70), + Common::Rect(137, 70, 142, 114)); + _screen->_backBuffer1.blitFrom(_screen->_backBuffer2, Common::Point(142, 71), + Common::Rect(142, 71, 159, 114)); + _screen->_backBuffer1.blitFrom(_screen->_backBuffer2, Common::Point(159, 72), + Common::Rect(159, 72, 170, 116)); + _screen->_backBuffer1.blitFrom(_screen->_backBuffer2, Common::Point(170, 73), + Common::Rect(170, 73, 184, 114)); + _screen->_backBuffer1.blitFrom(_screen->_backBuffer2, Common::Point(184, 18), + Common::Rect(184, 18, 212, 114)); + } } /** * This clears the mirror in scene 12 in case anything messed draw over it */ void ScalpelEngine::flushMirror12() { - // TODO + Common::Point pt((*_people)[AL]._position.x / 100, (*_people)[AL]._position.y / 100); + + // If player is in range of the mirror, then draw the entire mirror area to the screen + if (Common::Rect(70, 100, 200, 200).contains(pt)) + _screen->slamArea(137, 18, 47, 56); } } // End of namespace Scalpel -- cgit v1.2.3 From ffd65cfd36841f6e117d800043d1cf695951f8a9 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 1 May 2015 09:57:19 -1000 Subject: SHERLOCK: Fix animation for retrieving pocket watch --- engines/sherlock/objects.cpp | 2 ++ engines/sherlock/scene.cpp | 8 +++++++- 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index 3dc50e61b1..3cec0d800a 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -719,6 +719,8 @@ bool Object::checkEndOfSequence() { // Free the images delete _images; + _images = nullptr; + _imageFrame = nullptr; } } else { _type = INVALID; diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index ec7831820a..a9763a7fc5 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -1050,6 +1050,12 @@ int Scene::startCAnim(int cAnimNum, int playRate) { // Set canim to REMOVE type and free memory cObj.checkObject(); + for (uint idx = 0; idx < _canimShapes.size(); ++idx) { + if (&_canimShapes[idx] == &cObj) { + _canimShapes.remove_at(idx); + break; + } + } if (gotoCode > 0 && !talk._talkToAbort) { _goToScene = gotoCode; @@ -1376,7 +1382,7 @@ void Scene::doBgAnim() { if (_goToScene == -1) screen.slamArea(o._position.x, o._position.y, o._delta.x, o._delta.y); - _canimShapes.remove_at(idx); + _canimShapes[idx]._type = INVALID; if (_ongoingCans > 0) --_ongoingCans; } else if (o._type == ACTIVE_BG_SHAPE) { -- cgit v1.2.3 From b8372695ebc3b266f9fbe074dbbdd8e3015ce547 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 1 May 2015 10:08:14 -1000 Subject: SHERLOCK: Refactored out _ongoingCans field --- engines/sherlock/scene.cpp | 8 +------- engines/sherlock/scene.h | 1 - engines/sherlock/talk.cpp | 2 +- 3 files changed, 2 insertions(+), 9 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index a9763a7fc5..55cdde2f56 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -91,7 +91,6 @@ Scene::Scene(SherlockEngine *vm): _vm(vm) { _changes = false; _keyboardInput = 0; _walkedInScene = false; - _ongoingCans = 0; _version = 0; _lzwMode = false; _invGraphicItems = 0; @@ -201,7 +200,6 @@ bool Scene::loadScene(const Common::String &filename) { bool flag; _walkedInScene = false; - _ongoingCans = 0; // Reset the list of walkable areas _zones.clear(); @@ -962,8 +960,6 @@ int Scene::startCAnim(int cAnimNum, int playRate) { cObj._imageFrame = &(*cObj._images)[0]; cObj._maxFrames = cObj._images->size(); - ++_ongoingCans; - int frames = 0; if (playRate < 0) { // Reverse direction @@ -1317,7 +1313,7 @@ void Scene::doBgAnim() { _animating = 0; screen.slamRect(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT)); } else { - if (people[AL]._type != INVALID && ((_goToScene == -1 || _ongoingCans == 0))) { + if (people[AL]._type != INVALID && ((_goToScene == -1 || _canimShapes.size() == 0))) { if (people[AL]._type == REMOVE) { screen.slamRect(Common::Rect( people[AL]._oldPosition.x, people[AL]._oldPosition.y, @@ -1383,8 +1379,6 @@ void Scene::doBgAnim() { screen.slamArea(o._position.x, o._position.y, o._delta.x, o._delta.y); _canimShapes[idx]._type = INVALID; - if (_ongoingCans > 0) - --_ongoingCans; } else if (o._type == ACTIVE_BG_SHAPE) { screen.flushImage(o._imageFrame, o._position, &o._oldPosition.x, &o._oldPosition.y, &o._oldSize.x, &o._oldSize.y); diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h index 159f281bdf..4fb7ac228a 100644 --- a/engines/sherlock/scene.h +++ b/engines/sherlock/scene.h @@ -111,7 +111,6 @@ public: int _oldKey, _help, _oldHelp; int _oldTemp, _temp; bool _walkedInScene; - int _ongoingCans; int _version; bool _lzwMode; int _invGraphicItems; diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index da72125f72..a848e11392 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -134,7 +134,7 @@ void Talk::talkTo(const Common::String &filename) { // If there any canimations currently running, or a portrait is being cleared, // save the filename for later executing when the canimation is done - if (scene._ongoingCans || people._clearingThePortrait) { + if (scene._canimShapes.size() > 0 || people._clearingThePortrait) { // Make sure we're not in the middle of a script if (!_scriptMoreFlag) { _scriptName = filename; -- cgit v1.2.3 From 3f5c159068fdee253883e300cae524282db5b167 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 1 May 2015 10:24:53 -1000 Subject: SHERLOCK: Fix opening pocketwatch --- engines/sherlock/scene.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 55cdde2f56..cd913f8515 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -527,7 +527,7 @@ void Scene::checkSceneFlags(bool flag) { } } - // Check inventory + // Check inventory for items to remove based on flag changes for (int idx = 0; idx < _vm->_inventory->_holdings; ++idx) { InventoryItem &ii = (*_vm->_inventory)[idx]; if (ii._requiredFlag && !_vm->readFlags(ii._requiredFlag)) { @@ -536,10 +536,10 @@ void Scene::checkSceneFlags(bool flag) { _vm->_inventory->insert_at(_vm->_inventory->_holdings, tempItem); _vm->_inventory->remove_at(idx); _vm->_inventory->_holdings--; - break; } } + // Check inactive inventory items for ones to reactivate based on flag changes for (uint idx = _vm->_inventory->_holdings; idx < _vm->_inventory->size(); ++idx) { InventoryItem &ii = (*_vm->_inventory)[idx]; if (ii._requiredFlag && _vm->readFlags(ii._requiredFlag)) { @@ -548,7 +548,6 @@ void Scene::checkSceneFlags(bool flag) { _vm->_inventory->remove_at(idx); _vm->_inventory->insert_at(_vm->_inventory->_holdings, tempItem); _vm->_inventory->_holdings++; - break; } } } -- cgit v1.2.3 From edec4abfe5cace1b5a0761adc33bf8e526561f27 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 1 May 2015 11:48:41 -1000 Subject: SHERLOCK: Fix mirror display in scene 12 --- engines/sherlock/scalpel/scalpel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp index 69bafa8d67..d36f761239 100644 --- a/engines/sherlock/scalpel/scalpel.cpp +++ b/engines/sherlock/scalpel/scalpel.cpp @@ -693,7 +693,7 @@ void ScalpelEngine::doMirror12() { bool flipped = people[AL]._sequenceNumber == WALK_LEFT || people[AL]._sequenceNumber == STOP_LEFT || people[AL]._sequenceNumber == WALK_UPRIGHT || people[AL]._sequenceNumber == STOP_UPRIGHT || people[AL]._sequenceNumber == WALK_DOWNLEFT || people[AL]._sequenceNumber == STOP_DOWNLEFT; - _screen->transBlitFrom(imageFrame, pt + Common::Point(38, imageFrame._frame.h - 25), flipped); + _screen->_backBuffer1.transBlitFrom(imageFrame, pt + Common::Point(38, -imageFrame._frame.h - 25), flipped); // Redraw the mirror borders to prevent the drawn image of Holmes from appearing outside of the mirror _screen->_backBuffer1.blitFrom(_screen->_backBuffer2, Common::Point(114, 18), -- cgit v1.2.3 From da75ee1f8b233cbfacfd1f18a1be970edbc0b0f2 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 1 May 2015 12:29:40 -1000 Subject: SHERLOCK: Fix display of animation cutscenes --- engines/sherlock/animation.cpp | 9 +++++---- engines/sherlock/resources.cpp | 20 ++++++++++++++------ engines/sherlock/resources.h | 4 ++-- 3 files changed, 21 insertions(+), 12 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/animation.cpp b/engines/sherlock/animation.cpp index 810c0ecc34..e70bc84ff8 100644 --- a/engines/sherlock/animation.cpp +++ b/engines/sherlock/animation.cpp @@ -94,7 +94,7 @@ bool Animation::playPrologue(const Common::String &filename, int minDelay, int f // Load initial image Common::String vdaName = baseName + ".vda"; - ImageFile images(vdaName, true); + ImageFile images(vdaName, true, true); events.wait(minDelay); if (fade != 0 && fade != 255) @@ -119,15 +119,16 @@ bool Animation::playPrologue(const Common::String &filename, int minDelay, int f } else if (imageFrame != -1) { // Read position from either animation stream or the sprite frame itself if (imageFrame < 0) { - imageFrame += 32769; + imageFrame += 32768; pt.x = stream->readUint16LE(); pt.y = stream->readUint16LE(); } else { pt = images[imageFrame]._offset; } - // Draw the sprite - screen.transBlitFrom(images[imageFrame], pt); + // Draw the sprite. Note that we explicitly use the raw frame below, rather than the ImageFrame, + // since we don't want the offsets in the image file to be used, just the explicit position we specify + screen.transBlitFrom(images[imageFrame]._frame, pt); } else { // No sprite to show for this animation frame if (fade == 255) { diff --git a/engines/sherlock/resources.cpp b/engines/sherlock/resources.cpp index 0d66646286..788cacf82a 100644 --- a/engines/sherlock/resources.cpp +++ b/engines/sherlock/resources.cpp @@ -268,18 +268,18 @@ void ImageFile::setVm(SherlockEngine *vm) { _vm = vm; } -ImageFile::ImageFile(const Common::String &name, bool skipPal) { +ImageFile::ImageFile(const Common::String &name, bool skipPal, bool animImages) { Common::SeekableReadStream *stream = _vm->_res->load(name); Common::fill(&_palette[0], &_palette[PALETTE_SIZE], 0); - load(*stream, skipPal); + load(*stream, skipPal, animImages); delete stream; } ImageFile::ImageFile(Common::SeekableReadStream &stream, bool skipPal) { Common::fill(&_palette[0], &_palette[PALETTE_SIZE], 0); - load(stream, skipPal); + load(stream, skipPal, false); } ImageFile::~ImageFile() { @@ -290,7 +290,7 @@ ImageFile::~ImageFile() { /** * Load the data of the sprite */ -void ImageFile::load(Common::SeekableReadStream &stream, bool skipPalette) { +void ImageFile::load(Common::SeekableReadStream &stream, bool skipPalette, bool animImages) { loadPalette(stream); while (stream.pos() < stream.size()) { @@ -298,8 +298,16 @@ void ImageFile::load(Common::SeekableReadStream &stream, bool skipPalette) { frame._width = stream.readUint16LE() + 1; frame._height = stream.readUint16LE() + 1; frame._paletteBase = stream.readByte(); - frame._rleEncoded = stream.readByte() == 1; - frame._offset.x = stream.readByte(); + + if (animImages) { + // Animation cutscene image files use a 16-bit x offset + frame._offset.x = stream.readUint16LE(); + frame._rleEncoded = (frame._offset.x & 0xff) == 1; + } else { + // Standard image files have a separate byte for the RLE flag, and an 8-bit X offset + frame._rleEncoded = stream.readByte() == 1; + frame._offset.x = stream.readByte(); + } frame._offset.y = stream.readByte(); frame._rleEncoded = !skipPalette && frame._rleEncoded; diff --git a/engines/sherlock/resources.h b/engines/sherlock/resources.h index 45fda565bc..b173884322 100644 --- a/engines/sherlock/resources.h +++ b/engines/sherlock/resources.h @@ -104,13 +104,13 @@ class ImageFile : public Common::Array { private: static SherlockEngine *_vm; - void load(Common::SeekableReadStream &stream, bool skipPalette); + void load(Common::SeekableReadStream &stream, bool skipPalette, bool animImages); void loadPalette(Common::SeekableReadStream &stream); void decompressFrame(ImageFrame &frame, const byte *src); public: byte _palette[256 * 3]; public: - ImageFile(const Common::String &name, bool skipPal = false); + ImageFile(const Common::String &name, bool skipPal = false, bool animImages = false); ImageFile(Common::SeekableReadStream &stream, bool skipPal = false); ~ImageFile(); static void setVm(SherlockEngine *vm); -- cgit v1.2.3 From 093d7877e6656132ed136fb37559a4daf82cd985 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 1 May 2015 14:22:21 -1000 Subject: SHERLOCK: Fix conversation with Lord Brumwell --- engines/sherlock/talk.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index a848e11392..7464e4d341 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -909,7 +909,7 @@ void Talk::setSequence(int speaker) { Scene &scene = *_vm->_scene; // If no speaker is specified, then nothing needs to be done - if (speaker != -1) + if (speaker == -1) return; if (speaker) { -- cgit v1.2.3 From a4662b4699286a948644a8018d343f96e28ee019 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 1 May 2015 14:22:35 -1000 Subject: SHERLOCK: Fix getting Tarot cards --- engines/sherlock/scene.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index cd913f8515..497a8d551c 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -559,7 +559,7 @@ void Scene::checkSceneFlags(bool flag) { */ void Scene::checkInventory() { for (uint shapeIdx = 0; shapeIdx < _bgShapes.size(); ++shapeIdx) { - for (uint invIdx = 0; invIdx < _vm->_inventory->size(); ++invIdx) { + for (uint invIdx = 0; invIdx < _vm->_inventory->_holdings; ++invIdx) { if (scumm_stricmp(_bgShapes[shapeIdx]._name.c_str(), (*_vm->_inventory)[invIdx]._name.c_str()) == 0) { _bgShapes[shapeIdx]._type = INVALID; -- cgit v1.2.3 From 5b8fb0cf9097d3d288a3afe0615b6dffbaef3ea0 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 1 May 2015 14:54:28 -1000 Subject: SHERLOCK: Fix crash unlocking desk drawer in Palmist --- engines/sherlock/objects.cpp | 7 +++++++ engines/sherlock/objects.h | 1 + 2 files changed, 8 insertions(+) (limited to 'engines') diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index 3cec0d800a..ff8f6393db 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -377,6 +377,13 @@ void ActionType::synchronize(Common::SeekableReadStream &s) { /*----------------------------------------------------------------*/ +UseType::UseType() { + _cAnimNum = _cAnimSpeed = 0; + _useFlag = 0; + _dFlag[0] = 0; + _lFlag[0] = _lFlag[1] = 0; +} + void UseType::synchronize(Common::SeekableReadStream &s) { char buffer[12]; diff --git a/engines/sherlock/objects.h b/engines/sherlock/objects.h index e2b53ec541..10b491e5d7 100644 --- a/engines/sherlock/objects.h +++ b/engines/sherlock/objects.h @@ -160,6 +160,7 @@ struct UseType { int _lFlag[2]; Common::String _target; + UseType(); void synchronize(Common::SeekableReadStream &s); }; -- cgit v1.2.3 From 8671d29627821292dee5e950fdd17454ca289ee7 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 1 May 2015 15:58:47 -1000 Subject: SHERLOCK: Re-enabled intro credits --- engines/sherlock/sherlock.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index a8d3d9a535..49230f22de 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -107,8 +107,7 @@ Common::Error SherlockEngine::run() { _saves->loadGame(_loadGameSlot); _loadGameSlot = -1; } else { - // Temporarily disabled for now - // showOpening(); + showOpening(); } while (!shouldQuit()) { -- cgit v1.2.3 From 9fd73d0b9a689166aed05fc36f39307ac016bcb9 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 1 May 2015 15:59:36 -1000 Subject: SHERLOCK: Implemented showLBV and fixes for credits display --- engines/sherlock/scalpel/scalpel.cpp | 63 +++++++++++++++++++++++++----------- engines/sherlock/scalpel/scalpel.h | 2 ++ engines/sherlock/screen.cpp | 1 + 3 files changed, 48 insertions(+), 18 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp index d36f761239..c0910c52a1 100644 --- a/engines/sherlock/scalpel/scalpel.cpp +++ b/engines/sherlock/scalpel/scalpel.cpp @@ -330,9 +330,7 @@ bool ScalpelEngine::showAlleyCutscene() { finished = _animation->playPrologue("27PRO2", 1, 0, false, 2); if (finished) { - ImageFile screamImages("SCREAM.LBV", false); - _screen->_backBuffer1.transBlitFrom(screamImages[0], Common::Point(0, 0)); - _screen->_backBuffer2.blitFrom(_screen->_backBuffer1); + showLBV("scream.lbv"); finished = _events->delay(6000); } @@ -373,29 +371,40 @@ bool ScalpelEngine::showStreetCutscene() { return finished; } +/** + * Show the game credits + */ bool ScalpelEngine::scrollCredits() { + // Load the images for displaying credit text _titleOverride = "TITLE.LIB"; ImageFile creditsImages("credits.vgs", true); + _screen->setPalette(creditsImages._palette); + _titleOverride = ""; - _screen->_backBuffer1.copyFrom(*_screen->_backBuffer); + // Save a copy of the screen background for use in drawing each credit frame + _screen->_backBuffer1.blitFrom(*_screen); - for(int i = 0; i < 600 && !_events->kbHit(); i++) { - _screen->_backBuffer1.copyFrom(*_screen->_backBuffer); - if (i < 200) - _screen->transBlitFrom(creditsImages[0], Common::Point(10, -i), false, 0); - if (i > 0 && i < 400) - _screen->transBlitFrom(creditsImages[1], Common::Point(10, 200 - i), false, 0); - if (i > 200) - _screen->transBlitFrom(creditsImages[2], Common::Point(10, 400 - i), false, 0); + // Loop for showing the credits + for(int idx = 0; idx < 600 && !_events->kbHit() && !shouldQuit(); ++idx) { + // Copy the entire screen background before writing text + _screen->blitFrom(_screen->_backBuffer1); - warning("TODO: Use VideoBlockMove"); -// videoblockmove(SCREEN, BACKBUFFER, 0, 0, 320, 10); -// videoblockmove(SCREEN, BACKBUFFER, 0, 190, 320, 10); + // Write the text appropriate for the next frame + if (idx < 200) + _screen->transBlitFrom(creditsImages[0], Common::Point(10, -idx), false, 0); + if (idx > 0 && idx < 400) + _screen->transBlitFrom(creditsImages[1], Common::Point(10, 200 - idx), false, 0); + if (idx > 200) + _screen->transBlitFrom(creditsImages[2], Common::Point(10, 400 - idx), false, 0); + + // Don't show credit text on the top and bottom ten rows of the screen + _screen->blitFrom(_screen->_backBuffer1, Common::Point(0, 0), Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, 10)); + _screen->blitFrom(_screen->_backBuffer1, Common::Point(0, SHERLOCK_SCREEN_HEIGHT - 10), + Common::Rect(0, SHERLOCK_SCREEN_HEIGHT - 10, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); _events->delay(100); } - _titleOverride = ""; return true; } @@ -408,7 +417,8 @@ bool ScalpelEngine::showOfficeCutscene() { if (finished) finished = _animation->playPrologue("COFF2", 1, 0, false, 3); if (finished) { - warning("TODO: ShowLBV(""NOTE.LBV"");"); + showLBV("note.lbv"); + if (_sound->_voices) { finished = _sound->playSound("NOTE1", WAIT_KBD_OR_FINISH); if (finished) @@ -441,6 +451,11 @@ bool ScalpelEngine::showOfficeCutscene() { return finished; } +/** + * Load the default inventory for the game, which includes both the initial active inventory, + * as well as special pending inventory items which can appear automatically in the player's + * inventory once given required flags are set + */ void ScalpelEngine::loadInventory() { Inventory &inv = *_inventory; @@ -449,7 +464,7 @@ void ScalpelEngine::loadInventory() { inv.push_back(InventoryItem(0, "Message", "A message requesting help", "_ITEM03A")); inv.push_back(InventoryItem(0, "Holmes Card", "A number of business cards", "_ITEM07A")); - // Potential items + // Hidden items inv.push_back(InventoryItem(95, "Tickets", "Opera Tickets", "_ITEM10A")); inv.push_back(InventoryItem(138, "Cuff Link", "Cuff Link", "_ITEM04A")); inv.push_back(InventoryItem(138, "Wire Hook", "Wire Hook", "_ITEM06A")); @@ -462,6 +477,18 @@ void ScalpelEngine::loadInventory() { inv.push_back(InventoryItem(586, "Pawn ticket", "A pawn ticket", "_ITEM16A")); }; +/** + * Transition to show an image + */ +void ScalpelEngine::showLBV(const Common::String &filename) { + Common::SeekableReadStream *stream = _res->load(filename, "title.lib"); + ImageFile images(*stream); + delete stream; + + _screen->setPalette(images._palette); + _screen->_backBuffer1.blitFrom(images[0]._frame); + _screen->verticalTransition(); +} /** * Starting a scene within the game diff --git a/engines/sherlock/scalpel/scalpel.h b/engines/sherlock/scalpel/scalpel.h index 194bf5413e..2ba47a49e1 100644 --- a/engines/sherlock/scalpel/scalpel.h +++ b/engines/sherlock/scalpel/scalpel.h @@ -42,6 +42,8 @@ private: bool scrollCredits(); void loadInventory(); + + void showLBV(const Common::String &filename); protected: virtual void initialize(); diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp index 66590c3ada..01d3b9155a 100644 --- a/engines/sherlock/screen.cpp +++ b/engines/sherlock/screen.cpp @@ -35,6 +35,7 @@ Screen::Screen(SherlockEngine *vm) : Surface(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCR _transitionSeed = 1; _fadeStyle = false; _font = nullptr; + _backBuffer = nullptr; _fontHeight = 0; Common::fill(&_cMap[0], &_cMap[PALETTE_SIZE], 0); Common::fill(&_sMap[0], &_sMap[PALETTE_SIZE], 0); -- cgit v1.2.3 From cce0b5583160f1ea2aee2b294527e036165a84f1 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 1 May 2015 16:06:45 -1000 Subject: SHERLOCK: Extra comments for methods in ScalpelEngine --- engines/sherlock/scalpel/scalpel.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'engines') diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp index c0910c52a1..5274cbbec4 100644 --- a/engines/sherlock/scalpel/scalpel.cpp +++ b/engines/sherlock/scalpel/scalpel.cpp @@ -246,6 +246,9 @@ void ScalpelEngine::showOpening() { _sound->stopMusic(); } +/** + * Show the starting city cutscene which shows the game title + */ bool ScalpelEngine::showCityCutscene() { byte palette[PALETTE_SIZE]; @@ -318,6 +321,9 @@ bool ScalpelEngine::showCityCutscene() { return finished; } +/** + * Show the back alley where the initial murder takes place + */ bool ScalpelEngine::showAlleyCutscene() { byte palette[PALETTE_SIZE]; _sound->playMusic("prolog2.mus"); @@ -355,6 +361,9 @@ bool ScalpelEngine::showAlleyCutscene() { return finished; } +/** + * Show the Baker Street outside cutscene + */ bool ScalpelEngine::showStreetCutscene() { _titleOverride = "TITLE.LIB"; _soundOverride = "TITLE.SND"; @@ -408,6 +417,9 @@ bool ScalpelEngine::scrollCredits() { return true; } +/** + * Show Holmes and Watson at the breakfast table, lestrade's note, and then the scrolling credits + */ bool ScalpelEngine::showOfficeCutscene() { _sound->playMusic("PROLOG4.MUS"); _titleOverride = "TITLE2.LIB"; -- cgit v1.2.3 From 1e2ed9e3bc98ad7b0295df8484710a8223bfd01d Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 1 May 2015 16:32:09 -1000 Subject: SHERLOCK: Further fixes for credits display --- engines/sherlock/scalpel/scalpel.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp index 5274cbbec4..a90408fe11 100644 --- a/engines/sherlock/scalpel/scalpel.cpp +++ b/engines/sherlock/scalpel/scalpel.cpp @@ -385,10 +385,10 @@ bool ScalpelEngine::showStreetCutscene() { */ bool ScalpelEngine::scrollCredits() { // Load the images for displaying credit text - _titleOverride = "TITLE.LIB"; - ImageFile creditsImages("credits.vgs", true); + Common::SeekableReadStream *stream = _res->load("credits.vgs", "title.lib"); + ImageFile creditsImages(*stream); _screen->setPalette(creditsImages._palette); - _titleOverride = ""; + delete stream; // Save a copy of the screen background for use in drawing each credit frame _screen->_backBuffer1.blitFrom(*_screen); @@ -399,12 +399,10 @@ bool ScalpelEngine::scrollCredits() { _screen->blitFrom(_screen->_backBuffer1); // Write the text appropriate for the next frame - if (idx < 200) - _screen->transBlitFrom(creditsImages[0], Common::Point(10, -idx), false, 0); - if (idx > 0 && idx < 400) - _screen->transBlitFrom(creditsImages[1], Common::Point(10, 200 - idx), false, 0); + if (idx < 400) + _screen->transBlitFrom(creditsImages[0], Common::Point(10, 200 - idx), false, 0); if (idx > 200) - _screen->transBlitFrom(creditsImages[2], Common::Point(10, 400 - idx), false, 0); + _screen->transBlitFrom(creditsImages[1], Common::Point(10, 400 - idx), false, 0); // Don't show credit text on the top and bottom ten rows of the screen _screen->blitFrom(_screen->_backBuffer1, Common::Point(0, 0), Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, 10)); -- cgit v1.2.3 From 42a99354f9d0c4719e955008f57bf433fdbeabb3 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 1 May 2015 16:53:22 -1000 Subject: SHERLOCK: Rename playPrologue to play --- engines/sherlock/animation.cpp | 2 +- engines/sherlock/animation.h | 2 +- engines/sherlock/scalpel/scalpel.cpp | 46 ++++++++++++++++++------------------ engines/sherlock/talk.cpp | 2 +- 4 files changed, 26 insertions(+), 26 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/animation.cpp b/engines/sherlock/animation.cpp index e70bc84ff8..1d84a30c0f 100644 --- a/engines/sherlock/animation.cpp +++ b/engines/sherlock/animation.cpp @@ -64,7 +64,7 @@ static const int NO_FRAMES = FRAMES_END; Animation::Animation(SherlockEngine *vm): _vm(vm) { } -bool Animation::playPrologue(const Common::String &filename, int minDelay, int fade, +bool Animation::play(const Common::String &filename, int minDelay, int fade, bool setPalette, int speed) { Events &events = *_vm->_events; Screen &screen = *_vm->_screen; diff --git a/engines/sherlock/animation.h b/engines/sherlock/animation.h index da4c5baad7..3d87cb0a91 100644 --- a/engines/sherlock/animation.h +++ b/engines/sherlock/animation.h @@ -39,7 +39,7 @@ public: public: Animation(SherlockEngine *vm); - bool playPrologue(const Common::String &filename, int minDelay, int fade, bool setPalette, int speed); + bool play(const Common::String &filename, int minDelay, int fade, bool setPalette, int speed); }; } // End of namespace Sherlock diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp index a90408fe11..3fe094bcf4 100644 --- a/engines/sherlock/scalpel/scalpel.cpp +++ b/engines/sherlock/scalpel/scalpel.cpp @@ -255,7 +255,7 @@ bool ScalpelEngine::showCityCutscene() { _sound->playMusic("prolog1.mus"); _titleOverride = "title.lib"; _soundOverride = "title.snd"; - bool finished = _animation->playPrologue("26open1", 1, 255, true, 2); + bool finished = _animation->play("26open1", 1, 255, true, 2); if (finished) { ImageFile titleImages("title2.vgs", true); @@ -280,7 +280,7 @@ bool ScalpelEngine::showCityCutscene() { } if (finished) - finished = _animation->playPrologue("26open2", 1, 0, false, 2); + finished = _animation->play("26open2", 1, 0, false, 2); if (finished) { ImageFile titleImages("title.vgs", true); @@ -331,9 +331,9 @@ bool ScalpelEngine::showAlleyCutscene() { _titleOverride = "TITLE.LIB"; _soundOverride = "TITLE.SND"; - bool finished = _animation->playPrologue("27PRO1", 1, 3, true, 2); + bool finished = _animation->play("27PRO1", 1, 3, true, 2); if (finished) - finished = _animation->playPrologue("27PRO2", 1, 0, false, 2); + finished = _animation->play("27PRO2", 1, 0, false, 2); if (finished) { showLBV("scream.lbv"); @@ -341,7 +341,7 @@ bool ScalpelEngine::showAlleyCutscene() { } if (finished) - finished = _animation->playPrologue("27PRO3", 1, 0, true, 2); + finished = _animation->play("27PRO3", 1, 0, true, 2); if(finished) { _screen->getPalette(palette); @@ -370,10 +370,10 @@ bool ScalpelEngine::showStreetCutscene() { _sound->playMusic("PROLOG3.MUS"); - bool finished = _animation->playPrologue("14KICK", 1, 3, true, 2); + bool finished = _animation->play("14KICK", 1, 3, true, 2); if (finished) - finished = _animation->playPrologue("14NOTE", 1, 0, false, 2); + finished = _animation->play("14NOTE", 1, 0, false, 2); _titleOverride = ""; _soundOverride = ""; @@ -423,9 +423,9 @@ bool ScalpelEngine::showOfficeCutscene() { _titleOverride = "TITLE2.LIB"; _soundOverride = "TITLE.SND"; - bool finished = _animation->playPrologue("COFF1", 1, 3, true, 3); + bool finished = _animation->play("COFF1", 1, 3, true, 3); if (finished) - finished = _animation->playPrologue("COFF2", 1, 0, false, 3); + finished = _animation->play("COFF2", 1, 0, false, 3); if (finished) { showLBV("note.lbv"); @@ -445,10 +445,10 @@ bool ScalpelEngine::showOfficeCutscene() { } if (finished) - finished = _animation->playPrologue("COFF3", 1, 0, true, 3); + finished = _animation->play("COFF3", 1, 0, true, 3); if (finished) - finished = _animation->playPrologue("COFF4", 1, 0, false, 3); + finished = _animation->play("COFF4", 1, 0, false, 3); if (finished) finished = scrollCredits(); @@ -541,8 +541,8 @@ void ScalpelEngine::startScene() { // Blackwood's capture _res->addToCache("final2.vda", "epilogue.lib"); _res->addToCache("final2.vdx", "epilogue.lib"); - _animation->playPrologue("final1", 1, 3, true, 4); - _animation->playPrologue("final2", 1, 0, false, 4); + _animation->play("final1", 1, 3, true, 4); + _animation->play("final2", 1, 0, false, 4); break; case 52: @@ -558,8 +558,8 @@ void ScalpelEngine::startScene() { _res->addToCache("finale4.vda", "EPILOG2.lib"); _res->addToCache("finale4.vdx", "EPILOG2.lib"); - _animation->playPrologue("finalr1", 1, 3, true, 4); - _animation->playPrologue("finalr2", 1, 0, false, 4); + _animation->play("finalr1", 1, 3, true, 4); + _animation->play("finalr2", 1, 0, false, 4); if (!_res->isInCache("finale2.vda")) { // Finale file isn't cached @@ -571,12 +571,12 @@ void ScalpelEngine::startScene() { _res->addToCache("finale4.vdx", "EPILOG2.lib"); } - _animation->playPrologue("finale1", 1, 0, false, 4); - _animation->playPrologue("finale2", 1, 0, false, 4); - _animation->playPrologue("finale3", 1, 0, false, 4); + _animation->play("finale1", 1, 0, false, 4); + _animation->play("finale2", 1, 0, false, 4); + _animation->play("finale3", 1, 0, false, 4); _useEpilogue2 = true; - _animation->playPrologue("finale4", 1, 0, false, 4); + _animation->play("finale4", 1, 0, false, 4); _useEpilogue2 = false; break; @@ -587,9 +587,9 @@ void ScalpelEngine::startScene() { _res->addToCache("SUBWAY3.vda", "epilogue.lib"); _res->addToCache("SUBWAY3.vdx", "epilogue.lib"); - _animation->playPrologue("SUBWAY1", 1, 3, true, 4); - _animation->playPrologue("SUBWAY2", 1, 0, false, 4); - _animation->playPrologue("SUBWAY3", 1, 0, false, 4); + _animation->play("SUBWAY1", 1, 3, true, 4); + _animation->play("SUBWAY2", 1, 0, false, 4); + _animation->play("SUBWAY3", 1, 0, false, 4); // Set fading to direct fade temporary so the transition goes quickly. _scene->_tempFadeStyle = _screen->_fadeStyle ? 257 : 256; @@ -598,7 +598,7 @@ void ScalpelEngine::startScene() { case 70: // Brumwell suicide - _animation->playPrologue("suicid", 1, 3, true, 4); + _animation->play("suicid", 1, 3, true, 4); break; default: break; diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index 7464e4d341..603f47a446 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -1353,7 +1353,7 @@ void Talk::doScript(const Common::String &script) { for (int idx = 0; idx < 8 && str[idx] != '~'; ++idx) tempString += str[idx]; - anim.playPrologue(tempString, 1, 3, true, 4); + anim.play(tempString, 1, 3, true, 4); break; case ADD_ITEM_TO_INVENTORY: -- cgit v1.2.3 From b4c3d9840c99ce5d4e23eb0f646bd995f7d2c002 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 1 May 2015 17:17:24 -1000 Subject: SHERLOCK: Extra method comments --- engines/sherlock/animation.cpp | 3 +++ engines/sherlock/debugger.cpp | 6 ++++++ engines/sherlock/detection.cpp | 30 ++++++++++++++++++++++++++++++ engines/sherlock/events.cpp | 5 +++-- engines/sherlock/graphics.cpp | 9 +++++++-- engines/sherlock/inventory.cpp | 3 +++ engines/sherlock/journal.cpp | 3 +++ engines/sherlock/objects.cpp | 19 ++++++++++++++----- engines/sherlock/people.cpp | 14 ++++++++++---- engines/sherlock/scene.cpp | 5 ++++- engines/sherlock/screen.cpp | 15 +++++++++++++++ engines/sherlock/sherlock.cpp | 14 +++++++++++++- engines/sherlock/talk.cpp | 6 ++++++ engines/sherlock/user_interface.cpp | 17 +++++++++++++++-- 14 files changed, 132 insertions(+), 17 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/animation.cpp b/engines/sherlock/animation.cpp index 1d84a30c0f..aea4793a76 100644 --- a/engines/sherlock/animation.cpp +++ b/engines/sherlock/animation.cpp @@ -64,6 +64,9 @@ static const int NO_FRAMES = FRAMES_END; Animation::Animation(SherlockEngine *vm): _vm(vm) { } +/** + * Play a full-screen animation + */ bool Animation::play(const Common::String &filename, int minDelay, int fade, bool setPalette, int speed) { Events &events = *_vm->_events; diff --git a/engines/sherlock/debugger.cpp b/engines/sherlock/debugger.cpp index b8ac8bef6a..b3dac71d5e 100644 --- a/engines/sherlock/debugger.cpp +++ b/engines/sherlock/debugger.cpp @@ -30,6 +30,9 @@ Debugger::Debugger(SherlockEngine *vm) : GUI::Debugger(), _vm(vm) { registerCmd("scene", WRAP_METHOD(Debugger, cmd_scene)); } +/** + * Converts a decimal or hexadecimal string into a number + */ static int strToInt(const char *s) { if (!*s) // No string at all @@ -46,6 +49,9 @@ static int strToInt(const char *s) { return (int)tmp; } +/** + * Switch to another scene + */ bool Debugger::cmd_scene(int argc, const char **argv) { if (argc != 2) { debugPrintf("Format: scene \n"); diff --git a/engines/sherlock/detection.cpp b/engines/sherlock/detection.cpp index c4d1c65fd5..14fc04cc73 100644 --- a/engines/sherlock/detection.cpp +++ b/engines/sherlock/detection.cpp @@ -36,14 +36,23 @@ struct SherlockGameDescription { uint32 features; }; +/** + * Returns the Id of the game + */ uint32 SherlockEngine::getGameID() const { return _gameDescription->gameID; } +/** + * Returns the features the currently playing game has + */ uint32 SherlockEngine::getGameFeatures() const { return _gameDescription->features; } +/** + * Return's the platform the game's datafiles are for + */ Common::Platform SherlockEngine::getPlatform() const { return _gameDescription->desc.platform; } @@ -79,6 +88,9 @@ public: SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const; }; +/** + * Creates an instance of the game engine + */ bool SherlockMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const { const Sherlock::SherlockGameDescription *gd = (const Sherlock::SherlockGameDescription *)desc; if (gd) { @@ -97,6 +109,9 @@ bool SherlockMetaEngine::createInstance(OSystem *syst, Engine **engine, const AD return gd != 0; } +/** + * Returns a list of features the game's MetaEngine support + */ bool SherlockMetaEngine::hasFeature(MetaEngineFeature f) const { return (f == kSupportsListSaves) || @@ -106,6 +121,9 @@ bool SherlockMetaEngine::hasFeature(MetaEngineFeature f) const { (f == kSavesSupportThumbnail); } +/** + * Returns a list of features the game itself supports + */ bool Sherlock::SherlockEngine::hasFeature(EngineFeature f) const { return (f == kSupportsRTL) || @@ -113,19 +131,31 @@ bool Sherlock::SherlockEngine::hasFeature(EngineFeature f) const { (f == kSupportsSavingDuringRuntime); } +/** + * Return a list of savegames + */ SaveStateList SherlockMetaEngine::listSaves(const char *target) const { return Sherlock::SaveManager(nullptr, "").getSavegameList(target); } +/** + * Returns the maximum number of allowed save slots + */ int SherlockMetaEngine::getMaximumSaveSlot() const { return MAX_SAVEGAME_SLOTS; } +/** + * Deletes a savegame in the specified slot + */ void SherlockMetaEngine::removeSaveState(const char *target, int slot) const { Common::String filename = Sherlock::SaveManager(nullptr, target).generateSaveName(slot); g_system->getSavefileManager()->removeSavefile(filename); } +/** + * Given a specified savegame slot, returns extended information for the save + */ SaveStateDescriptor SherlockMetaEngine::querySaveMetaInfos(const char *target, int slot) const { Common::String filename = Sherlock::SaveManager(nullptr, target).generateSaveName(slot); Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading(filename); diff --git a/engines/sherlock/events.cpp b/engines/sherlock/events.cpp index f7cbdd301e..a4fc93edd9 100644 --- a/engines/sherlock/events.cpp +++ b/engines/sherlock/events.cpp @@ -208,7 +208,6 @@ Common::KeyState Events::getKey() { return keyState; } - /** * Clear any current keypress or mouse click */ @@ -227,7 +226,6 @@ void Events::clearKeyboard() { _pendingKeys.clear(); } - /** * Delay for a given number of game frames, where each frame is 1/60th of a second */ @@ -236,6 +234,9 @@ void Events::wait(int numFrames) { delay(totalMilli); } +/** + * Does a delay of the specified number of milliseconds + */ bool Events::delay(uint32 time, bool interruptable) { // Different handling for really short versus extended times if (time < 10) { diff --git a/engines/sherlock/graphics.cpp b/engines/sherlock/graphics.cpp index 6fd046e458..2095e7d35d 100644 --- a/engines/sherlock/graphics.cpp +++ b/engines/sherlock/graphics.cpp @@ -47,6 +47,10 @@ Surface::~Surface() { free(); } +/** + * Sets up an internal surface with the specified dimensions that will be automatically freed + * when the surface object is destroyed + */ void Surface::create(uint16 width, uint16 height) { if (_freePixels) free(); @@ -55,7 +59,6 @@ void Surface::create(uint16 width, uint16 height) { _freePixels = true; } - /** * Copy a surface into this one */ @@ -159,6 +162,9 @@ void Surface::fillRect(int x1, int y1, int x2, int y2, byte color) { fillRect(Common::Rect(x1, y1, x2, y2), color); } +/** + * Fill a given area of the surface with a given color + */ void Surface::fillRect(const Common::Rect &r, byte color) { Graphics::Surface::fillRect(r, color); addDirtyRect(r); @@ -196,5 +202,4 @@ bool Surface::clip(Common::Rect &srcBounds, Common::Rect &destBounds) { return true; } - } // End of namespace Sherlock diff --git a/engines/sherlock/inventory.cpp b/engines/sherlock/inventory.cpp index 798531ea14..935a306619 100644 --- a/engines/sherlock/inventory.cpp +++ b/engines/sherlock/inventory.cpp @@ -358,6 +358,9 @@ void Inventory::highlight(int index, byte color) { screen.slamArea(8 + slot * 52, 165, 44, 30); } +/** + * Support method for updating the screen + */ void Inventory::doInvJF() { Screen &screen = *_vm->_screen; Talk &talk = *_vm->_talk; diff --git a/engines/sherlock/journal.cpp b/engines/sherlock/journal.cpp index 67cff15218..25b0bb5451 100644 --- a/engines/sherlock/journal.cpp +++ b/engines/sherlock/journal.cpp @@ -91,6 +91,9 @@ void Journal::record(int converseNum, int statementNum, bool replyOnly) { } } +/** + * Load the list of location names that the journal will make reference to + */ void Journal::loadJournalLocations() { Resources &res = *_vm->_res; char c; diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index ff8f6393db..fa5dfee26c 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -361,6 +361,9 @@ void Sprite::checkSprite() { /*----------------------------------------------------------------*/ +/** + * Synchronize the data for a savegame + */ void ActionType::synchronize(Common::SeekableReadStream &s) { char buffer[12]; @@ -384,6 +387,9 @@ UseType::UseType() { _lFlag[0] = _lFlag[1] = 0; } +/** + * Synchronize the data for a savegame + */ void UseType::synchronize(Common::SeekableReadStream &s) { char buffer[12]; @@ -816,11 +822,11 @@ void Object::setObjSequence(int seq, bool wait) { } /** -* Checks for codes -* @param name The name to check for codes -* @param messages Provides a lookup list of messages that can be printed -* @returns 0 if no codes are found, 1 if codes were found -*/ + * Checks for codes + * @param name The name to check for codes + * @param messages Provides a lookup list of messages that can be printed + * @returns 0 if no codes are found, 1 if codes were found + */ int Object::checkNameForCodes(const Common::String &name, const char *const messages[]) { Map &map = *_vm->_map; People &people = *_vm->_people; @@ -1090,6 +1096,9 @@ const Common::Rect Object::getOldBounds() const { /*----------------------------------------------------------------*/ +/** + * Synchronize the data for a savegame + */ void CAnim::synchronize(Common::SeekableReadStream &s) { char buffer[12]; s.read(buffer, 12); diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp index ed6e0607bd..5c4014f1a2 100644 --- a/engines/sherlock/people.cpp +++ b/engines/sherlock/people.cpp @@ -217,6 +217,9 @@ People::~People() { delete[] _portrait._sequences; } +/** + * Reset the player data + */ void People::reset() { Sprite &p = _data[PLAYER]; @@ -239,6 +242,9 @@ void People::reset() { p._status = 0; } +/** + * Load the walking images for Sherlock + */ bool People::loadWalk() { if (_walkLoaded) { return false; @@ -267,10 +273,10 @@ bool People::freeWalk() { } /** -* Set the variables for moving a character from one poisition to another -* in a straight line - goAllTheWay must have been previously called to -* check for any obstacles in the path. -*/ + * Set the variables for moving a character from one poisition to another + * in a straight line - goAllTheWay must have been previously called to + * check for any obstacles in the path. + */ void People::setWalking() { Map &map = *_vm->_map; Scene &scene = *_vm->_scene; diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 497a8d551c..c714574e08 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -559,7 +559,7 @@ void Scene::checkSceneFlags(bool flag) { */ void Scene::checkInventory() { for (uint shapeIdx = 0; shapeIdx < _bgShapes.size(); ++shapeIdx) { - for (uint invIdx = 0; invIdx < _vm->_inventory->_holdings; ++invIdx) { + for (int invIdx = 0; invIdx < _vm->_inventory->_holdings; ++invIdx) { if (scumm_stricmp(_bgShapes[shapeIdx]._name.c_str(), (*_vm->_inventory)[invIdx]._name.c_str()) == 0) { _bgShapes[shapeIdx]._type = INVALID; @@ -802,6 +802,9 @@ void Scene::updateBackground() { screen.resetDisplayBounds(); } +/** + * Check whether the passed area intersects with one of the scene's exits + */ Exit *Scene::checkForExit(const Common::Rect &r) { for (uint idx = 0; idx < _exits.size(); ++idx) { if (_exits[idx]._bounds.intersects(r)) diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp index 01d3b9155a..97b23e7c8e 100644 --- a/engines/sherlock/screen.cpp +++ b/engines/sherlock/screen.cpp @@ -50,6 +50,9 @@ Screen::~Screen() { delete _font; } +/** + * Set the font to use for writing text on the screen + */ void Screen::setFont(int fontNumber) { _fontNumber = fontNumber; Common::String fname = Common::String::format("FONT%d.VGS", fontNumber + 1); @@ -64,6 +67,9 @@ void Screen::setFont(int fontNumber) { _fontHeight = MAX((uint16)_fontHeight, (*_font)[idx]._frame.h); } +/** + * Handles updating any dirty areas of the screen Surface object to the physical screen + */ void Screen::update() { // Merge the dirty rects mergeDirtyRects(); @@ -82,14 +88,23 @@ void Screen::update() { _dirtyRects.clear(); } +/** + * Return the currently active palette + */ void Screen::getPalette(byte palette[PALETTE_SIZE]) { g_system->getPaletteManager()->grabPalette(palette, 0, PALETTE_COUNT); } +/** + * Set the palette + */ void Screen::setPalette(const byte palette[PALETTE_SIZE]) { g_system->getPaletteManager()->setPalette(palette, 0, PALETTE_COUNT); } +/** + * Fades from the currently active palette to the passed palette + */ int Screen::equalizePalette(const byte palette[PALETTE_SIZE]) { int total = 0; byte tempPalette[PALETTE_SIZE]; diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index 49230f22de..e3d137a3a3 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -69,6 +69,9 @@ SherlockEngine::~SherlockEngine() { delete _res; } +/** + * Does basic initialization of the game engine + */ void SherlockEngine::initialize() { initGraphics(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT, false); @@ -93,7 +96,11 @@ void SherlockEngine::initialize() { _ui = new UserInterface(this); } +/** + * Main method for running the game + */ Common::Error SherlockEngine::run() { + // Initialize the engine initialize(); // If requested, load a savegame instead of showing the intro @@ -133,6 +140,9 @@ Common::Error SherlockEngine::run() { return Common::kNoError; } +/** + * Main loop for displaying a scene and handling all that occurs within it + */ void SherlockEngine::sceneLoop() { while (!shouldQuit() && _scene->_goToScene == -1) { // See if a script needs to be completed from either a goto room code, @@ -171,7 +181,6 @@ void SherlockEngine::handleInput() { _ui->handleInput(); } - /** * Read the state of a global flag */ @@ -193,6 +202,9 @@ void SherlockEngine::setFlags(int flagNum) { _scene->checkSceneFlags(true); } +/** + * Saves game configuration information + */ void SherlockEngine::saveConfig() { // TODO } diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index 603f47a446..d05c09ab38 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -100,6 +100,9 @@ Talk::Talk(SherlockEngine *vm): _vm(vm) { _scriptCurrentIndex = -1; } +/** + * Sets talk sequences + */ void Talk::setSequences(const byte *talkSequences, const byte *stillSequences, int maxPeople) { for (int idx = 0; idx < maxPeople; ++idx) { STILL_SEQUENCES.push_back(TalkSequences(stillSequences)); @@ -1726,6 +1729,9 @@ int Talk::waitForMore(int delay) { return key2; } +/** + * Pops an entry off of the script stack + */ void Talk::popStack() { if (!_scriptStack.empty()) { ScriptStackEntry scriptEntry = _scriptStack.pop(); diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index e7e7981966..f60e63a574 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -188,6 +188,9 @@ void Settings::drawInteface(bool flag) { } } +/** + * Draws the buttons for the settings dialog + */ int Settings::drawButtons(const Common::Point &pt, int _key) { Events &events = *_vm->_events; People &people = *_vm->_people; @@ -259,7 +262,6 @@ int Settings::drawButtons(const Common::Point &pt, int _key) { return found; } - /*----------------------------------------------------------------*/ UserInterface::UserInterface(SherlockEngine *vm) : _vm(vm) { @@ -298,6 +300,9 @@ UserInterface::~UserInterface() { delete _controlPanel; } +/** + * Resets the user interface + */ void UserInterface::reset() { _oldKey = -1; _help = _oldHelp = -1; @@ -1962,6 +1967,12 @@ void UserInterface::doTalkControl() { } } +/** + * Handles events when the Journal is active. + * @remarks Whilst this would in theory be better in the Journal class, since it displays in + * the user interface, it uses so many internal UI fields, that it sort of made some sense + * to put it in the UserInterface class. + */ void UserInterface::journalControl() { Events &events = *_vm->_events; Journal &journal = *_vm->_journal; @@ -2013,6 +2024,9 @@ void UserInterface::journalControl() { /** * Handles input when the settings window is being shown + * @remarks Whilst this would in theory be better in the Journal class, since it displays in + * the user interface, it uses so many internal UI fields, that it sort of made some sense + * to put it in the UserInterface class. */ void UserInterface::doControls() { Events &events = *_vm->_events; @@ -2702,5 +2716,4 @@ void UserInterface::checkAction(ActionType &action, const char *const messages[] events.setCursor(ARROW); } - } // End of namespace Sherlock -- cgit v1.2.3 From d9a42a80ffeb9eaee957bbc858f714e5cf362946 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 1 May 2015 17:27:59 -1000 Subject: SHERLOCK: Fix some remaining TODOs --- engines/sherlock/scene.cpp | 4 +--- engines/sherlock/sound.cpp | 6 ++++++ engines/sherlock/sound.h | 1 + engines/sherlock/user_interface.cpp | 1 - 4 files changed, 8 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index c714574e08..e69fb49766 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -1127,9 +1127,7 @@ void Scene::doBgAnim() { if (sound._diskSoundPlaying && !*sound._soundIsOn) { // Loaded sound just finished playing - // TODO: This is horrible.. refactor into the Sound class - delete[] sound._digiBuf; - sound._diskSoundPlaying = false; + sound.freeDigiSound(); } if (_restoreFlag) { diff --git a/engines/sherlock/sound.cpp b/engines/sherlock/sound.cpp index 1a6472a9e9..a452efd890 100644 --- a/engines/sherlock/sound.cpp +++ b/engines/sherlock/sound.cpp @@ -99,4 +99,10 @@ void Sound::waitTimerRoland(uint time) { // TODO } +void Sound::freeDigiSound() { + delete[] _digiBuf; + _digiBuf = nullptr; + _diskSoundPlaying = false; +} + } // End of namespace Sherlock diff --git a/engines/sherlock/sound.h b/engines/sherlock/sound.h index 28de692109..c85af2ac2a 100644 --- a/engines/sherlock/sound.h +++ b/engines/sherlock/sound.h @@ -67,6 +67,7 @@ public: void stopMusic(); void stopSndFuncPtr(int v1, int v2); void waitTimerRoland(uint time); + void freeDigiSound(); }; } // End of namespace Sherlock diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index f60e63a574..21a53c32ff 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -2019,7 +2019,6 @@ void UserInterface::journalControl() { screen._backBuffer1.blitFrom(screen._backBuffer2); scene.updateBackground(); screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT); - // TODO } /** -- cgit v1.2.3 From 12d3976c380e00f22c6f7a930ff56c215a7bd9ab Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 1 May 2015 18:21:13 -1000 Subject: SHERLOCK: Implement configuration settings save/load --- engines/sherlock/sherlock.cpp | 42 ++++++++++++++++++++++++++++++++++++++- engines/sherlock/sherlock.h | 3 +++ engines/sherlock/sound.cpp | 22 ++++++++++++++++---- engines/sherlock/sound.h | 7 ++++--- engines/sherlock/user_interface.h | 2 +- 5 files changed, 67 insertions(+), 9 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index e3d137a3a3..3ab2caabc4 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -94,6 +94,9 @@ void SherlockEngine::initialize() { _sound = new Sound(this); _talk = new Talk(this); _ui = new UserInterface(this); + + // Load game settings + loadConfig(); } /** @@ -202,11 +205,48 @@ void SherlockEngine::setFlags(int flagNum) { _scene->checkSceneFlags(true); } +/** + * Load game configuration esttings + */ +void SherlockEngine::loadConfig() { + // Load sound settings + syncSoundSettings(); + + // Load other settings + if (ConfMan.hasKey("font")) + _screen->setFont(ConfMan.getInt("font")); + if (ConfMan.hasKey("help_style")) + _ui->_helpStyle = ConfMan.getInt("help_style"); + if (ConfMan.hasKey("window_style")) + _ui->_windowStyle = ConfMan.getInt("window_style"); + if (ConfMan.hasKey("portraits_on")) + _people->_portraitsOn = ConfMan.getBool("portraits_on"); +} + /** * Saves game configuration information */ void SherlockEngine::saveConfig() { - // TODO + ConfMan.setBool("mute", _sound->_digitized); + ConfMan.setBool("music_mute", _sound->_music); + ConfMan.setBool("speech_mute", _sound->_voices); + + ConfMan.setInt("font", _screen->fontNumber()); + ConfMan.setInt("help_style", _ui->_helpStyle); + ConfMan.setInt("window_style", _ui->_windowStyle); + ConfMan.setBool("portraits_on", _people->_portraitsOn); + + ConfMan.flushToDisk(); +} + +/** + * Called by the engine when sound settings are updated + */ +void SherlockEngine::syncSoundSettings() { + Engine::syncSoundSettings(); + + // Load sound-related settings + _sound->syncSoundSettings(); } /** diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h index 3f0779421c..02e2e99229 100644 --- a/engines/sherlock/sherlock.h +++ b/engines/sherlock/sherlock.h @@ -74,6 +74,8 @@ private: void sceneLoop(); void handleInput(); + + void loadConfig(); protected: virtual void initialize(); @@ -117,6 +119,7 @@ public: virtual bool canSaveGameStateCurrently(); virtual Common::Error loadGameState(int slot); virtual Common::Error saveGameState(int slot, const Common::String &desc); + virtual void syncSoundSettings(); int getGameType() const; uint32 getGameID() const; diff --git a/engines/sherlock/sound.cpp b/engines/sherlock/sound.cpp index a452efd890..e66f82e5c4 100644 --- a/engines/sherlock/sound.cpp +++ b/engines/sherlock/sound.cpp @@ -21,20 +21,34 @@ */ #include "sherlock/sound.h" +#include "common/config-manager.h" namespace Sherlock { Sound::Sound(SherlockEngine *vm): _vm(vm) { + _digitized = false; + _music = false; + _voices = 0; _soundOn = false; _musicOn = false; _speechOn = false; - _voices = 0; _playingEpilogue = false; - _music = false; - _digitized = false; _diskSoundPlaying = false; _soundIsOn = nullptr; - _digiBuf = nullptr; +} + +/** + * Saves sound-related settings + */ +void Sound::syncSoundSettings() { + _digitized = !ConfMan.getBool("mute"); + _music = !ConfMan.getBool("mute") && !ConfMan.getBool("music_mute"); + _voices = !ConfMan.getBool("mute") && !ConfMan.getBool("speech_mute") ? 1 : 0; + + // TODO: For now, keep sound completely mute until sound is implemented + _digitized = false; + _music = false; + _voices = 0; } void Sound::loadSound(const Common::String &name, int priority) { diff --git a/engines/sherlock/sound.h b/engines/sherlock/sound.h index c85af2ac2a..3bd3a99f07 100644 --- a/engines/sherlock/sound.h +++ b/engines/sherlock/sound.h @@ -38,19 +38,20 @@ class Sound { private: SherlockEngine *_vm; public: + bool _digitized; + bool _music; + int _voices; bool _soundOn; bool _musicOn; bool _speechOn; - int _voices; bool _playingEpilogue; - bool _music; - bool _digitized; bool _diskSoundPlaying; byte *_soundIsOn; byte *_digiBuf; public: Sound(SherlockEngine *vm); + void syncSoundSettings(); void loadSound(const Common::String &name, int priority); bool playSound(const Common::String &name, WaitType waitType = WAIT_RETURN_IMMEDIATELY); void cacheSound(const Common::String &name, int index); diff --git a/engines/sherlock/user_interface.h b/engines/sherlock/user_interface.h index 99612b218b..ac2c16d7c2 100644 --- a/engines/sherlock/user_interface.h +++ b/engines/sherlock/user_interface.h @@ -85,7 +85,6 @@ private: int _bgFound; int _oldBgFound; int _keycode; - int _helpStyle; int _lookHelp; int _help, _oldHelp; int _key, _oldKey; @@ -137,6 +136,7 @@ public: int _invLookFlag; int _temp1; int _windowStyle; + int _helpStyle; public: UserInterface(SherlockEngine *vm); ~UserInterface(); -- cgit v1.2.3 From 7d50c49f5942d2a2e6cfaf32ddc182bcff5c4327 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 1 May 2015 18:22:25 -1000 Subject: SHERLOCK: Fix intro sequence crash --- engines/sherlock/screen.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'engines') diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp index 97b23e7c8e..d170772c98 100644 --- a/engines/sherlock/screen.cpp +++ b/engines/sherlock/screen.cpp @@ -35,7 +35,6 @@ Screen::Screen(SherlockEngine *vm) : Surface(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCR _transitionSeed = 1; _fadeStyle = false; _font = nullptr; - _backBuffer = nullptr; _fontHeight = 0; Common::fill(&_cMap[0], &_cMap[PALETTE_SIZE], 0); Common::fill(&_sMap[0], &_sMap[PALETTE_SIZE], 0); -- cgit v1.2.3 From a2ef3e240225940308c54243589014c922c38274 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 1 May 2015 18:29:42 -1000 Subject: SHERLOCK: Moved Settings dialog into it's own class --- engines/sherlock/module.mk | 1 + engines/sherlock/settings.cpp | 211 ++++++++++++++++++++++++++++++++++++ engines/sherlock/settings.h | 45 ++++++++ engines/sherlock/user_interface.cpp | 186 +------------------------------ engines/sherlock/user_interface.h | 11 -- 5 files changed, 258 insertions(+), 196 deletions(-) create mode 100644 engines/sherlock/settings.cpp create mode 100644 engines/sherlock/settings.h (limited to 'engines') diff --git a/engines/sherlock/module.mk b/engines/sherlock/module.mk index 44ba63f1e2..9334ebfd9c 100644 --- a/engines/sherlock/module.mk +++ b/engines/sherlock/module.mk @@ -19,6 +19,7 @@ MODULE_OBJS = \ saveload.o \ scene.o \ screen.o \ + settings.o \ sherlock.o \ sound.o \ talk.o \ diff --git a/engines/sherlock/settings.cpp b/engines/sherlock/settings.cpp new file mode 100644 index 0000000000..fb7730fc1d --- /dev/null +++ b/engines/sherlock/settings.cpp @@ -0,0 +1,211 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "sherlock/sherlock.h" +#include "sherlock/settings.h" + +namespace Sherlock { + +const int SETUP_POINTS[12][4] = { + { 4, 154, 101, 53 }, // Exit + { 4, 165, 101, 53 }, // Music Toggle + { 219, 165, 316, 268 }, // Voice Toggle + { 103, 165, 217, 160 }, // Sound Effects Toggle + { 219, 154, 316, 268 }, // Help Button Left/Right + { 103, 154, 217, 160 }, // New Font Style + { 4, 187, 101, 53 }, // Joystick Toggle + { 103, 187, 217, 160 }, // Calibrate Joystick + { 219, 176, 316, 268 }, // Fade Style + { 103, 176, 217, 160 }, // Window Open Style + { 4, 176, 101, 53 }, // Portraits Toggle + { 219, 187, 316, 268 } // _key Pad Accel. Toggle +}; + +const char *const SETUP_STRS0[2] = { "off", "on" }; +const char *const SETUP_STRS1[2] = { "Directly", "by Pixel" }; +const char *const SETUP_STRS2[2] = { "Left", "Right" }; +const char *const SETUP_STRS3[2] = { "Appear", "Slide" }; +const char *const SETUP_STRS4[2] = { "Slow", "Fast" }; +const char *const SETUP_STRS5[2] = { "Left", "Right" }; +const char *const SETUP_NAMES[12] = { + "Exit", "M", "V", "S", "B", "New Font Style", "J", "Calibrate Joystick", "F", "W", "P", "K" +}; + +/*----------------------------------------------------------------*/ + +/** + * Draws the interface for the settings window + */ +void Settings::drawInteface(bool flag) { + People &people = *_vm->_people; + Screen &screen = *_vm->_screen; + Sound &sound = *_vm->_sound; + UserInterface &ui = *_vm->_ui; + Common::String tempStr; + + if (!flag) { + screen._backBuffer1.fillRect(Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH, CONTROLS_Y1 + 1), BORDER_COLOR); + screen._backBuffer1.fillRect(Common::Rect(0, CONTROLS_Y1 + 1, 2, SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR); + screen._backBuffer1.fillRect(Common::Rect(SHERLOCK_SCREEN_WIDTH - 2, CONTROLS_Y1 + 1, SHERLOCK_SCREEN_WIDTH, + SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR); + screen._backBuffer1.hLine(0, SHERLOCK_SCREEN_HEIGHT - 1, SHERLOCK_SCREEN_WIDTH - 1, BORDER_COLOR); + screen._backBuffer1.fillRect(Common::Rect(2, CONTROLS_Y1 + 1, SHERLOCK_SCREEN_WIDTH - 2, + SHERLOCK_SCREEN_HEIGHT - 2), INV_BACKGROUND); + } + + screen.makeButton(Common::Rect(SETUP_POINTS[0][0], SETUP_POINTS[0][1], SETUP_POINTS[0][2], SETUP_POINTS[0][1] + 10), + SETUP_POINTS[0][3] - screen.stringWidth("Exit") / 2, "Exit"); + + tempStr = Common::String::format("Music %s", SETUP_STRS0[sound._music]); + screen.makeButton(Common::Rect(SETUP_POINTS[1][0], SETUP_POINTS[1][1], SETUP_POINTS[1][2], SETUP_POINTS[1][1] + 10), + SETUP_POINTS[1][3] - screen.stringWidth(tempStr) / 2, tempStr); + + tempStr = Common::String::format("Voices %s", SETUP_STRS0[sound._voices]); + screen.makeButton(Common::Rect(SETUP_POINTS[2][0], SETUP_POINTS[2][1], SETUP_POINTS[2][2], SETUP_POINTS[2][1] + 10), + SETUP_POINTS[2][3] - screen.stringWidth(tempStr) / 2, tempStr); + + tempStr = Common::String::format("Sound Effects %s", SETUP_STRS0[sound._digitized]); + screen.makeButton(Common::Rect(SETUP_POINTS[3][0], SETUP_POINTS[3][1], SETUP_POINTS[3][2], SETUP_POINTS[3][1] + 10), + SETUP_POINTS[3][3] - screen.stringWidth(tempStr) / 2, tempStr); + + tempStr = Common::String::format("Auto Help %s", SETUP_STRS5[ui._helpStyle]); + screen.makeButton(Common::Rect(SETUP_POINTS[4][0], SETUP_POINTS[4][1], SETUP_POINTS[4][2], SETUP_POINTS[4][1] + 10), + SETUP_POINTS[4][3] - screen.stringWidth(tempStr) / 2, tempStr); + screen.makeButton(Common::Rect(SETUP_POINTS[5][0], SETUP_POINTS[5][1], SETUP_POINTS[5][2], SETUP_POINTS[5][1] + 10), + SETUP_POINTS[5][3] - screen.stringWidth("New Font Style") / 2, "New Font Style"); + + // WORKAROUND: We don't support the joystick in ScummVM, so draw the next two buttons as disabled + tempStr = "Joystick Off"; + screen.makeButton(Common::Rect(SETUP_POINTS[6][0], SETUP_POINTS[6][1], SETUP_POINTS[6][2], SETUP_POINTS[6][1] + 10), + SETUP_POINTS[6][3] - screen.stringWidth(tempStr) / 2, tempStr); + screen.buttonPrint(Common::Point(SETUP_POINTS[6][3], SETUP_POINTS[6][1]), COMMAND_NULL, false, tempStr); + + tempStr = "Calibrate Joystick"; + screen.makeButton(Common::Rect(SETUP_POINTS[7][0], SETUP_POINTS[7][1], SETUP_POINTS[7][2], SETUP_POINTS[7][1] + 10), + SETUP_POINTS[7][3] - screen.stringWidth(tempStr) / 2, tempStr); + screen.buttonPrint(Common::Point(SETUP_POINTS[7][3], SETUP_POINTS[7][1]), COMMAND_NULL, false, tempStr); + + tempStr = Common::String::format("Fade %s", screen._fadeStyle ? "by Pixel" : "Directly"); + screen.makeButton(Common::Rect(SETUP_POINTS[8][0], SETUP_POINTS[8][1], SETUP_POINTS[8][2], SETUP_POINTS[8][1] + 10), + SETUP_POINTS[8][3] - screen.stringWidth(tempStr) / 2, tempStr); + + tempStr = Common::String::format("Windows %s", ui._windowStyle ? "Slide" : "Appear"); + screen.makeButton(Common::Rect(SETUP_POINTS[9][0], SETUP_POINTS[9][1], SETUP_POINTS[9][2], SETUP_POINTS[9][1] + 10), + SETUP_POINTS[9][3] - screen.stringWidth(tempStr) / 2, tempStr); + + tempStr = Common::String::format("Portraits %s", SETUP_STRS0[people._portraitsOn]); + screen.makeButton(Common::Rect(SETUP_POINTS[10][0], SETUP_POINTS[10][1], SETUP_POINTS[10][2], SETUP_POINTS[10][1] + 10), + SETUP_POINTS[10][3] - screen.stringWidth(tempStr) / 2, tempStr); + tempStr = Common::String::format("Key Pad %s", _vm->_keyPadSpeed ? "Fast" : "Slow"); + + screen.makeButton(Common::Rect(SETUP_POINTS[11][0], SETUP_POINTS[11][1], SETUP_POINTS[11][2], SETUP_POINTS[11][1] + 10), + SETUP_POINTS[11][3] - screen.stringWidth(tempStr) / 2, tempStr); + + // Show the window immediately, or slide it on-screen + if (!flag) { + if (!ui._windowStyle) { + screen.slamRect(Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); + } else { + ui.summonWindow(true, CONTROLS_Y1); + } + + ui._windowOpen = true; + } else { + screen.slamRect(Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); + } +} + +/** + * Draws the buttons for the settings dialog + */ +int Settings::drawButtons(const Common::Point &pt, int _key) { + Events &events = *_vm->_events; + People &people = *_vm->_people; + Screen &screen = *_vm->_screen; + Sound &sound = *_vm->_sound; + UserInterface &ui = *_vm->_ui; + int found = -1; + byte color; + Common::String tempStr; + + for (int idx = 0; idx < 12; ++idx) { + if ((pt.x > SETUP_POINTS[idx][0] && pt.x < SETUP_POINTS[idx][2] && pt.y > SETUP_POINTS[idx][1] + && pt.y < (SETUP_POINTS[idx][1] + 10) && (events._released || events._released)) + || (_key == SETUP_NAMES[idx][0])) { + found = idx; + color = COMMAND_HIGHLIGHTED; + } else { + color = COMMAND_FOREGROUND; + } + + // Print the button text + switch (idx) { + case 1: + tempStr = Common::String::format("Music %s", SETUP_STRS0[sound._music]); + screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr); + break; + case 2: + tempStr = Common::String::format("Voices %s", SETUP_STRS0[sound._voices]); + screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr); + break; + case 3: + tempStr = Common::String::format("Sound Effects %s", SETUP_STRS0[sound._digitized]); + screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr); + break; + case 4: + tempStr = Common::String::format("Auto Help %s", SETUP_STRS2[ui._helpStyle]); + screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr); + break; + case 6: + tempStr = "Joystick Off"; + screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), COMMAND_NULL, true, tempStr); + break; + case 7: + tempStr = "Calibrate Joystick"; + screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), COMMAND_NULL, true, tempStr); + break; + case 8: + tempStr = Common::String::format("Fade %s", SETUP_STRS1[screen._fadeStyle]); + screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr); + break; + case 9: + tempStr = Common::String::format("Windows %s", SETUP_STRS3[ui._windowStyle]); + screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr); + break; + case 10: + tempStr = Common::String::format("Portraits %s", SETUP_STRS0[people._portraitsOn]); + screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr); + break; + case 11: + tempStr = Common::String::format("Key Pad %s", SETUP_STRS4[_vm->_keyPadSpeed]); + screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr); + break; + default: + screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, SETUP_NAMES[idx]); + break; + } + } + + return found; +} + +} // End of namespace Sherlock diff --git a/engines/sherlock/settings.h b/engines/sherlock/settings.h new file mode 100644 index 0000000000..51157f4cae --- /dev/null +++ b/engines/sherlock/settings.h @@ -0,0 +1,45 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef SHERLOCK_SETTINGS_H +#define SHERLOCK_SETTINGS_H + +#include "common/scummsys.h" + +namespace Sherlock { + +class SherlockEngine; + +class Settings { +private: + SherlockEngine *_vm; +public: + Settings(SherlockEngine *vm) : _vm(vm) {} + + void drawInteface(bool flag); + + int drawButtons(const Common::Point &pt, int key); +}; + +} // End of namespace Sherlock + +#endif diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index 21a53c32ff..313f035bd5 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -22,6 +22,7 @@ #include "sherlock/user_interface.h" #include "sherlock/sherlock.h" +#include "sherlock/settings.h" namespace Sherlock { @@ -53,23 +54,6 @@ const int INVENTORY_POINTS[8][3] = { { 285, 315, 294 } }; -const int SETUP_POINTS[12][4] = { - { 4, 154, 101, 53 }, // Exit - { 4, 165, 101, 53 }, // Music Toggle - { 219, 165, 316, 268 }, // Voice Toggle - { 103, 165, 217, 160 }, // Sound Effects Toggle - { 219, 154, 316, 268 }, // Help Button Left/Right - { 103, 154, 217, 160 }, // New Font Style - { 4, 187, 101, 53 }, // Joystick Toggle - { 103, 187, 217, 160 }, // Calibrate Joystick - { 219, 176, 316, 268 }, // Fade Style - { 103, 176, 217, 160 }, // Window Open Style - { 4, 176, 101, 53 }, // Portraits Toggle - { 219, 187, 316, 268 } // _key Pad Accel. Toggle -}; - - - const char COMMANDS[13] = "LMTPOCIUGJFS"; const char INVENTORY_COMMANDS[9] = { "ELUG-+,." }; const char *const PRESS_KEY_FOR_MORE = "Press any Key for More."; @@ -94,174 +78,6 @@ const char *const MUSE[] = { "Doors don't smoke" }; -const char *const SETUP_STRS0[2] = { "off", "on" }; -const char *const SETUP_STRS1[2] = { "Directly", "by Pixel" }; -const char *const SETUP_STRS2[2] = { "Left", "Right" }; -const char *const SETUP_STRS3[2] = { "Appear", "Slide" }; -const char *const SETUP_STRS4[2] = { "Slow", "Fast" }; -const char *const SETUP_STRS5[2] = { "Left", "Right" }; -const char *const SETUP_NAMES[12] = { - "Exit", "M", "V", "S", "B", "New Font Style", "J", "Calibrate Joystick", "F", "W", "P", "K" -}; - -/*----------------------------------------------------------------*/ - -/** - * Draws the interface for the settings window - */ -void Settings::drawInteface(bool flag) { - People &people = *_vm->_people; - Screen &screen = *_vm->_screen; - Sound &sound = *_vm->_sound; - UserInterface &ui = *_vm->_ui; - Common::String tempStr; - - if (!flag) { - screen._backBuffer1.fillRect(Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH, CONTROLS_Y1 + 1), BORDER_COLOR); - screen._backBuffer1.fillRect(Common::Rect(0, CONTROLS_Y1 + 1, 2, SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR); - screen._backBuffer1.fillRect(Common::Rect(SHERLOCK_SCREEN_WIDTH - 2, CONTROLS_Y1 + 1, SHERLOCK_SCREEN_WIDTH, - SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR); - screen._backBuffer1.hLine(0, SHERLOCK_SCREEN_HEIGHT - 1, SHERLOCK_SCREEN_WIDTH - 1, BORDER_COLOR); - screen._backBuffer1.fillRect(Common::Rect(2, CONTROLS_Y1 + 1, SHERLOCK_SCREEN_WIDTH - 2, - SHERLOCK_SCREEN_HEIGHT - 2), INV_BACKGROUND); - } - - screen.makeButton(Common::Rect(SETUP_POINTS[0][0], SETUP_POINTS[0][1], SETUP_POINTS[0][2], SETUP_POINTS[0][1] + 10), - SETUP_POINTS[0][3] - screen.stringWidth("Exit") / 2, "Exit"); - - tempStr = Common::String::format("Music %s", SETUP_STRS0[sound._music]); - screen.makeButton(Common::Rect(SETUP_POINTS[1][0], SETUP_POINTS[1][1], SETUP_POINTS[1][2], SETUP_POINTS[1][1] + 10), - SETUP_POINTS[1][3] - screen.stringWidth(tempStr) / 2, tempStr); - - tempStr = Common::String::format("Voices %s", SETUP_STRS0[sound._voices]); - screen.makeButton(Common::Rect(SETUP_POINTS[2][0], SETUP_POINTS[2][1], SETUP_POINTS[2][2], SETUP_POINTS[2][1] + 10), - SETUP_POINTS[2][3] - screen.stringWidth(tempStr) / 2, tempStr); - - tempStr = Common::String::format("Sound Effects %s", SETUP_STRS0[sound._digitized]); - screen.makeButton(Common::Rect(SETUP_POINTS[3][0], SETUP_POINTS[3][1], SETUP_POINTS[3][2], SETUP_POINTS[3][1] + 10), - SETUP_POINTS[3][3] - screen.stringWidth(tempStr) / 2, tempStr); - - tempStr = Common::String::format("Auto Help %s", SETUP_STRS5[ui._helpStyle]); - screen.makeButton(Common::Rect(SETUP_POINTS[4][0], SETUP_POINTS[4][1], SETUP_POINTS[4][2], SETUP_POINTS[4][1] + 10), - SETUP_POINTS[4][3] - screen.stringWidth(tempStr) / 2, tempStr); - screen.makeButton(Common::Rect(SETUP_POINTS[5][0], SETUP_POINTS[5][1], SETUP_POINTS[5][2], SETUP_POINTS[5][1] + 10), - SETUP_POINTS[5][3] - screen.stringWidth("New Font Style") / 2, "New Font Style"); - - // WORKAROUND: We don't support the joystick in ScummVM, so draw the next two buttons as disabled - tempStr = "Joystick Off"; - screen.makeButton(Common::Rect(SETUP_POINTS[6][0], SETUP_POINTS[6][1], SETUP_POINTS[6][2], SETUP_POINTS[6][1] + 10), - SETUP_POINTS[6][3] - screen.stringWidth(tempStr) / 2, tempStr); - screen.buttonPrint(Common::Point(SETUP_POINTS[6][3], SETUP_POINTS[6][1]), COMMAND_NULL, false, tempStr); - - tempStr = "Calibrate Joystick"; - screen.makeButton(Common::Rect(SETUP_POINTS[7][0], SETUP_POINTS[7][1], SETUP_POINTS[7][2], SETUP_POINTS[7][1] + 10), - SETUP_POINTS[7][3] - screen.stringWidth(tempStr) / 2, tempStr); - screen.buttonPrint(Common::Point(SETUP_POINTS[7][3], SETUP_POINTS[7][1]), COMMAND_NULL, false, tempStr); - - tempStr = Common::String::format("Fade %s", screen._fadeStyle ? "by Pixel" : "Directly"); - screen.makeButton(Common::Rect(SETUP_POINTS[8][0], SETUP_POINTS[8][1], SETUP_POINTS[8][2], SETUP_POINTS[8][1] + 10), - SETUP_POINTS[8][3] - screen.stringWidth(tempStr) / 2, tempStr); - - tempStr = Common::String::format("Windows %s", ui._windowStyle ? "Slide" : "Appear"); - screen.makeButton(Common::Rect(SETUP_POINTS[9][0], SETUP_POINTS[9][1], SETUP_POINTS[9][2], SETUP_POINTS[9][1] + 10), - SETUP_POINTS[9][3] - screen.stringWidth(tempStr) / 2, tempStr); - - tempStr = Common::String::format("Portraits %s", SETUP_STRS0[people._portraitsOn]); - screen.makeButton(Common::Rect(SETUP_POINTS[10][0], SETUP_POINTS[10][1], SETUP_POINTS[10][2], SETUP_POINTS[10][1] + 10), - SETUP_POINTS[10][3] - screen.stringWidth(tempStr) / 2, tempStr); - tempStr = Common::String::format("Key Pad %s", _vm->_keyPadSpeed ? "Fast" : "Slow"); - - screen.makeButton(Common::Rect(SETUP_POINTS[11][0], SETUP_POINTS[11][1], SETUP_POINTS[11][2], SETUP_POINTS[11][1] + 10), - SETUP_POINTS[11][3] - screen.stringWidth(tempStr) / 2, tempStr); - - // Show the window immediately, or slide it on-screen - if (!flag) { - if (!ui._windowStyle) { - screen.slamRect(Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); - } else { - ui.summonWindow(true, CONTROLS_Y1); - } - - ui._windowOpen = true; - } else { - screen.slamRect(Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); - } -} - -/** - * Draws the buttons for the settings dialog - */ -int Settings::drawButtons(const Common::Point &pt, int _key) { - Events &events = *_vm->_events; - People &people = *_vm->_people; - Screen &screen = *_vm->_screen; - Sound &sound = *_vm->_sound; - UserInterface &ui = *_vm->_ui; - int found = -1; - byte color; - Common::String tempStr; - - for (int idx = 0; idx < 12; ++idx) { - if ((pt.x > SETUP_POINTS[idx][0] && pt.x < SETUP_POINTS[idx][2] && pt.y > SETUP_POINTS[idx][1] - && pt.y < (SETUP_POINTS[idx][1] + 10) && (events._released || events._released)) - || (_key == SETUP_NAMES[idx][0])) { - found = idx; - color = COMMAND_HIGHLIGHTED; - } else { - color = COMMAND_FOREGROUND; - } - - // Print the button text - switch (idx) { - case 1: - tempStr = Common::String::format("Music %s", SETUP_STRS0[sound._music]); - screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr); - break; - case 2: - tempStr = Common::String::format("Voices %s", SETUP_STRS0[sound._voices]); - screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr); - break; - case 3: - tempStr = Common::String::format("Sound Effects %s", SETUP_STRS0[sound._digitized]); - screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr); - break; - case 4: - tempStr = Common::String::format("Auto Help %s", SETUP_STRS2[ui._helpStyle]); - screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr); - break; - case 6: - tempStr = "Joystick Off"; - screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), COMMAND_NULL, true, tempStr); - break; - case 7: - tempStr = "Calibrate Joystick"; - screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), COMMAND_NULL, true, tempStr); - break; - case 8: - tempStr = Common::String::format("Fade %s", SETUP_STRS1[screen._fadeStyle]); - screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr); - break; - case 9: - tempStr = Common::String::format("Windows %s", SETUP_STRS3[ui._windowStyle]); - screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr); - break; - case 10: - tempStr = Common::String::format("Portraits %s", SETUP_STRS0[people._portraitsOn]); - screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr); - break; - case 11: - tempStr = Common::String::format("Key Pad %s", SETUP_STRS4[_vm->_keyPadSpeed]); - screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr); - break; - default: - screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, SETUP_NAMES[idx]); - break; - } - } - - return found; -} - /*----------------------------------------------------------------*/ UserInterface::UserInterface(SherlockEngine *vm) : _vm(vm) { diff --git a/engines/sherlock/user_interface.h b/engines/sherlock/user_interface.h index ac2c16d7c2..4e8753199b 100644 --- a/engines/sherlock/user_interface.h +++ b/engines/sherlock/user_interface.h @@ -63,17 +63,6 @@ class Inventory; class Talk; class UserInterface; -class Settings { -private: - SherlockEngine *_vm; -public: - Settings(SherlockEngine *vm) : _vm(vm) {} - - void drawInteface(bool flag); - - int drawButtons(const Common::Point &pt, int key); -}; - class UserInterface { friend class Inventory; friend class Settings; -- cgit v1.2.3 From 86dab70eae4791b84ca3891cad7db70a9683679a Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 1 May 2015 18:34:51 -1000 Subject: SHERLOCK: Remove unused key pad speed field --- engines/sherlock/settings.cpp | 7 ++++--- engines/sherlock/sherlock.cpp | 1 - engines/sherlock/sherlock.h | 1 - engines/sherlock/user_interface.cpp | 7 ------- 4 files changed, 4 insertions(+), 12 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/settings.cpp b/engines/sherlock/settings.cpp index fb7730fc1d..769c2c82e3 100644 --- a/engines/sherlock/settings.cpp +++ b/engines/sherlock/settings.cpp @@ -115,10 +115,11 @@ void Settings::drawInteface(bool flag) { tempStr = Common::String::format("Portraits %s", SETUP_STRS0[people._portraitsOn]); screen.makeButton(Common::Rect(SETUP_POINTS[10][0], SETUP_POINTS[10][1], SETUP_POINTS[10][2], SETUP_POINTS[10][1] + 10), SETUP_POINTS[10][3] - screen.stringWidth(tempStr) / 2, tempStr); - tempStr = Common::String::format("Key Pad %s", _vm->_keyPadSpeed ? "Fast" : "Slow"); + tempStr = "Key Pad Slow"; screen.makeButton(Common::Rect(SETUP_POINTS[11][0], SETUP_POINTS[11][1], SETUP_POINTS[11][2], SETUP_POINTS[11][1] + 10), SETUP_POINTS[11][3] - screen.stringWidth(tempStr) / 2, tempStr); + screen.buttonPrint(Common::Point(SETUP_POINTS[11][3], SETUP_POINTS[11][1]), COMMAND_NULL, false, tempStr); // Show the window immediately, or slide it on-screen if (!flag) { @@ -196,8 +197,8 @@ int Settings::drawButtons(const Common::Point &pt, int _key) { screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr); break; case 11: - tempStr = Common::String::format("Key Pad %s", SETUP_STRS4[_vm->_keyPadSpeed]); - screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr); + tempStr = "Key Pad Slow"; + screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), COMMAND_NULL, true, tempStr); break; default: screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, SETUP_NAMES[idx]); diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index 3ab2caabc4..0282d3e5f0 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -47,7 +47,6 @@ SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gam _ui = nullptr; _useEpilogue2 = false; _loadingSavedGame = false; - _keyPadSpeed = 0; _loadGameSlot = -1; _canLoadSave = false; } diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h index 02e2e99229..dfaaa70806 100644 --- a/engines/sherlock/sherlock.h +++ b/engines/sherlock/sherlock.h @@ -106,7 +106,6 @@ public: Common::String _titleOverride; bool _useEpilogue2; bool _loadingSavedGame; - int _keyPadSpeed; int _loadGameSlot; bool _canLoadSave; public: diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index 313f035bd5..cab0fb0ad8 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -1968,13 +1968,6 @@ void UserInterface::doControls() { updateConfig = true; settings.drawInteface(true); } - - if ((found == 11 && events._released) || _key == 'K') { - // Toggle keypad acceleration speed - _vm->_keyPadSpeed ^= 1; - updateConfig = true; - settings.drawInteface(true); - } } while (!_vm->shouldQuit()); banishWindow(); -- cgit v1.2.3 From 850bd739687129542c37db0beebd17369c71ed15 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 1 May 2015 18:47:13 -1000 Subject: SHERLOCK: Move Settings dialog event handling into Settings class --- engines/sherlock/settings.cpp | 138 ++++++++++++++++++++++++++++++++++ engines/sherlock/settings.h | 5 +- engines/sherlock/sherlock.cpp | 3 + engines/sherlock/user_interface.cpp | 146 +----------------------------------- engines/sherlock/user_interface.h | 2 - 5 files changed, 146 insertions(+), 148 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/settings.cpp b/engines/sherlock/settings.cpp index 769c2c82e3..aeeb92d3c1 100644 --- a/engines/sherlock/settings.cpp +++ b/engines/sherlock/settings.cpp @@ -209,4 +209,142 @@ int Settings::drawButtons(const Common::Point &pt, int _key) { return found; } + +/** +* Handles input when the settings window is being shown +* @remarks Whilst this would in theory be better in the Journal class, since it displays in +* the user interface, it uses so many internal UI fields, that it sort of made some sense +* to put it in the UserInterface class. +*/ +void Settings::show(SherlockEngine *vm) { + Events &events = *vm->_events; + People &people = *vm->_people; + Scene &scene = *vm->_scene; + Screen &screen = *vm->_screen; + Sound &sound = *vm->_sound; + Talk &talk = *vm->_talk; + UserInterface &ui = *vm->_ui; + int found; + bool updateConfig = false; + + Settings settings(vm); + settings.drawInteface(false); + + do { + if (ui._menuCounter) + ui.whileMenuCounter(); + + found = -1; + ui._key = -1; + + scene.doBgAnim(); + if (talk._talkToAbort) + return; + + events.setButtonState(); + Common::Point pt = events.mousePos(); + + if (events._pressed || events._released || events.kbHit()) { + ui.clearInfo(); + ui._key = -1; + + if (events.kbHit()) { + Common::KeyState keyState = events.getKey(); + ui._key = toupper(keyState.keycode); + + if (ui._key == Common::KEYCODE_RETURN || ui._key == Common::KEYCODE_SPACE) { + events._pressed = false; + events._oldButtons = 0; + ui._keycode = Common::KEYCODE_INVALID; + events._released = true; + } + } + + // Handle highlighting button under mouse + found = settings.drawButtons(pt, ui._key); + } + + if ((found == 0 && events._released) || (ui._key == 'E' || ui._key == Common::KEYCODE_ESCAPE)) + // Exit + break; + + if ((found == 1 && events._released) || ui._key == 'M') { + // Toggle music + if (sound._music) { + sound.stopSound(); + sound._music = false; + } + else { + sound._music = true; + sound.startSong(); + } + + updateConfig = true; + settings.drawInteface(true); + } + + if ((found == 2 && events._released) || ui._key == 'V') { + sound._voices = !sound._voices; + updateConfig = true; + settings.drawInteface(true); + } + + if ((found == 3 && events._released) || ui._key == 'S') { + // Toggle sound effects + sound._digitized = !sound._digitized; + updateConfig = true; + settings.drawInteface(true); + } + + if ((found == 4 && events._released) || ui._key == 'A') { + // Help button style + ui._helpStyle ^= 1; + updateConfig = true; + settings.drawInteface(true); + } + + if ((found == 5 && events._released) || ui._key == 'N') { + // New font style + int fontNum = screen.fontNumber() + 1; + if (fontNum == 3) + fontNum = 0; + + screen.setFont(fontNum); + updateConfig = true; + settings.drawInteface(true); + } + + if ((found == 8 && events._released) || ui._key == 'F') { + // Toggle fade style + screen._fadeStyle = !screen._fadeStyle; + updateConfig = true; + settings.drawInteface(true); + } + + if ((found == 9 && events._released) || ui._key == 'W') { + // Window style + ui._windowStyle ^= 1; + updateConfig = true; + settings.drawInteface(true); + } + + if ((found == 10 && events._released) || ui._key == 'P') { + // Toggle portraits being shown + people._portraitsOn = !people._portraitsOn; + updateConfig = true; + settings.drawInteface(true); + } + } while (!vm->shouldQuit()); + + ui.banishWindow(); + + if (updateConfig) + vm->saveConfig(); + + ui._keycode = Common::KEYCODE_INVALID; + ui._keyboardInput = false; + ui._windowBounds.top = CONTROLS_Y1; + ui._key = -1; +} + } // End of namespace Sherlock diff --git a/engines/sherlock/settings.h b/engines/sherlock/settings.h index 51157f4cae..90928452c4 100644 --- a/engines/sherlock/settings.h +++ b/engines/sherlock/settings.h @@ -28,16 +28,19 @@ namespace Sherlock { class SherlockEngine; +class UserInterface; class Settings { private: SherlockEngine *_vm; -public: + Settings(SherlockEngine *vm) : _vm(vm) {} void drawInteface(bool flag); int drawButtons(const Common::Point &pt, int key); +public: + static void show(SherlockEngine *vm); }; } // End of namespace Sherlock diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index 0282d3e5f0..f546e0d878 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -214,6 +214,8 @@ void SherlockEngine::loadConfig() { // Load other settings if (ConfMan.hasKey("font")) _screen->setFont(ConfMan.getInt("font")); + if (ConfMan.hasKey("fade_style")) + _screen->_fadeStyle = ConfMan.getBool("fade_style"); if (ConfMan.hasKey("help_style")) _ui->_helpStyle = ConfMan.getInt("help_style"); if (ConfMan.hasKey("window_style")) @@ -231,6 +233,7 @@ void SherlockEngine::saveConfig() { ConfMan.setBool("speech_mute", _sound->_voices); ConfMan.setInt("font", _screen->fontNumber()); + ConfMan.setBool("fade_style", _screen->_fadeStyle); ConfMan.setInt("help_style", _ui->_helpStyle); ConfMan.setInt("window_style", _ui->_windowStyle); ConfMan.setBool("portraits_on", _people->_portraitsOn); diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index cab0fb0ad8..73058e8fd8 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -1440,7 +1440,7 @@ void UserInterface::doMainControl() { case 'S': pushButton(11); _menuMode = SETUP_MODE; - doControls(); + Settings::show(_vm); break; default: break; @@ -1837,150 +1837,6 @@ void UserInterface::journalControl() { screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT); } -/** - * Handles input when the settings window is being shown - * @remarks Whilst this would in theory be better in the Journal class, since it displays in - * the user interface, it uses so many internal UI fields, that it sort of made some sense - * to put it in the UserInterface class. - */ -void UserInterface::doControls() { - Events &events = *_vm->_events; - People &people = *_vm->_people; - Scene &scene = *_vm->_scene; - Screen &screen = *_vm->_screen; - Sound &sound = *_vm->_sound; - Talk &talk = *_vm->_talk; - UserInterface &ui = *_vm->_ui; - int found; - bool updateConfig = false; - - Settings settings(_vm); - settings.drawInteface(false); - - do { - if (_menuCounter) - whileMenuCounter(); - - found = -1; - _key = -1; - - scene.doBgAnim(); - if (talk._talkToAbort) - return; - - events.setButtonState(); - Common::Point pt = events.mousePos(); - - if (events._pressed || events._released || events.kbHit()) { - clearInfo(); - _key = -1; - - if (events.kbHit()) { - Common::KeyState keyState = events.getKey(); - _key = toupper(keyState.keycode); - - if (_key == Common::KEYCODE_RETURN || _key == Common::KEYCODE_SPACE) { - events._pressed = false; - events._oldButtons = 0; - _keycode = Common::KEYCODE_INVALID; - events._released = true; - } - } - - // Handle highlighting button under mouse - found = settings.drawButtons(pt, _key); - } - - if ((found == 0 && events._released) || (_key == 'E' || _key == Common::KEYCODE_ESCAPE)) - // Exit - break; - - if ((found == 1 && events._released) || _key == 'M') { - // Toggle music - if (sound._music) { - sound.stopSound(); - sound._music = false; - } else { - sound._music = true; - sound.startSong(); - } - - updateConfig = true; - settings.drawInteface(true); - } - - if ((found == 2 && events._released) || _key == 'V') { - sound._voices = !sound._voices; - updateConfig = true; - settings.drawInteface(true); - } - - if ((found == 3 && events._released) || _key == 'S') { - // Toggle sound effects - sound._digitized = !sound._digitized; - updateConfig = true; - settings.drawInteface(true); - } - - if ((found == 4 && events._released) || _key == 'A') { - // Help button style - ui._helpStyle ^= 1; - updateConfig = true; - settings.drawInteface(true); - } - - if ((found == 5 && events._released) || _key == 'N') { - // New font style - int fontNum = screen.fontNumber() + 1; - if (fontNum == 3) - fontNum = 0; - - screen.setFont(fontNum); - updateConfig = true; - settings.drawInteface(true); - } - - if ((found == 6 && events._released) || _key == 'J') { - // Toggle joystick - not implemented under ScummVM - } - - if ((found == 7 && events._released) || _key == 'C') { - // Calibrate joystick - No implementation in ScummVM - } - - if ((found == 8 && events._released) || _key == 'F') { - // Toggle fade style - screen._fadeStyle = !screen._fadeStyle; - updateConfig = true; - settings.drawInteface(true); - } - - if ((found == 9 && events._released) || _key == 'W') { - // Window style - ui._windowStyle ^= 1; - updateConfig = true; - settings.drawInteface(true); - } - - if ((found == 10 && events._released) || _key == 'P') { - // Toggle portraits being shown - people._portraitsOn = !people._portraitsOn; - updateConfig = true; - settings.drawInteface(true); - } - } while (!_vm->shouldQuit()); - - banishWindow(); - - if (updateConfig) - _vm->saveConfig(); - - _keycode = Common::KEYCODE_INVALID; - _keyboardInput = false; - _windowBounds.top = CONTROLS_Y1; - _key = -1; -} - /** * Print the description of an object */ diff --git a/engines/sherlock/user_interface.h b/engines/sherlock/user_interface.h index 4e8753199b..89a33801dd 100644 --- a/engines/sherlock/user_interface.h +++ b/engines/sherlock/user_interface.h @@ -111,8 +111,6 @@ private: void doTalkControl(); void journalControl(); - void doControls(); - void checkUseAction(const UseType *use, const Common::String &invName, const char *const messages[], int objNum, int giveMode); void checkAction(ActionType &action, const char *const messages[], int objNum); -- cgit v1.2.3 From 7cf9fcd44e58a5a4b1988bb5ca6ec6862170c3d8 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 1 May 2015 19:13:53 -1000 Subject: SHERLOCK: Change _helpStyle from int to bool --- engines/sherlock/settings.cpp | 2 +- engines/sherlock/sherlock.cpp | 4 ++-- engines/sherlock/user_interface.cpp | 2 +- engines/sherlock/user_interface.h | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/settings.cpp b/engines/sherlock/settings.cpp index aeeb92d3c1..1673eca389 100644 --- a/engines/sherlock/settings.cpp +++ b/engines/sherlock/settings.cpp @@ -298,7 +298,7 @@ void Settings::show(SherlockEngine *vm) { if ((found == 4 && events._released) || ui._key == 'A') { // Help button style - ui._helpStyle ^= 1; + ui._helpStyle = !ui._helpStyle; updateConfig = true; settings.drawInteface(true); } diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index f546e0d878..c33ecb6d49 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -217,7 +217,7 @@ void SherlockEngine::loadConfig() { if (ConfMan.hasKey("fade_style")) _screen->_fadeStyle = ConfMan.getBool("fade_style"); if (ConfMan.hasKey("help_style")) - _ui->_helpStyle = ConfMan.getInt("help_style"); + _ui->_helpStyle = ConfMan.getBool("help_style"); if (ConfMan.hasKey("window_style")) _ui->_windowStyle = ConfMan.getInt("window_style"); if (ConfMan.hasKey("portraits_on")) @@ -234,7 +234,7 @@ void SherlockEngine::saveConfig() { ConfMan.setInt("font", _screen->fontNumber()); ConfMan.setBool("fade_style", _screen->_fadeStyle); - ConfMan.setInt("help_style", _ui->_helpStyle); + ConfMan.setBool("help_style", _ui->_helpStyle); ConfMan.setInt("window_style", _ui->_windowStyle); ConfMan.setBool("portraits_on", _people->_portraitsOn); diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index 73058e8fd8..d75e0770b9 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -86,7 +86,7 @@ UserInterface::UserInterface(SherlockEngine *vm) : _vm(vm) { _bgFound = 0; _oldBgFound = -1; _keycode = Common::KEYCODE_INVALID; - _helpStyle = 0; + _helpStyle = false; _menuCounter = 0; _menuMode = STD_MODE; _help = _oldHelp = 0; diff --git a/engines/sherlock/user_interface.h b/engines/sherlock/user_interface.h index 89a33801dd..a0b854af36 100644 --- a/engines/sherlock/user_interface.h +++ b/engines/sherlock/user_interface.h @@ -123,7 +123,7 @@ public: int _invLookFlag; int _temp1; int _windowStyle; - int _helpStyle; + bool _helpStyle; public: UserInterface(SherlockEngine *vm); ~UserInterface(); -- cgit v1.2.3 From 8fab80ce4750ad65b6e289614034478cebdf7854 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 1 May 2015 20:31:43 -1000 Subject: SHERLOCK: Tweak doBgAnim delays to better match original game --- engines/sherlock/scene.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index e69fb49766..ab57e9cfd2 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -1387,9 +1387,9 @@ void Scene::doBgAnim() { } _restoreFlag = true; - - events.wait(1); _doBgAnimDone = true; + + events.wait(3); screen.resetDisplayBounds(); // Check if the method was called for calling a portrait, and a talk was -- cgit v1.2.3 From 90b35d2381488daa4cf54101ebd8f4b9e8ca0083 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 1 May 2015 20:33:56 -1000 Subject: SHERLOCK: Allow fast quitting when randomTransition in progress --- engines/sherlock/screen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp index d170772c98..1f56261150 100644 --- a/engines/sherlock/screen.cpp +++ b/engines/sherlock/screen.cpp @@ -216,7 +216,7 @@ void Screen::randomTransition() { const int TRANSITION_MULTIPLIER = 0x15a4e35; _dirtyRects.clear(); - for (int idx = 0; idx <= 65535; ++idx) { + for (int idx = 0; idx <= 65535 && !_vm->shouldQuit(); ++idx) { _transitionSeed = _transitionSeed * TRANSITION_MULTIPLIER + 1; int offset = _transitionSeed & 65535; -- cgit v1.2.3 From cd2ead0a78d2f78cd0b4aecddf4e54520483855f Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 2 May 2015 21:41:19 +0200 Subject: SCI: lsl5 script patch to fix game breaking bug fixes green card phone number also calling limo at the same time bug for the English PC 1.000 release. --- engines/sci/engine/script_patches.cpp | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'engines') diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp index 173641f7ee..4011273ca3 100644 --- a/engines/sci/engine/script_patches.cpp +++ b/engines/sci/engine/script_patches.cpp @@ -1425,6 +1425,37 @@ static const SciScriptPatcherEntry larry2Signatures[] = { // =========================================================================== // Leisure Suit Larry 5 +// In Miami the player can call the green card telephone number and get +// green card including limo at the same time in the English 1.000 PC release. +// This results later in a broken game in case the player doesn't read +// the second telephone number for the actual limousine service, because +// in that case it's impossible for the player to get back to the airport. +// +// We disable the code, that is responsible to make the limo arrive. +// +// This bug was fixed in the European (dual language) versions of the game. +// +// Applies to at least: English PC floppy (1.000) +// Responsible method: sPhone::changeState(40) +static const uint16 larry5SignatureGreenCardLimoBug[] = { + 0x7a, // push2 + SIG_MAGICDWORD, + 0x39, 0x07, // pushi 07 + 0x39, 0x0c, // pushi 0Ch + 0x45, 0x0a, 0x04, // call export 10 of script 0 + 0x78, // push1 + 0x39, 0x26, // pushi 26h (limo arrived flag) + 0x45, 0x07, 0x02, // call export 7 of script 0 (sets flag) + SIG_END +}; + +static const uint16 larry5PatchGreenCardLimoBug[] = { + PATCH_ADDTOOFFSET(+8), + 0x34, PATCH_UINT16(0), // ldi 0000 (dummy) + 0x34, PATCH_UINT16(0), // ldi 0000 (dummy) + PATCH_END +}; + // In one of the conversations near the end (to be exact - room 380 and the text // about using champagne on Reverse Biaz - only used when you actually did that // in the game), the German text is too large, causing the textbox to get too large. @@ -1448,6 +1479,7 @@ static const uint16 larry5PatchGermanEndingPattiTalker[] = { // script, description, signature patch static const SciScriptPatcherEntry larry5Signatures[] = { + { true, 280, "English-only: fix green card limo bug", 1, larry5SignatureGreenCardLimoBug, larry5PatchGreenCardLimoBug }, { true, 380, "German-only: Enlarge Patti Textbox", 1, larry5SignatureGermanEndingPattiTalker, larry5PatchGermanEndingPattiTalker }, SCI_SIGNATUREENTRY_TERMINATOR }; -- cgit v1.2.3 From dceff029220aff2efcb7a533d2403c90b5651870 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 2 May 2015 13:53:20 -1000 Subject: SHERLOCK: Fix trying to enter theatre without talking to Lestrade --- engines/sherlock/user_interface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index d75e0770b9..93dd03316d 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -1469,7 +1469,7 @@ void UserInterface::doMiscControl(int allowed) { switch (allowed) { case ALLOW_OPEN: checkAction(obj._aOpen, MOPEN, _temp); - if (_menuMode && !talk._talkToAbort) { + if (_menuMode != TALK_MODE && !talk._talkToAbort) { _menuMode = STD_MODE; restoreButton(OPEN_MODE - 1); _key = _oldKey = -1; -- cgit v1.2.3 From eb4757d6e31171bde9b03fa44c20ab490639b5c0 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 2 May 2015 14:34:49 -1000 Subject: SHERLOCK: Fix original game bug when testing powdery substance --- engines/sherlock/talk.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'engines') diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index d05c09ab38..9af8a29c1e 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -433,6 +433,12 @@ void Talk::talkTo(const Common::String &filename) { // previous script can continue popStack(); + if (_vm->getGameID() == GType_SerratedScalpel && filename == "Tube59c") { + // WORKAROUND: Original game bug causes the results of testing the powdery substance + // to disappear too quickly. Introduce a delay to allow it to be properly displayed + ui._menuCounter = 30; + } + events.setCursor(ARROW); } -- cgit v1.2.3 From 9ff445497fe53b72193dcf944b54091080c90964 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 2 May 2015 16:29:08 -1000 Subject: SHERLOCK: Properly close door when entering Sarah's flat --- engines/sherlock/objects.cpp | 2 +- engines/sherlock/scene.cpp | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index fa5dfee26c..6f4795de7e 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -728,7 +728,7 @@ bool Object::checkEndOfSequence() { // Save details before shape is removed _delta.x = _imageFrame->_frame.w; _delta.y = _imageFrame->_frame.h; - _position = _imageFrame->_offset; + _position += _imageFrame->_offset; // Free the images delete _images; diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index ab57e9cfd2..2c5859024c 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -931,7 +931,7 @@ int Scene::startCAnim(int cAnimNum, int playRate) { cObj._frameNumber = -1; cObj._sequenceNumber = cAnimNum; cObj._oldPosition = Common::Point(0, 0); - cObj._oldPosition = Common::Point(0, 0); + cObj._oldSize = Common::Point(0, 0); cObj._goto = Common::Point(0, 0); cObj._status = 0; cObj._misc = 0; @@ -1050,6 +1050,10 @@ int Scene::startCAnim(int cAnimNum, int playRate) { cObj.checkObject(); for (uint idx = 0; idx < _canimShapes.size(); ++idx) { if (&_canimShapes[idx] == &cObj) { + // Do a final call to doBgAnim to erase the anim shape before it's erased + doBgAnim(); + + // Remove the completed sprite from the animation shapes array _canimShapes.remove_at(idx); break; } @@ -1372,7 +1376,7 @@ void Scene::doBgAnim() { } } - for (int idx = _canimShapes.size() - 1; idx >= 0; --idx) { + for (uint idx = 0; idx < _canimShapes.size(); ++idx) { Object &o = _canimShapes[idx]; if (o._type == REMOVE) { if (_goToScene == -1) -- cgit v1.2.3 From f97e550d8631bc1821da1c126ae545db15769c9c Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 2 May 2015 17:48:07 -1000 Subject: SHERLOCK: Don't mark leaving scene as visited during savegame loads --- engines/sherlock/saveload.cpp | 1 - engines/sherlock/scene.cpp | 11 +++++++---- engines/sherlock/scene.h | 1 + engines/sherlock/sherlock.cpp | 2 -- engines/sherlock/sherlock.h | 1 - 5 files changed, 8 insertions(+), 8 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/saveload.cpp b/engines/sherlock/saveload.cpp index 86a4e8417a..71e21618ae 100644 --- a/engines/sherlock/saveload.cpp +++ b/engines/sherlock/saveload.cpp @@ -388,7 +388,6 @@ void SaveManager::synchronize(Common::Serializer &s) { if (screen.fontNumber() != oldFont) journal.resetPosition(); - _vm->_loadingSavedGame = true; _justLoaded = true; } diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 2c5859024c..e3c1799d66 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -88,6 +88,7 @@ Scene::Scene(SherlockEngine *vm): _vm(vm) { Common::fill(&_sceneStats[idx][0], &_sceneStats[idx][65], false); _currentScene = -1; _goToScene = -1; + _loadingSavedGame = false; _changes = false; _keyboardInput = 0; _walkedInScene = false; @@ -162,10 +163,10 @@ void Scene::freeScene() { _vm->_sound->freeSong(); _vm->_sound->freeLoadedSounds(); - if (!_vm->_loadingSavedGame) + if (!_loadingSavedGame) saveSceneStatus(); else - _vm->_loadingSavedGame = false; + _loadingSavedGame = false; _sequenceBuffer.clear(); _descText.clear(); @@ -1494,10 +1495,12 @@ void Scene::synchronize(Common::Serializer &s) { if (s.isSaving()) saveSceneStatus(); - if (s.isSaving()) + if (s.isSaving()) { s.syncAsSint16LE(_currentScene); - else + } else { s.syncAsSint16LE(_goToScene); + _loadingSavedGame = true; + } for (int sceneNum = 0; sceneNum < SCENES_COUNT; ++sceneNum) { for (int flag = 0; flag < 65; ++flag) { diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h index 4fb7ac228a..7ee7db1119 100644 --- a/engines/sherlock/scene.h +++ b/engines/sherlock/scene.h @@ -89,6 +89,7 @@ private: Common::String _rrmName; int _selector; bool _lookHelp; + bool _loadingSavedGame; bool loadScene(const Common::String &filename); diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index c33ecb6d49..b8948f99d8 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -46,7 +46,6 @@ SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gam _talk = nullptr; _ui = nullptr; _useEpilogue2 = false; - _loadingSavedGame = false; _loadGameSlot = -1; _canLoadSave = false; } @@ -164,7 +163,6 @@ void SherlockEngine::sceneLoop() { } } - _scene->freeScene(); _people->freeWalk(); } diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h index dfaaa70806..95fe514e0c 100644 --- a/engines/sherlock/sherlock.h +++ b/engines/sherlock/sherlock.h @@ -105,7 +105,6 @@ public: Common::String _soundOverride; Common::String _titleOverride; bool _useEpilogue2; - bool _loadingSavedGame; int _loadGameSlot; bool _canLoadSave; public: -- cgit v1.2.3 From 0a2c50deb5c61500410a91556ed5e3ceb0cc9742 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 2 May 2015 18:15:24 -1000 Subject: SHERLOCK: Revised door close fix due to new bug when entering morgue --- engines/sherlock/scene.cpp | 31 +++++++++++++++++-------------- engines/sherlock/scene.h | 7 ++++++- 2 files changed, 23 insertions(+), 15 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index e3c1799d66..6e7f628616 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -83,6 +83,17 @@ void SceneSound::synchronize(Common::SeekableReadStream &s) { /*----------------------------------------------------------------*/ +int ObjectArray::indexOf(const Object &obj) const { + for (uint idx = 0; idx < size(); ++idx) { + if (&(*this)[idx] == &obj) + return idx; + } + + return -1; +} + +/*----------------------------------------------------------------*/ + Scene::Scene(SherlockEngine *vm): _vm(vm) { for (int idx = 0; idx < SCENES_COUNT; ++idx) Common::fill(&_sceneStats[idx][0], &_sceneStats[idx][65], false); @@ -1047,18 +1058,9 @@ int Scene::startCAnim(int cAnimNum, int playRate) { if (cObj._frameNumber <= 26) gotoCode = cObj._sequences[cObj._frameNumber + 3]; - // Set canim to REMOVE type and free memory - cObj.checkObject(); - for (uint idx = 0; idx < _canimShapes.size(); ++idx) { - if (&_canimShapes[idx] == &cObj) { - // Do a final call to doBgAnim to erase the anim shape before it's erased - doBgAnim(); - - // Remove the completed sprite from the animation shapes array - _canimShapes.remove_at(idx); - break; - } - } + // Unless anim shape has already been freed, set it to REMOVE so doBgAnim can free it + if (_canimShapes.indexOf(cObj) != -1) + cObj.checkObject(); if (gotoCode > 0 && !talk._talkToAbort) { _goToScene = gotoCode; @@ -1377,13 +1379,14 @@ void Scene::doBgAnim() { } } - for (uint idx = 0; idx < _canimShapes.size(); ++idx) { + for (int idx = _canimShapes.size() - 1; idx >= 0; --idx) { Object &o = _canimShapes[idx]; if (o._type == REMOVE) { if (_goToScene == -1) screen.slamArea(o._position.x, o._position.y, o._delta.x, o._delta.y); - _canimShapes[idx]._type = INVALID; + // Shape for an animation is no longer needed, so remove it completely + _canimShapes.remove_at(idx); } else if (o._type == ACTIVE_BG_SHAPE) { screen.flushImage(o._imageFrame, o._position, &o._oldPosition.x, &o._oldPosition.y, &o._oldSize.x, &o._oldSize.y); diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h index 7ee7db1119..c2cca8bad2 100644 --- a/engines/sherlock/scene.h +++ b/engines/sherlock/scene.h @@ -83,6 +83,11 @@ struct SceneSound { void synchronize(Common::SeekableReadStream &s); }; +class ObjectArray: public Common::Array { +public: + int indexOf(const Object &obj) const; +}; + class Scene { private: SherlockEngine *_vm; @@ -127,7 +132,7 @@ public: Common::Array _exits; SceneEntry _entrance; Common::Array _sounds; - Common::Array _canimShapes; + ObjectArray _canimShapes; bool _restoreFlag; int _animating; bool _doBgAnimDone; -- cgit v1.2.3 From c5d5694883a48974cf85f5d2a854d3a7c5d8b1d4 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 2 May 2015 18:51:13 -1000 Subject: SHERLOCK: Fix gfx glitch when returning to morgue for a second time --- engines/sherlock/scene.cpp | 5 +++++ engines/sherlock/sherlock.cpp | 1 + 2 files changed, 6 insertions(+) (limited to 'engines') diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 6e7f628616..8a47707aea 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -169,6 +169,9 @@ void Scene::selectScene() { * Fres all the graphics and other dynamically allocated data for the scene */ void Scene::freeScene() { + if (_currentScene == -1) + return; + _vm->_talk->freeTalkVars(); _vm->_inventory->freeInv(); _vm->_sound->freeSong(); @@ -190,6 +193,8 @@ void Scene::freeScene() { for (uint idx = 0; idx < _images.size(); ++idx) delete _images[idx]._images; _images.clear(); + + _currentScene = -1; } /** diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index b8948f99d8..8b25615792 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -163,6 +163,7 @@ void SherlockEngine::sceneLoop() { } } + _scene->freeScene(); _people->freeWalk(); } -- cgit v1.2.3 From d39f93af689bc014e3f4da580fe370be12db275c Mon Sep 17 00:00:00 2001 From: Christian Krause Date: Sun, 3 May 2015 12:17:59 +0200 Subject: SWORD25: Draw next movie frame only when an update is needed This fixes the problem that the movies are played too fast and get out of sync with additionally played speech samples. --- engines/sword25/fmv/movieplayer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sword25/fmv/movieplayer.cpp b/engines/sword25/fmv/movieplayer.cpp index 5d7dcf2506..eb0f0390dc 100644 --- a/engines/sword25/fmv/movieplayer.cpp +++ b/engines/sword25/fmv/movieplayer.cpp @@ -123,7 +123,7 @@ void MoviePlayer::update() { if (_decoder.endOfVideo()) { // Movie complete, so unload the movie unloadMovie(); - } else { + } else if (_decoder.needsUpdate()) { const Graphics::Surface *s = _decoder.decodeNextFrame(); if (s) { // Transfer the next frame -- cgit v1.2.3 From 30b5497e24965849469be0ff5c2620eef5ebfa0e Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Sun, 3 May 2015 13:44:07 +0200 Subject: SCI: Clarify function name --- engines/sci/engine/savegame.cpp | 2 +- engines/sci/graphics/screen.cpp | 4 ++-- engines/sci/graphics/screen.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 8fca7eabca..93b3a997cc 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -923,7 +923,7 @@ void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { g_sci->_gfxPorts->reset(); // clear screen if (g_sci->_gfxScreen) - g_sci->_gfxScreen->clear(); + g_sci->_gfxScreen->clearForRestoreGame(); #ifdef ENABLE_SCI32 // Also clear any SCI32 planes/screen items currently showing so they // don't show up after the load. diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp index dfcb5dbc14..ca5b5b3b8c 100644 --- a/engines/sci/graphics/screen.cpp +++ b/engines/sci/graphics/screen.cpp @@ -251,8 +251,8 @@ GfxScreen::~GfxScreen() { free(_displayScreen); } -// should not used regulary, only meant for restore game -void GfxScreen::clear() { +// should not be used regularly; only meant for restore game +void GfxScreen::clearForRestoreGame() { // reset all screen data memset(_visualScreen, 0, _pixels); memset(_priorityScreen, 0, _pixels); diff --git a/engines/sci/graphics/screen.h b/engines/sci/graphics/screen.h index 587d2ef3bc..1c946ef02f 100644 --- a/engines/sci/graphics/screen.h +++ b/engines/sci/graphics/screen.h @@ -76,7 +76,7 @@ public: byte getColorWhite() { return _colorWhite; } byte getColorDefaultVectorData() { return _colorDefaultVectorData; } - void clear(); + void clearForRestoreGame(); void copyToScreen(); void copyFromScreen(byte *buffer); void kernelSyncWithFramebuffer(); -- cgit v1.2.3 From 3d0c691694ddcf00a5bfc347626d38625f057dee Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Sun, 3 May 2015 17:17:25 +0200 Subject: SCI: Handle pronouns in parser When parsing a sentence, its type 0x142 word (presumably the object) is now stored. Any pronouns (type 0x080) are then automatically replaced by this stored word. --- engines/sci/engine/kparse.cpp | 3 ++ engines/sci/parser/vocabulary.cpp | 77 +++++++++++++++++++++++++++++++++++++++ engines/sci/parser/vocabulary.h | 12 ++++++ 3 files changed, 92 insertions(+) (limited to 'engines') diff --git a/engines/sci/engine/kparse.cpp b/engines/sci/engine/kparse.cpp index aa89b963cc..f85f33e3e8 100644 --- a/engines/sci/engine/kparse.cpp +++ b/engines/sci/engine/kparse.cpp @@ -117,6 +117,8 @@ reg_t kParse(EngineState *s, int argc, reg_t *argv) { } #endif + voc->replacePronouns(words); + int syntax_fail = voc->parseGNF(words); if (syntax_fail) { @@ -130,6 +132,7 @@ reg_t kParse(EngineState *s, int argc, reg_t *argv) { } else { voc->parserIsValid = true; + voc->storePronounReference(); writeSelectorValue(segMan, event, SELECTOR(claimed), 0); #ifdef DEBUG_PARSER diff --git a/engines/sci/parser/vocabulary.cpp b/engines/sci/parser/vocabulary.cpp index 000b037b44..828a57abeb 100644 --- a/engines/sci/parser/vocabulary.cpp +++ b/engines/sci/parser/vocabulary.cpp @@ -74,6 +74,8 @@ Vocabulary::Vocabulary(ResourceManager *resMan, bool foreign) : _resMan(resMan), parser_event = NULL_REG; parserIsValid = false; + + _pronounReference = 0x1000; // Non-existent word } Vocabulary::~Vocabulary() { @@ -738,4 +740,79 @@ int Vocabulary::parseNodes(int *i, int *pos, int type, int nr, int argc, const c return oldPos; } + +// FIXME: Duplicated from said.cpp +static int node_major(ParseTreeNode* node) { + assert(node->type == kParseTreeBranchNode); + assert(node->left->type == kParseTreeLeafNode); + return node->left->value; +} +static bool node_is_terminal(ParseTreeNode* node) { + return (node->right->right && + node->right->right->type != kParseTreeBranchNode); +} +static int node_terminal_value(ParseTreeNode* node) { + assert(node_is_terminal(node)); + return node->right->right->value; +} + +static ParseTreeNode* scanForMajor(ParseTreeNode *tree, int major) { + assert(tree); + + if (node_is_terminal(tree)) { + if (node_major(tree) == major) + return tree; + else + return 0; + } + + ParseTreeNode* ptr = tree->right; + + // Scan children + while (ptr->right) { + ptr = ptr->right; + + if (node_major(ptr->left) == major) + return ptr->left; + } + + if (major == 0x141) + return 0; + + // If not found, go into a 0x141 and try again + tree = scanForMajor(tree, 0x141); + if (!tree) + return 0; + return scanForMajor(tree, major); +} + +bool Vocabulary::storePronounReference() { + assert(parserIsValid); + + ParseTreeNode *ptr = scanForMajor(_parserNodes, 0x142); // 0x142 = object? + + while (ptr && !node_is_terminal(ptr)) + ptr = scanForMajor(ptr, 0x141); + + if (!ptr) + return false; + + _pronounReference = node_terminal_value(ptr); + + debugC(kDebugLevelParser, "Stored pronoun reference: %x", _pronounReference); + return true; +} + +void Vocabulary::replacePronouns(ResultWordListList &words) { + if (_pronounReference == 0x1000) + return; + + for (ResultWordListList::iterator i = words.begin(); i != words.end(); ++i) + for (ResultWordList::iterator j = i->begin(); j != i->end(); ++j) + if (j->_class & (VOCAB_CLASS_PRONOUN << 4)) { + j->_class = VOCAB_CLASS_NOUN << 4; + j->_group = _pronounReference; + } +} + } // End of namespace Sci diff --git a/engines/sci/parser/vocabulary.h b/engines/sci/parser/vocabulary.h index 09499946cb..f4adee6e55 100644 --- a/engines/sci/parser/vocabulary.h +++ b/engines/sci/parser/vocabulary.h @@ -232,6 +232,16 @@ public: */ int parseGNF(const ResultWordListList &words, bool verbose = false); + /** + * Find and store reference for future pronouns + */ + bool storePronounReference(); + + /** + * Replace pronouns by stored reference + */ + void replacePronouns(ResultWordListList &words); + /** * Constructs the Greibach Normal Form of the grammar supplied in 'branches'. * @param verbose Set to true for debugging. If true, the list is @@ -360,6 +370,8 @@ private: SynonymList _synonyms; /**< The list of synonyms */ Common::Array > _altInputs; + int _pronounReference; + public: // Accessed by said() ParseTreeNode _parserNodes[VOCAB_TREE_NODES]; /**< The parse tree */ -- cgit v1.2.3 From 32d46dc00ab82bebc46f57dba8eb1be7e226d6f2 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 3 May 2015 18:17:50 -1000 Subject: SHERLOCK: Fix crash when moving crates --- engines/sherlock/talk.cpp | 8 ++++++++ engines/sherlock/talk.h | 2 ++ 2 files changed, 10 insertions(+) (limited to 'engines') diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index 9af8a29c1e..953f884625 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -26,6 +26,14 @@ namespace Sherlock { +SequenceEntry::SequenceEntry() { + _objNum = 0; + _frameNumber = 0; + _seqTo = 0; +} + +/*----------------------------------------------------------------*/ + /** * Load the data for a single statement within a talk file */ diff --git a/engines/sherlock/talk.h b/engines/sherlock/talk.h index d545d31351..f96c3176d2 100644 --- a/engines/sherlock/talk.h +++ b/engines/sherlock/talk.h @@ -77,6 +77,8 @@ struct SequenceEntry { Common::Array _sequences; int _frameNumber; int _seqTo; + + SequenceEntry(); }; struct ScriptStackEntry { -- cgit v1.2.3 From 0554e893cef70dc7fd4bbdad8227d17b14d076d1 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 3 May 2015 18:19:12 -1000 Subject: SHERLOCK: Fix picking up knife in taxidermy --- engines/sherlock/talk.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index 953f884625..11385ca978 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -184,7 +184,7 @@ void Talk::talkTo(const Common::String &filename) { if (_savedSequences.size() > 0) { for (uint idx = 0; idx < _savedSequences.size(); ++idx) { SequenceEntry &ss = _savedSequences[idx]; - for (uint idx2 = 0; idx2 < _savedSequences.size(); ++idx2) + for (uint idx2 = 0; idx2 < ss._sequences.size(); ++idx2) scene._bgShapes[ss._objNum]._sequences[idx2] = ss._sequences[idx2]; // Reset the object's frame to the beginning of the sequence -- cgit v1.2.3 From ed7007162a092e4b9e3d9306b078af5a8984cad0 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 4 May 2015 21:19:05 +0200 Subject: SCI: Scripts: identify strings + debug command debug command is called "script_strings" / "scrs" --- engines/sci/console.cpp | 67 +++++++++++++++ engines/sci/console.h | 1 + engines/sci/engine/script.cpp | 187 ++++++++++++++++++++++++++++++++++++++++++ engines/sci/engine/script.h | 19 +++++ 4 files changed, 274 insertions(+) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 3f5548aac7..bc9ad362ab 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -209,6 +209,8 @@ Console::Console(SciEngine *engine) : GUI::Debugger(), registerCmd("bpe", WRAP_METHOD(Console, cmdBreakpointFunction)); // alias // VM registerCmd("script_steps", WRAP_METHOD(Console, cmdScriptSteps)); + registerCmd("script_strings", WRAP_METHOD(Console, cmdScriptStrings)); + registerCmd("scrs", WRAP_METHOD(Console, cmdScriptStrings)); registerCmd("vm_varlist", WRAP_METHOD(Console, cmdVMVarlist)); registerCmd("vmvarlist", WRAP_METHOD(Console, cmdVMVarlist)); // alias registerCmd("vl", WRAP_METHOD(Console, cmdVMVarlist)); // alias @@ -2828,6 +2830,71 @@ bool Console::cmdScriptSteps(int argc, const char **argv) { return true; } +bool Console::cmdScriptStrings(int argc, const char **argv) { + SegManager *segMan = _engine->_gamestate->_segMan; + int curScriptNr = -1; + SegmentId curSegmentNr; + Common::List segmentNrList; + + SegmentType curSegmentType = SEG_TYPE_INVALID; + SegmentObj *curSegmentObj = NULL; + Script *curScriptObj = NULL; + + if (argc < 2) { + debugPrintf("Shows the strings inside a specified script.\n"); + debugPrintf("Usage: %s