diff options
Diffstat (limited to 'engines')
117 files changed, 4577 insertions, 872 deletions
diff --git a/engines/avalanche/animation.cpp b/engines/avalanche/animation.cpp index 639abe99b3..74dd2100e5 100644 --- a/engines/avalanche/animation.cpp +++ b/engines/avalanche/animation.cpp @@ -815,10 +815,9 @@ void Animation::callSpecial(uint16 which) { } break; case 4: // This is the ghost room link. - _vm->fadeOut(); - _sprites[0]->turn(kDirRight); // you'll see this after we get back from bootstrap + _sprites[0]->turn(kDirRight); // You'll see this after we get back. _vm->_timer->addTimer(1, Timer::kProcGhostRoomPhew, Timer::kReasonGhostRoomPhew); - //_vm->_enid->backToBootstrap(3); TODO: Replace it with proper ScummVM-friendly function(s)! Do not remove until then! + _vm->_ghostroom->run(); break; case 5: if (_vm->_friarWillTieYouUp) { diff --git a/engines/avalanche/avalanche.cpp b/engines/avalanche/avalanche.cpp index a7e7be0ad3..073b9a9425 100644 --- a/engines/avalanche/avalanche.cpp +++ b/engines/avalanche/avalanche.cpp @@ -46,7 +46,6 @@ AvalancheEngine::AvalancheEngine(OSystem *syst, const AvalancheGameDescription * _clock = nullptr; _graphics = nullptr; _parser = nullptr; - _pingo = nullptr; _dialogs = nullptr; _background = nullptr; _sequence = nullptr; @@ -56,6 +55,9 @@ AvalancheEngine::AvalancheEngine(OSystem *syst, const AvalancheGameDescription * _closing = nullptr; _sound = nullptr; _nim = nullptr; + _ghostroom = nullptr; + _help = nullptr; + _shootemup = nullptr; _platform = gd->desc.platform; initVariables(); @@ -69,7 +71,6 @@ AvalancheEngine::~AvalancheEngine() { delete _parser; delete _clock; - delete _pingo; delete _dialogs; delete _background; delete _sequence; @@ -79,6 +80,9 @@ AvalancheEngine::~AvalancheEngine() { delete _closing; delete _sound; delete _nim; + delete _ghostroom; + delete _help; + delete _shootemup; for (int i = 0; i < 31; i++) { for (int j = 0; j < 2; j++) { @@ -152,7 +156,6 @@ Common::ErrorCode AvalancheEngine::initialize() { _parser = new Parser(this); _clock = new Clock(this); - _pingo = new Pingo(this); _dialogs = new Dialogs(this); _background = new Background(this); _sequence = new Sequence(this); @@ -162,6 +165,9 @@ Common::ErrorCode AvalancheEngine::initialize() { _closing = new Closing(this); _sound = new SoundHandler(this); _nim = new Nim(this); + _ghostroom = new GhostRoom(this); + _help = new Help(this); + _shootemup = new ShootEmUp(this); _graphics->init(); _dialogs->init(); diff --git a/engines/avalanche/avalanche.h b/engines/avalanche/avalanche.h index fe13fa8d9e..d2e5678ae9 100644 --- a/engines/avalanche/avalanche.h +++ b/engines/avalanche/avalanche.h @@ -32,7 +32,6 @@ #include "avalanche/graphics.h" #include "avalanche/parser.h" #include "avalanche/avalot.h" -#include "avalanche/pingo.h" #include "avalanche/dialogs.h" #include "avalanche/background.h" #include "avalanche/sequence.h" @@ -43,6 +42,9 @@ #include "avalanche/sound.h" #include "avalanche/nim.h" #include "avalanche/clock.h" +#include "avalanche/ghostroom.h" +#include "avalanche/help.h" +#include "avalanche/shootemup.h" #include "common/serializer.h" @@ -77,7 +79,6 @@ public: Clock *_clock; GraphicManager *_graphics; Parser *_parser; - Pingo *_pingo; Dialogs *_dialogs; Background *_background; Sequence *_sequence; @@ -87,6 +88,9 @@ public: Closing *_closing; SoundHandler *_sound; Nim *_nim; + GhostRoom *_ghostroom; + Help *_help; + ShootEmUp *_shootemup; OSystem *_system; diff --git a/engines/avalanche/background.cpp b/engines/avalanche/background.cpp index 5d168a20af..f49d103df3 100644 --- a/engines/avalanche/background.cpp +++ b/engines/avalanche/background.cpp @@ -279,24 +279,24 @@ void Background::load(byte number) { sprite._type = (PictureType)(f.readByte()); sprite._x = f.readSint16LE(); sprite._y = f.readSint16LE(); - sprite._xl = f.readSint16LE(); - sprite._yl = f.readSint16LE(); + sprite._width = f.readSint16LE(); + sprite._height = f.readSint16LE(); sprite._size = f.readSint32LE(); bool natural = f.readByte(); bool memorize = f.readByte(); if (memorize) { _sprites[i]._x = sprite._x; - _sprites[i]._xl = sprite._xl; + _sprites[i]._width = sprite._width; _sprites[i]._y = sprite._y; - _sprites[i]._yl = sprite._yl; + _sprites[i]._height = sprite._height; _sprites[i]._type = sprite._type; if (natural) _vm->_graphics->getNaturalPicture(_sprites[i]); else { _sprites[i]._size = sprite._size; - _sprites[i]._picture = _vm->_graphics->loadPictureRaw(f, _sprites[i]._xl * 8, _sprites[i]._yl + 1); + _sprites[i]._picture = _vm->_graphics->loadPictureRaw(f, _sprites[i]._width * 8, _sprites[i]._height + 1); } } else _sprites[i]._x = kOnDisk; @@ -335,11 +335,11 @@ void Background::draw(int16 destX, int16 destY, byte sprId) { sprite._type = (PictureType)(f.readByte()); sprite._x = f.readSint16LE(); sprite._y = f.readSint16LE(); - sprite._xl = f.readSint16LE(); - sprite._yl = f.readSint16LE(); + sprite._width = f.readSint16LE(); + sprite._height = f.readSint16LE(); sprite._size = f.readSint32LE(); f.skip(2); // Natural and Memorize are used in Load() - sprite._picture = _vm->_graphics->loadPictureRaw(f, sprite._xl * 8, sprite._yl + 1); + sprite._picture = _vm->_graphics->loadPictureRaw(f, sprite._width * 8, sprite._height + 1); if (destX < 0) { destX = sprite._x * 8; diff --git a/engines/avalanche/background.h b/engines/avalanche/background.h index 34d7a9a2cc..67020c861d 100644 --- a/engines/avalanche/background.h +++ b/engines/avalanche/background.h @@ -40,7 +40,7 @@ enum PictureType {kEga, kBgi, kNaturalImage}; struct SpriteType { PictureType _type; int16 _x, _y; - int16 _xl, _yl; + int16 _width, _height; int32 _size; Graphics::Surface _picture; }; diff --git a/engines/avalanche/enums.h b/engines/avalanche/enums.h index 2b5db67609..23192863f1 100644 --- a/engines/avalanche/enums.h +++ b/engines/avalanche/enums.h @@ -29,6 +29,10 @@ #define AVALANCHE_ENUMS_H namespace Avalanche { + + +enum Flavour { kFlavourEga, kFlavourBgi, kFlavourNatural, kFlavourTwo, kFlavourOne }; + enum Color { kColorBlack = 0, kColorBlue, kColorGreen, kColorCyan, kColorRed, kColorMagenta = 5, kColorBrown, kColorLightgray, kColorDarkgray, kColorLightblue, @@ -87,7 +91,7 @@ enum VerbCode { enum MouseCursor { kCurUpArrow = 0, kCurScrewDriver = 1, kCurRightArrow = 2, kCurFletch = 3, kCurWait = 4, kCurHand = 5, - kCurCrosshair = 6, kCurIBeam = 7 + kCurCrosshair = 6, kCurIBeam = 7, kCurHelp = 8 }; // Magic/portal constants: diff --git a/engines/avalanche/ghostroom.cpp b/engines/avalanche/ghostroom.cpp new file mode 100644 index 0000000000..b67df878ee --- /dev/null +++ b/engines/avalanche/ghostroom.cpp @@ -0,0 +1,364 @@ +/* ScummVM - Graphic Adventure Engine +* +* ScummVM is the legal property of its developers, whose names +* are too numerous to list here. Please refer to the COPYRIGHT +* file distributed with this source distribution. +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. + +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. + +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +* +*/ + +/* +* This code is based on the original source code of Lord Avalot d'Argent version 1.3. +* Copyright (c) 1994-1995 Mike: Mark and Thomas Thurman. +*/ + +#include "avalanche/avalanche.h" +#include "avalanche/ghostroom.h" + +#include "common/random.h" + +namespace Avalanche { + +const int8 GhostRoom::kAdjustment[5] = { 7, 0, 7, 7, 7 }; +const byte GhostRoom::kWaveOrder[5] = { 4, 0, 1, 2, 3 }; +const byte GhostRoom::kGlerkFade[26] = { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1, 0 }; +const byte GhostRoom::kGreldetFade[18] = { 0, 1, 2, 3, 4, 5, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 0, 0 }; + +GhostRoom::GhostRoom(AvalancheEngine *vm) { + _vm = vm; + + _glerkStage = 0; + _batX = 0; + _batY = 0; + _batCount = 0; + _aarghCount = 0; + _greldetX = _greldetY = 0; + _greldetCount = 0; + _redGreldet = false; + _wasLoaded = false; +} + +GhostRoom::~GhostRoom() { + for (int i = 0; i < 2; i++) + _eyes[i].free(); + + _exclamation.free(); + + for (int i = 0; i < 3; i++) + _bat[i].free(); + + for (int i = 0; i < 6; i++) + _aargh[i].free(); + + for (int i = 0; i < 5; i++) + _greenEyes[i].free(); + + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 6; j++) + _greldet[j][i].free(); + } +} + +void GhostRoom::wait(uint16 howLong) { + for (int i = 0; i < howLong; i++) { + Common::Event event; + _vm->getEvent(event); + if (event.type == Common::EVENT_KEYDOWN) + _vm->_sound->playNote(6177, 1); + _vm->_system->delayMillis(1); + } +} + +void GhostRoom::doBat() { + _batCount++; + + int8 dx = 0; + int8 iy = 0; + byte batImage = 0; + if ((_batCount % 2) == 1) { + if ((1 <= _batCount) && (_batCount <= 90)) { + dx = 2; + iy = 1; + batImage = 0; + } else if ((91 <= _batCount) && (_batCount <= 240)) { + dx = 1; + iy = 1; + batImage = 1; + } else if((241 <= _batCount) && (_batCount <= 260)) { + dx = 1; + iy = 4; + batImage = 2; + } + + if ((_batCount == 91) || (_batCount == 241)) // When the bat changes, blank out the old one. + _vm->_graphics->drawFilledRectangle(Common::Rect(_batX + _bat[batImage].w, _batY, _batX + _bat[batImage - 1].w, _batY + _bat[batImage - 1].h), kColorBlack); + + _vm->_graphics->drawFilledRectangle(Common::Rect(_batX, _batY, _batX + _bat[batImage].w, _batY + iy), kColorBlack); + _vm->_graphics->drawFilledRectangle(Common::Rect(_batX + _bat[batImage].w - dx, _batY, _batX + _bat[batImage].w, _batY + _bat[batImage].h), kColorBlack); + + _batX -= dx; + _batY++; + _vm->_graphics->ghostDrawPicture(_bat[batImage], _batX, _batY); + } +} + +void GhostRoom::bigGreenEyes(byte how) { + _vm->_graphics->ghostDrawPicture(_greenEyes[how], 330, 103); + _vm->_graphics->ghostDrawPicture(_greenEyes[how], 376, 103); + _vm->_graphics->refreshScreen(); +} + +ChunkBlock GhostRoom::readChunkBlock(Common::File &file) { + ChunkBlock cb; + cb._flavour = (Flavour)file.readByte(); + cb._x = file.readSint16LE(); + cb._y = file.readSint16LE(); + cb._width = file.readSint16LE(); + cb._height = file.readSint16LE(); + cb._size = file.readSint32LE(); + return cb; +} + +void GhostRoom::loadPictures() { + Common::File file; + + if (!file.open("spooky.avd")) + error("AVALANCHE: GhostRoom: File not found: spooky.avd"); + + file.seek(44); + + // Initializing ghost's array. + for (int i = 0; i < 5; i++) { + for (int j = 0; j < 2; j++) { + for (int y = 0; y < 66; y++) { + for (int x = 0; x < 26; x++) + _ghost[i][j][y][x] = 0; + } + } + } + + // Read in the pictures of the ghost. + for (int i = 0; i < 5; i++) { + ChunkBlock cb = readChunkBlock(file); + for (int j = 0; j < 2; j++) { + for (int y = 0; y <= cb._height; y++) + file.read(_ghost[i][j][y], cb._width / 8); + } + } + + for (int i = 0; i < 2; i++) + _eyes[i] = _vm->_graphics->ghostLoadPicture(file, dummyCoord); + + _exclamation = _vm->_graphics->ghostLoadPicture(file, dummyCoord); + + // Actually this function not just loads, but also draws the images, but they are part of the background + // and they are need to be drawn only once. + _vm->_graphics->ghostDrawBackgroundItems(file); + + for (int i = 0; i < 3; i++) + _bat[i] = _vm->_graphics->ghostLoadPicture(file, dummyCoord); + + + // Initializing glerk's array. + for (int i = 0; i < 6; i++) { + for (int j = 0; j < 4; j++) { + for (int y = 0; y < 35; y++) { + for (int x = 0; x < 9; x++) + _glerk[i][j][y][x] = 0; + } + } + } + + // Read in the pictures of the "glerk". + for (int i = 0; i < 6; i++) { + ChunkBlock cb = readChunkBlock(file); + for (int j = 0; j < 4; j++) { + for (int y = 0; y <= cb._height; y++) + file.read(_glerk[i][j][y], cb._width / 8); + } + } + + for (int i = 0; i < 6; i++) + _aargh[i] = _vm->_graphics->ghostLoadPicture(file, _aarghWhere[i]); + + for (int i = 0; i < 5; i++) + _greenEyes[i] = _vm->_graphics->ghostLoadPicture(file, dummyCoord); + + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 6; j++) + _greldet[j][i] = _vm->_graphics->ghostLoadPicture(file, dummyCoord); + } + + file.close(); +} + +void GhostRoom::run() { + CursorMan.showMouse(false); + _vm->_graphics->saveScreen(); + _vm->fadeOut(); + _vm->_graphics->drawFilledRectangle(Common::Rect(0, 0, 640, 200), kColorBlack); // Black out the whole screen. + _vm->fadeIn(); + + // Only load the pictures if it's our first time walking into the room. + // After that we simply use the already loaded images. + if (!_wasLoaded) { + loadPictures(); + _wasLoaded = true; + } + + // Avvy walks over: + _glerkStage = 0; + _batX = 277; + _batY = 40; + _batCount = 0; + + for (int x = 500; x >= 217; x--) { + // The floating eyeballs: + int xBound = x % 30; + if ((22 <= xBound) && (xBound <= 27)) { + if (xBound == 27) + _vm->_graphics->drawFilledRectangle(Common::Rect(x, 135, x + 17, 137), kColorBlack); + _vm->_graphics->ghostDrawPicture(_eyes[0], x, 136); + _vm->_graphics->drawDot(x + 16, 137, kColorBlack); + } else { + if (xBound == 21) + _vm->_graphics->drawFilledRectangle(Common::Rect(x, 137, x + 18, 139), kColorBlack); + _vm->_graphics->ghostDrawPicture(_eyes[0], x, 135); + _vm->_graphics->drawDot(x + 16, 136, kColorBlack); // Eyes would leave a trail 1 pixel high behind them. + } + + // Plot the Glerk: + if ((x % 10) == 0) { + if (_glerkStage > 25) + break; + + _vm->_graphics->ghostDrawGlerk(_glerk[kGlerkFade[_glerkStage]], 456, 14); + _glerkStage++; + } + + doBat(); + + _vm->_graphics->refreshScreen(); + + wait(15); + } + + // Blank out the Glerk's space. + _vm->_graphics->drawFilledRectangle(Common::Rect(456, 14, 530, 50), kColorBlack); + _vm->_graphics->refreshScreen(); + + + // Here comes the descending ghost: + for (int y = -64; y <= 103; y++) { + _vm->_graphics->ghostDrawGhost(_ghost[1 + (abs(y / 7) % 2) * 3], 0, y); + if (y > 0) + _vm->_graphics->drawFilledRectangle(Common::Rect(0, y - 1, 26 * 8, y), kColorBlack); + _vm->_graphics->refreshScreen(); + + wait(27); + } + + // Then it waves: + _aarghCount = -15; + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 5; j++) { + _vm->_graphics->drawFilledRectangle(Common::Rect(0, 96, 26 * 8, 169), kColorBlack); + _vm->_graphics->ghostDrawGhost(_ghost[kWaveOrder[j]], 0, 96 + kAdjustment[j]); + + _aarghCount++; + + if (_aarghCount >= 0) { + for (int k = 0; k <= _aarghCount; k++) + _vm->_graphics->ghostDrawPicture(_aargh[k], _aarghWhere[k].x, _aarghWhere[k].y); + } + + _vm->_graphics->refreshScreen(); + + wait(177); + } + } + + // The exclamation mark appears: + _vm->_graphics->ghostDrawPicture(_exclamation, 246, 127); + _vm->_graphics->refreshScreen(); + wait(777); + + // Erase "aargh": + _vm->_graphics->drawFilledRectangle(Common::Rect(172, 78, 348, 112), kColorBlack); + _vm->_graphics->refreshScreen(); + + for (int i = 4; i >= 0; i--) { + wait(377); + bigGreenEyes(i); + } + + // Erase the exclamation mark: + _vm->_graphics->drawFilledRectangle(Common::Rect(246, 127, 252, 134), kColorBlack); + _vm->_graphics->refreshScreen(); + + // Avvy hurries back: + _glerkStage = 0; + _greldetCount = 18; + _redGreldet = false; + + for (int x = 217; x <= 479; x++) { + // The floating eyeballs again: + int xBound = x % 30; + if ((22 <= xBound) && (xBound <= 27)) { + if (xBound == 22) + _vm->_graphics->drawFilledRectangle(Common::Rect(x + 22, 134, x + 38, 138), kColorBlack); + _vm->_graphics->ghostDrawPicture(_eyes[1], x + 23, 136); + _vm->_graphics->drawDot(x + 22, 137, kColorBlack); + } else { + if (xBound == 28) + _vm->_graphics->drawFilledRectangle(Common::Rect(x + 22, 135, x + 38, 139), kColorBlack); + _vm->_graphics->ghostDrawPicture(_eyes[1], x + 23, 135); + _vm->_graphics->drawDot(x + 22, 136, kColorBlack); // Eyes would leave a trail 1 pixel high behind them. + } + + // Plot the Green Eyes: + if ((x % 53) == 5) { + bigGreenEyes(_glerkStage); + _glerkStage++; + } + + // Plot the Greldet: + if (_greldetCount == 18) { + _greldetX = _vm->_rnd->getRandomNumber(599); + _greldetY = _vm->_rnd->getRandomNumber(79); + _greldetCount = 0; + _redGreldet = !_redGreldet; + } + + _vm->_graphics->ghostDrawPicture(_greldet[kGreldetFade[_greldetCount]][_redGreldet], _greldetX, _greldetY); + _greldetCount++; + + _vm->_graphics->refreshScreen(); + + wait(10); + } + + CursorMan.showMouse(true); + + _vm->fadeOut(); + _vm->_graphics->restoreScreen(); + _vm->_graphics->removeBackup(); + _vm->_animation->animLink(); + _vm->fadeIn(); +} + +} // End of namespace Avalanche diff --git a/engines/avalanche/ghostroom.h b/engines/avalanche/ghostroom.h new file mode 100644 index 0000000000..b4917d8cb4 --- /dev/null +++ b/engines/avalanche/ghostroom.h @@ -0,0 +1,88 @@ +/* ScummVM - Graphic Adventure Engine +* +* ScummVM is the legal property of its developers, whose names +* are too numerous to list here. Please refer to the COPYRIGHT +* file distributed with this source distribution. +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. + +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. + +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +* +*/ + +/* +* This code is based on the original source code of Lord Avalot d'Argent version 1.3. +* Copyright (c) 1994-1995 Mike: Mark and Thomas Thurman. +*/ + +#ifndef AVALANCHE_GHOSTROOM_H +#define AVALANCHE_GHOSTROOM_H + +#include "common/scummsys.h" +#include "graphics/surface.h" + +namespace Avalanche { +class AvalancheEngine; + +struct ChunkBlock { + Flavour _flavour; + int16 _x, _y; + int16 _width, _height; + int32 _size; +}; + +class GhostRoom { +public: + GhostRoom(AvalancheEngine *vm); + ~GhostRoom(); + + void run(); + ChunkBlock readChunkBlock(Common::File &file); + +private: + AvalancheEngine *_vm; + + static const int8 kAdjustment[5]; + static const byte kWaveOrder[5]; + static const byte kGlerkFade[26]; + static const byte kGreldetFade[18]; + + Common::Point dummyCoord; + byte _ghost[5][2][66][26]; + Graphics::Surface _eyes[2]; + Graphics::Surface _exclamation; + Graphics::Surface _bat[3]; + byte _glerk[6][4][35][9]; + Graphics::Surface _aargh[6]; + Common::Point _aarghWhere[6]; + Graphics::Surface _greenEyes[5]; + Graphics::Surface _greldet[6][2]; + + int16 _batX, _batY; + uint16 _batCount; + byte _glerkStage; + int8 _aarghCount; + int16 _greldetX, _greldetY; + byte _greldetCount; + bool _redGreldet; + bool _wasLoaded; + + void loadPictures(); + void wait(uint16 howLong); + void doBat(); + void bigGreenEyes(byte how); +}; + +} // End of namespace Avalanche + +#endif // AVALANCHE_GHOSTROOM_H diff --git a/engines/avalanche/graphics.cpp b/engines/avalanche/graphics.cpp index a8efc4be9b..a1087375b2 100644 --- a/engines/avalanche/graphics.cpp +++ b/engines/avalanche/graphics.cpp @@ -281,6 +281,10 @@ Common::Point GraphicManager::drawArc(Graphics::Surface &surface, int16 x, int16 return endPoint; } +void GraphicManager::drawDot(int x, int y, Color color) { + *(byte *)_surface.getBasePtr(x, y) = color; +} + void GraphicManager::drawLine(int x1, int y1, int x2, int y2, int penX, int penY, Color color) { _surface.drawThickLine(x1, y1, x2, y2, penX, penY, color); } @@ -348,6 +352,25 @@ void GraphicManager::drawNormalText(const Common::String text, FontType font, by drawText(_surface, text, font, fontHeight, x, y, color); } +/** + * Used in Help. Draws text double the size of the normal. + */ +void GraphicManager::drawBigText(const Common::String text, FontType font, byte fontHeight, int16 x, int16 y, Color color) { + for (uint i = 0; i < text.size(); i++) { + for (int j = 0; j < fontHeight; j++) { + byte pixel = font[(byte)text[i]][j]; + byte pixelBit = 0; + for (int bit = 0; bit < 16; bit++) { + if ((bit % 2) == 0) + pixelBit = (pixel >> (bit / 2)) & 1; + for (int k = 0; k < 2; k++) + if (pixelBit) + *(byte *)_surface.getBasePtr(x + i * 16 + 16 - bit, y + j * 2 + k) = color; + } + } + } +} + void GraphicManager::drawScrollText(const Common::String text, FontType font, byte fontHeight, int16 x, int16 y, Color color) { drawText(_scrolls, text, font, fontHeight, x, y, color); } @@ -500,6 +523,213 @@ void GraphicManager::nimFree() { _nimLogo.free(); } +void GraphicManager::ghostDrawGhost(byte ghostArr[2][66][26], uint16 destX, int16 destY) { + const byte kPlaneToUse[4] = { 0, 0, 0, 1 }; + // Constants from the original code: + uint16 height = 66; + const uint16 width = 26 * 8; + + // We have to mess around with the coords and the sizes since + // the ghost isn't always placed fully on the screen. + int yStart = 0; + if (destY < 0) { + yStart = abs(destY); + height -= yStart; + destY = 0; + } + + Graphics::Surface ghostPic; + ghostPic.create(width, height, Graphics::PixelFormat::createFormatCLUT8()); + + for (int y = 0; y < height; y++) { + for (int plane = 0; plane < 4; plane++) { + for (uint16 x = 0; x < width / 8; x ++) { + byte pixel = ghostArr[kPlaneToUse[plane]][y + yStart][x]; + for (int bit = 0; bit < 8; bit++) { + byte pixelBit = (pixel >> bit) & 1; + *(byte *)ghostPic.getBasePtr(x * 8 + 7 - bit, y) += (pixelBit << plane); + } + } + } + } + + drawPicture(_surface, ghostPic, destX, destY); + + ghostPic.free(); +} + +void GraphicManager::ghostDrawGlerk(byte glerkArr[4][35][9], uint16 destX, uint16 destY) { + // Constants from the original code: + const uint16 height = 35; + const uint16 width = 9 * 8; + + Graphics::Surface glerkPic; + glerkPic.create(width, height, Graphics::PixelFormat::createFormatCLUT8()); + + for (int y = 0; y < height; y++) { + for (int plane = 0; plane < 4; plane++) { + for (uint16 x = 0; x < width / 8; x++) { + byte pixel = glerkArr[plane][y][x]; + for (int bit = 0; bit < 8; bit++) { + byte pixelBit = (pixel >> bit) & 1; + *(byte *)glerkPic.getBasePtr(x * 8 + 7 - bit, y) += (pixelBit << plane); + } + } + } + } + + drawPicture(_surface, glerkPic, destX, destY); + + glerkPic.free(); +} + +/** + * With the use of the second argument, it replaces get_meg_aargh as well. + * @remarks Originally called 'get_me' and was located in Ghostroom. + */ +Graphics::Surface GraphicManager::ghostLoadPicture(Common::File &file, Common::Point &coord) { + ChunkBlock cb = _vm->_ghostroom->readChunkBlock(file); + + coord.x = cb._x; + coord.y = cb._y; + + Graphics::Surface picture = loadPictureGraphic(file); + + int bytesPerRow = (picture.w / 8); + if ((picture.w % 8) > 0) + bytesPerRow += 1; + int loadedBytes = picture.h * bytesPerRow * 4 + 4; + // * 4 is for the four planes, + 4 is for the reading of the width and the height at loadPictureGraphic's beginning. + + int bytesToSkip = cb._size - loadedBytes; + file.skip(bytesToSkip); + + return picture; +} + +void GraphicManager::ghostDrawPicture(const Graphics::Surface &picture, uint16 destX, uint16 destY) { + drawPicture(_surface, picture, destX, destY); +} + +/** + * Loads and puts 3 images (in this order: cobweb, Mark's signature, open door) into the background at the beginning of the ghostroom scene. + * @remarks Originally called 'plain_grab' and was located in Ghostroom. It was originally called 3 times. I unified these in one function, used a for cycle. + */ +void GraphicManager::ghostDrawBackgroundItems(Common::File &file) { + for (int num = 0; num < 3; num++) { + ChunkBlock cb = _vm->_ghostroom->readChunkBlock(file); + + int width = cb._width; + int height = cb._height + 1; + + Graphics::Surface picture; + picture.create(width, height, Graphics::PixelFormat::createFormatCLUT8()); + + // Load the picture according to it's type. + switch (cb._flavour) { + case kFlavourOne: // There is only one plane. + for (uint16 y = 0; y < height; y++) { + for (uint16 x = 0; x < width; x += 8) { + byte pixel = file.readByte(); + for (int i = 0; i < 8; i++) { + byte pixelBit = (pixel >> i) & 1; + *(byte *)picture.getBasePtr(x + 7 - i, y) = (pixelBit << 3); + } + } + } + break; + case kFlavourEga: + picture = loadPictureRaw(file, width, height); + break; + default: + break; + } + + drawPicture(_surface, picture, cb._x, cb._y); + + picture.free(); + } + refreshScreen(); +} + +/** +* @remarks Originally called 'plot_button' +*/ +void GraphicManager::helpDrawButton(int y, byte which) { + if (y > 200) { + _vm->_graphics->setBackgroundColor(kColorGreen); + _vm->_system->delayMillis(10); + _vm->_graphics->setBackgroundColor(kColorBlack); + return; + } + + Common::File file; + + if (!file.open("buttons.avd")) + error("AVALANCHE: Help: File not found: buttons.avd"); + + file.seek(which * 930); // 930 is the size of one button. + + Graphics::Surface button = loadPictureGraphic(file); + + int x = 0; + if (y == -177) { + x = 229; + y = 5; + } + else + x = 470; + + _vm->_graphics->drawPicture(_surface, button, x, y); + + button.free(); + file.close(); +} + +/** + * @remarks Originally called 'light' + */ +void GraphicManager::helpDrawHighlight(byte which, Color color) { + if (which == 177) // Dummy value for "no button at all". + return; + + which &= 31; + drawRectangle(Common::Rect(466, 38 + which * 27, 555, 63 + which * 27), color); +} + +/** + * @remarks Originally called 'titles' + */ +void GraphicManager::seuDrawTitle() { + Common::File file; + + if (!file.open("shoot1.avd")) + error("AVALANCHE: ShootEmUp: File not found: shoot1.avd"); + + const uint16 width = 320; + const uint16 height = 200; + + Graphics::Surface picture = loadPictureRaw(file, width, height); + + Graphics::Surface doubledPicture; + doubledPicture.create(width * 2, height, Graphics::PixelFormat::createFormatCLUT8()); + + // These cycles are for doubling the picture's width. + for (int x = (width * 2) - 2 ; x >= 0; x -= 2) { + for (int y = 0; y < height; y++) { + *(byte *)doubledPicture.getBasePtr(x, y) = *(byte *)doubledPicture.getBasePtr(x + 1, y) = *(byte *)picture.getBasePtr(x / 2, y); + } + } + + drawPicture(_surface, doubledPicture, 0, 0); + refreshScreen(); + + picture.free(); + doubledPicture.free(); + + file.close(); +} + /** * This function mimics Pascal's getimage(). */ @@ -510,7 +740,7 @@ Graphics::Surface GraphicManager::loadPictureGraphic(Common::File &file) { Graphics::Surface picture; // We make a Surface object for the picture itself. picture.create(width, height, Graphics::PixelFormat::createFormatCLUT8()); - + // Produce the picture. We read it in row-by-row, and every row has 4 planes. for (int y = 0; y < height; y++) { for (int8 plane = 3; plane >= 0; plane--) { // The planes are in the opposite way. @@ -518,8 +748,7 @@ Graphics::Surface GraphicManager::loadPictureGraphic(Common::File &file) { byte pixel = file.readByte(); for (int bit = 0; bit < 8; bit++) { byte pixelBit = (pixel >> bit) & 1; - if (pixelBit != 0) - *(byte *)picture.getBasePtr(x + 7 - bit, y) += (pixelBit << plane); + *(byte *)picture.getBasePtr(x + 7 - bit, y) += (pixelBit << plane); } } } @@ -567,8 +796,7 @@ Graphics::Surface GraphicManager::loadPictureSign(Common::File &file, int xl, in byte pixel = file.readByte(); for (int bit = 0; bit < 8; bit++) { byte pixelBit = (pixel >> bit) & 1; - if (pixelBit != 0) - *(byte *)picture.getBasePtr(xx + 7 - bit, yy) += (pixelBit << plane); + *(byte *)picture.getBasePtr(xx + 7 - bit, yy) += (pixelBit << plane); } } } @@ -587,6 +815,19 @@ void GraphicManager::shiftScreen() { _surface.drawLine(0, 0, _surface.w, 0, kColorBlack); } +void GraphicManager::drawWinningPic() { + Common::File file; + + if (!file.open("finale.avd")) + error("AVALANCHE: Timer: File not found: finale.avd"); + + Graphics::Surface winning = loadPictureRaw(file, 640, 200); + drawPicture(_surface, winning, 0, 0); + + winning.free(); + file.close(); +} + void GraphicManager::clearAlso() { _magics.fillRect(Common::Rect(0, 0, 640, 200), 0); _magics.frameRect(Common::Rect(0, 45, 640, 161), 15); @@ -799,10 +1040,10 @@ void GraphicManager::showScroll() { void GraphicManager::getNaturalPicture(SpriteType &sprite) { sprite._type = kNaturalImage; // We simply read from the screen and later, in drawSprite() we draw it right back. - sprite._size = sprite._xl * 8 * sprite._yl + 1; - sprite._picture.create(sprite._xl * 8, sprite._yl + 1, Graphics::PixelFormat::createFormatCLUT8()); - for (uint16 y = 0; y < sprite._yl + 1; y++) { - for (uint16 x = 0; x < sprite._xl * 8; x++) + sprite._size = sprite._width * 8 * sprite._height + 1; + sprite._picture.create(sprite._width * 8, sprite._height + 1, Graphics::PixelFormat::createFormatCLUT8()); + for (uint16 y = 0; y < sprite._height + 1; y++) { + for (uint16 x = 0; x < sprite._width * 8; x++) *(byte *)sprite._picture.getBasePtr(x, y) = *(byte *)_vm->_graphics->_surface.getBasePtr(sprite._x * 8 + x, sprite._y + y); } } diff --git a/engines/avalanche/graphics.h b/engines/avalanche/graphics.h index 636ae6fdf9..536a2c2f1a 100644 --- a/engines/avalanche/graphics.h +++ b/engines/avalanche/graphics.h @@ -38,6 +38,7 @@ namespace Avalanche { class AvalancheEngine; class AnimationType; struct SpriteType; +struct ChunkBlock; typedef byte FontType[256][16]; typedef byte ManiType[2049]; @@ -58,11 +59,15 @@ public: void loadDigits(); void loadMouse(byte which); + void drawDot(int x, int y, Color color); void drawLine(int x1, int y1, int x2, int y2, int penX, int penY, Color color); Common::Point drawScreenArc(int16 x, int16 y, int16 stAngle, int16 endAngle, uint16 radius, Color color); void drawPieSlice(int16 x, int16 y, int16 stAngle, int16 endAngle, uint16 radius, Color color); void drawTriangle(Common::Point *p, Color color); + void drawFilledRectangle(Common::Rect rect, Color color); + void drawRectangle(Common::Rect rect, Color color); void drawNormalText(const Common::String text, FontType font, byte fontHeight, int16 x, int16 y, Color color); + void drawBigText(const Common::String text, FontType font, byte fontHeight, int16 x, int16 y, Color color); // Very similar to drawText. TODO: Try to unify the two. void drawScrollText(const Common::String text, FontType font, byte fontHeight, int16 x, int16 y, Color color); void drawDigit(int index, int x, int y); void drawDirection(int index, int x, int y); @@ -79,8 +84,6 @@ public: void drawDebugLines(); // For the mini-game "Nim". - void drawFilledRectangle(Common::Rect rect, Color color); - void drawRectangle(Common::Rect rect, Color color); void nimLoad(); void nimDrawStone(int x, int y); void nimDrawInitials(); @@ -90,6 +93,23 @@ public: // Used in wobble() void shiftScreen(); + // Used in winning() + void drawWinningPic(); + + // Ghostroom's functions: + void ghostDrawGhost(byte ghostArr[2][66][26], uint16 destX, int16 destY); // Very similar to loadPictureSign(). TODO: Unify the two later if possible. + void ghostDrawGlerk(byte glerkArr[4][35][9], uint16 destX, uint16 destY); // Very similar to ghostDrawGhost(), but not enough to unify the two. + Graphics::Surface ghostLoadPicture(Common::File &file, Common::Point &coord); + void ghostDrawPicture(const Graphics::Surface &picture, uint16 destX, uint16 destY); + void ghostDrawBackgroundItems(Common::File &file); + + // Help's function: + void helpDrawButton(int y, byte which); + void helpDrawHighlight(byte which, Color color); + + // Shoot em' up's functions: + void seuDrawTitle(); + void clearAlso(); void clearTextBar(); void setAlsoLine(int x1, int y1, int x2, int y2, Color color); diff --git a/engines/avalanche/help.cpp b/engines/avalanche/help.cpp new file mode 100644 index 0000000000..0d4eff9c23 --- /dev/null +++ b/engines/avalanche/help.cpp @@ -0,0 +1,268 @@ +/* ScummVM - Graphic Adventure Engine +* +* ScummVM is the legal property of its developers, whose names +* are too numerous to list here. Please refer to the COPYRIGHT +* file distributed with this source distribution. +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. + +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. + +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +* +*/ + +/* +* This code is based on the original source code of Lord Avalot d'Argent version 1.3. +* Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman. +*/ + +/* Original name: HELPER The help system unit. */ + +#include "avalanche/avalanche.h" +#include "avalanche/help.h" + +#include "common/scummsys.h" + +namespace Avalanche { + +Help::Help(AvalancheEngine *vm) { + _vm = vm; + + for (int i = 0; i < 10; i++) { + _buttons[i]._trigger = Common::KEYCODE_INVALID; + _buttons[i]._whither = 0; + } + _highlightWas = 0; + _buttonNum = 0; + _holdLeft = false; +} + +/** + * Loads and draws the chosen page of the help. + * @remarks Originally called 'getme' + */ +void Help::switchPage(byte which) { + // Help icons are 80x20. + + _highlightWas = 177; // Forget where the highlight was. + + Common::File file; + + if (!file.open("help.avd")) + error("AVALANCHE: Help: File not found: help.avd"); + + file.seek(which * 2); + uint16 offset = file.readUint16LE(); + file.seek(offset); + + Common::String title = getLine(file); + + _vm->_graphics->drawFilledRectangle(Common::Rect(0, 0, 640, 200), kColorBlue); + _vm->_graphics->drawFilledRectangle(Common::Rect(8, 40, 450, 200), kColorWhite); + + byte index = file.readByte(); + _vm->_graphics->helpDrawButton(-177, index); + + // Plot the title: + _vm->_graphics->drawNormalText(title, _vm->_font, 8, 629 - 8 * title.size(), 26, kColorBlack); + _vm->_graphics->drawNormalText(title, _vm->_font, 8, 630 - 8 * title.size(), 25, kColorCyan); + + _vm->_graphics->drawBigText("help!", _vm->_font, 8, 549, 1, kColorBlack); + _vm->_graphics->drawBigText("help!", _vm->_font, 8, 550, 0, kColorCyan); + + byte y = 0; + do { + Common::String line = getLine(file); + if (!line.empty()) { + if (line.compareTo(Common::String('!')) == 0) // End of the help text is signalled with a '!'. + break; + if (line[0] == '\\') { + line.deleteChar(0); + _vm->_graphics->drawNormalText(line, _vm->_font, 8, 16, 41 + y * 10, kColorRed); + } + else + _vm->_graphics->drawNormalText(line, _vm->_font, 8, 16, 41 + y * 10, kColorBlack); + } + y++; + } while (true); + + // We are now at the end of the text. Next we must read the icons: + y = 0; + _buttonNum = 0; + while (!file.eos()) { + int trigger = file.readByte(); + + if (trigger == 177) + break; + switch (trigger) { + case 254: // Escape + trigger = 27; + break; + case 214: // PageUp + trigger = 280; + break; + case 216: // PageDown + trigger = 281; + break; + default: // A - Z + // The characters are stored in the file in uppercase, but we need the lowercase versions for KeyCode: + trigger = tolower(trigger); + break; + } + + _buttons[y]._trigger = Common::KeyCode(trigger); + index = file.readByte(); + if (_buttons[y]._trigger != Common::KEYCODE_INVALID) + _vm->_graphics->helpDrawButton(13 + (y + 1) * 27, index); + _buttons[y]._whither = file.readByte(); // This is the position to jump to. + + Common::String text = ""; + switch (_buttons[y]._trigger) { + case Common::KEYCODE_ESCAPE: + text = Common::String("Esc"); + break; + case Common::KEYCODE_PAGEUP: + text = Common::String(24); + break; + case Common::KEYCODE_PAGEDOWN: + text = Common::String(25); + break; + default: + text = Common::String(toupper(_buttons[y]._trigger)); + break; + } + + _vm->_graphics->drawBigText(text, _vm->_font, 8, 589 - (text.size() * 8), 18 + (y + 1) * 27, kColorBlack); + _vm->_graphics->drawBigText(text, _vm->_font, 8, 590 - (text.size() * 8), 17 + (y + 1) * 27, kColorCyan); + + y++; + _buttonNum++; + } + + _vm->_graphics->refreshScreen(); + + file.close(); +} + +Common::String Help::getLine(Common::File &file) { + Common::String line; + byte length = file.readByte(); + for (int i = 0; i < length; i++) { + char c = file.readByte(); + line += (c ^ 177); + } + return line; +} + +bool Help::handleMouse(const Common::Event &event) { + Common::Point mousePos; + mousePos.x = event.mouse.x; + mousePos.y = event.mouse.y / 2; + + int index = -1; + + if (event.type == Common::EVENT_LBUTTONUP) { // Clicked *somewhere*... + _holdLeft = false; + + if ((mousePos.x < 470) || (mousePos.x > 550) || (((mousePos.y - 13) % 27) > 20)) + index = -1; + else // Clicked on a button. + index = ((mousePos.y - 13) / 27) - 1; + } else { // LBUTTONDOWN or MOUSEMOVE + int highlightIs = 0; + + if ((mousePos.x > 470) && (mousePos.x <= 550) && (((mousePos.y - 13) % 27) <= 20)) { // No click, so highlight. + highlightIs = (mousePos.y - 13) / 27 - 1; + if ((highlightIs < 0) || (5 < highlightIs)) + highlightIs = 177; // In case of silly values. + } else + highlightIs = 177; + + if (((highlightIs != 177) && (event.type == Common::EVENT_LBUTTONDOWN)) || _holdLeft) { + _holdLeft = true; + highlightIs += 32; + } + + if (_highlightWas != highlightIs) { + _vm->_graphics->helpDrawHighlight(_highlightWas, kColorBlue); + _highlightWas = highlightIs; + if (_buttons[highlightIs & 31]._trigger != Common::KEYCODE_INVALID) { + if (highlightIs > 31) + _vm->_graphics->helpDrawHighlight(highlightIs, kColorLightcyan); + else + _vm->_graphics->helpDrawHighlight(highlightIs, kColorLightblue); + } + } + } + + if ((index >= 0) && (_buttons[index]._trigger != Common::KEYCODE_INVALID)) { + if (_buttons[index]._trigger == Common::KEYCODE_ESCAPE) + return true; + else { + _vm->fadeOut(); + switchPage(_buttons[index]._whither); + _vm->fadeIn(); + return false; + } + } + + return false; +} + +bool Help::handleKeyboard(const Common::Event &event) { + if (event.kbd.keycode == Common::KEYCODE_ESCAPE) + return true; + + for (int i = 0; i < _buttonNum; i++) { + if (_buttons[i]._trigger == event.kbd.keycode) { + _vm->fadeOut(); + switchPage(_buttons[i]._whither); + _vm->fadeIn(); + return false; + } + } + + return false; +} + +/** + * @remarks Originally called 'boot_help' + */ +void Help::run() { + _vm->_graphics->saveScreen(); + _vm->fadeOut(); + switchPage(0); + _vm->fadeIn(); + + _vm->_graphics->loadMouse(kCurHelp); + + // Originally it was the body of 'continue_help': + bool close = false; + while (!_vm->shouldQuit() && !close) { + Common::Event event; + _vm->getEvent(event); + if (event.type == Common::EVENT_KEYDOWN) + close = handleKeyboard(event); + else if ((event.type == Common::EVENT_LBUTTONDOWN) || (event.type == Common::EVENT_LBUTTONUP) || (event.type == Common::EVENT_MOUSEMOVE)) + close = handleMouse(event); + + _vm->_graphics->refreshScreen(); + } + // End of 'continue_help'. + + _vm->fadeOut(); + _vm->_graphics->restoreScreen(); + _vm->_graphics->removeBackup(); + _vm->fadeIn(); +} + +} // End of namespace Avalanche diff --git a/engines/avalanche/help.h b/engines/avalanche/help.h new file mode 100644 index 0000000000..f31a73d189 --- /dev/null +++ b/engines/avalanche/help.h @@ -0,0 +1,65 @@ +/* ScummVM - Graphic Adventure Engine +* +* ScummVM is the legal property of its developers, whose names +* are too numerous to list here. Please refer to the COPYRIGHT +* file distributed with this source distribution. +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. + +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. + +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +* +*/ + +/* +* This code is based on the original source code of Lord Avalot d'Argent version 1.3. +* Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman. +*/ + +/* Original name: HELPER The help system unit. */ + +#ifndef AVALANCHE_HELP_H +#define AVALANCHE_HELP_H + +namespace Avalanche { +class AvalancheEngine; + +class Help { +public: + Help(AvalancheEngine *vm); + + void run(); + +private: + struct Button { + Common::KeyCode _trigger; + byte _whither; + }; + + AvalancheEngine *_vm; + + Button _buttons[10]; + byte _highlightWas; + byte _buttonNum; // How many buttons do we have on the screen at the moment? + bool _holdLeft; // Is the left mouse button is still being held? + + void switchPage(byte which); + Common::String getLine(Common::File &file); // It was a nested function in getMe(). + + // These two return true if we have to leave the Help: + bool handleMouse(const Common::Event &event); + bool handleKeyboard(const Common::Event &event); +}; + +} // End of namespace Avalanche + +#endif // AVALANCHE_HELP_H diff --git a/engines/avalanche/module.mk b/engines/avalanche/module.mk index 39ca94e3f8..eb95e32585 100644 --- a/engines/avalanche/module.mk +++ b/engines/avalanche/module.mk @@ -11,13 +11,15 @@ MODULE_OBJS = \ graphics.o \ menu.o \ parser.o \ - pingo.o \ dialogs.o \ sequence.o \ sound.o \ timer.o \ nim.o \ - clock.o + clock.o \ + ghostroom.o \ + help.o \ + shootemup.o # This module can be built as a plugin ifeq ($(ENABLE_AVALANCHE), DYNAMIC_PLUGIN) diff --git a/engines/avalanche/parser.cpp b/engines/avalanche/parser.cpp index b0524a0d7e..1a9585e2a3 100644 --- a/engines/avalanche/parser.cpp +++ b/engines/avalanche/parser.cpp @@ -2043,8 +2043,7 @@ void Parser::doThat() { } break; case kVerbCodeHelp: - // boot_help(); - warning("STUB: Parser::doThat() - case kVerbCodehelp"); + _vm->_help->run(); break; case kVerbCodeLarrypass: _vm->_dialogs->displayText("Wrong game!"); diff --git a/engines/avalanche/pingo.cpp b/engines/avalanche/pingo.cpp deleted file mode 100644 index 40467ab839..0000000000 --- a/engines/avalanche/pingo.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This code is based on the original source code of Lord Avalot d'Argent version 1.3. - * Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman. - */ - -/* PINGO Full-screen sub-parts of the game. */ - -#include "avalanche/avalanche.h" -#include "avalanche/pingo.h" - -namespace Avalanche { - -Pingo::Pingo(AvalancheEngine *vm) { - _vm = vm; -} - -void Pingo::dPlot(int16 x, int16 y, Common::String z) { - warning("STUB: Pingo::dPlot()"); -} - -void Pingo::bossKey() { - warning("STUB: Pingo::bossKey()"); -} - -void Pingo::copy02() { // taken from Wobble (below) - warning("STUB: Pingo::copy02()"); -} - -void Pingo::copy03() { // taken from Wobble (below) - warning("STUB: Pingo::copy03()"); -} - -void Pingo::copyPage(byte frp, byte top) { // taken from Copy02 (above) - warning("STUB: Pingo::copyPage()"); -} - -void Pingo::winningPic() { - Common::File f; - _vm->fadeOut(); - - if (!f.open("finale.avd")) - error("AVALANCHE: File not found: finale.avd"); - -#if 0 - for (int bit = 0; bit <= 3; bit++) { - port[0x3c4] = 2; - port[0x3ce] = 4; - port[0x3c5] = 1 << bit; - port[0x3cf] = bit; - blockread(f, mem[0xa000 * 0], 16000); - } -#endif - - f.close(); - - warning("STUB: Pingo::winningPic()"); - - _vm->fadeIn(); - -#if 0 - do { - _vm->check(); - } while (!(keypressed() || (mrelease > 0))); - while (keypressed()) - char r = readkey(); - major_redraw(); -#endif - - warning("STUB: Pingo::winningPic()"); -} - -} // End of namespace Avalanche. diff --git a/engines/avalanche/shootemup.cpp b/engines/avalanche/shootemup.cpp new file mode 100644 index 0000000000..c9d089c23b --- /dev/null +++ b/engines/avalanche/shootemup.cpp @@ -0,0 +1,175 @@ +/* ScummVM - Graphic Adventure Engine +* +* ScummVM is the legal property of its developers, whose names +* are too numerous to list here. Please refer to the COPYRIGHT +* file distributed with this source distribution. +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. + +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. + +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +* +*/ + +/* +* This code is based on the original source code of Lord Avalot d'Argent version 1.3. +* Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman. +*/ + +#include "avalanche/avalanche.h" +#include "avalanche/shootemup.h" + +#include "common/random.h" + +namespace Avalanche { + +ShootEmUp::ShootEmUp(AvalancheEngine *vm) { + _vm = vm; + + _time = 0; +} + +void ShootEmUp::run() { + _vm->_graphics->seuDrawTitle(); + setup(); + initRunner(20, 70, 48, 54, _vm->_rnd->getRandomNumber(4) + 1, _vm->_rnd->getRandomNumber(3) - 2); + initRunner(600, 70, 48, 54, _vm->_rnd->getRandomNumber(4) + 1, _vm->_rnd->getRandomNumber(3) - 2); + initRunner(600, 100, 61, 67, -(_vm->_rnd->getRandomNumber(4)) + 1, _vm->_rnd->getRandomNumber(3) - 2); + initRunner(20, 100, 61, 67, -(_vm->_rnd->getRandomNumber(4)) + 1, _vm->_rnd->getRandomNumber(3) - 2); + do { + blankIt(); + hitPeople(); + plotThem(); + moveThem(); + moveAvvy(); + bumpFolk(); + peopleRunning(); + animate(); + escapeCheck(); + collisionCheck(); + updateTime(); + check321(); + readKbd(); + } while (_time != 0); +} + +bool ShootEmUp::overlap(uint16 a1x, uint16 a1y, uint16 a2x, uint16 a2y, uint16 b1x, uint16 b1y, uint16 b2x, uint16 b2y) { + warning("STUB: ShootEmUp::overlap()"); + return false; +} + +byte ShootEmUp::getStockNumber(byte x) { + warning("STUB: ShootEmUp::getStockNumber()"); + return 0; +} + +void ShootEmUp::blankIt() { + warning("STUB: ShootEmUp::blankIt()"); +} + +void ShootEmUp::moveThem() { + warning("STUB: ShootEmUp::moveThem()"); +} + +void ShootEmUp::plotThem() { + warning("STUB: ShootEmUp::plotThem()"); +} + +void ShootEmUp::define(int16 xx, int16 yy, byte pp, int8 ixx, int8 iyy, int16 time, bool isAMissile, bool doWeWipe) { + warning("STUB: ShootEmUp::define()"); +} + +void ShootEmUp::defineCameo(int16 xx, int16 yy, byte pp, int16 time) { + warning("STUB: ShootEmUp::defineCameo()"); +} + +void ShootEmUp::showStock(byte x) { + warning("STUB: ShootEmUp::showStock()"); +} + +void ShootEmUp::showScore() { + warning("STUB: ShootEmUp::showScore()"); +} + +void ShootEmUp::showTime() { + warning("STUB: ShootEmUp::showTime()"); +} + +void ShootEmUp::gain(int8 howMuch) { + warning("STUB: ShootEmUp::gain()"); +} + +void ShootEmUp::newEscape() { + warning("STUB: ShootEmUp::newEscape()"); +} + +void ShootEmUp::nextPage() { + warning("STUB: ShootEmUp::nextPage()"); +} + +void ShootEmUp::instructions() { + warning("STUB: ShootEmUp::instructions()"); +} + +void ShootEmUp::setup() { + warning("STUB: ShootEmUp::setup()"); +} + +void ShootEmUp::initRunner(int16 xx, int16 yy, byte f1, byte f2, int8 ixx, int8 iyy) { + warning("STUB: ShootEmUp::initRunner()"); +} + +void ShootEmUp::moveAvvy() { + warning("STUB: ShootEmUp::moveAvvy()"); +} + +void ShootEmUp::readKbd() { + warning("STUB: ShootEmUp::readKbd()"); +} + +void ShootEmUp::animate() { + warning("STUB: ShootEmUp::animate()"); +} + +void ShootEmUp::collisionCheck() { + warning("STUB: ShootEmUp::collisionCheck()"); +} + +void ShootEmUp::turnAround(byte who, bool randomX) { + warning("STUB: ShootEmUp::turnAround()"); +} + +void ShootEmUp::bumpFolk() { + warning("STUB: ShootEmUp::bumpFolk()"); +} + +void ShootEmUp::peopleRunning() { + warning("STUB: ShootEmUp::peopleRunning()"); +} + +void ShootEmUp::updateTime() { + warning("STUB: ShootEmUp::updateTime()"); +} + +void ShootEmUp::hitPeople() { + warning("STUB: ShootEmUp::hitPeople()"); +} + +void ShootEmUp::escapeCheck() { + warning("STUB: ShootEmUp::escapeCheck()"); +} + +void ShootEmUp::check321() { + warning("STUB: ShootEmUp::check321()"); +} + +} // End of namespace Avalanche diff --git a/engines/avalanche/shootemup.h b/engines/avalanche/shootemup.h new file mode 100644 index 0000000000..db1f113817 --- /dev/null +++ b/engines/avalanche/shootemup.h @@ -0,0 +1,76 @@ +/* ScummVM - Graphic Adventure Engine +* +* ScummVM is the legal property of its developers, whose names +* are too numerous to list here. Please refer to the COPYRIGHT +* file distributed with this source distribution. +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. + +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. + +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +* +*/ + +/* +* This code is based on the original source code of Lord Avalot d'Argent version 1.3. +* Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman. +*/ + +#ifndef AVALANCHE_SHOOTEMUP_H +#define AVALANCHE_SHOOTEMUP_H + +namespace Avalanche { +class AvalancheEngine; + +class ShootEmUp { +public: + ShootEmUp(AvalancheEngine *vm); + + void run(); + +private: + AvalancheEngine *_vm; + + byte _time; + + bool overlap(uint16 a1x, uint16 a1y, uint16 a2x, uint16 a2y, uint16 b1x, uint16 b1y, uint16 b2x, uint16 b2y); + byte getStockNumber(byte x); + void blankIt(); + void moveThem(); + void plotThem(); + void define(int16 xx, int16 yy, byte pp, int8 ixx, int8 iyy, int16 time, bool isAMissile, bool doWeWipe); + void defineCameo(int16 xx, int16 yy, byte pp, int16 time); + void showStock(byte x); + void showScore(); + void showTime(); + void gain(int8 howMuch); + void newEscape(); + void nextPage(); // Internal function of 'instructions' in the original. + void instructions(); + void setup(); + void initRunner(int16 xx, int16 yy, byte f1, byte f2, int8 ixx, int8 iyy); + void moveAvvy(); + void readKbd(); + void animate(); + void collisionCheck(); + void turnAround(byte who, bool randomX); + void bumpFolk(); + void peopleRunning(); + void updateTime(); + void hitPeople(); + void escapeCheck(); + void check321(); +}; + +} // End of namespace Avalanche + +#endif // AVALANCHE_SHOOTEMUP_H diff --git a/engines/avalanche/timer.cpp b/engines/avalanche/timer.cpp index c8ea820c0e..b7a8433e71 100644 --- a/engines/avalanche/timer.cpp +++ b/engines/avalanche/timer.cpp @@ -327,12 +327,11 @@ void Timer::hangAround2() { _vm->_animation->_sprites[0]->remove(); spr->remove(); // Get rid of Robin Hood and Friar Tuck. - addTimer(1, kProcAfterTheShootemup, kReasonHangingAround); - // Immediately call the following proc (when you have a chance). + addTimer(1, kProcAfterTheShootemup, kReasonHangingAround); // Immediately call the following proc (when you have a chance). _vm->_tiedUp = false; - // _vm->_enid->backToBootstrap(1); Call the shoot-'em-up. TODO: Replace it with proper ScummVM-friendly function(s)! Do not remove until then! + _vm->_shootemup->run(); } void Timer::afterTheShootemup() { @@ -632,17 +631,39 @@ void Timer::arkataShouts() { addTimer(160, kProcArkataShouts, kReasonArkataShouts); } +/** + * @remarks Contains the content of the function 'winning_pic', originally located in PINGO. + */ void Timer::winning() { _vm->_dialogs->displayScrollChain('Q', 79); - _vm->_pingo->winningPic(); - warning("STUB: Timer::winning()"); -#if 0 - do { - _vm->checkclick(); - } while (!(_vm->mrelease == 0)); -#endif - // TODO: To be implemented with Pingo::winningPic(). + // This was originally located in winning_pic: + CursorMan.showMouse(false); + _vm->_graphics->saveScreen(); + _vm->fadeOut(); + _vm->_graphics->drawWinningPic(); + _vm->_graphics->refreshScreen(); + _vm->fadeIn(); + + // Waiting for a keypress or a left mouseclick: + Common::Event event; + bool escape = false; + while (!_vm->shouldQuit() && !escape) { + _vm->_graphics->refreshScreen(); + while (_vm->getEvent(event)) { + if ((event.type == Common::EVENT_LBUTTONUP) || (event.type == Common::EVENT_KEYDOWN)) { + escape = true; + break; + } + } + } + + _vm->fadeOut(); + _vm->_graphics->restoreScreen(); + _vm->_graphics->removeBackup(); + _vm->fadeIn(); + CursorMan.showMouse(true); + // winning_pic's end. _vm->callVerb(kVerbCodeScore); _vm->_dialogs->displayText(" T H E E N D "); diff --git a/engines/cge/cge_main.cpp b/engines/cge/cge_main.cpp index 602b36d6ef..b4015334c8 100644 --- a/engines/cge/cge_main.cpp +++ b/engines/cge/cge_main.cpp @@ -125,9 +125,8 @@ char *CGEEngine::mergeExt(char *buf, const char *name, const char *ext) { } int CGEEngine::takeEnum(const char **tab, const char *text) { - const char **e; if (text) { - for (e = tab; *e; e++) { + for (const char **e = tab; *e; e++) { if (scumm_stricmp(text, *e) == 0) { return e - tab; } @@ -1029,7 +1028,6 @@ void CGEEngine::loadSprite(const char *fname, int ref, int scene, int col = 0, i bool east = false; bool port = false; bool tran = false; - int i, lcnt = 0; char tmpStr[kLineMax + 1]; Common::String line; @@ -1041,6 +1039,7 @@ void CGEEngine::loadSprite(const char *fname, int ref, int scene, int col = 0, i error("Bad SPR [%s]", tmpStr); uint16 len; + int i, lcnt = 0; for (line = sprf.readLine(); !sprf.eos(); line = sprf.readLine()) { len = line.size(); lcnt++; diff --git a/engines/cge/detection.cpp b/engines/cge/detection.cpp index c377970c51..11f2a43854 100644 --- a/engines/cge/detection.cpp +++ b/engines/cge/detection.cpp @@ -24,10 +24,22 @@ #include "engines/advancedDetector.h" #include "common/savefile.h" #include "common/system.h" +#include "common/translation.h" #include "base/plugins.h" #include "graphics/thumbnail.h" #include "cge/cge.h" +namespace CGE { + +struct CgeGameDescription { + ADGameDescription desc; + GameType gameType; +}; + +#define GAMEOPTION_COLOR_BLIND_DEFAULT_OFF GUIO_GAMEOPTIONS1 + +} // End of namespace CGE + static const PlainGameDescriptor CGEGames[] = { { "soltys", "Soltys" }, { "sfinx", "Sfinx" }, @@ -36,11 +48,6 @@ static const PlainGameDescriptor CGEGames[] = { namespace CGE { -struct CgeGameDescription { - ADGameDescription desc; - GameType gameType; -}; - static const CgeGameDescription gameDescriptions[] = { { @@ -63,7 +70,7 @@ static const CgeGameDescription gameDescriptions[] = { {"vol.dat", 0, "f9ae2e7f8f7cac91378cdafca43faf1e", 8437676}, AD_LISTEND }, - Common::PL_POL, Common::kPlatformDOS, ADGF_NO_FLAGS, GUIO0() + Common::PL_POL, Common::kPlatformDOS, ADGF_NO_FLAGS, GUIO1(GAMEOPTION_COLOR_BLIND_DEFAULT_OFF) }, kGameTypeSoltys }, @@ -75,7 +82,7 @@ static const CgeGameDescription gameDescriptions[] = { {"vol.dat", 0, "75d385a6074c58b69f7730481f256051", 1796710}, AD_LISTEND }, - Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO , GUIO0() + Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO , GUIO1(GAMEOPTION_COLOR_BLIND_DEFAULT_OFF) }, kGameTypeSoltys }, @@ -87,7 +94,7 @@ static const CgeGameDescription gameDescriptions[] = { {"vol.dat", 0, "c5d9b15863cab61dc125551576dece04", 1075272}, AD_LISTEND }, - Common::PL_POL, Common::kPlatformDOS, ADGF_DEMO , GUIO0() + Common::PL_POL, Common::kPlatformDOS, ADGF_DEMO , GUIO1(GAMEOPTION_COLOR_BLIND_DEFAULT_OFF) }, kGameTypeSoltys }, @@ -99,7 +106,7 @@ static const CgeGameDescription gameDescriptions[] = { {"vol.dat", 0, "4ffeff4abc99ac5999b55ccfc56ab1df", 8430868}, AD_LISTEND }, - Common::EN_ANY, Common::kPlatformDOS, ADGF_NO_FLAGS , GUIO0() + Common::EN_ANY, Common::kPlatformDOS, ADGF_NO_FLAGS , GUIO1(GAMEOPTION_COLOR_BLIND_DEFAULT_OFF) }, kGameTypeSoltys }, @@ -111,7 +118,7 @@ static const CgeGameDescription gameDescriptions[] = { {"vol.dat", 0, "0e43331c846094d77f5dd201827e0a3b", 8439339}, AD_LISTEND }, - Common::PL_POL, Common::kPlatformDOS, ADGF_NO_FLAGS, GUIO0() + Common::PL_POL, Common::kPlatformDOS, ADGF_NO_FLAGS, GUIO1(GAMEOPTION_COLOR_BLIND_DEFAULT_OFF) }, kGameTypeSoltys }, @@ -123,7 +130,7 @@ static const CgeGameDescription gameDescriptions[] = { {"vol.dat", 0, "ff10d54acc2c95696c57e05819b6906f", 8450151}, AD_LISTEND }, - Common::ES_ESP, Common::kPlatformDOS, ADGF_NO_FLAGS , GUIO0() + Common::ES_ESP, Common::kPlatformDOS, ADGF_NO_FLAGS , GUIO1(GAMEOPTION_COLOR_BLIND_DEFAULT_OFF) }, kGameTypeSoltys }, @@ -136,7 +143,7 @@ static const CgeGameDescription gameDescriptions[] = { {"vol.dat", 0, "de14291869a8eb7c2732ab783c7542ef", 34180844}, AD_LISTEND }, - Common::PL_POL, Common::kPlatformDOS, ADGF_NO_FLAGS, GUIO0() + Common::PL_POL, Common::kPlatformDOS, ADGF_NO_FLAGS, GUIO1(GAMEOPTION_COLOR_BLIND_DEFAULT_OFF) }, kGameTypeSfinx }, @@ -148,12 +155,25 @@ static const ADFileBasedFallback fileBasedFallback[] = { { &gameDescriptions[0].desc, { "vol.cat", "vol.dat", 0 } }, { 0, { 0 } } }; - } // End of namespace CGE +static const ADExtraGuiOptionsMap optionsList[] = { + { + GAMEOPTION_COLOR_BLIND_DEFAULT_OFF, + { + _s("Color Blind Mode"), + _s("Enable Color Blind Mode by default"), + "enable_color_blind", + false + } + }, + + AD_EXTRA_GUI_OPTIONS_TERMINATOR +}; + class CGEMetaEngine : public AdvancedMetaEngine { public: - CGEMetaEngine() : AdvancedMetaEngine(CGE::gameDescriptions, sizeof(CGE::CgeGameDescription), CGEGames) { + CGEMetaEngine() : AdvancedMetaEngine(CGE::gameDescriptions, sizeof(CGE::CgeGameDescription), CGEGames, optionsList) { _singleid = "soltys"; } @@ -169,8 +189,6 @@ public: return "Soltys (c) 1994-1996 L.K. Avalon"; } - - virtual bool hasFeature(MetaEngineFeature f) const; virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const; virtual int getMaximumSaveSlot() const; @@ -208,10 +226,9 @@ SaveStateList CGEMetaEngine::listSaves(const char *target) const { sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..) SaveStateList saveList; - int slotNum = 0; for (Common::StringArray::const_iterator filename = filenames.begin(); filename != filenames.end(); ++filename) { // Obtain the last 3 digits of the filename, since they correspond to the save slot - slotNum = atoi(filename->c_str() + filename->size() - 3); + int slotNum = atoi(filename->c_str() + filename->size() - 3); if (slotNum >= 0 && slotNum <= 99) { diff --git a/engines/cge/vga13h.cpp b/engines/cge/vga13h.cpp index 4954e638ab..b469c7197d 100644 --- a/engines/cge/vga13h.cpp +++ b/engines/cge/vga13h.cpp @@ -26,6 +26,7 @@ */ #include "common/array.h" +#include "common/config-manager.h" #include "common/rect.h" #include "graphics/palette.h" #include "cge/general.h" @@ -210,10 +211,10 @@ Sprite *Sprite::expand() { error("Bad SPR [%s]", fname); Common::String line; char tmpStr[kLineMax + 1]; - int len = 0, lcnt = 0; + int lcnt = 0; for (line = sprf.readLine(); !sprf.eos(); line = sprf.readLine()) { - len = line.size(); + int len = line.size(); Common::strlcpy(tmpStr, line.c_str(), sizeof(tmpStr)); lcnt++; if (len == 0 || *tmpStr == '.') @@ -637,6 +638,10 @@ Vga::Vga(CGEEngine *vm) : _frmCnt(0), _msg(NULL), _name(NULL), _setPal(false), _ _page[idx]->create(320, 200, Graphics::PixelFormat::createFormatCLUT8()); } + if (ConfMan.getBool("enable_color_blind")) + _mono = 1; + + _oldColors = (Dac *)malloc(sizeof(Dac) * kPalCount); _newColors = (Dac *)malloc(sizeof(Dac) * kPalCount); getColors(_oldColors); diff --git a/engines/cine/gfx.cpp b/engines/cine/gfx.cpp index 636c0cf8d9..18a569b9c4 100644 --- a/engines/cine/gfx.cpp +++ b/engines/cine/gfx.cpp @@ -246,17 +246,16 @@ void FWRenderer::incrustSprite(const BGIncrust &incrust) { * Draw command box on screen */ void FWRenderer::drawCommand() { - unsigned int i; - int x = 10, y = _cmdY; - if (disableSystemMenu == 0) { + int x = 10, y = _cmdY; + drawPlainBox(x, y, 301, 11, 0); drawBorder(x - 1, y - 1, 302, 12, 2); x += 2; y += 2; - for (i = 0; i < _cmd.size(); i++) { + for (unsigned int i = 0; i < _cmd.size(); i++) { x = drawChar(_cmd[i], x, y); } } @@ -458,12 +457,12 @@ void FWRenderer::drawDoubleBorder(int x, int y, int width, int height, byte colo * @param y Character coordinate */ int FWRenderer::drawChar(char character, int x, int y) { - int width, idx; + int width; if (character == ' ') { x += 5; } else if ((width = g_cine->_textHandler.fontParamTable[(unsigned char)character].characterWidth)) { - idx = g_cine->_textHandler.fontParamTable[(unsigned char)character].characterIdx; + int idx = g_cine->_textHandler.fontParamTable[(unsigned char)character].characterIdx; drawSpriteRaw(g_cine->_textHandler.textTable[idx][FONT_DATA], g_cine->_textHandler.textTable[idx][FONT_MASK], FONT_WIDTH, FONT_HEIGHT, _backBuffer, x, y); x += width + 1; } @@ -481,12 +480,12 @@ int FWRenderer::drawChar(char character, int x, int y) { * @param y Character coordinate */ int FWRenderer::undrawChar(char character, int x, int y) { - int width, idx; + int width; if (character == ' ') { x += 5; } else if ((width = g_cine->_textHandler.fontParamTable[(unsigned char)character].characterWidth)) { - idx = g_cine->_textHandler.fontParamTable[(unsigned char)character].characterIdx; + int idx = g_cine->_textHandler.fontParamTable[(unsigned char)character].characterIdx; const byte *sprite = g_cine->_textHandler.textTable[idx][FONT_DATA]; for (uint i = 0; i < FONT_HEIGHT; ++i) { byte *dst = _backBuffer + (y + i) * 320 + x; @@ -997,11 +996,10 @@ void SelectionMenu::drawMenu(FWRenderer &r, bool top) { } int lineY = y + 4; - int charX; const int elemCount = getElementCount(); for (int i = 0; i < elemCount; ++i, lineY += 9) { - charX = x + 4; + int charX = x + 4; if (i == _selection) { int color; @@ -1228,12 +1226,12 @@ void OSRenderer::incrustSprite(const BGIncrust &incrust) { * @param y Character coordinate */ int OSRenderer::drawChar(char character, int x, int y) { - int width, idx; + int width; if (character == ' ') { x += 5; } else if ((width = g_cine->_textHandler.fontParamTable[(unsigned char)character].characterWidth)) { - idx = g_cine->_textHandler.fontParamTable[(unsigned char)character].characterIdx; + int idx = g_cine->_textHandler.fontParamTable[(unsigned char)character].characterIdx; drawSpriteRaw2(g_cine->_textHandler.textTable[idx][FONT_DATA], 0, FONT_WIDTH, FONT_HEIGHT, _backBuffer, x, y); x += width + 1; } @@ -1834,7 +1832,7 @@ void OSRenderer::drawSprite(overlay *overlayPtr, const byte *spritePtr, int16 wi } } } - it++; + ++it; } // now, draw with the mask we created @@ -1887,7 +1885,6 @@ void maskBgOverlay(const byte *bgPtr, const byte *maskPtr, int16 width, int16 he byte *page, int16 x, int16 y) { int16 i, j, tmpWidth, tmpHeight; Common::List<BGIncrust>::iterator it; - byte *mask; const byte *backup = maskPtr; // background pass @@ -1915,7 +1912,7 @@ void maskBgOverlay(const byte *bgPtr, const byte *maskPtr, int16 width, int16 he for (it = g_cine->_bgIncrustList.begin(); it != g_cine->_bgIncrustList.end(); ++it) { tmpWidth = g_cine->_animDataTable[it->frame]._realWidth; tmpHeight = g_cine->_animDataTable[it->frame]._height; - mask = (byte *)malloc(tmpWidth * tmpHeight); + byte *mask = (byte *)malloc(tmpWidth * tmpHeight); if (it->param == 0) { generateMask(g_cine->_animDataTable[it->frame].data(), mask, tmpWidth * tmpHeight, it->part); diff --git a/engines/cine/main_loop.cpp b/engines/cine/main_loop.cpp index c822f1cabd..789e764df3 100644 --- a/engines/cine/main_loop.cpp +++ b/engines/cine/main_loop.cpp @@ -254,7 +254,7 @@ void purgeSeqList() { it = g_cine->_seqList.erase(it); } else { // Let the element be and jump to the next element - it++; + ++it; } } } diff --git a/engines/fullpipe/constants.h b/engines/fullpipe/constants.h index 408f765fce..bae0a2d799 100644 --- a/engines/fullpipe/constants.h +++ b/engines/fullpipe/constants.h @@ -39,12 +39,17 @@ namespace Fullpipe { #define MSG_MANSHADOWSOFF 5196 #define MSG_MANSHADOWSON 5197 #define MV_FLY_FLY 4917 +#define MV_LFT_CLOSE 1053 +#define MV_LFT_OPEN 1048 #define MV_MAN_GOLADDER 451 #define MV_MAN_GOLADDER2 2844 +#define MV_MAN_LIFTDOWN 1052 +#define MV_MAN_LIFTUP 1051 #define MV_MAN_LOOKUP 4773 #define rMV_MAN_LOOKUP 4775 #define MV_MAN_TOLADDER 448 #define MV_MAN_TOLADDER2 2841 +#define MV_MAN_STARTD 478 #define MV_MAN_STARTLADDER 452 #define MV_MAN_STARTLADDER2 2842 #define MV_MAN_STOPLADDER 454 @@ -83,6 +88,7 @@ namespace Fullpipe { #define PIC_CSR_ITN_RED 5329 #define PIC_CSR_LIFT 5176 #define PIC_CSR_MAP 5339 +#define PIC_HLP_BGR 3562 #define PIC_IN1_GAMETITLE 5169 #define PIC_IN1_PIPETITLE 5167 #define PIC_INV_MENU 991 @@ -210,9 +216,11 @@ namespace Fullpipe { #define SC_INTRO2 3907 #define SC_INV 858 #define SC_LDR 635 +#define SC_MAINMENU 4620 #define SC_MAP 5222 #define SC_TITLES 5166 #define SND_CMN_031 3516 +#define SND_CMN_032 3517 #define SND_CMN_060 4921 #define SND_CMN_061 4922 #define SND_CMN_070 5199 @@ -249,6 +257,8 @@ namespace Fullpipe { #define ST_LBN_7P 2772 #define ST_LBN_8P 2775 #define ST_LBN_9P 2778 +#define ST_LFT_CLOSED 1049 +#define ST_LFT_OPEN_NEW 1071 #define ST_MAN_EMPTY 476 #define ST_MAN_GOU 459 #define ST_MAN_RIGHT 325 @@ -575,6 +585,33 @@ namespace Fullpipe { #define ST_MAN8_STAND 774 #define ST_VMT_MIN 766 +// Scene 9 +#define ANI_BALL9 933 +#define ANI_GLOTATEL 924 +#define ANI_GRIT_9 2719 +#define ANI_PLEVATEL 919 +#define ANI_VISUNCHIK 904 +#define MSG_SC9_EATBALL 941 +#define MSG_SC9_FLOWN 943 +#define MSG_SC9_FROMLADDER 4207 +#define MSG_SC9_PLVCLICK 965 +#define MSG_SC9_SETSCROLL 964 +#define MSG_SC9_SHOWBALL 936 +#define MSG_SC9_STARTTIOTIA 4942 +#define MSG_SC9_TOLADDER 4206 +#define MV_GLT_FLYAWAY 931 +#define MV_MAN9_SHOOT 922 +#define MV_VSN_CYCLE2 2987 +#define PIC_SC9_LADDER_R 2700 +#define QU_TTA9_GOL 4937 +#define SND_9_006 3650 +#define SND_9_018 4200 +#define ST_GLT_SIT 926 +#define ST_GRT9_GRIT 2722 +#define ST_GRT9_NORM 2721 +#define ST_PLV_SIT 921 +#define ST_VSN_NORMAL 906 + // Scene 10 #define ANI_GUM 978 #define ANI_NADUVATEL 944 @@ -1073,6 +1110,52 @@ namespace Fullpipe { #define ST_VNT26_RIGHT2 3348 #define ST_VNT26_UP2 1948 +// Scene 27 +#define ANI_BITA 2026 +#define ANI_BITAHANDLER 3349 +#define ANI_MAID 2015 +#define ANI_VODILLA 1994 +#define MSG_SC27_CLICKBET 2048 +#define MSG_SC27_HANDLERTOBACK 3372 +#define MSG_SC27_HANDLERTOFRONT 3371 +#define MSG_SC27_SHOWNEXTBET 3369 +#define MSG_SC27_STARTBET 2047 +#define MSG_SC27_STARTWIPE 2057 +#define MSG_SC27_TAKEVENT 4584 +#define MV_BTA_FALL 2049 +#define MV_BTH_1_0 3366 +#define MV_BTH_2_1 3364 +#define MV_BTH_3_2 3362 +#define MV_BTH_4_3 3360 +#define MV_BTH_5_4 3358 +#define MV_MAN27_FLOW 1990 +#define MV_MAN27_THROWBET 1989 +#define PIC_SC27_HITZONE2 4756 +#define QU_DRV_GIVEVENT 2040 +#define QU_DRV_PUSHBUTTON 2056 +#define QU_DRV_PUSHBUTTON_NOVENT 4578 +#define QU_MID_CLEANVENT 4583 +#define QU_MID_SWITCHBACK 2044 +#define QU_SC27_RESTARTBETS 3370 +#define QU_SC27_SHOWBET 3368 +#define SND_27_026 4127 +#define SND_27_027 4128 +#define SND_27_044 4687 +#define ST_BTA_FALL 2054 +#define ST_BTA_HILITE 2052 +#define ST_BTA_NORM 2028 +#define ST_BTH_1 3365 +#define ST_BTH_2 3363 +#define ST_BTH_3 3361 +#define ST_BTH_4 3359 +#define ST_BTH_5 3357 +#define ST_DRV_SITNOVENT 1999 +#define ST_DRV_VENT 1996 +#define ST_MID_BROOM 2022 +#define ST_MID_SPADE 3489 +#define ST_MID_SWAB 2017 +#define ST_MID_SWAB2 2019 + // Scene 28 #define ANI_LIFT 982 #define ANI_LIFT_28 4238 diff --git a/engines/fullpipe/fullpipe.h b/engines/fullpipe/fullpipe.h index 1e583279f5..3a43f69fb1 100644 --- a/engines/fullpipe/fullpipe.h +++ b/engines/fullpipe/fullpipe.h @@ -288,10 +288,11 @@ public: void lift_clickButton(); void lift_walkAndGo(); void lift_goAnimation(); - void lift_sub1(StaticANIObject *ani); + void lift_animateButton(StaticANIObject *button); void lift_startExitQueue(); - void lift_sub05(ExCommand *ex); + void lift_hoverButton(ExCommand *ex); bool lift_checkButton(const char *varname); + void lift_openLift(); GameVar *_musicGameVar; Audio::SoundHandle _sceneTrackHandle; diff --git a/engines/fullpipe/gfx.cpp b/engines/fullpipe/gfx.cpp index 2d68600dbb..d72419b645 100644 --- a/engines/fullpipe/gfx.cpp +++ b/engines/fullpipe/gfx.cpp @@ -979,6 +979,9 @@ void Bitmap::putDibCB(int32 *palette) { byte *srcPtr = &_pixels[pitch * (endy - _y)]; + if (endy - _y < _height) + srcPtr = &_pixels[pitch * (_height - 1)]; + int starty = _y; if (starty < 0) { starty = 0; @@ -992,7 +995,7 @@ void Bitmap::putDibCB(int32 *palette) { } if (_flags & 0x1000000) { - for (int y = starty; y < endy; srcPtr -= pitch, y++) { + for (int y = starty; y <= endy; srcPtr -= pitch, y++) { curDestPtr = (uint16 *)g_fp->_backgroundSurface.getBasePtr(startx, y); copierKeyColor(curDestPtr, srcPtr, endx - startx + 1, _flags & 0xff, (int32 *)palette, cb05_format); } diff --git a/engines/fullpipe/init.cpp b/engines/fullpipe/init.cpp index 8de37b5c9e..fd90db9e0f 100644 --- a/engines/fullpipe/init.cpp +++ b/engines/fullpipe/init.cpp @@ -96,7 +96,7 @@ void FullpipeEngine::initObjectStates() { setObjectState(sO_Pool, getObjectEnumState(sO_Pool, sO_Overfull)); setObjectState(sO_Board_25, getObjectEnumState(sO_Board_25, sO_NearDudesStairs)); setObjectState(sO_Driver, getObjectEnumState(sO_Driver, sO_WithSteering)); - setObjectState(sO_Janitress, getObjectEnumState(sO_Janitress, sO_WithMop)); + setObjectState(sO_Maid, getObjectEnumState(sO_Maid, sO_WithSwab)); setObjectState(sO_LeftPipe_29, getObjectEnumState(sO_LeftPipe_29, sO_IsClosed)); setObjectState(sO_LeftPipe_30, getObjectEnumState(sO_LeftPipe_30, sO_IsClosed)); setObjectState(sO_Leg, getObjectEnumState(sO_Leg, sO_ShowingHeel)); diff --git a/engines/fullpipe/inventory.cpp b/engines/fullpipe/inventory.cpp index f5af0611cb..cf12a8279c 100644 --- a/engines/fullpipe/inventory.cpp +++ b/engines/fullpipe/inventory.cpp @@ -31,7 +31,7 @@ namespace Fullpipe { Inventory::~Inventory() { - warning("STUB: Inventory::~Inventory()"); + _itemsPool.clear(); } bool Inventory::load(MfcArchive &file) { @@ -90,7 +90,7 @@ Inventory2::Inventory2() { } Inventory2::~Inventory2() { - warning("STUB: Inventory2::~Inventory2()"); + removeMessageHandler(125, -1); } bool Inventory2::loadPartial(MfcArchive &file) { // Inventory2_SerializePartially @@ -123,7 +123,25 @@ void Inventory2::removeItem(int itemId, int count) { } void Inventory2::removeItem2(Scene *sceneObj, int itemId, int x, int y, int priority) { - warning("STUB: void removeItem2(sc, %d, %d, %d, %d)", itemId, x, y, priority); + int idx = getInventoryItemIndexById(itemId); + + if (idx >= 0) { + if (_inventoryItems[idx]->itemId >> 16) { + removeItem(itemId, 1); + + Scene *sc = g_fp->accessScene(_sceneId); + + if (sc) { + StaticANIObject *ani = new StaticANIObject(sc->getStaticANIObject1ById(itemId, -1)); + + sceneObj->addStaticANIObject(ani, 1); + + ani->_statics = (Statics *)ani->_staticsList[0]; + ani->setOXY(x, y); + ani->_priority = priority; + } + } + } } int Inventory2::getCountItemsWithId(int itemId) { diff --git a/engines/fullpipe/lift.cpp b/engines/fullpipe/lift.cpp index aa0c19e475..37c4a300a4 100644 --- a/engines/fullpipe/lift.cpp +++ b/engines/fullpipe/lift.cpp @@ -29,6 +29,8 @@ #include "fullpipe/scene.h" #include "fullpipe/statics.h" #include "fullpipe/messages.h" +#include "fullpipe/gameloader.h" +#include "fullpipe/motion.h" namespace Fullpipe { @@ -217,16 +219,172 @@ void FullpipeEngine::lift_init(Scene *sc, int enterSeq, int exitSeq) { } } -void FullpipeEngine::lift_exitSeq(ExCommand *ex) { - warning("STUB: FullpipeEngine::lift_exitSeq()"); +void FullpipeEngine::lift_exitSeq(ExCommand *cmd) { + if (cmd) { + MessageQueue *mq = _globalMessageQueueList->getMessageQueueById(cmd->_parId); + + if (mq) + mq->activateExCommandsByKind(34); + } + + _lift->changeStatics2(ST_LFT_CLOSED); + + MessageQueue *mq = new MessageQueue(_globalMessageQueueList->compact()); + + ExCommand *ex = new ExCommand(_aniMan->_id, 34, 256, 0, 0, 0, 1, 0, 0, 0); + + ex->_field_14 = 256; + ex->_messageNum = 256; + ex->_excFlags |= 3; + mq->addExCommandToEnd(ex); + + if (!cmd) { + ex = new ExCommand(_aniMan->_id, 2, 40, 0, 0, 0, 1, 0, 0, 0); + ex->_keyCode = _aniMan->_okeyCode; + ex->_excFlags |= 2; + mq->addExCommandToEnd(ex); + } + + ex = new ExCommand(_lift->_id, 1, MV_LFT_OPEN, 0, 0, 0, 1, 0, 0, 0); + ex->_keyCode = _lift->_okeyCode; + ex->_excFlags |= 2; + mq->addExCommandToEnd(ex); + + ex = new ExCommand(_aniMan->_id, 1, MV_MAN_STARTD, 0, 0, 0, 1, 0, 0, 0); + ex->_keyCode = _aniMan->_okeyCode; + ex->_excFlags |= 2; + mq->addExCommandToEnd(ex); + + ex = new ExCommand(_aniMan->_id, 5, -1, 0, 0, 0, 1, 0, 0, 0); + ex->_keyCode = _aniMan->_okeyCode; + ex->_field_14 = 10; + ex->_x = -1; + ex->_y = -1; + ex->_excFlags |= 3; + mq->addExCommandToEnd(ex); + + ex = new ExCommand(_aniMan->_id, 34, 256, 0, 0, 0, 1, 0, 0, 0); + ex->_excFlags |= 3; + ex->_field_14 = 256; + ex->_messageNum = 0; + mq->addExCommandToEnd(ex); + + ex = new ExCommand(0, 17, MSG_LIFT_STARTEXITQUEUE, 0, 0, 0, 1, 0, 0, 0); + ex->_excFlags |= 3; + mq->addExCommandToEnd(ex); + + ex = new ExCommand(_lift->_id, 1, MV_LFT_CLOSE, 0, 0, 0, 1, 0, 0, 0); + ex->_keyCode = _lift->_okeyCode; + ex->_excFlags |= 2; + + mq->addExCommandToEnd(ex); + + mq->chain(0); } void FullpipeEngine::lift_closedoorSeq() { - warning("STUB: FullpipeEngine::lift_closedoorSeq()"); + if (_lift->_movement) { + if (_lift->_movement->_id == MV_LFT_CLOSE) { + _lift->queueMessageQueue(0); + } else if (_lift->_movement->_id == MV_LFT_OPEN) { + int ph = _lift->_movement->_currDynamicPhaseIndex; + + _lift->changeStatics2(ST_LFT_OPEN_NEW); + _lift->startAnim(MV_LFT_CLOSE, 0, -1); + + if (_lift->_movement->_currMovement) + _lift->_movement->setDynamicPhaseIndex(_lift->_movement->_currMovement->_dynamicPhases.size() - ph); + else + _lift->_movement->setDynamicPhaseIndex(_lift->_movement->_dynamicPhases.size() - ph); + } else { + _lift->changeStatics2(ST_LFT_OPEN_NEW); + + _lift->startAnim(MV_LFT_CLOSE, 0, -1); + } + } else { + if (_lift->_statics->_staticsId == ST_LFT_CLOSED ) { + _lift->changeStatics2(ST_LFT_CLOSED); + } else { + _lift->startAnim(MV_LFT_CLOSE, 0, -1); + } + } + + MessageQueue *mq = new MessageQueue(_globalMessageQueueList->compact()); + ExCommand *ex = new ExCommand(0, 17, MSG_LIFT_GO, 0, 0, 0, 1, 0, 0, 0); + + ex->_excFlags |= 3; + mq->addExCommandToEnd(ex); + + if (!mq->chain(_lift)) + delete mq; } void FullpipeEngine::lift_walkAndGo() { - warning("STUB: FullpipeEngine::lift_walkAndGo()"); + MessageQueue *mq; + ExCommand *ex; + + if (abs(_liftX - _aniMan->_ox) > 1 || abs(_liftY - _aniMan->_oy) > 1 || _aniMan->_movement || _aniMan->_statics->_staticsId != ST_MAN_UP) { + mq = getCurrSceneSc2MotionController()->method34(_aniMan, _liftX, _liftY, 1, ST_MAN_UP); + + if (mq) { + ex = new ExCommand(0, 17, MSG_LIFT_CLICKBUTTON, 0, 0, 0, 1, 0, 0, 0); + ex->_excFlags |= 3; + + mq->addExCommandToEnd(ex); + } + } else { + lift_openLift(); + + mq = new MessageQueue(_liftEnterMQ, 0, 0); + + mq->setFlags(mq->getFlags() | 1); + + ex = new ExCommand(_aniMan->_id, 2, 15, 0, 0, 0, 1, 0, 0, 0); + ex->_keyCode = _aniMan->_okeyCode; + ex->_excFlags |= 2; + mq->addExCommand(ex); + + ex = new ExCommand(_aniMan->_id, 5, -1, 0, 0, 0, 1, 0, 0, 0); + ex->_keyCode = _aniMan->_okeyCode; + ex->_field_14 = _lift->_priority + 1; + ex->_x = -1; + ex->_y = -1; + ex->_excFlags |= 3; + mq->addExCommandToEnd(ex); + + ex = new ExCommand(0, 17, MSG_LIFT_CLOSEDOOR, 0, 0, 0, 1, 0, 0, 0); + ex->_excFlags |= 3; + mq->addExCommandToEnd(ex); + + mq->chain(0); + + _aniMan->_flags |= 1; + } +} + +void FullpipeEngine::lift_openLift() { + if (_lift->_movement) { + if (_lift->_movement->_id == MV_LFT_OPEN) { + _lift->queueMessageQueue(0); + } else if (_lift->_movement->_id == MV_LFT_CLOSE) { + int idx = _lift->_movement->_currDynamicPhaseIndex; + + _lift->changeStatics2(ST_LFT_CLOSED); + _lift->startAnim(MV_LFT_OPEN, 0, -1); + + if (_lift->_movement->_currMovement) + _lift->_movement->setDynamicPhaseIndex(_lift->_movement->_currMovement->_dynamicPhases.size() - idx); + else + _lift->_movement->setDynamicPhaseIndex(_lift->_movement->_dynamicPhases.size() - idx); + } else { + _lift->changeStatics2(ST_LFT_CLOSED); + _lift->startAnim(MV_LFT_OPEN, 0, -1); + } + } else if (_lift->_statics->_staticsId == ST_LFT_OPEN_NEW) { + _lift->changeStatics2(ST_LFT_OPEN_NEW); + } else { + _lift->startAnim(MV_LFT_OPEN, 0, -1); + } } void FullpipeEngine::lift_clickButton() { @@ -234,12 +392,89 @@ void FullpipeEngine::lift_clickButton() { lift_walkAndGo(); } -void FullpipeEngine::lift_goAnimation() { - warning("STUB: FullpipeEngine::lift_goAnimation()"); +void FullpipeEngine::lift_goAnimation() { if (_lastLiftButton) { + int parentId = _currentScene->_sceneId; + int buttonId = lift_getButtonIdN(_lastLiftButton->_statics->_staticsId); + + if (!buttonId) + return; + + int numItems = _gameLoader->_preloadItems.size(); + + for (int i = 0; i < numItems; i++) { + PreloadItem *pre = _gameLoader->_preloadItems[i]; + + if (pre->preloadId2 == buttonId && pre->preloadId1 == _currentScene->_sceneId) { + MessageQueue *mq = new MessageQueue(_globalMessageQueueList->compact()); + + ExCommand *ex = new ExCommand(ANI_MAN, 1, (pre->keyCode != LiftDown ? MV_MAN_LIFTDOWN : MV_MAN_LIFTUP), 0, 0, 0, 1, 0, 0, 0); + + ex->_keyCode = -1; + ex->_field_24 = 1; + ex->_excFlags |= 2; + + mq->addExCommandToEnd(ex); + + ex = new ExCommand(parentId, 17, 61, 0, 0, 0, 1, 0, 0, 0); + + ex->_keyCode = buttonId; + ex->_excFlags |= 3; + + mq->addExCommandToEnd(ex); + + _aniMan->_flags &= 0xFEFF; + + if (!mq->chain(_aniMan)) + delete mq; + + _aniMan->_flags |= 1; + } + } + } + + lift_exitSeq(0); + + if (_lastLiftButton) { + _lastLiftButton->_statics = _lastLiftButton->getStaticsById(lift_getButtonIdN(_lastLiftButton->_statics->_staticsId)); + _lastLiftButton = 0; + } } -void FullpipeEngine::lift_sub1(StaticANIObject *ani) { - warning("STUB: FullpipeEngine::lift_sub1()"); +void FullpipeEngine::lift_animateButton(StaticANIObject *button) { + int butId = lift_getButtonIdP(button->_statics->_staticsId); + + if (butId && butId != button->_statics->_staticsId) { + if (button == _lastLiftButton) { + playSound(SND_CMN_032, 0); + } else { + if (_lastLiftButton) { + int id = lift_getButtonIdN(_lastLiftButton->_statics->_staticsId); + + if (id) + _lastLiftButton->_statics = _lastLiftButton->getStaticsById(id); + + _lastLiftButton = 0; + } + + if (_aniMan->isIdle() && !(_aniMan->_flags & 0x100)) { + _lastLiftButton = button; + button->_statics = button->getStaticsById(butId); + + ExCommand *ex = new ExCommand(0, 35, SND_CMN_032, 0, 0, 0, 1, 0, 0, 0); + ex->_excFlags |= 3; + ex->_field_14 = 1; + ex->postMessage(); + + int id = lift_getButtonIdH(_lastLiftButton->_statics->_staticsId); + + if (id) { + _lastLiftButton->_statics = _lastLiftButton->getStaticsById(id); + + lift_walkAndGo(); + } + } + } + } } void FullpipeEngine::lift_startExitQueue() { @@ -248,12 +483,20 @@ void FullpipeEngine::lift_startExitQueue() { mq->chain(0); } -void FullpipeEngine::lift_sub05(ExCommand *ex) { - warning("STUB: FullpipeEngine::lift_sub05()"); +void FullpipeEngine::lift_hoverButton(ExCommand *cmd) { + if (_lastLiftButton) { + if (!(cmd->_keyCode & 2) || _liftX != cmd->_x || _liftY != cmd->_y) { + _lastLiftButton->_statics = _lastLiftButton->getStaticsById(lift_getButtonIdN(_lastLiftButton->_statics->_staticsId)); + _lastLiftButton = 0; + } + } } -bool FullpipeEngine::lift_checkButton(const char *varname) { - warning("STUB: FullpipeEngine::lift_checkButton(%s)", varname); +bool FullpipeEngine::lift_checkButton(const char *varName) { + GameVar *var = g_fp->getGameLoaderGameVar()->getSubVarByName("OBJSTATES")->getSubVarByName(sO_LiftButtons); + + if (var) + return lift_getButtonIdP(var->getSubVarByName(varName)->_value.intValue) > 0; return false; } diff --git a/engines/fullpipe/messages.cpp b/engines/fullpipe/messages.cpp index 7dfdd06fc8..55b5daaeaa 100644 --- a/engines/fullpipe/messages.cpp +++ b/engines/fullpipe/messages.cpp @@ -610,6 +610,23 @@ void MessageQueue::changeParam28ForObjectId(int objId, int oldParam28, int newPa } } +int MessageQueue::activateExCommandsByKind(int kind) { + int res = 0; + + for (uint i = 0; i < getCount(); i++) { + ExCommand *ex = getExCommandByIndex(i); + + if (ex->_messageKind == kind) { + ex->_messageKind = 0; + ex->_excFlags |= 1; + + res++; + } + } + + return res; +} + MessageQueue *GlobalMessageQueueList::getMessageQueueById(int id) { for (Common::Array<MessageQueue *>::iterator s = begin(); s != end(); ++s) { if ((*s)->_id == id) diff --git a/engines/fullpipe/messages.h b/engines/fullpipe/messages.h index 33bb827888..f8e9d16a73 100644 --- a/engines/fullpipe/messages.h +++ b/engines/fullpipe/messages.h @@ -158,6 +158,8 @@ class MessageQueue : public CObject { int calcDuration(StaticANIObject *obj); void changeParam28ForObjectId(int objId, int oldParam28, int newParam28); + + int activateExCommandsByKind(int kind); }; class GlobalMessageQueueList : public Common::Array<MessageQueue *> { diff --git a/engines/fullpipe/modal.cpp b/engines/fullpipe/modal.cpp index f52dc95a7c..2e7b33b050 100644 --- a/engines/fullpipe/modal.cpp +++ b/engines/fullpipe/modal.cpp @@ -755,8 +755,75 @@ ModalMainMenu::ModalMainMenu() { _field_34 = 0; } +ModalHelp::ModalHelp() { + _mainMenuScene = 0; + _bg = 0; + _isRunning = false; + _rect = g_fp->_sceneRect; + _hx = g_fp->_currentScene->_x; + _hy = g_fp->_currentScene->_y; + + g_fp->_sceneRect.left = 0; + g_fp->_sceneRect.bottom = 600; + g_fp->_sceneRect.top = 0; + g_fp->_sceneRect.right = 800; +} + +ModalHelp::~ModalHelp() { + g_fp->_gameLoader->unloadScene(SC_MAINMENU); + + g_fp->_sceneRect = _rect; + + g_fp->_currentScene->_x = _hx; + g_fp->_currentScene->_y = _hy; +} + +bool ModalHelp::handleMessage(ExCommand *cmd) { + if (cmd->_messageKind == 17) { + int msg = cmd->_messageNum; + + if (msg == 29 || msg == 36 || msg == 107) { + _isRunning = 0; + + return true; + } + } + + return false; +} + +bool ModalHelp::init(int counterdiff) { + g_fp->setCursor(PIC_CSR_DEFAULT); + + return _isRunning; +} + +void ModalHelp::update() { + g_fp->_sceneRect.left = 0; + g_fp->_sceneRect.top = 0; + g_fp->_sceneRect.right = 800; + g_fp->_sceneRect.bottom = 600; + + _bg->draw(0, 0, 0, 0); +} + +void ModalHelp::launch() { + _mainMenuScene = g_fp->accessScene(SC_MAINMENU); + + if (_mainMenuScene) { + _bg = _mainMenuScene->getPictureObjectById(PIC_HLP_BGR, 0)->_picture; + _isRunning = 1; + } +} + void FullpipeEngine::openHelp() { - warning("STUB: FullpipeEngine::openHelp()"); + if (!_modalObject) { + ModalHelp *help = new ModalHelp; + + _modalObject = help; + + help->launch(); + } } void FullpipeEngine::openMainMenu() { diff --git a/engines/fullpipe/modal.h b/engines/fullpipe/modal.h index 438e341c1c..aa9b997cd1 100644 --- a/engines/fullpipe/modal.h +++ b/engines/fullpipe/modal.h @@ -26,6 +26,7 @@ namespace Fullpipe { class PictureObject; +class Picture; class BaseModalObject { public: @@ -161,6 +162,52 @@ public: virtual void saveload() {} }; +class ModalHelp : public BaseModalObject { +public: + Scene *_mainMenuScene; + Picture *_bg; + bool _isRunning; + Common::Rect _rect; + int _hx; + int _hy; + +public: + ModalHelp(); + virtual ~ModalHelp(); + + virtual bool pollEvent() { return true; } + virtual bool handleMessage(ExCommand *message); + virtual bool init(int counterdiff); + virtual void update(); + virtual void saveload() {} + + void launch(); +}; + +class ModalQuery : public BaseModalObject { +public: + ModalQuery(); + virtual ~ModalQuery() {} + + virtual bool pollEvent() { return true; } + virtual bool handleMessage(ExCommand *message) { return false; } + virtual bool init(int counterdiff) { return true; } + virtual void update() {} + virtual void saveload() {} +}; + +class ModalSaveGame : public BaseModalObject { +public: + ModalSaveGame(); + virtual ~ModalSaveGame() {} + + virtual bool pollEvent() { return true; } + virtual bool handleMessage(ExCommand *message) { return false; } + virtual bool init(int counterdiff) { return true; } + virtual void update() {} + virtual void saveload() {} +}; + } // End of namespace Fullpipe diff --git a/engines/fullpipe/module.mk b/engines/fullpipe/module.mk index f6a94de421..db97fa202b 100644 --- a/engines/fullpipe/module.mk +++ b/engines/fullpipe/module.mk @@ -33,6 +33,7 @@ MODULE_OBJS = \ scenes/scene06.o \ scenes/scene07.o \ scenes/scene08.o \ + scenes/scene09.o \ scenes/scene10.o \ scenes/scene11.o \ scenes/scene12.o \ @@ -49,6 +50,7 @@ MODULE_OBJS = \ scenes/scene24.o \ scenes/scene25.o \ scenes/scene26.o \ + scenes/scene27.o \ scenes/scene28.o \ scenes/scene30.o \ scenes/scene31.o \ diff --git a/engines/fullpipe/motion.cpp b/engines/fullpipe/motion.cpp index f0318581f1..61612a2ca4 100644 --- a/engines/fullpipe/motion.cpp +++ b/engines/fullpipe/motion.cpp @@ -1814,6 +1814,204 @@ MessageQueue *MGM::genMovement(MGMInfo *mgminfo) { warning("STUB: MGM::genMovement()"); return 0; + +#if 0 + if (!mgminfo->ani) + return 0; + + mov = mgminfo->ani->_movement; + + if (!mov && !mgminfo->ani->_statics) + return 0; + + if (!(mgminfo->flags & 1)) { + if (mov) + mgminfo->staticsId1 = mov->_staticsObj2->_staticsId; + else + mgminfo->staticsId1 = mgminfo->ani->_statics->_staticsId; + } + + if (!(mgminfo->flags & 0x10) || !(mgminfo->flags & 0x20)) { + int nx = mgminfo->ani->_ox; + int ny = mgminfo->ani->_oy; + + if (mgminfo->ani->_movement) { + mgminfo->ani->calcNextStep(&point2); + nx += point2.x; + ny += point2.y; + } + + if (!(mgminfo->flags & 0x10)) + mgminfo->x2 = nx; + + if (!(mgminfo->flags & 0x20)) + mgminfo->y2 = ny; + } + + mov = mgminfo->ani->getMovementById(mgminfo->movementId); + + if (!mov) + return 0; + + itemIdx = getItemIndexById(mgminfo->ani->_id); + subIdx = getStaticsIndexById(itemIdx, mgminfo->staticsId1); + st2idx = getStaticsIndexById(itemIdx, mov->_staticsObj1->_staticsId); + st1idx = getStaticsIndexById(itemIdx, mov->_staticsObj2->_staticsId); + subOffset = getStaticsIndexById(itemIdx, mgminfo->staticsId2); + + clearMovements2(itemIdx); + recalcOffsets(itemIdx, subIdx, st2idx, 0, 1); + clearMovements2(itemIdx); + recalcOffsets(itemIdx, st1idx, subOffset, 0, 1); + + v71 = (Message *)(28 * itemIdx); + v16 = items[itemIdx].objId; + v17 = *(_DWORD *)(v16 + offsetof(MGMItem, staticsListCount)); + off = *(_DWORD *)(v16 + offsetof(MGMItem, subItems)); + v18 = (MGMSubItem *)(off + 24 * (subIdx + st2idx * v17)); + x1 = (int)&v18->movement->go.CObject.vmt; + v19 = (MGMSubItem *)(off + 24 * (st1idx + subOffset * v17)); + v69 = (LONG)&v19->movement->go.CObject.vmt; + + if (subIdx != st2idx && !x1) + return 0; + + if (st1idx != subOffset && !v69) + return 0; + + int n1x = mgminfo->x1 - mgminfo->x2 - v18->x - v19->x; + int n1y = mgminfo->y1 - mgminfo->y2 - v18->y - v19->y; + + mov->calcSomeXY(&point1, 0); + + int n2x = point1.x; + int n2y = point1.y; + int mult; + + if (mgminfo->flags & 0x40) { + mult = mgminfo->field_10; + len = -1; + n2x *= mult; + n2y *= mult; + } else { + calcLength(&point, mov, n1x, n1y, &mult, &len, 1); + n2x = point.x; + n2y = point.y; + } + + if (!(mgminfo->flags & 2)) { + len = -1; + n2x = mult * point1.x; + n1x = mult * point1.x; + mgminfo->x1 = mgminfo->x2 + mult * point1.x + v18->x + v19->x; + } + + if (!(mgminfo->flags & 4)) { + n2y = mult * point1.y; + n1y = mult * point1.y; + len = -1; + mgminfo->y1 = mgminfo->y2 + mult * point1.y + v18->y + v19->y; + } + + int px = 0; + int py = 0; + + if (x1) { + px = countPhases(itemIdx, subIdx, st2idx, 1); + py = countPhases(itemIdx, subIdx, st2idx, 2); + } + + if (mult > 1) { + px += (mult - 1) * mov->countPhasesWithFlag(-1, 1); + py += (mult - 1) * mov->countPhasesWithFlag(-1, 2); + } + + if (mult > 0) { + px += mov->countPhasesWithFlag(len, 1); + py += mov->countPhasesWithFlag(len, 2); + } + + if (v69) { + px += countPhases(itemIdx, st1idx, subOffset, 1); + py += countPhases(itemIdx, st1idx, subOffset, 2); + } + + int dx1 = n1x - n2x; + int dy1 = n1y - n2y; + + if (px) { + x1 = (int)((double)dx1 / (double)px); + } else { + x1 = 0; + } + + if (py) { + y1 = (int)((double)dy1 / (double)py); + } else { + y1 = 0; + } + + y2.x = dx1 - px * x1; + y2.y = dy1 - py * y1; + + if (n1x - n2x == px * x1) + x2.x = 0; + else + x2.x = (dx1 - px * x1) / abs(dx1 - px * x1); + + if (dy1 == py * y1) + x2.y = 0; + else + x2.y = (dy1 - py * y1) / abs(dy1 - py * y1); + + MessageQueue *mq = new MessageQueue(g_fp->_globalMessageQueueList->compact()); + ExCommand2 *ex2; + + for (v42 = subIdx; v42 != st2idx; v42 = v43->staticsIndex) { + v43 = &(*(MGMSubItem **)((char *)&this->items->subItems + (unsigned int)v71))[v42 + st2idx * *(int *)((char *)&this->items->staticsListCount + (unsigned int)v71)]; + ex2 = buildExCommand2(v43->movement, mgminfo->ani->go._id, x1, y1, &x2, &y2, -1); + ex2->_parId = mq->_id; + ex2->_keyCode = mgminfo->ani->_okeyCode; + + mq->addExCommandToEnd(ex2); + } + + for (i = 0; i < mult; ++i) { + int plen; + + if (i == mult - 1) + plen = len; + else + plen = -1; + + ex2 = buildExCommand2(mov, mgminfo->ani->_id, x1, y1, &x2, &y2, plen); + ex2->_parId = mq->_id; + ex2->_keyCode = mgminfo->ani->_okeyCode; + + mq->addExCommandToEnd(ex2); + } + + for (j = st1idx; j != subOffset; j = v50->staticsIndex) { + v50 = &(*(MGMSubItem **)((char *)&this->items->subItems + (unsigned int)v71))[j + subOffset * *(int *)((char *)&this->items->staticsListCount + (unsigned int)v71)]; + + ex2 = buildExCommand2(v50->movement, mgminfo->ani->_id, x1, y1, &x2, &y2, -1); + ex2->_parId = mq->_id; + ex2->_keyCode = mgminfo->ani->_okeyCode; + + mq->addExCommandToEnd(ex2); + } + + ExCommand *ex = new ExCommand(mgminfo->ani->_id, 5, -1, mgminfo->x1, mgminfo->y1, 0, 1, 0, 0, 0); + + ex->_field_14 = mgminfo->field_1C; + ex->_keyCode = mgminfo->ani->_okeyCode; + ex->_field_24 = 0; + ex->_excFlags |= 3; + + mq->addExCommandToEnd(ex); + + return mq; +#endif } void MGM::updateAnimStatics(StaticANIObject *ani, int staticsId) { @@ -1919,34 +2117,34 @@ int MGM::recalcOffsets(int idx, int st1idx, int st2idx, bool flip, bool flop) { return 0; } -Common::Point *MGM::calcLength(Common::Point *pRes, Movement *mov, int x, int y, int *x1, int *y1, int flag) { +Common::Point *MGM::calcLength(Common::Point *pRes, Movement *mov, int x, int y, int *mult, int *len, int flag) { Common::Point point; mov->calcSomeXY(point, 0); int p1x = point.x; int p1y = point.y; - int newx1 = 0; - int oldy1 = *y1; + int newmult = 0; + int oldlen = *len; if (abs(p1y) > abs(p1x)) { if (mov->calcSomeXY(point, 0)->y) - newx1 = (int)((double)y / point.y); + newmult = (int)((double)y / point.y); } else if (mov->calcSomeXY(point, 0)->x) { - newx1 = (int)((double)x / point.y); + newmult = (int)((double)x / point.y); } - if (newx1 < 0) - newx1 = 0; + if (newmult < 0) + newmult = 0; - *x1 = newx1; + *mult = newmult; int phase = 1; int sz; if (flag) { if (abs(p1y) > abs(p1x)) { - while (abs(p1y * newx1 + mov->calcSomeXY(point, 0)->y) < abs(y)) { + while (abs(p1y * newmult + mov->calcSomeXY(point, 0)->y) < abs(y)) { sz = mov->_currMovement ? mov->_currMovement->_dynamicPhases.size() : mov->_dynamicPhases.size(); if (phase >= sz) { @@ -1958,7 +2156,7 @@ Common::Point *MGM::calcLength(Common::Point *pRes, Movement *mov, int x, int y, phase++; } } else { - while (abs(p1x * newx1 + mov->calcSomeXY(point, 0)->x) < abs(x)) { + while (abs(p1x * newmult + mov->calcSomeXY(point, 0)->x) < abs(x)) { sz = mov->_currMovement ? mov->_currMovement->_dynamicPhases.size() : mov->_dynamicPhases.size(); if (phase >= sz) { @@ -1971,19 +2169,19 @@ Common::Point *MGM::calcLength(Common::Point *pRes, Movement *mov, int x, int y, } } - *y1 = phase - 1; + *len = phase - 1; } else { - *y1 = -1; + *len = -1; } int p2x = 0; int p2y = 0; - if (!oldy1) - oldy1 = -1; + if (!oldlen) + oldlen = -1; - if (oldy1 > 0) { - ++*x1; + if (oldlen > 0) { + ++*mult; mov->calcSomeXY(point, 0); p2x = point.x; @@ -1995,8 +2193,8 @@ Common::Point *MGM::calcLength(Common::Point *pRes, Movement *mov, int x, int y, p2y = p1y; } - pRes->x = p2x + p1x * newx1; - pRes->y = p2y + p1y * newx1; + pRes->x = p2x + p1x * newmult; + pRes->y = p2y + p1y * newmult; return pRes; } diff --git a/engines/fullpipe/motion.h b/engines/fullpipe/motion.h index 6ad46e719a..8ca1cdff57 100644 --- a/engines/fullpipe/motion.h +++ b/engines/fullpipe/motion.h @@ -176,7 +176,7 @@ public: int getStaticsIndex(int idx, Statics *st); void clearMovements2(int idx); int recalcOffsets(int idx, int st1idx, int st2idx, bool flip, bool flop); - Common::Point *calcLength(Common::Point *point, Movement *mov, int x, int y, int *x1, int *y1, int flag); + Common::Point *calcLength(Common::Point *point, Movement *mov, int x, int y, int *mult, int *len, int flag); ExCommand2 *buildExCommand2(Movement *mov, int objId, int x1, int y1, Common::Point *x2, Common::Point *y2, int len); }; diff --git a/engines/fullpipe/objectnames.h b/engines/fullpipe/objectnames.h index eafdb2a8e7..a3718519ca 100644 --- a/engines/fullpipe/objectnames.h +++ b/engines/fullpipe/objectnames.h @@ -192,7 +192,7 @@ namespace Fullpipe { #define sO_WithPlunger "\xd1 \xe2\xe0\xed\xf2\xf3\xe7\xee\xec" // "С вантузом" #define sO_WithJug "\xd1 \xe3\xee\xf0\xf8\xea\xee\xec" // "С горшком" #define sO_WithGum "\xd1 \xe6\xe2\xe0\xf7\xea\xee\xe9" // "С жвачкой" -#define sO_WithShovel "\xd1 \xeb\xee\xef\xe0\xf2\xee\xe9" // "С лопатой" +#define sO_WithSpade "\xd1 \xeb\xee\xef\xe0\xf2\xee\xe9" // "С лопатой" #define sO_WithSmall "\xd1 \xec\xe0\xeb\xfb\xec" // "С малым" #define sO_WithHammer "\xd1 \xec\xee\xeb\xee\xf2\xea\xee\xec" // "С молотком" #define sO_WithCoin "\xd1 \xec\xee\xed\xe5\xf2\xee\xe9" // "С монетой" @@ -208,9 +208,9 @@ namespace Fullpipe { #define sO_IsSitting "\xd1\xe8\xe4\xe8\xf2" // "Сидит" #define sO_IsLaughing "\xd1\xec\xe5\xe5\xf2\xf1\xff" // "Смеется" #define sO_WithAll "\xd1\xee \xe2\xf1\xe5\xec\xe8" // "Со всеми" -#define sO_WithMop "\xd1\xee \xf8\xe2\xe0\xe1\xf0\xee\xe9" // "Со шваброй" +#define sO_WithSwab "\xd1\xee \xf8\xe2\xe0\xe1\xf0\xee\xe9" // "Со шваброй" #define sO_WithHose "\xd1\xee \xf8\xeb\xe0\xed\xe3\xee\xec" // "Со шлангом" -#define sO_WithBrush "\xd1\xee \xf9\xe5\xf2\xea\xee\xe9" // "Со щеткой" +#define sO_WithBroom "\xd1\xee \xf9\xe5\xf2\xea\xee\xe9" // "Со щеткой" #define sO_IsSleeping "\xd1\xef\xe8\xf2" // "Спит" #define sO_OnRight "\xd1\xef\xf0\xe0\xe2\xe0" // "Справа" #define sO_IsStandingInBoots "\xd1\xf2\xee\xe8\xf2 \xe2 \xe1\xee\xf2\xe8\xed\xea\xe0\xf5" // "Стоит в ботинках" @@ -229,7 +229,7 @@ namespace Fullpipe { #define sO_NearPipeWithStool "\xd3 \xf2\xf0\xf3\xe1\xfb \xf1 \xf2\xe0\xe1\xf3\xf0\xe5\xf2\xea\xee\xe9" // "У трубы с табуреткой" #define sO_NearPipe "\xd3 \xf2\xf0\xf3\xe1\xfb" // "У трубы" #define sO_Janitors "\xd3\xe1\xee\xf0\xf9\xe8\xea\xe8" // "Уборщики" -#define sO_Janitress "\xd3\xe1\xee\xf0\xf9\xe8\xf6\xe0" // "Уборщица" +#define sO_Maid "\xd3\xe1\xee\xf0\xf9\xe8\xf6\xe0" // "Уборщица" #define sO_IsGone "\xd3\xe5\xf5\xe0\xeb\xe0" // "Уехала" #define sO_FallenTwice "\xd3\xef\xe0\xeb \xe4\xe2\xe0" // "Упал два" #define sO_FallenOnce "\xd3\xef\xe0\xeb \xf0\xe0\xe7" // "Упал раз" diff --git a/engines/fullpipe/scenes.cpp b/engines/fullpipe/scenes.cpp index 71c8b1efb5..96de1448c4 100644 --- a/engines/fullpipe/scenes.cpp +++ b/engines/fullpipe/scenes.cpp @@ -31,6 +31,7 @@ #include "fullpipe/behavior.h" #include "fullpipe/constants.h" +#include "fullpipe/objectnames.h" #include "fullpipe/scenes.h" #include "fullpipe/interaction.h" @@ -155,6 +156,25 @@ Vars::Vars() { scene08_stairsVisible = true; scene08_manOffsetY = 0; + scene09_flyingBall = 0; + scene09_var05 = 0; + scene09_glotatel = 0; + scene09_spitter = 0; + scene09_grit = 0; + scene09_var02 = 0; + scene09_var08 = 1; + scene09_var09 = 0; + scene09_var10 = -1; + scene09_var11 = -1; + scene09_var12 = -1000; + scene09_numMovingHangers = 0; + scene09_var13 = 0; + scene09_var15 = 0; + scene09_var17 = 0; + scene09_var19 = 0; + scene09_var18.x = 0; + scene09_var18.y = -15; + scene10_gum = 0; scene10_packet = 0; scene10_packet2 = 0; @@ -300,6 +320,22 @@ Vars::Vars() { scene26_sock = 0; scene26_activeVent = 0; + scene27_hitZone = 0; + scene27_driver = 0; + scene27_maid = 0; + scene27_batHandler = 0; + scene27_driverHasVent = true; + scene27_bat = 0; + scene27_dudeIsAiming = false; + scene27_maxPhaseReached = false; + scene27_wipeIsNeeded = false; + scene27_driverPushedButton = false; + scene27_numLostBats = 0; + scene27_knockCount = 0; + scene27_aimStartX = 0; + scene27_aimStartY = 0; + scene27_launchPhase = 0; + scene28_fliesArePresent = true; scene28_beardedDirection = true; scene28_darkeningObject = 0; @@ -618,7 +654,6 @@ bool FullpipeEngine::sceneSwitcher(EntranceInfo *entrance) { _updateCursorCallback = scene08_updateCursor; break; -#if 0 case SC_9: sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_9"); scene->preloadMovements(sceneVar); @@ -629,7 +664,6 @@ bool FullpipeEngine::sceneSwitcher(EntranceInfo *entrance) { insertMessageHandler(sceneHandler09, 2, 2); _updateCursorCallback = scene09_updateCursor; break; -#endif case SC_10: sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_10"); @@ -847,7 +881,6 @@ bool FullpipeEngine::sceneSwitcher(EntranceInfo *entrance) { _updateCursorCallback = scene26_updateCursor; break; -#if 0 case SC_27: sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_27"); scene->preloadMovements(sceneVar); @@ -858,7 +891,6 @@ bool FullpipeEngine::sceneSwitcher(EntranceInfo *entrance) { addMessageHandler(sceneHandler27, 2); _updateCursorCallback = scene27_updateCursor; break; -#endif case SC_28: sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_28"); @@ -1211,7 +1243,7 @@ void FullpipeEngine::updateMap(PreloadItem *pre) { break; case SC_23: - if (getObjectState("Верхний люк_23") == getObjectEnumState("Верхний люк_23", "Открыт")) { + if (getObjectState(sO_UpperHatch_23) == getObjectEnumState(sO_UpperHatch_23, sO_Opened)) { updateMapPiece(PIC_MAP_S23_1, 0); updateMapPiece(PIC_MAP_S23_2, 1); updateMapPiece(PIC_MAP_P07, 1); @@ -1284,7 +1316,7 @@ void FullpipeEngine::updateMap(PreloadItem *pre) { case SC_31: updateMapPiece(PIC_MAP_S31_2, 1); - if (getObjectState("Кактус") == getObjectEnumState("Кактус", "Вырос")) + if (getObjectState(sO_Cactus) == getObjectEnumState(sO_Cactus, sO_HasGrown)) updateMapPiece(PIC_MAP_S31_1, 1); if (pre->keyCode == TrubaRight) @@ -1295,7 +1327,7 @@ void FullpipeEngine::updateMap(PreloadItem *pre) { case SC_32: updateMapPiece(PIC_MAP_S32_2, 1); - if (getObjectState("Кактус") == getObjectEnumState("Кактус", "Вырос")) + if (getObjectState(sO_Cactus) == getObjectEnumState(sO_Cactus, sO_HasGrown)) updateMapPiece(PIC_MAP_S32_1, 1); break; @@ -1356,5 +1388,28 @@ void FullpipeEngine::updateMap(PreloadItem *pre) { } } +void BallChain::init(Ball **ball) { + *ball = pTail; + pTail = (Ball *)ball; + numBalls--; + + if (!numBalls) { + for (Ball *i = pHead; i; i = i->p0 ) + ; + numBalls = 0; + pTail = 0; + field_8 = 0; + pHead = 0; + free(cPlex); + cPlex = 0; + } +} + +Ball *BallChain::sub04(Ball *ballP, Ball *ballN) { + warning("STUB: BallChain::sub04"); + + return pTail; +} + } // End of namespace Fullpipe diff --git a/engines/fullpipe/scenes.h b/engines/fullpipe/scenes.h index 5f77f74706..6b4c7e3632 100644 --- a/engines/fullpipe/scenes.h +++ b/engines/fullpipe/scenes.h @@ -25,7 +25,9 @@ namespace Fullpipe { +struct Bat; struct BehaviorEntryInfo; +struct Hanger; class MGM; class MctlLadder; struct Ring; @@ -69,6 +71,10 @@ void scene08_setupMusic(); int sceneHandler08(ExCommand *cmd); int scene08_updateCursor(); +int scene09_updateCursor(); +void scene09_initScene(Scene *sc); +int sceneHandler09(ExCommand *cmd); + void scene10_initScene(Scene *sc); int sceneHandler10(ExCommand *cmd); int scene10_updateCursor(); @@ -136,8 +142,12 @@ void scene26_setupDrop(Scene *sc); int sceneHandler26(ExCommand *cmd); int scene26_updateCursor(); +void scene27_initScene(Scene *sc); +int sceneHandler27(ExCommand *ex); +int scene27_updateCursor(); + void scene28_initScene(Scene *sc); - int sceneHandler28(ExCommand *ex); +int sceneHandler28(ExCommand *ex); int scene28_updateCursor(); int scene30_updateCursor(); @@ -183,6 +193,30 @@ int sceneHandlerFinal(ExCommand *cmd); void sceneDbgMenu_initScene(Scene *sc); int sceneHandlerDbgMenu(ExCommand *cmd); +struct Ball { + Ball *p0; + Ball *p1; + StaticANIObject *ani; + + Ball() : p0(0), p1(0), ani(0) {} +}; + +struct BallChain { + Ball *pHead; + Ball *field_8; + int numBalls; + Ball *pTail; + byte *cPlex; + int cPlexLen; + + BallChain() : pHead(0), field_8(0), pTail(0), numBalls(0), cPlex(0), cPlexLen(0) {} + ~BallChain() { free(cPlex); } + + void init(Ball **ball); + Ball *sub04(Ball *ballP, Ball *ballN); + void reset() { pHead = 0; pTail = 0; field_8 = 0; numBalls = 0; free(cPlex); cPlex = 0; cPlexLen = 0; } +}; + class Vars { public: Vars(); @@ -314,6 +348,27 @@ public: bool scene08_stairsVisible; int scene08_manOffsetY; + int scene09_var02; + StaticANIObject *scene09_flyingBall; + int scene09_var05; + StaticANIObject *scene09_glotatel; + StaticANIObject *scene09_spitter; + StaticANIObject *scene09_grit; + int scene09_var08; + int scene09_var09; + int scene09_var10; + int scene09_var11; + int scene09_var12; + BallChain scene09_balls; + Common::Array<Hanger *> scene09_hangers; + BallChain scene09_var07; + int scene09_numMovingHangers; + int scene09_var13; + int scene09_var15; + int scene09_var17; + int scene09_var19; + Common::Point scene09_var18; + StaticANIObject *scene10_gum; StaticANIObject *scene10_packet; StaticANIObject *scene10_packet2; @@ -461,6 +516,25 @@ public: StaticANIObject *scene26_sock; StaticANIObject *scene26_activeVent; + PictureObject *scene27_hitZone; + StaticANIObject *scene27_driver; + StaticANIObject *scene27_maid; + StaticANIObject *scene27_batHandler; + bool scene27_driverHasVent; + StaticANIObject *scene27_bat; + bool scene27_dudeIsAiming; + bool scene27_maxPhaseReached; + bool scene27_wipeIsNeeded; + bool scene27_driverPushedButton; + int scene27_numLostBats; + int scene27_knockCount; + int scene27_aimStartX; + int scene27_aimStartY; + int scene27_launchPhase; + BallChain scene27_balls; + Common::Array<Bat *> scene27_bats; + Common::Array<Bat *> scene27_var07; + bool scene28_fliesArePresent; bool scene28_beardedDirection; PictureObject *scene28_darkeningObject; diff --git a/engines/fullpipe/scenes/scene03.cpp b/engines/fullpipe/scenes/scene03.cpp index 9ba84a540a..5d22931fb7 100644 --- a/engines/fullpipe/scenes/scene03.cpp +++ b/engines/fullpipe/scenes/scene03.cpp @@ -239,14 +239,14 @@ int sceneHandler03(ExCommand *ex) { break; case 64: - g_fp->lift_sub05(ex); + g_fp->lift_hoverButton(ex); break; case 29: { StaticANIObject *ani = g_fp->_currentScene->getStaticANIObjectAtPos(ex->_sceneClickX, ex->_sceneClickY); if (ani && ani->_id == ANI_LIFTBUTTON) { - g_fp->lift_sub1(ani); + g_fp->lift_animateButton(ani); ex->_messageKind = 0; return 0; diff --git a/engines/fullpipe/scenes/scene06.cpp b/engines/fullpipe/scenes/scene06.cpp index 7d637d8306..83b98c2722 100644 --- a/engines/fullpipe/scenes/scene06.cpp +++ b/engines/fullpipe/scenes/scene06.cpp @@ -622,7 +622,7 @@ int sceneHandler06(ExCommand *ex) { break; case 64: - g_fp->lift_sub05(ex); + g_fp->lift_hoverButton(ex); break; case MSG_SC6_TAKEBALL: @@ -647,7 +647,7 @@ int sceneHandler06(ExCommand *ex) { if (st) { if (!g_vars->scene06_arcadeEnabled && st->_id == ANI_LIFTBUTTON) { - g_fp->lift_sub1(st); + g_fp->lift_animateButton(st); ex->_messageKind = 0; return 0; } diff --git a/engines/fullpipe/scenes/scene09.cpp b/engines/fullpipe/scenes/scene09.cpp new file mode 100644 index 0000000000..6752864962 --- /dev/null +++ b/engines/fullpipe/scenes/scene09.cpp @@ -0,0 +1,484 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "fullpipe/fullpipe.h" + +#include "fullpipe/objectnames.h" +#include "fullpipe/constants.h" + +#include "fullpipe/gameloader.h" +#include "fullpipe/motion.h" +#include "fullpipe/scenes.h" +#include "fullpipe/statics.h" + +#include "fullpipe/interaction.h" +#include "fullpipe/behavior.h" + + +namespace Fullpipe { + +struct Hanger { + StaticANIObject *ani; + int field_4; + int field_8; + int phase; +}; + +void scene09_setupGrit(Scene *sc) { + if (g_vars->scene09_grit->_statics->_staticsId == ST_GRT9_GRIT) { + if (!getGameLoaderInventory()->getCountItemsWithId(ANI_INV_COIN)) { + if (g_fp->getObjectState(sO_CoinSlot_1) == g_fp->getObjectEnumState(sO_CoinSlot_1, sO_Empty) + && (g_vars->swallowedEgg1->_value.intValue == ANI_INV_EGGBOOT || g_vars->swallowedEgg2->_value.intValue == ANI_INV_EGGBOOT || g_vars->swallowedEgg3->_value.intValue == ANI_INV_EGGBOOT)) { + Scene *oldsc = g_fp->_currentScene; + g_fp->_currentScene = sc; + g_vars->scene09_grit->changeStatics2(ST_GRT9_NORM); + g_fp->_currentScene = oldsc; + } + } + } +} + +void scene09_initScene(Scene *sc) { + g_vars->scene09_flyingBall = 0; + g_vars->scene09_var05 = 0; + g_vars->scene09_glotatel = sc->getStaticANIObject1ById(ANI_GLOTATEL, -1); + g_vars->scene09_spitter = sc->getStaticANIObject1ById(ANI_PLEVATEL, -1); + g_vars->scene09_grit = sc->getStaticANIObject1ById(ANI_GRIT_9, -1); + g_vars->scene09_var08 = 1; + g_vars->scene09_var09 = 0; + g_vars->scene09_var10 = -1; + g_vars->scene09_var11 = -1; + g_vars->scene09_var12 = -1000; + + g_vars->scene09_balls.cPlexLen = 10; + g_vars->scene09_var07.cPlexLen = 10; + + while (g_vars->scene09_balls.numBalls) { + Ball *b = g_vars->scene09_balls.pHead->p0; + + g_vars->scene09_balls.pHead = g_vars->scene09_balls.pHead->p0; + + if (g_vars->scene09_balls.pHead) + g_vars->scene09_balls.pHead->p0->p1 = 0; + else + g_vars->scene09_balls.field_8 = 0; + + g_vars->scene09_balls.init(&b); + } + + g_vars->scene09_var13 = 3; + + g_vars->scene09_hangers.clear(); + g_vars->scene09_var15 = 4; + g_vars->scene09_numMovingHangers = 4; + + StaticANIObject *hanger = sc->getStaticANIObject1ById(ANI_VISUNCHIK, -1); + Hanger *hng = new Hanger; + + hng->ani = hanger; + hng->phase = 0; + hng->field_4 = 0; + hng->field_8 = 0; + + g_vars->scene09_hangers.push_back(hng); + + int x = 75; + + for (int i = 1; x < 300; i++, x += 75) { + StaticANIObject *ani = new StaticANIObject(hanger); + + ani->show1(x + hanger->_ox, hanger->_oy, MV_VSN_CYCLE2, 0); + sc->addStaticANIObject(hanger, 1); + + hng = new Hanger; + + hng->ani = ani; + hng->phase = 0; + hng->field_4 = 0; + hng->field_8 = 0; + + g_vars->scene09_hangers.push_back(hng); + } + + while (g_vars->scene09_var07.numBalls) { + Ball *ohead = g_vars->scene09_var07.pHead; + + g_vars->scene09_var07.pHead = g_vars->scene09_var07.pHead->p0; + + if (g_vars->scene09_var07.pHead) + ohead->p0->p1 = 0; + else + g_vars->scene09_var07.field_8 = 0; + + ohead->p0 = g_vars->scene09_var07.pTail; + + g_vars->scene09_var07.pTail = ohead; + + g_vars->scene09_var07.numBalls--; + } + + g_vars->scene09_var07.reset(); + + Ball *b9 = g_vars->scene09_var07.sub04(g_vars->scene09_var07.field_8, 0); + b9->ani = sc->getStaticANIObject1ById(ANI_BALL9, -1); + b9->ani->setAlpha(0xc8); + + if (g_vars->scene09_var07.field_8) { + g_vars->scene09_var07.field_8->p0 = b9; + g_vars->scene09_var07.field_8 = b9; + } else { + g_vars->scene09_var07.pHead = b9; + g_vars->scene09_var07.field_8 = b9; + } + + for (int i = 0; i < 4; i++) { + StaticANIObject *newball = new StaticANIObject(b9->ani); + + newball->setAlpha(0xc8); + + Ball *runPtr = g_vars->scene09_var07.pTail; + Ball *lastP = g_vars->scene09_var07.field_8; + + if (!g_vars->scene09_var07.pTail) { + g_vars->scene09_var07.cPlex = (byte *)calloc(g_vars->scene09_var07.cPlexLen, sizeof(Ball)); + + byte *p1 = g_vars->scene09_var07.cPlex + (g_vars->scene09_var07.cPlexLen - 1) * sizeof(Ball); + + if (g_vars->scene09_var07.cPlexLen - 1 < 0) { + runPtr = g_vars->scene09_var07.pTail; + } else { + runPtr = g_vars->scene09_var07.pTail; + + for (int j = 0; j < g_vars->scene09_var07.cPlexLen; j++) { + ((Ball *)p1)->p1 = runPtr; + runPtr = (Ball *)p1; + + p1 -= sizeof(Ball); + } + + g_vars->scene09_var07.pTail = runPtr; + } + } + + g_vars->scene09_var07.pTail = runPtr->p0; + runPtr->p1 = lastP; + runPtr->p0 = 0; + runPtr->ani = newball; + + g_vars->scene09_var07.numBalls++; + + if (g_vars->scene09_var07.field_8) + g_vars->scene09_var07.field_8->p0 = runPtr; + else + g_vars->scene09_var07.pHead = runPtr; + + g_vars->scene09_var07.field_8 = runPtr; + + sc->addStaticANIObject(newball, 1); + } + + g_fp->setObjectState(sO_RightStairs_9, g_fp->getObjectEnumState(sO_RightStairs_9, sO_IsClosed)); + + GameVar *eggvar = g_fp->getGameLoaderGameVar()->getSubVarByName("OBJSTATES")->getSubVarByName(sO_GulpedEggs); + + g_vars->swallowedEgg1 = eggvar->getSubVarByName(sO_Egg1); + g_vars->swallowedEgg2 = eggvar->getSubVarByName(sO_Egg2); + g_vars->swallowedEgg3 = eggvar->getSubVarByName(sO_Egg3); + + scene09_setupGrit(sc); + + g_fp->initArcadeKeys("SC_9"); + + g_fp->lift_setButton(sO_Level1, ST_LBN_1N); + + g_fp->setArcadeOverlay(PIC_CSR_ARCADE4); +} + +int sceneHandler09_updateScreenCallback() { + int res = g_fp->drawArcadeOverlay(g_fp->_objectIdAtCursor == ANI_VISUNCHIK || g_vars->scene09_var10 >= 0); + + if (!res) + g_fp->_updateScreenCallback = 0; + + return res; +} + +int scene09_updateCursor() { + g_fp->updateCursorCommon(); + + if (g_vars->scene09_var10 < 0) { + if (g_fp->_objectIdAtCursor == ANI_VISUNCHIK) { + if (g_fp->_cursorId == PIC_CSR_ITN) + g_fp->_updateScreenCallback = sceneHandler09_updateScreenCallback; + } else { + if (g_fp->_objectIdAtCursor == PIC_SC9_LADDER_R && g_fp->_cursorId == PIC_CSR_ITN) + g_fp->_cursorId = (g_vars->scene09_var02 < 350) ? PIC_CSR_GOD : PIC_CSR_GOU; + } + } else { + g_fp->_cursorId = PIC_CSR_ITN; + } + + return g_fp->_cursorId; +} + +void sceneHandler09_winArcade() { + if (g_vars->scene09_glotatel->_flags & 4) { + g_vars->scene09_glotatel->changeStatics2(ST_GLT_SIT); + g_vars->scene09_glotatel->startAnim(MV_GLT_FLYAWAY, 0, -1); + + g_fp->setObjectState(sO_Jug, g_fp->getObjectEnumState(sO_Jug, sO_Unblocked)); + g_fp->setObjectState(sO_RightStairs_9, g_fp->getObjectEnumState(sO_RightStairs_9, sO_IsOpened)); + + g_vars->scene09_var08 = 0; + } +} + +void sceneHandler09_startAuntie() { + MessageQueue *mq = new MessageQueue(g_fp->_currentScene->getMessageQueueById(QU_TTA9_GOL), 0, 1); + + mq->getExCommandByIndex(0)->_x = g_fp->_sceneRect.right + 30; + mq->chain(0); +} + +void sceneHandler09_spitterClick() { + if (g_vars->scene09_spitter->_flags & 4) { + PicAniInfo info; + + g_vars->scene09_spitter->getPicAniInfo(&info); + g_vars->scene09_spitter->_messageQueueId = 0; + g_vars->scene09_spitter->changeStatics2(ST_PLV_SIT); + + int x = g_vars->scene09_spitter->_ox - 10; + int y = g_vars->scene09_spitter->_oy + 145; + + g_vars->scene09_spitter->setPicAniInfo(&info); + + if (ABS(x - g_fp->_aniMan->_ox) > 1 || ABS(y - g_fp->_aniMan->_oy) > 1) { + MessageQueue *mq = getCurrSceneSc2MotionController()->method34(g_fp->_aniMan, x, y, 1, ST_MAN_UP); + + if (mq) { + ExCommand *ex = new ExCommand(0, 17, MSG_SC9_PLVCLICK, 0, 0, 0, 1, 0, 0, 0); + ex->_excFlags = 2; + mq->addExCommandToEnd(ex); + + postExCommand(g_fp->_aniMan->_id, 2, x, y, 0, -1); + } + } else { + if (!g_fp->_aniMan->_movement) { + g_vars->scene09_spitter->changeStatics2(ST_PLV_SIT); + g_vars->scene09_spitter->hide(); + + g_fp->_aniMan->startAnim(MV_MAN9_SHOOT, 0, -1); + + g_fp->stopAllSoundInstances(SND_9_006); + } + + g_fp->_aniMan2 = 0; + + if (g_fp->_sceneRect.left < 800) + g_fp->_currentScene->_x = 800 - g_fp->_sceneRect.left; + } + } +} + +void sceneHandler09_eatBall() { + warning("STUB: sceneHandler09_eatBall()"); +} + +void sceneHandler09_showBall() { + warning("STUB: sceneHandler09_showBall()"); +} + +void sceneHandler09_cycleHangers() { + warning("STUB: sceneHandler09_cycleHangers()"); +} + +void sceneHandler09_limitHangerPhase() { + warning("STUB: sceneHandler09_limitHangerPhase()"); +} + +void sceneHandler09_checkHangerCollide() { + warning("STUB: sceneHandler09_checkHangerCollide()"); +} + +void sceneHandler09_hangerStartCycle() { + warning("STUB: sceneHandler09_hangerStartCycle()"); +} + +int sceneHandler09(ExCommand *cmd) { + if (cmd->_messageKind != 17) + return 0; + + switch (cmd->_messageNum) { + case MSG_CMN_WINARCADE: + sceneHandler09_winArcade(); + break; + + case MSG_SC9_STARTTIOTIA: + sceneHandler09_startAuntie(); + break; + + case MSG_SC9_FROMLADDER: + getCurrSceneSc2MotionController()->setEnabled(); + getGameLoaderInteractionController()->enableFlag24(); + + g_vars->scene09_var09 = 0; + break; + + case MSG_SC9_TOLADDER: + getCurrSceneSc2MotionController()->clearEnabled(); + getGameLoaderInteractionController()->disableFlag24(); + + g_vars->scene09_var09 = 1; + break; + + case MSG_SC9_PLVCLICK: + sceneHandler09_spitterClick(); + break; + + case MSG_SC9_FLOWN: + g_vars->scene09_var08 = 0; + break; + + case MSG_SC9_EATBALL: + sceneHandler09_eatBall(); + break; + + case MSG_SC9_SHOWBALL: + sceneHandler09_showBall(); + break; + + case 33: + { + int res = 0; + + if (g_fp->_aniMan2) { + int x = g_fp->_aniMan2->_ox; + + g_vars->scene09_var02 = g_fp->_aniMan2->_oy; + + if (x < g_fp->_sceneRect.left + 200) + g_fp->_currentScene->_x = x - g_fp->_sceneRect.left - 300; + + if (x > g_fp->_sceneRect.right - 200) + g_fp->_currentScene->_x = x - g_fp->_sceneRect.right + 300; + + res = 1; + } else { + if (g_fp->_aniMan->_movement && g_fp->_aniMan->_movement->_id != MV_MAN9_SHOOT) + g_fp->_aniMan2 = g_fp->_aniMan; + } + + sceneHandler09_cycleHangers(); + sceneHandler09_limitHangerPhase(); + sceneHandler09_checkHangerCollide(); + + if (g_vars->scene09_var10 >= 0) + sceneHandler09_hangerStartCycle(); + + if (!g_vars->scene09_var17) + g_fp->_behaviorManager->updateBehaviors(); + + g_fp->startSceneTrack(); + + return res; + } + + case 30: + if (g_vars->scene09_var10 >= 0) { + if (ABS(g_vars->scene09_hangers[g_vars->scene09_var10]->phase) < 15) { + g_vars->scene09_hangers[g_vars->scene09_var10]->ani->_callback2 = 0; + g_vars->scene09_hangers[g_vars->scene09_var10]->ani->changeStatics2(ST_VSN_NORMAL); + } + } + + g_vars->scene09_var10 = -1; + + break; + + case 29: + { + StaticANIObject *ani = g_fp->_currentScene->getStaticANIObjectAtPos(g_fp->_sceneRect.left + cmd->_x, g_fp->_sceneRect.top + cmd->_y); + + if (ani) { + if (ani->_id == ANI_PLEVATEL) { + sceneHandler09_spitterClick(); + break; + } + + if (ani->_id == ANI_VISUNCHIK) { + if (g_vars->scene09_numMovingHangers > 0) { + int hng = 0; + + while (g_vars->scene09_hangers[hng]->ani != ani) { + ++hng; + + if (hng >= g_vars->scene09_numMovingHangers) + break; + } + + g_vars->scene09_var10 = hng; + g_vars->scene09_var11 = g_vars->scene09_hangers[hng]->phase; + g_vars->scene09_var12 = g_vars->scene09_hangers[hng]->phase; + + g_vars->scene09_var19 = cmd->_y; + + if (!g_vars->scene09_hangers[hng]->ani->_movement || g_vars->scene09_hangers[hng]->ani->_movement->_id != MV_VSN_CYCLE2) { + g_vars->scene09_hangers[hng]->ani->changeStatics2(ST_VSN_NORMAL); + g_vars->scene09_hangers[hng]->ani->startAnim(MV_VSN_CYCLE2, 0, -1); + g_vars->scene09_hangers[hng]->ani->_callback2 = 0; + } + + ExCommand *ex = new ExCommand(0, 35, SND_9_018, 0, 0, 0, 1, 0, 0, 0); + + ex->_field_14 = 1; + ex->_excFlags |= 2; + ex->postMessage(); + } + + break; + } + } + + if (g_vars->scene09_var09 && g_fp->_currentScene->getPictureObjectIdAtPos(cmd->_sceneClickX, cmd->_sceneClickY) == PIC_SC9_LADDER_R + && !cmd->_keyCode && !g_fp->_aniMan->_movement) { + handleObjectInteraction(g_fp->_aniMan, g_fp->_currentScene->getPictureObjectById(PIC_SC9_LADDER_R, 0), 0); + } + + if (!ani || !canInteractAny(g_fp->_aniMan, ani, cmd->_keyCode)) { + int picId = g_fp->_currentScene->getPictureObjectIdAtPos(cmd->_sceneClickX, cmd->_sceneClickY); + PictureObject *pic = g_fp->_currentScene->getPictureObjectById(picId, 0); + + if (!pic || !canInteractAny(g_fp->_aniMan, pic, cmd->_keyCode)) { + if ((g_fp->_sceneRect.right - cmd->_sceneClickX < 47 && g_fp->_sceneRect.right < g_fp->_sceneWidth - 1) || (cmd->_sceneClickX - g_fp->_sceneRect.left < 47 && g_fp->_sceneRect.left > 0)) + g_fp->processArcade(cmd); + } + } + + break; + } + } + + return 0; +} + +} // End of namespace Fullpipe diff --git a/engines/fullpipe/scenes/scene10.cpp b/engines/fullpipe/scenes/scene10.cpp index 9c00902bba..4f9e627fa4 100644 --- a/engines/fullpipe/scenes/scene10.cpp +++ b/engines/fullpipe/scenes/scene10.cpp @@ -170,7 +170,7 @@ int sceneHandler10(ExCommand *ex) { break; case 64: - g_fp->lift_sub05(ex); + g_fp->lift_hoverButton(ex); break; case 29: @@ -185,7 +185,7 @@ int sceneHandler10(ExCommand *ex) { StaticANIObject *ani = g_fp->_currentScene->getStaticANIObjectAtPos(ex->_sceneClickX, ex->_sceneClickY); if (ani && ani->_id == ANI_LIFTBUTTON) { - g_fp->lift_sub1(ani); + g_fp->lift_animateButton(ani); ex->_messageKind = 0; return 0; diff --git a/engines/fullpipe/scenes/scene14.cpp b/engines/fullpipe/scenes/scene14.cpp index ab0487974a..28f054fd32 100644 --- a/engines/fullpipe/scenes/scene14.cpp +++ b/engines/fullpipe/scenes/scene14.cpp @@ -749,7 +749,7 @@ int sceneHandler14(ExCommand *cmd) { break; case 64: - g_fp->lift_sub05(cmd); + g_fp->lift_hoverButton(cmd); break; case 33: @@ -820,7 +820,7 @@ int sceneHandler14(ExCommand *cmd) { StaticANIObject *ani = g_fp->_currentScene->getStaticANIObjectAtPos(cmd->_sceneClickX, cmd->_sceneClickY); if (ani && ani->_id == ANI_LIFTBUTTON) { - g_fp->lift_sub1(ani); + g_fp->lift_animateButton(ani); cmd->_messageKind = 0; break; } diff --git a/engines/fullpipe/scenes/scene15.cpp b/engines/fullpipe/scenes/scene15.cpp index 155897619f..9e11df92e4 100644 --- a/engines/fullpipe/scenes/scene15.cpp +++ b/engines/fullpipe/scenes/scene15.cpp @@ -156,7 +156,7 @@ int sceneHandler15(ExCommand *cmd) { break; case 64: - g_fp->lift_sub05(cmd); + g_fp->lift_hoverButton(cmd); break; case 29: @@ -171,7 +171,7 @@ int sceneHandler15(ExCommand *cmd) { StaticANIObject *ani = g_fp->_currentScene->getStaticANIObjectAtPos(cmd->_sceneClickX, cmd->_sceneClickY); if (ani && ani->_id == ANI_LIFTBUTTON) { - g_fp->lift_sub1(ani); + g_fp->lift_animateButton(ani); cmd->_messageKind = 0; } diff --git a/engines/fullpipe/scenes/scene27.cpp b/engines/fullpipe/scenes/scene27.cpp new file mode 100644 index 0000000000..8623b2b9b3 --- /dev/null +++ b/engines/fullpipe/scenes/scene27.cpp @@ -0,0 +1,759 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "fullpipe/fullpipe.h" + +#include "fullpipe/objectnames.h" +#include "fullpipe/constants.h" + +#include "fullpipe/gameloader.h" +#include "fullpipe/motion.h" +#include "fullpipe/scenes.h" +#include "fullpipe/statics.h" + +#include "fullpipe/interaction.h" +#include "fullpipe/behavior.h" + +#define DBG 0 + +namespace Fullpipe { + +struct Bat { + StaticANIObject *ani; + int field_4; + double power; + double field_10; + double currX; + double currY; + double powerCos; + double powerSin; +}; + +void scene27_initScene(Scene *sc) { + g_vars->scene27_hitZone = sc->getPictureObjectById(PIC_SC27_HITZONE2, 0); + g_vars->scene27_driver = sc->getStaticANIObject1ById(ANI_VODILLA, -1); + g_vars->scene27_maid = sc->getStaticANIObject1ById(ANI_MAID, -1); + g_vars->scene27_batHandler = sc->getStaticANIObject1ById(ANI_BITAHANDLER, -1); + + g_vars->scene27_balls.numBalls = 0; + g_vars->scene27_balls.pTail = 0; + g_vars->scene27_balls.field_8 = 0; + g_vars->scene27_balls.pHead = 0; + g_vars->scene27_balls.cPlexLen = 10; + + free(g_vars->scene27_balls.cPlex); + g_vars->scene27_balls.cPlex = 0; + + g_vars->scene27_bats.clear(); + g_vars->scene27_var07.clear(); + + g_vars->scene27_driverHasVent = true; + g_vars->scene27_bat = sc->getStaticANIObject1ById(ANI_BITA, -1); + + for (int i = 0; i < 4; i++) { + StaticANIObject *newbat = new StaticANIObject(g_vars->scene27_bat); + + Ball *runPtr = g_vars->scene27_balls.pTail; + Ball *lastP = g_vars->scene27_balls.field_8; + + if (!g_vars->scene27_balls.pTail) { + g_vars->scene27_balls.cPlex = (byte *)calloc(g_vars->scene27_balls.cPlexLen, sizeof(Ball)); + + byte *p1 = g_vars->scene27_balls.cPlex + (g_vars->scene27_balls.cPlexLen - 1) * sizeof(Ball); + + if (g_vars->scene27_balls.cPlexLen - 1 < 0) { + runPtr = g_vars->scene27_balls.pTail; + } else { + runPtr = g_vars->scene27_balls.pTail; + + for (int j = 0; j < g_vars->scene27_balls.cPlexLen; j++) { + ((Ball *)p1)->p1 = runPtr; + runPtr = (Ball *)p1; + + p1 -= sizeof(Ball); + } + + g_vars->scene27_balls.pTail = runPtr; + } + } + + g_vars->scene27_balls.pTail = runPtr->p0; + runPtr->p1 = lastP; + runPtr->p0 = 0; + runPtr->ani = newbat; + + g_vars->scene27_balls.numBalls++; + + if (g_vars->scene27_balls.field_8) + g_vars->scene27_balls.field_8->p0 = runPtr; + else + g_vars->scene27_balls.pHead = runPtr; + + g_vars->scene27_balls.field_8 = runPtr; + + sc->addStaticANIObject(newbat, 1); + } + + g_vars->scene27_dudeIsAiming = false; + g_vars->scene27_maxPhaseReached = false; + g_vars->scene27_wipeIsNeeded = false; + g_vars->scene27_driverPushedButton = false; + g_vars->scene27_numLostBats = 0; + g_vars->scene27_knockCount = 0; + g_vars->scene27_launchPhase = 0; + + Scene *oldsc = g_fp->_currentScene; + g_fp->_currentScene = sc; + + if (g_fp->getObjectState(sO_Maid) == g_fp->getObjectEnumState(sO_Maid, sO_WithSwab)) { + g_vars->scene27_maid->changeStatics2(ST_MID_SWAB2); + } else if (g_fp->getObjectState(sO_Maid) == g_fp->getObjectEnumState(sO_Maid, sO_WithBroom)) { + g_vars->scene27_maid->changeStatics2(ST_MID_BROOM); + } else if (g_fp->getObjectState(sO_Maid) == g_fp->getObjectEnumState(sO_Maid, sO_WithSpade)) { + g_vars->scene27_maid->changeStatics2(ST_MID_SPADE); + } + + g_fp->_currentScene = oldsc; + + g_fp->setArcadeOverlay(PIC_CSR_ARCADE7); +} + +int scene27_updateCursor() { + g_fp->updateCursorCommon(); + + if (g_vars->scene27_dudeIsAiming) { + if (g_fp->_cursorId != PIC_CSR_DEFAULT_INV && g_fp->_cursorId != PIC_CSR_ITN_INV) + g_fp->_cursorId = PIC_CSR_ARCADE7_D; + + } else if (g_fp->_objectIdAtCursor == ANI_MAN) { + if (g_vars->scene27_maxPhaseReached) + if (g_fp->_cursorId == PIC_CSR_DEFAULT) + g_fp->_cursorId = PIC_CSR_ITN; + } + + return g_fp->_cursorId; +} + +void sceneHandler27_driverGiveVent() { + g_vars->scene27_driver->changeStatics2(ST_DRV_VENT); + g_vars->scene27_driver->startMQIfIdle(QU_DRV_GIVEVENT, 1); + + g_vars->scene27_driverHasVent = false; + + getCurrSceneSc2MotionController()->setEnabled(); + getGameLoaderInteractionController()->enableFlag24(); + + g_fp->_behaviorManager->setFlagByStaticAniObject(g_fp->_aniMan, 1); +} + +void sceneHandler27_winArcade() { + if (g_fp->getObjectState(sO_Driver) == g_fp->getObjectEnumState(sO_Driver, sO_WithSteering)) { + g_vars->scene27_dudeIsAiming = false; + + g_fp->_aniMan->_callback2 = 0; + g_fp->_aniMan->changeStatics2(ST_MAN_RIGHT); + + sceneHandler27_driverGiveVent(); + } +} + +void sceneHandler27_takeVent() { + if (g_fp->getObjectState(sO_Maid) == g_fp->getObjectEnumState(sO_Maid, sO_WithSwab)) { + if (g_vars->scene27_maid->isIdle()) { + if (g_vars->scene27_maid->_flags & 4) { + g_vars->scene27_maid->changeStatics2(ST_MID_SWAB2); + g_vars->scene27_maid->startMQIfIdle(QU_MID_CLEANVENT, 1); + } + } + } +} + +void sceneHandler27_showNextBat() { + if (g_vars->scene27_bat) { + MessageQueue *mq = new MessageQueue(g_fp->_currentScene->getMessageQueueById(QU_SC27_SHOWBET), 0, 1); + + mq->replaceKeyCode(-1, g_vars->scene27_bat->_okeyCode); + mq->chain(0); + } + + g_vars->scene27_batHandler->_priority = 1045; +} + +int sceneHandler27_updateScreenCallback() { + int res; + + res = g_fp->drawArcadeOverlay(getGameLoaderInteractionController()->_flag24 == 0); + + if (!res) + g_fp->_updateScreenCallback = 0; + + return res; +} + +void sceneHandler27_aniManCallback(int *phase) { + if (!g_vars->scene27_maxPhaseReached) { + if (*phase >= 5) + g_vars->scene27_maxPhaseReached = true; + else + ++*phase; + } +} + +void sceneHandler27_throwBat() { + if (getGameLoaderInteractionController()->_flag24) + g_fp->_updateScreenCallback = sceneHandler27_updateScreenCallback; + + g_fp->_aniMan->_callback2 = sceneHandler27_aniManCallback; + + g_fp->_aniMan->startAnim(MV_MAN27_THROWBET, 0, -1); + + getCurrSceneSc2MotionController()->clearEnabled(); + getGameLoaderInteractionController()->disableFlag24(); + + g_fp->_behaviorManager->setFlagByStaticAniObject(g_fp->_aniMan, 0); + + g_vars->scene27_maxPhaseReached = false; + + g_vars->scene27_bat->hide(); +} + +void sceneHandler27_clickBat(ExCommand *cmd) { + int bx = g_vars->scene27_bat->_ox - 5; + int by = g_vars->scene27_bat->_oy - 71; + +#if DBG + sceneHandler27_throwBat(); + return; +#endif + + if (ABS(bx - g_fp->_aniMan->_ox) > 1 || ABS(by - g_fp->_aniMan->_oy) > 1 + || g_fp->_aniMan->_movement || g_fp->_aniMan->_statics->_staticsId != ST_MAN_RIGHT) { + MessageQueue *mq = getCurrSceneSc2MotionController()->method34(g_fp->_aniMan, bx, by, 1, ST_MAN_RIGHT); + + if (mq) { + mq->addExCommandToEnd(cmd->createClone()); + + postExCommand(g_fp->_aniMan->_id, 2, bx, by, 0, -1); + } + } else { + sceneHandler27_throwBat(); + } +} + +void sceneHandler27_maidSwab() { +#if DBG + return; +#endif + if (g_fp->getObjectState(sO_Maid) == g_fp->getObjectEnumState(sO_Maid, sO_WithSwab)) + g_vars->scene27_maid->changeStatics2(ST_MID_SWAB); +} + +void sceneHandler27_startBat(StaticANIObject *bat) { + Bat *newbat = new Bat; + + newbat->power = g_vars->scene27_launchPhase * 2.5 + 8.0; + newbat->field_10 = 0; + newbat->ani = bat; + newbat->powerCos = newbat->power * cos(0.0); + newbat->powerSin = newbat->power * sin(0.0); + newbat->currX = newbat->powerCos + (double)g_fp->_aniMan->_ox + 42.0; + newbat->currY = newbat->powerSin + (double)g_fp->_aniMan->_oy + 58.0; + + bat->_statics = (Statics *)bat->_staticsList[0]; + bat->setOXY((int)newbat->currX, (int)newbat->currY); + bat->_flags |= 4; + + g_vars->scene27_bats.push_back(newbat); + + sceneHandler27_maidSwab(); +} + +void sceneHandler27_startAiming() { + g_vars->scene27_dudeIsAiming = false; + g_vars->scene27_maxPhaseReached = false; + + g_fp->_aniMan->_callback2 = 0; + + g_vars->scene27_launchPhase = g_fp->_aniMan->_movement->_currDynamicPhaseIndex - 6; + + int phase = 21 - g_vars->scene27_launchPhase; + + if (phase < 14) + phase = 14; + + if (phase > 20) + phase = 20; + + g_fp->playSound(SND_27_044, 0); + + g_fp->_aniMan->_movement->setDynamicPhaseIndex(phase); +} + +void sceneHandler27_initAiming(ExCommand *cmd) { + g_vars->scene27_aimStartX = cmd->_x; + g_vars->scene27_aimStartY = cmd->_y; + g_vars->scene27_dudeIsAiming = true; + g_vars->scene27_maxPhaseReached = false; +} + +void sceneHandler27_aimDude() { + int phase = (g_vars->scene27_aimStartX - g_fp->_mouseScreenPos.x) / 20 + 6; + + if (phase < 6) + phase = 6; + + if (phase > 11) + phase = 11; + + if (g_fp->_aniMan->_movement) + g_fp->_aniMan->_movement->setDynamicPhaseIndex(phase); +} + +void sceneHandler27_wipeDo() { + for (uint i = 0; i < g_vars->scene27_bats.size(); i++) { + if (g_vars->scene27_bats[i]->currX < 800.0) { + g_vars->scene27_bats[i]->field_10 = atan2(800.0 - g_vars->scene27_bats[i]->currX, 520.0 - g_vars->scene27_bats[i]->currY); + g_vars->scene27_bats[i]->power += 1.0; + } + } +} + +bool sceneHandler27_batFallLogic(int batn) { + Bat *bat = g_vars->scene27_bats[batn]; + + int y = (bat->currY - 458.0) * 0.4848484848484849 + 734.0; + + if (y >= bat->currX) + return false; + + if (bat->currX - y > 15.0 || bat->ani->_statics->_staticsId == ST_BTA_FALL) { + bat->ani->_priority = 2020; + + g_vars->scene27_var07.push_back(bat); + + if (batn != g_vars->scene27_var07.size() - 1) + g_vars->scene27_var07.remove_at(batn); + } else if (!bat->ani->_movement) { + bat->ani->startAnim(MV_BTA_FALL, 0, -1); + } + + return true; +} + +bool sceneHandler27_batCalcDistance(int bat1, int bat2) { + double at = atan2(g_vars->scene27_bats[bat1]->currX - g_vars->scene27_bats[bat2]->currX, g_vars->scene27_bats[bat1]->currY - g_vars->scene27_bats[bat2]->currY); + double dy = g_vars->scene27_bats[bat1]->currY - g_vars->scene27_bats[bat2]->currY; + double dx = g_vars->scene27_bats[bat1]->currX - g_vars->scene27_bats[bat2]->currX; + double ay = cos(at); + double ax = sin(at); + + return sqrt(ax * ax * 0.25 + ay * ay) * 54.0 > sqrt(dx * dx + dy * dy); +} + +void sceneHandler27_knockBats(int bat1n, int bat2n) { + Bat *bat1 = g_vars->scene27_bats[bat1n]; + Bat *bat2 = g_vars->scene27_bats[bat2n]; + + if (0.0 != bat1->power) { + double rndF = (double)g_fp->_rnd->getRandomNumber(32767) * 0.0000009155552842799158 - 0.015 + + atan2(bat2->currX - bat1->currX, bat2->currY - bat1->currY); + double rndCos = cos(rndF); + double rndSin = sin(rndF); + + double pow1x = cos(bat1->field_10 - rndF) * (double)((int)(bat2->currX - bat1->currX) >= 0 ? 1 : -1) * bat1->power; + double pow1y = sin(bat1->field_10 - rndF) * (double)((int)(bat2->currY - bat1->currY) >= 0 ? 1 : -1) * bat1->power; + + bat1->powerCos -= pow1x * 1.1; + bat1->powerSin -= pow1y * 1.1; + + rndF = ((double)g_fp->_rnd->getRandomNumber(32767) * 0.0000009155552842799158 - 0.015 + + atan2(bat1->currX - bat2->currX, bat1->currY - bat2->currY)); + double pow2x = cos(bat2->field_10 - rndF) * (double)((int)(bat1->currX - bat2->currX) >= 0 ? 1 : -1) * bat2->power; + double pow2y = sin(bat2->field_10 - rndF) * (double)((int)(bat1->currY - bat2->currY) >= 0 ? 1 : -1) * bat2->power; + + bat2->powerCos -= pow2x * 1.1; + bat2->powerSin -= pow2y * 1.1; + + double dy = bat1->currY - bat2->currY; + double dx = bat1->currX - bat2->currX; + double dist = (sqrt(rndSin * rndSin * 0.25 + rndCos * rndCos) * 54.0 - sqrt(dx * dx + dy * dy)) / cos(rndF - bat1->field_10); + bat1->currX -= cos(bat1->field_10) * (dist + 1.0); + bat1->currY -= sin(bat1->field_10) * (dist + 1.0); + bat1->powerCos += pow2x * 0.64; + + if (bat1->currX <= 500.0) + bat1->powerSin = 0.0; + else + bat1->powerSin += pow2y * 0.64; + + bat1->field_10 = atan2(bat1->powerCos, bat1->powerSin); + bat1->power = sqrt(bat1->powerCos * bat1->powerCos + bat1->powerSin * bat1->powerSin); + bat2->powerCos += pow1x * 0.64; + + if (bat2->currX <= 500.0) + bat2->powerSin = 0; + else + bat2->powerSin += pow1y * 0.64; + + bat2->field_10 = atan2(bat2->powerCos, bat2->powerSin); + bat2->power = sqrt(bat2->powerCos * bat2->powerCos + bat2->powerSin * bat2->powerSin); + + g_fp->playSound(SND_27_026, 0); + } +} + +void sceneHandler27_batSetColors(int batn) { + Bat *bat = g_vars->scene27_bats[batn]; + + if (g_vars->scene27_hitZone->isPixelHitAtPos((int)bat->currX, (int)bat->currY) ) { + if (bat->ani->_statics->_staticsId == ST_BTA_NORM) { + if (!bat->ani->_movement) + bat->ani->_statics = bat->ani->getStaticsById(ST_BTA_HILITE); + } + } else { + if (bat->ani->_statics->_staticsId == ST_BTA_HILITE) { + if (!bat->ani->_movement) + bat->ani->_statics = bat->ani->getStaticsById(ST_BTA_NORM); + } + } +} + +void sceneHandler27_driverPushButton() { + if (g_fp->getObjectState(sO_Driver) == g_fp->getObjectEnumState(sO_Driver, sO_WithSteering)) { + g_vars->scene27_driver->changeStatics2(ST_DRV_VENT); + chainQueue(QU_DRV_PUSHBUTTON, 1); + + g_vars->scene27_driverPushedButton = true; + } else { + g_vars->scene27_driver->changeStatics2(ST_DRV_SITNOVENT); + + + chainQueue(QU_DRV_PUSHBUTTON_NOVENT, 1); + + g_vars->scene27_driverPushedButton = true; + } +} + +void sceneHandler27_maidSwitchback() { +#ifndef DBG + if (g_fp->getObjectState(sO_Maid) == g_fp->getObjectEnumState(sO_Maid, sO_WithSwab)) { + g_vars->scene27_maid->changeStatics2(ST_MID_SWAB); + g_vars->scene27_maid->startMQIfIdle(QU_MID_SWITCHBACK, 1); + } +#endif +} + +void sceneHandler27_batLogic() { + if (g_vars->scene27_balls.numBalls) { + g_vars->scene27_bat = g_vars->scene27_balls.pHead->ani; + + g_vars->scene27_balls.pHead = g_vars->scene27_balls.pHead->p0; + + if (g_vars->scene27_balls.pHead) + g_vars->scene27_balls.pHead->p0->p1 = 0; + else + g_vars->scene27_balls.field_8 = 0; + + g_vars->scene27_balls.init(&g_vars->scene27_balls.pHead->p0); + + int mv; + + switch (g_vars->scene27_batHandler->_statics->_staticsId) { + case ST_BTH_5: + mv = MV_BTH_5_4; + break; + + case ST_BTH_4: + mv = MV_BTH_4_3; + break; + + case ST_BTH_3: + mv = MV_BTH_3_2; + break; + + case ST_BTH_2: + mv = MV_BTH_2_1; + break; + + case ST_BTH_1: + mv = MV_BTH_1_0; + break; + + default: + chainQueue(QU_SC27_RESTARTBETS, 1); + + getCurrSceneSc2MotionController()->setEnabled(); + getGameLoaderInteractionController()->enableFlag24(); + + g_fp->_behaviorManager->setFlagByStaticAniObject(g_fp->_aniMan, 1); + + return; + } + + MessageQueue *mq = new MessageQueue(g_fp->_globalMessageQueueList->compact()); + + mq->setFlags(mq->getFlags() | 1); + + ExCommand *ex = new ExCommand(g_vars->scene27_batHandler->_id, 1, mv, 0, 0, 0, 1, 0, 0, 0); + ex->_excFlags |= 2; + mq->addExCommandToEnd(ex); + + ex = new ExCommand(0, 17, MSG_SC27_CLICKBET, 0, 0, 0, 1, 0, 0, 0); + ex->_excFlags |= 3; + mq->addExCommandToEnd(ex); + + mq->chain(0); + } else { + g_vars->scene27_bat = 0; + } +} + +void sceneHandler27_calcWinArcade() { + if (!g_vars->scene27_wipeIsNeeded && !g_vars->scene27_driverPushedButton) { + int numHilite = 0; + + for (uint i = 0; i < g_vars->scene27_bats.size(); i++) { + if (g_vars->scene27_bats[i]->ani->_statics->_staticsId == ST_BTA_HILITE) + numHilite++; + } + + if (numHilite >= 3) { + if (g_fp->getObjectState(sO_Driver) == g_fp->getObjectEnumState(sO_Driver, sO_WithSteering)) { + sceneHandler27_driverGiveVent(); + sceneHandler27_maidSwitchback(); + + return; + } + } + + if (!g_vars->scene27_balls.numBalls) { + sceneHandler27_driverPushButton(); + sceneHandler27_maidSwitchback(); + return; + } + + sceneHandler27_batLogic(); + } + + sceneHandler27_maidSwitchback(); +} + +void sceneHandler27_regenBats() { + g_vars->scene27_wipeIsNeeded = false; + + for (uint i = 0; i < g_vars->scene27_var07.size(); i++) { + g_vars->scene27_var07[i]->ani->hide(); + + Ball *runPtr = g_vars->scene27_balls.pTail; + Ball *lastP = g_vars->scene27_balls.field_8; + StaticANIObject *newbat = g_vars->scene27_var07[i]->ani; + + if (!g_vars->scene27_balls.pTail) { + g_vars->scene27_balls.cPlex = (byte *)calloc(g_vars->scene27_balls.cPlexLen, sizeof(Ball)); + + byte *p1 = g_vars->scene27_balls.cPlex + (g_vars->scene27_balls.cPlexLen - 1) * sizeof(Ball); + + if (g_vars->scene27_balls.cPlexLen - 1 < 0) { + runPtr = g_vars->scene27_balls.pTail; + } else { + runPtr = g_vars->scene27_balls.pTail; + + for (int j = 0; j < g_vars->scene27_balls.cPlexLen; j++) { + ((Ball *)p1)->p1 = runPtr; + runPtr = (Ball *)p1; + + p1 -= sizeof(Ball); + } + + g_vars->scene27_balls.pTail = runPtr; + } + } + + g_vars->scene27_balls.pTail = runPtr->p0; + runPtr->p1 = lastP; + runPtr->p0 = 0; + runPtr->ani = newbat; + + g_vars->scene27_balls.numBalls++; + + if (g_vars->scene27_balls.field_8) + g_vars->scene27_balls.field_8->p0 = runPtr; + else + g_vars->scene27_balls.pHead = runPtr; + + g_vars->scene27_balls.field_8 = runPtr; + } + + g_vars->scene27_var07.clear(); + + sceneHandler27_batLogic(); + + g_vars->scene27_driverPushedButton = false; +} + +void sceneHandler27_animateBats() { + int oldCount = g_vars->scene27_knockCount; + + g_vars->scene27_numLostBats = 0; + g_vars->scene27_knockCount = 0; + + for (uint i = 0; i < g_vars->scene27_bats.size(); i++) { + Bat *bat = g_vars->scene27_bats[i]; + + bat->currX = cos(bat->field_10) * bat->power + bat->currX; + bat->currY = sin(bat->field_10) * bat->power + bat->currY; + + bat->ani->setOXY((int)bat->currX, (int)bat->currY); + bat->ani->_priority = (int)(600.0 - bat->currY); + + double powerDelta; + + if (cos(bat->field_10) >= 0.0 || bat->currX >= 362.0) + powerDelta = bat->power * 0.035; + else + powerDelta = bat->power * 0.4; + + bat->power -= powerDelta; + bat->powerCos = cos(bat->field_10) * bat->power; + bat->powerSin = sin(bat->field_10) * bat->power; + + if (bat->power >= 0.5) + g_vars->scene27_knockCount++; + else + bat->power = 0; + + sceneHandler27_batSetColors(i); + + if (!sceneHandler27_batFallLogic(i) && !g_vars->scene27_wipeIsNeeded) { + for (uint j = 0; j < g_vars->scene27_bats.size(); j++) { + if (i != j && sceneHandler27_batCalcDistance(i, j)) + sceneHandler27_knockBats(i, j); + } + } + } + + for (uint i = 0; i < g_vars->scene27_var07.size(); i++) { + Bat *bat = g_vars->scene27_var07[i]; + + if (bat->currY >= 700.0) { + g_vars->scene27_numLostBats++; + } else { + bat->currX = bat->powerCos + bat->currX; + bat->currY = bat->powerSin + bat->currY; + bat->ani->setOXY((int)bat->currX, (int)bat->currY); + bat->powerSin = bat->powerSin + 1.0; + } + } + + if (oldCount != g_vars->scene27_knockCount && !g_vars->scene27_knockCount) + sceneHandler27_calcWinArcade(); + + if (g_vars->scene27_wipeIsNeeded) { + if (g_vars->scene27_numLostBats == 5) + sceneHandler27_regenBats(); + } +} + +int sceneHandler27(ExCommand *cmd) { + if (cmd->_messageKind != 17) + return 0; + + switch (cmd->_messageNum) { + case MSG_CMN_WINARCADE: + sceneHandler27_winArcade(); + break; + + case MSG_SC27_TAKEVENT: + sceneHandler27_takeVent(); + break; + + case MSG_SC27_SHOWNEXTBET: + sceneHandler27_showNextBat(); + break; + + case MSG_SC27_HANDLERTOFRONT: + g_vars->scene27_batHandler->_priority = 1005; + break; + + case MSG_SC27_STARTWIPE: + g_vars->scene27_wipeIsNeeded = true; + + g_fp->playSound(SND_27_027, 0); + + break; + + case MSG_SC27_CLICKBET: + sceneHandler27_clickBat(cmd); + break; + + case MSG_SC27_STARTBET: + if (g_vars->scene27_bat) + sceneHandler27_startBat(g_vars->scene27_bat); + + break; + + case 30: + if (g_vars->scene27_dudeIsAiming) + sceneHandler27_startAiming(); + + break; + + case 29: + if (g_fp->_aniMan == g_fp->_currentScene->getStaticANIObjectAtPos(g_fp->_sceneRect.left + cmd->_x, g_fp->_sceneRect.top + cmd->_y) + && g_vars->scene27_maxPhaseReached) + sceneHandler27_initAiming(cmd); + + break; + + case 33: + if (g_fp->_aniMan2) { + int x = g_fp->_aniMan2->_ox; + + if (x < g_fp->_sceneRect.left + 200) + g_fp->_currentScene->_x = x - 300 - g_fp->_sceneRect.left; + + if (x > g_fp->_sceneRect.right - 200) + g_fp->_currentScene->_x = x + 300 - g_fp->_sceneRect.right; + } + + if (g_vars->scene27_dudeIsAiming) + sceneHandler27_aimDude(); + + if (g_vars->scene27_wipeIsNeeded) { + sceneHandler27_wipeDo(); + + if (!g_fp->_aniMan->_movement && g_fp->_aniMan->_statics->_staticsId == ST_MAN_RIGHT) + g_fp->_aniMan->startAnim(MV_MAN27_FLOW, 0, -1); + } + + sceneHandler27_animateBats(); + + g_fp->_behaviorManager->updateBehaviors(); + g_fp->startSceneTrack(); + + break; + } + + return 0; +} + +} // End of namespace Fullpipe diff --git a/engines/fullpipe/scenes/scene30.cpp b/engines/fullpipe/scenes/scene30.cpp index a807e692a7..39a51deeef 100644 --- a/engines/fullpipe/scenes/scene30.cpp +++ b/engines/fullpipe/scenes/scene30.cpp @@ -111,7 +111,7 @@ int sceneHandler30(ExCommand *cmd) { break; case 64: - g_fp->lift_sub05(cmd); + g_fp->lift_hoverButton(cmd); break; case MSG_LIFT_GO: @@ -123,7 +123,7 @@ int sceneHandler30(ExCommand *cmd) { StaticANIObject *ani = g_fp->_currentScene->getStaticANIObjectAtPos(g_fp->_sceneRect.left + cmd->_x, g_fp->_sceneRect.top + cmd->_y); if (ani && ani->_id == ANI_LIFTBUTTON) { - g_fp->lift_sub1(ani); + g_fp->lift_animateButton(ani); cmd->_messageKind = 0; } diff --git a/engines/fullpipe/scenes/scene32.cpp b/engines/fullpipe/scenes/scene32.cpp index 597d3422f6..be7c983277 100644 --- a/engines/fullpipe/scenes/scene32.cpp +++ b/engines/fullpipe/scenes/scene32.cpp @@ -339,7 +339,7 @@ int sceneHandler32(ExCommand *cmd) { break; case 64: - g_fp->lift_sub05(cmd); + g_fp->lift_hoverButton(cmd); break; case MSG_SC6_INSTHANDLE: @@ -403,7 +403,7 @@ int sceneHandler32(ExCommand *cmd) { StaticANIObject *ani = g_fp->_currentScene->getStaticANIObjectAtPos(cmd->_sceneClickX, cmd->_sceneClickY); if (ani && ani->_id == ANI_LIFTBUTTON) { - g_fp->lift_sub1(ani); + g_fp->lift_animateButton(ani); cmd->_messageKind = 0; break; diff --git a/engines/fullpipe/scenes/scene34.cpp b/engines/fullpipe/scenes/scene34.cpp index b3e0db75af..0e690f4703 100644 --- a/engines/fullpipe/scenes/scene34.cpp +++ b/engines/fullpipe/scenes/scene34.cpp @@ -392,7 +392,7 @@ int sceneHandler34(ExCommand *cmd) { break; case 64: - g_fp->lift_sub05(cmd); + g_fp->lift_hoverButton(cmd); break; case MSG_LIFT_GO: @@ -426,7 +426,7 @@ int sceneHandler34(ExCommand *cmd) { } if (ani->_id == ANI_LIFTBUTTON) { - g_fp->lift_sub1(ani); + g_fp->lift_animateButton(ani); cmd->_messageKind = 0; diff --git a/engines/fullpipe/scenes/scene35.cpp b/engines/fullpipe/scenes/scene35.cpp index f10786b821..a42849eeb5 100644 --- a/engines/fullpipe/scenes/scene35.cpp +++ b/engines/fullpipe/scenes/scene35.cpp @@ -199,7 +199,7 @@ int sceneHandler35(ExCommand *cmd) { break; case 64: - g_fp->lift_sub05(cmd); + g_fp->lift_hoverButton(cmd); break; case 29: @@ -208,7 +208,7 @@ int sceneHandler35(ExCommand *cmd) { if (ani) if (ani->_id == ANI_LIFTBUTTON) { - g_fp->lift_sub1(ani); + g_fp->lift_animateButton(ani); cmd->_messageKind = 0; break; } diff --git a/engines/fullpipe/scenes/scene38.cpp b/engines/fullpipe/scenes/scene38.cpp index 016dc83c1b..7fb0be8509 100644 --- a/engines/fullpipe/scenes/scene38.cpp +++ b/engines/fullpipe/scenes/scene38.cpp @@ -368,7 +368,7 @@ int sceneHandler38(ExCommand *cmd) { break; case 64: - g_fp->lift_sub05(cmd); + g_fp->lift_hoverButton(cmd); break; case 29: @@ -376,7 +376,7 @@ int sceneHandler38(ExCommand *cmd) { StaticANIObject *ani = g_fp->_currentScene->getStaticANIObjectAtPos(g_fp->_sceneRect.left + cmd->_x, g_fp->_sceneRect.top + cmd->_y); if (ani && ani->_id == ANI_LIFTBUTTON) { - g_fp->lift_sub1(ani); + g_fp->lift_animateButton(ani); cmd->_messageKind = 0; } diff --git a/engines/gob/detection/tables.h b/engines/gob/detection/tables.h index 271f75af79..d042dfeede 100644 --- a/engines/gob/detection/tables.h +++ b/engines/gob/detection/tables.h @@ -55,6 +55,7 @@ static const PlainGameDescriptor gobGames[] = { {"ajworld", "A.J.'s World of Discovery"}, {"gob3", "Goblins Quest 3"}, {"gob3cd", "Goblins Quest 3 CD"}, + {"crousti", "Croustibat"}, {"lit1", "Lost in Time Part 1"}, {"lit2", "Lost in Time Part 2"}, {"lit", "Lost in Time"}, @@ -110,6 +111,7 @@ static const GOBGameDescription gameDescriptions[] = { #include "gob/detection/tables_adi4.h" // The ADI / Addy 4 series #include "gob/detection/tables_adibou.h" // The Adibou / Addy Junior series #include "gob/detection/tables_ajworld.h" // A.J.'s World of Discovery / ADI Jr. + #include "gob/detection/tables_crousti.h" // Croustibat { AD_TABLE_END_MARKER, kGameTypeNone, kFeaturesNone, 0, 0, 0} }; diff --git a/engines/avalanche/pingo.h b/engines/gob/detection/tables_crousti.h index 6eecaf6453..da4cd461c1 100644 --- a/engines/avalanche/pingo.h +++ b/engines/gob/detection/tables_crousti.h @@ -20,37 +20,26 @@ * */ -/* - * This code is based on the original source code of Lord Avalot d'Argent version 1.3. - * Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman. - */ - -/* PINGO Full-screen sub-parts of the game. */ - -#ifndef AVALANCHE_PINGO_H -#define AVALANCHE_PINGO_H - -#include "common/str.h" - -namespace Avalanche { -class AvalancheEngine; - -class Pingo { -public: - Pingo(AvalancheEngine *vm); - - void bossKey(); - void copy02(); - void copy03(); - void copyPage(byte frp, byte top); - void winningPic(); - -private: - AvalancheEngine *_vm; - - void dPlot(int16 x, int16 y, Common::String z); -}; - -} // End of namespace Avalanche. - -#endif // AVALANCHE_PINGO_H +/* Detection tables for Croustibat. */ + +#ifndef GOB_DETECTION_TABLES_CROUSTI_H +#define GOB_DETECTION_TABLES_CROUSTI_H + +// -- DOS VGA Floppy -- + +{ + { + "crousti", + "", + AD_ENTRY1s("intro.stk", "63fd795818fa72c32b903bbd99e18ea1", 851926), + PT_BRA, + kPlatformDOS, + ADGF_NO_FLAGS, + GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH) + }, + kGameTypeCrousti, + kFeaturesAdLib, + 0, 0, 0 +}, + +#endif // GOB_DETECTION_TABLES_CROUSTI_H diff --git a/engines/gob/draw_fascin.cpp b/engines/gob/draw_fascin.cpp index 12009d7ee5..c248cdf009 100644 --- a/engines/gob/draw_fascin.cpp +++ b/engines/gob/draw_fascin.cpp @@ -882,8 +882,6 @@ bool Draw_Fascination::overlapWin(int16 idWin1, int16 idWin2) { void Draw_Fascination::activeWin(int16 id) { bool found = false; int16 t[10], t2[10]; - int nextId = -1; - int oldId = -1; SurfacePtr tempSrf; SurfacePtr oldSrf[10]; @@ -906,6 +904,8 @@ void Draw_Fascination::activeWin(int16 id) { } if (found) { + int nextId = -1; + int oldId = -1; for (int i = 9; i >= 0; i--) { if (t[i] != -1) { if (nextId != -1) diff --git a/engines/gob/gob.cpp b/engines/gob/gob.cpp index fcf98f0355..c50f4c42a0 100644 --- a/engines/gob/gob.cpp +++ b/engines/gob/gob.cpp @@ -457,6 +457,7 @@ Common::Error GobEngine::initGameParts() { case kGameTypeWeen: case kGameTypeGob2: + case kGameTypeCrousti: _init = new Init_v2(this); _video = new Video_v2(this); _inter = new Inter_v2(this); diff --git a/engines/gob/gob.h b/engines/gob/gob.h index df73404596..e8da5fdcfc 100644 --- a/engines/gob/gob.h +++ b/engines/gob/gob.h @@ -55,6 +55,7 @@ class StaticTextWidget; * - Bambou le sauveur de la jungle * - Geisha * - Once Upon A Time: Little Red Riding Hood + * - Croustibat */ namespace Gob { @@ -134,7 +135,8 @@ enum GameType { kGameTypeBabaYaga, kGameTypeLittleRed, kGameTypeOnceUponATime, // Need more inspection to see if Baba Yaga or Abracadabra - kGameTypeAJWorld + kGameTypeAJWorld, + kGameTypeCrousti }; enum Features { diff --git a/engines/gob/inter.h b/engines/gob/inter.h index 2aa837e777..fabd31b66d 100644 --- a/engines/gob/inter.h +++ b/engines/gob/inter.h @@ -439,6 +439,7 @@ protected: void o2_animPalInit(OpFuncParams ¶ms); void o2_addHotspot(OpFuncParams ¶ms); void o2_removeHotspot(OpFuncParams ¶ms); + void o2_getTotTextItemPart(OpFuncParams ¶ms); void o2_goblinFunc(OpFuncParams ¶ms); void o2_stopSound(OpFuncParams ¶ms); void o2_loadSound(OpFuncParams ¶ms); @@ -540,7 +541,6 @@ protected: virtual void setupOpcodesFunc(); virtual void setupOpcodesGob(); - void o3_getTotTextItemPart(OpFuncParams ¶ms); void o3_speakerOn(OpFuncParams ¶ms); void o3_speakerOff(OpFuncParams ¶ms); void o3_copySprite(OpFuncParams ¶ms); diff --git a/engines/gob/inter_v2.cpp b/engines/gob/inter_v2.cpp index 6b7a4f03bd..9346a6adb8 100644 --- a/engines/gob/inter_v2.cpp +++ b/engines/gob/inter_v2.cpp @@ -124,6 +124,7 @@ void Inter_v2::setupOpcodesFunc() { OPCODEFUNC(0x18, o2_addHotspot); OPCODEFUNC(0x19, o2_removeHotspot); + OPCODEFUNC(0x1A, o2_getTotTextItemPart); OPCODEFUNC(0x25, o2_goblinFunc); @@ -1195,6 +1196,188 @@ void Inter_v2::o2_removeHotspot(OpFuncParams ¶ms) { _vm->_game->_hotspots->remove((stateType2 << 12) + id); } +void Inter_v2::o2_getTotTextItemPart(OpFuncParams ¶ms) { + byte *totData; + int16 totTextItem; + int16 part, curPart = 0; + int16 offX = 0, offY = 0; + int16 collId = 0, collCmd; + uint32 stringStartVar, stringVar; + bool end; + + totTextItem = _vm->_game->_script->readInt16(); + stringStartVar = _vm->_game->_script->readVarIndex(); + part = _vm->_game->_script->readValExpr(); + + stringVar = stringStartVar; + if (part == -1) { + warning("o2_getTotTextItemPart, part == -1"); + _vm->_draw->_hotspotText = GET_VARO_STR(stringVar); + } + + WRITE_VARO_UINT8(stringVar, 0); + + TextItem *textItem = _vm->_game->_resources->getTextItem(totTextItem); + if (!textItem) + return; + + totData = textItem->getData(); + + // Skip background rectangles + while (((int16) READ_LE_UINT16(totData)) != -1) + totData += 9; + totData += 2; + + while (*totData != 1) { + switch (*totData) { + case 2: + case 5: + totData++; + offX = READ_LE_UINT16(totData); + offY = READ_LE_UINT16(totData + 2); + totData += 4; + break; + + case 3: + case 4: + totData += 2; + break; + + case 6: + totData++; + + collCmd = *totData++; + if (collCmd & 0x80) { + collId = READ_LE_UINT16(totData); + totData += 2; + } + + // Skip collision coordinates + if (collCmd & 0x40) + totData += 8; + + if ((collCmd & 0x8F) && ((-collId - 1) == part)) { + int n = 0; + + while (1) { + if ((*totData < 1) || (*totData > 7)) { + if (*totData >= 32) { + WRITE_VARO_UINT8(stringVar++, *totData++); + n++; + } else + totData++; + continue; + } + + if ((n != 0) || (*totData == 1) || + (*totData == 6) || (*totData == 7)) { + WRITE_VARO_UINT8(stringVar, 0); + delete textItem; + return; + } + + switch (*totData) { + case 2: + case 5: + totData += 5; + break; + + case 3: + case 4: + totData += 2; + break; + } + } + + } + break; + + case 7: + case 8: + case 9: + totData++; + break; + + case 10: + if (curPart == part) { + WRITE_VARO_UINT8(stringVar++, 0xFF); + WRITE_VARO_UINT16(stringVar, offX); + WRITE_VARO_UINT16(stringVar + 2, offY); + WRITE_VARO_UINT16(stringVar + 4, + totData - _vm->_game->_resources->getTexts()); + WRITE_VARO_UINT8(stringVar + 6, 0); + delete textItem; + return; + } + + end = false; + while (!end) { + switch (*totData) { + case 2: + case 5: + if (ABS(offY - READ_LE_UINT16(totData + 3)) > 1) + end = true; + else + totData += 5; + break; + + case 3: + totData += 2; + break; + + case 10: + totData += totData[1] * 2 + 2; + break; + + default: + if (*totData < 32) + end = true; + while (*totData >= 32) + totData++; + break; + } + } + + if (part >= 0) + curPart++; + break; + + default: + while (1) { + + while (*totData >= 32) + WRITE_VARO_UINT8(stringVar++, *totData++); + WRITE_VARO_UINT8(stringVar, 0); + + if (((*totData != 2) && (*totData != 5)) || + (ABS(offY - READ_LE_UINT16(totData + 3)) > 1)) { + + if (curPart == part) { + delete textItem; + return; + } + + stringVar = stringStartVar; + WRITE_VARO_UINT8(stringVar, 0); + + while (*totData >= 32) + totData++; + + if (part >= 0) + curPart++; + break; + + } else + totData += 5; + + } + break; + } + } + + delete textItem; +} + void Inter_v2::o2_goblinFunc(OpFuncParams ¶ms) { OpGobParams gobParams; int16 cmd; diff --git a/engines/gob/inter_v3.cpp b/engines/gob/inter_v3.cpp index edf56012d9..d6d4c52476 100644 --- a/engines/gob/inter_v3.cpp +++ b/engines/gob/inter_v3.cpp @@ -50,7 +50,6 @@ void Inter_v3::setupOpcodesDraw() { void Inter_v3::setupOpcodesFunc() { Inter_v2::setupOpcodesFunc(); - OPCODEFUNC(0x1A, o3_getTotTextItemPart); OPCODEFUNC(0x22, o3_speakerOn); OPCODEFUNC(0x23, o3_speakerOff); OPCODEFUNC(0x32, o3_copySprite); @@ -66,188 +65,6 @@ void Inter_v3::setupOpcodesGob() { OPCODEGOB(100, o3_wobble); } -void Inter_v3::o3_getTotTextItemPart(OpFuncParams ¶ms) { - byte *totData; - int16 totTextItem; - int16 part, curPart = 0; - int16 offX = 0, offY = 0; - int16 collId = 0, collCmd; - uint32 stringStartVar, stringVar; - bool end; - - totTextItem = _vm->_game->_script->readInt16(); - stringStartVar = _vm->_game->_script->readVarIndex(); - part = _vm->_game->_script->readValExpr(); - - stringVar = stringStartVar; - if (part == -1) { - warning("o3_getTotTextItemPart, part == -1"); - _vm->_draw->_hotspotText = GET_VARO_STR(stringVar); - } - - WRITE_VARO_UINT8(stringVar, 0); - - TextItem *textItem = _vm->_game->_resources->getTextItem(totTextItem); - if (!textItem) - return; - - totData = textItem->getData(); - - // Skip background rectangles - while (((int16) READ_LE_UINT16(totData)) != -1) - totData += 9; - totData += 2; - - while (*totData != 1) { - switch (*totData) { - case 2: - case 5: - totData++; - offX = READ_LE_UINT16(totData); - offY = READ_LE_UINT16(totData + 2); - totData += 4; - break; - - case 3: - case 4: - totData += 2; - break; - - case 6: - totData++; - - collCmd = *totData++; - if (collCmd & 0x80) { - collId = READ_LE_UINT16(totData); - totData += 2; - } - - // Skip collision coordinates - if (collCmd & 0x40) - totData += 8; - - if ((collCmd & 0x8F) && ((-collId - 1) == part)) { - int n = 0; - - while (1) { - if ((*totData < 1) || (*totData > 7)) { - if (*totData >= 32) { - WRITE_VARO_UINT8(stringVar++, *totData++); - n++; - } else - totData++; - continue; - } - - if ((n != 0) || (*totData == 1) || - (*totData == 6) || (*totData == 7)) { - WRITE_VARO_UINT8(stringVar, 0); - delete textItem; - return; - } - - switch (*totData) { - case 2: - case 5: - totData += 5; - break; - - case 3: - case 4: - totData += 2; - break; - } - } - - } - break; - - case 7: - case 8: - case 9: - totData++; - break; - - case 10: - if (curPart == part) { - WRITE_VARO_UINT8(stringVar++, 0xFF); - WRITE_VARO_UINT16(stringVar, offX); - WRITE_VARO_UINT16(stringVar + 2, offY); - WRITE_VARO_UINT16(stringVar + 4, - totData - _vm->_game->_resources->getTexts()); - WRITE_VARO_UINT8(stringVar + 6, 0); - delete textItem; - return; - } - - end = false; - while (!end) { - switch (*totData) { - case 2: - case 5: - if (ABS(offY - READ_LE_UINT16(totData + 3)) > 1) - end = true; - else - totData += 5; - break; - - case 3: - totData += 2; - break; - - case 10: - totData += totData[1] * 2 + 2; - break; - - default: - if (*totData < 32) - end = true; - while (*totData >= 32) - totData++; - break; - } - } - - if (part >= 0) - curPart++; - break; - - default: - while (1) { - - while (*totData >= 32) - WRITE_VARO_UINT8(stringVar++, *totData++); - WRITE_VARO_UINT8(stringVar, 0); - - if (((*totData != 2) && (*totData != 5)) || - (ABS(offY - READ_LE_UINT16(totData + 3)) > 1)) { - - if (curPart == part) { - delete textItem; - return; - } - - stringVar = stringStartVar; - WRITE_VARO_UINT8(stringVar, 0); - - while (*totData >= 32) - totData++; - - if (part >= 0) - curPart++; - break; - - } else - totData += 5; - - } - break; - } - } - - delete textItem; -} - void Inter_v3::o3_speakerOn(OpFuncParams ¶ms) { int16 frequency = _vm->_game->_script->readValExpr(); int32 length = -1; diff --git a/engines/hopkins/anim.cpp b/engines/hopkins/anim.cpp index 2ec9cec009..238f27616e 100644 --- a/engines/hopkins/anim.cpp +++ b/engines/hopkins/anim.cpp @@ -668,7 +668,6 @@ void AnimationManager::playSequence(const Common::String &file, uint32 rate1, ui */ void AnimationManager::playSequence2(const Common::String &file, uint32 rate1, uint32 rate2, uint32 rate3, bool skipSeqFl) { byte *screenP; - int frameNumber; Common::File f; if (_vm->shouldQuit()) @@ -708,7 +707,7 @@ void AnimationManager::playSequence2(const Common::String &file, uint32 rate1, u if (!_vm->_events->_escKeyFl) { _vm->_events->_rateCounter = 0; - frameNumber = 0; + int frameNumber = 0; while (!_vm->shouldQuit()) { _vm->_soundMan->playAnimSound(frameNumber++); diff --git a/engines/hopkins/computer.cpp b/engines/hopkins/computer.cpp index f9e3ecafcd..c42474de64 100644 --- a/engines/hopkins/computer.cpp +++ b/engines/hopkins/computer.cpp @@ -675,15 +675,12 @@ void ComputerManager::displayBricks() { _breakoutSpeed = 1; int16 *level = _breakoutLevel; - int cellLeft; - int cellTop; - int cellType; for (int levelIdx = 0; ; levelIdx += 6) { - cellLeft = (int16)FROM_LE_16(level[levelIdx]); + int cellLeft = (int16)FROM_LE_16(level[levelIdx]); if (cellLeft == -1) break; - cellTop = FROM_LE_16(level[levelIdx + 1]); - cellType = FROM_LE_16(level[levelIdx + 4]); + int cellTop = FROM_LE_16(level[levelIdx + 1]); + int cellType = FROM_LE_16(level[levelIdx + 4]); if (cellType <= 6) ++_breakoutBrickNbr; @@ -833,7 +830,6 @@ int ComputerManager::displayHiscores() { _vm->_graphicsMan->setColorPercentage(254, 0, 0, 0); int yp; - int xp; // Loop for displaying the scores for (int scoreIndex = 0; scoreIndex <= 5; scoreIndex++) { yp = 19 * scoreIndex; @@ -853,7 +849,7 @@ int ComputerManager::displayHiscores() { int buttonIndex = 0; do { _vm->_events->refreshEvents(); - xp = _vm->_events->getMouseX(); + int xp = _vm->_events->getMouseX(); yp = _vm->_events->getMouseY(); if (_vm->_events->getMouseButton() == 1 && ABS(xp - 79) <= 33 && ABS(yp - 396) <= 13) diff --git a/engines/hopkins/detection.cpp b/engines/hopkins/detection.cpp index c617a5aacf..b81f51e607 100644 --- a/engines/hopkins/detection.cpp +++ b/engines/hopkins/detection.cpp @@ -29,6 +29,7 @@ #include "common/memstream.h" #include "engines/advancedDetector.h" #include "common/system.h" +#include "common/translation.h" #include "graphics/colormasks.h" #include "graphics/surface.h" @@ -69,6 +70,30 @@ static const PlainGameDescriptor hopkinsGames[] = { #include "hopkins/detection_tables.h" +static const ADExtraGuiOptionsMap optionsList[] = { + { + GAMEOPTION_GORE_DEFAULT_OFF, + { + _s("Gore Mode"), + _s("Enable Gore Mode when available"), + "enable_gore", + false + } + }, + + { + GAMEOPTION_GORE_DEFAULT_ON, + { + _s("Gore Mode"), + _s("Enable Gore Mode when available"), + "enable_gore", + true + } + }, + + AD_EXTRA_GUI_OPTIONS_TERMINATOR +}; + const static char *directoryGlobs[] = { "voice", "link", @@ -77,7 +102,7 @@ const static char *directoryGlobs[] = { class HopkinsMetaEngine : public AdvancedMetaEngine { public: - HopkinsMetaEngine() : AdvancedMetaEngine(Hopkins::gameDescriptions, sizeof(Hopkins::HopkinsGameDescription), hopkinsGames) { + HopkinsMetaEngine() : AdvancedMetaEngine(Hopkins::gameDescriptions, sizeof(Hopkins::HopkinsGameDescription), hopkinsGames, optionsList) { _maxScanDepth = 3; _directoryGlobs = directoryGlobs; } diff --git a/engines/hopkins/detection_tables.h b/engines/hopkins/detection_tables.h index c3ff563f6f..c6db7ab253 100644 --- a/engines/hopkins/detection_tables.h +++ b/engines/hopkins/detection_tables.h @@ -22,6 +22,9 @@ namespace Hopkins { +#define GAMEOPTION_GORE_DEFAULT_ON GUIO_GAMEOPTIONS1 +#define GAMEOPTION_GORE_DEFAULT_OFF GUIO_GAMEOPTIONS2 + static const HopkinsGameDescription gameDescriptions[] = { { // Hopkins FBI Linux Demo UK 1.00 and 1.02 @@ -35,7 +38,7 @@ static const HopkinsGameDescription gameDescriptions[] = { Common::EN_ANY, Common::kPlatformLinux, ADGF_DEMO, - GUIO1(GUIO_NONE) + GUIO1(GAMEOPTION_GORE_DEFAULT_ON) }, }, { @@ -51,7 +54,7 @@ static const HopkinsGameDescription gameDescriptions[] = { Common::EN_ANY, Common::kPlatformOS2, ADGF_NO_FLAGS, - GUIO1(GUIO_NONE) + GUIO1(GAMEOPTION_GORE_DEFAULT_ON) }, }, { @@ -66,7 +69,7 @@ static const HopkinsGameDescription gameDescriptions[] = { Common::EN_ANY, Common::kPlatformBeOS, ADGF_NO_FLAGS, - GUIO1(GUIO_NONE) + GUIO1(GAMEOPTION_GORE_DEFAULT_ON) }, }, { @@ -81,7 +84,7 @@ static const HopkinsGameDescription gameDescriptions[] = { Common::ES_ESP, Common::kPlatformWindows, ADGF_NO_FLAGS, - GUIO1(GUIO_NONE) + GUIO1(GAMEOPTION_GORE_DEFAULT_ON) }, }, { @@ -96,7 +99,7 @@ static const HopkinsGameDescription gameDescriptions[] = { Common::EN_ANY, Common::kPlatformWindows, ADGF_NO_FLAGS, - GUIO1(GUIO_NONE) + GUIO1(GAMEOPTION_GORE_DEFAULT_OFF) }, }, { @@ -111,7 +114,7 @@ static const HopkinsGameDescription gameDescriptions[] = { Common::RU_RUS, Common::kPlatformWindows, ADGF_NO_FLAGS, - GUIO1(GUIO_NONE) + GUIO1(GAMEOPTION_GORE_DEFAULT_ON) }, }, { @@ -126,7 +129,7 @@ static const HopkinsGameDescription gameDescriptions[] = { Common::FR_FRA, Common::kPlatformLinux, ADGF_NO_FLAGS, - GUIO1(GUIO_NONE) + GUIO1(GAMEOPTION_GORE_DEFAULT_ON) }, }, { @@ -141,7 +144,7 @@ static const HopkinsGameDescription gameDescriptions[] = { Common::EN_ANY, Common::kPlatformLinux, ADGF_NO_FLAGS, - GUIO1(GUIO_NONE) + GUIO1(GAMEOPTION_GORE_DEFAULT_ON) }, }, { @@ -156,11 +159,27 @@ static const HopkinsGameDescription gameDescriptions[] = { Common::FR_FRA, Common::kPlatformWindows, ADGF_NO_FLAGS, - GUIO1(GUIO_NONE) + GUIO1(GAMEOPTION_GORE_DEFAULT_ON) }, }, { + // Hopkins FBI Win95 Polish, provided by Paput in bug #6511 + { + "hopkins", + 0, + { + {"RES_VAN.RES", 0, "f2fec5172e4a7a9d35cb2a5f948ef6a9", 39400865}, + AD_LISTEND + }, + Common::PL_POL, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + GUIO1(GAMEOPTION_GORE_DEFAULT_OFF) + }, + }, + + { // Hopkins FBI Win95 Demo, provided by Strangerke // CHECKME: No voice! a second file is required though... Also, it has multi-language support { @@ -173,7 +192,7 @@ static const HopkinsGameDescription gameDescriptions[] = { Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO, - GUIO1(GUIO_NONE) + GUIO1(GAMEOPTION_GORE_DEFAULT_ON) }, }, { @@ -188,7 +207,7 @@ static const HopkinsGameDescription gameDescriptions[] = { Common::PL_POL, Common::kPlatformWindows, ADGF_DEMO, - GUIO1(GUIO_NONE) + GUIO1(GAMEOPTION_GORE_DEFAULT_OFF) }, }, { AD_TABLE_END_MARKER } diff --git a/engines/hopkins/files.cpp b/engines/hopkins/files.cpp index 2390ebbdf8..51d11afd91 100644 --- a/engines/hopkins/files.cpp +++ b/engines/hopkins/files.cpp @@ -25,6 +25,7 @@ #include "hopkins/hopkins.h" #include "hopkins/globals.h" +#include "common/config-manager.h" #include "common/system.h" #include "common/debug.h" #include "common/file.h" @@ -68,20 +69,11 @@ int FileManager::readStream(Common::ReadStream &stream, void *buf, size_t nbytes } /** - * Initialize censorship based on blood.dat file + * The original censorship was based on blood.dat file. + * It's now using the config manager and a per-engine GUI option. */ void FileManager::initCensorship() { - _vm->_globals->_censorshipFl = false; - - // If file doesn't exist, fallback to uncensored - if (fileExists("BLOOD.DAT")) { - char *data = (char *)loadFile("BLOOD.DAT"); - - if ((data[6] == 'u' && data[7] == 'k') || (data[6] == 'U' && data[7] == 'K')) - _vm->_globals->_censorshipFl = true; - - _vm->_globals->freeMemory((byte *)data); - } + _vm->_globals->_censorshipFl = ConfMan.getBool("enable_gore"); } /** diff --git a/engines/hopkins/graphics.cpp b/engines/hopkins/graphics.cpp index a64e81fcc9..c47cf95152 100644 --- a/engines/hopkins/graphics.cpp +++ b/engines/hopkins/graphics.cpp @@ -439,9 +439,7 @@ void GraphicsManager::display8BitRect(const byte *surface, int xs, int ys, int w } void GraphicsManager::displayScaled8BitRect(const byte *surface, int xp, int yp, int width, int height, int destX, int destY) { - int xCtr; const byte *palette; - int savedXCount; byte *loopDestP; const byte *loopSrcP; int yCtr; @@ -454,10 +452,10 @@ void GraphicsManager::displayScaled8BitRect(const byte *surface, int xp, int yp, do { yCtr = yCount; - xCtr = xCount; + int xCtr = xCount; loopSrcP = srcP; loopDestP = destP; - savedXCount = xCount; + int savedXCount = xCount; palette = _palettePixels; do { diff --git a/engines/hopkins/hopkins.cpp b/engines/hopkins/hopkins.cpp index 0e86fa26a9..5d8661c4ae 100644 --- a/engines/hopkins/hopkins.cpp +++ b/engines/hopkins/hopkins.cpp @@ -232,7 +232,7 @@ bool HopkinsEngine::runWin95Demo() { if (!_globals->_censorshipFl) _animMan->playAnim("BANQUE.ANM", "BANKUK.ANM", 200, 28, 200); else - _animMan->playAnim("BANQUE.ANM", "BANKUK.ANM", 200, 28, 200); + _animMan->playAnim("BANKUK.ANM", "BANQUE.ANM", 200, 28, 200); _soundMan->_specialSoundNum = 0; _soundMan->removeSample(1); _soundMan->removeSample(2); @@ -2860,7 +2860,6 @@ void HopkinsEngine::syncSoundSettings() { } bool HopkinsEngine::displayAdultDisclaimer() { - int xp, yp; int buttonIndex; _graphicsMan->_minX = 0; @@ -2880,8 +2879,8 @@ bool HopkinsEngine::displayAdultDisclaimer() { _events->_mouseSpriteId = 0; do { - xp = _events->getMouseX(); - yp = _events->getMouseY(); + int xp = _events->getMouseX(); + int yp = _events->getMouseY(); buttonIndex = 0; if (xp >= 37 && xp <= 169 && yp >= 406 && yp <= 445) diff --git a/engines/hopkins/lines.cpp b/engines/hopkins/lines.cpp index aa708fdfb2..e849f8635c 100644 --- a/engines/hopkins/lines.cpp +++ b/engines/hopkins/lines.cpp @@ -548,8 +548,6 @@ int LinesManager::avoidObstacleOnSegment(int lineIdx, int lineDataIdx, int route bool LinesManager::MIRACLE(int fromX, int fromY, int lineIdx, int destLineIdx, int routeIdx) { debugC(5, kDebugPath, "MIRACLE(%d, %d, %d, %d, %d)", fromX, fromY, lineIdx, destLineIdx, routeIdx); - int newLinesDataIdx = 0; - int newLinesIdx = 0; int lineIdxLeft = 0; int lineDataIdxLeft = 0; int lineIdxRight = 0; @@ -700,6 +698,8 @@ bool LinesManager::MIRACLE(int fromX, int fromY, int lineIdx, int destLineIdx, i newDir = DIR_LEFT; } + int newLinesDataIdx = 0; + int newLinesIdx = 0; switch(newDir) { case DIR_UP: newLinesIdx = linesIdxUp; @@ -1552,7 +1552,6 @@ void LinesManager::useRoute2(int idx, int curRouteIdx) { int LinesManager::characterRoute(int fromX, int fromY, int destX, int destY, int startLineIdx, int endLineIdx, int routeIdx) { debugC(5, kDebugPath, "characterRoute(%d, %d, %d, %d, %d, %d, %d)", fromX, fromY, destX, destY, startLineIdx, endLineIdx, routeIdx); int collDataIdxRoute2 = 0; - bool colResult = false; int curX = fromX; int curY = fromY; @@ -1603,7 +1602,6 @@ int LinesManager::characterRoute(int fromX, int fromY, int destX, int destY, int int collLineIdxRoute1 = -1; int collLineIdxRoute2 = -1; - int distX, distY; int repeatFlag = 0; int collDataIdxRoute0 = 0; int collDataIdxRoute1 = 0; @@ -1615,8 +1613,8 @@ int LinesManager::characterRoute(int fromX, int fromY, int destX, int destY, int useRoute0(idxRoute0, curRouteIdx); return 1; } - distX = abs(curX - destX) + 1; - distY = abs(curY - destY) + 1; + int distX = abs(curX - destX) + 1; + int distY = abs(curY - destY) + 1; int maxDist; if (distX > distY) maxDist = distX; @@ -1912,7 +1910,7 @@ int LinesManager::characterRoute(int fromX, int fromY, int destX, int destY, int posXRoute2 = _newPosX; posYRoute2 = _newPosY; - colResult = checkCollisionLine(_newPosX, _newPosY, &collDataIdxRoute2, &collLineIdxRoute2, 0, _lastLine); + bool colResult = checkCollisionLine(_newPosX, _newPosY, &collDataIdxRoute2, &collLineIdxRoute2, 0, _lastLine); if (colResult && collLineIdxRoute2 <= _lastLine) break; } @@ -2456,13 +2454,12 @@ bool LinesManager::PLAN_TEST(int paramX, int paramY, int superRouteIdx, int para int LinesManager::testLine(int paramX, int paramY, int *testValue, int *foundLineIdx, int *foundDataIdx) { debugC(5, kDebugPath, "testLine(%d, %d, testValue, foundLineIdx, foundDataIdx)", paramX, paramY); int16 *lineData; - int lineDataEndIdx; int collLineIdx; int collDataIdx; for (int idx = _lastLine + 1; idx < _linesNumb + 1; idx++) { lineData = _lineItem[idx]._lineData; - lineDataEndIdx = _lineItem[idx]._lineDataEndIdx; + int lineDataEndIdx = _lineItem[idx]._lineDataEndIdx; if (!lineData) continue; diff --git a/engines/hopkins/objects.cpp b/engines/hopkins/objects.cpp index 347a6aabe8..2c780dd428 100644 --- a/engines/hopkins/objects.cpp +++ b/engines/hopkins/objects.cpp @@ -376,7 +376,6 @@ void ObjectsManager::addObject(int objIndex) { void ObjectsManager::displaySprite() { int clipX; int clipY; - bool loopCondFl; uint16 arr[50]; // Handle copying any background areas that text are going to be drawn on @@ -441,6 +440,7 @@ void ObjectsManager::displaySprite() { for (int i = 1; i <= 48; i++) arr[i] = i; + bool loopCondFl; do { loopCondFl = false; for (int sortIdx = 1; sortIdx < _sortedDisplayCount; sortIdx++) { @@ -3613,12 +3613,10 @@ void ObjectsManager::showSpecialActionAnimation(const byte *spriteData, const Co realSpeed = speed / 3; int spriteIndex = 0; - bool completeTokenFl; - char nextChar; for (int idx = 0; ; idx++) { - completeTokenFl = false; - nextChar = animString[idx]; + bool completeTokenFl = false; + char nextChar = animString[idx]; if (nextChar == ',') { spriteIndex = atoi(tmpStr.c_str()); tmpStr = ""; diff --git a/engines/hopkins/sound.cpp b/engines/hopkins/sound.cpp index 92c5f51462..704ebe3349 100644 --- a/engines/hopkins/sound.cpp +++ b/engines/hopkins/sound.cpp @@ -200,14 +200,6 @@ SoundManager::SoundManager(HopkinsEngine *vm) { _currentSoundIndex = 0; _oldSoundNumber = 0; _modPlayingFl = false; - - for (int i = 0; i < VOICE_COUNT; ++i) - Common::fill((byte *)&_voice[i], (byte *)&_voice[i] + sizeof(VoiceItem), 0); - for (int i = 0; i < SWAV_COUNT; ++i) - Common::fill((byte *)&_sWav[i], (byte *)&_sWav[i] + sizeof(SwavItem), 0); - for (int i = 0; i < SOUND_COUNT; ++i) - Common::fill((byte *)&_sound[i], (byte *)&_sound[i] + sizeof(SoundItem), 0); - Common::fill((byte *)&_music, (byte *)&_music + sizeof(MusicItem), 0); } SoundManager::~SoundManager() { diff --git a/engines/hopkins/sound.h b/engines/hopkins/sound.h index f1d047ae8b..6ebb6fdb02 100644 --- a/engines/hopkins/sound.h +++ b/engines/hopkins/sound.h @@ -33,12 +33,16 @@ namespace Hopkins { class VoiceItem { public: + VoiceItem() : _status(false), _wavIndex(0) {} + bool _status; int _wavIndex; }; class SwavItem { public: + SwavItem() : _active(false), _audioStream(NULL), _freeSampleFl(false) {} + bool _active; Audio::RewindableAudioStream *_audioStream; Audio::SoundHandle _soundHandle; @@ -47,11 +51,15 @@ public: class MusicItem { public: + MusicItem() : _active(false) {} + bool _active; }; class SoundItem { public: + SoundItem() : _active(false) {} + bool _active; }; diff --git a/engines/hopkins/talk.cpp b/engines/hopkins/talk.cpp index c80ea15554..b6faf8b6fe 100644 --- a/engines/hopkins/talk.cpp +++ b/engines/hopkins/talk.cpp @@ -613,7 +613,6 @@ void TalkManager::displayBobDialogAnim(int idx) { _vm->_objectsMan->_bob[idx]._flipFl = false; _vm->_objectsMan->_bob[idx]._animData = _vm->_animMan->_animBqe[idx]._data; _vm->_objectsMan->_bob[idx]._bobMode = 10; - bqeData = _characterSprite; _vm->_objectsMan->_bob[idx]._spriteData = _characterSprite; _vm->_objectsMan->_bob[idx]._bobModeChange = newMode; _vm->_objectsMan->_bob[idx]._modeChangeCtr = -1; diff --git a/engines/hugo/detection.cpp b/engines/hugo/detection.cpp index ede4ab2279..ee41fe33f2 100644 --- a/engines/hugo/detection.cpp +++ b/engines/hugo/detection.cpp @@ -184,13 +184,12 @@ SaveStateList HugoMetaEngine::listSaves(const char *target) const { SaveStateList saveList; char slot[3]; - int slotNum = 0; for (Common::StringArray::const_iterator filename = filenames.begin(); filename != filenames.end(); ++filename) { slot[0] = filename->c_str()[filename->size() - 6]; slot[1] = filename->c_str()[filename->size() - 5]; slot[2] = '\0'; // Obtain the last 2 digits of the filename (without extension), since they correspond to the save slot - slotNum = atoi(slot); + int slotNum = atoi(slot); if (slotNum >= 0 && slotNum <= getMaximumSaveSlot()) { Common::InSaveFile *file = saveFileMan->openForLoading(*filename); if (file) { diff --git a/engines/hugo/dialogs.cpp b/engines/hugo/dialogs.cpp index 23e04dc479..333c14778d 100644 --- a/engines/hugo/dialogs.cpp +++ b/engines/hugo/dialogs.cpp @@ -107,7 +107,6 @@ void TopMenu::reflowLayout() { x += kButtonWidth + kButtonPad; _inventButton->resize(x * scale, y * scale, kButtonWidth * scale, kButtonHeight * scale); - x += kButtonWidth + kButtonPad; // Set the graphics to the 'on' buttons, except for the variable ones _whatButton->setGfx(_arrayBmp[4 * kMenuWhat + scale - 1]); diff --git a/engines/hugo/mouse.cpp b/engines/hugo/mouse.cpp index 4ef3db3e2b..4b874756a0 100644 --- a/engines/hugo/mouse.cpp +++ b/engines/hugo/mouse.cpp @@ -160,7 +160,6 @@ void MouseHandler::processRightClick(const int16 objId, const int16 cx, const in return; int16 inventObjId = _vm->_inventory->getInventoryObjId(); - bool foundFl = false; // TRUE if route found to object // Check if this was over iconbar if ((_vm->_inventory->getInventoryState() == kInventoryActive) && (cy < kInvDy + kDibOffY)) { // Clicked over iconbar object if (inventObjId == -1) @@ -172,12 +171,14 @@ void MouseHandler::processRightClick(const int16 objId, const int16 cx, const in } else { // Clicked over viewport object Object *obj = &_vm->_object->_objects[objId]; int16 x, y; - switch (obj->_viewx) { // Where to walk to - case -1: // Walk to object position + switch (obj->_viewx) { // Where to walk to + case -1: { // Walk to object position + bool foundFl = false; if (_vm->_object->findObjectSpace(obj, &x, &y)) - foundFl = _vm->_route->startRoute(kRouteGet, objId, x, y); + foundFl = _vm->_route->startRoute(kRouteGet, objId, x, y); // TRUE if route found to object if (!foundFl) // Can't get there, try to use from here _vm->_object->useObject(objId); + } break; case 0: // Immediate use _vm->_object->useObject(objId); // Pick up or use object diff --git a/engines/hugo/object.cpp b/engines/hugo/object.cpp index 44f46d2d79..315214c5a4 100644 --- a/engines/hugo/object.cpp +++ b/engines/hugo/object.cpp @@ -134,19 +134,19 @@ void ObjectHandler::restoreSeq(Object *obj) { void ObjectHandler::useObject(int16 objId) { debugC(1, kDebugObject, "useObject(%d)", objId); - const char *verb; // Background verb to use directly int16 inventObjId = _vm->_inventory->getInventoryObjId(); - Object *obj = &_objects[objId]; // Ptr to object + Object *obj = &_objects[objId]; // Ptr to object if (inventObjId == -1) { + const char *verb; // Background verb to use directly // Get or use objid directly if ((obj->_genericCmd & TAKE) || obj->_objValue) // Get collectible item sprintf(_vm->_line, "%s %s", _vm->_text->getVerb(_vm->_take, 0), _vm->_text->getNoun(obj->_nounIndex, 0)); - else if (obj->_cmdIndex != 0) // Use non-collectible item if able + else if (obj->_cmdIndex != 0) // Use non-collectible item if able sprintf(_vm->_line, "%s %s", _vm->_text->getVerb(_vm->_parser->getCmdDefaultVerbIdx(obj->_cmdIndex), 0), _vm->_text->getNoun(obj->_nounIndex, 0)); else if ((verb = _vm->_parser->useBG(_vm->_text->getNoun(obj->_nounIndex, 0))) != 0) sprintf(_vm->_line, "%s %s", verb, _vm->_text->getNoun(obj->_nounIndex, 0)); else - return; // Can't use object directly + return; // Can't use object directly } else { // Use status.objid on objid // Default to first cmd verb @@ -540,10 +540,8 @@ void ObjectHandler::setCarriedScreen(int screenNum) { * Load _numObj from Hugo.dat */ void ObjectHandler::loadNumObj(Common::ReadStream &in) { - int numElem; - for (int varnt = 0; varnt < _vm->_numVariant; varnt++) { - numElem = in.readUint16BE(); + int numElem = in.readUint16BE(); if (varnt == _vm->_gameVariant) _numObj = numElem; } diff --git a/engines/hugo/route.cpp b/engines/hugo/route.cpp index dc3c41de9c..c4ffa6c7ca 100644 --- a/engines/hugo/route.cpp +++ b/engines/hugo/route.cpp @@ -384,9 +384,9 @@ bool Route::findRoute(const int16 cx, const int16 cy) { _segment[_segmentNumb]._x2 = herox2; _segmentNumb++; - Common::Point *routeNode; // Ptr to route node // Look in segments[] for straight lines from destination to hero for (i = 0, _routeListIndex = 0; i < _segmentNumb - 1; i++) { + Common::Point *routeNode; // Ptr to route node if ((routeNode = newNode()) == 0) // New node for new segment return false; // Too many nodes routeNode->y = _segment[i]._y; @@ -438,7 +438,7 @@ bool Route::findRoute(const int16 cx, const int16 cy) { void Route::processRoute() { debugC(1, kDebugRoute, "processRoute"); - static bool turnedFl = false; // Used to get extra cylce for turning + static bool turnedFl = false; // Used to get extra cycle for turning if (_routeIndex < 0) return; diff --git a/engines/hugo/schedule.cpp b/engines/hugo/schedule.cpp index 17ffa9d391..e8359bfdfc 100644 --- a/engines/hugo/schedule.cpp +++ b/engines/hugo/schedule.cpp @@ -254,9 +254,8 @@ void Scheduler::waitForRefresh() { void Scheduler::loadAlNewscrIndex(Common::ReadStream &in) { debugC(6, kDebugSchedule, "loadAlNewscrIndex(&in)"); - int numElem; for (int varnt = 0; varnt < _vm->_numVariant; varnt++) { - numElem = in.readUint16BE(); + int numElem = in.readUint16BE(); if (varnt == _vm->_gameVariant) _alNewscrIndex = numElem; } @@ -568,9 +567,9 @@ void Scheduler::loadActListArr(Common::ReadStream &in) { Act tmpAct; - int numElem, numSubElem; + int numSubElem; for (int varnt = 0; varnt < _vm->_numVariant; varnt++) { - numElem = in.readUint16BE(); + int numElem = in.readUint16BE(); if (varnt == _vm->_gameVariant) { _actListArrSize = numElem; _actListArr = (Act **)malloc(sizeof(Act *) * _actListArrSize); @@ -1214,8 +1213,6 @@ Event *Scheduler::doAction(Event *curEvent) { Act *action = curEvent->_action; Object *obj1; int dx, dy; - Event *wrkEvent; // Save ev_p->nextEvent for return - switch (action->_a0._actType) { case ANULL: // Big NOP from DEL_EVENTS break; @@ -1444,7 +1441,7 @@ Event *Scheduler::doAction(Event *curEvent) { if (action->_a0._actType == NEW_SCREEN) { // New_screen() deletes entire list return nullptr; // nextEvent = nullptr since list now empty } else { - wrkEvent = curEvent->_nextEvent; + Event *wrkEvent = curEvent->_nextEvent; delQueue(curEvent); // Return event to free list return wrkEvent; // Return next event ptr } @@ -1601,10 +1598,9 @@ void Scheduler_v2d::promptAction(Act *action) { debug(1, "doAction(act3), expecting answer %s", _vm->_file->fetchString(action->_a3._responsePtr[0])); bool found = false; - const char *tmpStr; // General purpose string ptr for (int dx = 0; !found && (action->_a3._responsePtr[dx] != -1); dx++) { - tmpStr = _vm->_file->fetchString(action->_a3._responsePtr[dx]); + const char *tmpStr = _vm->_file->fetchString(action->_a3._responsePtr[dx]); if (response.contains(tmpStr)) found = true; } diff --git a/engines/hugo/text.cpp b/engines/hugo/text.cpp index 538a0341e2..5e7505744c 100644 --- a/engines/hugo/text.cpp +++ b/engines/hugo/text.cpp @@ -91,16 +91,14 @@ char **TextHandler::getVerbArray(int idx1) const { } char **TextHandler::loadTextsVariante(Common::ReadStream &in, uint16 *arraySize) { - int numTexts; - int entryLen; int len; char **res = nullptr; char *pos = nullptr; char *posBck = nullptr; for (int varnt = 0; varnt < _vm->_numVariant; varnt++) { - numTexts = in.readUint16BE(); - entryLen = in.readUint16BE(); + int numTexts = in.readUint16BE(); + int entryLen = in.readUint16BE(); pos = (char *)malloc(entryLen); if (varnt == _vm->_gameVariant) { if (arraySize) diff --git a/engines/kyra/sequences_hof.cpp b/engines/kyra/sequences_hof.cpp index 9fcce4eb55..776a3e50b0 100644 --- a/engines/kyra/sequences_hof.cpp +++ b/engines/kyra/sequences_hof.cpp @@ -1651,7 +1651,7 @@ void SeqPlayer_HOF::displayHoFTalkieScrollText(uint8 *data, const ScreenDim *d, textData[1].text += strlen((char *)textData[1].text); textData[1].text[0] = textData[1].unk1; cnt--; - memcpy(&textData[1], &textData[2], cnt * sizeof(ScrollTextData)); + memmove(&textData[1], &textData[2], cnt * sizeof(ScrollTextData)); } if (palCycle) { diff --git a/engines/kyra/timer_eob.cpp b/engines/kyra/timer_eob.cpp index f7a4e23006..95eb4f3080 100644 --- a/engines/kyra/timer_eob.cpp +++ b/engines/kyra/timer_eob.cpp @@ -347,7 +347,7 @@ void EoBCoreEngine::timerUpdateFoodStatus(int timerNum) { } void EoBCoreEngine::timerUpdateMonsterIdleAnim(int timerNum) { - for (int i = 0; i < 18; i++) { + for (int i = 0; i < 30; i++) { EoBMonsterInPlay *m = &_monsters[i]; if (m->mode == 7 || m->mode == 10 || (m->flags & 0x20) || (rollDice(1, 2, 0) != 1)) continue; diff --git a/engines/mortevielle/actions.cpp b/engines/mortevielle/actions.cpp index c5d55066ba..e13220d248 100644 --- a/engines/mortevielle/actions.cpp +++ b/engines/mortevielle/actions.cpp @@ -481,13 +481,24 @@ void MortevielleEngine::fctLook() { } return; } + int cx = _coreVar._currPlace; - if (_coreVar._currPlace == CHAPEL) + switch (_coreVar._currPlace) { + case CHAPEL: cx = 17; - if ((_coreVar._currPlace > MANOR_FRONT) && (_coreVar._currPlace < DOOR)) + break; + case MANOR_BACK: + case INSIDE_WELL: + case WELL: cx -= 4; - if (_coreVar._currPlace == ROOM26) + break; + case ROOM26: cx = 21; + break; + default: + break; + } + _crep = _tabdon[kArega + (cx * 7) + _num - 1]; if ((_coreVar._currPlace == ATTIC) && (_num == 8)) _crep = 126; diff --git a/engines/mortevielle/dialogs.cpp b/engines/mortevielle/dialogs.cpp index 09a4227cc0..1ab2af7008 100644 --- a/engines/mortevielle/dialogs.cpp +++ b/engines/mortevielle/dialogs.cpp @@ -292,7 +292,7 @@ bool DialogManager::showKnowledgeCheck() { Common::String choiceArray[15]; - int currChoice, prevChoice; + int currChoice; int correctCount = 0; for (int indx = 0; indx < 10; ++indx) { @@ -317,7 +317,7 @@ bool DialogManager::showKnowledgeCheck() { int optionPosY = 35; int maxLength = 0; - prevChoice = 1; + int prevChoice = 1; for (int j = firstOption; j <= lastOption; ++j, ++prevChoice) { tmpStr = _vm->getString(j); if ((int) tmpStr.size() > maxLength) diff --git a/engines/mortevielle/mouse.cpp b/engines/mortevielle/mouse.cpp index 2077a4cdc5..d71934ad1a 100644 --- a/engines/mortevielle/mouse.cpp +++ b/engines/mortevielle/mouse.cpp @@ -97,15 +97,13 @@ void MouseHandler::getMousePosition(int &x, int &y, bool &click) { * @remarks Originally called 'mov_mouse' */ void MouseHandler::moveMouse(bool &funct, char &key) { - bool p_key; - char in1, in2; int cx, cy; bool click; // Set defaults and check pending events funct = false; key = '\377'; - p_key = _vm->keyPressed(); + bool p_key = _vm->keyPressed(); // If mouse button clicked, return it if (_vm->getMouseClick()) @@ -116,7 +114,7 @@ void MouseHandler::moveMouse(bool &funct, char &key) { if (_vm->shouldQuit()) return; - in1 = _vm->getChar(); + char in1 = _vm->getChar(); getMousePosition(cx, cy, click); switch (toupper(in1)) { case '4': @@ -160,7 +158,7 @@ void MouseHandler::moveMouse(bool &funct, char &key) { p_key = _vm->keyPressed(); if (p_key) { - in2 = _vm->getChar(); + char in2 = _vm->getChar(); if ((in2 >= ';') && (in2 <= 'D')) { funct = true; diff --git a/engines/mortevielle/sound.cpp b/engines/mortevielle/sound.cpp index db1f7578f1..1270eeb63e 100644 --- a/engines/mortevielle/sound.cpp +++ b/engines/mortevielle/sound.cpp @@ -91,13 +91,12 @@ int SoundManager::decodeMusic(const byte *PSrc, byte *PDest, int size) { static const int tab[16] = { -96, -72, -48, -32, -20, -12, -8, -4, 0, 4, 8, 12, 20, 32, 48, 72 }; uint seed = 128; - int v; int decompSize = 0; int skipSize = 0; for (int idx1 = 0; idx1 < size; ++idx1) { byte srcByte = *PSrc++; - v = tab[srcByte >> 4]; + int v = tab[srcByte >> 4]; seed += v; *PDest++ = seed & 0xff; diff --git a/engines/mortevielle/utils.cpp b/engines/mortevielle/utils.cpp index 29c9be2e0c..d24585a677 100644 --- a/engines/mortevielle/utils.cpp +++ b/engines/mortevielle/utils.cpp @@ -258,7 +258,6 @@ void MortevielleEngine::handleAction() { clearVerbBar(); - bool handledOpcodeFl = false; _controlMenu = 0; if (!_keyPressedEsc) { _menu->drawMenu(); @@ -319,6 +318,7 @@ void MortevielleEngine::handleAction() { _menuOpcode = _currMenu; if ((_currMenu == MENU_ACTION) || (_currMenu == MENU_SELF)) _menuOpcode = _currAction; + bool handledOpcodeFl = false; if (!_anyone) { if ((_heroSearching) || (_obpart)) { if (_mouse->_pos.y < 12) diff --git a/engines/pegasus/neighborhood/tsa/fulltsa.cpp b/engines/pegasus/neighborhood/tsa/fulltsa.cpp index 99efe10272..75f652ad56 100644 --- a/engines/pegasus/neighborhood/tsa/fulltsa.cpp +++ b/engines/pegasus/neighborhood/tsa/fulltsa.cpp @@ -2691,16 +2691,18 @@ void FullTSA::receiveNotification(Notification *notification, const Notification } break; case kTSA37DownloadToOpMemReview: - switch (GameState.getTSAState()) { - case kPlayerOnWayToNorad: - g_opticalChip->playOpMemMovie(kPoseidonSpotID); - break; - case kPlayerOnWayToMars: - g_opticalChip->playOpMemMovie(kAriesSpotID); - break; - case kPlayerOnWayToWSC: - g_opticalChip->playOpMemMovie(kMercurySpotID); - break; + if (_vm->itemInBiochips(kOpticalBiochip)) { + switch (GameState.getTSAState()) { + case kPlayerOnWayToNorad: + g_opticalChip->playOpMemMovie(kPoseidonSpotID); + break; + case kPlayerOnWayToMars: + g_opticalChip->playOpMemMovie(kAriesSpotID); + break; + case kPlayerOnWayToWSC: + g_opticalChip->playOpMemMovie(kMercurySpotID); + break; + } } if (GameState.allTimeZonesFinished()) { diff --git a/engines/pegasus/neighborhood/tsa/tinytsa.cpp b/engines/pegasus/neighborhood/tsa/tinytsa.cpp index 0d11f5d904..0326c7f2ee 100644 --- a/engines/pegasus/neighborhood/tsa/tinytsa.cpp +++ b/engines/pegasus/neighborhood/tsa/tinytsa.cpp @@ -372,16 +372,18 @@ void TinyTSA::receiveNotification(Notification *notification, const Notification } break; case kTinyTSA37DownloadToOpMemReview: - switch (GameState.getTSAState()) { - case kPlayerOnWayToNorad: - g_opticalChip->playOpMemMovie(kPoseidonSpotID); - break; - case kPlayerOnWayToMars: - g_opticalChip->playOpMemMovie(kAriesSpotID); - break; - case kPlayerOnWayToWSC: - g_opticalChip->playOpMemMovie(kMercurySpotID); - break; + if (_vm->itemInBiochips(kOpticalBiochip)) { + switch (GameState.getTSAState()) { + case kPlayerOnWayToNorad: + g_opticalChip->playOpMemMovie(kPoseidonSpotID); + break; + case kPlayerOnWayToMars: + g_opticalChip->playOpMemMovie(kAriesSpotID); + break; + case kPlayerOnWayToWSC: + g_opticalChip->playOpMemMovie(kMercurySpotID); + break; + } } requestExtraSequence(kTinyTSA37OpMemReviewToMainMenu, kExtraCompletedFlag, kFilterNoInput); diff --git a/engines/queen/detection.cpp b/engines/queen/detection.cpp new file mode 100644 index 0000000000..57b314c088 --- /dev/null +++ b/engines/queen/detection.cpp @@ -0,0 +1,512 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "base/plugins.h" + +#include "engines/advancedDetector.h" + +#include "common/config-manager.h" +#include "common/file.h" +#include "common/gui_options.h" +#include "common/savefile.h" +#include "common/system.h" +#include "common/translation.h" + +#include "queen/queen.h" +#include "queen/resource.h" + +namespace Queen { + +struct QueenGameDescription { + ADGameDescription desc; +}; + +} // End of namespace Queen + +static const PlainGameDescriptor queenGames[] = { + {"queen", "Flight of the Amazon Queen"}, + {0, 0} +}; + +#define GAMEOPTION_ALT_INTRO GUIO_GAMEOPTIONS1 + +static const ADExtraGuiOptionsMap optionsList[] = { + { + GAMEOPTION_ALT_INTRO, + { + _s("Alternative intro"), + _s("Use an alternative game intro (CD version only)"), + "alt_intro", + false + } + }, + + AD_EXTRA_GUI_OPTIONS_TERMINATOR +}; + +namespace Queen { + +static const QueenGameDescription gameDescriptions[] = { + // Amiga Demo - English + { + { + "queen", + "Demo", + AD_ENTRY1s("queen.1", "f7a1a37ac93bf763b1569231237cb4d8", 563335), + Common::EN_ANY, + Common::kPlatformAmiga, + ADGF_DEMO, + GUIO1(GUIO_NOSPEECH) + }, + }, + + // Amiga Interview Demo - English + { + { + "queen", + "Interview", + AD_ENTRY1s("queen.1", "f5d42a18d8f5689480413871410663d7", 597032), + Common::EN_ANY, + Common::kPlatformAmiga, + ADGF_DEMO, + GUIO1(GUIO_NOSPEECH) + }, + }, + + // DOS Demo - English + { + { + "queen", + "Demo", + AD_ENTRY1s("queen.1", "f39334d8133840aa3bcbd733c12937cf", 3732177), + Common::EN_ANY, + Common::kPlatformDOS, + ADGF_DEMO, + GUIO1(GUIO_NOSPEECH) + }, + }, + + // DOS Interview Demo - English + { + { + "queen", + "Interview", + AD_ENTRY1s("queen.1", "30b3291f37665bf24d9482b183cb2f67", 1915913), + Common::EN_ANY, + Common::kPlatformDOS, + ADGF_DEMO, + GUIO1(GUIO_NOSPEECH) + }, + }, + + // PCGAMES DOS Demo - English + { + { + "queen", + "Demo", + AD_ENTRY1s("queen.1", "f39334d8133840aa3bcbd733c12937cf", 3724538), + Common::EN_ANY, + Common::kPlatformDOS, + ADGF_DEMO, + GUIO1(GUIO_NOSPEECH) + }, + }, + +#if 0 + // Amiga Floppy - English + { + { + "queen", + "Floppy", + AD_ENTRY1s("queen.1", NULL, 351775), // TODO: Fill in correct MD5 + Common::EN_ANY, + Common::kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO1(GUIO_NOSPEECH) + }, + }, +#endif + + // DOS Floppy - English + { + { + "queen", + "Floppy", + AD_ENTRY1s("queen.1", "f5e827645d3c887be3bdf4729d847756", 22677657), + Common::EN_ANY, + Common::kPlatformDOS, + ADGF_NO_FLAGS, + GUIO1(GUIO_NOSPEECH) + }, + }, + + // DOS CD - English + { + { + "queen", + "Talkie", + AD_ENTRY1s("queen.1", "b6302bccf70463de3d5faf0f0628f742", 190787021), + Common::EN_ANY, + Common::kPlatformDOS, + ADGF_NO_FLAGS, + GUIO1(GAMEOPTION_ALT_INTRO) + }, + }, + +#if 0 + // DOS Floppy - French + { + { + "queen", + "Floppy", + AD_ENTRY1s("queen.1", NULL, 22157304), // TODO: Fill in correct MD5 + Common::FR_FRA, + Common::kPlatformDOS, + ADGF_NO_FLAGS, + GUIO1(GUIO_NOSPEECH) + }, + }, +#endif + +#if 0 + // DOS CD - French + { + { + "queen", + "Talkie", + AD_ENTRY1s("queen.1", NULL, 186689095), // TODO: Fill in correct MD5 + Common::FR_FRA, + Common::kPlatformDOS, + ADGF_NO_FLAGS, + GUIO1(GAMEOPTION_ALT_INTRO) + }, + }, +#endif + +#if 0 + // DOS Floppy - German + { + { + "queen", + "Floppy", + AD_ENTRY1s("queen.1", NULL, 22240013), // TODO: Fill in correct MD5 + Common::DE_DEU, + Common::kPlatformDOS, + ADGF_NO_FLAGS, + GUIO1(GUIO_NOSPEECH) + }, + }, +#endif + +#if 0 + // DOS CD - German + { + { + "queen", + "Talkie", + AD_ENTRY1s("queen.1", NULL, 217648975), // TODO: Fill in correct MD5 + Common::DE_DEU, + Common::kPlatformDOS, + ADGF_NO_FLAGS, + GUIO1(GAMEOPTION_ALT_INTRO) + }, + }, +#endif + +#if 0 + // DOS CD - Hebrew + { + { + "queen", + "Talkie", + AD_ENTRY1s("queen.1", NULL, 190705558), // TODO: Fill in correct MD5 + Common::HE_ISR, + Common::kPlatformDOS, + ADGF_NO_FLAGS, + GUIO1(GAMEOPTION_ALT_INTRO) + }, + }, +#endif + +#if 0 + // DOS Floppy - Italian + { + { + "queen", + "Floppy", + AD_ENTRY1s("queen.1", NULL, 22461366), // TODO: Fill in correct MD5 + Common::IT_ITA, + Common::kPlatformDOS, + ADGF_NO_FLAGS, + GUIO1(GUIO_NOSPEECH) + }, + }, +#endif + + // DOS CD - Italian + { + { + "queen", + "Talkie", + AD_ENTRY1s("queen.1", "b6302bccf70463de3d5faf0f0628f742", 190795582), + Common::IT_ITA, + Common::kPlatformDOS, + ADGF_NO_FLAGS, + GUIO1(GAMEOPTION_ALT_INTRO) + }, + }, + +#if 0 + // DOS CD - Spanish + { + { + "queen", + "Talkie", + AD_ENTRY1s("queen.1", NULL, 190730602), // TODO: Fill in correct MD5 + Common::ES_ESP, + Common::kPlatformDOS, + ADGF_NO_FLAGS, + GUIO1(GAMEOPTION_ALT_INTRO) + }, + }, +#endif + + // DOS CD - English (Compressed Freeware Release v1.0) + { + { + "queen", + "Talkie", + AD_ENTRY1s("queen.1c", "a0749bb8b72e537ead1a63a3dde1443d", 54108887), + Common::EN_ANY, + Common::kPlatformDOS, + ADGF_NO_FLAGS, + GUIO1(GAMEOPTION_ALT_INTRO) + }, + }, + + // DOS CD - English (Compressed Freeware Release v1.1) + { + { + "queen", + "Talkie", + AD_ENTRY1s("queen.1c", "21fd690b372f8a6289f6f33bc986276c", 51222412), + Common::EN_ANY, + Common::kPlatformDOS, + ADGF_NO_FLAGS, + GUIO1(GAMEOPTION_ALT_INTRO) + }, + }, + + // DOS CD - French (Compressed Freeware Release v1.0) + { + { + "queen", + "Talkie", + AD_ENTRY1s("queen.1c", "67e3020f8a35e1df7b1c753b5aaa71e1", 97382620), + Common::FR_FRA, + Common::kPlatformDOS, + ADGF_NO_FLAGS, + GUIO1(GAMEOPTION_ALT_INTRO) + }, + }, + + // DOS CD - German (Compressed Freeware Release v1.0) + { + { + "queen", + "Talkie", + AD_ENTRY1s("queen.1c", "28f78dbec7e20f603a10c2f8ea889a5c", 108738717), + Common::DE_DEU, + Common::kPlatformDOS, + ADGF_NO_FLAGS, + GUIO1(GAMEOPTION_ALT_INTRO) + }, + }, + + // DOS CD - Hebrew (Compressed Freeware Release v1.0) + { + { + "queen", + "Talkie", + AD_ENTRY1s("queen.1c", "4d52d8780613ef27a2b779caecb20a21", 99391805), + Common::HE_ISR, + Common::kPlatformDOS, + ADGF_NO_FLAGS, + GUIO1(GAMEOPTION_ALT_INTRO) + }, + }, + + // DOS CD - Italian (Compressed Freeware Release v1.0) + { + { + "queen", + "Talkie", + AD_ENTRY1s("queen.1c", "2f72b715ed753cf905a37cdcc7ea611e", 98327801), + Common::IT_ITA, + Common::kPlatformDOS, + ADGF_NO_FLAGS, + GUIO1(GAMEOPTION_ALT_INTRO) + }, + }, + + // TODO: Freeware Release for Spanish DOS CD is missing. +#if 0 + // DOS CD - Spanish (Compressed Freeware Release v1.0) + { + { + "queen", + "Talkie", + AD_ENTRY1s("queen.1c", NULL, ?), + Common::ES_ESP, + Common::kPlatformDOS, + ADGF_NO_FLAGS, + GUIO1(GAMEOPTION_ALT_INTRO) + }, + }, +#endif + + { AD_TABLE_END_MARKER } +}; + +} // End of namespace Queen + +class QueenMetaEngine : public AdvancedMetaEngine { +public: + QueenMetaEngine() : AdvancedMetaEngine(Queen::gameDescriptions, sizeof(Queen::QueenGameDescription), queenGames, optionsList) { + _singleid = "queen"; + } + + virtual const char *getName() const { + return "Queen"; + } + + virtual const char *getOriginalCopyright() const { + return "Flight of the Amazon Queen (C) John Passfield and Steve Stamatiadis"; + } + + virtual bool hasFeature(MetaEngineFeature f) const; + virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const; + virtual SaveStateList listSaves(const char *target) const; + virtual int getMaximumSaveSlot() const { return 99; } + virtual void removeSaveState(const char *target, int slot) const; + + const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const; +}; + +bool QueenMetaEngine::hasFeature(MetaEngineFeature f) const { + return + (f == kSupportsListSaves) || + (f == kSupportsLoadingDuringStartup) || + (f == kSupportsDeleteSave); +} + +const ADGameDescription *QueenMetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const { + static ADGameDescription desc; + + // Iterate over all files in the given directory + for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) { + if (file->isDirectory()) { + continue; + } + if (file->getName().equalsIgnoreCase("queen.1") || file->getName().equalsIgnoreCase("queen.1c")) { + Common::File dataFile; + if (!dataFile.open(*file)) { + continue; + } + Queen::DetectedGameVersion version; + if (Queen::Resource::detectVersion(&version, &dataFile)) { + desc.gameid = "queen"; + desc.language = version.language; + desc.platform = version.platform; + desc.flags = ADGF_NO_FLAGS; + desc.guioptions = GUIO0(); + if (version.features & Queen::GF_DEMO) { + desc.extra = "Demo"; + desc.flags = ADGF_DEMO; + desc.guioptions = GUIO_NOSPEECH; + } else if (version.features & Queen::GF_INTERVIEW) { + desc.extra = "Interview"; + desc.flags = ADGF_DEMO; + desc.guioptions = GUIO_NOSPEECH; + } else if (version.features & Queen::GF_FLOPPY) { + desc.extra = "Floppy"; + desc.guioptions = GUIO_NOSPEECH; + } else if (version.features & Queen::GF_TALKIE) { + desc.extra = "Talkie"; + desc.guioptions = GAMEOPTION_ALT_INTRO; + } + return (const ADGameDescription *)&desc; + } + } + } + return 0; +} + +SaveStateList QueenMetaEngine::listSaves(const char *target) const { + Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); + Common::StringArray filenames; + char saveDesc[32]; + Common::String pattern("queen.s??"); + + filenames = saveFileMan->listSavefiles(pattern); + sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..) + + SaveStateList saveList; + for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) { + // Obtain the last 2 digits of the filename, since they correspond to the save slot + int slotNum = atoi(file->c_str() + file->size() - 2); + + if (slotNum >= 0 && slotNum <= 99) { + Common::InSaveFile *in = saveFileMan->openForLoading(*file); + if (in) { + for (int i = 0; i < 4; i++) + in->readUint32BE(); + in->read(saveDesc, 32); + saveList.push_back(SaveStateDescriptor(slotNum, saveDesc)); + delete in; + } + } + } + + return saveList; +} + +void QueenMetaEngine::removeSaveState(const char *target, int slot) const { + Common::String filename = Common::String::format("queen.s%02d", slot); + + g_system->getSavefileManager()->removeSavefile(filename); +} + +bool QueenMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const { + const Queen::QueenGameDescription *gd = (const Queen::QueenGameDescription *)desc; + + if (gd) + *engine = new Queen::QueenEngine(syst); //FIXME , gd); + + return (gd != 0); +} + +#if PLUGIN_ENABLED_DYNAMIC(QUEEN) + REGISTER_PLUGIN_DYNAMIC(QUEEN, PLUGIN_TYPE_ENGINE, QueenMetaEngine); +#else + REGISTER_PLUGIN_STATIC(QUEEN, PLUGIN_TYPE_ENGINE, QueenMetaEngine); +#endif diff --git a/engines/queen/module.mk b/engines/queen/module.mk index 5e0602cae7..8ba49a301d 100644 --- a/engines/queen/module.mk +++ b/engines/queen/module.mk @@ -6,6 +6,7 @@ MODULE_OBJS := \ credits.o \ cutaway.o \ debug.o \ + detection.o \ display.o \ graphics.o \ grid.o \ diff --git a/engines/queen/queen.cpp b/engines/queen/queen.cpp index 08fc594560..8d4db75cc1 100644 --- a/engines/queen/queen.cpp +++ b/engines/queen/queen.cpp @@ -23,14 +23,12 @@ #include "base/plugins.h" #include "common/config-manager.h" +#include "common/events.h" #include "common/file.h" #include "common/fs.h" -#include "common/gui_options.h" #include "common/savefile.h" #include "common/system.h" -#include "common/events.h" #include "common/textconsole.h" -#include "common/translation.h" #include "engines/util.h" @@ -49,177 +47,6 @@ #include "queen/talk.h" #include "queen/walk.h" -#include "engines/metaengine.h" - -static const PlainGameDescriptor queenGameDescriptor = { - "queen", "Flight of the Amazon Queen" -}; - -static const ExtraGuiOption queenExtraGuiOption = { - _s("Alternative intro"), - _s("Use an alternative game intro (CD version only)"), - "alt_intro", - false -}; - -class QueenMetaEngine : public MetaEngine { -public: - virtual const char *getName() const; - virtual const char *getOriginalCopyright() const; - - virtual bool hasFeature(MetaEngineFeature f) const; - virtual GameList getSupportedGames() const; - virtual const ExtraGuiOptions getExtraGuiOptions(const Common::String &target) const; - virtual GameDescriptor findGame(const char *gameid) const; - virtual GameList detectGames(const Common::FSList &fslist) const; - virtual SaveStateList listSaves(const char *target) const; - virtual int getMaximumSaveSlot() const; - virtual void removeSaveState(const char *target, int slot) const; - - virtual Common::Error createInstance(OSystem *syst, Engine **engine) const; -}; - -const char *QueenMetaEngine::getName() const { - return "Queen"; -} - -const char *QueenMetaEngine::getOriginalCopyright() const { - return "Flight of the Amazon Queen (C) John Passfield and Steve Stamatiadis"; -} - -bool QueenMetaEngine::hasFeature(MetaEngineFeature f) const { - return - (f == kSupportsListSaves) || - (f == kSupportsLoadingDuringStartup) || - (f == kSupportsDeleteSave); -} - -bool Queen::QueenEngine::hasFeature(EngineFeature f) const { - return - (f == kSupportsRTL) || - (f == kSupportsLoadingDuringRuntime) || - (f == kSupportsSavingDuringRuntime) || - (f == kSupportsSubtitleOptions); -} - -GameList QueenMetaEngine::getSupportedGames() const { - GameList games; - games.push_back(queenGameDescriptor); - return games; -} - -int QueenMetaEngine::getMaximumSaveSlot() const { return 99; } - -const ExtraGuiOptions QueenMetaEngine::getExtraGuiOptions(const Common::String &target) const { - Common::String guiOptions; - ExtraGuiOptions options; - - if (target.empty()) { - options.push_back(queenExtraGuiOption); - return options; - } - - if (ConfMan.hasKey("guioptions", target)) { - guiOptions = ConfMan.get("guioptions", target); - guiOptions = parseGameGUIOptions(guiOptions); - } - - if (!guiOptions.contains(GUIO_NOSPEECH)) - options.push_back(queenExtraGuiOption); - return options; -} - -GameDescriptor QueenMetaEngine::findGame(const char *gameid) const { - if (0 == scumm_stricmp(gameid, queenGameDescriptor.gameid)) { - return queenGameDescriptor; - } - return GameDescriptor(); -} - -GameList QueenMetaEngine::detectGames(const Common::FSList &fslist) const { - GameList detectedGames; - - // Iterate over all files in the given directory - for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) { - if (file->isDirectory()) { - continue; - } - if (file->getName().equalsIgnoreCase("queen.1") || file->getName().equalsIgnoreCase("queen.1c")) { - Common::File dataFile; - if (!dataFile.open(*file)) { - continue; - } - Queen::DetectedGameVersion version; - if (Queen::Resource::detectVersion(&version, &dataFile)) { - GameDescriptor dg(queenGameDescriptor.gameid, queenGameDescriptor.description, version.language, version.platform); - if (version.features & Queen::GF_DEMO) { - dg.updateDesc("Demo"); - dg.setGUIOptions(GUIO_NOSPEECH); - } else if (version.features & Queen::GF_INTERVIEW) { - dg.updateDesc("Interview"); - dg.setGUIOptions(GUIO_NOSPEECH); - } else if (version.features & Queen::GF_FLOPPY) { - dg.updateDesc("Floppy"); - dg.setGUIOptions(GUIO_NOSPEECH); - } else if (version.features & Queen::GF_TALKIE) { - dg.updateDesc("Talkie"); - } - detectedGames.push_back(dg); - break; - } - } - } - return detectedGames; -} - -SaveStateList QueenMetaEngine::listSaves(const char *target) const { - Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); - Common::StringArray filenames; - char saveDesc[32]; - Common::String pattern("queen.s??"); - - filenames = saveFileMan->listSavefiles(pattern); - sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..) - - SaveStateList saveList; - for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) { - // Obtain the last 2 digits of the filename, since they correspond to the save slot - int slotNum = atoi(file->c_str() + file->size() - 2); - - if (slotNum >= 0 && slotNum <= 99) { - Common::InSaveFile *in = saveFileMan->openForLoading(*file); - if (in) { - for (int i = 0; i < 4; i++) - in->readUint32BE(); - in->read(saveDesc, 32); - saveList.push_back(SaveStateDescriptor(slotNum, saveDesc)); - delete in; - } - } - } - - return saveList; -} - -void QueenMetaEngine::removeSaveState(const char *target, int slot) const { - Common::String filename = target; - filename += Common::String::format(".s%02d", slot); - - g_system->getSavefileManager()->removeSavefile(filename); -} - -Common::Error QueenMetaEngine::createInstance(OSystem *syst, Engine **engine) const { - assert(engine); - *engine = new Queen::QueenEngine(syst); - return Common::kNoError; -} - -#if PLUGIN_ENABLED_DYNAMIC(QUEEN) - REGISTER_PLUGIN_DYNAMIC(QUEEN, PLUGIN_TYPE_ENGINE, QueenMetaEngine); -#else - REGISTER_PLUGIN_STATIC(QUEEN, PLUGIN_TYPE_ENGINE, QueenMetaEngine); -#endif - namespace Queen { QueenEngine::QueenEngine(OSystem *syst) @@ -488,6 +315,14 @@ GUI::Debugger *QueenEngine::getDebugger() { return _debugger; } +bool Queen::QueenEngine::hasFeature(EngineFeature f) const { + return + (f == kSupportsRTL) || + (f == kSupportsLoadingDuringRuntime) || + (f == kSupportsSavingDuringRuntime) || + (f == kSupportsSubtitleOptions); +} + Common::Error QueenEngine::run() { initGraphics(GAME_SCREEN_WIDTH, GAME_SCREEN_HEIGHT, false); diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index 0f0c8dcd66..d26a519233 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -252,7 +252,7 @@ Common::String SciEngine::getSciLanguageString(const Common::String &str, kLangu } } - if (seeker) + if (*seeker) return Common::String(str.c_str(), seeker - str.c_str()); else return str; diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 52155cd09a..3b3f3edb38 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -2264,15 +2264,6 @@ void ResourceManager::detectSciVersion() { s_sciVersion = SCI_VERSION_1_1; return; } - // FIXME: this is really difficult, lsl1 spanish has map/vol sci1late - // and the only current detection difference is movecounttype which - // is increment here, but ignore for all the regular sci1late games - // the problem is, we dont have access to that detection till later - // so maybe (part of?) that detection should get moved in here - if (g_sci && (g_sci->getGameId() == GID_LSL1) && (g_sci->getLanguage() == Common::ES_ESP)) { - s_sciVersion = SCI_VERSION_1_MIDDLE; - return; - } s_sciVersion = SCI_VERSION_1_LATE; return; case kResVersionSci11: diff --git a/engines/toon/toon.cpp b/engines/toon/toon.cpp index 7b1456b05c..72cf57af8a 100644 --- a/engines/toon/toon.cpp +++ b/engines/toon/toon.cpp @@ -184,10 +184,10 @@ void ToonEngine::parseInput() { Common::Event event; while (_event->pollEvent(event)) { - bool hasModifier = event.kbd.hasFlags(Common::KBD_ALT|Common::KBD_CTRL|Common::KBD_SHIFT); + const bool hasModifier = (event.kbd.flags & Common::KBD_NON_STICKY) != 0; switch (event.type) { case Common::EVENT_KEYDOWN: - if ((event.kbd.ascii == 27 || event.kbd.ascii == 32) && !hasModifier) { + if ((event.kbd.keycode == Common::KEYCODE_ESCAPE || event.kbd.keycode == Common::KEYCODE_SPACE) && !hasModifier) { _audioManager->stopCurrentVoice(); } if (event.kbd.keycode == Common::KEYCODE_F5 && !hasModifier) { @@ -198,21 +198,21 @@ void ToonEngine::parseInput() { if (canLoadGameStateCurrently()) loadGame(-1); } - if (event.kbd.ascii == 't' && !hasModifier) { + if (event.kbd.keycode == Common::KEYCODE_t && !hasModifier) { _showConversationText = !_showConversationText; } - if (event.kbd.ascii == 'm' && !hasModifier) { + if (event.kbd.keycode == Common::KEYCODE_m && !hasModifier) { _audioManager->muteMusic(!_audioManager->isMusicMuted()); } - if (event.kbd.ascii == 'd' && !hasModifier) { + if (event.kbd.keycode == Common::KEYCODE_d && !hasModifier) { _audioManager->muteVoice(!_audioManager->isVoiceMuted()); } - if (event.kbd.ascii == 's' && !hasModifier) { + if (event.kbd.keycode == Common::KEYCODE_s && !hasModifier) { _audioManager->muteSfx(!_audioManager->isSfxMuted()); } if (event.kbd.flags & Common::KBD_ALT) { - int slotNum = event.kbd.ascii - '0'; + int slotNum = event.kbd.keycode - (event.kbd.keycode >= Common::KEYCODE_KP0 ? Common::KEYCODE_KP0 : Common::KEYCODE_0); if (slotNum >= 0 && slotNum <= 9 && canSaveGameStateCurrently()) { if (saveGame(slotNum, "")) { // ok @@ -229,7 +229,7 @@ void ToonEngine::parseInput() { } if (event.kbd.flags & Common::KBD_CTRL) { - int slotNum = event.kbd.ascii - '0'; + int slotNum = event.kbd.keycode - (event.kbd.keycode >= Common::KEYCODE_KP0 ? Common::KEYCODE_KP0 : Common::KEYCODE_0); if (slotNum >= 0 && slotNum <= 9 && canLoadGameStateCurrently()) { if (loadGame(slotNum)) { // ok diff --git a/engines/touche/menu.cpp b/engines/touche/menu.cpp index 85ca519f05..045b594aed 100644 --- a/engines/touche/menu.cpp +++ b/engines/touche/menu.cpp @@ -569,29 +569,29 @@ int ToucheEngine::displayQuitDialog() { quitLoop = true; switch (_language) { case Common::FR_FRA: - if (event.kbd.ascii == 'o' || event.kbd.ascii == 'O') { + if (event.kbd.keycode == Common::KEYCODE_o) { ret = 1; } break; case Common::DE_DEU: - if (event.kbd.ascii == 'j' || event.kbd.ascii == 'J') { + if (event.kbd.keycode == Common::KEYCODE_j) { ret = 1; } break; case Common::ES_ESP: - if (event.kbd.ascii == 's' || event.kbd.ascii == 'S') { + if (event.kbd.keycode == Common::KEYCODE_s) { ret = 1; } break; case Common::PL_POL: - if (event.kbd.ascii == 's' || event.kbd.ascii == 'S' || event.kbd.ascii == 't' || event.kbd.ascii == 'T') { + if (event.kbd.keycode == Common::KEYCODE_s || event.kbd.keycode == Common::KEYCODE_t) { ret = 1; } break; default: // According to cyx, the Italian version uses the same // keys as the English one. - if (event.kbd.ascii == 'y' || event.kbd.ascii == 'Y') { + if (event.kbd.keycode == Common::KEYCODE_y) { ret = 1; } break; diff --git a/engines/touche/touche.cpp b/engines/touche/touche.cpp index b3e3ca5b50..eb7010a824 100644 --- a/engines/touche/touche.cpp +++ b/engines/touche/touche.cpp @@ -416,13 +416,13 @@ void ToucheEngine::processEvents(bool handleKeyEvents) { this->getDebugger()->onFrame(); } } else { - if (event.kbd.ascii == 't') { + if (event.kbd.keycode == Common::KEYCODE_t) { ++_talkTextMode; if (_talkTextMode == kTalkModeCount) { _talkTextMode = 0; } displayTextMode(-(92 + _talkTextMode)); - } else if (event.kbd.ascii == ' ') { + } else if (event.kbd.keycode == Common::KEYCODE_SPACE) { updateKeyCharTalk(2); } } diff --git a/engines/tsage/blue_force/blueforce_scenes3.cpp b/engines/tsage/blue_force/blueforce_scenes3.cpp index feaf789392..28005845d3 100644 --- a/engines/tsage/blue_force/blueforce_scenes3.cpp +++ b/engines/tsage/blue_force/blueforce_scenes3.cpp @@ -4438,7 +4438,7 @@ void Scene360::postInit(SceneObjectList *OwnerList) { BF_GLOBALS._player._moveDiff.y = 4; BF_GLOBALS._player.enableControl(); - if ((BF_GLOBALS._sceneManager._previousScene == 355) || (BF_GLOBALS._sceneManager._previousScene != 370)) { + if (BF_GLOBALS._sceneManager._previousScene != 370) { BF_GLOBALS._player.setPosition(Common::Point(253, 135)); BF_GLOBALS._player.setStrip(2); diff --git a/engines/tsage/blue_force/blueforce_scenes5.cpp b/engines/tsage/blue_force/blueforce_scenes5.cpp index 101a39c4b7..d3ea36a078 100644 --- a/engines/tsage/blue_force/blueforce_scenes5.cpp +++ b/engines/tsage/blue_force/blueforce_scenes5.cpp @@ -1623,7 +1623,7 @@ void Scene570::PasswordEntry::process(Event &event) { checkPassword(); remove(); - } else if ((key >= 32) || (key <= 126)) { + } else if ((key >= 32) && (key <= 126)) { // Valid character pressed if (_entryBuffer.size() < 10) _entryBuffer += (char)key; diff --git a/engines/tsage/blue_force/blueforce_scenes9.cpp b/engines/tsage/blue_force/blueforce_scenes9.cpp index 405a436f55..a3dd3688be 100644 --- a/engines/tsage/blue_force/blueforce_scenes9.cpp +++ b/engines/tsage/blue_force/blueforce_scenes9.cpp @@ -516,7 +516,7 @@ void Scene900::postInit(SceneObjectList *OwnerList) { _door.setPosition(Common::Point(847, 45)); _door._flag = 1; - if ((BF_GLOBALS._sceneManager._previousScene == 880) || (BF_GLOBALS._sceneManager._previousScene != 910)) { + if (BF_GLOBALS._sceneManager._previousScene != 910) { BF_GLOBALS._walkRegions.disableRegion(26); BF_GLOBALS._player.disableControl(); if (BF_GLOBALS._bookmark == bFinishedWGreen) { diff --git a/engines/tsage/core.cpp b/engines/tsage/core.cpp index 16fe45044b..ba14830add 100644 --- a/engines/tsage/core.cpp +++ b/engines/tsage/core.cpp @@ -1593,12 +1593,12 @@ bool SceneItem::startAction(CursorType action, Event &event) { } void SceneItem::doAction(int action) { - const char *msg = NULL; - if (g_vm->getGameID() == GType_Ringworld2) { Event dummyEvent; ((Ringworld2::SceneExt *)GLOBALS._sceneManager._scene)->display((CursorType)action, dummyEvent); } else { + const char *msg = NULL; + switch ((int)action) { case CURSOR_LOOK: msg = LOOK_SCENE_HOTSPOT; @@ -2909,7 +2909,6 @@ void BackgroundSceneObject::copySceneToBackground() { void SceneObjectList::draw() { Common::Array<SceneObject *> objList; int paneNum = 0; - int xAmount = 0, yAmount = 0; if (_objList.size() == 0) { // Alternate draw mode @@ -2936,6 +2935,7 @@ void SceneObjectList::draw() { g_globals->_scrollFollower->_position.x - g_globals->_sceneManager._scene->_sceneBounds.left, g_globals->_scrollFollower->_position.y - g_globals->_sceneManager._scene->_sceneBounds.top); int loadCount = 0; + int xAmount = 0, yAmount = 0; if (objPos.x >= scrollerRect.right) { xAmount = 8; diff --git a/engines/tsage/core.h b/engines/tsage/core.h index c285fba669..6e50cc8d2e 100644 --- a/engines/tsage/core.h +++ b/engines/tsage/core.h @@ -465,7 +465,7 @@ enum AnimateMode {ANIM_MODE_NONE = 0, ANIM_MODE_1 = 1, ANIM_MODE_2 = 2, ANIM_MOD }; // Actor effect enumeration used in Return to Ringworld 2 -enum Effect { EFFECT_NONE = 0, EFFECT_SHADED = 1, EFFECT_3 = 3, +enum Effect { EFFECT_NONE = 0, EFFECT_SHADED = 1, EFFECT_SMOKE = 3, EFFECT_SHADOW_MAP = 5, EFFECT_SHADED2 = 6 }; class SceneObject; diff --git a/engines/tsage/graphics.cpp b/engines/tsage/graphics.cpp index 97857aca34..eb7adbe53a 100644 --- a/engines/tsage/graphics.cpp +++ b/engines/tsage/graphics.cpp @@ -1483,7 +1483,6 @@ int GfxFont::getStringFit(const char *&s, int maxWidth) { const char *nextWord = NULL; const char *sStart = s; int numChars = 1; - int strWidth = 1; char nextChar; for (;;) { @@ -1497,7 +1496,7 @@ int GfxFont::getStringFit(const char *&s, int maxWidth) { nextWord = s; } - strWidth = getStringWidth(sStart, numChars); + int strWidth = getStringWidth(sStart, numChars); if (strWidth > maxWidth) { if (nextWord) { s = nextWord; diff --git a/engines/tsage/ringworld/ringworld_dialogs.cpp b/engines/tsage/ringworld/ringworld_dialogs.cpp index 4728e66cd9..d512806903 100644 --- a/engines/tsage/ringworld/ringworld_dialogs.cpp +++ b/engines/tsage/ringworld/ringworld_dialogs.cpp @@ -385,7 +385,6 @@ void InventoryDialog::execute() { if ((RING_INVENTORY._selectedItem) && RING_INVENTORY._selectedItem->inInventory()) RING_INVENTORY._selectedItem->setCursor(); - GfxElement *hiliteObj; bool lookFlag = false; _gfxManager.activate(); @@ -399,7 +398,7 @@ void InventoryDialog::execute() { if (g_vm->shouldQuit()) break; - hiliteObj = NULL; + GfxElement *hiliteObj = nullptr; if ((event.eventType == EVENT_BUTTON_DOWN) && !_bounds.contains(event.mousePos)) break; diff --git a/engines/tsage/ringworld/ringworld_scenes10.cpp b/engines/tsage/ringworld/ringworld_scenes10.cpp index eac181e350..116dca10e9 100644 --- a/engines/tsage/ringworld/ringworld_scenes10.cpp +++ b/engines/tsage/ringworld/ringworld_scenes10.cpp @@ -1217,7 +1217,7 @@ void Scene9500::postInit(SceneObjectList *OwnerList) { g_globals->_events.setCursor(CURSOR_WALK); g_globals->_player.disableControl(); - if ((g_globals->_sceneManager._previousScene == 9200) || (g_globals->_sceneManager._previousScene != 9850)) { + if (g_globals->_sceneManager._previousScene != 9850) { _sceneMode = 0; if (RING_INVENTORY._helmet._sceneNumber != 1) { setAction(&_sequenceManager, this, 9501, &g_globals->_player, &_candle, NULL); diff --git a/engines/tsage/ringworld/ringworld_scenes3.cpp b/engines/tsage/ringworld/ringworld_scenes3.cpp index e834e659b5..5f33652458 100644 --- a/engines/tsage/ringworld/ringworld_scenes3.cpp +++ b/engines/tsage/ringworld/ringworld_scenes3.cpp @@ -4946,8 +4946,6 @@ void Scene2310::synchronize(Serializer &s) { } void Scene2310::process(Event &event) { - int frameNum = 0; - if (!event.handled && (event.eventType == EVENT_BUTTON_DOWN)) { int idx = 0; while (idx < 5) { @@ -4961,7 +4959,7 @@ void Scene2310::process(Event &event) { if (_wireIndex == 5) { // No wire is currently active, so start moving designated wire _wireIndex = idx; - frameNum = idx + 2; + int frameNum = idx + 2; if (event.mousePos.y > 105) idx = findObject(idx); diff --git a/engines/tsage/ringworld2/ringworld2_dialogs.cpp b/engines/tsage/ringworld2/ringworld2_dialogs.cpp index 3e35831138..24504f2f5a 100644 --- a/engines/tsage/ringworld2/ringworld2_dialogs.cpp +++ b/engines/tsage/ringworld2/ringworld2_dialogs.cpp @@ -316,7 +316,7 @@ void CharacterDialog::show() { } // Reset the current cursor - R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS); + R2_GLOBALS._events.setCursor(CURSOR_USE); // Change to whichever scene the newly selected character is in R2_GLOBALS._sceneManager.changeScene(R2_GLOBALS._player._characterScene[R2_GLOBALS._player._characterIndex]); diff --git a/engines/tsage/ringworld2/ringworld2_logic.cpp b/engines/tsage/ringworld2/ringworld2_logic.cpp index 39e398023d..c67e5c18c2 100644 --- a/engines/tsage/ringworld2/ringworld2_logic.cpp +++ b/engines/tsage/ringworld2/ringworld2_logic.cpp @@ -561,14 +561,14 @@ void SceneExt::saveCharacter(int characterIndex) { void SceneExt::scalePalette(int RFactor, int GFactor, int BFactor) { byte *tmpPal = R2_GLOBALS._scenePalette._palette; byte newR, newG, newB; - int tmp, varC, varD = 0; + int tmp, varD = 0; for (int i = 0; i < 256; i++) { newR = (RFactor * tmpPal[(3 * i)]) / 100; newG = (GFactor * tmpPal[(3 * i) + 1]) / 100; newB = (BFactor * tmpPal[(3 * i) + 2]) / 100; - varC = 769; + int varC = 769; for (int j = 255; j >= 0; j--) { tmp = abs(tmpPal[(3 * j)] - newR); if (tmp >= varC) @@ -625,6 +625,11 @@ void SceneHandlerExt::process(Event &event) { SceneHandler::process(event); } +void SceneHandlerExt::dispatch() { + R2_GLOBALS._playStream.dispatch(); + SceneHandler::dispatch(); +} + void SceneHandlerExt::postLoad(int priorSceneBeforeLoad, int currentSceneBeforeLoad) { // Set up the shading maps used for showing the player in shadows setupPaletteMaps(); @@ -2329,7 +2334,7 @@ void ScannerDialog::Button::reset() { case 1800: if (R2_GLOBALS._rimLocation < 1201) scanner._obj4.setup(4, 3, 3); - else if (R2_GLOBALS._rimLocation < 1201) + else if (R2_GLOBALS._rimLocation > 1201) scanner._obj4.setup(4, 3, 4); else scanner._obj4.setup(4, 3, 5); diff --git a/engines/tsage/ringworld2/ringworld2_logic.h b/engines/tsage/ringworld2/ringworld2_logic.h index c9695c921d..101b0f53cd 100644 --- a/engines/tsage/ringworld2/ringworld2_logic.h +++ b/engines/tsage/ringworld2/ringworld2_logic.h @@ -114,6 +114,7 @@ public: virtual void postInit(SceneObjectList *OwnerList = NULL); virtual void process(Event &event); virtual void postLoad(int priorSceneBeforeLoad, int currentSceneBeforeLoad); + virtual void dispatch(); void setupPaletteMaps(); }; diff --git a/engines/tsage/ringworld2/ringworld2_scenes0.cpp b/engines/tsage/ringworld2/ringworld2_scenes0.cpp index 2fbce0646c..fc7e34bc16 100644 --- a/engines/tsage/ringworld2/ringworld2_scenes0.cpp +++ b/engines/tsage/ringworld2/ringworld2_scenes0.cpp @@ -1678,7 +1678,7 @@ void Scene180::signal() { case 24: case 26: case 46: - setSceneDelay((R2_GLOBALS._speechSubtitles & 1) ? 1 : 18); + setSceneDelay((R2_GLOBALS._speechSubtitles & SPEECH_TEXT) ? 1 : 18); break; case 13: @@ -3486,7 +3486,7 @@ void Scene300::postInit(SceneObjectList *OwnerList) { R2_GLOBALS.clearFlag(60); R2_GLOBALS._events.setCursor(CURSOR_ARROW); _sceneMode = 16; - _stripManager.start(404, this); + _stripManager.start3(404, this, R2_GLOBALS._stripManager_lookupList); } else { R2_GLOBALS._player.enableControl(); R2_GLOBALS._player._canWalk = false; @@ -4151,11 +4151,22 @@ void Scene325::signal() { --v; if (_priorConsoleAction == 5) v += 8; + if (R2_GLOBALS.getFlag(51) && (v == 2)) R2_GLOBALS.setFlag(57); if (R2_GLOBALS.getFlag(44) && !R2_GLOBALS.getFlag(51)) { if (v != 13) { + if (_priorConsoleAction == 6) { + // Fix for original game bug. + // The passive short scan geographical and astronomical sentences + // are inverted in the original game. + if (v == 6) + v = 8; + else if (v == 8) + v = 6; + } + setMessage(328, v); } else { _scannerLocation = 864; @@ -4302,12 +4313,12 @@ void Scene325::signal() { if (_soundCount) --_soundCount; - if (!_soundCount || (R2_GLOBALS._speechSubtitles == 2)) { + if (!_soundCount || !(R2_GLOBALS._speechSubtitles & SPEECH_VOICE)) { _soundIndex = 0; R2_GLOBALS._playStream.stop(); } else { _sceneMode = 15; - R2_GLOBALS._playStream.play(_soundQueue[_soundIndex], this); + R2_GLOBALS._playStream.play(_soundQueue[_soundIndex++], this); } break; default: @@ -4513,6 +4524,7 @@ void Scene325::consoleAction(int id) { case 14: if (R2_GLOBALS.getFlag(55)) { consoleAction(4); + // Workaround for original game bug. // Empty message crashing the game. It should be a warning message forbidding to switch to active scan // SceneItem::display2(329, 17); } else { @@ -4688,7 +4700,7 @@ void Scene325::setMessage(int resNum, int lineNum) { R2_GLOBALS._sceneObjects->draw(); - if ((_soundCount != 0) && (R2_GLOBALS._speechSubtitles != 2)) { + if ((_soundCount != 0) && (R2_GLOBALS._speechSubtitles & SPEECH_VOICE)) { _sceneMode = 15; R2_GLOBALS._playStream.play(_soundQueue[_soundIndex++], this); } @@ -5753,24 +5765,47 @@ bool Scene600::Smoke::startAction(CursorType action, Event &event) { return false; } -GfxSurface Scene600::Smoke::getFrame() { - GfxSurface frame = SceneActor::getFrame(); +void Scene600::Smoke::draw() { + // Effect should always be active on smoke, but since the original had this + // check, include it here too + if (_effect == EFFECT_NONE) { + SceneActor::draw(); + return; + } - if (_effect) { - // Translate the frame using the scene's pixel map - byte *pixelMap = static_cast<Scene600 *>(R2_GLOBALS._sceneManager._scene)->_pixelMap; - Graphics::Surface surface = frame.lockSurface(); - byte *srcP = (byte *)surface.getPixels(); + // Determine the area of the screen to be updated + Rect destRect = _bounds; + destRect.translate(-g_globals->_sceneManager._scene->_sceneBounds.left, + -g_globals->_sceneManager._scene->_sceneBounds.top); - while (srcP < ((byte *)surface.getBasePtr(0, surface.h))) { - *srcP = pixelMap[*srcP]; - srcP++; - } + // Get the smoke frame, screen reference, and pixel palette translation map + GfxSurface frame = getFrame(); + Graphics::Surface s = frame.lockSurface(); + Graphics::Surface screen = g_globals->gfxManager().getSurface().lockSurface(); + byte *pixelMap = static_cast<Scene600 *>(R2_GLOBALS._sceneManager._scene)->_pixelMap; - frame.unlockSurface(); + // Loop through every pixel of the frame. Any pixel of the frame that's not a + // tranparency, get the same pixel from the screen background, and shade it using + // the scene's pixel translation map + for (int yp = 0; yp < s.h; ++yp) { + byte *frameSrcP = (byte *)s.getBasePtr(0, yp); + byte *screenP = (byte *)screen.getBasePtr(destRect.left, destRect.top + yp); + + for (int xp = 0; xp < s.w; ++xp, ++frameSrcP, ++screenP) { + if (*frameSrcP != frame._transColor) { + *frameSrcP = pixelMap[*screenP]; + } + } } - return frame; + // Finished updating the frame + frame.unlockSurface(); + g_globals->gfxManager().getSurface().unlockSurface(); + + // Draw the processed frame + Region *priorityRegion = g_globals->_sceneManager._scene->_priorities.find(_priority); + g_globals->gfxManager().copyFrom(frame, destRect, priorityRegion); + } bool Scene600::Doorway::startAction(CursorType action, Event &event) { @@ -5846,7 +5881,7 @@ bool Scene600::Laser::startAction(CursorType action, Event &event) { scene->_smoke.postInit(); scene->_smoke.setup(601, 3, 1); - scene->_smoke._effect = EFFECT_3; + scene->_smoke._effect = EFFECT_SMOKE; scene->_smoke._moveDiff = Common::Point(1, 1); scene->_smoke._moveRate = 2; scene->_smoke._numFrames = 3; @@ -6027,7 +6062,7 @@ void Scene600::postInit(SceneObjectList *OwnerList) { _smoke._numFrames = 3; _smoke.animate(ANIM_MODE_2, NULL); _smoke.fixPriority(130); - _smoke._effect = EFFECT_3; + _smoke._effect = EFFECT_SMOKE; _smoke.setDetails(600, 24, 25, 26, 1, (SceneItem *) NULL); _smoke.signal(); } @@ -6098,7 +6133,7 @@ void Scene600::signal() { R2_INVENTORY.setObjectScene(R2_AEROSOL, 600); R2_GLOBALS.setFlag(5); - _smoke._effect = EFFECT_3; + _smoke._effect = EFFECT_SMOKE; _smoke.signal(); break; case 606: diff --git a/engines/tsage/ringworld2/ringworld2_scenes0.h b/engines/tsage/ringworld2/ringworld2_scenes0.h index 216039a348..ba93dda652 100644 --- a/engines/tsage/ringworld2/ringworld2_scenes0.h +++ b/engines/tsage/ringworld2/ringworld2_scenes0.h @@ -661,7 +661,7 @@ class Scene600 : public SceneExt { public: virtual void signal(); virtual bool startAction(CursorType action, Event &event); - virtual GfxSurface getFrame(); + virtual void draw(); }; class Doorway : public SceneActor { public: diff --git a/engines/tsage/ringworld2/ringworld2_scenes1.cpp b/engines/tsage/ringworld2/ringworld2_scenes1.cpp index 075420a1c9..486c88e65d 100644 --- a/engines/tsage/ringworld2/ringworld2_scenes1.cpp +++ b/engines/tsage/ringworld2/ringworld2_scenes1.cpp @@ -3913,8 +3913,6 @@ void Scene1337::Action10::signal() { void Scene1337::Action11::signal() { Scene1337 *scene = (Scene1337 *)R2_GLOBALS._sceneManager._scene; - bool noAction = true; - switch (_actionIndex++) { case 0: { scene->_actionCard2->_card.postInit(); @@ -3944,6 +3942,8 @@ void Scene1337::Action11::signal() { scene->_aSound1.play(57); bool found = false; + bool noAction = true; + int i = -1; switch (scene->_actionIdx2) { @@ -5411,10 +5411,10 @@ void Scene1337::showOptionsDialog() { } void Scene1337::handleClick(int arg1, Common::Point pt) { - bool found = false; int curReg = R2_GLOBALS._sceneRegions.indexOf(g_globals->_events._mousePos); if (arg1 == 3) { + bool found = false; int i; for (i = 0; i <= 7; i++) { if ( _gameBoardSide[2]._outpostStation[i].isIn(pt) @@ -7439,7 +7439,7 @@ void Scene1550::DishControlsWindow::setup2(int visage, int stripFrameNum, int fr if (scene->_dish._frame == 1) _lever.setup(1559, 2, 1); else - _lever.setup(1559, 2, 2); + _lever.setup(1559, 2, 5); _lever.setPosition(Common::Point(156, 103)); _lever.fixPriority(251); _lever.setDetails(1550, 69, -1, -1, 2, (SceneItem *) NULL); @@ -7773,7 +7773,7 @@ void Scene1550::signal() { _dishControlsWindow.remove(); _sceneMode = 20; setAction(&_sequenceManager1, this, 1566, &_dish, &_dishTowerShadow, NULL); - R2_GLOBALS.setFlag(21); + R2_GLOBALS.setFlag(19); break; case 24: _dishControlsWindow.remove(); @@ -8699,7 +8699,7 @@ void Scene1550::enterArea() { warning("missing for loop, to be implemented"); warning("gfx_draw_slice"); } - warning("Missing sub2957D()"); + warning("gfx_flip_screen()"); warning("gfx_set_pane_p()"); #endif R2_GLOBALS._sceneManager._fadeMode = FADEMODE_IMMEDIATE; @@ -11190,7 +11190,7 @@ void Scene1800::SouthExit::changeScene() { if (R2_GLOBALS._player._characterIndex == R2_QUINN) scene->setAction(&scene->_sequenceManager, scene, 1802, &R2_GLOBALS._player, &scene->_companion, NULL); else - scene->setAction(&scene->_sequenceManager, scene, 1802, &R2_GLOBALS._player, &scene->_companion, NULL); + scene->setAction(&scene->_sequenceManager, scene, 1803, &R2_GLOBALS._player, &scene->_companion, NULL); } } diff --git a/engines/tsage/ringworld2/ringworld2_scenes2.cpp b/engines/tsage/ringworld2/ringworld2_scenes2.cpp index f928f3635c..ad9dbf5a98 100644 --- a/engines/tsage/ringworld2/ringworld2_scenes2.cpp +++ b/engines/tsage/ringworld2/ringworld2_scenes2.cpp @@ -4872,10 +4872,10 @@ void Scene2900::Map::drawBlock(const byte *data, int xp, int yp, void Scene2900::Map::moveArea(Rect &r, int xAmt, int yAmt) { Rect tempRect = r; tempRect.translate(xAmt, yAmt); - int xpSrc, xpDest, width; - int ypSrc, ypDest, height; if (tempRect.intersects(r)) { + int xpSrc, xpDest, width; + int ypSrc, ypDest, height; if (xAmt >= 0) { xpSrc = tempRect.left; width = tempRect.width() - xAmt; diff --git a/engines/tsage/ringworld2/ringworld2_scenes3.cpp b/engines/tsage/ringworld2/ringworld2_scenes3.cpp index e55ae8ff70..36d7bf845b 100644 --- a/engines/tsage/ringworld2/ringworld2_scenes3.cpp +++ b/engines/tsage/ringworld2/ringworld2_scenes3.cpp @@ -1275,7 +1275,7 @@ void Scene3250::signal() { } void Scene3250::dispatch() { - if ((R2_GLOBALS._player._visage == 3250) && (R2_GLOBALS._player._strip == 3) && (R2_GLOBALS._player._effect == 0)) { + if ((R2_GLOBALS._player._visage == 3250) && (R2_GLOBALS._player._strip == 3) && (R2_GLOBALS._player._effect == EFFECT_NONE)) { R2_GLOBALS._player._effect = EFFECT_SHADED2; R2_GLOBALS._player._shade = 6; } @@ -2221,24 +2221,24 @@ void Scene3375::signal() { } void Scene3375::dispatch() { - if ((R2_GLOBALS._player._position.y >= 168) && (R2_GLOBALS._player._effect == 1)) + if ((R2_GLOBALS._player._position.y >= 168) && (R2_GLOBALS._player._effect == EFFECT_SHADED)) R2_GLOBALS._player._effect = EFFECT_SHADED2; - else if ((R2_GLOBALS._player._position.y < 168) && (R2_GLOBALS._player._effect == 6)) + else if ((R2_GLOBALS._player._position.y < 168) && (R2_GLOBALS._player._effect == EFFECT_SHADED2)) R2_GLOBALS._player._effect = EFFECT_SHADED; - if ((_companion1._position.y >= 168) && (_companion1._effect == 1)) + if ((_companion1._position.y >= 168) && (_companion1._effect == EFFECT_SHADED)) _companion1._effect = EFFECT_SHADED2; - else if ((_companion1._position.y < 168) && (_companion1._effect == 6)) + else if ((_companion1._position.y < 168) && (_companion1._effect == EFFECT_SHADED2)) _companion1._effect = EFFECT_SHADED; - if ((_companion2._position.y >= 168) && (_companion2._effect == 1)) + if ((_companion2._position.y >= 168) && (_companion2._effect == EFFECT_SHADED)) _companion2._effect = EFFECT_SHADED2; - else if ((_companion2._position.y < 168) && (_companion2._effect == 6)) + else if ((_companion2._position.y < 168) && (_companion2._effect == EFFECT_SHADED2)) _companion2._effect = EFFECT_SHADED; - if ((_webbster._position.y >= 168) && (_webbster._effect == 1)) + if ((_webbster._position.y >= 168) && (_webbster._effect == EFFECT_SHADED)) _webbster._effect = EFFECT_SHADED2; - else if ((_webbster._position.y < 168) && (_webbster._effect == 6)) + else if ((_webbster._position.y < 168) && (_webbster._effect == EFFECT_SHADED2)) _webbster._effect = EFFECT_SHADED; Scene::dispatch(); @@ -3896,7 +3896,6 @@ void Scene3500::dispatch() { int16 mazePosY = 0; int deltaX = 0; int deltaY = 0; - int tmpCellId = 0; int cellId = 0; if ((_mazeChangeAmount == 0) && !_postFixupFl) { @@ -3912,7 +3911,7 @@ void Scene3500::dispatch() { mazePosY = _mazeUI.cellFromY(_mazePosition.y + 46) - 46; deltaX = abs(mazePosX - newMazeX); deltaY = abs(mazePosY - newMazeY); - tmpCellId = 0; + int tmpCellId = 0; switch (_mazeDirection) { case MAZEDIR_NORTH: @@ -3956,7 +3955,7 @@ void Scene3500::dispatch() { if ( (((cellId == 23) || (cellId == 24) || (cellId == 4)) && (newMazeY <= mazePosY) && (_mazePosition.y>= mazePosY)) || (((cellId == 25) || (cellId == 26) || (cellId == 5) || (cellId == 14) || (cellId == 15)) && (_mazeChangeAmount >= deltaY) && (_mazeChangeAmount > 3) && (_action1._turningFl != 0)) ) { newMazeY = mazePosY; - if ((cellId != 25) && (cellId != 26) && (cellId != 5) && (cellId != 14) && (cellId == 15)) + if ((cellId != 25) && (cellId != 26) && (cellId != 5) && (cellId != 14) && (cellId != 15)) R2_GLOBALS._sound2.play(339); _rotation->_idxChange = 0; _speed = 0; diff --git a/engines/tucker/tucker.cpp b/engines/tucker/tucker.cpp index 04e83efbe5..d443cd3a88 100644 --- a/engines/tucker/tucker.cpp +++ b/engines/tucker/tucker.cpp @@ -3682,7 +3682,8 @@ void TuckerEngine::setActionForInventoryObject() { _actionRequiresTwoObjects = false; return; } - if ((_partNum == 3 && (_actionObj1Num == 6 || _actionObj1Num == 3 || _actionObj1Num == 17)) || + // Items with unary usage i.e. "Use X", rather than "Use X on Y" + if ((_partNum == 3 && (_actionObj1Num == 6 || _actionObj1Num == 3 || _actionObj1Num == 17 || _actionObj1Num == 33)) || (_partNum == 2 && _actionObj1Num == 19) || (_partNum == 3 && (_actionObj1Num == 42 && _selectedObjectNum == 18)) ) { _actionVerbLocked = 0; diff --git a/engines/wintermute/ad/ad_scene.cpp b/engines/wintermute/ad/ad_scene.cpp index ab7ab51f30..df944ba8eb 100644 --- a/engines/wintermute/ad/ad_scene.cpp +++ b/engines/wintermute/ad/ad_scene.cpp @@ -2041,6 +2041,10 @@ bool AdScene::scSetProperty(const char *name, ScValue *value) { ////////////////////////////////////////////////////////////////////////// else if (strcmp(name, "ScrollSpeedX") == 0) { _scrollTimeH = value->getInt(); + if (_scrollTimeH == 0) { + warning("_scrollTimeH can't be 0, resetting to default"); + _scrollTimeH = 10; + } return STATUS_OK; } @@ -2049,6 +2053,10 @@ bool AdScene::scSetProperty(const char *name, ScValue *value) { ////////////////////////////////////////////////////////////////////////// else if (strcmp(name, "ScrollSpeedY") == 0) { _scrollTimeV = value->getInt(); + if (_scrollTimeV == 0) { + warning("_scrollTimeV can't be 0, resetting to default"); + _scrollTimeV = 10; + } return STATUS_OK; } diff --git a/engines/wintermute/base/font/base_font_truetype.cpp b/engines/wintermute/base/font/base_font_truetype.cpp index b879e789e3..f8eb40d42a 100644 --- a/engines/wintermute/base/font/base_font_truetype.cpp +++ b/engines/wintermute/base/font/base_font_truetype.cpp @@ -271,11 +271,7 @@ BaseSurface *BaseFontTT::renderTextToTexture(const WideString &text, int width, //debugC(kWintermuteDebugFont, "%s %d %d %d %d", text.c_str(), RGBCOLGetR(_layers[0]->_color), RGBCOLGetG(_layers[0]->_color), RGBCOLGetB(_layers[0]->_color), RGBCOLGetA(_layers[0]->_color)); // void drawString(Surface *dst, const Common::String &str, int x, int y, int w, uint32 color, TextAlign align = kTextAlignLeft, int deltax = 0, bool useEllipsis = true) const; Graphics::Surface *surface = new Graphics::Surface(); - if (_deletableFont) { // We actually have a TTF - surface->create((uint16)width, (uint16)(_lineHeight * lines.size()), _gameRef->_renderer->getPixelFormat()); - } else { // We are using a fallback, they can't do 32bpp - surface->create((uint16)width, (uint16)(_lineHeight * lines.size()), Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0)); - } + surface->create((uint16)width, (uint16)(_lineHeight * lines.size()), _gameRef->_renderer->getPixelFormat()); uint32 useColor = 0xffffffff; Common::Array<WideString>::iterator it; int heightOffset = 0; @@ -285,7 +281,6 @@ BaseSurface *BaseFontTT::renderTextToTexture(const WideString &text, int width, } BaseSurface *retSurface = _gameRef->_renderer->createSurface(); - Graphics::Surface *convertedSurface = surface->convertTo(_gameRef->_renderer->getPixelFormat()); if (_deletableFont) { // Reconstruct the alpha channel of the font. @@ -295,7 +290,7 @@ BaseSurface *BaseFontTT::renderTextToTexture(const WideString &text, int width, // to its original alpha value. Graphics::PixelFormat format = _gameRef->_renderer->getPixelFormat(); - uint32 *pixels = (uint32 *)convertedSurface->getPixels(); + uint32 *pixels = (uint32 *)surface->getPixels(); // This is a Surface we created ourselves, so no empty space between rows. for (int i = 0; i < surface->w * surface->h; ++i) { @@ -306,11 +301,9 @@ BaseSurface *BaseFontTT::renderTextToTexture(const WideString &text, int width, } } - retSurface->putSurface(*convertedSurface, true); - convertedSurface->free(); + retSurface->putSurface(*surface, true); surface->free(); delete surface; - delete convertedSurface; return retSurface; // TODO: _isUnderline, _isBold, _isItalic, _isStriked } diff --git a/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp b/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp index c33e8ba54b..cbc32387e1 100644 --- a/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp +++ b/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp @@ -447,7 +447,7 @@ bool BaseSurfaceOSystem::drawSprite(int x, int y, Rect32 *rect, Rect32 *newRect, bool BaseSurfaceOSystem::putSurface(const Graphics::Surface &surface, bool hasAlpha) { _loaded = true; - if (surface.format == _surface->format && surface.w == _surface->w && surface.h == _surface->h) { + if (surface.format == _surface->format && surface.pitch == _surface->pitch && surface.h == _surface->h) { const byte *src = (const byte *)surface.getBasePtr(0, 0); byte *dst = (byte *)_surface->getBasePtr(0, 0); memcpy(dst, src, surface.pitch * surface.h); diff --git a/engines/wintermute/video/video_theora_player.cpp b/engines/wintermute/video/video_theora_player.cpp index 299b64f915..3bce8628b8 100644 --- a/engines/wintermute/video/video_theora_player.cpp +++ b/engines/wintermute/video/video_theora_player.cpp @@ -305,7 +305,7 @@ bool VideoTheoraPlayer::update() { if (!_theoraDecoder->endOfVideo() && _theoraDecoder->getTimeToNextFrame() == 0) { const Graphics::Surface *decodedFrame = _theoraDecoder->decodeNextFrame(); if (decodedFrame) { - if (decodedFrame->format == _surface.format && decodedFrame->w == _surface.w && decodedFrame->h == _surface.h) { + if (decodedFrame->format == _surface.format && decodedFrame->pitch == _surface.pitch && decodedFrame->h == _surface.h) { const byte *src = (const byte *)decodedFrame->getBasePtr(0, 0); byte *dst = (byte *)_surface.getBasePtr(0, 0); memcpy(dst, src, _surface.pitch * _surface.h); |
