From 4a5d4ba94dd6320e137cde6ba27744613d2a1099 Mon Sep 17 00:00:00 2001 From: Gregory Montoir Date: Mon, 10 Nov 2008 20:38:54 +0000 Subject: add initial support for 'Bud Tucker in Double Trouble' svn-id: r34990 --- base/plugins.cpp | 3 + configure | 1 + engines/engines.mk | 5 + engines/tucker/detection.cpp | 88 + engines/tucker/graphics.cpp | 258 +++ engines/tucker/graphics.h | 64 + engines/tucker/locations.cpp | 3207 +++++++++++++++++++++++++++++++++++ engines/tucker/module.mk | 19 + engines/tucker/resource.cpp | 959 +++++++++++ engines/tucker/saveload.cpp | 116 ++ engines/tucker/sequences.cpp | 480 ++++++ engines/tucker/staticres.cpp | 219 +++ engines/tucker/tucker.cpp | 3778 ++++++++++++++++++++++++++++++++++++++++++ engines/tucker/tucker.h | 802 +++++++++ 14 files changed, 9999 insertions(+) create mode 100644 engines/tucker/detection.cpp create mode 100644 engines/tucker/graphics.cpp create mode 100644 engines/tucker/graphics.h create mode 100644 engines/tucker/locations.cpp create mode 100644 engines/tucker/module.mk create mode 100644 engines/tucker/resource.cpp create mode 100644 engines/tucker/saveload.cpp create mode 100644 engines/tucker/sequences.cpp create mode 100644 engines/tucker/staticres.cpp create mode 100644 engines/tucker/tucker.cpp create mode 100644 engines/tucker/tucker.h diff --git a/base/plugins.cpp b/base/plugins.cpp index 5429359658..cd91bed292 100644 --- a/base/plugins.cpp +++ b/base/plugins.cpp @@ -147,6 +147,9 @@ public: #if PLUGIN_ENABLED_STATIC(TOUCHE) LINK_PLUGIN(TOUCHE) #endif + #if PLUGIN_ENABLED_STATIC(TUCKER) + LINK_PLUGIN(TUCKER) + #endif // Music plugins // TODO: Use defines to disable or enable each MIDI driver as a diff --git a/configure b/configure index c54a955deb..8a08e89138 100755 --- a/configure +++ b/configure @@ -102,6 +102,7 @@ add_engine sword1 "Broken Sword 1" yes add_engine sword2 "Broken Sword 2" yes add_engine tinsel "Tinsel" no add_engine touche "Touche: The Adventures of the Fifth Musketeer" yes +add_engine tucker "Bud Tucker in Double Trouble" no _endian=unknown _need_memalign=no diff --git a/engines/engines.mk b/engines/engines.mk index 4dba913173..5115ac69aa 100644 --- a/engines/engines.mk +++ b/engines/engines.mk @@ -106,3 +106,8 @@ ifdef ENABLE_TOUCHE DEFINES += -DENABLE_TOUCHE=$(ENABLE_TOUCHE) MODULES += engines/touche endif + +ifdef ENABLE_TUCKER +DEFINES += -DENABLE_TUCKER=$(ENABLE_TUCKER) +MODULES += engines/tucker +endif diff --git a/engines/tucker/detection.cpp b/engines/tucker/detection.cpp new file mode 100644 index 0000000000..931e006fdb --- /dev/null +++ b/engines/tucker/detection.cpp @@ -0,0 +1,88 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "common/config-manager.h" +#include "common/advancedDetector.h" +#include "common/savefile.h" +#include "common/system.h" + +#include "base/plugins.h" + +#include "tucker/tucker.h" + +static const PlainGameDescriptor tuckerGames[] = { + { "tucker", "Bud Tucker in Double Trouble" }, + { 0, 0 } +}; + +static const Common::ADGameDescription tuckerGameDescriptions[] = { + { + "tucker", + "", + AD_ENTRY1s("infobar.txt", "f1e42a95972643462b9c3c2ea79d6683", 543), + Common::FR_FRA, + Common::kPlatformPC, + Common::ADGF_NO_FLAGS + }, + AD_TABLE_END_MARKER +}; + +static const Common::ADParams detectionParams = { + (const byte *)tuckerGameDescriptions, + sizeof(Common::ADGameDescription), + 512, + tuckerGames, + 0, + "tucker", + 0, + 0 +}; + +class TuckerMetaEngine : public Common::AdvancedMetaEngine { +public: + TuckerMetaEngine() : Common::AdvancedMetaEngine(detectionParams) { + } + + virtual const char *getName() const { + return "Tucker Engine"; + } + + virtual const char *getCopyright() const { + return "Bud Tucker in Double Trouble (C) Merit Studios"; + } + + virtual bool createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const { + if (desc) { + *engine = new Tucker::TuckerEngine(syst, desc->language); + } + return desc != 0; + } +}; + +#if PLUGIN_ENABLED_DYNAMIC(TUCKER) + REGISTER_PLUGIN_DYNAMIC(TUCKER, PLUGIN_TYPE_ENGINE, TuckerMetaEngine); +#else + REGISTER_PLUGIN_STATIC(TUCKER, PLUGIN_TYPE_ENGINE, TuckerMetaEngine); +#endif diff --git a/engines/tucker/graphics.cpp b/engines/tucker/graphics.cpp new file mode 100644 index 0000000000..4498f553bb --- /dev/null +++ b/engines/tucker/graphics.cpp @@ -0,0 +1,258 @@ +/* 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 "tucker/graphics.h" + +namespace Tucker { + +int Graphics::encodeRLE(const uint8 *src, uint8 *dst, int w, int h) { + int count = 0; + int dstOffset = 0; + int code = 0; + for (int y = 0; y < h; ++y) { + for (int x = 0; x < w; ++x) { + code = src[x]; + if (code == 0) { + ++count; + if (count > 200) { + dst[dstOffset++] = 0; + dst[dstOffset++] = count; + count = 0; + } + } else { + if (count > 0) { + dst[dstOffset++] = 0; + dst[dstOffset++] = count; + count = 0; + } + dst[dstOffset++] = code; + } + } + src += 320; + } + if (count > 0) { + dst[dstOffset++] = 0; + dst[dstOffset++] = count; + } + return dstOffset; +} + +int Graphics::encodeRAW(const uint8 *src, uint8 *dst, int w, int h) { + for (int y = 0; y < h; ++y) { + memcpy(dst, src, w); + dst += w; + src += 320; + } + return w * h; +} + +void Graphics::decodeRLE(uint8 *dst, const uint8 *src, int w, int h) { + int code = 0; + int offset = 0; + int color = 0; + for (int y = 0; y < h; ++y) { + for (int x = 0; x < w; ++x) { + if (code == 0) { + color = src[offset++]; + if (color == 0) { + code = src[offset++]; + --code; + if (x + code < w) { + x += code; + code = 0; + } else { + code -= w - 1 - x; + x = w - 1; + } + } + } else { + --code; + if (x + code < w) { + x += code; + code = 0; + } else { + code -= w - 1 - x; + x = w - 1; + } + } + if (color != 0) { + dst[x] = color; + } + } + dst += 640; + } +} + +void Graphics::decodeRLE_224(uint8 *dst, const uint8 *src, int w, int h) { + int code = 0; + int offset = 0; + int color = 0; + for (int y = 0; y < h; ++y) { + for (int x = 0; x < w; ++x) { + if (code == 0) { + color = src[offset++]; + if (color != 0) { + if (dst[x] < 0xE0) { + dst[x] = color; + } + } else { + code = src[offset++]; + --code; + if (x + code < w) { + x += code; + code = 0; + } else { + code -= w - 1 - x; + x = w - 1; + } + } + } else { + --code; + if (x + code < w) { + x += code; + code = 0; + } else { + code -= w - 1 - x; + x = w - 1; + } + } + } + dst += 640; + } +} + +void Graphics::decodeRLE_248(uint8 *dst, const uint8 *src, int w, int h, int y1, int y2, bool xflip) { + int code = 0; + int offset = 0; + int color = 0; + int dstOffset = 0; + for (int y = 0; y < h; ++y) { + for (int x = 0; x < w; ++x) { + dstOffset = xflip ? (w - 1 - x) : x; + if (code == 0) { + color = src[offset++]; + if (color == 0) { + code = src[offset++]; + --code; + if (x + code < w) { + x += code; + code = 0; + } else { + code -= w - 1 - x; + x = w - 1; + } + } + } else { + --code; + if (x + code < w) { + x += code; + code = 0; + } else { + code -= w - 1 - x; + x = w - 1; + } + } + if (color != 0) { + if ((dst[dstOffset] < 0xE0 || y + y1 < y2) && dst[dstOffset] < 0xF8) { + dst[dstOffset] = color; + } + } + } + dst += 640; + } +} + +void Graphics::decodeRLE_320(uint8 *dst, const uint8 *src, int w, int h) { + int code = 0; + int offset = 0; + int color = 0; + for (int y = 0; y < h; ++y) { + for (int x = 0; x < w; ++x) { + if (code == 0) { + color = src[offset++]; + if (color == 0) { + code = src[offset++]; + } + } + if (code == 0) { + dst[x] = color; + } else { + --code; + } + } + dst += 320; + } +} + +void Graphics::copyFrom640(const uint8 *src, uint8 *dst, int w, int h) { + for (int y = 0; y < h; ++y) { + memcpy(dst, src, w); + dst += w; + src += 640; + } +} + +void Graphics::copyTo640(uint8 *dst, const uint8 *src, int w, int srcPitch, int h) { + for (int y = 0; y < h; ++y) { + memcpy(dst, src, w); + dst += 640; + src += srcPitch; + } +} + +void Graphics::drawStringChar(uint8 *dst, uint8 chr, int pitch, uint8 chrColor, const uint8 *src) { + if (chr < 32 || chr - 32 >= kCharSet1CharsCount) { + return; + } + int offset = (chr - 32) * kCharSet1CharSize; + for (int y = 0; y < kCharSet1CharH; ++y) { + for (int x = 0; x < kCharSet1CharW; ++x) { + const int color = src[offset++]; + if (color != 0) { + dst[x] = (color == 128) ? color : chrColor; + } + } + dst += pitch; + } +} + +void Graphics::drawStringChar2(uint8 *dst, uint8 chr, int pitch, uint8 chrColor, const uint8 *src) { + if (chr < 32 || chr - 32 >= kCharSet2CharsCount) { + return; + } + int offset = (chr - 32) * kCharSet2CharSize; + for (int y = 0; y < kCharSet2CharH; ++y) { + for (int x = 0; x < kCharSet2CharW; ++x) { + const int color = src[offset++]; + if (color != 0) { + dst[x] = color; + } + } + dst += pitch; + } +} + + +} // namespace Tucker diff --git a/engines/tucker/graphics.h b/engines/tucker/graphics.h new file mode 100644 index 0000000000..c04ddc8b67 --- /dev/null +++ b/engines/tucker/graphics.h @@ -0,0 +1,64 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef TUCKER_GRAPHICS_H__ +#define TUCKER_GRAPHICS_H__ + +#include "common/util.h" + +namespace Tucker { + +enum { + kCharSet1CharW = 10, + kCharSet1CharH = 10, + kCharSet1CharSize = kCharSet1CharW * kCharSet1CharH, + kCharSet1CharsCount = 32 * 7, + kCharSet2CharW = 19, + kCharSet2CharH = 10, + kCharSet2CharSize = kCharSet2CharW * kCharSet2CharH, + kCharSet2CharsCount = 16 * 6 +}; + +class Graphics { +public: + + static int encodeRLE(const uint8 *src, uint8 *dst, int w, int h); + static int encodeRAW(const uint8 *src, uint8 *dst, int w, int h); + + static void decodeRLE(uint8 *dst, const uint8 *src, int w, int h); + static void decodeRLE_224(uint8 *dst, const uint8 *src, int w, int h); + static void decodeRLE_248(uint8 *dst, const uint8 *src, int w, int h, int y1, int y2, bool xflip); + static void decodeRLE_320(uint8 *dst, const uint8 *src, int w, int h); + + static void copyFrom640(const uint8 *src, uint8 *dst, int w, int h); + static void copyTo640(uint8 *dst, const uint8 *src, int w, int srcPitch, int h); + + static void drawStringChar(uint8 *dst, uint8 chr, int pitch, uint8 chrColor, const uint8 *src); + static void drawStringChar2(uint8 *dst, uint8 chr, int pitch, uint8 chrColor, const uint8 *src); +}; + +} // namespace Tucker + +#endif diff --git a/engines/tucker/locations.cpp b/engines/tucker/locations.cpp new file mode 100644 index 0000000000..92d4f68038 --- /dev/null +++ b/engines/tucker/locations.cpp @@ -0,0 +1,3207 @@ +/* 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 "tucker/tucker.h" +#include "tucker/graphics.h" + +namespace Tucker { + +static const int _data3UpdateLocation1_xTable[] = { 287, 120, 61 }; +static const int _data3UpdateLocation1_yTable[] = { 152, 8, 95 }; + +void TuckerEngine::execData3PreUpdate_locationNum1() { + if (_flagsTable[1] == 1) { + _flagsTable[1] = 2; + _locationSoundsTable[3].type = 2; + startSound(_locationSoundsTable[3].offset, 3, _locationSoundsTable[3].volume); + } + _mapSequenceFlagsLocationTable[0] = (_flagsTable[1] > 0) ? 1 : 0; + if (_updateLocationCounter == 0) { + execData3PreUpdate_locationNum1Helper1(); + execData3PreUpdate_locationNum1Helper2(); + } else { + --_updateLocationCounter; + if (_updateLocationCounter == 0) { + ++_updateLocationPos; + if (_updateLocationPos > 1) { + _updateLocationPos = 0; + } + for (int i = 0; i < 5; ++i) { + _updateLocationXPosTable[i] = _data3UpdateLocation1_xTable[_updateLocationPos]; + _updateLocationYPosTable[i] = _data3UpdateLocation1_yTable[_updateLocationPos]; + _updateLocationFlagsTable[i] = 0; + } + } + } +} + +void TuckerEngine::execData3PreUpdate_locationNum1Helper1() { + int code = 0; + if (_updateLocationXPosTable[0] > 0 && _updateLocationYPosTable[0] > 0) { + for (int i = 4; i > 0; --i) { + _updateLocationXPosTable[i] = _updateLocationXPosTable[i - 1]; + _updateLocationYPosTable[i] = _updateLocationYPosTable[i - 1]; + _updateLocationFlagsTable[i] = _updateLocationFlagsTable[i - 1]; + } + } + if (_updateLocationFlagsTable[0] == 1 && _updateLocationCounter == 0) { + setVolumeSound(12, _locationSoundsTable[12].volume); + } else { + setVolumeSound(12, 0); + } + static const int dxTable[] = { 0, -1, -1, -1, 0, 1, 1, 1 }; + static const int dyTable[] = { -1, -1, 0, 1, 1, 1, 0, -1 }; + for (int i = 0; code == 0 && i < 8; ++i) { + code = execData3PreUpdate_locationNum1Helper3(dxTable[i], dyTable[i]); + } + _updateLocationFlagsTable[0] = code; +} + +void TuckerEngine::execData3PreUpdate_locationNum1Helper2() { + static const int dxTable[] = { -95, 84, 110 }; + static const int dyTable[] = { -50, 46, 0 }; + int xPos = 0; + int yPos = 0; + for (int i = 0; i < 6; i += 2) { + if (_updateLocationFlagsTable[i] == 1) { + xPos = _updateLocationXPosTable[i] + dxTable[_updateLocationPos]; + yPos = _updateLocationYPosTable[i] + dyTable[_updateLocationPos]; + } + if (xPos > 319 || yPos > 199 || xPos < 0 || yPos < 0) { + xPos = 0; + yPos = 0; + } + _locationBackgroundGfxBuf[yPos * 640 + xPos] = 100; + } +} + +int TuckerEngine::execData3PreUpdate_locationNum1Helper3(int dx, int dy) { + static const int counterTable[3] = { 30, 50, 70 }; + const int xPos = _updateLocationXPosTable[0] + dx; + const int yPos = _updateLocationYPosTable[0] + dy; + static const int num[] = { 2, 3, 4, 1 }; + for (int i = 0; i < 4; ++i) { + if (xPos == _updateLocationXPosTable[num[i]] && yPos == _updateLocationYPosTable[num[i]]) { + return 0; + } + } + const int code = (int8)_loadLocBufPtr[yPos * 320 + xPos]; + if (code > 0) { + _updateLocationXPosTable[0] = xPos; + _updateLocationYPosTable[0] = yPos; + if (xPos == _data3UpdateLocation1_xTable[_updateLocationPos] && yPos == _data3UpdateLocation1_yTable[_updateLocationPos]) { + _updateLocationCounter = counterTable[_updateLocationPos]; + } + } + return code; +} + +void TuckerEngine::execData3PostUpdate_locationNum1() { + if (_flagsTable[63] == 0) { + if (getRandomNumber() < 400) { + _flagsTable[63] = 1; + startSound(_locationSoundsTable[2].offset, 2, _locationSoundsTable[2].volume); + } + } + _locationHeightTable[1] = (_yPosCurrent > 104) ? 60 : 0; +} + +void TuckerEngine::updateSprite_locationNum2() { + if (_flagsTable[9] == 2) { + _spritesTable[0].state = -1; + return; + } + if (_flagsTable[9] == 1) { + if (_flagsTable[10] == 1) { + _spritesTable[0].state = -1; + } else if (_charSpeechSoundCounter > 0 && _actionCharacterNum == 0) { + _spritesTable[0].state = 4; + _spritesTable[0].needUpdate = 1; + } else { + _spritesTable[0].needUpdate = 0; + _spritesTable[0].state = 5; + _flagsTable[10] = 1; + _spritesTable[0].gfxBackgroundOffset = 0; + } + return; + } + if (_charSpeechSoundCounter > 0 && _actionCharacterNum == 0) { + _spritesTable[0].state = 3; + _spritesTable[0].needUpdate = 1; + return; + } + if (_csDataHandled != 0) { + _spritesTable[0].needUpdate = 0; + if (_flagsTable[199] == 0) { + _flagsTable[199] = 1; + setCharacterAnimation(0, 0); + } else if (getRandomNumber() > 20000) { + _spritesTable[0].state = 6; + } else { + _spritesTable[0].state = 3; + _spritesTable[0].updateDelay = 5; + } + } else { + if (_flagsTable[199] == 0) { + _flagsTable[199] = 1; + setCharacterAnimation(1, 0); + } else if (getRandomNumber() < 20000) { + _spritesTable[0].state = 1; + _spritesTable[0].updateDelay = 5; + } else { + _spritesTable[0].state = 1; + } + } +} + +void TuckerEngine::execData3PreUpdate_locationNum2() { + static const int xPosTable[] = { 110, 117, 127, 146, 160, 183, 195, 210 }; + static const int yPosTable[] = { 50, 60, 60, 60, 50, 55, 50, 50 }; + static const int yMaxTable[] = { 100, 97, 94, 91, 89, 86, 83, 80 }; + if (_execData3Counter == 0) { + _execData3Counter = 1; + for (int i = 0; i < 3; ++i) { + _updateLocationYPosTable2[i] = 0; + } + if (_flagsTable[10] == 0) { + strcpy(_fileToLoad, "path02b.pcx"); + copyLocBitmap(0, 1); + } + for (int i = 0; i < 3; ++i) { + if (_updateLocationYPosTable2[i] > 0) { + for (int j = 0; j < 2; ++j) { + const int offset = (_updateLocationYPosTable2[i] + j) * 640 + _updateLocationXPosTable2[i]; + _locationBackgroundGfxBuf[offset] = 142 + j * 2; + } + _updateLocationYPosTable2[i] += 2; + if (_updateLocationYPosTable2[i] > _updateLocationYMaxTable[i]) { + _updateLocationYPosTable2[i] = 0; + const int num = (getRandomNumber() < 16000) ? 2 : 3; + startSound(_locationSoundsTable[num].offset, num, _locationSoundsTable[num].volume); + } + } else if (getRandomNumber() > 32000) { + const int num = getRandomNumber() / 8192; + _updateLocationXPosTable2[i] = xPosTable[num]; + _updateLocationYPosTable2[i] = yPosTable[num]; + _updateLocationYMaxTable[i] = yMaxTable[num]; + } + } + } + execData3PreUpdate_locationNum2Helper(); +} + +void TuckerEngine::execData3PreUpdate_locationNum2Helper() { + if (_fadePaletteCounter != 16) { + return; + } + int start, end; + if (_locationNum == 2) { + start = 116; + end = 125; + } else { + start = 215; + end = 223; + } + ++_updateLocationFadePaletteCounter; + if (_updateLocationFadePaletteCounter > 10 || _updateLocationFadePaletteCounter < 0) { + _updateLocationFadePaletteCounter = 0; + } + int step; + if (_updateLocationFadePaletteCounter < 6) { + step = _updateLocationFadePaletteCounter; + } else { + step = 10 - _updateLocationFadePaletteCounter; + } + for (int i = start; i < end; ++i) { + fadePaletteColor(i, step); + } +} + +void TuckerEngine::updateSprite_locationNum3_0(int i) { + int num; + if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + num = 5; + _spritesTable[i].needUpdate = 1; + } else if (_spritesTable[i].prevState == 5 && _spritesTable[i].animationFrame == 1) { + _spritesTable[i].needUpdate = 0; + int r = getRandomNumber(); + if (r < 12000) { + num = 3; + } else if (r < 24000) { + num = 1; + } else { + num = 2; + } + } else { + num = 5; + _spritesTable[i].animationFrame = 1; + _spritesTable[i].updateDelay = 10; + } + _spritesTable[i].state = num; + _spritesTable[i].prevAnimationFrame = 1; +} + +void TuckerEngine::updateSprite_locationNum3_1(int i) { + int num; + if (_flagsTable[207] == 1) { + num = -1; + } else if (_flagsTable[203] == 1) { + _spritesTable[i].needUpdate = 1; + num = 20; + _flagsTable[203] = 2; + } else if (_flagsTable[203] == 2) { + num = 12; + } else if (_flagsTable[203] == 3) { + _spritesTable[i].needUpdate = 0; + num = 19; + _flagsTable[203] = 0; + } else if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + _spritesTable[i].needUpdate = 1; + if (_flagsTable[21] == 0) { + num = 7; + } else { + num = 8; + } + } else { + _spritesTable[i].needUpdate = 0; + if (_csDataHandled != 0) { + num = 6; + if (getRandomNumber() < 32000) { + _spritesTable[i].updateDelay = 5; + } + } else if (_spritesTable[i].state == 6 && _spritesTable[i].animationFrame == 1) { + if (getRandomNumber() < 20000) { + num = 11; + _spritesTable[i].defaultUpdateDelay = 5; + } else { + num = 10; + } + } else { + num = 6; + _spritesTable[i].animationFrame = 1; + _spritesTable[i].updateDelay = 10; + } + } + _spritesTable[i].state = num; + _spritesTable[i].gfxBackgroundOffset = 320; +} + +void TuckerEngine::updateSprite_locationNum3_2(int i) { + int num; + if (_flagsTable[205] == 1) { + _flagsTable[205] = 0; + num = 18; + } else if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + _spritesTable[i].needUpdate = 1; + num = 17; + } else if (_flagsTable[45] == 1) { + _flagsTable[45] = 2; + num = 16; + } else if (_flagsTable[45] == 2) { + num = 17; + _spritesTable[i].updateDelay = 5; + _spritesTable[i].needUpdate = 0; + } else if (_flagsTable[45] == 3) { + _flagsTable[45] = 0; + num = 16; + _updateSpriteFlag2 = 1; + } else { + _spritesTable[i].needUpdate = 0; + ++_spritesTable[i].counter; + if (_spritesTable[i].counter <= 5) { + num = 14; + } else { + if (_spritesTable[i].counter > 8) { + _spritesTable[i].counter = 0; + } + num = 15; + } + } + _spritesTable[i].state = num; +} + +void TuckerEngine::execData3PreUpdate_locationNum3() { + execData3PreUpdate_locationNum2Helper(); + if (_flagsTable[7] == 0) { + _flagsTable[7] = 1; + } + if (_flagsTable[20] == 1 && _inventoryItemsState[7] == 1) { + _flagsTable[20] = 2; + } + if (_inventoryItemsState[19] == 1 && _flagsTable[54] == 1) { + _flagsTable[43] = 1; + } else { + _flagsTable[43] = 0; + } +} + +void TuckerEngine::updateSprite_locationNum4(int i) { + int flag = -1; + if (_flagsTable[9] == 2) { + if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + flag = 1; + _spritesTable[i].needUpdate = 1; + } else { + flag = 2; + _spritesTable[i].needUpdate = 0; + } + } + _spritesTable[i].state = -1; +} + +void TuckerEngine::execData3PreUpdate_locationNum4() { + if (_flagsTable[6] == 0) { + setVolumeSound(0, 0); + } else { + setVolumeSound(0, _locationSoundsTable[0].volume); + } +} + +void TuckerEngine::updateSprite_locationNum5_0() { + ++_spritesTable[0].counter; + if (_spritesTable[0].counter > 100) { + _spritesTable[0].counter = 0; + _spritesTable[0].state = 1; + _locationSoundsTable[1].type = 2; + startSound(_locationSoundsTable[1].offset, 1, _locationSoundsTable[1].volume); + } else if (_spritesTable[0].counter == 50) { + _locationSoundsTable[1].type = 2; + _spritesTable[0].state = 2; + startSound(_locationSoundsTable[1].offset, 1, _locationSoundsTable[1].volume); + } else { + _spritesTable[0].state = -1; + if (isSoundPlaying(1)) { + stopSound(1); + } + } +} + +void TuckerEngine::updateSprite_locationNum5_1(int i) { + _spritesTable[i].state = 3; +} + +void TuckerEngine::updateSprite_locationNum6_0(int i) { + int state; + if (_flagsTable[184] == 1) { + state = -1; + } else if (_flagsTable[26] > 0 && _flagsTable[26] < 4 && _flagsTable[27] > 0) { + state = 14; + } else if (_flagsTable[26] == 4 || _flagsTable[26] == 5) { + if (_charSpeechSoundCounter > 0 && _actionCharacterNum == 0) { + _spritesTable[0].needUpdate = 1; + state = 3; + _spritesTable[0].counter = 0; + } else if (_xPosCurrent < 370 && _flagsTable[26] == 4) { + state = 2; + } else if (_spritesTable[0].counter == 0) { + setCharacterAnimation(0, 0); + _updateSpriteFlag1 = 1; + ++_spritesTable[0].counter; + return; + } else { + state = 1; + _spritesTable[0].updateDelay = 2; + ++_spritesTable[0].counter; + if (_spritesTable[0].counter > 100) { + _spritesTable[0].counter = 0; + } + } + } else { + state = -1; + } + _spritesTable[i].state = state; + _spritesTable[i].gfxBackgroundOffset = 320; +} + +void TuckerEngine::updateSprite_locationNum6_1(int i) { + int state; + if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + if (_flagsTable[209] == 1) { + state = 9; + _spritesTable[i].needUpdate = 1; + } else { + _spritesTable[i].needUpdate = 1; + state = 10; + } + } else { + if (getRandomNumber() < 30000 || (_csDataHandled && _xPosCurrent == 248)) { + _spritesTable[i].needUpdate = 0; + state = 7; + _spritesTable[i].updateDelay = 5; + } else { + _spritesTable[i].needUpdate = 0; + state = 7; + _soundsMapTable[0] = 3; + _miscSoundFxDelayCounter[0] = 70; +// _miscSoundFxDelayCounter[-1] = 4; + _miscSoundFxDelayCounter[1] = 25; + } + } + _spritesTable[i].state = state; +} + +void TuckerEngine::updateSprite_locationNum6_2(int i) { + int state; + if (_flagsTable[26] < 5 || _flagsTable[207] > 0) { + state = -1; + } else if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + _spritesTable[i].needUpdate = 1; + state = 12; + } else { + state = 12; + _spritesTable[i].updateDelay = 2; + } + _spritesTable[i].state = state; +} + +void TuckerEngine::execData3PreUpdate_locationNum6() { + if (_flagsTable[26] > 3) { + execData3PreUpdate_locationNum6Helper1(); + } + if (_flagsTable[26] == 2) { + _currentSpriteAnimationLength = 2; + _currentSpriteAnimationFrame = 112; + if (_spritesTable[0].xSource < 45) { + _currentSpriteAnimationFrame2 = 144; + } else if (_spritesTable[0].xSource > 80) { + _currentSpriteAnimationFrame2 = 147; + } else if (_spritesTable[0].xSource < 60) { + _currentSpriteAnimationFrame2 = 145; + } else { + _currentSpriteAnimationFrame2 = 146; + } + } +} + +void TuckerEngine::execData3PreUpdate_locationNum6Helper1() { + if (_mainLoopCounter1 < 2) { + if (_flagsTable[26] == 1) { + if (_flagsTable[27] < 15) { + if (_flagsTable[27] == 0) { + startSound(_locationSoundsTable[2].offset, 2, _locationSoundsTable[2].volume); + startSound(_locationSoundsTable[1].offset, 1, _locationSoundsTable[1].volume); + } + ++_flagsTable[27]; + setVolumeSound(0, _locationSoundsTable[0].volume - _flagsTable[27] * 5); + setVolumeMusic(0, _locationMusicsTable[0].volume - _flagsTable[27] * 5); + } + } else if (_flagsTable[26] == 3) { + if (_flagsTable[27] > 0) { + if (_flagsTable[27] == 15) { + startSound(_locationSoundsTable[2].offset, 2, _locationSoundsTable[2].volume); + } + --_flagsTable[27]; + setVolumeSound(0, _locationSoundsTable[0].volume - _flagsTable[27] * 5); + setVolumeMusic(0, _locationMusicsTable[0].volume - _flagsTable[27] * 5); + int volume = _flagsTable[27]; + if (volume < _locationSoundsTable[1].volume) { + volume = _locationSoundsTable[1].volume; + } + setVolumeSound(1, volume); + } + } + } + int x1, x2; + switch (_flagsTable[27]) { + case 0: + x1 = 8; + x2 = 0; + break; + case 15: + x1 = 1; + x2 = 0; + break; + case 8: + x1 = _flagsTable[27]; + x2 = _flagsTable[27]; + break; + default: + x1 = 1; + x2 = 15 - _flagsTable[27]; + break; + } + for (int i = 0; i < x1; ++i) { + execData3PreUpdate_locationNum6Helper2(_locationBackgroundGfxBuf + 13125 + i * 8, _data3GfxBuf + _dataTable[238].sourceOffset); + execData3PreUpdate_locationNum6Helper2(_locationBackgroundGfxBuf + 13245 - i * 8, _data3GfxBuf + _dataTable[238].sourceOffset); + } + for (int i = 0; i < x2; ++i) { + execData3PreUpdate_locationNum6Helper2(_locationBackgroundGfxBuf + 13125 + x1 * 8 + i * 2, _data3GfxBuf + _dataTable[238].sourceOffset); + execData3PreUpdate_locationNum6Helper2(_locationBackgroundGfxBuf + 13249 - x1 * 8 - i * 2, _data3GfxBuf + _dataTable[238].sourceOffset); + } +} + +void TuckerEngine::execData3PreUpdate_locationNum6Helper2(uint8 *dst, const uint8 *src) { + for (int j = 0; j < 46; ++j) { + memcpy(dst + j * 640, src + j * 8, 8); + } + for (int j = 46; j < 51; ++j) { + for (int i = 0; i < 8; ++i) { + const int offset = j * 640 + i; + uint8 color = dst[offset]; + if (color < 224) { + dst[offset] = src[j * 8 + i]; + } + } + } +} + +void TuckerEngine::execData3PreUpdate_locationNum6Helper3(uint8 *dst, const uint8 *src) { + for (int j = 0; j < 51; ++j) { + for (int i = 0; i < 4; ++i) { + const int offset = j * 640 + i; + uint8 color = dst[offset]; + if (color < 224) { + dst[offset] = src[j * 8 + i * 2]; + } + } + } +} + +void TuckerEngine::updateSprite_locationNum7_0(int i) { + int state; + ++_spritesTable[i].counter; + if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + _spritesTable[i].needUpdate = 1; + state = 4; + } else { + _spritesTable[i].needUpdate = 0; + if (_spritesTable[i].counter > 0) { + state = 2; + _spritesTable[i].counter = 0; + } else { + state = 1; + } + } + _spritesTable[i].state = state; +} + +void TuckerEngine::updateSprite_locationNum7_1(int i) { + int state; + if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + _spritesTable[i].needUpdate = 1; + state = 5; + } else { + _spritesTable[i].needUpdate = 0; + state = 5; + _spritesTable[i].updateDelay = 5; + } + _spritesTable[i].state = state; +} + +void TuckerEngine::updateSprite_locationNum8_0(int i) { + _spritesTable[i].state = (_flagsTable[28] < 20) ? -1 : 7; +} + +void TuckerEngine::updateSprite_locationNum8_1(int i) { + int state; + if (_flagsTable[207] == 1) { + state = -1; + } else if (_flagsTable[28] == 18) { + state = 6; + _spritesTable[i].needUpdate = 0; + } else if (_flagsTable[29] == 0) { + state = 1; + } else if (_charSpeechSoundCounter > 0 && _actionCharacterNum == 1) { + _spritesTable[i].needUpdate = 1; + state = 5; + } else { + _spritesTable[i].needUpdate = 0; + state = 3; + } + if (_flagsTable[28] == 19) { + _flagsTable[28] = 20; + } + _spritesTable[i].state = state; +} + +void TuckerEngine::execData3PostUpdate_locationNum8() { + if (_execData3Counter == 0) { + _updateLocationYPosTable2[0] = 0; + } + if (_updateLocationYPosTable2[0] == 0) { + ++_execData3Counter; + if (_execData3Counter > 30) { + _updateLocationYPosTable2[0] = 16; + _updateLocationXPosTable2[0] = 264; + + } + } + if (_updateLocationYPosTable2[0] > 0) { + const int offset = _updateLocationYPosTable2[0] * 640 + _updateLocationXPosTable2[0]; + _locationBackgroundGfxBuf[offset] = 142; + _locationBackgroundGfxBuf[offset + 0x27F] = 143; + _locationBackgroundGfxBuf[offset + 0x280] = 143; + _locationBackgroundGfxBuf[offset + 0x281] = 144; + _locationBackgroundGfxBuf[offset + 0x4FF] = 144; + _locationBackgroundGfxBuf[offset + 0x500] = 144; + _locationBackgroundGfxBuf[offset + 0x501] = 145; + _locationBackgroundGfxBuf[offset + 0x77F] = 147; + _locationBackgroundGfxBuf[offset + 0x780] = 143; + _locationBackgroundGfxBuf[offset + 0x781] = 147; + _updateLocationYPosTable2[0] += 2; + if (_updateLocationYPosTable2[0] > 120) { + _updateLocationYPosTable2[0] = 0; + startSound(_locationSoundsTable[2].offset, 2, _locationSoundsTable[2].volume); + } + } + if (_flagsTable[28] > 1 && _flagsTable[28] < 5) { + _locationHeightTable[8] = 60; + } else { + _locationHeightTable[8] = 0; + } +} + +void TuckerEngine::updateSprite_locationNum9_0(int i) { + if (_charSpeechSoundCounter > 0 && _actionCharacterNum == 0) { + _spritesTable[0].needUpdate = 1; + _spritesTable[i].state = 3; + } else if (_updateLocationCounter2 > 0 || getRandomNumber() > 30000) { + _spritesTable[i].state = 1; + if (_updateLocationCounter2 == 0) { + _updateLocationCounter2 = 6; + } + } else if (getRandomNumber() > 30000) { + _spritesTable[i].state = 2; + _spritesTable[i].defaultUpdateDelay = 5; + } else { + _spritesTable[i].state = 1; + _spritesTable[i].animationFrame = 1; + _spritesTable[i].updateDelay = 10; + } +} + +void TuckerEngine::updateSprite_locationNum9_1(int i) { + ++_spritesTable[i].counter; + if (_spritesTable[i].counter > 10) { + _spritesTable[i].counter = 0; + _spritesTable[i].state = 5; + _spritesTable[i].defaultUpdateDelay = 5; + } else { + _spritesTable[i].state = 4; + } +} + +void TuckerEngine::updateSprite_locationNum9_2(int i) { + _spritesTable[i].state = 6; + _spritesTable[i].gfxBackgroundOffset = 320; +} + +void TuckerEngine::execData3PreUpdate_locationNum9() { + if (_flagsTable[7] < 2) { + _flagsTable[7] = 2; + } + if (_flagsTable[8] == 0 && _locationMusicsTable[0].volume != 0) { + _locationMusicsTable[0].volume = 0; + } else { + _locationMusicsTable[0].volume = _xPosCurrent / 40; + } + setVolumeMusic(0, _locationMusicsTable[0].volume); + if (!isSoundPlaying(1) && getRandomNumber() > 32000) { + int i = getRandomNumber() / 5500 + 3; + assert(i >= 0 && i < kLocationSoundsTableSize); + startSound(_locationSoundsTable[i].offset, i, _locationSoundsTable[i].volume); + } + if (_flagsTable[8] == 2 && _locationMaskType == 0) { + _flagsTable[8] = 0; + startSound(_locationSoundsTable[7].offset, 7, _locationSoundsTable[7].volume); + } +} + +void TuckerEngine::execData3PostUpdate_locationNum9() { + if (_spritesTable[1].state == 4) { + if (_spritesTable[1].flipX == 1) { + --_updateLocationXPosTable2[0]; + if (_updateLocationXPosTable2[0] < -50) { + _spritesTable[1].flipX = 0; + _updateLocationXPosTable2[0] = -50; + } + } else { + ++_updateLocationXPosTable2[0]; + if (_updateLocationXPosTable2[0] > 500) { + _spritesTable[1].flipX = 1; + _updateLocationXPosTable2[0] = 500; + } + } + } + _spritesTable[1].gfxBackgroundOffset = _updateLocationXPosTable2[0] + 8320; + for (int i = 1; i < 3; ++i) { + _spritesTable[i].colorType = 1; + _spritesTable[i].yMaxBackground = 60; + drawSprite(i); + _spritesTable[i].colorType = 0; + } +} + +void TuckerEngine::updateSprite_locationNum10() { + int state; + const int r = getRandomNumber(); + if (_flagsTable[99] == 1) { + state = -1; + } else if (_charSpeechSoundCounter > 0 && _actionCharacterNum == 0) { + _spritesTable[0].needUpdate = 1; + if (r < 26000) { + state = 1; + } else if (r < 29000) { + state = 2; + } else { + state = 3; + } + } else if (_csDataHandled) { + state = 2; + _spritesTable[0].updateDelay = 4; + } else { + _spritesTable[0].needUpdate = 0; + if (r > 26000) { + state = 5; + _spritesTable[0].prevAnimationFrame = 1; + } else if (r > 24000) { + state = 6; + _miscSoundFxDelayCounter[0] = 120; + _soundsMapTable[0] = 0; + } else { + setCharacterAnimation(0, 0); + } + } + _spritesTable[0].state = state; +} + +void TuckerEngine::execData3PreUpdate_locationNum10() { + if (_execData3Counter == 0) { + _execData3Counter = 1; + ++_flagsTable[68]; + if (_flagsTable[68] > 2) { + _flagsTable[68] = 0; + } + } + if (_flagsTable[47] == 1 && _inventoryItemsState[26] == 1) { + _flagsTable[47] = 2; + } + if (_spritesTable[0].state == 6 && _spritesTable[0].animationFrame == 18 && !isSoundPlaying(0)) { + startSound(_locationSoundsTable[0].offset, 0, _locationSoundsTable[0].volume); + } + if (_flagsTable[230] == 1 && getRandomNumber() > 32000) { + _flagsTable[230] = 0; + } +} + +void TuckerEngine::updateSprite_locationNum11_0(int i) { + const int r = getRandomNumber(); + if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + _spritesTable[i].needUpdate = 1; + _spritesTable[i].state = 2; + } else { + _spritesTable[i].needUpdate = 0; + if (r > 28000) { + _spritesTable[i].state = 3; + } else if (r > 20000) { + _spritesTable[i].state = 4; + } else { + _spritesTable[i].state = 3; + _spritesTable[i].animationFrame = 1; + _spritesTable[i].updateDelay = 5; + } + } +} + +void TuckerEngine::updateSprite_locationNum11_1(int i) { + if (getRandomNumber() > 20000) { + _spritesTable[i].state = 5; + } else { + _spritesTable[i].animationFrame = 14; + _updateSpriteFlag1 = 1; + _spritesTable[i].state = 5; + } +} + +void TuckerEngine::updateSprite_locationNum11_2(int i) { + if (getRandomNumber() > 20000) { + _spritesTable[i].state = 6; + } else { + _spritesTable[i].animationFrame = 17; + _spritesTable[i].state = 6; + _updateSpriteFlag1 = 1; + } +} + +void TuckerEngine::updateSprite_locationNum11_3(int i) { + _spritesTable[i].state = 7; +} + +void TuckerEngine::updateSprite_locationNum11_4(int i) { + if (getRandomNumber() > 30000 && _flagsTable[55] < 2) { + _spritesTable[i].state = 1; + startSound(_locationSoundsTable[6].offset, 6, _locationSoundsTable[6].volume); + } else { + _spritesTable[i].state = -1; + } +} + +void TuckerEngine::updateSprite_locationNum12_0(int i) { + ++_updateLocationCounter2; + if (_updateLocationCounter2 > 11) { + _updateLocationCounter2 = 0; + } + int state; + if (_flagsTable[207] > 0) { + state = -1; + } else if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + _spritesTable[i].needUpdate = 1; + state = 5; + } else { + _spritesTable[i].needUpdate = 0; + if (_updateLocationCounter2 < 4) { + state = 1; + } else if (_updateLocationCounter2 < 8) { + state = 2; + } else { + state = 4; + } + } + _spritesTable[i].state = state; +} + +void TuckerEngine::updateSprite_locationNum12_1(int i) { + int state; + const int r = getRandomNumber(); + if (r > 22000) { + state = 6; + } else if (r > 10000) { + state = 7; + } else { + state = 8; + } + _spritesTable[i].state = state; +} + +void TuckerEngine::execData3PreUpdate_locationNum12() { + if (_inventoryItemsState[12] == 1 && _flagsTable[38] == 0) { + _flagsTable[38] = 1; + } + if (_flagsTable[41] == 0) { + if (_locationMusicsTable[0].volume != 100) { + _locationMusicsTable[0].volume = 100; + setVolumeMusic(0, 100); + } + } else { + if (_locationMusicsTable[0].volume != 20) { + _locationMusicsTable[0].volume = 20; + setVolumeMusic(0, 20); + } + } +} + +void TuckerEngine::updateSprite_locationNum13(int i) { + int state; + if (_csDataHandled) { + if (_flagsTable[202] == 0) { + _flagsTable[202] = 1; + state = 3; + _spritesTable[i].stateIndex = -1; + } else if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + state = 4; + _spritesTable[i].needUpdate = 1; + } else { + _spritesTable[i].needUpdate = 0; + state = 5; + } + } else if (_flagsTable[202] == 1) { + _spritesTable[i].needUpdate = 0; + _flagsTable[202] = 0; + state = 6; + } else { + setCharacterAnimation(0, 0); + } + _spritesTable[i].state = state; +} + +void TuckerEngine::execData3PreUpdate_locationNum13() { + if (_flagsTable[69] == 0) { + if (getRandomNumber() > 31000) { + _flagsTable[69] = 1; + startSound(_locationSoundsTable[1].offset, 1, _locationSoundsTable[1].volume); + } else if (isSoundPlaying(1)) { + stopSound(1); + } + } + _flagsTable[8] = 2; + if (_spritesTable[0].state == 1) { + if (_spritesTable[0].animationFrame > 10 && _spritesTable[0].animationFrame < 20) { + if (!isSoundPlaying(0)) { + startSound(_locationSoundsTable[0].offset, 0, _locationSoundsTable[0].volume); + } + } + } + if (isSoundPlaying(0)) { + if (_spritesTable[0].animationFrame > 10 && _spritesTable[0].animationFrame < 20) { + stopSound(0); + } + } +} + +void TuckerEngine::updateSprite_locationNum14(int i) { + int state = 2; + if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + _spritesTable[i].needUpdate = 1; + state = (getRandomNumber() < 12000) ? 1 : 3; + } else if (getRandomNumber() < 26000) { + _spritesTable[i].updateDelay = 5; + } + _spritesTable[i].state = state; +} + +void TuckerEngine::execData3PreUpdate_locationNum14() { + if (!isSoundPlaying(0)) { + int num = -1; + const int i = getRandomNumber(); + if (i > 32000) { + num = 0; + } else if (i > 31800) { + num = 3; + } else if (i > 31600) { + num = 4; + } else if (i > 31400) { + num = 7; + } + if (num != -1) { + startSound(_locationSoundsTable[num].offset, num, _locationSoundsTable[num].volume); + } + } + _locationHeightTable[14] = (_xPosCurrent < 100) ? 0 : 60; + if (_updateLocationFadePaletteCounter == 0) { + for (int i = 0; i < 10; ++i) { + _updateLocation14ObjNum[i] = 0; + } + } + ++_updateLocationFadePaletteCounter; + if (_updateLocationFadePaletteCounter > 4) { + _updateLocationFadePaletteCounter = 1; + } + for (int i = 0; i < 10; ++i) { + execData3PreUpdate_locationNum14Helper1(i); + if (_updateLocationFadePaletteCounter == 1 && _updateLocation14ObjNum[i] > 0) { + execData3PreUpdate_locationNum14Helper2(i); + } + const int num = _updateLocation14ObjNum[i]; + if (num > 0) { + const int w = _dataTable[num].xSize; + const int h = _dataTable[num].ySize; + const int dstOffset = (_updateLocationYPosTable2[i] / 16 - h / 2) * 640 + (_updateLocationXPosTable2[i] - w / 2); + Graphics::decodeRLE_248(_locationBackgroundGfxBuf + dstOffset, _data3GfxBuf + _dataTable[num].sourceOffset, w, h, 0, 0, false); + } + } +} + +void TuckerEngine::execData3PreUpdate_locationNum14Helper1(int i) { + const int y = 1872; // XXX bug, 187/182 ? + if (_updateLocation14ObjNum[i] == 0) { + if (getRandomNumber() <= 30000) { + return; + } + _updateLocationXPosTable2[i] = 155; + _updateLocationYPosTable2[i] = y; + _updateLocation14Step[i] = -55 - getRandomNumber() / 512; + _updateLocation14ObjNum[i] = 231; + _updateLocation14Delay[i] = 16 + getRandomNumber() / 2048; + // XXX bug, missing return ? + } + _updateLocation14Step[i] = 4; + _updateLocationYPosTable2[i] += _updateLocation14Step[i]; + if (_updateLocationYPosTable2[i] > y) { + _updateLocationYPosTable2[i] = y; + _updateLocation14Step[i] = (-(getRandomNumber() + 32000) * _updateLocation14Step[i]) / 65536; + } + --_updateLocationXPosTable2[i]; + if (_updateLocationXPosTable2[i] == 0) { + _updateLocation14ObjNum[i] = 0; + } +} + +void TuckerEngine::execData3PreUpdate_locationNum14Helper2(int i) { + --_updateLocation14Delay[i]; + if (_updateLocation14Delay[i] == 0) { + _updateLocation14ObjNum[i] = 236; + } else { + ++_updateLocation14ObjNum[i]; + if (_updateLocation14ObjNum[i] > 237) { + _updateLocation14ObjNum[i] = 0; + } else if (_updateLocation14ObjNum[i] == 235) { + _updateLocation14ObjNum[i] = 231; + } + } +} + +void TuckerEngine::updateSprite_locationNum15_0(int i) { + _spritesTable[i].state = -1; +} + +void TuckerEngine::updateSprite_locationNum15_1(int i) { + int state; + int r = getRandomNumber(); + if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + _spritesTable[i].needUpdate = 1; + state = 6; + } else { + _spritesTable[i].needUpdate = 0; + if (r < 26000) { + state = 5; + } else if (r < 29000) { + state = 2; + _spritesTable[i].prevAnimationFrame = 1; + } else { + state = 4; + _spritesTable[4].counter = 1; + } + } + _spritesTable[i].state = state; +} + +void TuckerEngine::updateSprite_locationNum15_2(int i) { + _spritesTable[i].state = 3; + if (_spritesTable[4].counter > 0) { + ++_spritesTable[4].counter; + if (_spritesTable[4].counter > 6) { + _spritesTable[4].counter = 0; + } else { + _spritesTable[i].updateDelay = 2; + } + } else { + _spritesTable[i].updateDelay = 2; + } +} + +void TuckerEngine::execData3PreUpdate_locationNum15() { + ++_updateLocationFadePaletteCounter; + if (_updateLocationFadePaletteCounter > 500) { + if (!isSoundPlaying(1) && getRandomNumber() > 31000) { + const int i = getRandomNumber() / 4714; + startSound(_locationSoundsTable[i].offset, i, _locationSoundsTable[i].volume); + _updateLocationFadePaletteCounter = 0; + } + } +} + +void TuckerEngine::updateSprite_locationNum16_0(int i) { + int state; + int r = getRandomNumber(); + if (_flagsTable[210] > 0) { + state = -1; + } else if (_flagsTable[82] == 1) { + state = 2; + _flagsTable[82] = 2; + } else if (_flagsTable[82] == 2) { + state = -1; + } else if (_charSpeechSoundCounter > 0 && _actionCharacterNum == 0) { + if (_spritesTable[0].needUpdate == 0) { + _spritesTable[0].needUpdate = 1; + state = 1; + } else { + state = 1; + _spritesTable[0].animationFrame = 2; + _updateSpriteFlag1 = 1; + } + } else if (_csDataHandled) { + _spritesTable[0].needUpdate = 0; + if (r < 30000) { + state = 4; + _spritesTable[0].updateDelay = 5; + } else if (r < 31000) { + state = 4; + if (_xPosCurrent < 300) { + _miscSoundFxDelayCounter[0] = 2; + _soundsMapTable[0] = 9; + } + } else if (r < 32000) { + state = 5; + } else { + state = 6; + } + } + _spritesTable[i].state = state; +} + +void TuckerEngine::updateSprite_locationNum16_1(int i) { + int state; + if (_flagsTable[61] == 0) { + state = -1; + if (isSoundPlaying(0)) { + stopSound(0); + } else if (isSoundPlaying(1)) { + stopSound(1); + } + } else if (_flagsTable[60] == 0) { + state = 10; + if (isSoundPlaying(1)) { + _locationSoundsTable[1].type = 2; + startSound(_locationSoundsTable[1].offset, 1, _locationSoundsTable[1].volume); + } + } else { + state = 9; + if (isSoundPlaying(0)) { + _locationSoundsTable[0].type = 2; + startSound(_locationSoundsTable[0].offset, 0, _locationSoundsTable[0].volume); + } + } + _spritesTable[i].state = state; + _spritesTable[i].gfxBackgroundOffset = 320; +} + +void TuckerEngine::updateSprite_locationNum16_2(int i) { + int state = -1; + if (_flagsTable[78] == 0) { + if (_flagsTable[60] == 1 && _flagsTable[61] == 1) { + _flagsTable[78] = 1; + startSound(_locationSoundsTable[5].offset, 5, _locationSoundsTable[5].volume); + state = 7; + } + } else if (_flagsTable[78] == 1) { + if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + _spritesTable[i].needUpdate = 1; + state = 8; + } else { + if (getRandomNumber() > 32000) { + state = 7; + } else if (getRandomNumber() > 10000) { + state = 13; + _spritesTable[i].updateDelay = 5; + } else { + state = 13; + } + _spritesTable[i].needUpdate = 1; + } + } + _spritesTable[i].state = state; + _spritesTable[i].gfxBackgroundOffset = 320; +} + +void TuckerEngine::execData3PreUpdate_locationNum16() { + _locationHeightTable[16] = (_xPosCurrent < 320) ? 60 : 0; +} + +void TuckerEngine::updateSprite_locationNum17() { + int state; + if (_flagsTable[76] > 0) { + state = -1; + _disableCharactersPath = false; + } else if (_flagsTable[82] == 2) { + _flagsTable[82] = 3; + _disableCharactersPath = true; + _spritesTable[0].gfxBackgroundOffset = 100; + state = 1; + _spritesTable[0].backgroundOffset = -1; + } else if (_spritesTable[0].gfxBackgroundOffset < -160) { + state = -1; + } else { + state = 1; + _spritesTable[0].yMaxBackground = 0; + _spritesTable[0].colorType = 1; + } + _spritesTable[0].state = state; +} + +void TuckerEngine::updateSprite_locationNum18() { + int state; + if (_charSpeechSoundCounter > 0 && _actionCharacterNum == 0) { + _spritesTable[0].needUpdate = 1; + state = 2; + } else { + _spritesTable[0].needUpdate = 0; + state = 1; + const int r = getRandomNumber(); + if (r > 31000) { + state = 3; + } else if (r > 30000) { + state = 4; + } + } + _spritesTable[0].gfxBackgroundOffset = 0; + _spritesTable[0].backgroundOffset = 0; + _spritesTable[0].state = state; +} + +void TuckerEngine::updateSprite_locationNum19_0(int i) { + int state; + if (_flagsTable[206] == 1) { + state = 7; + _spritesTable[i].needUpdate = 0; + _flagsTable[206] = 0; + } else if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + ++_spritesTable[i].counter; + _spritesTable[i].needUpdate = 1; + if (_spritesTable[i].counter > 10) { + _spritesTable[i].counter = 0; + state = 2; + } else { + state = 1; + } + } else { + _spritesTable[i].needUpdate = 0; + if (_spritesTable[i].counter > 10) { + _spritesTable[i].counter = 0; + } + if (_spritesTable[i].counter == 2) { + state = 4; + _spritesTable[i].prevAnimationFrame = 1; + } else if (_spritesTable[i].counter == 5) { + state = 5; + _spritesTable[i].prevAnimationFrame = 1; + } else { + state = 5; + _spritesTable[i].updateDelay = 6; + } + } + _spritesTable[i].state = state; + _spritesTable[i].prevAnimationFrame = 1; +} + +void TuckerEngine::updateSprite_locationNum19_1(int i) { + _spritesTable[i].state = 9; + _spritesTable[i].gfxBackgroundOffset = 320; +} + +void TuckerEngine::updateSprite_locationNum19_2(int i) { + _spritesTable[i].gfxBackgroundOffset = 320; + _spritesTable[i].state = -1; +} + +void TuckerEngine::updateSprite_locationNum19_3(int i) { + setCharacterAnimation(0, i); +} + +void TuckerEngine::execData3PreUpdate_locationNum19() { + _locationHeightTable[19] = (_locationMaskType == 0) ? 0 : 60; +} + +void TuckerEngine::updateSprite_locationNum21() { + int state; + if (_flagsTable[58] == 2) { + state = 5; + _flagsTable[58] = 3; + setVolumeSound(2, 0); + } else if (_flagsTable[58] == 3) { + state = 6; + _flagsTable[58] = 4; + _locationSoundsTable[0].volume = 60; + _locationSoundsTable[5].volume = 60; + } else if (_flagsTable[58] == 4) { + state = 7; + _locationSoundsTable[4].volume = 60; + } else if (_flagsTable[59] == 4) { + _spritesTable[0].needUpdate = 1; + _flagsTable[59] = 2; + state = 2; + setVolumeSound(2, 0); + } else if (_flagsTable[59] == 3) { + _flagsTable[59] = 0; + state = 4; + setVolumeSound(2, _locationSoundsTable[2].volume); + } else if (_charSpeechSoundCounter > 0 && _actionCharacterNum == 0) { + _spritesTable[0].needUpdate = 1; + state = 3; + } else if (_flagsTable[59] == 2) { + _spritesTable[0].needUpdate = 0; + state = 3; + _spritesTable[0].updateDelay = 5; + } else if (_flagsTable[15] == 1) { + state = 3; + _spritesTable[0].updateDelay = 5; + } else { + _spritesTable[0].needUpdate = 0; + state = 1; + } + _spritesTable[0].state = state; + _spritesTable[0].gfxBackgroundOffset = 320; +} + +void TuckerEngine::updateSprite_locationNum22() { + if (_flagsTable[207] == 1) { + _spritesTable[0].state = -1; + } else if (_charSpeechSoundCounter > 0 && _actionCharacterNum == 0) { + _spritesTable[0].needUpdate = 1; + _spritesTable[0].state = 2; + } else { + _spritesTable[0].needUpdate = 0; + _spritesTable[0].state = 1; + } +} + +void TuckerEngine::execData3PreUpdate_locationNum21() { + if (_xPosCurrent > 460 && _flagsTable[58] == 0 && _nextAction == 0) { + _updateCharPositionNewType = 0; + _pendingActionDelay = 0; + _flagsTable[59] = 1; + _nextAction = 2; + _csDataLoaded = 0; + } + if (_flagsTable[58] > 0 && !isSoundPlaying(0)) { + const int r = getRandomNumber(); + if (r > 10000) { + int num; + if (r > 25000) { + num = 0; + } else if (r > 17000) { + num = 4; + } else { + num = 5; + } + startSound(_locationSoundsTable[num].offset, num, _locationSoundsTable[num].volume); + } + } + if (_spritesTable[0].state == 6) { + if (_spritesTable[0].animationFrame < 18) { + _spritesTable[0].gfxBackgroundOffset = 320 + _spritesTable[0].animationFrame * 638; + } else { + _spritesTable[0].gfxBackgroundOffset = 11840 - _spritesTable[0].animationFrame * 2; + } + } else { + _spritesTable[0].gfxBackgroundOffset = 320; + } + if (_inventoryItemsState[19] > 0) { + _flagsTable[43] = 1; + } +} + +void TuckerEngine::execData3PostUpdate_locationNum21() { + if (_flagsTable[58] > 3) { + drawSprite(0); + } +} + +void TuckerEngine::execData3PreUpdate_locationNum22() { + if (_flagsTable[53] > 1 && _flagsTable[53] != 4) { + if (_inventoryItemsState[5] > 0 && _inventoryItemsState[20] <= 0 && _inventoryItemsState[16] > 0 && _inventoryItemsState[27] > 0) { + _flagsTable[53] = 3; + } + if (_inventoryItemsState[5] > 0 || _inventoryItemsState[20] > 0 || _inventoryItemsState[16] > 0 || _inventoryItemsState[27] > 0) { + _flagsTable[53] = 5; + } + } + if (_flagsTable[210] < 2 && _csDataHandled == 0 && _flagsTable[54] == 1) { + _nextAction = 25; + _csDataLoaded = 0; + _flagsTable[210] = 2; + } +} + +void TuckerEngine::updateSprite_locationNum23_0(int i) { + int state; + if (_flagsTable[210] == 3) { + state = 12; + } else { + state = -1; + } + _spritesTable[i].state = state; +} + +void TuckerEngine::updateSprite_locationNum23_1(int i) { + int state; + if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + _spritesTable[i].needUpdate = 1; + state = 14; + } else if (getRandomNumber() < 30000) { + _spritesTable[i].needUpdate = 0; + state = 25; + } else { + _spritesTable[i].needUpdate = 0; + state = 13; + } + _spritesTable[i].state = state; +} + +void TuckerEngine::updateSprite_locationNum23_2(int i) { + int state; + if (_flagsTable[210] == 0) { + if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + _spritesTable[i].needUpdate = 1; + state = 6; + } else { + _spritesTable[i].needUpdate = 0; + state = (getRandomNumber() < 25000) ? 4 : 5; + } + } else if (_flagsTable[210] == 1) { + if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + _spritesTable[i].needUpdate = 1; + if (_flagsTable[211] == 10) { + state = 34; + } else if (_flagsTable[211] == 0) { + state = 30; + _flagsTable[211] = 1; + } else { + state = 31; + } + } else { + _spritesTable[i].needUpdate = 0; + if (_flagsTable[211] == 1) { + state = 32; + _flagsTable[211] = 0; + } else { + state = (getRandomNumber() < 25000) ? 10 : 11; + } + } + } else if (_flagsTable[210] == 2) { + if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + _spritesTable[i].needUpdate = 1; + state = 33; + } else { + _spritesTable[i].needUpdate = 0; + if (_flagsTable[212] == 0) { + state = 3; + _flagsTable[212] = 1; + } else if (_flagsTable[212] == 2) { + state = 29; + _flagsTable[212] = 3; + } else { + state = (getRandomNumber() < 25000) ? 22 : 23; + } + } + } + _spritesTable[i].state = state; +} + +void TuckerEngine::updateSprite_locationNum23_3(int i) { + int state; + if (_flagsTable[210] == 0 || _flagsTable[210] == 2) { + state = -1; + } else if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + _spritesTable[i].needUpdate = 1; + state = 8; + } else { + _spritesTable[i].needUpdate = 0; + state = 9; + } + _spritesTable[i].state = state; +} + +void TuckerEngine::updateSprite_locationNum24_0(int i) { + int state; + if (_flagsTable[103] == 4) { + _flagsTable[103] = 3; + state = 5; + } else if (_flagsTable[103] == 0) { + if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + _spritesTable[i].needUpdate = 1; + state = 2; + } else { + _spritesTable[i].needUpdate = 1; + state = 1; + if (getRandomNumber() < 30000) { + _spritesTable[i].updateDelay = 5; + } + } + } else if (_flagsTable[103] == 1 || _flagsTable[103] == 3) { + state = -1; + } else { + if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + _spritesTable[i].needUpdate = 1; + state = 4; + } else { + if (getRandomNumber() < 30000) { + _spritesTable[i].needUpdate = 0; + state = 6; + _spritesTable[i].updateDelay = 5; + } else { + _spritesTable[i].needUpdate = 0; + state = 6; + } + } + } + _spritesTable[i].state = state; +} + +void TuckerEngine::updateSprite_locationNum24_1(int i) { + if (_flagsTable[103] > 1) { + _spritesTable[i].state = 3; + } else { + _spritesTable[i].state = -1; + } +} + +void TuckerEngine::updateSprite_locationNum24_2(int i) { + int state; + if (_flagsTable[214] > 1) { + state = -1; + } else if (_flagsTable[214] == 1) { + _spritesTable[i].needUpdate = 0; + _flagsTable[214] = 2; + state = 9; + } else if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + _spritesTable[i].needUpdate = 1; + if (_flagsTable[213] == 1) { + state = 10; + } else if (_flagsTable[213] == 2) { + state = 14; + } else { + state = 8; + } + } else { + _spritesTable[i].needUpdate = 1; + state = 7; + } + _spritesTable[i].state = state; +} + +void TuckerEngine::updateSprite_locationNum24_3(int i) { + int state; + if (_flagsTable[239] == 1) { + state = -1; + } else if (_flagsTable[214] == 2) { + _flagsTable[239] = 1; + state = 13; + } else if (getRandomNumber() > 32000) { + state = 12; + } else { + state = 11; + } + _spritesTable[i].state = state; +} + +void TuckerEngine::execData3PreUpdate_locationNum24() { + _characterPrevBackFrontFacing = 0; + if (_flagsTable[112] == 0) { + _yPosCurrent = 132; + _xPosCurrent = 112; + } else if (_inventoryItemsState[2] == 1 && _inventoryItemsState[11] == 1 && _flagsTable[156] == 1 && _flagsTable[145] == 3) { + _flagsTable[156] = 2; + _nextAction = 61; + _csDataLoaded = 0; + } + if (_flagsTable[103] > 0 && (_inventoryItemsState[2] > 0 || _inventoryItemsState[11] > 0 || _flagsTable[156] > 0 || _flagsTable[145] == 3) && _flagsTable[217] == 0) { + _flagsTable[217] = 1; + } + _locationHeightTable[24] = (_yPosCurrent < 125) ? 60 : 0; +} + +void TuckerEngine::execData3PostUpdate_locationNum24() { + if (_yPosCurrent < 132) { + drawSprite(1); + drawSprite(0); + } +} + +void TuckerEngine::execData3PreUpdate_locationNum25() { + _backgroundSprOffset = _xPosCurrent - 160; +} + +void TuckerEngine::updateSprite_locationNum26_0(int i) { + if (_flagsTable[125] > 0 && _flagsTable[125] < 300) { + _flagsTable[126] = 1; + } + _spritesTable[i].gfxBackgroundOffset = _flagsTable[125]; + _spritesTable[i].state = 1; + _spritesTable[i].colorType = 99; +} + +void TuckerEngine::updateSprite_locationNum26_1(int i) { + int state; + if (_flagsTable[125] == 0) { + state = -1; + } else if (_flagsTable[125] > 299) { + state = 2; + _spritesTable[i].updateDelay = 5; + } else { + state = 2; + } + _spritesTable[i].gfxBackgroundOffset = _flagsTable[125]; + _spritesTable[i].colorType = 1; + _spritesTable[i].state = state; +} + +void TuckerEngine::execData3PreUpdate_locationNum26() { + _characterPrevBackFrontFacing = 1; + _spritesTable[1].gfxBackgroundOffset = _flagsTable[125]; + _spritesTable[0].gfxBackgroundOffset = _flagsTable[125]; + if (_flagsTable[125] > 0 && _flagsTable[125] < 300) { + if (!isSoundPlaying(5)) { + startSound(_locationSoundsTable[5].offset, 5, _locationSoundsTable[5].volume); + startSound(_locationSoundsTable[6].offset, 6, _locationSoundsTable[6].volume); + } + ++_flagsTable[125]; + _flagsTable[126] = 1; + } else { + if (isSoundPlaying(5)) { + stopSound(5); + stopSound(6); + } + } + if (_panelLockedFlag == 0) { + if (_xPosCurrent > 207 && _xPosCurrent < 256) { + _objectKeysLocationTable[26] = 0; + _objectKeysPosXTable[26] = 260; + } else { + _objectKeysLocationTable[26] = 1; + } + } +} + +void TuckerEngine::updateSprite_locationNum27(int i) { + int state; + if (_flagsTable[155] < 3 || _flagsTable[125] == 5) { + state = -1; + } else if (_flagsTable[155] == 3) { + state = 1; + _flagsTable[155] = 4; + } else if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + _spritesTable[i].needUpdate = 1; + state = 2; + } else if (getRandomNumber() < 30000) { + _spritesTable[i].needUpdate = 0; + state = 3; + _spritesTable[i].updateDelay = 5; + } else { + _spritesTable[i].needUpdate = 0; + state = 3; + } + _spritesTable[i].state = state; +} + +void TuckerEngine::execData3PreUpdate_locationNum27() { + _characterPrevBackFrontFacing = 0; +} + +void TuckerEngine::execData3PostUpdate_locationNum27() { + if (_flagsTable[155] == 4 && _yPosCurrent < 125) { + drawSprite(0); + } +} + +void TuckerEngine::updateSprite_locationNum28_0(int i) { + int state; + if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + state = 4; + _spritesTable[i].needUpdate = 1; + } else { + _spritesTable[i].needUpdate = 0; + ++_spritesTable[i].counter; + if (_spritesTable[i].counter > 30) { + _spritesTable[i].counter = 0; + } + if (_flagsTable[86] == 1) { + if (_spritesTable[i].counter == 16 || _spritesTable[i].counter == 27) { + state = 3; + } else { + state = 3; + _spritesTable[i].updateDelay = 5; + } + } else { + if (_spritesTable[i].counter == 5 || _spritesTable[i].counter == 11) { + state = 5; + } else if (_spritesTable[i].counter == 16 || _spritesTable[i].counter == 27) { + state = 6; + } else { + state = 6; + _spritesTable[i].updateDelay = 5; + } + } + } + _spritesTable[i].state = state; +} + +void TuckerEngine::updateSprite_locationNum28_1(int i) { + _spritesTable[i].state = (_flagsTable[86] == 1) ? 1 : -1; +} + +void TuckerEngine::updateSprite_locationNum28_2(int i) { + int state; + if (_flagsTable[155] == 1) { + state = 8; + _flagsTable[155] = 2; + } else { + state = -1; + } + _spritesTable[i].state = state; +} + +void TuckerEngine::execData3PreUpdate_locationNum28() { + if (_flagsTable[86] == 0 && _xPosCurrent > 265 && _nextAction == 0) { + _panelLockedFlag = 0; + _nextAction = 21; + _csDataLoaded = 0; + _pendingActionDelay = 0; + _pendingActionIndex = 0; + _updateCharPositionNewType = 0; + } +} + +void TuckerEngine::execData3PostUpdate_locationNum28() { + if (_yPosCurrent < 135) { + drawSprite(1); + } +} + +void TuckerEngine::updateSprite_locationNum29_0(int i) { + _spritesTable[i].state = (getRandomNumber() < 32000) ? -1 : 2; +} + +void TuckerEngine::updateSprite_locationNum29_1(int i) { + int state = -1; + if (getRandomNumber() >= 32000) { + state = 1; + _spritesTable[i].gfxBackgroundOffset = 320; + } + _spritesTable[i].state = state; +} + +void TuckerEngine::updateSprite_locationNum29_2(int i) { + _spritesTable[i].state = 3; + _spritesTable[i].gfxBackgroundOffset = 320; +} + +void TuckerEngine::execData3PreUpdate_locationNum29() { + static const uint8 r[] = { 0x0D, 0x0E, 0x0E, 0x0E, 0x0D, 0x0E, 0x0D, 0x0E, 0x0E, 0x0E, 0x0D }; + static const uint8 g[] = { 0x0E, 0x14, 0x1B, 0x14, 0x0E, 0x0D, 0x0E, 0x14, 0x1B, 0x14, 0x0E }; + static const uint8 b[] = { 0x2C, 0x34, 0x3B, 0x34, 0x2C, 0x24, 0x2C, 0x34, 0x3B, 0x34, 0x2C }; + if (_fadePaletteCounter == 16) { + ++_updateLocationFadePaletteCounter; + if (_updateLocationFadePaletteCounter > 10) { + _updateLocationFadePaletteCounter = 0; + } + int d = _updateLocationFadePaletteCounter / 2; + for (int i = 0; i < 5; ++i) { + setPaletteColor(118 + i, r[i] + d, g[i] + d, b[i] + d); + } + if (_flagsTable[143] == 1) { + _locationObjectsTable[2].xPos = 999; + _locationObjectsTable[3].xPos = 187; + } else { + _locationObjectsTable[2].xPos = 187; + _locationObjectsTable[3].xPos = 999; + } + } +} + +void TuckerEngine::updateSprite_locationNum30_34(int i) { + _spritesTable[i].state = i + 1; +} + +void TuckerEngine::execData3PreUpdate_locationNum30() { + if (!isSoundPlaying(1) && getRandomNumber() > 32500) { + startSound(_locationSoundsTable[1].offset, 1, _locationSoundsTable[1].volume); + } +} + +void TuckerEngine::execData3PreUpdate_locationNum31() { + execData3PreUpdate_locationNum31Helper(32000, 110); + execData3PreUpdate_locationNum31Helper(31000, 111); + if (_xPosCurrent < 112 && _flagsTable[104] == 0) { + _flagsTable[104] = 1; + } +} + +void TuckerEngine::execData3PreUpdate_locationNum31Helper(int r, int flag) { + if (getRandomNumber() > r && _flagsTable[flag] == 0) { + _flagsTable[flag] = 1; + } +} + +void TuckerEngine::execData3PreUpdate_locationNum32() { + if (_spritesTable[0].state == 12 && _spritesTable[0].animationFrame < 22) { + _flagsTable[113] = 1; + } else { + _flagsTable[113] = 0; + } +} + +void TuckerEngine::execData3PostUpdate_locationNum32() { + if (_yPosCurrent < 120) { + drawSprite(0); + } +} + +void TuckerEngine::updateSprite_locationNum31_0(int i) { + _spritesTable[i].state = (getRandomNumber() < 32000) ? 3 : 1; +} + +void TuckerEngine::updateSprite_locationNum31_1(int i) { + _spritesTable[i].state = (_flagsTable[86] == 1) ? 2 : -1; +} + +void TuckerEngine::updateSprite_locationNum32_0(int i) { + static const uint8 stateTable[] = { 12, 1, 11, 1, 11, 2, 1, 5, 5, 11, 1, 5, 5, 5 }; + ++_spritesTable[i].counter; + if (_flagsTable[123] == 2) { + _flagsTable[123] = 0; + } + int state; + if (_flagsTable[222] == 1) { + state = 19; + _flagsTable[222] = 2; + } else if (_flagsTable[222] == 2) { + state = 19; + _spritesTable[i].animationFrame = 23; + _updateSpriteFlag1 = 1; + } else if (_flagsTable[123] == 1) { + state = 17; + _flagsTable[123] = 2; + } else if (_flagsTable[222] == 3) { + state = 18; + } else if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + _spritesTable[i].needUpdate = 1; + state = 4; + } else if (_csDataHandled) { + state = 5; + } else { + _spritesTable[i].needUpdate = 0; + if (_spritesTable[i].counter > 13) { + _spritesTable[i].counter = 0; + } + state = stateTable[_spritesTable[i].counter]; + } + _spritesTable[i].state = state; +} + +void TuckerEngine::updateSprite_locationNum33_0(int i) { + int state = 5; + if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + _spritesTable[i].needUpdate = 1; + state = 7; + } else if (_flagsTable[87] == 1) { + state = 8; + } else if (_flagsTable[222] == 5) { + state = 4; + } else { + _spritesTable[i].needUpdate = 0; + state = (getRandomNumber() < 30000) ? 5 : 6; + } + _spritesTable[i].state = state; +} + +void TuckerEngine::updateSprite_locationNum33_1(int i) { + int state; + if (_flagsTable[87] == 1) { + state = 3; + } else if (_flagsTable[222] == 5) { + state = 2; + } else { + state = 1; + } + _spritesTable[i].state = state; +} + +void TuckerEngine::updateSprite_locationNum33_2(int i) { + int state; + if (_flagsTable[87] == 1) { + state = 11; + } else if (_flagsTable[222] == 5) { + state = 10; + } else { + state = 9; + } + _spritesTable[i].state = state; +} + +void TuckerEngine::execData3PreUpdate_locationNum33() { + if (_xPosCurrent < 90) { + if (_flagsTable[105] == 0) { + _flagsTable[105] = 3; + startSound(_locationSoundsTable[5].offset, 5, _locationSoundsTable[5].volume); + } + } else { + if (_flagsTable[105] == 1) { + _flagsTable[105] = 2; + startSound(_locationSoundsTable[5].offset, 5, _locationSoundsTable[5].volume); + } + } + if (_xPosCurrent > 230) { + if (_flagsTable[106] == 0) { + _flagsTable[106] = 3; + startSound(_locationSoundsTable[5].offset, 5, _locationSoundsTable[5].volume); + } + } else { + if (_flagsTable[106] == 1) { + _flagsTable[106] = 2; + startSound(_locationSoundsTable[5].offset, 5, _locationSoundsTable[5].volume); + } + } +} + +void TuckerEngine::execData3PreUpdate_locationNum34() { + if (_flagsTable[143] == 1) { + _locationObjectsTable[0].xPos = 0; + } +} + +void TuckerEngine::execData3PreUpdate_locationNum35() { + if (_flagsTable[250] > 0) { + _currentFxVolume = 0; + } +} + +void TuckerEngine::updateSprite_locationNum36(int i) { + _spritesTable[i].state = (getRandomNumber() < 32000) ? 1 : 2; +} + +void TuckerEngine::execData3PreUpdate_locationNum36() { + if (_execData3Counter == 0) { + _execData3Counter = 1; + _flagsTable[107] = 1; + } else if (_flagsTable[107] == 0 && _locationMaskType == 1 && _execData3Counter == 1) { + _execData3Counter = 2; + _flagsTable[107] = 1; + } +} + +void TuckerEngine::updateSprite_locationNum37(int i, int j, int offset) { + ++_spritesTable[i].counter; + if (_spritesTable[i].counter > offset) { + _spritesTable[i].state = j; + _spritesTable[i].counter = 0; + } else { + _spritesTable[i].state = -1; + } +} + +void TuckerEngine::execData3PreUpdate_locationNum38() { + if (_flagsTable[117] == 0 && _flagsTable[116] == 1) { + _flagsTable[116] = 0; + } +} + +void TuckerEngine::updateSprite_locationNum41(int i) { + int state; + if (_flagsTable[223] > 1) { + state = -1; + } else if (_flagsTable[223] == 1) { + state = 1; + _flagsTable[158] = 2; + } else if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + _spritesTable[i].needUpdate = 1; + state = 3; + } else if (getRandomNumber() < 30000) { + _spritesTable[i].needUpdate = 0; + state = 5; + } else { + _spritesTable[i].needUpdate = 0; + state = 4; + } + _spritesTable[i].state = state; +} + +void TuckerEngine::execData3PreUpdate_locationNum41() { + if (_backgroundSpriteCurrentAnimation == 4) { + if (_backgroundSpriteCurrentFrame == 8) { + _flagsTable[77] = 2; + } else if (_backgroundSpriteCurrentFrame == 7) { + _flagsTable[77] = 0; + } + if (_changeBackgroundSprite == 0) { + if (_backgroundSpriteCurrentFrame == 16 && !isSoundPlaying(4)) { + _locationSoundsTable[4].type = 2; + startSound(_locationSoundsTable[4].offset, 4, _locationSoundsTable[4].volume); + } else { + if (_backgroundSpriteCurrentFrame == 28) { + stopSound(4); + } + } + } else { + if (_backgroundSpriteCurrentFrame == 28 && !isSoundPlaying(4)) { + _locationSoundsTable[4].type = 2; + startSound(_locationSoundsTable[4].offset, 4, _locationSoundsTable[4].volume); + } else { + if (_backgroundSpriteCurrentFrame == 18) { + stopSound(4); + } + } + } + } + if (_panelLockedFlag == 1 && _yPosCurrent > 130 && _selectedObject.yPos > 135 && _nextAction == 0 && _flagsTable[223] == 0) { + _panelLockedFlag = 0; + _csDataLoaded = false; + _nextLocationNum = 0; + _selectedObject.locationObject_locationNum = 0; + _locationMaskType = 0; + _nextAction = _flagsTable[163] + 32; + ++_flagsTable[163]; + if (_flagsTable[163] > 2) { + _flagsTable[163] = 0; + } + if (_flagsTable[223] > 0 && _mapSequenceFlagsLocationTable[40] == 0) { + for (int i = 41; i < 53; ++i) { + _mapSequenceFlagsLocationTable[i - 1] = 1; + } + } + if (_flagsTable[77] == 0) { + _locationObjectsTable[3].xPos = 230; + } else { + _locationObjectsTable[3].xPos = 930; + } + } +} + +void TuckerEngine::updateSprite_locationNum42(int i) { + int state; + if (_flagsTable[223] == 0 || _flagsTable[223] > 3) { + state = -1; + } else if (_flagsTable[223] == 1) { + state = 1; + _flagsTable[223] = 2; + } else if (_flagsTable[223] == 2) { + state = 5; + _flagsTable[223] = 3; + } else if (_flagsTable[223] == 3) { + state = 5; + _spritesTable[i].updateDelay = 5; + _spritesTable[i].state = _spritesTable[i].firstFrame - 1; // XXX bug, fxNum ? + _updateSpriteFlag1 = 1; + } else { + state = 2; + } + _spritesTable[i].state = state; +} + +void TuckerEngine::execData3PreUpdate_locationNum42() { + _flagsTable[167] = 1; +} + +void TuckerEngine::updateSprite_locationNum43_2(int i) { + int state; + if (_flagsTable[237] > 0) { + state = -1; + } else if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + _spritesTable[i].needUpdate = 1; + state = 5; + } else if (_csDataHandled || _spritesTable[i].counter == 2) { + _spritesTable[i].needUpdate = 0; + state = 6; + } else if (_spritesTable[i].counter == 0) { + state = 3; + } else { + state = 4; + _spritesTable[i].counter = 2; + } + _spritesTable[i].state = state; +} + +void TuckerEngine::updateSprite_locationNum43_3(int i) { + int state; + if (_flagsTable[236] > 0) { + state = -1; + } else if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + state = 7; + _spritesTable[i].needUpdate = 1; + } else { + state = 8; + _spritesTable[i].needUpdate = 0; + } + _spritesTable[i].state = state; +} + +void TuckerEngine::updateSprite_locationNum43_4(int i) { + int state; + if (_flagsTable[236] > 0) { + state = -1; + } else if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + state = 9; + _spritesTable[i].needUpdate = 1; + } else { + state = 10; + _spritesTable[i].needUpdate = 0; + } + _spritesTable[i].state = state; +} + +void TuckerEngine::updateSprite_locationNum43_5(int i) { + _spritesTable[i].state = (_flagsTable[236] < 4) ? -1 : 11; +} + +void TuckerEngine::updateSprite_locationNum43_6(int i) { + _spritesTable[i].state = (_flagsTable[236] < 4) ? -1 : 12; +} + +void TuckerEngine::execData3PreUpdate_locationNum43() { + if (_panelLockedFlag == 1 && _xPosCurrent > 67 && _selectedObject.xPos > 68 && _locationMaskType == 0) { + _panelLockedFlag = 0; + _csDataLoaded = 0; + _nextAction = 5; + } + if (_xPosCurrent > 55 && _spritesTable[2].counter == 0) { + _spritesTable[2].counter = 1; + } +} + +void TuckerEngine::execData3PreUpdate_locationNum44() { + if (_backgroundSpriteCurrentAnimation == 1) { + if (!isSoundPlaying(3) && _backgroundSpriteCurrentFrame == 1) { + _locationSoundsTable[3].type = 2; + startSound(_locationSoundsTable[3].offset, 3, _locationSoundsTable[3].volume); + } + if (_backgroundSpriteCurrentFrame == 21) { + _flagsTable[77] = 1; + } else if (_backgroundSpriteCurrentFrame == 20) { + _flagsTable[77] = 2; + stopSound(3); + } + } else if (_backgroundSpriteCurrentAnimation == 4) { + if (_backgroundSpriteCurrentFrame == 20 && !isSoundPlaying(3)) { + startSound(_locationSoundsTable[3].offset, 3, _locationSoundsTable[3].volume); + } + } +} + +void TuckerEngine::updateSprite_locationNum48(int i) { + int state; + if (_flagsTable[160] == 0 || _flagsTable[160] > 2 || _flagsTable[207] > 0) { + state = -1; + } else if (_flagsTable[160] == 2) { + _flagsTable[160] = 3; + state = 3; + } else if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + _spritesTable[i].needUpdate = 1; + state = 2; + } else if (getRandomNumber() < 30000) { + _spritesTable[i].needUpdate = 0; + state = 2; + _spritesTable[i].updateDelay = 5; + } else { + _spritesTable[i].needUpdate = 0; + state = 2; + _spritesTable[i].updateDelay = 5; + } + _spritesTable[i].state = state; +} + +void TuckerEngine::updateSprite_locationNum49(int i) { + if (_flagsTable[136] == 1 && _flagsTable[207] == 0) { + _flagsTable[207] = 2; + } + if (_flagsTable[185] == 0 && _yPosCurrent < 125) { + _flagsTable[185] = 1; + } else if (_flagsTable[185] == 2 && (_yPosCurrent > 130 || _flagsTable[236] == 4)) { + _flagsTable[185] = 3; + } + int state; + if (_flagsTable[185] == 0 || _flagsTable[160] < 3) { + state = -1; + } else if (_flagsTable[185] == 1) { + _flagsTable[185] = 2; + state = 1; + } else if (_flagsTable[185] == 3) { + _flagsTable[185] = 0; + state = 4; + } else if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + _spritesTable[i].needUpdate = 1; + state = 2; + } else { + _spritesTable[i].needUpdate = 0; + if (getRandomNumber() < 30000 || _backgroundSpriteCurrentAnimation <= -1) { + state = 3; + _spritesTable[i].updateDelay = 1; + } else if (getRandomNumber() < 16000) { + state = 5; + } else { + state = 6; + } + } + _spritesTable[i].state = state; +} + +void TuckerEngine::execData3PreUpdate_locationNum49() { + _flagsTable[132] = 0; + if (_execData3Counter == 0) { + _execData3Counter = 1; + if (_flagsTable[181] == 2) { + _flagsTable[181] = 3; + } + } + static const int items[] = { 15, 44, 25, 27, 19, 21, 24, 13, 20, 29, 35, 23, 3 }; + for (int i = 0; i < 13; ++i) { + if (_inventoryItemsState[items[i]] == 1) { + _flagsTable[168 + i] = 1; + } + } + int counter = 0; + for (int i = 168; i < 181; ++i) { + if (_flagsTable[i] == 2) { + ++counter; + } + } + if (_nextAction == 0) { + if (counter == 2 && _flagsTable[236] == 0) { + _nextAction = 56; + _csDataLoaded = false; + } else if (counter == 6 && _flagsTable[236] == 1) { + _nextAction = 59; + _csDataLoaded = false; + } else if (counter == 10 && _flagsTable[236] == 2) { + _nextAction = 62; + _csDataLoaded = false; + } else if (counter == 13 && _flagsTable[236] == 3) { + _nextAction = 65; + _csDataLoaded = false; + } + } +} + +void TuckerEngine::updateSprite_locationNum50(int i) { + int state; + if (_flagsTable[240] == 0) { + state = i + 1; + if (i == 5) { + _flagsTable[240] = 1; + } + } else { + _spritesTable[i].animationFrame = _spritesTable[i].firstFrame - 1; + _spritesTable[i].updateDelay = 5; + _updateSpriteFlag1 = 1; + state = i + 1; + } + state = i + 1; // XXX bug ? + _spritesTable[i].state = state; +} + +void TuckerEngine::updateSprite_locationNum51_0(int i) { + static const int stateTable[] = { 3, 3, 4, 5, 3, 3, 5, 4, 3, 3, 4, 5, 4, 4 }; + ++_spritesTable[i].counter; + if (_spritesTable[i].counter > 13) { + _spritesTable[i].counter = 0; + } + _spritesTable[i].state = stateTable[_spritesTable[i].counter]; + _spritesTable[i].colorType = 1; + _spritesTable[i].yMaxBackground = 0; +} + +void TuckerEngine::updateSprite_locationNum51_1(int i) { + _spritesTable[i].state = 6; + _spritesTable[i].colorType = 1; + _spritesTable[i].yMaxBackground = 0; +} + +void TuckerEngine::updateSprite_locationNum51_2(int i) { + _spritesTable[i].state = 1; + _spritesTable[i].colorType = 1; + _spritesTable[i].yMaxBackground = 0; +} + +void TuckerEngine::execData3PreUpdate_locationNum52() { + if (_selectedObject.xPos > 108 && _panelLockedFlag > 0 && _nextAction == 0 && _locationMaskType == 0) { + _nextAction = 1; + _csDataLoaded = 0; + } +} + +void TuckerEngine::updateSprite_locationNum53_0(int i) { + if (_flagsTable[197] == 2) { + _flagsTable[197] = 3; + } + int state; + if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + _spritesTable[i].needUpdate = 1; + state = 1; + } else if (_flagsTable[197] == 1) { + state = 3; + _spritesTable[i].needUpdate = 0; + _flagsTable[197] = 2; + } else if (_flagsTable[192] == 1) { + _spritesTable[i].needUpdate = 0; + state = 5; + } else { + _spritesTable[i].needUpdate = 0; + state = 5; + _spritesTable[i].updateDelay = 5; + } + _spritesTable[i].state = state; +} + +void TuckerEngine::updateSprite_locationNum53_1(int i) { + int state; + if (_flagsTable[197] == 3) { + state = 6; + } else if (_flagsTable[197] == 4) { + state = 7; + } else { + state = -1; + } + _spritesTable[i].state = state; +} + +void TuckerEngine::execData3PreUpdate_locationNum53() { + if (_flagsTable[192] == 0 && _xPosCurrent < 200 && _nextAction == 0) { + _panelLockedFlag = 0; + _nextAction = 14; + _csDataLoaded = 0; + _pendingActionDelay = 0; + _pendingActionIndex = 0; + _updateCharPositionNewType = 0; + } +} + +void TuckerEngine::updateSprite_locationNum54(int i) { + int state = 3; + if (_flagsTable[141] == 2) { + _spritesTable[i].needUpdate = 0; + setCharacterAnimation(0, i); + _flagsTable[141] = 1; + _spritesTable[i].counter = 0; + } else if (_flagsTable[141] == 1 && _spritesTable[i].counter < 40) { + setCharacterAnimation(1, i); + ++_spritesTable[i].counter; + } else if (_flagsTable[141] == 1) { + setCharacterAnimation(2, i); + _flagsTable[141] = 3; + } else { + if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + _spritesTable[i].needUpdate = 2; + state = (getRandomNumber() < 12000) ? 2 : 4; + } else if (_flagsTable[141] == 3) { + state = 3; + _flagsTable[141] = 0; + _flagsTable[224] = 1; + _spritesTable[i].counter = 0; + if (_panelLockedFlag == 0 && _xPosCurrent > 130 && _inventoryItemsState[17] == 0) { + _nextAction = 18; + _csDataLoaded = false; + } + } else if (getRandomNumber() < 26000) { + state = 3; + _spritesTable[i].needUpdate = 0; + _spritesTable[i].updateDelay = 5; + } else { + state = 3; + _spritesTable[i].needUpdate = 0; + } + if (_inventoryItemsState[17] == 1) { + _flagsTable[224] = 2; + } + _spritesTable[i].state = state; + } +} + +void TuckerEngine::updateSprite_locationNum55(int i) { + if (_flagsTable[193] > 0 && _flagsTable[193] < 14) { + setCharacterAnimation(_flagsTable[193] - 1, i); + _updateSpriteFlag1 = 1; + if (_flagsTable[193] == 1 || _flagsTable[193] == 3 || _flagsTable[193] == 5 || _flagsTable[193] == 7 || _flagsTable[193] == 11 || _flagsTable[193] == 13) { + ++_flagsTable[193]; + } + } else { + _spritesTable[i].state = -1; + if (_flagsTable[193] == 14) { + _flagsTable[193] = 15; + } + } +} + +void TuckerEngine::updateSprite_locationNum56(int i) { + int state; + ++_spritesTable[i].counter; + if (_flagsTable[153] == 1) { + state = -1; + } else if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + _spritesTable[i].needUpdate = 1; + state = 2; + } else { + _spritesTable[i].needUpdate = 0; + state = 1; + } + _spritesTable[i].state = state; +} + +void TuckerEngine::updateSprite_locationNum57_0(int i) { + int state; + if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + _spritesTable[i].needUpdate = 1; + state = 5; + } else { + _spritesTable[i].needUpdate = 0; + if (getRandomNumber() < 30000) { + state = 1; + } else if (getRandomNumber() < 16000) { + state = 4; + } else { + state = 2; + } + } + _spritesTable[i].state = state; +} + +void TuckerEngine::updateSprite_locationNum57_1(int i) { + int state = 6; + if (getRandomNumber() < 30000) { + _spritesTable[i].updateDelay = 5; + } + _spritesTable[i].state = state; +} + +void TuckerEngine::execData3PreUpdate_locationNum57() { + if (_flagsTable[137] == 2 && _xPosCurrent < 42 && _yPosCurrent == 135) { + _flagsTable[137] = 0; + _backgroundSpriteCurrentAnimation = 2; + _backgroundSpriteCurrentFrame = 0; + _backgroundSprOffset = 0; + } +} + +void TuckerEngine::updateSprite_locationNum58(int i) { + int state; + if (_flagsTable[190] == 0) { + state = 1; + } else if (_flagsTable[190] == 1) { + state = 2; + _flagsTable[190] = 2; + } else { + state = 3; + if (_flagsTable[190] == 2) { + _flagsTable[190] = 3; + } + } + _spritesTable[i].state = state; + _spritesTable[i].gfxBackgroundOffset = 320; +} + +void TuckerEngine::execData3PreUpdate_locationNum58() { + if (_flagsTable[190] < 3 && _xPosCurrent > 310) { + _xPosCurrent = 310; + _panelLockedFlag = 0; + } + if (_flagsTable[190] > 0 && _locationSoundsTable[0].volume > 0) { + _locationSoundsTable[0].volume = 0; + _locationSoundsTable[4].volume = 0; + _locationSoundsTable[5].volume = 0; + if (isSoundPlaying(0)) { + stopSound(0); + } + } +} + +void TuckerEngine::updateSprite_locationNum59(int i) { + int state; + if (_flagsTable[207] == 1) { + state = -1; + } else if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + state = 3; + _spritesTable[i].needUpdate = 1; + } else if (_csDataHandled) { + _spritesTable[i].needUpdate = 0; + if (_flagsTable[199] == 0) { + _flagsTable[199] = 1; + setCharacterAnimation(0, 0); + return; + } + _spritesTable[i].needUpdate = 0; + state = 3; + _spritesTable[i].updateDelay = 5; + } else if (_flagsTable[199] == 1) { + _flagsTable[199] = 0; + _spritesTable[i].needUpdate = 0; + setCharacterAnimation(1, 0); + return; + } else { + _spritesTable[i].needUpdate = 0; + state = 1; + } + _spritesTable[i].state = state; +} + +void TuckerEngine::updateSprite_locationNum60_0(int i) { + int state; + if (_flagsTable[186] > 0) { + state = -1; + } else if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + _spritesTable[i].needUpdate = 1; + state = 9; + } else { + _spritesTable[i].needUpdate = 0; + state = (getRandomNumber() > 32000) ? 8 : 7; + } + _spritesTable[i].state = state; + _spritesTable[i].gfxBackgroundOffset = 320; +} + +void TuckerEngine::updateSprite_locationNum60_1(int i) { + int state; + if (_flagsTable[186] == 1) { + _flagsTable[186] = 2; + _spritesTable[i].needUpdate = 0; + state = 2; + } else if (_flagsTable[186] == 2) { + state = 6; + _flagsTable[187] = 1; + } else if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + _spritesTable[i].needUpdate = 1; + state = 1; + } else { + _spritesTable[i].needUpdate = 0; + state = (getRandomNumber() > 32000) ? 5 : 4; + } + _spritesTable[i].state = state; + _spritesTable[i].gfxBackgroundOffset = 320; +} + +void TuckerEngine::execData3PostUpdate_locationNum60() { + drawSprite(0); +} + +void TuckerEngine::updateSprite_locationNum61_0(int i) { + int state; + const int r = getRandomNumber(); + if (_flagsTable[88] == 1) { + state = 3; + _flagsTable[88] = 2; + } else if (_flagsTable[88] == 2) { + state = -1; + } else if (_charSpeechSoundCounter > 0 && _actionCharacterNum == 0) { + if (_spritesTable[i].needUpdate == 0) { + _spritesTable[i].needUpdate = 1; + state = 2; + } else { + state = 2; + _spritesTable[0].animationFrame = 2; + _updateSpriteFlag1 = 1; + } + } else { + _spritesTable[i].needUpdate = 0; + if (r < 30000) { + state = 7; + _spritesTable[i].updateDelay = 5; + } else if (r < 31000) { + state = 7; + } else if (r < 32000) { + state = 5; + } else { + state = 6; + } + } + _spritesTable[i].state = state; +} + +void TuckerEngine::updateSprite_locationNum61_1(int i) { + int state; + if (_flagsTable[151] == 1) { + state = -1; + } else if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + _spritesTable[i].needUpdate = 1; + state = 14; + } else if (_csDataHandled || getRandomNumber() < 29000) { + _spritesTable[i].needUpdate = 0; + state = 12; + _spritesTable[i].updateDelay = 5; + } else if (getRandomNumber() < 20000) { + state = 12; + } else { + state = 13; + } + _spritesTable[i].state = state; + _spritesTable[i].gfxBackgroundOffset = 320; +} + +void TuckerEngine::updateSprite_locationNum61_2(int i) { + int state; + const int r = getRandomNumber(); + _flagsTable[150] = 1; + if (_flagsTable[198] == 2) { + _flagsTable[150] = 2; + state = 16; + } else if (_flagsTable[198] == 1) { + if (_flagsTable[150] == 2) { + state = 10; + } else { + state = 18; + } + _flagsTable[198] = 2; + _flagsTable[150] = 0; + } else if (r < 32000) { + state = 15; + } else if (r < 32100) { + state = 1; + if (_xPosCurrent < 340 || _xPosCurrent > 380) { + _flagsTable[150] = 0; + if (_flagsTable[136] == 0) { + state = 17; + } + } else { + state = 15; + } + } else if (r < 32200) { + state = 4; + } else if (r < 32300) { + state = 8; + } else { + state = 9; + } + _flagsTable[248] = _flagsTable[150]; + if (_flagsTable[136] != 2) { + _flagsTable[150] = 0; + } + _spritesTable[i].state = state; + _spritesTable[i].gfxBackgroundOffset = 320; +} + +void TuckerEngine::execData3PreUpdate_locationNum61() { + if (_inventoryItemsState[36] == 1) { + _flagsTable[93] = (_inventoryItemsState[6] == 1) ? 3 : 1; + } else { + _flagsTable[93] = (_inventoryItemsState[6] == 1) ? 2 : 0; + } + _flagsTable[154] = _inventoryItemsState[16]; + if (_inventoryItemsState[16] == 2 && _inventoryItemsState[36] == 2) { + if (!_csDataHandled && _flagsTable[88] == 0) { + _flagsTable[88] = 1; + } + } +} + +void TuckerEngine::updateSprite_locationNum63_0(int i) { + int state; + if (_flagsTable[136] > 0 && _flagsTable[132] == 2) { + state = 12; + } else if (_flagsTable[132] != 2 || _flagsTable[133] != 1 || _flagsTable[136] > 0) { + state = -1; + } else if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + _spritesTable[i].needUpdate = 1; + state = 6; + } else { + _spritesTable[i].needUpdate = 0; + state = -1; + } + _spritesTable[i].state = state; +} + +void TuckerEngine::updateSprite_locationNum63_1(int i) { + int state = -1; + if (_flagsTable[132] == 2 && _flagsTable[133] == 1 && _flagsTable[136] > 0) { + state = -1; + } else if (getRandomNumber() > 30000) { + state = 5; + } else if (getRandomNumber() > 30000) { + state = 8; + } + _spritesTable[i].state = state; +} + +void TuckerEngine::updateSprite_locationNum63_2(int i) { + ++_spritesTable[i].counter; + int state = -1; + if (_flagsTable[132] == 2 && _flagsTable[133] == 1 && _flagsTable[136] > 0) { + if (_flagsTable[226] == 0) { + state = 9; + _spritesTable[i].updateDelay = 5; + } else if (_flagsTable[226] == 1) { + state = 9; + _flagsTable[226] = 2; + } else if (_flagsTable[226] == 2) { + state = 3; + } else { + _flagsTable[226] = 0; + state = 10; + } + } + _spritesTable[i].state = state; +} + +void TuckerEngine::updateSprite_locationNum63_3(int i) { + ++_spritesTable[i].counter; + int state = -1; + if (_flagsTable[133] == 1 && _flagsTable[132] == 2 && _flagsTable[136] > 0) { + if (_spritesTable[i].counter > 80) { + state = 7; + _spritesTable[i].counter = 0; + } else if (getRandomNumber() > 32000) { + state = 2; + } else if (getRandomNumber() > 32000) { + state = 4; + } else if (getRandomNumber() > 28000) { + state = 8; + } + } + _spritesTable[i].state = state; +} + +void TuckerEngine::updateSprite_locationNum63_4(int i) { + int state = -1; + if (_flagsTable[132] == 2 && _flagsTable[133] == 1 && _flagsTable[136] == 0) { + state = 1; + } + _spritesTable[i].state = state; +} + +void TuckerEngine::execData3PreUpdate_locationNum63() { + _currentGfxBackgroundCounter = 20 - _flagsTable[132] * 10; + if (_flagsTable[132] != _execData3Counter) { + _execData3Counter = _flagsTable[132]; + } + if (_flagsTable[133] == 0) { + _currentGfxBackgroundCounter = 30; + } + if (_flagsTable[136] > 0 && _flagsTable[132] == 2) { + _currentGfxBackgroundCounter = 20; + } + if (_flagsTable[133] == 0) { + for (int i = 0; i < 3; ++i) { + if (isSoundPlaying(i)) { + stopSound(i); + } + } + } else { + if (_flagsTable[132] == 0 || _flagsTable[132] == 2 || _flagsTable[136] > 0) { + if (!isSoundPlaying(1)) { + _locationSoundsTable[1].type = 2; + startSound(_locationSoundsTable[1].offset, 1, _locationSoundsTable[1].volume); + } + } else { + if (isSoundPlaying(1)) { + stopSound(1); + } + } + if (_flagsTable[132] == 1) { + if (!isSoundPlaying(0)) { + _locationSoundsTable[0].type = 2; + startSound(_locationSoundsTable[0].offset, 0, _locationSoundsTable[0].volume); + } + } else { + if (isSoundPlaying(1)) { + stopSound(1); + } + } + if (_flagsTable[132] == 2 && _flagsTable[136] == 0) { + if (!isSoundPlaying(2)) { + startSound(_locationSoundsTable[2].offset, 2, _locationSoundsTable[2].volume); + } + } else { + if (isSoundPlaying(2)) { + stopSound(2); + } + } + } +} + +void TuckerEngine::execData3PreUpdate_locationNum64() { + if (_currentGfxBackgroundCounter < 30) { + _locationHeightTable[64] = 48 - (_currentGfxBackgroundCounter / 10); + } else { + _locationHeightTable[64] = 47; + } +} + +void TuckerEngine::updateSprite_locationNum65(int i) { + int state; + if (_flagsTable[188] == 1) { + _flagsTable[188] = 2; + state = 1; + _spritesTable[i].gfxBackgroundOffset = 100; + } else if (_flagsTable[188] > 0 && _flagsTable[189] > 0) { + state = -1; + if (_xPosCurrent < 150 || _yPosCurrent > 240) { + _flagsTable[189] = 0; + } + } else { + if (_xPosCurrent >= 150 && _yPosCurrent < 240) { // XXX bug + if (getRandomNumber() > 32000) { + state = 2; + _flagsTable[189] = 1; + } else { + state = -1; + } + } else { + state = -1; + _flagsTable[189] = 0; + } + } + _spritesTable[i].state = state; +} + +void TuckerEngine::execData3PreUpdate_locationNum65() { + _flagsTable[137]= 0; +} + +void TuckerEngine::updateSprite_locationNum66_0(int i) { + int state; + if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + _spritesTable[i].needUpdate = 1; + state = 2; + } else { + _spritesTable[i].needUpdate = 0; + state = 2; + _spritesTable[i].updateDelay = 5; + } + _spritesTable[i].state = state; + _spritesTable[i].gfxBackgroundOffset = 320; +} + +void TuckerEngine::updateSprite_locationNum66_1(int i) { + int state; + if (_flagsTable[191] == 0 && _xPosCurrent > 568) { + if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + _spritesTable[i].needUpdate = 1; + state = 8; + } else if (getRandomNumber() > 30000) { + state = 10; + _spritesTable[i].needUpdate = 0; + } else { + state = 10; + _spritesTable[i].needUpdate = 0; + } + } else { + if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + _spritesTable[i].needUpdate = 1; + state = 9; + } else if (getRandomNumber() > 30000) { + state = 6; + _spritesTable[i].needUpdate = 0; + } else { + _spritesTable[i].needUpdate = 0; + state = 7; + _spritesTable[i].updateDelay = 5; + } + } + _spritesTable[i].state = state; + _spritesTable[i].gfxBackgroundOffset = 320; +} + +void TuckerEngine::updateSprite_locationNum66_2(int i) { + _spritesTable[i].disabled = 1; + _spritesTable[i].state = 3; +} + +void TuckerEngine::updateSprite_locationNum66_3(int i) { + _spritesTable[i].state = 4; +} + +void TuckerEngine::updateSprite_locationNum66_4(int i) { + _spritesTable[i].state = 5; + _spritesTable[i].gfxBackgroundOffset = 320; +} + +void TuckerEngine::execData3PreUpdate_locationNum66() { + _flagsTable[137]= 0; + if (_xPosCurrent > 583 && _flagsTable[191] == 0 && _nextAction == 0 && _locationMaskType == 0) { + _panelLockedFlag = 0; + _csDataLoaded = 0; + _nextLocationNum = 0; + _selectedObject.locationObject_locationNum = 0; + if (_flagsTable[131] == 0) { + _nextAction = 13; + } else if (_flagsTable[130] == 0) { + _nextAction = 14; + } else { + _nextAction = 35; + } + } +} + +void TuckerEngine::execData3PostUpdate_locationNum66() { + if (_spritesTable[2].flipX == 1) { + --_updateLocationXPosTable2[0]; + if (_updateLocationXPosTable2[0] < -50) { + _updateLocationXPosTable2[0] = 0; + _updateLocationXPosTable2[0] = -50; + } + } else { + ++_updateLocationXPosTable2[0]; + if (_updateLocationXPosTable2[0] > 500) { + _updateLocationXPosTable2[0] = 1; + _updateLocationXPosTable2[0] = 500; + } + } + _spritesTable[2].gfxBackgroundOffset = _updateLocationXPosTable2[0] + 8320; + const int spr = 2; + _spritesTable[spr].colorType = 1; + _spritesTable[spr].yMaxBackground = 0; + drawSprite(spr); + _spritesTable[spr].colorType = 0; +} + +void TuckerEngine::updateSprite_locationNum69_1(int i) { + int state; + if (_flagsTable[236] == 1) { + state = 4; + } else if (_flagsTable[236] == 2) { + state = 3; + } else if (_flagsTable[236] == 3) { + state = 2; + } else if (_flagsTable[236] == 4) { + if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + state = 9; + _spritesTable[i].needUpdate = 1; + } else { + state = 14; + _spritesTable[i].needUpdate = 0; + } + } else if (_flagsTable[236] == 5) { + state = 7; + _flagsTable[236] = 6; + } else { + state = -1; + } + _spritesTable[i].state = state; +} + +void TuckerEngine::updateSprite_locationNum69_2(int i) { + if (_flagsTable[237] == 2) { + _flagsTable[237] = 3; + } + int state; + if (_flagsTable[236] < 4 || _flagsTable[237] == 0) { + state = -1; + } else if (_flagsTable[237] == 1) { + state = 5; + _flagsTable[237] = 2; + } else if (_flagsTable[237] == 4 || _flagsTable[237] == 2 || _flagsTable[237] == 3 || _flagsTable[237] == 7) { + if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + state = 10; + _spritesTable[i].needUpdate = 1; + } else { + state = 12; + _spritesTable[i].needUpdate = 0; + } + } else if (_flagsTable[237] == 5) { + state = 16; + _flagsTable[237] = 6; + } else if (_flagsTable[237] == 6) { + state = 15; + _flagsTable[237] = 7; + } else if (_flagsTable[237] == 8) { + state = 6; + _flagsTable[237] = 9; + } else { + state = -1; + } + _spritesTable[i].state = state; +} + +void TuckerEngine::updateSprite_locationNum69_3(int i) { + int state; + if (_flagsTable[236] > 4) { + state = -1; + } else if (_flagsTable[237] == 3) { + state = 8; + _flagsTable[237] = 4; + } else if (_flagsTable[237] > 2 && _flagsTable[237] < 9) { + _flagsTable[238] = 1; + if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + state = 11; + _spritesTable[i].needUpdate = 1; + } else { + state = 13; + _spritesTable[i].needUpdate = 0; + } + } else { + state = -1; + } + _spritesTable[i].state = state; +} + +void TuckerEngine::execData3PreUpdate_locationNum70() { + const uint8 color = 103; + if (_execData3Counter == 0) { + startSound(_locationSoundsTable[6].offset, 6, _locationSoundsTable[6].volume); + _execData3Counter = 1; + _flagsTable[143] = 0; + _updateLocation70StringLen = 0; + _forceRedrawPanelItems = 1; + _panelState = 1; + setCursorType(2); + } + _forceRedrawPanelItems = 1; + _panelState = 1; + setCursorType(2); + int pos = getPositionForLine(22, _infoBarBuf); + int offset = (_flagsTable[143] == 0) ? 57688 : 46168; + drawStringAlt(_locationBackgroundGfxBuf + offset, color, &_infoBarBuf[pos]); + Graphics::drawStringChar(_locationBackgroundGfxBuf + offset + 5760, 62, 640, color, _charsetGfxBuf); + if (_flagsTable[143] != 0) { + pos = getPositionForLine(_flagsTable[143] * 2 + 23, _infoBarBuf); + drawStringAlt(_locationBackgroundGfxBuf + offset + 11520, color, &_infoBarBuf[pos]); + pos = getPositionForLine(_flagsTable[143] * 2 + 24, _infoBarBuf); + drawStringAlt(_locationBackgroundGfxBuf + offset + 17280, color, &_infoBarBuf[pos]); + } + execData3PreUpdate_locationNum70Helper(); + drawStringAlt(_locationBackgroundGfxBuf + offset + 5768, color, _updateLocation70String, _updateLocation70StringLen); +} + +void TuckerEngine::execData3PreUpdate_locationNum70Helper() { + if (_lastKeyPressed != 0 && _flagsTable[143] <= 0) { + if (_lastKeyPressed == Common::KEYCODE_BACKSPACE || _lastKeyPressed == Common::KEYCODE_DELETE) { + if (_updateLocation70StringLen > 0) { + --_updateLocation70StringLen; + startSound(_locationSoundsTable[0].offset, 0, _locationSoundsTable[0].volume); + } + } else if (_lastKeyPressed == Common::KEYCODE_RETURN) { + _flagsTable[143] = 1; + _nextAction = 1; + _csDataLoaded = false; + const int pos = getPositionForLine(23, _infoBarBuf); + if (memcmp(&_infoBarBuf[pos + 3], _updateLocation70String, 16) != 0) { + _flagsTable[143] = 2; + } + const int num = (_flagsTable[143] == 1) ? 4 : 5; + startSound(_locationSoundsTable[num].offset, num, _locationSoundsTable[num].volume); + } else if (_updateLocation70StringLen < 19) { + uint8 chr = 0; + switch (_lastKeyPressed) { + case Common::KEYCODE_SPACE: + chr = 32; + break; + case Common::KEYCODE_BACKQUOTE: + chr = 35; + break; + case Common::KEYCODE_LEFTPAREN: + chr = 40; + break; + case Common::KEYCODE_RIGHTPAREN: + chr = 41; + break; + case Common::KEYCODE_LESS: + chr = 44; + break; + case Common::KEYCODE_GREATER: + chr = 46; + break; + case Common::KEYCODE_COLON: + chr = 56; + break; + case Common::KEYCODE_QUESTION: + chr = 92; + break; + case Common::KEYCODE_QUOTE: + chr = 96; + break; + default: + if (_lastKeyPressed >= Common::KEYCODE_a && _lastKeyPressed >= Common::KEYCODE_z) { + chr = 'A' + (_lastKeyPressed - Common::KEYCODE_a); + } + break; + } + startSound(_locationSoundsTable[0].offset, 0, _locationSoundsTable[0].volume); + if (chr > 0) { + _updateLocation70String[_updateLocation70StringLen] = chr; + ++_updateLocation70StringLen; + } + } + } +} + +void TuckerEngine::updateSprite_locationNum71(int i) { + int state; + if (_flagsTable[155] != 6 || _flagsTable[207] == 1) { + state = -1; + } else if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + _spritesTable[i].needUpdate = 1; + state = 1; + } else if (getRandomNumber() < 30000) { + _spritesTable[i].needUpdate = 0; + state = 2; + _spritesTable[i].updateDelay = 5; + } else { + _spritesTable[i].needUpdate = 0; + state = 2; + } + _spritesTable[i].state = state; +} + +void TuckerEngine::updateSprite_locationNum72(int i) { + int state; + if (_flagsTable[155] != 7 || _flagsTable[207] == 1) { + state = -1; + } else if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + _spritesTable[i].needUpdate = 1; + state = 2; + } else { + _spritesTable[i].needUpdate = 0; + state = 1; + } + _spritesTable[i].state = state; +} + +void TuckerEngine::updateSprite_locationNum74(int i) { + static const uint8 stateTable[] = { 1, 3, 5, 5, 10, 16, 16 }; + int num = _flagsTable[236] - 74; + if (stateTable[num] + i == 21) { + if (_updateLocationFlag == 0) { + _updateLocationFlag = 1; + } else { + _spritesTable[i].animationFrame = _spritesTable[i].firstFrame - 1; + _spritesTable[i].updateDelay = 5; + _updateSpriteFlag1 = 1; + } + } + _spritesTable[i].state = stateTable[num] + i; +} + +void TuckerEngine::updateSprite_locationNum79(int i) { + int state; + if (_flagsTable[227] == 0) { + state = 1; + _flagsTable[227] = 1; + } else if (_flagsTable[227] == 1 && _charSpeechSoundCounter > 0) { + state = 2; + _spritesTable[i].needUpdate = 1; + } else if (_flagsTable[227] == 2) { + state = 3; + _flagsTable[227] = 3; + _spritesTable[i].needUpdate = 1; + } else { + _spritesTable[i].animationFrame = _spritesTable[i].firstFrame - 1; + _spritesTable[i].updateDelay = 5; + _updateSpriteFlag1 = 1; + state = 3; + } + _spritesTable[i].state = state; +} + +void TuckerEngine::updateSprite_locationNum81_0(int i) { + int state; + if (_charSpeechSoundCounter > 0 && _actionCharacterNum == i) { + _spritesTable[i].needUpdate = 1; + state = 3; + _flagsTable[288] = 1; + } else if (_flagsTable[288] < 2) { + _spritesTable[i].needUpdate = 0; + state = 2; + if (_flagsTable[288] == 1) { + _flagsTable[288] = 2; + } + } else { + _spritesTable[i].animationFrame = _spritesTable[i].firstFrame - 1; + _spritesTable[i].updateDelay = 5; + _updateSpriteFlag1 = 1; + state = 2; + } + _spritesTable[i].state = state; +} + +void TuckerEngine::updateSprite_locationNum81_1(int i) { + _spritesTable[i].state = 1; +} + +void TuckerEngine::updateSprite_locationNum82(int i) { + int state; + if (_charSpeechSoundCounter > 0) { + state = 1; + _flagsTable[229] = 1; + _spritesTable[i].needUpdate = 1; + } else if (_flagsTable[229] == 0) { + state = 1; + } else if (_flagsTable[229] == 1) { + state = 2; + _flagsTable[229] = 2; + _spritesTable[i].needUpdate = 0; + } else { + _spritesTable[i].animationFrame = _spritesTable[i].firstFrame - 1; + _spritesTable[i].updateDelay = 5; + _updateSpriteFlag1 = 1; + state = 2; + } + _spritesTable[i].state = state; +} + +} // namespace Tucker diff --git a/engines/tucker/module.mk b/engines/tucker/module.mk new file mode 100644 index 0000000000..4847fdc3ec --- /dev/null +++ b/engines/tucker/module.mk @@ -0,0 +1,19 @@ +MODULE := engines/tucker + +MODULE_OBJS := \ + detection.o \ + graphics.o \ + locations.o \ + resource.o \ + saveload.o \ + sequences.o \ + staticres.o \ + tucker.o + +# This module can be built as a plugin +ifeq ($(ENABLE_TUCKER), DYNAMIC_PLUGIN) +PLUGIN := 1 +endif + +# Include common rules +include $(srcdir)/rules.mk diff --git a/engines/tucker/resource.cpp b/engines/tucker/resource.cpp new file mode 100644 index 0000000000..eb12741b4b --- /dev/null +++ b/engines/tucker/resource.cpp @@ -0,0 +1,959 @@ +/* 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/file.h" + +#include "sound/audiostream.h" +#include "sound/flac.h" +#include "sound/mp3.h" +#include "sound/vorbis.h" +#include "sound/wave.h" + +#include "tucker/tucker.h" +#include "tucker/graphics.h" + +namespace Tucker { + +enum { + kCurrentCompressedSoundDataVersion = 1, + kCompressedSoundDataFileHeaderSize = 4 +}; + +struct CompressedSoundFile { + const char *filename; + Audio::AudioStream *(*makeStream)(Common::SeekableReadStream *stream, bool disposeAfterUse, uint32 startTime, uint32 duration, uint numLoops); +}; + +static const CompressedSoundFile compressedSoundFilesTable[] = { +#ifdef USE_FLAC + { "TUCKER.SOF", Audio::makeFlacStream }, +#endif +#ifdef USE_VORBIS + { "TUCKER.SOG", Audio::makeVorbisStream }, +#endif +#ifdef USE_MAD + { "TUCKER.SO3", Audio::makeMP3Stream }, +#endif + { 0, 0 } +}; + +static void decodeData(uint8 *data, int dataSize) { + for (int i = 0; i < dataSize; ++i) { + data[i] -= 0x80; + } +} + +static void stripData(uint8 *data, int dataSize) { + bool clearChr = false; + for (int i = 0; i < dataSize; ++i) { + if (!clearChr && data[i] == '/') { + clearChr = true; + } + if (clearChr) { + if (data[i] == '\n') { + clearChr = false; + } + data[i] = ' '; + } + } +} + +enum DataToken { + kDataTokenDw, + kDataTokenEx +}; + +class DataTokenizer { +public: + + DataTokenizer(uint8 *data, int dataSize, bool stripComments = false) + : _data(data), _dataSize(dataSize), _pos(0) { + if (stripComments) { + stripData(_data, _dataSize); + } + } + + int getNextInteger() { + bool negate = false; + int state = 0; + int num = 0; + while (_pos < _dataSize && state != 2) { + switch (state) { + case 0: + if (_data[_pos] == '-') { + state = 1; + negate = true; + } else if (_data[_pos] >= '0' && _data[_pos] <= '9') { + state = 1; + num = _data[_pos] - '0'; + } + break; + case 1: + if (_data[_pos] >= '0' && _data[_pos] <= '9') { + num *= 10; + num += _data[_pos] - '0'; + } else { + state = 2; + } + break; + } + ++_pos; + } + return negate ? -num : num; + } + + bool findNextToken(DataToken t) { + const char *token = 0; + switch (t) { + case kDataTokenDw: + token = "dw"; + break; + case kDataTokenEx: + token = "!!"; + break; + } + int tokenLen = strlen(token); + while (_pos < _dataSize - tokenLen) { + if (memcmp(_data + _pos, token, tokenLen) == 0) { + _pos += tokenLen; + return true; + } + ++_pos; + } + return false; + } + + bool findIndex(int num) { + int i = -1; + while (findNextToken(kDataTokenEx)) { + i = getNextInteger(); + if (i >= num) { + break; + } + } + return i == num; + } + + uint8 *_data; + int _dataSize; + int _pos; +}; + +uint8 *TuckerEngine::loadFile(uint8 *p) { + _fileLoadSize = 0; + if (_useEnc) { + char *ext = strrchr(_fileToLoad, '.'); + if (ext && strcmp(ext + 1, "c") == 0) { + strcpy(ext + 1, "enc"); + } + } + Common::File f; + if (!f.open(_fileToLoad)) { + return 0; + } + const int sz = f.size(); + if (!p) { + p = (uint8 *)malloc(sz); + } + if (p) { + f.read(p, sz); + if (_useEnc) { + decodeData(p, sz); + } + _fileLoadSize = sz; + } + return p; +} + +void TuckerEngine::openCompressedSoundFile() { + _compressedSoundType = -1; + for (int i = 0; compressedSoundFilesTable[i].filename; ++i) { + if (_fCompressedSound.open(compressedSoundFilesTable[i].filename)) { + int version = _fCompressedSound.readUint16LE(); + if (version == kCurrentCompressedSoundDataVersion) { + _compressedSoundType = i; + return; + } + warning("Unhandled version %d for compressed sound file '%s'", version, compressedSoundFilesTable[i].filename); + } + } + _fCompressedSound.readUint32LE(); +} + +void TuckerEngine::loadImage(uint8 *dst, int type) { + int count = 0; + Common::File f; + if (!f.open(_fileToLoad)) { + return; + } + f.seek(128, SEEK_SET); + int size = 0; + while (size < 64000) { + if (type == 2) { + ++count; + if (count > 500) { + count = 0; + isSpeechSoundPlaying(); + } + } + int code = f.readByte(); + if (code >= 0xC0) { + const int sz = code - 0xC0; + code = f.readByte(); + memset(dst + size, code, sz); + size += sz; + } else { + dst[size++] = code; + } + } + if (type != 0) { + f.seek(-768, SEEK_END); + for (int i = 0; i < 256; ++i) { + if (type == 2) { + isSpeechSoundPlaying(); + } + for (int c = 0; c < 3; ++c) { + _currentPalette[3 * i + c] = f.readByte(); + } + } + setBlackPalette(); + } +} + +void TuckerEngine::loadCursor() { + strcpy(_fileToLoad, "pointer.pcx"); + loadImage(_loadTempBuf, 0); + for (int cursor = 0; cursor < 7; ++cursor) { + Graphics::encodeRAW(_loadTempBuf + cursor * 320 * 16, _cursorGfxBuf + cursor * 256, 16, 16); + } +} + +void TuckerEngine::loadCharset() { + strcpy(_fileToLoad, "charset.pcx"); + loadImage(_loadTempBuf, 0); + loadCharsetHelper(kCharSet1CharW, kCharSet1CharH, 32, 7); +} + +void TuckerEngine::loadCharset2() { + _charWidthTable[58] = 7; + _charWidthTable[32] = 15; + for (int i = 0; i < 58; ++i) { + _charWidthTable[65 + i] = _charWidthCharset2[i]; + } + strcpy(_fileToLoad, "char2.pcx"); + loadImage(_loadTempBuf, 0); + loadCharsetHelper(kCharSet2CharW, kCharSet2CharH, 16, 6); +} + +void TuckerEngine::loadCharsetHelper(int charW, int charH, int xSize, int ySize) { + int offset = 0; + for (int y = 0; y < ySize; ++y) { + for (int x = 0; x < xSize; ++x) { + offset += Graphics::encodeRAW(_loadTempBuf + (y * 320) * charH + x * charW, _charsetGfxBuf + offset, charW, charH); + } + } +} + +void TuckerEngine::loadCharSizeDta() { + strcpy(_fileToLoad, "charsize.dta"); + loadFile(_loadTempBuf); + DataTokenizer t(_loadTempBuf, _fileLoadSize, true); + for (int i = 0; i < 256; ++i) { + _charWidthTable[i] = t.getNextInteger(); + } + _charWidthTable[225] = 0; +} + +void TuckerEngine::loadPanel() { + strcpy(_fileToLoad, (_panelNum == 0) ? "panel1.pcx" : "panel2.pcx"); + loadImage(_panelGfxBuf, 0); +} + +void TuckerEngine::loadBudSpr(int startOffset) { + int endOffset; + loadCTable01(0, startOffset, endOffset); + loadCTable02(0); + int frame = 0; + int spriteOffset = 0; + for (int i = startOffset; i < endOffset; ++i) { + if (_ctable01Table_sprite[frame] == i) { + switch (_flagsTable[137]) { + case 0: + sprintf(_fileToLoad, "bud_%d.pcx", frame + 1); + break; + case 1: + sprintf(_fileToLoad, "peg_%d.pcx", frame + 1); + break; + default: + sprintf(_fileToLoad, "mac_%d.pcx", frame + 1); + break; + } + loadImage(_loadTempBuf, 0); + ++frame; + } + int sz = Graphics::encodeRLE(_loadTempBuf + _spriteFramesTable[i].sourceOffset, _spritesGfxBuf + spriteOffset, _spriteFramesTable[i].xSize, _spriteFramesTable[i].ySize); + _spriteFramesTable[i].sourceOffset = spriteOffset; + spriteOffset += sz; + } +} + +void TuckerEngine::loadCTable01(int locationNum, int firstSpriteNum, int &lastSpriteNum) { + strcpy(_fileToLoad, "ctable01.c"); + loadFile(_loadTempBuf); + DataTokenizer t(_loadTempBuf, _fileLoadSize); + lastSpriteNum = firstSpriteNum; + int count = 0; + if (t.findIndex(_locationNum)) { + while (t.findNextToken(kDataTokenDw)) { + const int x = t.getNextInteger(); + if (x < 0) { + break; + } else if (x == 999) { + _ctable01Table_sprite[count] = lastSpriteNum; + ++count; + continue; + } + const int y = t.getNextInteger(); + SpriteFrame *c = &_spriteFramesTable[lastSpriteNum++]; + c->sourceOffset = y * 320 + x; + c->xSize = t.getNextInteger(); + c->ySize = t.getNextInteger(); + c->xOffset = t.getNextInteger(); + if (c->xOffset > 300) { + c->xOffset -= 500; + } + c->yOffset = t.getNextInteger(); + if (c->yOffset > 300) { + c->yOffset -= 500; + } + } + } + _ctable01Table_sprite[count] = -1; +} + +void TuckerEngine::loadCTable02(int fl) { + assert(fl == 0); + int entry = 0; + int i = 0; + strcpy(_fileToLoad, "ctable02.c"); + loadFile(_loadTempBuf); + DataTokenizer t(_loadTempBuf, _fileLoadSize); + while (t.findNextToken(kDataTokenDw)) { + _spriteAnimationsTable[entry].numParts = t.getNextInteger(); + if (_spriteAnimationsTable[entry].numParts < 1) { + return; + } + _spriteAnimationsTable[entry].rotateFlag = t.getNextInteger(); + int num = t.getNextInteger(); + if (num != fl) { + continue; + } + int start = 0; + _spriteAnimationsTable[entry].firstFrameIndex = i; + while (start != 999) { + start = t.getNextInteger(); + _spriteAnimationFramesTable[i] = start; + ++i; + } + ++entry; + } +} + +void TuckerEngine::loadLoc() { + int i = _locationWidthTable[_locationNum]; + _locationHeight = (_locationNum < 73) ? 140 : 200; + strcpy(_fileToLoad, (i == 1) ? "loc00.pcx" : "loc00a.pcx"); + copyLocBitmap(0, 0); + Graphics::copyFrom640(_locationBackgroundGfxBuf, _quadBackgroundGfxBuf, 320, _locationHeight); + if (_locationHeight == 200) { + return; + } + strcpy(_fileToLoad, (i != 2) ? "path00.pcx" : "path00a.pcx"); + copyLocBitmap(0, 1); + if (i > 1) { + strcpy(_fileToLoad, "loc00b.pcx"); + copyLocBitmap(320, 0); + Graphics::copyFrom640(_locationBackgroundGfxBuf + 320, _quadBackgroundGfxBuf + 44800, 320, 140); + if (i == 2) { + strcpy(_fileToLoad, "path00b.pcx"); + copyLocBitmap(320, 1); + } + } + if (i > 2) { + strcpy(_fileToLoad, "loc00c.pcx"); + copyLocBitmap(0, 0); + Graphics::copyFrom640(_locationBackgroundGfxBuf, _quadBackgroundGfxBuf + 89600, 320, 140); + } + if (_locationNum == 1) { + strcpy(_fileToLoad, "rochpath.pcx"); + _loadLocBufPtr = _quadBackgroundGfxBuf + 89600; + loadImage(_loadLocBufPtr, 0); + } + if (i > 3) { + strcpy(_fileToLoad, "loc00d.pcx"); + copyLocBitmap(0, 0); + Graphics::copyFrom640(_locationBackgroundGfxBuf + 320, _quadBackgroundGfxBuf + 134400, 320, 140); + } +} + +void TuckerEngine::loadObj() { + if (_locationNum == 99) { + return; + } + if (_locationNum < 24) { + _partNum = 1; + _speechSoundBaseNum = 2639; + } else if (_locationNum < 41 || (_locationNum >= 69 && _locationNum < 73) || (_locationNum > 79 && _locationNum < 83)) { + _partNum = 2; + _speechSoundBaseNum = 2679; + } else { + _partNum = 3; + _speechSoundBaseNum = 2719; + } + if (_partNum == _currentPartNum) { + return; + } + handleNewPartSequence(); + _currentPartNum = _partNum; + + sprintf(_fileToLoad, "objtxt%d.c", _partNum); + free(_objTxtBuf); + _objTxtBuf = loadFile(); + sprintf(_fileToLoad, "pt%dtext.c", _partNum); + free(_ptTextBuf); + _ptTextBuf = loadFile(); + + loadData(); + loadPanObj(); +} + +void TuckerEngine::loadData() { + int flag = 0; + int objNum = _partNum * 10; + strcpy(_fileToLoad, "data.c"); + loadFile(_loadTempBuf); + DataTokenizer t(_loadTempBuf, _fileLoadSize); + _dataCount = 0; + int count = 0; + int maxCount = 0; + while (flag < 2) { + flag = 0; + if (!t.findIndex(objNum)) { + flag = 2; + } + while (flag == 0) { + if (!t.findNextToken(kDataTokenDw)) { + flag = 1; + continue; + } + _dataCount = t.getNextInteger(); + if (_dataCount < 0) { + flag = 1; + continue; + } + if (_dataCount > maxCount) { + maxCount = _dataCount; + } + const int x = t.getNextInteger(); + const int y = t.getNextInteger(); + _dataTable[_dataCount].sourceOffset = y * 320 + x; + _dataTable[_dataCount].xSize = t.getNextInteger(); + _dataTable[_dataCount].ySize = t.getNextInteger(); + _dataTable[_dataCount].xDest = t.getNextInteger(); + _dataTable[_dataCount].yDest = t.getNextInteger(); + _dataTable[_dataCount].index = count; + } + if (flag < 2) { + ++objNum; + ++count; + } + } + _dataCount = maxCount; + int offset = 0; + for (int i = 0; i < count; ++i) { + sprintf(_fileToLoad, "scrobj%d%d.pcx", _partNum, i); + loadImage(_loadTempBuf, 0); + offset = loadDataHelper(offset, i); + } +} + +int TuckerEngine::loadDataHelper(int offset, int index) { + for (int i = 0; i < _dataCount + 1; ++i) { + if (_dataTable[i].index == index) { + int sz = Graphics::encodeRLE(_loadTempBuf + _dataTable[i].sourceOffset, _data3GfxBuf + offset, _dataTable[i].xSize, _dataTable[i].ySize); + _dataTable[i].sourceOffset = offset; + offset += sz; + } + } + return offset; +} + +void TuckerEngine::loadPanObj() { + sprintf(_fileToLoad, "panobjs%d.pcx", _partNum); + loadImage(_loadTempBuf, 0); + int offset = 0; + for (int y = 0; y < 5; ++y) { + for (int x = 0; x < 10; ++x) { + const int i = y * 10 + x; + _panelObjectsOffsetTable[i] = offset; + offset += Graphics::encodeRLE(_loadTempBuf + (y * 240 + x) * 32, _panelObjectsGfxBuf + offset, 32, 24); + } + } +} + +void TuckerEngine::loadData3() { + strcpy(_fileToLoad, "data3.c"); + loadFile(_loadTempBuf); + DataTokenizer t(_loadTempBuf, _fileLoadSize); + _locationAnimationsCount = 0; + if (t.findIndex(_locationNum)) { + while (t.findNextToken(kDataTokenDw)) { + int num = t.getNextInteger(); + if (num < 0) { + break; + } + assert(_locationAnimationsCount < kLocationAnimationsTableSize); + LocationAnimation *d = &_locationAnimationsTable[_locationAnimationsCount++]; + d->graphicNum = num; + const int seqNum = t.getNextInteger(); + int i = 0; + int j = 1; + if (seqNum > 0) { + while (j < seqNum) { + while (_staticData3Table[i] != 999) { + ++i; + } + ++i; + ++j; + } + d->animCurrentCounter = d->animInitCounter = i; + while (_staticData3Table[i + 1] != 999) { + ++i; + } + d->animLastCounter = i; + } else { + d->animLastCounter = 0; + } + d->getFlag = t.getNextInteger(); + d->inventoryNum = t.getNextInteger(); + d->flagNum = t.getNextInteger(); + d->flagValue = t.getNextInteger(); + d->selectable = t.getNextInteger(); + d->standX = t.getNextInteger(); + d->standY = t.getNextInteger(); + d->drawFlag = 0; + } + } +} + +void TuckerEngine::loadData4() { + strcpy(_fileToLoad,"data4.c"); + loadFile(_loadTempBuf); + DataTokenizer t(_loadTempBuf, _fileLoadSize); + t.findNextToken(kDataTokenDw); + _data4FlagDebug = t.getNextInteger(); + _displayGameHints = t.getNextInteger(); + // forces game hints feature +// _displayGameHints = 1; + _locationObjectsCount = 0; + if (t.findIndex(_locationNum)) { + while (t.findNextToken(kDataTokenDw)) { + int i = t.getNextInteger(); + if (i < 0) { + break; + } + assert(_locationObjectsCount < kLocationObjectsTableSize); + LocationObject *d = &_locationObjectsTable[_locationObjectsCount++]; + d->xPos = i; + d->yPos = t.getNextInteger(); + d->xSize = t.getNextInteger(); + d->ySize = t.getNextInteger(); + d->standX = t.getNextInteger(); + d->standY = t.getNextInteger(); + d->textNum = t.getNextInteger(); + d->cursorNum = t.getNextInteger(); + d->locationNum = t.getNextInteger(); + if (d->locationNum > 0) { + d->toX = t.getNextInteger(); + d->toY = t.getNextInteger(); + d->toX2 = t.getNextInteger(); + d->toY2 = t.getNextInteger(); + d->toWalkX2 = t.getNextInteger(); + d->toWalkY2 = t.getNextInteger(); + } + } + } +} + +void TuckerEngine::loadActionFile() { + switch (_partNum) { + case 1: + strcpy(_fileToLoad, "action1.c"); + break; + case 2: + strcpy(_fileToLoad, "action2.c"); + break; + default: + strcpy(_fileToLoad, "action3.c"); + break; + } + loadFile(_loadTempBuf); + DataTokenizer t(_loadTempBuf, _fileLoadSize); + _actionsCount = 0; + if (t.findIndex(_locationNum)) { + while (t.findNextToken(kDataTokenDw)) { + int keyA = t.getNextInteger(); + if (keyA < 0) { + break; + } + int keyB = t.getNextInteger(); + int keyC = t.getNextInteger(); + int keyD = t.getNextInteger(); + int keyE = t.getNextInteger(); + Action *action = &_actionsTable[_actionsCount++]; + action->key = keyE * 1000000 + keyD * 100000 + keyA * 10000 + keyB * 1000 + keyC; + action->testFlag1Num = t.getNextInteger(); + action->testFlag1Value = t.getNextInteger(); + action->testFlag2Num = t.getNextInteger(); + action->testFlag2Value = t.getNextInteger(); + action->speech = t.getNextInteger(); + action->flipX = t.getNextInteger(); + action->index = t.getNextInteger(); + action->delay = t.getNextInteger(); + action->setFlagNum = t.getNextInteger(); + action->setFlagValue = t.getNextInteger(); + action->fxNum = t.getNextInteger(); + action->fxDelay = t.getNextInteger(); + } + } +} + +void TuckerEngine::loadCharPos() { + strcpy(_fileToLoad, "charpos.c"); + loadFile(_loadTempBuf); + DataTokenizer t(_loadTempBuf, _fileLoadSize); + _charPosCount = 0; + if (t.findIndex(_locationNum)) { + while (t.findNextToken(kDataTokenDw)) { + const int i = t.getNextInteger(); + if (i < 0) { + break; + } + assert(_charPosCount < 4); + CharPos *charPos = &_charPosTable[_charPosCount++]; + charPos->xPos = i; + charPos->yPos = t.getNextInteger(); + charPos->xSize = t.getNextInteger(); + charPos->ySize = t.getNextInteger(); + charPos->xWalkTo = t.getNextInteger(); + charPos->yWalkTo = t.getNextInteger(); + charPos->flagNum = t.getNextInteger(); + charPos->flagValue = t.getNextInteger(); + charPos->direction = t.getNextInteger(); + charPos->name = t.getNextInteger(); + charPos->description = t.getNextInteger(); + } + } + int quitLoop = 0; + size_t count = 0; + while (quitLoop == 0) { + t.findNextToken(kDataTokenDw); + int num = 0; + while (num != 99) { + num = t.getNextInteger(); + assert(count < ARRAYSIZE(_characterAnimationsTable)); + _characterAnimationsTable[count] = num; + if (num < 0) { + quitLoop = 1; + break; + } + ++count; + } + } + quitLoop = 0; + count = 0; + while (quitLoop == 0) { + t.findNextToken(kDataTokenDw); + int num = 0; + while (num < 98) { + num = t.getNextInteger(); + assert(count < ARRAYSIZE(_characterStateTable)); + _characterStateTable[count] = num; + if (num == 98) { + --count; + } + if (num < 0) { + quitLoop = 1; + break; + } + ++count; + } + } +} + +void TuckerEngine::loadSprA02_01() { + for (int i = 1; i < kSprA02TableSize; ++i) { + free(_sprA02Table[i]); + _sprA02Table[i] = 0; + } + const int count = _sprA02LookupTable[_locationNum]; + for (int i = 1; i < count + 1; ++i) { + sprintf(_fileToLoad, "sprites/a%02d_%02d.spr", _locationNum, i); + _sprA02Table[i] = loadFile(); + } + _sprA02Table[0] = _sprA02Table[1]; +} + +void TuckerEngine::loadSprC02_01() { + for (int i = 1; i < kSprC02TableSize; ++i) { + free(_sprC02Table[i]); + _sprC02Table[i] = 0; + } + const int count = _sprC02LookupTable[_locationNum]; + for (int i = 1; i < count + 1; ++i) { + sprintf(_fileToLoad, "sprites/c%02d_%02d.spr", _locationNum, i); + _sprC02Table[i] = loadFile(); + } + _sprC02Table[0] = _sprC02Table[1]; + _spritesCount = _sprC02LookupTable2[_locationNum]; + for (int i = 0; i < kMaxCharacters; ++i) { + memset(&_spritesTable[i], 0, sizeof(Sprite)); + _spritesTable[i].state = -1; + _spritesTable[i].stateIndex = -1; + } +} + +void TuckerEngine::loadFx() { + strcpy(_fileToLoad, "fx.c"); + loadFile(_loadTempBuf); + DataTokenizer t(_loadTempBuf, _fileLoadSize); + t.findIndex(_locationNum); + t.findNextToken(kDataTokenDw); + _locationSoundsCount = t.getNextInteger(); + _locationSoundsTable[0].offset = 0; + _currentFxSet = 0; + for (int i = 0; i < _locationSoundsCount; ++i) { + _locationSoundsTable[i].num = t.getNextInteger(); + _locationSoundsTable[i].volume = t.getNextInteger(); + _locationSoundsTable[i].type = t.getNextInteger(); + if (_locationSoundsTable[i].type == 5) { + _currentFxSet = 1; + _currentFxIndex = i; + _currentFxVolume = _locationSoundsTable[i].volume; + _currentFxDist = t.getNextInteger(); + _currentFxScale = t.getNextInteger(); + } else if (_locationSoundsTable[i].type == 6 || _locationSoundsTable[i].type == 7 || _locationSoundsTable[i].type == 8) { + _locationSoundsTable[i].startFxSpriteState = t.getNextInteger(); + _locationSoundsTable[i].startFxSpriteNum = t.getNextInteger(); + _locationSoundsTable[i].updateType = t.getNextInteger(); + if (_locationSoundsTable[i].type == 7) { + _locationSoundsTable[i].flagNum = t.getNextInteger(); + _locationSoundsTable[i].flagValueStartFx = t.getNextInteger(); + _locationSoundsTable[i].stopFxSpriteState = t.getNextInteger(); + _locationSoundsTable[i].stopFxSpriteNum = t.getNextInteger(); + _locationSoundsTable[i].flagValueStopFx = t.getNextInteger(); + } + } + if (_locationSoundsTable[i].type == 8) { + _locationSoundsTable[i].type = 6; + } + } + t.findNextToken(kDataTokenDw); + int count = t.getNextInteger(); + _locationMusicsTable[0].offset = _locationSoundsTable[_locationSoundsCount].offset; + _locationMusicsCount = 0; + for (int i = 0; i < count; ++i) { + int flagNum = t.getNextInteger(); + int flagValue = t.getNextInteger(); + if (flagValue == _flagsTable[flagNum]) { + _locationMusicsTable[_locationMusicsCount].num = t.getNextInteger(); + _locationMusicsTable[_locationMusicsCount].volume = t.getNextInteger(); + _locationMusicsTable[_locationMusicsCount].flag = t.getNextInteger(); + ++_locationMusicsCount; + } else { + for (int j = 0; j < 3; ++j) { + t.getNextInteger(); + } + } + } +} + +void TuckerEngine::loadSound(Audio::Mixer::SoundType type, int num, int volume, bool loop, Audio::SoundHandle *handle) { + Audio::AudioStream *stream = 0; + if (_compressedSoundType < 0) { + const char *fmt = 0; + switch (type) { + case Audio::Mixer::kSFXSoundType: + fmt = "fx/fx%d.wav"; + break; + case Audio::Mixer::kMusicSoundType: + fmt = "music/mus%d.wav"; + break; + case Audio::Mixer::kSpeechSoundType: + fmt = "speech/sam%04d.wav"; + break; + default: + return; + } + char fileName[64]; + snprintf(fileName, sizeof(fileName), fmt, num); + Common::File f; + if (f.open(fileName)) { + int size, rate; + uint8 flags = 0; + if (Audio::loadWAVFromStream(f, size, rate, flags)) { + uint8 *data = (uint8 *)malloc(size); + if (data) { + f.read(data, size); + flags |= Audio::Mixer::FLAG_AUTOFREE; + if (loop) { + flags |= Audio::Mixer::FLAG_LOOP; + } + stream = Audio::makeLinearInputStream(data, size, rate, flags, 0, 0); + } + } + } + } else { + int offset = 0; + switch (type) { + case Audio::Mixer::kSFXSoundType: + offset = kCompressedSoundDataFileHeaderSize; + break; + case Audio::Mixer::kMusicSoundType: + offset = kCompressedSoundDataFileHeaderSize + 8; + break; + case Audio::Mixer::kSpeechSoundType: + offset = kCompressedSoundDataFileHeaderSize + 16; + break; + default: + return; + } + _fCompressedSound.seek(offset); + int dirOffset = _fCompressedSound.readUint32LE(); + int dirSize = _fCompressedSound.readUint32LE(); + if (num < dirSize) { + dirOffset += kCompressedSoundDataFileHeaderSize + 3 * 8; + _fCompressedSound.seek(dirOffset + num * 8); + int soundOffset = _fCompressedSound.readUint32LE(); + int soundSize = _fCompressedSound.readUint32LE(); + if (soundSize != 0) { + _fCompressedSound.seek(dirOffset + dirSize * 8 + soundOffset); + Common::MemoryReadStream *tmp = _fCompressedSound.readStream(soundSize); + if (tmp) { + stream = (compressedSoundFilesTable[_compressedSoundType].makeStream)(tmp, true, 0, 0, 1); + } + } + } + } + if (stream) { + _mixer->playInputStream(type, handle, stream, -1, volume * Audio::Mixer::kMaxChannelVolume / kMaxSoundVolume); + } +} + +void TuckerEngine::loadActionsTable() { + int table = 0; + do { + if (!_csDataLoaded) { + DataTokenizer t(_csDataBuf, _csDataSize); + bool found = t.findIndex(_locationNum); + assert(found); + for (int i = 0; i < _nextAction; ++i) { + found = t.findNextToken(kDataTokenDw); + assert(found); + } + _forceRedrawPanelItems = 1; + _panelState = 1; + setCursorType(2); + _tableInstructionsPtr = _csDataBuf + t._pos + 1; + _csDataLoaded = true; + _csDataHandled = 1; + } + if (_csDataTableFlag2 == 1 && _charSpeechSoundCounter > 0) { + break; + } + _csDataTableFlag2 = 0; + if (_stopActionOnPanelLock == 1) { + if (_panelLockedFlag) { + break; + } + _stopActionOnPanelLock = 0; + } + if (_stopActionCounter > 0) { + --_stopActionCounter; + break; + } + if (_stopActionOnSoundFlag != 0) { + if (isSoundPlaying(_soundInstructionIndex)) { + break; + } + _stopActionOnSoundFlag = 0; + } + if (_csDataTableCount != 0) { + if (_csDataTableCount == 99) { + if (_backgroundSpriteCurrentAnimation > -1) { + if (_backgroundSpriteCurrentFrame != _backgroundSpriteLastFrame) { + break; + } + _csDataTableCount = 0; + } else { + if (_spriteAnimationFramesTable[_spriteAnimationFrameIndex] != 999) { + break; + } + _csDataTableCount = 0; + } + } else { + if (_spritesTable[_csDataTableCount - 1].firstFrame - 1 != _spritesTable[_csDataTableCount - 1].animationFrame) { + break; + } + _csDataTableCount = 0; + } + } + if (_conversationOptionsCount != 0) { + if (_mouseButtons != 0 && _nextTableToLoadIndex != -1) { + _nextAction = _nextTableToLoadTable[_nextTableToLoadIndex]; + _csDataLoaded = false; + _conversationOptionsCount = 0; + setCursorType(2); + } + break; + } + table = 0; + while (table == 0) { + table = parseTableInstruction(); + } + } while (table == 3); + if (table == 2) { + _nextAction = 0; + _csDataLoaded = false; + _forceRedrawPanelItems = 1; + _panelState = 0; + setCursorType(0); + _csDataHandled = 0; + _skipPanelObjectUnderCursor = 0; + _mouseClick = 1; + } +} + +} // namespace Tucker diff --git a/engines/tucker/saveload.cpp b/engines/tucker/saveload.cpp new file mode 100644 index 0000000000..145c86ef18 --- /dev/null +++ b/engines/tucker/saveload.cpp @@ -0,0 +1,116 @@ +/* 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/savefile.h" + +#include "tucker/tucker.h" + +namespace Tucker { + +enum { + kCurrentGameStateVersion = 1 +}; + +void TuckerEngine::generateGameStateFileName(int num, char *dst, int len, bool prefixOnly) const { + if (prefixOnly) { + snprintf(dst, len, "%s.*", _targetName.c_str()); + } else { + snprintf(dst, len, "%s.%d", _targetName.c_str(), num); + } + dst[len] = 0; +} + +static void saveOrLoadInt(Common::WriteStream &stream, int &i) { + stream.writeSint32LE(i); +} + +static void saveOrLoadInt(Common::ReadStream &stream, int &i) { + i = stream.readSint32LE(); +} + +template +void TuckerEngine::saveOrLoadGameStateData(S &s) { + for (int i = 0; i < 300; ++i) { + saveOrLoadInt(s, _flagsTable[i]); + } + for (int i = 0; i < 40; ++i) { + saveOrLoadInt(s, _inventoryObjectsList[i]); + } + for (int i = 0; i < 50; ++i) { + saveOrLoadInt(s, _inventoryItemsState[i]); + } + for (int i = 0; i < 50; ++i) { + saveOrLoadInt(s, _panelObjectsOffsetTable[i]); + } + saveOrLoadInt(s, _mainSpritesBaseOffset); + saveOrLoadInt(s, _selectedObject.xPos); + saveOrLoadInt(s, _selectedObject.yPos); + saveOrLoadInt(s, _locationNum); + saveOrLoadInt(s, _xPosCurrent); + saveOrLoadInt(s, _yPosCurrent); + saveOrLoadInt(s, _inventoryObjectsCount); + saveOrLoadInt(s, _inventoryObjectsOffset); +} + +void TuckerEngine::loadGame(int slot) { + char gameStateFileName[64]; + generateGameStateFileName(slot, gameStateFileName, 63); + Common::InSaveFile *f = _saveFileMan->openForLoading(gameStateFileName); + if (f) { + uint16 version = f->readUint16LE(); + if (version < kCurrentGameStateVersion) { + warning("Unsupported gamestate version %d (slot %d)", version, slot); + } else { + f->skip(2); + saveOrLoadGameStateData(*f); + if (f->ioFailed()) { + warning("Can't read file '%s'", gameStateFileName); + } else { + _nextLocationNum = _locationNum; + setBlackPalette(); + loadBudSpr(0); + } + } + delete f; + } +} + +void TuckerEngine::saveGame(int slot) { + char gameStateFileName[64]; + generateGameStateFileName(slot, gameStateFileName, 63); + Common::OutSaveFile *f = _saveFileMan->openForSaving(gameStateFileName); + if (f) { + f->writeUint16LE(kCurrentGameStateVersion); + f->writeUint16LE(0); + saveOrLoadGameStateData(*f); + f->finalize(); + if (f->ioFailed()) { + warning("Can't write file '%s'", gameStateFileName); + } + delete f; + } +} + +} // namespace Tucker diff --git a/engines/tucker/sequences.cpp b/engines/tucker/sequences.cpp new file mode 100644 index 0000000000..780f3c694d --- /dev/null +++ b/engines/tucker/sequences.cpp @@ -0,0 +1,480 @@ +/* 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 "tucker/tucker.h" +#include "tucker/graphics.h" + +namespace Tucker { + +void TuckerEngine::handleCreditsSequence() { + static const int _creditsSequenceData1[] = { 200, 350, 650, 850, 1150, 1450, 12000 }; + static const int _creditsSequenceData2[] = { 1, 1, 5, 0, 6, 6, 0 }; + int counter4 = 0; + int counter3 = 0; + int num = 0; + int imgNum = 0; + int prevLocationNum = _locationNum; + int counter2 = 0; + int counter1 = 0; + loadCharset2(); + stopSounds(); + _locationNum = 74; + uint8 *imgBuf = (uint8 *)malloc(16 * 64000); + loadSprC02_01(); + _spritesCount = _creditsSequenceData2[num]; + for (int i = 0; i < _spritesCount; ++i) { + memset(&_spritesTable[i], 0, sizeof(Sprite)); + _spritesTable[i].state = -1; + _spritesTable[i].stateIndex = -1; + } + strcpy(_fileToLoad, "credits.txt"); + loadFile(_ptTextBuf); + strcpy(_fileToLoad, "loc74.pcx"); + loadImage(_quadBackgroundGfxBuf, 1); + startSpeechSound(9001, 120); + _timerCounter2 = 0; + _fadePaletteCounter = 0; + do { + if (_fadePaletteCounter < 16) { + fadeOutPalette(); + ++_fadePaletteCounter; + } + if (counter4 + 20 > _creditsSequenceData1[num]) { + fadeInPalette(); + } + ++imgNum; + if (imgNum == 16) { + imgNum = 0; + } + if (num < 6) { + Graphics::copyTo640(_locationBackgroundGfxBuf, _quadBackgroundGfxBuf, 320, 320, 200); + } else { + if (getLastKeyCode() > 0) { + return; + } + Graphics::copyTo640(_locationBackgroundGfxBuf, imgBuf + imgNum * 64000, 320, 320, 200); + drawString2(5, 48, counter2 * 6); + drawString2(5, 60, counter2 * 6 + 1); + drawString2(5, 80, counter2 * 6 + 2); + drawString2(5, 92, counter2 * 6 + 3); + drawString2(5, 140, counter2 * 6 + 4); + drawString2(5, 116, counter2 * 6 + 5); + ++counter1; + if (counter1 < 20) { + fadePaletteColor(191, kFadePaletteStep); + } else if (counter1 > 106) { + fadePaletteColor(191, -kFadePaletteStep); + } + if (counter1 > 116) { + counter1 = 0; + } + ++counter2; + if (counter2 > 17) { + counter2 = 0; + } + } + ++counter3; + if (counter3 == 2) { + counter3 = 0; + updateSprites(); + } + for (int i = 0; i < _spritesCount; ++i) { + drawSprite(i); + isSpeechSoundPlaying(); + } + copyToVGA(_locationBackgroundGfxBuf); + waitForTimer(3); + isSpeechSoundPlaying(); + _timerCounter1 = 0; + counter4 = _timerCounter2 / 3; + if (counter4 == _creditsSequenceData1[num]) { + _fadePaletteCounter = 0; + _spritesCount = _creditsSequenceData2[num]; + for (int i = 0; i < _spritesCount; ++i) { + memset(&_spritesTable[i], 0, sizeof(Sprite)); + _spritesTable[i].state = -1; + _spritesTable[i].stateIndex = -1; + } + ++num; + switch (num) { + case 1: + strcpy(_fileToLoad, "loc75.pcx"); + break; + case 2: + strcpy(_fileToLoad, "loc76.pcx"); + break; + case 3: + strcpy(_fileToLoad, "paper-3.pcx"); + break; + case 4: + strcpy(_fileToLoad, "loc77.pcx"); + break; + case 5: + strcpy(_fileToLoad, "loc78.pcx"); + break; + } + if (num == 6) { + for (int i = 0; i < 16; ++i) { + sprintf(_fileToLoad, "cogs%04d.pcx", i); + loadImage(imgBuf + i * 64000, 2); + } + } else { + loadImage(_quadBackgroundGfxBuf, 2); + } + _spritesCount = _creditsSequenceData2[num]; + ++_flagsTable[236]; + } + } while (isSpeechSoundPlaying()); + free(imgBuf); + _locationNum = prevLocationNum; + do { + if (_fadePaletteCounter > 0) { + fadeInPalette(); + --_fadePaletteCounter; + } + copyToVGA(_locationBackgroundGfxBuf); + waitForTimer(2); + } while (_fadePaletteCounter > 0); +} + +void TuckerEngine::handleCongratulationsSequence() { + _timerCounter2 = 0; + _fadePaletteCounter = 0; + stopSounds(); + strcpy(_fileToLoad, "congrat.pcx"); + loadImage(_loadTempBuf, 1); + Graphics::copyTo640(_locationBackgroundGfxBuf, _loadTempBuf, 320, 320, 200); + copyToVGA(_locationBackgroundGfxBuf); + while (_timerCounter2 < 450) { + while (_fadePaletteCounter < 14) { + ++_fadePaletteCounter; + fadeOutPalette(); + } + waitForTimer(3); + updateTimer(); + } +} + +void TuckerEngine::handleNewPartSequence() { + stopSounds(); + if (_flagsTable[219] == 1) { + _flagsTable[219] = 0; + for (int i = 0; i < 50; ++i) { + _inventoryItemsState[i] = 0; + } + _inventoryObjectsOffset = 0; + _inventoryObjectsCount = 0; + addObjectToInventory(30); + if (_partNum == 1 || _partNum == 3) { + addObjectToInventory(1); + addObjectToInventory(0); + } + _redrawPanelItemsCounter = 0; + } + _scrollOffset = 0; + switch (_partNum) { + case 1: + strcpy(_fileToLoad, "pt1bak.pcx"); + break; + case 2: + strcpy(_fileToLoad, "pt2bak.pcx"); + break; + default: + strcpy(_fileToLoad, "pt3bak.pcx"); + break; + } + loadImage(_quadBackgroundGfxBuf, 1); + switch (_partNum) { + case 1: + strcpy(_fileToLoad, "sprites/partone.spr"); + break; + case 2: + strcpy(_fileToLoad, "sprites/parttwo.spr"); + break; + default: + strcpy(_fileToLoad, "sprites/partthr.spr"); + break; + } + _spritesCount = 1; + memset(&_spritesTable[0], 0, sizeof(Sprite)); + _spritesTable[0].state = -1; + _spritesTable[0].stateIndex = -1; + int currentLocation = _locationNum; + _locationNum = 98; + for (int i = 1; i < kSprA02TableSize; ++i) { + free(_sprA02Table[i]); + _sprA02Table[i] = 0; + } + for (int i = 1; i < kSprC02TableSize; ++i) { + free(_sprC02Table[i]); + _sprC02Table[i] = 0; + } + _sprC02Table[1] = loadFile(); + startSpeechSound(9000, 60); + _fadePaletteCounter = 0; + do { + if (_fadePaletteCounter < 16) { + fadeOutPalette(); + ++_fadePaletteCounter; + } + Graphics::copyTo640(_locationBackgroundGfxBuf, _quadBackgroundGfxBuf, 320, 320, 200); + updateSprites(); + drawSprite(0); + copyToVGA(_locationBackgroundGfxBuf); + waitForTimer(3); + if (getLastKeyCode() > 0) { + stopSounds(); + } + } while (isSpeechSoundPlaying()); + do { + if (_fadePaletteCounter > 0) { + fadeInPalette(); + --_fadePaletteCounter; + } + Graphics::copyTo640(_locationBackgroundGfxBuf, _quadBackgroundGfxBuf, 320, 320, 200); + updateSprites(); + drawSprite(0); + copyToVGA(_locationBackgroundGfxBuf); + waitForTimer(3); + } while (_fadePaletteCounter > 0); + _locationNum = currentLocation; +} + +void TuckerEngine::handleMeanwhileSequence() { + backupPalette(); + switch (_partNum) { + case 1: + strcpy(_fileToLoad, "meanw01.pcx"); + break; + case 2: + strcpy(_fileToLoad, "meanw02.pcx"); + break; + default: + strcpy(_fileToLoad, "meanw03.pcx"); + break; + } + if (_flagsTable[215] == 0 && _flagsTable[231] == 1) { + strcpy(_fileToLoad, "loc80.pcx"); + } + loadImage(_quadBackgroundGfxBuf + 89600, 1); + _fadePaletteCounter = 0; + for (int i = 0; i < 60; ++i) { + if (_fadePaletteCounter < 16) { + fadeOutPalette(); + ++_fadePaletteCounter; + } + Graphics::copyTo640(_locationBackgroundGfxBuf, _quadBackgroundGfxBuf + 89600, 320, 320, 200); + copyToVGA(_locationBackgroundGfxBuf); + waitForTimer(3); + ++i; + } + do { + if (_fadePaletteCounter > 0) { + fadeInPalette(); + --_fadePaletteCounter; + } + Graphics::copyTo640(_locationBackgroundGfxBuf, _quadBackgroundGfxBuf + 89600, 320, 320, 200); + copyToVGA(_locationBackgroundGfxBuf); + waitForTimer(3); + } while (_fadePaletteCounter > 0); + restorePalette(); +} + +void TuckerEngine::handleMapSequence() { + strcpy(_fileToLoad, "map2.pcx"); + loadImage(_quadBackgroundGfxBuf + 89600, 0); + strcpy(_fileToLoad, "map1.pcx"); + loadImage(_loadTempBuf, 1); + _selectedObject.locationObject_locationNum = 0; + if (_flagsTable[7] > 0) { + copyMapRect(0, 0, 140, 86); + } + if (_flagsTable[7] > 1) { + copyMapRect(0, 60, 122, 120); + } + if (_flagsTable[7] > 2) { + copyMapRect(122, 114, 97, 86); + } + if (_flagsTable[7] == 4) { + copyMapRect(140, 0, 88, 125); + } + if (_flagsTable[120] == 1) { + copyMapRect(220, 0, 100, 180); + } + _fadePaletteCounter = 0; + int xPos, yPos, textNum = 0; + do { + waitForTimer(2); + updateMouseState(); + Graphics::copyTo640(_locationBackgroundGfxBuf + _scrollOffset, _quadBackgroundGfxBuf + 89600, 320, 320, 200); + if (_flagsTable[7] > 0 && _mousePosX > 30 && _mousePosX < 86 && _mousePosY > 36 && _mousePosY < 86) { + textNum = 13; + _nextLocationNum = (_partNum == 1) ? 3 : 65; + xPos = 620; + yPos = 130; + } else if (_flagsTable[7] > 1 && _mousePosX > 60 && _mousePosX < 120 && _mousePosY > 120 && _mousePosY < 170) { + textNum = 14; + _nextLocationNum = (_partNum == 1) ? 9 : 66; + xPos = 344; + yPos = 120; + } else if (_flagsTable[7] > 2 && _mousePosX > 160 && _mousePosX < 210 && _mousePosY > 110 && _mousePosY < 160) { + textNum = 15; + _nextLocationNum = (_partNum == 1) ? 16 : 61; + xPos = 590; + yPos = 130; + } else if ((_flagsTable[7] == 4 || _flagsTable[7] == 6) && _mousePosX > 150 && _mousePosX < 200 && _mousePosY > 20 && _mousePosY < 70) { + textNum = 16; + _nextLocationNum = (_partNum == 1) ? 20 : 68; + xPos = 20; + yPos = 130; + } else if (_flagsTable[120] == 1 && _mousePosX > 240 && _mousePosX < 290 && _mousePosY > 35 && _mousePosY < 90) { + textNum = 17; + _nextLocationNum = (_partNum == 1) ? 19 : 62; + xPos = 20; + yPos = 124; + } else if (_mousePosX > 135 && _mousePosX < 185 && _mousePosY > 170 && _mousePosY < 200) { + textNum = 18; + _nextLocationNum = _locationNum; + if (!_noPositionChangeAfterMap) { + xPos = _xPosCurrent; + yPos = _yPosCurrent; + } else if (_locationNum == 3 ||_locationNum == 65) { + xPos = 620; + yPos = 130; + } else if (_locationNum == 9 ||_locationNum == 66) { + xPos = 344; + yPos = 120; + } else if (_locationNum == 16 ||_locationNum == 61) { + xPos = 590; + yPos = 130; + } else if (_locationNum == 20 ||_locationNum == 68) { + xPos = 20; + yPos = 130; + } else { + xPos = 20; + yPos = 124; + } + } + if (textNum > 0) { + drawSpeechText(_scrollOffset + _mousePosX + 8, _mousePosY - 10, _infoBarBuf, textNum, 96); + } + copyToVGA(_locationBackgroundGfxBuf + _scrollOffset); + if (_fadePaletteCounter < 14) { + fadeOutPalette(); + ++_fadePaletteCounter; + } + } while (!_leftMouseButtonPressed || textNum == 0); + while (_fadePaletteCounter > 0) { + fadeInPalette(); + copyToVGA(_locationBackgroundGfxBuf + _scrollOffset); + --_fadePaletteCounter; + } + _mouseClick = 1; + if (_nextLocationNum == 9 && _noPositionChangeAfterMap) { + _backgroundSpriteCurrentAnimation = 2; + _backgroundSpriteCurrentFrame = 0; + setCursorType(2); + } else if (_nextLocationNum == 66 && _noPositionChangeAfterMap) { + _backgroundSpriteCurrentAnimation = 1; + _backgroundSpriteCurrentFrame = 0; + setCursorType(2); + } + _noPositionChangeAfterMap = false; + _xPosCurrent = xPos; + _yPosCurrent = yPos; +} + +void TuckerEngine::copyMapRect(int x, int y, int w, int h) { + const uint8 *src = _quadBackgroundGfxBuf + 89600 + y * 320 + x; + uint8 *dst = _loadTempBuf + y * 320 + x; + for (int i = 0; i < h; ++i) { + memcpy(dst, src, w); + src += 320; + dst += 320; + } +} + +int TuckerEngine::handleSpecialObjectSelectionSequence() { + if (_partNum == 1 && _selectedObjectNum == 6) { + strcpy(_fileToLoad, "news1.pcx"); + _flagsTable[7] = 1; + } else if (_partNum == 3 && _selectedObjectNum == 45) { + strcpy(_fileToLoad, "profnote.pcx"); + } else if (_partNum == 1 && _selectedObjectNum == 26) { + strcpy(_fileToLoad, "photo.pcx"); + } else if (_partNum == 3 && _selectedObjectNum == 39) { + strcpy(_fileToLoad, "news2.pcx"); + _flagsTable[135] = 1; + } else if (_currentInfoString1SourceType == 0 && _currentActionObj1Num == 259) { + strcpy(_fileToLoad, "postit.pcx"); + } else if (_currentInfoString1SourceType == 1 && _currentActionObj1Num == 91) { + strcpy(_fileToLoad, "memo.pcx"); + } else { + return 0; + } + while (_fadePaletteCounter > 0) { + fadeInPalette(); + copyToVGA(_locationBackgroundGfxBuf + _scrollOffset); + --_fadePaletteCounter; + } + _mouseClick = 1; + loadImage(_quadBackgroundGfxBuf, 1); + _fadePaletteCounter = 0; + while (1) { + waitForTimer(2); + updateMouseState(); + Graphics::copyTo640(_locationBackgroundGfxBuf + _scrollOffset, _quadBackgroundGfxBuf, 320, 320, 200); + if (_fadePaletteCounter < 14) { + fadeOutPalette(); + ++_fadePaletteCounter; + } + if (!_leftMouseButtonPressed && _mouseClick == 1) { + _mouseClick = 0; + } + if (_partNum == 3 && _selectedObjectNum == 45) { + for (int i = 0; i < 13; ++i) { + const int offset = _dataTable[204 + i].yDest * 640 + _dataTable[i].xDest; + static const int itemsTable[] = { 15, 44, 25, 19, 21, 24, 12, 27, 20, 29, 35, 23, 3 }; + if (_inventoryItemsState[itemsTable[i]] > 1) { + Graphics::decodeRLE(_locationBackgroundGfxBuf + _scrollOffset + offset, _data3GfxBuf + _dataTable[204 + i].sourceOffset, _dataTable[204 + i].xSize, _dataTable[204 + i].ySize); + } + } + } + copyToVGA(_locationBackgroundGfxBuf + _scrollOffset); + if (_leftMouseButtonPressed && _mouseClick != 1) { + while (_fadePaletteCounter > 0) { + fadeInPalette(); + copyToVGA(_locationBackgroundGfxBuf + _scrollOffset); + --_fadePaletteCounter; + } + _mouseClick = 1; + break; + } + } + loadLoc(); + return 1; +} + +} // namespace Tucker diff --git a/engines/tucker/staticres.cpp b/engines/tucker/staticres.cpp new file mode 100644 index 0000000000..dd3c449237 --- /dev/null +++ b/engines/tucker/staticres.cpp @@ -0,0 +1,219 @@ +/* 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 "tucker/tucker.h" + +namespace Tucker { + +const int TuckerEngine::_locationWidthTable[85] = { + 1, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1, 4, 2, 1, + 1, 2, 1, 2, 4, 1, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 4, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 1, 4, 1, + 1, 1, 1, 1, 2, 1, 2, 2, 2, 4, 4, 2, 2, 1, 1, 1, 4, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 +}; + +const uint8 TuckerEngine::_sprA02LookupTable[88] = { + 0, 6, 2, 8, 1, 0, 6, 0, 2, 2, 2, 1, 2, 0, 1, 1, 6, 0, + 1, 2, 1, 2, 3, 0, 6, 12, 7, 7, 1, 8, 1, 0, 3, 0, 4, + 5, 0, 0, 3, 3, 2, 7, 7, 0, 4, 1, 5, 2, 4, 1, 1, 2, 4, + 3, 1, 0, 2, 3, 4, 1, 1, 5, 3, 3, 1, 5, 3, 0, 1, 0, 0, + 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +const uint8 TuckerEngine::_sprC02LookupTable[100] = { + 0, 0, 6, 20, 3, 3, 15, 5, 9, 6, 7, 8, 8, 6, 3, 6, 13, + 3, 4, 10, 0, 7, 2, 34, 14, 0, 2, 3, 8, 3, 3, 3, 19, + 13, 1, 0, 2, 3, 0, 0, 0, 5, 5, 12, 0, 1, 0, 1, 3, 6, + 7, 6, 0, 7, 5, 1, 2, 6, 3, 4, 9, 18, 0, 12, 0, 2, 10, + 0, 0, 19, 0, 2, 2, 1, 22, 0, 0, 0, 0, 3, 0, 3, 2, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 +}; + +const uint8 TuckerEngine::_sprC02LookupTable2[100] = { + 0, 0, 1, 3, 1, 2, 3, 2, 2, 1, 1, 5, 2, 1, 1, 3, 3, 1, + 1, 4, 0, 1, 1, 4, 4, 0, 2, 1, 3, 3, 3, 2, 4, 4, 1, 0, + 1, 3, 0, 0, 0, 1, 1, 7, 0, 1, 0, 1, 1, 1, 7, 3, 0, 2, + 1, 1, 1, 2, 1, 1, 2, 3, 0, 5, 0, 1, 5, 0, 1, 4, 0, 1, + 1, 1, 1, 0, 0, 0, 0, 1, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 +}; + +const int TuckerEngine::_staticData3Table[1600] = { + 0x014, 0x014, 0x015, 0x016, 0x017, 0x017, 0x016, 0x015, 0x3E7, 0x0A9, 0x0A9, 0x0AA, 0x0AA, 0x0AB, 0x0AB, 0x0AC, + 0x0AC, 0x3E7, 0x05E, 0x05F, 0x060, 0x061, 0x3E7, 0x0AD, 0x0AE, 0x0AF, 0x0B0, 0x3E7, 0x052, 0x053, 0x054, 0x055, + 0x3E7, 0x056, 0x057, 0x058, 0x059, 0x3E7, 0x05A, 0x05B, 0x05C, 0x05D, 0x3E7, 0x062, 0x063, 0x064, 0x065, 0x3E7, + 0x066, 0x067, 0x068, 0x069, 0x3E7, 0x00C, 0x00D, 0x00E, 0x00F, 0x3E7, 0x01A, 0x01B, 0x01C, 0x01D, 0x3E7, 0x01E, + 0x01F, 0x020, 0x021, 0x3E7, 0x024, 0x025, 0x026, 0x027, 0x3E7, 0x0B1, 0x0B2, 0x0B3, 0x0B4, 0x3E7, 0x0CB, 0x0CC, + 0x0CD, 0x0CE, 0x3E7, 0x0CF, 0x0D0, 0x0D1, 0x0D2, 0x3E7, 0x0D3, 0x0D4, 0x0D5, 0x0D6, 0x3E7, 0x0D7, 0x0D8, 0x0D9, + 0x0DA, 0x3E7, 0x0B5, 0x0B6, 0x0B7, 0x0B8, 0x3E7, 0x04A, 0x04B, 0x04C, 0x04D, 0x3E7, 0x04E, 0x04F, 0x050, 0x051, + 0x3E7, 0x02A, 0x02B, 0x02C, 0x02D, 0x3E7, 0x02E, 0x02F, 0x030, 0x031, 0x3E6, 0x0E6, 0x001, 0x3E7, 0x0B9, 0x0BA, + 0x0BB, 0x0BC, 0x3E7, 0x06A, 0x06B, 0x06C, 0x06D, 0x3E7, 0x032, 0x033, 0x034, 0x035, 0x3E7, 0x036, 0x037, 0x038, + 0x039, 0x3E7, 0x03A, 0x03B, 0x03C, 0x03D, 0x3E7, 0x03E, 0x03F, 0x040, 0x041, 0x3E7, 0x042, 0x043, 0x044, 0x045, + 0x3E7, 0x046, 0x047, 0x048, 0x049, 0x3E7, 0x06E, 0x06F, 0x070, 0x071, 0x3E6, 0x045, 0x000, 0x3E7, 0x072, 0x073, + 0x074, 0x075, 0x3E7, 0x076, 0x077, 0x078, 0x079, 0x3E7, 0x07A, 0x07B, 0x07C, 0x07D, 0x3E7, 0x07F, 0x080, 0x081, + 0x082, 0x3E7, 0x085, 0x086, 0x087, 0x088, 0x3E7, 0x089, 0x08A, 0x08B, 0x08C, 0x3E7, 0x08F, 0x090, 0x091, 0x092, + 0x3E7, 0x0BD, 0x0BE, 0x0BF, 0x0C0, 0x3E7, 0x0C1, 0x0C2, 0x0C3, 0x0C4, 0x3E7, 0x0C5, 0x0C6, 0x0C7, 0x0C8, 0x3E7, + 0x093, 0x094, 0x095, 0x096, 0x3E7, 0x099, 0x099, 0x099, 0x09A, 0x09A, 0x09A, 0x09B, 0x09B, 0x09B, 0x09C, 0x09C, + 0x09C, 0x3E7, 0x09D, 0x09D, 0x09E, 0x09E, 0x09F, 0x09F, 0x0A0, 0x0A0, 0x3E7, 0x0A1, 0x0A1, 0x0A2, 0x0A2, 0x0A3, + 0x0A3, 0x0A4, 0x0A4, 0x3E7, 0x0A5, 0x0A5, 0x0A6, 0x0A6, 0x0A7, 0x0A7, 0x0A8, 0x0A8, 0x3E7, 0x0DE, 0x0DF, 0x0E0, + 0x0E1, 0x3E7, 0x010, 0x011, 0x012, 0x013, 0x3E7, 0x0E3, 0x0E4, 0x0E5, 0x0E6, 0x3E6, 0x03F, 0x000, 0x3E7, 0x000, + 0x001, 0x002, 0x003, 0x3E7, 0x004, 0x005, 0x006, 0x007, 0x3E7, 0x008, 0x009, 0x00A, 0x00B, 0x3E7, 0x00C, 0x00D, + 0x00E, 0x00F, 0x3E7, 0x010, 0x011, 0x012, 0x013, 0x3E7, 0x014, 0x015, 0x016, 0x017, 0x3E7, 0x018, 0x019, 0x01A, + 0x01B, 0x3E7, 0x01D, 0x01E, 0x01F, 0x020, 0x3E7, 0x021, 0x022, 0x023, 0x024, 0x3E7, 0x025, 0x026, 0x027, 0x028, + 0x3E7, 0x029, 0x02A, 0x02B, 0x02C, 0x3E7, 0x02D, 0x02E, 0x02F, 0x030, 0x3E7, 0x031, 0x032, 0x033, 0x034, 0x3E7, + 0x035, 0x036, 0x037, 0x038, 0x3E7, 0x039, 0x03A, 0x03B, 0x03C, 0x3E7, 0x03D, 0x03E, 0x03F, 0x040, 0x3E7, 0x041, + 0x042, 0x043, 0x044, 0x3E7, 0x049, 0x04A, 0x04B, 0x04C, 0x3E7, 0x04D, 0x04E, 0x04F, 0x050, 0x3E7, 0x051, 0x052, + 0x053, 0x054, 0x3E7, 0x055, 0x056, 0x057, 0x058, 0x3E7, 0x059, 0x05A, 0x05B, 0x05C, 0x3E7, 0x05D, 0x05E, 0x05F, + 0x060, 0x3E7, 0x061, 0x062, 0x063, 0x064, 0x3E7, 0x068, 0x069, 0x06A, 0x06B, 0x3E7, 0x06C, 0x06D, 0x06E, 0x06F, + 0x3E7, 0x070, 0x071, 0x072, 0x073, 0x3E7, 0x074, 0x075, 0x076, 0x077, 0x3E7, 0x07A, 0x07B, 0x07C, 0x07D, 0x3E7, + 0x07E, 0x07F, 0x080, 0x081, 0x3E7, 0x082, 0x083, 0x084, 0x085, 0x3E7, 0x086, 0x087, 0x088, 0x089, 0x3E7, 0x08A, + 0x08B, 0x08C, 0x08D, 0x3E7, 0x08E, 0x08E, 0x08F, 0x08F, 0x090, 0x090, 0x091, 0x091, 0x3E7, 0x000, 0x001, 0x002, + 0x003, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x3E7, + 0x004, 0x005, 0x006, 0x007, 0x3E7, 0x008, 0x009, 0x00A, 0x00B, 0x3E7, 0x00C, 0x00D, 0x00E, 0x00F, 0x3E7, 0x010, + 0x011, 0x012, 0x013, 0x3E7, 0x014, 0x015, 0x016, 0x017, 0x3E7, 0x018, 0x019, 0x01A, 0x01B, 0x01C, 0x01D, 0x01E, + 0x01F, 0x020, 0x021, 0x022, 0x023, 0x024, 0x025, 0x026, 0x027, 0x028, 0x029, 0x02A, 0x02B, 0x02C, 0x02D, 0x02E, + 0x02F, 0x030, 0x031, 0x032, 0x3E7, 0x033, 0x034, 0x035, 0x3E7, 0x036, 0x037, 0x038, 0x3E7, 0x039, 0x03A, 0x03B, + 0x3E6, 0x091, 0x003, 0x3E7, 0x03B, 0x03A, 0x039, 0x3E6, 0x091, 0x000, 0x3E7, 0x03C, 0x03D, 0x03E, 0x03F, 0x040, + 0x041, 0x042, 0x043, 0x044, 0x3E6, 0x06E, 0x000, 0x3E7, 0x045, 0x046, 0x047, 0x048, 0x049, 0x04A, 0x04B, 0x04C, + 0x04D, 0x04E, 0x3E6, 0x068, 0x002, 0x3E7, 0x04F, 0x050, 0x051, 0x052, 0x3E7, 0x052, 0x051, 0x050, 0x04F, 0x3E7, + 0x053, 0x054, 0x055, 0x056, 0x3E7, 0x057, 0x058, 0x059, 0x05A, 0x05B, 0x05C, 0x05D, 0x05E, 0x05F, 0x060, 0x061, + 0x062, 0x063, 0x064, 0x065, 0x3E7, 0x066, 0x067, 0x068, 0x069, 0x06A, 0x06B, 0x06C, 0x06D, 0x06E, 0x06F, 0x070, + 0x071, 0x072, 0x073, 0x074, 0x075, 0x076, 0x3E7, 0x077, 0x078, 0x079, 0x07A, 0x07B, 0x07C, 0x07D, 0x3E6, 0x069, + 0x001, 0x3E7, 0x07D, 0x07C, 0x07B, 0x07A, 0x079, 0x078, 0x077, 0x3E6, 0x069, 0x000, 0x3E7, 0x07E, 0x07F, 0x080, + 0x081, 0x082, 0x083, 0x084, 0x3E6, 0x06A, 0x001, 0x3E7, 0x084, 0x083, 0x082, 0x081, 0x080, 0x07F, 0x07E, 0x3E6, + 0x06A, 0x000, 0x3E7, 0x085, 0x086, 0x087, 0x088, 0x089, 0x08A, 0x08B, 0x08C, 0x08D, 0x08E, 0x08F, 0x090, 0x091, + 0x092, 0x093, 0x094, 0x095, 0x096, 0x097, 0x098, 0x099, 0x09A, 0x09B, 0x09C, 0x09D, 0x09E, 0x09F, 0x0A0, 0x0A1, + 0x0A2, 0x0A3, 0x0A4, 0x0A5, 0x0A6, 0x0A7, 0x0A8, 0x0A9, 0x3E7, 0x0AA, 0x0AB, 0x0AC, 0x0AD, 0x0AE, 0x0AF, 0x0B0, + 0x0B1, 0x0B2, 0x0B3, 0x3E6, 0x06B, 0x000, 0x3E7, 0x0B3, 0x3E7, 0x0B4, 0x0B4, 0x0B5, 0x0B5, 0x0B6, 0x0B6, 0x0B7, + 0x0B7, 0x3E7, 0x0B8, 0x0B9, 0x0B9, 0x0BB, 0x0BC, 0x0BD, 0x0BE, 0x0BF, 0x3E7, 0x0C0, 0x0C1, 0x0C2, 0x0C3, 0x0C4, + 0x0C5, 0x0C6, 0x0C7, 0x0C8, 0x0C9, 0x0CA, 0x0CB, 0x0CC, 0x0CD, 0x0CE, 0x0CF, 0x0D0, 0x0D1, 0x0D2, 0x0D3, 0x0D4, + 0x0D5, 0x0D6, 0x0D7, 0x0D8, 0x3E7, 0x0D9, 0x0DA, 0x0DB, 0x0DC, 0x0DD, 0x0DE, 0x0DF, 0x0E0, 0x0E1, 0x0E2, 0x0E3, + 0x0E4, 0x0E5, 0x0E6, 0x0E7, 0x0E8, 0x0E9, 0x3E7, 0x1C5, 0x0EA, 0x0EB, 0x0EC, 0x0ED, 0x0EE, 0x0EF, 0x0F0, 0x0F1, + 0x0F2, 0x3E7, 0x0F3, 0x0F4, 0x0F5, 0x0F6, 0x0F7, 0x0F8, 0x0F9, 0x0FA, 0x3E6, 0x074, 0x001, 0x3E7, 0x0FB, 0x0FC, + 0x0FD, 0x0FE, 0x3E7, 0x0FF, 0x100, 0x101, 0x102, 0x3E7, 0x103, 0x104, 0x105, 0x106, 0x107, 0x108, 0x109, 0x10A, + 0x10B, 0x10C, 0x10D, 0x10E, 0x10F, 0x110, 0x111, 0x112, 0x113, 0x114, 0x115, 0x116, 0x3E7, 0x116, 0x115, 0x114, + 0x113, 0x112, 0x111, 0x110, 0x10F, 0x10E, 0x3E7, 0x117, 0x118, 0x119, 0x11A, 0x3E7, 0x11B, 0x11C, 0x11D, 0x11E, + 0x3E7, 0x11F, 0x120, 0x121, 0x122, 0x3E7, 0x123, 0x124, 0x125, 0x3E6, 0x091, 0x003, 0x3E7, 0x125, 0x124, 0x123, + 0x3E7, 0x126, 0x127, 0x128, 0x3E7, 0x128, 0x127, 0x126, 0x3E7, 0x129, 0x12A, 0x12B, 0x12C, 0x12D, 0x12E, 0x12F, + 0x130, 0x131, 0x132, 0x133, 0x134, 0x135, 0x136, 0x137, 0x138, 0x139, 0x13A, 0x13B, 0x13C, 0x13D, 0x13E, 0x13F, + 0x140, 0x141, 0x142, 0x143, 0x144, 0x145, 0x146, 0x147, 0x148, 0x149, 0x14A, 0x14B, 0x14C, 0x14D, 0x14E, 0x14F, + 0x150, 0x151, 0x152, 0x3E7, 0x153, 0x154, 0x155, 0x156, 0x157, 0x159, 0x15A, 0x15B, 0x15C, 0x3E7, 0x15E, 0x15F, + 0x160, 0x161, 0x162, 0x163, 0x164, 0x165, 0x166, 0x167, 0x168, 0x169, 0x16A, 0x16B, 0x16C, 0x16D, 0x16E, 0x16F, + 0x170, 0x171, 0x172, 0x3E7, 0x173, 0x173, 0x173, 0x173, 0x173, 0x173, 0x173, 0x174, 0x174, 0x174, 0x174, 0x174, + 0x174, 0x3E7, 0x175, 0x175, 0x175, 0x175, 0x175, 0x175, 0x176, 0x3E7, 0x177, 0x178, 0x179, 0x17A, 0x17B, 0x17C, + 0x17D, 0x17E, 0x17F, 0x180, 0x181, 0x182, 0x183, 0x184, 0x185, 0x186, 0x187, 0x3E7, 0x188, 0x189, 0x18A, 0x18B, + 0x18C, 0x3E7, 0x198, 0x199, 0x19A, 0x19B, 0x19C, 0x19D, 0x19E, 0x19F, 0x1A0, 0x1A1, 0x1A2, 0x1A3, 0x1A4, 0x1A5, + 0x1A6, 0x1A7, 0x1A8, 0x1A9, 0x1AA, 0x1AB, 0x1AC, 0x1AD, 0x1AE, 0x1AF, 0x3E7, 0x1B0, 0x1B1, 0x1B2, 0x3E7, 0x1B3, + 0x1B4, 0x1B5, 0x1B6, 0x1B7, 0x1B8, 0x1B9, 0x1BA, 0x3E7, 0x1BB, 0x1BC, 0x1BD, 0x1BE, 0x1BF, 0x1C0, 0x1C1, 0x1C2, + 0x1C3, 0x1C4, 0x3E6, 0x06F, 0x000, 0x3E7, 0x098, 0x099, 0x09A, 0x3E7, 0x09A, 0x099, 0x098, 0x3E7, 0x09D, 0x09E, + 0x09F, 0x3E7, 0x09F, 0x09E, 0x09D, 0x3E7, 0x0A1, 0x0A2, 0x0A3, 0x3E7, 0x0A6, 0x0A7, 0x0A8, 0x0A9, 0x0AA, 0x0AB, + 0x0AC, 0x0AD, 0x3E6, 0x08E, 0x002, 0x3E7, 0x0AE, 0x0AF, 0x0B0, 0x0B1, 0x0B2, 0x0B3, 0x0B4, 0x0B5, 0x0B6, 0x0B7, + 0x0B8, 0x0B9, 0x0BA, 0x0BB, 0x0BC, 0x0BD, 0x0BE, 0x3E7, 0x0F2, 0x0F2, 0x0F3, 0x0F3, 0x0F4, 0x0F4, 0x3E6, 0x030, + 0x002, 0x3E7, 0x1D3, 0x1D4, 0x1D5, 0x1D6, 0x1D7, 0x1D8, 0x3E7, 0x0F6, 0x0F7, 0x0F8, 0x0F8, 0x3E7, 0x0FB, 0x0FC, + 0x0FD, 0x0FE, 0x0FF, 0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x3E6, 0x07F, 0x002, 0x3E7, 0x106, 0x107, 0x108, + 0x109, 0x10A, 0x10B, 0x10C, 0x10D, 0x10E, 0x10F, 0x110, 0x111, 0x3E7, 0x1E8, 0x1E7, 0x1E6, 0x1E5, 0x1E4, 0x1E3, + 0x1E2, 0x3E6, 0x095, 0x002, 0x3E7, 0x1A7, 0x1A8, 0x3E7, 0x1A9, 0x1AA, 0x1AB, 0x1AC, 0x1AD, 0x1A9, 0x1AA, 0x1AB, + 0x1AC, 0x3E6, 0x09D, 0x003, 0x3E7, 0x1A0, 0x1A1, 0x3E7, 0x0EA, 0x0EB, 0x0EC, 0x0ED, 0x0EE, 0x0EF, 0x0F0, 0x0F1, + 0x0F2, 0x0F3, 0x0F4, 0x0F5, 0x3E7, 0x0F6, 0x0F7, 0x0F8, 0x0F9, 0x0FA, 0x0FB, 0x0FC, 0x0FD, 0x0FE, 0x0FF, 0x100, + 0x101, 0x3E7, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107, 0x108, 0x109, 0x10A, 0x10B, 0x10C, 0x10D, 0x3E7, 0x10E, + 0x10F, 0x110, 0x111, 0x3E7, 0x112, 0x113, 0x114, 0x115, 0x3E7, 0x116, 0x117, 0x3E7, 0x118, 0x119, 0x11A, 0x11B, + 0x3E7, 0x11C, 0x11D, 0x3E7, 0x11E, 0x11F, 0x120, 0x121, 0x122, 0x123, 0x124, 0x125, 0x126, 0x127, 0x128, 0x129, + 0x3E7, 0x12A, 0x12B, 0x12C, 0x12D, 0x12E, 0x12F, 0x130, 0x131, 0x132, 0x133, 0x134, 0x135, 0x3E7, 0x136, 0x137, + 0x138, 0x139, 0x13A, 0x13B, 0x13C, 0x13D, 0x13E, 0x13F, 0x140, 0x141, 0x3E7, 0x106, 0x107, 0x108, 0x109, 0x10A, + 0x10B, 0x10C, 0x10D, 0x10E, 0x10F, 0x110, 0x111, 0x3E7, 0x1A2, 0x1A3, 0x1A4, 0x1A2, 0x1A3, 0x1A4, 0x1A2, 0x1A3, + 0x1A4, 0x1A2, 0x1A3, 0x1A4, 0x3E6, 0x09D, 0x005, 0x3E7, 0x3E7, 0x3E7, 0x3E7, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000 +}; + +const int TuckerEngine::_instructionIdTable[] = { + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'l', 'm', + 'n', 'o', 'p', 'r', 's', 't', 'v', 'w', 'x', '+' +}; + +int TuckerEngine::_locationHeightTable[80] = { + 0x00, 0x1C, 0x3C, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3C, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +int TuckerEngine::_objectKeysPosXTable[80] = { + 0x000, 0x0A0, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x12B, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x140, 0x000, 0x000, 0x000, 0x000, 0x09E, 0x060, 0x0C0, 0x040, 0x0A0, 0x12C, 0x068, 0x098, + 0x08E, 0x09A, 0x0A0, 0x098, 0x092, 0x096, 0x09A, 0x09A, 0x08C, 0x000, 0x000, 0x000, 0x000, 0x000, 0x0A0, 0x000, + 0x086, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x0A0, 0x185, 0x000, 0x0A0, 0x140, 0x140, 0x000, + 0x000, 0x124, 0x140, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, +}; + +int TuckerEngine::_objectKeysPosYTable[80] = { + 0x000, 0x06B, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x080, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x075, 0x000, 0x000, 0x000, 0x000, 0x086, 0x02B, 0x079, 0x07C, 0x07C, 0x07B, 0x073, 0x07B, + 0x06C, 0x08A, 0x086, 0x086, 0x086, 0x086, 0x083, 0x083, 0x07B, 0x000, 0x000, 0x000, 0x000, 0x000, 0x078, 0x000, + 0x082, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x089, 0x08A, 0x000, 0x088, 0x082, 0x076, 0x000, + 0x000, 0x07F, 0x083, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, +}; + +int TuckerEngine::_objectKeysLocationTable[80] = { + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x001, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x001, 0x000, 0x000, 0x000, 0x000, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, + 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x000, 0x000, 0x000, 0x000, 0x000, 0x001, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x001, 0x000, 0x000, 0x001, 0x001, 0x001, 0x000, + 0x000, 0x001, 0x001, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, +}; + +int TuckerEngine::_mapSequenceFlagsLocationTable[70] = { + 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 0, 0, +}; + +const int TuckerEngine::_charWidthCharset2[58] = { + 0x13, 0x0F, 0x10, 0x10, 0x10, 0x0E, 0x11, 0x10, 0x0D, 0x0A, 0x11, 0x0D, 0x14, 0x13, 0x13, 0x11, + 0x13, 0x12, 0x10, 0x11, 0x13, 0x14, 0x14, 0x10, 0x13, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x13, 0x0F, 0x10, 0x10, 0x10, 0x0E, 0x11, 0x10, 0x0D, 0x0A, 0x11, 0x0D, 0x14, 0x13, 0x13, 0x11, + 0x13, 0x12, 0x10, 0x11, 0x13, 0x14, 0x14, 0x10, 0x13, 0x10, +}; + +} // namespace Tucker 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(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(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 diff --git a/engines/tucker/tucker.h b/engines/tucker/tucker.h new file mode 100644 index 0000000000..f9458bebc9 --- /dev/null +++ b/engines/tucker/tucker.h @@ -0,0 +1,802 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef TUCKER_ENGINE_H__ +#define TUCKER_ENGINE_H__ + +#include "common/file.h" +#include "common/util.h" +#include "common/endian.h" +#include "common/events.h" +#include "common/stream.h" + +#include "sound/mixer.h" + +#include "engines/engine.h" + +namespace Tucker { + +struct Action { + int key; + int testFlag1Num; + int testFlag1Value; + int testFlag2Num; + int testFlag2Value; + int speech; + int flipX; + int index; + int delay; + int setFlagNum; + int setFlagValue; + int fxNum; + int fxDelay; +}; + +struct Sprite { + int state; + int gfxBackgroundOffset; + int updateDelay; + int backgroundOffset; + int needUpdate; + int stateIndex; + int counter; + int disabled; + int colorType; + int animationFrame; + int firstFrame; + uint8 *animationData; + int prevState; + int nextAnimationFrame; + int prevAnimationFrame; + int defaultUpdateDelay; + int xSource; + int yMaxBackground; + int flipX; +}; + +struct CharPos { + int xPos; + int yPos; + int xSize; + int ySize; + int xWalkTo; + int yWalkTo; + int flagNum; + int flagValue; + int direction; + int name; + int description; +}; + +struct SpriteFrame { + int sourceOffset; + int xOffset; + int yOffset; + int xSize; + int ySize; +}; + +struct SpriteAnimation { + int numParts; + int rotateFlag; + int firstFrameIndex; +}; + +struct Data { + int sourceOffset; + int xSize; + int ySize; + int xDest; + int yDest; + int index; +}; + +struct LocationAnimation { + int graphicNum; + int animInitCounter; + int animCurrentCounter; + int animLastCounter; + int getFlag; + int inventoryNum; + int flagNum; + int flagValue; + int selectable; + int standX; + int standY; + int drawFlag; +}; + +struct LocationObject { + int xPos; + int yPos; + int xSize; + int ySize; + int textNum; + int locationNum; + int toX; + int toY; + int toX2; + int toY2; + int toWalkX2; + int toWalkY2; + int standX; + int standY; + int cursorNum; +}; + +struct LocationSound { + int startFxSpriteState; + int startFxSpriteNum; + int updateType; + int stopFxSpriteState; + int stopFxSpriteNum; + int offset; + int type; + int volume; + int flagValueStartFx; + int flagValueStopFx; + int flagNum; + int num; +}; + +struct LocationMusic { + int flag; + int offset; + int volume; + int num; +}; + +enum { + kFadePaletteStep = 5, + kStartupLocation = 1, + kDefaultCharSpeechSoundCounter = 1, + kMaxSoundVolume = 127 +}; + +enum Verb { + kVerbWalk = 0, + kVerbLook = 1, + kVerbTalk = 2, + kVerbOpen = 3, + kVerbClose = 4, + kVerbGive = 5, + kVerbTake = 6, + kVerbMove = 7, + kVerbUse = 8 +}; + +class TuckerEngine: public Engine { +public: + + enum { + kLocationAnimationsTableSize = 20, + kLocationObjectsTableSize = 10, + kActionsTableSize = 100, + kFlagsTableSize = 800, + kLocationSoundsTableSize = 30, + kLocationMusicsTableSize = 4, + kSpriteFramesTableSize = 200, + kSprA02TableSize = 20, + kSprC02TableSize = 40, + kDataTableSize = 500, + kSpeechHistoryTableSize = 5, + kMaxCharacters = 8 + }; + + TuckerEngine(OSystem *system, Common::Language language); + ~TuckerEngine(); + + virtual Common::Error init(); + virtual Common::Error go(); + virtual bool hasFeature(EngineFeature f) const { return false; } + virtual void syncSoundSettings(); + +protected: + + int getRandomNumber(); + void allocateBuffers(); + void freeBuffers(); + void restart(); + void mainLoop(); + void updateTimer(); + void waitForTimer(int ticksCount); + void parseEvents(); + void updateCursorPos(int x, int y); + void setCursorNum(int num); + void setCursorType(int type); + void setupNewLocation(); + void copyLocBitmap(int offset, int isMask); + void updateMouseState(); + void updateCharPositionHelper(); + void updateCharPosition(); + void updateFlagsForCharPosition(); + void backupPalette(); + void restorePalette(); + void fadeOutPalette(int colorsCount = 256); + void fadeInPalette(int colorsCount = 256); + void fadePaletteColor(int color, int step); + void setBlackPalette(); + void setPaletteColor(int color, int r, int g, int b); + void updateCursor(); + int getLastKeyCode(); + void stopSounds(); + void playSounds(); + void updateCharactersPath(); + void setSoundVolumeDistance(); + void updateData3DrawFlag(); + void updateData3(); + void updateSfxData3_1(); + void updateSfxData3_2(); + void saveOrLoad(); + void handleMouseOnPanel(); + void switchPanelType(); + void redrawPanelOverBackground(); + void drawConversationTexts(); + void updateScreenScrolling(); + void updateGameHints(); + void startCharacterSounds(); + void updateSoundsTypes3_4(); + void drawData3(); + void execData3PreUpdate(); + void drawBackgroundSprites(int flipX); + void setVolumeSound(int index, int volume); + void setVolumeMusic(int index, int volume); + void startSound(int offset, int index, int volume); + void stopSound(int index); + bool isSoundPlaying(int index); + void startMusic(int offset, int index, int volume); + void stopMusic(int index); + void startSpeechSound(int num, int volume); + bool isSpeechSoundPlaying(); + void isSoundFinished(); + void redrawPanelItems(); + void redrawPanelItemsHelper(); + void drawSprite(int i); + void clearItemsGfx(); + void drawPausedInfoBar(); + const uint8 *getStringBuf(int type) const; + void drawInfoString(); + void drawGameHintString(); + void updateCharacterAnimation(); + void execData3PostUpdate(); + void addObjectToInventory(int num); + void removeObjectFromInventory(int num); + void handleMap(); + void updateSprites(); + void updateSprite(int i); + void drawStringInteger(int num, int x, int y, int digits); + void drawStringAlt(uint8 *dst, int color, const uint8 *str, int strLen = -1); + void drawString(uint8 *dst, int num, const uint8 *str); + void drawString2(int x, int y, int num); + void updateCharSpeechSound(); + void updateItemsGfxColors(int bit0, int bit7); + int testLocationMask(int x, int y); + int getStringWidth(int num, const uint8 *ptr); + int getPositionForLine(int num, const uint8 *ptr); + void copyToVGA(const uint8 *src); + void findActionKey(int count); + int parseTableInstruction(); + void moveUpInventoryObjects(); + void moveDownInventoryObjects(); + void setActionVerbUnderCursor(); + int getObjectUnderCursor(); + void setSelectedObjectKey(); + void setCharacterAnimation(int count, int spr); + int testLocationMaskArea(int xBase, int yBase, int xPos, int yPos); + void handleMouseClickOnInventoryObject(); + int setCharacterUnderCursor(); + int setLocationAnimationUnderCursor(); + void setActionForInventoryObject(); + void setActionState(); + void playSpeechForAction(int i); + void drawSpeechText(int xStart, int y, const uint8 *dataPtr, int num, int color); + int splitSpeechTextLines(const uint8 *dataPtr, int pos, int x, int &lineCharsCount, int &lineWidth); + void drawSpeechTextLine(const uint8 *dataPtr, int pos, int count, uint8 *dst, uint8 color); + + void execData3PreUpdate_locationNum1(); + void execData3PreUpdate_locationNum1Helper1(); + void execData3PreUpdate_locationNum1Helper2(); + int execData3PreUpdate_locationNum1Helper3(int dx, int dy); + void execData3PostUpdate_locationNum1(); + void updateSprite_locationNum2(); + void execData3PreUpdate_locationNum2(); + void execData3PreUpdate_locationNum2Helper(); + void updateSprite_locationNum3_0(int i); + void updateSprite_locationNum3_1(int i); + void updateSprite_locationNum3_2(int i); + void execData3PreUpdate_locationNum3(); + void updateSprite_locationNum4(int i); + void execData3PreUpdate_locationNum4(); + void updateSprite_locationNum5_0(); + void updateSprite_locationNum5_1(int i); + void updateSprite_locationNum6_0(int i); + void updateSprite_locationNum6_1(int i); + void updateSprite_locationNum6_2(int i); + void execData3PreUpdate_locationNum6(); + void execData3PreUpdate_locationNum6Helper1(); + void execData3PreUpdate_locationNum6Helper2(uint8 *dst, const uint8 *src); + void execData3PreUpdate_locationNum6Helper3(uint8 *dst, const uint8 *src); + void updateSprite_locationNum7_0(int i); + void updateSprite_locationNum7_1(int i); + void updateSprite_locationNum8_0(int i); + void updateSprite_locationNum8_1(int i); + void execData3PostUpdate_locationNum8(); + void updateSprite_locationNum9_0(int i); + void updateSprite_locationNum9_1(int i); + void updateSprite_locationNum9_2(int i); + void execData3PreUpdate_locationNum9(); + void execData3PostUpdate_locationNum9(); + void updateSprite_locationNum10(); + void execData3PreUpdate_locationNum10(); + void updateSprite_locationNum11_0(int i); + void updateSprite_locationNum11_1(int i); + void updateSprite_locationNum11_2(int i); + void updateSprite_locationNum11_3(int i); + void updateSprite_locationNum11_4(int i); + void updateSprite_locationNum12_0(int i); + void updateSprite_locationNum12_1(int i); + void execData3PreUpdate_locationNum12(); + void updateSprite_locationNum13(int i); + void execData3PreUpdate_locationNum13(); + void updateSprite_locationNum14(int i); + void execData3PreUpdate_locationNum14(); + void execData3PreUpdate_locationNum14Helper1(int i); + void execData3PreUpdate_locationNum14Helper2(int i); + void updateSprite_locationNum15_0(int i); + void updateSprite_locationNum15_1(int i); + void updateSprite_locationNum15_2(int i); + void execData3PreUpdate_locationNum15(); + void updateSprite_locationNum16_0(int i); + void updateSprite_locationNum16_1(int i); + void updateSprite_locationNum16_2(int i); + void execData3PreUpdate_locationNum16(); + void updateSprite_locationNum17(); + void updateSprite_locationNum18(); + void updateSprite_locationNum19_0(int i); + void updateSprite_locationNum19_1(int i); + void updateSprite_locationNum19_2(int i); + void updateSprite_locationNum19_3(int i); + void execData3PreUpdate_locationNum19(); + void updateSprite_locationNum21(); + void execData3PreUpdate_locationNum21(); + void execData3PostUpdate_locationNum21(); + void updateSprite_locationNum22(); + void execData3PreUpdate_locationNum22(); + void updateSprite_locationNum23_0(int i); + void updateSprite_locationNum23_1(int i); + void updateSprite_locationNum23_2(int i); + void updateSprite_locationNum23_3(int i); + void updateSprite_locationNum24_0(int i); + void updateSprite_locationNum24_1(int i); + void updateSprite_locationNum24_2(int i); + void updateSprite_locationNum24_3(int i); + void execData3PreUpdate_locationNum24(); + void execData3PostUpdate_locationNum24(); + void execData3PreUpdate_locationNum25(); + void updateSprite_locationNum26_0(int i); + void updateSprite_locationNum26_1(int i); + void execData3PreUpdate_locationNum26(); + void updateSprite_locationNum27(int i); + void execData3PreUpdate_locationNum27(); + void execData3PostUpdate_locationNum27(); + void updateSprite_locationNum28_0(int i); + void updateSprite_locationNum28_1(int i); + void updateSprite_locationNum28_2(int i); + void execData3PreUpdate_locationNum28(); + void execData3PostUpdate_locationNum28(); + void updateSprite_locationNum29_0(int i); + void updateSprite_locationNum29_1(int i); + void updateSprite_locationNum29_2(int i); + void execData3PreUpdate_locationNum29(); + void updateSprite_locationNum30_34(int i); + void execData3PreUpdate_locationNum30(); + void updateSprite_locationNum31_0(int i); + void updateSprite_locationNum31_1(int i); + void execData3PreUpdate_locationNum31(); + void execData3PreUpdate_locationNum31Helper(int r, int flag); + void updateSprite_locationNum32_0(int i); + void execData3PreUpdate_locationNum32(); + void execData3PostUpdate_locationNum32(); + void updateSprite_locationNum33_0(int i); + void updateSprite_locationNum33_1(int i); + void updateSprite_locationNum33_2(int i); + void execData3PreUpdate_locationNum33(); + void execData3PreUpdate_locationNum34(); + void execData3PreUpdate_locationNum35(); + void updateSprite_locationNum36(int i); + void execData3PreUpdate_locationNum36(); + void updateSprite_locationNum37(int i, int j, int offset); + void execData3PreUpdate_locationNum38(); + void updateSprite_locationNum41(int i); + void execData3PreUpdate_locationNum41(); + void updateSprite_locationNum42(int i); + void execData3PreUpdate_locationNum42(); + void updateSprite_locationNum43_2(int i); + void updateSprite_locationNum43_3(int i); + void updateSprite_locationNum43_4(int i); + void updateSprite_locationNum43_5(int i); + void updateSprite_locationNum43_6(int i); + void execData3PreUpdate_locationNum43(); + void execData3PreUpdate_locationNum44(); + void updateSprite_locationNum48(int i); + void updateSprite_locationNum49(int i); + void execData3PreUpdate_locationNum49(); + void updateSprite_locationNum50(int i); + void updateSprite_locationNum51_0(int i); + void updateSprite_locationNum51_1(int i); + void updateSprite_locationNum51_2(int i); + void execData3PreUpdate_locationNum52(); + void updateSprite_locationNum53_0(int i); + void updateSprite_locationNum53_1(int i); + void execData3PreUpdate_locationNum53(); + void updateSprite_locationNum54(int i); + void updateSprite_locationNum55(int i); + void updateSprite_locationNum56(int i); + void updateSprite_locationNum57_0(int i); + void updateSprite_locationNum57_1(int i); + void execData3PreUpdate_locationNum57(); + void updateSprite_locationNum58(int i); + void execData3PreUpdate_locationNum58(); + void updateSprite_locationNum59(int i); + void updateSprite_locationNum60_0(int i); + void updateSprite_locationNum60_1(int i); + void execData3PostUpdate_locationNum60(); + void updateSprite_locationNum61_0(int i); + void updateSprite_locationNum61_1(int i); + void updateSprite_locationNum61_2(int i); + void execData3PreUpdate_locationNum61(); + void updateSprite_locationNum63_0(int i); + void updateSprite_locationNum63_1(int i); + void updateSprite_locationNum63_2(int i); + void updateSprite_locationNum63_3(int i); + void updateSprite_locationNum63_4(int i); + void execData3PreUpdate_locationNum63(); + void execData3PreUpdate_locationNum64(); + void updateSprite_locationNum65(int i); + void execData3PreUpdate_locationNum65(); + void updateSprite_locationNum66_0(int i); + void updateSprite_locationNum66_1(int i); + void updateSprite_locationNum66_2(int i); + void updateSprite_locationNum66_3(int i); + void updateSprite_locationNum66_4(int i); + void execData3PreUpdate_locationNum66(); + void execData3PostUpdate_locationNum66(); + void updateSprite_locationNum69_1(int i); + void updateSprite_locationNum69_2(int i); + void updateSprite_locationNum69_3(int i); + void execData3PreUpdate_locationNum70(); + void execData3PreUpdate_locationNum70Helper(); + void updateSprite_locationNum71(int i); + void updateSprite_locationNum72(int i); + void updateSprite_locationNum74(int i); + void updateSprite_locationNum79(int i); + void updateSprite_locationNum81_0(int i); + void updateSprite_locationNum81_1(int i); + void updateSprite_locationNum82(int i); + + void generateGameStateFileName(int num, char *dst, int len, bool prefixOnly = false) const; + template void saveOrLoadGameStateData(S &s); + void loadGame(int slot); + void saveGame(int slot); + + void handleCreditsSequence(); + void handleCongratulationsSequence(); + void handleNewPartSequence(); + void handleMeanwhileSequence(); + void handleMapSequence(); + void copyMapRect(int x, int y, int w, int h); + int handleSpecialObjectSelectionSequence(); + + void openCompressedSoundFile(); + uint8 *loadFile(uint8 *p = 0); + void loadImage(uint8 *dst, int a); + void loadCursor(); + void loadCharset(); + void loadCharset2(); + void loadCharsetHelper(int charW, int charH, int xSize, int ySize); + void loadCharSizeDta(); + void loadPanel(); + void loadBudSpr(int startOffset); + void loadCTable01(int firstObjNum, int firstSpriteNum, int &lastSpriteNum); + void loadCTable02(int fl); + void loadLoc(); + void loadObj(); + void loadData(); + int loadDataHelper(int offset, int index); + void loadPanObj(); + void loadData3(); + void loadData4(); + void loadActionFile(); + void loadCharPos(); + void loadSprA02_01(); + void loadSprC02_01(); + void loadFx(); + void loadSound(Audio::Mixer::SoundType type, int num, int volume, bool loop, Audio::SoundHandle *handle); + void loadActionsTable(); + + + Common::RandomSource _rnd; + + int _quitGame; + bool _fastMode; + int _syncCounter; + uint32 _lastFrameTime; + int _mainLoopCounter1; + int _mainLoopCounter2; + int _timerCounter1; + int _timerCounter2; + int _flagsTable[kFlagsTableSize]; + int _partNum; + int _currentPartNum; + int _locationNum; + int _nextLocationNum; + int _gamePaused; + int _gamePaused2; + int _data4FlagDebug; + int _displayGameHints; + int _execData3Counter; + + uint8 _maxSaveGameSlot, _currentSaveGameSlot; + uint8 _firstSaveGameSlot, _lastSaveGameSlot; + + int _gameHintsIndex; + int _gameHintsCounter; + int _gameHintsDisplayText; + + char _fileToLoad[40]; + int _fileLoadSize; + bool _useEnc; + int _compressedSoundType; + Common::File _fCompressedSound; + uint8 *_loadTempBuf; + uint8 *_cursorGfxBuf; + uint8 *_charsetGfxBuf; + uint8 *_panelGfxBuf; + uint8 *_itemsGfxBuf; + uint8 *_spritesGfxBuf; + uint8 *_locationBackgroundGfxBuf; + uint8 *_data5Buf; + uint8 *_data3GfxBuf; + uint8 *_quadBackgroundGfxBuf; + uint8 *_objTxtBuf; + uint8 *_panelObjectsGfxBuf; + uint8 *_ptTextBuf; + uint8 *_infoBarBuf; + uint8 *_bgTextBuf; + uint8 *_charNameBuf; + uint8 *_locationBackgroundMaskBuf; + uint8 *_csDataBuf; + int _csDataSize; + uint8 _charWidthTable[256]; + + int _mousePosX, _mousePosY; + int _prevMousePosX, _prevMousePosY; + int _mouseButtonsMask; + int _mouseButtons; + int _mouseButton2; + int _mouseClick; + int _mouseClickOnPanelSliders; + int _mouseIdleCounter; + bool _leftMouseButtonPressed; + bool _rightMouseButtonPressed; + int _lastKeyPressed; + int _keyLastKeyCodePressed; + int _cursorNum; + int _cursorType; + int _updateCursorFlag; + + int _panelNum; + int _panelState; + int _forceRedrawPanelItems; + int _redrawPanelItemsCounter; + int _switchPanelFlag; + int _panelObjectsOffsetTable[50]; + int _switchPanelCounter; + int _conversationOptionsCount; + bool _fadedPanel; + int _panelLockedFlag; + int _panelItemWidth; + int _inventoryItemsState[50]; + int _inventoryObjectsList[40]; + int _inventoryObjectsOffset; + int _inventoryObjectsCount; + int _lastInventoryObjectIndex; + + uint8 *_sprA02Table[kSprA02TableSize]; + uint8 *_sprC02Table[kSprC02TableSize]; + Action _actionsTable[kActionsTableSize]; + int _actionsCount; + LocationObject _locationObjectsTable[kLocationObjectsTableSize]; + int _locationObjectsCount; + Sprite _spritesTable[kMaxCharacters]; + int _spritesCount; + LocationAnimation _locationAnimationsTable[kLocationAnimationsTableSize]; + int _locationAnimationsCount; + Data _dataTable[kDataTableSize]; + int _dataCount; + CharPos _charPosTable[kMaxCharacters]; + int _charPosCount; + LocationSound _locationSoundsTable[kLocationSoundsTableSize]; + int _locationSoundsCount; + LocationMusic _locationMusicsTable[kLocationMusicsTableSize]; + int _locationMusicsCount; + + int _currentFxSet; + int _currentFxDist; + int _currentFxScale; + int _currentFxVolume; + int _currentFxIndex; + int _speechSoundNum; + int _speechVolume; + Audio::SoundHandle _sfxHandles[6]; + Audio::SoundHandle _musicHandles[2]; + Audio::SoundHandle _speechHandle; + int _soundsMapTable[2]; + int _speechHistoryTable[kSpeechHistoryTableSize]; + int _charSpeechSoundVolumeTable[kMaxCharacters]; + int _charSpeechSoundCounter; + int _miscSoundFxDelayCounter[2]; + int _characterSoundFxDelayCounter; + int _characterSoundFxNum; + int _speechSoundBaseNum; + + int _pendingActionIndex; + int _pendingActionDelay; + int _charPositionFlagNum; + int _charPositionFlagValue; + int _actionVerb; + int _nextAction; + int _selectedObjectNum; + int _selectedObjectType; + int _selectedCharacterNum; + int _actionObj1Type, _actionObj2Type; + int _actionObj1Num, _actionObj2Num; + bool _actionRequiresTwoObjects; + int _skipPanelObjectUnderCursor; + int _actionPosX; + int _actionPosY; + int _selectedObjectLocationMask; + struct { + int xDefaultPos; + int yDefaultPos; + int xPos; + int yPos; + int locationObject_locationNum; + int locationObject_toX; + int locationObject_toY; + int locationObject_toX2; + int locationObject_toY2; + int locationObject_toWalkX2; + int locationObject_toWalkY2; + } _selectedObject; + int _selectedCharacterDirection; + int _selectedCharacter2Num; + int _currentActionObj1Num, _currentActionObj2Num; + int _currentInfoString1SourceType, _currentInfoString2SourceType; + int _speechActionCounterTable[9]; + int _actionCharacterNum; + + bool _csDataLoaded; + int _csDataHandled; + int _stopActionOnSoundFlag; + int _csDataTableFlag2; + int _stopActionOnPanelLock; + int _csDataTableCount; + int _stopActionCounter; + int _actionTextColor; + int _nextTableToLoadIndex; + int _nextTableToLoadTable[6]; + int _soundInstructionIndex; + const uint8 *_tableInstructionsPtr; + int _tableInstructionObj1Table[6]; + int _tableInstructionObj2Table[6]; + int _tableInstructionFlag; + int _tableInstructionItemNum1, _tableInstructionItemNum2; + int _instructionsActionsTable[6]; + int _validInstructionId; + + SpriteFrame _spriteFramesTable[kSpriteFramesTableSize]; + SpriteAnimation _spriteAnimationsTable[200]; + int _spriteAnimationFramesTable[500]; + int _spriteAnimationFrameIndex; + int _backgroundSpriteCurrentFrame; + int _backgroundSpriteLastFrame; + int _backgroundSpriteCurrentAnimation; + bool _disableCharactersPath; + bool _skipCurrentCharacterDraw; + int _xPosCurrent; + int _yPosCurrent; + const uint8 *_characterSpeechDataPtr; + int _ptTextOffset; + int _ctable01Table_sprite[20]; + int _characterAnimationsTable[200]; + int _characterStateTable[200]; + int _backgroundSprOffset; + int _updateCharPositionNewType; + int _updateCharPositionType; + int _mainSpritesBaseOffset; + int _currentSpriteAnimationLength; + int _currentSpriteAnimationFrame; + int _currentSpriteAnimationFrame2; + int _characterAnimationIndex; + int _characterFacingDirection; + int _characterPrevFacingDirection; + int _characterBackFrontFacing; + int _characterPrevBackFrontFacing; + int _characterAnimationNum; + int _noCharacterAnimationChange; + int _changeBackgroundSprite; + int _characterSpriteAnimationFrameCounter; + int _locationMaskIgnore; + int _locationMaskType; + int _locationMaskCounter; + int _updateSpriteFlag1; + int _updateSpriteFlag2; + int _handleMapCounter; + bool _noPositionChangeAfterMap; + + int _mirroredDrawing; + uint8 *_loadLocBufPtr; + uint8 *_backgroundSpriteDataPtr; + int _locationHeight; + int _scrollOffset; + int _currentGfxBackgroundCounter; + uint8 *_currentGfxBackground; + int _fadePaletteCounter; + uint8 _currentPalette[768]; + uint8 _backupPalette[768]; + + int _updateLocationFadePaletteCounter; + int _updateLocationCounter; + int _updateLocationPos; + int _updateLocationXPosTable[5], _updateLocationYPosTable[5]; + int _updateLocationFlagsTable[5]; + int _updateLocationXPosTable2[10], _updateLocationYPosTable2[10]; + int _updateLocationYMaxTable[3]; + int _updateLocation14Step[10]; + int _updateLocation14ObjNum[10]; + int _updateLocation14Delay[10]; + int _updateLocationCounter2; + int _updateLocationFlag; + int _updateLocation70StringLen; + uint8 _updateLocation70String[20]; + + static const int _locationWidthTable[85]; + static const uint8 _sprA02LookupTable[88]; + static const uint8 _sprC02LookupTable[100]; + static const uint8 _sprC02LookupTable2[100]; + static const int _staticData3Table[1600]; + static const int _instructionIdTable[20]; + static int _locationHeightTable[80]; + static int _objectKeysPosXTable[80]; + static int _objectKeysPosYTable[80]; + static int _objectKeysLocationTable[80]; + static int _mapSequenceFlagsLocationTable[70]; + static const int _charWidthCharset2[58]; +}; + +} // namespace Tucker + +#endif -- cgit v1.2.3