aboutsummaryrefslogtreecommitdiff
path: root/engines/kyra/kyra_v2.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/kyra/kyra_v2.cpp')
-rw-r--r--engines/kyra/kyra_v2.cpp1187
1 files changed, 1175 insertions, 12 deletions
diff --git a/engines/kyra/kyra_v2.cpp b/engines/kyra/kyra_v2.cpp
index 6857b3ac09..317fd218b2 100644
--- a/engines/kyra/kyra_v2.cpp
+++ b/engines/kyra/kyra_v2.cpp
@@ -29,29 +29,64 @@
#include "kyra/resource.h"
#include "kyra/wsamovie.h"
#include "kyra/sound.h"
+#include "kyra/script.h"
+#include "kyra/text.h"
+#include "kyra/timer.h"
#include "common/system.h"
namespace Kyra {
KyraEngine_v2::KyraEngine_v2(OSystem *system, const GameFlags &flags) : KyraEngine(system, flags) {
- memset(_gameShapes, 0, sizeof(_gameShapes));
+ memset(_defaultShapeTable, 0, sizeof(_defaultShapeTable));
_mouseSHPBuf = 0;
+
+ _gamePlayBuffer = 0;
+ _cCodeBuffer = _optionsBuffer = _chapterBuffer = 0;
+
+ _overwriteSceneFacing = false;
+ _mainCharX = _mainCharY = -1;
+ _drawNoShapeFlag = false;
+ _charPalEntry = 0;
+ _itemInHand = -1;
+ _unkSceneScreenFlag1 = false;
+ _noScriptEnter = true;
+ _currentChapter = 0;
+ _newChapterFile = 1;
+ _handItemSet = -1;
+ _lastProcessedSceneScript = 0;
+ _specialSceneScriptRunFlag = false;
+ memset(_animObjects, 0, sizeof(_animObjects));
+ _unkHandleSceneChangeFlag = false;
+ _pathfinderFlag = 0;
+
+ memset(&_sceneScriptData, 0, sizeof(_sceneScriptData));
}
KyraEngine_v2::~KyraEngine_v2() {
delete [] _mouseSHPBuf;
+ delete _screen;
+}
+
+Movie *KyraEngine_v2::createWSAMovie() {
+ return new WSAMovieV2(this);
}
int KyraEngine_v2::init() {
+ _screen = new Screen_v2(this, _system);
+ assert(_screen);
+ if (!_screen->init())
+ error("_screen->init() failed");
+
KyraEngine::init();
+
+ setupTimers();
- if (_res->getFileSize("6.FNT"))
- _screen->loadFont(Screen::FID_6_FNT, "6.FNT");
- if (_res->getFileSize("8FAT.FNT"))
- _screen->loadFont(Screen::FID_8_FNT, "8FAT.FNT");
- _screen->loadFont(Screen::FID_GOLDFONT_FNT, "GOLDFONT.FNT");
- _screen->setAnimBlockPtr(3500);
+ _screen->loadFont(_screen->FID_6_FNT, "6.FNT");
+ _screen->loadFont(_screen->FID_8_FNT, "8FAT.FNT");
+ _screen->loadFont(_screen->FID_GOLDFONT_FNT, "GOLDFONT.FNT");
+ _screen->loadFont(_screen->FID_BOOKFONT_FNT, "BOOKFONT.FNT");
+ _screen->setAnimBlockPtr(3504);
_screen->setScreenDim(0);
assert(_introStringsSize == 21);
@@ -66,11 +101,11 @@ int KyraEngine_v2::init() {
assert(_mouseSHPBuf);
for (int i = 0; i < 2; i++) {
- _gameShapes[i] = _screen->getPtrToShape(_mouseSHPBuf, i);
- assert(_gameShapes[i]);
+ _defaultShapeTable[i] = _screen->getPtrToShape(_mouseSHPBuf, i);
+ assert(_defaultShapeTable[i]);
}
- _screen->setMouseCursor(0, 0, _gameShapes[0]);
+ _screen->setMouseCursor(0, 0, _defaultShapeTable[0]);
return 0;
}
@@ -95,7 +130,7 @@ int KyraEngine_v2::go() {
_res->unloadPakFile("OUTFARM.PAK");
_res->unloadPakFile("FLYTRAP.PAK");
- seq_playSequences(kSequenceVirgin, kSequenceWestwood);
+ //seq_playSequences(kSequenceVirgin, kSequenceWestwood);
mainMenu();
return 0;
@@ -110,6 +145,11 @@ void KyraEngine_v2::mainMenu() {
switch (gui_handleMainMenu()) {
case 0:
+ _screen->showMouse();
+ startup();
+ runLoop();
+ cleanup();
+ running = false;
break;
case 1:
seq_playSequences(kSequenceOverview, kSequenceZanFaun);
@@ -123,7 +163,1130 @@ void KyraEngine_v2::mainMenu() {
break;
}
_screen->hideMouse();
- }
+ }
+}
+
+void KyraEngine_v2::startup() {
+ _screen->_curPage = 0;
+ delete [] _mouseSHPBuf;
+ _mouseSHPBuf = 0;
+
+ memset(_defaultShapeTable, 0, sizeof(_defaultShapeTable));
+ memset(_sceneShapeTable, 0, sizeof(_sceneShapeTable));
+ _gamePlayBuffer = new uint8[46080];
+ _unkBuf500Bytes = new uint8[500];
+
+ loadMouseShapes();
+ loadItemShapes();
+
+ _screen->setMouseCursor(0, 0, getShapePtr(0));
+
+ _screenBuffer = new uint8[64000];
+
+ loadCCodeBuffer("C_CODE.XXX");
+ loadOptionsBuffer("OPTIONS.XXX");
+ loadChapterBuffer(_newChapterFile);
+
+ _unkBuf200kByte = new uint8[200000];
+
+ showMessageFromCCode(265, 150, 0);
+
+ // XXX
+
+ showMessageFromCCode(0, 0, 207);
+
+ // XXX
+
+ _screen->setShapePages(5, 3);
+
+ memset(&_mainCharacter, 0, sizeof(_mainCharacter));
+ _mainCharacter.height = 0x30;
+ _mainCharacter.facing = 4;
+ _mainCharacter.animFrame = 0x12;
+ memset(_mainCharacter.inventory, -1, sizeof(_mainCharacter.inventory));
+
+ memset(_sceneAnims, 0, sizeof(_sceneAnims));
+ for (int i = 0; i < ARRAYSIZE(_sceneAnimMovie); ++i)
+ _sceneAnimMovie[i] = new WSAMovieV2(this);
+ memset(_wsaSlots, 0, sizeof(_wsaSlots));
+ for (int i = 0; i < ARRAYSIZE(_wsaSlots); ++i)
+ _wsaSlots[i] = new WSAMovieV2(this);
+
+ _maskPage = 0;//_screen->getPagePtr(5);
+ _screen->_curPage = 0;
+
+ _objectList = new Object[72];
+ memset(_objectList, 0, sizeof(Object)*72);
+ _shapeDescTable = new ShapeDesc[55];
+ memset(_shapeDescTable, 0, sizeof(ShapeDesc)*55);
+
+ for (int i = 9; i <= 32; ++i) {
+ _shapeDescTable[i-9].unk5 = 30;
+ _shapeDescTable[i-9].unk7 = 55;
+ _shapeDescTable[i-9].xAdd = -15;
+ _shapeDescTable[i-9].yAdd = -50;
+ }
+
+ for (int i = 19; i <= 24; ++i) {
+ _shapeDescTable[i-9].unk7 = 53;
+ _shapeDescTable[i-9].yAdd = -51;
+ }
+
+ _gfxBackUpRect = new uint8[_screen->getRectSize(32, 32)];
+ _itemList = new Item[30];
+ resetItemList();
+ //loadButtonShapes();
+ _loadedZTable = 1;
+ loadZShapes(_loadedZTable);
+ loadInventoryShapes();
+
+ _res->loadFileToBuf("PALETTE.COL", _screen->_currentPalette, 0x300);
+ _screen->loadBitmap("_PLAYFLD.CPS", 3, 3, 0);
+ _screen->copyPage(3, 0);
+ _screen->showMouse();
+ _screen->hideMouse();
+
+ clearAnimObjects();
+
+ // XXX
+
+ _sceneList = new SceneDesc[86];
+ runStartScript(1, 0);
+ loadNPCScript();
+
+ // XXX
+
+ enterNewScene(_mainCharacter.sceneId, _mainCharacter.facing, 0, 0, 1);
+ _screen->showMouse();
+
+ //sub_20EE8(1);
+ //setNextIdleAnimTimer();
+ //XXX
+ _timer->setDelay(0, 5);
+}
+
+void KyraEngine_v2::runLoop() {
+ _screen->updateScreen();
+
+ _quitFlag = false;
+ while (!_quitFlag) {
+ //XXX
+ int inputFlag = checkInput(0/*dword_324C5*/);
+ update();
+ if (inputFlag == 198 || inputFlag == 199) {
+ _unk3 = _handItemSet;
+ Common::Point mouse = getMousePos();
+ handleInput(mouse.x, mouse.y);
+ }
+ //XXX
+ }
+}
+
+void KyraEngine_v2::handleInput(int x, int y) {
+ //setNextIdleAnimTimer();
+ if (_unk5) {
+ _unk5 = 0;
+ return;
+ }
+
+ if (!_screen->isMouseVisible())
+ return;
+
+ if (_unk3 == -2) {
+ //snd_playSfx(13);
+ return;
+ }
+
+ //setNextIdleAnimTimer();
+
+ if (x <= 6 || x >= 312 || y <= 6 || y >= 135) {
+ bool exitOk = false;
+ assert(_unk3 + 6 >= 0);
+ switch (_unk3 + 6) {
+ case 0:
+ if (_sceneExit1 != 0xFFFF)
+ exitOk = true;
+ break;
+
+ case 1:
+ if (_sceneExit2 != 0xFFFF)
+ exitOk = true;
+ break;
+
+ case 2:
+ if (_sceneExit3 != 0xFFFF)
+ exitOk = true;
+ break;
+
+ case 3:
+ if (_sceneExit4 != 0xFFFF)
+ exitOk = true;
+ break;
+
+ default:
+ break;
+ }
+
+ if (exitOk) {
+ inputSceneChange(x, y, 1, 1);
+ return;
+ }
+ }
+
+ if (checkCharCollision(x, y) >= 0 && _unk3 >= -1) {
+ runSceneScript2();
+ return;
+ } else {
+ //XXX
+ }
+
+ //XXX
+
+ inputSceneChange(x, y, 1, 1);
+}
+
+int KyraEngine_v2::update() {
+ refreshAnimObjectsIfNeed();
+ updateMouse();
+ updateSpecialSceneScripts();
+ _timer->update();
+ //sub_274C0();
+ //updateInvWsa();
+ //sub_1574C();
+ //XXX
+ _screen->updateScreen();
+ return 0;
+}
+
+void KyraEngine_v2::updateMouse() {
+ int shapeIndex = 0;
+ int type = 0;
+ int xOffset = 0, yOffset = 0;
+ Common::Point mouse = getMousePos();
+
+ if (mouse.y <= 145) {
+ if (mouse.x <= 6) {
+ if (_sceneExit4 != 0xFFFF) {
+ type = -3;
+ shapeIndex = 4;
+ xOffset = 1;
+ yOffset = 5;
+ } else {
+ type = -2;
+ }
+ } else if (mouse.x >= 312) {
+ if (_sceneExit2 != 0xFFFF) {
+ type = -5;
+ shapeIndex = 2;
+ xOffset = 7;
+ yOffset = 5;
+ } else {
+ type = -2;
+ }
+ } else if (mouse.y >= 135) {
+ if (_sceneExit3 != 0xFFFF) {
+ type = -4;
+ shapeIndex = 3;
+ xOffset = 5;
+ yOffset = 10;
+ } else {
+ type = -2;
+ }
+ } else if (mouse.y <= 6) {
+ if (_sceneExit1 != 0xFFFF) {
+ type = -6;
+ shapeIndex = 1;
+ xOffset = 5;
+ yOffset = 1;
+ } else {
+ type = -2;
+ }
+ }
+ }
+
+ for (int i = 0; i < _specialExitCount; ++i) {
+ if (checkSpecialSceneExit(i, mouse.x, mouse.y)) {
+ switch (_specialExitTable[20+i]) {
+ case 0:
+ type = -6;
+ shapeIndex = 1;
+ xOffset = 5;
+ yOffset = 1;
+ break;
+
+ case 2:
+ type = -5;
+ shapeIndex = 2;
+ xOffset = 7;
+ yOffset = 5;
+ break;
+
+ case 4:
+ type = -4;
+ shapeIndex = 3;
+ xOffset = 5;
+ yOffset = 7;
+ break;
+
+ case 6:
+ type = -3;
+ shapeIndex = 4;
+ xOffset = 1;
+ yOffset = 5;
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ if (type == -2) {
+ shapeIndex = 5;
+ xOffset = 5;
+ yOffset = 9;
+ }
+
+ if (type != 0 && _handItemSet != type) {
+ _handItemSet = type;
+ _screen->hideMouse();
+ _screen->setMouseCursor(xOffset, yOffset, getShapePtr(shapeIndex));
+ _screen->showMouse();
+ }
+
+ if (type == 0 && _handItemSet != _itemInHand) {
+ if ((mouse.y > 145) || (mouse.x > 6 && mouse.x < 312 && mouse.y > 6 && mouse.y < 135)) {
+ _handItemSet = _itemInHand;
+ _screen->hideMouse();
+ if (_itemInHand == -1)
+ _screen->setMouseCursor(0, 0, getShapePtr(0));
+ else
+ _screen->setMouseCursor(8, 15, getShapePtr(_itemInHand+64));
+ _screen->showMouse();
+ }
+ }
+}
+
+int KyraEngine_v2::checkInput(void *p) {
+ Common::Event event;
+ int keys = 0;
+ while (_eventMan->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_KEYDOWN:
+ if (event.kbd.keycode == Common::KEYCODE_RETURN)
+ keys = 199;
+ break;
+
+ case Common::EVENT_LBUTTONUP:
+ keys = 198;
+ break;
+
+ case Common::EVENT_QUIT:
+ _quitFlag = true;
+ break;
+
+ default:
+ break;
+ }
+
+ //if ( _debugger->isAttached())
+ // _debugger->onFrame();
+ }
+
+ _system->delayMillis(10);
+ return keys;
+}
+
+void KyraEngine_v2::cleanup() {
+ delete [] _gamePlayBuffer;
+ delete [] _unkBuf500Bytes;
+ delete [] _screenBuffer;
+ delete [] _unkBuf200kByte;
+
+ for (int i = 0; i < ARRAYSIZE(_defaultShapeTable); ++i)
+ delete [] _defaultShapeTable[i];
+ freeSceneShapePtrs();
+
+ delete [] _cCodeBuffer;
+ delete [] _optionsBuffer;
+ delete [] _chapterBuffer;
+
+ delete [] _objectList;
+ delete [] _shapeDescTable;
+
+ delete [] _gfxBackUpRect;
+
+ delete [] _sceneList;
+
+ for (int i = 0; i < ARRAYSIZE(_sceneAnimMovie); ++i)
+ delete _sceneAnimMovie[i];
+ for (int i = 0; i < ARRAYSIZE(_wsaSlots); ++i)
+ delete _wsaSlots[i];
+}
+
+#pragma mark - Localization
+
+void KyraEngine_v2::loadCCodeBuffer(const char *file) {
+ char tempString[13];
+ strcpy(tempString, file);
+ changeFileExtension(tempString);
+
+ delete [] _cCodeBuffer;
+ _cCodeBuffer = _res->fileData(tempString, 0);
+}
+
+void KyraEngine_v2::loadOptionsBuffer(const char *file) {
+ char tempString[13];
+ strcpy(tempString, file);
+ changeFileExtension(tempString);
+
+ delete [] _optionsBuffer;
+ _optionsBuffer = _res->fileData(tempString, 0);
+}
+
+void KyraEngine_v2::loadChapterBuffer(int chapter) {
+ char tempString[14];
+
+ static const char *chapterFilenames[] = {
+ "CH1.XXX", "CH2.XXX", "CH3.XXX", "CH4.XXX", "CH5.XXX"
+ };
+
+ assert(chapter >= 1 && chapter <= ARRAYSIZE(chapterFilenames));
+ strcpy(tempString, chapterFilenames[chapter-1]);
+ changeFileExtension(tempString);
+
+ delete [] _chapterBuffer;
+ _chapterBuffer = _res->fileData(tempString, 0);
+ _currentChapter = chapter;
+}
+
+void KyraEngine_v2::changeFileExtension(char *buffer) {
+ while (*buffer != '.') ++buffer;
+
+ ++buffer;
+ strcpy(buffer, _languageExtension[_lang]);
+}
+
+const uint8 *KyraEngine_v2::getTableEntry(const uint8 *buffer, int id) {
+ return buffer + READ_LE_UINT16(buffer + (id<<1));
+}
+
+const char *KyraEngine_v2::getTableString(int id, const uint8 *buffer, int decode) {
+ const char *string = (const char*)getTableEntry(buffer, id);
+
+ if (decode) {
+ decodeString1(string, _internStringBuf);
+ decodeString2(_internStringBuf, _internStringBuf);
+ string = _internStringBuf;
+ }
+
+ return string;
+}
+
+const char *KyraEngine_v2::getChapterString(int id) {
+ if (_currentChapter != _newChapterFile)
+ loadChapterBuffer(_newChapterFile);
+
+ return getTableString(id, _chapterBuffer, 1);
+}
+
+int KyraEngine_v2::decodeString1(const char *src, char *dst) {
+ static const uint8 decodeTable1[] = {
+ 0x20, 0x65, 0x74, 0x61, 0x69, 0x6E, 0x6F, 0x73, 0x72, 0x6C, 0x68,
+ 0x63, 0x64, 0x75, 0x70, 0x6D
+ };
+
+ static const uint8 decodeTable2[] = {
+ 0x74, 0x61, 0x73, 0x69, 0x6F, 0x20, 0x77, 0x62, 0x20, 0x72, 0x6E,
+ 0x73, 0x64, 0x61, 0x6C, 0x6D, 0x68, 0x20, 0x69, 0x65, 0x6F, 0x72,
+ 0x61, 0x73, 0x6E, 0x72, 0x74, 0x6C, 0x63, 0x20, 0x73, 0x79, 0x6E,
+ 0x73, 0x74, 0x63, 0x6C, 0x6F, 0x65, 0x72, 0x20, 0x64, 0x74, 0x67,
+ 0x65, 0x73, 0x69, 0x6F, 0x6E, 0x72, 0x20, 0x75, 0x66, 0x6D, 0x73,
+ 0x77, 0x20, 0x74, 0x65, 0x70, 0x2E, 0x69, 0x63, 0x61, 0x65, 0x20,
+ 0x6F, 0x69, 0x61, 0x64, 0x75, 0x72, 0x20, 0x6C, 0x61, 0x65, 0x69,
+ 0x79, 0x6F, 0x64, 0x65, 0x69, 0x61, 0x20, 0x6F, 0x74, 0x72, 0x75,
+ 0x65, 0x74, 0x6F, 0x61, 0x6B, 0x68, 0x6C, 0x72, 0x20, 0x65, 0x69,
+ 0x75, 0x2C, 0x2E, 0x6F, 0x61, 0x6E, 0x73, 0x72, 0x63, 0x74, 0x6C,
+ 0x61, 0x69, 0x6C, 0x65, 0x6F, 0x69, 0x72, 0x61, 0x74, 0x70, 0x65,
+ 0x61, 0x6F, 0x69, 0x70, 0x20, 0x62, 0x6D
+ };
+
+ int size = 0;
+ uint cChar = 0;
+ while ((cChar = *src++) != 0) {
+ if (cChar & 0x80) {
+ cChar &= 0x7F;
+ int index = (cChar & 0x78) >> 3;
+ *dst++ = decodeTable1[index];
+ ++size;
+ assert(cChar < sizeof(decodeTable2));
+ cChar = decodeTable2[cChar];
+ }
+
+ *dst++ = cChar;
+ ++size;
+ }
+
+ *dst++ = 0;
+ return size;
+}
+
+void KyraEngine_v2::decodeString2(const char *src, char *dst) {
+ if (!src || !dst)
+ return;
+
+ char out = 0;
+ while ((out = *src) != 0) {
+ if (*src == 0x1B) {
+ ++src;
+ out = *src + 0x7F;
+ }
+ *dst++ = out;
+ ++src;
+ }
+
+ *dst = 0;
+}
+
+#pragma mark -
+
+void KyraEngine_v2::showMessageFromCCode(int id, int16 palIndex, int) {
+ const char *string = getTableString(id, _cCodeBuffer, 1);
+ showMessage(string, palIndex);
+}
+
+void KyraEngine_v2::showMessage(const char *string, int16 palIndex) {
+ _shownMessage = string;
+ _screen->hideMouse();
+ _screen->fillRect(0, 190, 319, 199, 0xCF);
+
+ if (string) {
+ if (palIndex != -1 || _msgUnk1) {
+ palIndex *= 3;
+ memcpy(_messagePal, _screen->_currentPalette + palIndex, 3);
+ memmove(_screen->_currentPalette + 765, _screen->_currentPalette + palIndex, 3);
+ _screen->setScreenPalette(_screen->_currentPalette);
+ }
+
+ int x = _text->getCenterStringX(string, 0, 320);
+ _text->printText(string, x, 190, 255, 207, 0);
+
+ setTimer1DelaySecs(7);
+ }
+
+ _msgUnk1 = 0;
+ _screen->showMouse();
+}
+
+void KyraEngine_v2::showChapterMessage(int id, int16 palIndex) {
+ showMessage(getChapterString(id), palIndex);
+}
+
+void KyraEngine_v2::loadMouseShapes() {
+ _screen->loadBitmap("_MOUSE.CSH", 3, 3, 0);
+
+ for (int i = 0; i <= 8; ++i) {
+ _defaultShapeTable[i] = _screen->makeShapeCopy(_screen->getCPagePtr(3), i);
+ assert(_defaultShapeTable[i]);
+ }
+}
+
+void KyraEngine_v2::loadItemShapes() {
+ _screen->loadBitmap("_ITEMS.CSH", 3, 3, 0);
+
+ for (int i = 64; i <= 239; ++i) {
+ _defaultShapeTable[i] = _screen->makeShapeCopy(_screen->getCPagePtr(3), i-64);
+ assert(_defaultShapeTable[i]);
+ }
+
+ _res->loadFileToBuf("_ITEMHT.DAT", _itemHtDat, sizeof(_itemHtDat));
+ assert(_res->getFileSize("_ITEMHT.DAT") == sizeof(_itemHtDat));
+
+ _screen->_curPage = 0;
+}
+
+void KyraEngine_v2::loadZShapes(int shapes) {
+ char file[10];
+ strcpy(file, "_ZX.SHP");
+
+ _loadedZTable = shapes;
+ file[2] = '0' + shapes;
+
+ uint8 *data = _res->fileData(file, 0);
+ for (int i = 9; i <= 32; ++i) {
+ delete [] _defaultShapeTable[i];
+ _defaultShapeTable[i] = _screen->makeShapeCopy(data, i-9);
+ }
+ delete [] data;
+
+ _loadedZTable = shapes;
+}
+
+void KyraEngine_v2::loadInventoryShapes() {
+ int curPageBackUp = _screen->_curPage;
+ _screen->_curPage = 2;
+
+ _screen->loadBitmap("_PLAYALL.CPS", 3, 3, 0);
+
+ for (int i = 0; i < 10; ++i)
+ _defaultShapeTable[240+i] = _screen->encodeShape(_inventoryX[i], _inventoryY[i], 16, 16, 0);
+
+ _screen->_curPage = curPageBackUp;
+}
+
+void KyraEngine_v2::runStartScript(int script, int unk1) {
+ char filename[14];
+ strcpy(filename, "_START0X.EMC");
+ filename[7] = script + '0';
+
+ ScriptData scriptData;
+ ScriptState scriptState;
+
+ _scriptInterpreter->loadScript(filename, &scriptData, &_opcodes);
+ _scriptInterpreter->initScript(&scriptState, &scriptData);
+ scriptState.regs[6] = unk1;
+ _scriptInterpreter->startScript(&scriptState, 0);
+ while (_scriptInterpreter->validScript(&scriptState))
+ _scriptInterpreter->runScript(&scriptState);
+ _scriptInterpreter->unloadScript(&scriptData);
+}
+
+void KyraEngine_v2::loadNPCScript() {
+ char filename[12];
+ strcpy(filename, "_NPC.EMC");
+
+ switch (_lang) {
+ case 0:
+ filename[5] = 'E';
+ break;
+
+ case 1:
+ filename[5] = 'F';
+ break;
+
+ case 2:
+ filename[5] = 'G';
+ break;
+
+ default:
+ break;
+ };
+
+ _scriptInterpreter->loadScript(filename, &_npcScriptData, &_opcodes);
+}
+
+void KyraEngine_v2::resetScaleTable() {
+ for (int i = 0; i < ARRAYSIZE(_scaleTable); ++i)
+ _scaleTable[i] = 0x100;
+}
+
+void KyraEngine_v2::setScaleTableItem(int item, int data) {
+ if (item >= 1 || item <= 15)
+ _scaleTable[item-1] = (data << 8) / 100;
+}
+
+int KyraEngine_v2::getScale(int x, int y) {
+ return _scaleTable[_screen->getLayer(x, y) - 1];
+}
+
+void KyraEngine_v2::setDrawLayerTableEntry(int entry, int data) {
+ if (entry >= 1 || entry <= 15)
+ _drawLayerTable[entry-1] = data;
+}
+
+int KyraEngine_v2::getDrawLayer(int x, int y) {
+ int layer = _screen->getLayer(x, y);
+ layer = _drawLayerTable[layer-1];
+ if (layer < 0)
+ layer = 0;
+ else if (layer >= 7)
+ layer = 6;
+ return layer;
+}
+
+void KyraEngine_v2::restorePage3() {
+ _screen->copyBlockToPage(2, 0, 0, 320, 144, _gamePlayBuffer);
+}
+
+void KyraEngine_v2::updateCharPal(int unk1) {
+ static bool unkVar1 = false;
+
+ if (!_useCharPal)
+ return;
+
+ int layer = _screen->getLayer(_mainCharacter.x1, _mainCharacter.y1);
+ int palEntry = _charPalTable[layer];
+
+ if (palEntry != _charPalEntry && unk1) {
+ const uint8 *src = &_scenePal[(palEntry << 4) * 3];
+ uint8 *ptr = _screen->getPalette(0) + 336;
+ for (int i = 0; i < 48; ++i) {
+ *ptr -= (*ptr - *src) >> 1;
+ ++ptr;
+ ++src;
+ }
+ _screen->setScreenPalette(_screen->getPalette(0));
+ unkVar1 = true;
+ _charPalEntry = palEntry;
+ } else if (unkVar1 && !unk1) {
+ memcpy(_screen->getPalette(0) + 336, &_scenePal[(palEntry << 4) * 3], 48);
+ _screen->setScreenPalette(_screen->getPalette(0));
+ unkVar1 = false;
+ }
+}
+
+int KyraEngine_v2::inputSceneChange(int x, int y, int unk1, int unk2) {
+ bool refreshNPC = false;
+ uint16 curScene = _mainCharacter.sceneId;
+ _pathfinderFlag = 15;
+
+ if (!_unkHandleSceneChangeFlag) {
+ if (_unk3 == -3) {
+ if (_sceneList[curScene].exit4 != 0xFFFF) {
+ x = 4;
+ y = _sceneEnterY4;
+ _pathfinderFlag = 7;
+ }
+ } else if (_unk3 == -5) {
+ if (_sceneList[curScene].exit2 != 0xFFFF) {
+ x = 316;
+ y = _sceneEnterY2;
+ _pathfinderFlag = 7;
+ }
+ } else if (_unk3 == -6) {
+ if (_sceneList[curScene].exit1 != 0xFFFF) {
+ x = _sceneEnterX1;
+ y = _sceneEnterY1 - 2;
+ _pathfinderFlag = 14;
+ }
+ } else if (_unk3 == -4) {
+ if (_sceneList[curScene].exit3 != 0xFFFF) {
+ x = _sceneEnterX3;
+ y = 147;
+ _pathfinderFlag = 11;
+ }
+ }
+ }
+
+ if (_pathfinderFlag) {
+ if (findItem(curScene, 13) >= 0 && _unk3 <= -3) {
+ //XXX
+ _pathfinderFlag = 0;
+ return 0;
+ } else if (_itemInHand == 72) {
+ //XXX
+ _pathfinderFlag = 0;
+ return 0;
+ } else if (findItem(curScene, 72) >= 0 && _unk3 <= -3) {
+ //XXX
+ _pathfinderFlag = 0;
+ return 0;
+ } else if (0/*XXX*/) {
+ //XXX
+ _pathfinderFlag = 0;
+ return 0;
+ }
+ }
+
+ if (ABS(_mainCharacter.x1 - x) < 4 || ABS(_mainCharacter.y1 - y) < 2)
+ return 0;
+
+ int curX = _mainCharacter.x1 & ~3;
+ int curY = _mainCharacter.y1 & ~1;
+ int dstX = x & ~3;
+ int dstY = y & ~1;
+
+ int wayLength = findWay(curX, curY, dstX, dstY, _movFacingTable, 600);
+ _pathfinderFlag = 0;
+ _timer->disable(5);
+
+ if (wayLength != 0 && wayLength != 0x7D00)
+ refreshNPC = (trySceneChange(_movFacingTable, unk1, unk2) != 0);
+
+ //XXX
+
+ if (refreshNPC)
+ enterNewSceneUnk2(0);
+
+ _pathfinderFlag = 0;
+ return refreshNPC;
+}
+
+bool KyraEngine_v2::checkSpecialSceneExit(int num, int x, int y) {
+ if (_specialExitTable[0+num] > x || _specialExitTable[5+num] > y ||
+ _specialExitTable[10+num] < x || _specialExitTable[15+num] < y)
+ return 0;
+ return 1;
+}
+
+void KyraEngine_v2::moveCharacter(int facing, int x, int y) {
+ _mainCharacter.facing = facing;
+ x &= ~3;
+ y &= ~1;
+
+ _screen->hideMouse();
+ switch (facing) {
+ case 0:
+ while (y < _mainCharacter.y1)
+ updateCharPosWithUpdate();
+ break;
+
+ case 2:
+ while (_mainCharacter.x1 < x)
+ updateCharPosWithUpdate();
+ break;
+
+ case 4:
+ while (y > _mainCharacter.y1)
+ updateCharPosWithUpdate();
+ break;
+
+ case 6:
+ while (_mainCharacter.x1 > x)
+ updateCharPosWithUpdate();
+ break;
+
+ default:
+ break;
+ }
+
+ _screen->showMouse();
+}
+
+int KyraEngine_v2::updateCharPos(int *table) {
+ static uint32 nextUpdate = 0;
+ static const int updateX[] = { 0, 4, 4, 4, 0, -4, -4, -4 };
+ static const int updateY[] = { -2, -2, 0, 2, 2, 2, 0, -2 };
+
+ if (_system->getMillis() < nextUpdate)
+ return 0;
+
+ int facing = _mainCharacter.facing;
+ _mainCharacter.x1 += updateX[facing];
+ _mainCharacter.y1 += updateY[facing];
+ updateCharAnimFrame(0, table);
+ nextUpdate = _system->getMillis() + _timer->getDelay(0) * _tickLength;
+ return 1;
+}
+
+void KyraEngine_v2::updateCharPosWithUpdate() {
+ updateCharPos(0);
+ update();
+}
+
+void KyraEngine_v2::updateCharAnimFrame(int charId, int *table) {
+ static int unkTable1[] = { 0, 0 };
+ static const int unkTable2[] = { 17, 0 };
+ static const int unkTable3[] = { 10, 0 };
+ static const int unkTable4[] = { 24, 0 };
+ static const int unkTable5[] = { 19, 0 };
+ static const int unkTable6[] = { 21, 0 };
+ static const int unkTable7[] = { 31, 0 };
+ static const int unkTable8[] = { 26, 0 };
+
+ Character *character = &_mainCharacter;
+ ++character->animFrame;
+ int facing = character->facing;
+
+ if (table) {
+ if (table[0] != table[-1] && table[-1] == table[1]) {
+ facing = getOppositeFacingDirection(table[-1]);
+ table[0] = table[-1];
+ }
+ }
+
+ if (!facing) {
+ ++unkTable1[charId];
+ } else if (facing == 4) {
+ ++unkTable1[charId+1];
+ } else if (facing == 7 || facing == 1 || facing == 5 || facing == 3) {
+ if (facing == 7 || facing == 1) {
+ if (unkTable1[charId] > 2)
+ facing = 0;
+ } else {
+ if (unkTable1[charId+1] > 2)
+ facing = 4;
+ }
+
+ unkTable1[charId] = 0;
+ unkTable1[charId+1] = 0;
+ }
+
+ if (facing == 0) {
+ if (character->animFrame < unkTable8[charId])
+ character->animFrame = unkTable8[charId];
+
+ if (character->animFrame > unkTable7[charId])
+ character->animFrame = unkTable8[charId];
+ } else if (facing == 4) {
+ if (character->animFrame < unkTable5[charId])
+ character->animFrame = unkTable5[charId];
+
+ if (character->animFrame > unkTable4[charId])
+ character->animFrame = unkTable5[charId];
+ } else {
+ if (character->animFrame > unkTable5[charId])
+ character->animFrame = unkTable6[charId];
+
+ if (character->animFrame == unkTable2[charId])
+ character->animFrame = unkTable3[charId];
+
+ if (character->animFrame > unkTable2[charId])
+ character->animFrame = unkTable3[charId] + 2;
+ }
+
+ updateCharacterAnim(charId);
+}
+
+int KyraEngine_v2::checkCharCollision(int x, int y) {
+ int scale1 = 0, scale2 = 0, scale3 = 0;
+ int x1 = 0, x2 = 0, y1 = 0, y2 = 0;
+ scale1 = getScale(_mainCharacter.x1, _mainCharacter.y1);
+ scale2 = (scale1 * 24) >> 8;
+ scale3 = (scale1 * 48) >> 8;
+
+ x1 = _mainCharacter.x1 - (scale2 >> 1);
+ x2 = _mainCharacter.x1 + (scale2 >> 1);
+ y1 = _mainCharacter.y1 - scale3;
+ y2 = _mainCharacter.y1;
+
+ if (x >= x1 && x <= x2 && y >= y1 && y <= y2)
+ return 0;
+
+ return -1;
+}
+
+#pragma mark -
+
+typedef Functor1Mem<ScriptState*, int, KyraEngine_v2> OpcodeV2;
+#define Opcode(x) OpcodeV2(this, &KyraEngine_v2::x)
+#define OpcodeUnImpl() OpcodeV2(this, 0)
+void KyraEngine_v2::setupOpcodeTable() {
+ static const OpcodeV2 opcodeTable[] = {
+ // 0x00
+ Opcode(o2_setCharacterFacingRefresh),
+ OpcodeUnImpl(),
+ Opcode(o2_defineObject),
+ Opcode(o2_refreshCharacter),
+ // 0x04
+ Opcode(o2_getCharacterX),
+ Opcode(o2_getCharacterY),
+ Opcode(o2_getCharacterFacing),
+ OpcodeUnImpl(),
+ // 0x08
+ Opcode(o2_setSceneComment),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x0c
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x10
+ OpcodeUnImpl(),
+ Opcode(o2_showChapterMessage),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x14
+ Opcode(o2_wsaClose),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ Opcode(o2_displayWsaFrame),
+ // 0x18
+ Opcode(o2_displayWsaSequentialFrames),
+ Opcode(o2_wsaOpen),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x1c
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x20
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ Opcode(o2_defineItem),
+ // 0x24
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ Opcode(o2_queryGameFlag),
+ // 0x28
+ Opcode(o2_resetGameFlag),
+ Opcode(o2_setGameFlag),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x2c
+ OpcodeUnImpl(),
+ Opcode(o2_hideMouse),
+ Opcode(o2_addSpecialExit),
+ OpcodeUnImpl(),
+ // 0x30
+ Opcode(o2_showMouse),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x34
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x38
+ Opcode(o2_dummy),
+ OpcodeUnImpl(),
+ Opcode(o2_setScaleTableItem),
+ Opcode(o2_setDrawLayerTableItem),
+ // 0x3c
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ Opcode(o2_drawSceneShapeOnPage),
+ // 0x40
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ Opcode(o2_dummy),
+ OpcodeUnImpl(),
+ // 0x44
+ OpcodeUnImpl(),
+ Opcode(o2_restoreBackBuffer),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x48
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x4c
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ Opcode(o2_dummy),
+ Opcode(o2_dummy),
+ // 0x50
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x54
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x58
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x5c
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x60
+ Opcode(o2_getRand),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x64
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x68
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x6c
+ Opcode(o2_encodeShape),
+ Opcode(o2_defineRoomEntrance),
+ OpcodeUnImpl(),
+ Opcode(o2_setSpecialSceneScriptRunTime),
+ // 0x70
+ Opcode(o2_defineSceneAnim),
+ Opcode(o2_updateSceneAnim),
+ Opcode(o2_updateSceneAnim),
+ OpcodeUnImpl(),
+ // 0x74
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x78
+ OpcodeUnImpl(),
+ Opcode(o2_defineRoom),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x7c
+ OpcodeUnImpl(),
+ Opcode(o2_dummy),
+ Opcode(o2_dummy),
+ OpcodeUnImpl(),
+ // 0x80
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x84
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x88
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x8c
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ Opcode(o2_setSpecialSceneScriptState),
+ // 0x90
+ Opcode(o2_clearSpecialSceneScriptState),
+ Opcode(o2_querySpecialSceneScriptState),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x94
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ Opcode(o2_wsaClose),
+ OpcodeUnImpl(),
+ // 0x98
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x9c
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0xa0
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0xa4
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0xa8
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0xac
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ Opcode(o2_dummy),
+ Opcode(o2_dummy),
+ };
+
+ for (int i = 0; i < ARRAYSIZE(opcodeTable); ++i)
+ _opcodes.push_back(&opcodeTable[i]);
}
} // end of namespace Kyra