aboutsummaryrefslogtreecommitdiff
path: root/engines/tucker/tucker.cpp
diff options
context:
space:
mode:
authorGregory Montoir2008-11-10 20:38:54 +0000
committerGregory Montoir2008-11-10 20:38:54 +0000
commit4a5d4ba94dd6320e137cde6ba27744613d2a1099 (patch)
tree9fe86b10f376fec7a60a224680537f85f0892399 /engines/tucker/tucker.cpp
parent2b59700d2a311c0486912435624bac78fe1f9dbb (diff)
downloadscummvm-rg350-4a5d4ba94dd6320e137cde6ba27744613d2a1099.tar.gz
scummvm-rg350-4a5d4ba94dd6320e137cde6ba27744613d2a1099.tar.bz2
scummvm-rg350-4a5d4ba94dd6320e137cde6ba27744613d2a1099.zip
add initial support for 'Bud Tucker in Double Trouble'
svn-id: r34990
Diffstat (limited to 'engines/tucker/tucker.cpp')
-rw-r--r--engines/tucker/tucker.cpp3778
1 files changed, 3778 insertions, 0 deletions
diff --git a/engines/tucker/tucker.cpp b/engines/tucker/tucker.cpp
new file mode 100644
index 0000000000..11b40eaf00
--- /dev/null
+++ b/engines/tucker/tucker.cpp
@@ -0,0 +1,3778 @@
+/* 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 "common/config-manager.h"
+#include "common/events.h"
+#include "common/system.h"
+
+#include "graphics/cursorman.h"
+
+#include "tucker/tucker.h"
+#include "tucker/graphics.h"
+
+namespace Tucker {
+
+TuckerEngine::TuckerEngine(OSystem *system, Common::Language language)
+ : Engine(system) {
+}
+
+TuckerEngine::~TuckerEngine() {
+}
+
+Common::Error TuckerEngine::init() {
+ _system->beginGFXTransaction();
+ initCommonGFX(false);
+ _system->initSize(320, 200);
+ _system->endGFXTransaction();
+
+ _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
+ _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume"));
+ _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
+ return Common::kNoError;
+}
+
+Common::Error TuckerEngine::go() {
+ mainLoop();
+ return Common::kNoError;
+}
+
+void TuckerEngine::syncSoundSettings() {
+ // TODO
+}
+
+int TuckerEngine::getRandomNumber() {
+ return _rnd.getRandomNumber(0x7FFF);
+}
+
+void TuckerEngine::allocateBuffers() {
+ _locationBackgroundGfxBuf = (uint8 *)calloc(1, 640 * 200);
+ _loadTempBuf = (uint8 *)calloc(1, 64010);
+ _panelGfxBuf = (uint8 *)calloc(1, 64010);
+ _itemsGfxBuf = (uint8 *)calloc(1, 19200);
+ _charsetGfxBuf = (uint8 *)calloc(1, 22400);
+ _cursorGfxBuf = (uint8 *)calloc(1, 256 * 7);
+ _infoBarBuf = (uint8 *)calloc(1, 1000);
+ _charNameBuf = 0;
+ _bgTextBuf = 0;
+ _objTxtBuf = 0;
+ _panelObjectsGfxBuf = (uint8 *)calloc(1, 20000);
+ _data5Buf = 0;
+ _data3GfxBuf = (uint8 *)calloc(1, 250000);
+ _quadBackgroundGfxBuf = (uint8 *)calloc(1, 320 * 140 * 4);
+ _locationBackgroundMaskBuf = (uint8 *)calloc(1, 640 * 140);
+ _csDataBuf = 0;
+ _spritesGfxBuf = (uint8 *)calloc(1, 160000);
+ _ptTextBuf = 0;
+ memset(_charWidthTable, 0, sizeof(_charWidthTable));
+}
+
+void TuckerEngine::freeBuffers() {
+ free(_locationBackgroundGfxBuf);
+ free(_loadTempBuf);
+ free(_panelGfxBuf);
+ free(_itemsGfxBuf);
+ free(_charsetGfxBuf);
+ free(_cursorGfxBuf);
+ free(_infoBarBuf);
+ free(_charNameBuf);
+ free(_bgTextBuf);
+ free(_objTxtBuf);
+ free(_panelObjectsGfxBuf);
+ free(_data5Buf);
+ free(_data3GfxBuf);
+ free(_quadBackgroundGfxBuf);
+ free(_locationBackgroundMaskBuf);
+ free(_csDataBuf);
+ free(_spritesGfxBuf);
+ free(_ptTextBuf);
+}
+
+void TuckerEngine::restart() {
+ _quitGame = 0;
+ _fastMode = false;
+ _syncCounter = 0;
+ _lastFrameTime = _system->getMillis();
+ _mainLoopCounter1 = _mainLoopCounter2 = 0;
+ _timerCounter1 = _timerCounter2 = 0;
+ _partNum = _currentPartNum = 0;
+ _locationNum = 0;
+ _nextLocationNum = ConfMan.getInt("boot_param");
+ if (_nextLocationNum == 0) {
+ _nextLocationNum = kStartupLocation;
+ }
+ _gamePaused = _gamePaused2 = 0;
+ memset(_flagsTable, 0, sizeof(_flagsTable));
+
+ _gameHintsIndex = 0;
+ _gameHintsCounter = 0;
+ _gameHintsDisplayText = 0;
+
+ memset(_sprA02Table, 0, sizeof(_sprA02Table));
+ memset(_sprC02Table, 0, sizeof(_sprC02Table));
+ memset(_actionsTable, 0, sizeof(_actionsTable));
+ _actionsCount = 0;
+ memset(_locationObjectsTable, 0, sizeof(_locationObjectsTable));
+ _locationObjectsCount = 0;
+ memset(_spritesTable, 0, sizeof(_spritesTable));
+ _spritesCount = 0;
+ memset(_locationAnimationsTable, 0, sizeof(_locationAnimationsTable));
+ _locationAnimationsCount = 0;
+ memset(_dataTable, 0, sizeof(_dataTable));
+ _dataCount = 0;
+ memset(_charPosTable, 0, sizeof(_charPosTable));
+ _charPosCount = 0;
+ memset(_locationSoundsTable, 0, sizeof(_locationSoundsTable));
+ _locationSoundsCount = 0;
+ memset(_locationMusicsTable, 0, sizeof(_locationMusicsTable));
+ _locationMusicsCount = 0;
+
+ _mousePosX = _mousePosY = 0;
+ _prevMousePosX = _prevMousePosY = 0;
+ _mouseButtonsMask = 0;
+ _mouseButton2 = 0;
+ _mouseClick = 0;
+ _mouseClickOnPanelSliders = 0;
+ _mouseIdleCounter = 0;
+ _leftMouseButtonPressed = _rightMouseButtonPressed = false;
+ _keyLastKeyCodePressed = _lastKeyPressed = 0;
+ _cursorNum = 0;
+ _cursorType = 0;
+ _updateCursorFlag = 0;
+
+ _panelNum = 1;
+ _panelState = 0;
+ _forceRedrawPanelItems = 1;
+ _redrawPanelItemsCounter = 0;
+ _switchPanelFlag = 0;
+ memset(_panelObjectsOffsetTable, 0, sizeof(_panelObjectsOffsetTable));
+ _switchPanelCounter = 0;
+ _conversationOptionsCount = 0;
+ _fadedPanel = false;
+ _panelLockedFlag = 0;
+ _panelItemWidth = 0;
+ memset(_inventoryItemsState, 0, sizeof(_inventoryItemsState));
+ memset(_inventoryObjectsList, 0, sizeof(_inventoryObjectsList));
+ _inventoryObjectsOffset = 0;
+ _inventoryObjectsCount = 0;
+ _lastInventoryObjectIndex = 0;
+
+ _currentFxSet = 0;
+ _currentFxDist = 0;
+ _currentFxScale = 0;
+ _currentFxVolume = 0;
+ _currentFxIndex = 0;
+ _speechSoundNum = 0;
+ _speechVolume = kMaxSoundVolume;
+ memset(_soundsMapTable, 0, sizeof(_soundsMapTable));
+ memset(_speechHistoryTable, 0, sizeof(_speechHistoryTable));
+ for (int i = 0; i < kMaxCharacters; ++i) {
+ _charSpeechSoundVolumeTable[i] = kMaxSoundVolume;
+ }
+ _charSpeechSoundCounter = 0;
+ memset(_miscSoundFxDelayCounter, 0, sizeof(_miscSoundFxDelayCounter));
+ _characterSoundFxDelayCounter = 0;
+ _characterSoundFxNum = 0;
+ _speechSoundBaseNum = 0;
+
+ _pendingActionIndex = 0;
+ _pendingActionDelay = 0;
+ _charPositionFlagNum = 0;
+ _charPositionFlagValue = 0;
+ _actionVerb = kVerbWalk;
+ _nextAction = 0;
+ _selectedObjectNum = 0;
+ _selectedObjectType = 0;
+ _selectedCharacterNum = 0;
+ _actionObj1Type = _actionObj2Type = 0;
+ _actionObj1Num = _actionObj2Num = 0;
+ _actionRequiresTwoObjects = 0;
+ _skipPanelObjectUnderCursor = 0;
+ _actionPosX = 0;
+ _actionPosY = 0;
+ _selectedObjectLocationMask = 0;
+ memset(&_selectedObject, 0, sizeof(_selectedObject));
+ _selectedCharacterDirection = 0;
+ _selectedCharacter2Num = 0;
+ _currentActionObj1Num = _currentActionObj2Num = 0;
+ _currentInfoString1SourceType = _currentInfoString2SourceType = 0;
+ memset(_speechActionCounterTable, 0, sizeof(_speechActionCounterTable));
+ _actionCharacterNum = 0;
+
+ _csDataLoaded = false;
+ _csDataHandled = 0;
+ _stopActionOnSoundFlag = 0;
+ _csDataTableFlag2 = 0;
+ _stopActionOnPanelLock = 0;
+ _csDataTableCount = 0;
+ _stopActionCounter = 0;
+ _actionTextColor = 0;
+ _nextTableToLoadIndex = 0;
+ memset(_nextTableToLoadTable, 0, sizeof(_nextTableToLoadTable));
+ _soundInstructionIndex = 0;
+ _tableInstructionsPtr = 0;
+ memset(_tableInstructionObj1Table, 0, sizeof(_tableInstructionObj1Table));
+ memset(_tableInstructionObj2Table, 0, sizeof(_tableInstructionObj2Table));
+ _tableInstructionFlag = 0;
+ _tableInstructionItemNum1 = _tableInstructionItemNum2 = 0;
+ memset(_instructionsActionsTable, 0, sizeof(_instructionsActionsTable));
+ _validInstructionId = 0;
+
+ memset(_spriteFramesTable, 0, sizeof(_spriteFramesTable));
+ memset(_spriteAnimationsTable, 0, sizeof(_spriteAnimationsTable));
+ memset(_spriteAnimationFramesTable, 0, sizeof(_spriteAnimationFramesTable));
+ _spriteAnimationFrameIndex = 0;
+ _backgroundSpriteCurrentFrame = 0;
+ _backgroundSpriteLastFrame = 0;
+ _backgroundSpriteCurrentAnimation = -1;
+ _disableCharactersPath = false;
+ _skipCurrentCharacterDraw = false;
+ _yPosCurrent = 131;
+ _xPosCurrent = 160;
+ _characterSpeechDataPtr = 0;
+ _ptTextOffset = 0;
+ memset(_ctable01Table_sprite, 0, sizeof(_ctable01Table_sprite));
+ memset(_characterAnimationsTable, 0, sizeof(_characterAnimationsTable));
+ memset(_characterStateTable, 0, sizeof(_characterStateTable));
+ _backgroundSprOffset = 0;
+ _updateCharPositionNewType = 0;
+ _updateCharPositionType = 0;
+ _mainSpritesBaseOffset = 0;
+ _currentSpriteAnimationLength = 0;
+ _currentSpriteAnimationFrame = 0;
+ _currentSpriteAnimationFrame2 = 0;
+ _characterAnimationIndex = -1;
+ _characterFacingDirection = _characterPrevFacingDirection = 0;
+ _characterBackFrontFacing = _characterPrevBackFrontFacing = 0;
+ _characterAnimationNum = 0;
+ _noCharacterAnimationChange = 0;
+ _changeBackgroundSprite = 0;
+ _characterSpriteAnimationFrameCounter = 0;
+ _locationMaskIgnore = 0;
+ _locationMaskType = 0;
+ _locationMaskCounter = 0;
+ _updateSpriteFlag1 = 0;
+ _updateSpriteFlag2 = 0;
+ _handleMapCounter = 0;
+ _noPositionChangeAfterMap = false;
+
+ _mirroredDrawing = 0;
+ _loadLocBufPtr = 0;
+ _backgroundSpriteDataPtr = 0;
+ _locationHeight = 0;
+ _scrollOffset = 0;
+ _currentGfxBackgroundCounter = 0;
+ _currentGfxBackground = 0;
+ _fadePaletteCounter = 0;
+ memset(&_currentPalette, 0, sizeof(_currentPalette));
+ memset(&_backupPalette, 0, sizeof(_backupPalette));
+
+ _updateLocationFadePaletteCounter = 0;
+ _updateLocationCounter = 10;
+ _updateLocationPos = 0;
+ for (int i = 0; i < 5; ++i) {
+ _updateLocationXPosTable[i] = 160;
+ _updateLocationYPosTable[i] = 131;
+ }
+ memset(_updateLocationFlagsTable, 0, sizeof(_updateLocationFlagsTable));
+ memset(_updateLocationXPosTable2, 0, sizeof(_updateLocationXPosTable2));
+ memset(_updateLocationYPosTable2, 0, sizeof(_updateLocationYPosTable2));
+ memset(_updateLocationYMaxTable, 0, sizeof(_updateLocationYMaxTable));
+ memset(_updateLocation14Step, 0, sizeof(_updateLocation14Step));
+ memset(_updateLocation14ObjNum, 0, sizeof(_updateLocation14ObjNum));
+ memset(_updateLocation14Delay, 0, sizeof(_updateLocation14Delay));
+ _updateLocationCounter2 = 0;
+ _updateLocationFlag = 0;
+ _updateLocation70StringLen = 0;
+ memset(_updateLocation70String, 0, sizeof(_updateLocation70String));
+}
+
+void TuckerEngine::mainLoop() {
+ allocateBuffers();
+ restart();
+
+ openCompressedSoundFile();
+ _useEnc = Common::File::exists("data5.enc");
+ loadCharSizeDta();
+ loadCharset();
+ loadPanel();
+ strcpy(_fileToLoad, "infobar.txt");
+ loadFile(_infoBarBuf);
+ strcpy(_fileToLoad, "data5.c");
+ _data5Buf = loadFile();
+ strcpy(_fileToLoad, "bgtext.c");
+ _bgTextBuf = loadFile();
+ strcpy(_fileToLoad, "charname.c");
+ _charNameBuf = loadFile();
+ strcpy(_fileToLoad, "csdata.c");
+ _csDataBuf = loadFile();
+ _csDataSize = _fileLoadSize;
+ strcpy(_fileToLoad, "nofiles.dta");
+ loadFile(_loadTempBuf);
+ if (_fileLoadSize > 1) {
+ _maxSaveGameSlot = _loadTempBuf[0];
+ _currentSaveGameSlot = _loadTempBuf[4];
+ }
+ loadBudSpr(0);
+ loadCursor();
+ setCursorNum(_cursorNum);
+ setCursorType(_cursorType);
+
+ _flagsTable[219] = 1;
+ _flagsTable[105] = 1;
+
+ _spriteAnimationFrameIndex = _spriteAnimationsTable[14].firstFrameIndex;
+
+ while (1) {
+ ++_syncCounter;
+ if (_flagsTable[137] != _flagsTable[138]) {
+ loadBudSpr(0);
+ _flagsTable[138] = _flagsTable[137];
+ }
+ if (_syncCounter >= 2) {
+ _syncCounter = 0;
+ waitForTimer(2);
+ }
+ updateMouseState();
+ if (_fadePaletteCounter < 16) {
+ if (_fadePaletteCounter > 1) {
+ fadeOutPalette();
+ }
+ ++_fadePaletteCounter;
+ }
+ if (_fadePaletteCounter > 19 && _fadePaletteCounter < 34) {
+ fadeInPalette();
+ ++_fadePaletteCounter;
+ }
+ if (_nextAction != 0) {
+ loadActionsTable();
+ }
+ if (_nextLocationNum > 0) {
+ setupNewLocation();
+ }
+ updateCharPosition();
+ if (_cursorType == 0) {
+ updateCursor();
+ } else if (_panelState == 2) {
+ handleMouseOnPanel();
+ }
+ if (_mainLoopCounter2 == 0) {
+ updateFlagsForCharPosition();
+ }
+ if (_syncCounter == 0 || !_disableCharactersPath) {
+ updateCharactersPath();
+ }
+ if (_mainLoopCounter2 == 0) {
+ updateCharacterAnimation();
+ if (_backgroundSpriteCurrentAnimation == -1) {
+ _flagsTable[207] = 0;
+ if (_flagsTable[220] > 0) {
+ _flagsTable[_flagsTable[220]] = _flagsTable[221];
+ _flagsTable[220] = 0;
+ }
+ if (_flagsTable[158] == 1) {
+ _flagsTable[158] = 0;
+ _skipCurrentCharacterDraw = 1;
+ }
+ _mainLoopCounter1 = 0;
+ }
+ }
+ if (_mainLoopCounter1 == 0) {
+ updateSprites();
+ updateData3();
+ updateSfxData3_1();
+ }
+ ++_mainLoopCounter2;
+ handleMap();
+ updateScreenScrolling();
+ if (_mainLoopCounter2 > 4) {
+ _mainLoopCounter2 = 0;
+ updateSfxData3_2();
+ }
+ ++_mainLoopCounter1;
+ if (_mainLoopCounter1 > 5) {
+ _mainLoopCounter1 = 0;
+ }
+ if (_locationHeight == 140) {
+ switchPanelType();
+ redrawPanelItems();
+ if (_displayGameHints != 0 && _gameHintsIndex < 6) {
+ updateGameHints();
+ }
+ if (_panelState == 0) {
+ if (_panelLockedFlag == 1 || _pendingActionDelay > 0) {
+ if (!_fadedPanel) {
+ updateItemsGfxColors(0x60, 0x80);
+ _fadedPanel = true;
+ }
+ } else {
+ _fadedPanel = false;
+ clearItemsGfx();
+ if (_gamePaused != 0) {
+ drawPausedInfoBar();
+ } else if (_gameHintsDisplayText == 1 && _mouseIdleCounter > 1000) {
+ drawGameHintString();
+ } else {
+ drawInfoString();
+ }
+ }
+ }
+ }
+ _mainSpritesBaseOffset = 0;
+ if (_locationWidthTable[_locationNum] > 3) {
+ ++_currentGfxBackgroundCounter;
+ if (_currentGfxBackgroundCounter > 39) {
+ _currentGfxBackgroundCounter = 0;
+ }
+ _currentGfxBackground = _quadBackgroundGfxBuf + (_currentGfxBackgroundCounter / 10) * 44800;
+ if (_fadePaletteCounter < 34 && _locationNum == 22) {
+ _spritesTable[0].gfxBackgroundOffset = (_currentGfxBackgroundCounter / 10) * 640;
+ _mainSpritesBaseOffset = _currentGfxBackgroundCounter / 10;
+ if (_locationNum == 22 && _currentGfxBackgroundCounter <= 29) {
+ _spritesTable[0].gfxBackgroundOffset = 640;
+ _mainSpritesBaseOffset = 1;
+ }
+ }
+ } else {
+ _currentGfxBackground = _quadBackgroundGfxBuf;
+ }
+ if (_syncCounter != 0) {
+ continue;
+ }
+ Graphics::copyTo640(_locationBackgroundGfxBuf + _scrollOffset, _currentGfxBackground + _scrollOffset, 320 - _scrollOffset, 320, _locationHeight);
+ Graphics::copyTo640(_locationBackgroundGfxBuf + 320, _currentGfxBackground + 44800, _scrollOffset, 320, _locationHeight);
+ drawData3();
+ execData3PreUpdate();
+ for (int i = 0; i < _spritesCount; ++i) {
+ if (_spritesTable[i].disabled == 0) {
+ drawSprite(i);
+ }
+ }
+ if (_skipCurrentCharacterDraw != 1) {
+ if (_backgroundSpriteCurrentAnimation > -1 && _backgroundSpriteCurrentFrame > 0) {
+ drawBackgroundSprites(0);
+ } else {
+ int offset;
+ SpriteFrame *chr = &_spriteFramesTable[_currentSpriteAnimationFrame];
+ if (_mirroredDrawing == 0) {
+ offset = (_yPosCurrent + _mainSpritesBaseOffset - 54 + chr->yOffset) * 640 + _xPosCurrent;
+ offset += chr->xOffset - 14;
+ } else {
+ offset = (_yPosCurrent + _mainSpritesBaseOffset - 54 + chr->yOffset) * 640 + _xPosCurrent;
+ offset -= chr->xSize + chr->xOffset - 14;
+ }
+ Graphics::decodeRLE_248(_locationBackgroundGfxBuf + offset, _spritesGfxBuf + chr->sourceOffset, chr->xSize, chr->ySize,
+ chr->yOffset, _locationHeightTable[_locationNum], _mirroredDrawing != 0);
+ if (_currentSpriteAnimationLength > 1) {
+ SpriteFrame *chr2 = &_spriteFramesTable[_currentSpriteAnimationFrame2];
+ if (_mirroredDrawing == 0) {
+ offset = (_yPosCurrent + _mainSpritesBaseOffset - 54 + chr2->yOffset) * 640 + _xPosCurrent;
+ offset += chr2->xOffset - 14;
+ } else {
+ offset = (_yPosCurrent + _mainSpritesBaseOffset - 54 + chr2->yOffset) * 640 + _xPosCurrent;
+ offset -= chr2->xSize + chr2->xOffset - 14;
+ }
+ Graphics::decodeRLE_248(_locationBackgroundGfxBuf + offset, _spritesGfxBuf + chr2->sourceOffset, chr2->xSize, chr2->ySize,
+ _spriteFramesTable[_currentSpriteAnimationFrame].yOffset, // _currentCharacter instead ?
+ _locationHeightTable[_locationNum], _mirroredDrawing != 0);
+ }
+ }
+ }
+ if (_locationHeight == 140) {
+ redrawPanelOverBackground();
+ }
+ if (_panelState == 3) {
+ saveOrLoad();
+ }
+ execData3PostUpdate();
+ if (_timerCounter2 > 45) {
+ _timerCounter2 = 0;
+ }
+ updateSoundsTypes3_4();
+ if (_currentFxSet != 0) {
+ setSoundVolumeDistance();
+ }
+ if (_data4FlagDebug != 0) {
+ drawStringInteger(_scrollOffset + _mousePosX, 0, 10, 3);
+ drawStringInteger(_scrollOffset + _mousePosY, 0, 20, 3);
+ drawStringInteger(_backgroundSpriteCurrentFrame, 0, 40, 3);
+ drawStringInteger(_backgroundSpriteCurrentAnimation, 0, 50, 3);
+ drawStringInteger(_mouseButton2, 0, 60, 3);
+ }
+ updateCharSpeechSound();
+ copyToVGA(_locationBackgroundGfxBuf + _scrollOffset);
+ startCharacterSounds();
+ for (int num = 0; num < 2; ++num) {
+ if (_miscSoundFxDelayCounter[num] > 0) {
+ --_miscSoundFxDelayCounter[num];
+ if (_miscSoundFxDelayCounter[num] == 0) {
+ const int index = _soundsMapTable[num];
+ startSound(_locationSoundsTable[index].offset, index, _locationSoundsTable[index].volume);
+ }
+ }
+ }
+ _lastKeyPressed = getLastKeyCode();
+ if (_gamePaused == 1 && _charSpeechSoundCounter == 0) {
+ stopSounds();
+ _gamePaused2 = 1;
+ while (1) {
+ if (_lastKeyPressed == Common::KEYCODE_p && _charSpeechSoundCounter <= 0) { // Paused
+ playSounds();
+ _gamePaused = _gamePaused2 = 0;
+ break;
+ }
+ _lastKeyPressed = getLastKeyCode();
+ if (_charSpeechSoundCounter == 0) {
+ if (_lastKeyPressed >= Common::KEYCODE_1 && _lastKeyPressed <= Common::KEYCODE_5) {
+ if (_speechHistoryTable[_lastKeyPressed - Common::KEYCODE_1] > 0) {
+ startSpeechSound(_speechHistoryTable[_lastKeyPressed - Common::KEYCODE_1], 100);
+ _charSpeechSoundCounter = kDefaultCharSpeechSoundCounter;
+ }
+ }
+ }
+ updateCharSpeechSound();
+ }
+ }
+ if (_lastKeyPressed == Common::KEYCODE_p && _locationNum == 70) {
+ _gamePaused = 1;
+ }
+ if (_lastKeyPressed == Common::KEYCODE_F3 && _displayGameHints != 0 && _gameHintsDisplayText == 1) {
+ _mouseButton2 = _gameHintsIndex + 1;
+ _mouseIdleCounter = 1100;
+ }
+ if (_lastKeyPressed == 1 && _data4FlagDebug != 0) {
+ _flagsTable[236] = 74;
+ }
+ if (_flagsTable[236] > 70) {
+ handleCreditsSequence();
+ _quitGame = 1;
+ }
+ if ((_lastKeyPressed == Common::KEYCODE_F4 && _data4FlagDebug != 0) || _quitGame == 1 || _flagsTable[100] != 0) {
+ break;
+ }
+ }
+ if (_flagsTable[100] != 1) {
+ handleCongratulationsSequence();
+ }
+ freeBuffers();
+}
+
+void TuckerEngine::updateTimer() {
+ ++_timerCounter1;
+ ++_timerCounter2;
+}
+
+void TuckerEngine::waitForTimer(int ticksCount) {
+ uint32 end = _lastFrameTime + ticksCount * 1000 / 46;
+ do {
+ updateTimer();
+ parseEvents();
+ _system->delayMillis(10);
+ _lastFrameTime = _system->getMillis();
+ } while (!_fastMode && _lastFrameTime < end);
+ _timerCounter1 = 0;
+}
+
+void TuckerEngine::parseEvents() {
+ Common::Event ev;
+ while (_eventMan->pollEvent(ev)) {
+ switch (ev.type) {
+ case Common::EVENT_KEYDOWN:
+ if (ev.kbd.flags == Common::KBD_CTRL) {
+ if (ev.kbd.keycode == Common::KEYCODE_f) {
+ _fastMode = !_fastMode;
+ }
+ }
+ _keyLastKeyCodePressed = ev.kbd.keycode;
+ break;
+ case Common::EVENT_MOUSEMOVE:
+ updateCursorPos(ev.mouse.x, ev.mouse.y);
+ break;
+ case Common::EVENT_LBUTTONDOWN:
+ updateCursorPos(ev.mouse.x, ev.mouse.y);
+ _mouseButtonsMask |= 1;
+ break;
+ case Common::EVENT_LBUTTONUP:
+ updateCursorPos(ev.mouse.x, ev.mouse.y);
+ break;
+ case Common::EVENT_RBUTTONDOWN:
+ updateCursorPos(ev.mouse.x, ev.mouse.y);
+ _mouseButtonsMask |= 2;
+ break;
+ case Common::EVENT_RBUTTONUP:
+ updateCursorPos(ev.mouse.x, ev.mouse.y);
+ break;
+ default:
+ break;
+ }
+ }
+ if (shouldQuit()) {
+ _flagsTable[100] = 1;
+ }
+}
+
+void TuckerEngine::updateCursorPos(int x, int y) {
+ _prevMousePosX = _mousePosX;
+ _prevMousePosY = _mousePosY;
+ _mousePosX = x;
+ _mousePosY = y;
+}
+
+void TuckerEngine::setCursorNum(int num) {
+ _cursorNum = num;
+ const int cursorW = 16;
+ const int cursorH = 16;
+ CursorMan.replaceCursor(_cursorGfxBuf + _cursorNum * 256, cursorW, cursorH, 1, 1, 0);
+}
+
+void TuckerEngine::setCursorType(int type) {
+ _cursorType = type;
+ CursorMan.showMouse(_cursorType < 2);
+}
+
+void TuckerEngine::setupNewLocation() {
+ _locationNum = _nextLocationNum;
+ loadObj();
+ _switchPanelFlag = 0;
+ _nextLocationNum = 0;
+ _fadePaletteCounter = 0;
+ _mainLoopCounter2 = 0;
+ _mainLoopCounter1 = 0;
+ _characterFacingDirection = 0;;
+ _skipPanelObjectUnderCursor = 0;
+ _locationMaskIgnore = 0;
+ _backgroundSprOffset = 0;
+ if (_backgroundSpriteCurrentAnimation > 0 && _backgroundSpriteCurrentFrame > 0) {
+ _backgroundSpriteCurrentAnimation = -1;
+ _backgroundSpriteCurrentFrame = 0;
+ }
+ if (_panelLockedFlag == 0 || (_backgroundSpriteCurrentAnimation > 0 && _locationNum != 25)) {
+ _locationMaskType = 0;
+ } else {
+ _locationMaskType = 3;
+ }
+ while (_spriteAnimationFramesTable[_spriteAnimationFrameIndex] != 999) {
+ ++_spriteAnimationFrameIndex;
+ }
+ _execData3Counter = 0;
+ stopSounds();
+ loadLoc();
+ loadData4();
+ loadData3();
+ loadActionFile();
+ loadCharPos();
+ loadSprA02_01();
+ loadSprC02_01();
+ loadFx();
+ playSounds();
+ if (_flagsTable[215] > 0) {
+ handleMeanwhileSequence();
+ _flagsTable[215] = 0;
+ }
+ if (_flagsTable[231] > 0) {
+ handleMeanwhileSequence();
+ _flagsTable[231] = 0;
+ }
+}
+
+void TuckerEngine::copyLocBitmap(int offset, int isMask) {
+ int type = (isMask == 0) ? 1 : 0;
+ if (offset > 0 && _locationNum == 16) {
+ type = 0;
+ }
+ if (isMask < 2) {
+ char strNum[3];
+ sprintf(strNum, "%02d", _locationNum);
+ const int digitOffset = (isMask == 0) ? 3 : 4;
+ memcpy(_fileToLoad + digitOffset, strNum, 2);
+ }
+ loadImage(_loadTempBuf, type);
+ uint8 *dst = (isMask == 1) ? _locationBackgroundMaskBuf : _locationBackgroundGfxBuf;
+ dst += offset;
+ const uint8 *src = _loadTempBuf;
+ for (int y = 0; y < _locationHeight; ++y) {
+ memcpy(dst, src, 320);
+ src += 320;
+ dst += 640;
+ }
+}
+
+void TuckerEngine::updateMouseState() {
+ if (_cursorType < 2) {
+ _leftMouseButtonPressed = (_mouseButtonsMask & 1) != 0;
+ if (_leftMouseButtonPressed) {
+ _mouseIdleCounter = 0;
+ _mouseButton2 = 0;
+ }
+ _rightMouseButtonPressed = (_mouseButtonsMask & 2) != 0;
+ _mouseButtonsMask = 0;
+ if (_prevMousePosX == _mousePosX && _prevMousePosY == _mousePosY) {
+ ++_mouseIdleCounter;
+ } else {
+ _mouseIdleCounter = 0;
+ _mouseButton2 = 0;
+ }
+ }
+ if (_mousePosX > 307) {
+ _mousePosX = 307;
+ }
+ if (_mousePosY > 195) {
+ _mousePosY = 195;
+ }
+ if (_cursorType == 1) {
+ if (_panelState == 1) {
+ setCursorNum(1);
+ }
+ if (_mousePosY < 140) {
+ _mousePosY = 140;
+ }
+ }
+}
+
+void TuckerEngine::updateCharPositionHelper() {
+ setCursorType(2);
+ _charSpeechSoundCounter = kDefaultCharSpeechSoundCounter;
+ _updateCharPositionNewType = 0;
+ startSpeechSound(_speechSoundNum, _speechVolume);
+ int pos = getPositionForLine(_speechSoundNum, _characterSpeechDataPtr);
+ _characterSpeechDataPtr += pos;
+ _speechSoundNum = 0;
+}
+
+void TuckerEngine::updateCharPosition() {
+ if (_updateCharPositionNewType == 0 || _locationMaskCounter == 0) {
+ return;
+ }
+ if (_updateCharPositionNewType == 1 && _locationNum != 18) {
+ int pos;
+ _actionPosX = _xPosCurrent;
+ _actionPosY = _yPosCurrent - 64;
+ _actionTextColor = 1;
+ _actionCharacterNum = 99;
+ switch (_currentInfoString1SourceType) {
+ case 0:
+ if (_currentActionObj1Num == 0) {
+ return;
+ }
+ if (_currentActionObj1Num == 259) {
+ handleSpecialObjectSelectionSequence();
+ _updateCharPositionNewType = 0;
+ return;
+ }
+ _speechSoundNum = _currentActionObj1Num;
+ _characterSpeechDataPtr = _ptTextBuf;
+ pos = getPositionForLine(_speechSoundNum + 1865, _characterSpeechDataPtr);
+ if (_characterSpeechDataPtr[pos] == '*') {
+ switch (_characterSpeechDataPtr[pos + 1]) {
+ case 'E':
+ ++_flagsTable[200];
+ if (_flagsTable[200] > 6) {
+ _flagsTable[200] = 1;
+ }
+ _speechSoundNum = 262 + _flagsTable[200];
+ break;
+ case 'M':
+ ++_flagsTable[200];
+ if (_flagsTable[200] > 10) {
+ _flagsTable[200] = 1;
+ }
+ _speechSoundNum = 268 + _flagsTable[200];
+ break;
+ case 'R':
+ ++_flagsTable[200];
+ if (_flagsTable[200] > 10) {
+ _flagsTable[200] = 1;
+ }
+ _speechSoundNum = 281 + _flagsTable[200];
+ break;
+ }
+ }
+ _speechSoundNum += 1865;
+ updateCharPositionHelper();
+ return;
+ case 1:
+ if (_locationAnimationsTable[_selectedCharacter2Num].getFlag == 1) {
+ _speechSoundNum = _speechSoundBaseNum + _locationAnimationsTable[_selectedCharacter2Num].inventoryNum;
+ _characterSpeechDataPtr = _ptTextBuf;
+ updateCharPositionHelper();
+ return;
+ } else if (_currentActionObj1Num == 91) {
+ handleSpecialObjectSelectionSequence();
+ _updateCharPositionNewType = 0;
+ return;
+ }
+ break;
+ case 2:
+ _characterSpeechDataPtr = _ptTextBuf;
+ _speechSoundNum = 2175 + _charPosTable[_selectedCharacterNum].description;
+ if (_charPosTable[_selectedCharacterNum].description != 0) {
+ updateCharPositionHelper();
+ return;
+ }
+ break;
+ }
+ }
+ int actionKey = _currentActionObj2Num * 1000000 + _currentInfoString2SourceType * 100000 + _updateCharPositionNewType * 10000 + _currentInfoString1SourceType * 1000 + _currentActionObj1Num;
+ int skip = 0;
+ int i;
+ for (i = 0; i < _actionsCount && skip == 0; ) {
+ if (_actionsTable[i].key == actionKey) {
+ skip = 1;
+ if (_actionsTable[i].testFlag1Num != 0) {
+ if (_actionsTable[i].testFlag1Num < 500) {
+ if (_flagsTable[_actionsTable[i].testFlag1Num] != _actionsTable[i].testFlag1Value) {
+ skip = 0;
+ }
+ } else if (_inventoryItemsState[_actionsTable[i].testFlag1Num - 500] != _actionsTable[i].testFlag1Value) {
+ skip = 0;
+ }
+ }
+ if (_actionsTable[i].testFlag2Num != 0) {
+ if (_actionsTable[i].testFlag2Num < 500) {
+ if (_flagsTable[_actionsTable[i].testFlag2Num] != _actionsTable[i].testFlag2Value) {
+ skip = 0;
+ }
+ } else if (_inventoryItemsState[_actionsTable[i].testFlag2Num - 500] != _actionsTable[i].testFlag2Value) {
+ skip = 0;
+ }
+ }
+ }
+ if (skip == 0) {
+ ++i;
+ }
+ }
+ if (skip == 0) {
+ playSpeechForAction(_updateCharPositionNewType);
+ _updateCharPositionNewType = 0;
+ return;
+ }
+ if (_actionsTable[i].speech != 6) {
+ if (_actionsTable[i].speech < 100) {
+ _spriteAnimationFrameIndex = _spriteAnimationsTable[_actionsTable[i].speech].firstFrameIndex;
+ _currentSpriteAnimationLength = _spriteAnimationsTable[_actionsTable[i].speech].numParts;
+ _mirroredDrawing = _actionsTable[i].flipX;
+ _characterFacingDirection = 5;
+ _mainLoopCounter2 = 0;
+ } else {
+ _backgroundSpriteCurrentAnimation = _actionsTable[i].speech - 100;
+ _backgroundSpriteCurrentFrame = 0;
+ _mirroredDrawing = 0;
+ }
+ }
+ _pendingActionDelay = _actionsTable[i].delay;
+ _charPositionFlagNum = _actionsTable[i].setFlagNum;
+ _charPositionFlagValue = _actionsTable[i].setFlagValue;
+ _pendingActionIndex = _actionsTable[i].index;
+ _characterSoundFxDelayCounter = _actionsTable[i].fxDelay;
+ _characterSoundFxNum = _actionsTable[i].fxNum;
+ _updateCharPositionType = _updateCharPositionNewType;
+ _updateCharPositionNewType = 0;
+}
+
+void TuckerEngine::updateFlagsForCharPosition() {
+ if (_pendingActionDelay != 0) {
+ --_pendingActionDelay;
+ if (_pendingActionDelay > 0) {
+ return;
+ }
+ if (_updateCharPositionType == 3 || _updateCharPositionType == 4 || _updateCharPositionType == 8 || _updateCharPositionType == 2) {
+ _flagsTable[_charPositionFlagNum] = _charPositionFlagValue;
+ } else if (_updateCharPositionType == 6 && _charPositionFlagValue == 1) {
+ addObjectToInventory(_charPositionFlagNum);
+ _forceRedrawPanelItems = 1;
+ }
+ if (_pendingActionIndex > 0) {
+ _nextAction = _pendingActionIndex;
+ }
+ }
+}
+
+void TuckerEngine::backupPalette() {
+ memcpy(_backupPalette, _currentPalette, 256 * 3);
+}
+
+void TuckerEngine::restorePalette() {
+ memcpy(_currentPalette, _backupPalette, 256 * 3);
+}
+
+void TuckerEngine::fadeOutPalette(int colorsCount) {
+ uint8 pal[256 * 4];
+ _system->grabPalette(pal, 0, colorsCount);
+ for (int color = 0; color < colorsCount; ++color) {
+ for (int i = 0; i < 3; ++i) {
+ const int c = int(pal[color * 4 + i]) + kFadePaletteStep * 4;
+ pal[color * 4 + i] = MIN<int>(c, _currentPalette[color * 3 + i]);
+ }
+ }
+ _system->setPalette(pal, 0, colorsCount);
+ _system->updateScreen();
+ _system->delayMillis(20);
+}
+
+void TuckerEngine::fadeInPalette(int colorsCount) {
+ uint8 pal[256 * 4];
+ _system->grabPalette(pal, 0, colorsCount);
+ for (int color = 0; color < colorsCount; ++color) {
+ for (int i = 0; i < 3; ++i) {
+ const int c = int(pal[color * 4 + i]) - kFadePaletteStep * 4;
+ pal[color * 4 + i] = MAX<int>(c, 0);
+ }
+ }
+ _system->setPalette(pal, 0, colorsCount);
+ _system->updateScreen();
+ _system->delayMillis(20);
+}
+
+void TuckerEngine::fadePaletteColor(int color, int step) {
+ uint8 rgb[4];
+ _system->grabPalette(rgb, color, 1);
+ for (int i = 0; i < 3; ++i) {
+ const int c = _currentPalette[color * 3 + i] + step * 4;
+ rgb[i] = MIN(c, 255);
+ }
+ _system->setPalette(rgb, color, 1);
+}
+
+void TuckerEngine::setBlackPalette() {
+ uint8 pal[256 * 4];
+ memset(pal, 0, sizeof(pal));
+ _system->setPalette(pal, 0, 256);
+}
+
+void TuckerEngine::setPaletteColor(int color, int r, int g, int b) {
+ uint8 rgb[4];
+ rgb[0] = r & 255;
+ rgb[1] = g & 255;
+ rgb[2] = b & 255;
+ rgb[3] = 255;
+ _system->setPalette(rgb, color, 1);
+}
+
+void TuckerEngine::updateCursor() {
+ setCursorNum(0);
+ if (_backgroundSpriteCurrentAnimation == -1 && _panelLockedFlag == 0 && _selectedObject.locationObject_locationNum > 0) {
+ _selectedObject.locationObject_locationNum = 0;
+ }
+ if (_locationMaskType > 0 || _selectedObject.locationObject_locationNum > 0 || _pendingActionDelay > 0) {
+ return;
+ }
+ if (_rightMouseButtonPressed) {
+ if (_updateCursorFlag == 0) {
+ ++_actionVerb;
+ if (_actionVerb > 8) {
+ _actionVerb = 0;
+ }
+ _updateCursorFlag = 1;
+ _skipPanelObjectUnderCursor = 1;
+ _actionRequiresTwoObjects = false;
+ }
+ } else {
+ _updateCursorFlag = 0;
+ }
+ if (_skipPanelObjectUnderCursor == 0) {
+ setActionVerbUnderCursor();
+ if (_actionVerb == 0 && _locationNum == 63) {
+ _actionVerb = 8;
+ }
+ }
+ _selectedObjectNum = 0;
+ _selectedObjectType = 0;
+ int num = setCharacterUnderCursor();
+ if (_selectedObjectType == 0) {
+ num = setLocationAnimationUnderCursor();
+ }
+ if (_selectedObjectType > 0) {
+ _selectedObjectNum = num;
+ } else {
+ num = getObjectUnderCursor();
+ if (num > -1) {
+ _selectedObjectNum = _locationObjectsTable[num].textNum;
+ }
+ }
+ handleMouseClickOnInventoryObject();
+ if (_actionVerb == 2 && _selectedObjectType != 2) {
+ _selectedObjectNum = 0;
+ _selectedObjectType = 0;
+ } else if (_actionVerb == 5 && _selectedObjectType != 3 && !_actionRequiresTwoObjects) {
+ _selectedObjectNum = 0;
+ _selectedObjectType = 0;
+ }
+ if (_skipPanelObjectUnderCursor == 0 && _selectedObjectType == 2 && _selectedObjectNum != 21) {
+ _actionVerb = 2;
+ }
+ if (!_actionRequiresTwoObjects) {
+ _actionObj1Num = _selectedObjectNum;
+ _actionObj1Type = _selectedObjectType;
+ _actionObj2Num = 0;
+ _actionObj2Type = 0;
+ } else if (_actionObj1Num == _selectedObjectNum && _actionObj1Type == _selectedObjectType) {
+ _selectedObjectNum = 0;
+ _selectedObjectType = 0;
+ _actionObj2Num = 0;
+ _actionObj2Type = 0;
+ } else {
+ _actionObj2Num = _selectedObjectNum;
+ _actionObj2Type = _selectedObjectType;
+ }
+ if (!_leftMouseButtonPressed) {
+ _mouseClick = 0;
+ }
+ if (_leftMouseButtonPressed && _mouseClick == 0) {
+ _fadedPanel = 0;
+ _mouseClick = 1;
+ clearItemsGfx();
+ drawInfoString();
+ if (_mousePosY >= 150 && _mousePosX < 212) {
+ if (_mousePosX < 200) {
+ setActionVerbUnderCursor();
+ _skipPanelObjectUnderCursor = 1;
+ _actionRequiresTwoObjects = false;
+ } else if (_mousePosY < 175) {
+ moveDownInventoryObjects();
+ } else {
+ moveUpInventoryObjects();
+ }
+ } else {
+ if (_selectedObjectType == 3) {
+ setActionForInventoryObject();
+ } else if (_actionVerb != 0) {
+ _skipPanelObjectUnderCursor = 0;
+ setActionState();
+ } else if (_actionObj1Num == 261 || (_actionObj1Num == 205 && _flagsTable[143] == 0)) {
+ _skipPanelObjectUnderCursor = 0;
+ setActionState();
+ } else {
+ _skipPanelObjectUnderCursor = 0;
+ _actionRequiresTwoObjects = false;
+ _updateCharPositionNewType = 0;
+ setSelectedObjectKey();
+ }
+ }
+ }
+}
+
+int TuckerEngine::getLastKeyCode() {
+ int keyCode = _keyLastKeyCodePressed;
+ _keyLastKeyCodePressed = 0;
+ return keyCode;
+}
+
+void TuckerEngine::stopSounds() {
+ for (int i = 0; i < _locationSoundsCount; ++i) {
+ stopSound(i);
+ }
+ for (int i = 0; i < _locationMusicsCount; ++i) {
+ stopMusic(i);
+ }
+}
+
+void TuckerEngine::playSounds() {
+ for (int i = 0; i < 29; ++i) {
+ if (i < _locationSoundsCount) {
+ if (_locationSoundsTable[i].type == 1 || _locationSoundsTable[i].type == 2 || _locationSoundsTable[i].type == 5 ||
+ (_locationSoundsTable[i].type == 7 && _flagsTable[_locationSoundsTable[i].flagNum] == _locationSoundsTable[i].flagValueStartFx)) {
+ startSound(_locationSoundsTable[i].offset, i, _locationSoundsTable[i].volume);
+ }
+ }
+ if (i < _locationMusicsCount) {
+ if (_locationMusicsTable[i].flag > 0) {
+ startMusic(_locationMusicsTable[i].offset, i, _locationMusicsTable[i].volume);
+ }
+ }
+ }
+}
+
+void TuckerEngine::updateCharactersPath() {
+ int i = 0;
+ int flag = 0;
+ if (_panelLockedFlag == 0) {
+ return;
+ }
+ if (_backgroundSpriteCurrentAnimation != -1 && _locationNum != 25) {
+ if (_xPosCurrent == _selectedObject.xPos && _yPosCurrent == _selectedObject.yPos) {
+ _locationMaskCounter = 1;
+ _panelLockedFlag = 0;
+ }
+ return;
+ }
+ int xPos = _xPosCurrent;
+ int yPos = _yPosCurrent;
+ if (_characterFacingDirection == 5) {
+ _characterPrevFacingDirection = 5;
+ }
+ if (_yPosCurrent > _selectedObject.yPos) {
+ if (testLocationMask(_xPosCurrent, _yPosCurrent - 1) == 1) {
+ --_yPosCurrent;
+ _characterFacingDirection = 4;
+ flag = 1;
+ } else {
+ ++i;
+ }
+ } else if (_yPosCurrent < _selectedObject.yPos) {
+ if (testLocationMask(_xPosCurrent, _yPosCurrent + 1) == 1) {
+ ++_yPosCurrent;
+ _characterFacingDirection = 2;
+ flag = 1;
+ } else {
+ ++i;
+ }
+ }
+ if (_xPosCurrent > _selectedObject.xPos) {
+ if (testLocationMask(_xPosCurrent - 1, _yPosCurrent) == 1) {
+ --_xPosCurrent;
+ _characterFacingDirection = 3;
+ _characterBackFrontFacing = 0;
+ flag = 1;
+ } else {
+ ++i;
+ }
+ } else if (_xPosCurrent < _selectedObject.xPos) {
+ if (testLocationMask(_xPosCurrent + 1, _yPosCurrent) == 1) {
+ ++_xPosCurrent;
+ _characterFacingDirection = 1;
+ _characterBackFrontFacing = 1;
+ flag = 1;
+ } else {
+ ++i;
+ }
+ }
+ if (flag == 0) {
+ if (_selectedObjectLocationMask == 1) {
+ _selectedObjectLocationMask = 0;
+ _selectedObject.xPos = _selectedObject.xDefaultPos;
+ _selectedObject.yPos = _selectedObject.yDefaultPos;
+ } else {
+ _panelLockedFlag = 0;
+ _characterFacingDirection = 0;
+ if (_xPosCurrent == _selectedObject.xPos && _yPosCurrent == _selectedObject.yPos) {
+ _locationMaskCounter = 1;
+ }
+ }
+ }
+ if (_locationNum == 25) {
+ if ((_backgroundSpriteCurrentAnimation == 3 || _characterBackFrontFacing != 0) && (_backgroundSpriteCurrentAnimation != 6 || _characterBackFrontFacing != 1)) {
+ _xPosCurrent = xPos;
+ _yPosCurrent = yPos;
+ return;
+ }
+ }
+ if (_xPosCurrent != _selectedObject.xPos || _yPosCurrent != _selectedObject.yPos) {
+ return;
+ }
+ if (_selectedObjectLocationMask != 0) {
+ return;
+ }
+ _locationMaskCounter = 1;
+ _panelLockedFlag = 0;
+ _locationMaskIgnore = 0;
+ if (_characterPrevFacingDirection <= 0 || _characterPrevFacingDirection >= 5) {
+ return;
+ }
+ if (_selectedObject.locationObject_locationNum == 0) {
+ _characterFacingDirection = 5;
+ while (_spriteAnimationFramesTable[_spriteAnimationFrameIndex] != 999) {
+ ++_spriteAnimationFrameIndex;
+ }
+ ++_spriteAnimationFrameIndex;
+ }
+}
+
+void TuckerEngine::setSoundVolumeDistance() {
+ int w = ABS(_xPosCurrent - _currentFxDist);
+ int d = w * _currentFxScale / 10;
+ int volume = (d > _currentFxVolume) ? 0 : _currentFxVolume - d;
+ setVolumeSound(_currentFxIndex, volume);
+}
+
+void TuckerEngine::updateData3DrawFlag() {
+ for (int i = 0; i < _locationAnimationsCount; ++i) {
+ if (_locationAnimationsTable[i].flagNum > 0 && _locationAnimationsTable[i].flagValue != _flagsTable[_locationAnimationsTable[i].flagNum]) {
+ _locationAnimationsTable[i].drawFlag = 0;
+ } else if (_locationAnimationsTable[i].getFlag == 0) {
+ _locationAnimationsTable[i].drawFlag = 1;
+ } else {
+ _locationAnimationsTable[i].drawFlag = (_inventoryItemsState[_locationAnimationsTable[i].inventoryNum] == 0) ? 1 : 0;
+ }
+ }
+}
+
+void TuckerEngine::updateData3() {
+ updateData3DrawFlag();
+ for (int i = 0; i < _locationAnimationsCount; ++i) {
+ if (_locationAnimationsTable[i].animLastCounter != 0 && _locationAnimationsTable[i].drawFlag != 0) {
+ if (_locationAnimationsTable[i].animLastCounter == _locationAnimationsTable[i].animCurrentCounter) {
+ _locationAnimationsTable[i].animCurrentCounter = _locationAnimationsTable[i].animInitCounter;
+ } else {
+ ++_locationAnimationsTable[i].animCurrentCounter;
+ }
+ const int index = _locationAnimationsTable[i].animCurrentCounter;
+ if (_staticData3Table[index] == 998) {
+ _flagsTable[_staticData3Table[index + 1]] = _staticData3Table[index + 2];
+ _locationAnimationsTable[i].animCurrentCounter = _locationAnimationsTable[i].animInitCounter;
+ _locationAnimationsTable[i].drawFlag = 0;
+ }
+ _locationAnimationsTable[i].graphicNum = _staticData3Table[_locationAnimationsTable[i].animCurrentCounter];
+ }
+ }
+ updateData3DrawFlag();
+}
+
+void TuckerEngine::updateSfxData3_1() {
+ for (int i = 0; i < _locationSoundsCount; ++i) {
+ if ((_locationSoundsTable[i].type == 6 || _locationSoundsTable[i].type == 7) && _locationSoundsTable[i].updateType == 1) {
+ for (int j = 0; j < _spritesCount; ++j) {
+ if (_spritesTable[j].animationFrame == _locationSoundsTable[i].startFxSpriteNum && _spritesTable[j].state == _locationSoundsTable[i].startFxSpriteState) {
+ if (_locationSoundsTable[i].type == 7) {
+ _flagsTable[_locationSoundsTable[i].flagNum] = _locationSoundsTable[i].flagValueStartFx;
+ }
+ startSound(_locationSoundsTable[i].offset, i, _locationSoundsTable[i].volume);
+ } else if (_locationSoundsTable[i].type == 7) {
+ if (_spritesTable[j].animationFrame == _locationSoundsTable[i].stopFxSpriteNum && _spritesTable[j].state == _locationSoundsTable[i].stopFxSpriteState) {
+ _flagsTable[_locationSoundsTable[i].flagNum] = _locationSoundsTable[i].flagValueStopFx;
+ stopSound(i);
+ }
+ }
+ }
+ }
+ }
+}
+
+void TuckerEngine::updateSfxData3_2() {
+ for (int i = 0; i < _locationSoundsCount; ++i) {
+ if ((_locationSoundsTable[i].type == 6 || _locationSoundsTable[i].type == 7) && _locationSoundsTable[i].updateType == 0) {
+ if (_locationSoundsTable[i].startFxSpriteNum == _backgroundSpriteCurrentFrame && _locationSoundsTable[i].startFxSpriteState == _backgroundSpriteCurrentAnimation) {
+ if (_locationSoundsTable[i].type == 7) {
+ _flagsTable[_locationSoundsTable[i].flagNum] = _locationSoundsTable[i].flagValueStartFx;
+ }
+ startSound(_locationSoundsTable[i].offset, i, _locationSoundsTable[i].volume);
+ } else if (_locationSoundsTable[i].type == 7) {
+ if (_locationSoundsTable[i].stopFxSpriteNum == _backgroundSpriteCurrentFrame && _locationSoundsTable[i].stopFxSpriteState == _backgroundSpriteCurrentAnimation) {
+ _flagsTable[_locationSoundsTable[i].flagNum] = _locationSoundsTable[i].flagValueStopFx;
+ stopSound(i);
+ }
+ }
+ }
+ }
+}
+
+void TuckerEngine::saveOrLoad() {
+ if (!_leftMouseButtonPressed) {
+ _mouseClick = 0;
+ }
+ if (_firstSaveGameSlot > 0) {
+ drawSpeechText(_scrollOffset + 120, 170, _infoBarBuf, _mouseClickOnPanelSliders + 19, 102);
+ int len = getStringWidth(_mouseClickOnPanelSliders + 19, _infoBarBuf);
+ drawStringInteger(_firstSaveGameSlot, len / 2 + 128, 160, 2);
+ } else {
+ drawSpeechText(_scrollOffset + 120, 170, _infoBarBuf, 21, 102);
+ }
+ if (_leftMouseButtonPressed && _mouseClick == 0) {
+ _mouseClick = 1;
+ if (_mousePosX > 228 && _mousePosX < 240 && _mousePosY > 154 & _mousePosY < 170) {
+ if (_firstSaveGameSlot < _lastSaveGameSlot) {
+ ++_firstSaveGameSlot;
+ _forceRedrawPanelItems = 1;
+ }
+ return;
+ }
+ if (_mousePosX > 228 && _mousePosX < 240 && _mousePosY > 170 && _mousePosY < 188) {
+ if (_firstSaveGameSlot > 1) {
+ --_firstSaveGameSlot;
+ _forceRedrawPanelItems = 1;
+ }
+ return;
+ }
+ if (_mousePosX > 244 && _mousePosX < 310 && _mousePosY > 170 && _mousePosY < 188) {
+ _forceRedrawPanelItems = 1;
+ _panelState = 2;
+ return;
+ }
+ if (_mousePosX > 260 && _mousePosX < 290 && _mousePosY > 152 && _mousePosY < 168) {
+ if (_mouseClickOnPanelSliders == 1) {
+ saveGame(_firstSaveGameSlot);
+ } else if (_firstSaveGameSlot > 0) {
+ loadGame(_firstSaveGameSlot);
+ }
+ _forceRedrawPanelItems = 1;
+ _panelState = 0;
+ setCursorType(0);
+ return;
+ }
+ }
+}
+
+void TuckerEngine::handleMouseOnPanel() {
+ if (!_leftMouseButtonPressed) {
+ _mouseClick = 0;
+ }
+ if (_leftMouseButtonPressed && _mouseClick == 0) {
+ _mouseClick = 1;
+ if (_mousePosY < 160 || _mousePosY > 176) {
+ return;
+ }
+ if (_mousePosX < 45 || _mousePosX > 275) {
+ return;
+ }
+ if (_mousePosX < 96) {
+ _mouseClickOnPanelSliders = 0;
+ _forceRedrawPanelItems = 1;
+ _panelState = 3;
+ _firstSaveGameSlot = _currentSaveGameSlot;
+ _lastSaveGameSlot = _maxSaveGameSlot;
+ } else if (_mousePosX < 158) {
+ _mouseClickOnPanelSliders = 1;
+ _forceRedrawPanelItems = 1;
+ _panelState = 3;
+ if (_maxSaveGameSlot < 99) {
+ _firstSaveGameSlot = _maxSaveGameSlot + 1;
+ _lastSaveGameSlot = _firstSaveGameSlot;
+ } else {
+ _lastSaveGameSlot = 99;
+ if (_currentSaveGameSlot < 99) {
+ _firstSaveGameSlot = _currentSaveGameSlot + 1;
+ } else {
+ _firstSaveGameSlot = 1;
+ }
+ }
+ } else if (_mousePosX < 218) {
+ _forceRedrawPanelItems = 1;
+ _panelState = 0;
+ setCursorType(0);
+ } else {
+ _quitGame = 1;
+ }
+ }
+}
+
+void TuckerEngine::switchPanelType() {
+ if (_panelState == 0 && _switchPanelFlag == 0 && _lastKeyPressed == Common::KEYCODE_F1) {
+ _switchPanelFlag = 1;
+ _switchPanelCounter = 1;
+ return;
+ }
+ if (_switchPanelFlag == 0) {
+ return;
+ }
+ if (_switchPanelFlag == 1) {
+ if (_switchPanelCounter == 25) {
+ if (_panelNum == 0) {
+ _panelNum = 1;
+ } else {
+ _panelNum = 0;
+ }
+ _switchPanelFlag = 2;
+ loadPanel();
+ _forceRedrawPanelItems = 1;
+ } else {
+ ++_switchPanelCounter;
+ }
+ } else {
+ --_switchPanelCounter;
+ if (_switchPanelCounter == 0) {
+ _switchPanelFlag = 0;
+ }
+ }
+}
+
+void TuckerEngine::redrawPanelOverBackground() {
+ const uint8 *src = _itemsGfxBuf;
+ uint8 *dst = _locationBackgroundGfxBuf + 89600 + _scrollOffset;
+ for (int y = 0; y < 10; ++y) {
+ memcpy(dst, src, 320);
+ src += 320;
+ dst += 640;
+ }
+ for (int y = 0; y < _switchPanelCounter; ++y) {
+ for (int x = 0; x < 320; ++x) {
+ dst[x] = 0;
+ }
+ dst += 640;
+ }
+ int y2 = 50 - _switchPanelCounter * 2;
+ for (int y = 0; y < y2; ++y) {
+ int i = y * 50 / y2;
+ memcpy(dst, src + i * 320, 320);
+ dst += 640;
+ }
+ for (int y = 0; y < _switchPanelCounter; ++y) {
+ for (int x = 0; x < 320; ++x) {
+ dst[x] = 0;
+ }
+ dst += 640;
+ }
+ if (_conversationOptionsCount > 0) {
+ drawConversationTexts();
+ }
+}
+
+void TuckerEngine::drawConversationTexts() {
+ int x = 0;
+ int y = 141;
+ int flag = 0;
+ for (int i = 0; i < _conversationOptionsCount; ++i) {
+ int color = 108;
+ if ((_mousePosY > y && _mousePosY < y + 11) || _nextTableToLoadIndex == i) {
+ color = 106;
+ }
+ drawSpeechText(x, y, _characterSpeechDataPtr, _instructionsActionsTable[i], color);
+ if (_mousePosY > y && _mousePosY < _panelItemWidth * 10 + y + 1) {
+ _nextTableToLoadIndex = i;
+ flag = 1;
+ }
+ y += _panelItemWidth * 10;
+ }
+ if (flag == 0) {
+ _nextTableToLoadIndex = -1;
+ }
+}
+
+void TuckerEngine::updateScreenScrolling() {
+ if (_locationWidthTable[_locationNum] != 2) {
+ _scrollOffset = 0;
+ } else if (_validInstructionId == 1) {
+ _scrollOffset = _xPosCurrent - 200;
+ } else if (_locationNum == 16 && _backgroundSpriteCurrentAnimation == 6 && _scrollOffset + 200 < _xPosCurrent) {
+ ++_scrollOffset;
+ if (_scrollOffset > 320) {
+ _scrollOffset = 320;
+ }
+ } else if (_scrollOffset + 120 > _xPosCurrent) {
+ _scrollOffset = _xPosCurrent - 120;
+ if (_scrollOffset < 0) {
+ _scrollOffset = 0;
+ }
+ } else if (_scrollOffset + 200 < _xPosCurrent) {
+ _scrollOffset = _xPosCurrent - 200;
+ if (_scrollOffset > 320) {
+ _scrollOffset = 320;
+ }
+ }
+}
+
+void TuckerEngine::updateGameHints() {
+ if (_gameHintsIndex == 0 && _flagsTable[3] > 0) {
+ _gameHintsIndex = 1;
+ _gameHintsCounter = 0;
+ _gameHintsDisplayText = 0;
+ } else if (_gameHintsIndex == 1 && _flagsTable[12] > 0) {
+ _gameHintsIndex = 2;
+ _gameHintsCounter = 0;
+ _gameHintsDisplayText = 0;
+ } else if (_gameHintsIndex == 2 && _flagsTable[20] > 0) {
+ _gameHintsIndex = 3;
+ _gameHintsCounter = 0;
+ _gameHintsDisplayText = 0;
+ } else if (_gameHintsIndex == 3 && _flagsTable[9] > 0) {
+ _gameHintsIndex = 4;
+ _gameHintsCounter = 0;
+ _gameHintsDisplayText = 0;
+ } else if (_gameHintsIndex == 4 && _flagsTable[23] > 0) {
+ _gameHintsIndex = 5;
+ _gameHintsCounter = 0;
+ _gameHintsDisplayText = 0;
+ } else if (_flagsTable[19] > 0) {
+ _gameHintsIndex = 6;
+ _gameHintsCounter = 0;
+ _gameHintsDisplayText = 0;
+ }
+ ++_gameHintsCounter;
+ if (_gameHintsCounter > 1500) {
+ _gameHintsDisplayText = 1;
+ }
+}
+
+void TuckerEngine::startCharacterSounds() {
+ if (_characterSoundFxDelayCounter != 0) {
+ --_characterSoundFxDelayCounter;
+ if (_characterSoundFxDelayCounter <= 0) {
+ startSound(_locationSoundsTable[_characterSoundFxNum].offset, _characterSoundFxNum, _locationSoundsTable[_characterSoundFxNum].volume);
+ }
+ }
+}
+
+void TuckerEngine::updateSoundsTypes3_4() {
+ if (isSoundPlaying(0)) {
+ return;
+ }
+ for (int i = 0; i < _locationSoundsCount; ++i) {
+ switch (_locationSoundsTable[i].type) {
+ case 3:
+ if (getRandomNumber() >= 32300) {
+ startSound(_locationSoundsTable[i].offset, 0, _locationSoundsTable[i].volume);
+ return;
+ }
+ break;
+ case 4:
+ if (getRandomNumber() >= 32763) {
+ startSound(_locationSoundsTable[i].offset, 0, _locationSoundsTable[i].volume);
+ return;
+ }
+ break;
+ }
+ }
+}
+
+void TuckerEngine::drawData3() {
+ for (int i = 0; i < _locationAnimationsCount; ++i) {
+ int num = _locationAnimationsTable[i].graphicNum;
+ const int offset = _dataTable[num].yDest * 640 + _dataTable[num].xDest;
+ if (_locationAnimationsTable[i].drawFlag != 0) {
+ Graphics::decodeRLE(_locationBackgroundGfxBuf + offset, _data3GfxBuf + _dataTable[num].sourceOffset, _dataTable[num].xSize, _dataTable[num].ySize);
+ }
+ }
+}
+
+void TuckerEngine::execData3PreUpdate() {
+ switch (_locationNum) {
+ case 1:
+ execData3PreUpdate_locationNum1();
+ break;
+ case 2:
+ execData3PreUpdate_locationNum2();
+ break;
+ case 3:
+ execData3PreUpdate_locationNum3();
+ break;
+ case 4:
+ execData3PreUpdate_locationNum4();
+ break;
+ case 6:
+ execData3PreUpdate_locationNum6();
+ break;
+ case 9:
+ execData3PreUpdate_locationNum9();
+ break;
+ case 10:
+ execData3PreUpdate_locationNum10();
+ break;
+ case 12:
+ execData3PreUpdate_locationNum12();
+ break;
+ case 13:
+ execData3PreUpdate_locationNum13();
+ break;
+ case 14:
+ if (_yPosCurrent > 126) {
+ execData3PreUpdate_locationNum14();
+ }
+ break;
+ case 15:
+ execData3PreUpdate_locationNum15();
+ break;
+ case 16:
+ execData3PreUpdate_locationNum16();
+ break;
+ case 19:
+ execData3PreUpdate_locationNum19();
+ break;
+ case 21:
+ execData3PreUpdate_locationNum21();
+ break;
+ case 22:
+ execData3PreUpdate_locationNum22();
+ break;
+ case 24:
+ execData3PreUpdate_locationNum24();
+ break;
+ case 25:
+ execData3PreUpdate_locationNum25();
+ break;
+ case 26:
+ execData3PreUpdate_locationNum26();
+ break;
+ case 27:
+ execData3PreUpdate_locationNum27();
+ break;
+ case 28:
+ execData3PreUpdate_locationNum28();
+ break;
+ case 29:
+ execData3PreUpdate_locationNum29();
+ break;
+ case 30:
+ execData3PreUpdate_locationNum30();
+ break;
+ case 31:
+ execData3PreUpdate_locationNum31();
+ break;
+ case 32:
+ execData3PreUpdate_locationNum32();
+ break;
+ case 33:
+ execData3PreUpdate_locationNum33();
+ break;
+ case 34:
+ execData3PreUpdate_locationNum34();
+ break;
+ case 35:
+ execData3PreUpdate_locationNum35();
+ break;
+ case 36:
+ execData3PreUpdate_locationNum36();
+ break;
+ case 38:
+ execData3PreUpdate_locationNum38();
+ break;
+ case 41:
+ execData3PreUpdate_locationNum41();
+ break;
+ case 42:
+ execData3PreUpdate_locationNum42();
+ break;
+ case 43:
+ execData3PreUpdate_locationNum43();
+ break;
+ case 44:
+ execData3PreUpdate_locationNum44();
+ break;
+ case 49:
+ execData3PreUpdate_locationNum49();
+ break;
+ case 52:
+ execData3PreUpdate_locationNum52();
+ break;
+ case 53:
+ execData3PreUpdate_locationNum53();
+ break;
+ case 57:
+ execData3PreUpdate_locationNum57();
+ break;
+ case 58:
+ execData3PreUpdate_locationNum58();
+ break;
+ case 61:
+ execData3PreUpdate_locationNum61();
+ break;
+ case 63:
+ execData3PreUpdate_locationNum63();
+ break;
+ case 64:
+ execData3PreUpdate_locationNum64();
+ break;
+ case 65:
+ execData3PreUpdate_locationNum65();
+ break;
+ case 66:
+ execData3PreUpdate_locationNum66();
+ break;
+ case 70:
+ execData3PreUpdate_locationNum70();
+ break;
+ }
+}
+
+void TuckerEngine::drawBackgroundSprites(int flipX) {
+ if (_backgroundSpriteDataPtr && _backgroundSpriteCurrentFrame != 0 && _backgroundSpriteCurrentFrame <= _backgroundSpriteLastFrame) {
+ int frameOffset = READ_LE_UINT24(_backgroundSpriteDataPtr + _backgroundSpriteCurrentFrame * 4);
+ int srcW = READ_LE_UINT16(_backgroundSpriteDataPtr + frameOffset);
+ int srcH = READ_LE_UINT16(_backgroundSpriteDataPtr + frameOffset + 2);
+ int srcX = READ_LE_UINT16(_backgroundSpriteDataPtr + frameOffset + 8);
+ int srcY = READ_LE_UINT16(_backgroundSpriteDataPtr + frameOffset + 10);
+ if (_locationNum == 22 && _backgroundSpriteCurrentAnimation > 1) {
+ srcY += _mainSpritesBaseOffset;
+ }
+ if (_locationNum == 29 && _backgroundSpriteCurrentAnimation == 3) {
+ srcX += 228;
+ } else if (_locationNum == 58 && _backgroundSpriteCurrentAnimation == 1) {
+ srcX += 100;
+ } else if (_xPosCurrent > 320 && _xPosCurrent < 640) {
+ srcX += 320;
+ }
+ int offset = _backgroundSprOffset + srcY * 640 + srcX;
+ Graphics::decodeRLE_248(_locationBackgroundGfxBuf + offset, _backgroundSpriteDataPtr + frameOffset + 12, srcW, srcH, 0, _locationHeightTable[_locationNum], flipX);
+ }
+}
+
+void TuckerEngine::setVolumeSound(int index, int volume) {
+ if (volume < 0) {
+ volume = 0;
+ }
+ _mixer->setChannelVolume(_sfxHandles[index], volume * Audio::Mixer::kMaxChannelVolume / kMaxSoundVolume);
+}
+
+void TuckerEngine::setVolumeMusic(int index, int volume) {
+ if (volume < 0) {
+ volume = 0;
+ }
+ _mixer->setChannelVolume(_musicHandles[index], volume * Audio::Mixer::kMaxChannelVolume / kMaxSoundVolume);
+}
+
+void TuckerEngine::startSound(int offset, int index, int volume) {
+ bool loop = (_locationSoundsTable[index].type == 2 || _locationSoundsTable[index].type == 5 || _locationSoundsTable[index].type == 7);
+ loadSound(Audio::Mixer::kSFXSoundType, _locationSoundsTable[index].num, volume, loop, &_sfxHandles[index]);
+}
+
+void TuckerEngine::stopSound(int index) {
+ _mixer->stopHandle(_sfxHandles[index]);
+}
+
+bool TuckerEngine::isSoundPlaying(int index) {
+ return _mixer->isSoundHandleActive(_sfxHandles[index]);
+}
+
+void TuckerEngine::startMusic(int offset, int index, int volume) {
+ bool loop = (_locationMusicsTable[index].flag == 2);
+ loadSound(Audio::Mixer::kMusicSoundType, _locationMusicsTable[index].num, volume, loop, &_musicHandles[index]);
+}
+
+void TuckerEngine::stopMusic(int index) {
+ _mixer->stopHandle(_musicHandles[index]);
+}
+
+void TuckerEngine::startSpeechSound(int num, int volume) {
+ loadSound(Audio::Mixer::kSpeechSoundType, num, volume, false, &_speechHandle);
+}
+
+bool TuckerEngine::isSpeechSoundPlaying() {
+ return _mixer->isSoundHandleActive(_speechHandle);
+}
+
+void TuckerEngine::redrawPanelItems() {
+ const uint8 *src;
+ uint8 *dst;
+ int sz;
+ if (_forceRedrawPanelItems != 0 || (_redrawPanelItemsCounter != 0 && _panelState == 0)) {
+ _forceRedrawPanelItems = 0;
+ if (_redrawPanelItemsCounter > 0) {
+ --_redrawPanelItemsCounter;
+ }
+ switch (_panelState) {
+ case 0:
+ src = _panelGfxBuf;
+ dst = _itemsGfxBuf + 3200;
+ sz = 16000;
+ break;
+ case 1:
+ src = _panelGfxBuf + 16320;
+ dst = _itemsGfxBuf;
+ sz = 19200;
+ break;
+ case 2:
+ src = _panelGfxBuf + 16320;
+ dst = _itemsGfxBuf;
+ sz = 19200;
+ memcpy(dst, src, sz);
+ src = _panelGfxBuf + 55040;
+ dst = _itemsGfxBuf + 6400;
+ sz = 5120;
+ break;
+ case 3:
+ src = _panelGfxBuf + 35200;
+ dst = _itemsGfxBuf;
+ sz = 19200;
+ break;
+ }
+ memcpy(dst, src, sz);
+ if (_panelState == 0) {
+ redrawPanelItemsHelper();
+ }
+ }
+}
+
+void TuckerEngine::redrawPanelItemsHelper() {
+ const int k = (_redrawPanelItemsCounter / 4) - ((_redrawPanelItemsCounter / 8) * 2);
+ for (int i = 0; i < 2; ++i) {
+ for (int j = 0; j < 3; ++j) {
+ if (i * 3 + j + _inventoryObjectsOffset >= _inventoryObjectsCount) {
+ continue;
+ }
+ if (i * 3 + j + _inventoryObjectsOffset == _lastInventoryObjectIndex && k != 0) {
+ continue;
+ }
+ const int obj = _inventoryObjectsList[i * 3 + j + _inventoryObjectsOffset];
+ const uint8 *src = _panelObjectsGfxBuf + _panelObjectsOffsetTable[obj];
+ uint8 *dst = _itemsGfxBuf + 3412 + i * 8320 + j * 34;
+ Graphics::decodeRLE_320(dst, src, 32, 24);
+ }
+ }
+}
+
+void TuckerEngine::drawSprite(int num) {
+ if (_spritesTable[num].animationFrame <= _spritesTable[num].firstFrame && _spritesTable[num].animationFrame > 0) {
+ if (_spritesTable[num].state != -1) {
+ const uint8 *p = _spritesTable[num].animationData;
+ if (!p) {
+ return;
+ }
+ int frameOffset = READ_LE_UINT24(p + _spritesTable[num].animationFrame * 4);
+ int srcW = READ_LE_UINT16(p + frameOffset);
+ int srcH = READ_LE_UINT16(p + frameOffset + 2);
+ int srcX = READ_LE_UINT16(p + frameOffset + 8);
+ int srcY = READ_LE_UINT16(p + frameOffset + 10);
+ int dstOffset = _spritesTable[num].gfxBackgroundOffset + srcX;
+ if (dstOffset < 600 && (_scrollOffset + 320 < dstOffset || _scrollOffset - srcW > dstOffset)) {
+ return;
+ }
+ _spritesTable[num].xSource = srcX;
+ _spritesTable[num].gfxBackgroundOffset += _spritesTable[num].backgroundOffset;
+ uint8 *dstPtr = _locationBackgroundGfxBuf + srcY * 640 + dstOffset;
+ const uint8 *srcPtr = p + frameOffset + 12;
+ if (_spritesTable[num].colorType == 0) {
+ Graphics::decodeRLE(dstPtr, srcPtr, srcW, srcH);
+ } else if (_spritesTable[num].colorType == 99) {
+ Graphics::decodeRLE_224(dstPtr, srcPtr, srcW, srcH);
+ } else {
+ Graphics::decodeRLE_248(dstPtr, srcPtr, srcW, srcH, 0, _spritesTable[num].yMaxBackground, _spritesTable[num].flipX != 0);
+ }
+ }
+ }
+}
+
+void TuckerEngine::clearItemsGfx() {
+ memset(_itemsGfxBuf, 0, 3200);
+}
+
+void TuckerEngine::drawPausedInfoBar() {
+ int len = getStringWidth(36, _infoBarBuf);
+ int x = 159 - len / 2;
+ drawString(_itemsGfxBuf + 326 + x, 36, _infoBarBuf);
+}
+
+const uint8 *TuckerEngine::getStringBuf(int type) const {
+ const uint8 *p = 0;
+ switch (type) {
+ case 0:
+ p = _data5Buf;
+ break;
+ case 1:
+ p = _bgTextBuf;
+ break;
+ case 2:
+ p = _charNameBuf;
+ break;
+ case 3:
+ p = _objTxtBuf;
+ break;
+ }
+ return p;
+}
+
+void TuckerEngine::drawInfoString() {
+ const uint8 *infoStrBuf = _infoBarBuf;
+ const uint8 *obj1StrBuf = getStringBuf(_actionObj1Type);
+ const uint8 *obj2StrBuf = 0;
+ int infoStringWidth = 0;
+ int object1NameWidth = 0;
+ int verbWidth = getStringWidth(_actionVerb + 1, infoStrBuf);
+ if (_actionObj1Num > 0 || _actionObj1Type > 0) {
+ object1NameWidth = getStringWidth(_actionObj1Num + 1, obj1StrBuf) + 4;
+ infoStringWidth = verbWidth + object1NameWidth;
+ } else {
+ infoStringWidth = verbWidth;
+ }
+ int verbPreposition = 0;
+ int verbPrepositionWidth = 0;
+ if (_actionRequiresTwoObjects) {
+ verbPreposition = (_actionVerb == 5) ? 12 : 11;
+ verbPrepositionWidth = getStringWidth(verbPreposition, infoStrBuf) + 4;
+ if ((_actionObj2Num > 0 || _actionObj2Type > 0) && verbPreposition > 0) {
+ infoStringWidth = 0;
+ verbWidth = 0;
+ object1NameWidth = 0;
+ }
+ infoStringWidth += verbPrepositionWidth;
+ obj2StrBuf = getStringBuf(_actionObj2Type);
+ if (_actionObj2Num > 0 && _actionObj2Type > 0) {
+ infoStringWidth += getStringWidth(_actionObj2Num + 1, obj2StrBuf);
+ }
+ }
+ const int xPos = 159 - infoStringWidth / 2;
+ if (verbPreposition == 0 || (_actionObj2Num == 0 && _actionObj2Type == 0)) {
+ drawString(_itemsGfxBuf + xPos, _actionVerb + 1, infoStrBuf);
+ if (_actionObj1Num != 0 || _actionObj1Type != 0) {
+ drawString(_itemsGfxBuf + 4 + xPos + verbWidth, _actionObj1Num + 1, obj1StrBuf);
+ }
+ }
+ if (verbPreposition > 0) {
+ drawString(_itemsGfxBuf + xPos + 4 + verbWidth + object1NameWidth, verbPreposition, infoStrBuf);
+ if (_actionObj2Num != 0 || _actionObj2Type != 0) {
+ drawString(_itemsGfxBuf + xPos + 4 + verbWidth + object1NameWidth + verbPrepositionWidth, _actionObj2Num + 1, obj2StrBuf);
+ }
+ }
+}
+
+void TuckerEngine::drawGameHintString() {
+ int len = getStringWidth(_mouseButton2 + 29, _infoBarBuf);
+ int x = 159 - len / 2;
+ drawString(_itemsGfxBuf + 326 + x, _mouseButton2 + 29, _infoBarBuf);
+}
+
+void TuckerEngine::updateCharacterAnimation() {
+ if (_characterAnimationIndex > -1) {
+ if (_backgroundSpriteCurrentFrame == 0) {
+ _backgroundSpriteCurrentAnimation = _characterAnimationsTable[_characterAnimationIndex];
+ ++_characterAnimationIndex;
+ _backgroundSpriteDataPtr = _sprA02Table[_backgroundSpriteCurrentAnimation];
+ _backgroundSpriteLastFrame = READ_LE_UINT16(_backgroundSpriteDataPtr);
+ _backgroundSpriteCurrentFrame = _characterAnimationsTable[_characterAnimationIndex];
+ ++_characterAnimationIndex;
+ } else if (_characterAnimationsTable[_characterAnimationIndex] == 99) {
+ _characterAnimationIndex = -1;
+ _backgroundSpriteCurrentAnimation = -1;
+ if (_nextAction == 0) {
+ setCursorType(0);
+ }
+ } else {
+ _backgroundSpriteCurrentFrame = _characterAnimationsTable[_characterAnimationIndex];
+ if (_noCharacterAnimationChange == 0) {
+ ++_characterAnimationIndex;
+ }
+ }
+ } else if (_backgroundSpriteCurrentAnimation > -1) {
+ while (_spriteAnimationFramesTable[_spriteAnimationFrameIndex] != 999) {
+ ++_spriteAnimationFrameIndex;
+ }
+ _characterFacingDirection = 0;
+ if (_changeBackgroundSprite == 1) {
+ if (_backgroundSpriteCurrentFrame == 0) {
+ _backgroundSpriteDataPtr = _sprA02Table[_backgroundSpriteCurrentAnimation];
+ _backgroundSpriteCurrentFrame = _backgroundSpriteLastFrame = READ_LE_UINT16(_backgroundSpriteDataPtr);
+ } else {
+ --_backgroundSpriteCurrentFrame;
+ if (_backgroundSpriteCurrentFrame > 1) {
+ _backgroundSpriteCurrentAnimation = -1;
+ _backgroundSpriteCurrentFrame = 0;
+ _changeBackgroundSprite = 0;
+ if (_nextAction == 0) {
+ setCursorType(0);
+ }
+ }
+ }
+ } else {
+ if (_backgroundSpriteCurrentFrame == 0) {
+ _backgroundSpriteCurrentFrame = 1;
+ assert(_backgroundSpriteCurrentAnimation >= 0 && _backgroundSpriteCurrentAnimation < kSprA02TableSize);
+ _backgroundSpriteDataPtr = _sprA02Table[_backgroundSpriteCurrentAnimation];
+ _backgroundSpriteLastFrame = READ_LE_UINT16(_backgroundSpriteDataPtr);
+ } else if (_locationNum == 25 && _panelLockedFlag != 1 && (_backgroundSpriteCurrentAnimation == 3 || _backgroundSpriteCurrentAnimation == 6)) {
+ _backgroundSpriteCurrentFrame = 0;
+ _backgroundSpriteCurrentAnimation = -1;
+ } else {
+ ++_backgroundSpriteCurrentFrame;
+ if (_backgroundSpriteCurrentFrame > _backgroundSpriteLastFrame) {
+ _backgroundSpriteCurrentAnimation = -1;
+ _backgroundSpriteCurrentFrame = 0;
+ if (_nextAction == 0 && _panelState == 0) {
+ setCursorType(0);
+ }
+ }
+ }
+ }
+ }
+ if (_locationNum == 24 && _flagsTable[103] == 0) {
+ if (_panelLockedFlag == 1) {
+ _panelLockedFlag = 0;
+ _selectedObject.locationObject_locationNum = 0;
+ if (_actionVerb != 2) {
+ _speechSoundNum = 2236;
+ startSpeechSound(_speechSoundNum, _speechVolume);
+ _characterSpeechDataPtr = _ptTextBuf + getPositionForLine(_speechSoundNum, _ptTextBuf);
+ _speechSoundNum = 0;
+ _actionPosX = _xPosCurrent;
+ _actionPosY = _yPosCurrent - 64;
+ _actionTextColor = 1;
+ _actionCharacterNum = 99;
+ setCursorType(2);
+ _charSpeechSoundCounter = kDefaultCharSpeechSoundCounter;
+
+ }
+ }
+ if (_charSpeechSoundCounter == 0 || _actionCharacterNum != 99) {
+ if (_backgroundSpriteCurrentAnimation == 5) {
+ _backgroundSpriteCurrentFrame = 0;
+ }
+ } else {
+ if (_backgroundSpriteCurrentAnimation != 5) {
+ _backgroundSpriteCurrentFrame = 0;
+ }
+ }
+ if (_backgroundSpriteCurrentFrame == 0) {
+ if (_charSpeechSoundCounter > 0 && _actionCharacterNum == 99) {
+ _backgroundSpriteCurrentAnimation = 5;
+ } else {
+ _backgroundSpriteCurrentAnimation = (getRandomNumber() < 33000) ? 2 : 3;
+ }
+ _backgroundSpriteCurrentFrame = 1;
+ _backgroundSpriteDataPtr = _sprA02Table[_backgroundSpriteCurrentAnimation];
+ _backgroundSpriteLastFrame = READ_LE_UINT16(_backgroundSpriteDataPtr);
+ }
+ } else if (_locationNum == 25) {
+ if (_backgroundSpriteCurrentFrame == 0) {
+ if (_characterBackFrontFacing == 0) {
+ if (_characterBackFrontFacing != _characterPrevBackFrontFacing) {
+ _backgroundSpriteCurrentAnimation = 10;
+ } else if (_panelLockedFlag == 1) {
+ _backgroundSpriteCurrentAnimation = 3;
+ } else if (_charSpeechSoundCounter > 0 && _actionCharacterNum == 99) {
+ _backgroundSpriteCurrentAnimation = 8;
+ } else {
+ _backgroundSpriteCurrentAnimation = (getRandomNumber() < 32000) ? 11 : 5;
+ }
+ } else {
+ if (_characterBackFrontFacing != _characterPrevBackFrontFacing) {
+ _backgroundSpriteCurrentAnimation = 2;
+ } else if (_panelLockedFlag == 1) {
+ _backgroundSpriteCurrentAnimation = 6;
+ } else if (_charSpeechSoundCounter > 0 && _actionCharacterNum == 99) {
+ _backgroundSpriteCurrentAnimation = 9;
+ } else {
+ _backgroundSpriteCurrentAnimation = (getRandomNumber() < 32000) ? 12 : 7;
+ }
+ }
+ _characterPrevBackFrontFacing = _characterBackFrontFacing;
+ _backgroundSpriteCurrentFrame = 1;
+ _backgroundSpriteDataPtr = _sprA02Table[_backgroundSpriteCurrentAnimation];
+ _backgroundSpriteLastFrame = READ_LE_UINT16(_backgroundSpriteDataPtr);
+ }
+ _backgroundSprOffset = _xPosCurrent - 160;
+ } else if (_locationNum == 63 && _backgroundSpriteCurrentFrame == 0) {
+ if (_charSpeechSoundCounter > 0 && _actionCharacterNum == 99) {
+ _backgroundSpriteCurrentAnimation = 1;
+ } else {
+ _backgroundSpriteCurrentAnimation = (getRandomNumber() < 32000) ? 3 : 2;
+ }
+ _backgroundSpriteCurrentFrame = 1;
+ _backgroundSpriteDataPtr = _sprA02Table[_backgroundSpriteCurrentAnimation];
+ _backgroundSpriteLastFrame = READ_LE_UINT16(_backgroundSpriteDataPtr);
+ }
+ int var8 = _spriteAnimationFramesTable[_spriteAnimationFrameIndex];
+ if (_panelLockedFlag == 0 && _characterFacingDirection < 5 && _selectedObject.locationObject_locationNum == 0) {
+ _characterFacingDirection = 0;
+ }
+ if (_charSpeechSoundCounter > 0 && _characterFacingDirection == 6 && _actionCharacterNum == 99) {
+ _characterFacingDirection = 6;
+ var8 = 999;
+ } else {
+ if (_characterFacingDirection == 6 && _charSpeechSoundCounter != 0 && _actionCharacterNum != 99) {
+ _characterFacingDirection = 0;
+ var8 = 999;
+ }
+ }
+ int num;
+ if (var8 == 999 || (_characterFacingDirection != _characterPrevFacingDirection && _characterFacingDirection < 5)) {
+ _mirroredDrawing = 0;
+ if (_characterFacingDirection == 6) {
+ if (_csDataHandled != 0) {
+ if (_selectedCharacterDirection == 1) {
+ num = 17;
+ } else if (_selectedCharacterDirection == 2) {
+ num = 16;
+ } else if (_selectedCharacterDirection == 4) {
+ num = 15;
+ } else {
+ num = 16;
+ _mirroredDrawing = 1;
+ }
+ } else {
+ num = 15;
+ }
+ }
+ if (_characterFacingDirection == 5) {
+ _characterFacingDirection = 0;
+ }
+ if (_characterFacingDirection == 0) {
+ if (_csDataHandled != 0) {
+ _mirroredDrawing = 0;
+ if (_selectedCharacterDirection == 1) {
+ num = 3;
+ } else if (_selectedCharacterDirection == 2) {
+ num = 1; // 2 ?
+ } else if (_selectedCharacterDirection == 3) {
+ num = 1;
+ _mirroredDrawing = 1;
+ } else {
+ num = 5;
+ }
+ } else if (getRandomNumber() < 2000) {
+ num = 13;
+ } else if (getRandomNumber() < 3000) {
+ num = 14;
+ if (_locationNum == 57) {
+ num = 18;
+ }
+ } else {
+ num = (getRandomNumber() < 20000) ? 18 : 6;
+ }
+ } else {
+ if (_characterFacingDirection == 1) {
+ num = 0;
+ } else if (_characterFacingDirection == 2) {
+ num = 4;
+ } else if (_characterFacingDirection == 3) {
+ num = 0;
+ _mirroredDrawing = 1;
+ } else if (_characterFacingDirection == 4) {
+ num = 2;
+ }
+ }
+ _currentSpriteAnimationLength = _spriteAnimationsTable[num].numParts;
+ _spriteAnimationFrameIndex = _spriteAnimationsTable[num].firstFrameIndex;
+ var8 = _spriteAnimationFramesTable[_spriteAnimationFrameIndex];
+ }
+ if (_characterAnimationNum > 0) {
+ num = _characterAnimationNum;
+ _currentSpriteAnimationLength = _spriteAnimationsTable[num].numParts;
+ _spriteAnimationFrameIndex = _spriteAnimationsTable[num].firstFrameIndex;
+ var8 = _spriteAnimationFramesTable[_spriteAnimationFrameIndex];
+ _characterAnimationNum = 0;
+ }
+ _currentSpriteAnimationFrame = var8;
+ ++_spriteAnimationFrameIndex;
+ if (_currentSpriteAnimationLength > 1) {
+ _currentSpriteAnimationFrame2 = _spriteAnimationFramesTable[_spriteAnimationFrameIndex];
+ ++_spriteAnimationFrameIndex;
+ if (_characterSpriteAnimationFrameCounter > 0) {
+ ++_characterSpriteAnimationFrameCounter;
+ if (_characterSpriteAnimationFrameCounter > 121) {
+ _characterSpriteAnimationFrameCounter = 0;
+ }
+ if (_selectedCharacterDirection == 1) {
+ _currentSpriteAnimationFrame = (_characterSpriteAnimationFrameCounter > 2 && _characterSpriteAnimationFrameCounter < 120) ? 122 : 121;
+ } else {
+ _currentSpriteAnimationFrame = (_characterSpriteAnimationFrameCounter > 2 && _characterSpriteAnimationFrameCounter < 120) ? 120 : 119;
+ }
+ }
+ }
+ _characterPrevFacingDirection = _characterFacingDirection;
+}
+
+void TuckerEngine::execData3PostUpdate() {
+ switch (_locationNum) {
+ case 1:
+ execData3PostUpdate_locationNum1();
+ break;
+ case 6:
+ if (_flagsTable[26] < 4) {
+ execData3PreUpdate_locationNum6Helper1();
+ }
+ break;
+ case 8:
+ execData3PostUpdate_locationNum8();
+ break;
+ case 9:
+ execData3PostUpdate_locationNum9();
+ break;
+ case 14:
+ if (_yPosCurrent < 127) {
+ execData3PreUpdate_locationNum14();
+ }
+ break;
+ case 21:
+ execData3PostUpdate_locationNum21();
+ break;
+ case 24:
+ execData3PostUpdate_locationNum24();
+ break;
+ case 27:
+ execData3PostUpdate_locationNum27();
+ break;
+ case 28:
+ execData3PostUpdate_locationNum28();
+ break;
+ case 32:
+ execData3PostUpdate_locationNum32();
+ break;
+ case 60:
+ execData3PostUpdate_locationNum60();
+ break;
+ case 66:
+ execData3PostUpdate_locationNum66();
+ break;
+ }
+}
+
+void TuckerEngine::addObjectToInventory(int num) {
+ _inventoryObjectsList[_inventoryObjectsCount] = num;
+ _lastInventoryObjectIndex = _inventoryObjectsCount;
+ _redrawPanelItemsCounter = 50;
+ ++_inventoryObjectsCount;
+ _inventoryItemsState[num] = 1;
+ if (_inventoryObjectsOffset + 5 < _lastInventoryObjectIndex) {
+ _inventoryObjectsOffset += 3;
+ }
+}
+
+void TuckerEngine::removeObjectFromInventory(int num) {
+ int i = 0;
+ while (_inventoryObjectsList[i] != num && i < _inventoryObjectsCount) {
+ ++i;
+ }
+ --_inventoryObjectsCount;
+ int j = i;
+ while (j < _inventoryObjectsCount) {
+ _inventoryObjectsList[j] = _inventoryObjectsList[j + 1];
+ ++j;
+ }
+ _inventoryItemsState[num] = 2;
+}
+
+void TuckerEngine::handleMap() {
+ if (_handleMapCounter > 0) {
+ ++_handleMapCounter;
+ if (_handleMapCounter > 19) {
+ _handleMapCounter = 0;
+ _locationMaskCounter = 1;
+ _panelLockedFlag = 0;
+ }
+ }
+ if (_panelLockedFlag == 0 && (_backgroundSpriteCurrentAnimation == -1 || _locationNum == 25) && _locationMaskType == 3) {
+ setCursorType(0);
+ if (_locationMaskCounter == 1) {
+ _characterFacingDirection = 0;
+ _locationMaskType = 0;
+ }
+ return;
+ }
+ if (_selectedObject.locationObject_locationNum != 0 && _locationMaskCounter != 0 && (_backgroundSpriteCurrentAnimation <= -1 || _locationNum == 25)) {
+ if (_locationNum == 25 || _backgroundSpriteCurrentAnimation != 4) {
+ if (_locationMaskType == 0) {
+ _locationMaskType = 1;
+ setCursorType(2);
+ if (_selectedObject.locationObject_toWalkX2 > 800) {
+ _backgroundSpriteCurrentAnimation = _selectedObject.locationObject_toWalkX2 - 900;
+ if (_selectedObject.locationObject_toWalkY2 > 499) {
+ _changeBackgroundSprite = 1;
+ _backgroundSprOffset = _selectedObject.locationObject_toWalkY2 - 500;
+ } else {
+ _backgroundSprOffset = _selectedObject.locationObject_toWalkY2;
+ _changeBackgroundSprite = 0;
+ }
+ _backgroundSpriteCurrentFrame = 0;
+ _mirroredDrawing = 0;
+ if (_locationNum == 25) {
+ _backgroundSpriteDataPtr = _sprA02Table[_backgroundSpriteCurrentAnimation];
+ _backgroundSpriteLastFrame = READ_LE_UINT16(_backgroundSpriteDataPtr);
+ _backgroundSpriteCurrentFrame = 1;
+ }
+ } else {
+ _locationMaskCounter = 0;
+ _selectedObject.xPos = _selectedObject.locationObject_toWalkX2;
+ _selectedObject.yPos = _selectedObject.locationObject_toWalkY2;
+ _handleMapCounter = 1;
+ _panelLockedFlag = 1;
+ }
+ return;
+ }
+ _locationMaskType = 2;
+ _panelState = 0;
+ setCursorType(0);
+ if (_selectedObject.locationObject_locationNum == 99) {
+ _noPositionChangeAfterMap = true;
+ handleMapSequence();
+ return;
+ }
+ for (int i = 0; i < 14; ++i) {
+ fadeInPalette();
+ copyToVGA(_locationBackgroundGfxBuf + _scrollOffset);
+ _fadePaletteCounter = 34;
+ }
+ _nextLocationNum = _selectedObject.locationObject_locationNum;
+ _xPosCurrent = _selectedObject.locationObject_toX;
+ _yPosCurrent = _selectedObject.locationObject_toY;
+ if (_selectedObject.locationObject_toX2 > 800) {
+ _backgroundSpriteCurrentAnimation = _selectedObject.locationObject_toX2 - 900;
+ if (_selectedObject.locationObject_toY2 > 499) {
+ _changeBackgroundSprite = 1;
+ _backgroundSprOffset = _selectedObject.locationObject_toY2 - 500;
+ } else {
+ _changeBackgroundSprite = 0;
+ _backgroundSprOffset = _selectedObject.locationObject_toY2;
+ }
+ _backgroundSpriteCurrentFrame = 0;
+ } else {
+ _selectedObject.xPos = _selectedObject.locationObject_toX2;
+ _selectedObject.yPos = _selectedObject.locationObject_toY2;
+ _panelLockedFlag = 1;
+ }
+ _scrollOffset = 0;
+ _handleMapCounter = 0;
+ _locationMaskCounter = 0;
+ _selectedObject.locationObject_locationNum = 0;
+ }
+ }
+}
+
+void TuckerEngine::updateSprites() {
+ const int count = (_locationNum == 9) ? 3 : _spritesCount;
+ for (int i = 0; i < count; ++i) {
+ if (_spritesTable[i].stateIndex > -1) {
+ ++_spritesTable[i].stateIndex;
+ if (_characterStateTable[_spritesTable[i].stateIndex] == 99) {
+ _spritesTable[i].stateIndex = -1;
+ _spritesTable[i].state = -1;
+ updateSprite(i);
+ } else {
+ _spritesTable[i].animationFrame = _characterStateTable[_spritesTable[i].stateIndex];
+ }
+ continue;
+ }
+ if (_spritesTable[i].state == -1) {
+ updateSprite(i);
+ continue;
+ }
+ if (_charSpeechSoundCounter > 0 && i == _actionCharacterNum && _spritesTable[i].needUpdate == 0) {
+ updateSprite(i);
+ continue;
+ }
+ if (_charSpeechSoundCounter == 0 && _spritesTable[i].needUpdate > 0) {
+ updateSprite(i);
+ continue;
+ }
+ if (_spritesTable[i].updateDelay > 0) {
+ --_spritesTable[i].updateDelay;
+ if (_spritesTable[i].updateDelay == 0) {
+ updateSprite(i);
+ }
+ continue;
+ }
+ if (_spritesTable[i].defaultUpdateDelay > 0) {
+ _spritesTable[i].updateDelay = _spritesTable[i].defaultUpdateDelay - 1;
+ ++_spritesTable[i].animationFrame;
+ if (_spritesTable[i].animationFrame == _spritesTable[i].firstFrame) {
+ updateSprite(i);
+ }
+ continue;
+ }
+ if (_spritesTable[i].nextAnimationFrame == 0) {
+ ++_spritesTable[i].animationFrame;
+ if (_spritesTable[i].firstFrame - 1 < _spritesTable[i].animationFrame) {
+ if (_spritesTable[i].prevAnimationFrame == 1) {
+ --_spritesTable[i].animationFrame;
+ _spritesTable[i].nextAnimationFrame = 1;
+ } else {
+ updateSprite(i);
+ }
+ }
+ continue;
+ }
+ --_spritesTable[i].animationFrame;
+ if (_spritesTable[i].animationFrame == 0) {
+ updateSprite(i);
+ }
+ }
+}
+
+void TuckerEngine::updateSprite(int i) {
+ _spritesTable[i].prevState = _spritesTable[i].state;
+ _spritesTable[i].prevAnimationFrame = 0;
+ _spritesTable[i].nextAnimationFrame = 0;
+ _updateSpriteFlag1 = 0;
+ _updateSpriteFlag2 = 0;
+ _spritesTable[i].defaultUpdateDelay = 0;
+ _spritesTable[i].updateDelay = 0;
+ switch (_locationNum) {
+ case 2:
+ updateSprite_locationNum2();
+ break;
+ case 3:
+ if (i == 0) {
+ updateSprite_locationNum3_0(i);
+ } else if (i == 1) {
+ updateSprite_locationNum3_1(i);
+ } else {
+ updateSprite_locationNum3_2(i);
+ }
+ break;
+ case 4:
+ updateSprite_locationNum4(0);
+ break;
+ case 5:
+ if (i == 0) {
+ updateSprite_locationNum5_0();
+ } else {
+ updateSprite_locationNum5_1(1);
+ }
+ break;
+ case 6:
+ if (i == 0) {
+ updateSprite_locationNum6_0(0);
+ } else if (i == 1) {
+ updateSprite_locationNum6_1(1);
+ } else {
+ updateSprite_locationNum6_2(2);
+ }
+ break;
+ case 7:
+ if (i == 0) {
+ updateSprite_locationNum7_0(0);
+ } else {
+ updateSprite_locationNum7_1(1);
+ }
+ break;
+ case 8:
+ if (i == 0) {
+ updateSprite_locationNum8_0(0);
+ } else {
+ updateSprite_locationNum8_1(1);
+ }
+ break;
+ case 9:
+ if (i == 0) {
+ updateSprite_locationNum9_0(i);
+ } else if (i == 1) {
+ updateSprite_locationNum9_1(i);
+ } else {
+ updateSprite_locationNum9_2(i);
+ }
+ break;
+ case 10:
+ updateSprite_locationNum10();
+ break;
+ case 11:
+ if (i == 0) {
+ updateSprite_locationNum11_0(0);
+ } else if (i == 1) {
+ updateSprite_locationNum11_1(1);
+ } else if (i == 2) {
+ updateSprite_locationNum11_2(2);
+ } else if (i == 3) {
+ updateSprite_locationNum11_3(3);
+ } else if (i == 4) {
+ updateSprite_locationNum11_4(4);
+ }
+ break;
+ case 12:
+ if (i == 0) {
+ updateSprite_locationNum12_0(0);
+ } else if (i == 1) {
+ updateSprite_locationNum12_1(1);
+ }
+ break;
+ case 13:
+ updateSprite_locationNum13(0);
+ break;
+ case 14:
+ updateSprite_locationNum14(0);
+ break;
+ case 15:
+ if (i == 1) {
+ updateSprite_locationNum15_1(1);
+ } else if (i == 2) {
+ updateSprite_locationNum15_2(2);
+ } else if (i == 0) {
+ updateSprite_locationNum15_0(0);
+ }
+ break;
+ case 16:
+ if (i == 0) {
+ updateSprite_locationNum16_0(0);
+ } else if (i == 1) {
+ updateSprite_locationNum16_1(1);
+ } else {
+ updateSprite_locationNum16_2(2);
+ }
+ break;
+ case 17:
+ updateSprite_locationNum17();
+ break;
+ case 18:
+ updateSprite_locationNum18();
+ break;
+ case 19:
+ if (i == 0) {
+ updateSprite_locationNum19_0(0);
+ } else if (i == 1) {
+ updateSprite_locationNum19_1(1);
+ } else if (i == 2) {
+ updateSprite_locationNum19_2(2);
+ } else {
+ updateSprite_locationNum19_3(3);
+ }
+ break;
+ case 21:
+ updateSprite_locationNum21();
+ break;
+ case 22:
+ updateSprite_locationNum22();
+ break;
+ case 23:
+ if (i == 0) {
+ updateSprite_locationNum23_0(0);
+ } else if (i == 1) {
+ updateSprite_locationNum23_1(1);
+ } else if (i == 2) {
+ updateSprite_locationNum23_2(2);
+ } else {
+ updateSprite_locationNum23_3(3);
+ }
+ break;
+ case 24:
+ if (i == 0) {
+ updateSprite_locationNum24_0(0);
+ } else if (i == 1) {
+ updateSprite_locationNum24_1(1);
+ } else if (i == 2) {
+ updateSprite_locationNum24_2(2);
+ } else {
+ updateSprite_locationNum24_3(3);
+ }
+ break;
+ case 26:
+ if (i == 0) {
+ updateSprite_locationNum26_0(0);
+ } else {
+ updateSprite_locationNum26_1(1);
+ }
+ break;
+ case 27:
+ updateSprite_locationNum27(0);
+ break;
+ case 28:
+ if (i == 0) {
+ updateSprite_locationNum28_0(0);
+ } else if (i == 1) {
+ updateSprite_locationNum28_1(1);
+ } else {
+ updateSprite_locationNum28_2(2);
+ }
+ break;
+ case 29:
+ if (i == 0) {
+ updateSprite_locationNum29_0(0);
+ } else if (i == 1) {
+ updateSprite_locationNum29_1(1);
+ } else {
+ updateSprite_locationNum29_2(2);
+ }
+ break;
+ case 30:
+ updateSprite_locationNum30_34(i);
+ break;
+ case 31:
+ if (i == 0) {
+ updateSprite_locationNum31_0(0);
+ } else {
+ updateSprite_locationNum31_1(1);
+ }
+ break;
+ case 32:
+ if (i == 0) {
+ updateSprite_locationNum32_0(0);
+ } else {
+ _spritesTable[i].state = -1;
+ }
+ break;
+ case 33:
+ if (i == 1) {
+ updateSprite_locationNum33_1(1);
+ } else if (i == 0) {
+ updateSprite_locationNum33_0(0);
+ } else if (i == 2) {
+ updateSprite_locationNum33_2(2);
+ } else {
+ _spritesTable[i].state = 12;
+ }
+ break;
+ case 34:
+ updateSprite_locationNum30_34(0);
+ break;
+ case 36:
+ updateSprite_locationNum36(0);
+ break;
+ case 37:
+ if (i == 0) {
+ _spritesTable[0].state = -1;
+ } else {
+ updateSprite_locationNum37(i, i + 1, 200 - i * 45);
+ }
+ break;
+ case 41:
+ updateSprite_locationNum41(i);
+ break;
+ case 42:
+ updateSprite_locationNum42(i);
+ break;
+ case 43:
+ if (i == 2) {
+ updateSprite_locationNum43_2(i);
+ } else if (i < 2) {
+ if (_flagsTable[236] < 4) {
+ _spritesTable[0].state = i + 1;
+ } else {
+ _spritesTable[0].state = -1;
+ }
+ } else if (i == 3) {
+ updateSprite_locationNum43_3(3);
+ } else if (i == 4) {
+ updateSprite_locationNum43_4(4);
+ } else if (i == 5) {
+ updateSprite_locationNum43_5(5);
+ } else {
+ updateSprite_locationNum43_6(6);
+ }
+ break;
+ case 45:
+ _spritesTable[0].state = 1;
+ break;
+ case 47:
+ _spritesTable[i].state = i + 1;
+ break;
+ case 48:
+ updateSprite_locationNum48(0);
+ break;
+ case 49:
+ updateSprite_locationNum49(0);
+ break;
+ case 50:
+ if (i < 6) {
+ updateSprite_locationNum50(i);
+ } else {
+ _spritesTable[i].state = i + 1;
+ }
+ break;
+ case 51:
+ if (i == 2) {
+ updateSprite_locationNum51_2(2);
+ } else if (i == 0) {
+ updateSprite_locationNum51_0(0);
+ } else {
+ updateSprite_locationNum51_1(1);
+ }
+ break;
+ case 53:
+ if (i == 0) {
+ updateSprite_locationNum53_0(0);
+ } else if (i == 1) {
+ updateSprite_locationNum53_1(1);
+ }
+ break;
+ case 54:
+ updateSprite_locationNum54(0);
+ break;
+ case 55:
+ updateSprite_locationNum55(0);
+ break;
+ case 56:
+ updateSprite_locationNum56(0);
+ break;
+ case 57:
+ if (i == 0) {
+ updateSprite_locationNum57_0(0);
+ } else if (i == 1) {
+ updateSprite_locationNum57_1(1);
+ }
+ break;
+ case 58:
+ updateSprite_locationNum58(0);
+ break;
+ case 59:
+ updateSprite_locationNum59(0);
+ break;
+ case 60:
+ if (i == 0) {
+ updateSprite_locationNum60_0(0);
+ } else {
+ updateSprite_locationNum60_1(1);
+ }
+ break;
+ case 61:
+ if (i == 0) {
+ updateSprite_locationNum61_0(0);
+ } else if (i == 2) {
+ updateSprite_locationNum61_2(2);
+ } else {
+ updateSprite_locationNum61_1(1);
+ }
+ break;
+ case 63:
+ if (i == 0) {
+ updateSprite_locationNum63_0(0);
+ } else if (i == 1) {
+ updateSprite_locationNum63_1(1);
+ } else if (i == 2) {
+ updateSprite_locationNum63_2(2);
+ } else if (i == 3) {
+ updateSprite_locationNum63_3(3);
+ } else if (i == 4) {
+ updateSprite_locationNum63_4(4);
+ }
+ break;
+ case 65:
+ updateSprite_locationNum65(0);
+ break;
+ case 66:
+ if (i == 0) {
+ updateSprite_locationNum66_0(0);
+ } else if (i == 1) {
+ updateSprite_locationNum66_1(1);
+ } else if (i == 2) {
+ updateSprite_locationNum66_2(2);
+ } else if (i == 3) {
+ updateSprite_locationNum66_3(3);
+ } else {
+ updateSprite_locationNum66_4(4);
+ }
+ break;
+ case 69:
+ if (i == 0) {
+ _spritesTable[0].state = 1;
+ } else if (i == 1) {
+ updateSprite_locationNum69_1(1);
+ } else if (i == 2) {
+ updateSprite_locationNum69_2(2);
+ } else if (i == 3) {
+ updateSprite_locationNum69_3(3);
+ }
+ break;
+ case 71:
+ updateSprite_locationNum71(0);
+ break;
+ case 72:
+ updateSprite_locationNum72(0);
+ break;
+ case 74:
+ updateSprite_locationNum74(i);
+ break;
+ case 79:
+ updateSprite_locationNum79(0);
+ break;
+ case 81:
+ if (i == 0) {
+ updateSprite_locationNum81_0(0);
+ } else if (i == 1) {
+ updateSprite_locationNum81_1(1);
+ }
+ break;
+ case 82:
+ updateSprite_locationNum82(0);
+ break;
+ case 98:
+ _spritesTable[0].state = 1;
+ break;
+ }
+ if (_spritesTable[i].stateIndex <= -1) {
+ if (_updateSpriteFlag1 == 0) {
+ _spritesTable[i].animationFrame = 1;
+ }
+ _spritesTable[i].animationData = _sprC02Table[_spritesTable[i].state];
+ _spritesTable[i].firstFrame = READ_LE_UINT16(_spritesTable[i].animationData);
+ if (_updateSpriteFlag2 == 1) {
+ _spritesTable[i].state = _spritesTable[i].firstFrame;
+ _spritesTable[i].nextAnimationFrame = 1;
+ _spritesTable[i].prevAnimationFrame = 1;
+ }
+ }
+}
+
+void TuckerEngine::drawStringInteger(int num, int x, int y, int digits) {
+ int offset = y * 640 + x + _scrollOffset;
+ char numStr[4];
+ assert(num < 1000);
+ sprintf(numStr, "%03d", num);
+ int i = (digits > 2) ? 0 : 1;
+ for (; i < 3; ++i) {
+ Graphics::drawStringChar(_locationBackgroundGfxBuf + offset, numStr[i], 640, 102, _charsetGfxBuf);
+ offset += 8;
+ }
+}
+
+void TuckerEngine::drawStringAlt(uint8 *dst, int color, const uint8 *str, int strLen) {
+ int pos = 0;
+ while (pos != strLen && str[pos] != '\n') {
+ const uint8 chr = str[pos];
+ Graphics::drawStringChar(dst, chr, 640, color, _charsetGfxBuf);
+ dst += _charWidthTable[chr];
+ ++pos;
+ }
+}
+
+void TuckerEngine::drawString(uint8 *dst, int num, const uint8 *str) {
+ int count = getPositionForLine(num, str);
+ while (str[count] != '\n') {
+ const uint8 chr = str[count];
+ Graphics::drawStringChar(dst, chr, 320, 1, _charsetGfxBuf);
+ dst += _charWidthTable[chr];
+ ++count;
+ }
+}
+
+void TuckerEngine::drawString2(int x, int y, int num) {
+ uint8 *dst = _locationBackgroundGfxBuf + y * 640 + x;
+ int pos = getPositionForLine(num, _ptTextBuf);
+ while (_ptTextBuf[pos] != '\n') {
+ const uint8 chr = _ptTextBuf[pos];
+ Graphics::drawStringChar2(dst, chr, 640, 1, _charsetGfxBuf);
+ dst += _charWidthTable[chr];
+ ++pos;
+ }
+}
+
+void TuckerEngine::updateCharSpeechSound() {
+ if (_charSpeechSoundCounter == 0) {
+ return;
+ }
+ --_charSpeechSoundCounter;
+ int i = isSpeechSoundPlaying();
+ if (_charSpeechSoundCounter == 0) {
+ _charSpeechSoundCounter = i;
+ if (_charSpeechSoundCounter == 0) {
+ _characterSpriteAnimationFrameCounter = 0;
+ }
+ }
+ if (_charSpeechSoundCounter == 0 && _csDataHandled == 0) {
+ setCursorType(0);
+ return;
+ }
+ static const int constEq0 = 0; // display text for speech
+ if (constEq0 == 1 && _gamePaused2 == 0) {
+ drawSpeechText(_actionPosX, _actionPosY, _characterSpeechDataPtr, _speechSoundNum, _actionTextColor);
+ }
+}
+
+void TuckerEngine::updateItemsGfxColors(int color1, int color128) {
+ for (int i = 0; i < 3200; ++i) {
+ if (_itemsGfxBuf[i] == 1) {
+ _itemsGfxBuf[i] = color1;
+ } else if (_itemsGfxBuf[i] == 128) {
+ _itemsGfxBuf[i] = color128;
+ }
+ }
+}
+
+int TuckerEngine::testLocationMask(int x, int y) {
+ if (_locationMaskType > 0 || _locationMaskIgnore > 0) {
+ return 1;
+ }
+ if (_locationNum == 26 || _locationNum == 32) {
+ y -= 3;
+ }
+ const int offset = y * 640 + x;
+ return _locationBackgroundMaskBuf[offset] > 0 ? 1 : 0;
+}
+
+int TuckerEngine::getStringWidth(int num, const uint8 *ptr) {
+ int w = 0;
+ int pos = getPositionForLine(num, ptr);
+ uint8 chr;
+ while ((chr = ptr[pos]) != '\n') {
+ w += _charWidthTable[chr];
+ ++pos;
+ }
+ return w;
+}
+
+int TuckerEngine::getPositionForLine(int num, const uint8 *ptr) {
+ int linesCount = 0;
+ int i = 0;
+ while (linesCount < num) {
+ if (ptr[i] == '\n') {
+ ++linesCount;
+ if (ptr[i + 1] == '\r') {
+ ++i;
+ }
+ }
+ ++i;
+ }
+ while (1) {
+ if (ptr[i] != '\n' && ptr[i] != '\r') {
+ break;
+ }
+ ++i;
+ }
+ return i;
+}
+
+void TuckerEngine::copyToVGA(const uint8 *src) {
+ _system->copyRectToScreen(src, 640, 0, 0, 320, 200);
+ _system->updateScreen();
+}
+
+void TuckerEngine::findActionKey(int count) {
+ _backgroundSpriteCurrentFrame = 0;
+ _characterAnimationIndex = 0;
+ for (int i = 0; i < count; ++i) {
+ while (_characterAnimationsTable[_characterAnimationIndex] != 99) {
+ ++_characterAnimationIndex;
+ }
+ ++_characterAnimationIndex;
+ }
+}
+
+static int parseInt(const uint8 *buf, int offset, int len) {
+ assert(len < 16);
+ char tmpBuf[16];
+ memcpy(tmpBuf, buf + offset, len);
+ tmpBuf[len] = 0;
+ return strtol(tmpBuf, 0, 10);
+}
+
+int TuckerEngine::parseTableInstruction() {
+ int spr;
+ printf("parseTableInstruction instruction %c %c %c\n", _tableInstructionsPtr[0], _tableInstructionsPtr[1], _tableInstructionsPtr[2]);
+ switch (_tableInstructionsPtr[0]) {
+ case 'p': // 12
+ if (_tableInstructionsPtr[1] == 'a') { // 0
+ _tableInstructionsPtr += 4;
+ _panelState = parseInt(_tableInstructionsPtr, 0, 2);
+ _forceRedrawPanelItems = 1;
+ _tableInstructionsPtr += 3;
+ return 0;
+ }
+ break;
+ case 'b': // 1
+ if (_tableInstructionsPtr[2] == 'a') { // 0
+ _backgroundSpriteCurrentAnimation = parseInt(_tableInstructionsPtr, 4, 3);
+ _backgroundSpriteCurrentFrame = 0;
+ _backgroundSprOffset = 0;
+ _mainLoopCounter2 = 0;
+ _tableInstructionsPtr += 8;
+ return 0;
+ }
+ if (_tableInstructionsPtr[2] == 'b') { // 1
+ int i = parseInt(_tableInstructionsPtr, 4, 3);
+ _spriteAnimationFrameIndex = _spriteAnimationsTable[i].firstFrameIndex;
+ _characterFacingDirection = 5;
+ _mainLoopCounter2 = 0;
+ _tableInstructionsPtr += 8;
+ return 0;
+ }
+ if (_tableInstructionsPtr[2] == 'c') { // 2
+ int i = parseInt(_tableInstructionsPtr, 4, 3);
+ findActionKey(i);
+ _backgroundSpriteCurrentFrame = 0;
+ _backgroundSprOffset = 0;
+ _tableInstructionsPtr += 8;
+ return 0;
+ }
+ if (_tableInstructionsPtr[2] == 'd') { // 4
+ _selectedCharacterDirection = parseInt(_tableInstructionsPtr, 4, 2);
+ _tableInstructionsPtr += 7;
+ return 0;
+ }
+ if (_tableInstructionsPtr[2] == 'f') { // 5
+ _skipCurrentCharacterDraw = 1;
+ _tableInstructionsPtr += 4;
+ return 0;
+ }
+ if (_tableInstructionsPtr[2] == 'h') { // 7
+ _noCharacterAnimationChange = parseInt(_tableInstructionsPtr, 4, 2);
+ _tableInstructionsPtr += 7;
+ return 0;
+ }
+ if (_tableInstructionsPtr[2] == 'n') { // 10
+ _skipCurrentCharacterDraw = 0;
+ _tableInstructionsPtr += 4;
+ return 0;
+ }
+ if (_tableInstructionsPtr[2] == 'o') { // 11
+ _backgroundSprOffset = parseInt(_tableInstructionsPtr, 4, 3);
+ _tableInstructionsPtr += 8;
+ return 0;
+ }
+ if (_tableInstructionsPtr[2] == 's') { // 14
+ int i = parseInt(_tableInstructionsPtr, 4, 3);
+ _speechSoundNum = i - 1;
+ _speechHistoryTable[4] = _speechHistoryTable[3];
+ _speechHistoryTable[3] = _speechHistoryTable[2];
+ _speechHistoryTable[2] = _speechHistoryTable[1];
+ _speechHistoryTable[1] = _speechHistoryTable[0];
+ _speechHistoryTable[0] = _partNum * 3000 + _ptTextOffset + _speechSoundNum - 3000;
+ startSpeechSound(_partNum * 3000 + _ptTextOffset + _speechSoundNum - 3000, _speechVolume);
+ _actionPosX = _xPosCurrent;
+ _actionPosY = _yPosCurrent - 64;
+ _actionTextColor = 1;
+ _actionCharacterNum = 99;
+ _charSpeechSoundCounter = kDefaultCharSpeechSoundCounter;
+ _tableInstructionsPtr += 8;
+ return 0;
+ }
+ if (_tableInstructionsPtr[2] == 'v') { // 16
+ _speechVolume = parseInt(_tableInstructionsPtr, 4, 3);
+ _tableInstructionsPtr += 8;
+ return 0;
+ }
+ if (_tableInstructionsPtr[2] == 'w') { // 17
+ _selectedObject.xPos = parseInt(_tableInstructionsPtr, 4, 3);
+ _selectedObject.yPos = parseInt(_tableInstructionsPtr, 8, 3);
+ _locationMaskIgnore = 1;
+ _panelLockedFlag = 1;
+ _tableInstructionsPtr += 12;
+ return 0;
+ }
+ if (_tableInstructionsPtr[2] == 'x') { // 18
+ _xPosCurrent = parseInt(_tableInstructionsPtr, 4, 3);
+ _yPosCurrent = parseInt(_tableInstructionsPtr, 8, 3);
+ _tableInstructionsPtr += 12;
+ return 0;
+ }
+ break;
+ case 'c': // 2
+ spr = _tableInstructionsPtr[1] - '0';
+ if (_tableInstructionsPtr[2] == 'a') { // 0
+ _spritesTable[spr].state = parseInt(_tableInstructionsPtr, 4, 3);
+ if (_spritesTable[spr].state == 999) {
+ _spritesTable[spr].state = -1;
+ }
+ _mainLoopCounter1 = 0;
+ _spritesTable[spr].updateDelay = 0;
+ _spritesTable[spr].nextAnimationFrame = 0;
+ _spritesTable[spr].prevAnimationFrame = 0;
+ _tableInstructionsPtr += 8;
+ return 0;
+ }
+ if (_tableInstructionsPtr[2] == 'e') { // 4
+ int i = parseInt(_tableInstructionsPtr, 4, 3);
+ setCharacterAnimation(i, spr);
+ _tableInstructionsPtr += 8;
+ return 0;
+ }
+ if (_tableInstructionsPtr[2] == 's') { // 14
+ int i = parseInt(_tableInstructionsPtr, 4, 3);
+ _speechSoundNum = i - 1;
+ _speechHistoryTable[4] = _speechHistoryTable[3];
+ _speechHistoryTable[3] = _speechHistoryTable[2];
+ _speechHistoryTable[2] = _speechHistoryTable[1];
+ _speechHistoryTable[1] = _speechHistoryTable[0];
+ _speechHistoryTable[0] = _partNum * 3000 + _ptTextOffset + _speechSoundNum - 3000;
+ startSpeechSound(_partNum * 3000 + _ptTextOffset + _speechSoundNum - 3000, _charSpeechSoundVolumeTable[spr]);
+ _charSpeechSoundCounter = kDefaultCharSpeechSoundCounter;
+ _actionTextColor = 181 + spr;
+ if (_tableInstructionFlag == 0) {
+ _actionPosX = _tableInstructionItemNum1;
+ _actionPosY = _tableInstructionItemNum2;
+ } else {
+ _actionPosX = _tableInstructionObj1Table[spr];
+ _actionPosY = _tableInstructionObj2Table[spr];
+ }
+ _actionCharacterNum = spr;
+ _tableInstructionsPtr += 8;
+ return 0;
+ }
+ if (_tableInstructionsPtr[2] == 'v') { // 16
+ _charSpeechSoundVolumeTable[spr] = parseInt(_tableInstructionsPtr, 4, 3);
+ _tableInstructionsPtr += 8;
+ return 0;
+ }
+ break;
+ case 'e': // 4
+ if (_tableInstructionsPtr[1] == 'n') { // 10
+ return 2;
+ }
+ break;
+ case 'f': // 5
+ if (_tableInstructionsPtr[2] == 'd') { // 3
+ _fadePaletteCounter = parseInt(_tableInstructionsPtr, 4, 2);
+ _tableInstructionsPtr += 7;
+ return 0;
+ }
+ if (_tableInstructionsPtr[1] == 'm') { // 9
+ _redrawPanelItemsCounter = 50;
+ _lastInventoryObjectIndex = 1;
+ _inventoryObjectsOffset = 0;
+ _tableInstructionsPtr += 3;
+ return 0;
+ }
+ if (_tableInstructionsPtr[1] == 'w') { // 17
+ _selectedCharacterNum = parseInt(_tableInstructionsPtr, 3, 2);
+ _tableInstructionsPtr += 6;
+ _actionVerb = 0;
+ _selectedObjectType = 0;
+ _selectedObjectNum = 1;
+ setSelectedObjectKey();
+ return 0;
+ }
+ if (_tableInstructionsPtr[2] == 'x') { // 18
+ int i = parseInt(_tableInstructionsPtr, 4, 2);
+ if (_tableInstructionsPtr[1] == 'l') { // 8
+ _locationSoundsTable[i].type = 2;
+ startSound(_locationSoundsTable[i].offset, i, _locationSoundsTable[i].volume);
+ } else {
+ if (isSoundPlaying(i)) {
+ stopSound(i);
+ }
+ }
+ _tableInstructionsPtr += 7;
+ return 0;
+ }
+ if (_tableInstructionsPtr[1] == 'x') { // 18
+ int i = parseInt(_tableInstructionsPtr, 3, 2);
+ startSound(_locationSoundsTable[i].offset, i, _locationSoundsTable[i].volume);
+ _soundInstructionIndex = i;
+ _tableInstructionsPtr += 6;
+ return 0;
+ }
+ break;
+ case 'g': // 6
+ if (_tableInstructionsPtr[2] == 'g') { // 6
+ int i = parseInt(_tableInstructionsPtr, 4, 3);
+ _flagsTable[i] = parseInt(_tableInstructionsPtr, 8, 2);
+ _tableInstructionsPtr += 11;
+ return 0;
+ }
+ if (_tableInstructionsPtr[1] == 'v') { // 16
+ _characterAnimationNum = parseInt(_tableInstructionsPtr, 3, 2);
+ _tableInstructionsPtr += 6;
+ return 0;
+ }
+ break;
+ case 'l': // 8
+ if (_tableInstructionsPtr[2] == 'c') { // 2
+ _nextLocationNum = parseInt(_tableInstructionsPtr, 4, 2);
+ _tableInstructionsPtr += 7;
+ return 1;
+ }
+ break;
+ case 'o': // 11
+ if (_tableInstructionsPtr[2] == 't') { // 15
+ _conversationOptionsCount = parseInt(_tableInstructionsPtr, 4, 2);
+ _tableInstructionsPtr += 7;
+ for (int i = 0; i < _conversationOptionsCount; ++i) {
+ _instructionsActionsTable[i] = parseInt(_tableInstructionsPtr, 0, 3) - 1;
+ _nextTableToLoadTable[i] = parseInt(_tableInstructionsPtr, 4, 3);
+ _tableInstructionsPtr += 8;
+ }
+ _nextTableToLoadIndex = -1;
+ setCursorType(1);
+ return 1;
+ }
+ if (_tableInstructionsPtr[2] == 'f') { // 5
+ int count = parseInt(_tableInstructionsPtr, 4, 2);
+ _tableInstructionsPtr += 7;
+ _conversationOptionsCount = 0;
+ for (int i = 0; i < count; ++i) {
+ int flag = parseInt(_tableInstructionsPtr, 0, 3);
+ int value = parseInt(_tableInstructionsPtr, 4, 2);
+ if (value == _flagsTable[flag]) {
+ _instructionsActionsTable[_conversationOptionsCount] = parseInt(_tableInstructionsPtr, 7, 3) - 1;
+ _nextTableToLoadTable[_conversationOptionsCount] = parseInt(_tableInstructionsPtr, 11, 3);
+ ++_conversationOptionsCount;
+ }
+ _tableInstructionsPtr += 15;
+ }
+ _nextTableToLoadIndex = -1;
+ setCursorType(1);
+ return 1;
+ }
+ if (_tableInstructionsPtr[2] == 'g') { // 6
+ int i = parseInt(_tableInstructionsPtr, 8, 2);
+ if (i == 0) {
+ int obj = parseInt(_tableInstructionsPtr, 4, 3);
+ removeObjectFromInventory(obj);
+ } else {
+ int obj = parseInt(_tableInstructionsPtr, 4, 3);
+ addObjectToInventory(obj);
+ }
+ _tableInstructionsPtr += 11;
+ return 0;
+ }
+ break;
+ case 's': // 14
+ if (_tableInstructionsPtr[2] == 'c') { // 2
+ _tableInstructionsPtr += 4;
+ _mainLoopCounter1 = 0;
+ return 0;
+ }
+ if (_tableInstructionsPtr[2] == 'e') { // 4
+ _nextAction = parseInt(_tableInstructionsPtr, 4, 3);
+ _csDataLoaded = false;
+ return 3;
+ }
+ if (_tableInstructionsPtr[2] == 'p') { // 12
+ if (_tableInstructionsPtr[1] == 's') { // 14
+ _tableInstructionFlag = 0;
+ _tableInstructionItemNum1 = parseInt(_tableInstructionsPtr, 4, 3);
+ _tableInstructionItemNum2 = parseInt(_tableInstructionsPtr, 8, 3);
+ } else {
+ int num = _tableInstructionsPtr[1] - '0';
+ _tableInstructionFlag = 1;
+ _tableInstructionObj1Table[num] = parseInt(_tableInstructionsPtr, 4, 3);
+ _tableInstructionObj2Table[num] = parseInt(_tableInstructionsPtr, 8, 3);
+ }
+ _tableInstructionsPtr += 12;
+ return 0;
+ }
+ if (_tableInstructionsPtr[1] == 'p') { // 12
+ _characterSpriteAnimationFrameCounter = 1;
+ _tableInstructionsPtr += 3;
+ return 0;
+ }
+ break;
+ case 't': // 15
+ if (_tableInstructionsPtr[2] == 'o') { // 11
+ _ptTextOffset = parseInt(_tableInstructionsPtr, 4, 4);
+ _characterSpeechDataPtr = _ptTextBuf + getPositionForLine(_ptTextOffset, _ptTextBuf);
+ _tableInstructionsPtr += 9;
+ return 0;
+ }
+ break;
+ case 'w': // 17
+ if (_tableInstructionsPtr[2] == '+') { // 19
+ _csDataTableFlag2 = 1;
+ _stopActionCounter = 20;
+ _tableInstructionsPtr += 4;
+ return 1;
+ }
+ if (_tableInstructionsPtr[2] == 'm') { // 9
+ _stopActionOnPanelLock = 1;
+ _tableInstructionsPtr += 4;
+ return 1;
+ }
+ if (_tableInstructionsPtr[2] == 't') { // 15
+ _stopActionCounter = parseInt(_tableInstructionsPtr, 4, 3);
+ _tableInstructionsPtr += 8;
+ return 1;
+ }
+ if (_tableInstructionsPtr[2] == 's') { // 14
+ _csDataTableFlag2 = 1;
+ _tableInstructionsPtr += 4;
+ return 1;
+ }
+ if (_tableInstructionsPtr[2] == 'a') { // 0
+ if (_tableInstructionsPtr[1] == 'b') { // 1
+ _csDataTableCount = 99;
+ } else {
+ _csDataTableCount = _tableInstructionsPtr[1] - '0' + 1;
+ }
+ return 1;
+ }
+ if (_tableInstructionsPtr[2] == 'x') { // 18
+ _stopActionOnSoundFlag = 1;
+ _tableInstructionsPtr += 4;
+ return 1;
+ }
+ break;
+ case 'x': // 18
+ if (_tableInstructionsPtr[2] == 'r') { // 13
+ _validInstructionId = 1;
+ _tableInstructionsPtr += 4;
+ return 0;
+ }
+ if (_tableInstructionsPtr[2] == 'm') { // 9
+ _validInstructionId = 0;
+ _tableInstructionsPtr += 4;
+ return 0;
+ }
+ break;
+ }
+ printf("Instruction not recognised %c %c %c\n", _tableInstructionsPtr[0], _tableInstructionsPtr[1], _tableInstructionsPtr[2]);
+ return 2;
+}
+
+void TuckerEngine::moveUpInventoryObjects() {
+ if (_inventoryObjectsOffset + 6 < _inventoryObjectsCount) {
+ _inventoryObjectsOffset += 3;
+ _forceRedrawPanelItems = 1;
+ }
+}
+
+void TuckerEngine::moveDownInventoryObjects() {
+ if (_inventoryObjectsOffset > 2) {
+ _inventoryObjectsOffset -= 3;
+ _forceRedrawPanelItems = 1;
+ }
+}
+
+void TuckerEngine::setActionVerbUnderCursor() {
+ if (_mousePosY < 150) {
+ _actionVerb = 0;
+ } else if (_mousePosX > 195) {
+ _actionVerb = 1;
+ } else if (_panelNum == 0) {
+ _actionVerb = ((_mousePosY - 150) / 17) * 3 + (_mousePosX / 67);
+ } else {
+ _actionVerb = 0;
+ if (_mousePosX < 30) {
+ _actionVerb = 7;
+ } else if (_mousePosX > 130 && _mousePosX < 165) {
+ _actionVerb = 5;
+ } else {
+ if (_mousePosY < 175) {
+ if (_mousePosX < 67) {
+ _actionVerb = 3;
+ } else if (_mousePosX > 164) {
+ _actionVerb = 6;
+ } else if (_mousePosX > 99) {
+ _actionVerb = 4;
+ }
+ } else {
+ if (_mousePosX < 85) {
+ _actionVerb = 1;
+ } else if (_mousePosX > 165) {
+ _actionVerb = 2;
+ } else {
+ _actionVerb = 8;
+ }
+ }
+ }
+ }
+}
+
+int TuckerEngine::getObjectUnderCursor() {
+ if (_mousePosY > 140) {
+ return -1;
+ }
+ for (int i = 0; i < _locationObjectsCount; ++i) {
+ if (_mousePosX + _scrollOffset + 1 <= _locationObjectsTable[i].xPos) {
+ continue;
+ }
+ if (_mousePosX + _scrollOffset >= _locationObjectsTable[i].xPos + _locationObjectsTable[i].xSize) {
+ continue;
+ }
+ if (_mousePosY <= _locationObjectsTable[i].yPos) {
+ continue;
+ }
+ if (_mousePosY >= _locationObjectsTable[i].yPos + _locationObjectsTable[i].ySize) {
+ continue;
+ }
+ _selectedObjectType = 0;
+ _selectedCharacterNum = i;
+ setCursorNum(_locationObjectsTable[i].cursorNum);
+ return i;
+ }
+ return -1;
+}
+
+void TuckerEngine::setSelectedObjectKey() {
+ const int x = _mousePosX + _scrollOffset;
+ if (_mousePosY > 139 && _nextAction == 0) {
+ return;
+ }
+ _panelLockedFlag = 1;
+ _locationMaskCounter = 0;
+ _actionRequiresTwoObjects = false;
+ _selectedObject.yPos = 0;
+ _selectedObject.locationObject_locationNum = 0;
+ _pendingActionIndex = 0;
+ if (_selectedObjectType == 0) {
+ if (_selectedObjectNum == 0) {
+ _selectedObject.xPos = x;
+ _selectedObject.yPos = _mousePosY;
+ } else {
+ _selectedObject.xPos = _locationObjectsTable[_selectedCharacterNum].standX;
+ _selectedObject.yPos = _locationObjectsTable[_selectedCharacterNum].standY;
+ if (_actionVerb == 0 || _actionVerb == 8) {
+ _selectedObject.locationObject_locationNum = _locationObjectsTable[_selectedCharacterNum].locationNum;
+ _selectedObject.locationObject_toX = _locationObjectsTable[_selectedCharacterNum].toX;
+ _selectedObject.locationObject_toY = _locationObjectsTable[_selectedCharacterNum].toY;
+ _selectedObject.locationObject_toX2 = _locationObjectsTable[_selectedCharacterNum].toX2;
+ _selectedObject.locationObject_toY2 = _locationObjectsTable[_selectedCharacterNum].toY2;
+ _selectedObject.locationObject_toWalkX2 = _locationObjectsTable[_selectedCharacterNum].toWalkX2;
+ _selectedObject.locationObject_toWalkY2 = _locationObjectsTable[_selectedCharacterNum].toWalkY2;
+
+ }
+ }
+ } else {
+ switch (_selectedObjectType) {
+ case 1:
+ _selectedObject.xPos = _locationAnimationsTable[_selectedCharacterNum].standX;
+ _selectedObject.yPos = _locationAnimationsTable[_selectedCharacterNum].standY;
+ break;
+ case 2:
+ _selectedObject.xPos = _charPosTable[_selectedCharacterNum].xWalkTo;
+ _selectedObject.yPos = _charPosTable[_selectedCharacterNum].yWalkTo;
+ break;
+ case 3:
+ _selectedObject.xPos = _xPosCurrent;
+ _selectedObject.yPos = _yPosCurrent;
+ break;
+ }
+ }
+ if (_selectedObject.yPos == 0) {
+ _selectedObject.xPos = x;
+ _selectedObject.yPos = _mousePosY;
+ }
+ _selectedObjectLocationMask = testLocationMask(_selectedObject.xPos, _selectedObject.yPos);
+ if (_selectedObjectLocationMask == 0 && _objectKeysLocationTable[_locationNum] == 1) {
+ if (_selectedObject.yPos < _objectKeysPosYTable[_locationNum]) {
+ while (_selectedObjectLocationMask == 0 && _selectedObject.yPos < _objectKeysPosYTable[_locationNum]) {
+ ++_selectedObject.yPos;
+ _selectedObjectLocationMask = testLocationMask(_selectedObject.xPos, _selectedObject.yPos);
+ }
+ } else {
+ while (_selectedObjectLocationMask == 0 && _selectedObject.yPos < _objectKeysPosYTable[_locationNum]) {
+ --_selectedObject.yPos;
+ _selectedObjectLocationMask = testLocationMask(_selectedObject.xPos, _selectedObject.yPos);
+ }
+ }
+ }
+ if (_selectedObjectLocationMask == 1) {
+ _selectedObjectLocationMask = testLocationMaskArea(_xPosCurrent, _yPosCurrent, _selectedObject.xPos, _selectedObject.yPos);
+ if (_selectedObjectLocationMask == 1 && _objectKeysPosXTable[_locationNum] > 0) {
+ _selectedObject.xDefaultPos = _selectedObject.xPos;
+ _selectedObject.yDefaultPos = _selectedObject.yPos;
+ _selectedObject.xPos = _objectKeysPosXTable[_locationNum];
+ _selectedObject.yPos = _objectKeysPosYTable[_locationNum];
+ if (_objectKeysLocationTable[_locationNum] == 1) {
+ _selectedObject.xPos = _selectedObject.xDefaultPos;
+ }
+ }
+ }
+}
+
+void TuckerEngine::setCharacterAnimation(int count, int spr) {
+ _spritesTable[spr].animationFrame = 0;
+ _spritesTable[spr].stateIndex = 0;
+ for (int i = 0; i < count; ++i) {
+ while (_characterStateTable[_spritesTable[spr].stateIndex] != 99) {
+ ++_spritesTable[spr].stateIndex;
+ }
+ ++_spritesTable[spr].stateIndex;
+ }
+ _spritesTable[spr].state = _characterStateTable[_spritesTable[spr].stateIndex];
+ ++_spritesTable[spr].stateIndex;
+ _spritesTable[spr].animationFrame = _characterStateTable[_spritesTable[spr].stateIndex];
+ ++_spritesTable[spr].stateIndex;
+ _spritesTable[spr].animationData = _sprC02Table[_spritesTable[spr].state];
+ _spritesTable[spr].firstFrame = READ_LE_UINT16(_spritesTable[spr].animationData);
+}
+
+int TuckerEngine::testLocationMaskArea(int xBase, int yBase, int xPos, int yPos) {
+ int i = 0;
+ bool quitLoop = false;
+ while (!quitLoop) {
+ bool flag = false;
+ if (yBase > yPos) {
+ if (testLocationMask(xBase, yBase - 1) == 1) {
+ --yBase;
+ flag = true;
+ } else {
+ ++i;
+ }
+ } else if (yBase < yPos) {
+ if (testLocationMask(xBase, yBase + 1) == 1) {
+ ++yBase;
+ flag = true;
+ } else {
+ ++i;
+ }
+ }
+ if (xBase > xPos) {
+ if (testLocationMask(xBase - 1, yBase) == 1) {
+ --xBase;
+ flag = true;
+ } else {
+ ++i;
+ }
+ } else if (xBase <= xPos) {
+ if (testLocationMask(xBase + 1, yBase) == 1) {
+ ++xBase;
+ flag = true;
+ } else {
+ ++i;
+ }
+ }
+ if (xBase == xPos && yBase == yPos) {
+ break;
+ }
+ if (!flag) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+void TuckerEngine::handleMouseClickOnInventoryObject() {
+ if (_panelState != 0) {
+ return;
+ }
+ if (_mousePosY < 150 || _mousePosX < 212) {
+ return;
+ }
+ int pos = ((_mousePosY - 150) / 25) * 3 + (_mousePosX - 212) / 36;
+ int obj = _inventoryObjectsOffset + pos;
+ if (_inventoryObjectsCount - 1 < obj) {
+ return;
+ }
+ _selectedObjectNum = _inventoryObjectsList[obj];
+ _selectedObjectType = 3;
+ switch (_selectedObjectNum) {
+ case 30:
+ if (_skipPanelObjectUnderCursor == 1 && _leftMouseButtonPressed) {
+ _selectedObjectType = 0;
+ _selectedObjectNum = 0;
+ _actionVerb = 0;
+ _skipPanelObjectUnderCursor = 0;
+ _forceRedrawPanelItems = 1;
+ _panelState = 2;
+ setCursorType(1);
+ }
+ break;
+ case 1:
+ if (_actionVerb == 8 && _leftMouseButtonPressed) {
+ if (_mapSequenceFlagsLocationTable[_locationNum - 1] == 1) {
+ handleMapSequence();
+ } else {
+ _actionPosX = _xPosCurrent;
+ _actionPosY = _yPosCurrent - 64;
+ _actionTextColor = 1;
+ _actionCharacterNum = 99;
+ setCursorType(2);
+ _charSpeechSoundCounter = kDefaultCharSpeechSoundCounter;
+ _updateCharPositionNewType = 0;
+ _speechSoundNum = 2235;
+ startSpeechSound(_speechSoundNum, _speechVolume);
+ _characterSpeechDataPtr = _ptTextBuf + getPositionForLine(_speechSoundNum, _ptTextBuf);
+ _speechSoundNum = 0;
+ _actionVerb = 0;
+ _selectedObjectType = 0;
+ _selectedObjectNum = 0;
+ _skipPanelObjectUnderCursor = 0;
+ }
+ }
+ break;
+ }
+}
+
+int TuckerEngine::setCharacterUnderCursor() {
+ if (_mousePosY > 140) {
+ return -1;
+ }
+ for (int i = 0; i < _charPosCount; ++i) {
+ if (_mousePosX + _scrollOffset <= _charPosTable[i].xPos) {
+ continue;
+ }
+ if (_mousePosX + _scrollOffset >= _charPosTable[i].xPos + _charPosTable[i].xSize) {
+ continue;
+ }
+ if (_mousePosY <= _charPosTable[i].yPos) {
+ continue;
+ }
+ if (_mousePosY >= _charPosTable[i].yPos + _charPosTable[i].ySize) {
+ continue;
+ }
+ if (_charPosTable[i].flagNum == 0 || _flagsTable[_charPosTable[i].flagNum] == _charPosTable[i].flagValue) {
+ _selectedObjectType = 2;
+ _selectedCharacterDirection = _charPosTable[i].direction;
+ _selectedCharacterNum = i;
+ return _charPosTable[i].name;
+ }
+ }
+ return -1;
+}
+
+int TuckerEngine::setLocationAnimationUnderCursor() {
+ if (_mousePosY > 140) {
+ return -1;
+ }
+ for (int i = _locationAnimationsCount - 1; i >= 0; --i) {
+ if (_locationAnimationsTable[i].drawFlag == 0) {
+ continue;
+ }
+ int num = _locationAnimationsTable[i].graphicNum;
+ if (_mousePosX + _scrollOffset + 1 <= _dataTable[num].xDest) {
+ continue;
+ }
+ if (_mousePosX + _scrollOffset >= _dataTable[num].xDest + _dataTable[num].xSize) {
+ continue;
+ }
+ if (_mousePosY <= _dataTable[num].yDest) {
+ continue;
+ }
+ if (_mousePosY >= _dataTable[num].yDest + _dataTable[num].ySize) {
+ continue;
+ }
+ if (_locationAnimationsTable[i].selectable == 0) {
+ return -1;
+ }
+ _selectedObjectType = 1;
+ _selectedCharacterNum = i;
+ _selectedCharacter2Num = i;
+ return _locationAnimationsTable[i].selectable;
+ }
+ return -1;
+}
+
+void TuckerEngine::setActionForInventoryObject() {
+ if (_actionVerb == 0 || _actionVerb == 2 || _actionVerb == 6 || _actionVerb == 7) {
+ playSpeechForAction(_actionVerb);
+ _skipPanelObjectUnderCursor = 0;
+ _actionRequiresTwoObjects = false;
+ return;
+ }
+ if (_actionVerb == 3 || _actionVerb == 4) {
+ if (!(_partNum == 2 && _selectedObjectNum == 19) && !(_partNum == 3 && _selectedObjectNum == 42)) {
+ playSpeechForAction(_actionVerb);
+ _skipPanelObjectUnderCursor = 0;
+ _actionRequiresTwoObjects = false;
+ return;
+ }
+ }
+ _currentActionObj1Num = _actionObj1Num;
+ _currentInfoString1SourceType = _actionObj1Type;
+ _currentActionObj2Num = _actionObj2Num;
+ _currentInfoString2SourceType = _actionObj2Type;
+ if (_actionVerb == 1 && _selectedObjectType == 3) {
+ if (_panelLockedFlag == 1) {
+ if (_locationMaskType != 0) {
+ return;
+ }
+ _panelLockedFlag = 0;
+ }
+ if (handleSpecialObjectSelectionSequence() == 1) {
+ return;
+ }
+ _speechSoundNum = _actionObj1Num + _speechSoundBaseNum;
+ startSpeechSound(_speechSoundNum, _speechVolume);
+ _characterSpeechDataPtr = _ptTextBuf + getPositionForLine(_speechSoundNum, _ptTextBuf);
+ _speechSoundNum = 0;
+ _actionPosX = _xPosCurrent;
+ _actionPosY = _yPosCurrent - 64;
+ _actionTextColor = 1;
+ _actionCharacterNum = 99;
+ setCursorType(2);
+ _charSpeechSoundCounter = kDefaultCharSpeechSoundCounter;
+ _skipPanelObjectUnderCursor = 0;
+ _actionRequiresTwoObjects = false;
+ return;
+ }
+ if ((_partNum == 3 && (_actionObj1Num == 6 || _actionObj1Num == 3 || _actionObj1Num == 17)) ||
+ (_partNum == 2 && _actionObj1Num == 19) ||
+ (_partNum == 3 && (_actionObj1Num == 42 && _selectedObjectNum == 18)) ) {
+ _skipPanelObjectUnderCursor = 0;
+ _actionRequiresTwoObjects = false;
+ _locationMaskCounter = 1;
+ setActionState();
+ return;
+ }
+ if (!_actionRequiresTwoObjects) {
+ _actionRequiresTwoObjects = true;
+ } else {
+ _skipPanelObjectUnderCursor = 0;
+ _actionRequiresTwoObjects = false;
+ _locationMaskCounter = 1;
+ setActionState();
+ }
+}
+
+void TuckerEngine::setActionState() {
+ _updateCharPositionNewType = (_actionVerb == 0) ? 8 : _actionVerb;
+ _currentActionObj1Num = _actionObj1Num;
+ _currentInfoString1SourceType = _actionObj1Type;
+ _currentActionObj2Num = _actionObj2Num;
+ _currentInfoString2SourceType = _actionObj2Type;
+ _actionRequiresTwoObjects = false;
+ if (_selectedObjectType < 3) {
+ setSelectedObjectKey();
+ }
+}
+
+void TuckerEngine::playSpeechForAction(int i) {
+ static const int speechActionTable[] = { 0, 2235, 2235, 2251, 2261, 2276, 2294, 2312, 2235 };
+ static const int maxCounterTable[] = { 0, 1, 13, 7, 12, 15, 15, 15, 14 };
+ ++_speechActionCounterTable[i];
+ if (_speechActionCounterTable[i] > maxCounterTable[i]) {
+ _speechActionCounterTable[i] = 0;
+ }
+ if (speechActionTable[i] >= 2000) {
+ if (_updateCharPositionNewType == 8 && _currentActionObj1Num == 6 && _currentInfoString1SourceType == 3) {
+ _speechSoundNum = 2395;
+ } else {
+ _speechSoundNum = _speechActionCounterTable[i] + speechActionTable[i];
+ }
+ startSpeechSound(_speechSoundNum, _speechVolume);
+ _characterSpeechDataPtr = _ptTextBuf + getPositionForLine(_speechSoundNum, _ptTextBuf);
+ _speechSoundNum = 0;
+ _actionPosX = _xPosCurrent;
+ _actionPosY = _yPosCurrent - 64;
+ _actionTextColor = 1;
+ _actionCharacterNum = 99;
+ setCursorType(2);
+ _charSpeechSoundCounter = kDefaultCharSpeechSoundCounter;
+ }
+}
+
+void TuckerEngine::drawSpeechText(int xStart, int y, const uint8 *dataPtr, int num, int color) {
+ int x = (xStart - _scrollOffset) * 2;
+ int offset = (_scrollOffset + 320 - xStart) * 2;
+ if (_conversationOptionsCount > 0) {
+ x = 319;
+ } else {
+ if (x > offset) {
+ x = offset;
+ }
+ if (x > 180) {
+ x = 220;
+ } else if (x < 150) {
+ x = 220;
+ }
+ }
+ int count = 0;
+ int flag = 0;
+ struct {
+ int w, count, offset;
+ } lines[5];
+ lines[0].offset = getPositionForLine(num, dataPtr);
+ while (flag == 0 && count < 4) {
+ int lineCharsCount, lineWidth;
+ flag = splitSpeechTextLines(dataPtr, lines[count].offset, x, lineCharsCount, lineWidth);
+ lines[count].w = lineWidth;
+ lines[count].count = lineCharsCount;
+ lines[count + 1].offset = lines[count].offset + lineCharsCount + 1;
+ ++count;
+ }
+ if (count * 10 > y) {
+ y = count * 10;
+ }
+ for (int i = 0; i < count; ++i) {
+ int dstOffset = xStart - lines[i].w / 2;
+ if (dstOffset < _scrollOffset) {
+ dstOffset = _scrollOffset;
+ } else if (lines[i].w > _scrollOffset + 320) {
+ dstOffset = _scrollOffset + 320 - lines[i].w;
+ }
+ uint8 *dst;
+ if (_conversationOptionsCount) {
+ dstOffset = xStart + _scrollOffset;
+ dst = (i * 10 + y) * 640 + _locationBackgroundGfxBuf + dstOffset;
+ _panelItemWidth = count; // ?
+ } else {
+ dst = (y - (count - i) * 10) * 640 + _locationBackgroundGfxBuf + dstOffset;
+ }
+ drawSpeechTextLine(dataPtr, lines[i].offset, lines[i].count, dst, color);
+ }
+}
+
+int TuckerEngine::splitSpeechTextLines(const uint8 *dataPtr, int pos, int x, int &lineCharsCount, int &lineWidth) {
+ int count = 0;
+ int w = 0;
+ lineCharsCount = 0;
+ lineWidth = 0;
+ while (x + 1 > w && dataPtr[pos] != '\n' && dataPtr[pos] != '\r') {
+ if (dataPtr[pos] == ' ') {
+ lineCharsCount = count;
+ lineWidth = w;
+ }
+ w += _charWidthTable[dataPtr[pos]];
+ ++count;
+ ++pos;
+ }
+ int ret = 0;
+ if (x + 1 > w) {
+ lineCharsCount = count;
+ lineWidth = w;
+ ret = 1;
+ }
+ return ret;
+}
+
+void TuckerEngine::drawSpeechTextLine(const uint8 *dataPtr, int pos, int count, uint8 *dst, uint8 color) {
+ while (count > 0 && dataPtr[pos] != '\n') {
+ Graphics::drawStringChar(dst, dataPtr[pos], 640, color, _charsetGfxBuf);
+ dst += _charWidthTable[dataPtr[pos]];
+ ++pos;
+ --count;
+ }
+}
+
+} // namespace Tucker