aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Montoir2007-10-29 23:35:50 +0000
committerGregory Montoir2007-10-29 23:35:50 +0000
commit6c6e8657b68ebc075871031ee8c662f349c4ab77 (patch)
tree1e2c691ffe1d142a3e781670ac63a981ebf70114
parentcaa451f5d2b471fc207739815638056f86fc8dce (diff)
downloadscummvm-rg350-6c6e8657b68ebc075871031ee8c662f349c4ab77.tar.gz
scummvm-rg350-6c6e8657b68ebc075871031ee8c662f349c4ab77.tar.bz2
scummvm-rg350-6c6e8657b68ebc075871031ee8c662f349c4ab77.zip
added 'igor' engine for the game 'Igor: Objective Uikokahonia'
svn-id: r29318
-rw-r--r--base/plugins.cpp3
-rw-r--r--base/plugins.h2
-rwxr-xr-xconfigure10
-rw-r--r--engines/engines.mk6
-rw-r--r--engines/igor/detection.cpp92
-rw-r--r--engines/igor/igor.cpp2941
-rw-r--r--engines/igor/igor.h924
-rw-r--r--engines/igor/menu.cpp346
-rw-r--r--engines/igor/module.mk44
-rw-r--r--engines/igor/parts/part_04.cpp116
-rw-r--r--engines/igor/parts/part_05.cpp291
-rw-r--r--engines/igor/parts/part_06.cpp419
-rw-r--r--engines/igor/parts/part_12.cpp581
-rw-r--r--engines/igor/parts/part_13.cpp247
-rw-r--r--engines/igor/parts/part_14.cpp615
-rw-r--r--engines/igor/parts/part_15.cpp521
-rw-r--r--engines/igor/parts/part_16.cpp304
-rw-r--r--engines/igor/parts/part_17.cpp529
-rw-r--r--engines/igor/parts/part_18.cpp215
-rw-r--r--engines/igor/parts/part_19.cpp336
-rw-r--r--engines/igor/parts/part_21.cpp492
-rw-r--r--engines/igor/parts/part_22.cpp186
-rw-r--r--engines/igor/parts/part_23.cpp304
-rw-r--r--engines/igor/parts/part_24.cpp340
-rw-r--r--engines/igor/parts/part_25.cpp256
-rw-r--r--engines/igor/parts/part_26.cpp297
-rw-r--r--engines/igor/parts/part_27.cpp296
-rw-r--r--engines/igor/parts/part_28.cpp369
-rw-r--r--engines/igor/parts/part_30.cpp325
-rw-r--r--engines/igor/parts/part_31.cpp453
-rw-r--r--engines/igor/parts/part_33.cpp519
-rw-r--r--engines/igor/parts/part_36.cpp177
-rw-r--r--engines/igor/parts/part_37.cpp139
-rw-r--r--engines/igor/parts/part_75.cpp119
-rw-r--r--engines/igor/parts/part_85.cpp227
-rw-r--r--engines/igor/parts/part_90.cpp76
-rw-r--r--engines/igor/parts/part_95.cpp72
-rw-r--r--engines/igor/parts/part_main.cpp974
-rw-r--r--engines/igor/resource_ids.h333
-rw-r--r--engines/igor/resource_tbl.h333
-rw-r--r--engines/igor/staticres.cpp1124
41 files changed, 15952 insertions, 1 deletions
diff --git a/base/plugins.cpp b/base/plugins.cpp
index 0de8baccc6..7ccd99ce34 100644
--- a/base/plugins.cpp
+++ b/base/plugins.cpp
@@ -107,6 +107,9 @@ public:
#ifndef DISABLE_GOB
LINK_PLUGIN(GOB)
#endif
+ #ifndef DISABLE_IGOR
+ LINK_PLUGIN(IGOR)
+ #endif
#ifndef DISABLE_KYRA
LINK_PLUGIN(KYRA)
#endif
diff --git a/base/plugins.h b/base/plugins.h
index c89b590a73..23a28b745c 100644
--- a/base/plugins.h
+++ b/base/plugins.h
@@ -89,7 +89,7 @@ public:
* Note: This MUST succeed for every gameID on the list returned by
* gameIDList(), but MAY also work for additional gameids (e.g. to support
* obsolete targets).
- * - DetectedGameList Engine_##ID##_detectGames(const FSList &fslist)
+ * - GameList Engine_##ID##_detectGames(const FSList &fslist)
* -> scans through the given file list (usually the contents of a directory),
* and attempts to detects games present in that location.
* - PluginError Engine_##ID##_create(OSystem *syst, Engine **engine)
diff --git a/configure b/configure
index 803bb1066d..783b1bffaa 100755
--- a/configure
+++ b/configure
@@ -55,6 +55,7 @@ _build_cine=yes
_build_cruise=no
_build_drascula=no
_build_gob=yes
+_build_igor=no
_build_kyra=yes
_build_lure=yes
_build_parallaction=yes
@@ -350,6 +351,7 @@ Optional Features:
--enable-cruise build the Cruise for a Corpse engine
--enable-drascula build the Drascula: The Vampire Strikes Back engine
--disable-gob don't build the Gobli*ns engine
+ --enable-igor build the Igor: Objective Uikokahonia engine
--disable-kyra don't build the Legend of Kyrandia engine
--disable-lure don't build the Lure of the Temptress engine
--disable-parallaction don't build the Parallaction engine
@@ -423,6 +425,7 @@ for ac_option in $@; do
--enable-cruise) _build_cruise=yes ;;
--enable-drascula) _build_drascula=yes ;;
--disable-gob) _build_gob=no ;;
+ --enable-igor) _build_igor=yes ;;
--disable-kyra) _build_kyra=no ;;
--disable-lure) _build_lure=no ;;
--disable-parallaction) _build_parallaction=no ;;
@@ -720,6 +723,7 @@ add_to_config_mk_if_no $_build_cine 'DISABLE_CINE = 1'
add_to_config_mk_if_no $_build_cruise 'DISABLE_CRUISE = 1'
add_to_config_mk_if_no $_build_drascula 'DISABLE_DRASCULA = 1'
add_to_config_mk_if_no $_build_gob 'DISABLE_GOB = 1'
+add_to_config_mk_if_no $_build_igor 'DISABLE_IGOR = 1'
add_to_config_mk_if_no $_build_kyra 'DISABLE_KYRA = 1'
add_to_config_mk_if_no $_build_lure 'DISABLE_LURE = 1'
add_to_config_mk_if_no $_build_parallaction 'DISABLE_PARALLACTION = 1'
@@ -1375,6 +1379,12 @@ if test "$_build_gob" = yes ; then
else
echo "disable"
fi
+echo_n " Igor: Objective Uikokahonia engine..."
+if test "$_build_igor" = yes ; then
+ echo "enable"
+else
+ echo "disable"
+fi
echo_n " Legend of Kyrandia engine..."
if test "$_build_kyra" = yes ; then
echo "enable"
diff --git a/engines/engines.mk b/engines/engines.mk
index e61537bc02..e2851d43ae 100644
--- a/engines/engines.mk
+++ b/engines/engines.mk
@@ -49,6 +49,12 @@ else
MODULES += engines/gob
endif
+ifdef DISABLE_IGOR
+DEFINES += -DDISABLE_IGOR
+else
+MODULES += engines/igor
+endif
+
ifdef DISABLE_KYRA
DEFINES += -DDISABLE_KYRA
else
diff --git a/engines/igor/detection.cpp b/engines/igor/detection.cpp
new file mode 100644
index 0000000000..05f5f9a3f9
--- /dev/null
+++ b/engines/igor/detection.cpp
@@ -0,0 +1,92 @@
+/* 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 "base/plugins.h"
+
+#include "common/config-manager.h"
+#include "common/file.h"
+#include "common/fs.h"
+
+#include "igor/igor.h"
+
+static const PlainGameDescriptor igorGameDescriptor = {
+ "igor", "Igor: Objective Uikokahonia"
+};
+
+static const char *igorDetectFileName = "IGOR.DAT";
+static uint32 igorDetectFileSize = 4086790;
+
+GameList Engine_IGOR_gameIDList() {
+ GameList games;
+ games.push_back(igorGameDescriptor);
+ return games;
+}
+
+GameDescriptor Engine_IGOR_findGameID(const char *gameid) {
+ if (scumm_stricmp(igorGameDescriptor.gameid, gameid) == 0) {
+ return igorGameDescriptor;
+ }
+ return GameDescriptor();
+}
+
+GameList Engine_IGOR_detectGames(const FSList &fslist) {
+ GameList detectedGames;
+ for (FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
+ if (file->isDirectory()) {
+ continue;
+ }
+ if (file->getName().equalsIgnoreCase(igorDetectFileName)) {
+ Common::File f;
+ if (!f.open(*file)) {
+ continue;
+ }
+ const uint32 sig = f.readUint32BE();
+ if (sig == MKID_BE('FBOV') && f.size() == igorDetectFileSize) {
+ GameDescriptor gd(igorGameDescriptor.gameid, igorGameDescriptor.description, Common::EN_ANY, Common::kPlatformPC);
+ gd.updateDesc("Demo");
+ detectedGames.push_back(gd);
+ break;
+ }
+ }
+ }
+ return detectedGames;
+}
+
+PluginError Engine_IGOR_create(OSystem *system, Engine **engine) {
+ FSList fslist;
+ FilesystemNode dir(ConfMan.get("path"));
+ if (!dir.getChildren(fslist, FilesystemNode::kListFilesOnly)) {
+ return kInvalidPathError;
+ }
+ GameList gameList = Engine_IGOR_detectGames(fslist);
+ if (gameList.size() != 1) {
+ return kNoGameDataFoundError;
+ }
+ assert(engine);
+ *engine = new Igor::IgorEngine(system);
+ return kNoError;
+}
+
+REGISTER_PLUGIN(IGOR, "Igor: Objective Uikokahonia", "Igor: Objective Uikokahonia (C) Pendulo Studios");
diff --git a/engines/igor/igor.cpp b/engines/igor/igor.cpp
new file mode 100644
index 0000000000..68e6eb2002
--- /dev/null
+++ b/engines/igor/igor.cpp
@@ -0,0 +1,2941 @@
+/* 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 "sound/voc.h"
+
+#include "igor/igor.h"
+
+namespace Igor {
+
+IgorEngine::IgorEngine(OSystem *system)
+ : Engine(system) {
+
+ _screenVGA = (uint8 *)malloc(320 * 200);
+ for (int i = 0; i < 4; ++i) {
+ _facingIgorFrames[i] = (uint8 *)malloc(13500);
+ }
+ _screenLayer1 = (uint8 *)malloc(320 * 144);
+ _screenLayer2 = (uint8 *)malloc(320 * 144);
+ _screenTextLayer = (uint8 *)malloc(320 * 144);
+ _screenTempLayer = (uint8 *)malloc(9996);
+ _igorHeadFrames = (uint8 *)malloc(3696);
+ _animFramesBuffer = (uint8 *)malloc(65535);
+ _inventoryPanelBuffer = (uint8 *)malloc(9600 * 2);
+ _inventoryImagesBuffer = (uint8 *)malloc(48000);
+ _verbsPanelBuffer = (uint8 *)malloc(3840);
+
+ Common::addSpecialDebugLevel(kDebugEngine, "Engine", "Engine debug level");
+ Common::addSpecialDebugLevel(kDebugResource, "Resource", "Resource debug level");
+ Common::addSpecialDebugLevel(kDebugScreen, "Screen", "Screen debug level");
+ Common::addSpecialDebugLevel(kDebugWalk, "Walk", "Walk debug level");
+ Common::addSpecialDebugLevel(kDebugGame, "Game", "Game debug level");
+}
+
+IgorEngine::~IgorEngine() {
+ Common::clearAllSpecialDebugLevels();
+ free(_screenVGA);
+ for (int i = 0; i < 4; ++i) {
+ free(_facingIgorFrames[i]);
+ }
+ free(_screenLayer1);
+ free(_screenLayer2);
+ free(_screenTextLayer);
+ free(_screenTempLayer);
+ free(_igorHeadFrames);
+ free(_animFramesBuffer);
+ free(_inventoryPanelBuffer);
+ free(_inventoryImagesBuffer);
+ free(_verbsPanelBuffer);
+}
+
+int IgorEngine::init() {
+ _system->beginGFXTransaction();
+ initCommonGFX(false);
+ _system->initSize(320, 200);
+ _system->endGFXTransaction();
+
+ _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
+ return 0;
+}
+
+void IgorEngine::restart() {
+ _screenVGAVOffset = 0;
+
+ memset(&_gameState, 0, sizeof(_gameState));
+ _nextTimer = 0;
+ _fastMode = false;
+ _language = kLanguageEnglish;
+
+ memset(_walkData, 0, sizeof(_walkData));
+ _walkCurrentPos = 0;
+ _walkDataLastIndex = _walkDataCurrentIndex = 0;
+ _walkCurrentFrame = 0;
+ _walkDataCurrentPosX = _walkDataCurrentPosY = 0;
+ _walkToObjectPosX = _walkToObjectPosY = 0;
+
+ memset(&_currentAction, 0, sizeof(_currentAction));
+ _currentAction.verb = kVerbWalk;
+ _actionCode = 0;
+ _actionWalkPoint = 0;
+ memset(_inputVars, 0, sizeof(_inputVars));
+ memset(_musicSequenceTable, 0, sizeof(_musicSequenceTable));
+
+ _talkDelay = _talkSpeechCounter = _talkDelayCounter = 0;
+ memset(_dialogueTextsTable, 0, sizeof(_dialogueTextsTable));
+ _dialogueTextsStart = 0;
+ _dialogueTextsCount = 0;
+ _dialogueDirtyRectY = 0;
+ _dialogueDirtyRectSize = 0;
+ memset(_dialogueQuestions, 0, sizeof(_dialogueQuestions));
+ memset(_dialogueReplies, 0, sizeof(_dialogueReplies));
+ _dialogueEnded = false;
+ _dialogueChoiceSelected = 0;
+ memset(_dialogueInfo, 0, sizeof(_dialogueInfo));
+
+ memset(_objectsState, 0, sizeof(_objectsState));
+ memcpy(_inventoryImages, INVENTORY_IMG_INIT, 36);
+ memset(_inventoryInfo, 0, sizeof(_inventoryInfo));
+ memset(_verbPrepositions, 0, sizeof(_verbPrepositions));
+ memset(_globalObjectNames, 0, sizeof(_globalObjectNames));
+ memset(_globalDialogueTexts, 0, sizeof(_globalDialogueTexts));
+ memset(_verbsName, 0, sizeof(_verbsName));
+ memset(_roomObjectNames, 0, sizeof(_roomObjectNames));
+
+ _igorTempFrames = _facingIgorFrames[0] + 10500;
+
+ memset(_roomObjectAreasTable, 0, sizeof(_roomObjectAreasTable));
+ memset(_roomActionsTable, 0, sizeof(_roomActionsTable));
+ _executeMainAction = 0;
+ _executeRoomAction = 0;
+ _previousMusic = 0;
+ memset(_musicSequenceTable, 0, sizeof(_musicSequenceTable));
+ _actionCode = 0;
+ _actionWalkPoint = 0;
+ memset(_inputVars, 0, sizeof(_inputVars));
+ _scrollInventory = false;
+ _roomCursorOn = true;
+ _currentCursor = 0;
+ _dialogueCursorOn = true;
+ _updateDialogue = 0;
+ _updateRoomBackground = 0;
+
+ _gameTicks = 0;
+}
+
+int IgorEngine::go() {
+ restart();
+ setupDefaultPalette();
+ _currentPart = kStartupPart;
+ if (!_ovlFile.open("IGOR.DAT")) {
+ error("Unable to open 'IGOR.DAT'");
+ }
+ if (!_sndFile.open("IGOR.FSD")) {
+ error("Unable to open 'IGOR.FSD'");
+ }
+ loadMainTexts();
+ loadIgorFrames();
+ _gameState.talkMode = kTalkModeTextOnly;
+ _gameState.talkSpeed = 3;
+ _talkSpeechCounter = 5;
+ _eventQuitGame = false;
+ PART_MAIN();
+ _ovlFile.close();
+ _sndFile.close();
+ return 0;
+}
+
+void IgorEngine::waitForTimer(int ticks) {
+ _system->copyRectToScreen(_screenVGA, 320, 0, _screenVGAVOffset, 320, 200 - _screenVGAVOffset);
+ _system->updateScreen();
+ uint32 endTicks = (ticks == -1) ? _nextTimer : _system->getMillis() + ticks * 1000 / kTickDelay;
+ do {
+ Common::Event ev;
+ while (_eventMan->pollEvent(ev)) {
+ switch (ev.type) {
+ case Common::EVENT_QUIT:
+ _currentPart = 255;
+ _eventQuitGame = true;
+ break;
+ case Common::EVENT_KEYDOWN:
+ if (ev.kbd.keycode == Common::KEYCODE_ESCAPE) {
+ _inputVars[kInputEscape] = 1;
+ } else if (ev.kbd.keycode == Common::KEYCODE_SPACE) {
+ _inputVars[kInputOptions] = 1;
+ } else if (ev.kbd.keycode == Common::KEYCODE_p) {
+ _inputVars[kInputPause] = 1;
+ }
+ break;
+ case Common::EVENT_MOUSEMOVE:
+ _inputVars[kInputCursorXPos] = ev.mouse.x;
+ _inputVars[kInputCursorYPos] = ev.mouse.y;
+ break;
+ case Common::EVENT_RBUTTONDOWN:
+ _inputVars[kInputSkipDialogue] = 1;
+ break;
+ case Common::EVENT_LBUTTONDOWN:
+ _inputVars[kInputClick] = 1;
+ _inputVars[kInputCursorXPos] = ev.mouse.x;
+ _inputVars[kInputCursorYPos] = ev.mouse.y;
+ break;
+ default:
+ break;
+ }
+ }
+ _system->delayMillis(10);
+ if (_system->getMillis() >= endTicks) {
+ break;
+ }
+ } while (!_fastMode);
+ _nextTimer = _system->getMillis() + 8 * 1000 / kTickDelay;
+ if (ticks != -1) {
+ return;
+ }
+ _gameTicks += 8;
+ if (_gameTicks == 64) {
+ _gameTicks = 0;
+ setCursor(_currentCursor);
+ _currentCursor = (_currentCursor + 1) & 3;
+ }
+}
+
+void IgorEngine::copyArea(uint8 *dst, int dstOffset, int dstPitch, const uint8 *src, int srcPitch, int w, int h, bool transparent) {
+ uint8 *p = dst + dstOffset;
+ for (int y = 0; y < h; ++y) {
+ if (transparent) {
+ for (int x = 0; x < w; ++x) {
+ if (src[x] != 0) {
+ p[x] = src[x];
+ }
+ }
+ } else {
+ memcpy(p, src, w);
+ }
+ p += dstPitch;
+ src += srcPitch;
+ }
+}
+
+int IgorEngine::getRandomNumber(int m) {
+ assert(m != 0);
+ return rand() % m;
+}
+
+void IgorEngine::playMusic(int num) {
+ debug(kDebugEngine, "playMusic() %d", num);
+ const int *seq = 0;
+ switch (num) {
+ case 2: {
+ static const int cmf[] = { CMF_2_1, CMF_2_2, CMF_2_3, CMF_2_4, 0 };
+ seq = cmf;
+ }
+ break;
+ case 3: {
+ static const int cmf[] = { CMF_3, 0 };
+ seq = cmf;
+ }
+ break;
+ case 4: {
+ static const int cmf[] = { CMF_4, 0 };
+ seq = cmf;
+ }
+ break;
+ case 7: {
+ static const int cmf[] = { CMF_7_1, CMF_7_2, CMF_7_3, CMF_7_4, 0 };
+ seq = cmf;
+ }
+ break;
+ case 8: {
+ static const int cmf[] = { CMF_8, 0 };
+ seq = cmf;
+ }
+ break;
+ case 9: {
+ static const int cmf[] = { CMF_9, 0 };
+ seq = cmf;
+ }
+ break;
+ case 10: {
+ static const int cmf[] = { CMF_10, 0 };
+ seq = cmf;
+ }
+ break;
+ case 11: {
+ static const int cmf[] = { CMF_11, 0 };
+ seq = cmf;
+ }
+ break;
+ case 12: {
+ static const int cmf[] = { CMF_12, 0 };
+ seq = cmf;
+ }
+ break;
+ }
+ if (seq) {
+ for (int i = 0; i < 5; ++i) {
+ free(_musicSequenceTable[i]);
+ }
+ for (int i = 0; seq[i]; ++i) {
+ _musicSequenceTable[i] = loadData(seq[i]);
+ }
+ }
+ _gameState.musicNum = num;
+ _gameState.musicSequenceIndex = 1;
+}
+
+void IgorEngine::updateMusic() {
+ if (_gameState.jumpToNextMusic) {
+ if (_gameState.musicNum == 2) {
+ _gameState.musicSequenceIndex = getRandomNumber(4) + 1;
+// _timerHandler0x1CCounter = 5;
+ } else if (_gameState.musicNum == 3 || _gameState.musicNum == 4 || _gameState.musicNum == 8 || _gameState.musicNum == 9 || _gameState.musicNum == 10) {
+// _timerHandler0x1CCounter = 50;
+ } else if (_gameState.musicNum == 7) {
+ if (_gameState.musicSequenceIndex == 4) {
+ _gameState.musicSequenceIndex = 1;
+ } else {
+ ++_gameState.musicSequenceIndex;
+ }
+// _timerHandler0x1CCounter = 5;
+ } else if (_gameState.musicNum == 11) {
+// _timerHandler0x1CCounter = 5;
+ }
+ }
+}
+
+void IgorEngine::playSound(int num, int fl) {
+ if (fl && _mixer->isSoundHandleActive(_sfxHandle)) {
+ return;
+ }
+ if (!fl) {
+// num = 20; // "Speech not recorded"
+ return;
+ }
+ --num;
+ _sndFile.seek(_fdsOffsetsTable[num]);
+ Audio::AudioStream *stream = Audio::makeVOCStream(_sndFile);
+ if (stream) {
+ _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_sfxHandle, stream);
+ }
+}
+
+void IgorEngine::stopSound() {
+ _mixer->stopHandle(_sfxHandle);
+}
+
+void IgorEngine::loadIgorFrames() {
+ loadData(FRM_IgorDirBack, _facingIgorFrames[0]);
+ loadData(FRM_IgorDirRight, _facingIgorFrames[1]);
+ loadData(FRM_IgorDirFront, _facingIgorFrames[2]);
+ loadData(FRM_IgorDirLeft, _facingIgorFrames[3]);
+ loadData(FRM_IgorHead, _igorHeadFrames);
+ memcpy(_igorPalette, PAL_IGOR_1, 48);
+}
+
+void IgorEngine::fixDialogueTextPosition(int num, int count, int *x, int *y) {
+ int textLineWidth = 0;
+ for (int i = 0; i < count; ++i) {
+ int w = getStringWidth(_globalDialogueTexts[num + i]);
+ if (w > textLineWidth) {
+ textLineWidth = w;
+ }
+ }
+ int textX = *x;
+ textX += textLineWidth / 2 - 1;
+ if (textX > 318) {
+ textX = 317 - textLineWidth;
+ } else {
+ textX -= textLineWidth;
+ }
+ if (textX < 1) {
+ textX = textLineWidth / 2 + 1;
+ } else {
+ textX += textLineWidth / 2;
+ }
+ *x = textX;
+
+ int textY = *y;
+ textY -= count * 10;
+ if (textY < 1) {
+ textY = 1;
+ }
+ *y = textY;
+}
+
+void IgorEngine::startCutsceneDialogue(int x, int y, int r, int g, int b) {
+ debug(kDebugEngine, "startCutsceneDialogue() pos %d,%d color %d,%d,%d", x, y, r, g, b);
+ --_dialogueTextsCount;
+ int talkX = x;
+ int talkY = y;
+ const DialogueText *dt = &_dialogueTextsTable[_dialogueTextsStart];
+ fixDialogueTextPosition(dt->num, dt->count, &talkX, &talkY);
+ _dialogueDirtyRectY = talkY * 320;
+ _dialogueDirtyRectSize = dt->count * 11 * 320;
+ assert(_dialogueDirtyRectSize < 320 * 72);
+ memcpy(_screenTextLayer, _screenVGA + _dialogueDirtyRectY, _dialogueDirtyRectSize);
+ memcpy(_screenTextLayer + 320 * 72, _screenVGA + _dialogueDirtyRectY, _dialogueDirtyRectSize);
+ for (int i = 0; i < dt->count; ++i) {
+ const char *textLine = _globalDialogueTexts[dt->num + i];
+ int textLineWidth = getStringWidth(textLine);
+ int textX = talkX - textLineWidth / 2;
+ int textY = i * 10;
+ drawString(_screenTextLayer, textLine, textX, textY, kTalkColor, kTalkShadowColor, kTalkShadowColor);
+ }
+ setPaletteColor(kTalkColor, r, g, b);
+ setPaletteColor(kTalkShadowColor, 0, 0, 0);
+ if (_gameState.talkMode != kTalkModeSpeechOnly) {
+ memcpy(_screenVGA + _dialogueDirtyRectY, _screenTextLayer, _dialogueDirtyRectSize);
+ }
+ if (_gameState.talkMode == kTalkModeTextOnly) {
+ _talkDelay = (2 * dt->count) * _talkDelays[_gameState.talkSpeed];
+ _talkDelayCounter = 0;
+ } else {
+ _talkDelay = -1;
+ _talkDelayCounter = 0;
+ }
+ if (_gameState.talkMode == kTalkModeTextOnly) {
+ playSound(24, 0);
+ }
+ _gameState.dialogueTextRunning = true;
+ _inputVars[kInputSkipDialogue] = 0;
+}
+
+void IgorEngine::waitForEndOfCutsceneDialogue(int x, int y, int r, int g, int b) {
+ do {
+ if (_gameState.dialogueTextRunning && _inputVars[kInputSkipDialogue]) {
+ _talkDelayCounter = _talkDelay;
+ _inputVars[kInputSkipDialogue] = 0;
+ }
+ if (compareGameTick(19, 32) && _gameState.dialogueTextRunning) {
+ if (_talkSpeechCounter > 2) {
+ if (_gameState.talkMode < 2) {
+ _talkDelayCounter = _talkDelay;
+ }
+ if (_talkDelay == _talkDelayCounter) {
+ if (_updateDialogue) {
+ (this->*_updateDialogue)(kUpdateDialogueAnimEndOfSentence);
+ }
+ memcpy(_screenVGA + _dialogueDirtyRectY, _screenTextLayer + 23040, _dialogueDirtyRectSize);
+ if (_dialogueTextsCount == 0) {
+ _gameState.dialogueTextRunning = 0;
+ } else {
+ ++_dialogueTextsStart;
+ if (_gameState.talkMode < 2) {
+ if (_talkSpeechCounter != -1) {
+ _talkSpeechCounter = 0;
+ } else {
+ _talkSpeechCounter = 5;
+ startCutsceneDialogue(x, y, r, g, b);
+ }
+ } else {
+ startCutsceneDialogue(x, y, r, g, b);
+ }
+ }
+ } else {
+ ++_talkDelayCounter;
+ if (_updateDialogue) {
+ (this->*_updateDialogue)(kUpdateDialogueAnimMiddleOfSentence);
+ }
+ }
+ } else {
+ if (_talkSpeechCounter == 2) {
+ startCutsceneDialogue(x, y, r, g, b);
+ }
+ ++_talkSpeechCounter;
+ }
+ }
+ if (_updateRoomBackground) {
+ (this->*_updateRoomBackground)();
+ }
+ if (_inputVars[kInputEscape]) return;
+ waitForTimer();
+ } while (_gameState.dialogueTextRunning);
+}
+
+void IgorEngine::fixIgorDialogueTextPosition(int num, int count, int *x, int *y) {
+ WalkData *wd = &_walkData[_walkDataLastIndex - 1];
+ *x = wd->x;
+ *y = wd->y - wd->scaleWidth - 3;
+ fixDialogueTextPosition(num, count, x, y);
+}
+
+void IgorEngine::startIgorDialogue() {
+ debug(kDebugEngine, "startIgorDialogue()");
+// if (_dialogueCursorOn) {
+// clearCursor();
+// }
+ --_dialogueTextsCount;
+ int talkX, talkY;
+ const DialogueText *dt = &_dialogueTextsTable[_dialogueTextsStart];
+ fixIgorDialogueTextPosition(dt->num, dt->count, &talkX, &talkY);
+ _dialogueDirtyRectY = talkY * 320;
+ _dialogueDirtyRectSize = dt->count * 11 * 320;
+ assert(_dialogueDirtyRectSize < 320 * 72);
+ memcpy(_screenTextLayer, _screenVGA + _dialogueDirtyRectY, _dialogueDirtyRectSize);
+
+ if (_currentPart == 690) {
+ memcpy(_screenTextLayer + 320 * 72, _screenLayer1 + _dialogueDirtyRectY, _dialogueDirtyRectSize);
+ if (_currentAction.verb == kVerbLook && _currentAction.object1Num == 15) {
+ memcpy(_screenTextLayer + 320 * 72, _screenVGA + _dialogueDirtyRectY, _dialogueDirtyRectSize);
+ }
+ if (_currentAction.verb == kVerbLook && _currentAction.object1Num == 19) {
+ memcpy(_screenTextLayer + 320 * 72, _screenVGA + _dialogueDirtyRectY, _dialogueDirtyRectSize);
+ }
+ } else {
+ memcpy(_screenTextLayer + 320 * 72, _screenVGA + _dialogueDirtyRectY, _dialogueDirtyRectSize);
+ }
+ for (int i = 0; i < dt->count; ++i) {
+ const char *textLine = _globalDialogueTexts[dt->num + i];
+ int textLineWidth = getStringWidth(textLine);
+ int textX = talkX - textLineWidth / 2;
+ int textY = i * 10;
+ drawString(_screenTextLayer, textLine, textX, textY, kTalkColor, kTalkShadowColor, kTalkShadowColor);
+ }
+ setPaletteColor(kTalkColor, _dialogueColor[0], _dialogueColor[1], _dialogueColor[2]);
+ setPaletteColor(kTalkShadowColor, 0, 0, 0);
+ if (_gameState.talkMode > 0) {
+ memcpy(_screenVGA + _dialogueDirtyRectY, _screenTextLayer, _dialogueDirtyRectSize);
+ }
+ if (_gameState.talkMode == 2) {
+ _talkDelay = (2 * dt->count) * _talkDelays[_gameState.talkSpeed];
+ _talkDelayCounter = 0;
+ } else {
+ _talkDelay = -1;
+ _talkDelayCounter = 0;
+ }
+ if (_gameState.talkMode >= 2) {
+ playSound(24, 0);
+ }
+ _gameState.dialogueTextRunning = true;
+ _inputVars[kInputSkipDialogue] = 0;
+}
+
+void IgorEngine::waitForEndOfIgorDialogue() {
+ do {
+ if (_gameState.dialogueTextRunning && _inputVars[kInputSkipDialogue]) {
+ _talkDelayCounter = _talkDelay;
+ _inputVars[kInputSkipDialogue] = 0;
+ }
+ if (compareGameTick(19, 32) && _gameState.dialogueTextRunning) {
+ if (_talkSpeechCounter > 2) {
+ if (_gameState.talkMode < 2) {
+ _talkDelayCounter = _talkDelay;
+ }
+ if (_talkDelay == _talkDelayCounter) {
+ animateIgorTalking(0);
+ memcpy(_screenVGA + _dialogueDirtyRectY, _screenTextLayer + 23040, _dialogueDirtyRectSize);
+ if (_dialogueTextsCount == 0) {
+ _gameState.dialogueTextRunning = 0;
+ } else {
+ ++_dialogueTextsStart;
+ if (_gameState.talkMode < 2) {
+ if (_talkSpeechCounter != -1) {
+ _talkSpeechCounter = 0;
+ } else {
+ _talkSpeechCounter = 5;
+ startIgorDialogue();
+ }
+ } else {
+ startIgorDialogue();
+ }
+ }
+ } else {
+ animateIgorTalking(getRandomNumber(6));
+ ++_talkDelayCounter;
+ }
+ } else {
+ if (_talkSpeechCounter == 2) {
+ startIgorDialogue();
+ }
+ ++_talkSpeechCounter;
+ }
+ }
+ if (_updateRoomBackground) {
+ (this->*_updateRoomBackground)();
+ }
+ if (_inputVars[kInputEscape]) return;
+ waitForTimer();
+ } while (_gameState.dialogueTextRunning);
+}
+
+int IgorEngine::getObjectFromInventory(int x) const {
+ if (x >= 20 && x <= 299) {
+ int i = (x - 20) / 40 + _inventoryInfo[72];
+ if (i <= _inventoryInfo[73]) {
+ return _inventoryInfo[i - 1];
+ }
+ }
+ return 0;
+}
+
+int IgorEngine::getSelectedVerb() const {
+ for (int i = 0; i <= 6; ++i) {
+ for (int w = 0; w <= 19; ++w) {
+ const uint8 *p = _screenVGA + 320 * 156 + i * 46 + w;
+ if (*p == 251) {
+ return i + 2;
+ }
+ }
+ }
+ return 0;
+}
+
+const ResourceEntry *IgorEngine::findData(int id) const {
+ --id;
+ assert(id >= 0 && id < _resourceEntriesCount);
+ const ResourceEntry *re = &_resourceEntriesTable[id];
+ assert(re->id == id + 1);
+ return re;
+}
+
+uint8 *IgorEngine::loadData(int id, uint8 *dst, int *size) {
+ const ResourceEntry *re = findData(id);
+ assert(re);
+ debug(kDebugResource, "loadData() id %d offset %d size %d", id, re->offs, re->size);
+ if (!dst) {
+ dst = (uint8 *)malloc(re->size);
+ if (!dst) {
+ error("Unable to allocate %d bytes", re->size);
+ }
+ }
+ _ovlFile.seek(re->offs);
+ _ovlFile.read(dst, re->size);
+ if (size) {
+ *size = re->size;
+ }
+ return dst;
+}
+
+static void decodeRoomString(const uint8 *src, char *dst, int sz) {
+ for (int i = 0; i < sz; ++i) {
+ uint8 code = *src++;
+ if ((code >= 0xAE && code <= 0xC7) || (code >= 0xCE && code <= 0xE7)) {
+ code -= 0x6D;
+ } else if (code > 0xE7) {
+ switch (code) {
+ case 0xE8:
+ code = 0xA0;
+ break;
+ case 0xE9:
+ code = 0x82;
+ break;
+ case 0xEA:
+ code = 0xA1;
+ break;
+ case 0xEB:
+ code = 0xA2;
+ break;
+ case 0xEC:
+ code = 0xA3;
+ break;
+ case 0xED:
+ code = 0xA4;
+ break;
+ case 0xEE:
+ code = 0xA5;
+ break;
+ }
+ }
+ *dst++ = (char)code;
+ }
+}
+
+void IgorEngine::decodeRoomStrings(const uint8 *p, bool skipObjectNames) {
+ if (!skipObjectNames) {
+ for (int i = 0; i < 20; ++i) {
+ _roomObjectNames[i][0] = '\0';
+ }
+ uint8 code = *p++;
+ int index = -1;
+ while (code != 0xF6) {
+ if (code == 0xF4) {
+ ++index;
+ }
+ int len = *p++;
+ if (len != 0) {
+ assert(index >= 0);
+ decodeRoomString(p, _roomObjectNames[index], len);
+ p += len;
+ _roomObjectNames[index][len] = '\0';
+ debug(kDebugResource, "decodeRoomStrings() _roomObjectNames[%d] '%s'", index, _roomObjectNames[index]);
+ }
+ code = *p++;
+ }
+ }
+ for (int i = 200; i < 250; ++i) {
+ _globalDialogueTexts[i][0] = '\0';
+ }
+ uint8 code = *p++;
+ int index = 200;
+ while (code != 0xF6) {
+ if (code == 0xF4) {
+ ++index;
+ }
+ int len = *p++;
+ if (len != 0) {
+ decodeRoomString(p, _globalDialogueTexts[index], len);
+ p += len;
+ _globalDialogueTexts[index][len] = '\0';
+ debug(kDebugResource, "decodeRoomStrings() _globalDialogueTexts[%d] '%s'", index, _globalDialogueTexts[index]);
+ }
+ code = *p++;
+ }
+}
+
+void IgorEngine::decodeRoomText(const uint8 *p) {
+ debug(kDebugResource, "decodeRoomText()");
+ memcpy(_walkXScaleRoom, p, 320); p += 320;
+ memcpy(_walkYScaleRoom, p, 432); p += 432;
+ decodeRoomStrings(p);
+}
+
+void IgorEngine::decodeRoomAreas(const uint8 *p, int count) {
+ for (int i = 0; i < count; ++i) {
+ RoomObjectArea *roa = &_roomObjectAreasTable[i];
+ roa->area = *p++;
+ assert((roa->area & 0x80) == 0);
+ roa->object = *p++;
+ roa->y1Lum = *p++;
+ roa->y2Lum = *p++;
+ roa->deltaLum = *p++;
+ }
+}
+
+void IgorEngine::decodeRoomMask(const uint8 *p) {
+ uint8 *dst = _screenLayer2;
+ int sz = 320 * 144;
+ while (sz != 0) {
+ uint8 b = *p++;
+ int len = READ_LE_UINT16(p); p += 2;
+ if (len > sz) {
+ len = sz;
+ }
+ memset(dst, b, len);
+ dst += len;
+ sz -= len;
+ }
+}
+
+void IgorEngine::loadRoomData(int pal, int img, int box, int msk, int txt) {
+ if (pal != 0) {
+ loadData(pal, _paletteBuffer);
+ }
+ if (img != 0) {
+ loadData(img, _screenLayer1);
+ }
+ if (box != 0) {
+ int sz;
+ uint8 *p = loadData(box, 0, &sz);
+ memset(_roomObjectAreasTable, 0, sizeof(_roomObjectAreasTable));
+ assert((sz % 5) == 0);
+ decodeRoomAreas(p, sz / 5);
+ free(p);
+ }
+ if (msk != 0) {
+ uint8 *p = loadData(msk);
+ decodeRoomMask(p);
+ free(p);
+ }
+ if (txt != 0) {
+ uint8 *p = loadData(txt);
+ decodeRoomText(p);
+ free(p);
+ }
+}
+
+void IgorEngine::loadAnimData(const int *anm, int loadOffset) {
+ if (loadOffset == 0) {
+ memset(_animFramesBuffer, 0, 65535);
+ }
+ while (*anm) {
+ int dataSize;
+ loadData(*anm++, &_animFramesBuffer[loadOffset], &dataSize);
+ loadOffset += dataSize;
+ }
+}
+
+void IgorEngine::loadActionData(int act) {
+ if (act != 0) {
+ assert(findData(act)->size <= 0x2000);
+ loadData(act, _roomActionsTable);
+ }
+}
+
+void IgorEngine::loadDialogueData(int dlg) {
+ uint8 *p = loadData(dlg);
+ int dialogueDataSize = _roomDataOffsets.dlg.questionsOffset + 164 + 41;
+ assert(dialogueDataSize <= 500);
+ memcpy(_gameState.dialogueData, p, dialogueDataSize);
+ assert(_roomDataOffsets.dlg.questionsSize <= MAX_DIALOGUE_QUESTIONS);
+ for (int i = 0; i < _roomDataOffsets.dlg.questionsSize; ++i) {
+ for (int n = 0; n < 2; ++n) {
+ const uint8 *src = p + _roomDataOffsets.dlg.questionsOffset + (i + 1) * 164 + _language * 82 + (n + 1) * 41;
+ int len = *src++;
+ if (len != 0) {
+ decodeRoomString(src, _dialogueQuestions[i][n], len);
+ _dialogueQuestions[i][n][len] = '\0';
+ debug(kDebugResource, "loadDialogueData() _dialogueQuestions[%d][%d] '%s'", i, n, _dialogueQuestions[i][n]);
+ }
+ }
+ }
+ assert(_roomDataOffsets.dlg.repliesSize <= MAX_DIALOGUE_REPLIES);
+ for (int i = 0; i < _roomDataOffsets.dlg.repliesSize; ++i) {
+ const uint8 *src = p + _roomDataOffsets.dlg.repliesOffset + (i + 1) * 102 + _language * 51;
+ int len = *src++;
+ if (len != 0) {
+ decodeRoomString(src, _dialogueReplies[i], len);
+ _dialogueReplies[i][len] = '\0';
+ debug(kDebugResource, "loadDialogueData() _dialogueReplies[%d] '%s'", i, _dialogueReplies[i]);
+ }
+ }
+ free(p);
+}
+
+static void decodeMainString(const uint8 *src, char *dst) {
+ int sz = *src - 0x6D;
+ if (sz != 0) {
+ ++src;
+ for (int i = 0; i < sz; ++i) {
+ uint8 code = src[i] - 0x6D;
+ dst[i] = (char)code;
+ }
+ }
+ dst[sz] = '\0';
+}
+
+void IgorEngine::loadMainTexts() {
+ loadData(IMG_VerbsPanel, _verbsPanelBuffer);
+ int dataSize;
+ uint8 *p = loadData(TXT_MainTable, 0, &dataSize);
+ const uint8 *src = &p[0] + _language * 7;
+ for (int i = 0; i < 3; ++i, src += 7 * 2) {
+ decodeMainString(src, _verbPrepositions[i]);
+ debug(kDebugResource, "loadMainTexts() _verbPrepositions[%d] '%s'", i, _verbPrepositions[i]);
+ }
+ src = &p[0x2A] + _language * 31;
+ for (int i = 0; i < 35; ++i, src += 31 * 2) {
+ decodeMainString(src, _globalObjectNames[i]);
+ debug(kDebugResource, "loadMainTexts() _globalObjectNames[%d] '%s'", i, _globalObjectNames[i]);
+ }
+ src = &p[0x8BA] + _language * 51;
+ for (int i = 0; i < 250; ++i, src += 51 * 2) {
+ decodeMainString(src, _globalDialogueTexts[i]);
+ debug(kDebugResource, "loadMainTexts() _globalDialogueTexts[%d] '%s'", i, _globalDialogueTexts[i]);
+ }
+ src = &p[0x6CA4] + _language * 12;
+ for (int i = 0; i < 9; ++i, src += 12 * 2) {
+ decodeMainString(src, _verbsName[i]);
+ debug(kDebugResource, "loadMainTexts() _verbsName[%d] '%s'", i, _verbsName[i]);
+ }
+ free(p);
+}
+
+void IgorEngine::setupDefaultPalette() {
+ memset(_currentPalette, 0, 255 * 3);
+ memset(&_currentPalette[255 * 3], 63, 3);
+ updatePalette(768);
+}
+
+void IgorEngine::updatePalette(int count) {
+ assert(count <= 768);
+ uint8 pal[1024];
+ for (int j = 0, i = 0; i < count; ++i) {
+ pal[j++] = (_currentPalette[i] << 2) | (_currentPalette[i] >> 4);
+ if (((i + 1) % 3) == 0) {
+ pal[j++] = 0;
+ }
+ }
+ _system->setPalette(pal, 0, count / 3);
+}
+
+void IgorEngine::clearPalette() {
+ memset(_currentPalette, 0, 768);
+ updatePalette(768);
+}
+
+void IgorEngine::setPaletteColor(uint8 index, uint8 r, uint8 g, uint8 b) {
+ uint8 pal[4];
+ pal[0] = (r << 2) | (r >> 4);
+ pal[1] = (g << 2) | (g >> 4);
+ pal[2] = (b << 2) | (b >> 4);
+ pal[3] = 0;
+ _system->setPalette(pal, index, 1);
+}
+
+void IgorEngine::setPaletteRange(int startColor, int endColor) {
+ debug(kDebugScreen, "setPaletteRange(%d, %d)", startColor, endColor);
+ assert(endColor - startColor + 1 <= 256);
+ for (int i = startColor; i <= endColor; ++i) {
+ setPaletteColor(i, _currentPalette[3 * i], _currentPalette[3 * i + 1], _currentPalette[3 * i + 2]);
+ }
+}
+
+void IgorEngine::fadeInPalette(int count) {
+ debug(kDebugScreen, "fadeInPalette(%d)", count);
+ _system->copyRectToScreen(_screenVGA, 320, 0, _screenVGAVOffset, 320, 200 - _screenVGAVOffset);
+ int m = 66;
+ do {
+ m -= 3;
+ for (int i = 0; i < count; ++i) {
+ if (_paletteBuffer[i] >= m) {
+ uint8 color = _currentPalette[i] + 3;
+ if (color > _paletteBuffer[i]) {
+ color = _paletteBuffer[i];
+ }
+ _currentPalette[i] = color;
+ }
+ }
+ updatePalette(count);
+ _system->updateScreen();
+ _system->delayMillis(1000 / 60);
+ } while (m > 0);
+}
+
+void IgorEngine::fadeOutPalette(int count) {
+ debug(kDebugScreen, "fadeOutPalette(%d)", count);
+ _system->copyRectToScreen(_screenVGA, 320, 0, _screenVGAVOffset, 320, 200 - _screenVGAVOffset);
+ memcpy(_paletteBuffer, _currentPalette, 768);
+ int m = 0;
+ do {
+ for (int i = 0; i < count; ++i) {
+ if (_paletteBuffer[i] >= m) {
+ uint8 color = _currentPalette[i];
+ if (color >= 3) {
+ color -= 3;
+ } else {
+ color = 0;
+ }
+ _currentPalette[i] = color;
+ }
+ }
+ updatePalette(count);
+ _system->updateScreen();
+ _system->delayMillis(1000 / 60);
+ m += 3;
+ } while (m < 66);
+}
+
+void IgorEngine::scrollPalette(int startColor, int endColor) {
+ debug(kDebugScreen, "scrollPalette(%d, %d)", startColor, endColor);
+ uint8 c[3];
+ memcpy(c, &_currentPalette[startColor * 3], 3);
+ memmove(&_currentPalette[startColor * 3], &_currentPalette[(startColor + 1) * 3], (endColor - startColor) * 3);
+ memcpy(&_currentPalette[endColor * 3], c, 3);
+}
+
+void IgorEngine::drawString(uint8 *dst, const char *s, int x, int y, int color1, int color2, int color3) {
+ int dx = 0;
+ while (*s) {
+ if (*s == ' ') {
+ dx += 5;
+ } else {
+ const int chr = _fontCharIndex[(uint8)*s];
+ const int chrWidth = _fontCharWidth[chr];
+ if (x + chrWidth > 320) {
+ break;
+ }
+ for (int j = 0; j < 11; ++j) {
+ uint8 *p = dst + (j + y) * 320 + x + dx;
+ for (int i = 0; i < 9; ++i) {
+ uint8 code = _fontData[(chr * 11 + j) * 9 + i];
+ if (code == 1) {
+ p[i] = color1;
+ } else if (code == 2 && color2 != -1) {
+ p[i] = color2;
+ } else if (code == 3 && color3 != -1) {
+ p[i] = color3;
+ }
+ }
+ }
+ dx += chrWidth;
+ }
+ ++s;
+ }
+}
+
+int IgorEngine::getStringWidth(const char *s) const {
+ int w = 0;
+ while (*s) {
+ if (*s == ' ') {
+ w += 5;
+ } else {
+ w += _fontCharWidth[_fontCharIndex[(uint8)*s]];
+ }
+ ++s;
+ }
+ return w;
+}
+
+void IgorEngine::drawActionSentence(const char *sentence, uint8 color) {
+ memset(_screenVGA + 144 * 320, 0, 11 * 320);
+ int w = getStringWidth(sentence);
+ int x = (320 - w) / 2;
+ drawString(_screenVGA, sentence, x, 144, color, 0, 0);
+}
+
+void IgorEngine::formatActionSentence(uint8 color) {
+ char actionSentence[512];
+ if (_currentAction.verb == kVerbWalk && _inputVars[kInputCursorYPos] > 143) {
+ _currentAction.object1Num = 0;
+ }
+ strcpy(actionSentence, _verbsName[_currentAction.verb]);
+ if (_currentAction.object1Num != 0) {
+ if (_currentAction.object1Type == kObjectTypeInventory) {
+ strcat(actionSentence, _globalObjectNames[_currentAction.object1Num]);
+ } else {
+ strcat(actionSentence, _roomObjectNames[_currentAction.object1Num]);
+ }
+ if (_currentAction.verbType != 0) {
+ strcat(actionSentence, _verbPrepositions[_currentAction.verbType]);
+ if (_currentAction.object2Num != 0) {
+ if (_currentAction.object2Type == kObjectTypeInventory) {
+ strcat(actionSentence, _globalObjectNames[_currentAction.object2Num]);
+ } else {
+ strcat(actionSentence, _roomObjectNames[_currentAction.object2Num]);
+ }
+ }
+ }
+ }
+ drawActionSentence(actionSentence, _sentenceColorIndex[color]);
+}
+
+const uint8 *IgorEngine::getAnimFrame(int baseOffset, int tableOffset, int frame) {
+ const uint8 *src = _animFramesBuffer + baseOffset;
+ assert(frame >= 1);
+ int frameOffset = READ_LE_UINT16(src + tableOffset + (frame - 1) * 2);
+ return src + frameOffset - 1;
+}
+
+void IgorEngine::decodeAnimFrame(const uint8 *src, uint8 *dst, bool preserveText) {
+ int y = READ_LE_UINT16(src) * 320; src += 2;
+ int h = READ_LE_UINT16(src); src += 2;
+ while (h--) {
+ int w = *src++;
+ int pos = y;
+ while (w--) {
+ pos += *src++;
+ int len = *src++;
+ if (len & 0x80) {
+ uint8 color = *src++;
+ len = 256 - len;
+ if (preserveText) {
+ for (int i = pos; i < pos + len; ++i) {
+ if (dst[i] != kTalkColor && dst[i] != kTalkShadowColor) {
+ dst[i] = color;
+ }
+ }
+ } else {
+ memset(dst + pos, color, len);
+ }
+ pos += len;
+ } else {
+ if (preserveText) {
+ for (int i = pos; i < pos + len; ++i) {
+ if (dst[i] != kTalkColor && dst[i] != kTalkShadowColor) {
+ dst[i] = src[i - pos];
+ }
+ }
+ } else {
+ memcpy(dst + pos, src, len);
+ }
+ src += len;
+ pos += len;
+ }
+ }
+ y += 320;
+ }
+}
+
+void IgorEngine::copyAnimFrame(int srcOffset, int frame, int frameSize, int w, int h, int dstOffset) {
+ for (int y = 0; y <= h; ++y) {
+ memcpy(_screenLayer1 + y * 320 + dstOffset, _animFramesBuffer + frame * frameSize + y * w + srcOffset, w);
+ }
+}
+
+void IgorEngine::setCursor(int num) {
+ uint8 cursor[11 * 11];
+ memset(cursor, 0, 11 * 11);
+ const uint8 *mask = &_mouseCursorMask[num * 24];
+ for (int i = 0; i < 24; ++i) {
+ if (mask[i]) {
+ const int offset = ((int8)_mouseCursorData[i + 24] + 5) * 11 + ((int8)_mouseCursorData[i] + 5);
+ cursor[offset] = 255;
+ }
+ }
+ CursorMan.replaceCursor(cursor, 11, 11, 5, 5, 0);
+}
+
+void IgorEngine::showCursor() {
+ debug(kDebugEngine, "showCursor()");
+ _roomCursorOn = true;
+ CursorMan.showMouse(_roomCursorOn);
+}
+
+void IgorEngine::hideCursor() {
+ debug(kDebugEngine, "hideCursor()");
+ _roomCursorOn = false;
+ CursorMan.showMouse(_roomCursorOn);
+}
+
+void IgorEngine::updateRoomLight(int fl) {
+ WalkData *wd = &_walkData[_walkDataLastIndex - 1];
+ if (wd->scaleHeight != 50 || _gameState.dialogueTextRunning) {
+ return;
+ }
+ int offset = 320 * (wd->y + 1 - wd->scaleWidth);
+ int x = wd->x - _walkWidthScaleTable[wd->scaleHeight - 1] / 2;
+ if (x <= 0) {
+ return;
+ }
+ offset += x;
+ int color = (fl == 0) ? 196 : 195;
+ switch (wd->posNum) {
+ case 2: {
+ RoomObjectArea *roa = &_roomObjectAreasTable[_screenLayer2[offset + 1298]];
+ if (wd->y > roa->y1Lum) {
+ if (wd->y <= roa->y2Lum && _gameState.enableLight == 1) {
+ color -= roa->deltaLum;
+ }
+ _screenVGA[offset + 1298] = color;
+ }
+ }
+ break;
+ case 3: {
+ RoomObjectArea *roa = &_roomObjectAreasTable[_screenLayer2[offset + 1293]];
+ if (wd->y > roa->y1Lum) {
+ if (wd->y <= roa->y2Lum && _gameState.enableLight == 1) {
+ color -= roa->deltaLum;
+ }
+ _screenVGA[offset + 1293] = color;
+ }
+ color = (fl == 0) ? 196 : 195;
+ roa = &_roomObjectAreasTable[_screenLayer2[offset + 1296]];
+ if (wd->y > roa->y1Lum) {
+ if (wd->y <= roa->y2Lum && _gameState.enableLight == 1) {
+ color -= roa->deltaLum;
+ }
+ _screenVGA[offset + 1296] = color;
+ }
+ }
+ break;
+ case 4: {
+ RoomObjectArea *roa = &_roomObjectAreasTable[_screenLayer2[offset + 1291]];
+ if (wd->y > roa->y1Lum) {
+ if (wd->y <= roa->y2Lum && _gameState.enableLight == 1) {
+ color -= roa->deltaLum;
+ }
+ _screenVGA[offset + 1291] = color;
+ }
+ }
+ break;
+ }
+}
+
+void IgorEngine::drawVerbsPanel() {
+ memcpy(_screenVGA + 320 * 156, _verbsPanelBuffer, 320 * 12);
+}
+
+void IgorEngine::redrawVerb(uint8 verb, bool highlight) {
+ uint8 verbBitmap[44 * 12];
+ if (verb >= 2 && verb <= 8) {
+ verb -= 2;
+ for (int i = 0; i <= 11; ++i) {
+ for (int j = 0; j <= 43; ++j) {
+ uint8 color = _verbsPanelBuffer[i * 320 + verb * 46 + j];
+ if (highlight && color != 0) {
+ color += 8;
+ }
+ verbBitmap[i * 44 + j] = color;
+ }
+ }
+ for (int i = 0; i <= 11; ++i) {
+ memcpy(_screenVGA + 320 * 156 + verb * 46 + i * 320, verbBitmap + i * 44, 44);
+ }
+ }
+}
+
+void IgorEngine::drawInventory(int start, int mode) {
+ loadData(IMG_InventoryPanel, _inventoryPanelBuffer);
+ loadData(IMG_Objects, _inventoryImagesBuffer);
+ int end = start + 6;
+ if (start <= end) {
+ int x = 1;
+ for (int y = start; y != end; ++y) {
+ if (_inventoryInfo[y - 1] == 0) {
+ for (int i = 1; i <= 30; ++i) {
+ memset(_inventoryPanelBuffer + x * 40 - 20 + (i - 1) * 320, 0, 40);
+ }
+ } else {
+ for (int i = 1; i <= 30; ++i) {
+ int img = _inventoryInfo[y - 1];
+ assert(img >= 1);
+ memcpy(_inventoryPanelBuffer + x * 40 - 20 + i * 320 - 321, _inventoryImagesBuffer + (i - 1) * 40 + (_inventoryImages[img - 1] - 1) * 1200, 40);
+ }
+ }
+ ++x;
+ }
+ }
+ if (_inventoryInfo[72] == 1) {
+ // 'hide' scroll up
+ for (int y = 5; y <= 11; ++y) {
+ for (int x = 4; x <= 12; ++x) {
+ uint8 *p = _inventoryPanelBuffer + y * 320 + x - 321;
+ if (*p == 0xF2) {
+ *p = 0xF3;
+ p = _inventoryPanelBuffer + y * 320 + x + 305 - 321;
+ *p = 0xF3;
+ }
+ }
+ }
+ }
+ if (_inventoryInfo[73] <= _inventoryInfo[72] + 6 || _inventoryInfo[72] >= _inventoryInfo[73] - 6) {
+ // 'hide' scroll down
+ for (int y = 19; y <= 25; ++y) {
+ for (int x = 4; x <= 12; ++x) {
+ uint8 *p = _inventoryPanelBuffer + y * 320 + x - 321;
+ if (*p == 0xF2) {
+ *p = 0xF3;
+ p = _inventoryPanelBuffer + y * 320 + x + 305 - 321;
+ *p = 0xF3;
+ }
+ }
+ }
+ }
+ switch (mode) {
+ case 0:
+ memcpy(_screenVGA + 54400, _inventoryPanelBuffer, 9600);
+ _scrollInventory = false;
+ break;
+ case 1:
+ for (int y = 0; y <= 11; ++y) {
+ for (int x = 0; x <= 14; ++x) {
+ uint8 *p = _screenVGA + x + y * 320 + 59520;
+ if ((*p & 0x80) != 0) {
+ *p += 8;
+ p = _screenVGA + x + y * 320 + 59825;
+ *p += 8;
+ }
+ }
+ }
+ memmove(_inventoryPanelBuffer + 9600, _inventoryPanelBuffer, 9600);
+ memcpy(_inventoryPanelBuffer, _screenVGA + 54400, 9600);
+ _scrollInventoryStartY = 7;
+ _scrollInventoryEndY = 31;
+ _scrollInventoryDy = 6;
+ _scrollInventory = true;
+ break;
+ case 2:
+ for (int y = 0; y <= 11; ++y) {
+ for (int x = 0; x <= 14; ++x) {
+ uint8 *p = _screenVGA + x + y * 320 + 55040;
+ if ((*p & 0x80) != 0) {
+ *p += 8;
+ p = _screenVGA + x + y * 320 + 55345;
+ *p += 8;
+ }
+ }
+ }
+ memmove(_inventoryPanelBuffer + 9600, _inventoryPanelBuffer, 9600);
+ memcpy(_inventoryPanelBuffer + 9600, _screenVGA + 54400, 9600);
+ _scrollInventoryStartY = 25;
+ _scrollInventoryEndY = 1;
+ _scrollInventoryDy = -6;
+ _scrollInventory = true;
+ break;
+ }
+}
+
+void IgorEngine::packInventory() {
+ for (int i = 1; i <= _inventoryInfo[73]; ++i) {
+ if (_inventoryImages[i - 1] != 0) {
+ continue;
+ }
+ int count = _inventoryInfo[73] - 1;
+ for (int index = i; index <= count; ++index) {
+ _inventoryImages[index - 1] = _inventoryImages[index];
+ _inventoryImages[_inventoryImages[index - 1] - 1] = index;
+ }
+ _inventoryImages[_inventoryInfo[73] - 1] = 0;
+ --_inventoryInfo[73];
+ }
+}
+
+void IgorEngine::scrollInventory() {
+ if (_scrollInventoryStartY == _scrollInventoryEndY) {
+ memcpy(_screenVGA + 54400, _inventoryPanelBuffer + (_scrollInventoryStartY - 1) * 320, 9600);
+ _scrollInventory = false;
+ } else {
+ _gameState.counter[2] = 54420;
+ for (_gameState.counter[1] = _scrollInventoryStartY; _gameState.counter[1] < _scrollInventoryStartY + 29; ++_gameState.counter[1]) {
+ memcpy(_screenVGA + _gameState.counter[2], _inventoryPanelBuffer + 320 * _gameState.counter[1] - 300, 280);
+ _gameState.counter[2] += 320;
+ }
+ _scrollInventoryStartY += _scrollInventoryDy;
+ }
+}
+
+void IgorEngine::addObjectToInventory(int object, int index) {
+ ++_inventoryInfo[73];
+ _inventoryInfo[_inventoryInfo[73] - 1] = object;
+ _inventoryInfo[index] = _inventoryInfo[73];
+ _inventoryInfo[72] = _inventoryOffsetTable[(_inventoryInfo[73] - 1) / 7];
+ drawInventory(_inventoryInfo[72], 0);
+ playSound(51, 1);
+}
+
+void IgorEngine::removeObjectFromInventory(int index) {
+ _inventoryInfo[_inventoryInfo[index] - 1] = 0;
+ _inventoryInfo[index] = 0;
+ packInventory();
+ if (_inventoryInfo[72] > _inventoryInfo[73]) {
+ _inventoryInfo[72] = _inventoryOffsetTable[(_inventoryInfo[73] - 1) / 7];
+ }
+ drawInventory(_inventoryInfo[72], 0);
+ playSound(63, 1);
+}
+
+void IgorEngine::executeAction(int action) {
+ debug(kDebugEngine, "executeAction %d", action);
+ assert(action < 200);
+ if (action <= 100) {
+ (this->*_executeMainAction)(action);
+ } else {
+ (this->*_executeRoomAction)(action);
+ }
+}
+
+void IgorEngine::clearAction() {
+ redrawVerb(_currentAction.verb, false);
+ memset(&_currentAction, 0, sizeof(_currentAction));
+ _currentAction.verb = kVerbWalk;
+ _actionCode = 0;
+ _actionWalkPoint = 0;
+}
+
+void IgorEngine::handleRoomInput() {
+ if (_inputVars[kInputPause]) {
+ _inputVars[kInputPause] = 0;
+ handlePause();
+ }
+ if (_inputVars[kInputOptions]) {
+ _inputVars[kInputOptions] = 0;
+ handleOptionsMenu();
+ }
+ if (_inputVars[kInputSkipDialogue] && _gameState.dialogueTextRunning) {
+ _talkDelayCounter = _talkDelay;
+ if (_gameState.talkMode != kTalkModeTextOnly && _talkSpeechCounter > 2) {
+ stopSound();
+ _talkSpeechCounter = -1;
+ }
+ _inputVars[kInputSkipDialogue] = 0;
+ }
+ if (!_roomCursorOn || _gameState.dialogueTextRunning || _scrollInventory) {
+ return;
+ }
+ if (_inputVars[kInputCursorYPos] >= 156 && _inputVars[kInputCursorYPos] <= 167) {
+ if (_inputVars[kInputClick]) {
+ int verb = _verbAreasTable[_inputVars[kInputCursorXPos]];
+ if (verb != _currentAction.verb) {
+ redrawVerb(_currentAction.verb, false);
+ _currentAction.verb = verb;
+ redrawVerb(_currentAction.verb, true);
+ }
+ // reset action command
+ memset(&_currentAction, 0, sizeof(_currentAction));
+ _currentAction.verb = verb;
+ _currentAction.verbType = 0;
+ formatActionSentence(0);
+ _inputVars[kInputClick] = 0;
+ }
+ return;
+ }
+ if (_inputVars[kInputCursorYPos] >= 172 && _inputVars[kInputCursorYPos] <= 183 && (_inputVars[kInputCursorXPos] < 15 || _inputVars[kInputCursorXPos] > 304)) {
+ if (_inputVars[kInputClick]) {
+ if (_inventoryInfo[72] > 1) {
+ _inventoryInfo[72] -= 7;
+ drawInventory(_inventoryInfo[72], 2);
+ }
+ _inputVars[kInputClick] = 0;
+ }
+ return;
+ }
+ if (_inputVars[kInputCursorYPos] >= 186 && _inputVars[kInputCursorYPos] <= 197 && (_inputVars[kInputCursorXPos] < 15 || _inputVars[kInputCursorXPos] > 304)) {
+ if (_inputVars[kInputClick]) {
+ if (_inventoryInfo[73] > _inventoryInfo[72] + 6) {
+ _inventoryInfo[72] += 7;
+ drawInventory(_inventoryInfo[72], 1);
+ }
+ _inputVars[kInputClick] = 0;
+ }
+ return;
+ }
+
+/* if (_inputVars[kInputClick]) {
+ if (_gameState.igorMoving) {
+ _walkDataCurrentPosX = _walkData[_walkDataCurrentIndex - 1].x;
+ _walkDataCurrentPosY = _walkData[_walkDataCurrentIndex - 1].y;
+ if (_roomObjectAreasTable[_screenLayer2[_walkDataCurrentPosY * 320 + _walkDataCurrentPosX].area == 0) {
+ return;
+ }
+ _walkDataCurrentPosX = _walkData[_walkDataCurrentIndex + 1].x;
+ _walkDataCurrentPosY = _walkData[_walkDataCurrentIndex + 1].y;
+ if (_roomObjectAreasTable[_screenLayer2[_walkDataCurrentPosY * 320 + _walkDataCurrentPosX].area == 0) {
+ return;
+ }
+ }
+ _inputVars[kInputClick] = 0;
+ }*/
+
+ bool actionHovering = !_inputVars[kInputClick];
+ _inputVars[kInputClick] = 0;
+
+ if (actionHovering && _actionCode != 0) {
+ return;
+ }
+
+ Action previousAction = _currentAction;
+ if (_inputVars[kInputCursorYPos] >= 170 && _inputVars[kInputCursorYPos] <= 199) {
+ int object = getObjectFromInventory(_inputVars[kInputCursorXPos]);
+ if (_currentAction.verbType == 0) {
+ _currentAction.object1Num = object;
+ _currentAction.object1Type = kObjectTypeInventory;
+ if (_currentAction.verb == kVerbUse && _roomActionsTable[_roomDataOffsets.action.useVerb + 10 + _currentAction.object1Num] != 0) {
+ formatActionSentence(0);
+ if (!actionHovering) {
+ _currentAction.verbType = 1;
+ }
+ return;
+ }
+ if (_currentAction.verb == kVerbGive && _roomActionsTable[_roomDataOffsets.action.giveVerb + 10 + _currentAction.object1Num] != 0) {
+ formatActionSentence(0);
+ if (!actionHovering) {
+ _currentAction.verbType = 2;
+ }
+ return;
+ }
+ } else {
+ _currentAction.object2Num = object;
+ _currentAction.object2Type = kObjectTypeInventory;
+ }
+ } else if (_inputVars[kInputCursorYPos] < 144) {
+ int area = _screenLayer2[_inputVars[kInputCursorYPos] * 320 + _inputVars[kInputCursorXPos]];
+ int object = _roomObjectAreasTable[area].object;
+ if (_currentAction.verbType == 0) {
+ _currentAction.object1Num = object;
+ _currentAction.object1Type = kObjectTypeRoom;
+ if (_currentAction.verb == kVerbUse && _roomActionsTable[_roomDataOffsets.action.useVerb + 48 + _currentAction.object1Num] != 0) {
+ formatActionSentence(0);
+ if (!actionHovering) {
+ _currentAction.verbType = 1;
+ }
+ return;
+ }
+ if (_currentAction.verb == kVerbGive && _roomActionsTable[_roomDataOffsets.action.giveVerb + 48 + _currentAction.object1Num] != 0) {
+ formatActionSentence(0);
+ if (!actionHovering) {
+ _currentAction.verbType = 2;
+ }
+ return;
+ }
+ } else {
+ _currentAction.object2Num = object;
+ _currentAction.object2Type = kObjectTypeRoom;
+ }
+ } else {
+ return;
+ }
+
+ if (_currentAction.verbType == 0) {
+ if (_currentAction.object1Type == kObjectTypeInventory) {
+ _actionCode = _inventoryActionsTable[(_currentAction.verb - 1) * 2 + _currentAction.object1Num * 20];
+ } else {
+ _actionCode = _roomActionsTable[_roomDataOffsets.action.defaultVerb + _currentAction.verb * 2 + _currentAction.object1Num * 20];
+ }
+ }
+ if (_currentAction.verbType == 1) {
+ int offset = _roomActionsTable[_roomDataOffsets.action.object2 + _currentAction.object2Num + _currentAction.object2Type * 38] * 2;
+ offset += _roomActionsTable[_roomDataOffsets.action.object1 + _currentAction.object1Num + _currentAction.object1Type * 38] * _roomDataOffsets.action.objectSize;
+ _actionCode = _roomActionsTable[_roomDataOffsets.action.useVerb + offset];
+ }
+ if (_currentAction.verbType == 2) {
+ int offset = _roomActionsTable[_roomDataOffsets.action.object2 + _currentAction.object2Num + _currentAction.object2Type * 38] * 2;
+ offset += _roomActionsTable[_roomDataOffsets.action.object1 + _currentAction.object1Num + _currentAction.object1Type * 38] * _roomDataOffsets.action.objectSize;
+ _actionCode = _roomActionsTable[_roomDataOffsets.action.giveVerb + offset];
+ }
+
+ if (actionHovering) {
+ formatActionSentence(0);
+ _currentAction.object2Num = 0;
+ _actionCode = 0;
+ return;
+ }
+ debug(kDebugEngine, "handleRoomInput() actionCode %d", _actionCode);
+ if (_actionCode == 0) {
+ clearAction();
+ return;
+ }
+
+ formatActionSentence(1);
+ if (_currentAction.verbType == 0) {
+ if (_currentAction.object1Type == kObjectTypeRoom) {
+ _actionWalkPoint = _roomActionsTable[_roomDataOffsets.action.defaultVerb + _currentAction.verb * 2 + _currentAction.object1Num * 20 + 1];
+ if (_actionWalkPoint > 0) {
+ if (_currentAction.object1Num == 0) {
+ // no object selected, just walk
+ _walkToObjectPosX = _inputVars[kInputCursorXPos];
+ _walkToObjectPosY = _inputVars[kInputCursorYPos];
+ if (_roomObjectAreasTable[_screenLayer2[_walkToObjectPosY * 320 + _walkToObjectPosX]].area == 0) {
+ fixWalkPosition(&_walkToObjectPosX, &_walkToObjectPosY);
+ }
+ } else {
+ // walk to object
+ int offset = READ_LE_UINT16(_roomActionsTable + _roomDataOffsets.obj.walkPoints + _currentAction.object1Num * 2);
+ _walkToObjectPosX = offset % 320;
+ _walkToObjectPosY = offset / 320;
+ debug(kDebugEngine, "handleRoomInput() walkToObject offset %d (0x%X)", offset, _roomDataOffsets.obj.walkPoints);
+ }
+ if (_gameState.igorMoving) {
+ // stop igor at the current position
+ _walkDataLastIndex = _walkDataCurrentIndex - 1;
+ _walkDataCurrentPosX = _walkData[_walkDataLastIndex].x;
+ _walkDataCurrentPosY = _walkData[_walkDataLastIndex].y;
+ _walkCurrentFrame = _walkData[_walkDataLastIndex].frameNum;
+ _walkCurrentPos = _walkData[_walkDataLastIndex].posNum;
+ WalkData::setNextFrame(_walkCurrentPos, _walkCurrentFrame);
+ } else {
+ --_walkDataLastIndex;
+ _walkDataCurrentPosX = _walkData[_walkDataLastIndex].x;
+ _walkDataCurrentPosY = _walkData[_walkDataLastIndex].y;
+ _walkCurrentPos = _walkData[_walkDataLastIndex].posNum;
+ _walkCurrentFrame = 1;
+ }
+ if (_walkDataCurrentPosX != _walkToObjectPosX || _walkDataCurrentPosY != _walkToObjectPosY) {
+ if (_roomDataOffsets.area.boxSize == 0) {
+ buildWalkPathSimple(_walkDataCurrentPosX, _walkDataCurrentPosY, _walkToObjectPosX, _walkToObjectPosY);
+ } else {
+ buildWalkPath(_walkDataCurrentPosX, _walkDataCurrentPosY, _walkToObjectPosX, _walkToObjectPosY);
+ }
+ if (_actionWalkPoint != 3) {
+ _walkCurrentFrame = 0;
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ }
+ if (_actionWalkPoint == 1) {
+ _walkCurrentPos = _roomActionsTable[_roomDataOffsets.obj.walkFacingPosition + _currentAction.object1Num];
+ _walkData[_walkDataLastIndex].posNum = _walkCurrentPos;
+ }
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ }
+ return;
+ }
+ }
+ hideCursor();
+ executeAction(_actionCode);
+ if (!_gameState.dialogueTextRunning) {
+ showCursor();
+ }
+ clearAction();
+ return;
+ }
+}
+
+void IgorEngine::animateIgorTalking(int frame) {
+ if (_currentPart == 850) {
+ PART_85_HELPER_6(frame);
+ return;
+ }
+ WalkData *wd = &_walkData[_walkDataLastIndex - 1];
+ int y = (wd->y - wd->scaleWidth + 1) * 320;
+ int delta = wd->x - _walkWidthScaleTable[wd->scaleHeight - 1] / 2;
+ if (delta > 0) {
+ y += delta;
+ }
+ for (int yOffset = 0; yOffset < wd->scaleWidth; y += 320, ++yOffset) {
+ int index = READ_LE_UINT16(_walkScaleTable + 0x6CE + wd->scaleHeight * 2) + yOffset;
+ uint8 yScale = _walkScaleTable[index];
+ if (yScale >= 11) {
+ continue;
+ }
+ for (int x = 0, xOffset = wd->clipSkipX - 1; x < wd->clipWidth; ++x, ++xOffset) {
+ index = READ_LE_UINT16(_walkScaleTable + 0x734 + _walkWidthScaleTable[wd->scaleHeight - 1] * 2) + xOffset;
+ uint8 xScale = _walkScaleTable[0x4FC + index];
+ if (xScale < 8 || xScale > 21) {
+ continue;
+ }
+ uint8 screenColor = _screenVGA[y + x];
+ if (screenColor < kTalkColor || screenColor > kTalkShadowColor) {
+ int offset = yScale * 14 + frame * 154 + (wd->posNum - 1) * 924 + (xScale - 8);
+ uint8 srcColor = _igorHeadFrames[offset];
+ if (srcColor == 0) {
+ _screenVGA[y + x] = _screenLayer1[y + x];
+ continue;
+ }
+ RoomObjectArea *roa = &_roomObjectAreasTable[_screenLayer2[y + x]];
+ if (wd->y <= roa->y1Lum) {
+ _screenVGA[y + x] = _screenLayer1[y + x];
+ continue;
+ }
+ if (wd->y <= roa->y2Lum && _gameState.enableLight == 1) {
+ srcColor -= roa->deltaLum;
+ }
+ _screenVGA[y + x] = srcColor;
+ }
+ }
+ }
+}
+
+void IgorEngine::handleRoomDialogue() {
+ if (_gameState.dialogueTextRunning) {
+ if (_talkDelayCounter == _talkDelay) {
+ animateIgorTalking(0);
+ memcpy(_screenVGA + _dialogueDirtyRectY, _screenTextLayer + 23040, _dialogueDirtyRectSize);
+ if (_dialogueTextsCount == 0) {
+ _gameState.dialogueTextRunning = false;
+ showCursor();
+ } else {
+ ++_dialogueTextsStart;
+ startIgorDialogue();
+ }
+ } else {
+ animateIgorTalking(getRandomNumber(6));
+ ++_talkDelayCounter;
+ }
+ }
+}
+
+void IgorEngine::handleRoomIgorWalk() {
+ if (_walkDataCurrentIndex > _walkDataLastIndex) {
+ _gameState.igorMoving = false;
+ _walkDataLastIndex = _walkDataCurrentIndex;
+ if (_actionCode > 0) {
+ hideCursor();
+ executeAction(_actionCode);
+ if (!_gameState.dialogueTextRunning) {
+ showCursor();
+ }
+ clearAction();
+ }
+ }
+ if (_gameState.igorMoving) {
+ moveIgor(_walkData[_walkDataCurrentIndex].posNum, _walkData[_walkDataCurrentIndex].frameNum);
+ ++_walkDataCurrentIndex;
+ }
+}
+
+void IgorEngine::handleRoomInventoryScroll() {
+ if (_scrollInventory) {
+ scrollInventory();
+ }
+}
+
+void IgorEngine::handleRoomLight() {
+ if (_gameState.dialogueTextRunning || _gameState.igorMoving) {
+ _gameState.updateLight = false;
+ } else if (_gameState.updateLight) {
+ updateRoomLight(0);
+ _gameState.updateLight = 0;
+ } else if (getRandomNumber(10) == 0) {
+ updateRoomLight(1);
+ _gameState.updateLight = true;
+ }
+}
+
+int IgorEngine::lookupScale(int xOffset, int yOffset, int h) const {
+ int index = READ_LE_UINT16(_walkScaleTable + 0x734 + _walkWidthScaleTable[h - 1] * 2);
+ int offset = _walkScaleTable[0x4FC + index + xOffset];
+ index = READ_LE_UINT16(_walkScaleTable + 0x6CE + h * 2);
+ offset += _walkScaleTable[index + yOffset] * 30;
+ return offset;
+}
+
+void IgorEngine::moveIgorHelper1(int pos, int frame) {
+ debug(kDebugWalk, "moveIgorHelper1 _walkDataCurrentIndex %d pos %d frame %d", _walkDataCurrentIndex, pos, frame);
+ uint8 _walkClipSkipX = _walkData[_walkDataCurrentIndex].clipSkipX;
+ uint8 _walkHeightScale = _walkData[_walkDataCurrentIndex].scaleHeight;
+ int16 _walkClipWidth = _walkData[_walkDataCurrentIndex].clipWidth;
+ uint16 _walkScaleWidth = _walkData[_walkDataCurrentIndex].scaleWidth;
+ uint8 _walkXPosChanged = _walkData[_walkDataCurrentIndex].xPosChanged;
+ int16 _walkDxPos = _walkData[_walkDataCurrentIndex].dxPos + 1;
+ uint8 _walkYPosChanged = _walkData[_walkDataCurrentIndex].yPosChanged;
+ int16 _walkDyPos = _walkData[_walkDataCurrentIndex].dyPos;
+ int16 _walkDataCurrentPosX2 = _walkData[_walkDataCurrentIndex].x;
+ int16 _walkDataCurrentPosY2 = _walkData[_walkDataCurrentIndex].y;
+
+ uint16 _walkDataDrawOffset = (_walkData[_walkDataCurrentIndex].y - _walkData[_walkDataCurrentIndex].scaleWidth + 1) * 320;
+
+ int xPos = _walkWidthScaleTable[_walkData[_walkDataCurrentIndex].scaleHeight - 1] / 2;
+ if (_walkData[_walkDataCurrentIndex].x > xPos) {
+ _walkDataDrawOffset += _walkData[_walkDataCurrentIndex].x - xPos;
+ }
+ if (_walkXPosChanged != 0) {
+ _walkDataDrawOffset -= _walkDxPos;
+ }
+ if (_walkYPosChanged != 0) {
+ _walkDataDrawOffset -= _walkDyPos * 320;
+ }
+ if (_gameState.enableLight == 2) {
+ int8 colorLum = _roomObjectAreasTable[_screenLayer2[_walkDataCurrentPosY2 * 320 + _walkDataCurrentPosX2]].y2Lum;
+ if (_gameState.colorLum != colorLum) {
+ for (int color = 192 * 3; color <= 207 * 3; ++color) {
+ int c = _currentPalette[color] + colorLum;
+ if (c < 1) {
+ c = 0;
+ } else if (c > 62) {
+ c = 63;
+ }
+ _currentPalette[color] = c;
+ }
+ setPaletteRange(192, 207);
+ _gameState.colorLum = colorLum;
+ }
+ }
+ uint16 screenIgorDrawOffset = _walkDataDrawOffset;
+ uint16 igorScaledWidth = _walkDxPos + _walkClipWidth;
+ uint16 igorScaledHeight = _walkHeightScale + _walkDyPos;
+ uint16 igorBodyScanLine = 0;
+ if (_walkYPosChanged != 0) {
+ for (int i = 1; i <= _walkDyPos; ++i) {
+ memcpy(_igorTempFrames + igorBodyScanLine * 50, _screenLayer1 + _walkDataDrawOffset, igorScaledWidth);
+ _walkDataDrawOffset += 320;
+ ++igorBodyScanLine;
+ }
+ }
+ if (_walkXPosChanged != 0) {
+ for (int yOffset = 0; yOffset < _walkScaleWidth; ++yOffset) {
+ assert(_walkDxPos > 0);
+ assert(igorBodyScanLine * 50 + _walkDxPos <= 3000);
+ memcpy(_igorTempFrames + igorBodyScanLine * 50, _screenLayer1 + _walkDataDrawOffset, _walkDxPos);
+ int xOffset = _walkClipSkipX - 1;
+ for (int i = 0; i < _walkClipWidth; ++i) {
+/* int index = READ_LE_UINT16(_walkScaleTable + 0x734 + _walkWidthScaleTable[_walkHeightScale - 1] * 2);
+ int offset = _walkScaleTable[0x4FC + index + xOffset];
+ index = READ_LE_UINT16(_walkScaleTable + 0x6CE + _walkHeightScale * 2);
+ offset += _walkScaleTable[index + yOffset] * 30;*/
+ int offset = lookupScale(xOffset, yOffset, _walkHeightScale);
+ offset += frame * 1500;
+ uint8 color = _facingIgorFrames[pos - 1][offset];
+ if (color != 0) {
+ assert(_walkDataDrawOffset + _walkDxPos + i >= 0);
+ int index = _screenLayer2[_walkDataDrawOffset + _walkDxPos + i];
+ int yPos = _roomObjectAreasTable[index].y1Lum;
+ if (_walkData[_walkDataCurrentIndex].y <= yPos) {
+ _igorTempFrames[igorBodyScanLine * 50 + i + _walkDxPos] = _screenLayer1[_walkDataDrawOffset + _walkDxPos + i];
+ } else {
+ if (_gameState.enableLight == 1 && _walkData[_walkDataCurrentIndex].y <= _roomObjectAreasTable[index].y2Lum) {
+ color -= _roomObjectAreasTable[index].deltaLum;
+ }
+ _igorTempFrames[igorBodyScanLine * 50 + i + _walkDxPos] = color;
+ }
+ } else {
+ _igorTempFrames[igorBodyScanLine * 50 + i + _walkDxPos] = _screenLayer1[_walkDataDrawOffset + _walkDxPos + i];
+ }
+ ++xOffset;
+ }
+ _walkDataDrawOffset += 320;
+ ++igorBodyScanLine;
+ }
+ } else {
+ for (int yOffset = 0; yOffset < _walkScaleWidth; ++yOffset) {
+ int xOffset = _walkClipSkipX - 1;
+ for (int i = 0; i < _walkClipWidth; ++i) {
+/* int index = READ_LE_UINT16(_walkScaleTable + 0x734 + _walkWidthScaleTable[_walkHeightScale - 1] * 2);
+ int offset = _walkScaleTable[0x4FC + index + xOffset];
+ index = READ_LE_UINT16(_walkScaleTable + 0x6CE + _walkHeightScale * 2);
+ offset += _walkScaleTable[index + yOffset] * 30;*/
+ int offset = lookupScale(xOffset, yOffset, _walkHeightScale);
+ offset += frame * 1500;
+ uint8 color = _facingIgorFrames[pos - 1][offset];
+ if (color != 0) {
+ assert(_walkDataDrawOffset + i >= 0);
+ int index = _screenLayer2[_walkDataDrawOffset + i];
+ int yPos = _roomObjectAreasTable[index].y1Lum;
+ if (_walkData[_walkDataCurrentIndex].y <= yPos) {
+ _igorTempFrames[igorBodyScanLine * 50 + i] = _screenLayer1[_walkDataDrawOffset + i];
+ } else {
+ if (_gameState.enableLight == 1 && _walkData[_walkDataCurrentIndex].y <= _roomObjectAreasTable[index].y2Lum) {
+ color -= _roomObjectAreasTable[index].deltaLum;
+ }
+ _igorTempFrames[igorBodyScanLine * 50 + i] = color;
+ }
+ } else {
+ _igorTempFrames[igorBodyScanLine * 50 + i] = _screenLayer1[_walkDataDrawOffset + i];
+ }
+ ++xOffset;
+ }
+ const uint8 *src = _screenLayer1 + _walkDataDrawOffset + _walkClipWidth;
+ memcpy(_igorTempFrames + igorBodyScanLine * 50 + _walkClipWidth, src, _walkDxPos);
+ _walkDataDrawOffset += 320;
+ ++igorBodyScanLine;
+ }
+ }
+ if (_walkYPosChanged == 0) {
+ for (int i = 1; i <= _walkDyPos; ++i) {
+ memcpy(_igorTempFrames + igorBodyScanLine * 50, _screenLayer1 + _walkDataDrawOffset, igorScaledWidth);
+ _walkDataDrawOffset += 320;
+ ++igorBodyScanLine;
+ }
+ }
+ for (igorBodyScanLine = 0; igorBodyScanLine < igorScaledHeight; ++igorBodyScanLine) {
+ assert(screenIgorDrawOffset + igorScaledWidth <= 320 * 200);
+ memcpy(_screenVGA + screenIgorDrawOffset, _igorTempFrames + igorBodyScanLine * 50, igorScaledWidth);
+ screenIgorDrawOffset += 320;
+ }
+}
+
+void IgorEngine::moveIgor(int pos, int frame) {
+ assert(_gameState.enableLight == 1 || _gameState.enableLight == 2);
+ moveIgorHelper1(pos, frame);
+}
+
+void IgorEngine::buildWalkPathSimple(int srcX, int srcY, int dstX, int dstY) {
+ debug(kDebugWalk, "IgorEngine::buildWalkPathSimple(%d, %d, %d, %d)", srcX, srcY, dstX, dstY);
+ if (srcX != dstX || srcY != dstY) {
+ _walkData[0] = _walkData[_walkDataLastIndex];
+ _walkDataLastIndex = 1;
+ buildWalkPathArea(srcX, srcY, dstX, dstY);
+ --_walkDataLastIndex;
+ }
+}
+
+void IgorEngine::getClosestAreaTrianglePoint(int dstArea, int srcArea, int *dstY, int *dstX, int srcY, int srcX) {
+ int minSqrDist = -1;
+ assert(dstArea >= 1 && srcArea >= 1);
+ const uint8 *p = _roomActionsTable + ((dstArea - 1) + (srcArea - 1) * _roomDataOffsets.area.boxSize) * 6;
+ for (int i = 0; i < 3; ++i) {
+ const uint16 offset = READ_LE_UINT16(p + i * 2);
+ const int yPos = offset / 320;
+ const int xPos = offset % 320;
+ int y = srcY - yPos;
+ int x = srcX - xPos;
+ int sqrDist = y * y + x * x;
+ if (minSqrDist == -1 || sqrDist < minSqrDist) {
+ *dstY = yPos;
+ *dstX = xPos;
+ minSqrDist = sqrDist;
+ }
+ }
+ debug(kDebugWalk, "getClosestAreaTrianglePoint() sqrDist %d pos %d,%d", minSqrDist, *dstX, *dstY);
+}
+
+void IgorEngine::getClosestAreaTrianglePoint2(int dstArea, int srcArea, int *dstY, int *dstX, int srcY1, int srcX1, int srcY2, int srcX2) {
+ int minSqrDist = -1;
+ assert(dstArea >= 1 && srcArea >= 1);
+ const uint8 *p = _roomActionsTable + ((dstArea - 1) + (srcArea - 1) * _roomDataOffsets.area.boxSize) * 6;
+ for (int i = 0; i < 3; ++i) {
+ const uint16 offset = READ_LE_UINT16(p + i * 2);
+ const int yPos = offset / 320;
+ const int xPos = offset % 320;
+ int y1 = srcY1 - yPos;
+ int x1 = srcX1 - xPos;
+ int y2 = srcY2 - yPos;
+ int x2 = srcX2 - xPos;
+ int sqrDist = y1 * y1 + x1 * x1 + y2 * y2 + x2 * x2;
+ if (minSqrDist == -1 || sqrDist < minSqrDist) {
+ *dstY = yPos;
+ *dstX = xPos;
+ minSqrDist = sqrDist;
+ }
+ }
+ debug(kDebugWalk, "getClosestAreaTrianglePoint2() sqrDist %d pos %d,%d", minSqrDist, *dstX, *dstY);
+}
+
+void IgorEngine::buildWalkPath(int srcX, int srcY, int dstX, int dstY) {
+ if (srcX != dstX || srcY != dstY) {
+ _walkData[0] = _walkData[_walkDataLastIndex];
+ _walkDataLastIndex = 1;
+ int srcArea = _roomObjectAreasTable[_screenLayer2[srcY * 320 + srcX]].area;
+ int dstArea = _roomObjectAreasTable[_screenLayer2[dstY * 320 + dstX]].area;
+ debug(kDebugWalk, "srcArea = %d dstArea = %d", srcArea, dstArea);
+ int currentArea = srcArea;
+ for (int i = 1; dstArea != currentArea; ++i) {
+ const int boxOffset = srcArea * _roomDataOffsets.area.boxSrcSize + dstArea * _roomDataOffsets.area.boxDstSize;
+ int nextArea = _roomActionsTable[boxOffset + i + _roomDataOffsets.area.box];
+ debug(kDebugWalk, "nextArea %d (%d,%d,%d)", nextArea, _roomDataOffsets.area.box, _roomDataOffsets.area.boxSrcSize, _roomDataOffsets.area.boxDstSize);
+ int nextPosX, nextPosY;
+ if (dstArea != nextArea) {
+ getClosestAreaTrianglePoint(nextArea, currentArea, &nextPosY, &nextPosX, srcY, srcX);
+ } else {
+ getClosestAreaTrianglePoint2(nextArea, currentArea, &nextPosY, &nextPosX, dstY, dstX, srcY, srcX);
+ }
+ debug(kDebugWalk, "buildWalkPath() transitionArea = %d next %d,%d pos %d,%d offset 0x%X", nextArea, nextPosX, nextPosY, dstX, dstY, _roomDataOffsets.area.box);
+ buildWalkPathArea(srcX, srcY, nextPosX, nextPosY);
+ srcX = nextPosX;
+ srcY = nextPosY;
+ currentArea = nextArea;
+ }
+ buildWalkPathArea(srcX, srcY, dstX, dstY);
+ --_walkDataLastIndex;
+ }
+ debug(kDebugWalk, "buildWalkPath() end _walkDataLastIndex %d", _walkDataLastIndex);
+}
+
+void IgorEngine::buildWalkPathArea(int srcX, int srcY, int dstX, int dstY) {
+ if (srcX != dstX || srcY != dstY) {
+ const int dx = dstX - srcX;
+ const int dy = dstY - srcY;
+ debug(kDebugWalk, "buildWalkPathArea() dx = %d dy = %d src %d,%d dst %d,%d", dx, dy, srcX, srcY, dstX, dstY);
+ assert(_walkDataLastIndex > 0);
+ if (ABS(dy) * 2 > ABS(dx)) {
+ if (srcY > dstY) {
+ buildWalkPathAreaUpDirection(srcX, srcY, dstX, dstY);
+ } else {
+ buildWalkPathAreaDownDirection(srcX, srcY, dstX, dstY);
+ }
+ } else {
+ if (srcX < dstX) {
+ buildWalkPathAreaRightDirection(srcX, srcY, dstX, dstY);
+ } else {
+ buildWalkPathAreaLeftDirection(srcX, srcY, dstX, dstY);
+ }
+ }
+ }
+}
+
+static int16 roundReal(float f) {
+ return (int16)(f + .5);
+}
+
+static int16 truncReal(float f) {
+ return (int16)f;
+}
+
+int IgorEngine::getVerticalStepsCount(int minX, int minY, int maxX, int maxY) {
+ debug(kDebugWalk, "getVerticalStepsCount() %d %d %d %d", minX, minY, maxX, maxY);
+ int curX = 2;
+ if ((_walkXScaleRoom[minX] != 1 || _walkXScaleRoom[maxX] != 3) && (_walkXScaleRoom[maxX] != 1 || _walkXScaleRoom[minX] != 3)) {
+ curX = _walkXScaleRoom[minX];
+ }
+ int curY = minY;
+ int count = 0;
+ while (1) {
+ uint8 scale = _walkYScaleRoom[(_walkXScaleRoom[curX] - 1) * 144 + curY];
+ scale = _walkScaleTable[0x901 + scale];
+ if (maxY - curY <= scale) {
+ break;
+ }
+ curY += scale;
+ ++count;
+ }
+ return count;
+}
+
+int IgorEngine::getHorizontalStepsCount(int minX, int minY, int maxX, int maxY) {
+ uint8 scale, frame = _walkCurrentFrame;
+
+ scale = _walkYScaleRoom[(_walkXScaleRoom[maxX] - 1) * 144 + maxY];
+ float r1 = _walkScaleSpeedTable[scale - 1];
+ scale = _walkYScaleRoom[(_walkXScaleRoom[minX] - 1) * 144 + minY];
+ float r2 = _walkScaleSpeedTable[scale - 1];
+ debug(kDebugWalk, "getHorizontalStepsCount() maxX - minX = %d r1 = %f r2 = %f", maxX - minX, r1, r2);
+
+ int16 steps = roundReal((maxX - minX) / ((r1 + r2) / 2.));
+ int count = 0;
+ if (steps != 0) {
+ float r3 = (maxY - minY) / (float)steps;
+ int curX = minX;
+ int curY = minY;
+ float r4 = r3;
+ while (1) {
+ scale = _walkYScaleRoom[(_walkXScaleRoom[curX] - 1) * 144 + curY];
+ uint8 c = _walkScaleTable[0x769 + scale * 8 + frame];
+ if (maxX - curX <= c) {
+ break;
+ }
+ curX += c;
+ curY = minY + truncReal(r4);
+ if (frame == 8) {
+ frame = 1;
+ } else {
+ ++frame;
+ }
+ r4 += r3;
+ ++count;
+ }
+ }
+ return count;
+}
+
+void IgorEngine::lookupScale(int curX, int curY, uint8 &scale, uint8 &xScale, uint8 &yScale) const {
+ scale = _walkYScaleRoom[(_walkXScaleRoom[curX] - 1) * 144 + curY];
+ yScale = _walkScaleTable[0x901 + scale];
+ xScale = _walkWidthScaleTable[scale - 1];
+}
+
+void IgorEngine::buildWalkPathAreaUpDirection(int srcX, int srcY, int dstX, int dstY) {
+ int _walkCurrentPosLocalVar = _walkCurrentPos;
+ if (_walkCurrentPos == 3) {
+ _walkCurrentPos = 1;
+ _walkData[_walkDataLastIndex] = _walkData[_walkDataLastIndex - 1];
+ _walkData[_walkDataLastIndex].posNum = (dstX > srcX) ? kFacingPositionRight : kFacingPositionLeft;
+ _walkData[_walkDataLastIndex].frameNum = 5;
+ ++_walkDataLastIndex;
+ } else {
+ _walkCurrentPos = 1;
+ }
+ if (_walkCurrentFrame > 6) {
+ _walkCurrentFrame -= 6;
+ }
+ WalkData *wd;
+ uint8 scale, xScale, yScale;
+ float vStepDist, vStepCur;
+ int curX = srcX;
+ int curY = srcY;
+ if (srcX > dstX) {
+ int vStepsCount = getVerticalStepsCount(dstX, dstY, srcX, srcY);
+ if (vStepsCount > 0) {
+ vStepCur = vStepDist = (srcX - dstX) / (float)vStepsCount;
+ for (int i = 1; i <= vStepsCount; ++i) {
+ wd = &_walkData[_walkDataLastIndex];
+ curX = srcX - truncReal(vStepCur);
+ lookupScale(curX, curY, scale, xScale, yScale);
+ curY -= yScale;
+ lookupScale(curX, curY, scale, xScale, yScale);
+ wd->setPos(curX, curY, 1, _walkCurrentFrame);
+ WalkData::setNextFrame(kFacingPositionBack, _walkCurrentFrame);
+ wd->setScale(scale, scale);
+ wd->yPosChanged = 0;
+ wd->dyPos = _walkData[_walkDataLastIndex - 1].y - wd->y;
+ int x = xScale - xScale / 2 + curX - 1;
+ if (x > 319) {
+ wd->clipSkipX = 1;
+ wd->clipWidth = 319 - (x - xScale);
+ wd->xPosChanged = 0;
+ wd->dxPos = 0;
+ } else {
+ x = curX - xScale / 2;
+ if (x < 0) {
+ wd->clipWidth = x + xScale;
+ wd->clipSkipX = xScale - wd->clipWidth + 1;
+ wd->xPosChanged = 0;
+ wd->dxPos = _walkData[_walkDataLastIndex - 1].x - wd->x;
+ } else {
+ wd->clipWidth = xScale;
+ wd->clipSkipX = 1;
+ wd->xPosChanged = 0;
+ wd->dxPos = _walkData[_walkDataLastIndex - 1].x - wd->x;
+ }
+ }
+ ++_walkDataLastIndex;
+ vStepCur += vStepDist;
+ }
+ } else {
+ if (_walkCurrentPosLocalVar == 1 && _walkToObjectPosX == dstX && _walkToObjectPosY == dstY) {
+ _walkData[_walkDataLastIndex] = _walkData[_walkDataLastIndex - 1];
+ _walkData[_walkDataLastIndex].posNum = 1;
+ _walkData[_walkDataLastIndex].frameNum = 1;
+ ++_walkDataLastIndex;
+ }
+ }
+ lookupScale(dstX, dstY, scale, xScale, yScale);
+ wd = &_walkData[_walkDataLastIndex];
+ wd->setPos(dstX, dstY, 1, _walkCurrentFrame);
+ WalkData::setNextFrame(kFacingPositionBack, _walkCurrentFrame);
+ wd->setScale(scale, scale);
+ wd->yPosChanged = 0;
+ wd->dyPos = _walkData[_walkDataLastIndex - 1].y - wd->y;
+ int x = xScale - xScale / 2 + dstX - 1;
+ if (x > 319) {
+ wd->clipSkipX = 1;
+ wd->clipWidth = 319 - (x - xScale / 2);
+ wd->xPosChanged = 0;
+ wd->dxPos = 0;
+ } else {
+ x = dstX - xScale / 2;
+ if (x < 0) {
+ wd->clipWidth = xScale + x;
+ wd->clipSkipX = xScale - wd->clipWidth + 1;
+ wd->xPosChanged = 0;
+ wd->dxPos = curX - dstX;
+ } else {
+ wd->clipWidth = xScale;
+ wd->clipSkipX = 1;
+ wd->xPosChanged = 0;
+ wd->dxPos = curX - dstX;
+ }
+ }
+ ++_walkDataLastIndex;
+ } else {
+ int vStepsCount = getVerticalStepsCount(dstX, dstY, srcX, srcY);
+ if (vStepsCount > 0) {
+ vStepCur = vStepDist = (dstX - srcX) / (float)vStepsCount;
+ for (int i = 1; i <= vStepsCount; ++i) {
+ wd = &_walkData[_walkDataLastIndex];
+ curX = srcX + truncReal(vStepCur);
+ lookupScale(curX, curY, scale, xScale, yScale);
+ curY -= yScale;
+ lookupScale(curX, curY, scale, xScale, yScale);
+ wd->setPos(curX, curY, 1, _walkCurrentFrame);
+ WalkData::setNextFrame(kFacingPositionBack, _walkCurrentFrame);
+ lookupScale(curX, curY, scale, xScale, yScale);
+ wd->setScale(scale, scale);
+ wd->yPosChanged = 0;
+ wd->dyPos = _walkData[_walkDataLastIndex - 1].y - wd->y;
+ int x = xScale - xScale / 2 + curX - 1;
+ if (x > 319) {
+ wd->clipSkipX = 1;
+ wd->clipWidth = 319 - (x - xScale);
+ wd->xPosChanged = 0;
+ wd->dxPos = wd->x - _walkData[_walkDataLastIndex - 1].x;
+ } else {
+ x = curX - xScale / 2;
+ if (x < 0) {
+ wd->clipWidth = x + xScale;
+ wd->clipSkipX = xScale - wd->clipWidth + 1;
+ wd->xPosChanged = 1;
+ wd->dxPos = 0;
+ } else {
+ wd->clipWidth = xScale;
+ wd->clipSkipX = 1;
+ wd->xPosChanged = 1;
+ wd->dxPos = wd->x - _walkData[_walkDataLastIndex - 1].x;
+ }
+ }
+ ++_walkDataLastIndex;
+ vStepCur += vStepDist;
+ }
+ } else {
+ if (_walkCurrentPosLocalVar == 1 && _walkToObjectPosX == dstX && _walkToObjectPosY == dstY) {
+ _walkData[_walkDataLastIndex] = _walkData[_walkDataLastIndex - 1];
+ _walkData[_walkDataLastIndex].posNum = 1;
+ _walkData[_walkDataLastIndex].frameNum = 1;
+ ++_walkDataLastIndex;
+ }
+ }
+ lookupScale(dstX, dstY, scale, xScale, yScale);
+ wd = &_walkData[_walkDataLastIndex];
+ wd->setPos(dstX, dstY, 1, _walkCurrentFrame);
+ WalkData::setNextFrame(kFacingPositionBack, _walkCurrentFrame);
+ wd->setScale(scale, scale);
+ wd->yPosChanged = 0;
+ wd->dyPos = _walkData[_walkDataLastIndex - 1].y - wd->y;
+ int x = xScale - xScale / 2 + dstX - 1;
+ if (x > 319) {
+ wd->clipSkipX = 1;
+ int16 _dx = x - xScale;
+ int16 _cx = 319 - _dx;
+ wd->clipWidth = _cx;
+ wd->xPosChanged = 0;
+ wd->dxPos = dstX - curX;
+ } else {
+ x = dstX - xScale / 2;
+ if (x < 0) {
+ wd->clipWidth = xScale + x;
+ wd->clipSkipX = xScale - wd->clipWidth + 1;
+ wd->xPosChanged = 1;
+ wd->dxPos = 0;
+ } else {
+ wd->clipWidth = xScale;
+ wd->clipSkipX = 1;
+ wd->xPosChanged = 1;
+ wd->dxPos = dstX - curX;
+ }
+ }
+ ++_walkDataLastIndex;
+ }
+}
+
+void IgorEngine::buildWalkPathAreaDownDirection(int srcX, int srcY, int dstX, int dstY) {
+ int _walkCurrentPosLocalVar = _walkCurrentPos;
+ if (_walkCurrentPos == 1) {
+ _walkCurrentPos = 3;
+ _walkData[_walkDataLastIndex] = _walkData[_walkDataLastIndex - 1];
+ _walkData[_walkDataLastIndex].posNum = (srcX > dstX) ? kFacingPositionLeft : kFacingPositionRight;
+ _walkData[_walkDataLastIndex].frameNum = 1;
+ ++_walkDataLastIndex;
+ } else {
+ _walkCurrentPos = 3;
+ }
+ if (_walkCurrentFrame > 6) {
+ _walkCurrentFrame -= 6;
+ }
+ WalkData *wd;
+ uint8 scale, xScale, yScale;
+ float vStepCur, vStepDist;
+ int curX = srcX;
+ int curY = srcY;
+ if (srcX > dstX) {
+ int vStepsCount = getVerticalStepsCount(srcX, srcY, dstX, dstY);
+ if (vStepsCount > 0) {
+ vStepCur = vStepDist = (srcX - dstX) / (float)vStepsCount;
+ for (int i = 1; i <= vStepsCount; ++i) {
+ wd = &_walkData[_walkDataLastIndex];
+ curX = srcX - truncReal(vStepCur);
+ lookupScale(curX, curY, scale, xScale, yScale);
+ curY += yScale;
+ lookupScale(curX, curY, scale, xScale, yScale);
+ wd->setPos(curX, curY, 3, _walkCurrentFrame);
+ WalkData::setNextFrame(kFacingPositionFront, _walkCurrentFrame);
+ wd->setScale(scale, scale);
+ wd->yPosChanged = 1;
+ wd->dyPos = wd->y - _walkData[_walkDataLastIndex - 1].y;
+ int x = xScale - xScale / 2 + curX - 1;
+ if (x > 319) {
+ wd->clipSkipX = 1;
+ wd->clipWidth = 319 - (x - xScale);
+ wd->xPosChanged = 0;
+ wd->dxPos = 0;
+ } else {
+ x = curX - xScale / 2;
+ if (x < 0) {
+ wd->clipWidth = x + xScale;
+ wd->clipSkipX = xScale - wd->clipWidth + 1;
+ wd->xPosChanged = 0;
+ wd->dxPos = _walkData[_walkDataLastIndex - 1].x - wd->x;
+ } else {
+ wd->clipWidth = xScale;
+ wd->clipSkipX = 1;
+ wd->xPosChanged = 0;
+ wd->dxPos = _walkData[_walkDataLastIndex - 1].x - wd->x;
+ }
+ }
+ ++_walkDataLastIndex;
+ vStepCur += vStepDist;
+ }
+ } else {
+ if (_walkCurrentPosLocalVar == 3 && _walkToObjectPosX == dstX && _walkToObjectPosY == dstY) {
+ _walkData[_walkDataLastIndex] = _walkData[_walkDataLastIndex - 1];
+ _walkData[_walkDataLastIndex].posNum = 3;
+ _walkData[_walkDataLastIndex].frameNum = 1;
+ ++_walkDataLastIndex;
+ }
+ }
+ lookupScale(dstX, dstY, scale, xScale, yScale);
+ wd = &_walkData[_walkDataLastIndex];
+ wd->setPos(dstX, dstY, 3, _walkCurrentFrame);
+ WalkData::setNextFrame(kFacingPositionFront, _walkCurrentFrame);
+ wd->setScale(scale, scale);
+ wd->yPosChanged = 1;
+ wd->dyPos = wd->y - _walkData[_walkDataLastIndex - 1].y;
+ int x = xScale - xScale / 2 + dstX - 1;
+ if (x > 319) {
+ wd->clipSkipX = 1;
+ wd->clipWidth = 319 - (x - xScale);
+ wd->xPosChanged = 0;
+ wd->dxPos = 0;
+ } else {
+ x = dstX - xScale / 2;
+ if (x < 0) {
+ wd->clipWidth = xScale + x;
+ wd->clipSkipX = xScale - wd->clipWidth + 1;
+ wd->xPosChanged = 0;
+ wd->dxPos = curX - dstX;
+ } else {
+ wd->clipWidth = xScale;
+ wd->clipSkipX = 1;
+ wd->xPosChanged = 0;
+ wd->dxPos = curX - dstX;
+ }
+ }
+ ++_walkDataLastIndex;
+ } else {
+ int vStepsCount = getVerticalStepsCount(srcX, srcY, dstX, dstY);
+ if (vStepsCount > 0) {
+ vStepCur = vStepDist = (dstX - srcX) / (float)vStepsCount;
+ for (int i = 1; i <= vStepsCount; ++i) {
+ wd = &_walkData[_walkDataLastIndex];
+ curX = srcX + truncReal(vStepCur);
+ lookupScale(curX, curY, scale, xScale, yScale);
+ curY += yScale;
+ lookupScale(curX, curY, scale, xScale, yScale);
+ wd->setPos(curX, curY, 3, _walkCurrentFrame);
+ WalkData::setNextFrame(kFacingPositionFront, _walkCurrentFrame);
+ wd->setScale(scale, scale);
+ wd->yPosChanged = 1;
+ wd->dyPos = wd->y - _walkData[_walkDataLastIndex - 1].y;
+ int x = xScale - xScale / 2 + curX - 1;
+ if (x > 319) {
+ wd->clipSkipX = 1;
+ wd->clipWidth = 319 - (x - xScale);
+ wd->xPosChanged = 1;
+ wd->dxPos = wd->x - _walkData[_walkDataLastIndex - 1].x;
+ } else {
+ x = curX - xScale / 2;
+ if (x < 0) {
+ wd->clipWidth = x + xScale;
+ wd->clipSkipX = xScale - wd->clipWidth + 1;
+ wd->xPosChanged = 1;
+ wd->dxPos = 0;
+ } else {
+ wd->clipWidth = xScale;
+ wd->clipSkipX = 1;
+ wd->xPosChanged = 1;
+ wd->dxPos = wd->x - _walkData[_walkDataLastIndex - 1].x;
+ }
+ }
+ ++_walkDataLastIndex;
+ vStepCur += vStepDist;
+ }
+ } else {
+ if (_walkCurrentPosLocalVar == 3 && _walkToObjectPosX == dstX && _walkToObjectPosY == dstY) {
+ _walkData[_walkDataLastIndex] = _walkData[_walkDataLastIndex - 1];
+ _walkData[_walkDataLastIndex].posNum = 3;
+ _walkData[_walkDataLastIndex].frameNum = 1;
+ ++_walkDataLastIndex;
+ }
+ }
+ lookupScale(dstX, dstY, scale, xScale, yScale);
+ wd = &_walkData[_walkDataLastIndex];
+ wd->setPos(dstX, dstY, 3, _walkCurrentFrame);
+ WalkData::setNextFrame(kFacingPositionFront, _walkCurrentFrame);
+ wd->setScale(scale, scale);
+ wd->yPosChanged = 1;
+ wd->dyPos = wd->y - _walkData[_walkDataLastIndex - 1].y;
+ int x = xScale - xScale / 2 + dstX - 1;
+ if (x > 319) {
+ wd->clipSkipX = 1;
+ wd->clipWidth = 319 - (x - xScale);
+ wd->xPosChanged = 1;
+ wd->dxPos = dstX - curX;
+ } else {
+ x = dstX - xScale / 2;
+ if (x < 0) {
+ wd->clipWidth = xScale + x;
+ wd->clipSkipX = xScale - wd->clipWidth + 1;
+ wd->xPosChanged = 1;
+ wd->dxPos = 0;
+ } else {
+ wd->clipWidth = xScale;
+ wd->clipSkipX = 1;
+ wd->xPosChanged = 1;
+ wd->dxPos = dstX - curX;
+ }
+ }
+ ++_walkDataLastIndex;
+ }
+}
+
+void IgorEngine::buildWalkPathAreaRightDirection(int srcX, int srcY, int dstX, int dstY) {
+ int _walkCurrentPosLocalVar = _walkCurrentPos;
+ if (_walkCurrentPos == kFacingPositionLeft) {
+ _walkCurrentPos = kFacingPositionRight;
+ _walkData[_walkDataLastIndex] = _walkData[_walkDataLastIndex - 1];
+ _walkData[_walkDataLastIndex].posNum = (srcY > dstY) ? kFacingPositionBack : kFacingPositionFront;
+ _walkData[_walkDataLastIndex].frameNum = 5;
+ ++_walkDataLastIndex;
+ } else {
+ _walkCurrentPos = kFacingPositionRight;
+ }
+ WalkData *wd;
+ uint8 scale, xScale, xSkip;
+ float hStepCur, hStepDist;
+ int curX = srcX;
+ int curY = srcY;
+ if (srcY > dstY) {
+ int hStepsCount = getHorizontalStepsCount(srcX, dstY, dstX, srcY);
+ if (hStepsCount > 0) {
+ hStepCur = hStepDist = (srcY - dstY) / (float)hStepsCount;
+ for (int i = 1; i <= hStepsCount; ++i) {
+ wd = &_walkData[_walkDataLastIndex];
+ scale = _walkYScaleRoom[(_walkXScaleRoom[curX] - 1) * 144 + curY];
+ xSkip = _walkScaleTable[0x769 + scale * 8 + _walkCurrentFrame];
+ if ((curX + xSkip) >= dstX) {
+ break;
+ }
+ curX += xSkip;
+ curY = srcY - truncReal(hStepCur);
+ wd->setPos(curX, curY, 2, _walkCurrentFrame);
+ scale = _walkYScaleRoom[(_walkXScaleRoom[curX] - 1) * 144 + curY];
+ xScale = _walkWidthScaleTable[scale - 1];
+ wd->setScale(scale, scale);
+ wd->yPosChanged = 0;
+ wd->dyPos = _walkData[_walkDataLastIndex - 1].y - wd->y;
+ int x = xScale - xScale / 2 + curX - 1;
+ if (x > 319) {
+ wd->clipSkipX = 1;
+ wd->clipWidth = 319 - (x - xScale);
+ wd->xPosChanged = 1;
+ wd->dxPos = xSkip;
+ } else {
+ x = x - xScale / 2;
+ if (x < 0) {
+ wd->clipWidth = x + xScale;
+ wd->clipSkipX = xScale - wd->clipWidth + 1;
+ wd->xPosChanged = 1;
+ wd->dxPos = 0;
+ } else {
+ wd->clipWidth = xScale;
+ wd->clipSkipX = 1;
+ wd->xPosChanged = 1;
+ wd->dxPos = xSkip;
+ }
+ }
+ ++_walkDataLastIndex;
+ hStepCur += hStepDist;
+ WalkData::setNextFrame(kFacingPositionRight, _walkCurrentFrame);
+ }
+ } else {
+ if (_walkCurrentPosLocalVar == 2 && _walkToObjectPosX == dstX && _walkToObjectPosY == dstY) {
+ _walkData[_walkDataLastIndex] = _walkData[_walkDataLastIndex - 1];
+ _walkData[_walkDataLastIndex].posNum = 2;
+ _walkData[_walkDataLastIndex].frameNum = 1;
+ ++_walkDataLastIndex;
+ }
+ }
+ wd = &_walkData[_walkDataLastIndex];
+ wd->setPos(dstX, dstY, 2, _walkCurrentFrame);
+ scale = _walkYScaleRoom[(_walkXScaleRoom[dstX] - 1) * 144 + dstY];
+ xScale = _walkWidthScaleTable[scale - 1];
+ wd->setScale(scale, scale);
+ wd->yPosChanged = 0;
+ wd->dyPos = _walkData[_walkDataLastIndex - 1].y - wd->y;
+ int x = xScale - xScale / 2 - 1;
+ if (x > 319) {
+ wd->clipSkipX = 1;
+ wd->clipWidth = 319 - (x - xScale);
+ wd->xPosChanged = 1;
+ wd->dxPos = dstX - curX;
+ } else {
+ x = dstX - xScale / 2;
+ if (x < 0) {
+ wd->clipWidth = xScale + x;
+ wd->clipSkipX = xScale - wd->clipWidth + 1;
+ wd->xPosChanged = 1;
+ wd->dxPos = 0;
+ } else {
+ wd->clipWidth = xScale;
+ wd->clipSkipX = 1;
+ wd->xPosChanged = 1;
+ wd->dxPos = dstX - curX;
+ }
+ }
+ ++_walkDataLastIndex;
+ WalkData::setNextFrame(kFacingPositionLeft, _walkCurrentFrame);
+ } else {
+ int hStepsCount = getHorizontalStepsCount(srcX, srcY, dstX, dstY);
+ if (hStepsCount > 0) {
+ hStepCur = hStepDist = (dstY - srcY) / (float)hStepsCount;
+ for (int i = 1; i <= hStepsCount; ++i) {
+ wd = &_walkData[_walkDataLastIndex];
+ scale = _walkYScaleRoom[(_walkXScaleRoom[curX] - 1) * 144 + curY];
+ xSkip = _walkScaleTable[0x769 + scale * 8 + _walkCurrentFrame];
+ if (curX + xSkip >= dstX) {
+ break;
+ }
+ curX += xSkip;
+ curY = srcY + truncReal(hStepCur);
+ _walkData[_walkDataLastIndex].setPos(curX, curY, 2, _walkCurrentFrame);
+ scale = _walkYScaleRoom[(_walkXScaleRoom[curX] - 1) * 144 + curY];
+ xScale = _walkWidthScaleTable[scale - 1];
+ wd->setScale(scale, scale);
+ wd->yPosChanged = 1;
+ wd->dyPos = wd->y - _walkData[_walkDataLastIndex - 1].y;
+ int x = xScale - xScale / 2 + curX - 1;
+ if (x > 319) {
+ wd->clipSkipX = 1;
+ wd->clipWidth = 319 - (x - xScale);
+ wd->xPosChanged = 1;
+ wd->dxPos = xSkip;
+ } else {
+ x = curX - xScale / 2;
+ if (x < 0) {
+ wd->clipWidth = x + xScale;
+ wd->clipSkipX = xScale - wd->clipWidth + 1;
+ wd->xPosChanged = 1;
+ wd->dxPos = 0;
+ } else {
+ wd->clipWidth = xScale;
+ wd->clipSkipX = 1;
+ wd->xPosChanged = 1;
+ wd->dxPos = xSkip;
+ }
+ }
+ ++_walkDataLastIndex;
+ hStepCur += hStepDist;
+ WalkData::setNextFrame(kFacingPositionRight, _walkCurrentFrame);
+ }
+ } else {
+ if (_walkCurrentPosLocalVar == 2 && _walkToObjectPosX == dstX && _walkToObjectPosY == dstY) {
+ _walkData[_walkDataLastIndex] = _walkData[_walkDataLastIndex - 1];
+ _walkData[_walkDataLastIndex].posNum = 2;
+ _walkData[_walkDataLastIndex].frameNum = 1;
+ ++_walkDataLastIndex;
+ }
+ }
+ wd = &_walkData[_walkDataLastIndex];
+ wd->setPos(dstX, dstY, 2, _walkCurrentFrame);
+ scale = _walkYScaleRoom[(_walkXScaleRoom[dstX] - 1) * 144 + dstY];
+ xScale = _walkWidthScaleTable[scale - 1];
+ wd->setScale(scale, scale);
+ wd->yPosChanged = 1;
+ wd->dyPos = wd->y - _walkData[_walkDataLastIndex - 1].y;
+ int x = xScale - xScale / 2 + dstX - 1;
+ if (x > 319) {
+ wd->clipSkipX = 1;
+ wd->clipWidth = 319 - (x - xScale);
+ wd->xPosChanged = 1;
+ wd->dxPos = dstX - curX;
+ } else {
+ x = dstX - xScale / 2;
+ if (x < 0) {
+ wd->clipWidth = xScale + x;
+ wd->clipSkipX = xScale - wd->clipWidth + 1;
+ wd->xPosChanged = 1;
+ wd->dxPos = 0;
+ } else {
+ wd->clipWidth = xScale;
+ wd->clipSkipX = 1;
+ wd->xPosChanged = 1;
+ wd->dxPos = dstX - curX;
+ }
+ }
+ ++_walkDataLastIndex;
+ WalkData::setNextFrame(kFacingPositionRight, _walkCurrentFrame);
+ }
+}
+
+void IgorEngine::buildWalkPathAreaLeftDirection(int srcX, int srcY, int dstX, int dstY) {
+ int _walkCurrentPosLocalVar = _walkCurrentPos;
+ if (_walkCurrentPos == kFacingPositionRight) {
+ _walkCurrentPos = kFacingPositionLeft;
+ _walkData[_walkDataLastIndex] = _walkData[_walkDataLastIndex - 1];
+ _walkData[_walkDataLastIndex].posNum = (srcY > dstY) ? kFacingPositionBack : kFacingPositionFront;
+ _walkData[_walkDataLastIndex].frameNum = 5;
+ ++_walkDataLastIndex;
+ } else {
+ _walkCurrentPos = kFacingPositionLeft;
+ }
+ WalkData *wd;
+ uint8 scale, xScale, xSkip;
+ float hStepCur, hStepDist;
+ int curX = srcX;
+ int curY = srcY;
+ if (srcY > dstY) {
+ int hStepsCount = getHorizontalStepsCount(dstX, dstY, srcX, srcY);
+ if (hStepsCount > 0) {
+ hStepCur = hStepDist = (srcY - dstY) / (float)hStepsCount;
+ for (int i = 1; i <= hStepsCount; ++i) {
+ wd = &_walkData[_walkDataLastIndex];
+ scale = _walkYScaleRoom[(_walkXScaleRoom[curX] - 1) * 144 + curY];
+ xSkip = _walkScaleTable[0x769 + scale * 8 + _walkCurrentFrame];
+ if ((curX - xSkip) <= dstX) {
+ break;
+ }
+ curX -= xSkip;
+ curY = srcY - truncReal(hStepCur);
+ wd->setPos(curX, curY, 4, _walkCurrentFrame);
+ scale = _walkYScaleRoom[(_walkXScaleRoom[curX] - 1) * 144 + curY];
+ xScale = _walkWidthScaleTable[scale - 1];
+ wd->setScale(scale, scale);
+ wd->yPosChanged = 0;
+ wd->dyPos = _walkData[_walkDataLastIndex - 1].y - wd->y;
+ int x = xScale - xScale / 2 + curX - 1;
+ if (x > 319) {
+ wd->clipSkipX = 1;
+ wd->clipWidth = 319 - (x - xScale);
+ wd->xPosChanged = 0;
+ wd->dxPos = 0;
+ } else {
+ x = curX - xScale / 2;
+ if (x < 0) {
+ wd->clipWidth = x + xScale;
+ wd->clipSkipX = xScale - wd->clipWidth + 1;
+ wd->xPosChanged = 0;
+ wd->dxPos = xSkip;
+ } else {
+ wd->clipWidth = xScale;
+ wd->clipSkipX = 1;
+ wd->xPosChanged = 0;
+ wd->dxPos = xSkip;
+ }
+ }
+ ++_walkDataLastIndex;
+ hStepCur += hStepDist;
+ WalkData::setNextFrame(kFacingPositionLeft, _walkCurrentFrame);
+ }
+ } else {
+ if (_walkCurrentPosLocalVar == 4 && _walkToObjectPosX == dstX && _walkToObjectPosY == dstY) {
+ _walkData[_walkDataLastIndex] = _walkData[_walkDataLastIndex - 1];
+ _walkData[_walkDataLastIndex].posNum = 4;
+ _walkData[_walkDataLastIndex].frameNum = 1;
+ ++_walkDataLastIndex;
+ }
+ }
+ wd = &_walkData[_walkDataLastIndex];
+ wd->setPos(dstX, dstY, 4, _walkCurrentFrame);
+ scale = _walkYScaleRoom[(_walkXScaleRoom[dstX] - 1) * 144 + dstY];
+ xScale = _walkWidthScaleTable[scale - 1];
+ wd->setScale(scale, scale);
+ wd->yPosChanged = 0;
+ wd->dyPos = curY - dstY;
+ int x = xScale - xScale / 2 + dstX - 1;
+ if (x > 319) {
+ wd->clipSkipX = 1;
+ wd->clipWidth = 319 - (x - xScale);
+ wd->xPosChanged = 0;
+ wd->dxPos = 0;
+ } else {
+ x = dstX - xScale / 2;
+ if (x < 0) {
+ wd->clipWidth = xScale + x;
+ wd->clipSkipX = xScale - wd->clipWidth + 1;
+ wd->xPosChanged = 0;
+ wd->dxPos = curX - dstX;
+ } else {
+ wd->clipWidth = xScale;
+ wd->clipSkipX = 1;
+ wd->xPosChanged = 0;
+ wd->dxPos = curX - dstX;
+ }
+ }
+ ++_walkDataLastIndex;
+ WalkData::setNextFrame(kFacingPositionLeft, _walkCurrentFrame);
+ } else {
+ int hStepsCount = getHorizontalStepsCount(dstX, srcY, srcX, dstY);
+ if (hStepsCount > 0) {
+ hStepCur = hStepDist = (dstY - srcY) / (float)hStepsCount;
+ for (int i = 1; i <= hStepsCount; ++i) {
+ wd = &_walkData[_walkDataLastIndex];
+ scale = _walkYScaleRoom[(_walkXScaleRoom[curX] - 1) * 144 + curY];
+ xSkip = _walkScaleTable[0x769 + scale * 8 + _walkCurrentFrame];
+ if (curX - xSkip <= dstX) {
+ break;
+ }
+ curX -= xSkip;
+ curY = srcY + truncReal(hStepCur);
+ wd->setPos(curX, curY, 4, _walkCurrentFrame);
+ scale = _walkYScaleRoom[(_walkXScaleRoom[curX] - 1) * 144 + curY];
+ xScale = _walkWidthScaleTable[scale - 1];
+ wd->setScale(scale, scale);
+ wd->yPosChanged = 1;
+ wd->dyPos = wd->y - _walkData[_walkDataLastIndex - 1].y;
+ int x = xScale - xScale / 2 + curX - 1;
+ if (x > 319) {
+ wd->clipSkipX = 1;
+ wd->clipWidth = 319 - (x - xScale);
+ wd->xPosChanged = 0;
+ wd->dxPos = 0;
+ } else {
+ x = curX - xScale / 2;
+ if (x < 0) {
+ wd->clipWidth = x + xScale;
+ wd->clipSkipX = xScale - wd->clipWidth + 1;
+ wd->xPosChanged = 0;
+ wd->dxPos = xSkip;
+ } else {
+ wd->clipWidth = xScale;
+ wd->clipSkipX = 1;
+ wd->xPosChanged = 0;
+ wd->dxPos = xSkip;
+ }
+ }
+ ++_walkDataLastIndex;
+ hStepCur += hStepDist;
+ WalkData::setNextFrame(kFacingPositionLeft, _walkCurrentFrame);
+ }
+ } else {
+ if (_walkCurrentPosLocalVar == 4 && _walkToObjectPosX == dstX && _walkToObjectPosY == dstY) {
+ _walkData[_walkDataLastIndex] = _walkData[_walkDataLastIndex - 1];
+ _walkData[_walkDataLastIndex].posNum = 4;
+ _walkData[_walkDataLastIndex].frameNum = 1;
+ ++_walkDataLastIndex;
+ }
+ }
+ wd = &_walkData[_walkDataLastIndex];
+ wd->setPos(dstX, dstY, 4, _walkCurrentFrame);
+ scale = _walkYScaleRoom[(_walkXScaleRoom[curX] - 1) * 144 + curY];
+ xScale = _walkWidthScaleTable[scale - 1];
+ wd->setScale(scale, scale);
+ wd->yPosChanged = 1;
+ wd->dyPos = curY - dstY;
+ int x = xScale - xScale / 2 + dstX - 1;
+ if (x > 319) {
+ wd->clipSkipX = 1;
+ wd->clipWidth = 319 - (x - xScale);
+ wd->xPosChanged = 0;
+ wd->dxPos = 0;
+ } else {
+ x = dstX - xScale / 2;
+ if (x < 0) {
+ wd->clipWidth = xScale + x;
+ wd->clipSkipX = xScale - wd->clipWidth + 1;
+ wd->xPosChanged = 0;
+ wd->dxPos = curX - dstX;
+ } else {
+ wd->clipWidth = xScale;
+ wd->clipSkipX = 1;
+ wd->xPosChanged = 0;
+ wd->dxPos = curX - dstX;
+ }
+ }
+ ++_walkDataLastIndex;
+ WalkData::setNextFrame(kFacingPositionLeft, _walkCurrentFrame);
+ }
+}
+
+void IgorEngine::waitForIgorMove() {
+ _gameTicks = 0;
+ do {
+ if (compareGameTick(1, 16)) {
+ if (_walkDataCurrentIndex > _walkDataLastIndex) {
+ _gameState.igorMoving = false;
+ _walkDataLastIndex = _walkDataCurrentIndex;
+ }
+ if (_gameState.igorMoving) {
+ moveIgor(_walkData[_walkDataCurrentIndex].posNum, _walkData[_walkDataCurrentIndex].frameNum);
+ ++_walkDataCurrentIndex;
+ }
+ }
+ if (_updateRoomBackground) {
+ (this->*_updateRoomBackground)();
+ }
+ waitForTimer();
+ } while (_gameState.igorMoving);
+}
+
+void IgorEngine::setRoomWalkBounds(int x1, int y1, int x2, int y2) {
+ assert(x1 <= x2 && y1 <= y2);
+ _roomWalkBounds.x1 = x1;
+ _roomWalkBounds.x2 = x2;
+ _roomWalkBounds.y1 = y1;
+ _roomWalkBounds.y2 = y2;
+}
+
+void IgorEngine::fixWalkPosition(int *x, int *y) {
+ int xPos = *x;
+ if (xPos < _roomWalkBounds.x1) {
+ xPos = _roomWalkBounds.x1;
+ }
+ if (xPos > _roomWalkBounds.x2) {
+ xPos = _roomWalkBounds.x2;
+ }
+ if (_currentPart == 22) {
+ *x = xPos;
+ *y = _roomWalkBounds.y1;
+ return;
+ }
+ int yPos = *y;
+ if (_currentPart == 13) {
+ if (xPos >= 92 && xPos <= 186 && yPos > 127) {
+ *x = xPos;
+ *y = 127;
+ return;
+ }
+ if (xPos >= 191 && xPos <= 289 && yPos > 127) {
+ *x = xPos;
+ *y = 127;
+ return;
+ }
+ }
+ // skip areas from top to bottom
+ while (_roomObjectAreasTable[_screenLayer2[yPos * 320 + xPos]].area == 0 && yPos < _roomWalkBounds.y2) {
+ ++yPos;
+ }
+ if (_currentPart == 17) {
+ if (yPos != 143 || _roomObjectAreasTable[_screenLayer2[45760 + xPos]].area != 0) {
+ *x = xPos;
+ *y = yPos;
+ return;
+ }
+ }
+ // skip areas from bottom to top
+ while (_roomObjectAreasTable[_screenLayer2[yPos * 320 + xPos]].area == 0 && yPos > _roomWalkBounds.y1) {
+ --yPos;
+ }
+ *x = xPos;
+ *y = yPos;
+}
+
+void IgorEngine::recolorDialogueChoice(int num, bool highlight) {
+ uint8 *p = _screenVGA + 320 * (11 * num + 135);
+ for (int i = 0; i < 320 * 11; ++i) {
+ if (highlight) {
+ if (p[i] == 240) {
+ p[i] = 241;
+ }
+ } else {
+ if (p[i] == 241) {
+ p[i] = 240;
+ }
+ }
+ }
+}
+
+void IgorEngine::handleDialogue(int x, int y, int r, int g, int b) {
+ _gameState.dialogueStarted = true;
+ _gameState.dialogueChoiceStart = 1;
+ _gameState.dialogueChoiceCount = 1;
+ _dialogueEnded = false;
+ do {
+ if (_currentPart / 10 == 15 && _objectsState[48] == 0) {
+ _gameState.dialogueData[6] = 0;
+ }
+ if (_currentPart / 10 == 12 && _objectsState[44] == 0) {
+ _gameState.dialogueData[6] = 1;
+ }
+ drawDialogueChoices();
+ (this->*_updateDialogue)(kUpdateDialogueAnimStanding);
+ _dialogueChoiceSelected = selectDialogue();
+ if (_dialogueChoiceSelected == 0) {
+ break;
+ } else if (_dialogueChoiceSelected == -1) {
+ return;
+ }
+ dialogueAskQuestion();
+ dialogueReplyToQuestion(x, y, r, g, b);
+ int offset = (_dialogueInfo[_dialogueChoiceSelected] - 1) * 6 + (_gameState.dialogueChoiceCount - 1) * 30 + (_gameState.dialogueChoiceStart - 1) * _roomDataOffsets.dlg.matSize;
+ int code = _gameState.dialogueData[offset + 5];
+ if ((code >= 1 && code <= 99) || (_currentPart / 10 == 15 && code == 1)) {
+ _gameState.dialogueData[offset] = 0;
+ if (_currentPart / 10 == 21 && (code == 60 || code == 70 || code == 80) && _dialogueInfo[0] == 1) {
+ _gameState.dialogueData[offset + 2] = 4;
+ }
+ if (_currentPart / 10 == 33 && (code == 21 || code == 22 || code == 23) && _dialogueInfo[0] == 1) {
+ _gameState.dialogueData[offset + 2] = 2;
+ }
+ }
+ debug(kDebugEngine, "handleDialogue() action %d offset %d", _gameState.dialogueData[offset + 2], offset);
+ switch (_gameState.dialogueData[offset + 2]) {
+ case 1:
+ _gameState.dialogueChoiceCount = _gameState.dialogueData[offset + 1];
+ ++_gameState.dialogueChoiceStart;
+ break;
+ case 2:
+ _gameState.dialogueChoiceCount = _gameState.dialogueData[offset + 1];
+ --_gameState.dialogueChoiceStart;
+ break;
+ case 4:
+ _gameState.dialogueChoiceCount = _gameState.dialogueData[offset + 1];
+ _gameState.dialogueChoiceStart -= 2;
+ break;
+ case 0:
+ _dialogueEnded = true;
+ break;
+ }
+ debug(kDebugEngine, "handleDialogue() end %d start %d count %d", _dialogueEnded, _gameState.dialogueChoiceStart, _gameState.dialogueChoiceCount);
+ } while (!_dialogueEnded);
+ memset(_screenVGA + 46080, 0, 17920);
+ drawVerbsPanel();
+ drawInventory(_inventoryInfo[72], 0);
+ _currentAction.verb = kVerbWalk;
+ _gameState.dialogueStarted = false;
+}
+
+void IgorEngine::drawDialogueChoices() {
+ memset(_screenVGA + 46080, 0, 56 * 320);
+ setPaletteColor(240, 0, 0, 0);
+ _dialogueInfo[0] = 0;
+ for (int i = 1; i <= 5; ++i) {
+ _dialogueInfo[i] = 0;
+ }
+ for (int i = 1; i <= 5; ++i) {
+ int offset = (i - 1) * 6 + (_gameState.dialogueChoiceCount - 1) * 30 + (_gameState.dialogueChoiceStart - 1) * _roomDataOffsets.dlg.matSize;
+ if (_gameState.dialogueData[offset] == 1) {
+ ++_dialogueInfo[0];
+ _dialogueInfo[_dialogueInfo[0]] = i;
+ int num = _gameState.dialogueData[offset + 3] - 1;
+ char questionText[128];
+ sprintf(questionText, "@%s %s", _dialogueQuestions[num][0], _dialogueQuestions[num][1]);
+ drawString(_screenVGA, questionText, 0, _dialogueInfo[0] * 11 + 135, 240, 0, 0);
+ }
+ debug(kDebugEngine, "drawDialogueChoices() i %d state %d num %d", i, _gameState.dialogueData[offset], _gameState.dialogueData[offset + 3]);
+ }
+ setPaletteColor(240, _paletteBuffer[0x2F6 + 1], _paletteBuffer[0x2F6 + 2], _paletteBuffer[0x2F6 + 3]);
+ setPaletteColor(241, _paletteBuffer[0x2F0 + 1], _paletteBuffer[0x2F0 + 2], _paletteBuffer[0x2F0 + 3]);
+}
+
+int IgorEngine::selectDialogue() {
+ showCursor();
+ int hoveredChoice = 0;
+ bool end = false;
+ do {
+ int currentChoice = (_inputVars[kInputCursorYPos] - 134) / 11;
+ if (currentChoice < 0) {
+ currentChoice = 0;
+ }
+
+ if (currentChoice != hoveredChoice) {
+ if (hoveredChoice != 0) {
+ recolorDialogueChoice(hoveredChoice, false);
+ }
+ hoveredChoice = currentChoice;
+ if (hoveredChoice != 0) {
+ recolorDialogueChoice(hoveredChoice, true);
+ }
+ }
+ if (_inputVars[kInputClick]) {
+ if (hoveredChoice != 0 && hoveredChoice <= _dialogueInfo[0]) {
+ end = true;
+ }
+ _inputVars[kInputClick] = 0;
+ }
+
+ waitForTimer();
+ } while (!end && !_eventQuitGame);
+ hideCursor();
+ return hoveredChoice;
+}
+
+void IgorEngine::dialogueAskQuestion() {
+ memset(_screenVGA + 46080, 0, 17920);
+ int offset = (_dialogueInfo[_dialogueChoiceSelected] - 1) * 6 + (_gameState.dialogueChoiceCount - 1) * 30 + (_gameState.dialogueChoiceStart - 1) * _roomDataOffsets.dlg.matSize;
+ int num = _gameState.dialogueData[offset + 3] - 1;
+ if (_currentPart / 10 == 17) {
+ num = 5;
+ }
+ debug(kDebugEngine, "dialogueAskQuestion() num %d offset %d", num, offset);
+ strcpy(_globalDialogueTexts[250], _dialogueQuestions[num][0]);
+ strcpy(_globalDialogueTexts[251], _dialogueQuestions[num][1]);
+ if (_globalDialogueTexts[251][0]) {
+ ADD_DIALOGUE_TEXT(250, 2);
+ } else {
+ ADD_DIALOGUE_TEXT(250, 1);
+ }
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+}
+
+void IgorEngine::dialogueReplyToQuestion(int x, int y, int r, int g, int b) {
+ int offset = (_dialogueInfo[_dialogueChoiceSelected] - 1) * 6 + (_gameState.dialogueChoiceCount - 1) * 30 + (_gameState.dialogueChoiceStart - 1) * _roomDataOffsets.dlg.matSize;
+ int reply = _gameState.dialogueData[offset + 4];
+ debug(kDebugEngine, "dialogueReplyToQuestion() dialogue choice %d reply %d", _dialogueChoiceSelected, reply);
+ if (reply == 0) {
+ return;
+ }
+ offset = _roomDataOffsets.dlg.matSize * 3 + reply;
+ int count = _gameState.dialogueData[offset - 1];
+ int dialogueIndex = 250;
+ for (int i = 0; i < count; ++i) {
+ int num = _gameState.dialogueData[offset] - 1;
+ int len = _gameState.dialogueData[offset + 1];
+ debug(kDebugEngine, "dialogueReplyToQuestion() reply %d %d offset %d", num, len, offset);
+ ADD_DIALOGUE_TEXT(dialogueIndex, len);
+ for (int j = 0; j < len; ++j) {
+ strcpy(_globalDialogueTexts[dialogueIndex], _dialogueReplies[num + j]);
+ ++dialogueIndex;
+ }
+ offset += 2;
+ }
+ SET_DIALOGUE_TEXT(1, count);
+ startCutsceneDialogue(x, y, r, g, b);
+ waitForEndOfCutsceneDialogue(x, y, r, g, b);
+}
+
+} // namespace Igor
diff --git a/engines/igor/igor.h b/engines/igor/igor.h
new file mode 100644
index 0000000000..3f17662ba3
--- /dev/null
+++ b/engines/igor/igor.h
@@ -0,0 +1,924 @@
+/* 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 IGOR_ENGINE_H
+#define IGOR_ENGINE_H
+
+#include "common/endian.h"
+#include "common/file.h"
+#include "common/rect.h"
+#include "common/util.h"
+
+#include "sound/mixer.h"
+
+#include "engines/engine.h"
+
+#include "igor/resource_ids.h"
+
+namespace Igor {
+
+enum {
+ kDebugEngine = 1 << 0,
+ kDebugResource = 1 << 1,
+ kDebugScreen = 1 << 2,
+ kDebugWalk = 1 << 3,
+ kDebugGame = 1 << 4
+};
+
+enum {
+ kStartupPart = 900,
+ kTalkColor = 240,
+ kTalkShadowColor = 241,
+ kTickDelay = 1193180 / 4096
+};
+
+enum {
+ kLanguageEnglish = 0,
+ kLanguageSpanish = 1
+};
+
+enum {
+ kTalkModeSpeechOnly = 0,
+ kTalkModeSpeechAndText = 1,
+ kTalkModeTextOnly = 2
+};
+
+enum Verb {
+ kVerbWalk = 1,
+ kVerbTalk,
+ kVerbTake,
+ kVerbLook,
+ kVerbUse,
+ kVerbOpen,
+ kVerbClose,
+ kVerbGive
+};
+
+enum ObjectType {
+ kObjectTypeInventory = 1,
+ kObjectTypeRoom = 2
+};
+
+enum FacingPosition {
+ kFacingPositionBack = 1,
+ kFacingPositionRight = 2,
+ kFacingPositionFront = 3,
+ kFacingPositionLeft = 4
+};
+
+enum {
+ kUpdateDialogueAnimEndOfSentence = 1,
+ kUpdateDialogueAnimMiddleOfSentence,
+ kUpdateDialogueAnimStanding
+};
+
+enum InputVar {
+ kInputSkipDialogue = 0,
+ kInputCursorXPos,
+ kInputCursorYPos,
+ kInputClick,
+ kInputEscape,
+ kInputPause,
+ kInputOptions,
+ kInputVarCount
+};
+
+struct DialogueText {
+ int num;
+ int count;
+};
+
+struct ResourceEntry {
+ int id;
+ uint32 offs;
+ uint32 size;
+};
+
+struct RoomObjectArea {
+ uint8 area;
+ uint8 object;
+ uint8 y1Lum;
+ uint8 y2Lum;
+ uint8 deltaLum;
+};
+
+struct RoomDataOffsets {
+ struct {
+ int box;
+ int boxSize;
+ int boxSrcSize;
+ int boxDstSize;
+ } area;
+ struct {
+ int walkPoints;
+ int walkFacingPosition;
+ } obj;
+ struct {
+ int defaultVerb;
+ int useVerb;
+ int giveVerb;
+ int object2;
+ int object1;
+ int objectSize;
+ } action;
+ struct {
+ int questionsOffset;
+ int questionsSize;
+ int repliesOffset;
+ int repliesSize;
+ int matSize;
+ } dlg;
+};
+
+struct RoomWalkBounds {
+ int x1, y1;
+ int x2, y2;
+};
+
+struct WalkData {
+ int16 x, y;
+ uint8 posNum;
+ uint8 frameNum;
+ uint8 clipSkipX;
+ int16 clipWidth;
+ int16 scaleWidth;
+ uint8 xPosChanged;
+ int16 dxPos;
+ uint8 yPosChanged;
+ int16 dyPos;
+ uint8 scaleHeight;
+
+ void setPos(int xPos, int yPos, uint8 facingPos, uint8 frame) {
+ x = xPos;
+ y = yPos;
+ posNum = facingPos;
+ frameNum = frame;
+ }
+
+ void setDefaultScale() {
+ clipSkipX = 1;
+ clipWidth = 30;
+ scaleWidth = 50;
+ xPosChanged = 1;
+ dxPos = 0;
+ yPosChanged = 1;
+ dyPos = 0;
+ scaleHeight = 50;
+ }
+
+ void setScale(int w, int h) {
+ scaleWidth = w;
+ scaleHeight = h;
+ }
+
+ static void setNextFrame(int pos, int &frame) {
+ switch (pos) {
+ case kFacingPositionBack:
+ case kFacingPositionFront:
+ if (frame == 6) {
+ frame = 1;
+ } else {
+ ++frame;
+ }
+ break;
+ case kFacingPositionLeft:
+ case kFacingPositionRight:
+ if (frame == 8) {
+ frame = 1;
+ } else {
+ ++frame;
+ }
+ break;
+ }
+ }
+};
+
+struct GameStateData {
+ uint8 enableLight;
+ int8 colorLum;
+ int16 counter[5];
+ bool igorMoving;
+ bool dialogueTextRunning;
+ bool updateLight;
+ bool unkF;
+ uint8 unk10;
+ uint8 unk11;
+ bool dialogueStarted;
+ // byte[1]
+ uint8 dialogueData[500];
+ uint8 dialogueChoiceStart;
+ uint8 dialogueChoiceCount;
+ // byte[2]
+ uint8 nextMusicCounter;
+ bool jumpToNextMusic;
+ uint8 configSoundEnabled;
+ uint8 talkSpeed;
+ uint8 talkMode;
+ // byte[3]
+ uint8 musicNum;
+ uint8 musicSequenceIndex;
+};
+
+struct Action {
+ uint8 verb;
+ uint8 object1Num;
+ uint8 object1Type;
+ uint8 verbType; // 1:use,2:give
+ uint8 object2Num;
+ uint8 object2Type;
+};
+
+class IgorEngine: public Engine {
+public:
+
+ enum {
+ MAX_DIALOGUE_TEXTS = 6,
+ MAX_OBJECT_NAME_LENGTH = 31,
+ MAX_DIALOGUE_TEXT_LENGTH = 51,
+ MAX_VERB_NAME_LENGTH = 12,
+ MAX_ROOM_OBJECT_AREAS = 256,
+ MAX_DIALOGUE_QUESTIONS = 30,
+ MAX_DIALOGUE_REPLIES = 70
+ };
+
+ typedef void (IgorEngine::*ExecuteActionProc)(int action);
+ typedef void (IgorEngine::*UpdateDialogueProc)(int action);
+ typedef void (IgorEngine::*UpdateRoomBackgroundProc)();
+
+ IgorEngine(OSystem *system);
+ virtual ~IgorEngine();
+
+ virtual int init();
+ virtual int go();
+
+ void restart();
+ void waitForTimer(int ticks = -1);
+
+ void handleOptionsMenu_paintSave();
+ bool handleOptionsMenu_handleKeyDownSave(int key);
+ void handleOptionsMenu_paintLoad();
+ bool handleOptionsMenu_handleKeyDownLoad(int key);
+ void handleOptionsMenu_paintQuit();
+ bool handleOptionsMenu_handleKeyDownQuit(int key);
+ void handleOptionsMenu_paintCtrl();
+ bool handleOptionsMenu_handleKeyDownCtrl(int key);
+
+protected:
+
+ bool compareGameTick(int add, int mod) const { return ((_gameTicks + (add & ~7)) % mod) == 0; } // { return ((_gameTicks + add) % mod) == 0; }
+ bool compareGameTick(int eq) const { return _gameTicks == (eq & ~7); } // { return _gameTicks == eq; }
+ void copyArea(uint8 *dst, int dstOffset, int dstPitch, const uint8 *src, int srcPitch, int w, int h, bool transparent = false);
+ int getRandomNumber(int m);
+ void handleOptionsMenu();
+ void handlePause();
+ void playMusic(int num);
+ void updateMusic();
+ void playSound(int num, int fl);
+ void stopSound();
+ void loadIgorFrames();
+ void fixDialogueTextPosition(int num, int count, int *x, int *y);
+ void startCutsceneDialogue(int x, int y, int r, int g, int b);
+ void waitForEndOfCutsceneDialogue(int x, int y, int r, int g, int b);
+ void fixIgorDialogueTextPosition(int num, int count, int *x, int *y);
+ void startIgorDialogue();
+ void waitForEndOfIgorDialogue();
+ int getObjectFromInventory(int x) const;
+ int getSelectedVerb() const;
+ const ResourceEntry *findData(int num) const;
+ uint8 *loadData(int num, uint8 *dst = 0, int *size = 0);
+ void decodeMainText(const uint8 *p);
+ void decodeRoomStrings(const uint8 *p, bool skipObjectNames = false);
+ void decodeRoomText(const uint8 *p);
+ void decodeRoomAreas(const uint8 *p, int count);
+ void decodeRoomMask(const uint8 *p);
+ void loadRoomData(int pal, int img, int box, int msk, int txt);
+ void loadAnimData(const int *anm, int loadOffset = 0);
+ void loadActionData(int act);
+ void loadDialogueData(int dlg);
+ void loadMainTexts();
+ void setupDefaultPalette();
+ void updatePalette(int count);
+ void clearPalette();
+ void setPaletteColor(uint8 index, uint8 r, uint8 g, uint8 b);
+ void setPaletteRange(int startColor, int endColor);
+ void fadeInPalette(int count);
+ void fadeOutPalette(int count);
+ void scrollPalette(int startColor, int endColor);
+ void drawString(uint8 *dst, const char *s, int x, int y, int color1, int color2 = -1, int color3 = -1);
+ int getStringWidth(const char *s) const;
+ void drawActionSentence(const char *sentence, uint8 color);
+ void formatActionSentence(uint8 color);
+ const uint8 *getAnimFrame(int baseOffset, int tableOffset, int frame);
+ void decodeAnimFrame(const uint8 *src, uint8 *dst, bool preserveText = false);
+ void copyAnimFrame(int srcOffset, int frame, int frameSize, int w, int h, int dstOffset);
+ void setCursor(int num);
+ void showCursor();
+ void hideCursor();
+ void updateRoomLight(int fl);
+ void drawVerbsPanel();
+ void redrawVerb(uint8 verb, bool highlight);
+ void drawInventory(int start, int mode);
+ void packInventory();
+ void scrollInventory();
+ void addObjectToInventory(int object, int index);
+ void removeObjectFromInventory(int index);
+ void executeAction(int action);
+ void clearAction();
+ void handleRoomInput();
+ void animateIgorTalking(int frame);
+ void handleRoomDialogue();
+ void handleRoomIgorWalk();
+ void handleRoomInventoryScroll();
+ void handleRoomLight();
+ int lookupScale(int xOffset, int yOffset, int h) const;
+ void moveIgorHelper1(int pos, int frame);
+ void moveIgor(int pos, int frame);
+ void buildWalkPathSimple(int srcX, int srcY, int dstX, int dstY);
+ void getClosestAreaTrianglePoint(int dstArea, int srcArea, int *dstY, int *dstX, int srcY, int srcX);
+ void getClosestAreaTrianglePoint2(int dstArea, int srcArea, int *dstY, int *dstX, int srcY1, int srcX1, int srcY2, int srcX2);
+ void buildWalkPath(int srcX, int srcY, int dstX, int dstY);
+ void buildWalkPathArea(int srcX, int srcY, int dstX, int dstY);
+ int getVerticalStepsCount(int minX, int minY, int maxX, int maxY);
+ int getHorizontalStepsCount(int minX, int minY, int maxX, int maxY);
+ void lookupScale(int curX, int curY, uint8 &scale, uint8 &xScale, uint8 &yScale) const;
+ void buildWalkPathAreaUpDirection(int srcX, int srcY, int dstX, int dstY);
+ void buildWalkPathAreaDownDirection(int srcX, int srcY, int dstX, int dstY);
+ void buildWalkPathAreaRightDirection(int srcX, int srcY, int dstX, int dstY);
+ void buildWalkPathAreaLeftDirection(int srcX, int srcY, int dstX, int dstY);
+ void waitForIgorMove();
+ void setRoomWalkBounds(int x1, int y1, int x2, int y2);
+ void fixWalkPosition(int *x, int *y);
+ void recolorDialogueChoice(int num, bool highlight);
+ void handleDialogue(int x, int y, int r, int g, int b);
+ void drawDialogueChoices();
+ int selectDialogue();
+ void dialogueAskQuestion();
+ void dialogueReplyToQuestion(int x, int y, int r, int g, int b);
+
+// void serializeGameState(int slot, File *f, bool saving);
+
+ Common::File _ovlFile;
+ Common::File _sndFile;
+
+ Audio::SoundHandle _sfxHandle;
+
+ uint8 *_screenVGA;
+ uint8 *_facingIgorFrames[4];
+ uint8 *_screenLayer1;
+ uint8 *_screenLayer2;
+ uint8 *_screenTextLayer;
+ uint8 *_screenTempLayer;
+ uint8 *_igorHeadFrames;
+ uint8 *_animFramesBuffer;
+ uint8 *_inventoryPanelBuffer;
+ uint8 *_inventoryImagesBuffer;
+ uint8 *_verbsPanelBuffer;
+ int _screenVGAVOffset;
+
+ bool _eventQuitGame;
+ GameStateData _gameState;
+ uint32 _nextTimer;
+ bool _fastMode;
+ int _language;
+
+ WalkData _walkData[100];
+ uint8 _walkCurrentPos;
+ int _walkDataLastIndex;
+ int _walkDataCurrentIndex;
+ int _walkCurrentFrame;
+ int _walkDataCurrentPosX, _walkDataCurrentPosY;
+ int _walkToObjectPosX, _walkToObjectPosY;
+
+ int _currentPart;
+ int _talkDelay;
+ int _talkSpeechCounter;
+ int _talkDelayCounter;
+ DialogueText _dialogueTextsTable[MAX_DIALOGUE_TEXTS];
+ int _dialogueTextsStart;
+ int _dialogueTextsCount;
+ int _dialogueDirtyRectY;
+ int _dialogueDirtyRectSize;
+ char _dialogueQuestions[MAX_DIALOGUE_QUESTIONS][2][41];
+ char _dialogueReplies[MAX_DIALOGUE_REPLIES][51];
+ bool _dialogueEnded;
+ int _dialogueChoiceSelected;
+ uint8 _dialogueInfo[6];
+
+ uint8 _objectsState[112];
+ uint8 _inventoryImages[36];
+ uint8 _inventoryInfo[74];
+ char _verbPrepositions[3][7];
+ char _globalObjectNames[35][MAX_OBJECT_NAME_LENGTH];
+ char _globalDialogueTexts[300][MAX_DIALOGUE_TEXT_LENGTH];
+ char _verbsName[9][MAX_VERB_NAME_LENGTH];
+ char _roomObjectNames[20][MAX_OBJECT_NAME_LENGTH];
+ uint8 _currentPalette[768];
+ uint8 _paletteBuffer[768];
+ uint8 _igorPalette[48];
+ uint8 *_igorTempFrames;
+ uint8 _walkXScaleRoom[320];
+ uint8 _walkYScaleRoom[144 * 3];
+ RoomObjectArea _roomObjectAreasTable[MAX_ROOM_OBJECT_AREAS];
+ uint8 _roomActionsTable[0x2000];
+ ExecuteActionProc _executeMainAction;
+ ExecuteActionProc _executeRoomAction;
+ uint8 _previousMusic;
+ uint8 *_musicSequenceTable[5];
+ Action _currentAction;
+ uint8 _actionCode;
+ uint8 _actionWalkPoint;
+ int _inputVars[kInputVarCount];
+ bool _scrollInventory;
+ int _scrollInventoryStartY, _scrollInventoryEndY, _scrollInventoryDy;
+ bool _roomCursorOn;
+ int _currentCursor;
+ bool _dialogueCursorOn;
+ RoomDataOffsets _roomDataOffsets;
+ RoomWalkBounds _roomWalkBounds;
+ UpdateDialogueProc _updateDialogue;
+ UpdateRoomBackgroundProc _updateRoomBackground;
+ int _gameTicks;
+
+ char _saveStateDescriptions[10][100];
+
+ static const uint8 _dialogueColor[];
+ static const uint8 _sentenceColorIndex[];
+ static const uint8 _fontCharIndex[];
+ static const uint8 _fontCharWidth[];
+ static const uint8 _fontData[];
+ static const uint8 _talkDelays[];
+ static const uint8 _verbAreasTable[];
+ static const uint8 _inventoryOffsetTable[];
+ static const uint8 _inventoryActionsTable[];
+ static const uint8 _walkWidthScaleTable[];
+ static const float _walkScaleSpeedTable[];
+ static const uint8 _walkScaleTable[];
+ static const uint8 _mouseCursorMask[];
+ static const uint8 _mouseCursorData[];
+ static const uint32 _fdsOffsetsTable[];
+ static const ResourceEntry _resourceEntriesTable[];
+ static const int _resourceEntriesCount;
+
+
+ //
+ // game logic
+ //
+
+ // main loop
+ void ADD_DIALOGUE_TEXT(int num, int count);
+ void SET_DIALOGUE_TEXT(int start, int count);
+ void SET_EXEC_ACTION_FUNC(int i, ExecuteActionProc p);
+ void EXEC_MAIN_ACTION(int action);
+ void EXEC_MAIN_ACTION_38();
+ void EXEC_MAIN_ACTION_43();
+ void EXEC_MAIN_ACTION_54();
+ void SET_PAL_208_96_1();
+ void SET_PAL_240_48_1();
+ void UPDATE_OBJECT_STATE(int num);
+ void PART_MEANWHILE();
+ void PART_MARGARET_ROOM_CUTSCENE_HELPER_1();
+ void PART_MARGARET_ROOM_CUTSCENE_HELPER_2(int frame);
+ void PART_MARGARET_ROOM_CUTSCENE_UPDATE_DIALOGUE_MARGARET(int action);
+ void PART_MARGARET_ROOM_CUTSCENE();
+ void PART_UPDATE_FIGURES_ON_PAPER(int delay);
+ void PART_MAIN();
+
+ // college map
+ void PART_04_EXEC_ACTION(int action);
+ void PART_04_CLEAR_OBJECT_STATE_84(int num);
+ void PART_04();
+
+ // bridge
+ void PART_05_EXEC_ACTION(int action);
+ void PART_05_ACTION_102();
+ void PART_05_ACTION_103();
+ void PART_05_UPDATE_ROOM_BACKGROUND();
+ void PART_05_HELPER_1();
+ void PART_05_HELPER_2();
+ void PART_05_HELPER_3(int frame);
+ void PART_05_HELPER_4(int num);
+ void PART_05_HELPER_5(int frame);
+ void PART_05_HELPER_6();
+ void PART_05();
+
+ // bridge (rock)
+ void PART_06_EXEC_ACTION(int action);
+ void PART_06_ACTION_102();
+ void PART_06_ACTION_103();
+ void PART_06_ACTION_105();
+ void PART_06_ACTION_107();
+ void PART_06_ACTION_108();
+ void PART_06_UPDATE_DIALOGUE_PHOTOGRAPHER(int action);
+ void PART_06_HANDLE_DIALOGUE_PHOTOGRAPHER();
+ void PART_06_UPDATE_ROOM_BACKGROUND();
+ void PART_06_HELPER_1(int frame);
+ void PART_06_HELPER_2();
+ void PART_06_HELPER_3();
+ void PART_06_HELPER_6(int num);
+ void PART_06_HELPER_7(int frame);
+ void PART_06_HELPER_8(int frame);
+ void PART_06_HELPER_12();
+ void PART_06_HELPER_13(int frame);
+ void PART_06_HELPER_14();
+ void PART_06_HELPER_15(int frame);
+ void PART_06();
+
+ // outside church
+ void PART_12_EXEC_ACTION(int action);
+ void PART_12_ACTION_101();
+ void PART_12_ACTION_104();
+ void PART_12_ACTION_105();
+ void PART_12_ACTION_108();
+ void PART_12_UPDATE_ROOM_BACKGROUND();
+ void PART_12_UPDATE_DIALOGUE_TOBIAS(int action);
+ void PART_12_HANDLE_DIALOGUE_CHURCHMAN();
+ void PART_12_HELPER_1(int num);
+ void PART_12_HELPER_2();
+ void PART_12_HELPER_3();
+ void PART_12_HELPER_4();
+ void PART_12_HELPER_5();
+ void PART_12_HELPER_6();
+ void PART_12_HELPER_8();
+ void PART_12_HELPER_9();
+ void PART_12_HELPER_10(int frame);
+ void PART_12();
+
+ // inside church
+ void PART_13_EXEC_ACTION(int action);
+ void PART_13_ACTION_101_103();
+ void PART_13_ACTION_104();
+ void PART_13_HELPER_1(int num);
+ void PART_13_HELPER_2();
+ void PART_13_HELPER_3();
+ void PART_13();
+
+ // church puzzle
+ void PART_14_EXEC_ACTION(int action);
+ void PART_14_UPDATE_ROOM_BACKGROUND_ACTION_108();
+ void PART_14_ACTION_101();
+ void PART_14_ACTION_103();
+ void PART_14_ACTION_105();
+ void PART_14_ACTION_106();
+ void PART_14_ACTION_108();
+ void PART_14_HELPER_1(int num);
+ void PART_14_HELPER_2();
+ void PART_14_HELPER_3();
+ void PART_14_HELPER_4();
+ void PART_14_HELPER_6();
+ void PART_14_HELPER_7(int frame);
+ void PART_14_HELPER_8(int start, int end);
+ void PART_14_HELPER_9();
+ void PART_14_HELPER_10();
+ void PART_14_PUSH_STONE(int screenOffset, int w, int h, int animOffset);
+ void PART_14();
+ void loadResourceData__ROOM_ChurchPuzzle();
+ void loadResourceData__ANIM_ChurchPuzzle();
+
+ // tobias office
+ void PART_15_EXEC_ACTION(int action);
+ void PART_15_ACTION_101();
+ void PART_15_ACTION_107();
+ void PART_15_ACTION_115();
+ void PART_15_ACTION_116();
+ void PART_15_UPDATE_DIALOGUE_TOBIAS(int action);
+ void PART_15_HANDLE_DIALOGUE_TOBIAS();
+ void PART_15_HELPER_1(int num);
+ void PART_15_HELPER_2();
+ void PART_15_HELPER_3();
+ void PART_15_HELPER_5();
+ void PART_15_HELPER_6(int frame);
+ void PART_15_HELPER_7(int frame);
+ void PART_15_HELPER_8(int frame);
+ void PART_15_HELPER_9(int frame);
+ void PART_15_HELPER_10(int frame);
+ void PART_15();
+
+ // laboratory
+ void PART_16_EXEC_ACTION(int action);
+ void PART_16_ACTION_101();
+ void PART_16_UPDATE_DIALOGUE_MARGARET_HARRISON(int action);
+ void PART_16_UPDATE_DIALOGUE_MARGARET(int action);
+ void PART_16_HELPER_1(int num);
+ void PART_16_HELPER_2();
+ void PART_16_HELPER_3();
+ void PART_16_HELPER_5();
+ void PART_16_HELPER_6(int frame);
+ void PART_16();
+ void loadResourceData__ROOM_Laboratory();
+ void loadResourceData__ANIM_Laboratory();
+
+ // outside college
+ void PART_17_EXEC_ACTION(int action);
+ void PART_17_ACTION_101();
+ void PART_17_ACTION_103();
+ void PART_17_ACTION_105();
+ void PART_17_ACTION_106();
+ void PART_17_HANDLE_DIALOGUE_PHILIP();
+ void PART_17_UPDATE_DIALOGUE_PHILIP(int action);
+ void PART_17_UPDATE_DIALOGUE_PHILIP_JIMMY(int action);
+ void PART_17_UPDATE_ROOM_BACKGROUND();
+ void PART_17_HELPER_1(int num);
+ void PART_17_HELPER_2();
+ void PART_17_HELPER_3(int lum);
+ void PART_17_HELPER_4();
+ void PART_17_HELPER_5(int lum);
+ void PART_17_HELPER_6();
+ void PART_17_HELPER_8(int num);
+ void PART_17_HELPER_9(int num);
+ void PART_17_HELPER_10();
+ void PART_17_HELPER_11(int frame);
+ void PART_17();
+
+ // men toilets
+ void PART_18_EXEC_ACTION(int action);
+ void PART_18_ACTION_109();
+ void PART_18_ACTION_111();
+ void PART_18_HELPER_1(int num);
+ void PART_18_HELPER_2();
+ void PART_18();
+ void loadResourceData__ROOM_MenToilets();
+ void loadResourceData__ANIM_MenToilets();
+
+ // women toilets
+ void PART_19_EXEC_ACTION(int action);
+ void PART_19_ACTION_107();
+ void PART_19_ACTION_109();
+ void PART_19_UPDATE_DIALOGUE_WOMEN(int action);
+ void PART_19_UPDATE_BACKGROUND_HELPER_9();
+ void PART_19_HELPER_1(int num);
+ void PART_19_HELPER_2();
+ void PART_19_HELPER_3();
+ void PART_19_HELPER_4();
+ void PART_19_HELPER_5();
+ void PART_19_HELPER_7(int frame);
+ void PART_19();
+
+ // college corridor margaret
+ void PART_21_EXEC_ACTION(int action);
+ void PART_21_ACTION_101();
+ void PART_21_ACTION_102();
+ void PART_21_ACTION_107();
+ void PART_21_ACTION_108();
+ void PART_21_ACTION_110();
+ void PART_21_ACTION_111();
+ void PART_21_ACTION_113();
+ void PART_21_UPDATE_ROOM_BACKGROUND();
+ void PART_21_UPDATE_DIALOGUE_MARGARET_1(int action);
+ void PART_21_UPDATE_DIALOGUE_MARGARET_2(int action);
+ void PART_21_UPDATE_DIALOGUE_MARGARET_3(int action);
+ void PART_21_HANDLE_DIALOGUE_MARGARET();
+ void PART_21_HELPER_1(int num);
+ void PART_21_HELPER_2();
+ void PART_21_HELPER_3();
+ void PART_21_HELPER_4();
+ void PART_21_HELPER_6(int frame);
+ void PART_21_HELPER_7();
+ void PART_21_HELPER_8();
+ void PART_21_HELPER_9();
+ void PART_21_HELPER_10();
+ void PART_21_HELPER_11(int frame);
+ void PART_21();
+
+ // bell church
+ void PART_22_EXEC_ACTION(int action);
+ void PART_22_ACTION_101();
+ void PART_22_ACTION_102();
+ void PART_22_HELPER_1(int num);
+ void PART_22_HELPER_2();
+ void PART_22();
+
+ // college corridor lucas
+ void PART_23_EXEC_ACTION(int action);
+ void PART_23_ACTION_105();
+ void PART_23_ACTION_107();
+ void PART_23_ACTION_108();
+ void PART_23_UPDATE_ROOM_BACKGROUND();
+ void PART_23_HELPER_1(int num);
+ void PART_23_HELPER_2(int frame);
+ void PART_23_HELPER_3();
+ void PART_23_HELPER_4();
+ void PART_23_HELPER_5();
+ void PART_23_HELPER_6();
+ void PART_23_HELPER_7(int frame);
+ void PART_23_HELPER_8(int frame);
+ void PART_23();
+
+ // college corridor sharon michael
+ void PART_24_EXEC_ACTION(int action);
+ void PART_24_ACTION_102();
+ void PART_24_ACTION_104();
+ void PART_24_ACTION_105();
+ void PART_24_ACTION_107();
+ void PART_24_UPDATE_ROOM_BACKGROUND();
+ void PART_24_HELPER_1(int num);
+ void PART_24_HELPER_2(int frame);
+ void PART_24_HELPER_3(int frame);
+ void PART_24_HELPER_4();
+ void PART_24_HELPER_5();
+ void PART_24_HELPER_7();
+ void PART_24_HELPER_8();
+ void PART_24_HELPER_9();
+ void PART_24();
+
+ // college corridor announcement board
+ void PART_25_EXEC_ACTION(int action);
+ void PART_25_ACTION_105();
+ void PART_25_ACTION_107();
+ void PART_25_ACTION_108();
+ void PART_25_HELPER_1(int num);
+ void PART_25_HELPER_2();
+ void PART_25_HELPER_3();
+ void PART_25_HELPER_4();
+ void PART_25_HELPER_5();
+ void PART_25_HELPER_7();
+ void PART_25();
+
+ // college corridor miss barrymore
+ void PART_26_EXEC_ACTION(int action);
+ void PART_26_ACTION_103();
+ void PART_26_ACTION_104();
+ void PART_26_ACTION_107();
+ void PART_26_UPDATE_ROOM_BACKGROUND();
+ void PART_26_HELPER_1(int num);
+ void PART_26_HELPER_2();
+ void PART_26_HELPER_3();
+ void PART_26_HELPER_4();
+ void PART_26_HELPER_5();
+ void PART_26_HELPER_7(int frame);
+ void PART_26();
+
+ // college lockers
+ void PART_27_EXEC_ACTION(int action);
+ void PART_27_ACTION_106();
+ void PART_27_ACTION_107();
+ void PART_27_ACTION_108();
+ void PART_27_ACTION_110();
+ void PART_27_HELPER_1(int num);
+ void PART_27_HELPER_2();
+ void PART_27_HELPER_3();
+ void PART_27_HELPER_4();
+ void PART_27_HELPER_5();
+ void PART_27();
+
+ // college corridor caroline
+ void PART_28_EXEC_ACTION(int action);
+ void PART_28_ACTION_108();
+ void PART_28_ACTION_109();
+ void PART_28_UPDATE_DIALOGUE_CAROLINE(int action);
+ void PART_28_UPDATE_ROOM_BACKGROUND();
+ void PART_28_HELPER_1(int num);
+ void PART_28_HELPER_2();
+ void PART_28_HELPER_3();
+ void PART_28_HELPER_5(int frame);
+ void PART_28_HELPER_6();
+ void PART_28_HELPER_8(int frame);
+ void PART_28();
+
+ // college corridor stairs first floor
+ void PART_30_EXEC_ACTION(int action);
+ void PART_30_ACTION_102();
+ void PART_30_ACTION_104();
+ void PART_30_UPDATE_DIALOGUE_LAURA(int action);
+ void PART_30_HANDLE_DIALOGUE_LAURA();
+ void PART_30_HELPER_1(int num);
+ void PART_30_HELPER_2();
+ void PART_30_HELPER_3();
+ void PART_30_HELPER_4();
+ void PART_30_HELPER_5();
+ void PART_30_HELPER_8();
+ void PART_30_HELPER_9(int frame);
+ void PART_30();
+
+ // college corridor stairs second floor
+ void PART_31_EXEC_ACTION(int action);
+ void PART_31_ACTION_102();
+ void PART_31_ACTION_103();
+ void PART_31_ACTION_106();
+ void PART_31_ACTION_110();
+ void PART_31_UPDATE_ROOM_BACKGROUND();
+ void PART_31_HELPER_1(int num);
+ void PART_31_HELPER_2(int frame);
+ void PART_31_HELPER_3();
+ void PART_31_HELPER_4();
+ void PART_31_HELPER_5();
+ void PART_31_HELPER_6();
+ void PART_31_HELPER_9();
+ void PART_31();
+
+ // library
+ void PART_33_EXEC_ACTION(int action);
+ void PART_33_ACTION_109();
+ void PART_33_ACTION_111();
+ void PART_33_ACTION_113();
+ void PART_33_ACTION_114();
+ void PART_33_ACTION_115();
+ void PART_33_UPDATE_DIALOGUE_HARRISON_1(int action);
+ void PART_33_UPDATE_DIALOGUE_HARRISON_2(int action);
+ void PART_33_UPDATE_DIALOGUE_HARRISON_3(int action);
+ void PART_33_HANDLE_DIALOGUE_HARRISON();
+ void PART_33_UPDATE_ROOM_BACKGROUND();
+ void PART_33_HELPER_1(int num);
+ void PART_33_HELPER_2();
+ void PART_33_HELPER_3();
+ void PART_33_HELPER_4(int frame);
+ void PART_33_HELPER_5(int frame);
+ void PART_33_HELPER_7();
+ void PART_33_HELPER_8(int frame);
+ void PART_33_HELPER_9();
+ void PART_33();
+ void loadResourceData__ROOM_Library();
+ void loadResourceData__ANIM_Library();
+
+ // chemistry classroom
+ void PART_36_EXEC_ACTION(int action);
+ void PART_36_ACTION_102();
+ void PART_36_HELPER_1(int num);
+ void PART_36_HELPER_2();
+ void PART_36_HELPER_4(int frame);
+ void PART_36_HELPER_5(int *x, int *y);
+ void PART_36();
+
+ // physics classroom
+ void PART_37_EXEC_ACTION(int action);
+ void PART_37_ACTION_102();
+ void PART_37_HELPER_1(int num);
+ void PART_37_HELPER_2();
+ void PART_37();
+
+ // philip vodka cutscene
+ void PART_75_UPDATE_DIALOGUE_PHILIP(int action);
+ void PART_75_HELPER_1(int frame);
+ void PART_75();
+
+ // introduction cutscene
+ void PART_85_UPDATE_ROOM_BACKGROUND();
+ void PART_85_UPDATE_DIALOGUE_PHILIP_LAURA(int action);
+ void PART_85_HELPER_1(int frameOffset2, int frameOffset1, int firstFrame, int lastFrame, int delay);
+ void PART_85_HELPER_2();
+ void PART_85_HELPER_4();
+ void PART_85_HELPER_6(int frame);
+ void PART_85();
+
+ // startup screens
+ void PART_90();
+
+ // shareware screens
+ void PART_95();
+
+
+ static const uint8 PAL_48_1[];
+ static const uint8 PAL_96_1[];
+ static const uint8 PAL_IGOR_1[];
+ static const uint8 PAL_IGOR_2[];
+ static const uint8 INVENTORY_IMG_INIT[];
+ static const RoomDataOffsets PART_04_ROOM_DATA_OFFSETS;
+ static const RoomDataOffsets PART_05_ROOM_DATA_OFFSETS;
+ static const RoomDataOffsets PART_06_ROOM_DATA_OFFSETS;
+ static const RoomDataOffsets PART_12_ROOM_DATA_OFFSETS;
+ static const RoomDataOffsets PART_13_ROOM_DATA_OFFSETS;
+ static const RoomDataOffsets PART_14_ROOM_DATA_OFFSETS;
+ static const RoomDataOffsets PART_15_ROOM_DATA_OFFSETS;
+ static const RoomDataOffsets PART_16_ROOM_DATA_OFFSETS;
+ static const RoomDataOffsets PART_17_ROOM_DATA_OFFSETS;
+ static const RoomDataOffsets PART_18_ROOM_DATA_OFFSETS;
+ static const RoomDataOffsets PART_19_ROOM_DATA_OFFSETS;
+ static const RoomDataOffsets PART_21_ROOM_DATA_OFFSETS;
+ static const RoomDataOffsets PART_22_ROOM_DATA_OFFSETS;
+ static const RoomDataOffsets PART_23_ROOM_DATA_OFFSETS;
+ static const RoomDataOffsets PART_24_ROOM_DATA_OFFSETS;
+ static const RoomDataOffsets PART_25_ROOM_DATA_OFFSETS;
+ static const RoomDataOffsets PART_26_ROOM_DATA_OFFSETS;
+ static const RoomDataOffsets PART_27_ROOM_DATA_OFFSETS;
+ static const RoomDataOffsets PART_28_ROOM_DATA_OFFSETS;
+ static const RoomDataOffsets PART_30_ROOM_DATA_OFFSETS;
+ static const RoomDataOffsets PART_31_ROOM_DATA_OFFSETS;
+ static const RoomDataOffsets PART_33_ROOM_DATA_OFFSETS;
+ static const RoomDataOffsets PART_36_ROOM_DATA_OFFSETS;
+ static const RoomDataOffsets PART_37_ROOM_DATA_OFFSETS;
+};
+
+} // namespace Igor
+
+#endif
diff --git a/engines/igor/menu.cpp b/engines/igor/menu.cpp
new file mode 100644
index 0000000000..abe38d35ea
--- /dev/null
+++ b/engines/igor/menu.cpp
@@ -0,0 +1,346 @@
+/* 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/events.h"
+#include "common/system.h"
+
+#include "igor/igor.h"
+
+namespace Igor {
+
+static const struct {
+ int y;
+ int h;
+} buttonsBarCoords[] = {
+ { 3, 1 },
+ { 1, 1 },
+ { 2, 2 },
+ { 4, 1 },
+ { 5, 10 },
+ { 6, 1 },
+ { 2, 2 },
+ { 7, 1 },
+ { 8, 93 },
+ { 9, 1 },
+ { 2, 2 },
+ { 3, 1 }
+};
+
+static void drawButtonsBar(uint8 *dst, const uint8 *src) {
+ int y0 = 15;
+ for (int i = 1; i <= 11; ++i) {
+ int y2 = y0 + buttonsBarCoords[i].h - 1;
+ if (y0 > y2) {
+ continue;
+ }
+ for (int y1 = y0; y1 <= y2; ++y1) {
+ memcpy(dst + (y1 - 15) * 320 + 43, src + (buttonsBarCoords[i].y - 1) * 234, 234);
+ ++y0;
+ }
+ }
+}
+
+static void redrawButton(uint8 *dst, int button, bool highlight) {
+ const int colorDiff = highlight ? 4 : -4;
+ for (int y = 0; y <= 11; ++y) {
+ uint8 *p = dst + (y + 3) * 320 + button * 46 + 43 + 3;
+ for (int x = 0; x <= 43; ++x) {
+ p[x] += colorDiff;
+ }
+ }
+}
+
+enum {
+ kPageSave = 0,
+ kPageLoad,
+ kPageQuit,
+ kPageCtrl,
+ kPagePlay
+};
+
+struct Page {
+ const char *captions[2];
+ int xPos[2];
+ void (IgorEngine::*paintProc)();
+ bool (IgorEngine::*handleKeyDownProc)(int key);
+};
+
+static const Page pages[] = {
+ {
+ { "SAVE", "Choose a position to SAVE to" },
+ { 53, 75 },
+ &IgorEngine::handleOptionsMenu_paintSave,
+ &IgorEngine::handleOptionsMenu_handleKeyDownSave
+ },
+ {
+ { "LOAD", "Choose a game to load" },
+ { 98, 93 },
+ &IgorEngine::handleOptionsMenu_paintLoad,
+ &IgorEngine::handleOptionsMenu_handleKeyDownLoad
+ },
+ {
+ { "QUIT", "QUIT" },
+ { 146, 146 },
+ &IgorEngine::handleOptionsMenu_paintQuit,
+ &IgorEngine::handleOptionsMenu_handleKeyDownQuit
+ },
+ {
+ { "CTRL", "Game CONTROLS" },
+ { 190, 112 },
+ &IgorEngine::handleOptionsMenu_paintCtrl,
+ &IgorEngine::handleOptionsMenu_handleKeyDownCtrl
+ },
+ {
+ { "PLAY", 0 },
+ { 237, 0 },
+ 0,
+ 0
+ }
+};
+
+void IgorEngine::handleOptionsMenu_paintSave() {
+ drawString(_screenTextLayer, "Not available in shareware version", 60, 70 - 16, 0xF6, -1, 0);
+}
+
+bool IgorEngine::handleOptionsMenu_handleKeyDownSave(int key) {
+ return true;
+}
+
+void IgorEngine::handleOptionsMenu_paintLoad() {
+ drawString(_screenTextLayer, "Not available in shareware version", 60, 70 - 16, 0xF6, -1, 0);
+}
+
+bool IgorEngine::handleOptionsMenu_handleKeyDownLoad(int key) {
+ return true;
+}
+
+void IgorEngine::handleOptionsMenu_paintQuit() {
+ drawString(_screenTextLayer, "Are you sure?", 120, 64 - 15, 0xF6, -1, 0);
+ drawString(_screenTextLayer, "(Y/N)", 143, 76 - 15, 0xF6, -1, 0);
+}
+
+bool IgorEngine::handleOptionsMenu_handleKeyDownQuit(int key) {
+ if (key == Common::KEYCODE_y) {
+ _currentPart = 255; // display the shareware screens
+ }
+ return true;
+}
+
+static void redrawRect(uint8 *dst, int num, bool border) {
+ const int x = 43 + 6;
+ const int y = 22 * num;
+ for (int i = 0; i < 21; ++i) {
+ memset(dst + (y + i) * 320 + x, 0xF8, 222);
+ }
+ if (border) {
+ memset(dst + y * 320 + x, 0xF7, 222);
+ memset(dst + (y + 20) * 320 + x, 0xF9, 222);
+ for (int i = 1; i < 20; ++i) {
+ dst[(y + i) * 320 + x ] = 0xF7;
+ dst[(y + i) * 320 + x + 221] = 0xF9;
+ }
+ }
+}
+
+void IgorEngine::handleOptionsMenu_paintCtrl() {
+ static const char *textsStrTable1[] = {
+ "Sound effects OFF",
+ "Sound effects ON",
+ "Sound effects UNAVAILABLE"
+ };
+ static int textsPosTable1[] = { 106, 110, 77 };
+ int i = _gameState.configSoundEnabled;
+ redrawRect(_screenTextLayer, 1, false);
+ drawString(_screenTextLayer, textsStrTable1[i], textsPosTable1[i], 41 - 15, 0xF7, -1, 0);
+
+ redrawRect(_screenTextLayer, 2, false);
+ drawString(_screenTextLayer, "Only TEXT AVAILABLE", 93, 63 - 15, 0xF7, -1, 0);
+
+ static const char *textsStrTable2[] = {
+ "Music OFF",
+ "Music ON",
+ "Music UNAVAILABLE"
+ };
+ static int textsPosTable2[] = { 129, 133, 100 };
+ i = 1;
+ redrawRect(_screenTextLayer, 3, false);
+ drawString(_screenTextLayer, textsStrTable2[i], textsPosTable2[i], 85 - 15, 0xF7, -1, 0);
+
+ static const char *textsStrTable3[] = {
+ "Text speed VERY SLOW",
+ "Text speed SLOW",
+ "Text speed NORMAL",
+ "Text speed FAST",
+ "Text speed VERY FAST"
+ };
+ static int textsPosTable3[] = { 93, 110, 102, 111, 94 };
+ i = _gameState.talkSpeed - 1;
+ redrawRect(_screenTextLayer, 4, true);
+ drawString(_screenTextLayer, textsStrTable3[i], textsPosTable3[i], 107 - 15, 0xF6, -1, 0);
+}
+
+bool IgorEngine::handleOptionsMenu_handleKeyDownCtrl(int key) {
+ switch (key) {
+ case Common::KEYCODE_ESCAPE:
+ return true;
+ case Common::KEYCODE_RETURN:
+ if (_gameState.talkSpeed == 5) {
+ _gameState.talkSpeed = 1;
+ } else {
+ ++_gameState.talkSpeed;
+ }
+ handleOptionsMenu_paintCtrl();
+ break;
+ }
+ return false;
+}
+
+void IgorEngine::handleOptionsMenu() {
+ hideCursor();
+ memcpy(_paletteBuffer, _currentPalette, 768);
+ memset(_screenVGA + 144 * 320, 0, 11 * 320);
+ _system->copyRectToScreen(_screenVGA, 320, 0, 0, 320, 200);
+ for (int m = 3; m < 22; m += 3) {
+ for (int i = 1 * 3; i <= 245 * 3; ++i) {
+ if (_paletteBuffer[i] >= m) {
+ _currentPalette[i] = MAX<int>(_paletteBuffer[i] - m, _currentPalette[i] - 3);
+ }
+ }
+ setPaletteRange(1, 245);
+ _system->updateScreen();
+ _system->delayMillis(1000 / 60);
+ }
+ setPaletteColor(255, 35, 35, 23);
+
+ memcpy(_screenTextLayer, _screenVGA + 4800, 36800);
+
+ uint8 *optionsMenu = loadData(IMG_OptionsMenu);
+ for (int i = 0; i < 36800; ++i) {
+ if (optionsMenu[i]) {
+ _screenTextLayer[i] = optionsMenu[i];
+ }
+ }
+ free(optionsMenu);
+ uint8 *optionsButton = loadData(IMG_OptionsButton);
+ drawButtonsBar(_screenTextLayer, optionsButton);
+ free(optionsButton);
+
+ const int yPosCaption = 18 - 15;
+ for (int i = 0; i < 5; ++i) {
+ drawString(_screenTextLayer, pages[i].captions[0], pages[i].xPos[0], yPosCaption, 0xF6, -1, 0);
+ }
+ redrawButton(_screenTextLayer, 0, true);
+
+ uint8 buttonsBarBackup[320 * 12];
+ int currentPage = 0;
+ bool menuLoop = true;
+ bool focusOnPage = false;
+ while (menuLoop && _currentPart != 255) {
+ int previousPage = currentPage;
+ Common::Event ev;
+ while (_eventMan->pollEvent(ev)) {
+ switch (ev.type) {
+ case Common::EVENT_QUIT:
+ _currentPart = 255;
+ _eventQuitGame = true;
+ break;
+ case Common::EVENT_KEYDOWN:
+ if (focusOnPage) {
+ if ((this->*pages[currentPage].handleKeyDownProc)(ev.kbd.keycode)) {
+ memcpy(_screenTextLayer + 3 * 320, buttonsBarBackup, 320 * 12);
+ for (int y = 22; y <= 110; ++y) {
+ memset(_screenTextLayer + y * 320 + 43 + 4, 0xF8, 226);
+ }
+ focusOnPage = false;
+ }
+ } else {
+ switch (ev.kbd.keycode) {
+ case Common::KEYCODE_ESCAPE:
+ menuLoop = false;
+ break;
+ case Common::KEYCODE_RETURN:
+ if (currentPage == kPagePlay) {
+ menuLoop = false;
+ } else {
+ memcpy(buttonsBarBackup, _screenTextLayer + 3 * 320, 320 * 12);
+ for (int y = 0; y <= 11; ++y) {
+ memset(_screenTextLayer + (y + 3) * 320 + 44, 0xF8, 232);
+ }
+ drawString(_screenTextLayer, pages[currentPage].captions[1], pages[currentPage].xPos[1], yPosCaption, 0xFB, -1, 0);
+ (this->*pages[currentPage].paintProc)();
+ focusOnPage = true;
+ }
+ break;
+ case Common::KEYCODE_LEFT:
+ --currentPage;
+ if (currentPage < 0) {
+ currentPage = 0;
+ }
+ break;
+ case Common::KEYCODE_RIGHT:
+ ++currentPage;
+ if (currentPage > 4) {
+ currentPage = 4;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ if (previousPage != currentPage) {
+ redrawButton(_screenTextLayer, previousPage, false);
+ redrawButton(_screenTextLayer, currentPage, true);
+ }
+ _system->delayMillis(10);
+ _system->copyRectToScreen(_screenTextLayer, 320, 0, 15, 320, 115);
+ _system->updateScreen();
+ }
+
+ for (int m = 21; m >= 3; m -= 3) {
+ for (int i = 1 * 3; i <= 245 * 3; ++i) {
+ if (_paletteBuffer[i] >= m) {
+ _currentPalette[i] = MIN<int>(_paletteBuffer[i], _currentPalette[i] + 3);
+ }
+ }
+ setPaletteRange(1, 245);
+ _system->updateScreen();
+ _system->delayMillis(1000 / 60);
+ }
+}
+
+void IgorEngine::handlePause() {
+ drawActionSentence("GAME PAUSED", 0xFB);
+ do {
+ waitForTimer();
+ } while (!_inputVars[kInputPause]);
+ memset(_inputVars, 0, sizeof(_inputVars));
+}
+
+} // namespace Igor
diff --git a/engines/igor/module.mk b/engines/igor/module.mk
new file mode 100644
index 0000000000..8c42a36a08
--- /dev/null
+++ b/engines/igor/module.mk
@@ -0,0 +1,44 @@
+MODULE := engines/igor
+
+MODULE_OBJS := \
+ detection.o \
+ igor.o \
+ menu.o \
+ staticres.o \
+ parts/part_04.o \
+ parts/part_05.o \
+ parts/part_06.o \
+ parts/part_12.o \
+ parts/part_13.o \
+ parts/part_14.o \
+ parts/part_15.o \
+ parts/part_16.o \
+ parts/part_17.o \
+ parts/part_18.o \
+ parts/part_19.o \
+ parts/part_21.o \
+ parts/part_22.o \
+ parts/part_23.o \
+ parts/part_24.o \
+ parts/part_25.o \
+ parts/part_26.o \
+ parts/part_27.o \
+ parts/part_28.o \
+ parts/part_30.o \
+ parts/part_31.o \
+ parts/part_33.o \
+ parts/part_36.o \
+ parts/part_37.o \
+ parts/part_75.o \
+ parts/part_85.o \
+ parts/part_90.o \
+ parts/part_95.o \
+ parts/part_main.o
+
+# This module can be built as a plugin
+ifdef BUILD_PLUGINS
+PLUGIN := 1
+endif
+
+# Include common rules
+include $(srcdir)/rules.mk
diff --git a/engines/igor/parts/part_04.cpp b/engines/igor/parts/part_04.cpp
new file mode 100644
index 0000000000..7090a64513
--- /dev/null
+++ b/engines/igor/parts/part_04.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 "igor/igor.h"
+
+namespace Igor {
+
+void IgorEngine::PART_04_EXEC_ACTION(int action) {
+ debug(kDebugGame, "PART_04_EXEC_ACTION %d", action);
+ switch (action) {
+ case 101:
+ _currentPart = 120;
+ break;
+ case 102:
+ case 103:
+ case 104:
+ ADD_DIALOGUE_TEXT(102, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 105:
+ if (_objectsState[111] == 0) {
+ _currentPart = 170;
+ } else {
+ _currentPart = 770;
+ }
+ break;
+ case 106:
+ _currentPart = 50;
+ break;
+ default:
+ error("PART_04_EXEC_ACTION unhandled action %d", action);
+ break;
+ }
+}
+
+void IgorEngine::PART_04_CLEAR_OBJECT_STATE_84(int num) {
+ _objectsState[84] = 0;
+}
+
+void IgorEngine::PART_04() {
+ if (_objectsState[106] == 1) {
+ _currentPart = 730;
+ playMusic(1);
+ return;
+ }
+ if (_objectsState[107] == 1) {
+ _objectsState[107] = 0;
+ _currentPart = 750;
+ playMusic(1);
+ return;
+ }
+ _gameState.enableLight = 1;
+ loadRoomData(PAL_Map, IMG_Map, BOX_Map, MSK_Map, TXT_Map);
+ loadActionData(DAT_Map);
+ _roomDataOffsets = PART_04_ROOM_DATA_OFFSETS;
+ SET_EXEC_ACTION_FUNC(1, &IgorEngine::PART_04_EXEC_ACTION);
+ PART_04_CLEAR_OBJECT_STATE_84(255);
+ memcpy(_screenVGA, _screenLayer1, 46080);
+ fadeInPalette(768);
+ _currentAction.verb = kVerbWalk;
+ if (_gameState.musicNum != 2) {
+ playMusic(2);
+ }
+ _walkData[0].x = 160;
+ _walkData[0].y = 133;
+ _walkData[0].scaleWidth = 49;
+ _walkData[0].scaleHeight = 49;
+ _walkDataLastIndex = 1;
+ _walkDataCurrentIndex = 1;
+ showCursor();
+ _gameState.igorMoving = false;
+ while (_currentPart == 40) {
+ handleRoomInput();
+ if (compareGameTick(19, 32)) {
+ handleRoomDialogue();
+ }
+ if (compareGameTick(4, 8)) {
+ handleRoomInventoryScroll();
+ }
+ scrollPalette(200, 207);
+ setPaletteRange(200, 207);
+ if (compareGameTick(1)) {
+ handleRoomLight();
+ }
+ scrollPalette(184, 199);
+ setPaletteRange(184, 199);
+ waitForTimer();
+ }
+ memcpy(_paletteBuffer, _currentPalette, 624);
+ fadeOutPalette(624);
+}
+
+} // namespace Igor
diff --git a/engines/igor/parts/part_05.cpp b/engines/igor/parts/part_05.cpp
new file mode 100644
index 0000000000..8a938ef587
--- /dev/null
+++ b/engines/igor/parts/part_05.cpp
@@ -0,0 +1,291 @@
+/* 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/system.h"
+
+#include "igor/igor.h"
+
+namespace Igor {
+
+void IgorEngine::PART_05_EXEC_ACTION(int action) {
+ debug(kDebugGame, "PART_05_EXEC_ACTION %d", action);
+ switch (action) {
+ case 101:
+ ADD_DIALOGUE_TEXT(201, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 102:
+ PART_05_ACTION_102();
+ break;
+ case 103:
+ PART_05_ACTION_103();
+ break;
+ case 104:
+ ADD_DIALOGUE_TEXT(203, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 105:
+ _currentPart = 40;
+ break;
+ default:
+ error("PART_05_EXEC_ACTION unhandled action %d", action);
+ break;
+ }
+}
+
+void IgorEngine::PART_05_ACTION_102() {
+ uint8 *walkTable3 = loadData(WLK_Bridge3);
+ uint8 *walkTable4 = loadData(WLK_Bridge4);
+ int xPos = 220;
+ int yPos = 0;
+ int i = 1;
+ do {
+ if (compareGameTick(1, 16)) {
+ for (int y = 0; y <= 143; ++y) {
+ memcpy(_screenLayer2 + y * 320, _screenLayer1 + y * 320 + i * 8, 320 - i * 8);
+ memcpy(_screenLayer2 + y * 320 + 320 - i * 8, _animFramesBuffer + y * 224, i * 8);
+ }
+ if (i < 15) {
+ xPos += _walkScaleTable[0x8F9 + _walkCurrentFrame];
+ assert(xPos >= 205);
+ yPos = walkTable3[xPos - 205];
+ WalkData::setNextFrame(kFacingPositionRight, _walkCurrentFrame);
+ } else {
+ _walkCurrentFrame = 0;
+ }
+ int yOffset = (yPos - 50) * 320 + xPos - 15 - i * 8;
+ for (_gameState.counter[1] = 0; _gameState.counter[1] <= 49; ++_gameState.counter[1]) {
+ yOffset += 320;
+ _gameState.counter[0] = yPos - 49 + _gameState.counter[1];
+ for (_gameState.counter[2] = 0; _gameState.counter[2] <= 29; ++_gameState.counter[2]) {
+ _gameState.counter[3] = xPos - 15 + _gameState.counter[2];
+ const int offset = _gameState.counter[0] * 134 + _gameState.counter[3];
+ if (_gameState.counter[0] >= 92 && _gameState.counter[0] <= 110 && offset >= 12533 && walkTable4[offset - 12533] == 1) {
+ continue;
+ }
+ uint8 color = _facingIgorFrames[kFacingPositionRight - 1][_walkCurrentFrame * 1500 + _gameState.counter[1] * 30 + _gameState.counter[2]];
+ if (color != 0) {
+ _screenLayer2[yOffset + _gameState.counter[2]] = color;
+ }
+ }
+ }
+ memcpy(_screenVGA, _screenLayer2, 46080);
+ ++i;
+ }
+ PART_05_UPDATE_ROOM_BACKGROUND();
+ waitForTimer();
+ } while (i != 29);
+ free(walkTable3);
+ free(walkTable4);
+ WalkData *wd = &_walkData[0];
+ wd->setPos(xPos - 224, yPos, 2, 0);
+ wd->setDefaultScale();
+ _currentPart = 60;
+}
+
+void IgorEngine::PART_05_ACTION_103() {
+ int i = 0;
+ do {
+ if (compareGameTick(1)) {
+ const int offset = 27526;
+ for (int j = 0; j <= 48; ++j) {
+ const uint8 *src = _animFramesBuffer + 0x7E18 + i * 1470 + j * 30;
+ memcpy(_screenVGA + j * 320 + offset, src, 30);
+ }
+ ++i;
+ }
+ PART_05_UPDATE_ROOM_BACKGROUND();
+ waitForTimer();
+ } while (i != 3);
+ addObjectToInventory(21, 56);
+ _objectsState[60] = 1;
+ PART_05_HELPER_4(255);
+}
+
+void IgorEngine::PART_05_UPDATE_ROOM_BACKGROUND() {
+ if (compareGameTick(61)) {
+ scrollPalette(160, 167);
+ setPaletteRange(160, 167);
+ }
+ if (compareGameTick(2, 8)) {
+ scrollPalette(168, 178);
+ setPaletteRange(168, 178);
+ }
+ if (compareGameTick(13, 16)) {
+ scrollPalette(179, 184);
+ setPaletteRange(179, 184);
+ }
+ if (compareGameTick(5, 32)) {
+ scrollPalette(185, 191);
+ setPaletteRange(185, 191);
+ }
+ if (compareGameTick(1)) {
+ switch (getRandomNumber(200)) {
+ case 0:
+ playSound(18, 1);
+ break;
+ case 3:
+ playSound(21, 1);
+ break;
+ case 9:
+ playSound(22, 1);
+ break;
+ case 17:
+ playSound(23, 1);
+ break;
+ }
+ }
+ if (_gameState.talkMode == kTalkModeTextOnly || !_gameState.dialogueTextRunning) {
+ playSound(17, 1);
+ }
+}
+
+void IgorEngine::PART_05_HELPER_1() {
+ const int offset = 23521;
+ for (int i = 0; i <= 48; ++i) {
+ memcpy(_animFramesBuffer + 0xDEA8 + i * 23 - 1, _screenLayer1 + i * 320 + offset, 23);
+ memcpy(_screenLayer1 + i * 320 + offset, _animFramesBuffer + 0x95C7 + i * 23, 23);
+ }
+}
+
+void IgorEngine::PART_05_HELPER_2() {
+ const int offset = 28668;
+ for (int i = 0; i <= 32; ++i) {
+ const uint8 *src = _animFramesBuffer + 0x7E54 + i * 23;
+ memcpy(_screenLayer1 + i * 320 + offset, src, 23);
+ }
+}
+
+void IgorEngine::PART_05_HELPER_3(int frame) {
+ const int offset = 26756;
+ for (int i = 0; i <= 5; ++i) {
+ const uint8 *src = _animFramesBuffer + 0x7E00 + frame * 42 + i * 7;
+ memcpy(_screenLayer1 + i * 320 + offset, src, 7);
+ }
+}
+
+void IgorEngine::PART_05_HELPER_4(int num) {
+ if (_objectsState[60] == 0) {
+ PART_05_HELPER_5(0);
+ return;
+ }
+ PART_05_HELPER_5(1);
+ _roomObjectAreasTable[24].object = 0;
+ for (int i = 27; i <= 29; ++i) {
+ _roomObjectAreasTable[i].object = 0;
+ }
+}
+
+void IgorEngine::PART_05_HELPER_5(int frame) {
+ const int offset = 41926;
+ for (int i = 0; i <= 2; ++i) {
+ const uint8 *src = _animFramesBuffer + 0x7E00 + frame * 12 + i * 4;
+ memcpy(_screenLayer1 + i * 320 + offset, src, 4);
+ }
+}
+
+void IgorEngine::PART_05_HELPER_6() {
+ _walkData[0].setPos(0, 141, 2, 0);
+ _walkData[0].setDefaultScale();
+ _walkDataLastIndex = 0;
+ _walkDataCurrentIndex = 1;
+ buildWalkPath(0, 141, 51, 123);
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+}
+
+void IgorEngine::PART_05() {
+ _gameState.enableLight = 1;
+ loadRoomData(PAL_SpringRock, IMG_SpringRock, BOX_SpringRock, MSK_SpringRock, TXT_SpringRock);
+ SET_PAL_240_48_1();
+ static const int anm2[] = { FRM_SpringRock1, FRM_SpringRock2, 0 };
+ loadAnimData(anm2, 0x7E00);
+ static const int anm3[] = { FRM_SpringRock3, FRM_SpringRock4, 0 };
+ loadAnimData(anm3, 0x81AE);
+ static const int anm4[] = { FRM_SpringRock5, FRM_SpringRock6, 0 };
+ loadAnimData(anm4, 0xA763);
+ if (_objectsState[61] != 0) {
+ PART_05_HELPER_1();
+ }
+ if (_objectsState[63] != 0) {
+ PART_05_HELPER_2();
+ }
+ if (_objectsState[62] != 0) {
+ PART_05_HELPER_3(0);
+ }
+ for (int i = 0; i <= 143; ++i) {
+ memcpy(_animFramesBuffer + i * 224, _screenLayer1 + i * 320 + 96, 224);
+ }
+ loadRoomData(PAL_SpringBridge, IMG_SpringBridge, BOX_SpringBridge, MSK_SpringBridge, TXT_SpringBridge);
+ static const int anm1[] = { FRM_SpringBridge1, FRM_SpringBridge2, 0 };
+ loadAnimData(anm1, 0x7E00);
+ SET_EXEC_ACTION_FUNC(1, &IgorEngine::PART_05_EXEC_ACTION);
+ _updateRoomBackground = &IgorEngine::PART_05_UPDATE_ROOM_BACKGROUND;
+ PART_05_HELPER_4(255);
+ loadActionData(DAT_SpringRock);
+ _roomDataOffsets = PART_05_ROOM_DATA_OFFSETS;
+ setRoomWalkBounds(0, 0, 319, 143);
+ _walkDataLastIndex = 1;
+ _walkDataCurrentIndex = 1;
+ if (_currentPart == 50) {
+ PART_05_HELPER_6();
+ }
+ showCursor();
+ _gameState.igorMoving = false;
+ while (_currentPart >= 50 && _currentPart <= 52) {
+ handleRoomInput();
+ if (compareGameTick(1, 16)) {
+ handleRoomIgorWalk();
+ }
+ if (compareGameTick(19, 32)) {
+ handleRoomDialogue();
+ }
+ if (compareGameTick(4, 8)) {
+ handleRoomInventoryScroll();
+ }
+ if (compareGameTick(1)) {
+ handleRoomLight();
+ }
+ PART_05_UPDATE_ROOM_BACKGROUND();
+ waitForTimer();
+ }
+ stopSound();
+ if (_currentPart == 255) {
+ fadeOutPalette(768);
+ } else if (_currentPart != 60) {
+ if (_objectsState[63] == 0) {
+ _objectsState[61] = _objectsState[62] = _objectsState[63] = 1;
+ }
+ memcpy(_currentPalette, _paletteBuffer, 624);
+ fadeOutPalette(624);
+ }
+ _updateRoomBackground = 0;
+}
+
+} // namespace Igor
diff --git a/engines/igor/parts/part_06.cpp b/engines/igor/parts/part_06.cpp
new file mode 100644
index 0000000000..e39e38b4d0
--- /dev/null
+++ b/engines/igor/parts/part_06.cpp
@@ -0,0 +1,419 @@
+/* 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/system.h"
+
+#include "igor/igor.h"
+
+namespace Igor {
+
+void IgorEngine::PART_06_EXEC_ACTION(int action) {
+ debug(kDebugGame, "PART_06_EXEC_ACTION %d", action);
+ switch (action) {
+ case 101:
+ ADD_DIALOGUE_TEXT(201, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 102:
+ PART_06_ACTION_102();
+ break;
+ case 103:
+ PART_06_ACTION_103();
+ break;
+ case 104:
+ ADD_DIALOGUE_TEXT(203, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 105:
+ PART_06_ACTION_105();
+ break;
+ case 106:
+ ADD_DIALOGUE_TEXT(204, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 107:
+ PART_06_ACTION_107();
+ break;
+ case 108:
+ PART_06_ACTION_108();
+ break;
+ default:
+ error("PART_06_EXEC_ACTION unhandled action %d", action);
+ break;
+ }
+}
+
+void IgorEngine::PART_06_ACTION_102() {
+ uint8 *walkTable1 = loadData(WLK_Bridge1);
+ uint8 *walkTable2 = loadData(WLK_Bridge2);
+ int xPos = 323;
+ int yPos = 0;
+ int i = 1;
+ do {
+ if (compareGameTick(1, 16)) {
+ for (int y = 0; y <= 143; ++y) {
+ memcpy(_screenLayer2 + y * 320 + i * 8, _screenLayer1 + y * 320, 320 - i * 8);
+ memcpy(_screenLayer2 + y * 320, _animFramesBuffer + y * 224 + 224 - i * 8, i * 8);
+ }
+ if (i < 15) {
+ xPos -= _walkScaleTable[0x8F9 + _walkCurrentFrame];
+ assert(xPos >= 205);
+ yPos = walkTable1[xPos - 205];
+ WalkData::setNextFrame(kFacingPositionLeft, _walkCurrentFrame);
+ } else {
+ _walkCurrentFrame = 0;
+ }
+ int yOffset = (yPos - 50) * 320 + xPos - 239 + i * 8;
+ for (_gameState.counter[1] = 0; _gameState.counter[1] <= 49; ++_gameState.counter[1]) {
+ yOffset += 320;
+ _gameState.counter[0] = yPos - 49 + _gameState.counter[1];
+ for (_gameState.counter[2] = 0; _gameState.counter[2] <= 29; ++_gameState.counter[2]) {
+ _gameState.counter[3] = xPos - 15 + _gameState.counter[2];
+ const int offset = _gameState.counter[0] * 134 + _gameState.counter[3];
+ if (_gameState.counter[0] >= 92 && _gameState.counter[0] <= 110 && offset >= 12533 && walkTable2[offset - 12533] == 1) {
+ continue;
+ }
+ uint8 color = _facingIgorFrames[kFacingPositionLeft - 1][_walkCurrentFrame * 1500 + _gameState.counter[1] * 30 + _gameState.counter[2]];
+ if (color != 0) {
+ _screenLayer2[yOffset + _gameState.counter[2]] = color;
+ }
+ }
+ }
+ memcpy(_screenVGA, _screenLayer2, 46080);
+ ++i;
+ }
+ PART_06_UPDATE_ROOM_BACKGROUND();
+ waitForTimer();
+ } while (i != 29);
+ free(walkTable1);
+ free(walkTable2);
+ WalkData *wd = &_walkData[0];
+ wd->setPos(xPos, yPos, 4, 0);
+ wd->setDefaultScale();
+ _currentPart = 51;
+}
+
+void IgorEngine::PART_06_ACTION_103() {
+ ADD_DIALOGUE_TEXT(215, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ PART_06_HELPER_8(0);
+ ADD_DIALOGUE_TEXT(216, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startCutsceneDialogue(170, 69, 55, 37, 63);
+ waitForEndOfCutsceneDialogue(170, 69, 55, 37, 63);
+ PART_06_HANDLE_DIALOGUE_PHOTOGRAPHER();
+ PART_06_HELPER_6(255);
+}
+
+void IgorEngine::PART_06_ACTION_105() {
+ _gameTicks = 0;
+ for (int i = 0; i <= 3; ++i) {
+ if (compareGameTick(1)) {
+ const int offset = 22568;
+ for (int j = 0; j <= 48; ++j) {
+ const uint8 *src = _animFramesBuffer + 0x81AE + i * 1715 + j * 35;
+ memcpy(_screenVGA + 320 * j + offset, src, 35);
+ }
+ }
+ PART_06_UPDATE_ROOM_BACKGROUND();
+ waitForTimer();
+ }
+ addObjectToInventory(36, 71);
+ _objectsState[62] = 0;
+ PART_06_HELPER_6(255);
+}
+
+void IgorEngine::PART_06_ACTION_107() {
+ PART_06_HELPER_8(0);
+ ADD_DIALOGUE_TEXT(205, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ ADD_DIALOGUE_TEXT(206, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startCutsceneDialogue(170, 69, 55, 37, 63);
+ waitForEndOfCutsceneDialogue(170, 69, 55, 37, 63);
+}
+
+void IgorEngine::PART_06_ACTION_108() {
+ PART_06_HELPER_8(0);
+ ADD_DIALOGUE_TEXT(208, 2);
+ ADD_DIALOGUE_TEXT(210, 2);
+ SET_DIALOGUE_TEXT(1, 2);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ ADD_DIALOGUE_TEXT(212, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startCutsceneDialogue(170, 69, 55, 37, 63);
+ waitForEndOfCutsceneDialogue(170, 69, 55, 37, 63);
+ int i = 7;
+ _gameTicks = 0;
+ do {
+ if (compareGameTick(1, 32)) {
+ const uint8 *src = _animFramesBuffer + 0xA763 + READ_LE_UINT16(_animFramesBuffer + 0xDB95 + i * 2) - 1;
+ decodeAnimFrame(src, _screenVGA, true);
+ ++i;
+ }
+ PART_06_UPDATE_ROOM_BACKGROUND();
+ if (i == 7) {
+ stopSound();
+ playSound(19, 1);
+ }
+ waitForTimer();
+ } while (i != 28);
+ removeObjectFromInventory(61);
+ _objectsState[61] = 0;
+ PART_06_HELPER_6(255);
+ _gameState.unkF = false;
+ ADD_DIALOGUE_TEXT(213, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+}
+
+void IgorEngine::PART_06_UPDATE_DIALOGUE_PHOTOGRAPHER(int action) {
+ switch (action) {
+ case kUpdateDialogueAnimEndOfSentence:
+ PART_06_HELPER_7(1);
+ break;
+ case kUpdateDialogueAnimMiddleOfSentence:
+ PART_06_HELPER_7(getRandomNumber(6) + 1);
+ break;
+ case kUpdateDialogueAnimStanding:
+ PART_06_HELPER_7(1);
+ break;
+ }
+}
+
+void IgorEngine::PART_06_HANDLE_DIALOGUE_PHOTOGRAPHER() {
+ loadDialogueData(DLG_SpringPhotographer);
+ _updateDialogue = &IgorEngine::PART_06_UPDATE_DIALOGUE_PHOTOGRAPHER;
+ handleDialogue(170, 69, 55, 37, 63);
+ _updateDialogue = 0;
+}
+
+void IgorEngine::PART_06_UPDATE_ROOM_BACKGROUND() {
+ if (compareGameTick(61)) {
+ scrollPalette(160, 167);
+ setPaletteRange(160, 167);
+ }
+ if (compareGameTick(2, 8)) {
+ scrollPalette(168, 178);
+ setPaletteRange(168, 178);
+ }
+ if (compareGameTick(13, 16)) {
+ scrollPalette(179, 184);
+ setPaletteRange(179, 184);
+ }
+ if (compareGameTick(5, 32)) {
+ scrollPalette(185, 191);
+ setPaletteRange(185, 191);
+ }
+ if (compareGameTick(1)) {
+ switch (getRandomNumber(20)) {
+ case 0:
+ playSound(18, 1);
+ break;
+ case 3:
+ playSound(21, 1);
+ break;
+ case 9:
+ playSound(22, 1);
+ break;
+ case 17:
+ playSound(23, 1);
+ break;
+ }
+ }
+}
+
+void IgorEngine::PART_06_HELPER_1(int frame) {
+ const int offset = 41926;
+ for (int i = 0; i <= 2; ++i) {
+ const uint8 *src = _animFramesBuffer + 0x7E00 + frame * 12 + i * 4;
+ memcpy(_screenLayer1 + i * 320 + offset, src, 4);
+ }
+}
+
+void IgorEngine::PART_06_HELPER_2() {
+ const int offset = 23521;
+ for (int i = 0; i <= 48; ++i) {
+ const uint8 *src = _screenLayer1 + i * 320 + offset;
+ memcpy(_animFramesBuffer + 0xDEA8 + i * 23 - 1, src, 23);
+ }
+}
+
+void IgorEngine::PART_06_HELPER_3() {
+ const int offset = 28668;
+ for (int i = 0; i <= 32; ++i) {
+ const uint8 *src = _animFramesBuffer + 0x7E54 + i * 23;
+ memcpy(_screenLayer1 + i * 320 + offset, src, 23);
+ memcpy(_screenVGA + i * 320 + offset, src, 23);
+ }
+}
+
+void IgorEngine::PART_06_HELPER_6(int num) {
+ if (num == 2 || num == 255) {
+ if (_objectsState[61] == 1) {
+ PART_06_HELPER_14();
+ _roomObjectAreasTable[3].object = 0;
+ _roomObjectAreasTable[13].area = 0;
+ _roomObjectAreasTable[15].area = 0;
+ _roomObjectAreasTable[17].area = 0;
+ _roomObjectAreasTable[18].area = 0;
+ } else {
+ PART_06_HELPER_12();
+ _roomObjectAreasTable[2].object = 0;
+ _roomObjectAreasTable[15].object = 0;
+ _roomObjectAreasTable[18].object = 0;
+ _roomObjectAreasTable[3].object = 0;
+ _roomObjectAreasTable[13].area = 3;
+ _roomObjectAreasTable[15].area = 3;
+ _roomObjectAreasTable[17].area = 3;
+ _roomObjectAreasTable[18].area = 3;
+ }
+ }
+ if (num == 3 || num == 255) {
+ if (_objectsState[62] == 1) {
+ PART_06_HELPER_13(0);
+ } else {
+ PART_06_HELPER_13(1);
+ _roomObjectAreasTable[3].object = 0;
+ }
+ }
+}
+
+void IgorEngine::PART_06_HELPER_7(int frame) {
+ const uint8 *src = _animFramesBuffer + 0xA763 + READ_LE_UINT16(_animFramesBuffer + 0xDB95 + frame * 2) - 1;
+ decodeAnimFrame(src, _screenVGA, true);
+}
+
+void IgorEngine::PART_06_HELPER_8(int frame) {
+ const int offset = 23521;
+ for (int i = 0; i <= 48; ++i) {
+ const uint8 *src = _animFramesBuffer + 0x95C7 + i * 23 + frame * 1127;
+ memcpy(_screenVGA + i * 320 + offset, src, 23);
+ }
+}
+
+void IgorEngine::PART_06_HELPER_12() {
+ const int offset = 23521;
+ for (int i = 0; i <= 48; ++i) {
+ const uint8 *src = _animFramesBuffer + 0xDEA7 + i * 23;
+ memcpy(_screenLayer1 + i * 320 + offset, src, 23);
+ }
+}
+
+void IgorEngine::PART_06_HELPER_13(int frame) {
+ const int offset = 26756;
+ for (int i = 0; i <= 5; ++i) {
+ const uint8 *src = _animFramesBuffer + 0x7E00 + frame * 42 + i * 7;
+ memcpy(_screenLayer1 + i * 320 + offset, src, 7);
+ }
+}
+
+void IgorEngine::PART_06_HELPER_14() {
+ const int offset = 23521;
+ for (int i = 0; i <= 48; ++i) {
+ const uint8 *src = _animFramesBuffer + 0x95C7 + i * 23;
+ memcpy(_screenLayer1 + i * 320 + offset, src, 23);
+ }
+}
+
+void IgorEngine::PART_06_HELPER_15(int frame) {
+ const uint8 *src = _animFramesBuffer + 0xA763 + READ_LE_UINT16(_animFramesBuffer + 0xDB95 + frame * 2) - 1;
+ decodeAnimFrame(src, _screenVGA, true);
+}
+
+void IgorEngine::PART_06() {
+ _gameState.enableLight = 1;
+ loadRoomData(PAL_SpringBridge, IMG_SpringBridge, BOX_SpringBridge, MSK_SpringBridge, TXT_SpringBridge);
+ static const int anm1[] = { FRM_SpringBridge1, FRM_SpringBridge2, 0 };
+ loadAnimData(anm1, 0x7E00);
+ if (_objectsState[60] == 0) {
+ PART_06_HELPER_1(0);
+ }
+ for (int i = 0; i <= 143; ++i) {
+ memcpy(_animFramesBuffer + i * 224, _screenLayer1 + i * 320, 224);
+ }
+ loadRoomData(PAL_SpringRock, IMG_SpringRock, BOX_SpringRock, MSK_SpringRock, TXT_SpringRock);
+ SET_PAL_240_48_1();
+ static const int anm2[] = { FRM_SpringRock1, FRM_SpringRock2, 0 };
+ loadAnimData(anm2, 0x7E00);
+ static const int anm3[] = { FRM_SpringRock3, FRM_SpringRock4, 0 };
+ loadAnimData(anm3, 0x81AE);
+ static const int anm4[] = { FRM_SpringRock5, FRM_SpringRock6, 0 };
+ loadAnimData(anm4, 0xA763);
+ PART_06_HELPER_2();
+ SET_EXEC_ACTION_FUNC(1, &IgorEngine::PART_06_EXEC_ACTION);
+ _updateRoomBackground = &IgorEngine::PART_06_UPDATE_ROOM_BACKGROUND;
+ PART_06_HELPER_6(255);
+ if (_objectsState[63] == 1) {
+ PART_06_HELPER_3();
+ }
+ if (_currentPart == 61) {
+ SET_PAL_208_96_1();
+ drawVerbsPanel();
+ drawInventory(1, 0);
+ _currentAction.verb = kVerbWalk;
+ memcpy(_paletteBuffer, _currentPalette, 624);
+ fadeInPalette(768);
+ }
+ loadActionData(DAT_SpringBridge);
+ _roomDataOffsets = PART_06_ROOM_DATA_OFFSETS;
+ _walkDataLastIndex = 1;
+ _walkDataCurrentIndex = 1;
+ showCursor();
+ _gameState.igorMoving = false;
+ _gameState.unkF = (_objectsState[61] == 1);
+ while (_currentPart >= 60 && _currentPart <= 61) {
+ setRoomWalkBounds(0, 0, _objectsState[61] == 0 ? 234 : 142, 143);
+ handleRoomInput();
+ if (compareGameTick(1, 16)) {
+ handleRoomIgorWalk();
+ }
+ if (compareGameTick(19, 32)) {
+ handleRoomDialogue();
+ }
+ if (compareGameTick(4, 8)) {
+ handleRoomInventoryScroll();
+ }
+ if (compareGameTick(1)) {
+ handleRoomLight();
+ }
+ PART_06_UPDATE_ROOM_BACKGROUND();
+ if (compareGameTick(61) && _gameState.unkF && getRandomNumber(10) == 0) {
+ PART_06_HELPER_8(getRandomNumber(4));
+ }
+ waitForTimer();
+ }
+ _updateRoomBackground = 0;
+}
+
+} // namespace Igor
diff --git a/engines/igor/parts/part_12.cpp b/engines/igor/parts/part_12.cpp
new file mode 100644
index 0000000000..055ce1eb1e
--- /dev/null
+++ b/engines/igor/parts/part_12.cpp
@@ -0,0 +1,581 @@
+/* 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 "igor/igor.h"
+
+namespace Igor {
+
+static const uint8 PART_12_DATA_ANIM_1[10] = { 0, 1, 2, 1, 2, 1, 2, 1, 2, 3 };
+
+static const uint8 PART_12_DATA_ANIM_2[16] = { 0, 1, 2, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 5, 6, 7 };
+
+void IgorEngine::PART_12_EXEC_ACTION(int action) {
+ switch (action) {
+ case 101:
+ PART_12_ACTION_101();
+ break;
+ case 102:
+ ADD_DIALOGUE_TEXT(201, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 103:
+ if (_objectsState[44] == 0) {
+ ADD_DIALOGUE_TEXT(203, 2);
+ } else {
+ ADD_DIALOGUE_TEXT(205, 1);
+ }
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 104:
+ PART_12_ACTION_104();
+ break;
+ case 105:
+ PART_12_ACTION_105();
+ break;
+ case 106:
+ ADD_DIALOGUE_TEXT(207, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 107:
+ ADD_DIALOGUE_TEXT(206, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 108:
+ PART_12_ACTION_108();
+ break;
+ default:
+ error("PART_12_EXEC_ACTION unhandled action %d", action);
+ break;
+ }
+}
+
+void IgorEngine::PART_12_ACTION_101() {
+ for (int i = 9; i <= 10; ++i) {
+ _roomObjectAreasTable[i].area = 3;
+ }
+ --_walkDataLastIndex;
+ buildWalkPath(272, 94, 196, 64);
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ _gameState.unk10 = 1;
+ _gameTicks = 0;
+ do {
+ if (compareGameTick(1, 16)) {
+ if (_walkDataCurrentIndex > _walkDataLastIndex) {
+ _gameState.igorMoving = false;
+ _walkDataLastIndex = _walkDataCurrentIndex;
+ }
+ if (_gameState.igorMoving) {
+ moveIgor(_walkData[_walkDataCurrentIndex].posNum, _walkData[_walkDataCurrentIndex].frameNum);
+ ++_walkDataCurrentIndex;
+ }
+ }
+ if (compareGameTick(2, 32) && _gameState.unk10 < 8) {
+ if (_objectsState[44] == 0) {
+ const uint8 *src = _animFramesBuffer + 0x761 + READ_LE_UINT16(_animFramesBuffer + 0x1107 + _gameState.unk10 * 2) - 1;
+ decodeAnimFrame(src, _screenVGA, true);
+ }
+ ++_gameState.unk10;
+ }
+ waitForTimer();
+ } while (_gameState.igorMoving || _gameState.unk10 != 8);
+ _currentPart = 40;
+}
+
+void IgorEngine::PART_12_ACTION_104() {
+ _walkCurrentFrame = 2;
+ --_walkDataLastIndex;
+ _roomObjectAreasTable[_screenLayer2[33390]].area = _roomObjectAreasTable[_screenLayer2[34686]].area;
+ buildWalkPath(126, 108, 110, 104);
+ _roomObjectAreasTable[_screenLayer2[33390]].area = 0;
+ _walkDataCurrentIndex = 1;
+ moveIgor(_walkData[_walkDataCurrentIndex].posNum, _walkData[_walkDataCurrentIndex].frameNum);
+ waitForTimer(35);
+ playSound(13, 1);
+ _walkDataCurrentIndex = _walkDataLastIndex;
+ const uint8 *src = _animFramesBuffer + 0x395B + READ_LE_UINT16(_animFramesBuffer + 0xA444) - 1;
+ decodeAnimFrame(src, _screenVGA);
+ decodeAnimFrame(src, _screenLayer1);
+ moveIgor(_walkData[_walkDataCurrentIndex].posNum, _walkData[_walkDataCurrentIndex].frameNum);
+ waitForTimer(35);
+ _walkDataCurrentIndex = _walkDataLastIndex - 1;
+ src = _animFramesBuffer + 0x395B + READ_LE_UINT16(_animFramesBuffer + 0xA446) - 1;
+ decodeAnimFrame(src, _screenVGA);
+ decodeAnimFrame(src, _screenLayer1);
+ _walkData[_walkDataCurrentIndex].xPosChanged = 1;
+ _walkData[_walkDataCurrentIndex].yPosChanged = 1;
+ moveIgor(_walkData[_walkDataCurrentIndex].posNum, _walkData[_walkDataCurrentIndex].frameNum);
+ waitForTimer(35);
+ _walkData[0].setPos(127, 108, 4, 0);
+ _walkData[0].clipSkipX = 1;
+ _walkData[0].clipWidth = 30;
+ _walkData[0].scaleWidth = 50;
+ _walkData[0].xPosChanged = 1;
+ _walkData[0].dxPos = 10;
+ _walkData[0].yPosChanged = 1;
+ _walkData[0].dyPos = 3;
+ _walkData[0].scaleHeight = 1;
+ _walkDataCurrentIndex = 0;
+ _walkDataLastIndex = 1;
+ src = _animFramesBuffer + 0x395B + READ_LE_UINT16(_animFramesBuffer + 0xA448) - 1;
+ decodeAnimFrame(src, _screenVGA);
+ decodeAnimFrame(src, _screenLayer1);
+ moveIgor(4, 0);
+ PART_12_HANDLE_DIALOGUE_CHURCHMAN();
+ for (int i = 4; i >= 1; --i) {
+ src = _animFramesBuffer + 0x395B + READ_LE_UINT16(_animFramesBuffer + 0xA43E + i * 2) - 1;
+ decodeAnimFrame(src, _screenVGA);
+ if (i > 1) {
+ waitForTimer(35);
+ } else {
+ playSound(14, 1);
+ }
+ }
+ src = _animFramesBuffer + 0x395B + READ_LE_UINT16(_animFramesBuffer + 0xA440) - 1;
+ decodeAnimFrame(src, _screenVGA);
+ PART_12_HELPER_1(255);
+}
+
+void IgorEngine::PART_12_ACTION_105() {
+ if (_objectsState[44] == 1) {
+ ADD_DIALOGUE_TEXT(216, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ return;
+ }
+ memset(_screenVGA + 46080, 0, 17920);
+ _inventoryInfo[_inventoryInfo[62] - 1] = 0;
+ _inventoryInfo[62] = 0;
+ packInventory();
+ if (_inventoryInfo[72] > _inventoryInfo[73]) {
+ _inventoryInfo[72] = _inventoryOffsetTable[(_inventoryInfo[73] - 1) / 7];
+ }
+ const int animOffset = (_objectsState[45] == 0) ? 0x2543 : 0xBF1E;
+ for (int i = 1; i <= 9; ++i) {
+ const int offset = 30149;
+ for (int j = 0; j <= 48; ++j) {
+ const uint8 *src = _animFramesBuffer + animOffset + PART_12_DATA_ANIM_1[i] * 1715 + j * 35 + 0xF94C;
+ memcpy(_screenVGA + j * 320 + offset, src, 35);
+ }
+ waitForTimer(30);
+ }
+ ADD_DIALOGUE_TEXT(209, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ for (int i = 9; i <= 10; ++i) {
+ _roomObjectAreasTable[i].area = 3;
+ }
+ --_walkDataLastIndex;
+ buildWalkPath(95, 142, 196, 64);
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+ _gameState.unk10 = 1;
+ _gameTicks = 0;
+ do {
+ if (compareGameTick(2, 32) && _gameState.unk10 < 8) {
+ const uint8 *src = _animFramesBuffer + 0x761 + READ_LE_UINT16(_animFramesBuffer + 0x1107 + _gameState.unk10 * 2) - 1;
+ decodeAnimFrame(src, _screenVGA, true);
+ ++_gameState.unk10;
+ }
+ waitForTimer();
+ } while (_gameState.unk10 != 8);
+ --_walkDataLastIndex;
+ buildWalkPath(196, 64, 95, 142);
+ PART_12_HELPER_2();
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ _gameTicks = 0;
+ do {
+ if (compareGameTick(1, 16)) {
+ if (_walkDataCurrentIndex > _walkDataLastIndex) {
+ _gameState.igorMoving = false;
+ _walkDataLastIndex = _walkDataCurrentIndex;
+ }
+ if (_gameState.igorMoving) {
+ moveIgor(_walkData[_walkDataCurrentIndex].posNum, _walkData[_walkDataCurrentIndex].frameNum);
+ ++_walkDataCurrentIndex;
+ }
+ }
+ if (compareGameTick(2, 32)) {
+ _gameState.unk10 = getRandomNumber(2) + 7;
+ const uint8 *src = _animFramesBuffer + 0x761 + READ_LE_UINT16(_animFramesBuffer + 0x1107 + _gameState.unk10 * 2) - 1;
+ decodeAnimFrame(src, _screenVGA, true);
+ }
+ waitForTimer();
+ } while (_gameState.igorMoving);
+ decodeAnimFrame(_animFramesBuffer + 0x761 + READ_LE_UINT16(_animFramesBuffer + 0x1117) - 1, _screenVGA, true);
+ if (_objectsState[45] == 0) {
+ for (int i = 1; i <= 15; ++i) {
+ const uint8 *src = _animFramesBuffer + 0x1119 + READ_LE_UINT16(_animFramesBuffer + 0x2532 + PART_12_DATA_ANIM_2[i] * 2) - 1;
+ decodeAnimFrame(src, _screenVGA, true);
+ waitForTimer(45);
+ }
+ } else {
+ for (int i = 1; i <= 15; ++i) {
+ const uint8 *src = _animFramesBuffer + 0xA47A + READ_LE_UINT16(_animFramesBuffer + 0xBF0D + PART_12_DATA_ANIM_2[i] * 2) - 1;
+ decodeAnimFrame(src, _screenVGA, true);
+ waitForTimer(45);
+ }
+ }
+ drawVerbsPanel();
+ redrawVerb(kVerbWalk, true);
+ _currentAction.verb = kVerbWalk;
+ addObjectToInventory(24, 59);
+ _objectsState[44] = 1;
+ PART_12_HELPER_1(255);
+ ADD_DIALOGUE_TEXT(211, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+}
+
+void IgorEngine::PART_12_ACTION_108() {
+ _walkCurrentFrame = 2;
+ --_walkDataLastIndex;
+ _roomObjectAreasTable[_screenLayer2[28555]].area = _roomObjectAreasTable[_screenLayer2[34686]].area;
+ buildWalkPath(126, 108, 75, 89);
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ _gameState.unk10 = 1;
+ _gameTicks = 0;
+ do {
+ if (compareGameTick(1, 16)) {
+ if (_walkDataCurrentIndex > _walkDataLastIndex) {
+ _gameState.igorMoving = false;
+ _walkDataLastIndex = _walkDataCurrentIndex;
+ }
+ if (_gameState.igorMoving) {
+ moveIgor(_walkData[_walkDataCurrentIndex].posNum, _walkData[_walkDataCurrentIndex].frameNum);
+ ++_walkDataCurrentIndex;
+ }
+ }
+ if (compareGameTick(2, 32) && _gameState.unk10 < 8) {
+ if (_objectsState[44] == 0) {
+ const uint8 *src = _animFramesBuffer + 0x761 + READ_LE_UINT16(_animFramesBuffer + 0x1107 + _gameState.unk10 * 2) - 1;
+ decodeAnimFrame(src, _screenVGA, true);
+ }
+ ++_gameState.unk10;
+ }
+ waitForTimer();
+ } while (_gameState.igorMoving || _gameState.unk10 != 8);
+ _currentPart = 130;
+}
+
+void IgorEngine::PART_12_UPDATE_ROOM_BACKGROUND() {
+ if (compareGameTick(1) && getRandomNumber(15) == 0) {
+ switch (getRandomNumber(4)) {
+ case 0:
+ playSound(21, 1);
+ break;
+ case 1:
+ playSound(22, 1);
+ break;
+ case 2:
+ playSound(23, 1);
+ break;
+ case 3:
+ playSound(18, 1);
+ break;
+ }
+ }
+}
+
+void IgorEngine::PART_12_UPDATE_DIALOGUE_TOBIAS(int action) {
+ switch (action) {
+ case kUpdateDialogueAnimEndOfSentence:
+ PART_12_HELPER_8();
+ break;
+ case kUpdateDialogueAnimMiddleOfSentence:
+ PART_12_HELPER_10(6 + getRandomNumber(6));
+ break;
+ case kUpdateDialogueAnimStanding:
+ PART_12_HELPER_8();
+ break;
+ }
+}
+
+void IgorEngine::PART_12_HANDLE_DIALOGUE_CHURCHMAN() {
+ loadDialogueData(DLG_OutsideChurch);
+ _updateDialogue = &IgorEngine::PART_12_UPDATE_DIALOGUE_TOBIAS;
+ handleDialogue(95, 55, 51, 28, 63);
+ _updateDialogue = 0;
+}
+
+void IgorEngine::PART_12_HELPER_1(int num) {
+ if (num == 2 || num == 255) {
+ if (_objectsState[45] == 0) {
+ _roomActionsTable[169] = 104;
+ _roomActionsTable[175] = 104;
+ _roomActionsTable[177] = 104;
+ _roomActionsTable[179] = 104;
+ _roomActionsTable[181] = 104;
+ _roomActionsTable[185] = 104;
+ _roomActionsTable[187] = 104;
+ _roomActionsTable[170] = 3;
+ _roomActionsTable[176] = 3;
+ _roomActionsTable[178] = 3;
+ _roomActionsTable[180] = 3;
+ _roomActionsTable[182] = 3;
+ _roomActionsTable[186] = 3;
+ _roomActionsTable[188] = 3;
+ } else {
+ PART_12_HELPER_9();
+ _roomActionsTable[169] = 108;
+ _roomActionsTable[175] = 106;
+ _roomActionsTable[177] = 2;
+ _roomActionsTable[179] = 11;
+ _roomActionsTable[181] = 107;
+ _roomActionsTable[185] = 35;
+ _roomActionsTable[187] = 35;
+ _roomActionsTable[170] = 1;
+ _roomActionsTable[176] = 1;
+ _roomActionsTable[178] = 1;
+ _roomActionsTable[180] = 1;
+ _roomActionsTable[182] = 1;
+ _roomActionsTable[186] = 1;
+ _roomActionsTable[188] = 1;
+ }
+ }
+}
+
+void IgorEngine::PART_12_HELPER_2() {
+ for (int i = 9; i <= 10; ++i) {
+ _roomObjectAreasTable[i].area = 0;
+ }
+}
+
+void IgorEngine::PART_12_HELPER_3() {
+ decodeAnimFrame(_animFramesBuffer, _screenVGA, true);
+}
+
+void IgorEngine::PART_12_HELPER_4() {
+ SET_PAL_240_48_1();
+ SET_PAL_208_96_1();
+ fadeInPalette(768);
+ playSound(13, 1);
+ for (int i = 1; i <= 5; ++i) {
+ const uint8 *src = _animFramesBuffer + 0x395B + READ_LE_UINT16(_animFramesBuffer + 0xA43E + i * 2) - 1;
+ decodeAnimFrame(src, _screenVGA, true);
+ if (_objectsState[44] == 0) {
+ src = _animFramesBuffer + READ_LE_UINT16(_animFramesBuffer + 0x74B + i * 2) - 1;
+ decodeAnimFrame(src, _screenVGA, true);
+ }
+ waitForTimer(30);
+ }
+ if (_objectsState[44] == 0) {
+ for (int i = 6; i <= 10; ++i) {
+ const uint8 *src = _animFramesBuffer + READ_LE_UINT16(_animFramesBuffer + 0x74B + i * 2) - 1;
+ decodeAnimFrame(src, _screenVGA, true);
+ waitForTimer(30);
+ }
+ }
+ ADD_DIALOGUE_TEXT(212, 2);
+ ADD_DIALOGUE_TEXT(214, 1);
+ ADD_DIALOGUE_TEXT(215, 1);
+ SET_DIALOGUE_TEXT(1, 3);
+ _updateDialogue = &IgorEngine::PART_12_UPDATE_DIALOGUE_TOBIAS;
+ startCutsceneDialogue(95, 55, 51, 28, 63);
+ waitForEndOfCutsceneDialogue(95, 55, 51, 28, 63);
+ _updateDialogue = 0;
+ for (int i = 12; i <= 29; ++i){
+ const uint8 *src = _animFramesBuffer + 0x395B + READ_LE_UINT16(_animFramesBuffer + 0xA43E + i * 2) - 1;
+ decodeAnimFrame(src, _screenVGA, true);
+ waitForTimer(30);
+ }
+ if (_objectsState[44] == 0) {
+ for (int i = 1; i <= 8; ++i) {
+ const uint8 *src = _animFramesBuffer + 0x761 + READ_LE_UINT16(_animFramesBuffer + 0x1107 + i * 2) - 1;
+ decodeAnimFrame(src, _screenVGA, true);
+ waitForTimer(30);
+ }
+ }
+ waitForTimer(255);
+ fadeOutPalette(768);
+ _objectsState[45] = 1;
+ drawVerbsPanel();
+ drawInventory(_inventoryInfo[72], 0);
+ _currentPart = 40;
+}
+
+void IgorEngine::PART_12_HELPER_5() {
+ _walkData[0].setPos(196, 64, 2, 0);
+ _walkData[0].setDefaultScale();
+ _walkData[0].clipSkipX = 1;
+ _walkData[0].clipWidth = 30;
+ _walkDataLastIndex = 0;
+ _walkDataCurrentIndex = 1;
+ buildWalkPath(196, 64, 238, 104);
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ _gameState.unk10 = 1;
+ waitForTimer(15);
+ _gameTicks = 0;
+ do {
+ if (compareGameTick(1, 16)) {
+ if (_walkDataCurrentIndex > _walkDataLastIndex) {
+ _gameState.igorMoving = false;
+ _walkDataLastIndex = _walkDataCurrentIndex;
+ }
+ if (_gameState.igorMoving) {
+ moveIgor(_walkData[_walkDataCurrentIndex].posNum, _walkData[_walkDataCurrentIndex].frameNum);
+ ++_walkDataCurrentIndex;
+ }
+ }
+ if (compareGameTick(2, 32) && _gameState.unk10 < 11) {
+ if (_objectsState[44] == 0) {
+ const uint8 *src = _animFramesBuffer + READ_LE_UINT16(_animFramesBuffer + 0x74B + _gameState.unk10 * 2) - 1;
+ decodeAnimFrame(src, _screenVGA, true);
+ }
+ ++_gameState.unk10;
+ }
+ waitForTimer();
+ } while (_gameState.igorMoving || _gameState.unk10 != 11);
+}
+
+void IgorEngine::PART_12_HELPER_6() {
+ playMusic(2);
+ PART_12_HELPER_1(255);
+ _walkData[0].setPos(75, 89, 2, 0);
+ _walkData[0].setDefaultScale();
+ _walkData[0].clipSkipX = 1;
+ _walkData[0].clipWidth = 30;
+ _roomObjectAreasTable[_screenLayer2[28555]].area = _roomObjectAreasTable[_screenLayer2[34686]].area;
+ buildWalkPath(75, 89, 126, 108);
+ _roomObjectAreasTable[_screenLayer2[28555]].area = 0;
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _gameState.igorMoving = true;
+ _gameState.unk10 = 1;
+ waitForTimer(15);
+ _gameTicks = 0;
+ do {
+ if (compareGameTick(1, 16)) {
+ if (_walkDataCurrentIndex > _walkDataLastIndex) {
+ _gameState.igorMoving = false;
+ _walkDataLastIndex = _walkDataCurrentIndex;
+ }
+ if (_gameState.igorMoving) {
+ moveIgor(_walkData[_walkDataCurrentIndex].posNum, _walkData[_walkDataCurrentIndex].frameNum);
+ ++_walkDataCurrentIndex;
+ }
+ }
+ if (compareGameTick(2, 32) && _gameState.unk10 < 11) {
+ if (_objectsState[44] == 0) {
+ const uint8 *src = _animFramesBuffer + READ_LE_UINT16(_animFramesBuffer + 0x74B + _gameState.unk10 * 2) - 1;
+ decodeAnimFrame(src, _screenVGA, true);
+ }
+ ++_gameState.unk10;
+ }
+ waitForTimer();
+ } while (_gameState.igorMoving || _gameState.unk10 != 11);
+}
+
+void IgorEngine::PART_12_HELPER_8() {
+ decodeAnimFrame(_animFramesBuffer + 0x395B + READ_LE_UINT16(_animFramesBuffer + 0xA454) - 1, _screenVGA, true);
+}
+
+void IgorEngine::PART_12_HELPER_9() {
+ decodeAnimFrame(_animFramesBuffer + 0x395B + READ_LE_UINT16(_animFramesBuffer + 0xA442) - 1, _screenLayer1, true);
+}
+
+void IgorEngine::PART_12_HELPER_10(int frame) {
+ decodeAnimFrame(_animFramesBuffer + 0x395B + READ_LE_UINT16(_animFramesBuffer + 0xA43E + frame * 2) - 1, _screenVGA, true);
+}
+
+void IgorEngine::PART_12() {
+ _gameState.enableLight = 1;
+ loadRoomData(PAL_OutsideChurch, IMG_OutsideChurch, BOX_OutsideChurch, MSK_OutsideChurch, TXT_OutsideChurch);
+ static const int anm[] = { FRM_OutsideChurch1, FRM_OutsideChurch2, FRM_OutsideChurch3, FRM_OutsideChurch4, FRM_OutsideChurch5, FRM_OutsideChurch6, FRM_OutsideChurch7, FRM_OutsideChurch8, FRM_OutsideChurch9, FRM_OutsideChurch10, FRM_OutsideChurch11, FRM_OutsideChurch12, 0 };
+ loadAnimData(anm);
+ loadActionData(DAT_OutsideChurch);
+ _roomDataOffsets = PART_12_ROOM_DATA_OFFSETS;
+ setRoomWalkBounds(89, 0, 275, 143);
+ SET_EXEC_ACTION_FUNC(1, &IgorEngine::PART_12_EXEC_ACTION);
+ PART_12_HELPER_1(255);
+ memcpy(_screenVGA, _screenLayer1, 46080);
+ if (_objectsState[44] == 0) {
+ PART_12_HELPER_3();
+ }
+ if (_currentPart == 122) {
+ PART_12_HELPER_4();
+ return;
+ }
+ _currentAction.verb = kVerbWalk;
+ fadeInPalette(768);
+ if (_currentPart == 120) {
+ PART_12_HELPER_5();
+ }
+ if (_currentPart == 121) {
+ PART_12_HELPER_6();
+ if (_objectsState[106] == 1) {
+ ADD_DIALOGUE_TEXT(216, 2);
+ ADD_DIALOGUE_TEXT(218, 1);
+ SET_DIALOGUE_TEXT(1, 2);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ --_walkDataLastIndex;
+ buildWalkPath(126, 108, 196, 64);
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+ _currentPart = 40;
+ goto PART_12_EXIT;
+ }
+ }
+ PART_12_HELPER_2();
+ showCursor();
+ _gameState.igorMoving = false;
+ while (_currentPart >= 120 && _currentPart <= 122) {
+ handleRoomInput();
+ if (compareGameTick(1, 16)) {
+ handleRoomIgorWalk();
+ }
+ if (compareGameTick(19, 32)) {
+ handleRoomDialogue();
+ }
+ if (compareGameTick(4, 8)) {
+ handleRoomInventoryScroll();
+ }
+ if (compareGameTick(1)) {
+ handleRoomLight();
+ }
+ PART_12_UPDATE_ROOM_BACKGROUND();
+ waitForTimer();
+ }
+PART_12_EXIT:
+ hideCursor();
+ fadeOutPalette(624);
+}
+
+} // namespace Igor
diff --git a/engines/igor/parts/part_13.cpp b/engines/igor/parts/part_13.cpp
new file mode 100644
index 0000000000..e33cc69918
--- /dev/null
+++ b/engines/igor/parts/part_13.cpp
@@ -0,0 +1,247 @@
+/* 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 "igor/igor.h"
+
+namespace Igor {
+
+void IgorEngine::PART_13_EXEC_ACTION(int action) {
+ switch (action) {
+ case 101:
+ PART_13_ACTION_101_103();
+ break;
+ case 102:
+ ADD_DIALOGUE_TEXT(201, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 103:
+ PART_13_ACTION_101_103();
+ break;
+ case 104:
+ PART_13_ACTION_104();
+ break;
+ case 105:
+ _currentPart = 140;
+ break;
+ default:
+ error("PART_13_EXEC_ACTION unhandled action %d", action);
+ break;
+ }
+}
+
+void IgorEngine::PART_13_ACTION_101_103() {
+ waitForTimer(255);
+ _walkDataCurrentIndex = 0;
+ _walkCurrentFrame = 1;
+ for (int i = 0; i <= 4; ++i) {
+ WalkData *wd = &_walkData[0];
+ if (i == 4) {
+ _walkCurrentFrame = 0;
+ }
+ wd->setPos(52 + i * 5, 88, 2, _walkCurrentFrame);
+ WalkData::setNextFrame(2, _walkCurrentFrame);
+ wd->clipSkipX = 1;
+ wd->clipWidth = 24;
+ wd->scaleWidth = 40;
+ wd->xPosChanged = 1;
+ wd->dxPos = 5;
+ wd->yPosChanged = 1;
+ wd->dyPos = 0;
+ wd->scaleHeight = 40;
+ moveIgor(wd->posNum, wd->frameNum);
+ waitForTimer(30);
+ }
+ _walkDataLastIndex = 1;
+ ADD_DIALOGUE_TEXT(203, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ _walkData[0].posNum = 3;
+ moveIgor(_walkData[0].posNum, _walkData[0].frameNum);
+ waitForTimer(30);
+ _walkCurrentFrame = 1;
+ for (int i = 4; i >= 0; --i) {
+ WalkData *wd = &_walkData[0];
+ if (i == 0) {
+ _walkCurrentFrame = 0;
+ }
+ wd->setPos(52 + i * 5, 88, 4, _walkCurrentFrame);
+ WalkData::setNextFrame(4, _walkCurrentFrame);
+ wd->clipSkipX = 1;
+ wd->clipWidth = 24;
+ wd->scaleWidth = 40;
+ wd->xPosChanged = 1;
+ wd->dxPos = 5;
+ wd->yPosChanged = 1;
+ wd->dyPos = 0;
+ wd->scaleHeight = 40;
+ moveIgor(wd->posNum, wd->frameNum);
+ waitForTimer(30);
+ }
+ waitForTimer(255);
+ WalkData *wd = &_walkData[0];
+ wd->setPos(70, 127, 2, 0);
+ wd->clipSkipX = 1;
+ wd->clipWidth = 13;
+ wd->scaleWidth = 22;
+ wd->xPosChanged = 1;
+ wd->dxPos = 0;
+ wd->yPosChanged = 1;
+ wd->dyPos = 0;
+ wd->scaleHeight = 22;
+ _walkDataLastIndex = 0;
+ _walkDataCurrentIndex = 1;
+ buildWalkPath(70, 127, 92, 127);
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _gameState.igorMoving = true;
+ _gameState.unk10 = 1;
+ _gameTicks = 0;
+ do {
+ if (compareGameTick(1, 16)) {
+ if (_walkDataCurrentIndex > _walkDataLastIndex) {
+ _gameState.igorMoving = false;
+ _walkDataLastIndex = _walkDataCurrentIndex;
+ }
+ if (_gameState.igorMoving) {
+ moveIgor(_walkData[_walkDataCurrentIndex].posNum, _walkData[_walkDataCurrentIndex].frameNum);
+ ++_walkDataCurrentIndex;
+ }
+ }
+ waitForTimer();
+ } while (_gameState.igorMoving);
+}
+
+void IgorEngine::PART_13_ACTION_104() {
+ _walkDataCurrentIndex = 0;
+ _walkCurrentFrame = 1;
+ for (_gameState.counter[1] = 9; _gameState.counter[1] >= 0; --_gameState.counter[1]) {
+ if (_gameState.counter[1] == 9) {
+ _walkCurrentFrame = 0;
+ }
+ _walkData[0].setPos(189, 143, 3, _walkCurrentFrame);
+ WalkData::setNextFrame(3, _walkCurrentFrame);
+ _walkData[0].clipSkipX = 1;
+ _walkData[0].clipWidth = 13;
+ _walkData[0].scaleWidth = 13 + _gameState.counter[1];
+ _walkData[0].xPosChanged = 1;
+ _walkData[0].dxPos = 0;
+ _walkData[0].yPosChanged = 1;
+ _walkData[0].dyPos = 3;
+ _walkData[0].scaleHeight = 22;
+ moveIgor(_walkData[0].posNum, _walkData[0].frameNum);
+ waitForTimer(15);
+ }
+ _currentPart = 121;
+}
+
+void IgorEngine::PART_13_HELPER_1(int num) {
+}
+
+void IgorEngine::PART_13_HELPER_2() {
+ WalkData *wd = &_walkData[0];
+ wd->setPos(314, 127, 4, 0);
+ wd->clipSkipX = 1;
+ wd->clipWidth = 13;
+ wd->scaleWidth = 22;
+ wd->xPosChanged = 1;
+ wd->dxPos = 0;
+ wd->yPosChanged = 1;
+ wd->dyPos = 0;
+ wd->scaleHeight = 22;
+ _walkDataLastIndex = 0;
+ buildWalkPath(314, 127, 288, 127);
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+}
+
+void IgorEngine::PART_13_HELPER_3() {
+ playMusic(4);
+ PART_13_HELPER_1(255);
+ _walkDataCurrentIndex = 0;
+ _walkCurrentFrame = 1;
+ for (int i = 0; i <= 9; ++i) {
+ WalkData *wd = &_walkData[0];
+ if (i == 9) {
+ _walkCurrentFrame = 0;
+ }
+ wd->setPos(189, 143, 1, _walkCurrentFrame);
+ WalkData::setNextFrame(1, _walkCurrentFrame);
+ wd->clipSkipX = 1;
+ wd->clipWidth = 13;
+ wd->scaleWidth = i + 13;
+ wd->xPosChanged = 1;
+ wd->dxPos = 0;
+ wd->yPosChanged = 1;
+ wd->dyPos = 0;
+ wd->scaleHeight = 22;
+ moveIgor(wd->posNum, wd->frameNum);
+ waitForTimer(15);
+ }
+ _walkDataLastIndex = 1;
+ _walkDataCurrentIndex = 1;
+}
+
+void IgorEngine::PART_13() {
+ _gameState.enableLight = 1;
+ loadRoomData(PAL_InsideChurch, IMG_InsideChurch, BOX_InsideChurch, MSK_InsideChurch, TXT_InsideChurch);
+ loadActionData(DAT_InsideChurch);
+ _roomDataOffsets = PART_13_ROOM_DATA_OFFSETS;
+ setRoomWalkBounds(92, 0, 288, 143);
+ SET_EXEC_ACTION_FUNC(1, &IgorEngine::PART_13_EXEC_ACTION);
+ PART_13_HELPER_1(255);
+ memcpy(_screenVGA, _screenLayer1, 46080);
+ _currentAction.verb = kVerbWalk;
+ fadeInPalette(768);
+ if (_currentPart == 130) {
+ PART_13_HELPER_3();
+ } else {
+ PART_13_HELPER_2();
+ }
+ showCursor();
+ _gameState.igorMoving = false;
+ while (_currentPart >= 130 && _currentPart <= 131) {
+ handleRoomInput();
+ if (compareGameTick(1, 16)) {
+ handleRoomIgorWalk();
+ }
+ if (compareGameTick(19, 32)) {
+ handleRoomDialogue();
+ }
+ if (compareGameTick(4, 8)) {
+ handleRoomInventoryScroll();
+ }
+ if (compareGameTick(1)) {
+ handleRoomLight();
+ }
+ waitForTimer();
+ }
+ hideCursor();
+ fadeOutPalette(624);
+}
+
+} // namespace Igor
diff --git a/engines/igor/parts/part_14.cpp b/engines/igor/parts/part_14.cpp
new file mode 100644
index 0000000000..d202f4db6a
--- /dev/null
+++ b/engines/igor/parts/part_14.cpp
@@ -0,0 +1,615 @@
+/* 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 "igor/igor.h"
+
+namespace Igor {
+
+static const uint8 PART_14_ANIM_DATA_1[6] = { 0, 2, 5, 1, 8, 3 };
+
+static int VAR_NEW_CHURCH_MOSAIC_STONE;
+static int VAR_CURRENT_CHURCH_MOSAIC_STONE;
+
+void IgorEngine::PART_14_EXEC_ACTION(int action) {
+ switch (action) {
+ case 101:
+ PART_14_ACTION_101();
+ break;
+ case 102:
+ ADD_DIALOGUE_TEXT(201, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 103:
+ PART_14_ACTION_103();
+ break;
+ case 104:
+ ADD_DIALOGUE_TEXT(202, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 105:
+ PART_14_ACTION_105();
+ break;
+ case 106:
+ PART_14_ACTION_106();
+ break;
+ case 107:
+ ADD_DIALOGUE_TEXT(203, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 108:
+ PART_14_ACTION_108();
+ break;
+ default:
+ error("PART_14_EXEC_ACTION unhandled action %d", action);
+ break;
+ }
+}
+
+void IgorEngine::PART_14_ACTION_101() {
+ _roomObjectAreasTable[_screenLayer2[22156]].area = 1;
+ _roomObjectAreasTable[_screenLayer2[27895]].area = 1;
+ --_walkDataLastIndex;
+ buildWalkPath(50, 103, 55, 87);
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+ for (int i = 192 * 3; i <= 207 * 3; ++i) {
+ if (_paletteBuffer[i] > 5) {
+ _currentPalette[i] -= 5;
+ } else {
+ _currentPalette[i] = 0;
+ }
+ }
+ setPaletteRange(192, 207);
+ --_walkDataLastIndex;
+ buildWalkPath(55, 87, 76, 69);
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+ _currentPart = 220;
+}
+
+void IgorEngine::PART_14_ACTION_103() {
+ fadeOutPalette(768);
+ PART_14_HELPER_9();
+ loadResourceData__ROOM_ChurchPuzzle();
+ memcpy(_screenVGA + 46080, 0, 17920);
+ drawVerbsPanel();
+ drawInventory(_inventoryInfo[72], 0);
+ fadeInPalette(768);
+ if (_currentPart == 145) {
+ for (int i = 1; i <= 10; ++i) {
+ const uint8 *src = _animFramesBuffer + 0x9486 + READ_LE_UINT16(_animFramesBuffer + 0xCCE4 + i * 2) - 1;
+ decodeAnimFrame(src, _screenVGA, true);
+ waitForTimer(60);
+ }
+ stopSound();
+ _objectsState[50] = 1;
+ }
+ PART_14_HELPER_1(255);
+ _currentPart = 140;
+}
+
+void IgorEngine::PART_14_ACTION_105() {
+ _walkDataCurrentIndex = 0;
+ for (int i = 9; i >= 0; --i) {
+ WalkData *wd = &_walkData[0];
+ if (i == 9) {
+ _walkCurrentFrame = 0;
+ }
+ wd->setPos(182, 143, 3, _walkCurrentFrame);
+ WalkData::setNextFrame(3, _walkCurrentFrame);
+ wd->clipSkipX = 1;
+ wd->clipWidth = 30;
+ wd->scaleWidth = 23 + i * 3;
+ wd->xPosChanged = 1;
+ wd->dxPos = 0;
+ wd->yPosChanged = 1;
+ wd->dyPos = 3;
+ wd->scaleHeight = 50;
+ moveIgor(wd->posNum, wd->frameNum);
+ waitForTimer(15);
+ }
+ _currentPart = 131;
+}
+
+void IgorEngine::PART_14_ACTION_106() {
+ --_walkDataLastIndex;
+ _roomObjectAreasTable[_screenLayer2[35684]].area = 2;
+ buildWalkPath(164, 126, 164, 111);
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+ for (int i = 192 * 3; i <= 207 * 3; ++i) {
+ if (_paletteBuffer[i] > 5) {
+ _currentPalette[i] -= 5;
+ } else {
+ _currentPalette[i] = 0;
+ }
+ }
+ setPaletteRange(192, 207);
+ _walkDataCurrentIndex = 0;
+ for (int i = 9; i >= 0; --i) {
+ WalkData *wd = &_walkData[0];
+ if (i == 9) {
+ _walkCurrentFrame = 0;
+ }
+ wd->setPos(164, 111, 1, _walkCurrentFrame);
+ WalkData::setNextFrame(1, _walkCurrentFrame);
+ wd->clipSkipX = 1;
+ wd->clipWidth = 30;
+ wd->scaleWidth = 23 + i * 3;
+ wd->xPosChanged = 1;
+ wd->dxPos = 0;
+ wd->yPosChanged = 1;
+ wd->dyPos = 3;
+ wd->scaleHeight = 50;
+ moveIgor(wd->posNum, wd->frameNum);
+ waitForTimer(15);
+ }
+ _objectsState[71] = 0;
+ _currentPart = 670;
+}
+
+void IgorEngine::PART_14_ACTION_108() {
+ _gameState.unkF = false;
+ _updateRoomBackground = &IgorEngine::PART_14_UPDATE_ROOM_BACKGROUND_ACTION_108;
+ ADD_DIALOGUE_TEXT(226, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ removeObjectFromInventory(43);
+ for (int i = 1; i <= 3; ++i) {
+ const uint8 *src = _animFramesBuffer + 0x2AAA + READ_LE_UINT16(_animFramesBuffer + 0x940C + i * 2) - 1;
+ decodeAnimFrame(src, _screenVGA, true);
+ waitForTimer(60);
+ }
+ _gameState.unkF = true;
+ playSound(33, 1);
+ PART_14_HELPER_8(4, 24);
+ stopSound();
+ ADD_DIALOGUE_TEXT(205, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startCutsceneDialogue(221, 85, 12, 33, 63);
+ waitForEndOfCutsceneDialogue(221, 85, 12, 33, 63);
+ PART_14_HELPER_8(25, 26);
+ PART_14_HELPER_8(60, 60);
+ WalkData *wd = &_walkData[_walkDataLastIndex - 1];
+ wd->x = 250;
+ wd->y = 138;
+ wd->posNum = 4;
+ ADD_DIALOGUE_TEXT(206, 1);
+ ADD_DIALOGUE_TEXT(207, 1);
+ SET_DIALOGUE_TEXT(1, 2);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ ADD_DIALOGUE_TEXT(208, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startCutsceneDialogue(221, 85, 12, 33, 63);
+ waitForEndOfCutsceneDialogue(221, 85, 12, 33, 63);
+ ADD_DIALOGUE_TEXT(210, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ ADD_DIALOGUE_TEXT(211, 2);
+ ADD_DIALOGUE_TEXT(213, 3);
+ ADD_DIALOGUE_TEXT(216, 1);
+ SET_DIALOGUE_TEXT(1, 3);
+ startCutsceneDialogue(221, 85, 12, 33, 63);
+ waitForEndOfCutsceneDialogue(221, 85, 12, 33, 63);
+ for (int i = 33; i <= 35; ++i) {
+ const uint8 *src = _animFramesBuffer + 0x2AAA + READ_LE_UINT16(_animFramesBuffer + 0x940C + i * 2) - 1;
+ decodeAnimFrame(src, _screenVGA, true);
+ waitForTimer(60);
+ }
+ addObjectToInventory(28, 63);
+ ADD_DIALOGUE_TEXT(217, 1);
+ ADD_DIALOGUE_TEXT(218, 1);
+ ADD_DIALOGUE_TEXT(219, 1);
+ SET_DIALOGUE_TEXT(1, 3);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ ADD_DIALOGUE_TEXT(220, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startCutsceneDialogue(221, 85, 12, 33, 63);
+ waitForEndOfCutsceneDialogue(221, 85, 12, 33, 63);
+ PART_14_HELPER_7(0);
+ _gameState.unkF = false;
+ _screenVGA[32865] = _screenLayer1[32865];
+ playSound(33, 1);
+ PART_14_HELPER_8(36, 60);
+ stopSound();
+ ADD_DIALOGUE_TEXT(222, 1);
+ ADD_DIALOGUE_TEXT(223, 1);
+ ADD_DIALOGUE_TEXT(224, 1);
+ ADD_DIALOGUE_TEXT(225, 1);
+ SET_DIALOGUE_TEXT(1, 4);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ PART_14_HELPER_1(255);
+ _updateRoomBackground = 0;
+}
+
+void IgorEngine::PART_14_UPDATE_ROOM_BACKGROUND_ACTION_108() {
+ if (compareGameTick(2, 16) && _gameState.unkF) {
+ PART_14_HELPER_7(getRandomNumber(2) + 1);
+ }
+}
+
+void IgorEngine::PART_14_HELPER_1(int num) {
+ if (num == 1 || num == 255) {
+ if (_objectsState[50] == 1) {
+ PART_14_HELPER_6();
+ _roomObjectAreasTable[3].object = 5;
+ _roomObjectAreasTable[4].object = 5;
+ _roomObjectAreasTable[7].object = 5;
+ _roomObjectAreasTable[8].object = 5;
+ } else {
+ _roomObjectAreasTable[3].object = 0;
+ _roomObjectAreasTable[4].object = 2;
+ _roomObjectAreasTable[7].object = 0;
+ _roomObjectAreasTable[8].object = 2;
+ }
+ }
+}
+
+void IgorEngine::PART_14_HELPER_2() {
+ _walkDataCurrentIndex = 0;
+ _walkCurrentFrame = 1;
+ for (int i = 0; i <= 9; ++i) {
+ WalkData *wd = &_walkData[0];
+ if (i == 9) {
+ _walkCurrentFrame = 0;
+ }
+ wd->setPos(182, 143, 1, _walkCurrentFrame);
+ WalkData::setNextFrame(1, _walkCurrentFrame);
+ wd->clipSkipX = 1;
+ wd->clipWidth = 30;
+ wd->scaleWidth = 23 + i * 3;
+ wd->xPosChanged = 1;
+ wd->dxPos = 0;
+ wd->yPosChanged = 1;
+ wd->dyPos = 3;
+ wd->scaleHeight = 32;
+ moveIgor(wd->posNum, wd->frameNum);
+ waitForTimer(15);
+ }
+ _walkDataLastIndex = 1;
+ _walkDataCurrentIndex = 1;
+ buildWalkPath(182, 143, 162, 138);
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+}
+
+void IgorEngine::PART_14_HELPER_3() {
+ for (int i = 192 * 3; i <= 207 * 3; ++i) {
+ if (_paletteBuffer[i] > 5) {
+ _currentPalette[i] -= 5;
+ } else {
+ _currentPalette[i] = 0;
+ }
+ }
+ setPaletteRange(192, 207);
+ WalkData *wd = &_walkData[0];
+ wd->setPos(76, 69, 4, 0);
+ wd->clipSkipX = 1;
+ wd->clipWidth = 24;
+ wd->scaleWidth = 40;
+ wd->xPosChanged = 1;
+ wd->dxPos = 0;
+ wd->yPosChanged = 1;
+ wd->dyPos = 0;
+ wd->scaleHeight = 40;
+ _walkDataLastIndex = 0;
+ _roomObjectAreasTable[_screenLayer2[22156]].area = 1;
+ _roomObjectAreasTable[_screenLayer2[27895]].area = 1;
+ buildWalkPath(76, 69, 55, 87);
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+ for (int i = 192 * 3; i <= 207 * 3; ++i) {
+ _currentPalette[i] = _paletteBuffer[i];
+ }
+ setPaletteRange(192, 207);
+ --_walkDataLastIndex;
+ buildWalkPath(55, 87, 50, 103);
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+ _roomObjectAreasTable[_screenLayer2[22156]].area = 0;
+ _roomObjectAreasTable[_screenLayer2[27895]].area = 0;
+}
+
+void IgorEngine::PART_14_HELPER_4() {
+ playMusic(4);
+ PART_14_HELPER_1(255);
+ for (int i = 192 * 3; i <= 207 * 3; ++i) {
+ if (_paletteBuffer[i] > 5) {
+ _currentPalette[i] -= 5;
+ } else {
+ _currentPalette[i] = 0;
+ }
+ }
+ setPaletteRange(192, 207);
+ _walkDataCurrentIndex = 0;
+ _walkCurrentFrame = 1;
+ _walkCurrentPos = 3;
+ for (int i = 0; i <= 9; ++i) {
+ WalkData *wd = &_walkData[0];
+ if (i == 9) {
+ _walkCurrentFrame = 0;
+ }
+ wd->setPos(164, 111, 3, _walkCurrentFrame);
+ WalkData::setNextFrame(3, _walkCurrentFrame);
+ wd->clipSkipX = 1;
+ wd->clipWidth = 30;
+ wd->scaleWidth = 23 + i * 3;
+ wd->xPosChanged = 1;
+ wd->dxPos = 0;
+ wd->yPosChanged = 1;
+ wd->dyPos = 3;
+ wd->scaleHeight = 50;
+ moveIgor(3, wd->frameNum);
+ waitForTimer(15);
+ }
+ for (int i = 192 * 3; i <= 207 * 3; ++i) {
+ _currentPalette[i] = _paletteBuffer[i];
+ }
+ setPaletteRange(192, 207);
+ _walkDataLastIndex = 0;
+ _roomObjectAreasTable[_screenLayer2[35684]].area = 2;
+ buildWalkPath(164, 111, 164, 126);
+ _roomObjectAreasTable[_screenLayer2[35684]].area = 0;
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+}
+
+void IgorEngine::PART_14_HELPER_6() {
+ const int offset = 18382;
+ for (int i = 0; i <= 65; ++i) {
+ memcpy(_screenLayer1 + i * 320 + offset, _animFramesBuffer + 0xD5BA + i * 44, 44);
+ }
+}
+
+void IgorEngine::PART_14_HELPER_7(int frame) {
+ const int offset = 38038;
+ for (int i = 0; i <= 1; ++i) {
+ memcpy(_screenVGA + i * 320 + offset, _animFramesBuffer + 0x2AA4 + frame * 2 + i, 1);
+ }
+}
+
+void IgorEngine::PART_14_HELPER_8(int start, int end) {
+ _gameState.counter[0] = start - 1;
+ do {
+ if (compareGameTick(1, 16)) {
+ ++_gameState.counter[0];
+ const uint8 *src = _animFramesBuffer + 0x2AAA + READ_LE_UINT16(_animFramesBuffer + 0x940C + _gameState.counter[0] * 2) - 1;
+ decodeAnimFrame(src, _screenVGA, true);
+ }
+ if (compareGameTick(2, 16) && _gameState.unkF) {
+ PART_14_HELPER_7(getRandomNumber(2) + 1);
+ }
+ waitForTimer();
+ } while (_gameState.counter[0] != end);
+}
+
+void IgorEngine::PART_14_HELPER_9() {
+ PART_14_HELPER_10();
+ memcpy(_screenTextLayer, _screenVGA, 46080);
+ memcpy(_screenVGA, _screenLayer1, 46080);
+ memcpy(_screenLayer1, _screenTextLayer, 46080);
+ memset(_screenVGA + 46080, 0, 17920);
+ fadeInPalette(768);
+ _inputVars[kInputCursorXPos] = 160;
+ _inputVars[kInputCursorYPos] = 72;
+ showCursor();
+ _gameState.counter[4] = 0;
+ _currentPart = 145;
+ _dialogueEnded = false;
+ VAR_CURRENT_CHURCH_MOSAIC_STONE = 255;
+ do {
+ int area = _screenLayer2[_inputVars[kInputCursorYPos] * 320 + _inputVars[kInputCursorXPos]];
+ if (area == 0) {
+ VAR_NEW_CHURCH_MOSAIC_STONE = 1;
+ } else if (area >= 1 && area <= 8) {
+ VAR_NEW_CHURCH_MOSAIC_STONE = 2;
+ } else if (area == 9) {
+ VAR_NEW_CHURCH_MOSAIC_STONE = 3;
+ }
+ if (VAR_NEW_CHURCH_MOSAIC_STONE != VAR_CURRENT_CHURCH_MOSAIC_STONE) {
+ switch (VAR_NEW_CHURCH_MOSAIC_STONE) {
+ case 1:
+ drawActionSentence("", 253);
+ break;
+ case 2:
+ drawActionSentence("Push stone", 253);
+ break;
+ case 3:
+ drawActionSentence("Exit", 253);
+ break;
+ }
+ VAR_CURRENT_CHURCH_MOSAIC_STONE = VAR_NEW_CHURCH_MOSAIC_STONE;
+ }
+ if (_inputVars[kInputClick]) {
+ _inputVars[kInputClick] = 0;
+ _dialogueEnded = area == 0;
+ if (area == 9) {
+ _currentPart = 146;
+ }
+ if (area >= 1 && area <= 8) {
+ drawActionSentence("Push stone", 251);
+ hideCursor();
+ playSound(34, 1);
+ switch (area) {
+ case 1:
+ PART_14_PUSH_STONE(33359, 28, 34, 0);
+ break;
+ case 2:
+ PART_14_PUSH_STONE(22800, 27, 34, 0x3D4);
+ break;
+ case 3:
+ PART_14_PUSH_STONE(10642, 39, 45, 0x785);
+ break;
+ case 4:
+ PART_14_PUSH_STONE(3624, 56, 39, 0xCCFA);
+ break;
+ case 5:
+ PART_14_PUSH_STONE(3679, 54, 38, 0xE87);
+ break;
+ case 6:
+ PART_14_PUSH_STONE(11077, 35, 35, 0x1D8F);
+ break;
+ case 7:
+ PART_14_PUSH_STONE(20688, 28, 36, 0x227B);
+ break;
+ case 8:
+ PART_14_PUSH_STONE(31889, 27, 38, 0x2687);
+ break;
+ }
+ }
+ stopSound();
+ drawActionSentence("Push stone", 253);
+ showCursor();
+ _dialogueEnded = false;
+ ++_gameState.counter[4];
+ if (_objectsState[2] == 0 || PART_14_ANIM_DATA_1[_gameState.counter[4]] != area) {
+ _currentPart = 0;
+ }
+ if (_gameState.counter[4] == 5) {
+ if (_currentPart == 145) {
+ _dialogueEnded = true;
+ } else {
+ _currentPart = 145;
+ _gameState.counter[4] = 0;
+ ADD_DIALOGUE_TEXT(204, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ playSound(35, 1);
+ waitForTimer(255);
+ stopSound();
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ }
+ }
+ }
+ if (_inputVars[kInputEscape]) {
+ _inputVars[kInputEscape] = 0;
+ _currentPart = 146;
+ _dialogueEnded = true;
+ }
+ } while (_currentPart >= 145 && _currentPart <= 146 && !_dialogueEnded);
+ drawActionSentence("", 253);
+ hideCursor();
+ if (_currentPart == 145) {
+ playSound(35, 1);
+ }
+ fadeOutPalette(768);
+ memcpy(_screenVGA, _screenLayer1, 46080);
+ SET_PAL_208_96_1();
+}
+
+void IgorEngine::PART_14_HELPER_10() {
+ loadData(PAL_ChurchMosaic, _paletteBuffer);
+ loadData(IMG_ChurchMosaic, _screenLayer1);
+ uint8 *p = loadData(MSK_ChurchMosaic);
+ decodeRoomMask(p);
+ free(p);
+}
+
+void IgorEngine::PART_14_PUSH_STONE(int screenOffset, int w, int h, int animOffset) {
+ for (int i = 0; i <= h; ++i) {
+ memcpy(_screenTempLayer + i * 100, _screenVGA + i * 320 + animOffset, w);
+ memcpy(_screenVGA + i * 320 + screenOffset, _animFramesBuffer + i * w, w);
+ }
+ waitForTimer(127);
+ for (int i = 0; i <= h; ++i) {
+ memcpy(_screenVGA + i * 320 + screenOffset, _screenTempLayer + i * 100, 28);
+ }
+}
+
+void IgorEngine::PART_14() {
+ _gameState.enableLight = 1;
+ loadResourceData__ROOM_ChurchPuzzle();
+ loadResourceData__ANIM_ChurchPuzzle();
+ loadActionData(DAT_ChurchPuzzle);
+ _roomDataOffsets = PART_14_ROOM_DATA_OFFSETS;
+ setRoomWalkBounds(0, 0, 256, 143);
+ SET_EXEC_ACTION_FUNC(1, &IgorEngine::PART_14_EXEC_ACTION);
+ PART_14_HELPER_1(255);
+ memcpy(_screenVGA, _screenLayer1, 46080);
+ _currentAction.verb = kVerbWalk;
+ fadeInPalette(768);
+ if (_currentPart == 140) {
+ PART_14_HELPER_2();
+ }
+ if (_currentPart == 141) {
+ PART_14_HELPER_3();
+ }
+ if (_currentPart == 142) {
+ PART_14_HELPER_4();
+ }
+ showCursor();
+ _gameState.igorMoving = false;
+ while (_currentPart >= 140 && _currentPart <= 142) {
+ handleRoomInput();
+ if (compareGameTick(1, 16)) {
+ handleRoomIgorWalk();
+ }
+ if (compareGameTick(19, 32)) {
+ handleRoomDialogue();
+ }
+ if (compareGameTick(4, 8)) {
+ handleRoomInventoryScroll();
+ }
+ if (compareGameTick(1)) {
+ handleRoomLight();
+ }
+ waitForTimer();
+ }
+ hideCursor();
+ fadeOutPalette(624);
+}
+
+void IgorEngine::loadResourceData__ROOM_ChurchPuzzle() {
+ loadRoomData(PAL_ChurchPuzzle, IMG_ChurchPuzzle, BOX_ChurchPuzzle, MSK_ChurchPuzzle, TXT_ChurchPuzzle);
+}
+
+void IgorEngine::loadResourceData__ANIM_ChurchPuzzle() {
+ static const int anm1[] = { FRM_ChurchPuzzle1, FRM_ChurchPuzzle2, FRM_ChurchPuzzle3, FRM_ChurchPuzzle4, 0 };
+ loadAnimData(anm1, 0);
+ static const int anm2[] = { FRM_ChurchPuzzle5, FRM_ChurchPuzzle6, FRM_ChurchPuzzle7, FRM_ChurchPuzzle8, FRM_ChurchPuzzle9, FRM_ChurchPuzzle10, FRM_ChurchPuzzle11, FRM_ChurchPuzzle12, 0 };
+ loadAnimData(anm2, 0x1D8F);
+ static const int anm3[] = { FRM_ChurchPuzzle13, FRM_ChurchPuzzle14, 0 };
+ loadAnimData(anm3, 0xCCE6);
+}
+
+} // namespace Igor
diff --git a/engines/igor/parts/part_15.cpp b/engines/igor/parts/part_15.cpp
new file mode 100644
index 0000000000..411fc73821
--- /dev/null
+++ b/engines/igor/parts/part_15.cpp
@@ -0,0 +1,521 @@
+/* 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 "igor/igor.h"
+
+namespace Igor {
+
+static const uint8 PART_15_ANIM_DATA_1[8] = { 5, 6, 0, 3, 3, 0, 0, 1 };
+
+static const uint8 PART_15_ANIM_DATA_2[8] = { 0, 1, 2, 3, 4, 3, 5, 6 };
+
+static const uint8 PART_15_ANIM_DATA_3[12] = { 0, 0, 1, 1, 1, 2, 1, 1, 1, 2, 1, 3 };
+
+static const uint8 PART_15_ANIM_DATA_4[8] = { 0, 7, 8, 3, 4, 3, 5, 6 };
+
+static const uint8 PART_15_ANIM_DATA_5[12] = { 0, 0, 1, 1, 1, 2, 1, 1, 1, 2, 1, 3 };
+
+void IgorEngine::PART_15_EXEC_ACTION(int action) {
+ switch (action) {
+ case 101:
+ PART_15_ACTION_101();
+ break;
+ case 102:
+ ADD_DIALOGUE_TEXT(204, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 103:
+ ADD_DIALOGUE_TEXT(205, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 104:
+ ADD_DIALOGUE_TEXT(207, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 105:
+ ADD_DIALOGUE_TEXT(205, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 106:
+ ADD_DIALOGUE_TEXT(205, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 107:
+ PART_15_ACTION_107();
+ break;
+ case 108:
+ ADD_DIALOGUE_TEXT(208, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 109:
+ ADD_DIALOGUE_TEXT(201, 1);
+ ADD_DIALOGUE_TEXT(202, 2);
+ SET_DIALOGUE_TEXT(1, 2);
+ startIgorDialogue();
+ break;
+ case 110:
+ ADD_DIALOGUE_TEXT(234, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 111:
+ ADD_DIALOGUE_TEXT(235, 1);
+ ADD_DIALOGUE_TEXT(236, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 112:
+ ADD_DIALOGUE_TEXT(237, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 113:
+ ADD_DIALOGUE_TEXT(235, 1);
+ ADD_DIALOGUE_TEXT(236, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 114:
+ ADD_DIALOGUE_TEXT(240, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 115:
+ PART_15_ACTION_115();
+ break;
+ case 116:
+ PART_15_ACTION_116();
+ break;
+ default:
+ error("PART_15_EXEC_ACTION unhandled action %d", action);
+ break;
+ }
+}
+
+void IgorEngine::PART_15_ACTION_101() {
+ --_walkDataLastIndex;
+ _roomObjectAreasTable[_screenLayer2[34560]].area = 1;
+ buildWalkPathSimple(34, 108, 0, 108);
+ _roomObjectAreasTable[_screenLayer2[34560]].area = 0;
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+ _currentPart = 271;
+}
+
+void IgorEngine::PART_15_ACTION_107() {
+ if (_gameState.counter[3] == 1) {
+ do {
+ PART_15_HELPER_3();
+ waitForTimer();
+ } while (_gameState.counter[3] != 0);
+ }
+ PART_15_HELPER_7(6);
+ PART_15_HANDLE_DIALOGUE_TOBIAS();
+}
+
+void IgorEngine::PART_15_ACTION_115() {
+ if (_gameState.counter[3] == 1) {
+ do {
+ PART_15_HELPER_3();
+ waitForTimer();
+ } while (_gameState.counter[3] != 0);
+ }
+ PART_15_HELPER_7(6);
+ ADD_DIALOGUE_TEXT(209, 1);
+ ADD_DIALOGUE_TEXT(210, 1);
+ SET_DIALOGUE_TEXT(1, 2);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ ADD_DIALOGUE_TEXT(212, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startCutsceneDialogue(133, 67, 0, 63, 19);
+ _updateDialogue = &IgorEngine::PART_15_UPDATE_DIALOGUE_TOBIAS;
+ waitForEndOfCutsceneDialogue(133, 67, 0, 63, 19);
+ _updateDialogue = 0;
+ ADD_DIALOGUE_TEXT(213, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ ADD_DIALOGUE_TEXT(214, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startCutsceneDialogue(133, 67, 0, 63, 19);
+ _updateDialogue = &IgorEngine::PART_15_UPDATE_DIALOGUE_TOBIAS;
+ waitForEndOfCutsceneDialogue(133, 67, 0, 63, 19);
+ _updateDialogue = 0;
+ for (int i = 1; i <= 11; ++i) {
+ PART_15_HELPER_9(PART_15_ANIM_DATA_3[i]);
+ waitForTimer(60);
+ }
+ PART_15_HELPER_7(6);
+ if (_objectsState[37] == 0) {
+ ADD_DIALOGUE_TEXT(215, 2);
+ ADD_DIALOGUE_TEXT(217, 1);
+ } else {
+ ADD_DIALOGUE_TEXT(218, 2);
+ ADD_DIALOGUE_TEXT(223, 1);
+ }
+ SET_DIALOGUE_TEXT(1, 2);
+ startCutsceneDialogue(133, 67, 0, 63, 19);
+ _updateDialogue = &IgorEngine::PART_15_UPDATE_DIALOGUE_TOBIAS;
+ waitForEndOfCutsceneDialogue(133, 67, 0, 63, 19);
+ _updateDialogue = 0;
+ if (_objectsState[37] == 0) {
+ return;
+ }
+ for (int i = 1; i <= 7; ++i) {
+ PART_15_HELPER_7(PART_15_ANIM_DATA_2[i]);
+ waitForTimer(40);
+ }
+ removeObjectFromInventory(70);
+ _objectsState[46] = 1;
+ if (_objectsState[47] == 0) {
+ ADD_DIALOGUE_TEXT(221, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startCutsceneDialogue(133, 67, 0, 63, 19);
+ _updateDialogue = &IgorEngine::PART_15_UPDATE_DIALOGUE_TOBIAS;
+ waitForEndOfCutsceneDialogue(133, 67, 0, 63, 19);
+ _updateDialogue = 0;
+ return;
+ }
+ ADD_DIALOGUE_TEXT(226, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startCutsceneDialogue(133, 67, 0, 63, 19);
+ _updateDialogue = &IgorEngine::PART_15_UPDATE_DIALOGUE_TOBIAS;
+ waitForEndOfCutsceneDialogue(133, 67, 0, 63, 19);
+ _updateDialogue = 0;
+ ADD_DIALOGUE_TEXT(228, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ ADD_DIALOGUE_TEXT(229, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startCutsceneDialogue(133, 67, 0, 63, 19);
+ _updateDialogue = &IgorEngine::PART_15_UPDATE_DIALOGUE_TOBIAS;
+ waitForEndOfCutsceneDialogue(133, 67, 0, 63, 19);
+ _updateDialogue = 0;
+ ADD_DIALOGUE_TEXT(230, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ _currentPart = 780;
+}
+
+void IgorEngine::PART_15_ACTION_116() {
+ if (_gameState.counter[3] == 1) {
+ do {
+ PART_15_HELPER_3();
+ waitForTimer();
+ } while (_gameState.counter[3] != 0);
+ }
+ PART_15_HELPER_7(6);
+ ADD_DIALOGUE_TEXT(209, 1);
+ ADD_DIALOGUE_TEXT(211, 1);
+ SET_DIALOGUE_TEXT(1, 2);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ ADD_DIALOGUE_TEXT(212, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startCutsceneDialogue(133, 67, 0, 63, 19);
+ _updateDialogue = &IgorEngine::PART_15_UPDATE_DIALOGUE_TOBIAS;
+ waitForEndOfCutsceneDialogue(133, 67, 0, 63, 19);
+ _updateDialogue = 0;
+ ADD_DIALOGUE_TEXT(213, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ ADD_DIALOGUE_TEXT(214, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startCutsceneDialogue(133, 67, 0, 63, 19);
+ _updateDialogue = &IgorEngine::PART_15_UPDATE_DIALOGUE_TOBIAS;
+ waitForEndOfCutsceneDialogue(133, 67, 0, 63, 19);
+ _updateDialogue = 0;
+ for (int i = 1; i <= 11; ++i) {
+ PART_15_HELPER_9(PART_15_ANIM_DATA_5[i]);
+ waitForTimer(60);
+ }
+ PART_15_HELPER_7(6);
+ if (_objectsState[37] == 0) {
+ ADD_DIALOGUE_TEXT(215, 2);
+ ADD_DIALOGUE_TEXT(217, 1);
+ } else {
+ ADD_DIALOGUE_TEXT(218, 2);
+ ADD_DIALOGUE_TEXT(223, 1);
+ }
+ SET_DIALOGUE_TEXT(1, 2);
+ startCutsceneDialogue(133, 67, 0, 63, 19);
+ _updateDialogue = &IgorEngine::PART_15_UPDATE_DIALOGUE_TOBIAS;
+ waitForEndOfCutsceneDialogue(133, 67, 0, 63, 19);
+ _updateDialogue = 0;
+ if (_objectsState[37] == 0) {
+ return;
+ }
+ for (int i = 1; i <= 7; ++i) {
+ PART_15_HELPER_7(PART_15_ANIM_DATA_4[i]);
+ waitForTimer(40);
+ }
+ removeObjectFromInventory(60);
+ _objectsState[47] = 1;
+ if (_objectsState[46] == 0) {
+ ADD_DIALOGUE_TEXT(224, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startCutsceneDialogue(133, 67, 0, 63, 19);
+ _updateDialogue = &IgorEngine::PART_15_UPDATE_DIALOGUE_TOBIAS;
+ waitForEndOfCutsceneDialogue(133, 67, 0, 63, 19);
+ _updateDialogue = 0;
+ return;
+ }
+ ADD_DIALOGUE_TEXT(226, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startCutsceneDialogue(133, 67, 0, 63, 19);
+ _updateDialogue = &IgorEngine::PART_15_UPDATE_DIALOGUE_TOBIAS;
+ waitForEndOfCutsceneDialogue(133, 67, 0, 63, 19);
+ _updateDialogue = 0;
+ ADD_DIALOGUE_TEXT(228, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ ADD_DIALOGUE_TEXT(229, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startCutsceneDialogue(133, 67, 0, 63, 19);
+ _updateDialogue = &IgorEngine::PART_15_UPDATE_DIALOGUE_TOBIAS;
+ waitForEndOfCutsceneDialogue(133, 67, 0, 63, 19);
+ _updateDialogue = 0;
+ ADD_DIALOGUE_TEXT(230, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ _currentPart = 780;
+}
+
+void IgorEngine::PART_15_UPDATE_DIALOGUE_TOBIAS(int action) {
+ switch (action) {
+ case kUpdateDialogueAnimEndOfSentence:
+ PART_15_HELPER_8(0);
+ break;
+ case kUpdateDialogueAnimMiddleOfSentence:
+ PART_15_HELPER_8(getRandomNumber(5));
+ break;
+ case kUpdateDialogueAnimStanding:
+ PART_15_HELPER_8(0);
+ break;
+ }
+}
+
+void IgorEngine::PART_15_HANDLE_DIALOGUE_TOBIAS() {
+ loadDialogueData(DLG_TobiasOffice);
+ _updateDialogue = &IgorEngine::PART_15_UPDATE_DIALOGUE_TOBIAS;
+ handleDialogue(133, 67, 0, 63, 19);
+ _updateDialogue = 0;
+}
+
+void IgorEngine::PART_15_HELPER_1(int num) {
+}
+
+void IgorEngine::PART_15_HELPER_2() {
+ _walkData[0].setPos(0, 108, 2, 0);
+ _walkData[0].clipSkipX = 1;
+ _walkData[0].clipWidth = 15;
+ _walkData[0].scaleWidth = 25;
+ _walkData[0].xPosChanged = 1;
+ _walkData[0].dxPos = 0;
+ _walkData[0].yPosChanged = 1;
+ _walkData[0].dyPos = 0;
+ _walkData[0].scaleHeight = 25;
+ _walkDataLastIndex = 0;
+ _walkDataCurrentIndex = 1;
+ _roomObjectAreasTable[_screenLayer2[34560]].area = 1;
+ buildWalkPathSimple(0, 108, 34, 108);
+ _roomObjectAreasTable[_screenLayer2[34560]].area = 0;
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+}
+
+void IgorEngine::PART_15_HELPER_3() {
+ if (compareGameTick(38) || compareGameTick(60)) {
+ if (_objectsState[48] != 1 && _gameState.counter[3] == 1) {
+ if (_gameState.unk11 == 0) {
+ _objectsState[48] = 1;
+ _objectsState[49] = 1;
+ _gameState.counter[3] = 0;
+ } else {
+ PART_15_HELPER_6(_gameState.unk11);
+ }
+ if (_gameState.unk11 == 7) {
+ _objectsState[49] = 2;
+ }
+ if (_objectsState[49] == 2) {
+ if (_gameState.counter[4] == 0) {
+ playSound(54, 1);
+ }
+ ++_gameState.counter[4];
+ if (_gameState.unk11 == 7) {
+ _gameState.unk11 = 6;
+ } else {
+ _gameState.unk11 = 7;
+ }
+ if (_gameState.counter[4] > 15) {
+ _objectsState[49] = 3;
+ _gameState.unk11 = 6;
+ }
+ } else if (_objectsState[49] == 1) {
+ ++_gameState.unk11;
+ } else {
+ --_gameState.unk11;
+ }
+ }
+ }
+}
+
+void IgorEngine::PART_15_HELPER_5() {
+ if (compareGameTick(7) || compareGameTick(29) || compareGameTick(61)) {
+ if (_gameState.unk10 >= 3) {
+ PART_15_HELPER_9(PART_15_ANIM_DATA_1[_gameState.unk10]);
+ ++_gameState.unk10;
+ if (_gameState.unk10 == 8) {
+ _gameState.unk10 = 1;
+ }
+ }
+ }
+ if (compareGameTick(5)) {
+ if (_gameState.unk10 >= 1 && _gameState.unk10 <= 2) {
+ PART_15_HELPER_9(_gameState.unk10);
+ if (_gameState.unk10 == 1 && getRandomNumber(10) == 0) {
+ _gameState.unk10 = 2;
+ } else {
+ _gameState.unk10 = 1;
+ }
+ if (getRandomNumber(30) == 0) {
+ _gameState.unk10 = 3;
+ }
+ }
+ }
+}
+
+void IgorEngine::PART_15_HELPER_6(int frame) {
+ _roomCursorOn = false;
+ for (_gameState.counter[1] = 0; _gameState.counter[1] <= 17; ++_gameState.counter[1]) {
+ for (_gameState.counter[2] = 0; _gameState.counter[2] <= 52; ++_gameState.counter[2]) {
+ int offset = (_gameState.counter[1] + 23) * 320 + _gameState.counter[2] + 18;
+ uint8 color = _screenVGA[offset];
+ if (color < 0xF0 || color > 0xF1) {
+ color = _animFramesBuffer[0x4B8C + frame * 954 + _gameState.counter[1] * 53 + _gameState.counter[2]];
+ }
+ _screenTempLayer[_gameState.counter[1] * 100 + _gameState.counter[2]] = color;
+ }
+ }
+ int offset = 7378;
+ for (_gameState.counter[1] = 0; _gameState.counter[1] <= 17; ++_gameState.counter[1]) {
+ memcpy(_screenVGA + _gameState.counter[1] * 320 + offset, _screenTempLayer + _gameState.counter[1] * 100, 53);
+ memcpy(_screenLayer1 + _gameState.counter[1] * 320 + offset, _animFramesBuffer + 0x4B8C + frame * 954 + _gameState.counter[1] * 53, 53);
+ }
+ if (_gameState.dialogueTextRunning) {
+ memcpy(_screenTextLayer + 23040, _screenLayer1 + _dialogueDirtyRectY, _dialogueDirtyRectSize);
+ }
+ if (_dialogueCursorOn) {
+ _roomCursorOn = true;
+ }
+}
+
+void IgorEngine::PART_15_HELPER_7(int frame) {
+ int offset = 20887;
+ for (int i = 0; i <= 35; ++i) {
+ memcpy(_screenVGA + i * 320 + offset, _animFramesBuffer + 0x49A + frame * 2124 + i * 59, 59);
+ }
+}
+
+void IgorEngine::PART_15_HELPER_8(int frame) {
+ int offset = 22847;
+ for (int i = 0; i <= 12; ++i) {
+ memcpy(_screenVGA + i * 320 + offset, _animFramesBuffer + 0x958 + frame * 182 + i * 14, 14);
+ }
+}
+
+void IgorEngine::PART_15_HELPER_9(int frame) {
+ int offset = 22835;
+ for (int i = 0; i <= 22; ++i) {
+ memcpy(_screenVGA + i * 320 + offset, _animFramesBuffer + frame * 598 + i * 26, 26);
+ }
+}
+
+void IgorEngine::PART_15() {
+ _gameState.enableLight = 2;
+ loadRoomData(PAL_TobiasOffice, IMG_TobiasOffice, BOX_TobiasOffice, MSK_TobiasOffice, TXT_TobiasOffice);
+ static const int anm[] = { ANM_TobiasOffice1, AOF_TobiasOffice1, ANM_TobiasOffice2, AOF_TobiasOffice2, 0 };
+ loadAnimData(anm);
+ loadActionData(DAT_TobiasOffice);
+ _roomDataOffsets = PART_15_ROOM_DATA_OFFSETS;
+ setRoomWalkBounds(28, 0, 96, 143);
+ SET_EXEC_ACTION_FUNC(1, &IgorEngine::PART_15_EXEC_ACTION);
+ _updateRoomBackground = 0;
+ PART_15_HELPER_1(255);
+ memcpy(_screenVGA, _screenLayer1, 46080);
+ _currentAction.verb = kVerbWalk;
+ fadeInPalette(768);
+ _gameState.unk10 = 1;
+ _gameState.unk11 = 2;
+ _gameState.counter[3] = 0;
+ _gameState.counter[4] = 0;
+ PART_15_HELPER_2();
+ showCursor();
+ _gameState.igorMoving = false;
+ while (_currentPart == 150) {
+ handleRoomInput();
+ if (compareGameTick(1, 16)) {
+ handleRoomIgorWalk();
+ }
+ if (compareGameTick(19, 32)) {
+ handleRoomDialogue();
+ }
+ if (compareGameTick(4, 8)) {
+ handleRoomInventoryScroll();
+ }
+ if (compareGameTick(1)) {
+ handleRoomLight();
+ }
+ PART_15_HELPER_5();
+ if (_gameTicks == 38 || _gameTicks == 60) {
+ if (_objectsState[48] != 1 && getRandomNumber(200) == 0 && _gameState.counter[3] == 0) {
+ _gameState.counter[3] = 1;
+ }
+ }
+ PART_15_HELPER_3();
+ waitForTimer();
+ }
+ if (_objectsState[48] == 1) {
+ _objectsState[48] = 2;
+ }
+ fadeOutPalette(624);
+}
+
+} // namespace Igor
diff --git a/engines/igor/parts/part_16.cpp b/engines/igor/parts/part_16.cpp
new file mode 100644
index 0000000000..d5f2e05ccd
--- /dev/null
+++ b/engines/igor/parts/part_16.cpp
@@ -0,0 +1,304 @@
+/* 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 "igor/igor.h"
+
+namespace Igor {
+
+static int VAR_CURRENT_TALKING_ACTOR;
+
+void IgorEngine::PART_16_EXEC_ACTION(int action) {
+ switch (action) {
+ case 101:
+ PART_16_ACTION_101();
+ break;
+ case 102:
+ ADD_DIALOGUE_TEXT(208, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 103:
+ _currentPart = 261;
+ break;
+ default:
+ error("PART_16_EXEC_ACTION unhandled action %d", action);
+ break;
+ }
+}
+
+void IgorEngine::PART_16_ACTION_101() {
+ if (_objectsState[52] == 1) {
+ ADD_DIALOGUE_TEXT(207, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ return;
+ }
+ ADD_DIALOGUE_TEXT(201, 1);
+ ADD_DIALOGUE_TEXT(202, 2);
+ SET_DIALOGUE_TEXT(1, 2);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ for (int i = 1; i <= 2; ++i) {
+ int offset = 20332;
+ for (int j = 0; j <= 48; ++j) {
+ const uint8 *src = _animFramesBuffer + j * 23 + (i - 1) * 1127;
+ memcpy(_screenVGA + j * 320 + offset, src, 23);
+ }
+ waitForTimer(120);
+ }
+ addObjectToInventory(20, 55);
+ _objectsState[52] = 1;
+ ADD_DIALOGUE_TEXT(204, 3);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+}
+
+void IgorEngine::PART_16_UPDATE_DIALOGUE_MARGARET_HARRISON(int action) {
+ switch (action) {
+ case kUpdateDialogueAnimEndOfSentence:
+ PART_16_HELPER_6((VAR_CURRENT_TALKING_ACTOR == 0) ? 34 : 48);
+ break;
+ case kUpdateDialogueAnimMiddleOfSentence:
+ PART_16_HELPER_6((VAR_CURRENT_TALKING_ACTOR == 0) ? getRandomNumber(5) + 30 : getRandomNumber(5) + 44);
+ break;
+ }
+}
+
+void IgorEngine::PART_16_UPDATE_DIALOGUE_MARGARET(int action) {
+ switch (action) {
+ case kUpdateDialogueAnimEndOfSentence:
+ PART_16_HELPER_6(49);
+ break;
+ case kUpdateDialogueAnimMiddleOfSentence:
+ PART_16_HELPER_6(getRandomNumber(4) + 49);
+ break;
+ }
+}
+
+void IgorEngine::PART_16_HELPER_1(int num) {
+}
+
+void IgorEngine::PART_16_HELPER_2() {
+ WalkData *wd = &_walkData[0];
+ wd->setPos(0, 135, 2, 0);
+ wd->clipSkipX = 1;
+ wd->clipWidth = 30;
+ wd->scaleWidth = 50;
+ wd->xPosChanged = 1;
+ wd->dxPos = 0;
+ wd->yPosChanged = 1;
+ wd->dyPos = 0;
+ wd->scaleHeight = 50;
+ _walkDataLastIndex = 0;
+ buildWalkPath(0, 135, 90, 135);
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+}
+
+void IgorEngine::PART_16_HELPER_3() {
+ memset(_screenVGA + 46080, 0, 17920);
+ ADD_DIALOGUE_TEXT(210, 1);
+ ADD_DIALOGUE_TEXT(211, 1);
+ ADD_DIALOGUE_TEXT(212, 1);
+ ADD_DIALOGUE_TEXT(213, 2);
+ SET_DIALOGUE_TEXT(1, 4);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ --_walkDataLastIndex;
+ buildWalkPath(90, 135, 200, 143);
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+ _walkDataCurrentIndex = 0;
+ for (int i = 15; i >= 0; --i) {
+ if (i == 15) {
+ _walkCurrentFrame = 0;
+ }
+ _walkData[0].setPos(200, 143, 3, _walkCurrentFrame);
+ WalkData::setNextFrame(3, _walkCurrentFrame);
+ _walkData[0].clipSkipX = 1;
+ _walkData[0].clipWidth = 30;
+ _walkData[0].scaleWidth = i * 3 + 5;
+ _walkData[0].xPosChanged = 1;
+ _walkData[0].dxPos = 0;
+ _walkData[0].yPosChanged = 1;
+ _walkData[0].dyPos = 3;
+ _walkData[0].scaleHeight = 50;
+ moveIgor(_walkData[0].posNum, _walkData[0].frameNum);
+ waitForTimer(15);
+ }
+ fadeOutPalette(768);
+ _currentPart = 331;
+ PART_33();
+ memset(_currentPalette, 0, 768);
+ setPaletteRange(208, 255);
+ do {
+ PART_MARGARET_ROOM_CUTSCENE();
+ } while (_objectsState[110] != 9);
+ setupDefaultPalette();
+ SET_PAL_240_48_1();
+ SET_PAL_208_96_1();
+ loadResourceData__ROOM_Laboratory();
+ loadResourceData__ANIM_Laboratory();
+ memcpy(_screenVGA, _screenLayer1, 46080);
+ PART_16_HELPER_1(255);
+ fadeInPalette(768);
+ waitForTimer(255);
+ for (int i = 1; i <= 29; ++i) {
+ decodeAnimFrame(_animFramesBuffer + 0x8CE + READ_LE_UINT16(_animFramesBuffer + 0x6F36 + i * 2) - 1, _screenVGA, true);
+ waitForTimer(25);
+ }
+ ADD_DIALOGUE_TEXT(215, 1);
+ ADD_DIALOGUE_TEXT(216, 1);
+ ADD_DIALOGUE_TEXT(217, 1);
+ SET_DIALOGUE_TEXT(1, 3);
+ startCutsceneDialogue(175, 78, 0, 58, 40);
+ VAR_CURRENT_TALKING_ACTOR = 0;
+ _updateDialogue = &IgorEngine::PART_16_UPDATE_DIALOGUE_MARGARET_HARRISON;
+ waitForEndOfCutsceneDialogue(175, 78, 0, 58, 40);
+ _updateDialogue = 0;
+ for (int i = 35; i <= 41; ++i) {
+ decodeAnimFrame(_animFramesBuffer + 0x8CE + READ_LE_UINT16(_animFramesBuffer + 0x6F36 + i * 2) - 1, _screenVGA, true);
+ waitForTimer(35);
+ }
+ ADD_DIALOGUE_TEXT(218, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startCutsceneDialogue(88, 69, 63, 32, 0);
+ _updateDialogue = &IgorEngine::PART_16_UPDATE_DIALOGUE_MARGARET;
+ waitForEndOfCutsceneDialogue(88, 69, 63, 32, 0);
+ _updateDialogue = 0;
+ for (int i = 42; i <= 43; ++i) {
+ decodeAnimFrame(_animFramesBuffer + 0x8CE + READ_LE_UINT16(_animFramesBuffer + 0x6F36 + i * 2) - 1, _screenVGA, true);
+ waitForTimer(35);
+ }
+ ADD_DIALOGUE_TEXT(220, 1);
+ ADD_DIALOGUE_TEXT(221, 1);
+ SET_DIALOGUE_TEXT(1, 2);
+ startCutsceneDialogue(175, 78, 0, 58, 40);
+ VAR_CURRENT_TALKING_ACTOR = 1;
+ _updateDialogue = &IgorEngine::PART_16_UPDATE_DIALOGUE_MARGARET_HARRISON;
+ waitForEndOfCutsceneDialogue(175, 78, 0, 58, 40);
+ _updateDialogue = 0;
+ ADD_DIALOGUE_TEXT(222, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startCutsceneDialogue(88, 69, 63, 32, 0);
+ _updateDialogue = &IgorEngine::PART_16_UPDATE_DIALOGUE_MARGARET;
+ waitForEndOfCutsceneDialogue(88, 69, 63, 32, 0);
+ _updateDialogue = 0;
+ playSound(26, 1);
+ for (int i = 53; i <= 61; ++i) {
+ decodeAnimFrame(_animFramesBuffer + 0x8CE + READ_LE_UINT16(_animFramesBuffer + 0x6F36 + i * 2) - 1, _screenVGA, true);
+ waitForTimer(35);
+ }
+ playSound(25, 1);
+ for (int i = 1; i <= 20; ++i) {
+ int frame = getRandomNumber(4) + 61;
+ decodeAnimFrame(_animFramesBuffer + 0x8CE + READ_LE_UINT16(_animFramesBuffer + 0x6F36 + frame * 2) - 1, _screenVGA, true);
+ waitForTimer(15);
+ }
+ playSound(27, 1);
+ PART_16_HELPER_5();
+ for (int i = 1; i <= 3; ++i) {
+ waitForTimer(255);
+ }
+ PART_16_HELPER_1(255);
+ addObjectToInventory(19, 54);
+ _objectsState[53] = 1;
+ _objectsState[65] = 3;
+ playMusic(3);
+ _currentPart = 261;
+}
+
+void IgorEngine::PART_16_HELPER_5() {
+ memset(&_currentPalette[3], 63, 621);
+ setPaletteRange(1, 207);
+ loadData(IMG_PhotoHarrisonMargaret, _screenVGA);
+ loadData(PAL_PhotoHarrisonMargaret, _paletteBuffer);
+ for (int m = 1; m <= 63; ++m) {
+ for (int i = 3; i <= 207 * 3; ++i) {
+ if (_paletteBuffer[i] <= m && _paletteBuffer[i] >= _currentPalette[i]) {
+ --_currentPalette[i];
+ }
+ }
+ setPaletteRange(1, 207);
+ waitForTimer();
+ }
+}
+
+void IgorEngine::PART_16_HELPER_6(int frame) {
+ const uint8 *src = _animFramesBuffer + 0x8CE + READ_LE_UINT16(_animFramesBuffer + 0x6F36 + frame * 2) - 1;
+ decodeAnimFrame(src, _screenVGA, true);
+}
+
+void IgorEngine::PART_16() {
+ _gameState.enableLight = 1;
+ loadResourceData__ROOM_Laboratory();
+ loadResourceData__ANIM_Laboratory();
+ loadActionData(DAT_Laboratory);
+ _roomDataOffsets = PART_16_ROOM_DATA_OFFSETS;
+ setRoomWalkBounds(0, 0, 248, 143);
+ SET_EXEC_ACTION_FUNC(1, &IgorEngine::PART_16_EXEC_ACTION);
+ PART_16_HELPER_1(255);
+ memcpy(_screenVGA, _screenLayer1, 46080);
+ _currentAction.verb = kVerbWalk;
+ fadeInPalette(768);
+ PART_16_HELPER_2();
+ if (_objectsState[65] == 2 && _inventoryInfo[71] != 0 && _objectsState[76] == 1) {
+ PART_16_HELPER_3();
+ }
+ showCursor();
+ _gameState.igorMoving = false;
+ while (_currentPart == 160) {
+ handleRoomInput();
+ if (compareGameTick(1, 16)) {
+ handleRoomIgorWalk();
+ }
+ if (compareGameTick(19, 32)) {
+ handleRoomDialogue();
+ }
+ if (compareGameTick(4, 8)) {
+ handleRoomInventoryScroll();
+ }
+ if (compareGameTick(1)) {
+ handleRoomLight();
+ }
+ waitForTimer();
+ }
+ hideCursor();
+ fadeOutPalette(624);
+}
+
+void IgorEngine::loadResourceData__ROOM_Laboratory() {
+ loadRoomData(PAL_Laboratory, IMG_Laboratory, BOX_Laboratory, MSK_Laboratory, TXT_Laboratory);
+}
+
+void IgorEngine::loadResourceData__ANIM_Laboratory() {
+ static const int anm[] = { FRM_Laboratory1, FRM_Laboratory2, FRM_Laboratory3, 0 };
+ loadAnimData(anm);
+}
+
+} // namespace Igor
diff --git a/engines/igor/parts/part_17.cpp b/engines/igor/parts/part_17.cpp
new file mode 100644
index 0000000000..45b77b0966
--- /dev/null
+++ b/engines/igor/parts/part_17.cpp
@@ -0,0 +1,529 @@
+/* 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 "igor/igor.h"
+
+namespace Igor {
+
+static int VAR_CURRENT_TALKING_ACTOR;
+
+void IgorEngine::PART_17_EXEC_ACTION(int action) {
+ switch (action) {
+ case 101:
+ PART_17_ACTION_101();
+ break;
+ case 102:
+ ADD_DIALOGUE_TEXT(225, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 103:
+ PART_17_ACTION_103();
+ break;
+ case 104:
+ ADD_DIALOGUE_TEXT(220, 3);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 105:
+ PART_17_ACTION_105();
+ break;
+ case 106:
+ PART_17_ACTION_106();
+ break;
+ default:
+ error("PART_17_EXEC_ACTION unhandled action %d", action);
+ break;
+ }
+}
+
+void IgorEngine::PART_17_ACTION_101() {
+ _roomObjectAreasTable[_screenLayer2[22034]].area = 8;
+ _roomObjectAreasTable[_screenLayer2[23923]].area = 8;
+ --_walkDataLastIndex;
+ buildWalkPath(243, 77, 243, 74);
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+ buildWalkPath(243, 74, 274, 68);
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+ _currentPart = 302;
+}
+
+void IgorEngine::PART_17_ACTION_103() {
+ PART_17_HELPER_8(0);
+ if (_gameState.counter[4] == 1) {
+ ADD_DIALOGUE_TEXT(201, 2);
+ } else if (_gameState.counter[4] == 2) {
+ ADD_DIALOGUE_TEXT(206, 2);
+ } else if (_gameState.counter[4] == 3) {
+ ADD_DIALOGUE_TEXT(210, 2);
+ }
+ SET_DIALOGUE_TEXT(1, 1);
+ startCutsceneDialogue(156, 32, 35, 38, 47);
+ _updateDialogue = &IgorEngine::PART_17_UPDATE_DIALOGUE_PHILIP;
+ waitForEndOfCutsceneDialogue(156, 32, 35, 38, 47);
+ _updateDialogue = 0;
+ if (_gameState.counter[4] == 1) {
+ ADD_DIALOGUE_TEXT(203, 1);
+ ADD_DIALOGUE_TEXT(204, 2);
+ SET_DIALOGUE_TEXT(1, 2);
+ } else if (_gameState.counter[4] == 2) {
+ ADD_DIALOGUE_TEXT(208, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ } else if (_gameState.counter[4] == 3) {
+ ADD_DIALOGUE_TEXT(212, 2);
+ ADD_DIALOGUE_TEXT(214, 1);
+ SET_DIALOGUE_TEXT(1, 2);
+ }
+ startCutsceneDialogue(135, 33, 63, 63, 0);
+ VAR_CURRENT_TALKING_ACTOR = 0;
+ _updateDialogue = &IgorEngine::PART_17_UPDATE_DIALOGUE_PHILIP_JIMMY;
+ waitForEndOfCutsceneDialogue(135, 33, 63, 63, 0);
+ _updateDialogue = 0;
+ PART_17_HELPER_11(0);
+ waitForTimer(255);
+ ADD_DIALOGUE_TEXT(215 + getRandomNumber(4), 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startCutsceneDialogue(135, 33, 63, 63, 0);
+ VAR_CURRENT_TALKING_ACTOR = 1;
+ _updateDialogue = &IgorEngine::PART_17_UPDATE_DIALOGUE_PHILIP_JIMMY;
+ waitForEndOfCutsceneDialogue(135, 33, 63, 63, 0);
+ _updateDialogue = 0;
+ PART_17_HANDLE_DIALOGUE_PHILIP();
+ PART_17_HELPER_1(255);
+ PART_17_HELPER_8(0);
+ --_walkDataLastIndex;
+ buildWalkPath(104, 87, 143, 123);
+ _walkDataCurrentIndex = 1;
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+ ADD_DIALOGUE_TEXT(219, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ if (_gameState.counter[4] == 3) {
+ _gameState.counter[4] = 1;
+ } else {
+ ++_gameState.counter[4];
+ }
+}
+
+void IgorEngine::PART_17_ACTION_105() {
+ _roomObjectAreasTable[5].area = 1;
+ _roomObjectAreasTable[10].area = 2;
+ _roomObjectAreasTable[11].area = 2;
+ _roomObjectAreasTable[13].area = 2;
+ _roomObjectAreasTable[16].area = 3;
+ _roomObjectAreasTable[17].area = 4;
+ _roomObjectAreasTable[26].area = 4;
+ _roomObjectAreasTable[28].area = 4;
+ --_walkDataLastIndex;
+ buildWalkPath(45, 95, 41, 86);
+ _walkDataCurrentIndex = 1;
+ _walkData[_walkDataLastIndex].frameNum = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+ PART_17_HELPER_5(143);
+ --_walkDataLastIndex;
+ _roomObjectAreasTable[_screenLayer2[44836]].area = 4;
+ buildWalkPath(41, 86, 36, 143);
+ _roomObjectAreasTable[_screenLayer2[44836]].area = 0;
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ for (int i = _walkDataCurrentIndex; i <= _walkDataLastIndex; ++i) {
+ _walkData[i].posNum = kFacingPositionBack;
+ }
+ waitForIgorMove();
+ for (int i = 17; i <= 85; ++i) {
+ _walkYScaleRoom[i] = ((i - 13) / 4) + 5;
+ }
+ for (int i = 86; i <= 135; ++i) {
+ _walkYScaleRoom[i] = 23;
+ }
+ _walkData[0].setPos(65, 115, 1, 0);
+ _walkData[0].setDefaultScale();
+ _walkData[0].clipSkipX = 1;
+ _walkData[0].clipWidth = 14;
+ _walkData[0].scaleWidth = 23;
+ _walkData[0].scaleHeight = 23;
+ _walkDataLastIndex = 0;
+ _roomObjectAreasTable[_screenLayer2[36865]].area = 4;
+ buildWalkPath(65, 115, 21, 17);
+ _roomObjectAreasTable[_screenLayer2[36865]].area = 0;
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+ _currentPart = 40;
+}
+
+void IgorEngine::PART_17_ACTION_106() {
+ if (_objectsState[55] == 1) {
+ ADD_DIALOGUE_TEXT(226, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ return;
+ }
+ playSound(24, 1);
+ for (int i = 0; i <= 8; ++i) {
+ int offset = 12575;
+ for (int j = 0; j <= 27; ++j) {
+ memcpy(_screenVGA + offset + i * 320, _animFramesBuffer + 0x1E6E + j * 40 + i * 1120, 40);
+ }
+ waitForTimer(30);
+ }
+ int offset = 12575;
+ for (int i = 0; i <= 27; ++i) {
+ memcpy(_screenVGA + offset + i * 320, _animFramesBuffer + 0x1E6E + i * 40, 40);
+ }
+ _objectsState[55] = 1;
+ _objectsState[3] = 1;
+ PART_17_HELPER_1(255);
+ UPDATE_OBJECT_STATE(4);
+ --_walkDataLastIndex;
+ buildWalkPath(104, 87, 143, 123);
+ _walkDataCurrentIndex = 1;
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+ ADD_DIALOGUE_TEXT(223, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+}
+
+void IgorEngine::PART_17_HANDLE_DIALOGUE_PHILIP() {
+ loadDialogueData(DLG_OutsideCollege);
+ warning("PART_17_HANDLE_DIALOGUE_PHILIP unimplemented");
+}
+
+void IgorEngine::PART_17_UPDATE_DIALOGUE_PHILIP(int action) {
+ switch (action) {
+ case kUpdateDialogueAnimEndOfSentence:
+ PART_17_HELPER_9(0);
+ break;
+ case kUpdateDialogueAnimMiddleOfSentence:
+ PART_17_HELPER_9(getRandomNumber(7));
+ break;
+ }
+}
+
+void IgorEngine::PART_17_UPDATE_DIALOGUE_PHILIP_JIMMY(int action) {
+ switch (action) {
+ case kUpdateDialogueAnimEndOfSentence:
+ if (VAR_CURRENT_TALKING_ACTOR == 0) {
+ PART_17_HELPER_8(0);
+ } else {
+ PART_17_HELPER_11(0);
+ }
+ break;
+ case kUpdateDialogueAnimMiddleOfSentence:
+ if (VAR_CURRENT_TALKING_ACTOR == 0) {
+ PART_17_HELPER_8(getRandomNumber(7));
+ } else {
+ PART_17_HELPER_11(getRandomNumber(6));
+ }
+ break;
+ }
+}
+
+void IgorEngine::PART_17_UPDATE_ROOM_BACKGROUND() {
+ if (compareGameTick(3, 32) && _gameState.unkF) {
+ switch (_gameState.unk10 / 16) {
+ case 0:
+ PART_17_HELPER_8(0);
+ PART_17_HELPER_9(getRandomNumber(7));
+ break;
+ case 1:
+ PART_17_HELPER_8(getRandomNumber(7));
+ PART_17_HELPER_9(0);
+ }
+ if (_gameState.unk10 == 31) {
+ _gameState.unk10 = 0;
+ } else {
+ ++_gameState.unk10;
+ }
+ }
+}
+
+void IgorEngine::PART_17_HELPER_1(int num) {
+ if (num == 1 || num == 255) {
+ if (_objectsState[54] == 0) {
+ _gameState.unkF = false;
+ } else {
+ PART_17_HELPER_3(0);
+ _gameState.unkF = true;
+ }
+ }
+ if (num == 2 || num == 255) {
+ if (_objectsState[55] == 1) {
+ _roomActionsTable[2698] = 0;
+ }
+ }
+ if (num == 3 || num == 255) {
+ if (_objectsState[56] == 1) {
+ _gameState.unkF = false;
+ PART_17_HELPER_3(6);
+ }
+ }
+}
+
+void IgorEngine::PART_17_HELPER_2() {
+ for (int i = 17; i <= 85; ++i) {
+ _walkYScaleRoom[i] = ((i - 13) / 4) + 5;
+ }
+ for (int i = 86; i <= 135; ++i) {
+ _walkYScaleRoom[i] = 23;
+ }
+ WalkData *wd = &_walkData[0];
+ wd->setPos(21, 17, 3, 0);
+ wd->clipSkipX = 1;
+ wd->clipWidth = 4;
+ wd->scaleWidth = 6;
+ wd->xPosChanged = 1;
+ wd->dxPos = 0;
+ wd->yPosChanged = 1;
+ wd->dyPos = 0;
+ wd->scaleHeight = 6;
+ _walkDataLastIndex = 0;
+ _roomObjectAreasTable[_screenLayer2[36865]].area = 4;
+ buildWalkPath(21, 17, 65, 115);
+ _roomObjectAreasTable[_screenLayer2[36865]].area = 0;
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+ for (int i = 17; i <= 135; ++i) {
+ _walkYScaleRoom[i] = 50;
+ }
+ _walkData[0].setPos(36, 140, 3, 0);
+ _walkData[0].setDefaultScale();
+ _walkData[0].clipSkipX = 1;
+ _walkData[0].clipWidth = 30;
+ _walkDataLastIndex = 0;
+ _roomObjectAreasTable[_screenLayer2[44836]].area = 4;
+ buildWalkPath(36, 143, 41, 86);
+ _roomObjectAreasTable[_screenLayer2[44836]].area = 0;
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ for (int i = _walkDataCurrentIndex; i <= _walkDataLastIndex; ++i) {
+ _walkData[i].posNum = kFacingPositionFront;
+ }
+ waitForIgorMove();
+ PART_17_HELPER_5(0);
+ --_walkDataLastIndex;
+ buildWalkPath(41, 86, 45, 95);
+ _walkDataCurrentIndex = 2;
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+ _roomObjectAreasTable[5].area = 0;
+ _roomObjectAreasTable[10].area = 0;
+ _roomObjectAreasTable[11].area = 0;
+ _roomObjectAreasTable[13].area = 0;
+ _roomObjectAreasTable[16].area = 0;
+ _roomObjectAreasTable[17].area = 0;
+ _roomObjectAreasTable[26].area = 0;
+ _roomObjectAreasTable[28].area = 0;
+}
+
+void IgorEngine::PART_17_HELPER_3(int lum) {
+ _roomObjectAreasTable[18].y1Lum = lum;
+ _roomObjectAreasTable[19].y1Lum = lum;
+ _roomObjectAreasTable[20].y1Lum = lum;
+}
+
+void IgorEngine::PART_17_HELPER_4() {
+ int offset = 11642;
+ for (int i = 0; i <= 48; ++i) {
+ memcpy(_screenLayer1 + offset + i * 320, _animFramesBuffer + i * 44, 44);
+ memcpy(_screenVGA + offset + i * 320, _animFramesBuffer + i * 44, 44);
+ }
+}
+
+void IgorEngine::PART_17_HELPER_5(int lum) {
+ _roomObjectAreasTable[23].y1Lum = lum;
+ _roomObjectAreasTable[26].y1Lum = lum;
+ _roomObjectAreasTable[27].y1Lum = lum;
+ _roomObjectAreasTable[32].y1Lum = lum;
+}
+
+void IgorEngine::PART_17_HELPER_6() {
+ playMusic(2);
+ PART_17_HELPER_1(255);
+ fadeInPalette(768);
+ _walkData[0].setPos(274, 68, 4, 1);
+ _walkData[0].setDefaultScale();
+ _walkData[0].clipSkipX = 1;
+ _walkData[0].clipWidth = 30;
+ _walkCurrentFrame = 1;
+ _walkDataCurrentIndex = 0;
+ _walkDataLastIndex = 0;
+ _roomObjectAreasTable[_screenLayer2[22034]].area = 8;
+ _roomObjectAreasTable[_screenLayer2[23923]].area = 8;
+ buildWalkPath(274, 68, 243, 74);
+ _roomObjectAreasTable[_screenLayer2[22034]].area = 0;
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+ --_walkDataLastIndex;
+ buildWalkPath(243, 74, 205, 124);
+ _roomObjectAreasTable[_screenLayer2[23923]].area = 0;
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+ PART_17_HELPER_5(0);
+ _roomObjectAreasTable[5].area = 0;
+ _roomObjectAreasTable[10].area = 0;
+ _roomObjectAreasTable[11].area = 0;
+ _roomObjectAreasTable[13].area = 0;
+ _roomObjectAreasTable[16].area = 0;
+ _roomObjectAreasTable[17].area = 0;
+ _roomObjectAreasTable[26].area = 0;
+ _roomObjectAreasTable[28].area = 0;
+}
+
+void IgorEngine::PART_17_HELPER_8(int num) {
+ for (int i = 0; i <= 8; ++i) {
+ for (int j = 0; j <= 10; ++j) {
+ int offset = (36 + i) * 320 + 130 + j;
+ uint8 color = _screenVGA[offset];
+ if (color >= 0xF0 && color <= 0xF1) {
+ _screenTempLayer[i * 100 + j] = _screenVGA[offset];
+ } else {
+ _screenTempLayer[i * 100 + j] = _animFramesBuffer[num * 99 + i * 11 + j + 0x1967];
+ }
+ }
+ }
+ int offset = 11650;
+ for (int i = 0; i <= 8; ++i) {
+ memcpy(_screenVGA + i * 320 + offset, _screenTempLayer + i * 100, 11);
+ memcpy(_screenLayer1 + i * 320 + offset, _animFramesBuffer + num * 99 + i * 11 + 0x1967, 11);
+ }
+}
+
+void IgorEngine::PART_17_HELPER_9(int num) {
+ for (int i = 0; i <= 26; ++i) {
+ for (int j = 0; j <= 22; ++j) {
+ int offset = (36 + i) * 320 + 143 + j;
+ uint8 color = _screenVGA[offset];
+ if ((color >= 0xC0 && color <= 0xCF) || (color >= 0xF0 && color <= 0xF1)) {
+ _screenTempLayer[i * 100 + j] = _screenVGA[offset];
+ } else {
+ _screenTempLayer[i * 100 + j] = _animFramesBuffer[num * 621 + i * 23 + j + 0x86C];
+ }
+ }
+ }
+ int offset = 11663;
+ for (int i = 0; i <= 26; ++i) {
+ memcpy(_screenVGA + i * 320 + offset, _screenTempLayer + i * 100, 23);
+ memcpy(_screenLayer1 + i * 320 + offset, _animFramesBuffer + num * 621 + i * 23 + 0x86C, 23);
+ }
+}
+
+void IgorEngine::PART_17_HELPER_11(int frame) {
+ for (int i = 0; i <= 8; ++i) {
+ for (int j = 0; j <= 10; ++j) {
+ int offset = (i + 36) * 320 + j + 130;
+ uint8 color = _screenVGA[offset];
+ if (color != 0 && color != 240) {
+ color = _animFramesBuffer[0x1C1C + frame * 99 + i * 11 + j];
+ }
+ _screenTempLayer[100 * i + j] = color;
+ }
+ }
+ for (int i = 0; i <= 8; ++i) {
+ const int offset = i * 320 + 11650;
+ memcpy(_screenVGA + offset, _screenTempLayer + i * 100, 11);
+ memcpy(_screenLayer1 + offset, _animFramesBuffer + 0x1C1C + frame * 99 + i * 11, 11);
+ }
+}
+
+void IgorEngine::PART_17() {
+ _gameState.enableLight = 1;
+ loadRoomData(PAL_OutsideCollege, IMG_OutsideCollege, BOX_OutsideCollege, MSK_OutsideCollege, TXT_OutsideCollege);
+ static const int anm[] = { FRM_OutsideCollege1, FRM_OutsideCollege2, FRM_OutsideCollege3, FRM_OutsideCollege4, FRM_OutsideCollege5, 0 };
+ loadAnimData(anm);
+ loadActionData(DAT_OutsideCollege);
+ _roomDataOffsets = PART_17_ROOM_DATA_OFFSETS;
+ setRoomWalkBounds(0, 0, 286, 143);
+ SET_EXEC_ACTION_FUNC(1, &IgorEngine::PART_17_EXEC_ACTION);
+ _updateRoomBackground = &IgorEngine::PART_17_UPDATE_ROOM_BACKGROUND;
+ PART_17_HELPER_1(255);
+ memcpy(_screenVGA, _screenLayer1, 46080);
+ if (_objectsState[56] == 1) {
+ _gameState.unkF = false;
+ PART_17_HELPER_3(6);
+ _roomObjectAreasTable[14].object = 0;
+ _roomObjectAreasTable[15].object = 0;
+ _roomObjectAreasTable[19].object = 0;
+ } else if (_gameState.unkF) {
+ PART_17_HELPER_4();
+ _gameState.counter[4] = 1;
+ } else {
+ _roomObjectAreasTable[14].object = 0;
+ _roomObjectAreasTable[15].object = 0;
+ _roomObjectAreasTable[19].object = 0;
+ }
+ _currentAction.verb = kVerbWalk;
+ if (_currentPart == 170) {
+ fadeInPalette(768);
+ PART_17_HELPER_2();
+ } else if (_currentPart == 171) {
+ PART_17_HELPER_6();
+ }
+ showCursor();
+ _gameState.igorMoving = false;
+ while (_currentPart == 170 || _currentPart == 171) {
+ handleRoomInput();
+ if (compareGameTick(1, 16)) {
+ handleRoomIgorWalk();
+ }
+ if (compareGameTick(19, 32)) {
+ handleRoomDialogue();
+ }
+ if (compareGameTick(4, 8)) {
+ handleRoomInventoryScroll();
+ }
+ if (compareGameTick(1)) {
+ handleRoomLight();
+ }
+ PART_17_UPDATE_ROOM_BACKGROUND();
+ waitForTimer();
+ }
+ if (_objectsState[55] == 1) {
+ _objectsState[56] = 1;
+ }
+ if (_objectsState[54] == 0) {
+ _objectsState[54] = 1;
+ }
+ hideCursor();
+ fadeOutPalette(624);
+ _updateRoomBackground = 0;
+}
+
+} // namespace Igor
diff --git a/engines/igor/parts/part_18.cpp b/engines/igor/parts/part_18.cpp
new file mode 100644
index 0000000000..11abb3cf2e
--- /dev/null
+++ b/engines/igor/parts/part_18.cpp
@@ -0,0 +1,215 @@
+/* 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 "igor/igor.h"
+
+namespace Igor {
+
+void IgorEngine::PART_18_EXEC_ACTION(int action) {
+ switch (action) {
+ case 101:
+ ADD_DIALOGUE_TEXT(201, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 102:
+ ADD_DIALOGUE_TEXT(202, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 103:
+ ADD_DIALOGUE_TEXT(205, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startCutsceneDialogue(99, 54, 43, 63, 0);
+ waitForEndOfCutsceneDialogue(99, 54, 43, 63, 0);
+ break;
+ case 104:
+ ADD_DIALOGUE_TEXT(206, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startCutsceneDialogue(132, 55, 63, 42, 0);
+ waitForEndOfCutsceneDialogue(132, 55, 63, 42, 0);
+ break;
+ case 105:
+ ADD_DIALOGUE_TEXT(207, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startCutsceneDialogue(167, 56, 0, 42, 42);
+ waitForEndOfCutsceneDialogue(167, 56, 0, 42, 42);
+ break;
+ case 106:
+ ADD_DIALOGUE_TEXT(208, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 107:
+ ADD_DIALOGUE_TEXT(209, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 108:
+ ADD_DIALOGUE_TEXT(210, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 109:
+ PART_18_ACTION_109();
+ break;
+ case 110:
+ _currentPart = 252;
+ break;
+ case 111:
+ PART_18_ACTION_111();
+ break;
+ default:
+ error("PART_18_EXEC_ACTION unhandled action %d", action);
+ break;
+ }
+}
+
+void IgorEngine::PART_18_ACTION_109() {
+ const int offset = 29480;
+ for (int i = 1; i <= 2; ++i) {
+ for (int j = 1; j <= 48; ++j) {
+ memcpy(_screenVGA + j * 320 + offset, _animFramesBuffer + (i - 1) * 1519 + j * 31, 31);
+ }
+ waitForTimer(120);
+ }
+ int part = _currentPart;
+ _currentPart = 191;
+ fadeOutPalette(768);
+ PART_19();
+ memcpy(_screenVGA, _screenLayer2, 46080);
+ loadResourceData__ROOM_MenToilets();
+ loadResourceData__ANIM_MenToilets();
+ loadActionData(DAT_MenToilets);
+ _roomDataOffsets = PART_18_ROOM_DATA_OFFSETS;
+ setRoomWalkBounds(0, 0, 319, 143);
+ SET_EXEC_ACTION_FUNC(1, &IgorEngine::PART_18_EXEC_ACTION);
+ PART_18_HELPER_1(255);
+ memset(_screenVGA + 46080, 0, 17920);
+ drawVerbsPanel();
+ removeObjectFromInventory(53);
+ fadeInPalette(768);
+ _currentPart = part;
+ ADD_DIALOGUE_TEXT(215, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+}
+
+void IgorEngine::PART_18_ACTION_111() {
+ if (_objectsState[0] == 0) {
+ ADD_DIALOGUE_TEXT(211, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ return;
+ }
+ if (_objectsState[0] == 2) {
+ ADD_DIALOGUE_TEXT(212, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ return;
+ }
+ const int offset = 26798;
+ for (int i = 0; i <= 28; ++i) {
+ memcpy(_screenVGA + i * 320 + offset, _animFramesBuffer + i * 28 + 0xF0A, 28);
+ }
+ playSound(47, 1);
+ for (int i = 1; i <= 2; ++i) {
+ waitForTimer(200);
+ }
+ for (int i = 0; i <= 28; ++i) {
+ memcpy(_screenVGA + i * 320 + offset, _animFramesBuffer + i * 28 + 0xBDE, 28);
+ }
+ ADD_DIALOGUE_TEXT(213, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ _objectsState[0] = 2;
+ UPDATE_OBJECT_STATE(1);
+}
+
+void IgorEngine::PART_18_HELPER_1(int num) {
+}
+
+void IgorEngine::PART_18_HELPER_2() {
+ _walkData[0].setPos(319, 142, 4, 0);
+ _walkData[0].clipSkipX = 1;
+ _walkData[0].clipWidth = 15;
+ _walkData[0].scaleWidth = 50;
+ _walkData[0].xPosChanged = 1;
+ _walkData[0].dxPos = 0;
+ _walkData[0].yPosChanged = 1;
+ _walkData[0].dyPos = 0;
+ _walkData[0].scaleHeight = 50;
+ _walkDataLastIndex = 0;
+ buildWalkPath(319, 142, 295, 142);
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+}
+
+void IgorEngine::PART_18() {
+ _gameState.enableLight = 1;
+ loadResourceData__ROOM_MenToilets();
+ loadResourceData__ANIM_MenToilets();
+ loadActionData(DAT_MenToilets);
+ _roomDataOffsets = PART_18_ROOM_DATA_OFFSETS;
+ setRoomWalkBounds(0, 0, 319, 143);
+ SET_EXEC_ACTION_FUNC(1, &IgorEngine::PART_18_EXEC_ACTION);
+ PART_18_HELPER_1(255);
+ memcpy(_screenVGA, _screenLayer1, 46080);
+ _currentAction.verb = kVerbWalk;
+ fadeInPalette(768);
+ PART_18_HELPER_2();
+ showCursor();
+ _gameState.igorMoving = false;
+ while (_currentPart == 180) {
+ handleRoomInput();
+ if (compareGameTick(1, 16)) {
+ handleRoomIgorWalk();
+ }
+ if (compareGameTick(19, 32)) {
+ handleRoomDialogue();
+ }
+ if (compareGameTick(4, 8)) {
+ handleRoomInventoryScroll();
+ }
+ if (compareGameTick(1)) {
+ handleRoomLight();
+ }
+ waitForTimer();
+ }
+ fadeOutPalette(624);
+}
+
+void IgorEngine::loadResourceData__ROOM_MenToilets() {
+ loadRoomData(PAL_MenToilets, IMG_MenToilets, BOX_MenToilets, MSK_MenToilets, TXT_MenToilets);
+}
+
+void IgorEngine::loadResourceData__ANIM_MenToilets() {
+ static const int anm[] = { FRM_MenToilets1, FRM_MenToilets2, 0 };
+ loadAnimData(anm);
+}
+
+} // namespace Igor
diff --git a/engines/igor/parts/part_19.cpp b/engines/igor/parts/part_19.cpp
new file mode 100644
index 0000000000..e7cf3b4327
--- /dev/null
+++ b/engines/igor/parts/part_19.cpp
@@ -0,0 +1,336 @@
+/* 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 "igor/igor.h"
+
+namespace Igor {
+
+static int VAR_CURRENT_TALKING_ACTOR;
+
+void IgorEngine::PART_19_EXEC_ACTION(int action) {
+ switch (action) {
+ case 101:
+ ADD_DIALOGUE_TEXT(201, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 102:
+ ADD_DIALOGUE_TEXT(202, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startCutsceneDialogue(99, 54, 43, 63, 0);
+ waitForEndOfCutsceneDialogue(99, 54, 43, 63, 0);
+ break;
+ case 103:
+ ADD_DIALOGUE_TEXT(203, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startCutsceneDialogue(132, 55, 63, 42, 0);
+ waitForEndOfCutsceneDialogue(132, 55, 63, 42, 0);
+ break;
+ case 104:
+ ADD_DIALOGUE_TEXT(204, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startCutsceneDialogue(167, 56, 0, 42, 42);
+ waitForEndOfCutsceneDialogue(167, 56, 0, 42, 42);
+ break;
+ case 105:
+ ADD_DIALOGUE_TEXT(205, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 106:
+ _currentPart = 232;
+ break;
+ case 107:
+ PART_19_ACTION_107();
+ break;
+ case 108:
+ ADD_DIALOGUE_TEXT(208, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 109:
+ PART_19_ACTION_109();
+ break;
+ default:
+ error("PART_19_EXEC_ACTION unhandled action %d", action);
+ break;
+ }
+}
+
+void IgorEngine::PART_19_ACTION_107() {
+ if (_objectsState[58] == 1) {
+ ADD_DIALOGUE_TEXT(211, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ return;
+ }
+ ADD_DIALOGUE_TEXT(206, 1);
+ ADD_DIALOGUE_TEXT(207, 1);
+ SET_DIALOGUE_TEXT(1, 2);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ for (int i = 1; i <= 2; ++i) {
+ const int offset = 27110;
+ for (int j = 0; j <= 48; ++j) {
+ memcpy(_screenVGA + j * 320 + offset, _animFramesBuffer + i * 1372 + j * 28 - 506, 28);
+ waitForTimer(120);
+ }
+ }
+ addObjectToInventory(12, 47);
+ _objectsState[58] = 1;
+ PART_19_HELPER_1(255);
+}
+
+void IgorEngine::PART_19_ACTION_109() {
+ if (_objectsState[2] == 1) {
+ ADD_DIALOGUE_TEXT(210, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ return;
+ }
+ for (int i = 1; i <= 4; ++i) {
+ const uint8 *src = _animFramesBuffer + READ_LE_UINT16(_animFramesBuffer + 0x354 + i * 2) - 1;
+ decodeAnimFrame(src, _screenVGA, true);
+ waitForTimer(45);
+ }
+ decodeAnimFrame(_animFramesBuffer + READ_LE_UINT16(_animFramesBuffer + 0x35E) - 1, _screenVGA, true);
+ playSound(45, 1);
+ PART_19_HELPER_5();
+ PART_19_HELPER_1(255);
+ stopSound();
+ decodeAnimFrame(_animFramesBuffer + READ_LE_UINT16(_animFramesBuffer + 0x360) - 1, _screenVGA, true);
+ ADD_DIALOGUE_TEXT(209, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+}
+
+void IgorEngine::PART_19_UPDATE_DIALOGUE_WOMEN(int action) {
+ switch (action) {
+ case kUpdateDialogueAnimEndOfSentence:
+ PART_19_HELPER_7((VAR_CURRENT_TALKING_ACTOR == 0) ? 35 : 40);
+ break;
+ case kUpdateDialogueAnimMiddleOfSentence:
+ PART_19_HELPER_7((VAR_CURRENT_TALKING_ACTOR == 0) ? 35 + getRandomNumber(5) : 40 + getRandomNumber(5));
+ break;
+ }
+}
+
+void IgorEngine::PART_19_UPDATE_BACKGROUND_HELPER_9() {
+ if (compareGameTick(3, 64) && _gameState.counter[1] <= 34) {
+ const uint8 *src = _animFramesBuffer + 0xE1A + READ_LE_UINT16(_animFramesBuffer + 0x404F + _gameState.counter[1] * 2) - 1;
+ decodeAnimFrame(src, _screenVGA, true);
+ ++_gameState.counter[1];
+ }
+}
+
+void IgorEngine::PART_19_HELPER_1(int num) {
+ if (num == 2 || num == 255) {
+ if (_objectsState[59] == 0) {
+ decodeAnimFrame(_animFramesBuffer + 0xE1A + READ_LE_UINT16(_animFramesBuffer + 0x4051) - 1, _screenLayer1, true);
+ }
+ }
+}
+
+void IgorEngine::PART_19_HELPER_2() {
+ int talkSpeed = _gameState.talkSpeed;
+ _gameState.talkSpeed = 5;
+ memcpy(_screenLayer2, _screenVGA, 46080);
+ memcpy(_screenVGA, _screenLayer1, 46080);
+ const uint8 *src = _animFramesBuffer + 0xE1A + READ_LE_UINT16(_animFramesBuffer + 0x4051) - 1;
+ decodeAnimFrame(src, _screenVGA, true);
+ memcpy(_screenLayer1, _screenVGA, 46080);
+ fadeInPalette(624);
+ ADD_DIALOGUE_TEXT(212, 3);
+ SET_DIALOGUE_TEXT(1, 1);
+ startCutsceneDialogue(243, 92, 63, 23, 33);
+ VAR_CURRENT_TALKING_ACTOR = 0;
+ _updateDialogue = &IgorEngine::PART_19_UPDATE_DIALOGUE_WOMEN;
+ waitForEndOfCutsceneDialogue(243, 92, 63, 23, 33);
+ _updateDialogue = 0;
+ for (int i = 2; i <= 9; ++i) {
+ src = _animFramesBuffer + 0xE1A + READ_LE_UINT16(_animFramesBuffer + 0x404F + i * 2) - 1;
+ waitForTimer(60);
+ }
+ ADD_DIALOGUE_TEXT(215, 1);
+ ADD_DIALOGUE_TEXT(216, 2);
+ SET_DIALOGUE_TEXT(1, 2);
+ startCutsceneDialogue(227, 91, 0, 63, 63);
+ _gameState.counter[1] = 10;
+ VAR_CURRENT_TALKING_ACTOR = 1;
+ _updateRoomBackground = &IgorEngine::PART_19_UPDATE_BACKGROUND_HELPER_9;
+ waitForEndOfCutsceneDialogue(227, 91, 0, 63, 63);
+ _updateRoomBackground = 0;
+ while (_gameState.counter[1] != 35) {
+ PART_19_UPDATE_BACKGROUND_HELPER_9();
+ }
+ for (int i = 47; i <= 48; ++i) {
+ src = _animFramesBuffer + 0xE1A + READ_LE_UINT16(_animFramesBuffer + 0x404F + i * 2) - 1;
+ decodeAnimFrame(src, _screenVGA, true);
+ waitForTimer(30);
+ }
+ for (int i = 1; i <= 3; ++i) {
+ for (int j = 49; j <= 50; ++j) {
+ src = _animFramesBuffer + 0xE1A + READ_LE_UINT16(_animFramesBuffer + 0x404F + j * 2) - 1;
+ decodeAnimFrame(src, _screenVGA, true);
+ waitForTimer(30);
+ if (j == 50) {
+ playSound(46, 1);
+ }
+ }
+ }
+ src = _animFramesBuffer + 0xE1A + READ_LE_UINT16(_animFramesBuffer + 0x40B5) - 1;
+ decodeAnimFrame(src, _screenVGA, true);
+ waitForTimer(30);
+ ADD_DIALOGUE_TEXT(218, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startCutsceneDialogue(243, 92, 63, 23, 33);
+ VAR_CURRENT_TALKING_ACTOR = 0;
+ _updateDialogue = &IgorEngine::PART_19_UPDATE_DIALOGUE_WOMEN;
+ waitForEndOfCutsceneDialogue(243, 92, 63, 23, 33);
+ _updateDialogue = 0;
+ ADD_DIALOGUE_TEXT(219, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startCutsceneDialogue(227, 91, 0, 63, 63);
+ VAR_CURRENT_TALKING_ACTOR = 1;
+ _updateDialogue = &IgorEngine::PART_19_UPDATE_DIALOGUE_WOMEN;
+ waitForEndOfCutsceneDialogue(227, 91, 0, 63, 63);
+ _updateDialogue = 0;
+ ADD_DIALOGUE_TEXT(221, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startCutsceneDialogue(243, 92, 63, 23, 33);
+ VAR_CURRENT_TALKING_ACTOR = 0;
+ _updateDialogue = &IgorEngine::PART_19_UPDATE_DIALOGUE_WOMEN;
+ waitForEndOfCutsceneDialogue(243, 92, 63, 23, 33);
+ _updateDialogue = 0;
+ ADD_DIALOGUE_TEXT(223, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startCutsceneDialogue(227, 91, 0, 63, 63);
+ VAR_CURRENT_TALKING_ACTOR = 1;
+ _updateDialogue = &IgorEngine::PART_19_UPDATE_DIALOGUE_WOMEN;
+ waitForEndOfCutsceneDialogue(227, 91, 0, 63, 63);
+ _updateDialogue = 0;
+ _objectsState[59] = 1;
+ fadeOutPalette(624);
+ _gameState.talkSpeed = talkSpeed;
+}
+
+void IgorEngine::PART_19_HELPER_3() {
+ _walkData[0].setPos(319, 142, 1, 0);
+ _walkData[0].setDefaultScale();
+ _walkData[0].clipSkipX = 1;
+ _walkData[0].clipWidth = 15;
+ _walkDataLastIndex = 0;
+ buildWalkPath(319, 142, 295, 142);
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+}
+
+void IgorEngine::PART_19_HELPER_4() {
+ decodeAnimFrame(_animFramesBuffer + 0xE1A + READ_LE_UINT16(_animFramesBuffer + 0x40AB) - 1, _screenVGA, true);
+ waitForTimer(60);
+ ADD_DIALOGUE_TEXT(225, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ --_walkDataLastIndex;
+ buildWalkPath(295, 142, 319, 142);
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+ _currentPart = 232;
+}
+
+void IgorEngine::PART_19_HELPER_5() {
+ fadeOutPalette(624);
+ uint8 *tmp = (uint8 *)malloc(64000 + 768);
+ if (tmp) {
+ memcpy(tmp, _screenVGA, 64000);
+ memcpy(tmp + 64000, _paletteBuffer, 768);
+ }
+ loadData(IMG_RomanNumbersPaper, _screenVGA);
+ loadData(PAL_RomanNumbersPaper, _paletteBuffer);
+ fadeInPalette(624);
+ PART_UPDATE_FIGURES_ON_PAPER(60);
+ _objectsState[2] = 1;
+ waitForTimer(255);
+ if (tmp) {
+ memcpy(_screenVGA, tmp, 64000);
+ memcpy(_paletteBuffer, tmp + 64000, 768);
+ free(tmp);
+ }
+}
+
+void IgorEngine::PART_19_HELPER_7(int frame) {
+ const uint8 *src = _animFramesBuffer + 0xE1A + READ_LE_UINT16(_animFramesBuffer + 0x404F + frame * 2) - 1;
+ decodeAnimFrame(src, _screenVGA, true);
+}
+
+void IgorEngine::PART_19() {
+ _gameState.enableLight = 1;
+ loadRoomData(PAL_WomenToilets, IMG_WomenToilets, BOX_WomenToilets, MSK_WomenToilets, TXT_WomenToilets);
+ static const int anm[] = { FRM_WomenToilets1, FRM_WomenToilets2, FRM_WomenToilets3, FRM_WomenToilets4, FRM_WomenToilets5, 0 };
+ loadAnimData(anm);
+ loadActionData(DAT_WomenToilets);
+ _roomDataOffsets = PART_19_ROOM_DATA_OFFSETS;
+ setRoomWalkBounds(0, 0, 319, 143);
+ if (_currentPart == 191) {
+ PART_19_HELPER_2();
+ } else {
+ SET_EXEC_ACTION_FUNC(1, &IgorEngine::PART_19_EXEC_ACTION);
+ PART_19_HELPER_1(255);
+ }
+ memcpy(_screenVGA, _screenLayer1, 46080);
+ _currentAction.verb = kVerbWalk;
+ fadeInPalette(768);
+ PART_19_HELPER_3();
+ if (_objectsState[59] == 0) {
+ PART_19_HELPER_4();
+ } else {
+ showCursor();
+ _gameState.igorMoving = false;
+ while (_currentPart == 190) {
+ handleRoomInput();
+ if (compareGameTick(1, 16)) {
+ handleRoomIgorWalk();
+ }
+ if (compareGameTick(19, 32)) {
+ handleRoomDialogue();
+ }
+ if (compareGameTick(4, 8)) {
+ handleRoomInventoryScroll();
+ }
+ if (compareGameTick(1)) {
+ handleRoomLight();
+ }
+ waitForTimer();
+ }
+ }
+ fadeOutPalette(624);
+}
+
+} // namespace Igor
diff --git a/engines/igor/parts/part_21.cpp b/engines/igor/parts/part_21.cpp
new file mode 100644
index 0000000000..2e4a39aec5
--- /dev/null
+++ b/engines/igor/parts/part_21.cpp
@@ -0,0 +1,492 @@
+/* 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 "igor/igor.h"
+
+namespace Igor {
+
+static const uint8 PART_21_ANIM_DATA_1[7] = { 0, 11, 12, 13, 20, 21, 14 };
+
+static const uint8 PART_21_ANIM_DATA_2[11] = { 0, 4, 5, 4, 5, 4, 5, 4, 5, 6, 0 };
+
+static bool IN_ACTION_111;
+
+void IgorEngine::PART_21_EXEC_ACTION(int action) {
+ switch (action) {
+ case 101:
+ PART_21_ACTION_101();
+ break;
+ case 102:
+ PART_21_ACTION_102();
+ break;
+ case 103:
+ ADD_DIALOGUE_TEXT(201, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 104:
+ ADD_DIALOGUE_TEXT(202, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 105:
+ ADD_DIALOGUE_TEXT(203, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 106:
+ ADD_DIALOGUE_TEXT(204, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 107:
+ PART_21_ACTION_107();
+ break;
+ case 108:
+ PART_21_ACTION_108();
+ break;
+ case 109:
+ ADD_DIALOGUE_TEXT(205, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 110:
+ PART_21_ACTION_110();
+ break;
+ case 111:
+ PART_21_ACTION_111();
+ break;
+ case 112:
+ ADD_DIALOGUE_TEXT(222, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 113:
+ PART_21_ACTION_113();
+ break;
+ default:
+ error("PART_21_EXEC_ACTION unhandled action %d", action);
+ break;
+ }
+}
+
+void IgorEngine::PART_21_ACTION_101() {
+ if (_objectsState[65] == 1) {
+ const int offset = 29440;
+ for (int i = 0; i <= 50; ++i) {
+ memcpy(_screenVGA + i * 320 + offset, _screenLayer1 + i * 320 + offset, 20);
+ }
+ PART_21_HELPER_10();
+ }
+ _currentPart = 303;
+}
+
+void IgorEngine::PART_21_ACTION_102() {
+ PART_21_HELPER_6(1);
+ ADD_DIALOGUE_TEXT(226, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ ADD_DIALOGUE_TEXT(227, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startCutsceneDialogue(76, 87, 63, 32, 0);
+ _updateDialogue = &IgorEngine::PART_21_UPDATE_DIALOGUE_MARGARET_2;
+ waitForEndOfCutsceneDialogue(76, 87, 63, 32, 0);
+ _updateDialogue = 0;
+ PART_21_HANDLE_DIALOGUE_MARGARET();
+ PART_21_HELPER_1(255);
+}
+
+void IgorEngine::PART_21_ACTION_107() {
+ if (_objectsState[64] == 1) {
+ EXEC_MAIN_ACTION(11);
+ return;
+ }
+ for (int i = 2; i <= 3; ++i) {
+ const int offset = 21902;
+ for (int j = 0; j <= 53; ++j) {
+ memcpy(_screenVGA + j * 320 + offset, _animFramesBuffer + (i - 1) * 1782 + j * 33, 33);
+ }
+ if (i == 3) {
+ playSound(13, 1);
+ } else {
+ waitForTimer(100);
+ }
+ }
+ _objectsState[64] = 1;
+ PART_21_HELPER_1(1);
+}
+
+void IgorEngine::PART_21_ACTION_108() {
+ if (_objectsState[64] == 0) {
+ EXEC_MAIN_ACTION(14);
+ return;
+ }
+ for (int i = 2; i >= 1; --i) {
+ const int offset = 21902;
+ for (int j = 0; j <= 53; ++j) {
+ memcpy(_screenVGA + j * 320 + offset, _animFramesBuffer + (i - 1) * 1782 + j * 33, 33);
+ }
+ if (i == 2) {
+ playSound(14, 1);
+ waitForTimer(100);
+ }
+ }
+ _objectsState[64] = 0;
+ PART_21_HELPER_1(1);
+}
+
+void IgorEngine::PART_21_ACTION_110() {
+ if (_objectsState[65] == 1) {
+ const int offset = 27180;
+ for (int i = 0; i <= 50; ++i) {
+ memcpy(_screenVGA + i * 320 + offset, _screenLayer1 + i * 320 + offset, 20);
+ }
+ PART_21_HELPER_10();
+ }
+ _currentPart = 270;
+}
+
+void IgorEngine::PART_21_ACTION_111() {
+ if (_inventoryInfo[65] == 0) {
+ ADD_DIALOGUE_TEXT(223, 2);
+ ADD_DIALOGUE_TEXT(225, 1);
+ SET_DIALOGUE_TEXT(1, 2);
+ startIgorDialogue();
+ return;
+ }
+ IN_ACTION_111 = true;
+ ADD_DIALOGUE_TEXT(208, 1);
+ ADD_DIALOGUE_TEXT(209, 1);
+ SET_DIALOGUE_TEXT(1, 2);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ const int offset = 28183;
+ for (int i = 0; i <= 49; ++i) {
+ memcpy(_screenVGA + i * 320 + offset, _animFramesBuffer + 0xCBE1 + i * 26, 26);
+ }
+ waitForTimer(100);
+ int i = 1;
+ do {
+ if (compareGameTick(3, 24)) {
+ for (int j = 0; j <= 49; ++j) {
+ memcpy(_screenVGA + j * 320 + offset, _animFramesBuffer + 0xBCA5 + PART_21_ANIM_DATA_2[i] * 1300 + j * 26, 26);
+ }
+ ++i;
+ }
+ PART_21_UPDATE_ROOM_BACKGROUND();
+ waitForTimer();
+ } while (i != 10);
+ IN_ACTION_111 = false;
+ removeObjectFromInventory(56);
+ _objectsState[65] = 1;
+ PART_21_HELPER_1(255);
+ ADD_DIALOGUE_TEXT(210, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+}
+
+void IgorEngine::PART_21_ACTION_113() {
+ if (_objectsState[64] != 0) {
+ _roomObjectAreasTable[_screenLayer2[34679]].area = 1;
+ --_walkDataLastIndex;
+ buildWalkPathSimple(165, 126, 119, 108);
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+ if (_objectsState[65] == 1) {
+ PART_21_HELPER_10();
+ }
+ _currentPart = 370;
+ }
+}
+
+void IgorEngine::PART_21_UPDATE_DIALOGUE_MARGARET_1(int action) {
+ switch (action) {
+ case kUpdateDialogueAnimEndOfSentence:
+ PART_21_HELPER_11(6);
+ break;
+ case kUpdateDialogueAnimMiddleOfSentence:
+ PART_21_HELPER_11(getRandomNumber(5) + 6);
+ break;
+ case kUpdateDialogueAnimStanding:
+ PART_21_HELPER_11(1);
+ break;
+ }
+}
+
+void IgorEngine::PART_21_UPDATE_DIALOGUE_MARGARET_2(int action) {
+ switch (action) {
+ case kUpdateDialogueAnimEndOfSentence:
+ PART_21_HELPER_6(6);
+ break;
+ case kUpdateDialogueAnimMiddleOfSentence:
+ PART_21_HELPER_6(getRandomNumber(5) + 6);
+ break;
+ }
+}
+
+void IgorEngine::PART_21_UPDATE_DIALOGUE_MARGARET_3(int action) {
+ switch (action) {
+ case kUpdateDialogueAnimEndOfSentence:
+ PART_21_HELPER_6(15);
+ break;
+ case kUpdateDialogueAnimMiddleOfSentence:
+ PART_21_HELPER_6(getRandomNumber(5) + 15);
+ break;
+ }
+}
+
+void IgorEngine::PART_21_HANDLE_DIALOGUE_MARGARET() {
+ loadDialogueData(DLG_CollegeCorridorMargaret);
+ _updateDialogue = &IgorEngine::PART_21_UPDATE_DIALOGUE_MARGARET_1;
+ handleDialogue(81, 76, 63, 32, 0);
+ _updateDialogue = 0;
+}
+
+void IgorEngine::PART_21_HELPER_1(int num) {
+ if (num == 1 || num == 255) {
+ if (_objectsState[64] == 0) {
+ PART_21_HELPER_7();
+ _roomActionsTable[4] = 6;
+ } else {
+ PART_21_HELPER_8();
+ _roomActionsTable[4] = 7;
+ }
+ }
+ if (num == 2 || num == 255) {
+ if (_objectsState[65] > 1) {
+ PART_21_HELPER_9();
+ }
+ if (_objectsState[65] == 2 || _objectsState[65] == 4) {
+ _roomObjectAreasTable[9].object = 0;
+ _roomObjectAreasTable[10].object = 0;
+ }
+ }
+}
+
+void IgorEngine::PART_21_HELPER_2() {
+ _walkData[0].setPos(0, 141, 2, 0);
+ _walkData[0].setDefaultScale();
+ _walkData[0].clipSkipX = 15;
+ _walkData[0].clipWidth = 15;
+ _walkDataLastIndex = 0;
+ buildWalkPathSimple(0, 141, 32, 137);
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+}
+
+void IgorEngine::PART_21_HELPER_3() {
+ _walkData[0].setPos(319, 133, 4, 0);
+ _walkData[0].setDefaultScale();
+ _walkData[0].clipWidth = 15;
+ _walkDataLastIndex = 0;
+ buildWalkPathSimple(319, 133, 239, 133);
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+}
+
+void IgorEngine::PART_21_HELPER_4() {
+ _walkData[0].setPos(119, 108, 2, 0);
+ _walkData[0].setDefaultScale();
+ _walkDataLastIndex = 0;
+ _roomObjectAreasTable[_screenLayer2[34679]].area = 1;
+ buildWalkPathSimple(119, 108, 175, 130);
+ _roomObjectAreasTable[_screenLayer2[34679]].area = 0;
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+}
+
+void IgorEngine::PART_21_HELPER_6(int frame) {
+ _roomCursorOn = false;
+ for (int i = 0; i <= 42; ++i) {
+ for (int j = 0; j <= 48; ++j) {
+ int offset = (i + 89) * 320 + j + 40;
+ uint8 color = _screenVGA[offset];
+ if ((color >= 192 && color <= 207) || color == 240 || color == 241) {
+ _screenTempLayer[i * 100 + j] = _screenVGA[offset];
+ } else {
+ _screenTempLayer[i * 100 + j] = _animFramesBuffer[frame * 2107 + i * 49 + j + 0xCA7];
+ }
+ }
+ }
+ int offset = 28520;
+ for (int i = 0; i <= 42; ++i) {
+ memcpy(_screenVGA + i * 320 + offset, _screenTempLayer + i * 100, 49);
+ memcpy(_screenLayer1 + i * 320 + offset, _animFramesBuffer + frame * 2107 + i * 49 + 0xCA7, 49);
+ }
+ if (_dialogueCursorOn) {
+ _roomCursorOn = true;
+ }
+}
+
+void IgorEngine::PART_21_HELPER_7() {
+ const int offset = 21901;
+ for (int i = 0; i <= 53; ++i) {
+ memcpy(_screenLayer1 + i * 320 + offset, _animFramesBuffer + i * 33 + 0xE031, 33);
+ }
+}
+
+void IgorEngine::PART_21_HELPER_8() {
+ const int offset = 21901;
+ for (int i = 0; i <= 53; ++i) {
+ memcpy(_screenLayer1 + i * 320 + offset, _animFramesBuffer + i * 33 + 0xE727, 33);
+ }
+}
+
+void IgorEngine::PART_21_HELPER_9() {
+ const int offset = 21901;
+ for (int i = 0; i <= 42; ++i) {
+ memcpy(_screenLayer1 + i * 320 + offset, _animFramesBuffer + i * 49 + 0x14E2, 49);
+ }
+}
+
+void IgorEngine::PART_21_HELPER_10() {
+ PART_21_HELPER_6(1);
+ memset(_screenVGA + 46080, 0, 17920);
+ waitForTimer(120);
+ for (int i = 1; i <= 6; ++i) {
+ PART_21_HELPER_6(PART_21_ANIM_DATA_1[i]);
+ if (i < 6) {
+ waitForTimer(100);
+ }
+ }
+ ADD_DIALOGUE_TEXT(212, 1);
+ ADD_DIALOGUE_TEXT(213, 1);
+ ADD_DIALOGUE_TEXT(214, 1);
+ ADD_DIALOGUE_TEXT(215, 2);
+ ADD_DIALOGUE_TEXT(217, 2);
+ SET_DIALOGUE_TEXT(1, 5);
+ startCutsceneDialogue(76, 87, 63, 32, 0);
+ _updateDialogue = &IgorEngine::PART_21_UPDATE_DIALOGUE_MARGARET_3;
+ waitForEndOfCutsceneDialogue(76, 87, 63, 32, 0);
+ _updateDialogue = 0;
+ ADD_DIALOGUE_TEXT(219, 1);
+ ADD_DIALOGUE_TEXT(220, 1);
+ ADD_DIALOGUE_TEXT(221, 1);
+ SET_DIALOGUE_TEXT(1, 3);
+ startCutsceneDialogue(76, 87, 63, 32, 0);
+ _updateDialogue = &IgorEngine::PART_21_UPDATE_DIALOGUE_MARGARET_3;
+ waitForEndOfCutsceneDialogue(76, 87, 63, 32, 0);
+ _updateDialogue = 0;
+ _objectsState[65] = 2;
+ drawVerbsPanel();
+ _currentAction.verb = kVerbWalk;
+ drawInventory(_inventoryInfo[72], 0);
+ PART_21_HELPER_1(255);
+ _objectsState[110] = 1;
+}
+
+void IgorEngine::PART_21_HELPER_11(int frame) {
+ const int offset = 28520;
+ for (int i = 0; i <= 42; ++i) {
+ memcpy(_screenLayer1 + i * 320 + offset, _animFramesBuffer + frame * 2107 + i * 49 + 0xCA7, 49);
+ }
+}
+
+void IgorEngine::PART_21_UPDATE_ROOM_BACKGROUND() {
+ if (IN_ACTION_111 && compareGameTick(3, 24)) {
+ const int offset = 28183;
+ int i = getRandomNumber(2) + 1;
+ for (int j = 0; j <= 49; ++j) {
+ memcpy(_screenVGA + j * 320 + offset, _animFramesBuffer + 0xBCA5 + i * 1300 + j * 26, 26);
+ }
+ ++i;
+ }
+ if (compareGameTick(61) && _objectsState[65] <= 1) {
+ if (_gameState.unk10 > 2) {
+ PART_21_HELPER_6(_gameState.unk10);
+ ++_gameState.unk10;
+ if (_gameState.unk10 == 6) {
+ ++_gameState.counter[4];
+ if (_gameState.counter[4] < 2) {
+ _gameState.unk10 = 4;
+ } else {
+ _gameState.counter[4] = 0;
+ _gameState.unk10 = 1;
+ }
+ }
+ } else {
+ PART_21_HELPER_6(_gameState.unk10);
+ ++_gameState.unk10;
+ if (_gameState.unk10 == 3 && getRandomNumber(6) != 0) {
+ _gameState.unk10 = 1;
+ }
+ }
+ }
+}
+
+void IgorEngine::PART_21() {
+ _gameState.enableLight = 2;
+ loadRoomData(PAL_CollegeCorridorMargaret, IMG_CollegeCorridorMargaret, BOX_CollegeCorridorMargaret, MSK_CollegeCorridorMargaret, TXT_CollegeCorridorMargaret);
+ static const int anm[] = { FRM_CollegeCorridorMargaret1, FRM_CollegeCorridorMargaret2, FRM_CollegeCorridorMargaret3, FRM_CollegeCorridorMargaret4, 0 };
+ loadAnimData(anm);
+ loadActionData(DAT_CollegeCorridorMargaret);
+ _roomDataOffsets = PART_21_ROOM_DATA_OFFSETS;
+ setRoomWalkBounds(0, 0, 319, 143);
+ SET_EXEC_ACTION_FUNC(1, &IgorEngine::PART_21_EXEC_ACTION);
+ _updateRoomBackground = &IgorEngine::PART_21_UPDATE_ROOM_BACKGROUND;
+ PART_21_HELPER_1(255);
+ memcpy(_screenVGA, _screenLayer1, 46080);
+ _currentAction.verb = kVerbWalk;
+ _gameState.unk10 = 1;
+ fadeInPalette(768);
+ if (_currentPart == 210) {
+ PART_21_HELPER_2();
+ } else if (_currentPart == 211) {
+ PART_21_HELPER_3();
+ } else if (_currentPart == 212) {
+ PART_21_HELPER_4();
+ }
+ showCursor();
+ _gameState.igorMoving = false;
+ while (_currentPart == 210 || _currentPart == 211 || _currentPart == 212) {
+ handleRoomInput();
+ if (compareGameTick(1, 16)) {
+ handleRoomIgorWalk();
+ }
+ if (compareGameTick(19, 32)) {
+ handleRoomDialogue();
+ }
+ if (compareGameTick(4, 8)) {
+ handleRoomInventoryScroll();
+ }
+ if (compareGameTick(1)) {
+ handleRoomLight();
+ }
+ PART_21_UPDATE_ROOM_BACKGROUND();
+ waitForTimer();
+ }
+ fadeOutPalette(624);
+ _updateRoomBackground = 0;
+}
+
+} // namespace Igor
diff --git a/engines/igor/parts/part_22.cpp b/engines/igor/parts/part_22.cpp
new file mode 100644
index 0000000000..5ed1ca3f7c
--- /dev/null
+++ b/engines/igor/parts/part_22.cpp
@@ -0,0 +1,186 @@
+/* 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 "igor/igor.h"
+
+namespace Igor {
+
+static const uint8 PART_22_ANIM_DATA_1[4] = { 0, 1, 2, 1 };
+
+void IgorEngine::PART_22_EXEC_ACTION(int action) {
+ switch (action) {
+ case 101:
+ PART_22_ACTION_101();
+ break;
+ case 102:
+ PART_22_ACTION_102();
+ break;
+ default:
+ error("PART_22_EXEC_ACTION unhandled action %d", action);
+ break;
+ }
+}
+
+void IgorEngine::PART_22_ACTION_101() {
+ if (_objectsState[78] == 1 && _inventoryInfo[64] == 0) {
+ ADD_DIALOGUE_TEXT(203, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ for (int i = 1; i <= 3; ++i) {
+ const int offset = 24141;
+ for (int j = 0; j <= 29; ++j) {
+ const uint8 *src = _animFramesBuffer + 0xA0E6 + PART_22_ANIM_DATA_1[i] * 1050 + j * 35;
+ memcpy(_screenVGA + j * 320 + offset, src, 35);
+ }
+ waitForTimer(60);
+ }
+ addObjectToInventory(29, 64);
+ PART_22_HELPER_1(255);
+ ADD_DIALOGUE_TEXT(205, 1);
+ ADD_DIALOGUE_TEXT(206, 1);
+ SET_DIALOGUE_TEXT(1, 2);
+ startIgorDialogue();
+ _objectsState[105] = 1;
+ } else {
+ ADD_DIALOGUE_TEXT(201, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ }
+}
+
+void IgorEngine::PART_22_ACTION_102() {
+ _walkDataCurrentIndex = 0;
+ _walkCurrentFrame = 1;
+ for (int i = 9; i >= 0; --i) {
+ WalkData *wd = &_walkData[0];
+ wd->setPos(138, 123, 1, _walkCurrentFrame);
+ WalkData::setNextFrame(1, _walkCurrentFrame);
+ wd->clipSkipX = 1;
+ wd->clipWidth = 30;
+ wd->scaleWidth = 23 + i * 3;
+ wd->xPosChanged = 1;
+ wd->dxPos = 0;
+ wd->yPosChanged = 1;
+ wd->dyPos = 3;
+ wd->scaleHeight = 50;
+ moveIgor(wd->posNum, wd->frameNum);
+ waitForTimer(15);
+ }
+ int i = 16;
+ do {
+ if (compareGameTick(1, 16)) {
+ memcpy(_screenTextLayer + (i * 8 + 16) * 320, _screenLayer1 + (128 - i * 8) * 320, (i * 8 + 16) * 320);
+ memcpy(_screenTextLayer + (i * 8 + 16) * 320, _animFramesBuffer, (128 - i * 8) * 320);
+ memcpy(_screenVGA, _screenTextLayer, 46080);
+ if (i == 0) {
+ i = 255;
+ } else {
+ --i;
+ }
+ }
+ waitForTimer();
+ } while (i != 255);
+ _currentPart = 141;
+}
+
+void IgorEngine::PART_22_HELPER_1(int num) {
+}
+
+void IgorEngine::PART_22_HELPER_2() {
+ int i = 16;
+ do {
+ if (compareGameTick(1, 16)) {
+ memcpy(_screenTextLayer, _screenLayer1 + (128 - i * 8) * 320, (i * 8 + 16) * 320);
+ memcpy(_screenTextLayer + (128 - i * 8) * 320, _animFramesBuffer, (i * 8 + 16) * 320);
+ memcpy(_screenVGA, _screenTextLayer, 46080);
+ ++i;
+ }
+ waitForTimer();
+ } while (i != 17);
+ _walkDataCurrentIndex = 0;
+ _walkCurrentFrame = 1;
+ for ( i = 0; i <= 9; ++i) {
+ WalkData *wd = &_walkData[0];
+ if (i == 9) {
+ _walkCurrentFrame = 0;
+ }
+ wd->setPos(138, 123, 3, _walkCurrentFrame);
+ WalkData::setNextFrame(3, _walkCurrentFrame);
+ wd->clipSkipX = 1;
+ wd->clipWidth = 30;
+ wd->scaleWidth = 23 + i * 3;
+ wd->xPosChanged = 1;
+ wd->dxPos = 0;
+ wd->yPosChanged = 1;
+ wd->dyPos = 3;
+ wd->scaleHeight = 50;
+ moveIgor(3, wd->frameNum);
+ waitForTimer(15);
+ }
+ _walkDataLastIndex = 0;
+ buildWalkPathSimple(138, 123, 150, 123);
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+}
+
+void IgorEngine::PART_22() {
+ _gameState.enableLight = 1;
+ loadRoomData(PAL_BellChurch, IMG_BellChurch, BOX_BellChurch, MSK_BellChurch, TXT_BellChurch);
+ static const int anm[] = { FRM_BellChurch1, FRM_BellChurch2, 0 };
+ loadAnimData(anm);
+ loadActionData(DAT_BellChurch);
+ _roomDataOffsets = PART_22_ROOM_DATA_OFFSETS;
+ setRoomWalkBounds(126, 123, 193, 123);
+ SET_EXEC_ACTION_FUNC(1, &IgorEngine::PART_22_EXEC_ACTION);
+ PART_22_HELPER_1(255);
+ memcpy(_screenVGA, _screenLayer1, 46080);
+ _currentAction.verb = kVerbWalk;
+ fadeInPalette(768);
+ PART_22_HELPER_2();
+ showCursor();
+ _gameState.igorMoving = false;
+ while (_currentPart == 220) {
+ handleRoomInput();
+ if (compareGameTick(1, 16)) {
+ handleRoomIgorWalk();
+ }
+ if (compareGameTick(19, 32)) {
+ handleRoomDialogue();
+ }
+ if (compareGameTick(4, 8)) {
+ handleRoomInventoryScroll();
+ }
+ if (compareGameTick(1)) {
+ handleRoomLight();
+ }
+ waitForTimer();
+ }
+ fadeOutPalette(624);
+}
+
+} // namespace Igor
diff --git a/engines/igor/parts/part_23.cpp b/engines/igor/parts/part_23.cpp
new file mode 100644
index 0000000000..e165ad5b1d
--- /dev/null
+++ b/engines/igor/parts/part_23.cpp
@@ -0,0 +1,304 @@
+/* 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 "igor/igor.h"
+
+namespace Igor {
+
+static const uint8 PART_23_ANIM_DATA_1[4] = { 0, 4, 1, 11 };
+
+void IgorEngine::PART_23_EXEC_ACTION(int action) {
+ switch (action) {
+ case 101:
+ _currentPart = 280;
+ break;
+ case 102:
+ ADD_DIALOGUE_TEXT(201, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 105:
+ PART_23_ACTION_105();
+ break;
+ case 106:
+ ADD_DIALOGUE_TEXT(205, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 107:
+ PART_23_ACTION_107();
+ break;
+ case 108:
+ PART_23_ACTION_108();
+ break;
+ case 109:
+ _currentPart = 300;
+ break;
+ case 110:
+ ADD_DIALOGUE_TEXT(203, 1);
+ ADD_DIALOGUE_TEXT(204, 1);
+ SET_DIALOGUE_TEXT(1, 2);
+ startIgorDialogue();
+ break;
+ case 111:
+ ADD_DIALOGUE_TEXT(208, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 112:
+ ADD_DIALOGUE_TEXT(210, 1);
+ ADD_DIALOGUE_TEXT(211, 1);
+ SET_DIALOGUE_TEXT(1, 2);
+ startIgorDialogue();
+ break;
+ case 113:
+ ADD_DIALOGUE_TEXT(212, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ default:
+ error("PART_23_EXEC_ACTION unhandled action %d", action);
+ break;
+ }
+}
+
+void IgorEngine::PART_23_ACTION_105() {
+ if (_objectsState[66] != 0) {
+ _roomObjectAreasTable[_screenLayer2[38633]].area = 1;
+ --_walkDataLastIndex;
+ buildWalkPathSimple(233, 132, 233, 120);
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+ _currentPart = 190;
+ }
+}
+
+void IgorEngine::PART_23_ACTION_107() {
+ if (_objectsState[66] == 1) {
+ EXEC_MAIN_ACTION(11);
+ } else {
+ const int offset = 23901;
+ for (int i = 2; i <= 3; ++i) {
+ for (int j = 0; j <= 53; ++j) {
+ memcpy(_screenVGA + j * 320 + offset, _animFramesBuffer + i * 1620 + j * 30 + 0x895, 30);
+ }
+ }
+ playSound(13, 1);
+ waitForTimer(100);
+ _objectsState[66] = 1;
+ PART_23_HELPER_1(1);
+ }
+}
+
+void IgorEngine::PART_23_ACTION_108() {
+ if (_objectsState[66] == 0) {
+ EXEC_MAIN_ACTION(14);
+ } else {
+ const int offset = 23901;
+ for (int i = 2; i <= 3; ++i) {
+ for (int j = 0; j <= 53; ++j) {
+ memcpy(_screenVGA + j * 320 + offset, _animFramesBuffer + PART_23_ANIM_DATA_1[i] * 1620 + j * 30 + 0x895, 30);
+ }
+ }
+ playSound(14, 1);
+ waitForTimer(100);
+ _objectsState[66] = 0;
+ PART_23_HELPER_1(1);
+ }
+}
+
+void IgorEngine::PART_23_UPDATE_ROOM_BACKGROUND() {
+ if (compareGameTick(29) || compareGameTick(61)) {
+ int rnd = getRandomNumber(11);
+ if (rnd <= 4) {
+ _gameState.unk10 = 1;
+ } else if (rnd <= 9) {
+ _gameState.unk10 = 2;
+ } else if (rnd == 10) {
+ if (_gameState.unk10 < 3) {
+ _gameState.unk10 = getRandomNumber(2) + 3;
+ } else {
+ _gameState.unk10 = getRandomNumber(2) + 1;
+ }
+ }
+ PART_23_HELPER_7(_gameState.unk10);
+ }
+}
+
+void IgorEngine::PART_23_HELPER_1(int num) {
+ if (num == 1 || num == 255) {
+ if (_objectsState[66] == 0) {
+ PART_23_HELPER_2(1);
+ _roomActionsTable[4] = 6;
+ } else {
+ PART_23_HELPER_2(2);
+ _roomActionsTable[4] = 7;
+ }
+ }
+ PART_23_HELPER_3();
+}
+
+void IgorEngine::PART_23_HELPER_2(int frame) {
+ const int offset = 23907;
+ for (int i = 0; i <= 53; ++i) {
+ memcpy(_screenLayer1 + i * 320 + offset, _animFramesBuffer + (frame - 1) * 1296 + i * 24, 24);
+ }
+}
+
+void IgorEngine::PART_23_HELPER_3() {
+ const int offset = 25763;
+ for (int i = 0; i <= 48; ++i) {
+ memcpy(_screenLayer1 + i * 320 + offset, _animFramesBuffer + i * 25 + 0xA20, 25);
+ }
+}
+
+void IgorEngine::PART_23_HELPER_4() {
+ _walkData[0].setPos(233, 120, 3, 0);
+ _walkData[0].setDefaultScale();
+ _walkDataLastIndex = 0;
+ _roomObjectAreasTable[_screenLayer2[38633]].area = 1;
+ buildWalkPathSimple(233, 120, 233, 137);
+ _roomObjectAreasTable[_screenLayer2[38633]].area = 0;
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+ if (_objectsState[59] == 0) {
+ for (int i = 0; i <= 53; ++i) {
+ for (int j = 0; j <= 23; ++j) {
+ uint8 color = _screenVGA[(i + 74) * 320 + j + 227];
+ if (color >= 0xC0 && color <= 0xCF) {
+ _screenTempLayer[i * 100 + j] = color;
+ } else {
+ _screenTempLayer[i * 100 + j] = _animFramesBuffer[i * 24 + j];
+ }
+ }
+ }
+ for (int i = 0; i <= 53; ++i) {
+ memcpy(_screenVGA + i * 320 + 23907, _screenTempLayer + i * 100, 24);
+ }
+ playSound(14, 1);
+ _objectsState[66] = 0;
+ PART_23_HELPER_1(1);
+ ADD_DIALOGUE_TEXT(206, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ }
+}
+
+void IgorEngine::PART_23_HELPER_5() {
+ _walkData[0].setPos(0, 134, 2, 0);
+ _walkData[0].setDefaultScale();
+ _walkData[0].clipSkipX = 15;
+ _walkData[0].clipWidth = 15;
+ _walkDataLastIndex = 0;
+ _walkDataCurrentIndex = 1;
+ buildWalkPathSimple(0, 134, 100, 140);
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+}
+
+void IgorEngine::PART_23_HELPER_6() {
+ _walkData[0].setPos(319, 134, 4, 0);
+ _walkData[0].setDefaultScale();
+ _walkData[0].clipWidth = 15;
+ _walkDataLastIndex = 0;
+ _walkDataCurrentIndex = 1;
+ buildWalkPathSimple(319, 134, 289, 134);
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+}
+
+void IgorEngine::PART_23_HELPER_7(int frame) {
+ _roomCursorOn = false;
+ for (int i = 0; i <= 18; ++i) {
+ for (int j = 0; j <= 14; ++j) {
+ int offset = (i + 80) * 320 + j + 162;
+ uint8 color = _screenVGA[offset];
+ if ((color >= 192 && color <= 207) || color == 240 || color == 241) {
+ _screenTempLayer[i * 100 + j] = color;
+ } else {
+ _screenTempLayer[i * 100 + j] = _animFramesBuffer[frame * 285 + i * 15 + j + 0x271C];
+ }
+ }
+ }
+ int offset = 25762;
+ for (int i = 0; i <= 18; ++i) {
+ memcpy(_screenVGA + i * 320 + offset, _screenTempLayer + i * 100, 15);
+ memcpy(_screenLayer1 + i * 320 + offset, _animFramesBuffer + frame * 285 + i * 15 + 0x271C, 15);
+ }
+ if (_dialogueCursorOn) {
+ _roomCursorOn = true;
+ }
+}
+
+void IgorEngine::PART_23() {
+ _gameState.enableLight = 2;
+ loadRoomData(PAL_CollegeCorridorLucas, IMG_CollegeCorridorLucas, BOX_CollegeCorridorLucas, MSK_CollegeCorridorLucas, TXT_CollegeCorridorLucas);
+ static const int anm[] = { FRM_CollegeCorridorLucas1, FRM_CollegeCorridorLucas2, FRM_CollegeCorridorLucas3, FRM_CollegeCorridorLucas4, 0 };
+ loadAnimData(anm);
+ loadActionData(DAT_CollegeCorridorLucas);
+ _roomDataOffsets = PART_23_ROOM_DATA_OFFSETS;
+ setRoomWalkBounds(15, 0, 319, 143);
+ SET_EXEC_ACTION_FUNC(1, &IgorEngine::PART_23_EXEC_ACTION);
+ _updateRoomBackground = &IgorEngine::PART_23_UPDATE_ROOM_BACKGROUND;
+ PART_23_HELPER_1(255);
+ memcpy(_screenVGA, _screenLayer1, 46080);
+ _currentAction.verb = kVerbWalk;
+ fadeInPalette(768);
+ if (_currentPart == 230) {
+ PART_23_HELPER_5();
+ } else if (_currentPart == 231) {
+ PART_23_HELPER_6();
+ } else if (_currentPart == 232) {
+ PART_23_HELPER_4();
+ }
+ showCursor();
+ _gameState.igorMoving = false;
+ while (_currentPart >= 230 && _currentPart <= 232) {
+ handleRoomInput();
+ if (compareGameTick(1, 16)) {
+ handleRoomIgorWalk();
+ }
+ if (compareGameTick(19, 32)) {
+ handleRoomDialogue();
+ }
+ if (compareGameTick(4, 8)) {
+ handleRoomInventoryScroll();
+ }
+ if (compareGameTick(1)) {
+ handleRoomLight();
+ }
+ PART_23_UPDATE_ROOM_BACKGROUND();
+ waitForTimer();
+ }
+ fadeOutPalette(624);
+ _updateRoomBackground = 0;
+}
+
+} // namespace Igor
diff --git a/engines/igor/parts/part_24.cpp b/engines/igor/parts/part_24.cpp
new file mode 100644
index 0000000000..5d3d485ae0
--- /dev/null
+++ b/engines/igor/parts/part_24.cpp
@@ -0,0 +1,340 @@
+/* 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 "igor/igor.h"
+
+namespace Igor {
+
+void IgorEngine::PART_24_EXEC_ACTION(int action) {
+ switch (action) {
+ case 101:
+ _currentPart = 313;
+ break;
+ case 102:
+ PART_24_ACTION_102();
+ break;
+ case 103:
+ ADD_DIALOGUE_TEXT(201, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 104:
+ PART_24_ACTION_104();
+ break;
+ case 105:
+ PART_24_ACTION_105();
+ break;
+ case 106:
+ ADD_DIALOGUE_TEXT(202, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 107:
+ PART_24_ACTION_107();
+ break;
+ case 108:
+ ADD_DIALOGUE_TEXT(203, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 109:
+ ADD_DIALOGUE_TEXT(204, 1);
+ ADD_DIALOGUE_TEXT(205, 1);
+ SET_DIALOGUE_TEXT(1, 2);
+ startIgorDialogue();
+ break;
+ case 110:
+ ADD_DIALOGUE_TEXT(206, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 111:
+ ADD_DIALOGUE_TEXT(208, 2);
+ ADD_DIALOGUE_TEXT(210, 2);
+ SET_DIALOGUE_TEXT(1, 2);
+ startIgorDialogue();
+ break;
+ case 112:
+ ADD_DIALOGUE_TEXT(212, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ default:
+ error("PART_24_EXEC_ACTION unhandled action %d", action);
+ break;
+ }
+}
+
+void IgorEngine::PART_24_ACTION_102() {
+ if (_objectsState[67] != 0) {
+ _roomObjectAreasTable[_screenLayer2[37188]].area = 1;
+ --_walkDataLastIndex;
+ buildWalkPathSimple(76, 128, 68, 116);
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+ _currentPart = 360;
+ }
+}
+
+void IgorEngine::PART_24_ACTION_104() {
+ if (_objectsState[67] == 1) {
+ executeAction(11);
+ return;
+ }
+ for (int i = 1; i <= 2; ++i) {
+ const int offset = 23104;
+ for (int j = 0; j <= 56; ++j) {
+ memcpy(_screenVGA + j * 320 + offset, _animFramesBuffer + i * 1938 + j * 34 + 0x69C, 34);
+ }
+ if (i == 2) {
+ playSound(13, 1);
+ } else if (i == 1) {
+ waitForTimer(100);
+ }
+ }
+ _objectsState[67] = 1;
+ PART_24_HELPER_1(1);
+}
+
+void IgorEngine::PART_24_ACTION_105() {
+ if (_objectsState[67] == 0) {
+ executeAction(14);
+ return;
+ }
+ for (int i = 3; i <= 4; ++i) {
+ const int offset = 23104;
+ for (int j = 0; j <= 56; ++j) {
+ memcpy(_screenVGA + j * 320 + offset, _animFramesBuffer + i * 1938 + j * 34 + 0x69C, 34);
+ }
+ if (i == 4) {
+ playSound(14, 1);
+ } else if (i == 3) {
+ waitForTimer(100);
+ }
+ }
+ _objectsState[67] = 0;
+ PART_24_HELPER_1(1);
+}
+
+void IgorEngine::PART_24_ACTION_107() {
+ _roomObjectAreasTable[_screenLayer2[38719]].area = 1;
+ --_walkDataLastIndex;
+ buildWalkPathSimple(266, 123, 319, 120);
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+ _currentPart = 330;
+}
+
+void IgorEngine::PART_24_UPDATE_ROOM_BACKGROUND() {
+ if (compareGameTick(29) || compareGameTick(61)) {
+ if (_gameState.unk10 == _gameState.counter[4]) {
+ _gameState.counter[4] = getRandomNumber(90) + 10;
+ _gameState.unk10 = 0;
+ if (_gameState.unkF) {
+ PART_24_HELPER_3(1);
+ } else {
+ PART_24_HELPER_3(2);
+ }
+ _gameState.unkF = !_gameState.unkF;
+ } else {
+ ++_gameState.unk10;
+ }
+ if (_gameState.unkF) {
+ PART_24_HELPER_3(getRandomNumber(6) + 1);
+ } else {
+ PART_24_HELPER_2(getRandomNumber(6) + 1);
+ }
+ }
+}
+
+void IgorEngine::PART_24_HELPER_1(int num) {
+ if (num == 1 || num == 255) {
+ if (_objectsState[67] == 0) {
+ PART_24_HELPER_4();
+ _roomActionsTable[2] = 6;
+ } else {
+ PART_24_HELPER_5();
+ _roomActionsTable[2] = 7;
+ }
+ }
+}
+
+void IgorEngine::PART_24_HELPER_2(int frame) {
+ _roomCursorOn = false;
+ for (int i = 0; i <= 48; ++i) {
+ for (int j = 0; j <= 22; ++j) {
+ int offset = (i + 76) * 320 + j + 149;
+ uint8 color = _screenVGA[offset];
+ if ((color >= 192 && color <= 207) || color == 240 || color == 241) {
+ _screenTempLayer[i * 100 + j] = _screenVGA[offset];
+ } else {
+ _screenTempLayer[i * 100 + j] = _animFramesBuffer[frame * 1127 + i * 23 + j + 0x3E3B];
+ }
+ }
+ }
+ int offset = 24469;
+ for (int i = 0; i <= 48; ++i) {
+ memcpy(_screenVGA + i * 320 + offset, _screenTempLayer + i * 100, 23);
+ memcpy(_screenLayer1 + i * 320 + offset, _animFramesBuffer + frame * 1127 + i * 23 + 0x3E3B, 23);
+ }
+ if (_gameState.dialogueTextRunning) {
+ memcpy(_screenTextLayer + 23040, _screenLayer1 + _dialogueDirtyRectY, _dialogueDirtyRectSize);
+ }
+ if (_dialogueCursorOn) {
+ _roomCursorOn = true;
+ }
+}
+
+void IgorEngine::PART_24_HELPER_3(int frame) {
+ _roomCursorOn = false;
+ for (int i = 0; i <= 42; ++i) {
+ for (int j = 0; j <= 21; ++j) {
+ int offset = (i + 80) * 320 + j + 173;
+ uint8 color = _screenVGA[offset];
+ if ((color >= 192 && color <= 207) || color == 240 || color == 241) {
+ _screenTempLayer[i * 100 + j] = _screenVGA[offset];
+ } else {
+ _screenTempLayer[i * 100 + j] = _animFramesBuffer[frame * 946 + i * 22 + j + 0x28C4];
+ }
+ }
+ }
+ int offset = 25773;
+ for (int i = 0; i <= 42; ++i) {
+ memcpy(_screenVGA + i * 320 + offset, _screenTempLayer + i * 100, 22);
+ memcpy(_screenLayer1 + i * 320 + offset, _animFramesBuffer + frame * 946 + i * 22 + 0x28C4, 22);
+ }
+ if (_gameState.dialogueTextRunning) {
+ memcpy(_screenTextLayer + 23040, _screenLayer1 + _dialogueDirtyRectY, _dialogueDirtyRectSize);
+ }
+ if (_dialogueCursorOn) {
+ _roomCursorOn = true;
+ }
+}
+
+void IgorEngine::PART_24_HELPER_4() {
+ const int offset = 22785;
+ for (int i = 0; i <= 54; ++i) {
+ memcpy(_screenLayer1 + i * 320 + offset, _animFramesBuffer + i * 33, 33);
+ }
+}
+
+void IgorEngine::PART_24_HELPER_5() {
+ const int offset = 22785;
+ for (int i = 0; i <= 54; ++i) {
+ memcpy(_screenLayer1 + i * 320 + offset, _animFramesBuffer + i * 33 + 0x717, 33);
+ }
+}
+
+void IgorEngine::PART_24_HELPER_7() {
+ _walkData[0].setPos(0, 138, 2, 0);
+ _walkData[0].setDefaultScale();
+ _walkData[0].clipSkipX = 15;
+ _walkData[0].clipWidth = 15;
+ _walkDataLastIndex = 0;
+ _walkDataCurrentIndex = 1;
+ buildWalkPathSimple(0, 138, 30, 140);
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+}
+
+void IgorEngine::PART_24_HELPER_8() {
+ _walkData[0].setPos(319, 123, 4, 0);
+ _walkData[0].setDefaultScale();
+ _walkData[0].clipSkipX = 1;
+ _walkData[0].clipWidth = 15;
+ _walkDataLastIndex = 0;
+ _walkDataCurrentIndex = 1;
+ _roomObjectAreasTable[_screenLayer2[39679]].area = 1;
+ buildWalkPathSimple(319, 123, 260, 123);
+ _roomObjectAreasTable[_screenLayer2[39679]].area = 0;
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+}
+
+void IgorEngine::PART_24_HELPER_9() {
+ _walkData[0].setPos(68, 116, 3, 0);
+ _walkData[0].setDefaultScale();
+ _walkData[0].clipSkipX = 1;
+ _walkData[0].clipWidth = 30;
+ _walkDataLastIndex = 0;
+ _walkDataCurrentIndex = 1;
+ _roomObjectAreasTable[_screenLayer2[37188]].area = 1;
+ buildWalkPathSimple(68, 116, 78, 130);
+ _roomObjectAreasTable[_screenLayer2[37188]].area = 0;
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+}
+
+void IgorEngine::PART_24() {
+ _gameState.enableLight = 2;
+ loadRoomData(PAL_CollegeCorridorSharonMichael, IMG_CollegeCorridorSharonMichael, BOX_CollegeCorridorSharonMichael, MSK_CollegeCorridorSharonMichael, TXT_CollegeCorridorSharonMichael);
+ static const int anm[] = { FRM_CollegeCorridorSharonMichael1, FRM_CollegeCorridorSharonMichael2, FRM_CollegeCorridorSharonMichael3, FRM_CollegeCorridorSharonMichael4, 0 };
+ loadAnimData(anm);
+ loadActionData(DAT_CollegeCorridorSharonMichael);
+ _roomDataOffsets = PART_24_ROOM_DATA_OFFSETS;
+ setRoomWalkBounds(0, 0, 319, 143);
+ SET_EXEC_ACTION_FUNC(1, &IgorEngine::PART_24_EXEC_ACTION);
+ _updateRoomBackground = &IgorEngine::PART_24_UPDATE_ROOM_BACKGROUND;
+ PART_24_HELPER_1(255);
+ memcpy(_screenVGA, _screenLayer1, 46080);
+ _currentAction.verb = kVerbWalk;
+ fadeInPalette(768);
+ if (_currentPart == 240) {
+ PART_24_HELPER_7();
+ } else if (_currentPart == 241) {
+ PART_24_HELPER_8();
+ } else if (_currentPart == 242) {
+ PART_24_HELPER_9();
+ }
+ showCursor();
+ _gameState.igorMoving = false;
+ while (_currentPart >= 240 && _currentPart <= 242) {
+ handleRoomInput();
+ if (compareGameTick(1, 16)) {
+ handleRoomIgorWalk();
+ }
+ if (compareGameTick(19, 32)) {
+ handleRoomDialogue();
+ }
+ if (compareGameTick(4, 8)) {
+ handleRoomInventoryScroll();
+ }
+ if (compareGameTick(1)) {
+ handleRoomLight();
+ }
+ PART_24_UPDATE_ROOM_BACKGROUND();
+ waitForTimer();
+ }
+ fadeOutPalette(624);
+ _updateRoomBackground = 0;
+}
+
+} // namespace Igor
diff --git a/engines/igor/parts/part_25.cpp b/engines/igor/parts/part_25.cpp
new file mode 100644
index 0000000000..67acbae58a
--- /dev/null
+++ b/engines/igor/parts/part_25.cpp
@@ -0,0 +1,256 @@
+/* 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 "igor/igor.h"
+
+namespace Igor {
+
+void IgorEngine::PART_25_EXEC_ACTION(int action) {
+ switch (action) {
+ case 101:
+ _currentPart = 260;
+ break;
+ case 102:
+ switch (getRandomNumber(3) + 1) {
+ case 1:
+ ADD_DIALOGUE_TEXT(204, 2);
+ ADD_DIALOGUE_TEXT(206, 1);
+ SET_DIALOGUE_TEXT(1, 2);
+ startIgorDialogue();
+ break;
+ case 2:
+ ADD_DIALOGUE_TEXT(207, 1);
+ ADD_DIALOGUE_TEXT(208, 1);
+ ADD_DIALOGUE_TEXT(209, 1);
+ ADD_DIALOGUE_TEXT(206, 1);
+ SET_DIALOGUE_TEXT(1, 4);
+ startIgorDialogue();
+ break;
+ case 3:
+ ADD_DIALOGUE_TEXT(210, 1);
+ ADD_DIALOGUE_TEXT(211, 1);
+ ADD_DIALOGUE_TEXT(206, 1);
+ SET_DIALOGUE_TEXT(1, 3);
+ startIgorDialogue();
+ break;
+ }
+ break;
+ case 103:
+ ADD_DIALOGUE_TEXT(201, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 104:
+ ADD_DIALOGUE_TEXT(212, 1);
+ ADD_DIALOGUE_TEXT(213, 1);
+ ADD_DIALOGUE_TEXT(214, 1);
+ ADD_DIALOGUE_TEXT(215, 1);
+ ADD_DIALOGUE_TEXT(216, 2);
+ SET_DIALOGUE_TEXT(1, 5);
+ startIgorDialogue();
+ break;
+ case 105:
+ PART_25_ACTION_105();
+ break;
+ case 106:
+ ADD_DIALOGUE_TEXT(203, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 107:
+ PART_25_ACTION_107();
+ break;
+ case 108:
+ PART_25_ACTION_108();
+ break;
+ case 109:
+ _currentPart = 310;
+ break;
+ default:
+ error("PART_25_EXEC_ACTION unhandled action %d", action);
+ break;
+ }
+}
+
+void IgorEngine::PART_25_ACTION_105() {
+ if (_objectsState[68] != 0) {
+ _roomObjectAreasTable[_screenLayer2[34370]].area = 1;
+ --_walkDataLastIndex;
+ buildWalkPath(133, 123, 130, 107);
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+ _currentPart = 180;
+ }
+}
+
+void IgorEngine::PART_25_ACTION_107() {
+ if (_objectsState[68] == 1) {
+ EXEC_MAIN_ACTION(11);
+ return;
+ }
+ for (int i = 1; i <= 2; ++i) {
+ const int offset = 21881;
+ for (int j = 0; j <= 55; ++j) {
+ memcpy(_screenVGA + j * 320 + offset, _animFramesBuffer + i * 1736 + j * 31 + 0x290, 31);
+ if (i == 2) {
+ playSound(13, 1);
+ }
+ if (i == 1) {
+ waitForTimer(100);
+ }
+ }
+ }
+ _objectsState[68] = 1;
+ PART_25_HELPER_1(1);
+}
+
+void IgorEngine::PART_25_ACTION_108() {
+ if (_objectsState[68] == 0) {
+ EXEC_MAIN_ACTION(14);
+ return;
+ }
+ for (int i = 3; i <= 4; ++i) {
+ const int offset = 21881;
+ for (int j = 0; j <= 55; ++j) {
+ memcpy(_screenVGA + j * 320 + offset, _animFramesBuffer + i * 1736 + j * 31 + 0x290, 31);
+ if (i == 4) {
+ playSound(14, 1);
+ }
+ if (i == 3) {
+ waitForTimer(100);
+ }
+ }
+ }
+ _objectsState[68] = 0;
+ PART_25_HELPER_1(1);
+}
+
+void IgorEngine::PART_25_HELPER_1(int num) {
+ if (num == 1 || num == 255) {
+ if (_objectsState[68] == 0) {
+ PART_25_HELPER_5();
+ _roomActionsTable[31] = 6;
+ } else {
+ PART_25_HELPER_7();
+ _roomActionsTable[31] = 7;
+ }
+ }
+}
+
+void IgorEngine::PART_25_HELPER_2() {
+ _walkData[0].setPos(0, 130, 2, 0);
+ _walkData[0].setDefaultScale();
+ _walkData[0].clipSkipX = 15;
+ _walkData[0].clipWidth = 15;
+ _walkDataLastIndex = 0;
+ _walkDataCurrentIndex = 1;
+ buildWalkPath(0, 130, 60, 135);
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+}
+
+void IgorEngine::PART_25_HELPER_3() {
+ _walkData[0].setPos(319, 138, 4, 0);
+ _walkData[0].setDefaultScale();
+ _walkData[0].clipWidth = 15;
+ _walkDataLastIndex = 0;
+ _walkDataCurrentIndex = 1;
+ buildWalkPath(319, 138, 289, 142);
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+}
+
+void IgorEngine::PART_25_HELPER_4() {
+ _walkData[0].setPos(130, 107, 3, 0);
+ _walkData[0].setDefaultScale();
+ _walkDataLastIndex = 0;
+ _roomObjectAreasTable[_screenLayer2[34370]].area = 1;
+ buildWalkPath(130, 107, 135, 125);
+ _roomObjectAreasTable[_screenLayer2[34370]].area = 0;
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+}
+
+void IgorEngine::PART_25_HELPER_5() {
+ const int offset = 22208;
+ for (int i = 0; i <= 51; ++i) {
+ memcpy(_screenLayer1 + i * 320 + offset, _animFramesBuffer + i * 23, 23);
+ }
+}
+
+void IgorEngine::PART_25_HELPER_7() {
+ const int offset = 22208;
+ for (int i = 0; i <= 51; ++i) {
+ memcpy(_screenLayer1 + i * 320 + offset, _animFramesBuffer + 0x4AC + i * 23, 23);
+ }
+}
+
+void IgorEngine::PART_25() {
+ _gameState.enableLight = 2;
+ loadRoomData(PAL_CollegeCorridorAnnouncementBoard, IMG_CollegeCorridorAnnouncementBoard, BOX_CollegeCorridorAnnouncementBoard, MSK_CollegeCorridorAnnouncementBoard, TXT_CollegeCorridorAnnouncementBoard);
+ static const int anm[] = { FRM_CollegeCorridorAnnouncementBoard1, FRM_CollegeCorridorAnnouncementBoard2, 0 };
+ loadAnimData(anm);
+ loadActionData(DAT_CollegeCorridorAnnouncementBoard);
+ _roomDataOffsets = PART_25_ROOM_DATA_OFFSETS;
+ setRoomWalkBounds(0, 0, 319, 143);
+ SET_EXEC_ACTION_FUNC(1, &IgorEngine::PART_25_EXEC_ACTION);
+ PART_25_HELPER_1(255);
+ memcpy(_screenVGA, _screenLayer1, 46080);
+ _currentAction.verb = kVerbWalk;
+ fadeInPalette(768);
+ if (_currentPart == 250) {
+ PART_25_HELPER_2();
+ } else if (_currentPart == 251) {
+ PART_25_HELPER_3();
+ } else if (_currentPart == 252) {
+ PART_25_HELPER_4();
+ }
+ showCursor();
+ _gameState.igorMoving = false;
+ while (_currentPart >= 250 && _currentPart <= 252) {
+ handleRoomInput();
+ if (compareGameTick(1, 16)) {
+ handleRoomIgorWalk();
+ }
+ if (compareGameTick(19, 32)) {
+ handleRoomDialogue();
+ }
+ if (compareGameTick(4, 8)) {
+ handleRoomInventoryScroll();
+ }
+ if (compareGameTick(1)) {
+ handleRoomLight();
+ }
+ waitForTimer();
+ }
+ fadeOutPalette(624);
+}
+
+} // namespace Igor
diff --git a/engines/igor/parts/part_26.cpp b/engines/igor/parts/part_26.cpp
new file mode 100644
index 0000000000..eea2cd4c3d
--- /dev/null
+++ b/engines/igor/parts/part_26.cpp
@@ -0,0 +1,297 @@
+/* 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 "igor/igor.h"
+
+namespace Igor {
+
+static const uint8 PART_26_ANIM_DATA_1[12] = { 6, 0, 2, 3, 4, 5, 6, 5, 4, 3, 2, 0 };
+
+void IgorEngine::PART_26_EXEC_ACTION(int action) {
+ switch (action) {
+ case 101:
+ ADD_DIALOGUE_TEXT(202, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 102:
+ ADD_DIALOGUE_TEXT(203, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 103:
+ PART_26_ACTION_103();
+ break;
+ case 104:
+ PART_26_ACTION_104();
+ break;
+ case 105:
+ ADD_DIALOGUE_TEXT(224, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 106:
+ _currentPart = 250;
+ break;
+ case 107:
+ PART_26_ACTION_107();
+ break;
+ case 108:
+ ADD_DIALOGUE_TEXT(216, 2);
+ ADD_DIALOGUE_TEXT(218, 1);
+ SET_DIALOGUE_TEXT(1, 2);
+ startIgorDialogue();
+ break;
+ case 109:
+ ADD_DIALOGUE_TEXT(219, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 110:
+ ADD_DIALOGUE_TEXT(220, 2);
+ ADD_DIALOGUE_TEXT(222, 1);
+ SET_DIALOGUE_TEXT(1, 2);
+ startIgorDialogue();
+ break;
+ case 111:
+ ADD_DIALOGUE_TEXT(223, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ default:
+ error("PART_26_EXEC_ACTION unhandled action %d", action);
+ break;
+ }
+}
+
+void IgorEngine::PART_26_ACTION_103() {
+ if (_objectsState[69] == 1) {
+ EXEC_MAIN_ACTION(11);
+ return;
+ }
+ for (int i = 1; i <= 2; ++i) {
+ const int offset = 19870;
+ for (int j = 0; j <= 65; ++j) {
+ memcpy(_screenVGA + j * 320 + offset, _animFramesBuffer + 0x16C0 + i * 2706 + j * 41, 41);
+ }
+ if (i == 2) {
+ playSound(13, 1);
+ } else if (i == 1) {
+ waitForTimer(100);
+ }
+ }
+ _objectsState[69] = 1;
+ PART_25_HELPER_1(1);
+}
+
+void IgorEngine::PART_26_ACTION_104() {
+ if (_objectsState[69] == 0) {
+ EXEC_MAIN_ACTION(14);
+ return;
+ }
+ for (int i = 3; i <= 4; ++i) {
+ const int offset = 19870;
+ for (int j = 0; j <= 65; ++j) {
+ memcpy(_screenVGA + j * 320 + offset, _animFramesBuffer + i * 2706 + j * 41 + 0x16C0, 41);
+ if (i == 4) {
+ playSound(14, 1);
+ }
+ if (i == 3) {
+ waitForTimer(100);
+ }
+ }
+ }
+ _objectsState[69] = 0;
+ PART_25_HELPER_1(1);
+}
+
+void IgorEngine::PART_26_ACTION_107() {
+ if (_objectsState[69] != 0) {
+ _roomObjectAreasTable[_screenLayer2[36800]].area = 1;
+ --_walkDataLastIndex;
+ buildWalkPath(62, 127, 0, 115);
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+ _currentPart = 160;
+ }
+}
+
+void IgorEngine::PART_26_UPDATE_ROOM_BACKGROUND() {
+ if (compareGameTick(29) || compareGameTick(61)) {
+ if (_gameState.unk10 > 2) {
+ if (_gameState.unk10 == 11) {
+ _gameState.unk10 = 2;
+ }
+ PART_26_HELPER_7(PART_26_ANIM_DATA_1[_gameState.unk10]);
+ if (_gameState.unk10 > 2) {
+ ++_gameState.unk10;
+ }
+ } else if (_gameState.unk10 == 1) {
+ _gameState.unk10 = 2;
+ PART_26_HELPER_7(_gameState.unk10);
+ } else if (getRandomNumber(25) == 0) {
+ _gameState.unk10 = 1;
+ PART_26_HELPER_7(_gameState.unk10);
+ } else if (getRandomNumber(30) == 0) {
+ _gameState.unk10 = 3;
+ }
+ }
+}
+
+void IgorEngine::PART_26_HELPER_1(int num) {
+ if (num == 1 || num == 255) {
+ if (_objectsState[69] == 0) {
+ PART_26_HELPER_2();
+ _roomActionsTable[0x1E] = 6;
+ } else {
+ PART_26_HELPER_3();
+ _roomActionsTable[0x1E] = 7;
+ }
+ }
+}
+
+void IgorEngine::PART_26_HELPER_2() {
+ const int offset = 19870;
+ for (int i = 0; i <= 64; ++i) {
+ memcpy(_screenLayer1 + i * 320 + offset, _animFramesBuffer + i * 25, 25);
+ }
+}
+
+void IgorEngine::PART_26_HELPER_3() {
+ const int offset = 19870;
+ for (int i = 0; i <= 64; ++i) {
+ memcpy(_screenLayer1 + i * 320 + offset, _animFramesBuffer + 0x659 + i * 25, 25);
+ }
+}
+
+void IgorEngine::PART_26_HELPER_4() {
+ _walkData[0].setPos(319, 125, 4, 0);
+ _walkData[0].setDefaultScale();
+ _walkData[0].clipWidth = 15;
+ _walkDataLastIndex = 0;
+ _walkDataCurrentIndex = 1;
+ buildWalkPathSimple(319, 125, 269, 140);
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+}
+
+void IgorEngine::PART_26_HELPER_5() {
+ _walkData[0].setPos(0, 115, 3, 0);
+ _walkData[0].setDefaultScale();
+ _walkData[0].clipSkipX = 2;
+ _walkData[0].clipWidth = 30;
+ _walkDataLastIndex = 0;
+ _roomObjectAreasTable[_screenLayer2[36800]].area = 1;
+ buildWalkPath(0, 115, 70, 127);
+ _roomObjectAreasTable[_screenLayer2[36800]].area = 0;
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+ if (_objectsState[65] == 3) {
+ ADD_DIALOGUE_TEXT(212, 1);
+ ADD_DIALOGUE_TEXT(213, 2);
+ ADD_DIALOGUE_TEXT(215, 1);
+ SET_DIALOGUE_TEXT(1, 3);
+ startIgorDialogue();
+ _objectsState[65] = 4;
+ drawVerbsPanel();
+ redrawVerb(kVerbWalk, true);
+ _currentAction.verb = kVerbWalk;
+ drawInventory(_inventoryInfo[72], 0);
+ playSound(51, 1);
+ PART_26_HELPER_1(255);
+ }
+}
+
+void IgorEngine::PART_26_HELPER_7(int frame) {
+ _roomCursorOn = false;
+ for (int i = 0; i <= 39; ++i) {
+ for (int j = 0; j <= 21; ++j) {
+ int offset = (i + 91) * 320 + j + 169;
+ uint8 color = _screenVGA[offset];
+ if (color < 192 || (color > 207 && color != 240 && color != 241)) {
+ color = _animFramesBuffer[0x942 + frame * 880 + i * 22 + j];
+ }
+ _screenTempLayer[100 * i + j] = color;
+ }
+ }
+ for (int i = 0; i <= 39; ++i) {
+ const int offset = i * 320 + 29289;
+ memcpy(_screenVGA + offset, _screenTempLayer + i * 100, 22);
+ memcpy(_screenLayer1 + offset, _animFramesBuffer + 0x942 + frame * 880 + i * 22, 22);
+ }
+ if (_dialogueCursorOn) {
+ _roomCursorOn = true;
+ }
+}
+
+void IgorEngine::PART_26() {
+ _gameState.enableLight = 1;
+ loadRoomData(PAL_CollegeCorridorMissBarrymore, IMG_CollegeCorridorMissBarrymore, BOX_CollegeCorridorMissBarrymore, MSK_CollegeCorridorMissBarrymore, TXT_CollegeCorridorMissBarrymore);
+ static const int anm[] = { FRM_CollegeCorridorMissBarrymore1, FRM_CollegeCorridorMissBarrymore2, FRM_CollegeCorridorMissBarrymore3, 0 };
+ loadAnimData(anm);
+ loadActionData(DAT_CollegeCorridorMissBarrymore);
+ _roomDataOffsets = PART_26_ROOM_DATA_OFFSETS;
+ setRoomWalkBounds(14, 0, 319, 143);
+ SET_EXEC_ACTION_FUNC(1, &IgorEngine::PART_26_EXEC_ACTION);
+ _updateRoomBackground = &IgorEngine::PART_26_UPDATE_ROOM_BACKGROUND;
+ PART_26_HELPER_1(255);
+ memcpy(_screenVGA, _screenLayer1, 46080);
+ _currentAction.verb = kVerbWalk;
+ _gameState.unk10 = true;
+ fadeInPalette(768);
+ if (_currentPart == 260) {
+ PART_26_HELPER_4();
+ } else {
+ PART_26_HELPER_5();
+ }
+ showCursor();
+ _gameState.igorMoving = false;
+ while (_currentPart >= 260 && _currentPart <= 261) {
+ handleRoomInput();
+ if (compareGameTick(1, 16)) {
+ handleRoomIgorWalk();
+ }
+ if (compareGameTick(19, 32)) {
+ handleRoomDialogue();
+ }
+ if (compareGameTick(4, 8)) {
+ handleRoomInventoryScroll();
+ }
+ if (compareGameTick(1)) {
+ handleRoomLight();
+ }
+ PART_26_UPDATE_ROOM_BACKGROUND();
+ waitForTimer();
+ }
+ fadeOutPalette(624);
+ _updateRoomBackground = 0;
+}
+
+} // namespace Igor
diff --git a/engines/igor/parts/part_27.cpp b/engines/igor/parts/part_27.cpp
new file mode 100644
index 0000000000..5d06e946a8
--- /dev/null
+++ b/engines/igor/parts/part_27.cpp
@@ -0,0 +1,296 @@
+/* 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 "igor/igor.h"
+
+namespace Igor {
+
+void IgorEngine::PART_27_EXEC_ACTION(int action) {
+ switch (action) {
+ case 101:
+ _currentPart = 231;
+ break;
+ case 102:
+ if (_objectsState[85] == 0) {
+ ADD_DIALOGUE_TEXT(216, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ _objectsState[85] = 1;
+ PART_27_HELPER_1(255);
+ } else {
+ ADD_DIALOGUE_TEXT(201, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ }
+ break;
+ case 103:
+ ADD_DIALOGUE_TEXT(203, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 104:
+ ADD_DIALOGUE_TEXT(204, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 105:
+ ADD_DIALOGUE_TEXT(205, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 106:
+ PART_27_ACTION_106();
+ break;
+ case 107:
+ PART_27_ACTION_107();
+ break;
+ case 108:
+ PART_27_ACTION_108();
+ break;
+ case 109:
+ ADD_DIALOGUE_TEXT(215, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 110:
+ PART_27_ACTION_110();
+ break;
+ case 111:
+ ADD_DIALOGUE_TEXT(222, 1);
+ ADD_DIALOGUE_TEXT(223, 2);
+ ADD_DIALOGUE_TEXT(225, 4);
+ SET_DIALOGUE_TEXT(1, 3);
+ startIgorDialogue();
+ break;
+ case 112:
+ ADD_DIALOGUE_TEXT(221, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 113:
+ _currentPart = 150;
+ break;
+ default:
+ error("PART_27_EXEC_ACTION unhandled action %d", action);
+ break;
+ }
+}
+
+void IgorEngine::PART_27_ACTION_106() {
+ if (_objectsState[84] == 1) {
+ EXEC_MAIN_ACTION(11);
+ return;
+ }
+ if (_objectsState[5] == 0) {
+ ADD_DIALOGUE_TEXT(206, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ return;
+ }
+ if (_objectsState[5] == 1) {
+ ADD_DIALOGUE_TEXT(209, 3);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ _objectsState[5] = 2;
+ return;
+ }
+ const int offset = 21810;
+ for (int i = 2; i <= 3; ++i) {
+ for (int j = 0; j <= 48; ++j) {
+ memcpy(_screenVGA + i * 320 + offset, _animFramesBuffer + 0x3A0 + i * 1568 + j * 32, 32);
+ }
+ if (i == 3) {
+ playSound(3, 1);
+ }
+ if (i == 2) {
+ waitForTimer(100);
+ }
+ }
+ _objectsState[84] = 1;
+ PART_27_HELPER_1(1);
+}
+
+void IgorEngine::PART_27_ACTION_107() {
+ if (_objectsState[84] == 0) {
+ EXEC_MAIN_ACTION(14);
+ return;
+ }
+ const int offset = 21810;
+ for (int i = 2; i >= 1; --i) {
+ for (int j = 0; j <= 48; ++j) {
+ memcpy(_screenVGA + i * 320 + offset, _animFramesBuffer + 0x3A0 + i * 1568 + j * 32, 32);
+ }
+ if (i == 2) {
+ playSound(14, 1);
+ waitForTimer(100);
+ }
+ }
+ _objectsState[84] = 0;
+ PART_27_HELPER_1(1);
+}
+
+void IgorEngine::PART_27_ACTION_108() {
+ if (_inventoryInfo[58] > 0 || _objectsState[42] == 2) {
+ ADD_DIALOGUE_TEXT(208, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ return;
+ }
+ ADD_DIALOGUE_TEXT(207, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ const int offset = 25012;
+ for (int i = 1; i <= 2; ++i) {
+ for (int j = 0; j <= 29; ++j) {
+ memcpy(_screenVGA + j * 320 + offset, _animFramesBuffer + i * 630 + j * 21 + 0x19AA, 21);
+ }
+ if (i == 1) {
+ waitForTimer(100);
+ }
+ }
+ addObjectToInventory(23, 58);
+ PART_27_HELPER_1(1);
+}
+
+void IgorEngine::PART_27_ACTION_110() {
+ ADD_DIALOGUE_TEXT(212, 1);
+ ADD_DIALOGUE_TEXT(213, 2);
+ SET_DIALOGUE_TEXT(1, 2);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ const int offset = 25012;
+ for (int i = 1; i <= 2; ++i) {
+ for (int j = 0; j <= 48; ++j) {
+ memcpy(_screenVGA + j * 320 + offset, _animFramesBuffer + 0x19AA + i * 630 + j * 21, 21);
+ }
+ if (i == 1) {
+ waitForTimer(100);
+ }
+ }
+ removeObjectFromInventory(55);
+ PART_27_HELPER_1(255);
+ _objectsState[107] = 1;
+}
+
+void IgorEngine::PART_27_HELPER_1(int num) {
+ if (num == 1 || num == 255) {
+ if (_objectsState[84] == 0) {
+ PART_27_HELPER_3();
+ _roomActionsTable[3] = 6;
+ _roomObjectAreasTable[6].object = 3;
+ } else {
+ PART_27_HELPER_4();
+ _roomActionsTable[3] = 7;
+ _roomObjectAreasTable[6].object = 4;
+ }
+ }
+ if (num == 2 || num == 255) {
+ if (_objectsState[85] == 0) {
+ _roomObjectAreasTable[5].object = 2;
+ _roomObjectAreasTable[6].object = 2;
+ } else {
+ _roomObjectAreasTable[5].object = 3;
+ }
+ }
+}
+
+void IgorEngine::PART_27_HELPER_2() {
+ _walkData[0].setPos(0, 132, 2, 0);
+ _walkData[0].setDefaultScale();
+ _walkData[0].clipWidth = 15;
+ _walkDataLastIndex = 0;
+ _walkDataCurrentIndex = 1;
+ buildWalkPathSimple(0, 132, 30, 132);
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+}
+
+void IgorEngine::PART_27_HELPER_3() {
+ const int offset = 21816;
+ for (int i = 0; i <= 47; ++i) {
+ memcpy(_screenLayer1 + i * 320 + offset, _animFramesBuffer + i * 26, 26);
+ }
+}
+
+void IgorEngine::PART_27_HELPER_4() {
+ const int offset = 21816;
+ for (int i = 0; i <= 47; ++i) {
+ memcpy(_screenLayer1 + i * 320 + offset, _animFramesBuffer + i * 26 + 0x4E0, 26);
+ }
+}
+
+void IgorEngine::PART_27_HELPER_5() {
+ _walkData[0].setPos(270, 134, 4, 0);
+ _walkData[0].setDefaultScale();
+ _walkDataLastIndex = 0;
+ _walkDataCurrentIndex = 1;
+ buildWalkPathSimple(270, 134, 140, 134);
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+}
+
+void IgorEngine::PART_27() {
+ _gameState.enableLight = 1;
+ loadRoomData(PAL_CollegeLockers, IMG_CollegeLockers, BOX_CollegeLockers, MSK_CollegeLockers, TXT_CollegeLockers);
+ static const int anm[] = { FRM_CollegeLockers1, FRM_CollegeLockers2, FRM_CollegeLockers3, 0 };
+ loadAnimData(anm);
+ loadActionData(DAT_CollegeLockers);
+ _roomDataOffsets = PART_27_ROOM_DATA_OFFSETS;
+ setRoomWalkBounds(0, 0, 319, 143);
+ SET_EXEC_ACTION_FUNC(1, &IgorEngine::PART_27_EXEC_ACTION);
+ PART_27_HELPER_1(255);
+ memcpy(_screenVGA, _screenLayer1, 46080);
+ _currentAction.verb = kVerbWalk;
+ fadeInPalette(768);
+ if (_currentPart == 270) {
+ PART_27_HELPER_2();
+ } else {
+ PART_27_HELPER_5();
+ }
+ showCursor();
+ _gameState.igorMoving = false;
+ while (_currentPart == 270 || _currentPart == 271) {
+ handleRoomInput();
+ if (compareGameTick(1, 16)) {
+ handleRoomIgorWalk();
+ }
+ if (compareGameTick(19, 32)) {
+ handleRoomDialogue();
+ }
+ if (compareGameTick(4, 8)) {
+ handleRoomInventoryScroll();
+ }
+ if (compareGameTick(1)) {
+ handleRoomLight();
+ }
+ waitForTimer();
+ }
+ fadeOutPalette(624);
+}
+
+} // namespace Igor
diff --git a/engines/igor/parts/part_28.cpp b/engines/igor/parts/part_28.cpp
new file mode 100644
index 0000000000..4b952ad3bb
--- /dev/null
+++ b/engines/igor/parts/part_28.cpp
@@ -0,0 +1,369 @@
+/* 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 "igor/igor.h"
+
+namespace Igor {
+
+void IgorEngine::PART_28_EXEC_ACTION(int action) {
+ switch (action) {
+ case 101:
+ _currentPart = 230;
+ break;
+ case 102:
+ ADD_DIALOGUE_TEXT(201, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 103:
+ ADD_DIALOGUE_TEXT(202, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 104:
+ ADD_DIALOGUE_TEXT(203, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 105:
+ ADD_DIALOGUE_TEXT(204, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 106:
+ if (_objectsState[111] == 0) {
+ ADD_DIALOGUE_TEXT(205, 1);
+ ADD_DIALOGUE_TEXT(206, 1);
+ SET_DIALOGUE_TEXT(1, 2);
+ startIgorDialogue();
+ } else {
+ ADD_DIALOGUE_TEXT(234, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ }
+ break;
+ case 107:
+ ADD_DIALOGUE_TEXT(237, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 108:
+ PART_28_ACTION_108();
+ break;
+ case 109:
+ PART_28_ACTION_109();
+ break;
+ case 110:
+ ADD_DIALOGUE_TEXT(228, 1);
+ ADD_DIALOGUE_TEXT(229, 1);
+ SET_DIALOGUE_TEXT(1, 2);
+ startIgorDialogue();
+ break;
+ case 111:
+ if (_objectsState[3] == 0) {
+ ADD_DIALOGUE_TEXT(226, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ } else {
+ ADD_DIALOGUE_TEXT(227, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ }
+ startIgorDialogue();
+ break;
+ case 112:
+ ADD_DIALOGUE_TEXT(235, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 113:
+ ADD_DIALOGUE_TEXT(236, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ default:
+ error("PART_28_EXEC_ACTION unhandled action %d", action);
+ break;
+ }
+}
+
+void IgorEngine::PART_28_ACTION_108() {
+ if (_objectsState[111] == 1) {
+ ADD_DIALOGUE_TEXT(218, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ ADD_DIALOGUE_TEXT(211, 1);
+ ADD_DIALOGUE_TEXT(212, 1);
+ ADD_DIALOGUE_TEXT(213, 2);
+ ADD_DIALOGUE_TEXT(215, 1);
+ ADD_DIALOGUE_TEXT(216, 1);
+ SET_DIALOGUE_TEXT(1, 5);
+ startCutsceneDialogue(182, 81, 63, 17, 17);
+ _updateDialogue = &IgorEngine::PART_28_UPDATE_DIALOGUE_CAROLINE;
+ waitForEndOfCutsceneDialogue(182, 81, 63, 17, 17);
+ ADD_DIALOGUE_TEXT(217, 1);
+ SET_DIALOGUE_TEXT(1, 5);
+ startCutsceneDialogue(182, 81, 63, 17, 17);
+ waitForEndOfCutsceneDialogue(182, 81, 63, 17, 17);
+ _updateDialogue = 0;
+ --_walkDataLastIndex;
+ buildWalkPath(213, 131, 160, 140);
+ _walkDataCurrentIndex = 1;
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _walkData[_walkDataLastIndex].posNum = 3;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+ ADD_DIALOGUE_TEXT(222, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ return;
+ }
+ if (_objectsState[87] < 2) {
+ ADD_DIALOGUE_TEXT(207, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ } else {
+ ADD_DIALOGUE_TEXT(218, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ }
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ if (_objectsState[87] < 2) {
+ ADD_DIALOGUE_TEXT(208, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ } else {
+ ADD_DIALOGUE_TEXT(219, 2);
+ ADD_DIALOGUE_TEXT(221, 1);
+ SET_DIALOGUE_TEXT(1, 2);
+ }
+ startCutsceneDialogue(182, 81, 63, 17, 17);
+ _updateDialogue = &IgorEngine::PART_28_UPDATE_DIALOGUE_CAROLINE;
+ waitForEndOfCutsceneDialogue(182, 81, 63, 17, 17);
+ _updateDialogue = 0;
+}
+
+void IgorEngine::PART_28_ACTION_109() {
+ for (int i = 1; i <= 7; ++i) {
+ const int offset = 25067;
+ for (int j = 0; j <= 34; ++j) {
+ memcpy(_screenVGA + j * 320 + offset, _animFramesBuffer + i * 1085 + j * 31 + 0x5EC9, 31);
+ }
+ if (i < 7) {
+ waitForTimer(45);
+ }
+ }
+ addObjectToInventory(22, 57);
+ _objectsState[87] = 1;
+ PART_28_HELPER_1(255);
+ ADD_DIALOGUE_TEXT(230, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+}
+
+void IgorEngine::PART_28_UPDATE_DIALOGUE_CAROLINE(int action) {
+ switch (action) {
+ case kUpdateDialogueAnimEndOfSentence:
+ PART_28_HELPER_5(7);
+ break;
+ case kUpdateDialogueAnimMiddleOfSentence:
+ PART_28_HELPER_5(getRandomNumber(5) + 7);
+ break;
+ }
+}
+
+void IgorEngine::PART_28_UPDATE_ROOM_BACKGROUND() {
+ if (compareGameTick(61)) {
+ if (_gameState.unk10 > 2) {
+ PART_28_HELPER_5(_gameState.unk10);
+ if (_gameState.unk10 < 6) {
+ ++_gameState.unk10;
+ } else {
+ _gameState.unk10 = 1;
+ }
+ } else {
+ PART_28_HELPER_5(_gameState.unk10);
+ if (_gameState.unk10 == 1) {
+ _gameState.unk10 = 2;
+ } else {
+ _gameState.unk10 = 1;
+ }
+ if (getRandomNumber(8) == 0) {
+ _gameState.unk10 = 3;
+ }
+ }
+ }
+}
+
+void IgorEngine::PART_28_HELPER_1(int num) {
+ WRITE_LE_UINT16(_roomActionsTable + 0x56, 42133);
+ if (num == 2 || num == 255) {
+ if (_objectsState[87] == 0) {
+ PART_28_HELPER_8(1);
+ } else {
+ PART_28_HELPER_8(0);
+ _roomObjectAreasTable[7].object = 0;
+ }
+ }
+}
+
+void IgorEngine::PART_28_HELPER_2() {
+ const int offset = 27374;
+ for (int i = 0; i <= 43; ++i) {
+ memcpy(_screenLayer1 + i * 320 + offset, _animFramesBuffer + i * 30, 30);
+ }
+}
+
+void IgorEngine::PART_28_HELPER_3() {
+ _walkData[0].setPos(319, 142, 4, 0);
+ _walkData[0].setDefaultScale();
+ _walkData[0].clipWidth = 15;
+ _walkDataLastIndex = 0;
+ _walkDataCurrentIndex = 1;
+ buildWalkPathSimple(319, 142, 289, 142);
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+}
+
+void IgorEngine::PART_28_HELPER_5(int frame) {
+ _roomCursorOn = false;
+ for (int i = 0; i <= 43; ++i) {
+ for (int j = 0; j <= 29; ++j) {
+ int offset = (i + 85) * 320 + j + 174;
+ uint8 color = _screenVGA[offset];
+ if ((color >= 192 && color <= 207) || color == 240 || color == 241) {
+ _screenTempLayer[i * 100 + j] = _screenVGA[offset];
+ } else {
+ _screenTempLayer[i * 100 + j] = _animFramesBuffer[(frame - 1) * 1320 + i * 30 + j];
+ }
+ }
+ }
+ int offset = 27374;
+ for (int i = 0; i <= 43; ++i) {
+ memcpy(_screenVGA + i * 320 + offset, _screenTempLayer + i * 100, 30);
+ memcpy(_screenLayer1 + i * 320 + offset, _animFramesBuffer + (frame - 1) * 1320 + i * 30, 30);
+ }
+ if (_gameState.dialogueTextRunning) {
+ memcpy(_screenTextLayer + 23040, _screenLayer1 + _dialogueDirtyRectY, _dialogueDirtyRectSize);
+ }
+ if (_dialogueCursorOn) {
+ _roomCursorOn = true;
+ }
+}
+
+void IgorEngine::PART_28_HELPER_6() {
+ setupDefaultPalette();
+ SET_PAL_240_48_1();
+ SET_PAL_208_96_1();
+ drawVerbsPanel();
+ drawInventory(_inventoryInfo[72], 0);
+ PART_28_HELPER_1(255);
+ fadeInPalette(768);
+ _walkData[0].setPos(319, 142, 4, 0);
+ _walkData[0].setDefaultScale();
+ _walkData[0].clipSkipX = 1;
+ _walkData[0].clipWidth = 15;
+ _walkDataLastIndex = 0;
+ _walkDataCurrentIndex = 1;
+ buildWalkPath(319, 142, 214, 130);
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _walkData[_walkDataLastIndex].posNum = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+ ADD_DIALOGUE_TEXT(209, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ waitForTimer(255);
+ ADD_DIALOGUE_TEXT(231, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ --_walkDataLastIndex;
+ buildWalkPath(214, 130, 214, 140);
+ _walkDataCurrentIndex = 1;
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+ ADD_DIALOGUE_TEXT(224, 2);
+ ADD_DIALOGUE_TEXT(232, 2);
+ SET_DIALOGUE_TEXT(1, 2);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+}
+
+void IgorEngine::PART_28_HELPER_8(int frame) {
+ const int offset = 33387;
+ for (int i = 0; i <= 8; ++i) {
+ memcpy(_screenLayer1 + i * 320 + offset, _animFramesBuffer + frame * 135 + i * 15 + 0x61F8, 15);
+ }
+}
+
+void IgorEngine::PART_28() {
+ _gameState.enableLight = 2;
+ loadRoomData(PAL_CollegeCorridorCaroline, IMG_CollegeCorridorCaroline, BOX_CollegeCorridorCaroline, MSK_CollegeCorridorCaroline, TXT_CollegeCorridorCaroline);
+ static const int anm[] = { FRM_CollegeCorridorCaroline1, FRM_CollegeCorridorCaroline2, FRM_CollegeCorridorCaroline3, 0 };
+ loadAnimData(anm);
+ loadActionData(DAT_CollegeCorridorCaroline);
+ _roomDataOffsets = PART_28_ROOM_DATA_OFFSETS;
+ setRoomWalkBounds(15, 0, 319, 143);
+ SET_EXEC_ACTION_FUNC(1, &IgorEngine::PART_28_EXEC_ACTION);
+ _updateRoomBackground = &IgorEngine::PART_28_UPDATE_ROOM_BACKGROUND;
+ PART_28_HELPER_2();
+ PART_28_HELPER_1(255);
+ memcpy(_screenVGA, _screenLayer1, 46080);
+ _currentAction.verb = kVerbWalk;
+ if (_currentPart == 280) {
+ fadeInPalette(768);
+ PART_28_HELPER_3();
+ } else if (_currentPart == 281) {
+ PART_28_HELPER_6();
+ }
+ showCursor();
+ _gameState.igorMoving = false;
+ while (_currentPart == 280 || _currentPart == 281) {
+ handleRoomInput();
+ if (compareGameTick(1, 16)) {
+ handleRoomIgorWalk();
+ }
+ if (compareGameTick(19, 32)) {
+ handleRoomDialogue();
+ }
+ if (compareGameTick(4, 8)) {
+ handleRoomInventoryScroll();
+ }
+ if (compareGameTick(1)) {
+ handleRoomLight();
+ }
+ PART_28_UPDATE_ROOM_BACKGROUND();
+ waitForTimer();
+ }
+ if (_objectsState[87] == 1) {
+ _objectsState[87] = 2;
+ }
+ fadeOutPalette(624);
+ _updateRoomBackground = 0;
+}
+
+} // namespace Igor
diff --git a/engines/igor/parts/part_30.cpp b/engines/igor/parts/part_30.cpp
new file mode 100644
index 0000000000..8cd8ca8626
--- /dev/null
+++ b/engines/igor/parts/part_30.cpp
@@ -0,0 +1,325 @@
+/* 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 "igor/igor.h"
+
+namespace Igor {
+
+void IgorEngine::PART_30_EXEC_ACTION(int action) {
+ switch (action) {
+ case 101:
+ _currentPart = 231;
+ break;
+ case 102:
+ PART_30_ACTION_102();
+ break;
+ case 103:
+ ADD_DIALOGUE_TEXT(203, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 104:
+ PART_30_ACTION_104();
+ break;
+ case 105:
+ ADD_DIALOGUE_TEXT(202, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 106:
+ _currentPart = 210;
+ break;
+ default:
+ error("PART_30_EXEC_ACTION unhandled action %d", action);
+ break;
+ }
+}
+
+void IgorEngine::PART_30_ACTION_102() {
+ _roomObjectAreasTable[_screenLayer2[24108]].area = 2;
+ --_walkDataLastIndex;
+ buildWalkPath(99, 119, 108, 75);
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+ _roomObjectAreasTable[_screenLayer2[24170]].area = 0;
+ --_walkDataLastIndex;
+ buildWalkPath(108, 75, 170, 75);
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+ _currentPart = 312;
+}
+
+void IgorEngine::PART_30_ACTION_104() {
+ --_walkDataLastIndex;
+ _roomObjectAreasTable[_screenLayer2[36318]].area = 2;
+ buildWalkPath(158, 119, 158, 113);
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+ _walkDataCurrentIndex = 0;
+ for (int i = 9; i >= 0; --i) {
+ if (i == 9) {
+ _walkCurrentFrame = 0;
+ }
+ _walkData[0].setPos(158, 113, 1, _walkCurrentFrame);
+ WalkData::setNextFrame(1, _walkCurrentFrame);
+ _walkData[0].setDefaultScale();
+ _walkData[0].clipSkipX = 1;
+ _walkData[0].clipWidth = 30;
+ _walkData[0].dyPos = 3;
+ _walkData[0].scaleWidth = i * 3 + 23;
+ moveIgor(_walkData[0].posNum, _walkData[0].frameNum);
+ waitForTimer(15);
+ }
+ _currentPart = (_objectsState[111] == 0) ? 171 : 771;
+}
+
+void IgorEngine::PART_30_UPDATE_DIALOGUE_LAURA(int action) {
+ switch (action) {
+ case kUpdateDialogueAnimEndOfSentence:
+ PART_30_HELPER_9(42);
+ break;
+ case kUpdateDialogueAnimMiddleOfSentence:
+ PART_30_HELPER_9(getRandomNumber(9) + 42);
+ break;
+ case kUpdateDialogueAnimStanding:
+ PART_30_HELPER_9(33);
+ break;
+ }
+}
+
+void IgorEngine::PART_30_HANDLE_DIALOGUE_LAURA() {
+ loadDialogueData(DLG_CollegeStairsFirstFloor);
+ _updateDialogue = &IgorEngine::PART_30_UPDATE_DIALOGUE_LAURA;
+ handleDialogue(201, 85, 63, 0, 38);
+ _updateDialogue = 0;
+}
+
+void IgorEngine::PART_30_HELPER_1(int num) {
+}
+
+void IgorEngine::PART_30_HELPER_2() {
+ _walkData[0].setPos(0, 138, 2, 0);
+ _walkData[0].setDefaultScale();
+ _walkData[0].clipWidth = 15;
+ _walkDataLastIndex = 0;
+ _walkDataCurrentIndex = 1;
+ buildWalkPath(0, 138, 30, 138);
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+}
+
+void IgorEngine::PART_30_HELPER_3() {
+ _roomObjectAreasTable[_screenLayer2[24170]].area = 2;
+ _walkData[0].setPos(170, 75, 4, 0);
+ _walkData[0].setDefaultScale();
+ _walkDataLastIndex = 0;
+ _roomObjectAreasTable[_screenLayer2[24108]].area = 2;
+ buildWalkPath(170, 75, 108, 75);
+ _roomObjectAreasTable[_screenLayer2[24170]].area = 0;
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+ --_walkDataLastIndex;
+ buildWalkPath(108, 75, 99, 119);
+ _roomObjectAreasTable[_screenLayer2[24108]].area = 0;
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+ --_walkDataLastIndex;
+ buildWalkPath(99, 119, 128, 123);
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+}
+
+void IgorEngine::PART_30_HELPER_4() {
+ _walkDataCurrentIndex = 0;
+ _walkCurrentFrame = 1;
+ _walkCurrentPos = 3;
+ for (int i = 0; i <= 9; ++i) {
+ if (i == 9) {
+ _walkCurrentFrame = 0;
+ }
+ _walkData[0].setPos(158, 113, 3, _walkCurrentFrame);
+ WalkData::setNextFrame(3, _walkCurrentFrame);
+ _walkData[0].setDefaultScale();
+ _walkData[0].scaleWidth = i * 3 + 23;
+ moveIgor(_walkData[0].posNum, _walkData[0].frameNum);
+ waitForTimer(15);
+ }
+ _walkDataLastIndex = 1;
+ _walkDataCurrentIndex = 1;
+ _roomObjectAreasTable[_screenLayer2[36318]].area = 2;
+ --_walkDataLastIndex;
+ buildWalkPath(158, 113, 128, 123);
+ _roomObjectAreasTable[_screenLayer2[36318]].area = 0;
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+}
+
+void IgorEngine::PART_30_HELPER_5() {
+ _walkData[0].setPos(319, 138, 4, 0);
+ _walkData[0].setDefaultScale();
+ _walkData[0].clipWidth = 15;
+ _walkDataLastIndex = 0;
+ _walkDataCurrentIndex = 1;
+ buildWalkPath(319, 138, 289, 138);
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+}
+
+void IgorEngine::PART_30_HELPER_8() {
+ playMusic(3);
+ memset(_screenVGA + 46080, 0, 17920);
+ fadeInPalette(768);
+ for (int i = 1; i <= 40; ++i) {
+ const uint8 *src = _animFramesBuffer + READ_LE_UINT16(_animFramesBuffer + 0xBE94 + i * 2) - 1;
+ decodeAnimFrame(src, _screenVGA, true);
+ if (i < 34) {
+ waitForTimer(25);
+ } else {
+ waitForTimer(15);
+ }
+ }
+ _walkData[0].setPos(172, 134, 2, 0);
+ _walkData[0].setDefaultScale();
+ _walkDataLastIndex = 1;
+ _walkDataCurrentIndex = 1;
+ _updateDialogue = &IgorEngine::PART_30_UPDATE_DIALOGUE_LAURA;
+ ADD_DIALOGUE_TEXT(203, 1);
+ ADD_DIALOGUE_TEXT(204, 1);
+ ADD_DIALOGUE_TEXT(205, 1);
+ SET_DIALOGUE_TEXT(1, 3);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ ADD_DIALOGUE_TEXT(206, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startCutsceneDialogue(201, 85, 63, 0, 38);
+ waitForEndOfCutsceneDialogue(201, 85, 63, 0, 38);
+ decodeAnimFrame(_animFramesBuffer + READ_LE_UINT16(_animFramesBuffer + 0xBEE6) - 1, _screenVGA, true);
+ for (int i = 1; i <= 41; ++i) {
+ const uint8 *src = _animFramesBuffer + READ_LE_UINT16(_animFramesBuffer + 0xBE94 + i * 2) - 1;
+ decodeAnimFrame(src, _screenVGA, true);
+ }
+ PART_30_HANDLE_DIALOGUE_LAURA();
+ ADD_DIALOGUE_TEXT(207, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ ADD_DIALOGUE_TEXT(208, 1);
+ ADD_DIALOGUE_TEXT(209, 1);
+ SET_DIALOGUE_TEXT(1, 2);
+ startCutsceneDialogue(201, 85, 63, 0, 38);
+ waitForEndOfCutsceneDialogue(201, 85, 63, 0, 38);
+ _updateDialogue = 0;
+ for (int i = 51; i <= 70; ++i) {
+ const uint8 *src = _animFramesBuffer + READ_LE_UINT16(_animFramesBuffer + 0xBE94 + i * 2) - 1;
+ decodeAnimFrame(src, _screenVGA, true);
+ if (i < 68) {
+ waitForTimer(25);
+ }
+ }
+ _walkData[0].setPos(164, 135, 3, 0);
+ _walkData[0].setDefaultScale();
+ _walkDataLastIndex = 1;
+ ADD_DIALOGUE_TEXT(210, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ memset(_screenVGA + 46080, 0, 17920);
+ drawVerbsPanel();
+ drawInventory(_inventoryInfo[72], 0);
+ _currentAction.verb = kVerbWalk;
+ _objectsState[73] = 1;
+ PART_30_HELPER_1(255);
+}
+
+void IgorEngine::PART_30_HELPER_9(int frame) {
+ const uint8 *src = _animFramesBuffer + READ_LE_UINT16(_animFramesBuffer + 0xBE94 + frame * 2) - 1;
+ decodeAnimFrame(src, _screenVGA, true);
+}
+
+void IgorEngine::PART_30() {
+ _gameState.enableLight = 2;
+ loadRoomData(PAL_CollegeStairsFirstFloor, IMG_CollegeStairsFirstFloor, BOX_CollegeStairsFirstFloor, MSK_CollegeStairsFirstFloor, TXT_CollegeStairsFirstFloor);
+ static const int anm[] = { FRM_CollegeStairsFirstFloor1, FRM_CollegeStairsFirstFloor2, 0 };
+ loadAnimData(anm);
+ loadActionData(DAT_CollegeStairsFirstFloor);
+ _roomDataOffsets = PART_30_ROOM_DATA_OFFSETS;
+ setRoomWalkBounds(0, 0, 319, 143);
+ SET_EXEC_ACTION_FUNC(1, &IgorEngine::PART_30_EXEC_ACTION);
+ PART_30_HELPER_1(255);
+ memcpy(_screenVGA, _screenLayer1, 46080);
+ _currentAction.verb = kVerbWalk;
+ if (_objectsState[73] == 0) {
+ PART_30_HELPER_8();
+ } else {
+ if (_currentPart != 302) {
+ fadeInPalette(768);
+ }
+ if (_currentPart == 300) {
+ PART_30_HELPER_2();
+ } else if (_currentPart == 301) {
+ PART_30_HELPER_3();
+ } else if (_currentPart == 302) {
+ playMusic(3);
+ fadeInPalette(768);
+ PART_30_HELPER_4();
+ } else if (_currentPart == 303) {
+ PART_30_HELPER_5();
+ }
+ }
+ if (!_gameState.dialogueTextRunning) {
+ showCursor();
+ }
+ _gameState.igorMoving = false;
+ while (_currentPart >= 300 && _currentPart <= 303) {
+ handleRoomInput();
+ if (compareGameTick(1, 16)) {
+ handleRoomIgorWalk();
+ }
+ if (compareGameTick(19, 32)) {
+ handleRoomDialogue();
+ }
+ if (compareGameTick(4, 8)) {
+ handleRoomInventoryScroll();
+ }
+ if (compareGameTick(1)) {
+ handleRoomLight();
+ }
+ waitForTimer();
+ }
+ fadeOutPalette(624);
+}
+
+} // namespace Igor
diff --git a/engines/igor/parts/part_31.cpp b/engines/igor/parts/part_31.cpp
new file mode 100644
index 0000000000..a3822d7982
--- /dev/null
+++ b/engines/igor/parts/part_31.cpp
@@ -0,0 +1,453 @@
+/* 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 "igor/igor.h"
+
+namespace Igor {
+
+static const uint8 PART_31_ANIM_DATA_1[] = { 0, 4, 5, 4, 5, 4, 5, 4, 5, 6 };
+
+static const uint8 PART_31_ANIM_DATA_2[] = { 0, 4, 5, 4, 5, 4, 5, 1, 2, 3 };
+
+void IgorEngine::PART_31_EXEC_ACTION(int action) {
+ switch (action) {
+ case 101:
+ _currentPart = 251;
+ break;
+ case 102:
+ PART_31_ACTION_102();
+ break;
+ case 103:
+ PART_31_ACTION_103();
+ break;
+ case 104:
+ if (_objectsState[72] == 0) {
+ EXEC_MAIN_ACTION(14);
+ } else {
+ ADD_DIALOGUE_TEXT(205, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ }
+ break;
+ case 105:
+ ADD_DIALOGUE_TEXT(201, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 106:
+ PART_31_ACTION_106();
+ break;
+ case 107:
+ ADD_DIALOGUE_TEXT(203, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 108:
+ _currentPart = 240;
+ break;
+ case 109:
+ ADD_DIALOGUE_TEXT(204, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 110:
+ PART_31_ACTION_110();
+ break;
+ case 111:
+ ADD_DIALOGUE_TEXT(206, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 112:
+ ADD_DIALOGUE_TEXT(208, 1);
+ ADD_DIALOGUE_TEXT(209, 2);
+ SET_DIALOGUE_TEXT(1, 2);
+ startIgorDialogue();
+ break;
+ case 113:
+ ADD_DIALOGUE_TEXT(211, 1);
+ ADD_DIALOGUE_TEXT(212, 1);
+ ADD_DIALOGUE_TEXT(213, 1);
+ SET_DIALOGUE_TEXT(1, 3);
+ startIgorDialogue();
+ break;
+ case 114:
+ ADD_DIALOGUE_TEXT(214, 1);
+ ADD_DIALOGUE_TEXT(215, 1);
+ SET_DIALOGUE_TEXT(1, 2);
+ startIgorDialogue();
+ break;
+ case 115:
+ ADD_DIALOGUE_TEXT(220, 3);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 116:
+ ADD_DIALOGUE_TEXT(218, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ default:
+ error("PART_31_EXEC_ACTION unhandled action %d", action);
+ break;
+ }
+}
+
+void IgorEngine::PART_31_ACTION_102() {
+ if (_objectsState[72] == 0) {
+ return;
+ }
+ _roomObjectAreasTable[_screenLayer2[33712]].area = 2;
+ --_walkDataLastIndex;
+ buildWalkPath(102, 120, 112, 105);
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+ _roomObjectAreasTable[_screenLayer2[20207]].area = 2;
+ --_walkDataLastIndex;
+ buildWalkPath(112, 105, 47, 63);
+ for (int i = 1; i <= _walkDataLastIndex; ++i) {
+ _walkData[i].posNum = i;
+ }
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+ _currentPart = 320;
+}
+
+void IgorEngine::PART_31_ACTION_103() {
+ if (_objectsState[72] == 1) {
+ EXEC_MAIN_ACTION(11);
+ return;
+ }
+ playSound(49, 1);
+ const int offset = 20250;
+ for (int i = 1; i <= 9; ++i) {
+ for (int j = 0; j <= 57; ++j) {
+ memcpy(_screenVGA + j * 320 + offset, _animFramesBuffer + PART_31_ANIM_DATA_1[i] * 1856 + j * 32 + 0x384, 32);
+ }
+ if (i < 9) {
+ waitForTimer(30);
+ }
+ }
+ ADD_DIALOGUE_TEXT(202, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+}
+
+void IgorEngine::PART_31_ACTION_106() {
+ --_walkDataLastIndex;
+ _roomObjectAreasTable[_screenLayer2[36326]].area = 2;
+ buildWalkPath(166, 120, 166, 113);
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+ _walkDataCurrentIndex = 0;
+ for (int i = 9; i >= 0; --i) {
+ if (i == 9) {
+ _walkCurrentFrame = 0;
+ }
+ WalkData *wd = &_walkData[0];
+ wd->setPos(166, 113, 1, _walkCurrentFrame);
+ WalkData::setNextFrame(1, _walkCurrentFrame);
+ wd->clipSkipX = 1;
+ wd->clipWidth = 30;
+ wd->scaleWidth = i * 3 + 23;
+ wd->xPosChanged = 1;
+ wd->dxPos = 0;
+ wd->yPosChanged = 1;
+ wd->dyPos = 3;
+ wd->scaleHeight = 50;
+ moveIgor(wd->posNum, wd->frameNum);
+ waitForTimer(15);
+ }
+ _currentPart = 301;
+}
+
+void IgorEngine::PART_31_ACTION_110() {
+ if (_objectsState[72] == 1) {
+ EXEC_MAIN_ACTION(11);
+ return;
+ }
+ const int offset = 20250;
+ for (int i = 1; i <= 9; ++i) {
+ for (int j = 0; j <= 57; ++j) {
+ memcpy(_screenVGA + j * 320 + offset, _animFramesBuffer + PART_31_ANIM_DATA_2[i] * 1856 + j * 32 + 0x384, 32);
+ }
+ if (i == 9) {
+ playSound(13, 1);
+ } else if (i < 8) {
+ waitForTimer(30);
+ } else if (i == 8) {
+ waitForTimer(10);
+ }
+ }
+ _objectsState[72] = 1;
+ PART_31_HELPER_1(1);
+}
+
+void IgorEngine::PART_31_UPDATE_ROOM_BACKGROUND() {
+ int xPos, pos;
+ if (_gameState.igorMoving) {
+ xPos = _walkData[_walkDataCurrentIndex - 1].x;
+ pos = _walkData[_walkDataCurrentIndex - 1].posNum;
+ } else {
+ xPos = _walkData[_walkDataLastIndex - 1].x;
+ pos = _walkData[_walkDataLastIndex - 1].posNum;
+ }
+ if (xPos < 160 && compareGameTick(3, 8)) {
+ if (pos == 2) {
+ if (_gameState.igorMoving) {
+ if (_gameState.unk10 == 1 || _gameState.unk10 == 2) {
+ _gameState.unk10 = 3;
+ PART_31_HELPER_2(_gameState.unk10);
+ return;
+ } else if (_gameState.unk10 == 3) {
+ _gameState.unk10 = 4;
+ PART_31_HELPER_2(_gameState.unk10);
+ return;
+ } else if (_gameState.unk10 == 4) {
+ if (getRandomNumber(30) == 0) {
+ _gameState.unk10 = 5;
+ PART_31_HELPER_2(_gameState.unk10);
+ _gameState.counter[4] = 0;
+ return;
+ }
+ } else if (_gameState.unk10 == 5) {
+ if (_gameState.counter[4] == 20) {
+ _gameState.unk10 = 4;
+ PART_31_HELPER_2(_gameState.unk10);
+ return;
+ } else {
+ ++_gameState.counter[4];
+ }
+ }
+ }
+ } else {
+ if (_gameState.unk10 == 4 || _gameState.unk10 == 5) {
+ _gameState.unk10 = 3;
+ PART_31_HELPER_2(_gameState.unk10);
+ return;
+ }
+ if (_gameState.unk10 == 1 || _gameState.unk10 == 3) {
+ _gameState.unk10 = 2;
+ PART_31_HELPER_2(_gameState.unk10);
+ return;
+ }
+ }
+ }
+ if (xPos > 159 && xPos < 251) {
+ if (compareGameTick(3, 32)) {
+ if (_gameState.unk10 == 2) {
+ _gameState.unk10 = 1;
+ } else {
+ _gameState.unk10 = 2;
+ }
+ PART_31_HELPER_2(_gameState.unk10);
+ return;
+ }
+ }
+ if (xPos > 250 && compareGameTick(3, 16)) {
+ if (_gameState.unk10 == 1) {
+ _gameState.unk10 = 2;
+ } else {
+ _gameState.unk10 = 1;
+ }
+ PART_31_HELPER_2(_gameState.unk10);
+ }
+}
+
+void IgorEngine::PART_31_HELPER_1(int num) {
+ if (num == 1 || num == 255) {
+ if (_objectsState[72] == 0) {
+ _roomActionsTable[74] = 6;
+ } else {
+ PART_31_HELPER_9();
+ _roomActionsTable[74] = 7;
+ }
+ }
+}
+
+void IgorEngine::PART_31_HELPER_2(int frame) {
+ _roomCursorOn = false;
+ for (int i = 0; i <= 42; ++i) {
+ for (int j = 0; j <= 30; ++j) {
+ int offset = (i + 88) * 320 + j + 288;
+ uint8 color = _screenVGA[offset];
+ if (color < 192 || (color > 207 && color != 240 && color != 241)) {
+ color = _animFramesBuffer[0x310F + frame * 1333 + i * 31 + j];
+ }
+ _screenTempLayer[100 * i + j] = color;
+ }
+ }
+ for (int i = 0; i <= 42; ++i) {
+ const int offset = i * 320 + 28448;
+ memcpy(_screenVGA + offset, _screenTempLayer + i * 100, 31);
+ memcpy(_screenLayer1 + offset, _animFramesBuffer + 0x310F + frame * 1333 + i * 31, 31);
+ }
+ if (_dialogueCursorOn) {
+ _roomCursorOn = true;
+ }
+}
+
+void IgorEngine::PART_31_HELPER_3() {
+ _walkData[0].setPos(0, 137, 2, 0);
+ _walkData[0].setDefaultScale();
+ _walkData[0].clipSkipX = 15;
+ _walkData[0].clipWidth = 15;
+ _walkDataLastIndex = 0;
+ buildWalkPath(0, 137, 30, 137);
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+}
+
+void IgorEngine::PART_31_HELPER_4() {
+ _walkData[0].setPos(47, 63, 2, 0);
+ _walkData[0].setDefaultScale();
+ _walkData[0].clipWidth = 30;
+ _walkDataLastIndex = 0;
+ _roomObjectAreasTable[_screenLayer2[20207]].area = 2;
+ _roomObjectAreasTable[_screenLayer2[33712]].area = 2;
+ buildWalkPath(47, 63, 112, 105);
+ for (int i = 1; i <= _walkDataCurrentIndex; ++i) {
+ _walkData[i].posNum = 2;
+ }
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+ buildWalkPath(112, 105, 102, 125);
+ _roomObjectAreasTable[_screenLayer2[20207]].area = 0;
+ _roomObjectAreasTable[_screenLayer2[33712]].area = 0;
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+}
+
+void IgorEngine::PART_31_HELPER_5() {
+ _walkDataCurrentIndex = 0;
+ _walkCurrentFrame = 1;
+ _walkCurrentPos = 3;
+ for (int i = 0; i <= 9; ++i) {
+ WalkData *wd = &_walkData[0];
+ if (i == 9) {
+ _walkCurrentFrame = 0;
+ }
+ wd->setPos(166, 113, 3, _walkCurrentFrame);
+ WalkData::setNextFrame(3, _walkCurrentFrame);
+ wd->clipSkipX = 1;
+ wd->clipWidth = 30;
+ wd->scaleWidth = i * 3 + 23;
+ wd->xPosChanged = 1;
+ wd->dxPos = 0;
+ wd->yPosChanged = 1;
+ wd->dyPos = 3;
+ wd->scaleHeight = 50;
+ moveIgor(wd->posNum, wd->frameNum);
+ waitForTimer(15);
+ }
+ _walkDataLastIndex = 1;
+ _walkDataCurrentIndex = 1;
+ _roomObjectAreasTable[_screenLayer2[36326]].area = 2;
+ --_walkDataLastIndex;
+ buildWalkPath(166, 113, 140, 123);
+ _roomObjectAreasTable[_screenLayer2[36326]].area = 0;
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+}
+
+void IgorEngine::PART_31_HELPER_6() {
+ _walkData[0].setPos(319, 138, 4, 0);
+ _walkData[0].setDefaultScale();
+ _walkData[0].clipWidth = 15;
+ _walkDataLastIndex = 0;
+ buildWalkPath(319, 138, 289, 138);
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+}
+
+void IgorEngine::PART_31_HELPER_9() {
+ const int offset = 20256;
+ for (int i = 0; i <= 52; ++i) {
+ memcpy(_screenLayer1 + i * 320 + offset, _animFramesBuffer + i * 26 + 0x562, 26);
+ }
+}
+
+void IgorEngine::PART_31() {
+ _gameState.enableLight = 2;
+ loadRoomData(PAL_CollegeStairsSecondFloor, IMG_CollegeStairsSecondFloor, BOX_CollegeStairsSecondFloor, MSK_CollegeStairsSecondFloor, TXT_CollegeStairsSecondFloor);
+ static const int anm[] = { FRM_CollegeStairsSecondFloor1, FRM_CollegeStairsSecondFloor2, FRM_CollegeStairsSecondFloor3, 0 };
+ loadAnimData(anm);
+ loadActionData(DAT_CollegeStairsSecondFloor);
+ _roomDataOffsets = PART_31_ROOM_DATA_OFFSETS;
+ setRoomWalkBounds(0, 0, 319, 143);
+ SET_EXEC_ACTION_FUNC(1, &IgorEngine::PART_31_EXEC_ACTION);
+ _updateRoomBackground = &IgorEngine::PART_31_UPDATE_ROOM_BACKGROUND;
+ PART_31_HELPER_1(255);
+ memcpy(_screenVGA, _screenLayer1, 46080);
+ _currentAction.verb = kVerbWalk;
+ _gameState.unk10 = 4;
+ PART_31_HELPER_2(_gameState.unk10);
+ fadeInPalette(768);
+ if (_currentPart == 310) {
+ PART_31_HELPER_3();
+ } else if (_currentPart == 311) {
+ PART_31_HELPER_4();
+ } else if (_currentPart == 312) {
+ PART_31_HELPER_5();
+ } else if (_currentPart == 313) {
+ PART_31_HELPER_6();
+ }
+ showCursor();
+ _gameState.igorMoving = false;
+ while (_currentPart >= 310 && _currentPart <= 313) {
+ handleRoomInput();
+ if (compareGameTick(1, 16)) {
+ handleRoomIgorWalk();
+ }
+ if (compareGameTick(19, 32)) {
+ handleRoomDialogue();
+ }
+ if (compareGameTick(4, 8)) {
+ handleRoomInventoryScroll();
+ }
+ if (compareGameTick(1)) {
+ handleRoomLight();
+ }
+ PART_31_UPDATE_ROOM_BACKGROUND();
+ waitForTimer();
+ }
+ _updateRoomBackground = 0;
+ fadeOutPalette(624);
+}
+
+} // namespace Igor
diff --git a/engines/igor/parts/part_33.cpp b/engines/igor/parts/part_33.cpp
new file mode 100644
index 0000000000..38ca6cce3b
--- /dev/null
+++ b/engines/igor/parts/part_33.cpp
@@ -0,0 +1,519 @@
+/* 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 "igor/igor.h"
+
+namespace Igor {
+
+static const uint8 PART_33_ANIM_DATA_4[4] = { 0, 1, 2, 1 };
+
+static const uint8 PART_33_ANIM_DATA_5[5] = { 0, 6, 7, 8, 1 };
+
+void IgorEngine::PART_33_EXEC_ACTION(int action) {
+ switch (action) {
+ case 101:
+ ADD_DIALOGUE_TEXT(201, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 102:
+ ADD_DIALOGUE_TEXT(202, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 103:
+ ADD_DIALOGUE_TEXT(203, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 104:
+ ADD_DIALOGUE_TEXT(204, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 105:
+ ADD_DIALOGUE_TEXT(205, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 106:
+ ADD_DIALOGUE_TEXT(206, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 107:
+ ADD_DIALOGUE_TEXT(207, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 108:
+ ADD_DIALOGUE_TEXT(208, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 109:
+ PART_33_ACTION_109();
+ break;
+ case 110:
+ ADD_DIALOGUE_TEXT(209, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 111:
+ PART_33_ACTION_111();
+ break;
+ case 112:
+ ADD_DIALOGUE_TEXT(213, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 113:
+ PART_33_ACTION_113();
+ break;
+ case 114:
+ PART_33_ACTION_114();
+ break;
+ case 115:
+ PART_33_ACTION_115();
+ break;
+ default:
+ error("PART_33_EXEC_ACTION unhandled action %d", action);
+ break;
+ }
+}
+
+void IgorEngine::PART_33_ACTION_109() {
+ if (_objectsState[4] == 0) {
+ ADD_DIALOGUE_TEXT(201, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ return;
+ }
+ if (_objectsState[74] == 1) {
+ ADD_DIALOGUE_TEXT(222, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ return;
+ }
+ for (int i = 1; i <= 3; ++i) {
+ for (int j = 0; j <= 48; ++j) {
+ memcpy(_screenVGA + j * 320 + 23448, _animFramesBuffer + 0x467 * (PART_33_ANIM_DATA_4[i] - 1) + j * 23, 23);
+ waitForTimer(120);
+ }
+ }
+ addObjectToInventory(31, 66);
+ _objectsState[74] = 1;
+ PART_33_HELPER_1(255);
+ ADD_DIALOGUE_TEXT(210, 1);
+ ADD_DIALOGUE_TEXT(211, 2);
+ SET_DIALOGUE_TEXT(1, 2);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+}
+
+void IgorEngine::PART_33_ACTION_111() {
+ if (_objectsState[75] == 1) {
+ PART_33_HELPER_9();
+ PART_33_HELPER_1(255);
+ ADD_DIALOGUE_TEXT(201, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ ADD_DIALOGUE_TEXT(202, 2);
+ ADD_DIALOGUE_TEXT(204, 2);
+ SET_DIALOGUE_TEXT(1, 2);
+ _updateDialogue = &IgorEngine::PART_33_UPDATE_DIALOGUE_HARRISON_2;
+ startCutsceneDialogue(47, 82, 0, 58, 40);
+ waitForEndOfCutsceneDialogue(47, 82, 0, 58, 40);
+ _updateDialogue = 0;
+ loadResourceData__ROOM_Library();
+ PART_33_HELPER_1(255);
+ } else {
+ PART_33_HANDLE_DIALOGUE_HARRISON();
+ PART_33_HELPER_1(255);
+ }
+}
+
+void IgorEngine::PART_33_ACTION_113() {
+ _walkDataCurrentIndex = 0;
+ for (int i = 9; i >= 0; --i) {
+ if (i == 9) {
+ _walkCurrentFrame = 0;
+ }
+ WalkData *wd = &_walkData[0];
+ wd->setPos(207, 143, 3, _walkCurrentFrame);
+ WalkData::setNextFrame(3, _walkCurrentFrame);
+ wd->clipSkipX = 1;
+ wd->clipWidth = 30;
+ wd->scaleWidth = i * 3 + 23;
+ wd->xPosChanged = 1;
+ wd->dxPos = 0;
+ wd->yPosChanged = 1;
+ wd->dyPos = 3;
+ wd->scaleHeight = 50;
+ moveIgor(wd->posNum, wd->frameNum);
+ waitForTimer(15);
+ }
+ _currentPart = 241;
+}
+
+void IgorEngine::PART_33_ACTION_114() {
+ for (int i = 0; i <= 28; ++i) {
+ memcpy(_screenVGA + i * 320 + 26279, _animFramesBuffer + i * 63 + 0x5827, 62);
+ }
+ ADD_DIALOGUE_TEXT(223, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ ADD_DIALOGUE_TEXT(224, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ _updateDialogue = &IgorEngine::PART_33_UPDATE_DIALOGUE_HARRISON_2;
+ startCutsceneDialogue(47, 82, 0, 58, 40);
+ waitForEndOfCutsceneDialogue(47, 82, 0, 58, 40);
+ _updateDialogue = 0;
+ for (int i = 2; i <= 5; ++i) {
+ for (int j = 0; j <= 28; ++j) {
+ memcpy(_screenVGA + j * 320 + 26279, _animFramesBuffer + i * 1827 + j * 63 + 0x5104, 62);
+ }
+ waitForTimer(60);
+ }
+ removeObjectFromInventory(54);
+ ADD_DIALOGUE_TEXT(225, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ _updateDialogue = &IgorEngine::PART_33_UPDATE_DIALOGUE_HARRISON_2;
+ startCutsceneDialogue(47, 82, 0, 58, 40);
+ waitForEndOfCutsceneDialogue(47, 82, 0, 58, 40);
+ _updateDialogue = 0;
+ for (int i = 0; i <= 28; ++i) {
+ memcpy(_screenVGA + i * 320 + 26279, _animFramesBuffer + i * 63 + 0x5827, 62);
+ }
+ ADD_DIALOGUE_TEXT(226, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ ADD_DIALOGUE_TEXT(227, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ _updateDialogue = &IgorEngine::PART_33_UPDATE_DIALOGUE_HARRISON_2;
+ startCutsceneDialogue(47, 82, 0, 58, 40);
+ waitForEndOfCutsceneDialogue(47, 82, 0, 58, 40);
+ _updateDialogue = 0;
+ ADD_DIALOGUE_TEXT(228, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ ADD_DIALOGUE_TEXT(229, 2);
+ ADD_DIALOGUE_TEXT(231, 2);
+ SET_DIALOGUE_TEXT(1, 2);
+ _updateDialogue = &IgorEngine::PART_33_UPDATE_DIALOGUE_HARRISON_2;
+ startCutsceneDialogue(47, 82, 0, 58, 40);
+ waitForEndOfCutsceneDialogue(47, 82, 0, 58, 40);
+ _updateDialogue = 0;
+ for (int i = 1; i <= 4; ++i) {
+ for (int j = 0; j <= 28; ++j) {
+ memcpy(_screenVGA + j * 320 + 26279, _animFramesBuffer + PART_33_ANIM_DATA_5[i] * 1827 + j * 63 + 0x5104, 62);
+ }
+ waitForTimer(60);
+ }
+ addObjectToInventory(35, 70);
+ PART_33_HELPER_1(255);
+ ADD_DIALOGUE_TEXT(233, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ _updateDialogue = &IgorEngine::PART_33_UPDATE_DIALOGUE_HARRISON_2;
+ startCutsceneDialogue(47, 82, 0, 58, 40);
+ waitForEndOfCutsceneDialogue(47, 82, 0, 58, 40);
+ _updateDialogue = 0;
+ _objectsState[75] = 1;
+}
+
+void IgorEngine::PART_33_ACTION_115() {
+ const int offset = 26279;
+ for (int i = 0; i <= 28; ++i) {
+ memcpy(_screenVGA + i * 320 + offset, _animFramesBuffer + i * 63 + 0x5827, 62);
+ }
+ waitForTimer(60);
+ ADD_DIALOGUE_TEXT(215, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ for (int i = 2; i <= 5; ++i) {
+ for (int j = 0; j <= 28; ++j) {
+ memcpy(_screenVGA + j * 320 + offset, _animFramesBuffer + i * 1827 + j * 63 + 0x5104, 62);
+ }
+ waitForTimer(60);
+ }
+ removeObjectFromInventory(67);
+ PART_33_HELPER_1(255);
+ ADD_DIALOGUE_TEXT(217, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ _updateDialogue = &IgorEngine::PART_33_UPDATE_DIALOGUE_HARRISON_2;
+ startCutsceneDialogue(47, 82, 0, 58, 40);
+ waitForEndOfCutsceneDialogue(47, 82, 0, 58, 40);
+ _updateDialogue = 0;
+ for (int i = 0; i <= 28; ++i) {
+ memcpy(_screenVGA + i * 320 + offset, _animFramesBuffer + i * 63 + 0x5827, 62);
+ }
+ ADD_DIALOGUE_TEXT(219, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ _updateDialogue = &IgorEngine::PART_33_UPDATE_DIALOGUE_HARRISON_2;
+ startCutsceneDialogue(47, 82, 0, 58, 40);
+ waitForEndOfCutsceneDialogue(47, 82, 0, 58, 40);
+ _updateDialogue = 0;
+ for (int i = 0; i <= 28; ++i) {
+ memcpy(_screenVGA + i * 320 + offset, _animFramesBuffer + i * 63 + 0x5827, 62);
+ }
+ _objectsState[76] = 1;
+}
+
+void IgorEngine::PART_33_HANDLE_DIALOGUE_HARRISON() {
+ loadDialogueData(DLG_Library);
+ _updateDialogue = &IgorEngine::PART_33_UPDATE_DIALOGUE_HARRISON_3;
+ handleDialogue(47, 82, 0, 58, 40);
+ _updateDialogue = 0;
+}
+
+void IgorEngine::PART_33_UPDATE_DIALOGUE_HARRISON_1(int action) {
+ switch (action) {
+ case kUpdateDialogueAnimEndOfSentence:
+ PART_33_HELPER_4(1);
+ break;
+ case kUpdateDialogueAnimMiddleOfSentence:
+ PART_33_HELPER_4(getRandomNumber(4) + 2);
+ break;
+ }
+}
+
+void IgorEngine::PART_33_UPDATE_DIALOGUE_HARRISON_2(int action) {
+ switch (action) {
+ case kUpdateDialogueAnimEndOfSentence:
+ PART_33_HELPER_8(4);
+ break;
+ case kUpdateDialogueAnimMiddleOfSentence:
+ PART_33_HELPER_8(4 + getRandomNumber(3));
+ break;
+ }
+}
+
+void IgorEngine::PART_33_UPDATE_DIALOGUE_HARRISON_3(int action) {
+ switch (action) {
+ case kUpdateDialogueAnimEndOfSentence:
+ PART_33_HELPER_5(4);
+ break;
+ case kUpdateDialogueAnimMiddleOfSentence:
+ PART_33_HELPER_5(4 + getRandomNumber(3));
+ break;
+ case kUpdateDialogueAnimStanding:
+ PART_33_HELPER_5(4);
+ break;
+ }
+}
+
+void IgorEngine::PART_33_UPDATE_ROOM_BACKGROUND() {
+ if (compareGameTick(61) && _objectsState[75] != 2) {
+ PART_33_HELPER_8(_gameState.unk10);
+ _gameState.unk10 = getRandomNumber(4) + 1;
+ if (_gameState.unk10 >= 1 && _gameState.unk10 <= 2) {
+ _gameState.unk10 = 1;
+ } else {
+ _gameState.unk10 = 2;
+ }
+ }
+}
+
+void IgorEngine::PART_33_HELPER_1(int num) {
+ if (num == 2 || num == 255) {
+ if (_objectsState[75] <= 1) {
+ PART_33_HELPER_3();
+ } else {
+ _roomObjectAreasTable[27].object = 0;
+ }
+ }
+}
+
+void IgorEngine::PART_33_HELPER_2() {
+ playMusic(11);
+ memcpy(_screenLayer2, _screenVGA, 46080);
+ memcpy(_screenVGA, _screenLayer1, 46080);
+ decodeAnimFrame(_animFramesBuffer + 0x8CE + READ_LE_UINT16(_animFramesBuffer + 0x5255) - 1, _screenVGA, true);
+ memcpy(_screenLayer1, _screenVGA, 46080);
+ fadeInPalette(624);
+ ADD_DIALOGUE_TEXT(220, 1);
+ ADD_DIALOGUE_TEXT(221, 1);
+ SET_DIALOGUE_TEXT(1, 2);
+ _updateDialogue = &IgorEngine::PART_33_UPDATE_DIALOGUE_HARRISON_1;
+ startCutsceneDialogue(92, 79, 0, 58, 40);
+ waitForEndOfCutsceneDialogue(92, 79, 0, 58, 40);
+ _updateDialogue = 0;
+ for (int i = 6; i <= 25; ++i) {
+ decodeAnimFrame(_animFramesBuffer + 0x8CE + READ_LE_UINT16(_animFramesBuffer + 0x5253 + i * 2) - 1, _screenVGA, true);
+ waitForTimer(30);
+ }
+ fadeOutPalette(624);
+}
+
+void IgorEngine::PART_33_HELPER_3() {
+ const int offset = 29479;
+ for (int i = 0; i <= 14; ++i) {
+ memcpy(_screenLayer1 + i * 320 + offset, _animFramesBuffer + 0x5287 + i * 16, 16);
+ }
+}
+
+void IgorEngine::PART_33_HELPER_4(int frame) {
+ decodeAnimFrame(_animFramesBuffer + 0x8CE + READ_LE_UINT16(_animFramesBuffer + 0x5253 + frame * 2) - 1, _screenVGA, true);
+}
+
+void IgorEngine::PART_33_HELPER_5(int frame) {
+ _roomCursorOn = false;
+ for (int i = 0; i <= 14; ++i) {
+ for (int j = 0; j <= 15; ++j) {
+ int offset = (i + 92) * 320 + j + 39;
+ uint8 color = _screenVGA[offset];
+ if (color < 192 || (color > 207 && color != 240 && color != 241)) {
+ color = _animFramesBuffer[0x5197 + frame * 240 + i * 16 + j];
+ }
+ _screenTempLayer[100 * i + j] = color;
+ }
+ }
+ for (int i = 0; i <= 14; ++i) {
+ const int offset = i * 320 + 29479;
+ memcpy(_screenVGA + offset, _screenTempLayer + i * 100, 16);
+ memcpy(_screenLayer1 + offset, _animFramesBuffer + 0x5197 + frame * 240 + i * 16, 16);
+ }
+ if (_dialogueCursorOn) {
+ _roomCursorOn = true;
+ }
+}
+
+void IgorEngine::PART_33_HELPER_7() {
+ _walkDataCurrentIndex = 0;
+ _walkCurrentFrame = 1;
+ _walkCurrentPos = 1;
+ for (int i = 0; i <= 9; ++i) {
+ WalkData *wd = &_walkData[0];
+ wd->setPos(207, 143, 1, _walkCurrentFrame);
+ WalkData::setNextFrame(1, _walkCurrentFrame);
+ wd->clipSkipX = 1;
+ wd->clipWidth = 30;
+ wd->scaleWidth = 23 + i * 3;
+ wd->xPosChanged = 1;
+ wd->dxPos = 0;
+ wd->yPosChanged = 1;
+ wd->dyPos = 3;
+ wd->scaleHeight = 50;
+ moveIgor(wd->posNum, wd->frameNum);
+ waitForTimer(15);
+ }
+ _walkDataLastIndex = 1;
+ _walkDataCurrentIndex = 1;
+ --_walkDataLastIndex;
+ buildWalkPath(207, 143, 187, 138);
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+}
+
+void IgorEngine::PART_33_HELPER_8(int frame) {
+ _roomCursorOn = false;
+ for (int i = 0; i <= 14; ++i) {
+ for (int j = 0; j <= 15; ++j) {
+ int offset = (i + 92) * 320 + j + 39;
+ uint8 color = _screenVGA[offset];
+ if (color < 192 || (color > 207 && color != 240 && color != 241)) {
+ color = _animFramesBuffer[0x5197 + frame * 240 + i * 16 + j];
+ }
+ _screenTempLayer[100 * i + j] = color;
+ }
+ }
+ for (int i = 0; i <= 14; ++i) {
+ const int offset = i * 320 + 29479;
+ memcpy(_screenVGA + offset, _screenTempLayer + i * 100, 16);
+ memcpy(_screenLayer1 + offset, _animFramesBuffer + 0x5197 + frame * 240 + i * 16, 16);
+ }
+ if (_dialogueCursorOn) {
+ _roomCursorOn = true;
+ }
+}
+
+void IgorEngine::PART_33_HELPER_9() {
+ uint8 *p = loadData(TXT_Library2);
+ decodeRoomStrings(p, true);
+ free(p);
+}
+
+void IgorEngine::PART_33() {
+ _gameState.enableLight = 1;
+ _gameState.unk10 = 1;
+ loadResourceData__ROOM_Library();
+ loadResourceData__ANIM_Library();
+ loadActionData(DAT_Library);
+ _roomDataOffsets = PART_33_ROOM_DATA_OFFSETS;
+ setRoomWalkBounds(0, 0, 276, 143);
+ if (_currentPart == 331) {
+ PART_33_HELPER_2();
+ return;
+ }
+ SET_EXEC_ACTION_FUNC(1, &IgorEngine::PART_33_EXEC_ACTION);
+ _updateRoomBackground = &IgorEngine::PART_33_UPDATE_ROOM_BACKGROUND;
+ PART_33_HELPER_1(255);
+ memcpy(_screenVGA, _screenLayer1, 46080);
+ _currentAction.verb = kVerbWalk;
+ fadeInPalette(768);
+ PART_33_HELPER_7();
+ showCursor();
+ _gameState.igorMoving = false;
+ while (_currentPart == 330) {
+ handleRoomInput();
+ if (compareGameTick(1, 16)) {
+ handleRoomIgorWalk();
+ }
+ if (compareGameTick(19, 32)) {
+ handleRoomDialogue();
+ }
+ if (compareGameTick(4, 8)) {
+ handleRoomInventoryScroll();
+ }
+ if (compareGameTick(1)) {
+ handleRoomLight();
+ }
+ PART_33_UPDATE_ROOM_BACKGROUND();
+ waitForTimer();
+ }
+ if (_objectsState[75] == 1) {
+ _objectsState[75] = 2;
+ }
+ fadeOutPalette(624);
+ _updateRoomBackground = 0;
+}
+
+void IgorEngine::loadResourceData__ROOM_Library() {
+ loadRoomData(PAL_Library, IMG_Library, BOX_Library, MSK_Library, TXT_Library);
+}
+
+void IgorEngine::loadResourceData__ANIM_Library() {
+ static const int anm[] = { FRM_Library1, FRM_Library2, FRM_Library3, FRM_Library4, FRM_Library5, 0 };
+ loadAnimData(anm);
+}
+
+} // namespace Igor
diff --git a/engines/igor/parts/part_36.cpp b/engines/igor/parts/part_36.cpp
new file mode 100644
index 0000000000..9510ac6ae5
--- /dev/null
+++ b/engines/igor/parts/part_36.cpp
@@ -0,0 +1,177 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "igor/igor.h"
+
+namespace Igor {
+
+void IgorEngine::PART_36_EXEC_ACTION(int action) {
+ switch (action) {
+ case 101:
+ ADD_DIALOGUE_TEXT(201, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 102:
+ PART_36_ACTION_102();
+ break;
+ case 103:
+ ADD_DIALOGUE_TEXT(202, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 104:
+ ADD_DIALOGUE_TEXT(203, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 105:
+ ADD_DIALOGUE_TEXT(204, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 106:
+ ADD_DIALOGUE_TEXT(209, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 107:
+ ADD_DIALOGUE_TEXT(206, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 108:
+ ADD_DIALOGUE_TEXT(208, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 109:
+ _currentPart = 242;
+ break;
+ default:
+ error("PART_36_EXEC_ACTION unhandled action %d", action);
+ break;
+ }
+}
+
+void IgorEngine::PART_36_ACTION_102() {
+ for (_gameState.counter[0] = 1; _gameState.counter[0] >= 0; --_gameState.counter[0]) {
+ for (_gameState.counter[1] = 0; _gameState.counter[1] <= 48; ++_gameState.counter[1]) {
+ for (_gameState.counter[2] = 0; _gameState.counter[2] <= 33; ++_gameState.counter[2]) {
+ uint8 color = _animFramesBuffer[14 + _gameState.counter[0] * 1666 + _gameState.counter[1] * 34 + _gameState.counter[2]];
+ int offset = (_gameState.counter[1] + 74) * 320 + _gameState.counter[2] + 70;
+ if (color < 192 || color > 207) {
+ _screenTempLayer[100 * _gameState.counter[1] + _gameState.counter[2]] = color;
+ continue;
+ }
+ RoomObjectArea *roa = &_roomObjectAreasTable[_screenLayer2[offset]];
+ if (roa->y1Lum > 0) {
+ _screenTempLayer[100 * _gameState.counter[1] + _gameState.counter[2]] = _screenLayer1[offset];
+ } else {
+ if (roa->y2Lum > 0) {
+ color -= roa->deltaLum;
+ }
+ _screenTempLayer[100 * _gameState.counter[1] + _gameState.counter[2]] = color;
+ }
+ }
+ }
+ for (_gameState.counter[1] = 0; _gameState.counter[1] <= 48; ++_gameState.counter[1]) {
+ memcpy(_screenVGA + _gameState.counter[1] * 320 + 23750, _screenTempLayer + _gameState.counter[1] * 100, 34);
+ }
+ waitForTimer(45);
+ }
+ addObjectToInventory(30, 65);
+ _objectsState[88] = 1;
+ PART_36_HELPER_1(255);
+}
+
+void IgorEngine::PART_36_HELPER_1(int num) {
+ if (num == 1 || num == 255) {
+ if (_objectsState[88] == 0) {
+ PART_36_HELPER_4(1);
+ } else {
+ PART_36_HELPER_4(0);
+ _roomObjectAreasTable[6].object = 1;
+ _roomObjectAreasTable[7].object = 1;
+ }
+ }
+}
+
+void IgorEngine::PART_36_HELPER_2() {
+ _walkData[0].setPos(319, 143, 4, 0);
+ _walkData[0].setDefaultScale();
+ _walkDataLastIndex = 0;
+ _walkCurrentFrame = 1;
+ buildWalkPath(319, 143, 259, 143);
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+}
+
+void IgorEngine::PART_36_HELPER_4(int frame) {
+ if (frame == 0) {
+ memcpy(_screenLayer1 + 31430, _animFramesBuffer, 7);
+ } else if (frame == 1) {
+ memcpy(_screenLayer1 + 31430, _animFramesBuffer + 7, 7);
+ }
+}
+
+void IgorEngine::PART_36() {
+ _gameState.enableLight = 1;
+ loadRoomData(PAL_ChemistryClassroom, IMG_ChemistryClassroom, BOX_ChemistryClassroom, MSK_ChemistryClassroom, TXT_ChemistryClassroom);
+ static const int anm[] = { FRM_ChemistryClassroom1, FRM_ChemistryClassroom2, 0 };
+ loadAnimData(anm);
+ loadActionData(DAT_ChemistryClassroom);
+ _roomDataOffsets = PART_36_ROOM_DATA_OFFSETS;
+ setRoomWalkBounds(90, 0, 319, 143);
+ SET_EXEC_ACTION_FUNC(1, &IgorEngine::PART_36_EXEC_ACTION);
+ PART_36_HELPER_1(255);
+ memcpy(_screenVGA, _screenLayer1, 46080);
+ _currentAction.verb = kVerbWalk;
+ fadeInPalette(768);
+ PART_36_HELPER_2();
+ showCursor();
+ _gameState.igorMoving = false;
+ while (_currentPart == 360) {
+ handleRoomInput();
+ if (compareGameTick(1, 16)) {
+ handleRoomIgorWalk();
+ }
+ if (compareGameTick(19, 32)) {
+ handleRoomDialogue();
+ }
+ if (compareGameTick(4, 8)) {
+ handleRoomInventoryScroll();
+ }
+ if (compareGameTick(1)) {
+ handleRoomLight();
+ }
+ waitForTimer();
+ }
+ fadeOutPalette(624);
+}
+
+} // namespace Igor
diff --git a/engines/igor/parts/part_37.cpp b/engines/igor/parts/part_37.cpp
new file mode 100644
index 0000000000..ff2c2f74cf
--- /dev/null
+++ b/engines/igor/parts/part_37.cpp
@@ -0,0 +1,139 @@
+/* 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 "igor/igor.h"
+
+namespace Igor {
+
+void IgorEngine::PART_37_EXEC_ACTION(int action) {
+ switch (action) {
+ case 101:
+ _currentPart = 212;
+ break;
+ case 102:
+ PART_37_ACTION_102();
+ break;
+ case 103:
+ ADD_DIALOGUE_TEXT(203, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 104:
+ ADD_DIALOGUE_TEXT(205, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 105:
+ ADD_DIALOGUE_TEXT(207, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 106:
+ ADD_DIALOGUE_TEXT(206, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ default:
+ error("PART_37_EXEC_ACTION unhandled action %d", action);
+ break;
+ }
+}
+
+void IgorEngine::PART_37_ACTION_102() {
+ if (_objectsState[89] == 1) {
+ ADD_DIALOGUE_TEXT(202, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ return;
+ }
+ ADD_DIALOGUE_TEXT(201, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ for (int i = 1; i >= 0; --i) {
+ int offset = 16423;
+ for (int j = 0; j <= 49; ++j) {
+ memcpy(_screenVGA + j * 320 + offset, _animFramesBuffer + i * 1550 + j * 31, 31);
+ }
+ waitForTimer(60);
+ }
+ addObjectToInventory(32, 67);
+ _objectsState[89] = 1;
+ PART_37_HELPER_1(255);
+}
+
+void IgorEngine::PART_37_HELPER_1(int num) {
+}
+
+void IgorEngine::PART_37_HELPER_2() {
+ _walkData[0].setPos(0, 143, 2, 0);
+ _walkData[0].setDefaultScale();
+ _walkData[0].clipSkipX = 16;
+ _walkData[0].clipWidth = 15;
+ _walkDataLastIndex = 0;
+ _walkCurrentFrame = 1;
+ buildWalkPath(0, 143, 60, 143);
+ _walkData[_walkDataLastIndex].frameNum = 0;
+ _walkDataCurrentIndex = 1;
+ _gameState.igorMoving = true;
+ waitForIgorMove();
+}
+
+void IgorEngine::PART_37() {
+ _gameState.enableLight = 1;
+ loadRoomData(PAL_PhysicsClassroom, IMG_PhysicsClassroom, BOX_PhysicsClassroom, MSK_PhysicsClassroom, TXT_PhysicsClassroom);
+ static const int anm[] = { FRM_PhysicsClassroom1, 0 };
+ loadAnimData(anm);
+ loadActionData(DAT_PhysicsClassroom);
+ _roomDataOffsets = PART_37_ROOM_DATA_OFFSETS;
+ setRoomWalkBounds(0, 0, 228, 143);
+ SET_EXEC_ACTION_FUNC(1, &IgorEngine::PART_37_EXEC_ACTION);
+ PART_37_HELPER_1(255);
+ memcpy(_screenVGA, _screenLayer1, 46080);
+ _currentAction.verb = kVerbWalk;
+ fadeInPalette(768);
+ PART_37_HELPER_2();
+ showCursor();
+ _gameState.igorMoving = false;
+ while (_currentPart == 370) {
+ handleRoomInput();
+ if (compareGameTick(1, 16)) {
+ handleRoomIgorWalk();
+ }
+ if (compareGameTick(19, 32)) {
+ handleRoomDialogue();
+ }
+ if (compareGameTick(4, 8)) {
+ handleRoomInventoryScroll();
+ }
+ if (compareGameTick(1)) {
+ handleRoomLight();
+ }
+ waitForTimer();
+ }
+ fadeOutPalette(624);
+}
+
+} // namespace Igor
diff --git a/engines/igor/parts/part_75.cpp b/engines/igor/parts/part_75.cpp
new file mode 100644
index 0000000000..a1108149db
--- /dev/null
+++ b/engines/igor/parts/part_75.cpp
@@ -0,0 +1,119 @@
+/* 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 "igor/igor.h"
+
+namespace Igor {
+
+static const uint8 PART_75_ANIM_DATA_1[18] = {
+ 0, 8, 9, 8, 9, 8, 9, 8, 9, 8, 9, 10, 11, 12, 13, 14, 15, 16
+};
+
+static const uint8 PART_75_ANIM_DATA_2[37] = {
+ 0, 31, 32, 33, 34, 31, 32, 33, 34, 31, 32, 33, 34, 31, 32, 33, 34, 31, 32,
+ 33, 34, 31, 32, 33, 34, 31, 32, 33, 34, 31, 32, 33, 34, 31, 32, 33, 34
+};
+
+void IgorEngine::PART_75_UPDATE_DIALOGUE_PHILIP(int action) {
+ switch (action) {
+ case kUpdateDialogueAnimEndOfSentence:
+ PART_75_HELPER_1(2);
+ break;
+ case kUpdateDialogueAnimMiddleOfSentence:
+ PART_75_HELPER_1(getRandomNumber(5) + 2);
+ break;
+ }
+}
+
+void IgorEngine::PART_75_HELPER_1(int frame) {
+ const uint8 *src = _animFramesBuffer + READ_LE_UINT16(_animFramesBuffer + 0x5E6D + frame * 2) - 1;
+ decodeAnimFrame(src, _screenVGA);
+}
+
+void IgorEngine::PART_75() {
+ PART_MEANWHILE();
+ _gameState.enableLight = 1;
+ loadRoomData(PAL_PhilipRoom, IMG_PhilipRoom, BOX_PhilipRoom, MSK_PhilipRoom, TXT_PhilipRoom);
+ static const int anm[] = { ANM_PhilipVodka, AOF_PhilipVodka, 0 };
+ loadAnimData(anm);
+ memcpy(_screenVGA, _screenLayer1, 46080);
+ _updateDialogue = &IgorEngine::PART_75_UPDATE_DIALOGUE_PHILIP;
+ PART_75_HELPER_1(1);
+ PART_75_HELPER_1(7);
+ memset(_currentPalette, 0, 768);
+ fadeInPalette(768);
+ _gameState.igorMoving = false;
+ ADD_DIALOGUE_TEXT(201, 1);
+ ADD_DIALOGUE_TEXT(202, 2);
+ ADD_DIALOGUE_TEXT(204, 1);
+ SET_DIALOGUE_TEXT(1, 3);
+ startCutsceneDialogue(187, 82, 63, 63, 0);
+ waitForEndOfCutsceneDialogue(187, 82, 63, 63, 0);
+ for (int i = 1; i <= 17; ++i) {
+ PART_75_HELPER_1(PART_75_ANIM_DATA_1[i]);
+ waitForTimer(30);
+ }
+ ADD_DIALOGUE_TEXT(205, 1);
+ ADD_DIALOGUE_TEXT(206, 1);
+ SET_DIALOGUE_TEXT(1, 2);
+ startCutsceneDialogue(187, 82, 63, 63, 0);
+ waitForEndOfCutsceneDialogue(187, 82, 63, 63, 0);
+ for (int i = 17; i <= 30; ++i) {
+ PART_75_HELPER_1(i);
+ waitForTimer(15);
+ }
+ ADD_DIALOGUE_TEXT(208, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startCutsceneDialogue(187, 82, 63, 63, 0);
+ playSound(62, 1);
+ for (int i = 1; i <= 36; ++i) {
+ PART_75_HELPER_1(PART_75_ANIM_DATA_2[i]);
+ waitForTimer(15);
+ }
+ memcpy(_screenVGA + _dialogueDirtyRectY, _screenTextLayer + 23040, _dialogueDirtyRectSize);
+ ADD_DIALOGUE_TEXT(209, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startCutsceneDialogue(187, 82, 63, 63, 0);
+ PART_75_HELPER_1(35);
+ waitForTimer(255);
+ PART_75_HELPER_1(36);
+ waitForTimer(140);
+ memcpy(_screenVGA + _dialogueDirtyRectY, _screenTextLayer + 23040, _dialogueDirtyRectSize);
+ ADD_DIALOGUE_TEXT(210, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startCutsceneDialogue(187, 82, 63, 63, 0);
+ waitForEndOfCutsceneDialogue(187, 82, 63, 63, 0);
+ for (int i = 1; i <= 40; ++i) {
+ PART_75_HELPER_1(getRandomNumber(4) + 37);
+ waitForTimer(30);
+ }
+ memcpy(_screenVGA + _dialogueDirtyRectY, _screenTextLayer + 23040, _dialogueDirtyRectSize);
+ _gameState.dialogueTextRunning = false;
+ _updateDialogue = 0;
+ _currentPart = 122;
+ fadeOutPalette(768);
+}
+
+} // namespace Igor
diff --git a/engines/igor/parts/part_85.cpp b/engines/igor/parts/part_85.cpp
new file mode 100644
index 0000000000..495ffbd7a7
--- /dev/null
+++ b/engines/igor/parts/part_85.cpp
@@ -0,0 +1,227 @@
+/* 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/system.h"
+
+#include "igor/igor.h"
+
+namespace Igor {
+
+static bool VAR_WATER_SOUND_PLAYING;
+static int VAR_CURRENT_TALKING_ACTOR;
+
+void IgorEngine::PART_85_UPDATE_ROOM_BACKGROUND() {
+ if (compareGameTick(61)) {
+ scrollPalette(160, 167);
+ setPaletteRange(160, 167);
+ }
+ if (compareGameTick(2, 8)) {
+ scrollPalette(168, 178);
+ setPaletteRange(168, 178);
+ }
+ if (compareGameTick(13, 16)) {
+ scrollPalette(179, 184);
+ setPaletteRange(179, 184);
+ }
+ if (compareGameTick(5, 32)) {
+ scrollPalette(185, 191);
+ setPaletteRange(185, 191);
+ }
+ if (!VAR_WATER_SOUND_PLAYING) {
+ return;
+ }
+ if (_gameState.talkMode == kTalkModeTextOnly || !_gameState.dialogueTextRunning) {
+ playSound(17, 1);
+ }
+}
+
+void IgorEngine::PART_85_UPDATE_DIALOGUE_PHILIP_LAURA(int action) {
+ switch (action) {
+ case kUpdateDialogueAnimEndOfSentence:
+ decodeAnimFrame(_animFramesBuffer - 1 + READ_LE_UINT16(_animFramesBuffer + 0x7480), _screenVGA, true);
+ break;
+ case kUpdateDialogueAnimMiddleOfSentence:
+ if (VAR_CURRENT_TALKING_ACTOR != 0) {
+ _gameState.counter[0] = getRandomNumber(5) + 8;
+ } else {
+ _gameState.counter[0] = getRandomNumber(5) + 13;
+ }
+ decodeAnimFrame(getAnimFrame(0, 0x7480, _gameState.counter[0]), _screenVGA, true);
+ break;
+ }
+}
+
+void IgorEngine::PART_85_HELPER_1(int frameOffset2, int frameOffset1, int firstFrame, int lastFrame, int delay) {
+ do {
+ if (compareGameTick(0, delay)) {
+ decodeAnimFrame(_animFramesBuffer + frameOffset2 - 1 + READ_LE_UINT16(_animFramesBuffer + frameOffset1 + firstFrame * 2 - 3), _screenVGA, true);
+ ++firstFrame;
+ }
+ PART_85_UPDATE_ROOM_BACKGROUND();
+ if (_inputVars[kInputEscape]) return;
+ waitForTimer();
+ } while (firstFrame <= lastFrame);
+}
+
+void IgorEngine::PART_85_HELPER_2() {
+ int x = 1;
+ do {
+ if (compareGameTick(0, 16)) {
+ for (int y = 0; y <= 143; ++y) {
+ memcpy(_screenTextLayer + y * 320, _screenLayer1 + y * 320 + x * 8, 320 - x * 8);
+ memcpy(_screenTextLayer + y * 320 + 320 - x * 8, _screenLayer2 + y * 320 + 96, x * 8);
+ }
+ memcpy(_screenVGA, _screenTextLayer, 46080);
+ ++x;
+ }
+ PART_85_UPDATE_ROOM_BACKGROUND();
+ waitForTimer();
+ } while (x != 29 && !_inputVars[kInputEscape]);
+}
+
+void IgorEngine::PART_85_HELPER_6(int frame) {
+ const int offset = (_walkCurrentPos == 4) ? 24564 : 22643;
+ copyArea(_screenVGA, offset, 320, _screenLayer2 + offset, 320, 14, 8);
+ copyArea(_screenVGA, offset, 320, _igorHeadFrames + (_walkCurrentPos - 1) * 924 + frame * 154, 14, 14, 8, true);
+}
+
+void IgorEngine::PART_85() {
+ playMusic(2);
+ loadRoomData(PAL_SpringRock, IMG_SpringRock, BOX_SpringRock, MSK_SpringRock, TXT_SpringRock);
+ memcpy(_screenLayer2, _screenLayer1, 46080);
+ loadRoomData(PAL_SpringBridgeIntro, IMG_SpringBridgeIntro, 0, 0, TXT_SpringBridgeIntro);
+ static const int anm[] = { ANM_PhilipLauraIntro, AOF_PhilipLauraIntro, ANM_LauraIntro, AOF_LauraIntro, 0 };
+ loadAnimData(anm);
+ memcpy(_screenVGA, _screenLayer1, 46080);
+ _updateDialogue = &IgorEngine::PART_85_UPDATE_DIALOGUE_PHILIP_LAURA;
+ _updateRoomBackground = &IgorEngine::PART_85_UPDATE_ROOM_BACKGROUND;
+ VAR_WATER_SOUND_PLAYING = true;
+ playSound(17, 1);
+ decodeAnimFrame(getAnimFrame(0, 0x7480, 1), _screenVGA, true);
+ fadeInPalette(768);
+ if (_inputVars[kInputEscape]) goto PART_85_EXIT;
+ PART_85_HELPER_1(0, 0x7481, 2, 7, 32);
+ if (_inputVars[kInputEscape]) goto PART_85_EXIT;
+ ADD_DIALOGUE_TEXT(201, 3);
+ ADD_DIALOGUE_TEXT(204, 1);
+ SET_DIALOGUE_TEXT(1, 2);
+ startCutsceneDialogue(89, 56, 63, 63, 0);
+ VAR_CURRENT_TALKING_ACTOR = 0;
+ waitForEndOfCutsceneDialogue(89, 56, 63, 63, 0);
+ if (_inputVars[kInputEscape]) goto PART_85_EXIT;
+ ADD_DIALOGUE_TEXT(205, 3);
+ SET_DIALOGUE_TEXT(1, 1);
+ startCutsceneDialogue(113, 59, 63, 0, 38);
+ VAR_CURRENT_TALKING_ACTOR = 1;
+ waitForEndOfCutsceneDialogue(113, 59, 63, 0, 38);
+ if (_inputVars[kInputEscape]) goto PART_85_EXIT;
+ ADD_DIALOGUE_TEXT(208, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startCutsceneDialogue(89, 56, 63, 63, 0);
+ VAR_CURRENT_TALKING_ACTOR = 0;
+ waitForEndOfCutsceneDialogue(89, 56, 63, 63, 0);
+ if (_inputVars[kInputEscape]) goto PART_85_EXIT;
+ ADD_DIALOGUE_TEXT(209, 2);
+ ADD_DIALOGUE_TEXT(211, 1);
+ ADD_DIALOGUE_TEXT(212, 1);
+ ADD_DIALOGUE_TEXT(213, 1);
+ ADD_DIALOGUE_TEXT(214, 1);
+ SET_DIALOGUE_TEXT(1, 5);
+ startCutsceneDialogue(113, 59, 63, 0, 38);
+ VAR_CURRENT_TALKING_ACTOR = 1;
+ waitForEndOfCutsceneDialogue(113, 59, 63, 0, 38);
+ if (_inputVars[kInputEscape]) goto PART_85_EXIT;
+ PART_85_HELPER_1(0, 0x7481, 2, 7, 32);
+ if (_inputVars[kInputEscape]) goto PART_85_EXIT;
+ ADD_DIALOGUE_TEXT(215, 1);
+ ADD_DIALOGUE_TEXT(216, 2);
+ ADD_DIALOGUE_TEXT(218, 1);
+ SET_DIALOGUE_TEXT(1, 3);
+ startCutsceneDialogue(89, 56, 63, 63, 0);
+ VAR_CURRENT_TALKING_ACTOR = 0;
+ waitForEndOfCutsceneDialogue(89, 56, 63, 63, 0);
+ if (_inputVars[kInputEscape]) goto PART_85_EXIT;
+ ADD_DIALOGUE_TEXT(219, 2);
+ ADD_DIALOGUE_TEXT(221, 2);
+ SET_DIALOGUE_TEXT(1, 2);
+ startCutsceneDialogue(113, 59, 63, 0, 38);
+ VAR_CURRENT_TALKING_ACTOR = 1;
+ waitForEndOfCutsceneDialogue(113, 59, 63, 0, 38);
+ if (_inputVars[kInputEscape]) goto PART_85_EXIT;
+ decodeAnimFrame(getAnimFrame(0, 0x7480, 1), _screenVGA, true);
+ PART_85_HELPER_1(0, 0x7481, 2, 7, 32);
+ if (_inputVars[kInputEscape]) goto PART_85_EXIT;
+ PART_85_HELPER_1(0, 0x7481, 18, 37, 20);
+ if (_inputVars[kInputEscape]) goto PART_85_EXIT;
+ PART_85_HELPER_2();
+ VAR_WATER_SOUND_PLAYING = false;
+ stopSound();
+ if (_inputVars[kInputEscape]) goto PART_85_EXIT;
+ PART_85_HELPER_1(0x74CA, 0xA6C4, 1, 6, 32);
+ if (_inputVars[kInputEscape]) goto PART_85_EXIT;
+ for (_gameState.counter[4] = 0; _gameState.counter[4] != 200; ++_gameState.counter[4]) {
+ PART_85_UPDATE_ROOM_BACKGROUND();
+ if (_inputVars[kInputEscape]) goto PART_85_EXIT;
+ waitForTimer();
+ }
+ _walkData[0].x = 251;
+ _walkData[0].y = 125;
+ _walkData[0].scaleWidth = 50;
+ _walkDataLastIndex = 1;
+ _walkCurrentPos = 4;
+ ADD_DIALOGUE_TEXT(223, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ if (_inputVars[kInputEscape]) goto PART_85_EXIT;
+ PART_85_HELPER_1(0x74CA, 0xA6C4, 7, 9, 32);
+ if (_inputVars[kInputEscape]) goto PART_85_EXIT;
+ _walkData[0].x = 250;
+ _walkData[0].y = 119;
+ _walkCurrentPos = 3;
+ ADD_DIALOGUE_TEXT(225, 2);
+ ADD_DIALOGUE_TEXT(227, 3);
+ SET_DIALOGUE_TEXT(1, 2);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ if (_inputVars[kInputEscape]) goto PART_85_EXIT;
+ PART_85_HELPER_1(0x74CA, 0xA6C4, 10, 24, 16);
+
+PART_85_EXIT:
+ stopSound();
+ _gameState.dialogueTextRunning = false;
+ _inputVars[kInputEscape] = 0;
+ _walkData[0].setPos(155, 121, 4, 0);
+ _walkData[0].setDefaultScale();
+ copyArea(_screenLayer2, 23180, 320, _facingIgorFrames[3], 30, 30, 50, true);
+ memcpy(_screenVGA, _screenLayer2, 46080);
+ memset(_currentPalette + 0x270, 0, 0x8D);
+ setPaletteRange(208, 254);
+ _currentPart = 61;
+ _updateDialogue = 0;
+ _updateRoomBackground = 0;
+}
+
+} // namespace Igor
diff --git a/engines/igor/parts/part_90.cpp b/engines/igor/parts/part_90.cpp
new file mode 100644
index 0000000000..e5578fc18e
--- /dev/null
+++ b/engines/igor/parts/part_90.cpp
@@ -0,0 +1,76 @@
+/* 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 "igor/igor.h"
+
+namespace Igor {
+
+static const char *STR_COPYRIGHT = "(C) 1995 Optik Software. All rights reserved.";
+
+void IgorEngine::PART_90() {
+ memset(_currentPalette, 0, 768);
+ setPaletteRange(0, 255);
+ switch (_currentPart) {
+ case 900:
+ loadData(PAL_OptikSoftware, _paletteBuffer);
+ loadData(IMG_OptikSoftware, _screenVGA);
+ break;
+ case 901:
+ loadData(PAL_Presents, _paletteBuffer);
+ loadData(IMG_Presents, _screenVGA);
+ break;
+ case 902:
+ loadData(PAL_GraphicAdventure, _paletteBuffer);
+ loadData(IMG_GraphicAdventure, _screenVGA);
+ break;
+ case 903:
+ loadData(PAL_PenduloStudios, _paletteBuffer);
+ loadData(IMG_PenduloStudios, _screenVGA);
+ break;
+ case 904:
+ loadData(PAL_TitleScreen, _paletteBuffer);
+ loadData(IMG_TitleScreen, _screenVGA);
+ drawString(_screenVGA, STR_COPYRIGHT, 2, 187, 0xF5, 0, 0);
+ break;
+ }
+ fadeInPalette(768);
+ while (!_inputVars[kInputEscape] && !_eventQuitGame) {
+ waitForTimer();
+ if (_inputVars[kInputOptions]) {
+ _inputVars[kInputOptions] = 0;
+ handleOptionsMenu();
+ break;
+ }
+ }
+ _inputVars[kInputEscape] = 0;
+ fadeOutPalette(768);
+ if (_currentPart == 904) {
+ _currentPart = 850;
+ } else {
+ ++_currentPart;
+ }
+}
+
+} // namespace Igor
diff --git a/engines/igor/parts/part_95.cpp b/engines/igor/parts/part_95.cpp
new file mode 100644
index 0000000000..0abe2d7149
--- /dev/null
+++ b/engines/igor/parts/part_95.cpp
@@ -0,0 +1,72 @@
+/* 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 "igor/igor.h"
+
+namespace Igor {
+
+void IgorEngine::PART_95() {
+ memset(_currentPalette, 0, 768);
+ setPaletteRange(0, 255);
+ memset(_screenVGA, 0, 64000);
+ switch (_currentPart) {
+ case 950:
+ loadData(PAL_Shareware1, _paletteBuffer);
+ loadData(IMG_Shareware1, _screenVGA);
+ break;
+ case 951:
+ loadData(PAL_Shareware2, _paletteBuffer);
+ loadData(IMG_Shareware2, _screenVGA);
+ break;
+ case 952:
+ loadData(PAL_Shareware3, _paletteBuffer);
+ loadData(IMG_Shareware3, _screenVGA);
+ break;
+ case 953:
+ loadData(PAL_Shareware4, _paletteBuffer);
+ loadData(IMG_Shareware4, _screenVGA);
+ break;
+ case 954:
+ loadData(PAL_Shareware5, _paletteBuffer);
+ loadData(IMG_Shareware5, _screenVGA);
+ break;
+ case 955:
+ loadData(PAL_Shareware6, _paletteBuffer);
+ loadData(IMG_Shareware6, _screenVGA);
+ break;
+ case 956:
+ loadData(PAL_Shareware7, _paletteBuffer);
+ loadData(IMG_Shareware7, _screenVGA);
+ break;
+ }
+ fadeInPalette(768);
+ for (int i = 0; !_inputVars[kInputEscape] && i < 3000; ++i) {
+ waitForTimer();
+ }
+ _inputVars[kInputEscape] = 0;
+ fadeOutPalette(768);
+}
+
+} // namespace Igor
diff --git a/engines/igor/parts/part_main.cpp b/engines/igor/parts/part_main.cpp
new file mode 100644
index 0000000000..0a6587f1e5
--- /dev/null
+++ b/engines/igor/parts/part_main.cpp
@@ -0,0 +1,974 @@
+/* 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/system.h"
+
+#include "igor/igor.h"
+
+namespace Igor {
+
+void IgorEngine::ADD_DIALOGUE_TEXT(int num, int count) {
+ assert(_dialogueTextsCount < MAX_DIALOGUE_TEXTS);
+ DialogueText *dt = &_dialogueTextsTable[_dialogueTextsCount];
+ dt->num = num;
+ dt->count = count;
+ ++_dialogueTextsCount;
+}
+
+void IgorEngine::SET_DIALOGUE_TEXT(int start, int count) {
+ _dialogueTextsStart = start - 1;
+ _dialogueTextsCount = count;
+}
+
+void IgorEngine::SET_EXEC_ACTION_FUNC(int i, ExecuteActionProc p) {
+ switch (i) {
+ case 0:
+ _executeMainAction = p;
+ break;
+ case 1:
+ _executeRoomAction = p;
+ break;
+ }
+}
+
+void IgorEngine::EXEC_MAIN_ACTION(int action) {
+ switch (action) {
+ case 0:
+ case 1:
+ break;
+ case 2: {
+ int num, rnd = getRandomNumber(100);
+ if (rnd < 34) {
+ num = 11;
+ } else if (rnd < 69) {
+ num = 12;
+ } else if (rnd < 94) {
+ num = 13;
+ } else {
+ num = 14;
+ }
+ ADD_DIALOGUE_TEXT(num, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ }
+ break;
+ case 3:
+ ADD_DIALOGUE_TEXT(15, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 4:
+ ADD_DIALOGUE_TEXT(10, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 5:
+ ADD_DIALOGUE_TEXT(9, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 6:
+ ADD_DIALOGUE_TEXT(8, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 7:
+ ADD_DIALOGUE_TEXT(6, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 8:
+ ADD_DIALOGUE_TEXT(7, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 9:
+ ADD_DIALOGUE_TEXT(16 + getRandomNumber(2), 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 10:
+ ADD_DIALOGUE_TEXT(18, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 11:
+ ADD_DIALOGUE_TEXT(19, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 12:
+ ADD_DIALOGUE_TEXT(20 + getRandomNumber(2), 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 13:
+ ADD_DIALOGUE_TEXT(22, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 14:
+ ADD_DIALOGUE_TEXT(23, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 15:
+ ADD_DIALOGUE_TEXT(24, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 16:
+ ADD_DIALOGUE_TEXT(25, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 17:
+ ADD_DIALOGUE_TEXT(26 + getRandomNumber(2), 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 18:
+ ADD_DIALOGUE_TEXT(28, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 19:
+ ADD_DIALOGUE_TEXT(4, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 20:
+ ADD_DIALOGUE_TEXT(5, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 21:
+ ADD_DIALOGUE_TEXT(1 + getRandomNumber(3), 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 22:
+ ADD_DIALOGUE_TEXT(51, 1);
+ ADD_DIALOGUE_TEXT(52, 1);
+ SET_DIALOGUE_TEXT(1, 2);
+ startIgorDialogue();
+ break;
+ case 23:
+ ADD_DIALOGUE_TEXT(53, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 24:
+ ADD_DIALOGUE_TEXT(54, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 25:
+ ADD_DIALOGUE_TEXT(55, 3);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 26:
+ ADD_DIALOGUE_TEXT(58, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 27:
+ ADD_DIALOGUE_TEXT(59, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 28:
+ ADD_DIALOGUE_TEXT(61, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 29:
+ ADD_DIALOGUE_TEXT(62, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 30:
+ ADD_DIALOGUE_TEXT(64, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 31:
+ ADD_DIALOGUE_TEXT(63, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 32:
+ ADD_DIALOGUE_TEXT(65, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 33:
+ ADD_DIALOGUE_TEXT(66, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 34:
+ ADD_DIALOGUE_TEXT(30, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 35:
+ ADD_DIALOGUE_TEXT(29, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 36:
+ ADD_DIALOGUE_TEXT(67, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 37:
+ ADD_DIALOGUE_TEXT(69, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 38:
+ EXEC_MAIN_ACTION_38();
+ break;
+ case 39:
+ ADD_DIALOGUE_TEXT(70, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 40:
+ ADD_DIALOGUE_TEXT(71, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 41:
+ ADD_DIALOGUE_TEXT(72, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 42:
+ ADD_DIALOGUE_TEXT(73, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 43:
+ EXEC_MAIN_ACTION_43();
+ break;
+ case 44:
+ ADD_DIALOGUE_TEXT(156, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 45:
+ ADD_DIALOGUE_TEXT(92, 1);
+ ADD_DIALOGUE_TEXT(93, 3);
+ SET_DIALOGUE_TEXT(1, 2);
+ startIgorDialogue();
+ break;
+ case 46:
+ if (_objectsState[3] == 0) {
+ ADD_DIALOGUE_TEXT(85, 1);
+ } else {
+ ADD_DIALOGUE_TEXT(86, 2);
+ }
+ SET_DIALOGUE_TEXT(1, 2);
+ startIgorDialogue();
+ break;
+ case 48:
+ ADD_DIALOGUE_TEXT(77 + _objectsState[0], 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ case 50:
+ if (_objectsState[1] == 0) {
+ ADD_DIALOGUE_TEXT(80, 1);
+ ADD_DIALOGUE_TEXT(81, 1);
+ SET_DIALOGUE_TEXT(1, 2);
+ startIgorDialogue();
+ } else {
+ ADD_DIALOGUE_TEXT(82, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ }
+ break;
+ case 51:
+ if (_objectsState[7] == 0) {
+ ADD_DIALOGUE_TEXT(157, 1);
+ } else {
+ ADD_DIALOGUE_TEXT(158, 1);
+ }
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 52:
+ ADD_DIALOGUE_TEXT(89, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 53:
+ ADD_DIALOGUE_TEXT(88, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 54:
+ EXEC_MAIN_ACTION_54();
+ break;
+ case 55:
+ ADD_DIALOGUE_TEXT(159, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 56:
+ ADD_DIALOGUE_TEXT(160, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 57:
+ ADD_DIALOGUE_TEXT(31, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 58:
+ ADD_DIALOGUE_TEXT(140, 1);
+ ADD_DIALOGUE_TEXT(141, 1);
+ ADD_DIALOGUE_TEXT(142, 1);
+ ADD_DIALOGUE_TEXT(143, 1);
+ SET_DIALOGUE_TEXT(1, 4);
+ startIgorDialogue();
+ _objectsState[4] = 2;
+ break;
+ case 59:
+ ADD_DIALOGUE_TEXT(97, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 60:
+ ADD_DIALOGUE_TEXT(161, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 61:
+ if (_inventoryInfo[51] != 0) {
+ ADD_DIALOGUE_TEXT(76, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ } else {
+ ADD_DIALOGUE_TEXT(74, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ addObjectToInventory(16, 51);
+ }
+ break;
+ case 62:
+ _inventoryImages[_inventoryInfo[52] - 1] = 0;
+ _inventoryInfo[52] = 0;
+ packInventory();
+ _inventoryImages[_inventoryInfo[59] - 1] = 0;
+ _inventoryInfo[59] = 0;
+ packInventory();
+ _objectsState[1] = 1;
+ UPDATE_OBJECT_STATE(2);
+ addObjectToInventory(24, 59);
+ ADD_DIALOGUE_TEXT(169, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 63:
+ ADD_DIALOGUE_TEXT(170, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ _inventoryImages[_inventoryInfo[68] - 1] = 0;
+ _inventoryInfo[68] = 0;
+ packInventory();
+ _inventoryImages[_inventoryInfo[69] - 1] = 0;
+ _inventoryInfo[69] = 0;
+ packInventory();
+ _objectsState[6] = 1;
+ UPDATE_OBJECT_STATE(7);
+ addObjectToInventory(34, 69);
+ break;
+ case 64:
+ if (_objectsState[6] == 0) {
+ ADD_DIALOGUE_TEXT(162, 1);
+ } else if (_objectsState[6] == 1) {
+ ADD_DIALOGUE_TEXT(163, 1);
+ } else if (_objectsState[6] == 2) {
+ ADD_DIALOGUE_TEXT(164, 1);
+ }
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 65:
+ ADD_DIALOGUE_TEXT(165, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 66:
+ ADD_DIALOGUE_TEXT(166, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 67:
+ ADD_DIALOGUE_TEXT(167, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 68:
+ ADD_DIALOGUE_TEXT(168, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ case 69:
+ ADD_DIALOGUE_TEXT(96, 1);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ break;
+ default:
+ warning("EXEC_MAIN_ACTION() Unhandled action %d", action);
+ break;
+ }
+}
+
+void IgorEngine::EXEC_MAIN_ACTION_38() {
+ memcpy(_paletteBuffer, _currentPalette, 624);
+ fadeOutPalette(624);
+ uint8 *tmp = (uint8 *)malloc(64000 + 768);
+ if (tmp) {
+ memcpy(tmp, _screenVGA, 64000);
+ memcpy(tmp + 64000, _paletteBuffer, 768);
+ }
+ loadData(IMG_NewsPaper, _screenVGA);
+ loadData(PAL_NewsPaper, _paletteBuffer);
+ fadeInPalette(624);
+// mov _dialogueColor+3, 0
+ WalkData *wd = &_walkData[_walkDataLastIndex - 1];
+ int _walkDataCurrentPosX2 = wd->x;
+ int _walkDataCurrentPosY2 = wd->y;
+ int _walkDataCurrentWScale = wd->scaleWidth;
+ wd->x = 80;
+ wd->y = 130;
+ wd->scaleWidth = 50;
+ ADD_DIALOGUE_TEXT(144, 1);
+ ADD_DIALOGUE_TEXT(145, 3);
+ ADD_DIALOGUE_TEXT(148, 2);
+ ADD_DIALOGUE_TEXT(150, 2);
+ SET_DIALOGUE_TEXT(1, 4);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ wd->x = 240;
+ wd->y = 130;
+ ADD_DIALOGUE_TEXT(152, 1);
+ ADD_DIALOGUE_TEXT(153, 3);
+ SET_DIALOGUE_TEXT(1, 2);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ wd->x = _walkDataCurrentPosX2;
+ wd->y = _walkDataCurrentPosY2;
+ wd->scaleWidth = _walkDataCurrentWScale;
+ fadeOutPalette(624);
+ if (tmp) {
+ memcpy(_screenVGA, tmp, 64000);
+ memcpy(_paletteBuffer, tmp + 64000, 768);
+ free(tmp);
+ }
+ fadeInPalette(624);
+ _objectsState[2] = 1;
+// mov _dialogueColor+3, 63
+}
+
+void IgorEngine::EXEC_MAIN_ACTION_43() {
+ memcpy(_paletteBuffer, _currentPalette, 624);
+ fadeOutPalette(624);
+ uint8 *tmp = (uint8 *)malloc(64000 + 768);
+ if (tmp) {
+ memcpy(tmp, _screenVGA, 64000);
+ memcpy(tmp + 64000, _paletteBuffer, 768);
+ }
+ loadData(IMG_PhotoHarrisonMargaret, _screenVGA);
+ loadData(PAL_PhotoHarrisonMargaret, _paletteBuffer);
+ fadeInPalette(624);
+// mov _dialogueColor+3, 0
+ WalkData *wd = &_walkData[_walkDataLastIndex - 1];
+ int _walkDataCurrentPosX2 = wd->x;
+ int _walkDataCurrentPosY2 = wd->y;
+ int _walkDataCurrentWScale = wd->scaleWidth;
+ wd->x = 160;
+ wd->y = 130;
+ wd->scaleWidth = 50;
+ ADD_DIALOGUE_TEXT(83, 2);
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ _currentAction.object1Num = 0;
+ wd->x = _walkDataCurrentPosX2;
+ wd->y = _walkDataCurrentPosY2;
+ wd->scaleWidth = _walkDataCurrentWScale;
+ fadeOutPalette(624);
+ if (tmp) {
+ memcpy(_screenVGA, tmp, 64000);
+ memcpy(_paletteBuffer, tmp + 64000, 768);
+ free(tmp);
+ }
+ fadeInPalette(624);
+// mov _dialogueColor+3, 63
+}
+
+void IgorEngine::EXEC_MAIN_ACTION_54() {
+ memcpy(_paletteBuffer, _currentPalette, 624);
+ fadeOutPalette(624);
+ uint8 *tmp = (uint8 *)malloc(64000 + 768);
+ if (tmp) {
+ memcpy(tmp, _screenVGA, 64000);
+ memcpy(tmp + 64000, _paletteBuffer, 768);
+ }
+ loadData(IMG_RomanNumbersPaper, _screenVGA);
+ loadData(PAL_RomanNumbersPaper, _paletteBuffer);
+ PART_UPDATE_FIGURES_ON_PAPER(0);
+ fadeInPalette(624);
+ WalkData *wd = &_walkData[_walkDataLastIndex - 1];
+ int _walkDataCurrentPosX2 = wd->x;
+ int _walkDataCurrentPosY2 = wd->y;
+ int _walkDataCurrentWScale = wd->scaleWidth;
+ wd->x = 160;
+ wd->y = 130;
+ wd->scaleWidth = 50;
+ if (_objectsState[2] == 0) {
+ ADD_DIALOGUE_TEXT(99, 1);
+ } else {
+ ADD_DIALOGUE_TEXT(100, 2);
+ }
+ SET_DIALOGUE_TEXT(1, 1);
+ startIgorDialogue();
+ waitForEndOfIgorDialogue();
+ wd->x = _walkDataCurrentPosX2;
+ wd->y = _walkDataCurrentPosY2;
+ wd->scaleWidth = _walkDataCurrentWScale;
+ fadeOutPalette(624);
+ if (tmp) {
+ memcpy(_screenVGA, tmp, 64000);
+ memcpy(_paletteBuffer, tmp + 64000, 768);
+ free(tmp);
+ }
+ fadeInPalette(624);
+}
+
+void IgorEngine::SET_PAL_208_96_1() {
+ memcpy(_paletteBuffer + 208 * 3, PAL_96_1, 96);
+}
+
+void IgorEngine::SET_PAL_240_48_1() {
+ memcpy(_paletteBuffer + 240 * 3, PAL_48_1, 48);
+}
+
+void IgorEngine::UPDATE_OBJECT_STATE(int num) {
+ if (num == 1 || num == 255) {
+ switch (_objectsState[0]) {
+ case 0:
+ memcpy(_globalObjectNames + 0x592 / 62, " bottle of whisky", 30);
+ break;
+ case 1:
+ memcpy(_globalObjectNames + 0x592 / 62, " empty bottle", 30);
+ break;
+ case 2:
+ memcpy(_globalObjectNames + 0x592 / 62, " bottle of water", 30);
+ break;
+ }
+ }
+ if (num == 2 || num == 255) {
+ switch (_objectsState[1]) {
+ case 0:
+ _inventoryImages[23] = 27;
+ memcpy(_globalObjectNames + 0x5D0 / 62, " lizard", 30);
+ break;
+ default:
+ _inventoryImages[23] = 35;
+ memcpy(_globalObjectNames + 0x5D0 / 62, " fat lizard", 30);
+ break;
+ }
+ }
+ if (num == 4 || num == 255) {
+ switch (_objectsState[3]) {
+ case 0:
+ memcpy(_globalObjectNames + 0x554 / 62, " Caroline%s folder", 30);
+ break;
+ case 1:
+ memcpy(_globalObjectNames + 0x554 / 62, " Philip%s folder", 30);
+ break;
+ }
+ }
+ if (num == 7 || num == 255) {
+ switch (_objectsState[6]) {
+ case 0:
+ _inventoryImages[33] = 21;
+ break;
+ case 1:
+ _inventoryImages[33] = 14;
+ break;
+ case 2:
+ _inventoryImages[33] = 7;
+ break;
+ }
+ }
+ if (num == 8 || num == 255) {
+ if (_objectsState[7] == 0) {
+ memcpy(_globalObjectNames + 0x60E / 62, " statuette", 30);
+ _inventoryImages[24] = 29;
+ } else {
+ memcpy(_globalObjectNames + 0x60E / 62, " reward", 30);
+ _inventoryImages[24] = 39;
+ }
+ }
+}
+
+void IgorEngine::PART_MEANWHILE() {
+ hideCursor();
+ memset(_currentPalette, 0, 768);
+ setPaletteRange(208, 255);
+ loadData(IMG_Meanwhile, _screenVGA);
+ _paletteBuffer[3] = 63;
+ _paletteBuffer[4] = 32;
+ _paletteBuffer[5] = 0;
+ _paletteBuffer[6] = 44;
+ _paletteBuffer[7] = 12;
+ _paletteBuffer[8] = 0;
+ fadeInPalette(9);
+ for (int i = 0; i <= 5 && !_inputVars[kInputEscape]; ++i) {
+ waitForTimer(250);
+ }
+ _inputVars[kInputEscape] = 0;
+ fadeOutPalette(9);
+}
+
+static int VAR_MARGARET_ROOM_ANIM_COUNTER;
+
+void IgorEngine::PART_MARGARET_ROOM_CUTSCENE_HELPER_1() {
+ const uint8 *src = _animFramesBuffer + READ_LE_UINT16(_animFramesBuffer + 0x2A63 + VAR_MARGARET_ROOM_ANIM_COUNTER * 2) - 1;
+ decodeAnimFrame(src, _screenVGA);
+}
+
+void IgorEngine::PART_MARGARET_ROOM_CUTSCENE_HELPER_2(int frame) {
+ const int offset = ((VAR_MARGARET_ROOM_ANIM_COUNTER - 1) * 5 + frame) * 2;
+ const uint8 *src = _animFramesBuffer + 0x2A75 + READ_LE_UINT16(_animFramesBuffer + offset + 0xD887) - 1;
+ decodeAnimFrame(src, _screenVGA);
+}
+
+void IgorEngine::PART_MARGARET_ROOM_CUTSCENE_UPDATE_DIALOGUE_MARGARET(int action) {
+ switch (action) {
+ case kUpdateDialogueAnimEndOfSentence:
+ PART_MARGARET_ROOM_CUTSCENE_HELPER_2(1);
+ break;
+ case kUpdateDialogueAnimMiddleOfSentence:
+ PART_MARGARET_ROOM_CUTSCENE_HELPER_2(getRandomNumber(5) + 1);
+ break;
+ }
+}
+
+void IgorEngine::PART_MARGARET_ROOM_CUTSCENE() {
+ _gameState.enableLight = 1;
+ VAR_MARGARET_ROOM_ANIM_COUNTER = _objectsState[110] + 1;
+ if (VAR_MARGARET_ROOM_ANIM_COUNTER == 9) {
+ VAR_MARGARET_ROOM_ANIM_COUNTER = 1;
+ }
+ loadRoomData(PAL_MargaretRoom, IMG_MargaretRoom, BOX_MargaretRoom, MSK_MargaretRoom, TXT_MargaretRoom);
+ static const int anm[] = { FRM_MargaretRoom1, FRM_MargaretRoom2, FRM_MargaretRoom3, FRM_MargaretRoom4, 0 };
+ loadAnimData(anm);
+ memcpy(_screenVGA, _screenLayer1, 46080);
+ _updateDialogue = &IgorEngine::PART_MARGARET_ROOM_CUTSCENE_UPDATE_DIALOGUE_MARGARET;
+ PART_MARGARET_ROOM_CUTSCENE_HELPER_1();
+ memset(_currentPalette, 0, 768);
+ fadeInPalette(768);
+ _gameState.igorMoving = false;
+ switch (VAR_MARGARET_ROOM_ANIM_COUNTER) {
+ case 1:
+ ADD_DIALOGUE_TEXT(223, 1);
+ ADD_DIALOGUE_TEXT(224, 1);
+ ADD_DIALOGUE_TEXT(225, 1);
+ break;
+ case 2:
+ ADD_DIALOGUE_TEXT(201, 1);
+ ADD_DIALOGUE_TEXT(202, 1);
+ ADD_DIALOGUE_TEXT(203, 1);
+ break;
+ case 3:
+ ADD_DIALOGUE_TEXT(204, 1);
+ ADD_DIALOGUE_TEXT(205, 1);
+ ADD_DIALOGUE_TEXT(206, 1);
+ break;
+ case 4:
+ ADD_DIALOGUE_TEXT(207, 1);
+ ADD_DIALOGUE_TEXT(208, 1);
+ ADD_DIALOGUE_TEXT(209, 1);
+ break;
+ case 5:
+ ADD_DIALOGUE_TEXT(210, 1);
+ ADD_DIALOGUE_TEXT(211, 1);
+ ADD_DIALOGUE_TEXT(212, 1);
+ break;
+ case 6:
+ ADD_DIALOGUE_TEXT(213, 2);
+ ADD_DIALOGUE_TEXT(215, 1);
+ ADD_DIALOGUE_TEXT(216, 1);
+ break;
+ case 7:
+ ADD_DIALOGUE_TEXT(217, 1);
+ ADD_DIALOGUE_TEXT(218, 1);
+ ADD_DIALOGUE_TEXT(219, 1);
+ break;
+ case 8:
+ ADD_DIALOGUE_TEXT(220, 1);
+ ADD_DIALOGUE_TEXT(221, 1);
+ ADD_DIALOGUE_TEXT(222, 1);
+ break;
+ }
+ SET_DIALOGUE_TEXT(1, 3);
+ startCutsceneDialogue(200, 73, 63, 32, 0);
+ waitForEndOfCutsceneDialogue(200, 73, 63, 32, 0);
+ waitForTimer(255);
+ _updateDialogue = 0;
+ ++_objectsState[110];
+ memcpy(_paletteBuffer, _currentPalette, 768);
+ fadeOutPalette(768);
+ memset(_screenVGA, 0, 46080);
+ if (_objectsState[110] < 9 && _currentPart != 331) {
+ setupDefaultPalette();
+ SET_PAL_240_48_1();
+ SET_PAL_208_96_1();
+ drawVerbsPanel();
+ drawInventory(_inventoryInfo[72], 0);
+ }
+}
+
+void IgorEngine::PART_UPDATE_FIGURES_ON_PAPER(int delay) {
+ uint8 *framesData = loadData(FRM_NumbersPaper1);
+ uint8 *framesOffsets = loadData(FRM_NumbersPaper2);
+ for (int i = 1; i <= 20; ++i) {
+ const uint8 *p = framesData + READ_LE_UINT16(framesOffsets + (i - 1) * 2) - 1;
+ decodeAnimFrame(p, _screenVGA, true);
+ waitForTimer(delay);
+ }
+ free(framesData);
+ free(framesOffsets);
+}
+
+void IgorEngine::PART_MAIN() {
+ SET_EXEC_ACTION_FUNC(0, &IgorEngine::EXEC_MAIN_ACTION);
+ memset(_objectsState, 0, 112);
+ _objectsState[21] = 1;
+ _objectsState[49] = 1;
+ memset(_inventoryInfo, 0, 36);
+ _inventoryInfo[0] = 1; // ordering
+ _inventoryInfo[1] = 2;
+ _inventoryInfo[2] = 4;
+ _inventoryInfo[36] = 1;
+ _inventoryInfo[37] = 2;
+ _inventoryInfo[39] = 3;
+ _inventoryInfo[72] = 1; // first object
+ _inventoryInfo[73] = 3; // last object
+ UPDATE_OBJECT_STATE(255);
+ if (_currentPart != kStartupPart) { // boot param
+ SET_PAL_208_96_1();
+ SET_PAL_240_48_1();
+ drawVerbsPanel();
+ drawInventory(1, 0);
+ }
+ do {
+ debug(kDebugGame, "PART_MAIN _currentPart %d", _currentPart);
+ switch (_currentPart) {
+ case 40:
+ PART_04();
+ break;
+ case 50:
+ case 51:
+ case 52:
+ PART_05();
+ break;
+ case 60:
+ case 61:
+ case 62:
+ PART_06();
+ break;
+ case 120:
+ case 121:
+ case 122:
+ PART_12();
+ break;
+ case 130:
+ case 131:
+ PART_13();
+ break;
+ case 140:
+ case 141:
+ case 142:
+ PART_14();
+ break;
+ case 150:
+ PART_15();
+ break;
+ case 160:
+ PART_16();
+ break;
+ case 170:
+ case 171:
+ PART_17();
+ break;
+ case 180:
+ case 181:
+ PART_18();
+ break;
+ case 190:
+ case 191:
+ PART_19();
+ break;
+ case 210:
+ case 211:
+ case 212:
+ PART_21();
+ break;
+ case 220:
+ case 221:
+ PART_22();
+ break;
+ case 230:
+ case 231:
+ case 232:
+ PART_23();
+ break;
+ case 240:
+ case 241:
+ case 242:
+ PART_24();
+ break;
+ case 250:
+ case 251:
+ case 252:
+ PART_25();
+ break;
+ case 260:
+ case 261:
+ PART_26();
+ break;
+ case 270:
+ case 271:
+ PART_27();
+ break;
+ case 280:
+ case 281:
+ PART_28();
+ break;
+ case 300:
+ case 301:
+ case 302:
+ case 303:
+ PART_30();
+ break;
+ case 310:
+ case 311:
+ case 312:
+ case 313:
+ PART_31();
+ break;
+ case 330:
+ case 331:
+ PART_33();
+ break;
+ case 360:
+ PART_36();
+ break;
+ case 370:
+ PART_37();
+ break;
+ case 750:
+ PART_75();
+ break;
+ case 850:
+ memset(_screenVGA, 0, 64000);
+ _screenVGAVOffset = 24;
+ _system->copyRectToScreen(_screenVGA, 320, 0, 0, 320, _screenVGAVOffset);
+ PART_85();
+ memset(_screenVGA + 46080, 0, 17920);
+ _nextTimer = _system->getMillis() + 1000 / 60;
+ for (int y = _screenVGAVOffset; y >= 0; --y) {
+ _system->copyRectToScreen(_screenVGA, 320, 0, y, 320, 145);
+ _system->updateScreen();
+ int diff = _nextTimer - _system->getMillis();
+ if (diff > 0) {
+ _system->delayMillis(diff);
+ }
+ _nextTimer = _system->getMillis() + 1000 / 60;
+ }
+ _screenVGAVOffset = 0;
+ _inputVars[kInputCursorXPos] = 160;
+ _inputVars[kInputCursorYPos] = 72;
+ _system->warpMouse(_inputVars[kInputCursorXPos], _inputVars[kInputCursorYPos]);
+ break;
+ case 900:
+ case 901:
+ case 902:
+ case 903:
+ case 904:
+ PART_90();
+ break;
+ default:
+ warning("PART_MAIN() Unhandled part %d", _currentPart);
+ _currentPart = 255;
+ break;
+ }
+ if (_currentPart >= 10) {
+ if (_currentPart <= 24 || _currentPart == 51) {
+ continue;
+ }
+ if (_currentPart == 60 || _currentPart == 102 || _currentPart == 110) {
+ continue;
+ }
+ }
+ if (_currentPart == 340 || _currentPart == 351 || _currentPart == 750) {
+ continue;
+ }
+ if (_currentPart == 122 || _currentPart == 255) {
+ continue;
+ }
+ if (_objectsState[110] < 1 || _objectsState[110] > 7) {
+ continue;
+ }
+ if (_gameState.nextMusicCounter != 5) {
+ ++_gameState.nextMusicCounter;
+ } else {
+ if (_gameState.musicNum != 11) {
+ _previousMusic = _gameState.musicNum;
+ playMusic(11);
+ }
+ PART_MEANWHILE();
+ PART_MARGARET_ROOM_CUTSCENE();
+ if (_previousMusic != 11) {
+ playMusic(_previousMusic);
+ }
+ _gameState.nextMusicCounter = 0;
+ }
+ } while (_currentPart != 255 && !_eventQuitGame);
+ for (_currentPart = 950; _currentPart <= 956 && !_eventQuitGame; ++_currentPart) {
+ PART_95();
+ }
+}
+
+} // namespace Igor
diff --git a/engines/igor/resource_ids.h b/engines/igor/resource_ids.h
new file mode 100644
index 0000000000..e684a50e62
--- /dev/null
+++ b/engines/igor/resource_ids.h
@@ -0,0 +1,333 @@
+#define FNT_Dialogue 1
+#define ANM_PhilipVodka 2
+#define AOF_PhilipVodka 3
+#define TXT_PhilipRoom 4
+#define IMG_PhilipRoom 5
+#define PAL_PhilipRoom 6
+#define MSK_PhilipRoom 7
+#define BOX_PhilipRoom 8
+#define DAT_PhysicsClassroom 9
+#define FRM_PhysicsClassroom1 10
+#define TXT_PhysicsClassroom 11
+#define IMG_PhysicsClassroom 12
+#define PAL_PhysicsClassroom 13
+#define MSK_PhysicsClassroom 14
+#define BOX_PhysicsClassroom 15
+#define DAT_ChemistryClassroom 16
+#define FRM_ChemistryClassroom1 17
+#define FRM_ChemistryClassroom2 18
+#define TXT_ChemistryClassroom 19
+#define IMG_ChemistryClassroom 20
+#define PAL_ChemistryClassroom 21
+#define MSK_ChemistryClassroom 22
+#define BOX_ChemistryClassroom 23
+#define DAT_CollegeStairsSecondFloor 24
+#define FRM_CollegeStairsSecondFloor1 25
+#define FRM_CollegeStairsSecondFloor2 26
+#define FRM_CollegeStairsSecondFloor3 27
+#define TXT_CollegeStairsSecondFloor 28
+#define IMG_CollegeStairsSecondFloor 29
+#define PAL_CollegeStairsSecondFloor 30
+#define MSK_CollegeStairsSecondFloor 31
+#define BOX_CollegeStairsSecondFloor 32
+#define DAT_CollegeStairsFirstFloor 33
+#define DLG_CollegeStairsFirstFloor 34
+#define FRM_CollegeStairsFirstFloor1 35
+#define FRM_CollegeStairsFirstFloor2 36
+#define TXT_CollegeStairsFirstFloor 37
+#define IMG_CollegeStairsFirstFloor 38
+#define PAL_CollegeStairsFirstFloor 39
+#define MSK_CollegeStairsFirstFloor 40
+#define BOX_CollegeStairsFirstFloor 41
+#define DAT_CollegeCorridorMissBarrymore 42
+#define FRM_CollegeCorridorMissBarrymore1 43
+#define FRM_CollegeCorridorMissBarrymore2 44
+#define FRM_CollegeCorridorMissBarrymore3 45
+#define TXT_CollegeCorridorMissBarrymore 46
+#define IMG_CollegeCorridorMissBarrymore 47
+#define PAL_CollegeCorridorMissBarrymore 48
+#define MSK_CollegeCorridorMissBarrymore 49
+#define BOX_CollegeCorridorMissBarrymore 50
+#define DAT_CollegeCorridorAnnouncementBoard 51
+#define FRM_CollegeCorridorAnnouncementBoard1 52
+#define FRM_CollegeCorridorAnnouncementBoard2 53
+#define TXT_CollegeCorridorAnnouncementBoard 54
+#define IMG_CollegeCorridorAnnouncementBoard 55
+#define PAL_CollegeCorridorAnnouncementBoard 56
+#define MSK_CollegeCorridorAnnouncementBoard 57
+#define BOX_CollegeCorridorAnnouncementBoard 58
+#define DAT_CollegeCorridorSharonMichael 59
+#define FRM_CollegeCorridorSharonMichael1 60
+#define FRM_CollegeCorridorSharonMichael2 61
+#define FRM_CollegeCorridorSharonMichael3 62
+#define FRM_CollegeCorridorSharonMichael4 63
+#define TXT_CollegeCorridorSharonMichael 64
+#define IMG_CollegeCorridorSharonMichael 65
+#define PAL_CollegeCorridorSharonMichael 66
+#define MSK_CollegeCorridorSharonMichael 67
+#define BOX_CollegeCorridorSharonMichael 68
+#define DAT_CollegeCorridorCaroline 69
+#define FRM_CollegeCorridorCaroline1 70
+#define FRM_CollegeCorridorCaroline3 71
+#define FRM_CollegeCorridorCaroline2 72
+#define TXT_CollegeCorridorCaroline 73
+#define IMG_CollegeCorridorCaroline 74
+#define PAL_CollegeCorridorCaroline 75
+#define MSK_CollegeCorridorCaroline 76
+#define BOX_CollegeCorridorCaroline 77
+#define DAT_CollegeCorridorLucas 78
+#define FRM_CollegeCorridorLucas1 79
+#define FRM_CollegeCorridorLucas2 80
+#define FRM_CollegeCorridorLucas3 81
+#define FRM_CollegeCorridorLucas4 82
+#define TXT_CollegeCorridorLucas 83
+#define IMG_CollegeCorridorLucas 84
+#define PAL_CollegeCorridorLucas 85
+#define MSK_CollegeCorridorLucas 86
+#define BOX_CollegeCorridorLucas 87
+#define DAT_CollegeCorridorMargaret 88
+#define DLG_CollegeCorridorMargaret 89
+#define FRM_CollegeCorridorMargaret1 90
+#define FRM_CollegeCorridorMargaret2 91
+#define FRM_CollegeCorridorMargaret3 92
+#define FRM_CollegeCorridorMargaret4 93
+#define TXT_CollegeCorridorMargaret 94
+#define IMG_CollegeCorridorMargaret 95
+#define PAL_CollegeCorridorMargaret 96
+#define MSK_CollegeCorridorMargaret 97
+#define BOX_CollegeCorridorMargaret 98
+#define DAT_CollegeLockers 99
+#define FRM_CollegeLockers1 100
+#define FRM_CollegeLockers2 101
+#define FRM_CollegeLockers3 102
+#define TXT_CollegeLockers 103
+#define IMG_CollegeLockers 104
+#define PAL_CollegeLockers 105
+#define MSK_CollegeLockers 106
+#define BOX_CollegeLockers 107
+#define DAT_MenToilets 108
+#define DAT_WomenToilets 109
+#define FRM_WomenToilets1 110
+#define FRM_WomenToilets2 111
+#define FRM_WomenToilets3 112
+#define FRM_WomenToilets4 113
+#define FRM_WomenToilets5 114
+#define TXT_WomenToilets 115
+#define IMG_WomenToilets 116
+#define PAL_WomenToilets 117
+#define MSK_WomenToilets 118
+#define BOX_WomenToilets 119
+#define FRM_MenToilets1 120
+#define FRM_MenToilets2 121
+#define TXT_MenToilets 122
+#define IMG_MenToilets 123
+#define PAL_MenToilets 124
+#define MSK_MenToilets 125
+#define BOX_MenToilets 126
+#define DAT_OutsideCollege 127
+#define DLG_OutsideCollege 128
+#define FRM_OutsideCollege1 129
+#define FRM_OutsideCollege2 130
+#define FRM_OutsideCollege3 131
+#define FRM_OutsideCollege4 132
+#define FRM_OutsideCollege5 133
+#define TXT_OutsideCollege 134
+#define IMG_OutsideCollege 135
+#define PAL_OutsideCollege 136
+#define MSK_OutsideCollege 137
+#define BOX_OutsideCollege 138
+#define DAT_Laboratory 139
+#define FRM_Laboratory1 140
+#define FRM_Laboratory2 141
+#define FRM_Laboratory3 142
+#define TXT_Laboratory 143
+#define IMG_Laboratory 144
+#define PAL_Laboratory 145
+#define MSK_Laboratory 146
+#define BOX_Laboratory 147
+#define FRM_MargaretRoom1 148
+#define FRM_MargaretRoom2 149
+#define FRM_MargaretRoom3 150
+#define FRM_MargaretRoom4 151
+#define TXT_MargaretRoom 152
+#define IMG_MargaretRoom 153
+#define PAL_MargaretRoom 154
+#define MSK_MargaretRoom 155
+#define BOX_MargaretRoom 156
+#define DAT_Map 157
+#define TXT_Map 158
+#define IMG_Map 159
+#define PAL_Map 160
+#define MSK_Map 161
+#define BOX_Map 162
+#define DAT_TobiasOffice 163
+#define DLG_TobiasOffice 164
+#define ANM_TobiasOffice1 165
+#define AOF_TobiasOffice1 166
+#define ANM_TobiasOffice2 167
+#define AOF_TobiasOffice2 168
+#define TXT_TobiasOffice 169
+#define IMG_TobiasOffice 170
+#define PAL_TobiasOffice 171
+#define MSK_TobiasOffice 172
+#define BOX_TobiasOffice 173
+#define DAT_BellChurch 174
+#define FRM_BellChurch1 175
+#define FRM_BellChurch2 176
+#define TXT_BellChurch 177
+#define IMG_BellChurch 178
+#define PAL_BellChurch 179
+#define MSK_BellChurch 180
+#define BOX_BellChurch 181
+#define DAT_ChurchPuzzle 182
+#define IMG_ChurchMosaic 183
+#define PAL_ChurchMosaic 184
+#define MSK_ChurchMosaic 185
+#define FRM_ChurchPuzzle1 186
+#define FRM_ChurchPuzzle2 187
+#define FRM_ChurchPuzzle3 188
+#define FRM_ChurchPuzzle13 189
+#define FRM_ChurchPuzzle4 190
+#define FRM_ChurchPuzzle5 191
+#define FRM_ChurchPuzzle6 192
+#define FRM_ChurchPuzzle7 193
+#define FRM_ChurchPuzzle8 194
+#define FRM_ChurchPuzzle9 195
+#define FRM_ChurchPuzzle10 196
+#define FRM_ChurchPuzzle11 197
+#define FRM_ChurchPuzzle12 198
+#define FRM_ChurchPuzzle14 199
+#define TXT_ChurchPuzzle 200
+#define IMG_ChurchPuzzle 201
+#define PAL_ChurchPuzzle 202
+#define MSK_ChurchPuzzle 203
+#define BOX_ChurchPuzzle 204
+#define DAT_InsideChurch 205
+#define TXT_InsideChurch 206
+#define IMG_InsideChurch 207
+#define PAL_InsideChurch 208
+#define MSK_InsideChurch 209
+#define BOX_InsideChurch 210
+#define DAT_OutsideChurch 211
+#define DLG_OutsideChurch 212
+#define FRM_OutsideChurch8 213
+#define FRM_OutsideChurch9 214
+#define FRM_OutsideChurch1 215
+#define FRM_OutsideChurch2 216
+#define FRM_OutsideChurch3 217
+#define FRM_OutsideChurch4 218
+#define FRM_OutsideChurch5 219
+#define FRM_OutsideChurch6 220
+#define FRM_OutsideChurch7 221
+#define FRM_OutsideChurch10 222
+#define FRM_OutsideChurch11 223
+#define FRM_OutsideChurch12 224
+#define TXT_OutsideChurch 225
+#define IMG_OutsideChurch 226
+#define PAL_OutsideChurch 227
+#define MSK_OutsideChurch 228
+#define BOX_OutsideChurch 229
+#define DAT_SpringBridge 230
+#define WLK_Bridge1 231
+#define WLK_Bridge2 232
+#define DLG_SpringPhotographer 233
+#define DAT_SpringRock 234
+#define WLK_Bridge3 235
+#define WLK_Bridge4 236
+#define FRM_SpringRock1 237
+#define FRM_SpringRock2 238
+#define FRM_SpringRock3 239
+#define FRM_SpringRock4 240
+#define FRM_SpringRock5 241
+#define FRM_SpringRock6 242
+#define FRM_SpringBridge1 243
+#define FRM_SpringBridge2 244
+#define TXT_SpringBridge 245
+#define IMG_SpringBridge 246
+#define PAL_SpringBridge 247
+#define MSK_SpringBridge 248
+#define BOX_SpringBridge 249
+#define DAT_Library 250
+#define DLG_Library 251
+#define FRM_Library1 252
+#define FRM_Library2 253
+#define FRM_Library3 254
+#define FRM_Library4 255
+#define FRM_Library5 256
+#define TXT_Library2 257
+#define TXT_Library 258
+#define IMG_Library 259
+#define PAL_Library 260
+#define MSK_Library 261
+#define BOX_Library 262
+#define ANM_PhilipLauraIntro 263
+#define AOF_PhilipLauraIntro 264
+#define ANM_LauraIntro 265
+#define AOF_LauraIntro 266
+#define TXT_SpringBridgeIntro 267
+#define IMG_SpringBridgeIntro 268
+#define PAL_SpringBridgeIntro 269
+#define TXT_SpringRock 270
+#define IMG_SpringRock 271
+#define PAL_SpringRock 272
+#define MSK_SpringRock 273
+#define BOX_SpringRock 274
+#define PAL_Shareware7 275
+#define IMG_Shareware7 276
+#define PAL_Shareware6 277
+#define IMG_Shareware6 278
+#define PAL_Shareware5 279
+#define IMG_Shareware5 280
+#define PAL_Shareware4 281
+#define IMG_Shareware4 282
+#define PAL_Shareware3 283
+#define IMG_Shareware3 284
+#define PAL_Shareware2 285
+#define IMG_Shareware2 286
+#define PAL_Shareware1 287
+#define IMG_Shareware1 288
+#define PAL_TitleScreen 289
+#define IMG_TitleScreen 290
+#define PAL_PenduloStudios 291
+#define IMG_PenduloStudios 292
+#define PAL_GraphicAdventure 293
+#define IMG_GraphicAdventure 294
+#define PAL_Presents 295
+#define IMG_Presents 296
+#define PAL_OptikSoftware 297
+#define IMG_OptikSoftware 298
+#define IMG_Meanwhile 299
+#define IMG_OptionsButton 300
+#define IMG_OptionsMenu 301
+#define CMF_8 302
+#define CMF_9 303
+#define CMF_10 304
+#define CMF_11 305
+#define CMF_12 306
+#define CMF_2_1 307
+#define CMF_2_2 308
+#define CMF_2_3 309
+#define CMF_2_4 310
+#define CMF_3 311
+#define CMF_4 312
+#define CMF_7_1 313
+#define CMF_7_2 314
+#define CMF_7_3 315
+#define CMF_7_4 316
+#define FRM_IgorDirBack 317
+#define FRM_IgorDirRight 318
+#define FRM_IgorDirFront 319
+#define FRM_IgorDirLeft 320
+#define FRM_IgorHead 321
+#define IMG_VerbsPanel 322
+#define TXT_MainTable 323
+#define IMG_RomanNumbersPaper 324
+#define PAL_RomanNumbersPaper 325
+#define FRM_NumbersPaper1 326
+#define FRM_NumbersPaper2 327
+#define IMG_NewsPaper 328
+#define PAL_NewsPaper 329
+#define IMG_PhotoHarrisonMargaret 330
+#define PAL_PhotoHarrisonMargaret 331
+#define IMG_InventoryPanel 332
+#define IMG_Objects 333
diff --git a/engines/igor/resource_tbl.h b/engines/igor/resource_tbl.h
new file mode 100644
index 0000000000..b94036c9c8
--- /dev/null
+++ b/engines/igor/resource_tbl.h
@@ -0,0 +1,333 @@
+{ FNT_Dialogue, 0xb09, 9306 },
+{ ANM_PhilipVodka, 0x300d, 24175 },
+{ AOF_PhilipVodka, 0x8e7c, 80 },
+{ TXT_PhilipRoom, 0x9580, 1164 },
+{ IMG_PhilipRoom, 0x9a0c, 46080 },
+{ PAL_PhilipRoom, 0x14e0c, 768 },
+{ MSK_PhilipRoom, 0x1510c, 3 },
+{ BOX_PhilipRoom, 0x1510f, 1280 },
+{ DAT_PhysicsClassroom, 0x18d44, 6017 },
+{ FRM_PhysicsClassroom1, 0x1a70d, 3100 },
+{ TXT_PhysicsClassroom, 0x1ba08, 1145 },
+{ IMG_PhysicsClassroom, 0x1be81, 46080 },
+{ PAL_PhysicsClassroom, 0x27281, 624 },
+{ MSK_PhysicsClassroom, 0x274f1, 1557 },
+{ BOX_PhysicsClassroom, 0x27b06, 1280 },
+{ DAT_ChemistryClassroom, 0x2b988, 6345 },
+{ FRM_ChemistryClassroom1, 0x2d4e1, 14 },
+{ FRM_ChemistryClassroom2, 0x2d4ef, 3332 },
+{ TXT_ChemistryClassroom, 0x2e8d6, 1226 },
+{ IMG_ChemistryClassroom, 0x2eda0, 46080 },
+{ PAL_ChemistryClassroom, 0x3a1a0, 624 },
+{ MSK_ChemistryClassroom, 0x3a410, 1980 },
+{ BOX_ChemistryClassroom, 0x3abcc, 1280 },
+{ DAT_CollegeStairsSecondFloor, 0x3f4bf, 6393 },
+{ FRM_CollegeStairsSecondFloor1, 0x410b8, 2756 },
+{ FRM_CollegeStairsSecondFloor2, 0x41b7c, 11136 },
+{ FRM_CollegeStairsSecondFloor3, 0x446fc, 6665 },
+{ TXT_CollegeStairsSecondFloor, 0x467ff, 1559 },
+{ IMG_CollegeStairsSecondFloor, 0x46e16, 46080 },
+{ PAL_CollegeStairsSecondFloor, 0x52216, 624 },
+{ MSK_CollegeStairsSecondFloor, 0x52486, 4128 },
+{ BOX_CollegeStairsSecondFloor, 0x534a6, 1280 },
+{ DAT_CollegeStairsFirstFloor, 0x579a5, 6017 },
+{ DLG_CollegeStairsFirstFloor, 0x5a3e8, 2713 },
+{ FRM_CollegeStairsFirstFloor1, 0x5af95, 48790 },
+{ FRM_CollegeStairsFirstFloor2, 0x66e2b, 140 },
+{ TXT_CollegeStairsFirstFloor, 0x675ad, 1228 },
+{ IMG_CollegeStairsFirstFloor, 0x67a79, 46080 },
+{ PAL_CollegeStairsFirstFloor, 0x72e79, 624 },
+{ MSK_CollegeStairsFirstFloor, 0x730e9, 2934 },
+{ BOX_CollegeStairsFirstFloor, 0x73c5f, 1280 },
+{ DAT_CollegeCorridorMissBarrymore, 0x77fa3, 6137 },
+{ FRM_CollegeCorridorMissBarrymore1, 0x79a88, 3250 },
+{ FRM_CollegeCorridorMissBarrymore2, 0x7a73a, 5280 },
+{ FRM_CollegeCorridorMissBarrymore3, 0x7bbda, 10824 },
+{ TXT_CollegeCorridorMissBarrymore, 0x7ed09, 1412 },
+{ IMG_CollegeCorridorMissBarrymore, 0x7f28d, 46080 },
+{ PAL_CollegeCorridorMissBarrymore, 0x8a68d, 624 },
+{ MSK_CollegeCorridorMissBarrymore, 0x8a8fd, 2484 },
+{ BOX_CollegeCorridorMissBarrymore, 0x8b2b1, 1280 },
+{ DAT_CollegeCorridorAnnouncementBoard, 0x8f34f, 5973 },
+{ FRM_CollegeCorridorAnnouncementBoard1, 0x90d44, 2392 },
+{ FRM_CollegeCorridorAnnouncementBoard2, 0x9169c, 6944 },
+{ TXT_CollegeCorridorAnnouncementBoard, 0x9389f, 1238 },
+{ IMG_CollegeCorridorAnnouncementBoard, 0x93d75, 46080 },
+{ PAL_CollegeCorridorAnnouncementBoard, 0x9f175, 624 },
+{ MSK_CollegeCorridorAnnouncementBoard, 0x9f3e5, 3117 },
+{ BOX_CollegeCorridorAnnouncementBoard, 0xa0012, 1280 },
+{ DAT_CollegeCorridorSharonMichael, 0xa3544, 5993 },
+{ FRM_CollegeCorridorSharonMichael1, 0xa4f4d, 3630 },
+{ FRM_CollegeCorridorSharonMichael2, 0xa5d7b, 7752 },
+{ FRM_CollegeCorridorSharonMichael3, 0xa7bc3, 5676 },
+{ FRM_CollegeCorridorSharonMichael4, 0xa91ef, 6762 },
+{ TXT_CollegeCorridorSharonMichael, 0xab344, 1387 },
+{ IMG_CollegeCorridorSharonMichael, 0xab8af, 46080 },
+{ PAL_CollegeCorridorSharonMichael, 0xb6caf, 624 },
+{ MSK_CollegeCorridorSharonMichael, 0xb6f1f, 3144 },
+{ BOX_CollegeCorridorSharonMichael, 0xb7b67, 1280 },
+{ DAT_CollegeCorridorCaroline, 0xbc49a, 6509 },
+{ FRM_CollegeCorridorCaroline1, 0xbe139, 25080 },
+{ FRM_CollegeCorridorCaroline3, 0xc4331, 7595 },
+{ FRM_CollegeCorridorCaroline2, 0xc60dc, 270 },
+{ TXT_CollegeCorridorCaroline, 0xc68e4, 2037 },
+{ IMG_CollegeCorridorCaroline, 0xc70d9, 46080 },
+{ PAL_CollegeCorridorCaroline, 0xd24d9, 624 },
+{ MSK_CollegeCorridorCaroline, 0xd2749, 2151 },
+{ BOX_CollegeCorridorCaroline, 0xd2fb0, 1280 },
+{ DAT_CollegeCorridorLucas, 0xd6381, 6109 },
+{ FRM_CollegeCorridorLucas1, 0xd7df4, 2592 },
+{ FRM_CollegeCorridorLucas2, 0xd8814, 1225 },
+{ FRM_CollegeCorridorLucas3, 0xd8cdd, 6480 },
+{ FRM_CollegeCorridorLucas4, 0xda62d, 1140 },
+{ TXT_CollegeCorridorLucas, 0xdb18c, 1387 },
+{ IMG_CollegeCorridorLucas, 0xdb6f7, 46080 },
+{ PAL_CollegeCorridorLucas, 0xe6af7, 624 },
+{ MSK_CollegeCorridorLucas, 0xe6d67, 3297 },
+{ BOX_CollegeCorridorLucas, 0xe7a48, 1280 },
+{ DAT_CollegeCorridorMargaret, 0xeb74f, 6273 },
+{ DLG_CollegeCorridorMargaret, 0xee325, 6860 },
+{ FRM_CollegeCorridorMargaret1, 0xeff79, 5346 },
+{ FRM_CollegeCorridorMargaret2, 0xf145b, 44247 },
+{ FRM_CollegeCorridorMargaret3, 0xfc132, 7800 },
+{ FRM_CollegeCorridorMargaret4, 0xfdfaa, 3564 },
+{ TXT_CollegeCorridorMargaret, 0xff494, 1642 },
+{ IMG_CollegeCorridorMargaret, 0xffafe, 46080 },
+{ PAL_CollegeCorridorMargaret, 0x10aefe, 624 },
+{ MSK_CollegeCorridorMargaret, 0x10b16e, 3690 },
+{ BOX_CollegeCorridorMargaret, 0x10bfd8, 1280 },
+{ DAT_CollegeLockers, 0x10f230, 6437 },
+{ FRM_CollegeLockers1, 0x110dcb, 2496 },
+{ FRM_CollegeLockers2, 0x11178b, 4704 },
+{ FRM_CollegeLockers3, 0x1129eb, 1260 },
+{ TXT_CollegeLockers, 0x1135be, 1812 },
+{ IMG_CollegeLockers, 0x113cd2, 46080 },
+{ PAL_CollegeLockers, 0x11f0d2, 624 },
+{ MSK_CollegeLockers, 0x11f342, 2235 },
+{ BOX_CollegeLockers, 0x11fbfd, 1280 },
+{ DAT_MenToilets, 0x123cd7, 6465 },
+{ DAT_WomenToilets, 0x129cd1, 6385 },
+{ FRM_WomenToilets1, 0x12b96a, 854 },
+{ FRM_WomenToilets2, 0x12bcc0, 12 },
+{ FRM_WomenToilets3, 0x12bccc, 2744 },
+{ FRM_WomenToilets4, 0x12c784, 12855 },
+{ FRM_WomenToilets5, 0x12f9bb, 102 },
+{ TXT_WomenToilets, 0x130110, 1637 },
+{ IMG_WomenToilets, 0x130775, 46080 },
+{ PAL_WomenToilets, 0x13bb75, 624 },
+{ MSK_WomenToilets, 0x13bde5, 2022 },
+{ BOX_WomenToilets, 0x13c5cb, 1280 },
+{ FRM_MenToilets1, 0x13cb79, 3038 },
+{ FRM_MenToilets2, 0x13d757, 1624 },
+{ TXT_MenToilets, 0x13e492, 1322 },
+{ IMG_MenToilets, 0x13e9bc, 46080 },
+{ PAL_MenToilets, 0x149dbc, 624 },
+{ MSK_MenToilets, 0x14a02c, 1980 },
+{ BOX_MenToilets, 0x14a7e8, 1280 },
+{ DAT_OutsideCollege, 0x14fe08, 6777 },
+{ DLG_OutsideCollege, 0x152677, 953 },
+{ FRM_OutsideCollege1, 0x152bb8, 2156 },
+{ FRM_OutsideCollege2, 0x153424, 4347 },
+{ FRM_OutsideCollege3, 0x15451f, 693 },
+{ FRM_OutsideCollege4, 0x1547d4, 594 },
+{ FRM_OutsideCollege5, 0x154a26, 10080 },
+{ TXT_OutsideCollege, 0x157875, 1741 },
+{ IMG_OutsideCollege, 0x157f42, 46080 },
+{ PAL_OutsideCollege, 0x163342, 624 },
+{ MSK_OutsideCollege, 0x1635b2, 4974 },
+{ BOX_OutsideCollege, 0x164920, 1280 },
+{ DAT_Laboratory, 0x168d8d, 5645 },
+{ FRM_Laboratory1, 0x16a6a2, 2254 },
+{ FRM_Laboratory2, 0x16af70, 26218 },
+{ FRM_Laboratory3, 0x1715da, 128 },
+{ TXT_Laboratory, 0x171d41, 1527 },
+{ IMG_Laboratory, 0x172338, 46080 },
+{ PAL_Laboratory, 0x17d738, 624 },
+{ MSK_Laboratory, 0x17d9a8, 2130 },
+{ BOX_Laboratory, 0x17e1fa, 1280 },
+{ FRM_MargaretRoom1, 0x181864, 10853 },
+{ FRM_MargaretRoom2, 0x1842c9, 16 },
+{ FRM_MargaretRoom3, 0x1842d9, 44564 },
+{ FRM_MargaretRoom4, 0x18f0ed, 80 },
+{ TXT_MargaretRoom, 0x18f7f9, 1707 },
+{ IMG_MargaretRoom, 0x18fea4, 46080 },
+{ PAL_MargaretRoom, 0x19b2a4, 768 },
+{ MSK_MargaretRoom, 0x19b5a4, 3 },
+{ BOX_MargaretRoom, 0x19b5a7, 1280 },
+{ DAT_Map, 0x19e0b8, 6273 },
+{ TXT_Map, 0x1a0184, 1023 },
+{ IMG_Map, 0x1a0583, 46080 },
+{ PAL_Map, 0x1ab983, 624 },
+{ MSK_Map, 0x1abbf3, 1809 },
+{ BOX_Map, 0x1ac304, 1280 },
+{ DAT_TobiasOffice, 0x1b0072, 5945 },
+{ DLG_TobiasOffice, 0x1b2ab1, 10590 },
+{ ANM_TobiasOffice1, 0x1b5595, 2392 },
+{ AOF_TobiasOffice1, 0x1b5eed, 910 },
+{ ANM_TobiasOffice2, 0x1b627b, 16992 },
+{ AOF_TobiasOffice2, 0x1ba4db, 6678 },
+{ TXT_TobiasOffice, 0x1bc5dc, 2086 },
+{ IMG_TobiasOffice, 0x1bce02, 46080 },
+{ PAL_TobiasOffice, 0x1c8202, 624 },
+{ MSK_TobiasOffice, 0x1c8472, 1455 },
+{ BOX_TobiasOffice, 0x1c8a21, 1280 },
+{ DAT_BellChurch, 0x1cb75d, 5617 },
+{ FRM_BellChurch1, 0x1ccf40, 42240 },
+{ FRM_BellChurch2, 0x1d6f40, 2100 },
+{ TXT_BellChurch, 0x1d7e57, 1158 },
+{ IMG_BellChurch, 0x1d82dd, 46080 },
+{ PAL_BellChurch, 0x1e36dd, 624 },
+{ MSK_BellChurch, 0x1e394d, 861 },
+{ BOX_BellChurch, 0x1e3caa, 1280 },
+{ DAT_ChurchPuzzle, 0x1e8cb7, 6137 },
+{ IMG_ChurchMosaic, 0x1eb513, 46080 },
+{ PAL_ChurchMosaic, 0x1f6913, 720 },
+{ MSK_ChurchMosaic, 0x1f6be3, 2445 },
+{ FRM_ChurchPuzzle1, 0x1f7862, 980 },
+{ FRM_ChurchPuzzle2, 0x1f7c36, 945 },
+{ FRM_ChurchPuzzle3, 0x1f7fe7, 1794 },
+{ FRM_ChurchPuzzle13, 0x1f86e9, 2240 },
+{ FRM_ChurchPuzzle4, 0x1f8fa9, 2106 },
+{ FRM_ChurchPuzzle5, 0x1f97e3, 1260 },
+{ FRM_ChurchPuzzle6, 0x1f9ccf, 1036 },
+{ FRM_ChurchPuzzle7, 0x1fa0db, 1053 },
+{ FRM_ChurchPuzzle8, 0x1fa4f8, 6 },
+{ FRM_ChurchPuzzle9, 0x1fa4fe, 26980 },
+{ FRM_ChurchPuzzle10, 0x200e62, 120 },
+{ FRM_ChurchPuzzle11, 0x200eda, 11607 },
+{ FRM_ChurchPuzzle12, 0x203c31, 20 },
+{ FRM_ChurchPuzzle14, 0x203c45, 2904 },
+{ TXT_ChurchPuzzle, 0x204eb0, 1587 },
+{ IMG_ChurchPuzzle, 0x2054e3, 46080 },
+{ PAL_ChurchPuzzle, 0x2108e3, 624 },
+{ MSK_ChurchPuzzle, 0x210b53, 1992 },
+{ BOX_ChurchPuzzle, 0x21131b, 1280 },
+{ DAT_InsideChurch, 0x2151fd, 5973 },
+{ TXT_InsideChurch, 0x217231, 1070 },
+{ IMG_InsideChurch, 0x21765f, 46080 },
+{ PAL_InsideChurch, 0x222a5f, 624 },
+{ MSK_InsideChurch, 0x222ccf, 2352 },
+{ BOX_InsideChurch, 0x2235ff, 1280 },
+{ DAT_OutsideChurch, 0x228b56, 6017 },
+{ DLG_OutsideChurch, 0x22b768, 5130 },
+{ FRM_OutsideChurch8, 0x22ceb2, 27365 },
+{ FRM_OutsideChurch9, 0x233997, 58 },
+{ FRM_OutsideChurch1, 0x2339d1, 1869 },
+{ FRM_OutsideChurch2, 0x23411e, 20 },
+{ FRM_OutsideChurch3, 0x234132, 2472 },
+{ FRM_OutsideChurch4, 0x234ada, 16 },
+{ FRM_OutsideChurch5, 0x234aea, 5147 },
+{ FRM_OutsideChurch6, 0x235f05, 14 },
+{ FRM_OutsideChurch7, 0x235f13, 5145 },
+{ FRM_OutsideChurch10, 0x23732c, 6805 },
+{ FRM_OutsideChurch11, 0x238dc1, 14 },
+{ FRM_OutsideChurch12, 0x238dcf, 5145 },
+{ TXT_OutsideChurch, 0x23a8bc, 1427 },
+{ IMG_OutsideChurch, 0x23ae4f, 46080 },
+{ PAL_OutsideChurch, 0x24624f, 624 },
+{ MSK_OutsideChurch, 0x2464bf, 3264 },
+{ BOX_OutsideChurch, 0x24717f, 1280 },
+{ DAT_SpringBridge, 0x24bdb6, 6017 },
+{ WLK_Bridge1, 0x24d537, 134 },
+{ WLK_Bridge2, 0x24d5bd, 2546 },
+{ DLG_SpringPhotographer, 0x24f896, 15460 },
+{ DAT_SpringRock, 0x257596, 6195 },
+{ WLK_Bridge3, 0x258dc9, 134 },
+{ WLK_Bridge4, 0x258e4f, 2546 },
+{ FRM_SpringRock1, 0x259bc1, 84 },
+{ FRM_SpringRock2, 0x259c15, 759 },
+{ FRM_SpringRock3, 0x259f0c, 5145 },
+{ FRM_SpringRock4, 0x25b325, 4508 },
+{ FRM_SpringRock5, 0x25c4c1, 13364 },
+{ FRM_SpringRock6, 0x25f8f5, 54 },
+{ FRM_SpringBridge1, 0x25f9b9, 24 },
+{ FRM_SpringBridge2, 0x25f9d1, 4410 },
+{ TXT_SpringBridge, 0x2611ee, 1071 },
+{ IMG_SpringBridge, 0x26161d, 46080 },
+{ PAL_SpringBridge, 0x26ca1d, 720 },
+{ MSK_SpringBridge, 0x26cced, 3936 },
+{ BOX_SpringBridge, 0x26dc4d, 1280 },
+{ DAT_Library, 0x272a7f, 7325 },
+{ DLG_Library, 0x275c55, 3573 },
+{ FRM_Library1, 0x276c08, 2254 },
+{ FRM_Library2, 0x2774d6, 18823 },
+{ FRM_Library3, 0x27be5d, 50 },
+{ FRM_Library4, 0x27be8f, 1440 },
+{ FRM_Library5, 0x27c42f, 14616 },
+{ TXT_Library2, 0x27ffad, 237 },
+{ TXT_Library, 0x280794, 2024 },
+{ IMG_Library, 0x280f7c, 46080 },
+{ PAL_Library, 0x28c37c, 624 },
+{ MSK_Library, 0x28c5ec, 2217 },
+{ BOX_Library, 0x28ce95, 1280 },
+{ ANM_PhilipLauraIntro, 0x28e5ac, 29824 },
+{ AOF_PhilipLauraIntro, 0x295a2c, 74 },
+{ ANM_LauraIntro, 0x295a76, 12793 },
+{ AOF_LauraIntro, 0x298c6f, 48 },
+{ TXT_SpringBridgeIntro, 0x299249, 1846 },
+{ IMG_SpringBridgeIntro, 0x29997f, 46080 },
+{ PAL_SpringBridgeIntro, 0x2a4d7f, 720 },
+{ TXT_SpringRock, 0x2a5756, 1374 },
+{ IMG_SpringRock, 0x2a5cb4, 46080 },
+{ PAL_SpringRock, 0x2b10b4, 720 },
+{ MSK_SpringRock, 0x2b1384, 3117 },
+{ BOX_SpringRock, 0x2b1fb1, 1280 },
+{ PAL_Shareware7, 0x2b2790, 768 },
+{ IMG_Shareware7, 0x2b2a90, 46080 },
+{ PAL_Shareware6, 0x2bdf09, 768 },
+{ IMG_Shareware6, 0x2be209, 46080 },
+{ PAL_Shareware5, 0x2c9682, 768 },
+{ IMG_Shareware5, 0x2c9982, 46080 },
+{ PAL_Shareware4, 0x2d4dfb, 768 },
+{ IMG_Shareware4, 0x2d50fb, 46080 },
+{ PAL_Shareware3, 0x2e0574, 768 },
+{ IMG_Shareware3, 0x2e0874, 46080 },
+{ PAL_Shareware2, 0x2ebced, 768 },
+{ IMG_Shareware2, 0x2ebfed, 46080 },
+{ PAL_Shareware1, 0x2f7466, 768 },
+{ IMG_Shareware1, 0x2f7766, 46080 },
+{ PAL_TitleScreen, 0x302ec8, 768 },
+{ IMG_TitleScreen, 0x3031c8, 64000 },
+{ PAL_PenduloStudios, 0x312c40, 768 },
+{ IMG_PenduloStudios, 0x312f40, 64000 },
+{ PAL_GraphicAdventure, 0x3229b8, 768 },
+{ IMG_GraphicAdventure, 0x322cb8, 64000 },
+{ PAL_Presents, 0x332730, 768 },
+{ IMG_Presents, 0x332a30, 64000 },
+{ PAL_OptikSoftware, 0x3424a8, 768 },
+{ IMG_OptikSoftware, 0x3427a8, 64000 },
+{ IMG_Meanwhile, 0x352279, 46080 },
+{ IMG_OptionsButton, 0x36b111, 2106 },
+{ IMG_OptionsMenu, 0x36b94b, 36800 },
+{ CMF_8, 0x374cfc, 4926 },
+{ CMF_9, 0x37603a, 6249 },
+{ CMF_10, 0x3778a3, 5982 },
+{ CMF_11, 0x379001, 12793 },
+{ CMF_12, 0x37c1fa, 22275 },
+{ CMF_2_1, 0x381b77, 4111 },
+{ CMF_2_2, 0x382b86, 4303 },
+{ CMF_2_3, 0x383c55, 4343 },
+{ CMF_2_4, 0x384d4c, 5943 },
+{ CMF_3, 0x386483, 5898 },
+{ CMF_4, 0x387b8d, 3133 },
+{ CMF_7_1, 0x3887ca, 4671 },
+{ CMF_7_2, 0x389a09, 646 },
+{ CMF_7_3, 0x389c8f, 2014 },
+{ CMF_7_4, 0x38a46d, 1369 },
+{ FRM_IgorDirBack, 0x38abb8, 10500 },
+{ FRM_IgorDirRight, 0x38d4bc, 13500 },
+{ FRM_IgorDirFront, 0x390978, 10500 },
+{ FRM_IgorDirLeft, 0x39327c, 13500 },
+{ FRM_IgorHead, 0x396738, 3696 },
+{ IMG_VerbsPanel, 0x39fd50, 3840 },
+{ TXT_MainTable, 0x3a0c50, 28028 },
+{ IMG_RomanNumbersPaper, 0x3a7e14, 46080 },
+{ PAL_RomanNumbersPaper, 0x3b3214, 624 },
+{ FRM_NumbersPaper1, 0x3b36ae, 51163 },
+{ FRM_NumbersPaper2, 0x3bfe89, 40 },
+{ IMG_NewsPaper, 0x3c017f, 46080 },
+{ PAL_NewsPaper, 0x3cb57f, 624 },
+{ IMG_PhotoHarrisonMargaret, 0x3cbcf9, 46080 },
+{ PAL_PhotoHarrisonMargaret, 0x3d70f9, 624 },
+{ IMG_InventoryPanel, 0x3d7a76, 9600 },
+{ IMG_Objects, 0x3d9ff6, 48000 },
diff --git a/engines/igor/staticres.cpp b/engines/igor/staticres.cpp
new file mode 100644
index 0000000000..aeb0cfb88f
--- /dev/null
+++ b/engines/igor/staticres.cpp
@@ -0,0 +1,1124 @@
+/* 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 "igor/igor.h"
+
+namespace Igor {
+
+const uint8 IgorEngine::_dialogueColor[] = { 0x3F, 0x3F, 0x3F };
+
+const uint8 IgorEngine::_sentenceColorIndex[]= { 0xFD, 0xFB, 0xF1 };
+
+const uint8 IgorEngine::_fontCharIndex[] = {
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x5E, 0x53, 0x51, 0x59, 0x5D, 0x5A, 0x5C, 0x63, 0x44, 0x45, 0x63, 0x47, 0x4D, 0x46, 0x4F, 0x4B,
+ 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x50, 0x4E, 0x49, 0x48, 0x4A, 0x55,
+ 0x5B, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
+ 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x57, 0x4C, 0x58, 0x63, 0x63,
+ 0x63, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x29,
+ 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x63, 0x63, 0x36, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x35, 0x37, 0x38, 0x39, 0x28, 0x56, 0x63, 0x63, 0x54, 0x63, 0x63, 0x63, 0x63, 0x52, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63
+};
+
+const uint8 IgorEngine::_fontCharWidth[] = {
+ 0x07, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x07, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x07, 0x08, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x07, 0x08, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x05, 0x06, 0x07, 0x05, 0x08, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x08, 0x08, 0x06, 0x07, 0x06, 0x06, 0x05, 0x06, 0x06, 0x08, 0x07, 0x07, 0x07, 0x08, 0x07,
+ 0x07, 0x07, 0x07, 0x07, 0x05, 0x05, 0x07, 0x07, 0x07, 0x06, 0x06, 0x07, 0x07, 0x04, 0x04, 0x03,
+ 0x03, 0x06, 0x03, 0x03, 0x07, 0x07, 0x08, 0x05, 0x05, 0x08, 0x04, 0x06, 0x08, 0x07, 0x05
+};
+
+const uint8 IgorEngine::_fontData[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x02, 0x01, 0x01, 0x03, 0x03, 0x01, 0x01, 0x02, 0x00, 0x02, 0x01, 0x01,
+ 0x03, 0x02, 0x01, 0x01, 0x03, 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x00, 0x02,
+ 0x01, 0x01, 0x03, 0x03, 0x01, 0x01, 0x03, 0x00, 0x02, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x03,
+ 0x00, 0x02, 0x02, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02,
+ 0x01, 0x01, 0x03, 0x03, 0x01, 0x01, 0x02, 0x00, 0x02, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x03,
+ 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x03, 0x00, 0x02, 0x01, 0x01, 0x03, 0x03, 0x01,
+ 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x01, 0x01, 0x03, 0x03, 0x03, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x03, 0x00, 0x02,
+ 0x02, 0x03, 0x03, 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03,
+ 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x03, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x03, 0x00, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x01,
+ 0x01, 0x03, 0x02, 0x01, 0x01, 0x02, 0x00, 0x02, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x03, 0x00,
+ 0x02, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x03, 0x02, 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03,
+ 0x03, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x03, 0x00, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x03, 0x03, 0x03, 0x01, 0x03,
+ 0x00, 0x02, 0x01, 0x01, 0x03, 0x01, 0x02, 0x02, 0x03, 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x03,
+ 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x01, 0x03, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x03,
+ 0x02, 0x03, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02, 0x02, 0x03,
+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x03, 0x03,
+ 0x03, 0x01, 0x03, 0x00, 0x02, 0x01, 0x01, 0x03, 0x01, 0x02, 0x02, 0x03, 0x00, 0x02, 0x01, 0x01,
+ 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x01, 0x03, 0x00, 0x00, 0x02, 0x02,
+ 0x01, 0x01, 0x03, 0x02, 0x03, 0x00, 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01,
+ 0x01, 0x03, 0x03, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03, 0x02,
+ 0x01, 0x01, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x03, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x03, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x00,
+ 0x02, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x03, 0x00, 0x02, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01,
+ 0x03, 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x00, 0x02, 0x01, 0x01, 0x03, 0x03,
+ 0x01, 0x01, 0x03, 0x00, 0x02, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x03, 0x00, 0x02, 0x01, 0x01,
+ 0x03, 0x02, 0x01, 0x01, 0x03, 0x00, 0x02, 0x02, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x00, 0x02, 0x02, 0x03, 0x01, 0x01, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x02, 0x01,
+ 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x01, 0x01, 0x03, 0x02, 0x02, 0x00,
+ 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x03, 0x03, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x03,
+ 0x00, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x03, 0x00, 0x02, 0x01, 0x01, 0x03, 0x02, 0x01,
+ 0x01, 0x03, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x02, 0x02, 0x03,
+ 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x03, 0x02, 0x01,
+ 0x01, 0x03, 0x00, 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x03, 0x00, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x03, 0x03, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01,
+ 0x01, 0x03, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x03, 0x02,
+ 0x02, 0x03, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01,
+ 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x01, 0x01, 0x03, 0x00, 0x02, 0x02, 0x02, 0x00, 0x02, 0x01, 0x01, 0x03, 0x02, 0x02, 0x01, 0x02,
+ 0x02, 0x02, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x03, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02,
+ 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02,
+ 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x03, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x03, 0x01, 0x03,
+ 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x03, 0x02, 0x03, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x03,
+ 0x00, 0x02, 0x01, 0x01, 0x03, 0x02, 0x02, 0x03, 0x03, 0x00, 0x02, 0x02, 0x03, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01,
+ 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01,
+ 0x03, 0x02, 0x01, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x03, 0x02, 0x02, 0x01, 0x01, 0x03, 0x02,
+ 0x01, 0x01, 0x03, 0x00, 0x02, 0x01, 0x01, 0x03, 0x02, 0x02, 0x03, 0x03, 0x00, 0x02, 0x02, 0x03,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01,
+ 0x01, 0x03, 0x03, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x03, 0x00, 0x02, 0x01, 0x01, 0x03,
+ 0x02, 0x01, 0x01, 0x03, 0x02, 0x02, 0x01, 0x01, 0x03, 0x02, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01,
+ 0x03, 0x03, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03,
+ 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x03, 0x03, 0x01, 0x01,
+ 0x02, 0x00, 0x02, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x03, 0x00, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x03, 0x03, 0x00, 0x02, 0x01, 0x01, 0x03, 0x03, 0x03, 0x03, 0x00, 0x02, 0x02, 0x01, 0x01,
+ 0x03, 0x02, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02,
+ 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x01, 0x01, 0x03, 0x03,
+ 0x01, 0x01, 0x02, 0x00, 0x02, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x03, 0x00, 0x02, 0x01, 0x01,
+ 0x03, 0x02, 0x01, 0x01, 0x03, 0x00, 0x02, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x03, 0x00, 0x02,
+ 0x01, 0x01, 0x03, 0x01, 0x01, 0x01, 0x03, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x03,
+ 0x00, 0x00, 0x02, 0x02, 0x03, 0x01, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03,
+ 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02,
+ 0x01, 0x01, 0x03, 0x03, 0x01, 0x01, 0x02, 0x00, 0x02, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x03,
+ 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x03, 0x00, 0x02, 0x01, 0x01, 0x03, 0x03, 0x01,
+ 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x01, 0x03,
+ 0x02, 0x01, 0x01, 0x03, 0x02, 0x02, 0x03, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02,
+ 0x00, 0x02, 0x01, 0x01, 0x03, 0x03, 0x01, 0x01, 0x02, 0x00, 0x02, 0x01, 0x01, 0x03, 0x02, 0x02,
+ 0x03, 0x03, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x03,
+ 0x03, 0x01, 0x01, 0x02, 0x00, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x03, 0x00, 0x02, 0x02,
+ 0x01, 0x01, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x00, 0x02, 0x01, 0x03, 0x01, 0x01, 0x03, 0x01, 0x03, 0x00, 0x02, 0x02, 0x03,
+ 0x01, 0x01, 0x03, 0x02, 0x03, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x03, 0x02, 0x00,
+ 0x00, 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x03,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x01,
+ 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x00, 0x02, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x03, 0x00,
+ 0x02, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x03, 0x00, 0x02, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01,
+ 0x03, 0x00, 0x02, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x03, 0x00, 0x02, 0x01, 0x01, 0x03, 0x02,
+ 0x01, 0x01, 0x03, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x02, 0x02,
+ 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x00, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x00, 0x02, 0x01, 0x01, 0x03, 0x02, 0x01,
+ 0x01, 0x03, 0x00, 0x02, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x03, 0x00, 0x02, 0x01, 0x01, 0x03,
+ 0x02, 0x01, 0x01, 0x03, 0x00, 0x02, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x03, 0x00, 0x02, 0x02,
+ 0x01, 0x01, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x00, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01,
+ 0x03, 0x00, 0x02, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x03, 0x02, 0x02, 0x01, 0x01, 0x03, 0x02,
+ 0x01, 0x01, 0x03, 0x01, 0x02, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x03, 0x02, 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01, 0x03, 0x02, 0x02, 0x01, 0x03, 0x03, 0x02,
+ 0x01, 0x03, 0x03, 0x00, 0x02, 0x02, 0x03, 0x00, 0x02, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02,
+ 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x00, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x01, 0x01, 0x03, 0x02, 0x02, 0x01, 0x01, 0x03, 0x02, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01,
+ 0x03, 0x03, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x03, 0x03, 0x00, 0x02, 0x02, 0x01, 0x01, 0x03,
+ 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x03, 0x03, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01,
+ 0x03, 0x00, 0x02, 0x01, 0x01, 0x03, 0x02, 0x02, 0x03, 0x03, 0x00, 0x02, 0x02, 0x03, 0x03, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01,
+ 0x01, 0x02, 0x00, 0x02, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x03, 0x00, 0x02, 0x01, 0x01, 0x03,
+ 0x02, 0x01, 0x01, 0x03, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x02,
+ 0x02, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x03, 0x02, 0x00, 0x00,
+ 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x03, 0x03, 0x01, 0x01, 0x01, 0x03, 0x02,
+ 0x01, 0x03, 0x03, 0x01, 0x01, 0x01, 0x03, 0x03, 0x02, 0x02, 0x03, 0x01, 0x01, 0x01, 0x03, 0x03,
+ 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x03, 0x03, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x03, 0x03,
+ 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02, 0x02, 0x03, 0x03,
+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x01,
+ 0x01, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x00, 0x00, 0x02, 0x01, 0x01,
+ 0x03, 0x01, 0x01, 0x03, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00,
+ 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03,
+ 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x01,
+ 0x01, 0x03, 0x01, 0x01, 0x02, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x00, 0x00,
+ 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x00, 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x03,
+ 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00,
+ 0x00, 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x02, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x02, 0x03,
+ 0x03, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01,
+ 0x01, 0x03, 0x03, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x02,
+ 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x03, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x00, 0x00, 0x02, 0x01, 0x01,
+ 0x03, 0x01, 0x01, 0x03, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x00, 0x00, 0x02,
+ 0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02,
+ 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x02, 0x00, 0x00,
+ 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x03, 0x03, 0x03,
+ 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03,
+ 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x03, 0x03, 0x00,
+ 0x00, 0x02, 0x02, 0x01, 0x01, 0x03, 0x02, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01,
+ 0x03, 0x02, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02,
+ 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x00, 0x02, 0x01, 0x01,
+ 0x03, 0x01, 0x01, 0x03, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x00, 0x00, 0x02,
+ 0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x00, 0x00, 0x02, 0x02, 0x02, 0x03, 0x01, 0x01, 0x03, 0x00,
+ 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01,
+ 0x01, 0x03, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00,
+ 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x02, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03,
+ 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x01,
+ 0x01, 0x03, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x02, 0x02, 0x02, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x01, 0x02, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x03, 0x02, 0x00, 0x00, 0x00, 0x02, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01,
+ 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x02,
+ 0x02, 0x02, 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x03, 0x00,
+ 0x00, 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x03,
+ 0x03, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01,
+ 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x02, 0x02, 0x02, 0x02, 0x00,
+ 0x02, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x02, 0x00, 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03,
+ 0x03, 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x02, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x02, 0x00, 0x02, 0x02, 0x03,
+ 0x03, 0x02, 0x02, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x02, 0x01, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x03, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02,
+ 0x01, 0x01, 0x03, 0x02, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x03, 0x01, 0x03, 0x01, 0x01,
+ 0x03, 0x02, 0x01, 0x01, 0x03, 0x01, 0x03, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x03, 0x02, 0x03,
+ 0x01, 0x01, 0x03, 0x02, 0x02, 0x03, 0x03, 0x00, 0x02, 0x02, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02,
+ 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x02, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x01,
+ 0x01, 0x03, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x00, 0x00, 0x02, 0x01, 0x01,
+ 0x03, 0x01, 0x01, 0x03, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x02, 0x00, 0x00, 0x02, 0x01,
+ 0x01, 0x03, 0x01, 0x01, 0x03, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x00, 0x00,
+ 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x02, 0x03, 0x03,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02,
+ 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x02, 0x00,
+ 0x00, 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x01, 0x01,
+ 0x03, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03,
+ 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00,
+ 0x00, 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x01,
+ 0x01, 0x02, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x00, 0x00, 0x02, 0x01, 0x01,
+ 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x02,
+ 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x00, 0x02, 0x01,
+ 0x01, 0x03, 0x01, 0x01, 0x03, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x00, 0x00,
+ 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x01, 0x01, 0x03,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02,
+ 0x03, 0x03, 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, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x00,
+ 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x03,
+ 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x03, 0x02, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x02, 0x02, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x03, 0x01, 0x01, 0x02, 0x00, 0x00, 0x02,
+ 0x01, 0x01, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x03, 0x02, 0x02, 0x00, 0x00, 0x02, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x03, 0x03, 0x03, 0x00, 0x00,
+ 0x00, 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x02, 0x02,
+ 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03,
+ 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00,
+ 0x00, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x01, 0x01,
+ 0x03, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03,
+ 0x01, 0x01, 0x03, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x00, 0x02,
+ 0x02, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x00, 0x00, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x00, 0x00, 0x02, 0x01, 0x01,
+ 0x03, 0x01, 0x01, 0x03, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x00, 0x00, 0x02,
+ 0x02, 0x01, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x03, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02,
+ 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x01, 0x01, 0x03, 0x01, 0x02, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x03, 0x01, 0x03, 0x01,
+ 0x01, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02, 0x02, 0x01, 0x01, 0x03,
+ 0x01, 0x01, 0x03, 0x03, 0x00, 0x02, 0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02,
+ 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x03, 0x03, 0x00, 0x02, 0x02, 0x01,
+ 0x01, 0x01, 0x03, 0x03, 0x00, 0x02, 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01,
+ 0x01, 0x03, 0x03, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x03, 0x03, 0x00, 0x02, 0x02, 0x03, 0x03,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x01, 0x01,
+ 0x02, 0x01, 0x01, 0x02, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x00, 0x00, 0x02,
+ 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x00,
+ 0x00, 0x02, 0x02, 0x02, 0x03, 0x01, 0x01, 0x03, 0x00, 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x03,
+ 0x03, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 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, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00,
+ 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x02, 0x01, 0x03, 0x03, 0x01, 0x01, 0x03,
+ 0x03, 0x00, 0x02, 0x02, 0x03, 0x01, 0x01, 0x03, 0x03, 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x03,
+ 0x03, 0x01, 0x02, 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x00, 0x02, 0x02, 0x03,
+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x03, 0x03,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03,
+ 0x01, 0x01, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x00, 0x00, 0x02, 0x01,
+ 0x01, 0x03, 0x01, 0x01, 0x03, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x00, 0x00,
+ 0x00, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01,
+ 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x00, 0x02, 0x02,
+ 0x02, 0x03, 0x03, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02,
+ 0x01, 0x01, 0x03, 0x01, 0x01, 0x02, 0x00, 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x00,
+ 0x00, 0x02, 0x01, 0x01, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x02, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x00,
+ 0x02, 0x02, 0x02, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x01, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x03, 0x02, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03,
+ 0x03, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x03, 0x03, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x02, 0x00, 0x00, 0x02, 0x01,
+ 0x01, 0x03, 0x01, 0x01, 0x03, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x00, 0x00,
+ 0x02, 0x02, 0x01, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x03, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02,
+ 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x02, 0x00, 0x00, 0x02,
+ 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x00,
+ 0x00, 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x01, 0x01,
+ 0x03, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03,
+ 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00,
+ 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x03, 0x03, 0x03, 0x01,
+ 0x01, 0x02, 0x02, 0x01, 0x01, 0x03, 0x00, 0x02, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x03, 0x00,
+ 0x02, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x03, 0x00, 0x02, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01,
+ 0x03, 0x02, 0x02, 0x01, 0x01, 0x03, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x03, 0x00,
+ 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01,
+ 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00,
+ 0x02, 0x02, 0x02, 0x01, 0x01, 0x03, 0x02, 0x02, 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x00, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02,
+ 0x01, 0x01, 0x03, 0x03, 0x01, 0x01, 0x02, 0x00, 0x02, 0x02, 0x03, 0x03, 0x02, 0x01, 0x01, 0x03,
+ 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x03, 0x03, 0x00, 0x02, 0x02, 0x01, 0x01, 0x03, 0x03,
+ 0x03, 0x02, 0x00, 0x02, 0x01, 0x01, 0x03, 0x03, 0x01, 0x01, 0x02, 0x00, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x03, 0x00, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x02, 0x01, 0x01, 0x03, 0x03, 0x01, 0x01, 0x02, 0x00, 0x02, 0x02, 0x03, 0x03, 0x02,
+ 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x01, 0x03, 0x03, 0x00, 0x02, 0x02, 0x02,
+ 0x02, 0x03, 0x01, 0x01, 0x02, 0x00, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x03, 0x00, 0x02,
+ 0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02,
+ 0x01, 0x01, 0x01, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x00, 0x02, 0x02,
+ 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x00, 0x02, 0x01, 0x01, 0x03, 0x03, 0x01, 0x01, 0x03, 0x02,
+ 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x01, 0x01,
+ 0x03, 0x03, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02,
+ 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x02, 0x01, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03,
+ 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x03, 0x03, 0x03, 0x01,
+ 0x01, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x03, 0x00, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x01, 0x01, 0x03, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x02,
+ 0x02, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x03,
+ 0x03, 0x03, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x03, 0x02, 0x02, 0x00, 0x00, 0x02, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x01, 0x01, 0x03, 0x03, 0x01, 0x01, 0x02, 0x00, 0x02,
+ 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x03, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x03,
+ 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x02, 0x01,
+ 0x01, 0x03, 0x03, 0x01, 0x01, 0x03, 0x00, 0x02, 0x02, 0x03, 0x03, 0x02, 0x01, 0x01, 0x03, 0x00,
+ 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x03,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02,
+ 0x00, 0x02, 0x01, 0x01, 0x03, 0x03, 0x01, 0x01, 0x02, 0x00, 0x02, 0x01, 0x01, 0x03, 0x02, 0x01,
+ 0x01, 0x03, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x03, 0x00, 0x02, 0x01, 0x01, 0x03,
+ 0x03, 0x01, 0x01, 0x02, 0x00, 0x02, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x03, 0x00, 0x02, 0x02,
+ 0x01, 0x01, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x02, 0x01, 0x01, 0x03, 0x03, 0x01, 0x01, 0x02, 0x00, 0x02, 0x01, 0x01,
+ 0x03, 0x02, 0x01, 0x01, 0x03, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x00, 0x00,
+ 0x02, 0x02, 0x03, 0x03, 0x01, 0x01, 0x03, 0x00, 0x00, 0x02, 0x02, 0x02, 0x01, 0x01, 0x03, 0x03,
+ 0x00, 0x00, 0x02, 0x01, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x03,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02,
+ 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02,
+ 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x02,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02,
+ 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x00, 0x00, 0x00, 0x02,
+ 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01,
+ 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x00,
+ 0x02, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x01, 0x01, 0x03, 0x02,
+ 0x02, 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x02, 0x02, 0x03, 0x01, 0x01,
+ 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x02, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x00, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x02, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x02, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x02,
+ 0x02, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x02, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01,
+ 0x01, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x02, 0x02, 0x01,
+ 0x01, 0x03, 0x03, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x02, 0x03, 0x03, 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, 0x02,
+ 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x02,
+ 0x02, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x00,
+ 0x02, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x03, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01,
+ 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x02, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02,
+ 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x02, 0x02, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x02, 0x02, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x03,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x02,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02,
+ 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x02, 0x02, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x01, 0x01, 0x02,
+ 0x01, 0x01, 0x02, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x00, 0x00, 0x02, 0x01,
+ 0x01, 0x03, 0x01, 0x01, 0x03, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x02, 0x02, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01,
+ 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x02, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x02, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 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, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x03, 0x03, 0x00,
+ 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x03, 0x02, 0x02, 0x02, 0x00, 0x02, 0x01, 0x01, 0x03, 0x02,
+ 0x01, 0x01, 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x02, 0x02,
+ 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00,
+ 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x01, 0x01, 0x03, 0x03, 0x01,
+ 0x01, 0x02, 0x00, 0x02, 0x02, 0x03, 0x03, 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x02, 0x02,
+ 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x02, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x03, 0x02,
+ 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01, 0x01,
+ 0x03, 0x02, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x03, 0x02, 0x02,
+ 0x01, 0x01, 0x03, 0x02, 0x02, 0x03, 0x03, 0x00, 0x02, 0x02, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00,
+ 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01,
+ 0x03, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x02,
+ 0x02, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00,
+ 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x01, 0x01, 0x03,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01,
+ 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00,
+ 0x02, 0x02, 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x00,
+ 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03,
+ 0x03, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x03, 0x01,
+ 0x01, 0x03, 0x03, 0x02, 0x02, 0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01,
+ 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x02, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00,
+ 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x03, 0x03,
+ 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x03, 0x01, 0x01,
+ 0x01, 0x03, 0x03, 0x02, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x03, 0x02, 0x02, 0x02, 0x01, 0x01,
+ 0x01, 0x02, 0x01, 0x01, 0x02, 0x00, 0x02, 0x02, 0x03, 0x03, 0x03, 0x02, 0x03, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x02, 0x01, 0x01, 0x03, 0x03, 0x01, 0x01, 0x02, 0x00, 0x02, 0x01, 0x01, 0x03, 0x02,
+ 0x02, 0x03, 0x03, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02,
+ 0x03, 0x03, 0x01, 0x01, 0x02, 0x00, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x03, 0x00, 0x02,
+ 0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, 0x02, 0x02, 0x03, 0x01, 0x03, 0x03, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+const uint8 IgorEngine::_talkDelays[] = { 0, 27, 22, 17, 12, 7, 0 };
+
+const uint8 IgorEngine::_verbAreasTable[] = {
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x03, 0x03,
+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+ 0x07, 0x07, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
+};
+
+const uint8 IgorEngine::_inventoryOffsetTable[] = { 1, 8, 15, 22, 29, 36, 42, 0 };
+
+const uint8 IgorEngine::_inventoryActionsTable[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x16, 0x00, 0x01, 0x00, 0x09, 0x00,
+ 0x0C, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x17, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x18, 0x00, 0x6A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x19, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x1A, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x1B, 0x00,
+ 0x01, 0x00, 0x09, 0x00, 0x0C, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x1C, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x1D, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x1E, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x1F, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x21, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x24, 0x00, 0x01, 0x00, 0x3D, 0x01,
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x25, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x26, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x27, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x00, 0x08, 0x00, 0x2A, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x2B, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x2C, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x2D, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x2E, 0x00,
+ 0x01, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x30, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x32, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x33, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x34, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x35, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x36, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x37, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x38, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x3A, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x3B, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x41, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x40, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x42, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00
+};
+
+const uint8 IgorEngine::_walkWidthScaleTable[] = {
+ 0x01, 0x01, 0x02, 0x02, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x07, 0x07, 0x08, 0x08, 0x09, 0x0A,
+ 0x0A, 0x0B, 0x0B, 0x0C, 0x0D, 0x0D, 0x0E, 0x0E, 0x0F, 0x10, 0x10, 0x11, 0x11, 0x12, 0x13, 0x13,
+ 0x14, 0x14, 0x15, 0x16, 0x16, 0x17, 0x17, 0x18, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1C, 0x1C, 0x1D,
+ 0x1D, 0x1E
+};
+
+const float IgorEngine::_walkScaleSpeedTable[] = {
+ 0.6250, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.1250, 1.3750, 1.6250, 1.6250,
+ 1.6250, 1.6250, 2.0000, 2.1250, 2.3750, 2.3750, 2.6250, 2.6250, 2.7500, 2.7500,
+ 2.7500, 3.0000, 3.0000, 3.0000, 3.0000, 3.6250, 3.6250, 3.6250, 3.8750, 3.8750,
+ 3.8750, 4.0000, 4.0000, 4.3750, 4.3750, 4.6250, 4.6250, 5.0000, 5.0000, 5.0000,
+ 5.0000, 5.2500, 5.5000, 5.6250, 5.6250, 5.6250, 5.6250, 5.6250, 5.6250, 5.6250
+};
+
+// XXX split into 3 arrays (scaleTable ...), sizeof == 0x934
+const uint8 IgorEngine::_walkScaleTable[] = { // 0x769, 0x901
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
+ 0x30, 0x31, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
+ 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D,
+ 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D,
+ 0x2E, 0x2F, 0x30, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
+ 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D,
+ 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D,
+ 0x2E, 0x2F, 0x30, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
+ 0x0D, 0x0E, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D,
+ 0x1E, 0x1F, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E,
+ 0x2F, 0x30, 0x00, 0x01, 0x02, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
+ 0x21, 0x22, 0x23, 0x24, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
+ 0x11, 0x12, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1E, 0x1F, 0x20, 0x21, 0x22,
+ 0x23, 0x24, 0x25, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x31, 0x00, 0x01, 0x02,
+ 0x03, 0x04, 0x05, 0x06, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x10, 0x11, 0x12, 0x13, 0x14,
+ 0x15, 0x16, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
+ 0x27, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x15, 0x16, 0x17, 0x18, 0x19,
+ 0x1A, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x2A, 0x2B, 0x2C,
+ 0x2D, 0x2E, 0x2F, 0x30, 0x00, 0x01, 0x02, 0x03, 0x04, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0C, 0x0D,
+ 0x0E, 0x0F, 0x10, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1F, 0x20,
+ 0x21, 0x22, 0x23, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x00, 0x01,
+ 0x02, 0x03, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0B, 0x0C, 0x0D, 0x0E, 0x10, 0x11, 0x12, 0x13, 0x14,
+ 0x16, 0x17, 0x18, 0x19, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x21, 0x22, 0x23, 0x24, 0x26, 0x27, 0x28,
+ 0x29, 0x2A, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x00, 0x01, 0x02, 0x04, 0x05, 0x06, 0x07, 0x09, 0x0A,
+ 0x0B, 0x0C, 0x0E, 0x0F, 0x10, 0x11, 0x13, 0x14, 0x15, 0x16, 0x18, 0x19, 0x1A, 0x1B, 0x1D, 0x1E,
+ 0x1F, 0x20, 0x22, 0x23, 0x24, 0x25, 0x27, 0x28, 0x29, 0x2A, 0x2C, 0x2D, 0x2E, 0x2F, 0x31, 0x00,
+ 0x01, 0x02, 0x04, 0x05, 0x06, 0x07, 0x09, 0x0A, 0x0B, 0x0D, 0x0E, 0x0F, 0x10, 0x12, 0x13, 0x14,
+ 0x16, 0x17, 0x18, 0x19, 0x1B, 0x1C, 0x1D, 0x1F, 0x20, 0x21, 0x22, 0x24, 0x25, 0x26, 0x28, 0x29,
+ 0x2A, 0x2B, 0x2D, 0x2E, 0x2F, 0x31, 0x00, 0x01, 0x02, 0x04, 0x05, 0x06, 0x08, 0x09, 0x0A, 0x0C,
+ 0x0D, 0x0E, 0x10, 0x11, 0x12, 0x14, 0x15, 0x16, 0x18, 0x19, 0x1A, 0x1B, 0x1D, 0x1E, 0x1F, 0x21,
+ 0x22, 0x23, 0x25, 0x26, 0x27, 0x29, 0x2A, 0x2B, 0x2D, 0x2E, 0x2F, 0x31, 0x00, 0x01, 0x03, 0x04,
+ 0x05, 0x07, 0x08, 0x09, 0x0B, 0x0C, 0x0D, 0x0F, 0x10, 0x11, 0x13, 0x14, 0x15, 0x17, 0x18, 0x1A,
+ 0x1B, 0x1C, 0x1E, 0x1F, 0x20, 0x22, 0x23, 0x24, 0x26, 0x27, 0x28, 0x2A, 0x2B, 0x2C, 0x2E, 0x2F,
+ 0x31, 0x00, 0x01, 0x03, 0x04, 0x05, 0x07, 0x08, 0x0A, 0x0B, 0x0C, 0x0E, 0x0F, 0x11, 0x12, 0x13,
+ 0x15, 0x16, 0x18, 0x19, 0x1A, 0x1C, 0x1D, 0x1E, 0x20, 0x21, 0x23, 0x24, 0x25, 0x27, 0x28, 0x2A,
+ 0x2B, 0x2C, 0x2E, 0x2F, 0x30, 0x00, 0x01, 0x03, 0x04, 0x06, 0x07, 0x09, 0x0A, 0x0B, 0x0D, 0x0E,
+ 0x10, 0x11, 0x12, 0x14, 0x15, 0x17, 0x18, 0x1A, 0x1B, 0x1C, 0x1E, 0x1F, 0x21, 0x22, 0x24, 0x25,
+ 0x26, 0x28, 0x29, 0x2B, 0x2C, 0x2E, 0x2F, 0x31, 0x00, 0x01, 0x03, 0x04, 0x06, 0x07, 0x09, 0x0A,
+ 0x0C, 0x0D, 0x0F, 0x10, 0x12, 0x13, 0x15, 0x16, 0x17, 0x19, 0x1A, 0x1C, 0x1D, 0x1F, 0x20, 0x22,
+ 0x23, 0x25, 0x26, 0x28, 0x29, 0x2B, 0x2C, 0x2E, 0x2F, 0x30, 0x00, 0x02, 0x03, 0x05, 0x06, 0x08,
+ 0x09, 0x0B, 0x0C, 0x0E, 0x0F, 0x11, 0x12, 0x14, 0x15, 0x17, 0x18, 0x1A, 0x1B, 0x1D, 0x1E, 0x20,
+ 0x21, 0x23, 0x24, 0x26, 0x27, 0x29, 0x2A, 0x2C, 0x2D, 0x2F, 0x31, 0x00, 0x02, 0x03, 0x05, 0x06,
+ 0x08, 0x09, 0x0B, 0x0D, 0x0E, 0x10, 0x11, 0x13, 0x14, 0x16, 0x18, 0x19, 0x1B, 0x1C, 0x1E, 0x1F,
+ 0x21, 0x22, 0x24, 0x26, 0x27, 0x29, 0x2A, 0x2C, 0x2D, 0x2F, 0x31, 0x00, 0x02, 0x03, 0x05, 0x07,
+ 0x08, 0x0A, 0x0B, 0x0D, 0x0F, 0x10, 0x12, 0x13, 0x15, 0x17, 0x18, 0x1A, 0x1C, 0x1D, 0x1F, 0x20,
+ 0x22, 0x24, 0x25, 0x27, 0x28, 0x2A, 0x2C, 0x2D, 0x2F, 0x30, 0x00, 0x02, 0x04, 0x05, 0x07, 0x09,
+ 0x0A, 0x0C, 0x0D, 0x0F, 0x11, 0x13, 0x14, 0x16, 0x18, 0x19, 0x1B, 0x1D, 0x1E, 0x20, 0x22, 0x23,
+ 0x25, 0x27, 0x28, 0x2A, 0x2B, 0x2D, 0x2F, 0x30, 0x00, 0x02, 0x04, 0x05, 0x07, 0x09, 0x0B, 0x0C,
+ 0x0E, 0x10, 0x11, 0x13, 0x15, 0x17, 0x18, 0x1A, 0x1C, 0x1E, 0x1F, 0x21, 0x23, 0x24, 0x26, 0x28,
+ 0x2A, 0x2B, 0x2D, 0x2F, 0x31, 0x00, 0x02, 0x04, 0x06, 0x07, 0x09, 0x0B, 0x0D, 0x0F, 0x10, 0x12,
+ 0x14, 0x16, 0x17, 0x19, 0x1B, 0x1D, 0x1F, 0x20, 0x22, 0x24, 0x26, 0x28, 0x29, 0x2B, 0x2D, 0x2F,
+ 0x30, 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0B, 0x0D, 0x0F, 0x11, 0x13, 0x15, 0x17, 0x18, 0x1A,
+ 0x1C, 0x1E, 0x20, 0x22, 0x24, 0x25, 0x27, 0x29, 0x2B, 0x2D, 0x2F, 0x31, 0x00, 0x02, 0x04, 0x06,
+ 0x08, 0x0A, 0x0C, 0x0E, 0x10, 0x12, 0x14, 0x16, 0x18, 0x19, 0x1B, 0x1D, 0x1F, 0x21, 0x23, 0x25,
+ 0x27, 0x29, 0x2B, 0x2D, 0x2F, 0x30, 0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F, 0x11, 0x13,
+ 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F, 0x21, 0x23, 0x25, 0x27, 0x29, 0x2B, 0x2D, 0x2F, 0x31, 0x01,
+ 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F, 0x11, 0x13, 0x15, 0x18, 0x1A, 0x1C, 0x1E, 0x20, 0x22,
+ 0x24, 0x26, 0x28, 0x2A, 0x2C, 0x2E, 0x31, 0x01, 0x03, 0x05, 0x07, 0x09, 0x0C, 0x0E, 0x10, 0x12,
+ 0x14, 0x16, 0x19, 0x1B, 0x1D, 0x1F, 0x21, 0x23, 0x26, 0x28, 0x2A, 0x2C, 0x2E, 0x31, 0x01, 0x03,
+ 0x05, 0x08, 0x0A, 0x0C, 0x0E, 0x11, 0x13, 0x15, 0x18, 0x1A, 0x1C, 0x1E, 0x21, 0x23, 0x25, 0x27,
+ 0x2A, 0x2C, 0x2E, 0x31, 0x01, 0x03, 0x06, 0x08, 0x0A, 0x0D, 0x0F, 0x12, 0x14, 0x16, 0x19, 0x1B,
+ 0x1D, 0x20, 0x22, 0x25, 0x27, 0x29, 0x2C, 0x2E, 0x31, 0x01, 0x04, 0x06, 0x09, 0x0B, 0x0E, 0x10,
+ 0x13, 0x15, 0x18, 0x1A, 0x1D, 0x1F, 0x22, 0x24, 0x27, 0x29, 0x2C, 0x2E, 0x31, 0x01, 0x04, 0x06,
+ 0x09, 0x0C, 0x0E, 0x11, 0x14, 0x16, 0x19, 0x1B, 0x1E, 0x21, 0x23, 0x26, 0x29, 0x2B, 0x2E, 0x31,
+ 0x01, 0x04, 0x07, 0x0A, 0x0C, 0x0F, 0x12, 0x15, 0x18, 0x1A, 0x1D, 0x20, 0x23, 0x25, 0x28, 0x2B,
+ 0x2E, 0x31, 0x01, 0x04, 0x07, 0x0A, 0x0D, 0x10, 0x13, 0x16, 0x19, 0x1C, 0x1F, 0x22, 0x25, 0x28,
+ 0x2B, 0x2E, 0x31, 0x02, 0x05, 0x08, 0x0B, 0x0E, 0x11, 0x14, 0x18, 0x1B, 0x1E, 0x21, 0x24, 0x27,
+ 0x2A, 0x2D, 0x31, 0x02, 0x05, 0x09, 0x0C, 0x0F, 0x13, 0x16, 0x19, 0x1D, 0x20, 0x23, 0x27, 0x2A,
+ 0x2D, 0x31, 0x02, 0x06, 0x09, 0x0D, 0x10, 0x14, 0x18, 0x1B, 0x1F, 0x22, 0x26, 0x29, 0x2D, 0x31,
+ 0x02, 0x06, 0x0A, 0x0E, 0x12, 0x16, 0x19, 0x1D, 0x21, 0x25, 0x29, 0x2D, 0x31, 0x03, 0x07, 0x0B,
+ 0x0F, 0x13, 0x18, 0x1C, 0x20, 0x24, 0x28, 0x2C, 0x31, 0x03, 0x08, 0x0C, 0x11, 0x15, 0x1A, 0x1E,
+ 0x23, 0x27, 0x2C, 0x31, 0x04, 0x09, 0x0E, 0x13, 0x18, 0x1D, 0x22, 0x27, 0x2C, 0x31, 0x04, 0x0A,
+ 0x0F, 0x15, 0x1A, 0x20, 0x25, 0x2B, 0x31, 0x05, 0x0B, 0x11, 0x18, 0x1E, 0x24, 0x2A, 0x31, 0x06,
+ 0x0D, 0x14, 0x1B, 0x22, 0x29, 0x31, 0x07, 0x0F, 0x18, 0x20, 0x28, 0x31, 0x09, 0x13, 0x1D, 0x27,
+ 0x31, 0x0B, 0x18, 0x24, 0x31, 0x0F, 0x20, 0x31, 0x18, 0x31, 0x31, 0x00, 0x00, 0x01, 0x02, 0x03,
+ 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13,
+ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
+ 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1D, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
+ 0x1A, 0x1B, 0x1D, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0A, 0x0B, 0x0C, 0x0D,
+ 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x00, 0x01,
+ 0x02, 0x03, 0x04, 0x05, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0F, 0x10, 0x11, 0x12, 0x13,
+ 0x14, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x00, 0x01, 0x02, 0x03, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0A, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x12, 0x13, 0x14, 0x15, 0x16, 0x18, 0x19, 0x1A, 0x1B,
+ 0x1C, 0x00, 0x01, 0x02, 0x04, 0x05, 0x06, 0x07, 0x09, 0x0A, 0x0B, 0x0C, 0x0E, 0x0F, 0x10, 0x11,
+ 0x13, 0x14, 0x15, 0x16, 0x18, 0x19, 0x1A, 0x1B, 0x1D, 0x00, 0x01, 0x02, 0x04, 0x05, 0x06, 0x08,
+ 0x09, 0x0A, 0x0C, 0x0D, 0x0E, 0x0F, 0x11, 0x12, 0x13, 0x15, 0x16, 0x17, 0x19, 0x1A, 0x1B, 0x1D,
+ 0x00, 0x01, 0x03, 0x04, 0x05, 0x07, 0x08, 0x09, 0x0B, 0x0C, 0x0D, 0x0F, 0x10, 0x12, 0x13, 0x14,
+ 0x16, 0x17, 0x18, 0x1A, 0x1B, 0x1C, 0x00, 0x01, 0x03, 0x04, 0x06, 0x07, 0x09, 0x0A, 0x0B, 0x0D,
+ 0x0E, 0x10, 0x11, 0x12, 0x14, 0x15, 0x17, 0x18, 0x1A, 0x1B, 0x1C, 0x00, 0x02, 0x03, 0x05, 0x06,
+ 0x08, 0x09, 0x0B, 0x0C, 0x0E, 0x0F, 0x11, 0x12, 0x14, 0x15, 0x17, 0x18, 0x1A, 0x1B, 0x1D, 0x00,
+ 0x02, 0x03, 0x05, 0x06, 0x08, 0x0A, 0x0B, 0x0D, 0x0E, 0x10, 0x11, 0x13, 0x15, 0x16, 0x18, 0x19,
+ 0x1B, 0x1C, 0x00, 0x02, 0x04, 0x05, 0x07, 0x09, 0x0A, 0x0C, 0x0D, 0x0F, 0x11, 0x13, 0x14, 0x16,
+ 0x18, 0x19, 0x1B, 0x1D, 0x00, 0x02, 0x04, 0x06, 0x07, 0x09, 0x0B, 0x0D, 0x0E, 0x10, 0x12, 0x14,
+ 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, 0x0F, 0x11, 0x13,
+ 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, 0x10, 0x12, 0x14,
+ 0x16, 0x18, 0x1A, 0x1C, 0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0E, 0x10, 0x12, 0x14, 0x16, 0x18,
+ 0x1A, 0x1D, 0x01, 0x03, 0x05, 0x08, 0x0A, 0x0C, 0x0F, 0x11, 0x13, 0x16, 0x18, 0x1A, 0x1D, 0x01,
+ 0x04, 0x06, 0x09, 0x0B, 0x0E, 0x10, 0x13, 0x15, 0x18, 0x1A, 0x1D, 0x01, 0x04, 0x07, 0x09, 0x0C,
+ 0x0F, 0x12, 0x14, 0x17, 0x1A, 0x1D, 0x02, 0x05, 0x08, 0x0B, 0x0E, 0x11, 0x14, 0x17, 0x1A, 0x1D,
+ 0x02, 0x05, 0x09, 0x0C, 0x0F, 0x13, 0x16, 0x19, 0x1D, 0x02, 0x06, 0x0A, 0x0E, 0x11, 0x15, 0x19,
+ 0x1D, 0x03, 0x07, 0x0B, 0x10, 0x14, 0x18, 0x1D, 0x04, 0x09, 0x0E, 0x13, 0x18, 0x1D, 0x05, 0x0B,
+ 0x11, 0x17, 0x1D, 0x06, 0x0E, 0x15, 0x1D, 0x09, 0x13, 0x1D, 0x0E, 0x1D, 0x1D, 0x00, 0xFB, 0x04,
+ 0xFA, 0x04, 0xF8, 0x04, 0xF5, 0x04, 0xF1, 0x04, 0xEC, 0x04, 0xE6, 0x04, 0xDF, 0x04, 0xD7, 0x04,
+ 0xCE, 0x04, 0xC4, 0x04, 0xB9, 0x04, 0xAD, 0x04, 0xA0, 0x04, 0x92, 0x04, 0x83, 0x04, 0x73, 0x04,
+ 0x62, 0x04, 0x50, 0x04, 0x3D, 0x04, 0x29, 0x04, 0x14, 0x04, 0xFE, 0x03, 0xE7, 0x03, 0xCF, 0x03,
+ 0xB6, 0x03, 0x9C, 0x03, 0x81, 0x03, 0x65, 0x03, 0x48, 0x03, 0x2A, 0x03, 0x0B, 0x03, 0xEB, 0x02,
+ 0xCA, 0x02, 0xA8, 0x02, 0x85, 0x02, 0x61, 0x02, 0x3C, 0x02, 0x16, 0x02, 0xEF, 0x01, 0xC7, 0x01,
+ 0x9E, 0x01, 0x74, 0x01, 0x49, 0x01, 0x1D, 0x01, 0xF0, 0x00, 0xC2, 0x00, 0x93, 0x00, 0x63, 0x00,
+ 0x32, 0x00, 0x00, 0x00, 0xD1, 0x01, 0xD0, 0x01, 0xCE, 0x01, 0xCB, 0x01, 0xC7, 0x01, 0xC2, 0x01,
+ 0xBC, 0x01, 0xB5, 0x01, 0xAD, 0x01, 0xA4, 0x01, 0x9A, 0x01, 0x8F, 0x01, 0x83, 0x01, 0x76, 0x01,
+ 0x68, 0x01, 0x59, 0x01, 0x49, 0x01, 0x38, 0x01, 0x26, 0x01, 0x13, 0x01, 0xFF, 0x00, 0xEA, 0x00,
+ 0xD4, 0x00, 0xBD, 0x00, 0xA5, 0x00, 0x8C, 0x00, 0x72, 0x00, 0x57, 0x00, 0x3B, 0x00, 0x1E, 0x00,
+ 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02,
+ 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02,
+ 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02,
+ 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03,
+ 0x02, 0x02, 0x03, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03, 0x03, 0x02, 0x03, 0x03,
+ 0x02, 0x02, 0x03, 0x03, 0x03, 0x02, 0x04, 0x03, 0x02, 0x02, 0x03, 0x03, 0x03, 0x02, 0x04, 0x03,
+ 0x02, 0x02, 0x03, 0x03, 0x03, 0x02, 0x04, 0x03, 0x02, 0x02, 0x03, 0x03, 0x04, 0x02, 0x04, 0x04,
+ 0x02, 0x02, 0x03, 0x03, 0x04, 0x02, 0x04, 0x04, 0x02, 0x02, 0x03, 0x03, 0x04, 0x02, 0x04, 0x04,
+ 0x02, 0x02, 0x04, 0x04, 0x05, 0x03, 0x05, 0x05, 0x03, 0x03, 0x04, 0x04, 0x04, 0x02, 0x05, 0x04,
+ 0x03, 0x03, 0x04, 0x04, 0x04, 0x02, 0x05, 0x04, 0x03, 0x03, 0x04, 0x04, 0x04, 0x02, 0x05, 0x04,
+ 0x03, 0x03, 0x04, 0x04, 0x05, 0x02, 0x05, 0x05, 0x03, 0x03, 0x04, 0x04, 0x05, 0x02, 0x05, 0x05,
+ 0x03, 0x03, 0x04, 0x04, 0x05, 0x02, 0x05, 0x05, 0x03, 0x03, 0x04, 0x04, 0x05, 0x02, 0x06, 0x05,
+ 0x03, 0x03, 0x04, 0x04, 0x05, 0x02, 0x06, 0x05, 0x03, 0x03, 0x05, 0x05, 0x05, 0x03, 0x06, 0x05,
+ 0x03, 0x03, 0x05, 0x05, 0x05, 0x03, 0x06, 0x05, 0x03, 0x03, 0x05, 0x05, 0x06, 0x03, 0x06, 0x06,
+ 0x03, 0x03, 0x05, 0x05, 0x06, 0x03, 0x06, 0x06, 0x03, 0x03, 0x05, 0x05, 0x06, 0x03, 0x07, 0x06,
+ 0x04, 0x04, 0x05, 0x05, 0x06, 0x03, 0x07, 0x06, 0x04, 0x04, 0x06, 0x06, 0x07, 0x04, 0x08, 0x07,
+ 0x04, 0x04, 0x07, 0x07, 0x08, 0x05, 0x09, 0x08, 0x05, 0x05, 0x07, 0x07, 0x08, 0x05, 0x09, 0x08,
+ 0x05, 0x05, 0x07, 0x07, 0x08, 0x05, 0x09, 0x08, 0x05, 0x05, 0x07, 0x07, 0x08, 0x05, 0x09, 0x08,
+ 0x05, 0x05, 0x07, 0x07, 0x08, 0x05, 0x09, 0x08, 0x05, 0x05, 0x07, 0x07, 0x08, 0x05, 0x09, 0x08,
+ 0x05, 0x05, 0x08, 0x08, 0x09, 0x05, 0x0A, 0x09, 0x06, 0x06, 0x08, 0x08, 0x09, 0x05, 0x0A, 0x09,
+ 0x06, 0x06, 0x08, 0x08, 0x09, 0x05, 0x0A, 0x09, 0x06, 0x06, 0x08, 0x08, 0x09, 0x05, 0x0A, 0x09,
+ 0x06, 0x06, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+ 0x03, 0x03, 0x03, 0x03
+};
+
+const uint8 IgorEngine::_mouseCursorMask[] = {
+ 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00
+};
+
+const uint8 IgorEngine::_mouseCursorData[] = {
+ 0x00, 0xFC, 0x00, 0x04, 0xFD, 0x00, 0x03, 0xFE, 0x02, 0xFB, 0xFC, 0xFD, 0x03, 0x04, 0x05, 0xFE,
+ 0x02, 0xFD, 0x00, 0x03, 0xFC, 0x00, 0x04, 0x00, 0xFB, 0xFC, 0xFC, 0xFC, 0xFD, 0xFD, 0xFD, 0xFE,
+ 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05
+};
+
+const uint32 IgorEngine::_fdsOffsetsTable[] = {
+ 0x000000, 0x000001, 0x000002, 0x0018E4, 0x003301, 0x003302, 0x003303, 0x003304,
+ 0x003305, 0x003306, 0x003307, 0x003308, 0x003309, 0x003EEB, 0x005908, 0x005909,
+ 0x00590A, 0x01542C, 0x016418, 0x016419, 0x01D37F, 0x01E4A1, 0x01F42C, 0x01F95F,
+ 0x026B80, 0x026B81, 0x026B82, 0x026B83, 0x026B84, 0x026B85, 0x026B86, 0x026B87,
+ 0x026B88, 0x02CA59, 0x02DD76, 0x02ED6A, 0x02ED6B, 0x02ED6C, 0x02ED6D, 0x02ED6E,
+ 0x02ED6F, 0x02ED70, 0x02ED71, 0x02ED72, 0x02ED73, 0x047F4F, 0x047F50, 0x04AC64,
+ 0x04EFC5, 0x052755, 0x052756, 0x052988, 0x058119, 0x05811A, 0x06202A, 0x06202B,
+ 0x06202C, 0x06202D, 0x06202E, 0x06202F, 0x062030, 0x062031, 0x070CB2
+};
+
+const ResourceEntry IgorEngine::_resourceEntriesTable[] = {
+#include "resource_tbl.h"
+};
+
+const int IgorEngine::_resourceEntriesCount = ARRAYSIZE(_resourceEntriesTable);
+
+const uint8 IgorEngine::PAL_48_1[] = {
+ 0x2D, 0x16, 0x00, 0x3D, 0x26, 0x01, 0x32, 0x32, 0x24, 0x16, 0x1D, 0x16, 0x12, 0x19, 0x12, 0x0B,
+ 0x12, 0x0B, 0x32, 0x32, 0x24, 0x16, 0x1D, 0x16, 0x12, 0x19, 0x12, 0x0B, 0x12, 0x0B, 0x3D, 0x3D,
+ 0x3D, 0x3D, 0x26, 0x01, 0x36, 0x1F, 0x01, 0x2D, 0x16, 0x00, 0x0F, 0x08, 0x00, 0x3F, 0x3F, 0x3F
+};
+
+const uint8 IgorEngine::PAL_96_1[] = {
+ 0x00, 0x00, 0x00, 0x18, 0x00, 0x19, 0x00, 0x00, 0x1D, 0x00, 0x03, 0x21, 0x00, 0x09, 0x26, 0x00,
+ 0x11, 0x2B, 0x00, 0x00, 0x32, 0x00, 0x16, 0x00, 0x03, 0x1F, 0x00, 0x00, 0x21, 0x0C, 0x14, 0x23,
+ 0x00, 0x00, 0x27, 0x19, 0x18, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x26, 0x00, 0x00, 0x30, 0x00, 0x00,
+ 0x32, 0x0D, 0x00, 0x32, 0x19, 0x00, 0x33, 0x21, 0x00, 0x32, 0x28, 0x00, 0x3F, 0x3A, 0x18, 0x3F,
+ 0x3F, 0x33, 0x38, 0x38, 0x38, 0x2E, 0x2E, 0x2E, 0x1C, 0x1C, 0x1C, 0x12, 0x12, 0x12, 0x06, 0x06,
+ 0x06, 0x0E, 0x05, 0x00, 0x1D, 0x0D, 0x02, 0x2A, 0x17, 0x00, 0x2A, 0x1E, 0x16, 0x31, 0x27, 0x23
+};
+
+const uint8 IgorEngine::PAL_IGOR_1[] = {
+ 0x35, 0x1F, 0x17, 0x30, 0x19, 0x10, 0x25, 0x13, 0x0B, 0x1D, 0x0E, 0x05, 0x06, 0x06, 0x06, 0x3E,
+ 0x3E, 0x3E, 0x27, 0x1A, 0x00, 0x35, 0x27, 0x06, 0x2B, 0x26, 0x23, 0x25, 0x20, 0x1D, 0x1D, 0x1A,
+ 0x17, 0x06, 0x0B, 0x14, 0x04, 0x08, 0x0E, 0x02, 0x05, 0x09, 0x01, 0x02, 0x04, 0x25, 0x05, 0x05
+};
+
+const uint8 IgorEngine::PAL_IGOR_2[] = {
+ 0x34, 0x1F, 0x17, 0x30, 0x19, 0x11, 0x25, 0x13, 0x0B, 0x1D, 0x0E, 0x05, 0x06, 0x06, 0x06, 0x3D,
+ 0x3D, 0x3D, 0x27, 0x1A, 0x00, 0x1C, 0x0F, 0x00, 0x2B, 0x26, 0x23, 0x25, 0x20, 0x1D, 0x1D, 0x19,
+ 0x17, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+const uint8 IgorEngine::INVENTORY_IMG_INIT[] = {
+ 1, 2, 40, 4, 5, 6, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20, 22, 23, 24, 25, 26, 27, 29, 30,
+ 31, 32, 33, 34, 36, 37, 28, 21, 38, 3
+};
+
+const RoomDataOffsets IgorEngine::PART_04_ROOM_DATA_OFFSETS = {
+ { 0, 0, 0, 0 },
+ { 0, 0 },
+ { 23, 231, 3247, 127, 203, 84 },
+ { 0, 0, 0, 0, 0 }
+};
+
+const RoomDataOffsets IgorEngine::PART_05_ROOM_DATA_OFFSETS = {
+ { 125, 5, 20, 4 },
+ { 253, 262 },
+ { 265, 437, 3313, 329, 405, 80 },
+ { 0, 0, 0, 0, 0 }
+};
+
+const RoomDataOffsets IgorEngine::PART_06_ROOM_DATA_OFFSETS = {
+ { 45, 3, 6, 2 },
+ { 75, 84 },
+ { 87, 259, 3135, 151, 227, 80 },
+ { 135, 30, 5158, 100, 60 }
+};
+
+const RoomDataOffsets IgorEngine::PART_12_ROOM_DATA_OFFSETS = {
+ { 45, 3, 6, 2 },
+ { 75, 84 },
+ { 87, 259, 3135, 151, 227, 80 },
+ { -85, 15, 2478, 25, 30 }
+};
+
+const RoomDataOffsets IgorEngine::PART_13_ROOM_DATA_OFFSETS = {
+ { 20, 2, 2, 1 },
+ { 31, 40 },
+ { 43, 215, 3091, 107, 183, 80 },
+ { 0, 0, 0, 0, 0 }
+};
+
+const RoomDataOffsets IgorEngine::PART_14_ROOM_DATA_OFFSETS = {
+ { 20, 2, 2, 1 },
+ { 32, 43 },
+ { 47, 237, 3183, 131, 207, 82 },
+ { 0, 0, 0, 0, 0 }
+};
+
+const RoomDataOffsets IgorEngine::PART_15_ROOM_DATA_OFFSETS = {
+ { 0, 0, 0, 0 },
+ { 3, 12 },
+ { 15, 187, 3063, 79, 155, 80 },
+ { 45, 22, 3756, 66, 60 }
+};
+
+const RoomDataOffsets IgorEngine::PART_16_ROOM_DATA_OFFSETS = {
+ { 20, 2, 2, 1 },
+ { 29, 34 },
+ { 35, 171, 2907, 59, 135, 76 },
+ { 0, 0, 0, 0, 0 }
+};
+
+const RoomDataOffsets IgorEngine::PART_17_ROOM_DATA_OFFSETS = {
+ { 320, 8, 56, 7 },
+ { 835, 844 },
+ { 847, 1019, 3895, 911, 987, 80 },
+ { -174, 5, 257, 1, 30 }
+};
+
+const RoomDataOffsets IgorEngine::PART_18_ROOM_DATA_OFFSETS = {
+ { 20, 2, 2, 1 },
+ { 34, 49 },
+ { 55, 281, 3367, 179, 255, 86 },
+ { 0, 0, 0, 0, 0 }
+};
+
+const RoomDataOffsets IgorEngine::PART_19_ROOM_DATA_OFFSETS = {
+ { 20, 2, 2, 1 },
+ { 33, 46 },
+ { 51, 259, 3359, 155, 231, 84 },
+ { 0, 0, 0, 0, 0 }
+};
+
+const RoomDataOffsets IgorEngine::PART_21_ROOM_DATA_OFFSETS = {
+ { 0, 0, 0, 0 },
+ { 5, 18 },
+ { 23, 231, 3247, 127, 203, 84 },
+ { -85, 10, 1658, 50, 30 }
+};
+
+const RoomDataOffsets IgorEngine::PART_22_ROOM_DATA_OFFSETS = {
+ { 0, 0, 0, 0 },
+ { 1, 6 },
+ { 7, 143, 2879, 31, 107, 76 },
+ { 0, 0, 0, 0, 0 }
+};
+
+const RoomDataOffsets IgorEngine::PART_23_ROOM_DATA_OFFSETS = {
+ { 0, 0, 0, 0 },
+ { 4, 15 },
+ { 19, 209, 3155, 103, 179, 82 },
+ { 0, 0, 0, 0, 0 }
+};
+
+const RoomDataOffsets IgorEngine::PART_24_ROOM_DATA_OFFSETS = {
+ { 0, 0, 0, 0 },
+ { 5, 18 },
+ { 23, 235, 3111, 127, 203, 80 },
+ { 0, 0, 0, 0, 0 }
+};
+
+const RoomDataOffsets IgorEngine::PART_25_ROOM_DATA_OFFSETS = {
+ { 20, 2, 2, 1 },
+ { 31, 40 },
+ { 43, 215, 3091, 107, 183, 80 },
+ { 0, 0, 0, 0, 0 }
+};
+
+const RoomDataOffsets IgorEngine::PART_26_ROOM_DATA_OFFSETS = {
+ { 20, 2, 2, 1 },
+ { 32, 43 },
+ { 47, 237, 3183, 131, 207, 82 },
+ { 0, 0, 0, 0, 0 }
+};
+
+const RoomDataOffsets IgorEngine::PART_27_ROOM_DATA_OFFSETS = {
+ { 0, 0, 0, 0 },
+ { 6, 21 },
+ { 27, 253, 3339, 151, 227, 86 },
+ { 0, 0, 0, 0, 0 }
+};
+
+const RoomDataOffsets IgorEngine::PART_28_ROOM_DATA_OFFSETS = {
+ { 45, 3, 6, 2 },
+ { 78, 93 },
+ { 99, 325, 3411, 223, 299, 86 },
+ { 0, 0, 0, 0, 0 }
+};
+
+const RoomDataOffsets IgorEngine::PART_30_ROOM_DATA_OFFSETS = {
+ { 45, 3, 6, 2 },
+ { 75, 84 },
+ { 87, 259, 3135, 151, 227, 80 },
+ { -90, 9, 1489, 11, 30 }
+};
+
+const RoomDataOffsets IgorEngine::PART_31_ROOM_DATA_OFFSETS = {
+ { 45, 3, 6, 2 },
+ { 79, 96 },
+ { 103, 351, 3367, 247, 323, 84 },
+ { 0, 0, 0, 0, 0 }
+};
+
+const RoomDataOffsets IgorEngine::PART_33_ROOM_DATA_OFFSETS = {
+ { 180, 6, 30, 5 },
+ { 405, 426 },
+ { 435, 715, 4011, 619, 695, 92 },
+ { -46, 9, 1533, 19, 60 }
+};
+
+const RoomDataOffsets IgorEngine::PART_36_ROOM_DATA_OFFSETS = {
+ { 45, 3, 6, 2 },
+ { 77, 90 },
+ { 95, 303, 3319, 199, 275, 84 },
+ { 0, 0, 0, 0, 0 }
+};
+
+const RoomDataOffsets IgorEngine::PART_37_ROOM_DATA_OFFSETS = {
+ { 45, 3, 6, 2 },
+ { 75, 84 },
+ { 87, 259, 3135, 151, 227, 80 },
+ { 0, 0, 0, 0, 0 }
+};
+
+} // namespace Igor