From 1904e944c561a21dbe6271f64393f2bfc5f584f9 Mon Sep 17 00:00:00 2001 From: johndoe123 Date: Wed, 14 Nov 2012 12:21:13 +0000 Subject: NEVERHOOD: Add initCubeSymbolsPuzzle - Add microtiles to the screen update to eliminate overdraw (microtiles code taken from the Toltecs engine) - Fix sprite dimensions in AsScene1402PuzzleBox which caused a crash - Fix screen shaking in Scene1402 (the puzzle box and bridge parts now shake along :) - Use addSoundItem/addMusicItem in the SoundMan instead of directly using push_back on the resp. arrays - Remove old code and comments --- engines/neverhood/gamemodule.cpp | 14 ++- engines/neverhood/gamemodule.h | 1 + engines/neverhood/microtiles.cpp | 164 ++++++++++++++++++++++++++++++++++++ engines/neverhood/microtiles.h | 64 ++++++++++++++ engines/neverhood/module.mk | 1 + engines/neverhood/module1400.cpp | 12 +-- engines/neverhood/module2200.cpp | 7 +- engines/neverhood/scene.cpp | 153 +++++++++------------------------ engines/neverhood/scene.h | 13 ++- engines/neverhood/screen.cpp | 94 +++++++-------------- engines/neverhood/screen.h | 8 +- engines/neverhood/smackerplayer.cpp | 17 +--- engines/neverhood/smackerplayer.h | 1 - engines/neverhood/sound.cpp | 44 +++++----- engines/neverhood/sprite.cpp | 11 +-- 15 files changed, 357 insertions(+), 247 deletions(-) create mode 100644 engines/neverhood/microtiles.cpp create mode 100644 engines/neverhood/microtiles.h diff --git a/engines/neverhood/gamemodule.cpp b/engines/neverhood/gamemodule.cpp index c7ce53fe79..be4f5d3d51 100644 --- a/engines/neverhood/gamemodule.cpp +++ b/engines/neverhood/gamemodule.cpp @@ -276,7 +276,15 @@ void GameModule::initCodeSymbolsPuzzle() { setGlobalVar(V_NOISY_SYMBOL_INDEX, _vm->_rnd->getRandomNumber(11 - 1) + 1); setSubVar(VA_IS_PUZZLE_INIT, 0x0CD09B50, 1); } +} +void GameModule::initCubeSymbolsPuzzle() { + if (!getSubVar(VA_IS_PUZZLE_INIT, 0x60400854)) { + NonRepeatingRandomNumbers cubeSymbols(_vm->_rnd, 9); + for (uint32 cubePosition = 0; cubePosition < 9; ++cubePosition) + setSubVar(VA_CUBE_POSITIONS, cubePosition, (uint32)(cubeSymbols.getNumber() - 1)); + setSubVar(VA_IS_PUZZLE_INIT, 0x60400854, 1); + } } uint32 GameModule::getCurrRadioMusicFileHash() { @@ -352,7 +360,7 @@ void GameModule::startup() { setSubVar(VA_CURR_WATER_PIPES_LEVEL, 4, 4); // <<>> createScene(_vm->gameState().sceneNum, _vm->gameState().which); @@ -364,9 +372,9 @@ void GameModule::startup() { _vm->gameState().sceneNum = 28; createModule(2700, -1); #endif -#if 0 +#if 1 _vm->gameState().sceneNum = 0; - createModule(1800, -1); + createModule(1400, -1); #endif #if 0 _vm->gameState().sceneNum = 0; diff --git a/engines/neverhood/gamemodule.h b/engines/neverhood/gamemodule.h index e1461d2413..53adb859f8 100644 --- a/engines/neverhood/gamemodule.h +++ b/engines/neverhood/gamemodule.h @@ -49,6 +49,7 @@ public: void initTestTubes2Puzzle(); void initCannonSymbolsPuzzle(); void initCodeSymbolsPuzzle(); + void initCubeSymbolsPuzzle(); uint32 getCurrRadioMusicFileHash(); protected: Entity *_prevChildObject; diff --git a/engines/neverhood/microtiles.cpp b/engines/neverhood/microtiles.cpp new file mode 100644 index 0000000000..ee64fdadc5 --- /dev/null +++ b/engines/neverhood/microtiles.cpp @@ -0,0 +1,164 @@ +/* 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 "neverhood/microtiles.h" + +namespace Neverhood { + +MicroTileArray::MicroTileArray(int16 width, int16 height) { + _tilesW = (width / TileSize) + ((width % TileSize) > 0 ? 1 : 0); + _tilesH = (height / TileSize) + ((height % TileSize) > 0 ? 1 : 0); + _tiles = new BoundingBox[_tilesW * _tilesH]; + clear(); +} + +MicroTileArray::~MicroTileArray() { + delete[] _tiles; +} + +void MicroTileArray::addRect(Common::Rect r) { + + int ux0, uy0, ux1, uy1; + int tx0, ty0, tx1, ty1; + int ix0, iy0, ix1, iy1; + + r.clip(Common::Rect(0, 0, 639, 479)); + + ux0 = r.left / TileSize; + uy0 = r.top / TileSize; + ux1 = r.right / TileSize; + uy1 = r.bottom / TileSize; + + tx0 = r.left % TileSize; + ty0 = r.top % TileSize; + tx1 = r.right % TileSize; + ty1 = r.bottom % TileSize; + + for (int yc = uy0; yc <= uy1; yc++) { + for (int xc = ux0; xc <= ux1; xc++) { + ix0 = (xc == ux0) ? tx0 : 0; + ix1 = (xc == ux1) ? tx1 : TileSize - 1; + iy0 = (yc == uy0) ? ty0 : 0; + iy1 = (yc == uy1) ? ty1 : TileSize - 1; + updateBoundingBox(_tiles[xc + yc * _tilesW], ix0, iy0, ix1, iy1); + } + } + +} + +void MicroTileArray::clear() { + memset(_tiles, 0, _tilesW * _tilesH * sizeof(BoundingBox)); +} + +byte MicroTileArray::TileX0(const BoundingBox &boundingBox) { + return (boundingBox >> 24) & 0xFF; +} + +byte MicroTileArray::TileY0(const BoundingBox &boundingBox) { + return (boundingBox >> 16) & 0xFF; +} + +byte MicroTileArray::TileX1(const BoundingBox &boundingBox) { + return (boundingBox >> 8) & 0xFF; +} + +byte MicroTileArray::TileY1(const BoundingBox &boundingBox) { + return boundingBox & 0xFF; +} + +bool MicroTileArray::isBoundingBoxEmpty(const BoundingBox &boundingBox) { + return boundingBox == EmptyBoundingBox; +} + +bool MicroTileArray::isBoundingBoxFull(const BoundingBox &boundingBox) { + return boundingBox == FullBoundingBox; +} + +void MicroTileArray::setBoundingBox(BoundingBox &boundingBox, byte x0, byte y0, byte x1, byte y1) { + boundingBox = (x0 << 24) | (y0 << 16) | (x1 << 8) | y1; +} + +void MicroTileArray::updateBoundingBox(BoundingBox &boundingBox, byte x0, byte y0, byte x1, byte y1) { + if (!isBoundingBoxEmpty(boundingBox)) { + x0 = MIN(TileX0(boundingBox), x0); + y0 = MIN(TileY0(boundingBox), y0); + x1 = MAX(TileX1(boundingBox), x1); + y1 = MAX(TileY1(boundingBox), y1); + } + setBoundingBox(boundingBox, x0, y0, x1, y1); +} + +RectArray *MicroTileArray::getRectangles() { + + RectArray *rects = new RectArray(); + + int x, y; + int x0, y0, x1, y1; + int i = 0; + + for (y = 0; y < _tilesH; ++y) { + for (x = 0; x < _tilesW; ++x) { + + int start; + int finish = 0; + BoundingBox boundingBox = _tiles[i]; + + if (isBoundingBoxEmpty(boundingBox)) { + ++i; + continue; + } + + x0 = (x * TileSize) + TileX0(boundingBox); + y0 = (y * TileSize) + TileY0(boundingBox); + y1 = (y * TileSize) + TileY1(boundingBox); + + start = i; + + if (TileX1(boundingBox) == TileSize - 1 && x != _tilesW - 1) { // check if the tile continues + while (!finish) { + ++x; + ++i; + if (x == _tilesW || i >= _tilesW * _tilesH || + TileY0(_tiles[i]) != TileY0(boundingBox) || + TileY1(_tiles[i]) != TileY1(boundingBox) || + TileX0(_tiles[i]) != 0) + { + --x; + --i; + finish = 1; + } + } + } + + x1 = (x * TileSize) + TileX1(_tiles[i]); + + rects->push_back(Common::Rect(x0, y0, x1 + 1, y1 + 1)); + + ++i; + } + } + + return rects; +} + +} // End of namespace Neverhood diff --git a/engines/neverhood/microtiles.h b/engines/neverhood/microtiles.h new file mode 100644 index 0000000000..2ad6796903 --- /dev/null +++ b/engines/neverhood/microtiles.h @@ -0,0 +1,64 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * + */ + +#ifndef NEVERHOOD_MICROTILES_H +#define NEVERHOOD_MICROTILES_H + +#include "common/scummsys.h" +#include "common/array.h" +#include "common/util.h" +#include "common/rect.h" + +namespace Neverhood { + +typedef uint32 BoundingBox; + +const BoundingBox FullBoundingBox = 0x00001F1F; +const BoundingBox EmptyBoundingBox = 0x00000000; +const int TileSize = 32; + +typedef Common::Array RectArray; + +class MicroTileArray { +public: + MicroTileArray(int16 width, int16 height); + ~MicroTileArray(); + void addRect(Common::Rect r); + void clear(); + RectArray *getRectangles(); +protected: + BoundingBox *_tiles; + int16 _tilesW, _tilesH; + byte TileX0(const BoundingBox &boundingBox); + byte TileY0(const BoundingBox &boundingBox); + byte TileX1(const BoundingBox &boundingBox); + byte TileY1(const BoundingBox &boundingBox); + bool isBoundingBoxEmpty(const BoundingBox &boundingBox); + bool isBoundingBoxFull(const BoundingBox &boundingBox); + void setBoundingBox(BoundingBox &boundingBox, byte x0, byte y0, byte x1, byte y1); + void updateBoundingBox(BoundingBox &boundingBox, byte x0, byte y0, byte x1, byte y1); +}; + +} // namespace Neverhood + +#endif // NEVERHOOD_MICROTILES_H diff --git a/engines/neverhood/module.mk b/engines/neverhood/module.mk index 224dfb579f..9069203e9b 100644 --- a/engines/neverhood/module.mk +++ b/engines/neverhood/module.mk @@ -12,6 +12,7 @@ MODULE_OBJS = \ graphics.o \ klayman.o \ menumodule.o \ + microtiles.o \ module.o \ module1000.o \ module1100.o \ diff --git a/engines/neverhood/module1400.cpp b/engines/neverhood/module1400.cpp index 249494179e..db3acb68f5 100644 --- a/engines/neverhood/module1400.cpp +++ b/engines/neverhood/module1400.cpp @@ -780,7 +780,7 @@ SsScene1402BridgePart::SsScene1402BridgePart(NeverhoodEngine *vm, uint32 fileHas AsScene1402PuzzleBox::AsScene1402PuzzleBox(NeverhoodEngine *vm, Scene *parentScene, int status) : AnimatedSprite(vm, 1100), _parentScene(parentScene) { - createSurface(900, 152, 147); + createSurface(900, 347, 230); SetFilterY(&Sprite::defFilterY); SetUpdateHandler(&AnimatedSprite::update); @@ -844,9 +844,10 @@ Scene1402::Scene1402(NeverhoodEngine *vm, Module *parentModule, int which) SetMessageHandler(&Scene1402::handleMessage); + _vm->_screen->setYOffset(0); + setBackground(0x231482F0); setBackgroundY(-10); - // TODO g_screen->field_26 = 0; setPalette(0x231482F0); _palette->addPalette(0x91D3A391, 0, 64, 0); insertMouse433(0x482F4239); @@ -891,7 +892,7 @@ Scene1402::Scene1402(NeverhoodEngine *vm, Module *parentModule, int which) startShaking(); } } - + if (_asPuzzleBox) _asPuzzleBox->setClipRect(0, 0, 640, _ssBridgePart3->getDrawRect().y2()); @@ -919,10 +920,10 @@ Scene1402::Scene1402(NeverhoodEngine *vm, Module *parentModule, int which) void Scene1402::upShaking() { if (_isShaking) { setBackgroundY(_vm->_rnd->getRandomNumber(10 - 1) - 10); - // TODO g_screen->field_26 = -10 - _background->getDrawRect().y; + _vm->_screen->setYOffset(-10 - getBackgroundY()); } else { setBackgroundY(-10); - // TODO g_screen->field_26 = 0; + _vm->_screen->setYOffset(0); SetUpdateHandler(&Scene::update); } Scene::update(); @@ -973,6 +974,7 @@ uint32 Scene1402::handleMessage(int messageNum, const MessageParam ¶m, Entit } else setMessageList2(0x004B0B68); } + break; } return 0; } diff --git a/engines/neverhood/module2200.cpp b/engines/neverhood/module2200.cpp index 8616592c18..8a7e3464a5 100644 --- a/engines/neverhood/module2200.cpp +++ b/engines/neverhood/module2200.cpp @@ -539,9 +539,7 @@ Scene2201::Scene2201(NeverhoodEngine *vm, Module *parentModule, int which) Sprite *tempSprite; - if (!getSubVar(VA_IS_PUZZLE_INIT, 0x60400854)) { - // TODO _vm->gameModule()->initScene2201Vars(); - } + _vm->gameModule()->initCubeSymbolsPuzzle(); SetMessageHandler(&Scene2201::handleMessage); SetUpdateHandler(&Scene2201::update); @@ -875,7 +873,8 @@ Scene2202::Scene2202(NeverhoodEngine *vm, Module *parentModule, int which) : Scene(vm, parentModule, true), _isSolved(false), _leaveScene(false), _isCubeMoving(false), _ssMovingCube(NULL), _ssDoneMovingCube(NULL) { - // TODO initScene2201Vars(); + _vm->gameModule()->initCubeSymbolsPuzzle(); + SetMessageHandler(&Scene2202::handleMessage); SetUpdateHandler(&Scene2202::update); diff --git a/engines/neverhood/scene.cpp b/engines/neverhood/scene.cpp index aa4efaca13..6141ee4487 100644 --- a/engines/neverhood/scene.cpp +++ b/engines/neverhood/scene.cpp @@ -29,7 +29,7 @@ Scene::Scene(NeverhoodEngine *vm, Module *parentModule, bool clearHitRects) : Entity(vm, 0), _parentModule(parentModule), _dataResource(vm) { _isKlaymanBusy = false; - _systemCallbackFlag = false; + _doConvertMessages = false; _messageList = NULL; _rectType = 0; _mouseClickPos.x = 0; @@ -46,7 +46,6 @@ Scene::Scene(NeverhoodEngine *vm, Module *parentModule, bool clearHitRects) } _vm->_screen->setFps(24); _vm->_screen->setSmackerDecoder(NULL); - // TODO g_screen->resetDirtyRects(); _canAcceptInput = true; _messageList2 = NULL; _smackerPlayer = NULL; @@ -229,7 +228,6 @@ void Scene::update() { if (_mouseClicked) { if (_klayman) { - // TODO: Merge later if (_canAcceptInput && _klayman->hasMessageHandler() && sendMessage(_klayman, 0x1008, 0) != 0 && @@ -262,27 +260,11 @@ uint32 Scene::handleMessage(int messageNum, const MessageParam ¶m, Entity *s case 0: // mouse moved if (_mouseCursor && _mouseCursor->hasMessageHandler()) sendMessage(_mouseCursor, 0x4002, param); - // TODO Seems unused: queryPositionSomeRects(param.asPoint().x, param.asPoint().y); break; case 1: // mouse clicked _mouseClicked = true; _mouseClickPos = param.asPoint(); break; - /* ORIGINAL DEBUG - case 3: - drawSurfaceRects(); - break; - */ - /* ORIGINAL DEBUG - case 4: - drawRectListRects(); - break; - */ - /* ORIGINAL DEBUG - case 5: - broadcastObjectMessage5(); - break; - */ case 6: sendMessage(_parentModule, 0x1009, param); break; @@ -331,34 +313,7 @@ uint32 Scene::handleMessage(int messageNum, const MessageParam ¶m, Entity *s return 0; } -void Scene::smackerUpdate() { - //**ALL TODO -#if 0 - _smackerPlayer->handleUpdate(); - if (_smackerDone) { - delete _smackerPlayer; - _smackerPlayer = NULL; - _updateHandlerCb = _savedUpdateHandlerCb; - _messageHandlerCb = _savedMessageHandlerCb; - if (_palette) - _palette->usePalette(); - // TODO _background->restore(); - // TODO g_screen->smackerPlayer = NULL; - } -#endif -} - -uint32 Scene::smackerHandleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - switch (messageNum) { - case 0x3002: - _smackerDone = true; - break; - } - return 0; -} - bool Scene::queryPositionSprite(int16 mouseX, int16 mouseY) { - //debug("Scene::queryPositionSprite(%d, %d)", mouseX, mouseY); for (uint i = 0; i < _vm->_collisionMan->getSpriteCount(); i++) { Sprite *sprite = _vm->_collisionMan->getSprite(i); if (sprite->hasMessageHandler() && sprite->isPointInside(mouseX, mouseY) && @@ -380,7 +335,6 @@ bool Scene::queryPositionRectList(int16 mouseX, int16 mouseY) { for (uint j = 0; j < rectList[i].subRects.size(); j++) { debug(2, " (%d, %d) ? (%d, %d, %d, %d)", mouseX, mouseY, rectList[i].subRects[j].rect.x1, rectList[i].subRects[j].rect.y1, rectList[i].subRects[j].rect.x2, rectList[i].subRects[j].rect.y2); if (rectList[i].subRects[j].rect.contains(mouseX, mouseY)) { - //debug("Scene::queryPositionRectList() -> %08X", rectList[i].subRects[j].messageListId); return setMessageList2(rectList[i].subRects[j].messageListId); } } @@ -394,53 +348,33 @@ bool Scene::queryPositionRectList(int16 mouseX, int16 mouseY) { return true; } -void Scene::setMessageList(uint32 id, bool canAcceptInput, bool systemCallbackFlag) { - setMessageList(_vm->_staticData->getMessageList(id), canAcceptInput, systemCallbackFlag); +void Scene::setMessageList(uint32 id, bool canAcceptInput, bool doConvertMessages) { + setMessageList(_vm->_staticData->getMessageList(id), canAcceptInput, doConvertMessages); } -void Scene::setMessageList(MessageList *messageList, bool canAcceptInput, bool systemCallbackFlag) { - //debug("Scene::setMessageList(%p)", (void*)messageList); +void Scene::setMessageList(MessageList *messageList, bool canAcceptInput, bool doConvertMessages) { _messageList = messageList; _messageListCount = _messageList ? _messageList->size() : 0; _messageListIndex = 0; _isKlaymanBusy = false; _canAcceptInput = canAcceptInput; - _systemCallbackFlag = systemCallbackFlag; + _doConvertMessages = doConvertMessages; _messageListStatus = 1; sendMessage(_klayman, 0x101C, 0); - -#if 0 - // DEBUG: Show message list - for (uint i = 0; i < messageList->size(); i++) { - debug("A: %02d: %04X, %08X", i, (*messageList)[i].messageNum, (*messageList)[i].messageValue); - } - debug("A: ================================================================"); -#endif - } -bool Scene::setMessageList2(uint32 id, bool canAcceptInput, bool systemCallbackFlag) { - return setMessageList2(_vm->_staticData->getMessageList(id), canAcceptInput, systemCallbackFlag); +bool Scene::setMessageList2(uint32 id, bool canAcceptInput, bool doConvertMessages) { + return setMessageList2(_vm->_staticData->getMessageList(id), canAcceptInput, doConvertMessages); } -bool Scene::setMessageList2(MessageList *messageList, bool canAcceptInput, bool systemCallbackFlag) { - //debug("Scene::setMessageList2(%p)", (void*)messageList); - -#if 0 - // DEBUG: Show message list - for (uint i = 0; i < messageList->size(); i++) { - debug("B: %02d: %04X, %08X", i, (*messageList)[i].messageNum, (*messageList)[i].messageValue); - } - debug("B: ================================================================"); -#endif - +bool Scene::setMessageList2(MessageList *messageList, bool canAcceptInput, bool doConvertMessages) { if (_messageListStatus == 0 || (_messageListStatus == 1 && messageList != _messageList2) || (_messageListStatus == 2 && messageList == _messageList2)) { // NOTE Skipped unneeded resource preloading code _messageValue = -1; _messageList2 = messageList; - setMessageList(messageList, canAcceptInput, systemCallbackFlag); + setMessageList(messageList, canAcceptInput, doConvertMessages); return true; } return false; @@ -465,45 +399,39 @@ void Scene::processMessageList() { uint32 messageNum = (*_messageList)[_messageListIndex].messageNum; uint32 messageParam = (*_messageList)[_messageListIndex].messageValue; - //debug("Scene::processMessageList() %04X, %08X", messageNum, messageParam); - - _messageListIndex++; - if (_messageListIndex == _messageListCount) { + ++_messageListIndex; + if (_messageListIndex == _messageListCount) sendMessage(_klayman, 0x1021, 0); - } - if (_systemCallbackFlag) { + if (_doConvertMessages) messageNum = convertMessageNum(messageNum); - } - if (messageNum != 0x4003) { - if (messageNum == 0x1009 || messageNum == 0x1024) { - sendMessage(_parentModule, messageNum, messageParam); - } else if (messageNum == 0x100A) { - _messageValue = messageParam; - sendMessage(_parentModule, messageNum, messageParam); - } else if (messageNum == 0x4001) { - _isKlaymanBusy = true; - sendPointMessage(_klayman, 0x4001, _mouseClickPos); - } else if (messageNum == 0x100D) { - if (this->hasMessageHandler() && sendMessage(this, 0x100D, messageParam) != 0) - continue; - } else if (messageNum == 0x101A) { - _messageListStatus = 0; - } else if (messageNum == 0x101B) { - _messageListStatus = 2; - } else if (messageNum == 0x1020) { - _canAcceptInput = false; - } else if (messageNum >= 0x2000 && messageNum <= 0x2FFF) { - if (this->hasMessageHandler() && sendMessage(this, messageNum, messageParam) != 0) { - _isMessageListBusy = false; - return; - } - } else { - _isKlaymanBusy = true; - if (_klayman->hasMessageHandler() && sendMessage(_klayman, messageNum, messageParam) != 0) { - _isKlaymanBusy = false; - } - } - } + if (messageNum == 0x1009 || messageNum == 0x1024) { + sendMessage(_parentModule, messageNum, messageParam); + } else if (messageNum == 0x100A) { + _messageValue = messageParam; + sendMessage(_parentModule, messageNum, messageParam); + } else if (messageNum == 0x4001) { + _isKlaymanBusy = true; + sendPointMessage(_klayman, 0x4001, _mouseClickPos); + } else if (messageNum == 0x100D) { + if (this->hasMessageHandler() && sendMessage(this, 0x100D, messageParam) != 0) + continue; + } else if (messageNum == 0x101A) { + _messageListStatus = 0; + } else if (messageNum == 0x101B) { + _messageListStatus = 2; + } else if (messageNum == 0x1020) { + _canAcceptInput = false; + } else if (messageNum >= 0x2000 && messageNum <= 0x2FFF) { + if (this->hasMessageHandler() && sendMessage(this, messageNum, messageParam) != 0) { + _isMessageListBusy = false; + return; + } + } else if (messageNum != 0x4003) { + _isKlaymanBusy = true; + if (_klayman->hasMessageHandler() && sendMessage(_klayman, messageNum, messageParam) != 0) { + _isKlaymanBusy = false; + } + } if (_messageListIndex == _messageListCount) { _canAcceptInput = true; _messageList = NULL; @@ -538,7 +466,6 @@ void Scene::clearRectList() { void Scene::loadHitRectList() { HitRectList *hitRectList = _dataResource.getHitRectList(); - //debug("Scene::loadHitRectList() hitRectList = %p", (void*)hitRectList); if (hitRectList) { _hitRectList = *hitRectList; _vm->_collisionMan->setHitRects(&_hitRectList); diff --git a/engines/neverhood/scene.h b/engines/neverhood/scene.h index 21f054e123..b531796f40 100644 --- a/engines/neverhood/scene.h +++ b/engines/neverhood/scene.h @@ -170,7 +170,7 @@ protected: int _messageListStatus; uint _messageListCount; uint _messageListIndex; - bool _systemCallbackFlag; + bool _doConvertMessages; bool _canAcceptInput; bool _isKlaymanBusy; @@ -189,17 +189,14 @@ protected: void (Entity::*_savedUpdateHandlerCb)(); uint32 (Entity::*_savedMessageHandlerCb)(int messageNum, const MessageParam ¶m, Entity *sender); - bool _smackerDone; int _messageValue; uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void smackerUpdate(); - uint32 smackerHandleMessage(int messageNum, const MessageParam ¶m, Entity *sender); bool queryPositionSprite(int16 mouseX, int16 mouseY); bool queryPositionRectList(int16 mouseX, int16 mouseY); - void setMessageList(uint32 id, bool canAcceptInput = true, bool systemCallbackFlag = false); - void setMessageList(MessageList *messageList, bool canAcceptInput = true, bool systemCallbackFlag = false); - bool setMessageList2(uint32 id, bool canAcceptInput = true, bool systemCallbackFlag = false); - bool setMessageList2(MessageList *messageList, bool canAcceptInput = true, bool systemCallbackFlag = false); + void setMessageList(uint32 id, bool canAcceptInput = true, bool doConvertMessages = false); + void setMessageList(MessageList *messageList, bool canAcceptInput = true, bool doConvertMessages = false); + bool setMessageList2(uint32 id, bool canAcceptInput = true, bool doConvertMessages = false); + bool setMessageList2(MessageList *messageList, bool canAcceptInput = true, bool doConvertMessages = false); void processMessageList(); void setRectList(uint32 id); void setRectList(RectList *rectList); diff --git a/engines/neverhood/screen.cpp b/engines/neverhood/screen.cpp index 7321ddb233..352e59e9b2 100644 --- a/engines/neverhood/screen.cpp +++ b/engines/neverhood/screen.cpp @@ -26,7 +26,8 @@ namespace Neverhood { Screen::Screen(NeverhoodEngine *vm) - : _vm(vm), _paletteData(NULL), _paletteChanged(false), _smackerDecoder(NULL) { + : _vm(vm), _paletteData(NULL), _paletteChanged(false), _smackerDecoder(NULL), + _yOffset(0) { _ticks = _vm->_system->getMillis(); @@ -35,10 +36,12 @@ Screen::Screen(NeverhoodEngine *vm) _renderQueue = new RenderQueue(); _prevRenderQueue = new RenderQueue(); + _microTiles = new MicroTileArray(640, 480); } Screen::~Screen() { + delete _microTiles; delete _renderQueue; delete _prevRenderQueue; _backScreen->free(); @@ -56,16 +59,8 @@ void Screen::update() { return; } - // NOTE This is more or less experimental code for a smart "render queue". - // It works well so far but needs some optimizing, e.g. reducing overdraw. - // Maybe I'll use my microtiles code from the Toltecs engine. - // Also better move this to a separate method or even class. - - Common::Array updateRects; + _microTiles->clear(); - for (RenderQueue::iterator jt = _prevRenderQueue->begin(); jt != _prevRenderQueue->end(); ++jt) - (*jt)._refresh = true; - for (RenderQueue::iterator it = _renderQueue->begin(); it != _renderQueue->end(); ++it) { RenderItem &renderItem = (*it); renderItem._refresh = true; @@ -81,27 +76,34 @@ void Screen::update() { for (RenderQueue::iterator jt = _prevRenderQueue->begin(); jt != _prevRenderQueue->end(); ++jt) { RenderItem &prevRenderItem = (*jt); if (prevRenderItem._refresh) - updateRects.push_back(Common::Rect(prevRenderItem._destX, prevRenderItem._destY, prevRenderItem._destX + prevRenderItem._width, prevRenderItem._destY + prevRenderItem._height)); + _microTiles->addRect(Common::Rect(prevRenderItem._destX, prevRenderItem._destY, prevRenderItem._destX + prevRenderItem._width, prevRenderItem._destY + prevRenderItem._height)); } for (RenderQueue::iterator it = _renderQueue->begin(); it != _renderQueue->end(); ++it) { RenderItem &renderItem = (*it); if (renderItem._refresh) - updateRects.push_back(Common::Rect(renderItem._destX, renderItem._destY, renderItem._destX + renderItem._width, renderItem._destY + renderItem._height)); + _microTiles->addRect(Common::Rect(renderItem._destX, renderItem._destY, renderItem._destX + renderItem._width, renderItem._destY + renderItem._height)); + renderItem._refresh = true; } + RectArray *updateRects = _microTiles->getRectangles(); + for (RenderQueue::iterator it = _renderQueue->begin(); it != _renderQueue->end(); ++it) { RenderItem &renderItem = (*it); - for (Common::Array::iterator ri = updateRects.begin(); ri != updateRects.end(); ++ri) + for (RectArray::iterator ri = updateRects->begin(); ri != updateRects->end(); ++ri) blitRenderItem(renderItem, *ri); } SWAP(_renderQueue, _prevRenderQueue); _renderQueue->clear(); - for (Common::Array::iterator ri = updateRects.begin(); ri != updateRects.end(); ++ri) - _vm->_system->copyRectToScreen((const byte*)_backScreen->getBasePtr((*ri).left, (*ri).top), _backScreen->pitch, (*ri).left, (*ri).top, (*ri).width(), (*ri).height()); - + for (Common::Array::iterator ri = updateRects->begin(); ri != updateRects->end(); ++ri) { + Common::Rect &r = *ri; + _vm->_system->copyRectToScreen((const byte*)_backScreen->getBasePtr(r.left, r.top), _backScreen->pitch, r.left, r.top, r.width(), r.height()); + } + + delete updateRects; + } uint32 Screen::getNextFrameTime() { @@ -120,6 +122,14 @@ int Screen::getFps() { return 1000 / _frameDelay; } +void Screen::setYOffset(int16 yOffset) { + _yOffset = yOffset; +} + +int16 Screen::getYOffset() { + return _yOffset; +} + void Screen::setPaletteData(byte *paletteData) { _paletteChanged = true; _paletteData = paletteData; @@ -194,15 +204,8 @@ void Screen::drawSurface2(const Graphics::Surface *surface, NDrawRect &drawRect, ddRect.y1 = 0; } - //debug(2, "draw: x = %d; y = %d; (%d, %d, %d, %d)", destX, destY, ddRect.x1, ddRect.y1, ddRect.x2, ddRect.y2); - queueBlit(surface, destX, destY, ddRect, transparent, version, shadowSurface); - // Useful for debugging - //_backScreen->frameRect(Common::Rect(clipRect.x1, clipRect.y1, clipRect.x2, clipRect.y2), 250); - //_backScreen->frameRect(Common::Rect(destX, destY, destX + ddRect.x2, destY + ddRect.y2), 255); - //_backScreen->frameRect(Common::Rect(drawRect.x, drawRect.y, drawRect.x + drawRect.width, drawRect.y + drawRect.height), 255); - } void Screen::drawSurface3(const Graphics::Surface *surface, int16 x, int16 y, NDrawRect &drawRect, NRect &clipRect, bool transparent, byte version) { @@ -240,45 +243,6 @@ void Screen::drawSurface3(const Graphics::Surface *surface, int16 x, int16 y, ND } -void Screen::blit(const Graphics::Surface *surface, int16 destX, int16 destY, NRect &ddRect, bool transparent, - const Graphics::Surface *shadowSurface) { - - const byte *source = (const byte*)surface->getBasePtr(ddRect.x1, ddRect.y1); - byte *dest = (byte*)_backScreen->getBasePtr(destX, destY); - int width = ddRect.x2 - ddRect.x1; - int height = ddRect.y2 - ddRect.y1; - - if (width <= 0 || height <= 0) - return; - - if (shadowSurface) { - const byte *shadowSource = (const byte*)shadowSurface->getBasePtr(destX, destY); - while (height--) { - for (int xc = 0; xc < width; xc++) - if (source[xc] != 0) - dest[xc] = shadowSource[xc]; - source += surface->pitch; - shadowSource += shadowSurface->pitch; - dest += _backScreen->pitch; - } - } else if (!transparent) { - while (height--) { - memcpy(dest, source, width); - source += surface->pitch; - dest += _backScreen->pitch; - } - } else { - while (height--) { - for (int xc = 0; xc < width; xc++) - if (source[xc] != 0) - dest[xc] = source[xc]; - source += surface->pitch; - dest += _backScreen->pitch; - } - } - -} - void Screen::drawDoubleSurface2(const Graphics::Surface *surface, NDrawRect &drawRect) { const byte *source = (const byte*)surface->getBasePtr(0, 0); @@ -377,8 +341,8 @@ void Screen::drawSurfaceClipRects(const Graphics::Surface *surface, NDrawRect &d void Screen::queueBlit(const Graphics::Surface *surface, int16 destX, int16 destY, NRect &ddRect, bool transparent, byte version, const Graphics::Surface *shadowSurface) { - int width = ddRect.x2 - ddRect.x1; - int height = ddRect.y2 - ddRect.y1; + const int width = ddRect.x2 - ddRect.x1; + const int height = ddRect.y2 - ddRect.y1; if (width <= 0 || height <= 0) return; @@ -406,7 +370,7 @@ void Screen::blitRenderItem(const RenderItem &renderItem, const Common::Rect &cl const int16 y0 = MAX(clipRect.top, renderItem._destY); const int16 x1 = MIN(clipRect.right, renderItem._destX + renderItem._width); const int16 y1 = MIN(clipRect.bottom, renderItem._destY + renderItem._height); - int16 width = x1 - x0; + const int16 width = x1 - x0; int16 height = y1 - y0; if (width < 0 || height < 0) diff --git a/engines/neverhood/screen.h b/engines/neverhood/screen.h index 4e7618b7b2..33de141ec2 100644 --- a/engines/neverhood/screen.h +++ b/engines/neverhood/screen.h @@ -27,6 +27,7 @@ #include "graphics/surface.h" #include "video/smk_decoder.h" #include "neverhood/neverhood.h" +#include "neverhood/microtiles.h" #include "neverhood/graphics.h" namespace Neverhood { @@ -64,6 +65,8 @@ public: uint32 getNextFrameTime(); void setFps(int fps); int getFps(); + void setYOffset(int16 yOffset); + int16 getYOffset(); void setPaletteData(byte *paletteData); void unsetPaletteData(byte *paletteData); byte *getPaletteData() { return _paletteData; } @@ -75,8 +78,6 @@ public: const Graphics::Surface *shadowSurface = NULL); void drawSurface3(const Graphics::Surface *surface, int16 x, int16 y, NDrawRect &drawRect, NRect &clipRect, bool transparent, byte version); void drawShadowSurface(const Graphics::Surface *surface, const Graphics::Surface *shadowSurface, int16 x, int16 y, NDrawRect &drawRect, NRect &clipRect); - void blit(const Graphics::Surface *surface, int16 destX, int16 destY, NRect &ddRect, bool transparent, - const Graphics::Surface *shadowSurface = NULL); void drawDoubleSurface2(const Graphics::Surface *surface, NDrawRect &drawRect); void drawUnk(const Graphics::Surface *surface, NDrawRect &drawRect, NDrawRect &sysRect, NRect &clipRect, bool transparent, byte version); void drawSurfaceClipRects(const Graphics::Surface *surface, NDrawRect &drawRect, NRect *clipRects, uint clipRectsCount, bool transparent, byte version); @@ -86,13 +87,14 @@ public: void blitRenderItem(const RenderItem &renderItem, const Common::Rect &clipRect); protected: NeverhoodEngine *_vm; + MicroTileArray *_microTiles; Graphics::Surface *_backScreen; Video::SmackerDecoder *_smackerDecoder; int32 _ticks; int32 _frameDelay; byte *_paletteData; bool _paletteChanged; - // + int16 _yOffset; bool _fullRefresh; RenderQueue *_renderQueue, *_prevRenderQueue; }; diff --git a/engines/neverhood/smackerplayer.cpp b/engines/neverhood/smackerplayer.cpp index d7a244ba94..04959b42b0 100644 --- a/engines/neverhood/smackerplayer.cpp +++ b/engines/neverhood/smackerplayer.cpp @@ -44,7 +44,6 @@ void SmackerSurface::setSmackerFrame(const Graphics::Surface *smackerFrame) { _drawRect.y = 0; _drawRect.width = smackerFrame->w; _drawRect.height = smackerFrame->h; - // TODO: Check if _sysRect is needed at all in the reimplementation... _sysRect.x = 0; _sysRect.y = 0; _sysRect.width = (smackerFrame->w + 3) & 0xFFFC; // align by 4 bytes @@ -66,7 +65,7 @@ void SmackerDoubleSurface::draw() { // SmackerPlayer SmackerPlayer::SmackerPlayer(NeverhoodEngine *vm, Scene *scene, uint32 fileHash, bool doubleSurface, bool flag, bool paused) - : Entity(vm, 0), _scene(scene), _doubleSurface(doubleSurface), _dirtyFlag(false), _videoDone(false), _paused(paused), + : Entity(vm, 0), _scene(scene), _doubleSurface(doubleSurface), _videoDone(false), _paused(paused), _palette(NULL), _smackerDecoder(NULL), _smackerSurface(NULL), _stream(NULL), _smackerFirst(true), _drawX(-1), _drawY(-1) { @@ -96,8 +95,6 @@ void SmackerPlayer::open(uint32 fileHash, bool keepLastFrame) { _stream = _vm->_res->createStream(fileHash); - // TODO: _keepLastFrame stuff - _smackerDecoder = new Video::SmackerDecoder(); _smackerDecoder->loadStream(_stream); @@ -164,11 +161,6 @@ void SmackerPlayer::update() { if (!_smackerDecoder) return; - if (_dirtyFlag) { - // TODO _vm->_screen->resetDirtyRects(); - _dirtyFlag = false; - } - if (_paused) { if (_smackerFirst) updateFrame(); @@ -208,13 +200,6 @@ void SmackerPlayer::updateFrame() { _smackerFirst = false; } - if (_doubleSurface) { - // TODO - } - - // TODO _vm->_screen->_skipUpdate = true; - _dirtyFlag = true; - if (_smackerDecoder->hasDirtyPalette()) updatePalette(); diff --git a/engines/neverhood/smackerplayer.h b/engines/neverhood/smackerplayer.h index 63c9ebb774..b4d8ddbe69 100644 --- a/engines/neverhood/smackerplayer.h +++ b/engines/neverhood/smackerplayer.h @@ -73,7 +73,6 @@ protected: Common::SeekableReadStream *_stream; bool _keepLastFrame; bool _videoDone; - bool _dirtyFlag; bool _paused; int _drawX, _drawY; void update(); diff --git a/engines/neverhood/sound.cpp b/engines/neverhood/sound.cpp index 18f40dccaa..52783cc1d3 100644 --- a/engines/neverhood/sound.cpp +++ b/engines/neverhood/sound.cpp @@ -166,7 +166,7 @@ void SoundMan::addMusic(uint32 nameHash, uint32 musicFileHash) { musicItem->_countdown = 24; musicItem->_musicResource = new MusicResource(_vm); musicItem->_musicResource->load(musicFileHash); - _musicItems.push_back(musicItem); + addMusicItem(musicItem); } void SoundMan::deleteMusic(uint32 musicFileHash) { @@ -203,7 +203,7 @@ void SoundMan::stopMusic(uint32 musicFileHash, int16 countdown, int16 fadeVolume void SoundMan::addSound(uint32 nameHash, uint32 soundFileHash) { SoundItem *soundItem = new SoundItem(_vm, nameHash, soundFileHash, false, 50, 600, false, 0, false, 0); - _soundItems.push_back(soundItem); + addSoundItem(soundItem); } void SoundMan::addSoundList(uint32 nameHash, const uint32 *soundFileHashList) { @@ -337,8 +337,6 @@ void SoundMan::deleteMusicGroup(uint32 nameHash) { void SoundMan::deleteSoundGroup(uint32 nameHash) { - SoundItem *soundItem; - if (_soundIndex1 != -1 && _soundItems[_soundIndex1]->_nameHash == nameHash) { deleteSoundByIndex(_soundIndex1); _soundIndex1 = -1; @@ -349,13 +347,9 @@ void SoundMan::deleteSoundGroup(uint32 nameHash) { _soundIndex2 = -1; } - for (uint index = 0; index < _soundItems.size(); ++index) { - soundItem = _soundItems[index]; - if (soundItem && soundItem->_nameHash == nameHash) { - delete soundItem; - _soundItems[index] = NULL; - } - } + for (uint index = 0; index < _soundItems.size(); ++index) + if (_soundItems[index] && _soundItems[index]->_nameHash == nameHash) + deleteSoundByIndex(index); } @@ -384,16 +378,14 @@ void SoundMan::playTwoSounds(uint32 nameHash, uint32 soundFileHash1, uint32 soun soundItem = new SoundItem(_vm, nameHash, soundFileHash1, false, 0, 0, _playOnceAfterCountdown, _initialCountdown, false, currCountdown1); soundItem->_soundResource->setVolume(80); - _soundIndex1 = _soundItems.size(); - _soundItems.push_back(soundItem); + _soundIndex1 = addSoundItem(soundItem); } if (soundFileHash2 != 0) { soundItem = new SoundItem(_vm, nameHash, soundFileHash2, false, 0, 0, _playOnceAfterCountdown, _initialCountdown, false, currCountdown2); soundItem->_soundResource->setVolume(80); - _soundIndex2 = _soundItems.size(); - _soundItems.push_back(soundItem); + _soundIndex2 = addSoundItem(soundItem); } } @@ -410,8 +402,7 @@ void SoundMan::playSoundThree(uint32 nameHash, uint32 soundFileHash) { if (soundFileHash != 0) { soundItem = new SoundItem(_vm, nameHash, soundFileHash, false, 0, 0, false, _initialCountdown3, false, 0); - _soundIndex3 = _soundItems.size(); - _soundItems.push_back(soundItem); + _soundIndex3 = addSoundItem(soundItem); } } @@ -445,15 +436,26 @@ SoundItem *SoundMan::getSoundItemByHash(uint32 soundFileHash) { } int16 SoundMan::addMusicItem(MusicItem *musicItem) { - return 0; // TODO +#if 0 + for (uint i = 0; i < _musicItems.size(); ++i) + if (!_musicItems[i]) { + _musicItems[i] = musicItem; + return i; + } +#endif + int16 musicIndex = _musicItems.size(); + _musicItems.push_back(musicItem); + return musicIndex; } int16 SoundMan::addSoundItem(SoundItem *soundItem) { +#if 0 for (uint i = 0; i < _soundItems.size(); ++i) if (!_soundItems[i]) { _soundItems[i] = soundItem; return i; } +#endif int16 soundIndex = _soundItems.size(); _soundItems.push_back(soundItem); return soundIndex; @@ -541,6 +543,8 @@ int16 AudioResourceMan::addSound(uint32 fileHash) { void AudioResourceMan::removeSound(int16 soundIndex) { AudioResourceManSoundItem *soundItem = _soundItems[soundIndex]; + if (_vm->_mixer->isSoundHandleActive(soundItem->_soundHandle)) + _vm->_mixer->stopHandle(soundItem->_soundHandle); if (soundItem->_data) { _vm->_res->unloadResource(soundItem->_resourceHandle); soundItem->_data = NULL; @@ -549,8 +553,6 @@ void AudioResourceMan::removeSound(int16 soundIndex) { _vm->_res->unuseResource(soundItem->_resourceHandle); soundItem->_resourceHandle = -1; } - if (_vm->_mixer->isSoundHandleActive(soundItem->_soundHandle)) - _vm->_mixer->stopHandle(soundItem->_soundHandle); delete soundItem; _soundItems[soundIndex] = NULL; } @@ -565,6 +567,8 @@ void AudioResourceMan::loadSound(int16 soundIndex) { void AudioResourceMan::unloadSound(int16 soundIndex) { AudioResourceManSoundItem *soundItem = _soundItems[soundIndex]; + if (_vm->_mixer->isSoundHandleActive(soundItem->_soundHandle)) + _vm->_mixer->stopHandle(soundItem->_soundHandle); if (soundItem->_data) { _vm->_res->unloadResource(soundItem->_resourceHandle); soundItem->_data = NULL; diff --git a/engines/neverhood/sprite.cpp b/engines/neverhood/sprite.cpp index d034783b03..1e73078a1b 100644 --- a/engines/neverhood/sprite.cpp +++ b/engines/neverhood/sprite.cpp @@ -21,6 +21,7 @@ */ #include "neverhood/sprite.h" +#include "neverhood/screen.h" namespace Neverhood { @@ -74,13 +75,6 @@ bool Sprite::checkCollision(NRect &rect) { } uint32 Sprite::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { - switch (messageNum) { - case 0x0005: - // TODO: Draw debug marker (?) - // TODO g_Screen->drawLine(_x - 5, _y, _x + 6, _y); - // TODO g_Screen->drawLine(_x, _y - 5, _x, _y + 6); - break; - } return 0; } @@ -93,8 +87,7 @@ void Sprite::createSurface(int surfacePriority, int16 width, int16 height) { } int16 Sprite::defFilterY(int16 y) { - // TODO return y - g_screen->field_26; - return y; + return y - _vm->_screen->getYOffset(); } void Sprite::setClipRect(int16 x1, int16 y1, int16 x2, int16 y2) { -- cgit v1.2.3