diff options
| -rw-r--r-- | base/plugins.cpp | 3 | ||||
| -rwxr-xr-x | configure | 1 | ||||
| -rw-r--r-- | engines/engines.mk | 5 | ||||
| -rw-r--r-- | engines/tucker/detection.cpp | 88 | ||||
| -rw-r--r-- | engines/tucker/graphics.cpp | 258 | ||||
| -rw-r--r-- | engines/tucker/graphics.h | 64 | ||||
| -rw-r--r-- | engines/tucker/locations.cpp | 3207 | ||||
| -rw-r--r-- | engines/tucker/module.mk | 19 | ||||
| -rw-r--r-- | engines/tucker/resource.cpp | 959 | ||||
| -rw-r--r-- | engines/tucker/saveload.cpp | 116 | ||||
| -rw-r--r-- | engines/tucker/sequences.cpp | 480 | ||||
| -rw-r--r-- | engines/tucker/staticres.cpp | 219 | ||||
| -rw-r--r-- | engines/tucker/tucker.cpp | 3778 | ||||
| -rw-r--r-- | engines/tucker/tucker.h | 802 | 
14 files changed, 9999 insertions, 0 deletions
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 @@ -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 <class S> +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<int>(c, _currentPalette[color * 3 + i]); +		} +	} +	_system->setPalette(pal, 0, colorsCount); +	_system->updateScreen(); +	_system->delayMillis(20); +} + +void TuckerEngine::fadeInPalette(int colorsCount) { +	uint8 pal[256 * 4]; +	_system->grabPalette(pal, 0, colorsCount); +	for (int color = 0; color < colorsCount; ++color) { +		for (int i = 0; i < 3; ++i) { +			const int c = int(pal[color * 4 + i]) - kFadePaletteStep * 4; +			pal[color * 4 + i] = MAX<int>(c, 0); +		} +	} +	_system->setPalette(pal, 0, colorsCount); +	_system->updateScreen(); +	_system->delayMillis(20); +} + +void TuckerEngine::fadePaletteColor(int color, int step) { +	uint8 rgb[4]; +	_system->grabPalette(rgb, color, 1); +	for (int i = 0; i < 3; ++i) { +		const int c = _currentPalette[color * 3 + i] + step * 4; +		rgb[i] = MIN(c, 255); +	} +	_system->setPalette(rgb, color, 1); +} + +void TuckerEngine::setBlackPalette() { +	uint8 pal[256 * 4]; +	memset(pal, 0, sizeof(pal)); +	_system->setPalette(pal, 0, 256); +} + +void TuckerEngine::setPaletteColor(int color, int r, int g, int b) { +	uint8 rgb[4]; +	rgb[0] = r & 255; +	rgb[1] = g & 255; +	rgb[2] = b & 255; +	rgb[3] = 255; +	_system->setPalette(rgb, color, 1); +} + +void TuckerEngine::updateCursor() { +	setCursorNum(0); +	if (_backgroundSpriteCurrentAnimation == -1 && _panelLockedFlag == 0 && _selectedObject.locationObject_locationNum > 0) { +		_selectedObject.locationObject_locationNum = 0; +	} +	if (_locationMaskType > 0 || _selectedObject.locationObject_locationNum > 0 || _pendingActionDelay > 0) { +		return; +	} +	if (_rightMouseButtonPressed) { +		if (_updateCursorFlag == 0) { +			++_actionVerb; +			if (_actionVerb > 8) { +				_actionVerb = 0; +			} +			_updateCursorFlag = 1; +			_skipPanelObjectUnderCursor = 1; +			_actionRequiresTwoObjects = false; +		} +	} else { +		_updateCursorFlag = 0; +	} +	if (_skipPanelObjectUnderCursor == 0) { +		setActionVerbUnderCursor(); +		if (_actionVerb == 0 && _locationNum == 63) { +			_actionVerb = 8; +		} +	} +	_selectedObjectNum = 0; +	_selectedObjectType = 0; +	int num = setCharacterUnderCursor(); +	if (_selectedObjectType == 0) { +		num = setLocationAnimationUnderCursor(); +	} +	if (_selectedObjectType > 0) { +		_selectedObjectNum = num; +	} else { +		num = getObjectUnderCursor(); +		if (num > -1) { +			_selectedObjectNum = _locationObjectsTable[num].textNum; +		} +	} +	handleMouseClickOnInventoryObject(); +	if (_actionVerb == 2 && _selectedObjectType != 2) { +		_selectedObjectNum = 0; +		_selectedObjectType = 0; +	} else if (_actionVerb == 5 && _selectedObjectType != 3 && !_actionRequiresTwoObjects) { +		_selectedObjectNum = 0; +		_selectedObjectType = 0; +	} +	if (_skipPanelObjectUnderCursor == 0 && _selectedObjectType == 2 && _selectedObjectNum != 21) { +		_actionVerb = 2; +	} +	if (!_actionRequiresTwoObjects) { +		_actionObj1Num = _selectedObjectNum; +		_actionObj1Type = _selectedObjectType; +		_actionObj2Num = 0; +		_actionObj2Type = 0; +	} else if (_actionObj1Num == _selectedObjectNum && _actionObj1Type == _selectedObjectType) { +		_selectedObjectNum = 0; +		_selectedObjectType = 0; +		_actionObj2Num = 0; +		_actionObj2Type = 0; +	} else { +		_actionObj2Num = _selectedObjectNum; +		_actionObj2Type = _selectedObjectType; +	} +	if (!_leftMouseButtonPressed) { +		_mouseClick = 0; +	} +	if (_leftMouseButtonPressed && _mouseClick == 0) { +		_fadedPanel = 0; +		_mouseClick = 1; +		clearItemsGfx(); +		drawInfoString(); +		if (_mousePosY >= 150 && _mousePosX < 212) { +			if (_mousePosX < 200) { +				setActionVerbUnderCursor(); +				_skipPanelObjectUnderCursor = 1; +				_actionRequiresTwoObjects = false; +			} else if (_mousePosY < 175) { +				moveDownInventoryObjects(); +			} else { +				moveUpInventoryObjects(); +			} + 		} else { +			if (_selectedObjectType == 3) { +				setActionForInventoryObject(); +			} else if (_actionVerb != 0) { +				_skipPanelObjectUnderCursor = 0; +				setActionState(); +			} else if (_actionObj1Num == 261 || (_actionObj1Num == 205 && _flagsTable[143] == 0)) { +				_skipPanelObjectUnderCursor = 0; +				setActionState(); +			} else { +				_skipPanelObjectUnderCursor = 0; +				_actionRequiresTwoObjects = false; +				_updateCharPositionNewType = 0; +				setSelectedObjectKey(); +			} +		} +	} +} + +int TuckerEngine::getLastKeyCode() { +	int keyCode = _keyLastKeyCodePressed; +	_keyLastKeyCodePressed = 0; +	return keyCode; +} + +void TuckerEngine::stopSounds() { +	for (int i = 0; i < _locationSoundsCount; ++i) { +		stopSound(i); +	} +	for (int i = 0; i < _locationMusicsCount; ++i) { +		stopMusic(i); +	} +} + +void TuckerEngine::playSounds() { +	for (int i = 0; i < 29; ++i) { +		if (i < _locationSoundsCount) { +			if (_locationSoundsTable[i].type == 1 || _locationSoundsTable[i].type == 2 || _locationSoundsTable[i].type == 5 || +				(_locationSoundsTable[i].type == 7 && _flagsTable[_locationSoundsTable[i].flagNum] == _locationSoundsTable[i].flagValueStartFx)) { +				startSound(_locationSoundsTable[i].offset, i, _locationSoundsTable[i].volume); +			} +		} +		if (i < _locationMusicsCount) { +			if (_locationMusicsTable[i].flag > 0) { +				startMusic(_locationMusicsTable[i].offset, i, _locationMusicsTable[i].volume); +			} +		} +	} +} + +void TuckerEngine::updateCharactersPath() { +	int i = 0; +	int flag = 0; +	if (_panelLockedFlag == 0) { +		return; +	} +	if (_backgroundSpriteCurrentAnimation != -1 && _locationNum != 25) { +		if (_xPosCurrent == _selectedObject.xPos && _yPosCurrent == _selectedObject.yPos) { +			_locationMaskCounter = 1; +			_panelLockedFlag = 0; +		} +		return; +	} +	int xPos = _xPosCurrent; +	int yPos = _yPosCurrent; +	if (_characterFacingDirection == 5) { +		_characterPrevFacingDirection = 5; +	} +	if (_yPosCurrent > _selectedObject.yPos) { +		if (testLocationMask(_xPosCurrent, _yPosCurrent - 1) == 1) { +			--_yPosCurrent; +			_characterFacingDirection = 4; +			flag = 1; +		} else { +			++i; +		} +	} else if (_yPosCurrent < _selectedObject.yPos) { +		if (testLocationMask(_xPosCurrent, _yPosCurrent + 1) == 1) { +			++_yPosCurrent; +			_characterFacingDirection = 2; +			flag = 1; +		} else { +			++i; +		} +	} +	if (_xPosCurrent > _selectedObject.xPos) { +		if (testLocationMask(_xPosCurrent - 1, _yPosCurrent) == 1) { +			--_xPosCurrent; +			_characterFacingDirection = 3; +			_characterBackFrontFacing = 0; +			flag = 1; +		} else { +			++i; +		} +	} else if (_xPosCurrent < _selectedObject.xPos) { +		if (testLocationMask(_xPosCurrent + 1, _yPosCurrent) == 1) { +			++_xPosCurrent; +			_characterFacingDirection = 1; +			_characterBackFrontFacing = 1; +			flag = 1; +		} else { +			++i; +		} +	} +	if (flag == 0) { +		if (_selectedObjectLocationMask == 1) { +			_selectedObjectLocationMask = 0; +			_selectedObject.xPos = _selectedObject.xDefaultPos; +			_selectedObject.yPos = _selectedObject.yDefaultPos; +		} else { +			_panelLockedFlag = 0; +			_characterFacingDirection = 0; +			if (_xPosCurrent == _selectedObject.xPos && _yPosCurrent == _selectedObject.yPos) { +				_locationMaskCounter = 1; +			} +		} +	} +	if (_locationNum == 25) { +		if ((_backgroundSpriteCurrentAnimation == 3 || _characterBackFrontFacing != 0) && (_backgroundSpriteCurrentAnimation != 6 || _characterBackFrontFacing != 1)) { +			_xPosCurrent = xPos; +			_yPosCurrent = yPos; +			return; +		} +	} +	if (_xPosCurrent != _selectedObject.xPos || _yPosCurrent != _selectedObject.yPos) { +		return; +	} +	if (_selectedObjectLocationMask != 0) { +		return; +	} +	_locationMaskCounter = 1; +	_panelLockedFlag = 0; +	_locationMaskIgnore = 0; +	if (_characterPrevFacingDirection <= 0 || _characterPrevFacingDirection >= 5) { +		return; +	} +	if (_selectedObject.locationObject_locationNum == 0) { +		_characterFacingDirection = 5; +		while (_spriteAnimationFramesTable[_spriteAnimationFrameIndex] != 999) { +			++_spriteAnimationFrameIndex; +		} +		++_spriteAnimationFrameIndex; +	} +} + +void TuckerEngine::setSoundVolumeDistance() { +	int w = ABS(_xPosCurrent - _currentFxDist); +	int d = w * _currentFxScale / 10; +	int volume = (d > _currentFxVolume) ? 0 : _currentFxVolume - d; +	setVolumeSound(_currentFxIndex, volume); +} + +void TuckerEngine::updateData3DrawFlag() { +	for (int i = 0; i < _locationAnimationsCount; ++i) { +		if (_locationAnimationsTable[i].flagNum > 0 && _locationAnimationsTable[i].flagValue != _flagsTable[_locationAnimationsTable[i].flagNum]) { +			_locationAnimationsTable[i].drawFlag = 0; +		} else if (_locationAnimationsTable[i].getFlag == 0) { +			_locationAnimationsTable[i].drawFlag = 1; +		} else { +			_locationAnimationsTable[i].drawFlag = (_inventoryItemsState[_locationAnimationsTable[i].inventoryNum] == 0) ? 1 : 0; +		} +	} +} + +void TuckerEngine::updateData3() { +	updateData3DrawFlag(); +	for (int i = 0; i < _locationAnimationsCount; ++i) { +		if (_locationAnimationsTable[i].animLastCounter != 0 && _locationAnimationsTable[i].drawFlag != 0) { +			if (_locationAnimationsTable[i].animLastCounter == _locationAnimationsTable[i].animCurrentCounter) { +				_locationAnimationsTable[i].animCurrentCounter = _locationAnimationsTable[i].animInitCounter; +			} else { +				++_locationAnimationsTable[i].animCurrentCounter; +			} +			const int index = _locationAnimationsTable[i].animCurrentCounter; +			if (_staticData3Table[index] == 998) { +				_flagsTable[_staticData3Table[index + 1]] = _staticData3Table[index + 2]; +				_locationAnimationsTable[i].animCurrentCounter = _locationAnimationsTable[i].animInitCounter; +				_locationAnimationsTable[i].drawFlag = 0; +			} +			_locationAnimationsTable[i].graphicNum = _staticData3Table[_locationAnimationsTable[i].animCurrentCounter]; +		} +	} +	updateData3DrawFlag(); +} + +void TuckerEngine::updateSfxData3_1() { +	for (int i = 0; i < _locationSoundsCount; ++i) { +		if ((_locationSoundsTable[i].type == 6 || _locationSoundsTable[i].type == 7) && _locationSoundsTable[i].updateType == 1) { +			for (int j = 0; j < _spritesCount; ++j) { +				if (_spritesTable[j].animationFrame == _locationSoundsTable[i].startFxSpriteNum && _spritesTable[j].state == _locationSoundsTable[i].startFxSpriteState) { +					if (_locationSoundsTable[i].type == 7) { +						_flagsTable[_locationSoundsTable[i].flagNum] = _locationSoundsTable[i].flagValueStartFx; +					} +					startSound(_locationSoundsTable[i].offset, i, _locationSoundsTable[i].volume); +				} else if (_locationSoundsTable[i].type == 7) { +					if (_spritesTable[j].animationFrame == _locationSoundsTable[i].stopFxSpriteNum && _spritesTable[j].state == _locationSoundsTable[i].stopFxSpriteState) { +						_flagsTable[_locationSoundsTable[i].flagNum] = _locationSoundsTable[i].flagValueStopFx; +						stopSound(i); +					} +				} +			} +		} +	} +} + +void TuckerEngine::updateSfxData3_2() { +	for (int i = 0; i < _locationSoundsCount; ++i) { +		if ((_locationSoundsTable[i].type == 6 || _locationSoundsTable[i].type == 7) && _locationSoundsTable[i].updateType == 0) { +			if (_locationSoundsTable[i].startFxSpriteNum == _backgroundSpriteCurrentFrame && _locationSoundsTable[i].startFxSpriteState == _backgroundSpriteCurrentAnimation) { +				if (_locationSoundsTable[i].type == 7) { +					_flagsTable[_locationSoundsTable[i].flagNum] = _locationSoundsTable[i].flagValueStartFx; +				} +				startSound(_locationSoundsTable[i].offset, i, _locationSoundsTable[i].volume); +			} else if (_locationSoundsTable[i].type == 7) { +				if (_locationSoundsTable[i].stopFxSpriteNum == _backgroundSpriteCurrentFrame && _locationSoundsTable[i].stopFxSpriteState == _backgroundSpriteCurrentAnimation) { +					_flagsTable[_locationSoundsTable[i].flagNum] = _locationSoundsTable[i].flagValueStopFx; +					stopSound(i); +				} +			} +		} +	} +} + +void TuckerEngine::saveOrLoad() { +	if (!_leftMouseButtonPressed) { +		_mouseClick = 0; +	} +	if (_firstSaveGameSlot > 0) { +		drawSpeechText(_scrollOffset + 120, 170, _infoBarBuf, _mouseClickOnPanelSliders + 19, 102); +		int len = getStringWidth(_mouseClickOnPanelSliders + 19, _infoBarBuf); +		drawStringInteger(_firstSaveGameSlot, len / 2 + 128, 160, 2); +	} else { +		drawSpeechText(_scrollOffset + 120, 170, _infoBarBuf, 21, 102); +	} +	if (_leftMouseButtonPressed && _mouseClick == 0) { +		_mouseClick = 1; +		if (_mousePosX > 228 && _mousePosX < 240 && _mousePosY > 154 & _mousePosY < 170) { +			if (_firstSaveGameSlot < _lastSaveGameSlot) { +				++_firstSaveGameSlot; +				_forceRedrawPanelItems = 1; +			} +			return; +		} +		if (_mousePosX > 228 && _mousePosX < 240 && _mousePosY > 170 && _mousePosY < 188) { +			if (_firstSaveGameSlot > 1) { +				--_firstSaveGameSlot; +				_forceRedrawPanelItems = 1; +			} +			return; +		} +		if (_mousePosX > 244 && _mousePosX < 310 && _mousePosY > 170 && _mousePosY < 188) { +			_forceRedrawPanelItems = 1; +			_panelState = 2; +			return; +		} +		if (_mousePosX > 260 && _mousePosX < 290 && _mousePosY > 152 && _mousePosY < 168) { +			if (_mouseClickOnPanelSliders == 1) { +				saveGame(_firstSaveGameSlot); +			} else if (_firstSaveGameSlot > 0) { +				loadGame(_firstSaveGameSlot); +			} +			_forceRedrawPanelItems = 1; +			_panelState = 0; +			setCursorType(0); +			return; +		} +	} +} + +void TuckerEngine::handleMouseOnPanel() { +	if (!_leftMouseButtonPressed) { +		_mouseClick = 0; +	} +	if (_leftMouseButtonPressed && _mouseClick == 0) { +		_mouseClick = 1; +		if (_mousePosY < 160 || _mousePosY > 176) { +			return; +		} +		if (_mousePosX < 45 || _mousePosX > 275) { +			return; +		} +		if (_mousePosX < 96) { +			_mouseClickOnPanelSliders = 0; +			_forceRedrawPanelItems = 1; +			_panelState = 3; +			_firstSaveGameSlot = _currentSaveGameSlot; +			_lastSaveGameSlot = _maxSaveGameSlot; +		} else if (_mousePosX < 158) { +			_mouseClickOnPanelSliders = 1; +			_forceRedrawPanelItems = 1; +			_panelState = 3; +			if (_maxSaveGameSlot < 99) { +				_firstSaveGameSlot = _maxSaveGameSlot + 1; +				_lastSaveGameSlot = _firstSaveGameSlot; +			} else { +				_lastSaveGameSlot = 99; +				if (_currentSaveGameSlot < 99) { +					_firstSaveGameSlot = _currentSaveGameSlot + 1; +				} else { +					_firstSaveGameSlot = 1; +				} +			} +		} else if (_mousePosX < 218) { +			_forceRedrawPanelItems = 1; +			_panelState = 0; +			setCursorType(0); +		} else { +			_quitGame = 1; +		} +	} +} + +void TuckerEngine::switchPanelType() { +	if (_panelState == 0 && _switchPanelFlag == 0 && _lastKeyPressed == Common::KEYCODE_F1) { +		_switchPanelFlag = 1; +		_switchPanelCounter = 1; +		return; +	} +	if (_switchPanelFlag == 0) { +		return; +	} +	if (_switchPanelFlag == 1) { +		if (_switchPanelCounter == 25) { +			if (_panelNum == 0) { +				_panelNum = 1; +			} else { +				_panelNum = 0; +			} +			_switchPanelFlag = 2; +			loadPanel(); +			_forceRedrawPanelItems = 1; +		} else { +			++_switchPanelCounter; +		} +	} else { +		--_switchPanelCounter; +		if (_switchPanelCounter == 0) { +			_switchPanelFlag = 0; +		} +	} +} + +void TuckerEngine::redrawPanelOverBackground() { +	const uint8 *src = _itemsGfxBuf; +	uint8 *dst = _locationBackgroundGfxBuf + 89600 + _scrollOffset; +	for (int y = 0; y < 10; ++y) { +		memcpy(dst, src, 320); +		src += 320; +		dst += 640; +	} +	for (int y = 0; y < _switchPanelCounter; ++y) { +		for (int x = 0; x < 320; ++x) { +			dst[x] = 0; +		} +		dst += 640; +	} +	int y2 = 50 - _switchPanelCounter * 2; +	for (int y = 0; y < y2; ++y) { +		int i = y * 50 / y2; +		memcpy(dst, src + i * 320, 320); +		dst += 640; +	} +	for (int y = 0; y < _switchPanelCounter; ++y) { +		for (int x = 0; x < 320; ++x) { +			dst[x] = 0; +		} +		dst += 640; +	} +	if (_conversationOptionsCount > 0) { +		drawConversationTexts(); +	} +} + +void TuckerEngine::drawConversationTexts() { +	int x = 0; +	int y = 141; +	int flag = 0; +	for (int i = 0; i <  _conversationOptionsCount; ++i) { +		int color = 108; +		if ((_mousePosY > y && _mousePosY < y + 11) || _nextTableToLoadIndex == i) { +			color = 106; +		} +		drawSpeechText(x, y, _characterSpeechDataPtr, _instructionsActionsTable[i], color); +		if (_mousePosY > y && _mousePosY < _panelItemWidth * 10 + y + 1) { +			_nextTableToLoadIndex = i; +			flag = 1; +		} +		y += _panelItemWidth * 10; +	} +	if (flag == 0) { +		_nextTableToLoadIndex = -1; +	} +} + +void TuckerEngine::updateScreenScrolling() { +	if (_locationWidthTable[_locationNum] != 2) { +		_scrollOffset = 0; +	} else if (_validInstructionId == 1) { +		_scrollOffset = _xPosCurrent - 200; +	} else if (_locationNum == 16 && _backgroundSpriteCurrentAnimation == 6 && _scrollOffset + 200 < _xPosCurrent) { +		++_scrollOffset; +		if (_scrollOffset > 320) { +			_scrollOffset = 320; +		} +	} else if (_scrollOffset + 120 > _xPosCurrent) { +		_scrollOffset = _xPosCurrent - 120; +		if (_scrollOffset < 0) { +			_scrollOffset = 0; +		} +	} else if (_scrollOffset + 200 < _xPosCurrent) { +		_scrollOffset = _xPosCurrent - 200; +		if (_scrollOffset > 320) { +			_scrollOffset = 320; +		} +	} +} + +void TuckerEngine::updateGameHints() { +	if (_gameHintsIndex == 0 && _flagsTable[3] > 0) { +		_gameHintsIndex = 1; +		_gameHintsCounter = 0; +		_gameHintsDisplayText = 0; +	} else if (_gameHintsIndex == 1 && _flagsTable[12] > 0) { +		_gameHintsIndex = 2; +		_gameHintsCounter = 0; +		_gameHintsDisplayText = 0; +	} else if (_gameHintsIndex == 2 && _flagsTable[20] > 0) { +		_gameHintsIndex = 3; +		_gameHintsCounter = 0; +		_gameHintsDisplayText = 0; +	} else if (_gameHintsIndex == 3 && _flagsTable[9] > 0) { +		_gameHintsIndex = 4; +		_gameHintsCounter = 0; +		_gameHintsDisplayText = 0; +	} else if (_gameHintsIndex == 4 && _flagsTable[23] > 0) { +		_gameHintsIndex = 5; +		_gameHintsCounter = 0; +		_gameHintsDisplayText = 0; +	} else if (_flagsTable[19] > 0) { +		_gameHintsIndex = 6; +		_gameHintsCounter = 0; +		_gameHintsDisplayText = 0; +	} +	++_gameHintsCounter; +	if (_gameHintsCounter > 1500) { +		_gameHintsDisplayText = 1; +	} +} + +void TuckerEngine::startCharacterSounds() { +	if (_characterSoundFxDelayCounter != 0) { +		--_characterSoundFxDelayCounter; +		if (_characterSoundFxDelayCounter <= 0) { +			startSound(_locationSoundsTable[_characterSoundFxNum].offset, _characterSoundFxNum, _locationSoundsTable[_characterSoundFxNum].volume); +		} +	} +} + +void TuckerEngine::updateSoundsTypes3_4() { +	if (isSoundPlaying(0)) { +		return; +	} +	for (int i = 0; i < _locationSoundsCount; ++i) { +		switch (_locationSoundsTable[i].type) { +		case 3: +			if (getRandomNumber() >= 32300) { +				startSound(_locationSoundsTable[i].offset, 0, _locationSoundsTable[i].volume); +				return; +			} +			break; +		case 4: +			if (getRandomNumber() >= 32763) { +				startSound(_locationSoundsTable[i].offset, 0, _locationSoundsTable[i].volume); +				return; +			} +			break; +		} +	} +} + +void TuckerEngine::drawData3() { +	for (int i = 0; i < _locationAnimationsCount; ++i) { +		int num = _locationAnimationsTable[i].graphicNum; +		const int offset = _dataTable[num].yDest * 640 + _dataTable[num].xDest; +		if (_locationAnimationsTable[i].drawFlag != 0) { +			Graphics::decodeRLE(_locationBackgroundGfxBuf + offset, _data3GfxBuf + _dataTable[num].sourceOffset, _dataTable[num].xSize, _dataTable[num].ySize); +		} +	} +} + +void TuckerEngine::execData3PreUpdate() { +	switch (_locationNum) { +	case 1: +		execData3PreUpdate_locationNum1(); +		break; +	case 2: +		execData3PreUpdate_locationNum2(); +		break; +	case 3: +		execData3PreUpdate_locationNum3(); +		break; +	case 4: +		execData3PreUpdate_locationNum4(); +		break; +	case 6: +		execData3PreUpdate_locationNum6(); +		break; +	case 9: +		execData3PreUpdate_locationNum9(); +		break; +	case 10: +		execData3PreUpdate_locationNum10(); +		break; +	case 12: +		execData3PreUpdate_locationNum12(); +		break; +	case 13: +		execData3PreUpdate_locationNum13(); +		break; +	case 14: +		if (_yPosCurrent > 126) { +			execData3PreUpdate_locationNum14(); +		} +		break; +	case 15: +		execData3PreUpdate_locationNum15(); +		break; +	case 16: +		execData3PreUpdate_locationNum16(); +		break; +	case 19: +		execData3PreUpdate_locationNum19(); +		break; +	case 21: +		execData3PreUpdate_locationNum21(); +		break; +	case 22: +		execData3PreUpdate_locationNum22(); +		break; +	case 24: +		execData3PreUpdate_locationNum24(); +		break; +	case 25: +		execData3PreUpdate_locationNum25(); +		break; +	case 26: +		execData3PreUpdate_locationNum26(); +		break; +	case 27: +		execData3PreUpdate_locationNum27(); +		break; +	case 28: +		execData3PreUpdate_locationNum28(); +		break; +	case 29: +		execData3PreUpdate_locationNum29(); +		break; +	case 30: +		execData3PreUpdate_locationNum30(); +		break; +	case 31: +		execData3PreUpdate_locationNum31(); +		break; +	case 32: +		execData3PreUpdate_locationNum32(); +		break; +	case 33: +		execData3PreUpdate_locationNum33(); +		break; +	case 34: +		execData3PreUpdate_locationNum34(); +		break; +	case 35: +		execData3PreUpdate_locationNum35(); +		break; +	case 36: +		execData3PreUpdate_locationNum36(); +		break; +	case 38: +		execData3PreUpdate_locationNum38(); +		break; +	case 41: +		execData3PreUpdate_locationNum41(); +		break; +	case 42: +		execData3PreUpdate_locationNum42(); +		break; +	case 43: +		execData3PreUpdate_locationNum43(); +		break; +	case 44: +		execData3PreUpdate_locationNum44(); +		break; +	case 49: +		execData3PreUpdate_locationNum49(); +		break; +	case 52: +		execData3PreUpdate_locationNum52(); +		break; +	case 53: +		execData3PreUpdate_locationNum53(); +		break; +	case 57: +		execData3PreUpdate_locationNum57(); +		break; +	case 58: +		execData3PreUpdate_locationNum58(); +		break; +	case 61: +		execData3PreUpdate_locationNum61(); +		break; +	case 63: +		execData3PreUpdate_locationNum63(); +		break; +	case 64: +		execData3PreUpdate_locationNum64(); +		break; +	case 65: +		execData3PreUpdate_locationNum65(); +		break; +	case 66: +		execData3PreUpdate_locationNum66(); +		break; +	case 70: +		execData3PreUpdate_locationNum70(); +		break; +	} +} + +void TuckerEngine::drawBackgroundSprites(int flipX) { +	if (_backgroundSpriteDataPtr && _backgroundSpriteCurrentFrame != 0 && _backgroundSpriteCurrentFrame <= _backgroundSpriteLastFrame) { +		int frameOffset = READ_LE_UINT24(_backgroundSpriteDataPtr + _backgroundSpriteCurrentFrame * 4); +		int srcW = READ_LE_UINT16(_backgroundSpriteDataPtr + frameOffset); +		int srcH = READ_LE_UINT16(_backgroundSpriteDataPtr + frameOffset + 2); +		int srcX = READ_LE_UINT16(_backgroundSpriteDataPtr + frameOffset + 8); +		int srcY = READ_LE_UINT16(_backgroundSpriteDataPtr + frameOffset + 10); +		if (_locationNum == 22 && _backgroundSpriteCurrentAnimation > 1) { +			srcY += _mainSpritesBaseOffset; +		} +		if (_locationNum == 29 && _backgroundSpriteCurrentAnimation == 3) { +			srcX += 228; +		} else if (_locationNum == 58 && _backgroundSpriteCurrentAnimation == 1) { +			srcX += 100; +		} else if (_xPosCurrent > 320 && _xPosCurrent < 640) { +			srcX += 320; +		} +		int offset = _backgroundSprOffset + srcY * 640 + srcX; +		Graphics::decodeRLE_248(_locationBackgroundGfxBuf + offset, _backgroundSpriteDataPtr + frameOffset + 12, srcW, srcH, 0, _locationHeightTable[_locationNum], flipX); +	} +} + +void TuckerEngine::setVolumeSound(int index, int volume) { +	if (volume < 0) { +		volume = 0; +	} +	_mixer->setChannelVolume(_sfxHandles[index], volume * Audio::Mixer::kMaxChannelVolume / kMaxSoundVolume); +} + +void TuckerEngine::setVolumeMusic(int index, int volume) { +	if (volume < 0) { +		volume = 0; +	} +	_mixer->setChannelVolume(_musicHandles[index], volume * Audio::Mixer::kMaxChannelVolume / kMaxSoundVolume); +} + +void TuckerEngine::startSound(int offset, int index, int volume) { +	bool loop = (_locationSoundsTable[index].type == 2 || _locationSoundsTable[index].type == 5 || _locationSoundsTable[index].type == 7); +	loadSound(Audio::Mixer::kSFXSoundType, _locationSoundsTable[index].num, volume, loop, &_sfxHandles[index]); +} + +void TuckerEngine::stopSound(int index) { +	_mixer->stopHandle(_sfxHandles[index]); +} + +bool TuckerEngine::isSoundPlaying(int index) { +	return _mixer->isSoundHandleActive(_sfxHandles[index]); +} + +void TuckerEngine::startMusic(int offset, int index, int volume) { +	bool loop = (_locationMusicsTable[index].flag == 2); +	loadSound(Audio::Mixer::kMusicSoundType, _locationMusicsTable[index].num, volume, loop, &_musicHandles[index]); +} + +void TuckerEngine::stopMusic(int index) { +	_mixer->stopHandle(_musicHandles[index]); +} + +void TuckerEngine::startSpeechSound(int num, int volume) { +	loadSound(Audio::Mixer::kSpeechSoundType, num, volume, false, &_speechHandle); +} + +bool TuckerEngine::isSpeechSoundPlaying() { +	return _mixer->isSoundHandleActive(_speechHandle); +} + +void TuckerEngine::redrawPanelItems() { +	const uint8 *src; +	uint8 *dst; +	int sz; +	if (_forceRedrawPanelItems != 0 || (_redrawPanelItemsCounter != 0 && _panelState == 0)) { +		_forceRedrawPanelItems = 0; +		if (_redrawPanelItemsCounter > 0) { +			--_redrawPanelItemsCounter; +		} +		switch (_panelState) { +		case 0: +			src = _panelGfxBuf; +			dst = _itemsGfxBuf + 3200; +			sz = 16000; +			break; +		case 1: +			src = _panelGfxBuf + 16320; +			dst = _itemsGfxBuf; +			sz = 19200; +			break; +		case 2: +			src = _panelGfxBuf + 16320; +			dst = _itemsGfxBuf; +			sz = 19200; +			memcpy(dst, src, sz); +			src = _panelGfxBuf + 55040; +			dst = _itemsGfxBuf + 6400; +			sz = 5120; +			break; +		case 3: +			src = _panelGfxBuf + 35200; +			dst = _itemsGfxBuf; +			sz = 19200; +			break; +		} +		memcpy(dst, src, sz); +		if (_panelState == 0) { +			redrawPanelItemsHelper(); +		} +	} +} + +void TuckerEngine::redrawPanelItemsHelper() { +	const int k = (_redrawPanelItemsCounter / 4) - ((_redrawPanelItemsCounter / 8) * 2); +	for (int i = 0; i < 2; ++i) { +		for (int j = 0; j < 3; ++j) { +			if (i * 3 + j + _inventoryObjectsOffset >= _inventoryObjectsCount) { +				continue; +			} +			if (i * 3 + j + _inventoryObjectsOffset == _lastInventoryObjectIndex && k != 0) { +				continue; +			} +			const int obj = _inventoryObjectsList[i * 3 + j + _inventoryObjectsOffset]; +			const uint8 *src = _panelObjectsGfxBuf + _panelObjectsOffsetTable[obj]; +			uint8 *dst = _itemsGfxBuf + 3412 + i * 8320 + j * 34; +			Graphics::decodeRLE_320(dst, src, 32, 24); +		} +	} +} + +void TuckerEngine::drawSprite(int num) { +	if (_spritesTable[num].animationFrame <= _spritesTable[num].firstFrame && _spritesTable[num].animationFrame > 0) { +		if (_spritesTable[num].state != -1) { +			const uint8 *p = _spritesTable[num].animationData; +			if (!p) { +				return; +			} +			int frameOffset = READ_LE_UINT24(p + _spritesTable[num].animationFrame * 4); +			int srcW = READ_LE_UINT16(p + frameOffset); +			int srcH = READ_LE_UINT16(p + frameOffset + 2); +			int srcX = READ_LE_UINT16(p + frameOffset + 8); +			int srcY = READ_LE_UINT16(p + frameOffset + 10); +			int dstOffset = _spritesTable[num].gfxBackgroundOffset + srcX; +			if (dstOffset < 600 && (_scrollOffset + 320 < dstOffset || _scrollOffset - srcW > dstOffset)) { +				return; +			} +			_spritesTable[num].xSource = srcX; +			_spritesTable[num].gfxBackgroundOffset += _spritesTable[num].backgroundOffset; +			uint8 *dstPtr = _locationBackgroundGfxBuf + srcY * 640 + dstOffset; +			const uint8 *srcPtr = p + frameOffset + 12; +			if (_spritesTable[num].colorType == 0) { +				Graphics::decodeRLE(dstPtr, srcPtr, srcW, srcH); +			} else if (_spritesTable[num].colorType == 99) { +				Graphics::decodeRLE_224(dstPtr, srcPtr, srcW, srcH); +			} else { +				Graphics::decodeRLE_248(dstPtr, srcPtr, srcW, srcH, 0, _spritesTable[num].yMaxBackground, _spritesTable[num].flipX != 0); +			} +		} +	} +} + +void TuckerEngine::clearItemsGfx() { +	memset(_itemsGfxBuf, 0, 3200); +} + +void TuckerEngine::drawPausedInfoBar() { +	int len = getStringWidth(36, _infoBarBuf); +	int x = 159 - len / 2; +	drawString(_itemsGfxBuf + 326 + x, 36, _infoBarBuf); +} + +const uint8 *TuckerEngine::getStringBuf(int type) const { +	const uint8 *p = 0; +	switch (type) { +	case 0: +		p = _data5Buf; +		break; +	case 1: +		p = _bgTextBuf; +		break; +	case 2: +		p = _charNameBuf; +		break; +	case 3: +		p = _objTxtBuf; +		break; +	} +	return p; +} + +void TuckerEngine::drawInfoString() { +	const uint8 *infoStrBuf = _infoBarBuf; +	const uint8 *obj1StrBuf = getStringBuf(_actionObj1Type); +	const uint8 *obj2StrBuf = 0; +	int infoStringWidth = 0; +	int object1NameWidth = 0; +	int verbWidth = getStringWidth(_actionVerb + 1, infoStrBuf); +	if (_actionObj1Num > 0 || _actionObj1Type > 0) { +		object1NameWidth = getStringWidth(_actionObj1Num + 1, obj1StrBuf) + 4; +		infoStringWidth = verbWidth + object1NameWidth; +	} else { +		infoStringWidth = verbWidth; +	} +	int verbPreposition = 0; +	int verbPrepositionWidth = 0; +	if (_actionRequiresTwoObjects) { +		verbPreposition = (_actionVerb == 5) ? 12 : 11; +		verbPrepositionWidth = getStringWidth(verbPreposition, infoStrBuf) + 4; +		if ((_actionObj2Num > 0 || _actionObj2Type > 0) && verbPreposition > 0) { +			infoStringWidth = 0; +			verbWidth = 0; +			object1NameWidth = 0; +		} +		infoStringWidth += verbPrepositionWidth; +		obj2StrBuf = getStringBuf(_actionObj2Type); +		if (_actionObj2Num > 0 && 	_actionObj2Type > 0) { +			infoStringWidth += getStringWidth(_actionObj2Num + 1, obj2StrBuf); +		} +	} +	const int xPos = 159 - infoStringWidth / 2; +	if (verbPreposition == 0 || (_actionObj2Num == 0 && _actionObj2Type == 0)) { +		drawString(_itemsGfxBuf + xPos, _actionVerb + 1, infoStrBuf); +		if (_actionObj1Num != 0 || _actionObj1Type != 0) { +			drawString(_itemsGfxBuf + 4 + xPos + verbWidth, _actionObj1Num + 1, obj1StrBuf); +		} +	} +	if (verbPreposition > 0) { +		drawString(_itemsGfxBuf + xPos + 4 + verbWidth + object1NameWidth, verbPreposition, infoStrBuf); +		if (_actionObj2Num != 0 || _actionObj2Type != 0) { +			drawString(_itemsGfxBuf + xPos + 4 + verbWidth + object1NameWidth + verbPrepositionWidth, _actionObj2Num + 1, obj2StrBuf); +		} +	} +} + +void TuckerEngine::drawGameHintString() { +	int len = getStringWidth(_mouseButton2 + 29, _infoBarBuf); +	int x = 159 - len / 2; +	drawString(_itemsGfxBuf + 326 + x, _mouseButton2 + 29, _infoBarBuf); +} + +void TuckerEngine::updateCharacterAnimation() { +	if (_characterAnimationIndex > -1) { +		if (_backgroundSpriteCurrentFrame == 0) { +			_backgroundSpriteCurrentAnimation = _characterAnimationsTable[_characterAnimationIndex]; +			++_characterAnimationIndex; +			_backgroundSpriteDataPtr = _sprA02Table[_backgroundSpriteCurrentAnimation]; +			_backgroundSpriteLastFrame = READ_LE_UINT16(_backgroundSpriteDataPtr); +			_backgroundSpriteCurrentFrame = _characterAnimationsTable[_characterAnimationIndex]; +			++_characterAnimationIndex; +		} else if (_characterAnimationsTable[_characterAnimationIndex] == 99) { +			_characterAnimationIndex = -1; +			_backgroundSpriteCurrentAnimation = -1; +			if (_nextAction == 0) { +				setCursorType(0); +			} +		} else { +			_backgroundSpriteCurrentFrame = _characterAnimationsTable[_characterAnimationIndex]; +			if (_noCharacterAnimationChange == 0) { +				++_characterAnimationIndex; +			} +		} +	} else if (_backgroundSpriteCurrentAnimation > -1) { +		while (_spriteAnimationFramesTable[_spriteAnimationFrameIndex] != 999) { +			++_spriteAnimationFrameIndex; +		} +		_characterFacingDirection = 0; +		if (_changeBackgroundSprite == 1) { +			if (_backgroundSpriteCurrentFrame == 0) { +				_backgroundSpriteDataPtr = _sprA02Table[_backgroundSpriteCurrentAnimation]; +				_backgroundSpriteCurrentFrame = _backgroundSpriteLastFrame = READ_LE_UINT16(_backgroundSpriteDataPtr); +			} else { +				--_backgroundSpriteCurrentFrame; +				if (_backgroundSpriteCurrentFrame > 1) { +					_backgroundSpriteCurrentAnimation = -1; +					_backgroundSpriteCurrentFrame = 0; +					_changeBackgroundSprite = 0; +					if (_nextAction == 0) { +						setCursorType(0); +					} +				} +			} +		} else { +			if (_backgroundSpriteCurrentFrame == 0) { +				_backgroundSpriteCurrentFrame = 1; +				assert(_backgroundSpriteCurrentAnimation >= 0 && _backgroundSpriteCurrentAnimation < kSprA02TableSize); +				_backgroundSpriteDataPtr = _sprA02Table[_backgroundSpriteCurrentAnimation]; +				_backgroundSpriteLastFrame = READ_LE_UINT16(_backgroundSpriteDataPtr); +			} else if (_locationNum == 25 && _panelLockedFlag != 1 && (_backgroundSpriteCurrentAnimation == 3 || _backgroundSpriteCurrentAnimation == 6)) { +				_backgroundSpriteCurrentFrame = 0; +				_backgroundSpriteCurrentAnimation = -1; +			} else { +				++_backgroundSpriteCurrentFrame; +				if (_backgroundSpriteCurrentFrame > _backgroundSpriteLastFrame) { +					_backgroundSpriteCurrentAnimation = -1; +					_backgroundSpriteCurrentFrame = 0; +					if (_nextAction == 0 && _panelState == 0) { +						setCursorType(0); +					} +				} +			} +		} +	} +	if (_locationNum == 24 && _flagsTable[103] == 0) { +		if (_panelLockedFlag == 1) { +			_panelLockedFlag = 0; +			_selectedObject.locationObject_locationNum = 0; +			if (_actionVerb != 2) { +				_speechSoundNum = 2236; +				startSpeechSound(_speechSoundNum, _speechVolume); +				_characterSpeechDataPtr = _ptTextBuf + getPositionForLine(_speechSoundNum, _ptTextBuf); +				_speechSoundNum = 0; +				_actionPosX = _xPosCurrent; +				_actionPosY = _yPosCurrent - 64; +				_actionTextColor = 1; +				_actionCharacterNum = 99; +				setCursorType(2); +				_charSpeechSoundCounter = kDefaultCharSpeechSoundCounter; + +			} +		} +		if (_charSpeechSoundCounter == 0 || _actionCharacterNum != 99) { +			if (_backgroundSpriteCurrentAnimation == 5) { +				_backgroundSpriteCurrentFrame = 0; +			} +		} else { +			if (_backgroundSpriteCurrentAnimation != 5) { +				_backgroundSpriteCurrentFrame = 0; +			} +		} +		if (_backgroundSpriteCurrentFrame == 0) { +			if (_charSpeechSoundCounter > 0 && _actionCharacterNum == 99) { +				_backgroundSpriteCurrentAnimation = 5; +			} else { +				_backgroundSpriteCurrentAnimation = (getRandomNumber() < 33000) ? 2 : 3; +			} +			_backgroundSpriteCurrentFrame = 1; +			_backgroundSpriteDataPtr = _sprA02Table[_backgroundSpriteCurrentAnimation]; +			_backgroundSpriteLastFrame = READ_LE_UINT16(_backgroundSpriteDataPtr); +		} +	} else if (_locationNum == 25) { +		if (_backgroundSpriteCurrentFrame == 0) { +			if (_characterBackFrontFacing == 0) { +				if (_characterBackFrontFacing != _characterPrevBackFrontFacing) { +					_backgroundSpriteCurrentAnimation = 10; +				} else if (_panelLockedFlag == 1) { +					_backgroundSpriteCurrentAnimation = 3; +				} else if (_charSpeechSoundCounter > 0 && _actionCharacterNum == 99) { +					_backgroundSpriteCurrentAnimation = 8; +				} else { +					_backgroundSpriteCurrentAnimation = (getRandomNumber() < 32000) ? 11 : 5; +				} +			} else { +				if (_characterBackFrontFacing != _characterPrevBackFrontFacing) { +					_backgroundSpriteCurrentAnimation = 2; +				} else if (_panelLockedFlag == 1) { +					_backgroundSpriteCurrentAnimation = 6; +				} else if (_charSpeechSoundCounter > 0 && _actionCharacterNum == 99) { +					_backgroundSpriteCurrentAnimation = 9; +				} else { +					_backgroundSpriteCurrentAnimation = (getRandomNumber() < 32000) ? 12 : 7; +				} +			} +			_characterPrevBackFrontFacing = _characterBackFrontFacing; +			_backgroundSpriteCurrentFrame = 1; +			_backgroundSpriteDataPtr = _sprA02Table[_backgroundSpriteCurrentAnimation]; +			_backgroundSpriteLastFrame = READ_LE_UINT16(_backgroundSpriteDataPtr); +		} +		_backgroundSprOffset = _xPosCurrent - 160; +	} else if (_locationNum == 63 && _backgroundSpriteCurrentFrame == 0) { +		if (_charSpeechSoundCounter > 0 && _actionCharacterNum == 99) { +			_backgroundSpriteCurrentAnimation = 1; +		} else { +			_backgroundSpriteCurrentAnimation = (getRandomNumber() < 32000) ? 3 : 2; +		} +		_backgroundSpriteCurrentFrame = 1; +		_backgroundSpriteDataPtr = _sprA02Table[_backgroundSpriteCurrentAnimation]; +		_backgroundSpriteLastFrame = READ_LE_UINT16(_backgroundSpriteDataPtr); +	} +	int var8 = _spriteAnimationFramesTable[_spriteAnimationFrameIndex]; +	if (_panelLockedFlag == 0 && _characterFacingDirection < 5 && _selectedObject.locationObject_locationNum == 0) { +		_characterFacingDirection = 0; +	} +	if (_charSpeechSoundCounter > 0 && _characterFacingDirection == 6 && _actionCharacterNum == 99) { +		_characterFacingDirection = 6; +		var8 = 999; +	} else { +		if (_characterFacingDirection == 6 && _charSpeechSoundCounter != 0 && _actionCharacterNum != 99) { +			_characterFacingDirection = 0; +			var8 = 999; +		} +	} +	int num; +	if (var8 == 999 || (_characterFacingDirection != _characterPrevFacingDirection && _characterFacingDirection < 5)) { +		_mirroredDrawing = 0; +		if (_characterFacingDirection == 6) { +			if (_csDataHandled != 0) { +				if (_selectedCharacterDirection == 1) { +					num = 17; +				} else if (_selectedCharacterDirection == 2) { +					num = 16; +				} else if (_selectedCharacterDirection == 4) { +					num = 15; +				} else { +					num = 16; +					_mirroredDrawing = 1; +				} +			} else { +				num = 15; +			} +		} +		if (_characterFacingDirection == 5) { +			_characterFacingDirection = 0; +		} +		if (_characterFacingDirection == 0) { +			if (_csDataHandled != 0) { +				_mirroredDrawing = 0; +				if (_selectedCharacterDirection == 1) { +					num = 3; +				} else if (_selectedCharacterDirection == 2) { +					num = 1; // 2 ? +				} else if (_selectedCharacterDirection == 3) { +					num = 1; +					_mirroredDrawing = 1; +				} else { +					num = 5; +				} +			} else if (getRandomNumber() < 2000) { +				num = 13; +			} else if (getRandomNumber() < 3000) { +				num = 14; +				if (_locationNum == 57) { +					num = 18; +				} +			} else { +				num = (getRandomNumber() < 20000) ? 18 : 6; +			} +		} else { +			if (_characterFacingDirection == 1) { +				num = 0; +			} else if (_characterFacingDirection == 2) { +				num = 4; +			} else if (_characterFacingDirection == 3) { +				num = 0; +				_mirroredDrawing = 1; +			} else if (_characterFacingDirection == 4) { +				num = 2; +			} +		} +		_currentSpriteAnimationLength = _spriteAnimationsTable[num].numParts; +		_spriteAnimationFrameIndex = _spriteAnimationsTable[num].firstFrameIndex; +		var8 = _spriteAnimationFramesTable[_spriteAnimationFrameIndex]; +	} +	if (_characterAnimationNum > 0) { +		num = _characterAnimationNum; +		_currentSpriteAnimationLength = _spriteAnimationsTable[num].numParts; +		_spriteAnimationFrameIndex = _spriteAnimationsTable[num].firstFrameIndex; +		var8 = _spriteAnimationFramesTable[_spriteAnimationFrameIndex]; +		_characterAnimationNum = 0; +	} +	_currentSpriteAnimationFrame = var8; +	++_spriteAnimationFrameIndex; +	if (_currentSpriteAnimationLength > 1) { +		_currentSpriteAnimationFrame2 = _spriteAnimationFramesTable[_spriteAnimationFrameIndex]; +		++_spriteAnimationFrameIndex; +		if (_characterSpriteAnimationFrameCounter > 0) { +			++_characterSpriteAnimationFrameCounter; +			if (_characterSpriteAnimationFrameCounter > 121) { +				_characterSpriteAnimationFrameCounter = 0; +			} +			if (_selectedCharacterDirection == 1) { +				_currentSpriteAnimationFrame = (_characterSpriteAnimationFrameCounter > 2 && _characterSpriteAnimationFrameCounter < 120) ? 122 : 121; +			} else { +				_currentSpriteAnimationFrame = (_characterSpriteAnimationFrameCounter > 2 && _characterSpriteAnimationFrameCounter < 120) ? 120 : 119; +			} +		} +	} +	_characterPrevFacingDirection = _characterFacingDirection; +} + +void TuckerEngine::execData3PostUpdate() { +	switch (_locationNum) { +	case 1: +		execData3PostUpdate_locationNum1(); +		break; +	case 6: +		if (_flagsTable[26] < 4) { +			execData3PreUpdate_locationNum6Helper1(); +		} +		break; +	case 8: +		execData3PostUpdate_locationNum8(); +		break; +	case 9: +		execData3PostUpdate_locationNum9(); +		break; +	case 14: +		if (_yPosCurrent < 127) { +			execData3PreUpdate_locationNum14(); +		} +		break; +	case 21: +		execData3PostUpdate_locationNum21(); +		break; +	case 24: +		execData3PostUpdate_locationNum24(); +		break; +	case 27: +		execData3PostUpdate_locationNum27(); +		break; +	case 28: +		execData3PostUpdate_locationNum28(); +		break; +	case 32: +		execData3PostUpdate_locationNum32(); +		break; +	case 60: +		execData3PostUpdate_locationNum60(); +		break; +	case 66: +		execData3PostUpdate_locationNum66(); +		break; +	} +} + +void TuckerEngine::addObjectToInventory(int num) { +	_inventoryObjectsList[_inventoryObjectsCount] = num; +	_lastInventoryObjectIndex = _inventoryObjectsCount; +	_redrawPanelItemsCounter = 50; +	++_inventoryObjectsCount; +	_inventoryItemsState[num] = 1; +	if (_inventoryObjectsOffset + 5 < _lastInventoryObjectIndex) { +		_inventoryObjectsOffset += 3; +	} +} + +void TuckerEngine::removeObjectFromInventory(int num) { +	int i = 0; +	while (_inventoryObjectsList[i] != num && i < _inventoryObjectsCount) { +		++i; +	} +	--_inventoryObjectsCount; +	int j = i; +	while (j < _inventoryObjectsCount) { +		_inventoryObjectsList[j] = _inventoryObjectsList[j + 1]; +		++j; +	} +	_inventoryItemsState[num] = 2; +} + +void TuckerEngine::handleMap() { +	if (_handleMapCounter > 0) { +		++_handleMapCounter; +		if (_handleMapCounter > 19) { +			_handleMapCounter = 0; +			_locationMaskCounter = 1; +			_panelLockedFlag = 0; +		} +	} +	if (_panelLockedFlag == 0 && (_backgroundSpriteCurrentAnimation == -1 || _locationNum == 25) && _locationMaskType == 3) { +		setCursorType(0); +		if (_locationMaskCounter == 1) { +			_characterFacingDirection = 0; +			_locationMaskType = 0; +		} +		return; +	} +	if (_selectedObject.locationObject_locationNum != 0 && _locationMaskCounter != 0 && (_backgroundSpriteCurrentAnimation <= -1 || _locationNum == 25)) { +		if (_locationNum == 25 || _backgroundSpriteCurrentAnimation != 4) { +			if (_locationMaskType == 0) { +				_locationMaskType = 1; +				setCursorType(2); +				if (_selectedObject.locationObject_toWalkX2 > 800) { +					_backgroundSpriteCurrentAnimation = _selectedObject.locationObject_toWalkX2 - 900; +					if (_selectedObject.locationObject_toWalkY2 > 499) { +						_changeBackgroundSprite = 1; +						_backgroundSprOffset = _selectedObject.locationObject_toWalkY2 - 500; +					} else { +						_backgroundSprOffset = _selectedObject.locationObject_toWalkY2; +						_changeBackgroundSprite = 0; +					} +					_backgroundSpriteCurrentFrame = 0; +					_mirroredDrawing = 0; +					if (_locationNum == 25) { +						_backgroundSpriteDataPtr = _sprA02Table[_backgroundSpriteCurrentAnimation]; +						_backgroundSpriteLastFrame = READ_LE_UINT16(_backgroundSpriteDataPtr); +						_backgroundSpriteCurrentFrame = 1; +					} +				} else { +					_locationMaskCounter = 0; +					_selectedObject.xPos = _selectedObject.locationObject_toWalkX2; +					_selectedObject.yPos = _selectedObject.locationObject_toWalkY2; +					_handleMapCounter = 1; +					_panelLockedFlag = 1; +				} +				return; +			} +			_locationMaskType = 2; +			_panelState = 0; +			setCursorType(0); +			if (_selectedObject.locationObject_locationNum == 99) { +				_noPositionChangeAfterMap = true; +				handleMapSequence(); +				return; +			} +			for (int i = 0; i < 14; ++i) { +				fadeInPalette(); +				copyToVGA(_locationBackgroundGfxBuf + _scrollOffset); +				_fadePaletteCounter = 34; +			} +			_nextLocationNum = _selectedObject.locationObject_locationNum; +			_xPosCurrent = _selectedObject.locationObject_toX; +			_yPosCurrent = _selectedObject.locationObject_toY; +			if (_selectedObject.locationObject_toX2 > 800) { +				_backgroundSpriteCurrentAnimation = _selectedObject.locationObject_toX2 - 900; +				if (_selectedObject.locationObject_toY2 > 499) { +					_changeBackgroundSprite = 1; +					_backgroundSprOffset = _selectedObject.locationObject_toY2 - 500; +				} else { +					_changeBackgroundSprite = 0; +					_backgroundSprOffset = _selectedObject.locationObject_toY2; +				} +				_backgroundSpriteCurrentFrame = 0; +			} else { +				_selectedObject.xPos = _selectedObject.locationObject_toX2; +				_selectedObject.yPos = _selectedObject.locationObject_toY2; +				_panelLockedFlag = 1; +			} +			_scrollOffset = 0; +			_handleMapCounter = 0; +			_locationMaskCounter = 0; +			_selectedObject.locationObject_locationNum = 0; +		} +	} +} + +void TuckerEngine::updateSprites() { +	const int count = (_locationNum == 9) ? 3 : _spritesCount; +	for (int i = 0; i < count; ++i) { +		if (_spritesTable[i].stateIndex > -1) { +			++_spritesTable[i].stateIndex; +			if (_characterStateTable[_spritesTable[i].stateIndex] == 99) { +				_spritesTable[i].stateIndex = -1; +				_spritesTable[i].state = -1; +				updateSprite(i); +			} else { +				_spritesTable[i].animationFrame = _characterStateTable[_spritesTable[i].stateIndex]; +			} +			continue; +		} +		if (_spritesTable[i].state == -1) { +			updateSprite(i); +			continue; +		} +		if (_charSpeechSoundCounter > 0 && i == _actionCharacterNum && _spritesTable[i].needUpdate == 0) { +			updateSprite(i); +			continue; +		} +		if (_charSpeechSoundCounter == 0 && _spritesTable[i].needUpdate > 0) { +			updateSprite(i); +			continue; +		} +		if (_spritesTable[i].updateDelay > 0) { +			--_spritesTable[i].updateDelay; +			if (_spritesTable[i].updateDelay == 0) { +				updateSprite(i); +			} +			continue; +		} +		if (_spritesTable[i].defaultUpdateDelay > 0) { +			_spritesTable[i].updateDelay = _spritesTable[i].defaultUpdateDelay - 1; +			++_spritesTable[i].animationFrame; +			if (_spritesTable[i].animationFrame == _spritesTable[i].firstFrame) { +				updateSprite(i); +			} +			continue; +		} +		if (_spritesTable[i].nextAnimationFrame == 0) { +			++_spritesTable[i].animationFrame; +			if (_spritesTable[i].firstFrame - 1 < _spritesTable[i].animationFrame) { +				if (_spritesTable[i].prevAnimationFrame == 1) { +					--_spritesTable[i].animationFrame; +					_spritesTable[i].nextAnimationFrame = 1; +				} else { +					updateSprite(i); +				} +			} +			continue; +		} +		--_spritesTable[i].animationFrame; +		if (_spritesTable[i].animationFrame == 0) { +			updateSprite(i); +		} +	} +} + +void TuckerEngine::updateSprite(int i) { +	_spritesTable[i].prevState = _spritesTable[i].state; +	_spritesTable[i].prevAnimationFrame = 0; +	_spritesTable[i].nextAnimationFrame = 0; +	_updateSpriteFlag1 = 0; +	_updateSpriteFlag2 = 0; +	_spritesTable[i].defaultUpdateDelay = 0; +	_spritesTable[i].updateDelay = 0; +	switch (_locationNum) { +	case 2: +		updateSprite_locationNum2(); +		break; +	case 3: +		if (i == 0) { +			updateSprite_locationNum3_0(i); +		} else if (i == 1) { +			updateSprite_locationNum3_1(i); +		} else { +			updateSprite_locationNum3_2(i); +		} +		break; +	case 4: +		updateSprite_locationNum4(0); +		break; +	case 5: +		if (i == 0) { +			updateSprite_locationNum5_0(); +		} else { +			updateSprite_locationNum5_1(1); +		} +		break; +	case 6: +		if (i == 0) { +			updateSprite_locationNum6_0(0); +		} else if (i == 1) { +			updateSprite_locationNum6_1(1); +		} else { +			updateSprite_locationNum6_2(2); +		} +		break; +	case 7: +		if (i == 0) { +			updateSprite_locationNum7_0(0); +		} else { +			updateSprite_locationNum7_1(1); +		} +		break; +	case 8: +		if (i == 0) { +			updateSprite_locationNum8_0(0); +		} else { +			updateSprite_locationNum8_1(1); +		} +		break; +	case 9: +		if (i == 0) { +			updateSprite_locationNum9_0(i); +		} else if (i == 1) { +			updateSprite_locationNum9_1(i); +		} else { +			updateSprite_locationNum9_2(i); +		} +		break; +	case 10: +		updateSprite_locationNum10(); +		break; +	case 11: +		if (i == 0) { +			updateSprite_locationNum11_0(0); +		} else if (i == 1) { +			updateSprite_locationNum11_1(1); +		} else if (i == 2) { +			updateSprite_locationNum11_2(2); +		} else if (i == 3) { +			updateSprite_locationNum11_3(3); +		} else if (i == 4) { +			updateSprite_locationNum11_4(4); +		} +		break; +	case 12: +		if (i == 0) { +			updateSprite_locationNum12_0(0); +		} else if (i == 1) { +			updateSprite_locationNum12_1(1); +		} +		break; +	case 13: +		updateSprite_locationNum13(0); +		break; +	case 14: +		updateSprite_locationNum14(0); +		break; +	case 15: +		if (i == 1) { +			updateSprite_locationNum15_1(1); +		} else if (i == 2) { +			updateSprite_locationNum15_2(2); +		} else if (i == 0) { +			updateSprite_locationNum15_0(0); +		} +		break; +	case 16: +		if (i == 0) { +			updateSprite_locationNum16_0(0); +		} else if (i == 1) { +			updateSprite_locationNum16_1(1); +		} else { +			updateSprite_locationNum16_2(2); +		} +		break; +	case 17: +		updateSprite_locationNum17(); +		break; +	case 18: +		updateSprite_locationNum18(); +		break; +	case 19: +		if (i == 0) { +			updateSprite_locationNum19_0(0); +		} else if (i == 1) { +			updateSprite_locationNum19_1(1); +		} else if (i == 2) { +			updateSprite_locationNum19_2(2); +		} else { +			updateSprite_locationNum19_3(3); +		} +		break; +	case 21: +		updateSprite_locationNum21(); +		break; +	case 22: +		updateSprite_locationNum22(); +		break; +	case 23: +		if (i == 0) { +			updateSprite_locationNum23_0(0); +		} else if (i == 1) { +			updateSprite_locationNum23_1(1); +		} else if (i == 2) { +			updateSprite_locationNum23_2(2); +		} else { +			updateSprite_locationNum23_3(3); +		} +		break; +	case 24: +		if (i == 0) { +			updateSprite_locationNum24_0(0); +		} else if (i == 1) { +			updateSprite_locationNum24_1(1); +		} else if (i == 2) { +			updateSprite_locationNum24_2(2); +		} else { +			updateSprite_locationNum24_3(3); +		} +		break; +	case 26: +		if (i == 0) { +			updateSprite_locationNum26_0(0); +		} else { +			updateSprite_locationNum26_1(1); +		} +		break; +	case 27: +		updateSprite_locationNum27(0); +		break; +	case 28: +		if (i == 0) { +			updateSprite_locationNum28_0(0); +		} else if (i == 1) { +			updateSprite_locationNum28_1(1); +		} else { +			updateSprite_locationNum28_2(2); +		} +		break; +	case 29: +		if (i == 0) { +			updateSprite_locationNum29_0(0); +		} else if (i == 1) { +			updateSprite_locationNum29_1(1); +		} else { +			updateSprite_locationNum29_2(2); +		} +		break; +	case 30: +		updateSprite_locationNum30_34(i); +		break; +	case 31: +		if (i == 0) { +			updateSprite_locationNum31_0(0); +		} else { +			updateSprite_locationNum31_1(1); +		} +		break; +	case 32: +		if (i == 0) { +			updateSprite_locationNum32_0(0); +		} else { +			_spritesTable[i].state = -1; +		} +		break; +	case 33: +		if (i == 1) { +			updateSprite_locationNum33_1(1); +		} else if (i == 0) { +			updateSprite_locationNum33_0(0); +		} else if (i == 2) { +			updateSprite_locationNum33_2(2); +		} else { +			_spritesTable[i].state = 12; +		} +		break; +	case 34: +		updateSprite_locationNum30_34(0); +		break; +	case 36: +		updateSprite_locationNum36(0); +		break; +	case 37: +		if (i == 0) { +			_spritesTable[0].state = -1; +		} else { +			updateSprite_locationNum37(i, i + 1, 200 - i * 45); +		} +		break; +	case 41: +		updateSprite_locationNum41(i); +		break; +	case 42: +		updateSprite_locationNum42(i); +		break; +	case 43: +		if (i == 2) { +			updateSprite_locationNum43_2(i); +		} else if (i < 2) { +			if (_flagsTable[236] < 4) { +				_spritesTable[0].state = i + 1; +			} else { +				_spritesTable[0].state = -1; +			} +		} else if (i == 3) { +			updateSprite_locationNum43_3(3); +		} else if (i == 4) { +			updateSprite_locationNum43_4(4); +		} else if (i == 5) { +			updateSprite_locationNum43_5(5); +		} else { +			updateSprite_locationNum43_6(6); +		} +		break; +	case 45: +		_spritesTable[0].state = 1; +		break; +	case 47: +		_spritesTable[i].state = i + 1; +		break; +	case 48: +		updateSprite_locationNum48(0); +		break; +	case 49: +		updateSprite_locationNum49(0); +		break; +	case 50: +		if (i < 6) { +			updateSprite_locationNum50(i); +		} else { +			_spritesTable[i].state = i + 1; +		} +		break; +	case 51: +		if (i == 2) { +			updateSprite_locationNum51_2(2); +		} else if (i == 0) { +			updateSprite_locationNum51_0(0); +		} else { +			updateSprite_locationNum51_1(1); +		} +		break; +	case 53: +		if (i == 0) { +			updateSprite_locationNum53_0(0); +		} else if (i == 1) { +			updateSprite_locationNum53_1(1); +		} +		break; +	case 54: +		updateSprite_locationNum54(0); +		break; +	case 55: +		updateSprite_locationNum55(0); +		break; +	case 56: +		updateSprite_locationNum56(0); +		break; +	case 57: +		if (i == 0) { +			updateSprite_locationNum57_0(0); +		} else if (i == 1) { +			updateSprite_locationNum57_1(1); +		} +		break; +	case 58: +		updateSprite_locationNum58(0); +		break; +	case 59: +		updateSprite_locationNum59(0); +		break; +	case 60: +		if (i == 0) { +			updateSprite_locationNum60_0(0); +		} else { +			updateSprite_locationNum60_1(1); +		} +		break; +	case 61: +		if (i == 0) { +			updateSprite_locationNum61_0(0); +		} else if (i == 2) { +			updateSprite_locationNum61_2(2); +		} else { +			updateSprite_locationNum61_1(1); +		} +		break; +	case 63: +		if (i == 0) { +			updateSprite_locationNum63_0(0); +		} else if (i == 1) { +			updateSprite_locationNum63_1(1); +		} else if (i == 2) { +			updateSprite_locationNum63_2(2); +		} else if (i == 3) { +			updateSprite_locationNum63_3(3); +		} else if (i == 4) { +			updateSprite_locationNum63_4(4); +		} +		break; +	case 65: +		updateSprite_locationNum65(0); +		break; +	case 66: +		if (i == 0) { +			updateSprite_locationNum66_0(0); +		} else if (i == 1) { +			updateSprite_locationNum66_1(1); +		} else if (i == 2) { +			updateSprite_locationNum66_2(2); +		} else if (i == 3) { +			updateSprite_locationNum66_3(3); +		} else { +			updateSprite_locationNum66_4(4); +		} +		break; +	case 69: +		if (i == 0) { +			_spritesTable[0].state = 1; +		} else if (i == 1) { +			updateSprite_locationNum69_1(1); +		} else if (i == 2) { +			updateSprite_locationNum69_2(2); +		} else if (i == 3) { +			updateSprite_locationNum69_3(3); +		} +		break; +	case 71: +		updateSprite_locationNum71(0); +		break; +	case 72: +		updateSprite_locationNum72(0); +		break; +	case 74: +		updateSprite_locationNum74(i); +		break; +	case 79: +		updateSprite_locationNum79(0); +		break; +	case 81: +		if (i == 0) { +			updateSprite_locationNum81_0(0); +		} else if (i == 1) { +			updateSprite_locationNum81_1(1); +		} +		break; +	case 82: +		updateSprite_locationNum82(0); +		break; +	case 98: +		_spritesTable[0].state = 1; +		break; +	} +	if (_spritesTable[i].stateIndex <= -1) { +		if (_updateSpriteFlag1 == 0) { +			_spritesTable[i].animationFrame = 1; +		} +		_spritesTable[i].animationData = _sprC02Table[_spritesTable[i].state]; +		_spritesTable[i].firstFrame = READ_LE_UINT16(_spritesTable[i].animationData); +		if (_updateSpriteFlag2 == 1) { +			_spritesTable[i].state = _spritesTable[i].firstFrame; +			_spritesTable[i].nextAnimationFrame = 1; +			_spritesTable[i].prevAnimationFrame = 1; +		} +	} +} + +void TuckerEngine::drawStringInteger(int num, int x, int y, int digits) { +	int offset = y * 640 + x + _scrollOffset; +	char numStr[4]; +	assert(num < 1000); +	sprintf(numStr, "%03d", num); +	int i = (digits > 2) ? 0 : 1; +	for (; i < 3; ++i) { +		Graphics::drawStringChar(_locationBackgroundGfxBuf + offset, numStr[i], 640, 102, _charsetGfxBuf); +		offset += 8; +	} +} + +void TuckerEngine::drawStringAlt(uint8 *dst, int color, const uint8 *str, int strLen) { +	int pos = 0; +	while (pos != strLen && str[pos] != '\n') { +		const uint8 chr = str[pos]; +		Graphics::drawStringChar(dst, chr, 640, color, _charsetGfxBuf); +		dst += _charWidthTable[chr]; +		++pos; +	} +} + +void TuckerEngine::drawString(uint8 *dst, int num, const uint8 *str) { +	int count = getPositionForLine(num, str); +	while (str[count] != '\n') { +		const uint8 chr = str[count]; +		Graphics::drawStringChar(dst, chr, 320, 1, _charsetGfxBuf); +		dst += _charWidthTable[chr]; +		++count; +	} +} + +void TuckerEngine::drawString2(int x, int y, int num) { +	uint8 *dst = _locationBackgroundGfxBuf + y * 640 + x; +	int pos = getPositionForLine(num, _ptTextBuf); +	while (_ptTextBuf[pos] != '\n') { +		const uint8 chr = _ptTextBuf[pos]; +		Graphics::drawStringChar2(dst, chr, 640, 1, _charsetGfxBuf); +		dst += _charWidthTable[chr]; +		++pos; +	} +} + +void TuckerEngine::updateCharSpeechSound() { +	if (_charSpeechSoundCounter == 0) { +		return; +	} +	--_charSpeechSoundCounter; +	int i = isSpeechSoundPlaying(); +	if (_charSpeechSoundCounter == 0) { +		_charSpeechSoundCounter = i; +		if (_charSpeechSoundCounter == 0) { +			_characterSpriteAnimationFrameCounter = 0; +		} +	} +	if (_charSpeechSoundCounter == 0 && _csDataHandled == 0) { +		setCursorType(0); +		return; +	} +	static const int constEq0 = 0; // display text for speech +	if (constEq0 == 1 && _gamePaused2 == 0) { +		drawSpeechText(_actionPosX, _actionPosY, _characterSpeechDataPtr, _speechSoundNum, _actionTextColor); +	} +} + +void TuckerEngine::updateItemsGfxColors(int color1, int color128) { +	for (int i = 0; i < 3200; ++i) { +		if (_itemsGfxBuf[i] == 1) { +			_itemsGfxBuf[i] = color1; +		} else if (_itemsGfxBuf[i] == 128) { +			_itemsGfxBuf[i] = color128; +		} +	} +} + +int TuckerEngine::testLocationMask(int x, int y) { +	if (_locationMaskType > 0 || _locationMaskIgnore > 0) { +		return 1; +	} +	if (_locationNum == 26 || _locationNum == 32) { +		y -= 3; +	} +	const int offset = y * 640 + x; +	return _locationBackgroundMaskBuf[offset] > 0 ? 1 : 0; +} + +int TuckerEngine::getStringWidth(int num, const uint8 *ptr) { +	int w = 0; +	int pos = getPositionForLine(num, ptr); +	uint8 chr; +	while ((chr = ptr[pos]) != '\n') { +		w += _charWidthTable[chr]; +		++pos; +	} +	return w; +} + +int TuckerEngine::getPositionForLine(int num, const uint8 *ptr) { +	int linesCount = 0; +	int i = 0; +	while (linesCount < num) { +		if (ptr[i] == '\n') { +			++linesCount; +			if (ptr[i + 1] == '\r') { +				++i; +			} +		} +		++i; +	} +	while (1) { +		if (ptr[i] != '\n' && ptr[i] != '\r') { +			break; +		} +		++i; +	} +	return i; +} + +void TuckerEngine::copyToVGA(const uint8 *src) { +	_system->copyRectToScreen(src, 640, 0, 0, 320, 200); +	_system->updateScreen(); +} + +void TuckerEngine::findActionKey(int count) { +	_backgroundSpriteCurrentFrame = 0; +	_characterAnimationIndex = 0; +	for (int i = 0; i < count; ++i) { +		while (_characterAnimationsTable[_characterAnimationIndex] != 99) { +			++_characterAnimationIndex; +		} +		++_characterAnimationIndex; +	} +} + +static int parseInt(const uint8 *buf, int offset, int len) { +	assert(len < 16); +	char tmpBuf[16]; +	memcpy(tmpBuf, buf + offset, len); +	tmpBuf[len] = 0; +	return strtol(tmpBuf, 0, 10); +} + +int TuckerEngine::parseTableInstruction() { +	int spr; +	printf("parseTableInstruction instruction %c %c %c\n", _tableInstructionsPtr[0], _tableInstructionsPtr[1], _tableInstructionsPtr[2]); +	switch (_tableInstructionsPtr[0]) { +	case 'p': // 12 +		if (_tableInstructionsPtr[1] == 'a') { // 0 +			_tableInstructionsPtr += 4; +			_panelState = parseInt(_tableInstructionsPtr, 0, 2); +			_forceRedrawPanelItems = 1; +			_tableInstructionsPtr += 3; +			return 0; +		} +		break; +	case 'b': // 1 +		if (_tableInstructionsPtr[2] == 'a') { // 0 +			_backgroundSpriteCurrentAnimation = parseInt(_tableInstructionsPtr, 4, 3); +			_backgroundSpriteCurrentFrame = 0; +			_backgroundSprOffset = 0; +			_mainLoopCounter2 = 0; +			_tableInstructionsPtr += 8; +			return 0; +		} +		if (_tableInstructionsPtr[2] == 'b') { // 1 +			int i = parseInt(_tableInstructionsPtr, 4, 3); +			_spriteAnimationFrameIndex = _spriteAnimationsTable[i].firstFrameIndex; +			_characterFacingDirection = 5; +			_mainLoopCounter2 = 0; +			_tableInstructionsPtr += 8; +			return 0; +		} +		if (_tableInstructionsPtr[2] == 'c') { // 2 +			int i = parseInt(_tableInstructionsPtr, 4, 3); +			findActionKey(i); +			_backgroundSpriteCurrentFrame = 0; +			_backgroundSprOffset = 0; +			_tableInstructionsPtr += 8; +			return 0; +		} +		if (_tableInstructionsPtr[2] == 'd') { // 4 +			_selectedCharacterDirection = parseInt(_tableInstructionsPtr, 4, 2); +			_tableInstructionsPtr += 7; +			return 0; +		} +		if (_tableInstructionsPtr[2] == 'f') { // 5 +			_skipCurrentCharacterDraw = 1; +			_tableInstructionsPtr += 4; +			return 0; +		} +		if (_tableInstructionsPtr[2] == 'h') { // 7 +			_noCharacterAnimationChange = parseInt(_tableInstructionsPtr, 4, 2); +			_tableInstructionsPtr += 7; +			return 0; +		} +		if (_tableInstructionsPtr[2] == 'n') { // 10 +			_skipCurrentCharacterDraw = 0; +			_tableInstructionsPtr += 4; +			return 0; +		} +		if (_tableInstructionsPtr[2] == 'o') { // 11 +			_backgroundSprOffset = parseInt(_tableInstructionsPtr, 4, 3); +			_tableInstructionsPtr += 8; +			return 0; +		} +		if (_tableInstructionsPtr[2] == 's') { // 14 +			int i = parseInt(_tableInstructionsPtr, 4, 3); +			_speechSoundNum = i - 1; +			_speechHistoryTable[4] = _speechHistoryTable[3]; +			_speechHistoryTable[3] = _speechHistoryTable[2]; +			_speechHistoryTable[2] = _speechHistoryTable[1]; +			_speechHistoryTable[1] = _speechHistoryTable[0]; +			_speechHistoryTable[0] = _partNum * 3000 + _ptTextOffset + _speechSoundNum - 3000; +			startSpeechSound(_partNum * 3000 + _ptTextOffset + _speechSoundNum - 3000, _speechVolume); +			_actionPosX = _xPosCurrent; +			_actionPosY = _yPosCurrent - 64; +			_actionTextColor = 1; +			_actionCharacterNum = 99; +			_charSpeechSoundCounter = kDefaultCharSpeechSoundCounter; +			_tableInstructionsPtr += 8; +			return 0; +		} +		if (_tableInstructionsPtr[2] == 'v') { // 16 +			_speechVolume = parseInt(_tableInstructionsPtr, 4, 3); +			_tableInstructionsPtr += 8; +			return 0; +		} +		if (_tableInstructionsPtr[2] == 'w') { // 17 +			_selectedObject.xPos = parseInt(_tableInstructionsPtr, 4, 3); +			_selectedObject.yPos = parseInt(_tableInstructionsPtr, 8, 3); +			_locationMaskIgnore = 1; +			_panelLockedFlag = 1; +			_tableInstructionsPtr += 12; +			return 0; +		} +		if (_tableInstructionsPtr[2] == 'x') { // 18 +			_xPosCurrent = parseInt(_tableInstructionsPtr, 4, 3); +			_yPosCurrent = parseInt(_tableInstructionsPtr, 8, 3); +			_tableInstructionsPtr += 12; +			return 0; +		} +		break; +	case 'c': // 2 +		spr = _tableInstructionsPtr[1] - '0'; +		if (_tableInstructionsPtr[2] == 'a') { // 0 +			_spritesTable[spr].state = parseInt(_tableInstructionsPtr, 4, 3); +			if (_spritesTable[spr].state == 999) { +				_spritesTable[spr].state = -1; +			} +			_mainLoopCounter1 = 0; +			_spritesTable[spr].updateDelay = 0; +			_spritesTable[spr].nextAnimationFrame = 0; +			_spritesTable[spr].prevAnimationFrame = 0; +			_tableInstructionsPtr += 8; +			return 0; +		} +		if (_tableInstructionsPtr[2] == 'e') { // 4 +			int i = parseInt(_tableInstructionsPtr, 4, 3); +			setCharacterAnimation(i, spr); +			_tableInstructionsPtr += 8; +			return 0; +		} +		if (_tableInstructionsPtr[2] == 's') { // 14 +			int i = parseInt(_tableInstructionsPtr, 4, 3); +			_speechSoundNum = i - 1; +			_speechHistoryTable[4] = _speechHistoryTable[3]; +			_speechHistoryTable[3] = _speechHistoryTable[2]; +			_speechHistoryTable[2] = _speechHistoryTable[1]; +			_speechHistoryTable[1] = _speechHistoryTable[0]; +			_speechHistoryTable[0] = _partNum * 3000 + _ptTextOffset + _speechSoundNum - 3000; +			startSpeechSound(_partNum * 3000 + _ptTextOffset + _speechSoundNum - 3000, _charSpeechSoundVolumeTable[spr]); +			_charSpeechSoundCounter = kDefaultCharSpeechSoundCounter; +			_actionTextColor = 181 + spr; +			if (_tableInstructionFlag == 0) { +				_actionPosX = _tableInstructionItemNum1; +				_actionPosY = _tableInstructionItemNum2; +			} else { +				_actionPosX = _tableInstructionObj1Table[spr]; +				_actionPosY = _tableInstructionObj2Table[spr]; +			} +			_actionCharacterNum = spr; +			_tableInstructionsPtr += 8; +			return 0; +		} +		if (_tableInstructionsPtr[2] == 'v') { // 16 +			_charSpeechSoundVolumeTable[spr] = parseInt(_tableInstructionsPtr, 4, 3); +			_tableInstructionsPtr += 8; +			return 0; +		} +		break; +	case 'e': // 4 +		if (_tableInstructionsPtr[1] == 'n') { // 10 +			return 2; +		} +		break; +	case 'f': // 5 +		if (_tableInstructionsPtr[2] == 'd') { // 3 +			_fadePaletteCounter = parseInt(_tableInstructionsPtr, 4, 2); +			_tableInstructionsPtr += 7; +			return 0; +		} +		if (_tableInstructionsPtr[1] == 'm') { // 9 +			_redrawPanelItemsCounter = 50; +			_lastInventoryObjectIndex = 1; +			_inventoryObjectsOffset = 0; +			_tableInstructionsPtr += 3; +			return 0; +		} +		if (_tableInstructionsPtr[1] == 'w') { // 17 +			_selectedCharacterNum = parseInt(_tableInstructionsPtr, 3, 2); +			_tableInstructionsPtr += 6; +			_actionVerb = 0; +			_selectedObjectType = 0; +			_selectedObjectNum = 1; +			setSelectedObjectKey(); +			return 0; +		} +		if (_tableInstructionsPtr[2] == 'x') { // 18 +			int i = parseInt(_tableInstructionsPtr, 4, 2); +			if (_tableInstructionsPtr[1] == 'l') { // 8 +				_locationSoundsTable[i].type = 2; +				startSound(_locationSoundsTable[i].offset, i, _locationSoundsTable[i].volume); +			} else { +				if (isSoundPlaying(i)) { +					stopSound(i); +				} +			} +			_tableInstructionsPtr += 7; +			return 0; +		} +		if (_tableInstructionsPtr[1] == 'x') { // 18 +			int i = parseInt(_tableInstructionsPtr, 3, 2); +			startSound(_locationSoundsTable[i].offset, i, _locationSoundsTable[i].volume); +			_soundInstructionIndex = i; +			_tableInstructionsPtr += 6; +			return 0; +		} +		break; +	case 'g': // 6 +		if (_tableInstructionsPtr[2] == 'g') { // 6 +			int i = parseInt(_tableInstructionsPtr, 4, 3); +			_flagsTable[i] = parseInt(_tableInstructionsPtr, 8, 2); +			_tableInstructionsPtr += 11; +			return 0; +		} +		if (_tableInstructionsPtr[1] == 'v') { // 16 +			_characterAnimationNum = parseInt(_tableInstructionsPtr, 3, 2); +			_tableInstructionsPtr += 6; +			return 0; +		} +		break; +	case 'l': // 8 +		if (_tableInstructionsPtr[2] == 'c') { // 2 +			_nextLocationNum = parseInt(_tableInstructionsPtr, 4, 2); +			_tableInstructionsPtr += 7; +			return 1; +		} +		break; +	case 'o': // 11 +		if (_tableInstructionsPtr[2] == 't') { // 15 +			_conversationOptionsCount = parseInt(_tableInstructionsPtr, 4, 2); +			_tableInstructionsPtr += 7; +			for (int i = 0; i < _conversationOptionsCount; ++i) { +				_instructionsActionsTable[i] = parseInt(_tableInstructionsPtr, 0, 3) - 1; +				_nextTableToLoadTable[i] = parseInt(_tableInstructionsPtr, 4, 3); +				_tableInstructionsPtr += 8; +			} +			_nextTableToLoadIndex = -1; +			setCursorType(1); +			return 1; +		} +		if (_tableInstructionsPtr[2] == 'f') { // 5 +			int count = parseInt(_tableInstructionsPtr, 4, 2); +			_tableInstructionsPtr += 7; +			_conversationOptionsCount = 0; +			for (int i = 0; i < count; ++i) { +				int flag = parseInt(_tableInstructionsPtr, 0, 3); +				int value = parseInt(_tableInstructionsPtr, 4, 2); +				if (value == _flagsTable[flag]) { +					_instructionsActionsTable[_conversationOptionsCount] = parseInt(_tableInstructionsPtr, 7, 3) - 1; +					_nextTableToLoadTable[_conversationOptionsCount] = parseInt(_tableInstructionsPtr, 11, 3); +					++_conversationOptionsCount; +				} +				_tableInstructionsPtr += 15; +			} +			_nextTableToLoadIndex = -1; +			setCursorType(1); +			return 1; +		} +		if (_tableInstructionsPtr[2] == 'g') { // 6 +			int i = parseInt(_tableInstructionsPtr, 8, 2); +			if (i == 0) { +				int obj = parseInt(_tableInstructionsPtr, 4, 3); +				removeObjectFromInventory(obj); +			} else { +				int obj = parseInt(_tableInstructionsPtr, 4, 3); +				addObjectToInventory(obj); +			} +			_tableInstructionsPtr += 11; +			return 0; +		} +		break; +	case 's': // 14 +		if (_tableInstructionsPtr[2] == 'c') { // 2 +			_tableInstructionsPtr += 4; +			_mainLoopCounter1 = 0; +			return 0; +		} +		if (_tableInstructionsPtr[2] == 'e') { // 4 +			_nextAction = parseInt(_tableInstructionsPtr, 4, 3); +			_csDataLoaded = false; +			return 3; +		} +		if (_tableInstructionsPtr[2] == 'p') { // 12 +			if (_tableInstructionsPtr[1] == 's') { // 14 +				_tableInstructionFlag = 0; +				_tableInstructionItemNum1 = parseInt(_tableInstructionsPtr, 4, 3); +				_tableInstructionItemNum2 = parseInt(_tableInstructionsPtr, 8, 3); +			} else { +				int num = _tableInstructionsPtr[1] - '0'; +				_tableInstructionFlag = 1; +				_tableInstructionObj1Table[num] = parseInt(_tableInstructionsPtr, 4, 3); +				_tableInstructionObj2Table[num] = parseInt(_tableInstructionsPtr, 8, 3); +			} +			_tableInstructionsPtr += 12; +			return 0; +		} +		if (_tableInstructionsPtr[1] == 'p') { // 12 +			_characterSpriteAnimationFrameCounter = 1; +			_tableInstructionsPtr += 3; +			return 0; +		} +		break; +	case 't': // 15 +		if (_tableInstructionsPtr[2] == 'o') { // 11 +			_ptTextOffset = parseInt(_tableInstructionsPtr, 4, 4); +			_characterSpeechDataPtr = _ptTextBuf + getPositionForLine(_ptTextOffset, _ptTextBuf); +			_tableInstructionsPtr += 9; +			return 0; +		} +		break; +	case 'w': // 17 +		if (_tableInstructionsPtr[2] == '+') { // 19 +			_csDataTableFlag2 = 1; +			_stopActionCounter = 20; +			_tableInstructionsPtr += 4; +			return 1; +		} +		if (_tableInstructionsPtr[2] == 'm') { // 9 +			_stopActionOnPanelLock = 1; +			_tableInstructionsPtr += 4; +			return 1; +		} +		if (_tableInstructionsPtr[2] == 't') { // 15 +			_stopActionCounter = parseInt(_tableInstructionsPtr, 4, 3); +			_tableInstructionsPtr += 8; +			return 1; +		} +		if (_tableInstructionsPtr[2] == 's') { // 14 +			_csDataTableFlag2 = 1; +			_tableInstructionsPtr += 4; +			return 1; +		} +		if (_tableInstructionsPtr[2] == 'a') { // 0 +			if (_tableInstructionsPtr[1] == 'b') { // 1 +				_csDataTableCount = 99; +			} else { +				_csDataTableCount = _tableInstructionsPtr[1] - '0' + 1; +			} +			return 1; +		} +		if (_tableInstructionsPtr[2] == 'x') { // 18 +			_stopActionOnSoundFlag = 1; +			_tableInstructionsPtr += 4; +			return 1; +		} +		break; +	case 'x': // 18 +		if (_tableInstructionsPtr[2] == 'r') { // 13 +			_validInstructionId = 1; +			_tableInstructionsPtr += 4; +			return 0; +		} +		if (_tableInstructionsPtr[2] == 'm') { // 9 +			_validInstructionId = 0; +			_tableInstructionsPtr += 4; +			return 0; +		} +		break; +	} +	printf("Instruction not recognised %c %c %c\n", _tableInstructionsPtr[0], _tableInstructionsPtr[1], _tableInstructionsPtr[2]); +	return 2; +} + +void TuckerEngine::moveUpInventoryObjects() { +	if (_inventoryObjectsOffset + 6 < _inventoryObjectsCount) { +		_inventoryObjectsOffset += 3; +		_forceRedrawPanelItems = 1; +	} +} + +void TuckerEngine::moveDownInventoryObjects() { +	if (_inventoryObjectsOffset > 2) { +		_inventoryObjectsOffset -= 3; +		_forceRedrawPanelItems = 1; +	} +} + +void TuckerEngine::setActionVerbUnderCursor() { +	if (_mousePosY < 150) { +		_actionVerb = 0; +	} else if (_mousePosX > 195) { +		_actionVerb = 1; +	} else if (_panelNum == 0) { +		_actionVerb = ((_mousePosY - 150) / 17) * 3 + (_mousePosX / 67); +	} else { +		_actionVerb = 0; +		if (_mousePosX < 30) { +			_actionVerb = 7; +		} else if (_mousePosX > 130 && _mousePosX < 165) { +			_actionVerb = 5; +		} else { +			if (_mousePosY < 175) { +				if (_mousePosX < 67) { +					_actionVerb = 3; +				} else if (_mousePosX > 164) { +					_actionVerb = 6; +				} else if (_mousePosX > 99) { +					_actionVerb = 4; +				} +			} else { +				if (_mousePosX < 85) { +					_actionVerb = 1; +				} else if (_mousePosX > 165) { +					_actionVerb = 2; +				} else { +					_actionVerb = 8; +				} +			} +		} +	} +} + +int TuckerEngine::getObjectUnderCursor() { +	if (_mousePosY > 140) { +		return -1; +	} +	for (int i = 0; i < _locationObjectsCount; ++i) { +		if (_mousePosX + _scrollOffset + 1 <= _locationObjectsTable[i].xPos) { +			continue; +		} +		if (_mousePosX + _scrollOffset >= _locationObjectsTable[i].xPos + _locationObjectsTable[i].xSize) { +			continue; +		} +		if (_mousePosY <= _locationObjectsTable[i].yPos) { +			continue; +		} +		if (_mousePosY >= _locationObjectsTable[i].yPos + _locationObjectsTable[i].ySize) { +			continue; +		} +		_selectedObjectType = 0; +		_selectedCharacterNum = i; +		setCursorNum(_locationObjectsTable[i].cursorNum); +		return i; +	} +	return -1; +} + +void TuckerEngine::setSelectedObjectKey() { +	const int x = _mousePosX + _scrollOffset; +	if (_mousePosY > 139 && _nextAction == 0) { +		return; +	} +	_panelLockedFlag = 1; +	_locationMaskCounter = 0; +	_actionRequiresTwoObjects = false; +	_selectedObject.yPos = 0; +	_selectedObject.locationObject_locationNum = 0; +	_pendingActionIndex = 0; +	if (_selectedObjectType == 0) { +		if (_selectedObjectNum == 0) { +			_selectedObject.xPos = x; +			_selectedObject.yPos = _mousePosY; +		} else { +			_selectedObject.xPos = _locationObjectsTable[_selectedCharacterNum].standX; +			_selectedObject.yPos = _locationObjectsTable[_selectedCharacterNum].standY; +			if (_actionVerb == 0 || _actionVerb == 8) { +				_selectedObject.locationObject_locationNum = _locationObjectsTable[_selectedCharacterNum].locationNum; +				_selectedObject.locationObject_toX = _locationObjectsTable[_selectedCharacterNum].toX; +				_selectedObject.locationObject_toY = _locationObjectsTable[_selectedCharacterNum].toY; +				_selectedObject.locationObject_toX2 = _locationObjectsTable[_selectedCharacterNum].toX2; +				_selectedObject.locationObject_toY2 = _locationObjectsTable[_selectedCharacterNum].toY2; +				_selectedObject.locationObject_toWalkX2 = _locationObjectsTable[_selectedCharacterNum].toWalkX2; +				_selectedObject.locationObject_toWalkY2 = _locationObjectsTable[_selectedCharacterNum].toWalkY2; + +			} +		} +	} else { +		switch (_selectedObjectType) { +		case 1: +			_selectedObject.xPos = _locationAnimationsTable[_selectedCharacterNum].standX; +			_selectedObject.yPos = _locationAnimationsTable[_selectedCharacterNum].standY; +			break; +		case 2: +			_selectedObject.xPos = _charPosTable[_selectedCharacterNum].xWalkTo; +			_selectedObject.yPos = _charPosTable[_selectedCharacterNum].yWalkTo; +			break; +		case 3: +			_selectedObject.xPos = _xPosCurrent; +			_selectedObject.yPos = _yPosCurrent; +			break; +		} +	} +	if (_selectedObject.yPos == 0) { +		_selectedObject.xPos = x; +		_selectedObject.yPos = _mousePosY; +	} +	_selectedObjectLocationMask = testLocationMask(_selectedObject.xPos, _selectedObject.yPos); +	if (_selectedObjectLocationMask == 0 && _objectKeysLocationTable[_locationNum] == 1) { +		if (_selectedObject.yPos < _objectKeysPosYTable[_locationNum]) { +			while (_selectedObjectLocationMask == 0 && _selectedObject.yPos < _objectKeysPosYTable[_locationNum]) { +				++_selectedObject.yPos; +				_selectedObjectLocationMask = testLocationMask(_selectedObject.xPos, _selectedObject.yPos); +			} +		} else { +			while (_selectedObjectLocationMask == 0 && _selectedObject.yPos < _objectKeysPosYTable[_locationNum]) { +				--_selectedObject.yPos; +				_selectedObjectLocationMask = testLocationMask(_selectedObject.xPos, _selectedObject.yPos); +			} +		} +	} +	if (_selectedObjectLocationMask == 1) { +		_selectedObjectLocationMask = testLocationMaskArea(_xPosCurrent, _yPosCurrent, _selectedObject.xPos, _selectedObject.yPos); +		if (_selectedObjectLocationMask == 1 && _objectKeysPosXTable[_locationNum] > 0) { +			_selectedObject.xDefaultPos = _selectedObject.xPos; +			_selectedObject.yDefaultPos = _selectedObject.yPos; +			_selectedObject.xPos = _objectKeysPosXTable[_locationNum]; +			_selectedObject.yPos = _objectKeysPosYTable[_locationNum]; +			if (_objectKeysLocationTable[_locationNum] == 1) { +				_selectedObject.xPos = _selectedObject.xDefaultPos; +			} +		} +	} +} + +void TuckerEngine::setCharacterAnimation(int count, int spr) { +	_spritesTable[spr].animationFrame = 0; +	_spritesTable[spr].stateIndex = 0; +	for (int i = 0; i < count; ++i) { +		while (_characterStateTable[_spritesTable[spr].stateIndex] != 99) { +			++_spritesTable[spr].stateIndex; +		} +		++_spritesTable[spr].stateIndex; +	} +	_spritesTable[spr].state = _characterStateTable[_spritesTable[spr].stateIndex]; +	++_spritesTable[spr].stateIndex; +	_spritesTable[spr].animationFrame = _characterStateTable[_spritesTable[spr].stateIndex]; +	++_spritesTable[spr].stateIndex; +	_spritesTable[spr].animationData = _sprC02Table[_spritesTable[spr].state]; +	_spritesTable[spr].firstFrame = READ_LE_UINT16(_spritesTable[spr].animationData); +} + +int TuckerEngine::testLocationMaskArea(int xBase, int yBase, int xPos, int yPos) { +	int i = 0; +	bool quitLoop = false; +	while (!quitLoop) { +		bool flag = false; +		if (yBase > yPos) { +			if (testLocationMask(xBase, yBase - 1) == 1) { +				--yBase; +				flag = true; +			} else { +				++i; +			} +		} else if (yBase < yPos) { +			if (testLocationMask(xBase, yBase + 1) == 1) { +				++yBase; +				flag = true; +			} else { +				++i; +			} +		} +		if (xBase > xPos) { +			if (testLocationMask(xBase - 1, yBase) == 1) { +				--xBase; +				flag = true; +			} else { +				++i; +			} +		} else if (xBase <= xPos) { +			if (testLocationMask(xBase + 1, yBase) == 1) { +				++xBase; +				flag = true; +			} else { +				++i; +			} +		} +		if (xBase == xPos && yBase == yPos) { +			break; +		} +		if (!flag) { +			return 1; +		} +	} +	return 0; +} + +void TuckerEngine::handleMouseClickOnInventoryObject() { +	if (_panelState != 0) { +		return; +	} +	if (_mousePosY < 150 || _mousePosX < 212) { +		return; +	} +	int pos = ((_mousePosY - 150) / 25) * 3 + (_mousePosX - 212) / 36; +	int obj = _inventoryObjectsOffset + pos; +	if (_inventoryObjectsCount - 1 < obj) { +		return; +	} +	_selectedObjectNum = _inventoryObjectsList[obj]; +	_selectedObjectType = 3; +	switch (_selectedObjectNum) { +	case 30: +		if (_skipPanelObjectUnderCursor == 1 && _leftMouseButtonPressed) { +			_selectedObjectType = 0; +			_selectedObjectNum = 0; +			_actionVerb = 0; +			_skipPanelObjectUnderCursor = 0; +			_forceRedrawPanelItems = 1; +			_panelState = 2; +			setCursorType(1); +		} +		break; +	case 1: +		if (_actionVerb == 8 && _leftMouseButtonPressed) { +			if (_mapSequenceFlagsLocationTable[_locationNum - 1] == 1) { +				handleMapSequence(); +			} else { +				_actionPosX = _xPosCurrent; +				_actionPosY = _yPosCurrent - 64; +				_actionTextColor = 1; +				_actionCharacterNum = 99; +				setCursorType(2); +				_charSpeechSoundCounter = kDefaultCharSpeechSoundCounter; +				_updateCharPositionNewType = 0; +				_speechSoundNum = 2235; +				startSpeechSound(_speechSoundNum, _speechVolume); +				_characterSpeechDataPtr = _ptTextBuf + getPositionForLine(_speechSoundNum, _ptTextBuf); +				_speechSoundNum = 0; +				_actionVerb = 0; +				_selectedObjectType = 0; +				_selectedObjectNum = 0; +				_skipPanelObjectUnderCursor = 0; +			} +		} +		break; +	} +} + +int TuckerEngine::setCharacterUnderCursor() { +	if (_mousePosY > 140) { +		return -1; +	} +	for (int i = 0; i < _charPosCount; ++i) { +		if (_mousePosX + _scrollOffset <= _charPosTable[i].xPos) { +			continue; +		} +		if (_mousePosX + _scrollOffset >= _charPosTable[i].xPos + _charPosTable[i].xSize) { +			continue; +		} +		if (_mousePosY <= _charPosTable[i].yPos) { +			continue; +		} +		if (_mousePosY >= _charPosTable[i].yPos + _charPosTable[i].ySize) { +			continue; +		} +		if (_charPosTable[i].flagNum == 0 || _flagsTable[_charPosTable[i].flagNum] == _charPosTable[i].flagValue) { +			_selectedObjectType = 2; +			_selectedCharacterDirection = _charPosTable[i].direction; +			_selectedCharacterNum = i; +			return _charPosTable[i].name; +		} +	} +	return -1; +} + +int TuckerEngine::setLocationAnimationUnderCursor() { +	if (_mousePosY > 140) { +		return -1; +	} +	for (int i = _locationAnimationsCount - 1; i >= 0; --i) { +		if (_locationAnimationsTable[i].drawFlag == 0) { +			continue; +		} +		int num = _locationAnimationsTable[i].graphicNum; +		if (_mousePosX + _scrollOffset + 1 <= _dataTable[num].xDest) { +			continue; +		} +		if (_mousePosX + _scrollOffset >= _dataTable[num].xDest + _dataTable[num].xSize) { +			continue; +		} +		if (_mousePosY <= _dataTable[num].yDest) { +			continue; +		} +		if (_mousePosY >= _dataTable[num].yDest + _dataTable[num].ySize) { +			continue; +		} +		if (_locationAnimationsTable[i].selectable == 0) { +			return -1; +		} +		_selectedObjectType = 1; +		_selectedCharacterNum = i; +		_selectedCharacter2Num = i; +		return _locationAnimationsTable[i].selectable; +	} +	return -1; +} + +void TuckerEngine::setActionForInventoryObject() { +	if (_actionVerb == 0 || _actionVerb == 2 || _actionVerb == 6 || _actionVerb == 7) { +		playSpeechForAction(_actionVerb); +		_skipPanelObjectUnderCursor = 0; +		_actionRequiresTwoObjects = false; +		return; +	} +	if (_actionVerb == 3 || _actionVerb == 4) { +		if (!(_partNum == 2 && _selectedObjectNum == 19) && !(_partNum == 3 && _selectedObjectNum == 42)) { +			playSpeechForAction(_actionVerb); +			_skipPanelObjectUnderCursor = 0; +			_actionRequiresTwoObjects = false; +			return; +		} +	} +	_currentActionObj1Num = _actionObj1Num; +	_currentInfoString1SourceType = _actionObj1Type; +	_currentActionObj2Num = _actionObj2Num; +	_currentInfoString2SourceType = _actionObj2Type; +	if (_actionVerb == 1 && _selectedObjectType == 3) { +		if (_panelLockedFlag == 1) { +			if (_locationMaskType != 0) { +				return; +			} +			_panelLockedFlag = 0; +		} +		if (handleSpecialObjectSelectionSequence() == 1) { +			return; +		} +		_speechSoundNum = _actionObj1Num + _speechSoundBaseNum; +		startSpeechSound(_speechSoundNum, _speechVolume); +		_characterSpeechDataPtr = _ptTextBuf + getPositionForLine(_speechSoundNum, _ptTextBuf); +		_speechSoundNum = 0; +		_actionPosX = _xPosCurrent; +		_actionPosY = _yPosCurrent - 64; +		_actionTextColor = 1; +		_actionCharacterNum = 99; +		setCursorType(2); +		_charSpeechSoundCounter = kDefaultCharSpeechSoundCounter; +		_skipPanelObjectUnderCursor = 0; +		_actionRequiresTwoObjects = false; +		return; +	} +	if ((_partNum == 3 && (_actionObj1Num == 6 || _actionObj1Num == 3 || _actionObj1Num == 17)) || +		(_partNum == 2 && _actionObj1Num == 19) || +		(_partNum == 3 && (_actionObj1Num == 42 && _selectedObjectNum == 18)) ) { +		_skipPanelObjectUnderCursor = 0; +		_actionRequiresTwoObjects = false; +		_locationMaskCounter = 1; +		setActionState(); +		return; +	} +	if (!_actionRequiresTwoObjects) { +		_actionRequiresTwoObjects = true; +	} else { +		_skipPanelObjectUnderCursor = 0; +		_actionRequiresTwoObjects = false; +		_locationMaskCounter = 1; +		setActionState(); +	} +} + +void TuckerEngine::setActionState() { +	_updateCharPositionNewType = (_actionVerb == 0) ? 8 : _actionVerb; +	_currentActionObj1Num = _actionObj1Num; +	_currentInfoString1SourceType = _actionObj1Type; +	_currentActionObj2Num = _actionObj2Num; +	_currentInfoString2SourceType = _actionObj2Type; +	_actionRequiresTwoObjects = false; +	if (_selectedObjectType < 3) { +		setSelectedObjectKey(); +	} +} + +void TuckerEngine::playSpeechForAction(int i) { +	static const int speechActionTable[] = { 0, 2235, 2235, 2251, 2261, 2276, 2294, 2312, 2235 }; +	static const int maxCounterTable[] = { 0, 1, 13, 7, 12, 15, 15, 15, 14 }; +	++_speechActionCounterTable[i]; +	if (_speechActionCounterTable[i] > maxCounterTable[i]) { +		_speechActionCounterTable[i] = 0; +	} +	if (speechActionTable[i] >= 2000) { +		if (_updateCharPositionNewType == 8 && _currentActionObj1Num == 6 && _currentInfoString1SourceType == 3) { +			_speechSoundNum = 2395; +		} else { +			_speechSoundNum = _speechActionCounterTable[i] + speechActionTable[i]; +		} +		startSpeechSound(_speechSoundNum, _speechVolume); +		_characterSpeechDataPtr = _ptTextBuf + getPositionForLine(_speechSoundNum, _ptTextBuf); +		_speechSoundNum = 0; +		_actionPosX = _xPosCurrent; +		_actionPosY = _yPosCurrent - 64; +		_actionTextColor = 1; +		_actionCharacterNum = 99; +		setCursorType(2); +		_charSpeechSoundCounter = kDefaultCharSpeechSoundCounter; +	} +} + +void TuckerEngine::drawSpeechText(int xStart, int y, const uint8 *dataPtr, int num, int color) { +	int x = (xStart - _scrollOffset) * 2; +	int offset = (_scrollOffset + 320 - xStart) * 2; +	if (_conversationOptionsCount > 0) { +		x = 319; +	} else { +		if (x > offset) { +			x = offset; +		} +		if (x > 180) { +			x = 220; +		} else if (x < 150) { +			x = 220; +		} +	} +	int count = 0; +	int flag = 0; +	struct { +		int w, count, offset; +	} lines[5]; +	lines[0].offset = getPositionForLine(num, dataPtr); +	while (flag == 0 && count < 4) { +		int lineCharsCount, lineWidth; +		flag = splitSpeechTextLines(dataPtr, lines[count].offset, x, lineCharsCount, lineWidth); +		lines[count].w = lineWidth; +		lines[count].count = lineCharsCount; +		lines[count + 1].offset = lines[count].offset + lineCharsCount + 1; +		++count; +	} +	if (count * 10 > y) { +		y = count * 10; +	} +	for (int i = 0; i < count; ++i) { +		int dstOffset = xStart - lines[i].w / 2; +		if (dstOffset < _scrollOffset) { +			dstOffset = _scrollOffset; +		} else if (lines[i].w > _scrollOffset + 320) { +			dstOffset = _scrollOffset + 320 - lines[i].w; +		} +		uint8 *dst; +		if (_conversationOptionsCount) { +			dstOffset = xStart + _scrollOffset; +			dst = (i * 10 + y) * 640 + _locationBackgroundGfxBuf + dstOffset; +			_panelItemWidth = count; // ? +		} else { +			dst = (y - (count - i) * 10) * 640 + _locationBackgroundGfxBuf + dstOffset; +		} +		drawSpeechTextLine(dataPtr, lines[i].offset, lines[i].count, dst, color); +	} +} + +int TuckerEngine::splitSpeechTextLines(const uint8 *dataPtr, int pos, int x, int &lineCharsCount, int &lineWidth) { +	int count = 0; +	int w = 0; +	lineCharsCount = 0; +	lineWidth = 0; +	while (x + 1 > w && dataPtr[pos] != '\n' && dataPtr[pos] != '\r') { +		if (dataPtr[pos] == ' ') { +			lineCharsCount = count; +			lineWidth = w; +		} +		w += _charWidthTable[dataPtr[pos]]; +		++count; +		++pos; +	} +	int ret = 0; +	if (x + 1 > w) { +		lineCharsCount = count; +		lineWidth = w; +		ret = 1; +	} +	return ret; +} + +void TuckerEngine::drawSpeechTextLine(const uint8 *dataPtr, int pos, int count, uint8 *dst, uint8 color) { +	while (count > 0 && dataPtr[pos] != '\n') { +		Graphics::drawStringChar(dst, dataPtr[pos], 640, color, _charsetGfxBuf); +		dst += _charWidthTable[dataPtr[pos]]; +		++pos; +		--count; +	} +} + +} // namespace Tucker 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 <class S> 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  | 
