diff options
Diffstat (limited to 'engines')
-rw-r--r-- | engines/gob/draw_v1.cpp | 29 | ||||
-rw-r--r-- | engines/gob/draw_v2.cpp | 42 | ||||
-rw-r--r-- | engines/gob/game.cpp | 128 | ||||
-rw-r--r-- | engines/gob/game.h | 169 | ||||
-rw-r--r-- | engines/gob/game_fascin.cpp | 155 | ||||
-rw-r--r-- | engines/gob/game_v1.cpp | 1220 | ||||
-rw-r--r-- | engines/gob/game_v2.cpp | 1344 | ||||
-rw-r--r-- | engines/gob/game_v6.cpp | 1009 | ||||
-rw-r--r-- | engines/gob/hotspots.cpp | 1706 | ||||
-rw-r--r-- | engines/gob/hotspots.h | 177 | ||||
-rw-r--r-- | engines/gob/inter.cpp | 3 | ||||
-rw-r--r-- | engines/gob/inter_v1.cpp | 3 | ||||
-rw-r--r-- | engines/gob/inter_v2.cpp | 61 | ||||
-rw-r--r-- | engines/gob/inter_v6.cpp | 21 | ||||
-rw-r--r-- | engines/gob/module.mk | 3 |
15 files changed, 1958 insertions, 4112 deletions
diff --git a/engines/gob/draw_v1.cpp b/engines/gob/draw_v1.cpp index 94ee32a031..625b738b8a 100644 --- a/engines/gob/draw_v1.cpp +++ b/engines/gob/draw_v1.cpp @@ -33,6 +33,7 @@ #include "gob/util.h" #include "gob/game.h" #include "gob/resources.h" +#include "gob/hotspots.h" #include "gob/scenery.h" #include "gob/inter.h" #include "gob/sound/sound.h" @@ -58,7 +59,6 @@ void Draw_v1::blitCursor() { } void Draw_v1::animateCursor(int16 cursor) { - Game::Collision *ptr; int16 cursorIndex = cursor; int16 newX = 0, newY = 0; uint16 hotspotX = 0, hotspotY = 0; @@ -66,29 +66,10 @@ void Draw_v1::animateCursor(int16 cursor) { _showCursor = 2; if (cursorIndex == -1) { - cursorIndex = 0; - for (ptr = _vm->_game->_collisionAreas; ptr->left != 0xFFFF; ptr++) { - if (ptr->flags & 0xFFF0) - continue; + cursorIndex = + _vm->_game->_hotspots->findCursor(_vm->_global->_inter_mouseX, + _vm->_global->_inter_mouseY); - if (ptr->left > _vm->_global->_inter_mouseX) - continue; - - if (ptr->right < _vm->_global->_inter_mouseX) - continue; - - if (ptr->top > _vm->_global->_inter_mouseY) - continue; - - if (ptr->bottom < _vm->_global->_inter_mouseY) - continue; - - if ((ptr->flags & 0xF) < 3) - cursorIndex = 1; - else - cursorIndex = 3; - break; - } if (_cursorAnimLow[cursorIndex] == -1) cursorIndex = 1; } @@ -317,7 +298,7 @@ void Draw_v1::printTotText(int16 id) { _renderFlags = savedFlags; if (_renderFlags & RENDERFLAG_COLLISIONS) - _vm->_game->checkCollisions(0, 0, 0, 0); + _vm->_game->_hotspots->check(0, 0); if ((_renderFlags & RENDERFLAG_CAPTUREPOP) && *_vm->_scenery->_pCaptureCounter != 0) { (*_vm->_scenery->_pCaptureCounter)--; diff --git a/engines/gob/draw_v2.cpp b/engines/gob/draw_v2.cpp index 2843456f42..e09c565b79 100644 --- a/engines/gob/draw_v2.cpp +++ b/engines/gob/draw_v2.cpp @@ -34,6 +34,7 @@ #include "gob/game.h" #include "gob/script.h" #include "gob/resources.h" +#include "gob/hotspots.h" #include "gob/scenery.h" #include "gob/inter.h" #include "gob/video.h" @@ -82,7 +83,6 @@ void Draw_v2::blitCursor() { } void Draw_v2::animateCursor(int16 cursor) { - Game::Collision *ptr; int16 cursorIndex = cursor; int16 newX = 0, newY = 0; uint16 hotspotX = 0, hotspotY = 0; @@ -91,32 +91,10 @@ void Draw_v2::animateCursor(int16 cursor) { // .-- _draw_animateCursorSUB1 --- if (cursorIndex == -1) { - cursorIndex = 0; - for (ptr = _vm->_game->_collisionAreas; ptr->left != 0xFFFF; ptr++) { - if ((ptr->flags & 0xF00) || (ptr->id & 0x4000)) - continue; - - if (ptr->left > _vm->_global->_inter_mouseX) - continue; - - if (ptr->right < _vm->_global->_inter_mouseX) - continue; - - if (ptr->top > _vm->_global->_inter_mouseY) - continue; - - if (ptr->bottom < _vm->_global->_inter_mouseY) - continue; - - if ((ptr->flags & 0xF000) == 0) { - if ((ptr->flags & 0xF) >= 3) { - cursorIndex = 3; - break; - } else if (((ptr->flags & 0xF0) != 0x10) && (cursorIndex == 0)) - cursorIndex = 1; - } else if (cursorIndex == 0) - cursorIndex = (ptr->flags >> 12) & 0xF; - } + cursorIndex = + _vm->_game->_hotspots->findCursor(_vm->_global->_inter_mouseX, + _vm->_global->_inter_mouseY); + if (_cursorAnimLow[cursorIndex] == -1) cursorIndex = 1; } @@ -407,8 +385,8 @@ void Draw_v2::printTotText(int16 id) { adjustCoords(2, &rectRight, &rectBottom); if (colId != -1) - _vm->_game->addNewCollision(colId + 0xD000, rectLeft, rectTop, - rectRight, rectBottom, 2, 0, 0, 0); + _vm->_game->_hotspots->add(colId + 0xD000, rectLeft, rectTop, + rectRight, rectBottom, (uint16) Hotspots::kTypeClick, 0, 0, 0, 0); if (_needAdjust != 2) printTextCentered(colCmd & 0x0F, rectLeft + 4, rectTop + 4, @@ -501,8 +479,8 @@ void Draw_v2::printTotText(int16 id) { rectBottom = destY + (int16)READ_LE_UINT16(ptr + 6); adjustCoords(2, &rectLeft, &rectTop); adjustCoords(2, &rectRight, &rectBottom); - _vm->_game->addNewCollision(colId + 0x0D000, rectLeft, rectTop, - rectRight, rectBottom, 2, 0, 0, 0); + _vm->_game->_hotspots->add(colId + 0x0D000, rectLeft, rectTop, + rectRight, rectBottom, (uint16) Hotspots::kTypeClick, 0, 0, 0, 0); ptr += 8; } break; @@ -604,7 +582,7 @@ void Draw_v2::printTotText(int16 id) { if (!(_renderFlags & RENDERFLAG_COLLISIONS)) return; - _vm->_game->checkCollisions(0, 0, 0, 0); + _vm->_game->_hotspots->check(0, 0); if (*_vm->_scenery->_pCaptureCounter != 0) { (*_vm->_scenery->_pCaptureCounter)--; diff --git a/engines/gob/game.cpp b/engines/gob/game.cpp index f69b899ce1..b75726cc75 100644 --- a/engines/gob/game.cpp +++ b/engines/gob/game.cpp @@ -33,6 +33,7 @@ #include "gob/variables.h" #include "gob/script.h" #include "gob/resources.h" +#include "gob/hotspots.h" #include "gob/inter.h" #include "gob/draw.h" #include "gob/mult.h" @@ -169,30 +170,14 @@ bool Environments::has(Resources *resources, uint8 startEnv, int16 except) const Game::Game(GobEngine *vm) : _vm(vm) { - _collisionAreas = 0; - _shouldPushColls = 0; - _captureCount = 0; - _collStackSize = 0; - - for (int i = 0; i < 5; i++) { - _collStack[i] = 0; - _collStackElemSizes[i] = 0; - } - _curTotFile[0] = 0; _totToLoad[0] = 0; _startTimeKey = 0; _mouseButtons = kMouseButtonsNone; - _lastCollKey = 0; - _lastCollAreaIndex = 0; - _lastCollId = 0; - - _activeCollResId = 0; - _activeCollIndex = 0; _handleMouse = 0; _forceHandleMouse = 0; _menuLevel = 0; @@ -203,7 +188,6 @@ Game::Game(GobEngine *vm) : _vm(vm) { _noCd = false; _tempStr[0] = 0; - _collStr[0] = 0; _numEnvironments = 0; _curEnvironment = 0; @@ -211,19 +195,14 @@ Game::Game(GobEngine *vm) : _vm(vm) { _environments = new Environments(_vm); _script = new Script(_vm); _resources = new Resources(_vm); + _hotspots = new Hotspots(_vm); } Game::~Game() { delete _environments; delete _script; delete _resources; -} - -void Game::freeCollision(int16 id) { - for (int i = 0; i < 250; i++) { - if (_collisionAreas[i].id == id) - _collisionAreas[i].left = 0xFFFF; - } + delete _hotspots; } void Game::capturePush(int16 left, int16 top, int16 width, int16 height) { @@ -379,21 +358,10 @@ int16 Game::checkKeys(int16 *pMouseX, int16 *pMouseY, return _vm->_util->checkKey(); } -int16 Game::adjustKey(int16 key) { - if (key <= 0x60 || key >= 0x7B) - return key; - - return key - 0x20; -} - void Game::start(void) { - _collisionAreas = new Collision[250]; - memset(_collisionAreas, 0, 250 * sizeof(Collision)); - prepareStart(); playTot(-2); - delete[] _collisionAreas; _vm->_draw->closeScreen(); for (int i = 0; i < SPRITES_COUNT; i++) @@ -430,7 +398,7 @@ void Game::totSub(int8 flags, const char *newTotFile) { return; } - pushCollisions(0); + _hotspots->push(0, true); if (flags & 2) playTot(-1); @@ -440,7 +408,7 @@ void Game::totSub(int8 flags, const char *newTotFile) { if (_vm->_inter->_terminate != 2) _vm->_inter->_terminate = 0; - popCollisions(); + _hotspots->pop(); if ((flags & 1) && _vm->_inter->_variables) { _vm->_inter->delocateVars(); @@ -488,13 +456,13 @@ void Game::switchTotSub(int16 index, int16 skipPlay) { return; } - pushCollisions(0); + _hotspots->push(0, true); playTot(skipPlay); if (_vm->_inter->_terminate != 2) _vm->_inter->_terminate = 0; - popCollisions(); + _hotspots->pop(); clearUnusedEnvironment(); @@ -503,87 +471,6 @@ void Game::switchTotSub(int16 index, int16 skipPlay) { _environments->get(_curEnvironment); } -void Game::setCollisions(byte arg_0) { - uint16 left; - uint16 top; - uint16 width; - uint16 height; - Collision *collArea; - - for (collArea = _collisionAreas; collArea->left != 0xFFFF; collArea++) { - if (((collArea->id & 0xC000) != 0x8000) || (collArea->funcSub == 0)) - continue; - - _script->call(collArea->funcSub); - - left = _script->readValExpr(); - top = _script->readValExpr(); - width = _script->readValExpr(); - height = _script->readValExpr(); - if ((_vm->_draw->_renderFlags & RENDERFLAG_CAPTUREPOP) && - (left != 0xFFFF)) { - left += _vm->_draw->_backDeltaX; - top += _vm->_draw->_backDeltaY; - } - if (_vm->_draw->_needAdjust != 2) { - _vm->_draw->adjustCoords(0, &left, &top); - if ((collArea->flags & 0x0F) < 3) - _vm->_draw->adjustCoords(2, &width, &height); - else { - height &= 0xFFFE; - _vm->_draw->adjustCoords(2, 0, &height); - } - } - collArea->left = left; - collArea->top = top; - collArea->right = left + width - 1; - collArea->bottom = top + height - 1; - - _script->pop(); - } -} - -void Game::collSub(uint16 offset) { - int16 collStackSize; - - _script->call(offset); - - _shouldPushColls = 1; - collStackSize = _collStackSize; - - _vm->_inter->funcBlock(0); - - if (collStackSize != _collStackSize) - popCollisions(); - - _shouldPushColls = 0; - - _script->pop(); - - setCollisions(); -} - -void Game::collAreaSub(int16 index, int8 enter) { - uint16 collId; - - collId = _collisionAreas[index].id & 0xF000; - - if ((collId == 0xA000) || (collId == 0x9000)) { - if (enter == 0) - WRITE_VAR(17, _collisionAreas[index].id & 0x0FFF); - else - WRITE_VAR(17, -(_collisionAreas[index].id & 0x0FFF)); - } - - if (enter != 0) { - if (_collisionAreas[index].funcEnter != 0) - collSub(_collisionAreas[index].funcEnter); - } else { - if (_collisionAreas[index].funcLeave != 0) - collSub(_collisionAreas[index].funcLeave); - } -} - void Game::clearUnusedEnvironment() { if (!_environments->has(_script)) { delete _script; @@ -593,7 +480,6 @@ void Game::clearUnusedEnvironment() { delete _resources; _resources = 0; } - } } // End of namespace Gob diff --git a/engines/gob/game.h b/engines/gob/game.h index eb579d44a4..e6a7a4c089 100644 --- a/engines/gob/game.h +++ b/engines/gob/game.h @@ -33,6 +33,7 @@ namespace Gob { class Script; class Resources; class Variables; +class Hotspots; class Environments { public: @@ -69,37 +70,9 @@ private: class Game { public: - -#include "common/pack-start.h" // START STRUCT PACKING - - struct Collision { - int16 id; - uint16 left; - uint16 top; - uint16 right; - uint16 bottom; - int16 flags; - int16 key; - uint16 funcEnter; - uint16 funcLeave; - uint16 funcSub; - Script *script; - } PACKED_STRUCT; - - struct InputDesc { - int16 fontIndex; - int16 backColor; - int16 frontColor; - byte *ptr; - } PACKED_STRUCT; - -#include "common/pack-end.h" // END STRUCT PACKING - - Collision *_collisionAreas; - Collision *_collStack[5]; - - Script *_script; + Script *_script; Resources *_resources; + Hotspots *_hotspots; char _curTotFile[14]; char _totToLoad[20]; @@ -113,6 +86,9 @@ public: bool _noCd; + byte _handleMouse; + char _forceHandleMouse; + Game(GobEngine *vm); virtual ~Game(); @@ -130,54 +106,19 @@ public: virtual void totSub(int8 flags, const char *newTotFile); virtual void switchTotSub(int16 index, int16 skipPlay); - void freeCollision(int16 id); - virtual void playTot(int16 skipPlay) = 0; - virtual void clearCollisions(void) = 0; - virtual int16 addNewCollision(int16 id, uint16 left, uint16 top, - uint16 right, uint16 bottom, int16 flags, int16 key, - uint16 funcEnter, uint16 funcLeave, uint16 funcSub = 0) = 0; - virtual void collisionsBlock(void) = 0; - virtual int16 multiEdit(int16 time, int16 index, int16 *pCurPos, - InputDesc *inpDesc, int16 *collResId, - int16 *collIndex, bool mono = true) = 0; - virtual int16 inputArea(int16 xPos, int16 yPos, int16 width, int16 height, - int16 backColor, int16 frontColor, char *str, int16 fontIndex, - char inpType, int16 *pTotTime, int16 *collResId, - int16 *collIndex, bool mono = true) = 0; - virtual int16 checkCollisions(byte handleMouse, int16 deltaTime, - int16 *pResId, int16 *pResIndex) = 0; - virtual void prepareStart(void) = 0; - virtual void pushCollisions(char all) = 0; - virtual void popCollisions(void) = 0; - protected: - int16 _lastCollKey; - int16 _lastCollAreaIndex; - int16 _lastCollId; - - int16 _activeCollResId; - int16 _activeCollIndex; - byte _handleMouse; - char _forceHandleMouse; uint32 _menuLevel; char _tempStr[256]; - int16 _collStackSize; - int16 _collStackElemSizes[5]; - - char _shouldPushColls; - // Capture Common::Rect _captureStack[20]; int16 _captureCount; - char _collStr[256]; - // For totSub() int8 _curEnvironment; int8 _numEnvironments; @@ -185,125 +126,41 @@ protected: GobEngine *_vm; - virtual int16 adjustKey(int16 key); - - void collAreaSub(int16 index, int8 enter); - - virtual void setCollisions(byte arg_0 = 1); - virtual void collSub(uint16 offset); - - virtual int16 checkMousePoint(int16 all, int16 *resId, int16 *resIndex) = 0; - void clearUnusedEnvironment(); }; class Game_v1 : public Game { public: - virtual void playTot(int16 skipPlay); - - virtual void clearCollisions(void); - virtual int16 addNewCollision(int16 id, uint16 left, uint16 top, - uint16 right, uint16 bottom, int16 flags, int16 key, - uint16 funcEnter, uint16 funcLeave, uint16 funcSub = 0); - virtual void collisionsBlock(void); - virtual int16 multiEdit(int16 time, int16 index, int16 *pCurPos, - InputDesc *inpDesc, int16 *collResId, - int16 *collIndex, bool mono = true); - virtual int16 inputArea(int16 xPos, int16 yPos, int16 width, int16 height, - int16 backColor, int16 frontColor, char *str, int16 fontIndex, - char inpType, int16 *pTotTime, int16 *collResId, - int16 *collIndex, bool mono = true); - virtual int16 checkCollisions(byte handleMouse, int16 deltaTime, - int16 *pResId, int16 *pResIndex); - - virtual void prepareStart(void); - - virtual void pushCollisions(char all); - virtual void popCollisions(void); - Game_v1(GobEngine *vm); virtual ~Game_v1() {} -protected: - virtual int16 checkMousePoint(int16 all, int16 *resId, int16 *resIndex); -}; - -class Game_v2 : public Game_v1 { -public: virtual void playTot(int16 skipPlay); - virtual void clearCollisions(void); - virtual int16 addNewCollision(int16 id, uint16 left, uint16 top, - uint16 right, uint16 bottom, int16 flags, int16 key, - uint16 funcEnter, uint16 funcLeave, uint16 funcSub = 0); - virtual void collisionsBlock(void); - virtual int16 multiEdit(int16 time, int16 index, int16 *pCurPos, - InputDesc *inpDesc, int16 *collResId, - int16 *collIndex, bool mono = true); - virtual int16 inputArea(int16 xPos, int16 yPos, int16 width, int16 height, - int16 backColor, int16 frontColor, char *str, int16 fontIndex, - char inpType, int16 *pTotTime, int16 *collResId, - int16 *collIndex, bool mono = true); - virtual int16 checkCollisions(byte handleMouse, int16 deltaTime, - int16 *pResId, int16 *pResIndex); - virtual void prepareStart(void); +}; - virtual void pushCollisions(char all); - virtual void popCollisions(void); - +class Game_v2 : public Game_v1 { +public: Game_v2(GobEngine *vm); virtual ~Game_v2() {} -protected: - struct CollLast { - int16 key; - int16 id; - int16 areaIndex; - }; - - CollLast _collLasts[5]; + virtual void playTot(int16 skipPlay); - virtual int16 checkMousePoint(int16 all, int16 *resId, int16 *resIndex); + virtual void prepareStart(void); }; class Game_v6 : public Game_v2 { public: - virtual void totSub(int8 flags, const char *newTotFile); - - virtual int16 addNewCollision(int16 id, uint16 left, uint16 top, - uint16 right, uint16 bottom, int16 flags, int16 key, - uint16 funcEnter, uint16 funcLeave, uint16 funcSub = 0); - - virtual void prepareStart(void); - - virtual void pushCollisions(char all); - - virtual int16 checkCollisions(byte handleMouse, int16 deltaTime, - int16 *pResId, int16 *pResIndex); - virtual void collisionsBlock(void); - Game_v6(GobEngine *vm); virtual ~Game_v6() {} -protected: - uint32 _someTimeDly; - - virtual void setCollisions(byte arg_0 = 1); - virtual void collSub(uint16 offset); - - virtual int16 adjustKey(int16 key); - - virtual int16 checkMousePoint(int16 all, int16 *resId, int16 *resIndex); + virtual void totSub(int8 flags, const char *newTotFile); - void collSubReenter(); + virtual void prepareStart(void); }; class Game_Fascination : public Game_v2 { public: - virtual int16 checkCollisions(byte handleMouse, int16 deltaTime, - int16 *pResId, int16 *pResIndex); - Game_Fascination(GobEngine *vm); virtual ~Game_Fascination() {} }; diff --git a/engines/gob/game_fascin.cpp b/engines/gob/game_fascin.cpp index 1387bf1de1..20480f778f 100644 --- a/engines/gob/game_fascin.cpp +++ b/engines/gob/game_fascin.cpp @@ -45,159 +45,4 @@ namespace Gob { Game_Fascination::Game_Fascination(GobEngine *vm) : Game_v2(vm) { } -int16 Game_Fascination::checkCollisions(byte handleMouse, int16 deltaTime, int16 *pResId, - int16 *pResIndex) { - int16 resIndex; - int16 key; - int16 oldIndex; - int16 oldId; - int16 newkey; - uint32 timeKey; - - _scrollHandleMouse = handleMouse != 0; - - if (deltaTime >= -1) { - _lastCollKey = 0; - _lastCollAreaIndex = 0; - _lastCollId = 0; - } - - if (pResId != 0) - *pResId = 0; - - resIndex = 0; - - if ((_vm->_draw->_cursorIndex == -1) && - (handleMouse != 0) && (_lastCollKey == 0)) { - _lastCollKey = checkMousePoint(1, &_lastCollId, &_lastCollAreaIndex); - - if ((_lastCollKey != 0) && (_lastCollId & 0x8000)) - collAreaSub(_lastCollAreaIndex, 1); - } - - if (handleMouse != 0) { - if ((handleMouse==1) && (_vm->_draw->_renderFlags & RENDERFLAG_UNKNOWN)) - warning("checkCollisions : RENDERFLAG_UNKNOWN - Unknown behavior"); - _vm->_draw->animateCursor(-1); - } - - timeKey = _vm->_util->getTimeKey(); - while (1) { - if (_vm->_inter->_terminate || _vm->shouldQuit()) { - if (handleMouse) - _vm->_draw->blitCursor(); - return 0; - } - - if (!_vm->_draw->_noInvalidated) { - if (handleMouse != 0) - _vm->_draw->animateCursor(-1); - else - _vm->_draw->blitInvalidated(); - _vm->_video->waitRetrace(); - } - - key = checkKeys(&_vm->_global->_inter_mouseX, - &_vm->_global->_inter_mouseY, &_mouseButtons, handleMouse); - - if ((handleMouse == 0) && (_mouseButtons != kMouseButtonsNone)) { - _vm->_util->waitMouseRelease(0); - key = 3; - } - - if (key != 0) { - - if (handleMouse & 1) - _vm->_draw->blitCursor(); - - if (pResId != 0) - *pResId = 0; - - if (pResIndex != 0) - *pResIndex = 0; - - if (_lastCollKey != 0) - collAreaSub(_lastCollAreaIndex, 0); - - _lastCollKey = 0; - if (key != 0) - return key; - } - - if (handleMouse != 0) { - if (_mouseButtons != kMouseButtonsNone) { - if (deltaTime > 0) { - _vm->_draw->animateCursor(2); - _vm->_util->delay(deltaTime); - } else if (handleMouse & 1) - _vm->_util->waitMouseRelease(1); - _vm->_draw->animateCursor(-1); - - if (pResId != 0) - *pResId = 0; - - key = checkMousePoint(0, pResId, &resIndex); - if (pResIndex != 0) - *pResIndex = resIndex; - - if ((key != 0) || ((pResId != 0) && (*pResId != 0))) { - if ((handleMouse & 1) && - ((deltaTime <= 0) || (_mouseButtons == kMouseButtonsNone))) - _vm->_draw->blitCursor(); - - if ((_lastCollKey != 0) && (key != _lastCollKey)) - collAreaSub(_lastCollAreaIndex, 0); - - _lastCollKey = 0; - return key; - } - - if (handleMouse & 4) - return 0; - - if (_lastCollKey != 0) - collAreaSub(_lastCollAreaIndex, 0); - - _lastCollKey = checkMousePoint(1, &_lastCollId, &_lastCollAreaIndex); - if ((_lastCollKey != 0) && (_lastCollId & 0x8000)) - collAreaSub(_lastCollAreaIndex, 1); - } else if ((_vm->_global->_inter_mouseX != _vm->_draw->_cursorX) || - (_vm->_global->_inter_mouseY != _vm->_draw->_cursorY)) { - - oldIndex = _lastCollAreaIndex; - oldId = _lastCollId; - newkey = checkMousePoint(1, &_lastCollId, &_lastCollAreaIndex); - - if (newkey != _lastCollKey) { - if ((_lastCollKey != 0) && (oldId & 0x8000)) - collAreaSub(oldIndex, 0); - - _lastCollKey = newkey; - - if ((newkey != 0) && (_lastCollId & 0x8000)) - collAreaSub(_lastCollAreaIndex, 1); - } - } - } - - if ((deltaTime < 0) && (key == 0) && (_mouseButtons == kMouseButtonsNone)) { - uint32 curtime = _vm->_util->getTimeKey(); - if ((curtime + deltaTime) > timeKey) { - if (pResId != 0) - *pResId = 0; - - if (pResIndex != 0) - *pResIndex = 0; - - return 0; - } - } - - if (handleMouse != 0) - _vm->_draw->animateCursor(-1); - - _vm->_util->delay(10); - } -} - } // End of namespace Gob diff --git a/engines/gob/game_v1.cpp b/engines/gob/game_v1.cpp index ca6a7044cb..5948a21b9c 100644 --- a/engines/gob/game_v1.cpp +++ b/engines/gob/game_v1.cpp @@ -160,294 +160,7 @@ void Game_v1::playTot(int16 skipPlay) { _script->pop(); } -void Game_v1::clearCollisions() { - for (int i = 0; i < 250; i++) { - _collisionAreas[i].id = 0; - _collisionAreas[i].left = 0xFFFF; - } -} - -int16 Game_v1::addNewCollision(int16 id, uint16 left, uint16 top, - uint16 right, uint16 bottom, int16 flags, int16 key, - uint16 funcEnter, uint16 funcLeave, uint16 funcSub) { - Collision *ptr; - - debugC(5, kDebugCollisions, "addNewCollision"); - debugC(5, kDebugCollisions, "id = %X", id); - debugC(5, kDebugCollisions, "left = %d, top = %d, right = %d, bottom = %d", - left, top, right, bottom); - debugC(5, kDebugCollisions, "flags = %X, key = %X", flags, key); - debugC(5, kDebugCollisions, "funcEnter = %d, funcLeave = %d", - funcEnter, funcLeave); - - for (int i = 0; i < 250; i++) { - if (_collisionAreas[i].left != 0xFFFF) - continue; - - ptr = &_collisionAreas[i]; - ptr->id = id; - ptr->left = left; - ptr->top = top; - ptr->right = right; - ptr->bottom = bottom; - ptr->flags = flags; - ptr->key = key; - ptr->funcEnter = funcEnter; - ptr->funcLeave = funcLeave; - ptr->funcSub = funcSub; - ptr->script = 0; - - return i; - } - error("Game_v1::addNewCollision(): Collision array full"); - return 0; -} - -void Game_v1::pushCollisions(char all) { - Collision *srcPtr; - Collision *destPtr; - int16 size; - - debugC(1, kDebugCollisions, "pushCollisions"); - for (size = 0, srcPtr = _collisionAreas; srcPtr->left != 0xFFFF; srcPtr++) { - if (all || (srcPtr->id & 0x8000)) - size++; - } - - destPtr = new Collision[size]; - _collStack[_collStackSize] = destPtr; - _collStackElemSizes[_collStackSize] = size; - _collStackSize++; - - for (srcPtr = _collisionAreas; srcPtr->left != 0xFFFF; srcPtr++) { - if (all || (srcPtr->id & 0x8000)) { - memcpy(destPtr, srcPtr, sizeof(Collision)); - srcPtr->left = 0xFFFF; - destPtr++; - } - } -} - -void Game_v1::popCollisions(void) { - Collision *destPtr; - Collision *srcPtr; - - debugC(1, kDebugCollisions, "popCollision"); - - _collStackSize--; - for (destPtr = _collisionAreas; destPtr->left != 0xFFFF; destPtr++) - ; - - srcPtr = _collStack[_collStackSize]; - memcpy(destPtr, srcPtr, - _collStackElemSizes[_collStackSize] * sizeof(Collision)); - - delete[] _collStack[_collStackSize]; -} - -int16 Game_v1::checkCollisions(byte handleMouse, int16 deltaTime, - int16 *pResId, int16 *pResIndex) { - int16 resIndex; - int16 key; - int16 oldIndex; - int16 oldId; - uint32 timeKey; - bool firstIteration = true; - - if (deltaTime >= -1) { - _lastCollKey = 0; - _lastCollAreaIndex = 0; - _lastCollId = 0; - } - - if (pResId != 0) - *pResId = 0; - - resIndex = 0; - - timeKey = _vm->_util->getTimeKey(); - - if ((_vm->_draw->_cursorIndex == -1) && (handleMouse != 0) && - (_lastCollKey == 0)) { - _lastCollKey = checkMousePoint(1, &_lastCollId, &_lastCollAreaIndex); - - if ((_lastCollKey != 0) && ((_lastCollId & 0x8000) != 0)) { - _script->call(_collisionAreas[_lastCollAreaIndex].funcEnter); - _vm->_inter->funcBlock(0); - _script->pop(); - } - } - - if (handleMouse != 0) - _vm->_draw->animateCursor(-1); - - while (1) { - if (_vm->_inter->_terminate) { - if (handleMouse) - _vm->_draw->blitCursor(); - return 0; - } - - if (!_vm->_draw->_noInvalidated) { - if (handleMouse) - _vm->_draw->animateCursor(-1); - else - _vm->_draw->blitInvalidated(); - } - - // NOTE: the original asm does the below checkKeys call - // _before_ this check. However, that can cause keypresses to get lost - // since there's a return statement in this check. - // Additionally, I added a 'deltaTime == -1' check there, since - // when this function is called with deltaTime == -1 in inputArea, - // and the return value is then discarded. - if (deltaTime < 0) { - uint32 curtime = _vm->_util->getTimeKey(); - if ((deltaTime == -1) || (((curtime + deltaTime) > timeKey) && !firstIteration)) { - if (pResId != 0) - *pResId = 0; - - if (pResIndex != 0) - *pResIndex = 0; - - return 0; - } - } - - key = checkKeys(&_vm->_global->_inter_mouseX, - &_vm->_global->_inter_mouseY, &_mouseButtons, handleMouse); - - if ((handleMouse == 0) && (_mouseButtons != kMouseButtonsNone)) { - _vm->_util->waitMouseRelease(0); - key = 3; - } - - if (key != 0) { - - if (handleMouse == 1) - _vm->_draw->blitCursor(); - - if (pResId != 0) - *pResId = 0; - - if (pResIndex != 0) - *pResIndex = 0; - - if ((_lastCollKey != 0) && - (_collisionAreas[_lastCollAreaIndex].funcLeave != 0)) { - - _script->call(_collisionAreas[_lastCollAreaIndex].funcLeave); - _vm->_inter->funcBlock(0); - _script->pop(); - } - - _lastCollKey = 0; - if (key != 0) - return key; - } - - if (handleMouse != 0) { - if (_mouseButtons != kMouseButtonsNone) { - oldIndex = 0; - - _vm->_draw->animateCursor(2); - if (deltaTime <= 0) { - if (handleMouse == 1) - _vm->_util->waitMouseRelease(1); - } else if (deltaTime > 0) - _vm->_util->delay(deltaTime); - - _vm->_draw->animateCursor(-1); - if (pResId != 0) - *pResId = 0; - - key = checkMousePoint(0, pResId, &resIndex); - - if (pResIndex != 0) - *pResIndex = resIndex; - - if ((key != 0) || ((pResId != 0) && (*pResId != 0))) { - if ((handleMouse == 1) && - ((deltaTime <= 0) || (_mouseButtons == kMouseButtonsNone))) - _vm->_draw->blitCursor(); - - if ((_lastCollKey != 0) && - (_collisionAreas[_lastCollAreaIndex].funcLeave != 0)) { - - _script->call(_collisionAreas[_lastCollAreaIndex].funcLeave); - _vm->_inter->funcBlock(0); - _script->pop(); - - } - _lastCollKey = 0; - return key; - } - - if ((_lastCollKey != 0) && - (_collisionAreas[_lastCollAreaIndex].funcLeave != 0)) { - - _script->call(_collisionAreas[_lastCollAreaIndex].funcLeave); - _vm->_inter->funcBlock(0); - _script->pop(); - - } - - _lastCollKey = - checkMousePoint(1, &_lastCollId, &_lastCollAreaIndex); - - if ((_lastCollKey != 0) && ((_lastCollId & 0x8000) != 0)) { - - _script->call(_collisionAreas[_lastCollAreaIndex].funcEnter); - _vm->_inter->funcBlock(0); - _script->pop(); - - } - } else { - - if ((handleMouse != 0) && - ((_vm->_global->_inter_mouseX != _vm->_draw->_cursorX) || - (_vm->_global->_inter_mouseY != _vm->_draw->_cursorY))) { - oldIndex = _lastCollAreaIndex; - oldId = _lastCollId; - - key = checkMousePoint(1, &_lastCollId, &_lastCollAreaIndex); - - if (key != _lastCollKey) { - if ((_lastCollKey != 0) && ((oldId & 0x8000) != 0)) { - - _script->call(_collisionAreas[oldIndex].funcLeave); - _vm->_inter->funcBlock(0); - _script->pop(); - - } - - _lastCollKey = key; - if ((_lastCollKey != 0) && ((_lastCollId & 0x8000) != 0)) { - - _script->call(_collisionAreas[_lastCollAreaIndex].funcEnter); - _vm->_inter->funcBlock(0); - _script->pop(); - - } - - } - } - } - } - - if (handleMouse != 0) - _vm->_draw->animateCursor(-1); - - if (deltaTime < -10) - _vm->_util->delay(10); - - firstIteration = false; - } -} - void Game_v1::prepareStart(void) { - clearCollisions(); - _vm->_global->_pPaletteDesc->unused2 = _vm->_draw->_unusedPalette2; _vm->_global->_pPaletteDesc->unused1 = _vm->_draw->_unusedPalette1; _vm->_global->_pPaletteDesc->vgaPal = _vm->_draw->_vgaPalette; @@ -489,937 +202,4 @@ void Game_v1::prepareStart(void) { _startTimeKey = _vm->_util->getTimeKey(); } -void Game_v1::collisionsBlock(void) { - InputDesc descArray[20]; - int16 array[250]; - byte count; - int16 collResId; - int16 curCmd; - int16 cmd; - int16 cmdHigh; - int16 key; - int16 flags; - uint16 left; - uint16 top; - uint16 width; - uint16 height; - int16 var_22; - int16 index; - int16 curEditIndex; - int16 deltaTime; - int16 descIndex2; - int16 stackPos2; - int16 descIndex; - int16 timeVal; - char *str; - int16 savedCollStackSize; - int16 i; - int16 counter; - int16 var_24; - int16 var_26; - int16 collStackPos; - Collision *collPtr; - uint32 timeKey; - - if (_shouldPushColls) - pushCollisions(1); - - collResId = -1; - _script->skip(1); - count = _script->readByte(); - _handleMouse = _script->readByte(); - deltaTime = 1000 * _script->readByte(); - descIndex2 = _script->readByte(); - stackPos2 = _script->readByte(); - descIndex = _script->readByte(); - - if ((stackPos2 != 0) || (descIndex != 0)) - deltaTime /= 100; - - timeVal = deltaTime; - _script->skip(1); - - uint32 startPos = _script->pos(); - - WRITE_VAR(16, 0); - var_22 = 0; - index = 0; - curEditIndex = 0; - - for (curCmd = 0; curCmd < count; curCmd++) { - array[curCmd] = 0; - cmd = _script->readByte(); - - if ((cmd & 0x40) != 0) { - cmd -= 0x40; - cmdHigh = _script->readByte(); - cmdHigh <<= 8; - } else - cmdHigh = 0; - - if ((cmd & 0x80) != 0) { - left = _script->readValExpr(); - top = _script->readValExpr(); - width = _script->readValExpr(); - height = _script->readValExpr(); - } else { - left = _script->readUint16(); - top = _script->readUint16(); - width = _script->readUint16(); - height = _script->readUint16(); - } - cmd &= 0x7F; - - debugC(1, kDebugCollisions, "collisionsBlock(%d)", cmd); - - switch (cmd) { - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - - _vm->_util->clearKeyBuf(); - var_22 = 1; - key = _script->readVarIndex(); - descArray[index].fontIndex = _script->readInt16(); - descArray[index].backColor = _script->readByte(); - descArray[index].frontColor = _script->readByte(); - - if ((cmd < 5) || (cmd > 8)) { - descArray[index].ptr = 0; - } else { - descArray[index].ptr = _script->getData() + _script->pos() + 2; - _script->skip(_script->readInt16()); - } - - if (left == 0xFFFF) - break; - - if ((cmd & 1) == 0) { - addNewCollision(curCmd + 0x8000, left, top, left + width * - _vm->_draw->_fonts[descArray[index].fontIndex]->itemWidth - 1, - top + height - 1, cmd, key, 0, _script->pos()); - - _script->skip(_script->peekUint16(2) + 2); - } else { - addNewCollision(curCmd + 0x8000, left, top, left + width * - _vm->_draw->_fonts[descArray[index].fontIndex]->itemWidth - 1, - top + height - 1, cmd, key, 0, 0); - } - index++; - break; - - case 21: - key = _script->readInt16(); - array[curCmd] = _script->readInt16(); - flags = _script->readInt16() & 3; - - addNewCollision(curCmd + 0x8000, left, top, - left + width - 1, top + height - 1, - (flags << 4) + cmdHigh + 2, key, _script->pos(), 0); - - _script->skip(_script->peekUint16(2) + 2); - break; - - case 20: - collResId = curCmd; - // Fall through to case 2 - - case 2: - key = _script->readInt16(); - array[curCmd] = _script->readInt16(); - flags = _script->readInt16() & 3; - - addNewCollision(curCmd + 0x8000, left, top, - left + width - 1, - top + height - 1, - (flags << 4) + cmdHigh + 2, key, 0, _script->pos()); - - _script->skip(_script->peekUint16(2) + 2); - break; - - case 0: - _script->skip(6); - startPos = _script->pos(); - _script->skip(_script->peekUint16(2) + 2); - key = curCmd + 0xA000; - - addNewCollision(curCmd + 0x8000, left, top, - left + width - 1, top + height - 1, - cmd + cmdHigh, key, - startPos, _script->pos()); - - _script->skip(_script->peekUint16(2) + 2); - break; - - case 1: - key = _script->readInt16(); - array[curCmd] = _script->readInt16(); - flags = _script->readInt16() & 3; - - startPos = _script->pos(); - _script->skip(_script->peekUint16(2) + 2); - if (key == 0) - key = curCmd + 0xA000; - - addNewCollision(curCmd + 0x8000, left, top, - left + width - 1, top + height - 1, - (flags << 4) + cmd + cmdHigh, key, - startPos, _script->pos()); - - _script->skip(_script->peekUint16(2) + 2); - break; - } - } - - _forceHandleMouse = 0; - _vm->_util->clearKeyBuf(); - - do { - if (var_22 != 0) { - key = multiEdit(deltaTime, index, &curEditIndex, - descArray, &_activeCollResId, &_activeCollIndex); - - if (key == kKeyReturn) { - for (i = 0; i < 250; i++) { - if (_collisionAreas[i].left == 0xFFFF) - continue; - - if ((_collisionAreas[i].id & 0x8000) == 0) - continue; - - if ((_collisionAreas[i].flags & 1) != 0) - continue; - - if ((_collisionAreas[i].flags & 0x0F) <= 2) - continue; - - collResId = _collisionAreas[i].id; - _activeCollResId = collResId; - collResId &= 0x7FFF; - _activeCollIndex = i; - break; - } - break; - } - } else - key = checkCollisions(_handleMouse, -deltaTime, - &_activeCollResId, &_activeCollIndex); - - if (((key & 0xFF) >= ' ') && ((key & 0xFF) <= 0xFF) && - ((key >> 8) > 1) && ((key >> 8) < 12)) - key = '0' + (((key >> 8) - 1) % 10) + (key & 0xFF00); - - if (_activeCollResId == 0) { - if (key != 0) { - for (i = 0; i < 250; i++) { - if (_collisionAreas[i].left == 0xFFFF) - continue; - - if ((_collisionAreas[i].id & 0x8000) == 0) - continue; - - if ((_collisionAreas[i].key == key) || - (_collisionAreas[i].key == 0x7FFF)) { - - _activeCollResId = _collisionAreas[i].id; - _activeCollIndex = i; - break; - } - } - - if (_activeCollResId == 0) { - for (i = 0; i < 250; i++) { - if (_collisionAreas[i].left == 0xFFFF) - continue; - - if ((_collisionAreas[i].id & 0x8000) == 0) - continue; - - if ((_collisionAreas[i].key & 0xFF00) != 0) - continue; - - if (_collisionAreas[i].key == 0) - continue; - - if ((adjustKey(key & 0xFF) == adjustKey(_collisionAreas[i].key)) || - (_collisionAreas[i].key == 0x7FFF)) { - _activeCollResId = _collisionAreas[i].id; - _activeCollIndex = i; - break; - } - } - } - } else { - - if ((deltaTime != 0) && (VAR(16) == 0)) { - if (stackPos2 != 0) { - collStackPos = 0; - collPtr = _collisionAreas; - - for (i = 0, collPtr = _collisionAreas; - collPtr->left != 0xFFFF; i++, collPtr++) { - - if ((collPtr->id & 0x8000) == 0) - continue; - - collStackPos++; - if (collStackPos != stackPos2) - continue; - - _activeCollResId = collPtr->id; - _activeCollIndex = i; - WRITE_VAR(2, _vm->_global->_inter_mouseX); - WRITE_VAR(3, _vm->_global->_inter_mouseY); - WRITE_VAR(4, (uint32) _mouseButtons); - WRITE_VAR(16, array[(uint16) _activeCollResId & ~0x8000]); - - if (collPtr->funcLeave != 0) { - timeKey = _vm->_util->getTimeKey(); - - uint32 savedPos = _script->pos(); - - _script->seek(collPtr->funcLeave); - - _shouldPushColls = 1; - savedCollStackSize = _collStackSize; - _vm->_inter->funcBlock(0); - - if (savedCollStackSize != _collStackSize) - popCollisions(); - - _shouldPushColls = 0; - - _script->seek(savedPos); - - deltaTime = timeVal - - (_vm->_util->getTimeKey() - timeKey); - - if (deltaTime < 2) - deltaTime = 2; - } - - if (VAR(16) == 0) - _activeCollResId = 0; - break; - } - } else { - if (descIndex != 0) { - counter = 0; - for (i = 0; i < 250; i++) { - if (_collisionAreas[i].left == 0xFFFF) - continue; - - if ((_collisionAreas[i].id & 0x8000) == 0) - continue; - - counter++; - if (counter != descIndex) - continue; - - _activeCollResId = _collisionAreas[i].id; - _activeCollIndex = i; - break; - } - } else { - for (i = 0; i < 250; i++) { - if (_collisionAreas[i].left == 0xFFFF) - continue; - - if ((_collisionAreas[i].id & 0x8000) == 0) - continue; - - _activeCollResId = _collisionAreas[i].id; - _activeCollIndex = i; - break; - } - } - } - } else { - if (descIndex2 != 0) { - counter = 0; - for (i = 0; i < 250; i++) { - if (_collisionAreas[i].left == 0xFFFF) - continue; - - if ((_collisionAreas[i].id & 0x8000) == 0) - continue; - - counter++; - if (counter != descIndex2) - continue; - - _activeCollResId = _collisionAreas[i].id; - _activeCollIndex = i; - break; - } - } - } - } - } - - if (_activeCollResId == 0) - continue; - - if (_collisionAreas[_activeCollIndex].funcLeave != 0) - continue; - - WRITE_VAR(2, _vm->_global->_inter_mouseX); - WRITE_VAR(3, _vm->_global->_inter_mouseY); - WRITE_VAR(4, (uint32) _mouseButtons); - WRITE_VAR(16, array[(uint16) _activeCollResId & ~0x8000]); - - if (_collisionAreas[_activeCollIndex].funcEnter != 0) { - uint32 savedPos = _script->pos(); - - _script->seek(_collisionAreas[_activeCollIndex].funcEnter); - - _shouldPushColls = 1; - - collStackPos = _collStackSize; - _vm->_inter->funcBlock(0); - if (collStackPos != _collStackSize) - popCollisions(); - _shouldPushColls = 0; - - _script->seek(savedPos); - } - - WRITE_VAR(16, 0); - _activeCollResId = 0; - } - while ((_activeCollResId == 0) && !_vm->_inter->_terminate && !_vm->shouldQuit()); - - if (((uint16) _activeCollResId & ~0x8000) == collResId) { - collStackPos = 0; - var_24 = 0; - var_26 = 1; - for (i = 0; i < 250; i++) { - if (_collisionAreas[i].left == 0xFFFF) - continue; - - if ((_collisionAreas[i].id & 0x8000) == 0) - continue; - - if ((_collisionAreas[i].flags & 0x0F) < 3) - continue; - - if ((_collisionAreas[i].flags & 0x0F) > 10) - continue; - - if ((_collisionAreas[i].flags & 0x0F) > 8) { - char *ptr; - strncpy0(_tempStr, GET_VARO_STR(_collisionAreas[i].key), 255); - while ((ptr = strchr(_tempStr, ' ')) != 0) { - _vm->_util->cutFromStr(_tempStr, (ptr - _tempStr), 1); - ptr = strchr(_tempStr, ' '); - } - WRITE_VARO_STR(_collisionAreas[i].key, _tempStr); - } - - if (((_collisionAreas[i].flags & 0x0F) >= 5) && - ((_collisionAreas[i].flags & 0x0F) <= 8)) { - str = (char *) descArray[var_24].ptr; - - strncpy0(_tempStr, GET_VARO_STR(_collisionAreas[i].key), 255); - - if ((_collisionAreas[i].flags & 0x0F) < 7) - _vm->_util->cleanupStr(_tempStr); - - int16 pos = 0; - do { - strncpy0(_collStr, str, 255); - pos += strlen(str) + 1; - - str += strlen(str) + 1; - - if ((_collisionAreas[i].flags & 0x0F) < 7) - _vm->_util->cleanupStr(_collStr); - - if (strcmp(_tempStr, _collStr) == 0) { - WRITE_VAR(17, VAR(17) + 1); - WRITE_VAR(17 + var_26, 1); - break; - } - } while (READ_LE_UINT16(descArray[var_24].ptr - 2) > pos); - collStackPos++; - } else { - WRITE_VAR(17 + var_26, 2); - } - var_24++; - var_26++; - } - - if (collStackPos != (int16) VAR(17)) - WRITE_VAR(17, 0); - else - WRITE_VAR(17, 1); - } - - if (!_vm->_inter->_terminate) { - _script->seek(_collisionAreas[_activeCollIndex].funcLeave); - - WRITE_VAR(2, _vm->_global->_inter_mouseX); - WRITE_VAR(3, _vm->_global->_inter_mouseY); - WRITE_VAR(4, (uint32) _mouseButtons); - - if (VAR(16) == 0) - WRITE_VAR(16, array[(uint16) _activeCollResId & ~0x8000]); - } else - _script->setFinished(true); - - for (curCmd = 0; curCmd < count; curCmd++) - freeCollision(curCmd + 0x8000); -} - -int16 Game_v1::multiEdit(int16 time, int16 index, int16 *pCurPos, - InputDesc * inpDesc, int16 *collResId, int16 *collIndex, bool mono) { - Collision *collArea; - int16 descInd; - int16 key; - int16 found = -1; - int16 i; - - descInd = 0; - for (i = 0; i < 250; i++) { - collArea = &_collisionAreas[i]; - - if (collArea->left == 0xFFFF) - continue; - - if ((collArea->id & 0x8000) == 0) - continue; - - if ((collArea->flags & 0x0F) < 3) - continue; - - if ((collArea->flags & 0x0F) > 10) - continue; - - strncpy0(_tempStr, GET_VARO_STR(collArea->key), 255); - - _vm->_draw->_destSpriteX = collArea->left; - _vm->_draw->_destSpriteY = collArea->top; - _vm->_draw->_spriteRight = collArea->right - collArea->left + 1; - _vm->_draw->_spriteBottom = collArea->bottom - collArea->top + 1; - - _vm->_draw->_destSurface = 21; - - _vm->_draw->_backColor = inpDesc[descInd].backColor; - _vm->_draw->_frontColor = inpDesc[descInd].frontColor; - _vm->_draw->_textToPrint = _tempStr; - _vm->_draw->_transparency = 1; - _vm->_draw->_fontIndex = inpDesc[descInd].fontIndex; - _vm->_draw->spriteOperation(DRAW_FILLRECT); - _vm->_draw->_destSpriteY += - ((collArea->bottom - collArea->top + 1) - 8) / 2; - - _vm->_draw->spriteOperation(DRAW_PRINTTEXT); - descInd++; - } - - for (i = 0; i < 40; i++) - WRITE_VAR_OFFSET(i * 4 + 0x44, 0); - - while (1) { - descInd = 0; - - for (i = 0; i < 250; i++) { - collArea = &_collisionAreas[i]; - - if (collArea->left == 0xFFFF) - continue; - - if ((collArea->id & 0x8000) == 0) - continue; - - if ((collArea->flags & 0x0F) < 3) - continue; - - if ((collArea->flags & 0x0F) > 10) - continue; - - if (descInd == *pCurPos) { - found = i; - break; - } - - descInd++; - } - - assert(found != -1); - - collArea = &_collisionAreas[found]; - - key = inputArea(collArea->left, collArea->top, - collArea->right - collArea->left + 1, - collArea->bottom - collArea->top + 1, - inpDesc[*pCurPos].backColor, inpDesc[*pCurPos].frontColor, - GET_VARO_STR(collArea->key), inpDesc[*pCurPos].fontIndex, - collArea->flags, &time, collResId, collIndex); - - if (_vm->_inter->_terminate) - return 0; - - switch (key) { - case kKeyNone: - if (*collResId == 0) - return 0; - - if ((_collisionAreas[*collIndex].flags & 0x0F) < 3) - return 0; - - if ((_collisionAreas[*collIndex].flags & 0x0F) > 10) - return 0; - - *pCurPos = 0; - for (i = 0; i < 250; i++) { - collArea = &_collisionAreas[i]; - - if (collArea->left == 0xFFFF) - continue; - - if ((collArea->id & 0x8000) == 0) - continue; - - if ((collArea->flags & 0x0F) < 3) - continue; - - if ((collArea->flags & 0x0F) > 10) - continue; - - if (i == *collIndex) - break; - - pCurPos[0]++; - } - break; - - case kKeyF1: - case kKeyF2: - case kKeyF3: - case kKeyF4: - case kKeyF5: - case kKeyF6: - case kKeyF7: - case kKeyF8: - case kKeyF9: - case kKeyF10: - return key; - - case kKeyReturn: - - if (index == 1) - return key; - - if (*pCurPos == index - 1) { - *pCurPos = 0; - break; - } - - pCurPos[0]++; - break; - - case kKeyDown: - if (index - 1 > *pCurPos) - pCurPos[0]++; - break; - - case kKeyUp: - if (*pCurPos > 0) - pCurPos[0]--; - break; - } - } -} - -int16 Game_v1::inputArea(int16 xPos, int16 yPos, int16 width, int16 height, - int16 backColor, int16 frontColor, char *str, int16 fontIndex, - char inpType, int16 *pTotTime, int16 *collResId, int16 *collIndex, bool mono) { - int16 handleMouse; - uint32 editSize; - Video::FontDesc *pFont; - char curSym; - int16 key; - const char *str1; - const char *str2; - int16 i; - uint32 pos; - int16 flag; - int16 savedKey; - - if ((_handleMouse != 0) && - ((_vm->_global->_useMouse != 0) || (_forceHandleMouse != 0))) - handleMouse = 1; - else - handleMouse = 0; - - pos = strlen(str); - pFont = _vm->_draw->_fonts[fontIndex]; - editSize = width / pFont->itemWidth; - - while (1) { - strncpy0(_tempStr, str, 254); - strcat(_tempStr, " "); - if (strlen(_tempStr) > editSize) - strncpy0(_tempStr, str, 255); - - _vm->_draw->_destSpriteX = xPos; - _vm->_draw->_destSpriteY = yPos; - _vm->_draw->_spriteRight = editSize * pFont->itemWidth; - _vm->_draw->_spriteBottom = height; - - _vm->_draw->_destSurface = 21; - _vm->_draw->_backColor = backColor; - _vm->_draw->_frontColor = frontColor; - _vm->_draw->_textToPrint = _tempStr; - _vm->_draw->_transparency = 1; - _vm->_draw->_fontIndex = fontIndex; - _vm->_draw->spriteOperation(DRAW_FILLRECT); - - _vm->_draw->_destSpriteY = yPos + (height - 8) / 2; - - _vm->_draw->spriteOperation(DRAW_PRINTTEXT); - if (pos == editSize) - pos--; - - curSym = _tempStr[pos]; - - flag = 1; - - while (1) { - _tempStr[0] = curSym; - _tempStr[1] = 0; - - _vm->_draw->_destSpriteX = xPos + pFont->itemWidth * pos; - _vm->_draw->_destSpriteY = yPos + height - 1; - _vm->_draw->_spriteRight = pFont->itemWidth; - _vm->_draw->_spriteBottom = 1; - _vm->_draw->_destSurface = 21; - _vm->_draw->_backColor = frontColor; - _vm->_draw->spriteOperation(DRAW_FILLRECT); - - if (flag != 0) - key = checkCollisions(handleMouse, -1, collResId, collIndex); - flag = 0; - - key = checkCollisions(handleMouse, -300, collResId, collIndex); - - if (*pTotTime > 0) { - *pTotTime -= 300; - if (*pTotTime <= 1) { - key = 0; - *collResId = 0; - break; - } - } - - _tempStr[0] = curSym; - _tempStr[1] = 0; - _vm->_draw->_destSpriteX = xPos + pFont->itemWidth * pos; - _vm->_draw->_destSpriteY = yPos + height - 1; - _vm->_draw->_spriteRight = pFont->itemWidth; - _vm->_draw->_spriteBottom = 1; - _vm->_draw->_destSurface = 21; - _vm->_draw->_backColor = backColor; - _vm->_draw->_frontColor = frontColor; - _vm->_draw->_textToPrint = _tempStr; - _vm->_draw->_transparency = 1; - _vm->_draw->spriteOperation(DRAW_FILLRECT); - - _vm->_draw->_destSpriteY = yPos + (height - 8) / 2; - _vm->_draw->spriteOperation(DRAW_PRINTTEXT); - - if ((key != 0) || (*collResId != 0)) - break; - - key = checkCollisions(handleMouse, -300, collResId, collIndex); - - if (*pTotTime > 0) { - *pTotTime -= 300; - if (*pTotTime <= 1) { - key = 0; - *collResId = 0; - break; - } - } - - if ((key != 0) || (*collResId != 0)) - break; - - if (_vm->_inter->_terminate) - return 0; - } - - if ((key == 0) || (*collResId != 0) || _vm->_inter->_terminate) - return 0; - - switch (key) { - case kKeyRight: - if ((pos < strlen(str)) && (pos < (editSize - 1))) { - pos++; - continue; - } - return kKeyDown; - - case kKeyLeft: - if (pos > 0) { - pos--; - continue; - } - return kKeyUp; - - case kKeyBackspace: - if (pos > 0) { - _vm->_util->cutFromStr(str, pos - 1, 1); - pos--; - continue; - } - - case kKeyDelete: - if (pos >= strlen(str)) - continue; - - _vm->_util->cutFromStr(str, pos, 1); - continue; - - case kKeyReturn: - case kKeyF1: - case kKeyF2: - case kKeyF3: - case kKeyF4: - case kKeyF5: - case kKeyF6: - case kKeyF7: - case kKeyF8: - case kKeyF9: - case kKeyF10: - case kKeyUp: - case kKeyDown: - return key; - - case kKeyEscape: - if (_vm->_global->_useMouse != 0) - continue; - - _forceHandleMouse = !_forceHandleMouse; - - if ((_handleMouse != 0) && - ((_vm->_global->_useMouse != 0) || (_forceHandleMouse != 0))) - handleMouse = 1; - else - handleMouse = 0; - - if (_vm->_global->_pressedKeys[1] == 0) - continue; - - while (_vm->_global->_pressedKeys[1] != 0) - ; - continue; - - default: - - savedKey = key; - key &= 0xFF; - - if (((inpType == 9) || (inpType == 10)) && - (key >= ' ') && (key <= 0xFF)) { - str1 = "0123456789-.,+ "; - str2 = "0123456789-,,+ "; - - if (((savedKey >> 8) > 1) && ((savedKey >> 8) < 12)) - key = ((savedKey >> 8) - 1) % 10 + '0'; - - for (i = 0; str1[i] != 0; i++) { - if (key == str1[i]) { - key = str2[i]; - break; - } - } - - if (i == (int16) strlen(str1)) - key = 0; - } - - if ((key >= ' ') && (key <= 0xFF)) { - if (editSize == strlen(str)) - _vm->_util->cutFromStr(str, strlen(str) - 1, 1); - - if ((key >= 'a') && (key <= 'z')) - key += ('A' - 'a'); - - pos++; - _tempStr[0] = key; - _tempStr[1] = 0; - - _vm->_util->insertStr(_tempStr, str, pos - 1); - } - - } - } -} - -int16 Game_v1::checkMousePoint(int16 all, int16 *resId, int16 *resIndex) { - Collision *ptr; - int16 i; - - if (resId != 0) - *resId = 0; - - *resIndex = 0; - - ptr = _collisionAreas; - for (i = 0; ptr->left != 0xFFFF; ptr++, i++) { - if (all) { - if ((ptr->flags & 0xF) > 1) - continue; - - if ((ptr->flags & 0xFF00) != 0) - continue; - - if ((_vm->_global->_inter_mouseX < ptr->left) || - (_vm->_global->_inter_mouseX > ptr->right) || - (_vm->_global->_inter_mouseY < ptr->top) || - (_vm->_global->_inter_mouseY > ptr->bottom)) - continue; - - if (resId != 0) - *resId = ptr->id; - - *resIndex = i; - return ptr->key; - } else { - if ((ptr->flags & 0xFF00) != 0) - continue; - - if (((ptr->flags & 0xF) != 1) && ((ptr->flags & 0xF) != 2)) - continue; - - if ((((ptr->flags & 0xF0) >> 4) != (((int32) _mouseButtons) - 1)) - && (((ptr->flags & 0xF0) >> 4) != 2)) - continue; - - if ((_vm->_global->_inter_mouseX < ptr->left) || - (_vm->_global->_inter_mouseX > ptr->right) || - (_vm->_global->_inter_mouseY < ptr->top) || - (_vm->_global->_inter_mouseY > ptr->bottom)) - continue; - - if (resId != 0) - *resId = ptr->id; - *resIndex = i; - return ptr->key; - } - } - - if ((_mouseButtons != kMouseButtonsLeft) && (all == 0)) - return kKeyEscape; - - return 0; -} - } // End of namespace Gob diff --git a/engines/gob/game_v2.cpp b/engines/gob/game_v2.cpp index db4e87287f..9cc4da3cc9 100644 --- a/engines/gob/game_v2.cpp +++ b/engines/gob/game_v2.cpp @@ -179,268 +179,7 @@ void Game_v2::playTot(int16 skipPlay) { _script->pop(); } -void Game_v2::clearCollisions() { - _lastCollKey = 0; - - for (int i = 0; i < 150; i++) - _collisionAreas[i].left = 0xFFFF; -} - -int16 Game_v2::addNewCollision(int16 id, uint16 left, uint16 top, - uint16 right, uint16 bottom, int16 flags, int16 key, - uint16 funcEnter, uint16 funcLeave, uint16 funcSub) { - Collision *ptr; - - debugC(5, kDebugCollisions, "addNewCollision"); - debugC(5, kDebugCollisions, "id = %X", id); - debugC(5, kDebugCollisions, "left = %d, top = %d, right = %d, bottom = %d", - left, top, right, bottom); - debugC(5, kDebugCollisions, "flags = %X, key = %X", flags, key); - debugC(5, kDebugCollisions, "funcEnter = %d, funcLeave = %d", - funcEnter, funcLeave); - - for (int i = 0; i < 150; i++) { - if ((_collisionAreas[i].left != 0xFFFF) && (_collisionAreas[i].id != id)) - continue; - - ptr = &_collisionAreas[i]; - ptr->id = id; - ptr->left = left; - ptr->top = top; - ptr->right = right; - ptr->bottom = bottom; - ptr->flags = flags; - ptr->key = key; - ptr->funcEnter = funcEnter; - ptr->funcLeave = funcLeave; - ptr->funcSub = funcSub; - ptr->script = 0; - - return i; - } - error("Game_v2::addNewCollision(): Collision array full"); - return 0; -} - -void Game_v2::pushCollisions(char all) { - Collision *srcPtr; - Collision *destPtr; - int16 size; - - debugC(1, kDebugCollisions, "pushCollisions"); - for (size = 0, srcPtr = _collisionAreas; srcPtr->left != 0xFFFF; srcPtr++) - if (all || (((uint16) srcPtr->id) >= 20)) - size++; - - destPtr = new Collision[size]; - _collStack[_collStackSize] = destPtr; - - if (_vm->_inter->_terminate) - return; - - _collStackElemSizes[_collStackSize] = size; - - if (_shouldPushColls != 0) - _collStackElemSizes[_collStackSize] |= 0x8000; - - _shouldPushColls = 0; - _collLasts[_collStackSize].key = _lastCollKey; - _collLasts[_collStackSize].id = _lastCollId; - _collLasts[_collStackSize].areaIndex = _lastCollAreaIndex; - _lastCollKey = 0; - _lastCollId = 0; - _lastCollAreaIndex = 0; - _collStackSize++; - - for (srcPtr = _collisionAreas; srcPtr->left != 0xFFFF; srcPtr++) { - if (all || (((uint16) srcPtr->id) >= 20)) { - memcpy(destPtr, srcPtr, sizeof(Collision)); - srcPtr->left = 0xFFFF; - destPtr++; - } - } -} - -void Game_v2::popCollisions(void) { - Collision *destPtr; - Collision *srcPtr; - - debugC(1, kDebugCollisions, "popCollision"); - - _collStackSize--; - - _shouldPushColls = _collStackElemSizes[_collStackSize] & 0x8000 ? 1 : 0; - _collStackElemSizes[_collStackSize] &= 0x7FFF; - - _lastCollKey = _collLasts[_collStackSize].key; - _lastCollId = _collLasts[_collStackSize].id; - _lastCollAreaIndex = _collLasts[_collStackSize].areaIndex; - - for (destPtr = _collisionAreas; destPtr->left != 0xFFFF; destPtr++) - ; - - srcPtr = _collStack[_collStackSize]; - memcpy(destPtr, srcPtr, - _collStackElemSizes[_collStackSize] * sizeof(Collision)); - - delete[] _collStack[_collStackSize]; -} - -int16 Game_v2::checkCollisions(byte handleMouse, int16 deltaTime, int16 *pResId, - int16 *pResIndex) { - int16 resIndex; - int16 key; - int16 oldIndex; - int16 oldId; - int16 newkey; - uint32 timeKey; - - _scrollHandleMouse = handleMouse != 0; - - if (deltaTime >= -1) { - _lastCollKey = 0; - _lastCollAreaIndex = 0; - _lastCollId = 0; - } - - if (pResId != 0) - *pResId = 0; - - resIndex = 0; - - if ((_vm->_draw->_cursorIndex == -1) && - (handleMouse != 0) && (_lastCollKey == 0)) { - _lastCollKey = checkMousePoint(1, &_lastCollId, &_lastCollAreaIndex); - - if ((_lastCollKey != 0) && (_lastCollId & 0x8000)) - collAreaSub(_lastCollAreaIndex, 1); - } - - if (handleMouse != 0) - _vm->_draw->animateCursor(-1); - - timeKey = _vm->_util->getTimeKey(); - while (1) { - if (_vm->_inter->_terminate || _vm->shouldQuit()) { - if (handleMouse) - _vm->_draw->blitCursor(); - return 0; - } - - if (!_vm->_draw->_noInvalidated) { - if (handleMouse != 0) - _vm->_draw->animateCursor(-1); - else - _vm->_draw->blitInvalidated(); - _vm->_video->waitRetrace(); - } - - key = checkKeys(&_vm->_global->_inter_mouseX, - &_vm->_global->_inter_mouseY, &_mouseButtons, handleMouse); - - if ((handleMouse == 0) && (_mouseButtons != kMouseButtonsNone)) { - _vm->_util->waitMouseRelease(0); - key = 3; - } - - if (key != 0) { - - if (handleMouse & 1) - _vm->_draw->blitCursor(); - - if (pResId != 0) - *pResId = 0; - - if (pResIndex != 0) - *pResIndex = 0; - - if (_lastCollKey != 0) - collAreaSub(_lastCollAreaIndex, 0); - - _lastCollKey = 0; - if (key != 0) - return key; - } - - if (handleMouse != 0) { - if (_mouseButtons != kMouseButtonsNone) { - if (deltaTime > 0) { - _vm->_draw->animateCursor(2); - _vm->_util->delay(deltaTime); - } else if (handleMouse & 1) - _vm->_util->waitMouseRelease(1); - _vm->_draw->animateCursor(-1); - - if (pResId != 0) - *pResId = 0; - - key = checkMousePoint(0, pResId, &resIndex); - if (pResIndex != 0) - *pResIndex = resIndex; - - if ((key != 0) || ((pResId != 0) && (*pResId != 0))) { - if ((handleMouse & 1) && - ((deltaTime <= 0) || (_mouseButtons == kMouseButtonsNone))) - _vm->_draw->blitCursor(); - - if ((_lastCollKey != 0) && (key != _lastCollKey)) - collAreaSub(_lastCollAreaIndex, 0); - - _lastCollKey = 0; - return key; - } - - if (handleMouse & 4) - return 0; - - if (_lastCollKey != 0) - collAreaSub(_lastCollAreaIndex, 0); - - _lastCollKey = checkMousePoint(1, &_lastCollId, &_lastCollAreaIndex); - if ((_lastCollKey != 0) && (_lastCollId & 0x8000)) - collAreaSub(_lastCollAreaIndex, 1); - } else if ((_vm->_global->_inter_mouseX != _vm->_draw->_cursorX) || - (_vm->_global->_inter_mouseY != _vm->_draw->_cursorY)) { - - oldIndex = _lastCollAreaIndex; - oldId = _lastCollId; - newkey = checkMousePoint(1, &_lastCollId, &_lastCollAreaIndex); - - if (newkey != _lastCollKey) { - if ((_lastCollKey != 0) && (oldId & 0x8000)) - collAreaSub(oldIndex, 0); - - _lastCollKey = newkey; - - if ((newkey != 0) && (_lastCollId & 0x8000)) - collAreaSub(_lastCollAreaIndex, 1); - } - } - } - - if ((deltaTime < 0) && (key == 0) && (_mouseButtons == kMouseButtonsNone)) { - uint32 curtime = _vm->_util->getTimeKey(); - if ((curtime + deltaTime) > timeKey) { - if (pResId != 0) - *pResId = 0; - - if (pResIndex != 0) - *pResIndex = 0; - - return 0; - } - } - - if (handleMouse != 0) - _vm->_draw->animateCursor(-1); - - _vm->_util->delay(10); - } -} - void Game_v2::prepareStart(void) { - clearCollisions(); - _vm->_global->_pPaletteDesc->unused2 = _vm->_draw->_unusedPalette2; _vm->_global->_pPaletteDesc->unused1 = _vm->_draw->_unusedPalette1; _vm->_global->_pPaletteDesc->vgaPal = _vm->_draw->_vgaPalette; @@ -476,1087 +215,4 @@ void Game_v2::prepareStart(void) { _startTimeKey = _vm->_util->getTimeKey(); } -void Game_v2::collisionsBlock(void) { - InputDesc descArray[20]; - int16 array[250]; - byte count; - int16 collResId; - int16 curCmd; - int16 cmd; - int16 cmdHigh; - int16 key; - int16 flags; - uint16 left; - uint16 top; - uint16 width; - uint16 height; - int16 var_1C; - int16 index; - int16 curEditIndex; - int16 deltaTime; - int16 stackPos2; - int16 descIndex; - int16 timeVal; - char *str; - int16 i; - int16 counter; - int16 var_24; - int16 var_26; - int16 collStackPos; - Collision *collPtr; - Collision *collArea; - int16 timeKey; - byte collAreaStart; - uint32 startPos; - uint32 offsetPos; - - if (_shouldPushColls) - pushCollisions(0); - - collAreaStart = 0; - while (_collisionAreas[collAreaStart].left != 0xFFFF) - collAreaStart++; - collArea = &_collisionAreas[collAreaStart]; - - _shouldPushColls = 0; - collResId = -1; - - _script->skip(1); - count = _script->readByte(); - - _handleMouse = _script->readByte(); - deltaTime = 1000 * _script->readByte(); - _script->skip(1); - stackPos2 = _script->readByte(); - descIndex = _script->readByte(); - - if ((stackPos2 != 0) || (descIndex != 0)) - deltaTime /= 100; - - timeVal = deltaTime; - _script->skip(1); - - startPos = _script->pos(); - WRITE_VAR(16, 0); - - var_1C = 0; - index = 0; - curEditIndex = 0; - - for (curCmd = 0; curCmd < count; curCmd++) { - array[curCmd] = 0; - cmd = _script->readByte(); - - if ((cmd & 0x40) != 0) { - cmd -= 0x40; - cmdHigh = _script->readByte(); - cmdHigh <<= 8; - } else - cmdHigh = 0; - - if ((cmd & 0x80) != 0) { - offsetPos = _script->pos(); - left = _script->readValExpr(); - top = _script->readValExpr(); - width = _script->readValExpr(); - height = _script->readValExpr(); - } else { - offsetPos = 0; - left = _script->readUint16(); - top = _script->readUint16(); - width = _script->readUint16(); - height = _script->readUint16(); - } - - if ((_vm->_draw->_renderFlags & RENDERFLAG_CAPTUREPOP) && (left != 0xFFFF)) { - left += _vm->_draw->_backDeltaX; - top += _vm->_draw->_backDeltaY; - } - - if (left != 0xFFFF) { - _vm->_draw->adjustCoords(0, &left, &top); - if (((cmd & 0x3F) < 20) && ((cmd & 0x3F) >= 3)) { - if (_vm->_draw->_needAdjust != 2) - height &= 0xFFFE; - _vm->_draw->adjustCoords(0, 0, &width); - } else - _vm->_draw->adjustCoords(0, &height, &width); - } - - cmd &= 0x7F; - debugC(1, kDebugCollisions, "collisionsBlock(%d)", cmd); - - switch (cmd) { - case 0: - _script->skip(6); - startPos = _script->pos(); - _script->skip(_script->peekUint16(2) + 2); - key = curCmd + 0xA000; - - addNewCollision(curCmd + 0x8000, left, top, - left + width - 1, top + height - 1, - cmd + cmdHigh, key, startPos, - _script->pos(), offsetPos); - - _script->skip(_script->peekUint16(2) + 2); - - break; - - case 1: - key = _script->readInt16(); - array[curCmd] = _script->readInt16(); - flags = _script->readInt16(); - - startPos = _script->pos(); - _script->skip(_script->peekUint16(2) + 2); - - if (key == 0) - key = curCmd + 0xA000; - - addNewCollision(curCmd + 0x8000, left, top, - left + width - 1, top + height - 1, - (flags << 4) + cmd + cmdHigh, key, startPos, - _script->pos(), offsetPos); - - _script->skip(_script->peekUint16(2) + 2); - break; - - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - _vm->_util->clearKeyBuf(); - var_1C = 1; - key = _script->readVarIndex(); - descArray[index].fontIndex = _script->readInt16(); - descArray[index].backColor = _script->readByte(); - descArray[index].frontColor = _script->readByte(); - - if ((cmd >= 5) && (cmd <= 8)) { - descArray[index].ptr = _script->getData() + _script->pos() + 2; - _script->skip(_script->peekUint16() + 2); - } else - descArray[index].ptr = 0; - - if (left == 0xFFFF) { - if ((cmd & 1) == 0) { - _script->skip(_script->peekUint16(2) + 2); - } - break; - } - - if ((cmd & 1) == 0) { - addNewCollision(curCmd + 0x8000, left, top, left + width * - _vm->_draw->_fonts[descArray[index].fontIndex]-> itemWidth - 1, - top + height - 1, cmd, key, 0, - _script->pos()); - - _script->skip(_script->peekUint16(2) + 2); - } else - addNewCollision(curCmd + 0x8000, left, top, left + width * - _vm->_draw->_fonts[descArray[index].fontIndex]-> itemWidth - 1, - top + height - 1, cmd, key, 0, 0); - - index++; - break; - - case 11: - _script->skip(6); - for (i = 0; i < 150; i++) { - if ((_collisionAreas[i].id & 0xF000) == 0xE000) { - _collisionAreas[i].id &= 0xBFFF; - _collisionAreas[i].funcEnter = - _script->pos(); - _collisionAreas[i].funcLeave = - _script->pos(); - } - } - _script->skip(_script->peekUint16(2) + 2); - break; - - case 12: - _script->skip(6); - for (i = 0; i < 150; i++) { - if ((_collisionAreas[i].id & 0xF000) == 0xD000) { - _collisionAreas[i].id &= 0xBFFF; - _collisionAreas[i].funcEnter = - _script->pos(); - _collisionAreas[i].funcLeave = - _script->pos(); - } - } - _script->skip(_script->peekUint16(2) + 2); - break; - - case 20: - collResId = curCmd; - // Fall through to case 2 - - case 2: - key = _script->readInt16(); - array[curCmd] = _script->readInt16(); - flags = _script->readInt16(); - - addNewCollision(curCmd + 0x8000, left, top, - left + width - 1, top + height - 1, - (flags << 4) + cmdHigh + 2, key, 0, - _script->pos(), offsetPos); - - _script->skip(_script->peekUint16(2) + 2); - - break; - - case 21: - key = _script->readInt16(); - array[curCmd] = _script->readInt16(); - flags = _script->readInt16() & 3; - - addNewCollision(curCmd + 0x8000, left, top, - left + width - 1, top + height - 1, - (flags << 4) + cmdHigh + 2, key, - _script->pos(), 0, offsetPos); - - _script->skip(_script->peekUint16(2) + 2); - - break; - } - } - - _forceHandleMouse = 0; - _vm->_util->clearKeyBuf(); - - do { - if (var_1C != 0) { - key = multiEdit(deltaTime, index, &curEditIndex, descArray, - &_activeCollResId, &_activeCollIndex); - - WRITE_VAR(55, curEditIndex); - if (key == kKeyReturn) { - for (i = 0; i < 150; i++) { - if (_collisionAreas[i].left == 0xFFFF) - break; - - if ((_collisionAreas[i].id & 0xC000) != 0x8000) - continue; - - if ((_collisionAreas[i].flags & 1) != 0) - continue; - - if ((_collisionAreas[i].flags & 0x0F) <= 2) - continue; - - _activeCollResId = _collisionAreas[i].id; - collResId = _collisionAreas[i].id & 0x7FFF; - _activeCollIndex = i; - break; - } - break; - } - } else - key = checkCollisions(_handleMouse, -deltaTime, - &_activeCollResId, &_activeCollIndex); - - if (((key & 0xFF) >= ' ') && ((key & 0xFF) <= 0xFF) && - ((key >> 8) > 1) && ((key >> 8) < 12)) - key = '0' + (((key >> 8) - 1) % 10) + (key & 0xFF00); - - if (_activeCollResId == 0) { - if (key != 0) { - for (i = 0; i < 150; i++) { - if (_collisionAreas[i].left == 0xFFFF) - break; - - if ((_collisionAreas[i].id & 0xC000) != 0x8000) - continue; - - if ((_collisionAreas[i].key == key) || - (_collisionAreas[i].key == 0x7FFF)) { - _activeCollResId = _collisionAreas[i].id; - _activeCollIndex = i; - break; - } - } - - if (_activeCollResId == 0) { - for (i = 0; i < 150; i++) { - if (_collisionAreas[i].left == 0xFFFF) - break; - - if ((_collisionAreas[i].id & 0xC000) != 0x8000) - continue; - - if ((_collisionAreas[i].key & 0xFF00) != 0) - continue; - - if (_collisionAreas[i].key == 0) - continue; - - if ((adjustKey(key & 0xFF) == adjustKey(_collisionAreas[i].key)) || - (_collisionAreas[i].key == 0x7FFF)) { - _activeCollResId = _collisionAreas[i].id; - _activeCollIndex = i; - break; - } - } - } - } else if (deltaTime != 0) { - if (stackPos2 != 0) { - collStackPos = 0; - - for (i = 0, collPtr = collArea; collPtr->left != 0xFFFF; i++, collPtr++) { - if ((collPtr->id & 0xF000) != 0x8000) - continue; - - collStackPos++; - if (collStackPos != stackPos2) - continue; - - _activeCollResId = collPtr->id; - _activeCollIndex = i + collAreaStart; - _vm->_inter->storeMouse(); - if (VAR(16) != 0) - break; - - if ((_activeCollResId & 0xF000) == 0x8000) - WRITE_VAR(16, array[_activeCollResId & 0xFFF]); - else - WRITE_VAR(16, _activeCollResId & 0xFFF); - - if (collPtr->funcLeave != 0) { - int16 collResIdBak = _activeCollResId; - int16 collIndexBak = _activeCollIndex; - - timeKey = _vm->_util->getTimeKey(); - collSub(collPtr->funcLeave); - - _activeCollResId = collResIdBak; - _activeCollIndex = collIndexBak; - - _vm->_inter->animPalette(); - - deltaTime = timeVal - (_vm->_util->getTimeKey() - timeKey); - - if (deltaTime < 2) - deltaTime = 2; - if (deltaTime > timeVal) - deltaTime = timeVal; - } - - if (VAR(16) == 0) - _activeCollResId = 0; - break; - } - } else { - if (descIndex != 0) { - - counter = 0; - for (i = 0, collPtr = collArea; collPtr->left != 0xFFFF; i++, collPtr++) { - if ((collPtr->id & 0xF000) == 0x8000) - if (++counter == descIndex) { - _activeCollResId = collPtr->id; - _activeCollIndex = i + collAreaStart; - break; - } - } - - } else { - - for (i = 0, collPtr = _collisionAreas; collPtr->left != 0xFFFF; i++, collPtr++) { - if ((collPtr->id & 0xF000) == 0x8000) { - _activeCollResId = collPtr->id; - _activeCollIndex = i; - break; - } - } - if ((_lastCollKey != 0) && - (_collisionAreas[_lastCollAreaIndex].funcLeave != 0)) - collSub(_collisionAreas[_lastCollAreaIndex].funcLeave); - _lastCollKey = 0; - } - - } - } - } - - if ((_activeCollResId == 0) || - (_collisionAreas[_activeCollIndex].funcLeave != 0)) - continue; - - _vm->_inter->storeMouse(); - if ((_activeCollResId & 0xF000) == 0x8000) - WRITE_VAR(16, array[_activeCollResId & 0xFFF]); - else - WRITE_VAR(16, _activeCollResId & 0xFFF); - - if (_collisionAreas[_activeCollIndex].funcEnter != 0) - collSub(_collisionAreas[_activeCollIndex].funcEnter); - - WRITE_VAR(16, 0); - _activeCollResId = 0; - } - while ((_activeCollResId == 0) && !_vm->_inter->_terminate && !_vm->shouldQuit()); - - if ((_activeCollResId & 0xFFF) == collResId) { - collStackPos = 0; - var_24 = 0; - var_26 = 1; - for (i = 0; i < 150; i++) { - if (_collisionAreas[i].left == 0xFFFF) - continue; - - if ((_collisionAreas[i].id & 0xC000) == 0x8000) - continue; - - if ((_collisionAreas[i].flags & 0x0F) < 3) - continue; - - if ((_collisionAreas[i].flags & 0x0F) > 10) - continue; - - if ((_collisionAreas[i].flags & 0x0F) > 8) { - char *ptr; - strncpy0(_tempStr, GET_VARO_STR(_collisionAreas[i].key), 255); - while ((ptr = strchr(_tempStr, ' '))) - _vm->_util->cutFromStr(_tempStr, (ptr - _tempStr), 1); - if (_vm->_language == 2) - while ((ptr = strchr(_tempStr, '.'))) - *ptr = ','; - WRITE_VARO_STR(_collisionAreas[i].key, _tempStr); - } - - if (((_collisionAreas[i].flags & 0x0F) >= 5) && - ((_collisionAreas[i].flags & 0x0F) <= 8)) { - str = (char *) descArray[var_24].ptr; - - strncpy0(_tempStr, GET_VARO_STR(_collisionAreas[i].key), 255); - - if ((_collisionAreas[i].flags & 0x0F) < 7) - _vm->_util->cleanupStr(_tempStr); - - int16 pos = 0; - do { - strncpy0(_collStr, str, 255); - pos += strlen(str) + 1; - - str += strlen(str) + 1; - - if ((_collisionAreas[i].flags & 0x0F) < 7) - _vm->_util->cleanupStr(_collStr); - - if (strcmp(_tempStr, _collStr) == 0) { - WRITE_VAR(17, VAR(17) + 1); - WRITE_VAR(17 + var_26, 1); - break; - } - } while (READ_LE_UINT16(descArray[var_24].ptr - 2) > pos); - collStackPos++; - } else { - WRITE_VAR(17 + var_26, 2); - } - var_24++; - var_26++; - } - - if (collStackPos != (int16) VAR(17)) - WRITE_VAR(17, 0); - else - WRITE_VAR(17, 1); - } - - if (_handleMouse == 1) - _vm->_draw->blitCursor(); - - if (!_vm->_inter->_terminate) { - _script->seek(_collisionAreas[_activeCollIndex].funcLeave); - - _vm->_inter->storeMouse(); - if (VAR(16) == 0) { - if ((_activeCollResId & 0xF000) == 0x8000) - WRITE_VAR(16, array[_activeCollResId & 0xFFF]); - else - WRITE_VAR(16, _activeCollResId & 0xFFF); - } - } else - _script->setFinished(true); - - for (curCmd = 0; curCmd < count; curCmd++) - freeCollision(curCmd + 0x8000); - - for (i = 0; i < 150; i++) { - if (((_collisionAreas[i].id & 0xF000) == 0xA000) || - ((_collisionAreas[i].id & 0xF000) == 0x9000)) - _collisionAreas[i].id |= 0x4000; - } -} - -int16 Game_v2::multiEdit(int16 time, int16 index, int16 *pCurPos, - InputDesc * inpDesc, int16 *collResId, int16 *collIndex, bool mono) { - Collision *collArea; - int16 descInd; - int16 key; - int16 found = -1; - int16 i; - byte *fontExtraBak = 0; - int16 needAdjust = 0; - - descInd = 0; - for (i = 0; i < 150; i++) { - collArea = &_collisionAreas[i]; - - if (collArea->left == 0xFFFF) - continue; - - if ((collArea->id & 0xC000) != 0x8000) - continue; - - if ((collArea->flags & 0x0F) < 3) - continue; - - if ((collArea->flags & 0x0F) > 10) - continue; - - strncpy0(_tempStr, GET_VARO_STR(collArea->key), 255); - - _vm->_draw->_destSpriteX = collArea->left; - _vm->_draw->_destSpriteY = collArea->top; - _vm->_draw->_spriteRight = collArea->right - collArea->left + 1; - _vm->_draw->_spriteBottom = collArea->bottom - collArea->top + 1; - - _vm->_draw->_destSurface = 21; - - _vm->_draw->_backColor = inpDesc[descInd].backColor; - _vm->_draw->_frontColor = inpDesc[descInd].frontColor; - _vm->_draw->_textToPrint = _tempStr; - _vm->_draw->_transparency = 1; - _vm->_draw->_fontIndex = inpDesc[descInd].fontIndex; - - if (mono) { - fontExtraBak = _vm->_draw->_fonts[_vm->_draw->_fontIndex]->extraData; - needAdjust = _vm->_draw->_needAdjust; - _vm->_draw->_needAdjust = 2; - _vm->_draw->_fonts[_vm->_draw->_fontIndex]->extraData = 0; - } - - _vm->_draw->spriteOperation(DRAW_FILLRECT | 0x10); - - _vm->_draw->_destSpriteY += ((collArea->bottom - collArea->top + 1) - - _vm->_draw->_fonts[_vm->_draw->_fontIndex]->itemHeight) / 2; - _vm->_draw->spriteOperation(DRAW_PRINTTEXT | 0x10); - - if (mono) { - _vm->_draw->_needAdjust = needAdjust; - _vm->_draw->_fonts[_vm->_draw->_fontIndex]->extraData = fontExtraBak; - } - - descInd++; - } - - for (i = 0; i < 40; i++) - WRITE_VAR_OFFSET(i * 4 + 0x44, 0); - - while (1) { - descInd = 0; - - for (i = 0; i < 150; i++) { - collArea = &_collisionAreas[i]; - - if (collArea->left == 0xFFFF) - continue; - - if ((collArea->id & 0xC000) != 0x8000) - continue; - - if ((collArea->flags & 0x0F) < 3) - continue; - - if ((collArea->flags & 0x0F) > 10) - continue; - - if (descInd == *pCurPos) { - found = i; - break; - } - - descInd++; - } - - assert(found != -1); - - collArea = &_collisionAreas[found]; - - key = inputArea(collArea->left, collArea->top, - collArea->right - collArea->left + 1, - collArea->bottom - collArea->top + 1, - inpDesc[*pCurPos].backColor, inpDesc[*pCurPos].frontColor, - GET_VARO_STR(collArea->key), inpDesc[*pCurPos].fontIndex, - collArea->flags, &time, collResId, collIndex, mono); - - if (_vm->_inter->_terminate) - return 0; - - switch (key) { - case kKeyNone: - if (*collResId == 0) - return 0; - - if (_mouseButtons != kMouseButtonsNone) { - for (collArea = _collisionAreas, i = 0; - collArea->left != 0xFFFF; collArea++, i++) { - if ((collArea->flags & 0xF00)) - continue; - - if ((collArea->id & 0x4000)) - continue; - - if ((collArea->left > _vm->_global->_inter_mouseX) || - (collArea->right < _vm->_global->_inter_mouseX) || - (collArea->top > _vm->_global->_inter_mouseY) || - (collArea->bottom < _vm->_global->_inter_mouseY)) - continue; - - if ((collArea->id & 0xF000)) - continue; - - if ((collArea->flags & 0x0F) < 3) - continue; - - if ((collArea->flags & 0x0F) > 10) - continue; - - *collIndex = i; - } - } - - if ((_collisionAreas[*collIndex].flags & 0x0F) < 3) - return 0; - - if ((_collisionAreas[*collIndex].flags & 0x0F) > 10) - return 0; - - *pCurPos = 0; - for (i = 0; i < 150; i++) { - collArea = &_collisionAreas[i]; - - if (collArea->left == 0xFFFF) - continue; - - if ((collArea->id & 0xC000) != 0x8000) - continue; - - if ((collArea->flags & 0x0F) < 3) - continue; - - if ((collArea->flags & 0x0F) > 10) - continue; - - if (i != *collIndex) - pCurPos[0]++; - } - break; - - case kKeyF1: - case kKeyF2: - case kKeyF3: - case kKeyF4: - case kKeyF5: - case kKeyF6: - case kKeyF7: - case kKeyF8: - case kKeyF9: - case kKeyF10: - return key; - - case kKeyReturn: - - if (index == 1) - return key; - - if (*pCurPos == index - 1) { - *pCurPos = 0; - break; - } - - pCurPos[0]++; - break; - - case kKeyDown: - if (index - 1 > *pCurPos) - pCurPos[0]++; - break; - - case kKeyUp: - if (*pCurPos > 0) - pCurPos[0]--; - break; - } - } -} - -int16 Game_v2::inputArea(int16 xPos, int16 yPos, int16 width, int16 height, - int16 backColor, int16 frontColor, char *str, int16 fontIndex, - char inpType, int16 *pTotTime, int16 *collResId, int16 *collIndex, bool mono) { - byte handleMouse; - uint32 editSize; - Video::FontDesc *pFont; - char curSym; - int16 key; - const char *str1; - const char *str2; - int16 i; - uint32 pos; - int16 flag; - int16 savedKey; - byte *fontExtraBak = 0; - int16 needAdjust = 0; - - if ((_handleMouse != 0) && - ((_vm->_global->_useMouse != 0) || (_forceHandleMouse != 0))) - handleMouse = 1; - else - handleMouse = 0; - - pos = strlen(str); - pFont = _vm->_draw->_fonts[fontIndex]; - editSize = (!mono && pFont->extraData) ? 0 : (width / pFont->itemWidth); - - while (1) { - strncpy0(_tempStr, str, 254); - strcat(_tempStr, " "); - if ((editSize != 0) && strlen(_tempStr) > editSize) - strncpy0(_tempStr, str, 255); - - if (mono) { - fontExtraBak = _vm->_draw->_fonts[fontIndex]->extraData; - needAdjust = _vm->_draw->_needAdjust; - _vm->_draw->_needAdjust = 2; - _vm->_draw->_fonts[fontIndex]->extraData = 0; - } - - _vm->_draw->_destSpriteX = xPos; - _vm->_draw->_destSpriteY = yPos; - _vm->_draw->_spriteRight = mono ? (editSize * pFont->itemWidth) : width; - _vm->_draw->_spriteBottom = height; - - _vm->_draw->_destSurface = 21; - _vm->_draw->_backColor = backColor; - _vm->_draw->_frontColor = frontColor; - _vm->_draw->_textToPrint = _tempStr; - _vm->_draw->_transparency = 1; - _vm->_draw->_fontIndex = fontIndex; - _vm->_draw->spriteOperation(DRAW_FILLRECT | 0x10 ); - - _vm->_draw->_destSpriteY = yPos + (height - pFont->itemHeight) / 2; - _vm->_draw->spriteOperation(DRAW_PRINTTEXT | 0x10); - - if (mono) { - _vm->_draw->_needAdjust = needAdjust; - _vm->_draw->_fonts[fontIndex]->extraData = fontExtraBak; - } - - if ((editSize != 0) && (pos == editSize)) - pos--; - - curSym = _tempStr[pos]; - - flag = 1; - - if (_vm->_inter->_variables) - WRITE_VAR(56, pos); - - while (1) { - if (mono) { - fontExtraBak = _vm->_draw->_fonts[fontIndex]->extraData; - needAdjust = _vm->_draw->_needAdjust; - _vm->_draw->_needAdjust = 2; - _vm->_draw->_fonts[fontIndex]->extraData = 0; - } - - _tempStr[0] = curSym; - _tempStr[1] = 0; - - if (pFont->extraData) { - _vm->_draw->_destSpriteY = yPos; - _vm->_draw->_spriteBottom = height; - _vm->_draw->_spriteRight = 1; - - _vm->_draw->_destSpriteX = xPos; - for (uint32 j = 0; j < pos; j++) - _vm->_draw->_destSpriteX += pFont->extraData[str[j] - pFont->startItem]; - - } else { - _vm->_draw->_destSpriteX = xPos + pFont->itemWidth * pos; - _vm->_draw->_destSpriteY = yPos + height - 1; - _vm->_draw->_spriteRight = pFont->itemWidth; - _vm->_draw->_spriteBottom = 1; - } - - _vm->_draw->_destSurface = 21; - _vm->_draw->_backColor = frontColor; - _vm->_draw->spriteOperation(DRAW_FILLRECT | 0x10); - - if (mono) { - _vm->_draw->_needAdjust = needAdjust; - _vm->_draw->_fonts[fontIndex]->extraData = fontExtraBak; - } - - if (flag != 0) { - key = checkCollisions(handleMouse, -1, collResId, collIndex); - if (key == 0) - key = checkCollisions(handleMouse, -300, collResId, collIndex); - flag = 0; - } else - key = checkCollisions(handleMouse, -300, collResId, collIndex); - - if (mono) { - fontExtraBak = _vm->_draw->_fonts[fontIndex]->extraData; - needAdjust = _vm->_draw->_needAdjust; - _vm->_draw->_needAdjust = 2; - _vm->_draw->_fonts[fontIndex]->extraData = 0; - } - - _tempStr[0] = curSym; - _tempStr[1] = 0; - - if (pFont->extraData) { - _vm->_draw->_destSpriteY = yPos; - _vm->_draw->_spriteBottom = height; - _vm->_draw->_spriteRight = 1; - - _vm->_draw->_destSpriteX = xPos; - for (uint32 j = 0; j < pos; j++) - _vm->_draw->_destSpriteX += pFont->extraData[str[j] - pFont->startItem]; - - } else { - _vm->_draw->_destSpriteX = xPos + pFont->itemWidth * pos; - _vm->_draw->_destSpriteY = yPos + height - 1; - _vm->_draw->_spriteRight = pFont->itemWidth; - _vm->_draw->_spriteBottom = 1; - } - - _vm->_draw->_destSurface = 21; - _vm->_draw->_backColor = backColor; - _vm->_draw->_frontColor = frontColor; - _vm->_draw->_textToPrint = _tempStr; - _vm->_draw->_transparency = 1; - _vm->_draw->_fontIndex = fontIndex; - _vm->_draw->spriteOperation(DRAW_FILLRECT | 0x10); - - _vm->_draw->_destSpriteY = yPos + (height - pFont->itemHeight) / 2; - _vm->_draw->spriteOperation(DRAW_PRINTTEXT | 0x10); - - if (mono) { - _vm->_draw->_needAdjust = needAdjust; - _vm->_draw->_fonts[fontIndex]->extraData = fontExtraBak; - } - - if ((key != 0) || (*collResId != 0)) - break; - - key = checkCollisions(handleMouse, -300, collResId, collIndex); - - if ((key != 0) || (*collResId != 0) || - _vm->_inter->_terminate || _vm->shouldQuit()) - break; - - if (*pTotTime > 0) { - *pTotTime -= 600; - if (*pTotTime <= 1) { - key = 0; - *collResId = 0; - break; - } - } - } - - if ((key == 0) || (*collResId != 0) || - _vm->_inter->_terminate || _vm->shouldQuit()) - return 0; - - switch (key) { - case kKeyRight: - if ((pos > strlen(str)) || (pos > (editSize - 1)) || (editSize == 0)) { - pos++; - continue; - } - return kKeyDown; - - case kKeyLeft: - if (pos > 0) { - pos--; - continue; - } - return kKeyUp; - - case kKeyBackspace: - if (pos > 0) { - _vm->_util->cutFromStr(str, pos - 1, 1); - pos--; - continue; - } else { - if (pos < strlen(str)) - _vm->_util->cutFromStr(str, pos, 1); - } - - case kKeyDelete: - if (pos >= strlen(str)) - continue; - - _vm->_util->cutFromStr(str, pos, 1); - continue; - - case kKeyReturn: - case kKeyF1: - case kKeyF2: - case kKeyF3: - case kKeyF4: - case kKeyF5: - case kKeyF6: - case kKeyF7: - case kKeyF8: - case kKeyF9: - case kKeyF10: - case kKeyUp: - case kKeyDown: - return key; - - case kKeyEscape: - if (_vm->_global->_useMouse != 0) - continue; - - _forceHandleMouse = !_forceHandleMouse; - - if ((_handleMouse != 0) && - ((_vm->_global->_useMouse != 0) || (_forceHandleMouse != 0))) - handleMouse = 1; - else - handleMouse = 0; - - while (_vm->_global->_pressedKeys[1] != 0) - ; - continue; - - default: - - savedKey = key; - key &= 0xFF; - - if (((inpType == 9) || (inpType == 10)) && - (key >= ' ') && (key <= 0xFF)) { - str1 = "0123456789-.,+ "; - str2 = "0123456789-,,+ "; - - if ((((savedKey >> 8) > 1) && ((savedKey >> 8) < 12)) && - ((_vm->_global->_pressedKeys[42] != 0) || - (_vm->_global->_pressedKeys[56] != 0))) - key = ((savedKey >> 8) - 1) % 10 + '0'; - - for (i = 0; str1[i] != 0; i++) { - if (key == str1[i]) { - key = str2[i]; - break; - } - } - - if (i == (int16) strlen(str1)) - key = 0; - } - - if ((key >= ' ') && (key <= 0xFF)) { - if (editSize == 0) { - int length = _vm->_draw->stringLength(str, fontIndex) + - pFont->extraData[' ' - pFont->startItem] + - pFont->extraData[key - pFont->startItem]; - - if (length > width) - continue; - - if (((int32) strlen(str)) >= (_vm->_global->_inter_animDataSize * 4 - 1)) - continue; - - } else { - if (strlen(str) > editSize) - continue; - else if (editSize == strlen(str)) - _vm->_util->cutFromStr(str, strlen(str) - 1, 1); - } - - pos++; - _tempStr[0] = key; - _tempStr[1] = 0; - - _vm->_util->insertStr(_tempStr, str, pos - 1); - } - - } - } -} - -int16 Game_v2::checkMousePoint(int16 all, int16 *resId, int16 *resIndex) { - Collision *ptr; - int16 i; - - if (resId != 0) - *resId = 0; - - *resIndex = 0; - - ptr = _collisionAreas; - for (i = 0; ptr->left != 0xFFFF; ptr++, i++) { - if (ptr->id & 0x4000) - continue; - - if (all) { - if ((ptr->flags & 0xF) > 1) - continue; - - if ((ptr->flags & 0xF00) != 0) - continue; - - if ((_vm->_global->_inter_mouseX < ptr->left) || - (_vm->_global->_inter_mouseX > ptr->right) || - (_vm->_global->_inter_mouseY < ptr->top) || - (_vm->_global->_inter_mouseY > ptr->bottom)) - continue; - - if (resId != 0) - *resId = ptr->id; - - *resIndex = i; - return ptr->key; - } else { - if ((ptr->flags & 0xF00) != 0) - continue; - - if ((ptr->flags & 0xF) < 1) - continue; - - if ((((ptr->flags & 0xF0) >> 4) != (((int32) _mouseButtons) - 1)) && - (((ptr->flags & 0xF0) >> 4) != 2)) - continue; - - if ((_vm->_global->_inter_mouseX < ptr->left) || - (_vm->_global->_inter_mouseX > ptr->right) || - (_vm->_global->_inter_mouseY < ptr->top) || - (_vm->_global->_inter_mouseY > ptr->bottom)) - continue; - - if (resId != 0) - *resId = ptr->id; - *resIndex = i; - if (((ptr->flags & 0xF) == 1) || ((ptr->flags & 0xF) == 2)) - return ptr->key; - return 0; - } - } - - if ((_mouseButtons != kMouseButtonsLeft) && (all == 0)) - return kKeyEscape; - - return 0; -} - } // End of namespace Gob diff --git a/engines/gob/game_v6.cpp b/engines/gob/game_v6.cpp index 985f72c23a..e8e08578b3 100644 --- a/engines/gob/game_v6.cpp +++ b/engines/gob/game_v6.cpp @@ -33,13 +33,13 @@ #include "gob/global.h" #include "gob/script.h" #include "gob/resources.h" +#include "gob/hotspots.h" #include "gob/inter.h" #include "gob/draw.h" namespace Gob { Game_v6::Game_v6(GobEngine *vm) : Game_v2(vm) { - _someTimeDly = 0; } // flagbits: 5 = freeInterVariables, 6 = skipPlay @@ -75,7 +75,7 @@ void Game_v6::totSub(int8 flags, const char *newTotFile) { return; } - pushCollisions(0); + _hotspots->push(0, true); if (flags & 6) playTot(-1); @@ -85,8 +85,8 @@ void Game_v6::totSub(int8 flags, const char *newTotFile) { if (_vm->_inter->_terminate < 2) _vm->_inter->_terminate = 0; - clearCollisions(); - popCollisions(); +_hotspots->clear(); +_hotspots->pop(); if ((flags & 5) && _vm->_inter->_variables) { _vm->_inter->delocateVars(); @@ -99,45 +99,6 @@ void Game_v6::totSub(int8 flags, const char *newTotFile) { _environments->get(_numEnvironments); } -int16 Game_v6::addNewCollision(int16 id, uint16 left, uint16 top, - uint16 right, uint16 bottom, int16 flags, int16 key, - uint16 funcEnter, uint16 funcLeave, uint16 funcSub) { - Collision *ptr; - - debugC(5, kDebugCollisions, "addNewCollision"); - debugC(5, kDebugCollisions, "id = %X", id); - debugC(5, kDebugCollisions, "left = %d, top = %d, right = %d, bottom = %d", - left, top, right, bottom); - debugC(5, kDebugCollisions, "flags = %X, key = %X", flags, key); - debugC(5, kDebugCollisions, "funcEnter = %d, funcLeave = %d", - funcEnter, funcLeave); - - for (int i = 0; i < 150; i++) { - if ((_collisionAreas[i].left != 0xFFFF) && (_collisionAreas[i].id != id)) - continue; - - ptr = &_collisionAreas[i]; - - if ((ptr->id & 0xBFFF) != (id & 0xBFFF)) - ptr->id = id; - - ptr->left = left; - ptr->top = top; - ptr->right = right; - ptr->bottom = bottom; - ptr->flags = flags; - ptr->key = key; - ptr->funcEnter = funcEnter; - ptr->funcLeave = funcLeave; - ptr->funcSub = funcSub; - ptr->script = _script; - - return i; - } - error("Game_v6::addNewCollision(): Collision array full"); - return 0; -} - void Game_v6::prepareStart(void) { _noCd = false; @@ -149,966 +110,4 @@ void Game_v6::prepareStart(void) { Game_v2::prepareStart(); } -void Game_v6::pushCollisions(char all) { - Collision *srcPtr; - Collision *destPtr; - int16 size; - - debugC(1, kDebugCollisions, "pushCollisions"); - for (size = 0, srcPtr = _collisionAreas; srcPtr->left != 0xFFFF; srcPtr++) { - if ( (all == 1) || - ((all == 0) && (((uint16) srcPtr->id) >= 20)) || - ((all == 2) && (((srcPtr->id & 0xF000) == 0xD000) || - ((srcPtr->id & 0xF000) == 0x4000) || - ((srcPtr->id & 0xF000) == 0xE000)))) - size++; - } - - if (_collStackSize >= 5) - error("Game_v6::pushCollisions: _collStackSize == %d", _collStackSize); - - destPtr = new Collision[size]; - _collStack[_collStackSize] = destPtr; - - if (_vm->_inter->_terminate) - return; - - _collStackElemSizes[_collStackSize] = size; - - if (_shouldPushColls != 0) - _collStackElemSizes[_collStackSize] |= 0x8000; - - _shouldPushColls = 0; - _collLasts[_collStackSize].key = _lastCollKey; - _collLasts[_collStackSize].id = _lastCollId; - _collLasts[_collStackSize].areaIndex = _lastCollAreaIndex; - _lastCollKey = 0; - _lastCollId = 0; - _lastCollAreaIndex = 0; - _collStackSize++; - - for (srcPtr = _collisionAreas; srcPtr->left != 0xFFFF; srcPtr++) { - if ( (all == 1) || - ((all == 0) && (((uint16) srcPtr->id) >= 20)) || - ((all == 2) && (((srcPtr->id & 0xF000) == 0xD000) || - ((srcPtr->id & 0xF000) == 0x4000) || - ((srcPtr->id & 0xF000) == 0xE000)))) { - - memcpy(destPtr, srcPtr, sizeof(Collision)); - srcPtr->left = 0xFFFF; - destPtr++; - } - } -} - -int16 Game_v6::checkCollisions(byte handleMouse, int16 deltaTime, int16 *pResId, - int16 *pResIndex) { - int16 resIndex; - int16 key; - uint32 timeKey; - - _scrollHandleMouse = handleMouse != 0; - - if (deltaTime >= -1) { - _lastCollKey = 0; - _lastCollAreaIndex = 0; - _lastCollId = 0; - } - - if (pResId != 0) - *pResId = 0; - - resIndex = 0; - - if ((_lastCollKey != 0) && - ( (_collisionAreas[_lastCollAreaIndex].id != _lastCollId) || - (_collisionAreas[_lastCollAreaIndex].key != _lastCollKey))) { - - _lastCollKey = 0; - _lastCollAreaIndex = 0; - _lastCollId = 0; - } - - if ((_vm->_draw->_cursorIndex == -1) && - (handleMouse != 0) && (_lastCollKey == 0)) { - _lastCollKey = checkMousePoint(1, &_lastCollId, &_lastCollAreaIndex); - - if ((_lastCollKey != 0) && (_lastCollId & 0x8000)) - collAreaSub(_lastCollAreaIndex, 1); - } - - if (handleMouse != 0) - _vm->_draw->animateCursor(-1); - - timeKey = _vm->_util->getTimeKey(); - _vm->_draw->blitInvalidated(); - while (1) { - if (_vm->_inter->_terminate || _vm->shouldQuit()) { - if (handleMouse) - _vm->_draw->blitCursor(); - return 0; - } - - collSubReenter(); - if (!_vm->_draw->_noInvalidated) { - if (handleMouse != 0) - _vm->_draw->animateCursor(-1); - else - _vm->_draw->blitInvalidated(); - _vm->_video->waitRetrace(); - } - - key = checkKeys(&_vm->_global->_inter_mouseX, - &_vm->_global->_inter_mouseY, &_mouseButtons, handleMouse); - - if ((handleMouse == 0) && (_mouseButtons != kMouseButtonsNone)) { - _vm->_util->waitMouseRelease(0); - key = 3; - } - - if (key != 0) { - - if (handleMouse & 1) - _vm->_draw->blitCursor(); - - if (pResId != 0) - *pResId = 0; - - if (pResIndex != 0) - *pResIndex = 0; - - if ((_lastCollKey != 0) && (_lastCollId & 0x8000)) - collAreaSub(_lastCollAreaIndex, 0); - - _lastCollKey = 0; - if (key != 0) - return key; - - if (handleMouse) - _vm->_draw->animateCursor(-1); - } - - if (handleMouse != 0) { - if (_mouseButtons != kMouseButtonsNone) { - - if (deltaTime > 0) { - _vm->_draw->animateCursor(2); - _vm->_util->delay(deltaTime); - } else if (handleMouse & 1) - _vm->_util->waitMouseRelease(1); - - _vm->_draw->animateCursor(-1); - - if (pResId != 0) - *pResId = 0; - - key = checkMousePoint(0, pResId, &resIndex); - if (pResIndex != 0) - *pResIndex = resIndex; - - if ((key != 0) || ((pResId != 0) && (*pResId != 0))) { - if ((handleMouse & 1) && - ((deltaTime <= 0) || (_mouseButtons == kMouseButtonsNone))) - _vm->_draw->blitCursor(); - - if (key != _lastCollKey) - collAreaSub(_lastCollAreaIndex, 0); - - _lastCollKey = 0; - return key; - } - - if (handleMouse & 4) - return 0; - - if (_lastCollKey != 0) - collAreaSub(_lastCollAreaIndex, 0); - - _lastCollKey = checkMousePoint(1, &_lastCollId, &_lastCollAreaIndex); - if ((_lastCollKey != 0) && (_lastCollId & 0x8000)) - collAreaSub(_lastCollAreaIndex, 1); - } else - collSubReenter(); - } - - if ((deltaTime == -2) && (key == 0) && (_mouseButtons == kMouseButtonsNone)) { - if (pResId != 0) - *pResId = 0; - - if (pResIndex != 0) - *pResIndex = 0; - - return 0; - - } else if (handleMouse != 0) - _vm->_draw->animateCursor(-1); - - if ((deltaTime < 0) && (key == 0) && (_mouseButtons == kMouseButtonsNone)) { - uint32 curtime = _vm->_util->getTimeKey(); - if ((curtime + deltaTime) > timeKey) { - if (pResId != 0) - *pResId = 0; - - if (pResIndex != 0) - *pResIndex = 0; - - return 0; - } - } - - _vm->_util->delay(10); - } -} - -void Game_v6::collisionsBlock(void) { - InputDesc descArray[20]; - int16 array[300]; - byte count; - int16 collResId; - int16 curCmd; - int16 cmd; - int16 cmdHigh; - int16 key; - int16 flags; - uint16 left; - uint16 top; - uint16 width; - uint16 height; - int16 deltaTime; - int16 stackPos2; - int16 descIndex; - int16 timeVal; - char *str; - int16 i; - int16 counter; - int16 var_24; - int16 var_26; - int16 collStackPos; - Collision *collPtr; - Collision *collArea; - byte collAreaStart; - int16 activeCollResId = 0; - int16 activeCollIndex = 0; - uint32 startPos; - uint32 offsetPos; - - if (_shouldPushColls) - pushCollisions(0); - - collAreaStart = 0; - while (_collisionAreas[collAreaStart].left != 0xFFFF) - collAreaStart++; - collArea = &_collisionAreas[collAreaStart]; - - _shouldPushColls = 0; - collResId = -1; - - _script->skip(1); - count = _script->readByte(); - - _handleMouse = _script->peekByte(0); - deltaTime = 1000 * _script->peekByte(1); - stackPos2 = _script->peekByte(3); - descIndex = _script->peekByte(4); - byte var_42 = _script->peekByte(5); - - if ((stackPos2 != 0) || (descIndex != 0)) { - deltaTime /= 100; - if (_script->peekByte(1) == 100) - deltaTime = 2; - } - - timeVal = deltaTime; - _script->skip(6); - - startPos = _script->pos(); - WRITE_VAR(16, 0); - - byte var_41 = 0; - int16 var_46 = 0; - int16 var_1C = 0; - int16 index = 0; - int16 curEditIndex = 0; - int right = 0, funcLeave = 0; - - for (curCmd = 0; curCmd < count; curCmd++) { - array[curCmd] = 0; - cmd = _script->readByte(); - - if ((cmd & 0x40) != 0) { - cmd -= 0x40; - cmdHigh = _script->readByte(); - cmdHigh <<= 8; - } else - cmdHigh = 0; - - if ((cmd & 0x80) != 0) { - offsetPos = _script->pos(); - left = _script->readValExpr(); - top = _script->readValExpr(); - width = _script->readValExpr(); - height = _script->readValExpr(); - } else { - offsetPos = 0; - left = _script->readUint16(); - top = _script->readUint16(); - width = _script->readUint16(); - height = _script->readUint16(); - } - - if ((_vm->_draw->_renderFlags & RENDERFLAG_CAPTUREPOP) && (left != 0xFFFF)) { - left += _vm->_draw->_backDeltaX; - top += _vm->_draw->_backDeltaY; - } - - if (left != 0xFFFF) { - _vm->_draw->adjustCoords(0, &left, &top); - if (((cmd & 0x3F) < 20) && ((cmd & 0x3F) >= 3)) { - if (_vm->_draw->_needAdjust != 2) - height &= 0xFFFE; - _vm->_draw->adjustCoords(0, 0, &width); - } else - _vm->_draw->adjustCoords(0, &height, &width); - } - - cmd &= 0x7F; - debugC(1, kDebugCollisions, "collisionsBlock(%d)", cmd); - - switch (cmd) { - case 0: - _script->skip(6); - startPos = _script->pos(); - _script->skip(_script->peekUint16(2) + 2); - key = curCmd + 0xA000; - - addNewCollision(curCmd + 0x8000, left, top, - left + width - 1, top + height - 1, - cmd + cmdHigh, key, startPos, - _script->pos(), offsetPos); - - _script->skip(_script->peekUint16(2) + 2); - - break; - - case 1: - key = _script->readInt16(); - array[curCmd] = _script->readInt16(); - flags = _script->readInt16(); - - startPos = _script->pos(); - _script->skip(_script->peekUint16(2) + 2); - - if (key == 0) - key = curCmd + 0xA000; - - addNewCollision(curCmd + 0x8000, left, top, - left + width - 1, top + height - 1, - (flags << 4) + cmd + cmdHigh, key, startPos, - _script->pos(), offsetPos); - - _script->skip(_script->peekUint16(2) + 2); - - break; - - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - _vm->_util->clearKeyBuf(); - var_1C = 1; - key = _script->readVarIndex(); - descArray[index].fontIndex = _script->readInt16(); - descArray[index].backColor = _script->readByte(); - descArray[index].frontColor = _script->readByte(); - - if ((cmd >= 5) && (cmd <= 8)) { - descArray[index].ptr = _script->getData() + _script->pos() + 2; - _script->skip(_script->peekUint16() + 2); - } else - descArray[index].ptr = 0; - - if (left == 0xFFFF) { - if ((cmd & 1) == 0) { - _script->skip(_script->peekUint16(2) + 2); - } - break; - } - - right = left + width - 1; - if (!_vm->_draw->_fonts[descArray[index].fontIndex]->extraData) - right = left + width * _vm->_draw->_fonts[descArray[index].fontIndex]->itemWidth - 1; - - funcLeave = 0; - if (!(cmd & 1)) - funcLeave = _script->pos(); - - addNewCollision(curCmd + 0x8000, left, top, right, - top + height - 1, cmd, key, 0, funcLeave, 0); - - if (!(cmd & 1)) { - _script->skip(_script->peekUint16(2) + 2); - } - - index++; - break; - - case 11: - _script->skip(6); - for (i = 0; i < 150; i++) { - if ((_collisionAreas[i].id & 0xF000) == 0xE000) { - _collisionAreas[i].id &= 0xBFFF; - _collisionAreas[i].funcEnter = - _script->pos(); - _collisionAreas[i].funcLeave = - _script->pos(); - } - } - _script->skip(_script->peekUint16(2) + 2); - break; - - case 12: - _script->skip(6); - for (i = 0; i < 150; i++) { - if ((_collisionAreas[i].id & 0xF000) == 0xD000) { - _collisionAreas[i].id &= 0xBFFF; - _collisionAreas[i].funcEnter = - _script->pos(); - _collisionAreas[i].funcLeave = - _script->pos(); - } - } - _script->skip(_script->peekUint16(2) + 2); - break; - - case 20: - collResId = curCmd; - // Fall through to case 2 - - case 2: - key = _script->readInt16(); - array[curCmd] = _script->readInt16(); - flags = _script->readInt16(); - - addNewCollision(curCmd + 0x8000, left, top, - left + width - 1, top + height - 1, - (flags << 4) + cmdHigh + 2, key, 0, - _script->pos(), offsetPos); - - _script->skip(_script->peekUint16(2) + 2); - - break; - - case 21: - key = _script->readInt16(); - array[curCmd] = _script->readInt16(); - flags = _script->readInt16() & 3; - - addNewCollision(curCmd + 0x8000, left, top, - left + width - 1, top + height - 1, - (flags << 4) + cmdHigh + 2, key, - _script->pos(), 0, offsetPos); - - _script->skip(_script->peekUint16(2) + 2); - - break; - } - } - - if (var_42 != 0) - setCollisions(1); - - _forceHandleMouse = 0; - _vm->_util->clearKeyBuf(); - - do { - if (var_1C != 0) { - key = multiEdit(deltaTime, index, &curEditIndex, descArray, - &activeCollResId, &activeCollIndex, false); - - WRITE_VAR(55, curEditIndex); - if (key == kKeyReturn) { - for (i = 0; i < 150; i++) { - if (_collisionAreas[i].left == 0xFFFF) - break; - - if ((_collisionAreas[i].id & 0xC000) != 0x8000) - continue; - - if ((_collisionAreas[i].flags & 1) != 0) - continue; - - if ((_collisionAreas[i].flags & 0x0F) <= 2) - continue; - - activeCollResId = _collisionAreas[i].id; - collResId = _collisionAreas[i].id & 0x7FFF; - activeCollIndex = i; - break; - } - break; - } - } else - key = checkCollisions(_handleMouse, -deltaTime, - &activeCollResId, &activeCollIndex); - - if (((key & 0xFF) >= ' ') && ((key & 0xFF) <= 0xFF) && - ((key >> 8) > 1) && ((key >> 8) < 12)) - key = '0' + (((key >> 8) - 1) % 10) + (key & 0xFF00); - - if (activeCollResId == 0) { - if (key != 0) { - for (i = 0; i < 150; i++) { - if (_collisionAreas[i].left == 0xFFFF) - break; - - if ((_collisionAreas[i].id & 0xC000) != 0x8000) - continue; - - if ((_collisionAreas[i].key == key) || - (_collisionAreas[i].key == 0x7FFF)) { - activeCollResId = _collisionAreas[i].id; - activeCollIndex = i; - break; - } - } - - if (activeCollResId == 0) { - for (i = 0; i < 150; i++) { - if (_collisionAreas[i].left == 0xFFFF) - break; - - if ((_collisionAreas[i].id & 0xC000) != 0x8000) - continue; - - if ((_collisionAreas[i].key & 0xFF00) != 0) - continue; - - if (_collisionAreas[i].key == 0) - continue; - - if (adjustKey(key & 0xFF) == adjustKey(_collisionAreas[i].key)) { - activeCollResId = _collisionAreas[i].id; - activeCollIndex = i; - break; - } - } - } - } else if (deltaTime != 0) { - if (stackPos2 != 0) { - collStackPos = 0; - - for (i = 0, collPtr = collArea; collPtr->left != 0xFFFF; i++, collPtr++) { - if ((collPtr->id & 0xF000) != 0x8000) - continue; - - collStackPos++; - if (collStackPos != stackPos2) - continue; - - activeCollResId = collPtr->id; - activeCollIndex = i + collAreaStart; - _vm->_inter->storeMouse(); - if (VAR(16) != 0) - break; - - if ((activeCollResId & 0xF000) == 0x8000) - WRITE_VAR(16, array[activeCollResId & 0xFFF]); - else - WRITE_VAR(16, activeCollResId & 0xFFF); - - if (collPtr->funcLeave != 0) { - uint32 timeKey = _vm->_util->getTimeKey(); - collSub(collPtr->funcLeave); - - if (timeVal != 2) { - deltaTime = timeVal - (_vm->_util->getTimeKey() - timeKey); - - if ((deltaTime - var_46) < 3) { - var_46 -= (deltaTime - 3); - deltaTime = 3; - } else if (var_46 != 0) { - deltaTime -= var_46; - var_46 = 0; - } - - if (deltaTime > timeVal) - deltaTime = timeVal; - - } else - deltaTime = 2; - - } - - if (VAR(16) == 0) - activeCollResId = 0; - else - var_41 = 1; - - break; - } - } else { - if (descIndex != 0) { - - counter = 0; - for (i = 0, collPtr = collArea; collPtr->left != 0xFFFF; i++, collPtr++) { - if ((collPtr->id & 0xF000) == 0x8000) - if (++counter == descIndex) { - activeCollResId = collPtr->id; - activeCollIndex = i + collAreaStart; - break; - } - } - - } else { - - for (i = 0, collPtr = _collisionAreas; collPtr->left != 0xFFFF; i++, collPtr++) { - if ((collPtr->id & 0xF000) == 0x8000) { - activeCollResId = collPtr->id; - activeCollIndex = i; - break; - } - } - if ((_lastCollKey != 0) && - (_collisionAreas[_lastCollAreaIndex].funcLeave != 0)) - collSub(_collisionAreas[_lastCollAreaIndex].funcLeave); - - _lastCollKey = 0; - } - - } - } - } - - if (var_41 != 0) - break; - - if ((activeCollResId == 0) || - (_collisionAreas[activeCollIndex].funcLeave != 0)) - continue; - - _vm->_inter->storeMouse(); - if ((activeCollResId & 0xF000) == 0x8000) - WRITE_VAR(16, array[activeCollResId & 0xFFF]); - else - WRITE_VAR(16, activeCollResId & 0xFFF); - - if (_collisionAreas[activeCollIndex].funcEnter != 0) - collSub(_collisionAreas[activeCollIndex].funcEnter); - - WRITE_VAR(16, 0); - activeCollResId = 0; - } - while ((activeCollResId == 0) && !_vm->_inter->_terminate && !_vm->shouldQuit()); - - if ((activeCollResId & 0xFFF) == collResId) { - collStackPos = 0; - var_24 = 0; - var_26 = 1; - for (i = 0; i < 150; i++) { - if (_collisionAreas[i].left == 0xFFFF) - continue; - - if ((_collisionAreas[i].id & 0xC000) != 0x8000) - continue; - - if ((_collisionAreas[i].flags & 0x0F) < 3) - continue; - - if ((_collisionAreas[i].flags & 0x0F) > 10) - continue; - - if ((_collisionAreas[i].flags & 0x0F) > 8) { - char *ptr; - strncpy0(_tempStr, GET_VARO_STR(_collisionAreas[i].key), 255); - while ((ptr = strchr(_tempStr, ' '))) - _vm->_util->cutFromStr(_tempStr, (ptr - _tempStr), 1); - if (_vm->_language == 2) - while ((ptr = strchr(_tempStr, '.'))) - *ptr = ','; - WRITE_VARO_STR(_collisionAreas[i].key, _tempStr); - } - - if (((_collisionAreas[i].flags & 0x0F) >= 5) && - ((_collisionAreas[i].flags & 0x0F) <= 8)) { - str = (char *) descArray[var_24].ptr; - - strncpy0(_tempStr, GET_VARO_STR(_collisionAreas[i].key), 255); - - if ((_collisionAreas[i].flags & 0x0F) < 7) - _vm->_util->cleanupStr(_tempStr); - - int16 pos = 0; - do { - strncpy0(_collStr, str, 255); - pos += strlen(str) + 1; - - str += strlen(str) + 1; - - if ((_collisionAreas[i].flags & 0x0F) < 7) - _vm->_util->cleanupStr(_collStr); - - if (strcmp(_tempStr, _collStr) == 0) { - WRITE_VAR(17, VAR(17) + 1); - WRITE_VAR(17 + var_26, 1); - break; - } - } while (READ_LE_UINT16(descArray[var_24].ptr - 2) > pos); - collStackPos++; - } else { - WRITE_VAR(17 + var_26, 2); - } - var_24++; - var_26++; - } - - if (collStackPos != (int16) VAR(17)) - WRITE_VAR(17, 0); - else - WRITE_VAR(17, 1); - } - - if (_handleMouse == 1) - _vm->_draw->blitCursor(); - - if (!_vm->_inter->_terminate && (var_41 == 0)) { - _script->seek(_collisionAreas[activeCollIndex].funcLeave); - - _vm->_inter->storeMouse(); - if (VAR(16) == 0) { - if ((activeCollResId & 0xF000) == 0x8000) - WRITE_VAR(16, array[activeCollResId & 0xFFF]); - else - WRITE_VAR(16, activeCollResId & 0xFFF); - } - } else - _script->setFinished(true); - - for (curCmd = 0; curCmd < count; curCmd++) - freeCollision(curCmd + 0x8000); - - for (i = 0; i < 150; i++) { - if (((_collisionAreas[i].id & 0xF000) == 0xA000) || - ((_collisionAreas[i].id & 0xF000) == 0x9000)) - _collisionAreas[i].id |= 0x4000; - } -} - -void Game_v6::setCollisions(byte arg_0) { - for (Collision *collArea = _collisionAreas; collArea->left != 0xFFFF; collArea++) { - if (((collArea->id & 0xC000) != 0x8000) || (collArea->funcSub == 0)) - continue; - - if (arg_0 == 0) - if (collArea->flags & 0x80) - continue; - - Script *curScript = _script; - - _script = collArea->script; - if (!_script) - _script = curScript; - - _script->call(collArea->funcSub); - - int16 left = _script->readValExpr(); - int16 top = _script->readValExpr(); - int16 width = _script->readValExpr(); - int16 height = _script->readValExpr(); - uint16 flags = 0; - - if ((collArea->id & 0xF000) == 0xA000) - flags = _script->readValExpr(); - - if ((_vm->_draw->_renderFlags & RENDERFLAG_CAPTUREPOP) && - (left != -1)) { - left += _vm->_draw->_backDeltaX; - top += _vm->_draw->_backDeltaY; - } - if (_vm->_draw->_needAdjust != 2) { - _vm->_draw->adjustCoords(0, &left, &top); - if ((collArea->flags & 0x0F) < 3) - _vm->_draw->adjustCoords(2, &width, &height); - else { - height &= 0xFFFE; - _vm->_draw->adjustCoords(2, 0, &height); - } - } - - if (left < 0) { - width += left; - left = 0; - } - - if (top < 0) { - height += top; - top = 0; - } - - collArea->left = left; - collArea->top = top; - collArea->right = left + width - 1; - collArea->bottom = top + height - 1; - - if ((collArea->id & 0xF000) == 0xA000) - collArea->flags = flags; - - _script->pop(); - - _script = curScript; - } -} - -void Game_v6::collSub(uint16 offset) { - int16 collStackSize; - - uint32 savedPos = _script->pos(); - - _script->seek(offset); - - _shouldPushColls = 1; - collStackSize = _collStackSize; - - _vm->_inter->funcBlock(0); - - if (collStackSize != _collStackSize) - popCollisions(); - - _shouldPushColls = 0; - - _script->seek(savedPos); - - if ((_vm->_util->getTimeKey() - _someTimeDly) > 500) - setCollisions(0); -} - -static const byte adjustTable[] = { - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x21, 0x21, 0x21, 0x21, 0x21, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x81, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, - 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, - 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, - 0x12, 0x12, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, - 0x40, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x40, 0x40, 0x40, 0x40, 0x40, - 0x40, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x40, 0x40, 0x40, 0x40, 0x20, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -int16 Game_v6::adjustKey(int16 key) { - if (key == -1) - return -1; - - if (adjustTable[key & 0xFF] & 8) - return ((key & 0xFF) - 0x20); - - return key & 0xFF; -} - -int16 Game_v6::checkMousePoint(int16 all, int16 *resId, int16 *resIndex) { - Collision *ptr; - int16 i; - - if (resId != 0) - *resId = 0; - - *resIndex = 0; - - ptr = _collisionAreas; - for (i = 0; ptr->left != 0xFFFF; ptr++, i++) { - if (ptr->id & 0x4000) - continue; - - if (all) { - if ((ptr->flags & 0xF) > 1) - continue; - - if ((ptr->flags & 0xF00) != 0) - continue; - - if ((_vm->_global->_inter_mouseX < ptr->left) || - (_vm->_global->_inter_mouseX > ptr->right) || - (_vm->_global->_inter_mouseY < ptr->top) || - (_vm->_global->_inter_mouseY > ptr->bottom)) - continue; - - if (resId != 0) - *resId = ptr->id; - - *resIndex = i; - return ptr->key; - } else { - if ((ptr->flags & 0xF00) != 0) - continue; - - if ((ptr->flags & 0xF) < 1) - continue; - - if ((((ptr->flags & 0x70) >> 4) != (((int32) _mouseButtons) - 1)) && - (((ptr->flags & 0x70) >> 4) != 2)) - continue; - - if ((_vm->_global->_inter_mouseX < ptr->left) || - (_vm->_global->_inter_mouseX > ptr->right) || - (_vm->_global->_inter_mouseY < ptr->top) || - (_vm->_global->_inter_mouseY > ptr->bottom)) - continue; - - if (resId != 0) - *resId = ptr->id; - *resIndex = i; - if (((ptr->flags & 0xF) == 1) || ((ptr->flags & 0xF) == 2)) - return ptr->key; - return 0; - } - } - - if ((_mouseButtons != kMouseButtonsLeft) && (all == 0)) - return kKeyEscape; - - return 0; -} - -void Game_v6::collSubReenter() { - int16 lastCollAreaIndex = _lastCollAreaIndex; - int16 lastCollId = _lastCollId; - int16 collKey = checkMousePoint(1, &_lastCollId, &_lastCollAreaIndex); - - if (collKey == _lastCollKey) - return; - - if ((_lastCollKey != 0) && (lastCollId & 0x8000)) - collAreaSub(lastCollAreaIndex, 0); - - _lastCollKey = collKey; - - if ((_lastCollKey != 0) && (_lastCollId & 0x8000)) - collAreaSub(_lastCollAreaIndex, 1); -} - } // End of namespace Gob diff --git a/engines/gob/hotspots.cpp b/engines/gob/hotspots.cpp new file mode 100644 index 0000000000..bed9d6a7cb --- /dev/null +++ b/engines/gob/hotspots.cpp @@ -0,0 +1,1706 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#include "gob/hotspots.h" +#include "gob/global.h" +#include "gob/helper.h" +#include "gob/draw.h" +#include "gob/game.h" +#include "gob/script.h" +#include "gob/inter.h" + +namespace Gob { + +Hotspots::Hotspot::Hotspot() { + clear(); +} + +Hotspots::Hotspot::Hotspot(uint16 i, + uint16 l, uint16 t, uint16 r, uint16 b, uint16 f, uint16 k, + uint16 enter, uint16 leave, uint16 pos) { + + id = i; + left = l; + top = t; + right = r; + bottom = b; + flags = f; + key = k; + funcEnter = enter; + funcLeave = leave; + funcPos = pos; + script = 0; +} + +void Hotspots::Hotspot::clear() { + id = 0; + left = 0xFFFF; + top = 0; + right = 0; + bottom = 0; + flags = 0; + key = 0; + funcEnter = 0; + funcLeave = 0; + funcPos = 0; + script = 0; +} + +Hotspots::Type Hotspots::Hotspot::getType() const { + return (Type) (flags & 0xF); +} + +MouseButtons Hotspots::Hotspot::getButton() const { + uint8 buttonBits = ((flags & 0x70) >> 4); + + if (buttonBits == 0) + return kMouseButtonsLeft; + if (buttonBits == 1) + return kMouseButtonsRight; + if (buttonBits == 2) + return kMouseButtonsAny; + + return kMouseButtonsNone; +} + +uint8 Hotspots::Hotspot::getWindow() const { + return (flags & 0x0F00) >> 8; +} + +uint8 Hotspots::Hotspot::getCursor() const { + return (flags & 0xF000) >> 12; +} + +bool Hotspots::Hotspot::isIn(uint16 x, uint16 y) const { + if (x < left) + return false; + if (x > right) + return false; + if (y < top) + return false; + if (y > bottom) + return false; + + return true; +} + +bool Hotspots::Hotspot::buttonMatch(MouseButtons button) const { + MouseButtons myButton = getButton(); + + if (myButton == kMouseButtonsAny) + return true; + + if (myButton == kMouseButtonsNone) + return false; + + if (myButton == button) + return true; + + return false; +} + + +Hotspots::Hotspots(GobEngine *vm) : _vm(vm) { + _hotspots = new Hotspot[kHotspotCount]; + + _shouldPush = false; + + _currentKey = 0; + _currentIndex = 0; + _currentId = 0; +} + +Hotspots::~Hotspots() { + delete[] _hotspots; + + while (!_stack.empty()) { + StackEntry backup = _stack.pop(); + + delete[] backup.hotspots; + } +} + +void Hotspots::clear() { + _currentKey = 0; + + for (int i = 0; i < kHotspotCount; i++) + _hotspots[i].clear(); +} + +uint16 Hotspots::add(uint16 id, + uint16 left, uint16 top, uint16 right, uint16 bottom, + uint16 flags, uint16 key, + uint16 funcEnter, uint16 funcLeave, uint16 funcPos) { + + Hotspot hotspot(id, left, top, right, bottom, + flags, key, funcEnter, funcLeave, funcPos); + + return add(hotspot); +} + +uint16 Hotspots::add(const Hotspot &hotspot) { + for (int i = 0; i < kHotspotCount; i++) { + Hotspot &spot = _hotspots[i]; + + // free space => add same id => update + if (! ((spot.left == 0xFFFF) || (spot.id == hotspot.id))) + continue; + + // When updating, keep bit 0x4000 intact + uint16 id = hotspot.id; + if ((spot.id & 0xBFFF) == (hotspot.id & 0xBFFF)) + id = spot.id; + + // Set + spot = hotspot; + spot.id = id; + + // Remember the current script + spot.script = _vm->_game->_script; + + return i; + } + + error("Hotspots::add(): Hotspot array full"); + return 0xFFFF; +} + +void Hotspots::remove(uint16 id) { + for (int i = 0; i < kHotspotCount; i++) { + if (_hotspots[i].id == id) + _hotspots[i].clear(); + } +} + +void Hotspots::removeState(uint16 state) { + for (int i = 0; i < kHotspotCount; i++) { + Hotspot &spot = _hotspots[i]; + + if ((spot.id & 0xF000) == state) + spot.clear(); + } +} + +void Hotspots::recalculate(bool force) { + for (int i = 0; i < kHotspotCount; i++) { + Hotspot &spot = _hotspots[i]; + + if (spot.left == 0xFFFF) + // End reached + break; + + if (!force && ((spot.flags & 0x80) != 0)) + continue; + + if (spot.funcPos == 0) + continue; + + // Setting the needed script + Script *curScript = _vm->_game->_script; + + _vm->_game->_script = spot.script; + if (!_vm->_game->_script) + _vm->_game->_script = curScript; + + // Calling the function that contains the positions + _vm->_game->_script->call(spot.funcPos); + + // Calculate positions + int16 left = _vm->_game->_script->readValExpr(); + int16 top = _vm->_game->_script->readValExpr(); + int16 width = _vm->_game->_script->readValExpr(); + int16 height = _vm->_game->_script->readValExpr(); + + // Re-read the flags too, if applicable + uint16 flags = 0; + if ((spot.id & 0xF000) == 0xA000) + flags = _vm->_game->_script->readValExpr(); + + // Apply backDelta, if needed + if ((_vm->_draw->_renderFlags & RENDERFLAG_CAPTUREPOP) && (left != -1)) { + left += _vm->_draw->_backDeltaX; + top += _vm->_draw->_backDeltaY; + } + + // Clamping + if (left < 0) { + width += left; + left = 0; + } + if (top < 0) { + height += top; + top = 0; + } + + // Set the updated position + spot.left = left; + spot.top = top; + spot.right = left + width - 1; + spot.bottom = top + height - 1; + + if ((spot.id & 0xF000) == 0xA000) + spot.flags = flags; + + // Return + _vm->_game->_script->pop(); + + _vm->_game->_script = curScript; + } +} + +void Hotspots::push(uint8 all, bool force) { + // Should we push at all? + if (!_shouldPush && !force) + return; + + // Count the hotspots + uint32 size = 0; + for (int i = 0; i < kHotspotCount; i++) { + Hotspot &spot = _hotspots[i]; + + if (spot.left == 0xFFFF) + // End reached + break; + + // Save all of them + if ( (all == 1) || + // Don't save the global ones + ((all == 0) && (spot.id >= 20)) || + // Only save the ones with the correct state + ((all == 2) && (((spot.id & 0xF000) == 0xD000) || + ((spot.id & 0xF000) == 0x4000) || + ((spot.id & 0xF000) == 0xE000)))) { + size++; + } + + } + + StackEntry backup; + + backup.shouldPush = _shouldPush; + backup.size = size; + backup.key = _currentKey; + backup.id = _currentId; + backup.index = _currentIndex; + + backup.hotspots = new Hotspot[size]; + + // Copy the hotspots + Hotspot *destPtr = backup.hotspots; + for (int i = 0; i < kHotspotCount; i++) { + Hotspot &spot = _hotspots[i]; + + if (spot.left == 0xFFFF) + // End reached + break; + + // Save all of them + if ( (all == 1) || + // Don't save the global ones + ((all == 0) && (spot.id >= 20)) || + // Only save the ones with the correct state + ((all == 2) && (((spot.id & 0xF000) == 0xD000) || + ((spot.id & 0xF000) == 0x4000) || + ((spot.id & 0xF000) == 0xE000)))) { + + memcpy(destPtr, &spot, sizeof(Hotspot)); + destPtr++; + + spot.left = 0xFFFF; + } + + } + + // Reset current state + _shouldPush = false; + _currentKey = 0; + _currentId = 0; + _currentIndex = 0; + + _stack.push(backup); +} + +void Hotspots::pop() { + assert(!_stack.empty()); + + StackEntry backup = _stack.pop(); + + // Find the end of the filled hotspot space + int i; + Hotspot *destPtr = _hotspots; + for (i = 0; i < kHotspotCount; i++, destPtr++) + if (destPtr->left == 0xFFFF) + break; + + if (((uint32) (kHotspotCount - i)) < backup.size) + error("Hotspots::pop(): Not enough free space in the current Hotspot " + "array to pop %d elements (got %d)", backup.size, kHotspotCount - i); + + memcpy(destPtr, backup.hotspots, backup.size * sizeof(Hotspot)); + + _shouldPush = backup.shouldPush; + _currentKey = backup.key; + _currentId = backup.id; + _currentIndex = backup.index; + + delete[] backup.hotspots; +} + +bool Hotspots::isValid(uint16 key, uint16 id, uint16 index) const { + if (index >= kHotspotCount) + return false; + + if (key == 0) + return false; + + if (!(id & 0x8000)) + return false; + + return true; +} + +void Hotspots::call(uint16 offset) { + _vm->_game->_script->call(offset); + + _shouldPush = true; + + int16 stackSize = _stack.size(); + + _vm->_inter->funcBlock(0); + + while (stackSize != _stack.size()) + pop(); + + _shouldPush = false; + + _vm->_game->_script->pop(); + + recalculate(false); +} + +void Hotspots::enter(uint16 index) { + if (index >= kHotspotCount) { + warning("Hotspots::enter(): Index %d out of range", index); + return; + } + + Hotspot &spot = _hotspots[index]; + + if (((spot.id & 0xF000) == 0xA000) || ((spot.id & 0xF000) == 0x9000)) + WRITE_VAR(17, -(spot.id & 0x0FFF)); + + if (spot.funcEnter != 0) + call(spot.funcEnter); +} + +void Hotspots::leave(uint16 index) { + if (index >= kHotspotCount) { + warning("Hotspots::leave(): Index %d out of range", index); + return; + } + + Hotspot &spot = _hotspots[index]; + + if (((spot.id & 0xF000) == 0xA000) || ((spot.id & 0xF000) == 0x9000)) + WRITE_VAR(17, spot.id & 0x0FFF); + + if (spot.funcLeave != 0) + call(spot.funcLeave); +} + +uint16 Hotspots::checkMouse(Type type, uint16 &id, uint16 &index) const { + id = 0; + index = 0; + + if (type == kTypeMove) { + + for (int i = 0; i < kHotspotCount; i++) { + Hotspot &spot = _hotspots[i]; + + if (spot.left == 0xFFFF) + break; + + if (spot.id & 0x4000) + continue; + + if (spot.getType() > kTypeMove) + continue; + + if (spot.getWindow() != 0) + continue; + + if (!spot.isIn(_vm->_global->_inter_mouseX, _vm->_global->_inter_mouseY)) + continue; + + id = spot.id; + index = i; + + return spot.key; + } + + return 0; + + } else if (type == kTypeClick) { + + for (int i = 0; i < kHotspotCount; i++) { + Hotspot &spot = _hotspots[i]; + + if (spot.left == 0xFFFF) + break; + + if (spot.id & 0x4000) + continue; + + if (spot.getWindow() != 0) + continue; + + if (spot.getType() < kTypeMove) + continue; + + if (!spot.isIn(_vm->_global->_inter_mouseX, _vm->_global->_inter_mouseY)) + continue; + + if (!spot.buttonMatch(_vm->_game->_mouseButtons)) + continue; + + id = spot.id; + index = i; + + if ((spot.getType() == kTypeMove) || (spot.getType() == kTypeClick)) + return spot.key; + + return 0; + } + + if (_vm->_game->_mouseButtons != kMouseButtonsLeft) + return kKeyEscape; + + return 0; + + } + + return 0; +} + +void Hotspots::checkHotspotChanged() { + uint16 key, id, index; + + key = checkMouse(kTypeMove, id, index); + + if (key == _currentKey) + return; + + if (isValid(_currentKey, _currentId, _currentIndex)) + leave(_currentIndex); + + _currentKey = key; + _currentId = id; + _currentIndex = index; + + if (isValid(key, id, index)) + enter(index); +} + +uint16 Hotspots::check(uint8 handleMouse, int16 delay, uint16 &id, uint16 &index) { + _vm->_game->_scrollHandleMouse = handleMouse != 0; + + if (delay >= -1) { + _currentKey = 0; + _currentId = 0; + _currentIndex = 0; + } + + id = 0; + index = 0; + + if (handleMouse) { + if ((_vm->_draw->_cursorIndex == -1) && (_currentKey == 0)) { + _currentKey = checkMouse(kTypeMove, _currentId, _currentIndex); + + if (isValid(_currentKey, _currentId, _currentIndex)) + enter(_currentIndex); + } + + _vm->_draw->animateCursor(-1); + } + + uint32 startTime = _vm->_util->getTimeKey(); + + _vm->_draw->blitInvalidated(); + _vm->_video->retrace(); + + uint16 key = 0; + while (key == 0) { + + if (_vm->_inter->_terminate || _vm->shouldQuit()) { + if (handleMouse) + _vm->_draw->blitCursor(); + return 0; + } + + checkHotspotChanged(); + + if (!_vm->_draw->_noInvalidated) { + if (handleMouse) + _vm->_draw->animateCursor(-1); + else + _vm->_draw->blitInvalidated(); + _vm->_video->waitRetrace(); + } + + key = _vm->_game->checkKeys(&_vm->_global->_inter_mouseX, + &_vm->_global->_inter_mouseY, &_vm->_game->_mouseButtons, handleMouse); + + if (!handleMouse && (_vm->_game->_mouseButtons != kMouseButtonsNone)) { + _vm->_util->waitMouseRelease(0); + key = 3; + } + + if (key != 0) { + if (handleMouse & 1) + _vm->_draw->blitCursor(); + + id = 0; + index = 0; + + if (isValid(_currentKey, _currentId, _currentIndex)) + leave(_currentIndex); + + _currentKey = 0; + break; + } + + if (handleMouse) { + + if (_vm->_game->_mouseButtons != kMouseButtonsNone) { + + if (delay > 0) { + _vm->_draw->animateCursor(2); + _vm->_util->delay(delay); + } else if (handleMouse & 1) + _vm->_util->waitMouseRelease(1); + + _vm->_draw->animateCursor(-1); + + key = checkMouse(kTypeClick, id, index); + + if ((key != 0) || (id != 0)) { + if ( (handleMouse & 1) && + ((delay <= 0) || (_vm->_game->_mouseButtons == kMouseButtonsNone))) + _vm->_draw->blitCursor(); + + if (key != _currentKey) + leave(_currentIndex); + + _currentKey = 0; + break; + } + + if (handleMouse & 4) + return 0; + + if (_currentKey != 0) + leave(_currentIndex); + + _currentKey = checkMouse(kTypeMove, _currentId, _currentIndex); + if (isValid(_currentKey, _currentId, _currentIndex)) + enter(_currentIndex); + + } else + checkHotspotChanged(); + + } + + if ((delay == -2) && (key == 0) && + (_vm->_game->_mouseButtons == kMouseButtonsNone)) { + + id = 0; + index = 0; + break; + } + + if (handleMouse) + _vm->_draw->animateCursor(-1); + + if ((delay < 0) && (key == 0) && + (_vm->_game->_mouseButtons == kMouseButtonsNone)) { + + uint32 curTime = _vm->_util->getTimeKey(); + // Timeout reached? + if ((curTime + delay) > startTime) { + id = 0; + index = 0; + break; + } + + } + + _vm->_util->delay(10); + + } + + return key; +} + +uint16 Hotspots::check(uint8 handleMouse, int16 delay) { + uint16 id, index; + + return Hotspots::check(handleMouse, delay, id, index); +} + +uint16 Hotspots::readString(uint16 xPos, uint16 yPos, uint16 width, uint16 height, + uint16 backColor, uint16 frontColor, char *str, uint16 fontIndex, + Type type, int16 &duration, uint16 &id, uint16 index) { + + if ((fontIndex >= 8) || !_vm->_draw->_fonts[fontIndex]) + return 0; + + bool handleMouse = false; + if ( (_vm->_game->_handleMouse != 0) && + ((_vm->_global->_useMouse != 0) || (_vm->_game->_forceHandleMouse != 0))) + handleMouse = true; + + Video::FontDesc &font = *_vm->_draw->_fonts[fontIndex]; + + bool monoSpaced = (font.extraData == 0); + + uint32 pos = strlen(str); + uint32 editSize = monoSpaced ? 0 : (width / font.itemWidth); + + uint16 key = 0; + char tempStr[256]; + + while (1) { + strncpy0(tempStr, str, 254); + strcat(tempStr, " "); + if ((editSize != 0) && strlen(tempStr) > editSize) + strncpy0(tempStr, str, 255); + + _vm->_draw->_destSpriteX = xPos; + _vm->_draw->_destSpriteY = yPos; + _vm->_draw->_spriteRight = monoSpaced ? (editSize * font.itemWidth) : width; + _vm->_draw->_spriteBottom = height; + + _vm->_draw->_destSurface = 21; + _vm->_draw->_backColor = backColor; + _vm->_draw->_frontColor = frontColor; + _vm->_draw->_textToPrint = tempStr; + _vm->_draw->_transparency = 1; + _vm->_draw->_fontIndex = fontIndex; + _vm->_draw->spriteOperation(DRAW_FILLRECT | 0x10 ); + + _vm->_draw->_destSpriteY = yPos + (height - font.itemHeight) / 2; + _vm->_draw->spriteOperation(DRAW_PRINTTEXT | 0x10); + + if ((editSize != 0) && (pos == editSize)) + pos--; + + char curSym = tempStr[pos]; + + if (_vm->_inter->_variables) + WRITE_VAR(56, pos); + + bool first = true; + while (1) { + tempStr[0] = curSym; + tempStr[1] = 0; + + if (font.extraData) { + _vm->_draw->_destSpriteY = yPos; + _vm->_draw->_spriteBottom = height; + _vm->_draw->_spriteRight = 1; + + _vm->_draw->_destSpriteX = xPos; + for (uint32 j = 0; j < pos; j++) + _vm->_draw->_destSpriteX += font.extraData[str[j] - font.startItem]; + + } else { + _vm->_draw->_destSpriteX = xPos + font.itemWidth * pos; + _vm->_draw->_destSpriteY = yPos + height - 1; + _vm->_draw->_spriteRight = font.itemWidth; + _vm->_draw->_spriteBottom = 1; + } + + _vm->_draw->_destSurface = 21; + _vm->_draw->_backColor = frontColor; + _vm->_draw->spriteOperation(DRAW_FILLRECT | 0x10); + + if (first) { + key = check(handleMouse, -1, id, index); + + if (key == 0) + key = check(handleMouse, -300, id, index); + + first = false; + } else + key = check(handleMouse, -300, id, index); + + tempStr[0] = curSym; + tempStr[1] = 0; + + if (font.extraData) { + _vm->_draw->_destSpriteY = yPos; + _vm->_draw->_spriteBottom = height; + _vm->_draw->_spriteRight = 1; + + _vm->_draw->_destSpriteX = xPos; + for (uint32 j = 0; j < pos; j++) + _vm->_draw->_destSpriteX += font.extraData[str[j] - font.startItem]; + + } else { + _vm->_draw->_destSpriteX = xPos + font.itemWidth * pos; + _vm->_draw->_destSpriteY = yPos + height - 1; + _vm->_draw->_spriteRight = font.itemWidth; + _vm->_draw->_spriteBottom = 1; + } + + _vm->_draw->_destSurface = 21; + _vm->_draw->_backColor = backColor; + _vm->_draw->_frontColor = frontColor; + _vm->_draw->_textToPrint = tempStr; + _vm->_draw->_transparency = 1; + _vm->_draw->_fontIndex = fontIndex; + _vm->_draw->spriteOperation(DRAW_FILLRECT | 0x10); + + _vm->_draw->_destSpriteY = yPos + (height - font.itemHeight) / 2; + _vm->_draw->spriteOperation(DRAW_PRINTTEXT | 0x10); + + if ((key != 0) || (id != 0)) + break; + + key = check(handleMouse, -300, id, index); + + if ((key != 0) || (id != 0) || + _vm->_inter->_terminate || _vm->shouldQuit()) + break; + + if (duration > 0) { + duration -= 600; + if (duration <= 1) { + key = 0; + id = 0; + break; + } + } + } + + if ((key == 0) || (id != 0) || + _vm->_inter->_terminate || _vm->shouldQuit()) + return 0; + + switch (key) { + case kKeyRight: + if ((pos > strlen(str)) || (pos > (editSize - 1)) || (editSize == 0)) { + pos++; + continue; + } + return kKeyDown; + + case kKeyLeft: + if (pos > 0) { + pos--; + continue; + } + return kKeyUp; + + case kKeyBackspace: + if (pos > 0) { + _vm->_util->cutFromStr(str, pos - 1, 1); + pos--; + continue; + } else { + if (pos < strlen(str)) + _vm->_util->cutFromStr(str, pos, 1); + } + + case kKeyDelete: + if (pos >= strlen(str)) + continue; + + _vm->_util->cutFromStr(str, pos, 1); + continue; + + case kKeyReturn: + case kKeyF1: + case kKeyF2: + case kKeyF3: + case kKeyF4: + case kKeyF5: + case kKeyF6: + case kKeyF7: + case kKeyF8: + case kKeyF9: + case kKeyF10: + case kKeyUp: + case kKeyDown: + return key; + + case kKeyEscape: + if (_vm->_global->_useMouse != 0) + continue; + + _vm->_game->_forceHandleMouse = !_vm->_game->_forceHandleMouse; + + handleMouse = false; + if ( (_vm->_game->_handleMouse != 0) && + ((_vm->_global->_useMouse != 0) || (_vm->_game->_forceHandleMouse != 0))) + handleMouse = true; + + while (_vm->_global->_pressedKeys[1] != 0) + ; + continue; + + default: + uint16 savedKey = key; + + key &= 0xFF; + + if (((type == kTypeInputFloatNoLeave) || (type == kTypeInputFloatLeave)) && + (key >= ' ') && (key <= 0xFF)) { + const char *str1 = "0123456789-.,+ "; + const char *str2 = "0123456789-,,+ "; + + if ((((savedKey >> 8) > 1) && ((savedKey >> 8) < 12)) && + ((_vm->_global->_pressedKeys[42] != 0) || + (_vm->_global->_pressedKeys[56] != 0))) + key = ((savedKey >> 8) - 1) % 10 + '0'; + + int i; + for (i = 0; str1[i] != 0; i++) { + if (key == str1[i]) { + key = str2[i]; + break; + } + } + + if (i == (int16) strlen(str1)) + key = 0; + } + + if ((key >= ' ') && (key <= 0xFF)) { + if (editSize == 0) { + int length = _vm->_draw->stringLength(str, fontIndex) + + font.extraData[' ' - font.startItem] + + font.extraData[key - font.startItem]; + + if (length > width) + continue; + + if (((int32) strlen(str)) >= (_vm->_global->_inter_animDataSize * 4 - 1)) + continue; + + } else { + if (strlen(str) > editSize) + continue; + else if (editSize == strlen(str)) + _vm->_util->cutFromStr(str, strlen(str) - 1, 1); + } + + pos++; + tempStr[0] = key; + tempStr[1] = 0; + + _vm->_util->insertStr(tempStr, str, pos - 1); + } + + } + } +} + +uint16 Hotspots::handleInput(int16 time, uint16 maxPos, uint16 &curPos, + InputDesc *inpDesc, uint16 &id, uint16 &index) { + + uint16 descInd = 0; + uint16 key = 0; + uint16 found = 0xFFFF; + + for (int i = 0; i < kHotspotCount; i++) { + Hotspot &spot = _hotspots[i]; + + if (spot.left == 0xFFFF) + continue; + + if ((spot.id & 0xC000) != 0x8000) + continue; + + if (spot.getType() < kTypeInput1NoLeave) + continue; + + if (spot.getType() > kTypeInputFloatLeave) + continue; + + char tempStr[256]; + strncpy0(tempStr, GET_VARO_STR(spot.key), 255); + + _vm->_draw->_destSpriteX = spot.left; + _vm->_draw->_destSpriteY = spot.top; + _vm->_draw->_spriteRight = spot.right - spot.left + 1; + _vm->_draw->_spriteBottom = spot.bottom - spot.top + 1; + + _vm->_draw->_destSurface = 21; + + _vm->_draw->_backColor = inpDesc[descInd].backColor; + _vm->_draw->_frontColor = inpDesc[descInd].frontColor; + _vm->_draw->_textToPrint = tempStr; + _vm->_draw->_transparency = 1; + _vm->_draw->_fontIndex = inpDesc[descInd].fontIndex; + + _vm->_draw->spriteOperation(DRAW_FILLRECT | 0x10); + + _vm->_draw->_destSpriteY += ((spot.bottom - spot.top + 1) - + _vm->_draw->_fonts[_vm->_draw->_fontIndex]->itemHeight) / 2; + _vm->_draw->spriteOperation(DRAW_PRINTTEXT | 0x10); + + descInd++; + } + + for (int i = 0; i < 40; i++) + WRITE_VAR_OFFSET(i * 4 + 0x44, 0); + + while (1) { + descInd = 0; + + for (int i = 0; i < kHotspotCount; i++) { + Hotspot &spot = _hotspots[i]; + + if (spot.left == 0xFFFF) + continue; + + if ((spot.id & 0xC000) != 0x8000) + continue; + + if (spot.getType() < kTypeInput1NoLeave) + continue; + + if (spot.getType() > kTypeInputFloatLeave) + continue; + + if (descInd == curPos) { + found = i; + break; + } + + descInd++; + } + + assert(found != 0xFFFF); + + Hotspot inputSpot = _hotspots[found]; + + key = readString(inputSpot.left, inputSpot.top, + inputSpot.right - inputSpot.left + 1, + inputSpot.bottom - inputSpot.top + 1, + inpDesc[curPos].backColor, inpDesc[curPos].frontColor, + GET_VARO_STR(inputSpot.key), inpDesc[curPos].fontIndex, + inputSpot.getType(), time, id, index); + + if (_vm->_inter->_terminate) + return 0; + + switch (key) { + case kKeyNone: + if (id == 0) + return 0; + + if (_vm->_game->_mouseButtons != kMouseButtonsNone) { + for (int i = 0; i < kHotspotCount; i++) { + Hotspot &spot = _hotspots[i]; + + if (spot.left == 0xFFFF) + break; + + if (spot.getWindow() != 0) + continue; + + if ((spot.id & 0x4000)) + continue; + + if (!spot.isIn(_vm->_global->_inter_mouseX, _vm->_global->_inter_mouseY)) + continue; + + if ((spot.id & 0xF000)) + continue; + + if (spot.getType() < kTypeInput1NoLeave) + continue; + + if (spot.getType() > kTypeInputFloatLeave) + continue; + + index = i; + break; + } + } + + if (_hotspots[index].getType() < kTypeInput1NoLeave) + return 0; + + if (_hotspots[index].getType() > kTypeInputFloatLeave) + return 0; + + curPos = 0; + for (int i = 0; i < kHotspotCount; i++) { + Hotspot &spot = _hotspots[i]; + + if (spot.left == 0xFFFF) + continue; + + if ((spot.id & 0xC000) != 0x8000) + continue; + + if (spot.getType() < kTypeInput1NoLeave) + continue; + + if (spot.getType() > kTypeInputFloatLeave) + continue; + + if (i == index) + break; + + curPos++; + } + break; + + case kKeyF1: + case kKeyF2: + case kKeyF3: + case kKeyF4: + case kKeyF5: + case kKeyF6: + case kKeyF7: + case kKeyF8: + case kKeyF9: + case kKeyF10: + return key; + + case kKeyReturn: + + if (maxPos == 1) + return key; + + if (curPos == (maxPos - 1)) { + curPos = 0; + break; + } + + curPos++; + break; + + case kKeyDown: + if ((maxPos - 1) > curPos) + curPos++; + break; + + case kKeyUp: + if (curPos > 0) + curPos--; + break; + } + } +} + +void Hotspots::evaluate() { + InputDesc descArray[20]; + int16 array[300]; + char *str; + int16 counter; + int16 var_24; + int16 var_26; + int16 collStackPos; + + push(0); + + uint16 endIndex = 0; + while (_hotspots[endIndex].left != 0xFFFF) + endIndex++; + + _shouldPush = false; + + _vm->_game->_script->skip(1); + + byte count = _vm->_game->_script->readByte(); + + _vm->_game->_handleMouse = _vm->_game->_script->peekByte(0); + int16 duration = _vm->_game->_script->peekByte(1); + byte stackPos2 = _vm->_game->_script->peekByte(3); + byte descIndex = _vm->_game->_script->peekByte(4); + bool needRecalculation = _vm->_game->_script->peekByte(5) != 0; + + duration *= 1000; + if ((stackPos2 != 0) || (descIndex != 0)) { + duration /= 100; + if (_vm->_game->_script->peekByte(1) == 100) + duration = 2; + } + + int16 timeVal = duration; + + _vm->_game->_script->skip(6); + + WRITE_VAR(16, 0); + + byte var_41 = 0; + int16 var_46 = 0; + + uint16 id = 0; + uint16 validId = 0xFFFF; + uint16 index = 0; + + bool hasInput = false; + uint16 inputIndex = 0; + + for (uint16 i = 0; i < count; i++) { + array[i] = 0; + + byte type = _vm->_game->_script->readByte(); + byte window = 0; + + if ((type & 0x40) != 0) { + type -= 0x40; + window = _vm->_game->_script->readByte(); + } + + uint16 left, top, width, height, right, bottom; + uint32 funcEnter = 0, funcLeave = 0, funcPos = 0; + if ((type & 0x80) != 0) { + funcPos = _vm->_game->_script->pos(); + left = _vm->_game->_script->readValExpr(); + top = _vm->_game->_script->readValExpr(); + width = _vm->_game->_script->readValExpr(); + height = _vm->_game->_script->readValExpr(); + } else { + funcPos = 0; + left = _vm->_game->_script->readUint16(); + top = _vm->_game->_script->readUint16(); + width = _vm->_game->_script->readUint16(); + height = _vm->_game->_script->readUint16(); + } + + if ((_vm->_draw->_renderFlags & RENDERFLAG_CAPTUREPOP) && (left != 0xFFFF)) { + left += _vm->_draw->_backDeltaX; + top += _vm->_draw->_backDeltaY; + } + + right = left + width - 1; + bottom = top + height - 1; + + int16 key = 0; + int16 flags = 0; + Video::FontDesc *font = 0; + + type &= 0x7F; + switch (type) { + case kTypeNone: + _vm->_game->_script->skip(6); + + funcEnter = _vm->_game->_script->pos(); + _vm->_game->_script->skipBlock(); + + funcLeave = _vm->_game->_script->pos(); + _vm->_game->_script->skipBlock(); + + key = i + 0xA000; + flags = type + (window << 8); + + add(i + 0x8000, left, top, right, bottom, + flags, key, funcEnter, funcLeave, funcPos); + break; + + case kTypeMove: + key = _vm->_game->_script->readInt16(); + array[i] = _vm->_game->_script->readInt16(); + flags = _vm->_game->_script->readInt16(); + + funcEnter = _vm->_game->_script->pos(); + _vm->_game->_script->skipBlock(); + + funcLeave = _vm->_game->_script->pos(); + _vm->_game->_script->skipBlock(); + + if (key == 0) + key = i + 0xA000; + flags = type + (window << 8) + (flags << 4); + + add(i + 0x8000, left, top, right, bottom, + flags, key, funcEnter, funcLeave, funcPos); + break; + + case kTypeInput1NoLeave: + case kTypeInput1Leave: + case kTypeInput2NoLeave: + case kTypeInput2Leave: + case kTypeInput3NoLeave: + case kTypeInput3Leave: + case kTypeInputFloatNoLeave: + case kTypeInputFloatLeave: + hasInput = true; + + _vm->_util->clearKeyBuf(); + + key = _vm->_game->_script->readVarIndex(); + descArray[inputIndex].fontIndex = _vm->_game->_script->readInt16(); + descArray[inputIndex].backColor = _vm->_game->_script->readByte(); + descArray[inputIndex].frontColor = _vm->_game->_script->readByte(); + descArray[inputIndex].ptr = 0; + + if ((type >= kTypeInput2NoLeave) && (type <= kTypeInput3Leave)) { + descArray[inputIndex].ptr = _vm->_game->_script->getData() + _vm->_game->_script->pos() + 2; + _vm->_game->_script->skip(_vm->_game->_script->peekUint16() + 2); + } + + if (left == 0xFFFF) { + if ((type & 1) == 0) + _vm->_game->_script->skipBlock(); + break; + } + + font = _vm->_draw->_fonts[descArray[inputIndex].fontIndex]; + if (!font->extraData) + right = left + width * font->itemWidth - 1; + + funcEnter = 0; + funcPos = 0; + funcLeave = 0; + if (!(type & 1)) { + funcLeave = _vm->_game->_script->pos(); + _vm->_game->_script->skipBlock(); + } + + flags = type; + + inputIndex++; + + add(i + 0x8000, left, top, right, bottom, + flags, key, funcEnter, funcLeave, funcPos); + + break; + + case 11: + _vm->_game->_script->skip(6); + + for (int j = 0; j < kHotspotCount; j++) { + Hotspot &spot = _hotspots[j]; + + if ((spot.id & 0xF000) == 0xE000) { + spot.id &= 0xBFFF; + spot.funcEnter = _vm->_game->_script->pos(); + spot.funcLeave = _vm->_game->_script->pos(); + } + } + + _vm->_game->_script->skipBlock(); + break; + + case 12: + _vm->_game->_script->skip(6); + + for (int j = 0; j < kHotspotCount; j++) { + Hotspot &spot = _hotspots[j]; + + if ((spot.id & 0xF000) == 0xD000) { + spot.id &= 0xBFFF; + spot.funcEnter = _vm->_game->_script->pos(); + spot.funcLeave = _vm->_game->_script->pos(); + } + } + + _vm->_game->_script->skipBlock(); + break; + + case 20: + validId = i; + // Fall through to case 2 + case kTypeClick: + key = _vm->_game->_script->readInt16(); + array[i] = _vm->_game->_script->readInt16(); + flags = _vm->_game->_script->readInt16(); + + funcEnter = 0; + + funcLeave = _vm->_game->_script->pos(); + _vm->_game->_script->skipBlock(); + + flags = 2 + (window << 8) + (flags << 4); + + add(i + 0x8000, left, top, right, bottom, + flags, key, funcEnter, funcLeave, funcPos); + break; + + case 21: + key = _vm->_game->_script->readInt16(); + array[i] = _vm->_game->_script->readInt16(); + flags = _vm->_game->_script->readInt16() & 3; + + funcEnter = _vm->_game->_script->pos(); + _vm->_game->_script->skipBlock(); + + funcLeave = 0; + + flags = 2 + (window << 8) + (flags << 4); + + add(i + 0x8000, left, top, right, bottom, + flags, key, funcEnter, funcLeave, funcPos); + break; + } + } + + if (needRecalculation) + recalculate(true); + + _vm->_game->_forceHandleMouse = 0; + _vm->_util->clearKeyBuf(); + + do { + uint16 key = 0; + if (hasInput) { + uint16 curEditIndex = 0; + + key = handleInput(duration, inputIndex, curEditIndex, descArray, id, index); + + WRITE_VAR(55, curEditIndex); + if (key == kKeyReturn) { + for (int i = 0; i < kHotspotCount; i++) { + Hotspot &spot = _hotspots[i]; + + if (spot.left == 0xFFFF) + break; + + if ((spot.id & 0xC000) != 0x8000) + continue; + + if ((spot.getType() & 1) != 0) + continue; + + if (spot.getType() <= kTypeClick) + continue; + + id = spot.id; + validId = spot.id & 0x7FFF; + index = i; + break; + } + break; + } + } else + key = check(_vm->_game->_handleMouse, -duration, id, index); + + if (((key & 0xFF) >= ' ') && ((key & 0xFF) <= 0xFF) && + ((key >> 8) > 1) && ((key >> 8) < 12)) + key = '0' + (((key >> 8) - 1) % 10) + (key & 0xFF00); + + if (id == 0) { + if (key != 0) { + for (int i = 0; i < kHotspotCount; i++) { + Hotspot &spot = _hotspots[i]; + + if (spot.left == 0xFFFF) + break; + + if ((spot.id & 0xC000) != 0x8000) + continue; + + if ((spot.key == key) || (spot.key == 0x7FFF)) { + id = spot.id; + index = i; + break; + } + } + + if (id == 0) { + for (int i = 0; i < kHotspotCount; i++) { + Hotspot &spot = _hotspots[i]; + + if (spot.left == 0xFFFF) + break; + + if ((spot.id & 0xC000) != 0x8000) + continue; + + if ((spot.key & 0xFF00) != 0) + continue; + + if (spot.key == 0) + continue; + + if (toupper(key & 0xFF) == toupper(spot.key)) { + id = spot.id; + index = i; + break; + } + } + } + } else if (duration != 0) { + if (stackPos2 != 0) { + collStackPos = 0; + + for (int i = endIndex; i < kHotspotCount; i++) { + Hotspot &spot = _hotspots[i]; + + if (spot.left == 0xFFFF) + break; + + if ((spot.id & 0xF000) != 0x8000) + continue; + + collStackPos++; + if (collStackPos != stackPos2) + continue; + + id = spot.id; + index = i; + _vm->_inter->storeMouse(); + if (VAR(16) != 0) + break; + + if ((id & 0xF000) == 0x8000) + WRITE_VAR(16, array[id & 0xFFF]); + else + WRITE_VAR(16, id & 0xFFF); + + if (spot.funcLeave != 0) { + uint32 timeKey = _vm->_util->getTimeKey(); + call(spot.funcLeave); + + if (timeVal != 2) { + duration = timeVal - (_vm->_util->getTimeKey() - timeKey); + + if ((duration - var_46) < 3) { + var_46 -= (duration - 3); + duration = 3; + } else if (var_46 != 0) { + duration -= var_46; + var_46 = 0; + } + + if (duration > timeVal) + duration = timeVal; + + } else + duration = 2; + + } + + if (VAR(16) == 0) + id = 0; + else + var_41 = 1; + + break; + } + + } else { + if (descIndex != 0) { + + counter = 0; + for (int i = endIndex; i < kHotspotCount; i++) { + Hotspot &spot = _hotspots[i]; + + if (spot.left == 0xFFFF) + break; + + if ((spot.id & 0xF000) == 0x8000) { + if (++counter == descIndex) { + id = spot.id; + index = i; + break; + } + } + + } + + } else { + + for (int i = 0; i < kHotspotCount; i++) { + Hotspot &spot = _hotspots[i]; + + if (spot.left == 0xFFFF) + break; + + if ((spot.id & 0xF000) == 0x8000) { + id = spot.id; + index = i; + break; + } + } + + if ((_currentKey != 0) && (_hotspots[_currentIndex].funcLeave != 0)) + call(_hotspots[_currentIndex].funcLeave); + + _currentKey = 0; + } + + } + } + } + + if (var_41 != 0) + break; + + if ((id == 0) || (_hotspots[index].funcLeave != 0)) + continue; + + _vm->_inter->storeMouse(); + + if ((id & 0xF000) == 0x8000) + WRITE_VAR(16, array[id & 0xFFF]); + else + WRITE_VAR(16, id & 0xFFF); + + if (_hotspots[index].funcEnter != 0) + call(_hotspots[index].funcEnter); + + WRITE_VAR(16, 0); + id = 0; + } + while ((id == 0) && !_vm->_inter->_terminate && !_vm->shouldQuit()); + + char tempStr[256]; + if ((id & 0xFFF) == validId) { + collStackPos = 0; + var_24 = 0; + var_26 = 1; + for (int i = 0; i < kHotspotCount; i++) { + Hotspot &spot = _hotspots[i]; + + if (spot.left == 0xFFFF) + continue; + + if ((spot.id & 0xC000) != 0x8000) + continue; + + if (spot.getType() < kTypeInput1NoLeave) + continue; + + if (spot.getType() > kTypeInputFloatLeave) + continue; + + if (spot.getType() > kTypeInput3Leave) { + char *ptr; + strncpy0(tempStr, GET_VARO_STR(spot.key), 255); + while ((ptr = strchr(tempStr, ' '))) + _vm->_util->cutFromStr(tempStr, (ptr - tempStr), 1); + if (_vm->_global->_language == kLanguageBritish) + while ((ptr = strchr(tempStr, '.'))) + *ptr = ','; + WRITE_VARO_STR(spot.key, tempStr); + } + + if ((spot.getType() >= kTypeInput2NoLeave) && (spot.getType() <= kTypeInput3Leave)) { + str = (char *) descArray[var_24].ptr; + + strncpy0(tempStr, GET_VARO_STR(spot.key), 255); + + if (spot.getType() < kTypeInput3NoLeave) + _vm->_util->cleanupStr(tempStr); + + int16 pos = 0; + do { + char spotStr[256]; + + strncpy0(spotStr, str, 255); + pos += strlen(str) + 1; + + str += strlen(str) + 1; + + if (spot.getType() < kTypeInput3NoLeave) + _vm->_util->cleanupStr(spotStr); + + if (strcmp(tempStr, spotStr) == 0) { + WRITE_VAR(17, VAR(17) + 1); + WRITE_VAR(17 + var_26, 1); + break; + } + } while (READ_LE_UINT16(descArray[var_24].ptr - 2) > pos); + collStackPos++; + } else { + WRITE_VAR(17 + var_26, 2); + } + var_24++; + var_26++; + } + + if (collStackPos != (int16) VAR(17)) + WRITE_VAR(17, 0); + else + WRITE_VAR(17, 1); + } + + if (_vm->_game->_handleMouse == 1) + _vm->_draw->blitCursor(); + + if (!_vm->_inter->_terminate && (var_41 == 0)) { + _vm->_game->_script->seek(_hotspots[index].funcLeave); + + _vm->_inter->storeMouse(); + if (VAR(16) == 0) { + if ((id & 0xF000) == 0x8000) + WRITE_VAR(16, array[id & 0xFFF]); + else + WRITE_VAR(16, id & 0xFFF); + } + } else + _vm->_game->_script->setFinished(true); + + for (int i = 0; i < count; i++) + remove(i + 0x8000); + + for (int i = 0; i < kHotspotCount; i++) { + Hotspot &spot = _hotspots[i]; + + if (((spot.id & 0xF000) == 0xA000) || ((spot.id & 0xF000) == 0x9000)) + spot.id |= 0x4000; + } + +} + +int16 Hotspots::findCursor(uint16 x, uint16 y) const { + int16 cursor = 0; + + for (int i = 0; i < kHotspotCount; i++) { + Hotspot &spot = _hotspots[i]; + + if (spot.left == 0xFFFF) + break; + + if ((spot.getWindow() != 0) || (spot.id & 0x4000)) + continue; + + if (!spot.isIn(x, y)) + continue; + + if (spot.getCursor() == 0) { + if (spot.getType() >= kTypeInput1NoLeave) { + cursor = 3; + break; + } else if ((spot.getButton() != kMouseButtonsRight) && (cursor == 0)) + cursor = 1; + } else if (cursor == 0) + cursor = spot.getCursor(); + } + + return cursor; +} + +} // End of namespace Gob diff --git a/engines/gob/hotspots.h b/engines/gob/hotspots.h new file mode 100644 index 0000000000..0bafb94937 --- /dev/null +++ b/engines/gob/hotspots.h @@ -0,0 +1,177 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#ifndef GOB_HOTSPOTS_H +#define GOB_HOTSPOTS_H + +#include "common/stack.h" + +#include "gob/util.h" + +namespace Gob { + +class Script; + +class Hotspots { +public: + static const int kHotspotCount = 250; + + enum Type { + kTypeNone = 0, + kTypeMove = 1, + kTypeClick = 2, + kTypeInput1NoLeave = 3, + kTypeInput1Leave = 4, + kTypeInput2NoLeave = 5, + kTypeInput2Leave = 6, + kTypeInput3NoLeave = 7, + kTypeInput3Leave = 8, + kTypeInputFloatNoLeave = 9, + kTypeInputFloatLeave = 10 + }; + + Hotspots(GobEngine *vm); + ~Hotspots(); + + void clear(); + + /** Add a hotspot, returning the new index. */ + uint16 add(uint16 id, + uint16 left, uint16 top, uint16 right, uint16 bottom, + uint16 flags, uint16 key, + uint16 funcEnter, uint16 funcLeave, uint16 funcPos); + + void remove(uint16 id); + void removeState(uint16 state); + + /** Push the current hotspots onto the stack. + * + * @param all 0: Don't push global ones; 1: Push all; 2: Push only the ones with the correct state + * @param force Force a push although _shouldPush is false + */ + void push(uint8 all, bool force = false); + /** Pop hotspots from the stack. */ + void pop(); + + uint16 check(uint8 handleMouse, int16 delay, uint16 &id, uint16 &index); + uint16 check(uint8 handleMouse, int16 delay); + + void evaluate(); + + int16 findCursor(uint16 x, uint16 y) const; + +private: + struct Hotspot { + uint16 id; + uint16 left; + uint16 top; + uint16 right; + uint16 bottom; + uint16 flags; + uint16 key; + uint16 funcEnter; + uint16 funcLeave; + uint16 funcPos; + Script *script; + + Hotspot(); + Hotspot(uint16 i, + uint16 l, uint16 t, uint16 r, uint16 b, uint16 f, uint16 k, + uint16 enter, uint16 leave, uint16 pos); + + void clear(); + + Type getType() const; + MouseButtons getButton() const; + uint8 getWindow() const; + uint8 getCursor() const; + + /** Are the specified coordinates in the hotspot? */ + bool isIn(uint16 x, uint16 y) const; + /** Does the specified button trigger the hotspot? */ + bool buttonMatch(MouseButtons button) const; + }; + + struct StackEntry { + bool shouldPush; + Hotspot *hotspots; + uint32 size; + uint32 key; + uint32 id; + uint32 index; + }; + + struct InputDesc { + uint16 fontIndex; + uint16 backColor; + uint16 frontColor; + byte *ptr; + }; + + GobEngine *_vm; + + Hotspot *_hotspots; + Common::Stack<StackEntry> _stack; + + bool _shouldPush; + + uint16 _currentKey; + uint16 _currentIndex; + uint16 _currentId; + + /** Add a hotspot, returning the new index. */ + uint16 add(const Hotspot &hotspot); + + /** Recalculate all hotspot parameters + * + * @param force Force recalculation of all hotspots, including global ones. + */ + void recalculate(bool force); + + bool isValid(uint16 key, uint16 id, uint16 index) const; + + /** Call a hotspot subroutine. */ + void call(uint16 offset); + /** Handling hotspot enter events. */ + void enter(uint16 index); + /** Handling hotspot leave events. */ + void leave(uint16 index); + + /** Which hotspot is the mouse cursor currently at? */ + uint16 checkMouse(Type type, uint16 &id, uint16 &index) const; + +void checkHotspotChanged(); + + uint16 readString(uint16 xPos, uint16 yPos, uint16 width, uint16 height, + uint16 backColor, uint16 frontColor, char *str, uint16 fontIndex, + Type type, int16 &duration, uint16 &id, uint16 index); + + uint16 handleInput(int16 time, uint16 hotspotIndex, uint16 &curPos, + InputDesc *inpDesc, uint16 &id, uint16 &index); +}; + +} // End of namespace Gob + +#endif // GOB_HOTSPOTS_H diff --git a/engines/gob/inter.cpp b/engines/gob/inter.cpp index 5ec0647d29..afd215a00d 100644 --- a/engines/gob/inter.cpp +++ b/engines/gob/inter.cpp @@ -35,6 +35,7 @@ #include "gob/game.h" #include "gob/expression.h" #include "gob/script.h" +#include "gob/hotspots.h" #include "gob/scenery.h" #include "gob/sound/sound.h" @@ -334,7 +335,7 @@ void Inter::callSub(int16 retFlag) { if (block == 1) funcBlock(retFlag); else if (block == 2) - _vm->_game->collisionsBlock(); + _vm->_game->_hotspots->evaluate(); else error("Unknown block type %d in Inter::callSub()", block); } diff --git a/engines/gob/inter_v1.cpp b/engines/gob/inter_v1.cpp index 23c9351dd4..7d32104552 100644 --- a/engines/gob/inter_v1.cpp +++ b/engines/gob/inter_v1.cpp @@ -37,6 +37,7 @@ #include "gob/expression.h" #include "gob/script.h" #include "gob/resources.h" +#include "gob/hotspots.h" #include "gob/goblin.h" #include "gob/inter.h" #include "gob/map.h" @@ -1173,7 +1174,7 @@ bool Inter_v1::o1_keyFunc(OpFuncParams ¶ms) { case 0: _vm->_draw->_showCursor &= ~2; _vm->_util->longDelay(1); - key = _vm->_game->checkCollisions(0, 0, 0, 0); + key = _vm->_game->_hotspots->check(0, 0); storeKey(key); _vm->_util->clearKeyBuf(); diff --git a/engines/gob/inter_v2.cpp b/engines/gob/inter_v2.cpp index 82822330b1..d71a321db7 100644 --- a/engines/gob/inter_v2.cpp +++ b/engines/gob/inter_v2.cpp @@ -39,6 +39,7 @@ #include "gob/expression.h" #include "gob/script.h" #include "gob/resources.h" +#include "gob/hotspots.h" #include "gob/goblin.h" #include "gob/map.h" #include "gob/mult.h" @@ -1177,66 +1178,48 @@ bool Inter_v2::o2_animPalInit(OpFuncParams ¶ms) { } bool Inter_v2::o2_addCollision(OpFuncParams ¶ms) { - int16 id; - int16 left, top, width, height; - int16 flags; - int16 key; - int16 funcSub; - - id = _vm->_game->_script->readValExpr(); - funcSub = _vm->_game->_script->pos(); - left = _vm->_game->_script->readValExpr(); - top = _vm->_game->_script->readValExpr(); - width = _vm->_game->_script->readValExpr(); - height = _vm->_game->_script->readValExpr(); - flags = _vm->_game->_script->readValExpr(); - key = _vm->_game->_script->readInt16(); + int16 id = _vm->_game->_script->readValExpr(); + uint16 funcPos = _vm->_game->_script->pos(); + int16 left = _vm->_game->_script->readValExpr(); + int16 top = _vm->_game->_script->readValExpr(); + uint16 width = _vm->_game->_script->readValExpr(); + uint16 height = _vm->_game->_script->readValExpr(); + uint16 flags = _vm->_game->_script->readValExpr(); + uint16 key = _vm->_game->_script->readInt16(); if (key == 0) key = ABS(id) + 41960; - _vm->_draw->adjustCoords(0, &left, &top); - _vm->_draw->adjustCoords(2, &width, &height); - if (left < 0) { width += left; - left = 0; + left = 0; } if (top < 0) { height += top; - top = 0; + top = 0; } int16 index; if (id < 0) - index = _vm->_game->addNewCollision(0xD000 - id, left & 0xFFFC, top & 0xFFFC, - left + width + 3, top + height + 3, flags, key, 0, 0); + index = _vm->_game->_hotspots->add(0xD000 - id, left & 0xFFFC, top & 0xFFFC, + left + width + 3, top + height + 3, flags, key, 0, 0, funcPos); else - index = _vm->_game->addNewCollision(0xE000 + id, left, top, - left + width - 1, top + height - 1, flags, key, 0, 0); - - _vm->_game->_collisionAreas[index].funcSub = funcSub; + index = _vm->_game->_hotspots->add(0xE000 + id, left, top, + left + width - 1, top + height - 1, flags, key, 0, 0, funcPos); return false; } bool Inter_v2::o2_freeCollision(OpFuncParams ¶ms) { - int16 id; + int16 id = _vm->_game->_script->readValExpr(); - id = _vm->_game->_script->readValExpr(); - if (id == -2) { - for (int i = 0; i < 150; i++) { - if ((_vm->_game->_collisionAreas[i].id & 0xF000) == 0xD000) - _vm->_game->_collisionAreas[i].left = 0xFFFF; - } - } else if (id == -1) { - for (int i = 0; i < 150; i++) { - if ((_vm->_game->_collisionAreas[i].id & 0xF000) == 0xE000) - _vm->_game->_collisionAreas[i].left = 0xFFFF; - } - } else - _vm->_game->freeCollision(0xE000 + id); + if (id == -2) + _vm->_game->_hotspots->removeState(0xD000); + else if (id == -1) + _vm->_game->_hotspots->removeState(0xE000); + else + _vm->_game->_hotspots->remove(0xE000 + id); return false; } diff --git a/engines/gob/inter_v6.cpp b/engines/gob/inter_v6.cpp index 14bfa1e840..b366d39d0d 100644 --- a/engines/gob/inter_v6.cpp +++ b/engines/gob/inter_v6.cpp @@ -36,6 +36,7 @@ #include "gob/expression.h" #include "gob/script.h" #include "gob/resources.h" +#include "gob/hotspots.h" #include "gob/draw.h" #include "gob/sound/sound.h" #include "gob/videoplayer.h" @@ -359,29 +360,23 @@ bool Inter_v6::o6_freeCollision(OpFuncParams ¶ms) { switch (id + 5) { case 0: - _vm->_game->pushCollisions(1); + _vm->_game->_hotspots->push(1); break; case 1: - _vm->_game->popCollisions(); + _vm->_game->_hotspots->pop(); break; case 2: - _vm->_game->pushCollisions(2); + _vm->_game->_hotspots->push(2); break; case 3: - for (int i = 0; i < 150; i++) { - if (((_vm->_game->_collisionAreas[i].id & 0xF000) == 0xD000) || - ((_vm->_game->_collisionAreas[i].id & 0xF000) == 0x4000)) - _vm->_game->_collisionAreas[i].left = 0xFFFF; - } + _vm->_game->_hotspots->removeState(0xD000); + _vm->_game->_hotspots->removeState(0x4000); break; case 4: - for (int i = 0; i < 150; i++) { - if ((_vm->_game->_collisionAreas[i].id & 0xF000) == 0xE000) - _vm->_game->_collisionAreas[i].left = 0xFFFF; - } + _vm->_game->_hotspots->removeState(0xE000); break; default: - _vm->_game->freeCollision(0xE000 + id); + _vm->_game->_hotspots->remove(0xE000 + id); break; } diff --git a/engines/gob/module.mk b/engines/gob/module.mk index 695976da61..6c8b735019 100644 --- a/engines/gob/module.mk +++ b/engines/gob/module.mk @@ -22,7 +22,7 @@ MODULE_OBJS := \ goblin_v2.o \ goblin_v3.o \ goblin_v4.o \ - videoplayer.o \ + hotspots.o \ init.o \ init_v1.o \ init_v2.o \ @@ -56,6 +56,7 @@ MODULE_OBJS := \ video_v1.o \ video_v2.o \ video_v6.o \ + videoplayer.o \ demos/demoplayer.o \ demos/scnplayer.o \ demos/batplayer.o \ |