diff options
Diffstat (limited to 'engines')
120 files changed, 1842 insertions, 1839 deletions
diff --git a/engines/access/access.cpp b/engines/access/access.cpp index 6ad1b22408..7f59ae7ad6 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,7 @@ AccessEngine::AccessEngine(OSystem *syst, const AccessGameDescription *gameDesc) _vidX = _vidY = 0; _cheatFl = false; _restartFl = false; + _printEnd = 0; } AccessEngine::~AccessEngine() { @@ -220,12 +222,13 @@ 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(); - _events->pollEvents(); + while(_sound->isSFXPlaying() && !shouldQuit()) + _events->pollEvents(); + + _scripts->cmdFreeSound(); if (_events->isKeyMousePressed()) { _sndSubFile += soundsLeft; @@ -254,9 +257,11 @@ 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(); - _events->pollEvents(); + while(_sound->isSFXPlaying() && !shouldQuit()) + _events->pollEvents(); + + _scripts->cmdFreeSound(); if (_events->_leftButton) { _events->debounceLeft(); 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 933a98aded..4c9df7b8ff 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); } @@ -261,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)); @@ -522,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); @@ -552,7 +558,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 +589,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 +676,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..6dffb85e5e 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(); @@ -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); @@ -341,19 +341,16 @@ 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) { - _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 +382,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; @@ -493,55 +490,62 @@ 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; _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); + 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(); } @@ -1035,7 +1039,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; } @@ -1276,8 +1280,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 +1323,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(); @@ -1371,6 +1375,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() { @@ -1410,7 +1426,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(); @@ -1480,11 +1496,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() { @@ -1510,8 +1526,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) @@ -1744,7 +1758,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(); @@ -1909,7 +1923,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/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/amazon/amazon_scripts.cpp b/engines/access/amazon/amazon_scripts.cpp index 633188e4dd..92acb3686d 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(); @@ -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(); @@ -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/animation.cpp b/engines/access/animation.cpp index 548e7db02d..14d7c0d4cc 100644 --- a/engines/access/animation.cpp +++ b/engines/access/animation.cpp @@ -310,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(); diff --git a/engines/access/asurface.cpp b/engines/access/asurface.cpp index 38af7add00..5f4372d5af 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() { @@ -186,7 +187,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 +202,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 +248,12 @@ 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) { + 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); @@ -260,7 +262,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 +274,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/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<Common::Rect> _bubbles; public: 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/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<CharEntry> _charTable; - int _converseMode; int _charFlag; - // Fields that are included in savegames - int _conversation; public: CharManager(AccessEngine *vm); 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]; 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/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/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/player.cpp b/engines/access/player.cpp index d547aedc1d..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; @@ -73,6 +72,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/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]; 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: diff --git a/engines/access/screen.cpp b/engines/access/screen.cpp index 35069ba683..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; @@ -266,19 +267,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..1bd24894d7 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); @@ -73,7 +75,7 @@ void Scripts::charLoop() { _sequence = 2000; searchForSequence(); _vm->_images.clear(); - _vm->_buffer2.copyFrom(_vm->_buffer1); + _vm->_buffer2.blitFrom(_vm->_buffer1); _vm->_newRects.clear(); executeScript(); @@ -792,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 a7d96dac9a..da267bdc4c 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" @@ -31,8 +30,6 @@ namespace Access { SoundManager::SoundManager(AccessEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer) { - _playingSound = false; - _isVoice = false; } SoundManager::~SoundManager() { @@ -44,11 +41,23 @@ 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) { - debugC(1, kDebugSound, "queueSound(%d, %d, %d)", idx, fileNum, subfile); +void SoundManager::loadSoundTable(int idx, int fileNum, int subfile, int priority) { + debugC(1, kDebugSound, "loadSoundTable(%d, %d, %d)", idx, fileNum, subfile); Resource *soundResource; @@ -58,7 +67,7 @@ void SoundManager::queueSound(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) { @@ -77,19 +86,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 +134,34 @@ 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, DisposeAfterUse::NO); + _queue.push_back(audioStream); } else error("Unknown format"); - audioHandle = Audio::SoundHandle(); - _mixer->playStream(Audio::Mixer::kSFXSoundType, &audioHandle, - audioStream, -1, _mixer->kMaxChannelVolume, 0, - DisposeAfterUse::NO); - - /* - 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 (!_mixer->isSoundHandleActive(_effectsHandle)) + _mixer->playStream(Audio::Mixer::kSFXSoundType, &_effectsHandle, + _queue[0], -1, _mixer->kMaxChannelVolume, 0, + DisposeAfterUse::YES); +} + +void SoundManager::checkSoundQueue() { + debugC(5, kDebugSound, "checkSoundQueue"); + + if (_queue.empty() || _mixer->isSoundHandleActive(_effectsHandle)) + return; + + _queue.remove_at(0); + + if (_queue.size()) + _mixer->playStream(Audio::Mixer::kSFXSoundType, &_effectsHandle, + _queue[0], -1, _mixer->kMaxChannelVolume, 0, + DisposeAfterUse::YES); +} + +bool SoundManager::isSFXPlaying() { + return _mixer->isSoundHandleActive(_effectsHandle); } void SoundManager::loadSounds(Common::Array<RoomInfo::SoundIdent> &sounds) { diff --git a/engines/access/sound.h b/engines/access/sound.h index d0f4584fac..90f6656e26 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,22 +48,23 @@ class SoundManager { private: AccessEngine *_vm; Audio::Mixer *_mixer; - Audio::SoundHandle _soundHandle; + Audio::SoundHandle _effectsHandle; + Common::Array<Audio::RewindableAudioStream *> _queue; void clearSounds(); void playSound(Resource *res, int priority); public: Common::Array<SoundEntry> _soundTable; - bool _playingSound; - bool _isVoice; public: SoundManager(AccessEngine *vm, Audio::Mixer *mixer); ~SoundManager(); - void queueSound(int idx, int fileNum, int subfile); + void loadSoundTable(int idx, int fileNum, int subfile, int priority = 1); void playSound(int soundIndex); + void checkSoundQueue(); + bool isSFXPlaying(); Resource *loadSound(int fileNum, int subfile); void loadSounds(Common::Array<RoomInfo::SoundIdent> &sounds); diff --git a/engines/access/video.cpp b/engines/access/video.cpp index b7d5652e5b..63d0aa5c89 100644 --- a/engines/access/video.cpp +++ b/engines/access/video.cpp @@ -27,10 +27,21 @@ 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; + + _header._frameCount = 0; + _header._width = _header._height = 0; + _header._flags = VIDEOFLAG_NONE; } VideoPlayer::~VideoPlayer() { 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..693c53c2bf 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[6]; 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..39759b4649 100644 --- a/engines/agi/loader_v3.cpp +++ b/engines/agi/loader_v3.cpp @@ -198,14 +198,13 @@ 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; 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); 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 }; 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); 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); 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) { diff --git a/engines/fullpipe/scenes/scene04.cpp b/engines/fullpipe/scenes/scene04.cpp index fd1ececdf2..4a87ae5b87 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) { @@ -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() { 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) diff --git a/engines/fullpipe/statics.cpp b/engines/fullpipe/statics.cpp index 880c2eb0df..de3e1ea728 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); } @@ -1594,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++) diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h index d6bdef946b..32d1a58765 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.114 (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) 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; diff --git a/engines/sci/graphics/portrait.cpp b/engines/sci/graphics/portrait.cpp index 668de616fb..3311f47022 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,8 +228,9 @@ 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); + debug("kPortrait: rave data is '%s'", debugPrint); } #endif @@ -273,6 +300,14 @@ void Portrait::doit(Common::Point position, uint16 resourceId, uint16 noun, uint raveLipSyncData = NULL; } +#ifdef DEBUG_PORTRAIT + 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; // Wait till syncTime passed, then show specific animation bitmap @@ -295,6 +330,8 @@ void Portrait::doit(Common::Point position, uint16 resourceId, uint16 noun, uint timerPositionWithin = timerPosition; raveLipSyncTicks = *raveLipSyncData++; while ( (raveLipSyncData < _lipSyncDataOffsetTableEnd) && (raveLipSyncTicks != 0xFF) ) { + if (raveLipSyncTicks) + raveLipSyncTicks--; // 1 -> wait 0 ticks, 2 -> wait 1 tick, etc. timerPositionWithin += raveLipSyncTicks; do { @@ -308,6 +345,13 @@ void Portrait::doit(Common::Point position, uint16 resourceId, uint16 noun, uint } while ((curPosition != -1) && (curPosition < timerPositionWithin) && (!userAbort)); raveLipSyncBitmapNr = *raveLipSyncData++; +#ifdef DEBUG_PORTRAIT + 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 raveLipSyncBitmapNr--; 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; } } diff --git a/engines/zvision/core/console.cpp b/engines/zvision/core/console.cpp index 4dd10d6f40..b5e542d777 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("dumpfiles", WRAP_METHOD(Console, cmdDumpFiles)); } bool Console::cmdLoadVideo(int argc, const char **argv) { @@ -78,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; @@ -103,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); @@ -133,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; @@ -205,6 +214,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 <fileName> to dump a file\n", argv[0]); @@ -217,17 +240,31 @@ 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::cmdDumpFiles(int argc, const char **argv) { + Common::String fileName; + Common::SeekableReadStream *in; - delete[] buffer; + if (argc != 2) { + debugPrintf("Use %s <file extension> to dump all files with a specific extension\n", argv[0]); + return true; + } + + SearchManager::MatchList fileList; + _engine->getSearchManager()->listMembersWithExtension(fileList, argv[1]); + + 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..a7bd88ebc3 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 cmdDumpFiles(int argc, const char **argv); }; } // End of namespace ZVision diff --git a/engines/zvision/core/events.cpp b/engines/zvision/core/events.cpp index 6cf0ae5d0d..7804130e2a 100644 --- a/engines/zvision/core/events.cpp +++ b/engines/zvision/core/events.cpp @@ -28,8 +28,9 @@ #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 "zvision/text/string_manager.h" #include "common/events.h" #include "common/system.h" @@ -39,23 +40,50 @@ 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) { case Common::KEYCODE_s: - if (getMenuBarEnable() & menuBar_Save) + if (_menu->getEnable() & kMenubarSave) _scriptManager->changeLocation('g', 'j', 's', 'e', 0); break; case Common::KEYCODE_r: - if (getMenuBarEnable() & menuBar_Restore) + if (_menu->getEnable() & kMenubarRestore) _scriptManager->changeLocation('g', 'j', 'r', 'e', 0); break; case Common::KEYCODE_p: - if (getMenuBarEnable() & menuBar_Settings) + if (_menu->getEnable() & kMenubarSettings) _scriptManager->changeLocation('g', 'j', 'p', 'e', 0); break; case Common::KEYCODE_q: - if (getMenuBarEnable() & menuBar_Exit) + if (_menu->getEnable() & kMenubarExit) ifQuit(); break; default: @@ -70,11 +98,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), @@ -91,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); @@ -101,7 +129,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), @@ -130,21 +158,29 @@ void ZVision::cheatCodes(uint8 key) { } } - if (checkCode("FRAME")) - 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")) - showDebugMsg(Common::String::format("COMPUTERARCH: var-viewer not implemented")); - if (_scriptManager->getStateValue(StateKey_DebugCheats) == 1) if (checkCode("GO????")) _scriptManager->changeLocation(getBufferedKey(3), 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 (getBufferedKey(0) == 0xBF && _scriptManager->getStateValue(StateKey_World) == 't') + _scriptManager->changeLocation('g', 'j', 'h', 'e', 0); } void ZVision::processEvents() { @@ -207,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; } @@ -279,26 +320,33 @@ 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<int16>(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; + if (mspeed <= 0) { + mspeed = 25; + } + _mouseVelocity = MIN(((Common::Rational(mspeed, ROTATION_SCREEN_EDGE_OFFSET) * (clippedPos.x - _workingWindow.left)) - mspeed).toInt(), -1); + _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; + if (mspeed <= 0) { + mspeed = 25; + } + _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; @@ -306,21 +354,23 @@ 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; + if (mspeed <= 0) { + mspeed = 25; + } + _mouseVelocity = MIN(((Common::Rational(mspeed, ROTATION_SCREEN_EDGE_OFFSET) * (pos.y - _workingWindow.top)) - mspeed).toInt(), -1); _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; + if (mspeed <= 0) { + mspeed = 25; + } + _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; @@ -441,4 +491,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/detection.cpp b/engines/zvision/detection.cpp index ebf5bdcfdd..1eaff83413 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" @@ -55,6 +55,11 @@ 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_DISABLE_ANIM_WHILE_TURNING GUIO_GAMEOPTIONS4 + static const ZVisionGameDescription gameDescriptions[] = { { @@ -66,7 +71,7 @@ static const ZVisionGameDescription gameDescriptions[] = { Common::EN_ANY, Common::kPlatformDOS, ADGF_NO_FLAGS, - GUIO1(GUIO_NONE) + GUIO4(GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_DOUBLE_FPS, GAMEOPTION_ENABLE_VENUS, GAMEOPTION_DISABLE_ANIM_WHILE_TURNING) }, GID_NEMESIS }, @@ -80,7 +85,7 @@ static const ZVisionGameDescription gameDescriptions[] = { Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO, - GUIO1(GUIO_NONE) + GUIO4(GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_DOUBLE_FPS, GAMEOPTION_ENABLE_VENUS, GAMEOPTION_DISABLE_ANIM_WHILE_TURNING) }, GID_NEMESIS }, @@ -94,35 +99,35 @@ static const ZVisionGameDescription gameDescriptions[] = { Common::EN_ANY, Common::kPlatformWindows, ADGF_NO_FLAGS, - GUIO1(GUIO_NONE) + GUIO3(GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_DOUBLE_FPS, GAMEOPTION_DISABLE_ANIM_WHILE_TURNING) }, GID_GRANDINQUISITOR }, { - // 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, - GUIO1(GUIO_NONE) + ADGF_NO_FLAGS, + GUIO3(GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_DOUBLE_FPS, GAMEOPTION_DISABLE_ANIM_WHILE_TURNING) }, 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, - GUIO1(GUIO_NONE) + ADGF_DEMO, + GUIO3(GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_DOUBLE_FPS, GAMEOPTION_DISABLE_ANIM_WHILE_TURNING) }, GID_GRANDINQUISITOR }, @@ -140,23 +145,53 @@ 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 + } + }, + + { + 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 + } + }, -static const ExtraGuiOption ZVisionExtraGuiOption2 = { - _s("Double FPS"), - _s("Halve the update delay"), - "doublefps", - false + { + 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 }; 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 +207,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 +257,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; @@ -308,6 +335,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/core/save_manager.cpp b/engines/zvision/file/save_manager.cpp index 20bd39fde5..042fafd38e 100644 --- a/engines/zvision/core/save_manager.cpp +++ b/engines/zvision/file/save_manager.cpp @@ -22,8 +22,8 @@ #include "common/scummsys.h" -#include "zvision/core/save_manager.h" #include "zvision/zvision.h" +#include "zvision/file/save_manager.h" #include "zvision/scripting/script_manager.h" #include "zvision/graphics/render_manager.h" @@ -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)); @@ -90,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) { @@ -102,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) { @@ -112,19 +113,10 @@ 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) { - file->writeUint32BE(SAVEGAME_ID); // Write version @@ -148,9 +140,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 +215,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(); } diff --git a/engines/zvision/core/save_manager.h b/engines/zvision/file/save_manager.h index 75841331e7..fc8db67566 100644 --- a/engines/zvision/core/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/file/search_manager.cpp b/engines/zvision/file/search_manager.cpp index 30c269c290..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()); @@ -265,7 +270,7 @@ void SearchManager::addDir(const Common::String &name) { void SearchManager::listDirRecursive(Common::List<Common::String> &_list, const Common::FSNode &fsNode, int depth) { Common::FSList fsList; - if ( fsNode.getChildren(fsList) ) { + if (fsNode.getChildren(fsList)) { _list.push_back(fsNode.getPath()); @@ -275,4 +280,11 @@ void SearchManager::listDirRecursive(Common::List<Common::String> &_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<Common::String> &dirList, const Common::FSNode &fsNode, int depth); - struct Node { Common::String name; Common::Archive *arch; }; - Common::List<Common::String> _dirList; - typedef Common::HashMap<Common::String, Node, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> MatchList; - Common::List<Common::Archive *> _archList; - MatchList _files; - - Common::String _root; + void listMembersWithExtension(MatchList &fileList, Common::String extension); private: + + void listDirRecursive(Common::List<Common::String> &dirList, const Common::FSNode &fsNode, int depth); + + Common::List<Common::String> _dirList; + Common::List<Common::Archive *> _archList; + Common::String _root; + MatchList _files; }; } diff --git a/engines/zvision/graphics/cursors/cursor.cpp b/engines/zvision/graphics/cursors/cursor.cpp index 07323b45c4..f32c68645d 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), @@ -86,12 +57,15 @@ 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)); +#ifndef SCUMM_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) { 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(); diff --git a/engines/zvision/graphics/cursors/cursor_manager.cpp b/engines/zvision/graphics/cursors/cursor_manager.cpp index 92fd461c72..c364426bad 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), @@ -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/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/graphics/effects/fog.cpp b/engines/zvision/graphics/effects/fog.cpp index f59e82a4a0..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; @@ -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/fog.h b/engines/zvision/graphics/effects/fog.h index 45d6f9596d..498347609e 100644 --- a/engines/zvision/graphics/effects/fog.h +++ b/engines/zvision/graphics/effects/fog.h @@ -23,13 +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; -class FogFx : public Effect { +// Used by Zork: Nemesis for the mixing chamber gas effect in the gas puzzle (location tt5e, when the blinds are down) +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 00b3811d65..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; @@ -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/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/effect.h b/engines/zvision/graphics/graphics_effect.h index c6653c6037..bfa266b11d 100644 --- a/engines/zvision/graphics/effect.h +++ b/engines/zvision/graphics/graphics_effect.h @@ -20,8 +20,8 @@ * */ -#ifndef EFFECT_H_INCLUDED -#define EFFECT_H_INCLUDED +#ifndef GRAPHICS_EFFECT_H_INCLUDED +#define GRAPHICS_EFFECT_H_INCLUDED #include "common/rect.h" #include "common/list.h" @@ -33,13 +33,13 @@ namespace ZVision { class ZVision; -class Effect { +class GraphicsEffect { 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); + 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 ~Effect() {} + virtual ~GraphicsEffect() {} uint32 getKey() { return _key; @@ -80,4 +80,4 @@ typedef Common::List<EffectMapUnit> EffectMap; } // End of namespace ZVision -#endif // EFFECT_H_INCLUDED +#endif // GRAPHICS_EFFECT_H_INCLUDED diff --git a/engines/zvision/graphics/render_manager.cpp b/engines/zvision/graphics/render_manager.cpp index b9305f5dcc..a1cc8ac53c 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); @@ -103,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; @@ -127,14 +129,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); @@ -162,97 +179,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) { @@ -272,8 +200,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; @@ -282,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 SCUMM_LITTLE_ENDIAN + for (uint32 i = 0; i < decompressedSize; ++i) + buffer[i] = FROM_LE_16(buffer[i]); +#endif } else { isTGZ = false; @@ -318,7 +249,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 @@ -334,7 +265,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 @@ -343,9 +274,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) { @@ -459,10 +387,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); @@ -473,8 +397,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; @@ -484,8 +410,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); @@ -493,17 +422,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); @@ -514,10 +442,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; @@ -527,8 +456,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); @@ -536,12 +468,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++; @@ -553,7 +485,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++; @@ -565,7 +497,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++; @@ -576,35 +508,20 @@ void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, const Com default: break; } - srcBuffer += src.pitch; + srcBuffer += srcAdapted->pitch; dstBuffer += dst.pitch; } -} - -void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, Graphics::Surface &dst, int x, int y) { - 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); + srcAdapted->free(); + delete srcAdapted; } -void RenderManager::blitSurfaceToBkg(const Graphics::Surface &src, int x, int y) { +void RenderManager::blitSurfaceToBkg(const Graphics::Surface &src, int x, int y, int32 colorkey) { 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()) @@ -613,23 +530,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()); @@ -639,20 +543,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()) @@ -676,28 +572,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(); @@ -788,12 +674,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(); } } @@ -813,18 +702,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) { @@ -868,20 +748,23 @@ 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); + 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; } 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); } } @@ -889,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); } @@ -1072,9 +955,221 @@ 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 + +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); +} + +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 29bbd8f411..c22f9a78c9 100644 --- a/engines/zvision/graphics/render_manager.h +++ b/engines/zvision/graphics/render_manager.h @@ -24,14 +24,14 @@ #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" #include "graphics/surface.h" -#include "effect.h" +#include "graphics_effect.h" class OSystem; @@ -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: @@ -61,7 +61,7 @@ private: }; typedef Common::HashMap<uint16, OneSubtitle> SubtitleMap; - typedef Common::List<Effect *> EffectsList; + typedef Common::List<GraphicsEffect *> EffectsList; private: ZVision *_engine; @@ -137,6 +137,7 @@ private: // Visual effects list EffectsList _effects; + bool _doubleFPS; public: void initialize(); @@ -146,6 +147,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. * @@ -227,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 @@ -265,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(); @@ -281,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. @@ -293,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. @@ -306,7 +300,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); @@ -328,8 +322,19 @@ 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 + + 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); + + void checkBorders(); + void rotateTo(int16 to, int16 time); + void updateRotation(); }; } // End of namespace ZVision 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; diff --git a/engines/zvision/module.mk b/engines/zvision/module.mk index 00652f0824..93fba2879d 100644 --- a/engines/zvision/module.mk +++ b/engines/zvision/module.mk @@ -4,10 +4,9 @@ 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 \ + file/save_manager.o \ file/search_manager.o \ file/zfs_archive.o \ graphics/cursors/cursor_manager.o \ @@ -17,8 +16,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 \ @@ -32,19 +29,22 @@ 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 \ - 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 \ + 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/actions.cpp b/engines/zvision/scripting/actions.cpp index 0422a2c028..a61fa26223 100644 --- a/engines/zvision/scripting/actions.cpp +++ b/engines/zvision/scripting/actions.cpp @@ -29,20 +29,21 @@ #include "zvision/graphics/render_manager.h" #include "zvision/sound/zork_raw.h" #include "zvision/video/zork_avi_decoder.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/file/save_manager.h" +#include "zvision/scripting/menu.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" -#include "zvision/core/save_manager.h" #include "zvision/graphics/cursors/cursor_manager.h" #include "common/file.h" @@ -105,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)); } @@ -156,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); @@ -167,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); @@ -243,23 +244,6 @@ bool ActionDisableControl::execute() { } ////////////////////////////////////////////////////////////////////////////// -// 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 +279,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) : @@ -363,7 +347,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; @@ -406,7 +390,7 @@ bool ActionInventory::execute() { } ////////////////////////////////////////////////////////////////////////////// -// ActionKill +// ActionKill - only used by ZGI ////////////////////////////////////////////////////////////////////////////// ActionKill::ActionKill(ZVision *engine, int32 slotkey, const Common::String &line) : @@ -414,31 +398,31 @@ 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; + _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; @@ -456,7 +440,7 @@ ActionMenuBarEnable::ActionMenuBarEnable(ZVision *engine, int32 slotkey, const C } bool ActionMenuBarEnable::execute() { - _engine->menuBarEnable(_menus); + _engine->getMenuHandler()->setEnable(_menus); return true; } @@ -475,9 +459,11 @@ 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 + // 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; @@ -577,14 +563,14 @@ ActionPreloadAnimation::ActionPreloadAnimation(ZVision *engine, int32 slotkey, c char fileName[25]; - // The two %*u are always 0 and dont seem to have a use - sscanf(line.c_str(), "%25s %*u %*u %d %d", fileName, &_mask, &_framerate); + // 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); - } + // 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); } @@ -594,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(); @@ -617,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; @@ -645,14 +631,14 @@ 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) { - 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); - } + // 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); } @@ -662,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(); @@ -697,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); @@ -716,7 +702,7 @@ bool ActionQuit::execute() { } ////////////////////////////////////////////////////////////////////////////// -// ActionRegion +// ActionRegion - only used by Zork: Nemesis ////////////////////////////////////////////////////////////////////////////// ActionRegion::ActionRegion(ZVision *engine, int32 slotkey, const Common::String &line) : @@ -745,13 +731,13 @@ bool ActionRegion::execute() { if (_engine->getScriptManager()->getSideFX(_slotKey)) return true; - Effect *effct = NULL; + GraphicsEffect *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: { @@ -763,7 +749,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: { @@ -779,16 +765,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; @@ -846,7 +832,7 @@ ActionRotateTo::ActionRotateTo(ZVision *engine, int32 slotkey, const Common::Str } bool ActionRotateTo::execute() { - _engine->rotateTo(_toPos, _time); + _engine->getRenderManager()->rotateTo(_toPos, _time); return true; } @@ -861,21 +847,12 @@ ActionSetPartialScreen::ActionSetPartialScreen(ZVision *engine, int32 slotkey, c _y = 0; 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, &_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"); } } @@ -907,7 +884,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); } @@ -919,24 +896,6 @@ bool ActionSetScreen::execute() { } ////////////////////////////////////////////////////////////////////////////// -// 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 ////////////////////////////////////////////////////////////////////////////// @@ -966,7 +925,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,23 +976,19 @@ 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); } 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; - AnimationNode *animnode = (AnimationNode *)fx; - if (animnode->getFrameDelay() > 200) // Hack for fix incorrect framedelay in some animpreload - animnode->setNewFrameDelay(66); // ~15fps - _engine->getScriptManager()->addSideFX(new SyncSoundNode(_engine, _slotKey, _fileName, _syncto)); return true; } diff --git a/engines/zvision/scripting/actions.h b/engines/zvision/scripting/actions.h index 292e25e19c..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); @@ -338,7 +321,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); @@ -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/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/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/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 0a6b977ead..d7cbcb1f71 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, handles the door lock puzzle with the skeletal fingers (td9e) class FistControl : public Control { public: FistControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream); @@ -63,10 +64,6 @@ private: Video::VideoDecoder *_animation; Common::Rect _anmRect; int32 _soundKey; - int32 _frameCur; - int32 _frameEnd; - int32 _frameTime; - int32 _lastRenderedFrame; int32 _animationId; public: @@ -75,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<Common::Rect> > &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 b18d44c7a6..99d1fd0979 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, 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); @@ -41,9 +42,6 @@ public: private: int32 _framesCount; - int32 _frameTime; - int32 _curFrame; - int32 _lastRenderedFrame; int32 _cycle; int32 _cyclesCount; Video::VideoDecoder *_animation; @@ -55,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 e75cc15743..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); @@ -96,11 +94,10 @@ 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; - _frameDelay = 0; + _animation->start(); } else if (param.matchString("focus", true)) { _focused = true; _engine->getScriptManager()->setFocusControlKey(_key); @@ -199,7 +196,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); @@ -212,18 +209,12 @@ 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(); - 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); 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)); } 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.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/paint_control.h b/engines/zvision/scripting/controls/paint_control.h index 8097290ac2..8c01f0e68a 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, 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.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 6e1095e304..3e8c17635c 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); @@ -51,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 diff --git a/engines/zvision/scripting/controls/save_control.cpp b/engines/zvision/scripting/controls/save_control.cpp index b35611feca..6cedddffeb 100644 --- a/engines/zvision/scripting/controls/save_control.cpp +++ b/engines/zvision/scripting/controls/save_control.cpp @@ -29,7 +29,8 @@ #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 "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/scripting/controls/titler_control.cpp b/engines/zvision/scripting/controls/titler_control.cpp index 10ba0af655..542e0a0b67 100644 --- a/engines/zvision/scripting/controls/titler_control.cpp +++ b/engines/zvision/scripting/controls/titler_control.cpp @@ -67,14 +67,16 @@ 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); } } TitlerControl::~TitlerControl() { - if (_surface) + if (_surface) { + _surface->free(); delete _surface; + } } void TitlerControl::setString(int strLine) { diff --git a/engines/zvision/scripting/controls/titler_control.h b/engines/zvision/scripting/controls/titler_control.h index 075e47c9e9..dd96e4a846 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, 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/sidefx/animation_node.cpp b/engines/zvision/scripting/effects/animation_effect.cpp index 3a21227d1a..511a0db353 100644 --- a/engines/zvision/scripting/sidefx/animation_node.cpp +++ b/engines/zvision/scripting/effects/animation_effect.cpp @@ -22,7 +22,7 @@ #include "common/scummsys.h" -#include "zvision/scripting/sidefx/animation_node.h" +#include "zvision/scripting/effects/animation_effect.h" #include "zvision/zvision.h" #include "zvision/graphics/render_manager.h" @@ -33,20 +33,27 @@ 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), +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); - _frmDelay = 1000.0 / _animation->getDuration().framerate(); - if (frate > 0) - _frmDelay = 1000.0 / frate; + 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() { +AnimationEffect::~AnimationEffect() { if (_animation) delete _animation; @@ -56,60 +63,83 @@ 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(); } -bool AnimationNode::process(uint32 deltaTimeInMillis) { +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); - 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) - _engine->getScriptManager()->setStateValue(nod->slot, 1); - } else { - nod->_curFrame++; - - if (nod->_curFrame > nod->stop) { - nod->loop--; - - if (nod->loop == 0) { - if (nod->slot >= 0) - _engine->getScriptManager()->setStateValue(nod->slot, 2); - if (nod->_scaled) - 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->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 (frame) { + if (needsUpdate) { + const Graphics::Surface *frame = _animation->decodeNextFrame(); + if (frame) { uint32 dstw; uint32 dsth; - if (_engine->getRenderManager()->getRenderTable()->getRenderState() == RenderTable::PANORAMA) { + if (isPanorama) { dstw = nod->pos.height(); dsth = nod->pos.width(); } else { @@ -126,6 +156,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; } @@ -135,22 +166,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); - 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); + renderManager->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); + renderManager->blitSurfaceToBkg(*frame, nod->pos.left, nod->pos.top, _mask); } } } @@ -159,16 +185,12 @@ bool AnimationNode::process(uint32 deltaTimeInMillis) { return false; } -void AnimationNode::addPlayNode(int32 slot, int x, int y, int x2, int y2, int startFrame, int endFrame, int loops) { +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; - nod.stop = endFrame; - - if (nod.stop >= (int)_animation->getFrameCount()) - nod.stop = _animation->getFrameCount() - 1; - + nod.stop = CLIP<int>(endFrame, 0, _animation->getFrameCount() - 1); nod.slot = slot; nod._curFrame = -1; nod._delay = 0; @@ -176,12 +198,14 @@ void AnimationNode::addPlayNode(int32 slot, int x, int y, int x2, int y2, int st _playList.push_back(nod); } -bool AnimationNode::stop() { +bool AnimationEffect::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(); @@ -190,21 +214,4 @@ 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; -} - } // End of namespace ZVision diff --git a/engines/zvision/scripting/sidefx/animation_node.h b/engines/zvision/scripting/effects/animation_effect.h index 3adfd91f32..fd6e24ab8b 100644 --- a/engines/zvision/scripting/sidefx/animation_node.h +++ b/engines/zvision/scripting/effects/animation_effect.h @@ -23,7 +23,7 @@ #ifndef ZVISION_ANIMATION_NODE_H #define ZVISION_ANIMATION_NODE_H -#include "zvision/scripting/sidefx.h" +#include "zvision/scripting/scripting_effect.h" #include "common/rect.h" #include "common/list.h" @@ -39,10 +39,10 @@ namespace ZVision { class ZVision; -class AnimationNode : public SideFX { +class AnimationEffect : public ScriptingEffect { public: - AnimationNode(ZVision *engine, uint32 controlKey, const Common::String &fileName, int32 mask, int32 frate, bool DisposeAfterUse = true); - ~AnimationNode(); + AnimationEffect(ZVision *engine, uint32 controlKey, const Common::String &fileName, int32 mask, int32 frate, bool disposeAfterUse = true); + ~AnimationEffect(); struct playnode { Common::Rect pos; @@ -61,10 +61,10 @@ private: PlayNodes _playList; int32 _mask; - bool _DisposeAfterUse; + bool _disposeAfterUse; Video::VideoDecoder *_animation; - int32 _frmDelay; + int32 _frmDelayOverride; public: bool process(uint32 deltaTimeInMillis); @@ -72,9 +72,6 @@ public: void addPlayNode(int32 slot, int x, int y, int x2, int y2, int startFrame, int endFrame, int loops = 1); bool stop(); - - void setNewFrameDelay(int32 newDelay); - int32 getFrameDelay(); }; } // End of namespace ZVision diff --git a/engines/zvision/scripting/sidefx/distort_node.cpp b/engines/zvision/scripting/effects/distort_effect.cpp index 0d5c8b1ed5..78c4a1b9a8 100644 --- a/engines/zvision/scripting/sidefx/distort_node.cpp +++ b/engines/zvision/scripting/effects/distort_effect.cpp @@ -22,7 +22,7 @@ #include "common/scummsys.h" -#include "zvision/scripting/sidefx/distort_node.h" +#include "zvision/scripting/effects/distort_effect.h" #include "zvision/zvision.h" #include "zvision/scripting/script_manager.h" @@ -34,7 +34,7 @@ namespace ZVision { DistortNode::DistortNode(ZVision *engine, uint32 key, int16 speed, float startAngle, float endAngle, float startLineScale, float endLineScale) - : SideFX(engine, key, SIDEFX_DISTORT) { + : ScriptingEffect(engine, key, SCRIPTING_EFFECT_DISTORT) { _angle = _engine->getRenderManager()->getRenderTable()->getAngle(); _linScale = _engine->getRenderManager()->getRenderTable()->getLinscale(); @@ -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/scripting/sidefx/distort_node.h b/engines/zvision/scripting/effects/distort_effect.h index 787a69bdde..c64f10e6ff 100644 --- a/engines/zvision/scripting/sidefx/distort_node.h +++ b/engines/zvision/scripting/effects/distort_effect.h @@ -23,13 +23,13 @@ #ifndef ZVISION_DISTORT_NODE_H #define ZVISION_DISTORT_NODE_H -#include "zvision/scripting/sidefx.h" +#include "zvision/scripting/scripting_effect.h" namespace ZVision { class ZVision; -class DistortNode : public SideFX { +class DistortNode : public ScriptingEffect { public: DistortNode(ZVision *engine, uint32 key, int16 speed, float startAngle, float endAngle, float startLineScale, float endLineScale); ~DistortNode(); diff --git a/engines/zvision/scripting/sidefx/music_node.cpp b/engines/zvision/scripting/effects/music_effect.cpp index 56598189f6..102f330305 100644 --- a/engines/zvision/scripting/sidefx/music_node.cpp +++ b/engines/zvision/scripting/effects/music_effect.cpp @@ -22,7 +22,7 @@ #include "common/scummsys.h" -#include "zvision/scripting/sidefx/music_node.h" +#include "zvision/scripting/effects/music_effect.h" #include "zvision/zvision.h" #include "zvision/scripting/script_manager.h" @@ -37,7 +37,7 @@ namespace ZVision { MusicNode::MusicNode(ZVision *engine, uint32 key, Common::String &filename, bool loop, int8 volume) - : MusicNodeBASE(engine, key, SIDEFX_AUDIO) { + : MusicNodeBASE(engine, key, SCRIPTING_EFFECT_AUDIO) { _loop = loop; _volume = volume; _crossfade = false; @@ -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); @@ -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; @@ -179,26 +179,26 @@ void MusicNode::setVolume(uint8 newVolume) { } PanTrackNode::PanTrackNode(ZVision *engine, uint32 key, uint32 slot, int16 pos) - : SideFX(engine, key, SIDEFX_PANTRACK) { + : ScriptingEffect(engine, key, SCRIPTING_EFFECT_PANTRACK) { _slot = slot; - SideFX *fx = _engine->getScriptManager()->getSideFX(slot); - if (fx && fx->getType() == SIDEFX_AUDIO) { + ScriptingEffect *fx = _engine->getScriptManager()->getSideFX(slot); + if (fx && fx->getType() == SCRIPTING_EFFECT_AUDIO) { MusicNodeBASE *mus = (MusicNodeBASE *)fx; mus->setPanTrack(pos); } } PanTrackNode::~PanTrackNode() { - SideFX *fx = _engine->getScriptManager()->getSideFX(_slot); - if (fx && fx->getType() == SIDEFX_AUDIO) { + 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, SIDEFX_AUDIO) { + : MusicNodeBASE(engine, key, SCRIPTING_EFFECT_AUDIO) { _volume = volume; _prog = program; _noteNumber = note; diff --git a/engines/zvision/scripting/sidefx/music_node.h b/engines/zvision/scripting/effects/music_effect.h index 09bdc3707e..31d538f668 100644 --- a/engines/zvision/scripting/sidefx/music_node.h +++ b/engines/zvision/scripting/effects/music_effect.h @@ -24,8 +24,8 @@ #define ZVISION_MUSIC_NODE_H #include "audio/mixer.h" -#include "zvision/scripting/sidefx.h" -#include "zvision/graphics/subtitles.h" +#include "zvision/scripting/scripting_effect.h" +#include "zvision/text/subtitles.h" namespace Common { class String; @@ -33,9 +33,9 @@ class String; namespace ZVision { -class MusicNodeBASE : public SideFX { +class MusicNodeBASE : public ScriptingEffect { public: - MusicNodeBASE(ZVision *engine, uint32 key, SideFXType type) : SideFX(engine, key, type) {} + MusicNodeBASE(ZVision *engine, uint32 key, ScriptingEffectType type) : ScriptingEffect(engine, key, type) {} ~MusicNodeBASE() {} /** @@ -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); @@ -120,7 +121,7 @@ private: int8 _prog; }; -class PanTrackNode : public SideFX { +class PanTrackNode : public ScriptingEffect { public: PanTrackNode(ZVision *engine, uint32 key, uint32 slot, int16 pos); ~PanTrackNode(); diff --git a/engines/zvision/scripting/sidefx/region_node.cpp b/engines/zvision/scripting/effects/region_effect.cpp index de613d8af2..78061cf4de 100644 --- a/engines/zvision/scripting/sidefx/region_node.cpp +++ b/engines/zvision/scripting/effects/region_effect.cpp @@ -22,7 +22,7 @@ #include "common/scummsys.h" -#include "zvision/scripting/sidefx/region_node.h" +#include "zvision/scripting/effects/region_effect.h" #include "zvision/zvision.h" #include "zvision/scripting/script_manager.h" @@ -30,8 +30,8 @@ namespace ZVision { -RegionNode::RegionNode(ZVision *engine, uint32 key, Effect *effect, uint32 delay) - : SideFX(engine, key, SIDEFX_REGION) { +RegionNode::RegionNode(ZVision *engine, uint32 key, GraphicsEffect *effect, uint32 delay) + : ScriptingEffect(engine, key, SCRIPTING_EFFECT_REGION) { _effect = effect; _delay = delay; _timeLeft = 0; diff --git a/engines/zvision/scripting/sidefx/region_node.h b/engines/zvision/scripting/effects/region_effect.h index ec716b6e3e..4fc16224ff 100644 --- a/engines/zvision/scripting/sidefx/region_node.h +++ b/engines/zvision/scripting/effects/region_effect.h @@ -25,16 +25,16 @@ #include "graphics/surface.h" -#include "zvision/scripting/sidefx.h" -#include "zvision/graphics/effect.h" +#include "zvision/scripting/scripting_effect.h" +#include "zvision/graphics/graphics_effect.h" namespace ZVision { class ZVision; -class RegionNode : public SideFX { +class RegionNode : public ScriptingEffect { public: - RegionNode(ZVision *engine, uint32 key, Effect *effect, uint32 delay); + RegionNode(ZVision *engine, uint32 key, GraphicsEffect *effect, uint32 delay); ~RegionNode(); /** @@ -49,7 +49,7 @@ public: private: int32 _timeLeft; uint32 _delay; - Effect *_effect; + GraphicsEffect *_effect; }; } // End of namespace ZVision diff --git a/engines/zvision/scripting/sidefx/syncsound_node.cpp b/engines/zvision/scripting/effects/syncsound_effect.cpp index c1f139694b..70ba97deb8 100644 --- a/engines/zvision/scripting/sidefx/syncsound_node.cpp +++ b/engines/zvision/scripting/effects/syncsound_effect.cpp @@ -22,7 +22,7 @@ #include "common/scummsys.h" -#include "zvision/scripting/sidefx/syncsound_node.h" +#include "zvision/scripting/effects/syncsound_effect.h" #include "zvision/zvision.h" #include "zvision/scripting/script_manager.h" @@ -36,7 +36,7 @@ namespace ZVision { SyncSoundNode::SyncSoundNode(ZVision *engine, uint32 key, Common::String &filename, int32 syncto) - : SideFX(engine, key, SIDEFX_AUDIO) { + : ScriptingEffect(engine, key, SCRIPTING_EFFECT_AUDIO) { _syncto = syncto; _sub = NULL; @@ -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/scripting/sidefx/syncsound_node.h b/engines/zvision/scripting/effects/syncsound_effect.h index 7cd02a8aef..0eabff77a3 100644 --- a/engines/zvision/scripting/sidefx/syncsound_node.h +++ b/engines/zvision/scripting/effects/syncsound_effect.h @@ -24,15 +24,15 @@ #define ZVISION_SYNCSOUND_NODE_H #include "audio/mixer.h" -#include "zvision/scripting/sidefx.h" -#include "zvision/graphics/subtitles.h" +#include "zvision/scripting/scripting_effect.h" +#include "zvision/text/subtitles.h" namespace Common { class String; } namespace ZVision { -class SyncSoundNode : public SideFX { +class SyncSoundNode : public ScriptingEffect { public: SyncSoundNode(ZVision *engine, uint32 key, Common::String &file, int32 syncto); ~SyncSoundNode(); diff --git a/engines/zvision/scripting/sidefx/timer_node.cpp b/engines/zvision/scripting/effects/timer_effect.cpp index 170f6e7472..778f9dec6c 100644 --- a/engines/zvision/scripting/sidefx/timer_node.cpp +++ b/engines/zvision/scripting/effects/timer_effect.cpp @@ -22,7 +22,7 @@ #include "common/scummsys.h" -#include "zvision/scripting/sidefx/timer_node.h" +#include "zvision/scripting/effects/timer_effect.h" #include "zvision/zvision.h" #include "zvision/scripting/script_manager.h" @@ -32,7 +32,7 @@ namespace ZVision { TimerNode::TimerNode(ZVision *engine, uint32 key, uint timeInSeconds) - : SideFX(engine, key, SIDEFX_TIMER) { + : ScriptingEffect(engine, key, SCRIPTING_EFFECT_TIMER) { _timeLeft = 0; if (_engine->getGameId() == GID_NEMESIS) diff --git a/engines/zvision/scripting/sidefx/timer_node.h b/engines/zvision/scripting/effects/timer_effect.h index 7a26aff251..5e45d54d7d 100644 --- a/engines/zvision/scripting/sidefx/timer_node.h +++ b/engines/zvision/scripting/effects/timer_effect.h @@ -23,13 +23,13 @@ #ifndef ZVISION_TIMER_NODE_H #define ZVISION_TIMER_NODE_H -#include "zvision/scripting/sidefx.h" +#include "zvision/scripting/scripting_effect.h" namespace ZVision { class ZVision; -class TimerNode : public SideFX { +class TimerNode : public ScriptingEffect { public: TimerNode(ZVision *engine, uint32 key, uint timeInSeconds); ~TimerNode(); diff --git a/engines/zvision/scripting/sidefx/ttytext_node.cpp b/engines/zvision/scripting/effects/ttytext_effect.cpp index 9a7fa01649..c60b3aa8c5 100644 --- a/engines/zvision/scripting/sidefx/ttytext_node.cpp +++ b/engines/zvision/scripting/effects/ttytext_effect.cpp @@ -22,7 +22,7 @@ #include "common/scummsys.h" -#include "zvision/scripting/sidefx/ttytext_node.h" +#include "zvision/scripting/effects/ttytext_effect.h" #include "zvision/zvision.h" #include "zvision/scripting/script_manager.h" @@ -35,7 +35,7 @@ namespace ZVision { ttyTextNode::ttyTextNode(ZVision *engine, uint32 key, const Common::String &file, const Common::Rect &r, int32 delay) : - SideFX(engine, key, SIDEFX_TTYTXT), + ScriptingEffect(engine, key, SCRIPTING_EFFECT_TTYTXT), _fnt(engine) { _delay = delay; _r = r; @@ -56,8 +56,8 @@ ttyTextNode::ttyTextNode(ZVision *engine, uint32 key, const Common::String &file delete infile; } - _img.create(_r.width(), _r.height(), _engine->_pixelFormat); - _style.sharp = true; + _img.create(_r.width(), _r.height(), _engine->_resourcePixelFormat); + _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->_resourcePixelFormat.RGBToColor(_style._red, _style._green, _style._blue); if (_dx + _fnt.getCharWidth(chr) > _r.width()) newline(); diff --git a/engines/zvision/scripting/sidefx/ttytext_node.h b/engines/zvision/scripting/effects/ttytext_effect.h index b6cbed3e34..8d8a2518c7 100644 --- a/engines/zvision/scripting/sidefx/ttytext_node.h +++ b/engines/zvision/scripting/effects/ttytext_effect.h @@ -26,16 +26,16 @@ #include "common/rect.h" #include "graphics/surface.h" -#include "zvision/scripting/sidefx.h" +#include "zvision/scripting/scripting_effect.h" #include "zvision/text/text.h" -#include "zvision/graphics/truetype_font.h" +#include "zvision/text/truetype_font.h" namespace Common { class String; } namespace ZVision { -class ttyTextNode : public SideFX { +class ttyTextNode : public ScriptingEffect { public: ttyTextNode(ZVision *engine, uint32 key, const Common::String &file, const Common::Rect &r, int32 delay); ~ttyTextNode(); diff --git a/engines/zvision/core/menu.cpp b/engines/zvision/scripting/menu.cpp index 31e0d71370..16aa57e3ae 100644 --- a/engines/zvision/core/menu.cpp +++ b/engines/zvision/scripting/menu.cpp @@ -20,26 +20,22 @@ * */ -#include "common/scummsys.h" - -#include "zvision/core/menu.h" - #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 + 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) { @@ -122,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; @@ -131,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; } @@ -146,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; @@ -216,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; @@ -231,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) @@ -313,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); } @@ -356,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) @@ -389,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) { @@ -402,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]) { @@ -425,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; @@ -450,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; @@ -469,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]) { @@ -491,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; } @@ -539,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; } @@ -587,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], @@ -598,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], @@ -609,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], @@ -620,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], @@ -644,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) { @@ -721,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/core/menu.h b/engines/zvision/scripting/menu.h index ebe0bb50ac..a88587966f 100644 --- a/engines/zvision/core/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/scr_file_handling.cpp b/engines/zvision/scripting/scr_file_handling.cpp index c117da5ec2..227c43557c 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)); @@ -234,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)); @@ -248,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)); @@ -264,6 +267,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)); @@ -276,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)) { @@ -345,25 +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, 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 (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) return new PaintControl(_engine, key, stream); } else if (controlType.equalsIgnoreCase("titler")) { + // Only used in Zork Nemesis, handles the death screen with the Restore/Exit buttons (cjde) return new TitlerControl(_engine, key, stream); } return NULL; diff --git a/engines/zvision/scripting/script_manager.cpp b/engines/zvision/scripting/script_manager.cpp index 4c1e69072d..464e8bfe4d 100644 --- a/engines/zvision/scripting/script_manager.cpp +++ b/engines/zvision/scripting/script_manager.cpp @@ -27,9 +27,10 @@ #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" +#include "zvision/scripting/menu.h" +#include "zvision/scripting/effects/timer_effect.h" #include "common/algorithm.h" #include "common/hashmap.h" @@ -381,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); @@ -429,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(); @@ -568,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); @@ -583,7 +580,7 @@ void ScriptManager::ChangeLocationReal() { _referenceTable.clear(); addPuzzlesToReferenceTable(universe); - _engine->menuBarEnable(0xFFFF); + _engine->getMenuHandler()->setEnable(0xFFFF); if (_nextLocation.world != _currentLocation.world) { cleanScriptScope(nodeview); @@ -652,7 +649,7 @@ void ScriptManager::ChangeLocationReal() { execScope(nodeview); } - _engine->checkBorders(); + _engine->getRenderManager()->checkBorders(); } void ScriptManager::serialize(Common::WriteStream *stream) { diff --git a/engines/zvision/scripting/script_manager.h b/engines/zvision/scripting/script_manager.h index 1e308faf0d..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" @@ -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 { @@ -111,7 +116,7 @@ typedef Common::List<Puzzle *> PuzzleList; typedef Common::Queue<Puzzle *> PuzzleQueue; typedef Common::List<Control *> ControlList; typedef Common::HashMap<uint32, int32> StateMap; -typedef Common::List<SideFX *> SideFXList; +typedef Common::List<ScriptingEffect *> SideFXList; typedef Common::List<Common::Event> EventList; class ScriptManager { @@ -191,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); @@ -282,7 +287,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 +296,6 @@ public: */ void parseScrFile(const Common::String &fileName, ScriptScope &scope); -private: /** * Parses the stream into a Puzzle object * Helper method for parseScrFile. diff --git a/engines/zvision/scripting/sidefx.h b/engines/zvision/scripting/scripting_effect.h index 5bb14f0cdd..0af1d9c21c 100644 --- a/engines/zvision/scripting/sidefx.h +++ b/engines/zvision/scripting/scripting_effect.h @@ -20,8 +20,8 @@ * */ -#ifndef SIDEFX_H_INCLUDED -#define SIDEFX_H_INCLUDED +#ifndef SCRIPTING_EFFECT_H_INCLUDED +#define SCRIPTING_EFFECT_H_INCLUDED namespace Common { class SeekableReadStream; @@ -33,29 +33,39 @@ namespace ZVision { class ZVision; -class SideFX { +/** + * 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 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 + 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 }; - SideFX() : _engine(0), _key(0), _type(SIDEFX_UNK) {} - SideFX(ZVision *engine, uint32 key, SideFXType type) : _engine(engine), _key(key), _type(type) {} - virtual ~SideFX() {} + 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; } - SideFXType getType() { + ScriptingEffectType getType() { return _type; } @@ -103,7 +113,7 @@ public: protected: ZVision *_engine; uint32 _key; - SideFXType _type; + ScriptingEffectType _type; // Static member functions public: @@ -111,4 +121,4 @@ public: }; } // End of namespace ZVision -#endif // SIDEFX_H_INCLUDED +#endif // SCRIPTING_EFFECT_H_INCLUDED diff --git a/engines/zvision/sound/zork_raw.cpp b/engines/zvision/sound/zork_raw.cpp index 8688039325..6d1980b1af 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; @@ -216,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()) @@ -244,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 @@ -123,20 +123,6 @@ public: }; /** - * 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. * * @param stream Stream object to play from. 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); 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/graphics/subtitles.cpp b/engines/zvision/text/subtitles.cpp index d2c56f0991..acf4c37c2f 100644 --- a/engines/zvision/graphics/subtitles.cpp +++ b/engines/zvision/text/subtitles.cpp @@ -21,7 +21,7 @@ */ #include "zvision/graphics/render_manager.h" -#include "zvision/graphics/subtitles.h" +#include "zvision/text/subtitles.h" #include "zvision/file/search_manager.h" #include "zvision/text/text.h" diff --git a/engines/zvision/graphics/subtitles.h b/engines/zvision/text/subtitles.h index c3da6583a4..c3da6583a4 100644 --- a/engines/zvision/graphics/subtitles.h +++ b/engines/zvision/text/subtitles.h diff --git a/engines/zvision/text/text.cpp b/engines/zvision/text/text.cpp index 406c36e5b0..a5ed044424 100644 --- a/engines/zvision/text/text.cpp +++ b/engines/zvision/text/text.cpp @@ -33,27 +33,31 @@ #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 { 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; +#if 0 + _newline = false; + _escapement = 0; +#endif + _italic = false; + _justify = TXT_JUSTIFY_LEFT; + _size = 12; +#if 0 + _skipcolor = false; +#endif + _strikeout = false; + _underline = false; + _statebox = 0; + _sharp = false; } txtReturn cTxtStyle::parseStyle(const Common::String &strin, int16 ln) { @@ -80,10 +84,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 +95,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 +104,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,43 +113,47 @@ 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 0 if ((retval & TXT_RET_NEWLN) == 0) - newline = 0; + _newline = 0; - newline++; + _newline++; +#endif 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; } } } else if (token.matchString("escapement", true)) { if (!tokenizer.empty()) { token = tokenizer.nextToken(); +#if 0 int32 tmp = atoi(token.c_str()); - escapement = tmp; + _escapement = tmp; +#endif } } 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 +162,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 +177,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 +192,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; } } @@ -198,29 +206,31 @@ 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; + _skipcolor = true; } else if (token.matchString("off", true)) { - skipcolor = false; + _skipcolor = false; } +#endif } } else if (token.matchString("image", true)) { // Not used } 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 +257,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 +278,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->_resourcePixelFormat.RGBToColor(style._red, style._green, style._blue); return fnt.renderSolidText(txt, clr); } @@ -307,13 +317,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->_resourcePixelFormat.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 +362,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 +406,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(); } @@ -452,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; } @@ -495,10 +506,12 @@ 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)); + } 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)); diff --git a/engines/zvision/text/text.h b/engines/zvision/text/text.h index ecec3ccde6..c942b8141a 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 { @@ -55,21 +55,25 @@ 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 +#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 ?? }; diff --git a/engines/zvision/graphics/truetype_font.cpp b/engines/zvision/text/truetype_font.cpp index 2dbd7ca358..622a02a6a8 100644 --- a/engines/zvision/graphics/truetype_font.cpp +++ b/engines/zvision/text/truetype_font.cpp @@ -32,7 +32,7 @@ #include "zvision/zvision.h" #include "zvision/graphics/render_manager.h" -#include "zvision/graphics/truetype_font.h" +#include "zvision/text/truetype_font.h" namespace ZVision { @@ -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) && !_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; @@ -255,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/graphics/truetype_font.h b/engines/zvision/text/truetype_font.h index b5fac4af8a..b5fac4af8a 100644 --- a/engines/zvision/graphics/truetype_font.h +++ b/engines/zvision/text/truetype_font.h diff --git a/engines/zvision/video/rlf_decoder.cpp b/engines/zvision/video/rlf_decoder.cpp index bdb5dc18bc..db598a25b6 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() { @@ -41,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) @@ -54,7 +56,7 @@ RLFDecoder::RLFVideoTrack::RLFVideoTrack(Common::SeekableReadStream *stream) _height(0), _frameTime(0), _frames(0), - _curFrame(0), + _displayedFrame(-1), _frameBufferByteSize(0) { if (!readHeader()) { @@ -62,7 +64,7 @@ RLFDecoder::RLFVideoTrack::RLFVideoTrack(Common::SeekableReadStream *stream) return; } - _currentFrameBuffer.create(_width, _height, Graphics::createPixelFormat<565>()); + _currentFrameBuffer.create(_width, _height, getPixelFormat()); _frameBufferByteSize = _width * _height * sizeof(uint16); _frames = new Frame[_frameCount]; @@ -83,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 @@ -163,16 +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; - if (frame < 0) { - _curFrame = 0; - return false; - } - - 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) { @@ -196,19 +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() { - // When an animation ends, rewind - if (_curFrame == (int)_frameCount) - seek(Audio::Timestamp(0, getFrameRate().toInt())); + if (_displayedFrame >= (int)_frameCount) + return NULL; - applyFrameToCurrent(_curFrame); + _displayedFrame++; + applyFrameToCurrent(_displayedFrame); - _curFrame++; return &_currentFrameBuffer; } @@ -242,10 +234,7 @@ void RLFDecoder::RLFVideoTrack::decodeMaskedRunLengthEncoding(int8 *source, int8 return; } - byte r, g, b; - Graphics::colorToRGB<Graphics::ColorMasks<555> >(READ_LE_UINT16(source + sourceOffset), r, g, b); - uint16 destColor = Graphics::RGBToColor<Graphics::ColorMasks<565> >(r, g, b); - WRITE_UINT16(dest + destOffset, destColor); + WRITE_UINT16(dest + destOffset, READ_LE_UINT16(source + sourceOffset)); sourceOffset += 2; destOffset += 2; @@ -289,10 +278,7 @@ void RLFDecoder::RLFVideoTrack::decodeSimpleRunLengthEncoding(int8 *source, int8 return; } - byte r, g, b; - Graphics::colorToRGB<Graphics::ColorMasks<555> >(READ_LE_UINT16(source + sourceOffset), r, g, b); - uint16 destColor = Graphics::RGBToColor<Graphics::ColorMasks<565> >(r, g, b); - WRITE_UINT16(dest + destOffset, destColor); + WRITE_UINT16(dest + destOffset, READ_LE_UINT16(source + sourceOffset)); sourceOffset += 2; destOffset += 2; @@ -306,9 +292,7 @@ void RLFDecoder::RLFVideoTrack::decodeSimpleRunLengthEncoding(int8 *source, int8 return; } - byte r, g, b; - Graphics::colorToRGB<Graphics::ColorMasks<555> >(READ_LE_UINT16(source + sourceOffset), r, g, b); - uint16 sampleColor = Graphics::RGBToColor<Graphics::ColorMasks<565> >(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..8b8cbaecd5 100644 --- a/engines/zvision/video/rlf_decoder.h +++ b/engines/zvision/video/rlf_decoder.h @@ -45,15 +45,15 @@ 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*/ } - int getCurFrame() const { return _curFrame; } + Graphics::PixelFormat getPixelFormat() const { return Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0); /* RGB 555 */ } + int getCurFrame() const { return _displayedFrame; } int getFrameCount() const { return _frameCount; } const Graphics::Surface *decodeNextFrame(); bool isSeekable() const { return true; } 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 { @@ -121,7 +121,7 @@ private: Frame *_frames; Common::Array<uint> _completeFrames; - int _curFrame; + int _displayedFrame; Graphics::Surface _currentFrameBuffer; uint32 _frameBufferByteSize; diff --git a/engines/zvision/video/video.cpp b/engines/zvision/video/video.cpp index 189fb22194..0913b28818 100644 --- a/engines/zvision/video/video.cpp +++ b/engines/zvision/video/video.cpp @@ -29,7 +29,8 @@ #include "zvision/zvision.h" #include "zvision/core/clock.h" #include "zvision/graphics/render_manager.h" -#include "zvision/graphics/subtitles.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" @@ -48,7 +49,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; } @@ -70,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(); @@ -101,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) { @@ -109,7 +116,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/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); } diff --git a/engines/zvision/zvision.cpp b/engines/zvision/zvision.cpp index c32cceb26e..54991aced3 100644 --- a/engines/zvision/zvision.cpp +++ b/engines/zvision/zvision.cpp @@ -27,13 +27,13 @@ #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/core/menu.h" +#include "zvision/scripting/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" @@ -46,42 +46,41 @@ #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 17 +#define ZVISION_SETTINGS_KEYS_COUNT 11 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 + {"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), - _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), @@ -95,12 +94,14 @@ ZVision::ZVision(OSystem *syst, const ZVisionGameDescription *gameDesc) _menu(nullptr), _searchManager(nullptr), _textRenderer(nullptr), - _halveDelay(false), + _doubleFPS(false), _audioId(0), _frameRenderDelay(2), _keyboardVelocity(0), _mouseVelocity(0), - _videoIsPlaying(false) { + _videoIsPlaying(false), + _renderedFrameCount(0), + _fps(0) { debug(1, "ZVision::ZVision"); @@ -124,24 +125,45 @@ 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; + getTimerManager()->removeTimerProc(&fpsTimerCallback); + // Remove all of our debug levels DebugMan.clearAllDebugChannels(); } 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 = (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); @@ -150,8 +172,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(); } @@ -182,17 +211,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, _resourcePixelFormat, _doubleFPS); _saveManager = new SaveManager(this); _stringManager = new StringManager(this); - _cursorManager = new CursorManager(this, &_pixelFormat); + _cursorManager = new CursorManager(this, _resourcePixelFormat); _textRenderer = new TextRenderer(this); _midiManager = new MidiManager(); @@ -212,7 +241,10 @@ void ZVision::initialize() { // Create debugger console. It requires GFX to be initialized _console = new Console(this); - _halveDelay = ConfMan.getBool("doublefps"); + _doubleFPS = ConfMan.getBool("doublefps"); + + // Initialize FPS timer callback + getTimerManager()->installTimerProc(&fpsTimerCallback, 1000000, this, "zvisionFPS"); } Common::Error ZVision::run() { @@ -222,6 +254,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") && !_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(); @@ -231,7 +279,7 @@ Common::Error ZVision::run() { _cursorManager->setItemID(_scriptManager->getStateValue(StateKey_InventoryItem)); processEvents(); - updateRotation(); + _renderManager->updateRotation(); _scriptManager->update(deltaTime); _menu->process(deltaTime); @@ -243,8 +291,9 @@ Common::Error ZVision::run() { _renderManager->renderSceneToScreen(); // Update the screen - if (_frameRenderDelay <= 0) { + if (canRender()) { _system->updateScreen(); + _renderedFrameCount++; } else { _frameRenderDelay--; } @@ -254,85 +303,18 @@ Common::Error ZVision::run() { // Ensure non-negative delay = delay < 0 ? 0 : delay; - if (_halveDelay) { + if (_doubleFPS) { delay >>= 1; } - _system->delayMillis(delay); - } - - 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; - } - } + if (canSaveGameStateCurrently() && shouldPerformAutoSave(_saveManager->getLastSaveTime())) { + _saveManager->autoSave(); } - _system->updateScreen(); - if (_halveDelay) - _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 (_halveDelay) - _system->delayMillis(33); - else - _system->delayMillis(66); + _system->delayMillis(delay); } - _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); + return Common::kNoError; } void ZVision::pauseEngineIntern(bool pause) { @@ -349,10 +331,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; } @@ -361,188 +339,23 @@ bool ZVision::canRender() { return _frameRenderDelay <= 0; } -void ZVision::updateRotation() { - int16 _velocity = _mouseVelocity + _keyboardVelocity; - - if (_halveDelay) - _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); - } - } +GUI::Debugger *ZVision::getDebugger() { + return _console; } -void ZVision::checkBorders() { - RenderTable::RenderState renderState = _renderManager->getRenderTable()->getRenderState(); - if (renderState == RenderTable::PANORAMA) { - int16 startPosition = _scriptManager->getStateValue(StateKey_ViewPos); - - int16 newPosition = startPosition; +void ZVision::syncSoundSettings() { + Engine::syncSoundSettings(); - 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 (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; + _scriptManager->setStateValue(StateKey_Subtitles, ConfMan.getBool("subtitles") ? 1 : 0); } -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::fpsTimerCallback(void *refCon) { + ((ZVision *)refCon)->fpsTimer(); } -void ZVision::showDebugMsg(const Common::String &msg, int16 delay) { - uint16 msgid = _renderManager->createSubArea(); - _renderManager->updateSubArea(msgid, msg); - _renderManager->deleteSubArea(msgid, delay); +void ZVision::fpsTimer() { + _fps = _renderedFrameCount; + _renderedFrameCount = 0; } } // End of namespace ZVision diff --git a/engines/zvision/zvision.h b/engines/zvision/zvision.h index 7ea10ed64d..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; @@ -68,7 +79,8 @@ public: * edges of this Rectangle */ Common::Rect _workingWindow; - const Graphics::PixelFormat _pixelFormat; + const Graphics::PixelFormat _resourcePixelFormat; + const Graphics::PixelFormat _screenPixelFormat; private: enum { @@ -118,9 +130,11 @@ private: Common::Event _event; int _frameRenderDelay; + int _renderedFrameCount; + int _fps; int16 _mouseVelocity; int16 _keyboardVelocity; - bool _halveDelay; + bool _doubleFPS; bool _videoIsPlaying; uint8 _cheatBuffer[KEYBUF_SIZE]; @@ -154,15 +168,32 @@ 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); + 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. @@ -175,29 +206,24 @@ 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(); - - 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(); + static void fpsTimerCallback(void *refCon); + void fpsTimer(); + int getFPS() const { + return _fps; + } + + GUI::Debugger *getDebugger(); + void syncSoundSettings(); void loadSettings(); void saveSettings(); - void menuBarEnable(uint16 menus); - uint16 getMenuBarEnable(); - bool ifQuit(); - void checkBorders(); - void showDebugMsg(const Common::String &msg, int16 delay = 3000); - // Engine features bool hasFeature(EngineFeature f) const; bool canLoadGameStateCurrently(); @@ -214,7 +240,6 @@ private: void processEvents(); void onMouseMove(const Common::Point &pos); - void updateRotation(); void registerDefaultSettings(); void shortKeys(Common::Event); |