diff options
author | Gregory Montoir | 2007-10-29 23:35:50 +0000 |
---|---|---|
committer | Gregory Montoir | 2007-10-29 23:35:50 +0000 |
commit | 6c6e8657b68ebc075871031ee8c662f349c4ab77 (patch) | |
tree | 1e2c691ffe1d142a3e781670ac63a981ebf70114 | |
parent | caa451f5d2b471fc207739815638056f86fc8dce (diff) | |
download | scummvm-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
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) @@ -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 |