diff options
author | Johannes Schickel | 2005-10-29 18:37:40 +0000 |
---|---|---|
committer | Johannes Schickel | 2005-10-29 18:37:40 +0000 |
commit | 50cc43ba5845a1017f876bc84cd6b7d05950d8b5 (patch) | |
tree | 687449392fe1992e12c6060d5ade3b6acdda8306 | |
parent | a47cc783e47b8153dea8fa33140805ff1ee3f32b (diff) | |
download | scummvm-rg350-50cc43ba5845a1017f876bc84cd6b7d05950d8b5.tar.gz scummvm-rg350-50cc43ba5845a1017f876bc84cd6b7d05950d8b5.tar.bz2 scummvm-rg350-50cc43ba5845a1017f876bc84cd6b7d05950d8b5.zip |
Implemented some basic opcodes, and basic character drawing, also
started to change a bit of the sprite code (thanks to vinterstum for his work)
It is still WIP code and breaks CD version, since all the used tables have to
be located in one cd version binary.
svn-id: r19361
-rw-r--r-- | kyra/kyra.cpp | 1509 | ||||
-rw-r--r-- | kyra/kyra.h | 355 | ||||
-rw-r--r-- | kyra/screen.cpp | 417 | ||||
-rw-r--r-- | kyra/screen.h | 13 | ||||
-rw-r--r-- | kyra/script.cpp | 4 | ||||
-rw-r--r-- | kyra/script.h | 7 | ||||
-rw-r--r-- | kyra/script_v1.cpp | 955 | ||||
-rw-r--r-- | kyra/sprites.cpp | 85 | ||||
-rw-r--r-- | kyra/sprites.h | 11 | ||||
-rw-r--r-- | kyra/staticres.cpp | 308 |
10 files changed, 3445 insertions, 219 deletions
diff --git a/kyra/kyra.cpp b/kyra/kyra.cpp index eb48efa8c6..3d45754063 100644 --- a/kyra/kyra.cpp +++ b/kyra/kyra.cpp @@ -45,8 +45,6 @@ #include "kyra/sprites.h" #include "kyra/wsamovie.h" -#define TEST_SPRITES 1 - using namespace Kyra; enum { @@ -269,6 +267,44 @@ int KyraEngine::init(GameDetector &detector) { assert(_sprites); _seq = new SeqPlayer(this, _system); assert(_seq); + + _currentCharacter = 0; + _characterList = new Character[11]; + assert(_characterList); + for (int i = 0; i < 11; ++i) { + memset(&_characterList[i], 0, sizeof(Character)); + } + _characterList[0].sceneId = 5; + _characterList[0].height = 48; + _characterList[0].facing = 3; + _characterList[0].currentAnimFrame = 7; + + _objectQueue = 0; + _animStates = new AnimObject[31]; + assert(_animStates); + _charactersAnimState = &_animStates[0]; + _animObjects = &_animStates[5]; + _unkAnimsBuffer = &_animStates[16]; + + _scriptInterpreter = new ScriptHelper(this); + assert(_scriptInterpreter); + + _npcScriptData = new ScriptData; + memset(_npcScriptData, 0, sizeof(ScriptData)); + assert(_npcScriptData); + _scriptMain = new ScriptState; + assert(_scriptMain); + memset(_scriptMain, 0, sizeof(ScriptState)); + + _scriptClickData = new ScriptData; + assert(_scriptClickData); + memset(_scriptClickData, 0, sizeof(ScriptData)); + _scriptClick = new ScriptState; + assert(_scriptClick); + memset(_scriptClick, 0, sizeof(ScriptState)); + + memset(_shapes, 0, sizeof(_shapes)); + memset(_wsaObjects, 0, sizeof(_wsaObjects)); _fastMode = false; _talkCoords.y = 0x88; @@ -280,6 +316,16 @@ int KyraEngine::init(GameDetector &detector) { _mouseX = _mouseY = 0; _needMouseUpdate = true; + + _brandonPosX = _brandonPosY = -1; + _brandonDrawFrame = 113; + + memset(_itemTable, 0, sizeof(_itemTable)); + memset(_exitList, 0xFFFF, sizeof(_exitList)); + _exitListPtr = 0; + + _movFacingTable = new int[150]; + assert(_movFacingTable); return 0; } @@ -290,9 +336,31 @@ KyraEngine::~KyraEngine() { delete _res; delete _midi; delete _seq; + delete _scriptInterpreter; + + delete _npcScriptData; + delete _scriptMain; + + delete _scriptClickData; + delete _scriptClick; + + delete [] _animStates; + delete [] _characterList; - for (int i = 0; i < ARRAYSIZE(_itemShapes); ++i) { - free(_itemShapes[i]); + delete [] _movFacingTable; + + for (int i = 0; i < ARRAYSIZE(_shapes); ++i) { + if (_shapes[i] != 0) { + free(_shapes[i]); + for (int i2 = 0; i2 < ARRAYSIZE(_shapes); i2++) { + if (_shapes[i2] == _shapes[i] && i2 != i) { + _shapes[i2] = 0; + } + } + } + } + for (int i = 0; i < ARRAYSIZE(_sceneAnimTable); ++i) { + free(_sceneAnimTable[i]); } } @@ -330,14 +398,72 @@ void KyraEngine::startup() { _screen->setTextColorMap(colorMap); // _screen->setFont(Screen::FID_6_FNT); _screen->setAnimBlockPtr(3750); - memset(_itemShapes, 0, sizeof(_itemShapes)); + memset(_sceneAnimTable, 0, sizeof(_sceneAnimTable)); loadMouseShapes(); + _currentCharacter = &_characterList[0]; + for (int i = 1; i < 5; ++i) + setCharacterDefaultFrame(i); + for (int i = 5; i <= 10; ++i) + setCharactersPositions(i); + setCharactersHeight(); + resetBrandonPosionFlags(); + _maskBuffer = _screen->getPagePtr(5); + _screen->_curPage = 0; + // XXX + for (int i = 0; i < 0x0C; ++i) { + int size = _screen->getRectSize(3, 24); + _shapes[365+i] = (byte*)malloc(size); + } + _shapes[0] = (byte*)malloc(_screen->getRectSize(3, 24)); + memset(_shapes[0], 0, _screen->getRectSize(3, 24)); + _shapes[1] = (byte*)malloc(_screen->getRectSize(4, 32)); + memset(_shapes[1], 0, _screen->getRectSize(4, 32)); + _shapes[2] = (byte*)malloc(_screen->getRectSize(8, 69)); + memset(_shapes[2], 0, _screen->getRectSize(8, 69)); + _shapes[3] = (byte*)malloc(_screen->getRectSize(8, 69)); + memset(_shapes[3], 0, _screen->getRectSize(8, 69)); + for (int i = 0; i < _roomTableSize; ++i) { + for (int item = 0; item < 12; ++item) { + _roomTable[i].itemsTable[item] = 0xFF; + _roomTable[i].itemsXPos[item] = 0; + _roomTable[i].itemsYPos[item] = 0; + _roomTable[i].unkField3[item] = 0; + } + } + loadCharacterShapes(); + loadSpecialEffectShapes(); + loadSpecialEffectShapes(); + loadItems(); + loadMainScreen(); + loadPalette("PALETTE.COL", _screen->_currentPalette); + _screen->setScreenPalette(_screen->_currentPalette); + // XXX + _screen->showMouse(); + _screen->hideMouse(); + initAnimStateList(); + setCharactersInDefaultScene(); + + if (!_scriptInterpreter->loadScript("_STARTUP.EMC", _npcScriptData, _opcodeTable, _opcodeTableSize, 0)) { + error("Could not load \"_STARTUP.EMC\" script"); + } + _scriptInterpreter->initScript(_scriptMain, _npcScriptData); + if (!_scriptInterpreter->startScript(_scriptMain, 0)) { + error("Could not start script function 0 of script \"_STARTUP.EMC\""); + } + while (_scriptInterpreter->validScript(_scriptMain)) { + _scriptInterpreter->runScript(_scriptMain); + } + + _scriptInterpreter->unloadScript(_npcScriptData); + if (!_scriptInterpreter->loadScript("_NPC.EMC", _npcScriptData, _opcodeTable, _opcodeTableSize, 0)) { + error("Could not load \"_NPC.EMC\" script"); + } + + snd_playTheme(1); + enterNewScene(_currentCharacter->sceneId, _currentCharacter->facing, 0, 0, 1); _gameSpeed = 50; memset(_flagsTable, 0, sizeof(_flagsTable)); - - setupRooms(); - // XXX } void KyraEngine::delay(uint32 amount) { @@ -349,8 +475,10 @@ void KyraEngine::delay(uint32 amount) { case OSystem::EVENT_KEYDOWN: if (event.kbd.keycode == 'q' || event.kbd.keycode == 27) { _quitFlag = true; - } else if (event.kbd.keycode == ' ') { - loadRoom((++_currentRoom) % MAX_NUM_ROOMS); + } else { + ++_currentRoom; + if (_currentRoom > ARRAYSIZE(_shapes)) + _currentRoom = 3; } break; case OSystem::EVENT_MOUSEMOVE: @@ -358,12 +486,6 @@ void KyraEngine::delay(uint32 amount) { _mouseY = event.mouse.y; _needMouseUpdate = true; break; - case OSystem::EVENT_LBUTTONDOWN: - loadRoom((++_currentRoom) % MAX_NUM_ROOMS); - break; - case OSystem::EVENT_RBUTTONDOWN: - loadRoom((--_currentRoom) % MAX_NUM_ROOMS); - break; case OSystem::EVENT_QUIT: _quitFlag = true; break; @@ -377,89 +499,13 @@ void KyraEngine::delay(uint32 amount) { } while (_system->getMillis() < start + amount); } -void KyraEngine::drawRoom() { - //_screen->clearPage(0); - _screen->copyRegion(0, 0, 0, 0, 320, 200, 10, 0); - _screen->copyRegion(4, 4, 4, 4, 308, 132, 14, 0); - _sprites->doAnims(); - _sprites->drawSprites(14, 0); -} - -void KyraEngine::setupRooms() { - // XXX - // Just a few sample rooms, most with sprite anims. - memset(_rooms, 0, sizeof(_rooms)); - _rooms[0].filename = "gemcut"; - _rooms[1].filename = "arch"; - _rooms[2].filename = "sorrow"; - _rooms[3].filename = "emcav"; - _rooms[4].filename = "extpot"; - _rooms[5].filename = "spell"; - _rooms[6].filename = "song"; - _rooms[7].filename = "belroom"; - _rooms[8].filename = "kyragem"; - _rooms[9].filename = "lephole"; - _rooms[10].filename = "sickwil"; - _rooms[11].filename = "temple"; -} - -void KyraEngine::loadRoom(uint16 roomID) { - debug(9, "KyraEngine::loadRoom(%i)", roomID); - char buf[12]; - - loadPalette("palette.col", _screen->_currentPalette); - - //loadPalette(_rooms[roomID].palFilename, _screen->_currentPalette); - //_screen->setScreenPalette(_screen->_currentPalette); - - _screen->clearPage(14); - _screen->clearPage(0); - _screen->clearPage(10); - - // Loading GUI bitmap - if ((_features & GF_ENGLISH) && (_features & GF_TALKIE)) - loadBitmap("MAIN_ENG.CPS", 10, 10, 0); - else if(_features & GF_FRENCH) - loadBitmap("MAIN_FRE.CPS", 10, 10, 0); - else if(_features & GF_GERMAN) - loadBitmap("MAIN_GER.CPS", 10, 10, 0); - else if ((_features & GF_ENGLISH) && (_features & GF_FLOPPY)) - loadBitmap("MAIN15.CPS", 10, 10, 0); - else if (_features & GF_SPANISH) - loadBitmap("MAIN_SPA.CPS", 10, 10, 0); - else - warning("no main graphics file found"); - - // Loading main room background - strncpy(buf, _rooms[roomID].filename, 8); - strcat(buf, ".cps"); - loadBitmap( buf, 14, 14, 0); - - // Loading the room mask - strncpy(buf, _rooms[roomID].filename, 8); - strcat(buf, ".msc"); - loadBitmap( buf, 12, 12, 0); - - // Loading room data - strncpy(buf, _rooms[roomID].filename, 8); - strcat(buf, ".dat"); - _sprites->loadDAT(buf); - - drawRoom(); - _screen->showMouse(); - _needMouseUpdate = true; -} - void KyraEngine::mainLoop() { debug(9, "KyraEngine::mainLoop()"); -#ifdef TEST_SPRITES - _currentRoom = 0; - loadRoom(_currentRoom); + _currentRoom = 11; while (!_quitFlag) { int32 frameTime = (int32)_system->getMillis(); - drawRoom(); if (_needMouseUpdate) { _screen->hideMouse(); _screen->showMouse(); @@ -469,7 +515,6 @@ void KyraEngine::mainLoop() { delay((frameTime + _gameSpeed) - _system->getMillis()); } -#endif } void KyraEngine::loadPalette(const char *filename, uint8 *palData) { @@ -784,7 +829,7 @@ void KyraEngine::seq_intro() { &KyraEngine::seq_introKallakWriting, &KyraEngine::seq_introKallakMalcolm }; - _skipIntroFlag = true; // only true if user already played the game once + _skipIntroFlag = true; // only true if user already saved the game once _seq->setCopyViewOffs(true); _screen->setFont(Screen::FID_8_FNT); snd_playTheme(MUSIC_INTRO, 2); @@ -903,6 +948,7 @@ bool KyraEngine::seq_skipSequence() const { void KyraEngine::snd_playTheme(int file, int track) { debug(9, "KyraEngine::snd_playTheme(%d)", file); assert(file < _xmidiFilesCount); + _curMusicTheme = _newMusicTheme = file; _midi->playMusic(_xmidiFiles[file]); _midi->playTrack(track, false); } @@ -958,17 +1004,1272 @@ void KyraEngine::snd_haltTrack() { void KyraEngine::loadMouseShapes() { loadBitmap("MOUSE.CPS", 3, 3, 0); _screen->_curPage = 2; - _itemShapes[4] = _screen->encodeShape(0, 0, 8, 10, 0); - _itemShapes[5] = _screen->encodeShape(0, 0x17, 0x20, 7, 0); - _itemShapes[6] = _screen->encodeShape(0x50, 0x12, 0x10, 9, 0); - _itemShapes[7] = _screen->encodeShape(0x60, 0x12, 0x10, 11, 0); - _itemShapes[8] = _screen->encodeShape(0x70, 0x12, 0x10, 9, 0); - _itemShapes[9] = _screen->encodeShape(0x80, 0x12, 0x10, 11, 0); - _itemShapes[10] = _screen->encodeShape(0x90, 0x12, 0x10, 10, 0); - _itemShapes[364] = _screen->encodeShape(0x28, 0, 0x10, 13, 0); + _shapes[4] = _screen->encodeShape(0, 0, 8, 10, 0); + _shapes[5] = _screen->encodeShape(0, 0x17, 0x20, 7, 0); + _shapes[6] = _screen->encodeShape(0x50, 0x12, 0x10, 9, 0); + _shapes[7] = _screen->encodeShape(0x60, 0x12, 0x10, 11, 0); + _shapes[8] = _screen->encodeShape(0x70, 0x12, 0x10, 9, 0); + _shapes[9] = _screen->encodeShape(0x80, 0x12, 0x10, 11, 0); + _shapes[10] = _screen->encodeShape(0x90, 0x12, 0x10, 10, 0); + _shapes[364] = _screen->encodeShape(0x28, 0, 0x10, 13, 0); _screen->setMouseCursor(1, 1, 0); - _screen->setMouseCursor(1, 1, _itemShapes[4]); + _screen->setMouseCursor(1, 1, _shapes[4]); _screen->setShapePages(3, 5); } +void KyraEngine::loadCharacterShapes() { + int curImage = 0xFF; + int videoPage = _screen->_curPage; + _screen->_curPage = 2; + for (int i = 0; i < 115; ++i) { + assert(i < _defaultShapeTableSize); + Shape *shape = &_defaultShapeTable[i]; + if (shape->imageIndex == 0xFF) { + _shapes[i+4] = 0; + continue; + } + if (shape->imageIndex != curImage) { + assert(shape->imageIndex < _characterImageTableSize); + loadBitmap(_characterImageTable[shape->imageIndex], 3, 3, 0); + curImage = shape->imageIndex; + } + _shapes[i+4] = _screen->encodeShape(shape->x, shape->y, shape->w, shape->h, 1); + } + _screen->_curPage = videoPage; +} + +void KyraEngine::loadSpecialEffectShapes() { + loadBitmap("EFFECTS.CPS", 3, 3, 0); + _screen->_curPage = 2; + + int currShape; + for (currShape = 173; currShape < 183; currShape++) + _shapes[4 + currShape] = _screen->encodeShape((currShape-173) * 24, 0, 24, 24, 1); + + for (currShape = 183; currShape < 190; currShape++) + _shapes[4 + currShape] = _screen->encodeShape((currShape-183) * 24, 24, 24, 24, 1); + + for (currShape = 190; currShape < 201; currShape++) + _shapes[4 + currShape] = _screen->encodeShape((currShape-190) * 24, 48, 24, 24, 1); + + for (currShape = 201; currShape < 206; currShape++) + _shapes[4 + currShape] = _screen->encodeShape((currShape-201) * 16, 106, 16, 16, 1); +} + +int KyraEngine::findDuplicateItemShape(int shape) { + static uint8 dupTable[] = { + 0x48, 0x46, 0x49, 0x47, 0x4a, 0x46, 0x4b, 0x47, + 0x4c, 0x46, 0x4d, 0x47, 0x5b, 0x5a, 0x5c, 0x5a, + 0x5d, 0x5a, 0x5e, 0x5a, 0xFF, 0xFF + }; + + int i = 0; + + while (dupTable[i] != 0xFF) { + if (dupTable[i] == shape) + return dupTable[i+1]; + i += 2; + } + return -1; +} + +void KyraEngine::loadItems() { + int shape; + + loadBitmap("JEWELS3.CPS", 3, 3, 0); + _screen->_curPage = 2; + + _shapes[327] = 0; + + for (shape = 1; shape < 6; shape++ ) + _shapes[327 + shape] = _screen->encodeShape((shape - 1) * 32, 0, 32, 17, 0); + + for (shape = 330; shape <= 334; shape++) + _shapes[4 + shape] = _screen->encodeShape((shape-330) * 32, 102, 32, 17, 0); + + for (shape = 335; shape <= 339; shape++) + _shapes[4 + shape] = _screen->encodeShape((shape-335) * 32, 17, 32, 17, 0); + + for (shape = 340; shape <= 344; shape++) + _shapes[4 + shape] = _screen->encodeShape((shape-340) * 32, 34, 32, 17, 0); + + for (shape = 345; shape <= 349; shape++) + _shapes[4 + shape] = _screen->encodeShape((shape-345) * 32, 51, 32, 17, 0); + + for (shape = 350; shape <= 354; shape++) + _shapes[4 + shape] = _screen->encodeShape((shape-350) * 32, 68, 32, 17, 0); + + for (shape = 355; shape <= 359; shape++) + _shapes[4 + shape] = _screen->encodeShape((shape-355) * 32, 85, 32, 17, 0); + + + loadBitmap("ITEMS.CPS", 3, 3, 0); + _screen->_curPage = 2; + + for (int i = 0; i < 107; i++) { + shape = findDuplicateItemShape(i); + + if (shape != -1) + _shapes[220 + i] = _shapes[220 + shape]; + else + _shapes[220 + i] = _screen->encodeShape( (i % 20) * 16, i/20 * 16, 16, 16, 0); + } + + uint32 size; + uint8 *fileData = _res->fileData("_ITEM_HT.DAT", &size); + assert(fileData); + + for (int i = 0; i < 107; i++) { + _itemTable[i].height = fileData[i]; + _itemTable[i].unk1 = _itemTable[i].unk2 = 0; + } + + delete[] fileData; +} + +void KyraEngine::loadMainScreen() { + if ((_features & GF_ENGLISH) && (_features & GF_TALKIE)) + loadBitmap("MAIN_ENG.CPS", 3, 3, 0); + else if(_features & GF_FRENCH) + loadBitmap("MAIN_FRE.CPS", 3, 3, 0); + else if(_features & GF_GERMAN) + loadBitmap("MAIN_GER.CPS", 3, 3, 0); + else if ((_features & GF_ENGLISH) && (_features & GF_FLOPPY)) + loadBitmap("MAIN15.CPS", 3, 3, 0); + else if (_features & GF_SPANISH) + loadBitmap("MAIN_SPA.CPS", 3, 3, 0); + else + warning("no main graphics file found"); + + uint8 *_page3 = _screen->getPagePtr(3); + uint8 *_page0 = _screen->getPagePtr(0); + memcpy(_page0, _page3, 320*200); +} + +void KyraEngine::setCharactersInDefaultScene() { + static uint32 defaultSceneTable[][4] = { + { 0xFFFF, 0x0004, 0x0003, 0xFFFF }, + { 0xFFFF, 0x0022, 0xFFFF, 0x0000 }, + { 0xFFFF, 0x001D, 0x0021, 0xFFFF }, + { 0xFFFF, 0x0000, 0x0000, 0xFFFF } + }; + + for (int i = 1; i < 5; ++i) { + Character *cur = &_characterList[i]; + cur->field_20 = 0; + uint32 *curTable = defaultSceneTable[i-1]; + cur->sceneId = curTable[0]; + if (cur->sceneId == _currentCharacter->sceneId) { + ++cur->field_20; + cur->sceneId = curTable[cur->field_20]; + } + cur->field_23 = curTable[cur->field_20+1]; + } +} + +void KyraEngine::setCharacterDefaultFrame(int character) { + static uint16 initFrameTable[] = { + 0x07, 0x29, 0x4D, 0x00, 0x00 + }; + assert(character < ARRAYSIZE(initFrameTable)); + Character *edit = &_characterList[character]; + edit->sceneId = 0xFFFF; + edit->facing = 0; + edit->currentAnimFrame = initFrameTable[character]; + edit->unk6 = 1; +} + +void KyraEngine::setCharactersPositions(int character) { + static int16 initXPosTable[] = { + 0x3200, 0x0024, 0x2230, 0x2F00, 0x0020, 0x002B, + 0x00CA, 0x00F0, 0x0082, 0x00A2, 0x0042, 0x6767, + 0x5A60 + }; + static int8 initYPosTable[] = { + 0x00, 0xA2, 0x00, 0x42, 0x00, + 0x67, 0x67, 0x60, 0x5A, 0x71, + 0x76 + }; + assert(character < ARRAYSIZE(initXPosTable)); + Character *edit = &_characterList[character]; + edit->x1 = edit->x2 = initXPosTable[character]; + edit->y1 = edit->y2 = initYPosTable[character]; +} + +void KyraEngine::setCharactersHeight() { + static int8 initHeightTable[] = { + 0x30, 0x28, 0x30, 0x2F, 0x38, + 0x2C, 0x2A, 0x2F, 0x26, 0x23, + 0x28 + }; + for (int i = 0; i < 11; ++i) { + _characterList[i].height = initHeightTable[i]; + } +} + +int KyraEngine::setGameFlag(int flag) { + _flagsTable[flag >> 3] |= (1 << (flag & 7)); + return 1; +} + +int KyraEngine::queryGameFlag(int flag) { + return ((_flagsTable[flag >> 3] >> (flag & 7)) & 1); +} + +int KyraEngine::resetGameFlag(int flag) { + _flagsTable[flag >> 3] &= ~(1 << (flag & 7)); + return 0; +} + +void KyraEngine::enterNewScene(int sceneId, int facing, int unk1, int unk2, int brandonAlive) { + int unkVar1 = 1; + _screen->hideMouse(); + if (_currentCharacter->sceneId == 7 && sceneId == 24) { + _newMusicTheme = 2; + } else if (_currentCharacter->sceneId == 25 && sceneId == 109) { + _newMusicTheme = 3; + } else if (_currentCharacter->sceneId == 120 && sceneId == 37) { + _newMusicTheme = 4; + } else if (_currentCharacter->sceneId == 52 && sceneId == 199) { + _newMusicTheme = 5; + } else if (_currentCharacter->sceneId == 37 && sceneId == 120) { + _newMusicTheme = 3; + } else if (_currentCharacter->sceneId == 109 && sceneId == 25) { + _newMusicTheme = 2; + } else if (_currentCharacter->sceneId == 24 && sceneId == 7) { + _newMusicTheme = 1; + } + if (_newMusicTheme != _curMusicTheme) { + snd_playTheme(_newMusicTheme); + } + switch (_currentCharacter->sceneId) { + case 1: + if (sceneId == 0) { + moveCharacterToPos(0, 0, _currentCharacter->x1, 84); + unkVar1 = 0; + } + break; + + case 3: + if (sceneId == 2) { + moveCharacterToPos(0, 6, 155, _currentCharacter->y1); + unkVar1 = 0; + } + break; + + case 26: + if (sceneId == 27) { + moveCharacterToPos(0, 6, 155, _currentCharacter->y1); + unkVar1 = 0; + } + break; + + case 44: + if (sceneId == 45) { + moveCharacterToPos(0, 2, 192, _currentCharacter->y1); + unkVar1 = 0; + } + break; + + default: + break; + } + + if (unkVar1 && unk1) { + int xpos = _currentCharacter->x1; + int ypos = _currentCharacter->y1; + switch (facing) { + case 0: + ypos = _currentCharacter->y1 - 6; + break; + + case 2: + xpos = 336; + break; + + case 4: + ypos = 143; + break; + + case 6: + xpos = -16; + break; + + default: + break; + } + + moveCharacterToPos(0, 2, xpos, ypos); + } + + for (int i = 0; i < 10; ++i) { + wsa_close(_wsaObjects[i]); + _wsaObjects[i] = 0; + } + + if (!brandonAlive) { + _scriptInterpreter->initScript(_scriptClick, _scriptClickData); + _scriptInterpreter->startScript(_scriptClick, 5); + while (_scriptInterpreter->validScript(_scriptClick)) { + _scriptInterpreter->runScript(_scriptClick); + } + } + + memset(_entranceMouseCursorTracks, 0xFFFF, sizeof(uint16)*4); + _currentCharacter->sceneId = sceneId; + assert(sceneId < _roomFilenameTableSize); + + assert(sceneId < _roomTableSize); + Room *currentRoom = &_roomTable[sceneId]; + + assert(_currentCharacter->sceneId < _roomTableSize); + int tableId = _roomTable[_currentCharacter->sceneId].nameIndex; + assert(tableId < _roomFilenameTableSize); + char datFileNameBuffer[32]; + strcpy(datFileNameBuffer, _roomFilenameTable[tableId]); + strcat(datFileNameBuffer, ".DAT"); + _sprites->loadDAT(datFileNameBuffer); + + loadSceneMSC(); + + _walkBlockNorth = currentRoom->northExit; + _walkBlockEast = currentRoom->eastExit; + _walkBlockSouth = currentRoom->southExit; + _walkBlockWest = currentRoom->westExit; + + if (_walkBlockNorth == 0xFFFF) { + blockOutRegion(0, 0, 320, (_northExitHeight & 0xFF)+3); + } + if (_walkBlockEast == 0xFFFF) { + blockOutRegion(312, 0, 8, 139); + } + if (_walkBlockSouth == 0xFFFF) { + blockOutRegion(0, 135, 320, 8); + } + if (_walkBlockWest == 0xFFFF) { + blockOutRegion(0, 0, 8, 139); + } + + if (!brandonAlive) { + // XXX + } + + startSceneScript(brandonAlive); + // XXX setupSceneItems + initSceneData(facing, unk2, brandonAlive); + + // XXX setTextFadeTimerCountdown + _scriptClick->variables[3] = 1; + + _screen->showMouse(); + if (!brandonAlive) { + // XXX seq_poisionDeathNow + } +} + +void KyraEngine::moveCharacterToPos(int character, int facing, int xpos, int ypos) { + debug(9, "moveCharacterToPos(%d, %d, %d, %d)", character, facing, xpos, ypos); + Character *ch = &_characterList[character]; + _screen->hideMouse(); + xpos &= 0xFFFC; + ypos &= 0xFFFE; + switch (facing) { + case 0: + if (ypos < ch->y1) { + setCharacterPositionWithUpdate(character); + } + break; + + case 2: + if (ch->x1 < xpos) { + setCharacterPositionWithUpdate(character); + } + break; + + case 4: + if (ypos > ch->y1) { + setCharacterPositionWithUpdate(character); + } + break; + + case 6: + if (ch->x1 > xpos) { + setCharacterPositionWithUpdate(character); + } + break; + + default: + break; + } + _screen->showMouse(); +} + +void KyraEngine::setCharacterPositionWithUpdate(int character) { + debug(9, "setCharacterPositionWithUpdate(%d)", character); + // XXX game_updateAnimsFlags + setCharacterPosition(character, 0); + updateAllObjectShapes(); + // XXX processPalette + if (_currentCharacter->sceneId == 210) { + // XXX game_updateKyragemFading + } +} + +int KyraEngine::setCharacterPosition(int character, uint8 *unk1) { + debug(9, "setCharacterPosition(%d)", character); + static bool firstRun = true; + if (character == 0) { + if (firstRun) { + firstRun = false; + _currentCharacter->x1 += _charXPosTable[character]; + _currentCharacter->y1 += _charYPosTable[character]; + setCharacterPositionHelper(0, unk1); + return 1; + } + } else { + _characterList[character].x1 += _charXPosTable[character]; + _characterList[character].y1 += _charYPosTable[character]; + if (_characterList[character].sceneId == _currentCharacter->sceneId) { + setCharacterPositionHelper(character, 0); + } + } + return 0; +} + +void KyraEngine::setCharacterPositionHelper(int character, uint8 *unk1) { + Character *ch = &_characterList[character]; + int facing = ch->facing; + if (unk1) { + // XXX + } + + static uint8 facingIsZero[8]; + static uint8 facingIsFour[8]; + + if (facing == 0) { + ++facingIsZero[character]; + } else { + bool resetTables = false; + if (facing != 7) { + if (facing - 1 != 0) { + if (facing != 4) { + if (facing == 3 || facing == 5) { + if (facingIsFour[character] < 2) { + facing = 4; + } + resetTables = true; + } + } else { + ++facingIsFour[character]; + } + } else { + if (facingIsZero[character] < 2) { + facing = 0; + } + resetTables = true; + } + } + + if (resetTables) { + facingIsZero[character] = 0; + facingIsFour[character] = 0; + } + } + + static uint16 maxAnimationFrame[] = { + 0x000F, 0x0031, 0x0055, 0x0000, 0x0000, 0x0000, + 0x0008, 0x002A, 0x004E, 0x0000, 0x0000, 0x0000, + 0x0022, 0x0046, 0x006A, 0x0000, 0x0000, 0x0000, + 0x001D, 0x0041, 0x0065, 0x0000, 0x0000, 0x0000, + 0x001F, 0x0043, 0x0067, 0x0000, 0x0000, 0x0000, + 0x0028, 0x004C, 0x0070, 0x0000, 0x0000, 0x0000, + 0x0023, 0x0047, 0x006B, 0x0000, 0x0000, 0x0000 + }; + + if (facing == 0) { + if (maxAnimationFrame[36+character] > ch->currentAnimFrame) { + ch->currentAnimFrame = maxAnimationFrame[36+character]; + } + if (maxAnimationFrame[30+character] > ch->currentAnimFrame) { + ch->currentAnimFrame = maxAnimationFrame[36+character]; + } + } else if (facing == 4) { + if (maxAnimationFrame[18+character] > ch->currentAnimFrame) { + ch->currentAnimFrame = maxAnimationFrame[18+character]; + } + if (maxAnimationFrame[12+character] > ch->currentAnimFrame) { + ch->currentAnimFrame = maxAnimationFrame[18+character]; + } + } else { + if (maxAnimationFrame[18+character] > ch->currentAnimFrame) { + ch->currentAnimFrame = maxAnimationFrame[30+character]; + } + if (maxAnimationFrame[character] == ch->currentAnimFrame) { + ch->currentAnimFrame = maxAnimationFrame[6+character]; + } + if (maxAnimationFrame[character] > ch->currentAnimFrame) { + ch->currentAnimFrame = maxAnimationFrame[6+character]+2; + } + } + + if (character == 0) { + if (_brandonStatusBit & 0x10) + ch->currentAnimFrame = 88; + } + + animRefreshNPC(character); +} + +int KyraEngine::getOppositeFacingDirection(int dir) { + switch (dir) { + case 0: + return 2; + break; + + case 1: + return 1; + break; + + case 3: + return 7; + break; + + case 4: + return 6; + break; + + case 5: + return 5; + break; + + case 6: + return 4; + break; + + case 7: + return 3; + break; + + default: + break; + } + return 0; +} + +void KyraEngine::loadSceneMSC() { + assert(_currentCharacter->sceneId < _roomTableSize); + int tableId = _roomTable[_currentCharacter->sceneId].nameIndex; + assert(tableId < _roomFilenameTableSize); + char fileNameBuffer[32]; + strcpy(fileNameBuffer, _roomFilenameTable[tableId]); + strcat(fileNameBuffer, ".MSC"); + loadBitmap(fileNameBuffer, 3, 5, 0); +} + +// maybe move this two functions to Screen +void KyraEngine::blockInRegion(int x, int y, int width, int height) { + debug(9, "blockInRegion(%d, %d, %d, %d, %d)", x, y, width, height); + assert(_screen->_shapePages[0]); + byte *toPtr = _screen->_shapePages[0] + (y * 320 + x); + for (int i = 0; i < height; ++i) { + byte *backUpTo = toPtr; + for (int i2 = 0; i2 < width; ++i2) { + *toPtr++ &= 0x7F; + } + toPtr = (backUpTo + 320); + } +} + +void KyraEngine::blockOutRegion(int x, int y, int width, int height) { + debug(9, "blockOutRegion(%d, %d, %d, %d, %d)", x, y, width, height); + assert(_screen->_shapePages[0]); + byte *toPtr = _screen->_shapePages[0] + (y * 320 + x); + for (int i = 0; i < height; ++i) { + byte *backUpTo = toPtr; + for (int i2 = 0; i2 < width; ++i2) { + *toPtr++ |= 0x80; + } + toPtr = (backUpTo + 320); + } +} + +void KyraEngine::startSceneScript(int brandonAlive) { + debug(9, "startSceneScript(%d)", brandonAlive); + assert(_currentCharacter->sceneId < _roomTableSize); + int tableId = _roomTable[_currentCharacter->sceneId].nameIndex; + assert(tableId < _roomFilenameTableSize); + char fileNameBuffer[32]; + strcpy(fileNameBuffer, _roomFilenameTable[tableId]); + strcat(fileNameBuffer, ".CPS"); + loadBitmap(fileNameBuffer, 3, 3, 0); + + _sprites->loadSceneShapes(); + // TODO: check there it is done normally + _screen->setScreenPalette(_screen->_currentPalette); + _screen->copyRegion(4, 4, 4, 4, 308, 132, 3, 0); + + _scaleMode = 1; + for (int i = 0; i < 145; ++i) { + _scaleTable[i] = 256; + } + + clearNoDropRects(); + _scriptInterpreter->initScript(_scriptClick, _scriptClickData); + strcpy(fileNameBuffer, _roomFilenameTable[tableId]); + strcat(fileNameBuffer, ".EMC"); + _scriptInterpreter->unloadScript(_scriptClickData); + _scriptInterpreter->loadScript(fileNameBuffer, _scriptClickData, _opcodeTable, _opcodeTableSize, 0); + _scriptInterpreter->startScript(_scriptClick, 0); + _scriptClick->variables[0] = _currentCharacter->sceneId; + _scriptClick->variables[7] = brandonAlive; + + while (_scriptInterpreter->validScript(_scriptClick)) { + _scriptInterpreter->runScript(_scriptClick); + } +} + +void KyraEngine::initSceneData(int facing, int unk1, int brandonAlive) { + debug(9, "initSceneData(%d, %d, %d)", facing, unk1, brandonAlive); + + int xpos2 = 0; + int setFacing = 1; + + int xpos = 0, ypos = 0; + + if (_brandonPosX == -1 && _brandonPosY == -1) { + switch (facing) { + case 0: + xpos = ypos = -1; + break; + + case 1: case 2: case 8: + xpos = _sceneExits.SouthXPos; + ypos = _sceneExits.SouthYPos; + break; + + case 3: + xpos = _sceneExits.WestXPos; + ypos = _sceneExits.WestYPos; + break; + + case 4: case 5: case 6: + xpos = _sceneExits.NorthXPos; + ypos = _sceneExits.NorthYPos; + break; + + case 7: + xpos = _sceneExits.EastXPos; + ypos = _sceneExits.EastYPos; + break; + + default: + break; + } + + if ((_northExitHeight & 0xFF) >= ypos) { + ypos = (_northExitHeight & 0xFF); + } + if (xpos >= 308) { + xpos = 304; + } + if ((_northExitHeight >> 8) - 2 <= ypos) { + ypos = (_northExitHeight >> 8) - 4; + } + if (xpos <= 12) { + xpos = 16; + } + } + + if (_brandonPosX > -1) { + xpos = _brandonPosX; + } + if (_brandonPosY > -1) { + ypos = _brandonPosY; + } + + int ypos2 = 0; + if (_brandonPosX > -1 && _brandonPosY > -1) { + switch (_currentCharacter->sceneId) { + case 1: + _currentCharacter->x1 = xpos; + _currentCharacter->x2 = xpos; + _currentCharacter->y1 = ypos; + _currentCharacter->y2 = ypos; + facing = 4; + xpos2 = 192; + ypos2 = 104; + break; + + case 3: + _currentCharacter->x1 = xpos; + _currentCharacter->x2 = xpos; + _currentCharacter->y1 = ypos; + _currentCharacter->y2 = ypos; + facing = 2; + xpos2 = 204; + ypos2 = 94; + break; + + case 26: + _currentCharacter->x1 = xpos; + _currentCharacter->x2 = xpos; + _currentCharacter->y1 = ypos; + _currentCharacter->y2 = ypos; + facing = 4; + xpos2 = 192; + ypos2 = 128; + break; + + case 44: + _currentCharacter->x1 = xpos; + _currentCharacter->x2 = xpos; + _currentCharacter->y1 = ypos; + _currentCharacter->y2 = ypos; + facing = 6; + xpos2 = 156; + ypos2 = 96; + break; + + case 37: + _currentCharacter->x1 = xpos; + _currentCharacter->x2 = xpos; + _currentCharacter->y1 = ypos; + _currentCharacter->y2 = ypos; + facing = 2; + xpos2 = 148; + ypos2 = 114; + break; + + default: + break; + } + + setFacing = 0; + unk1 = 1; + } + + _brandonPosX = _brandonPosY = -1; + + if (unk1 != 0 && setFacing != 0) { + xpos2 = xpos; + switch (facing) { + case 0: + ypos = 142; + break; + + case 2: + xpos = -16; + break; + + case 4: + ypos = (_northExitHeight & 0xFF) - 4; + break; + + case 6: + xpos = 335; + break; + + default: + break; + } + } + + xpos2 &= 0xFFFC; + ypos2 &= 0xFE; + xpos &= 0xFFFC; + ypos &= 0xFFFE; + _currentCharacter->facing = facing; + _currentCharacter->x1 = xpos; + _currentCharacter->x2 = xpos; + _currentCharacter->y1 = ypos; + _currentCharacter->y2 = ypos; + + initSceneObjectList(brandonAlive); + + if (unk1 != 0 && brandonAlive == 0) { + moveCharacterToPos(0, facing, xpos2, ypos2); + } + + // XXX _mousePointerFlag + _scriptClick->variables[4] = -1; + _scriptClick->variables[7] = brandonAlive; + _scriptInterpreter->startScript(_scriptClick, 3); + while (_scriptInterpreter->validScript(_scriptClick)) { + _scriptInterpreter->runScript(_scriptClick); + } +} + +void KyraEngine::resetBrandonPosionFlags() { + _brandonStatusBit = 0; + for (int i = 0; i < 256; ++i) { + _unkBrandonPoisonFlags[i] = i; + } +} + +void KyraEngine::initAnimStateList() { + _animStates[0].index = 0; + _animStates[0].active = 1; + _animStates[0].flags = 0x800; + _animStates[0].background = _shapes[2]; + _animStates[0].rectSize = _screen->getRectSize(4, 48); + _animStates[0].width = 4; + _animStates[0].height = 48; + _animStates[0].width2 = 4; + _animStates[0].height2 = 3; + + for (int i = 1; i <= 4; ++i) { + _animStates[i].index = i; + _animStates[i].active = 0; + _animStates[i].flags = 0x800; + _animStates[i].background = _shapes[3]; + _animStates[i].rectSize = _screen->getRectSize(4, 64); + _animStates[i].width = 4; + _animStates[i].height = 48; + _animStates[i].width2 = 4; + _animStates[i].height2 = 3; + } + + for (int i = 5; i < 16; ++i) { + _animStates[i].index = i; + _animStates[i].active = 0; + _animStates[i].flags = 0; + } + + for (int i = 16; i < 28; ++i) { + _animStates[i].index = i; + _animStates[i].flags = 0; + _animStates[i].background = _shapes[349+i]; + _animStates[i].rectSize = _screen->getRectSize(3, 24); + _animStates[i].width = 3; + _animStates[i].height = 16; + _animStates[i].width2 = 0; + _animStates[i].height2 = 0; + } +} + +void KyraEngine::initSceneObjectList(int brandonAlive) { + warning("STUB: initSceneObjectList"); +} + +#pragma mark - +#pragma mark - Item handling +#pragma mark - + +void KyraEngine::addToNoDropRects(int x, int y, int w, int h) { + debug(9, "addToNoDropRects(%d, %d, %d, %d)", x, y, w, h); + for (int rect = 0; rect < 11; ++rect) { + if (_noDropRects[rect].x == -1) { + _noDropRects[rect].x = x; + _noDropRects[rect].y = y; + _noDropRects[rect].x2 = x + w - 1; + _noDropRects[rect].y2 = y + h - 1; + break; + } + } +} + +void KyraEngine::clearNoDropRects() { + debug(9, "clearNoDropRects()"); + memset(_noDropRects, -1, sizeof(_noDropRects)); +} + +byte KyraEngine::findFreeItemInScene(int scene) { + debug(9, "findFreeItemInScene(%d)", scene); + assert(scene < _roomTableSize); + Room *room = &_roomTable[scene]; + for (int i = 0; i < 12; ++i) { + if (room->itemsTable[i] != 0xFF) + return i; + } + return 0xFF; +} + +byte KyraEngine::findItemAtPos(int x, int y) { + assert(_currentCharacter->sceneId < _roomTableSize); + uint8 *itemsTable = _roomTable[_currentCharacter->sceneId].itemsTable; + uint16 *xposOffset = _roomTable[_currentCharacter->sceneId].itemsXPos; + uint8 *yposOffset = _roomTable[_currentCharacter->sceneId].itemsYPos; + + int highestYPos = -1; + byte returnValue = 0xFF; + + for (int i = 0; i < 12; ++i) { + if (*itemsTable != 0xFF) { + int xpos = *xposOffset - 8; + int xpos2 = *xposOffset + 10; + if (x > xpos && x < xpos2) { + assert(*itemsTable < ARRAYSIZE(_itemTable)); + int itemHeight = _itemTable[*itemsTable].height; + int ypos = *yposOffset; + int ypos2 = ypos - itemHeight - 3; + + if (y < ypos2 && (ypos+3) > y) { + if (highestYPos <= ypos) { + returnValue = i; + highestYPos = ypos; + } + } + } + } + xposOffset += 2; + yposOffset += 1; + itemsTable += 1; + } + + return returnValue; +} + +void KyraEngine::placeItemInGenericMapScene(int item, int index) { + debug(9, "placeItemInGenericMapScene(%d, %d)", item, index); + static const uint16 itemMapSceneMinTable[] = { + 0x0000, 0x0011, 0x006D, 0x0025, 0x00C7, 0x0000 + }; + static const uint16 itemMapSceneMaxTable[] = { + 0x0010, 0x0024, 0x00C6, 0x006C, 0x00F5, 0x0000 + }; + + int minValue = itemMapSceneMinTable[index]; + int maxValue = itemMapSceneMaxTable[index]; + + while (true) { + int room = _rnd.getRandomNumberRng(minValue, maxValue); + assert(room < _roomTableSize); + int nameIndex = _roomTable[room].nameIndex; + bool placeItem = false; + + switch (nameIndex) { + case 0: case 1: case 2: case 3: + case 4: case 5: case 6: case 11: + case 12: case 16: case 17: case 20: + case 22: case 23: case 25: case 26: + case 27: case 31: case 33: case 34: + case 36: case 37: case 58: case 59: + case 60: case 61: case 83: case 84: + case 85: case 104: case 105: case 106: + placeItem = true; + break; + + case 51: + if (room != 46) { + placeItem = true; + break; + } + default: + placeItem = false; + break; + } + + if (placeItem) { + Room *roomPtr = &_roomTable[room]; + if (roomPtr->northExit == 0xFFFF && roomPtr->eastExit == 0xFFFF && roomPtr->southExit == 0xFFFF && roomPtr->westExit == 0xFFFF) { + placeItem = false; + } else if (_currentCharacter->sceneId == room) { + placeItem = false; + } + } + + if (placeItem) { + warning("placeItemInGenericMapScene: placing an item is NOT implemented"); + //if (!sub_B010(room, item, -1, -1, 2, 0)) + // continue; + break; + } + } +} + +#pragma mark - +#pragma mark - Animation specific code +#pragma mark - + +void KyraEngine::restoreAllObjectBackgrounds() { + AnimObject *curObject = _objectQueue; + _screen->_curPage = 2; + + while (curObject) { + // XXX + if (curObject->active) { + preserveOrRestoreBackground(curObject, true); + curObject->x2 = curObject->x1; + curObject->y2 = curObject->y1; + } + curObject = curObject->nextAnimObject; + } + + _screen->_curPage = 0; +} + +void KyraEngine::preserveAnyChangedBackgrounds() { + AnimObject *curObject = _objectQueue; + _screen->_curPage = 2; + + while (curObject) { + // XXX + if (curObject->active && curObject->bkgdChangeFlag) { + preserveOrRestoreBackground(curObject, false); + curObject->bkgdChangeFlag = 0; + } + curObject = curObject->nextAnimObject; + } + + _screen->_curPage = 0; +} + +void KyraEngine::preserveOrRestoreBackground(AnimObject *obj, bool restore) { + int x, y, width = obj->width, height = obj->height; + + if (restore) { + x = obj->x2; + y = obj->y2; + } else { + x = obj->x1; + y = obj->y1; + } + + if (x < 0) + x = 0; + if (y < 0) + y = 0; + + int temp; + + temp = x + width; + if (temp >= 319) { + x = 319 - width; + } + temp = y + height; + if (temp >= 136) { + y = 136 - height; + } + + if (restore) { + _screen->copyCurPageBlock(x >> 3, y, width, height, obj->background); + } else { + _screen->copyBlockToPage(_screen->_curPage, x, y, width, height, obj->background); + } +} + +void KyraEngine::prepDrawAllObjects() { + AnimObject *curObject = _objectQueue; + int drawPage = 2; + int flagUnk1 = 0, flagUnk2 = 0, flagUnk3 = 0; + // XXX + if (_brandonStatusBit & 0x20) + flagUnk1 = 0x200; + if (_brandonStatusBit & 0x40) + flagUnk2 = 0x4000; + + while (curObject) { + if (curObject->active) { + int xpos = curObject->x1; + int ypos = curObject->y1; + + int temp = 0; /*si*/ + if (curObject->flags & 0x800) { + temp = 7; + } else { + // XXX + temp = 0; + } + + // XXX + if (!true) { + // XXX + } + + curObject->flags |= 0x800; + if (curObject->index == 0) { + flagUnk3 = 0x100; + + if (flagUnk1 & 0x200 || flagUnk2 & 0x4000) { + flagUnk3 = 0; + } + + if (_brandonStatusBit & 2) { + curObject->flags &= 0xFFFFFFFE; + } + + if (!_scaleMode) { + if (flagUnk3 & 0x100) { + _screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | flagUnk1 | 0x100, (uint8*)_unkBrandonPoisonFlags, 1, temp); + } else if (flagUnk3 & 0x4000) { + // XXX + int hackVar = 0; + _screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | flagUnk1 | 0x4000, hackVar, 0); + } else { + _screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | flagUnk1, temp); + } + } else { + if (flagUnk3 & 0x100) { + _screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | flagUnk1 | 0x104, (uint8*)_unkBrandonPoisonFlags, 1, temp, _brandonScaleX, _brandonScaleY); + } else if (flagUnk3 & 0x4000) { + // XXX + int hackVar = 0; + _screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | flagUnk1 | 0x4004, 0, temp, hackVar, _brandonScaleX, _brandonScaleY); + } else { + _screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | flagUnk1 | 0x4, temp, _brandonScaleX, _brandonScaleY); + } + } + } else { + if (curObject->index >= 16 && curObject->index <= 27) { + // XXX + _screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | 4, temp, (int)_scaleTable[curObject->drawY]); + } else { + _screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags, temp); + } + } + } + curObject = curObject->nextAnimObject; + } +} + +void KyraEngine::copyChangedObjectsForward(int refreshFlag) { + AnimObject *curObject = _objectQueue; + while (curObject) { + if (curObject->active) { + if (curObject->refreshFlag || refreshFlag) { + int xpos = 0, ypos = 0, width = 0, height = 0; + xpos = curObject->x1; + ypos = curObject->y1; + width = curObject->width; + height = curObject->height; + + _screen->copyRegion(xpos, ypos, xpos, ypos, width, height, 2, 0); + curObject->refreshFlag = 0; + } + } + curObject = curObject->nextAnimObject; + } +} + +void KyraEngine::updateAllObjectShapes() { + restoreAllObjectBackgrounds(); + preserveAnyChangedBackgrounds(); + prepDrawAllObjects(); + copyChangedObjectsForward(0); + + _screen->updateScreen(); +} + +void KyraEngine::animRefreshNPC(int character) { + AnimObject *animObj = &_charactersAnimState[character]; + Character *ch = &_characterList[character]; + + animObj->refreshFlag = 1; + animObj->bkgdChangeFlag = 1; + int facing = ch->facing; + if (facing >= 1 && facing <= 3) { + ch->inventoryItems[7] |= 1; + } else if (facing >= 5 && facing <= 7) { + ch->inventoryItems[7] &= 0xFE; + } + + animObj->drawY = ch->y1; + animObj->sceneAnimPtr = _shapes[4+ch->currentAnimFrame]; + animObj->animFrameNumber = ch->currentAnimFrame; + // XXX + if (character == 0) { + if (_brandonStatusBit & 10) { + animObj->animFrameNumber = 88; + ch->currentAnimFrame = 88; + } + if (_brandonStatusBit & 2) { + animObj->animFrameNumber = _brandonDrawFrame; + ch->currentAnimFrame = _brandonDrawFrame; + animObj->sceneAnimPtr = _shapes[4+_brandonDrawFrame]; + // XXX + } + } + + int xOffset = _defaultShapeTable[ch->currentAnimFrame].xOffset; + int yOffset = _defaultShapeTable[ch->currentAnimFrame].yOffset; + + if (_scaleMode) { + animObj->x1 = ch->x1; + animObj->y1 = ch->y1; + + _brandonScaleX = _scaleTable[ch->y1]; + _brandonScaleY = _scaleTable[ch->y1]; + + animObj->x1 += (_brandonScaleX * xOffset) >> 8; + animObj->y1 += (_brandonScaleY * yOffset) >> 8; + } else { + animObj->x1 += ch->x1 + xOffset; + animObj->y1 += ch->y1 + yOffset; + } + animObj->width2 = 4; + animObj->height2 = 3; + + _objectQueue = objectRemoveQueue(_objectQueue, animObj); + if (_objectQueue) { + + } else { + _objectQueue = objectAddHead(_objectQueue, animObj); + } +} + +#pragma mark - +#pragma mark - Queue handling +#pragma mark - + +AnimObject *KyraEngine::objectRemoveQueue(AnimObject *queue, AnimObject *rem) { + AnimObject *cur = queue; + AnimObject *prev = queue; + while (cur != rem && cur) { + AnimObject *temp = cur->nextAnimObject; + if (!temp) + break; + prev = cur; + cur = temp; + } + + if (cur == queue) { + if (!cur) + return 0; + return cur->nextAnimObject; + } + + if (!cur->nextAnimObject) { + if (!prev) { + return 0; + } else { + prev->nextAnimObject = 0; + } + } else { + if (cur == rem) { + prev->nextAnimObject = rem->nextAnimObject; + } + } + + return queue; +} + +AnimObject *KyraEngine::objectAddHead(AnimObject *queue, AnimObject *head) { + head->nextAnimObject = queue; + return head; +} + +AnimObject *KyraEngine::objectQueue(AnimObject *queue, AnimObject *add) { + if (add->drawY <= queue->drawY || !queue) { + add->nextAnimObject = queue; + return add; + } + AnimObject *cur = queue; + AnimObject *prev = queue; + while (add->drawY > cur->drawY) { + AnimObject *temp = cur->nextAnimObject; + if (!temp) + break; + prev = cur; + cur = temp; + } + + if (add->drawY <= cur->drawY) { + prev->nextAnimObject = add; + add->nextAnimObject = cur; + } else { + cur->nextAnimObject = add; + add->nextAnimObject = 0; + } + return 0; +} } // End of namespace Kyra diff --git a/kyra/kyra.h b/kyra/kyra.h index ead9cbe771..1ba9aa5e18 100644 --- a/kyra/kyra.h +++ b/kyra/kyra.h @@ -31,8 +31,6 @@ class AudioStream; namespace Kyra { -#define MAX_NUM_ROOMS 12 - enum { GF_FLOPPY = 1 << 0, GF_TALKIE = 1 << 1, @@ -58,39 +56,80 @@ struct Character { uint32 unk6; uint8 inventoryItems[10]; int16 x1, y1, x2, y2; + uint16 field_20; + uint16 field_23; }; struct Shape { - uint8 unk0; - uint8 unk1; - uint8 imageNum; + uint8 imageIndex; + int8 xOffset, yOffset; uint8 x, y, w, h; }; struct Room { -// uint8 id; + uint8 nameIndex; uint16 northExit; uint16 eastExit; uint16 southExit; uint16 westExit; uint8 itemsTable[12]; - const char *filename; + uint16 itemsXPos[12]; + uint8 itemsYPos[12]; + uint32 unkField3[12]; // maybe pointer to shape of the item }; -struct Cursor { +struct AnimObject { + uint8 index; + uint32 active; + uint32 refreshFlag; + uint32 bkgdChangeFlag; + uint32 flags; + int16 drawY; + uint8 *sceneAnimPtr; + uint16 animFrameNumber; + uint8 *background; + uint16 rectSize; + int16 x1, y1; + int16 x2, y2; + uint16 width; + uint16 height; + uint16 width2; + uint16 height2; + AnimObject *nextAnimObject; +}; + +struct Rect { int x, y; - int w, h; + int x2, y2; }; struct TalkCoords { uint16 y, x, w; }; +struct Item { + uint8 unk1; + uint8 height; + uint8 unk2; + uint8 unk3; +}; + struct SeqLoop { const uint8 *ptr; uint16 count; }; +struct SceneExits { + int16 NorthXPos; + int8 NorthYPos; + int16 EastXPos; + int8 EastYPos; + int16 SouthXPos; + int8 SouthYPos; + int16 WestXPos; + int8 WestYPos; +}; + struct WSAMovieV1; class MusicPlayer; @@ -99,6 +138,9 @@ class Resource; class PAKFile; class Screen; class Sprites; +struct ScriptState; +struct ScriptData; +class ScriptHelper; class KyraEngine : public Engine { friend class MusicPlayer; @@ -124,10 +166,15 @@ public: uint8 game() const { return _game; } uint32 features() const { return _features; } + SceneExits sceneExits() const { return _sceneExits; } + // ugly hack used by the dat loader + SceneExits &sceneExits() { return _sceneExits; } Common::RandomSource _rnd; + int16 _northExitHeight; typedef void (KyraEngine::*IntroProc)(); + typedef int (KyraEngine::*OpcodeProc)(ScriptState *script); const char **seqWSATable() { return (const char **)_seq_WSATable; } const char **seqCPSTable() { return (const char **)_seq_CPSTable; } @@ -155,6 +202,163 @@ public: int mouseX() { return _mouseX; } int mouseY() { return _mouseY; } + + // all opcode procs (maybe that is somehow useless atm) + int cmd_magicInMouseItem(ScriptState *script); + int cmd_characterSays(ScriptState *script); + int cmd_pauseTicks(ScriptState *script); + int cmd_drawSceneAnimShape(ScriptState *script); + int cmd_queryGameFlag(ScriptState *script); + int cmd_setGameFlag(ScriptState *script); + int cmd_resetGameFlag(ScriptState *script); + int cmd_runNPCScript(ScriptState *script); + int cmd_setSpecialExitList(ScriptState *script); + int cmd_blockInWalkableRegion(ScriptState *script); + int cmd_blockOutWalkableRegion(ScriptState *script); + int cmd_walkPlayerToPoint(ScriptState *script); + int cmd_dropItemInScene(ScriptState *script); + int cmd_drawAnimShapeIntoScene(ScriptState *script); + int cmd_createMouseItem(ScriptState *script); + int cmd_savePageToDisk(ScriptState *script); + int cmd_sceneAnimOn(ScriptState *script); + int cmd_sceneAnimOff(ScriptState *script); + int cmd_getElapsedSeconds(ScriptState *script); + int cmd_mouseIsPointer(ScriptState *script); + int cmd_destroyMouseItem(ScriptState *script); + int cmd_runSceneAnimUntilDone(ScriptState *script); + int cmd_fadeSpecialPalette(ScriptState *script); + int cmd_playAdlibSound(ScriptState *script); + int cmd_playAdlibScore(ScriptState *script); + int cmd_phaseInSameScene(ScriptState *script); + int cmd_setScenePhasingFlag(ScriptState *script); + int cmd_resetScenePhasingFlag(ScriptState *script); + int cmd_queryScenePhasingFlag(ScriptState *script); + int cmd_sceneToDirection(ScriptState *script); + int cmd_setBirthstoneGem(ScriptState *script); + int cmd_placeItemInGenericMapScene(ScriptState *script); + int cmd_setBrandonStatusBit(ScriptState *script); + int cmd_pauseSeconds(ScriptState *script); + int cmd_getCharactersLocation(ScriptState *script); + int cmd_runNPCSubscript(ScriptState *script); + int cmd_magicOutMouseItem(ScriptState *script); + int cmd_internalAnimOn(ScriptState *script); + int cmd_forceBrandonToNormal(ScriptState *script); + int cmd_poisonDeathNow(ScriptState *script); + int cmd_setScaleMode(ScriptState *script); + int cmd_openWSAFile(ScriptState *script); + int cmd_closeWSAFile(ScriptState *script); + int cmd_runWSAFromBeginningToEnd(ScriptState *script); + int cmd_displayWSAFrame(ScriptState *script); + int cmd_enterNewScene(ScriptState *script); + int cmd_setSpecialEnterXAndY(ScriptState *script); + int cmd_runWSAFrames(ScriptState *script); + int cmd_popBrandonIntoScene(ScriptState *script); + int cmd_restoreAllObjectBackgrounds(ScriptState *script); + int cmd_setCustomPaletteRange(ScriptState *script); + int cmd_loadPageFromDisk(ScriptState *script); + int cmd_customPrintTalkString(ScriptState *script); + int cmd_restoreCustomPrintBackground(ScriptState *script); + int cmd_hideMouse(ScriptState *script); + int cmd_showMouse(ScriptState *script); + int cmd_getCharacterX(ScriptState *script); + int cmd_getCharacterY(ScriptState *script); + int cmd_changeCharactersFacing(ScriptState *script); + int cmd_CopyWSARegion(ScriptState *script); + int cmd_printText(ScriptState *script); + int cmd_random(ScriptState *script); + int cmd_loadSoundFile(ScriptState *script); + int cmd_displayWSAFrameOnHidPage(ScriptState *script); + int cmd_displayWSASequentialFrames(ScriptState *script); + int cmd_drawCharacterStanding(ScriptState *script); + int cmd_internalAnimOff(ScriptState *script); + int cmd_changeCharactersXAndY(ScriptState *script); + int cmd_clearSceneAnimatorBeacon(ScriptState *script); + int cmd_querySceneAnimatorBeacon(ScriptState *script); + int cmd_refreshSceneAnimator(ScriptState *script); + int cmd_placeItemInOffScene(ScriptState *script); + int cmd_wipeDownMouseItem(ScriptState *script); + int cmd_placeCharacterInOtherScene(ScriptState *script); + int cmd_getKey(ScriptState *script); + int cmd_specificItemInInventory(ScriptState *script); + int cmd_popMobileNPCIntoScene(ScriptState *script); + int cmd_mobileCharacterInScene(ScriptState *script); + int cmd_hideMobileCharacter(ScriptState *script); + int cmd_unhideMobileCharacter(ScriptState *script); + int cmd_setCharactersLocation(ScriptState *script); + int cmd_walkCharacterToPoint(ScriptState *script); + int cmd_specialEventDisplayBrynnsNote(ScriptState *script); + int cmd_specialEventRemoveBrynnsNote(ScriptState *script); + int cmd_setLogicPage(ScriptState *script); + int cmd_fatPrint(ScriptState *script); + int cmd_preserveAllObjectBackgrounds(ScriptState *script); + int cmd_updateSceneAnimations(ScriptState *script); + int cmd_sceneAnimationActive(ScriptState *script); + int cmd_setCharactersMovementDelay(ScriptState *script); + int cmd_getCharactersFacing(ScriptState *script); + int cmd_bkgdScrollSceneAndMasksRight(ScriptState *script); + int cmd_dispelMagicAnimation(ScriptState *script); + int cmd_findBrightestFireberry(ScriptState *script); + int cmd_setFireberryGlowPalette(ScriptState *script); + int cmd_setDeathHandlerFlag(ScriptState *script); + int cmd_drinkPotionAnimation(ScriptState *script); + int cmd_makeAmuletAppear(ScriptState *script); + int cmd_drawItemShapeIntoScene(ScriptState *script); + int cmd_setCharactersCurrentFrame(ScriptState *script); + int cmd_waitForConfirmationMouseClick(ScriptState *script); + int cmd_pageFlip(ScriptState *script); + int cmd_setSceneFile(ScriptState *script); + int cmd_getItemInMarbleVase(ScriptState *script); + int cmd_setItemInMarbleVase(ScriptState *script); + int cmd_addItemToInventory(ScriptState *script); + int cmd_intPrint(ScriptState *script); + int cmd_shakeScreen(ScriptState *script); + int cmd_createAmuletJewel(ScriptState *script); + int cmd_setSceneAnimCurrXY(ScriptState *script); + int cmd_Poison_Brandon_And_Remaps(ScriptState *script); + int cmd_fillFlaskWithWater(ScriptState *script); + int cmd_getCharactersMovementDelay(ScriptState *script); + int cmd_getBirthstoneGem(ScriptState *script); + int cmd_queryBrandonStatusBit(ScriptState *script); + int cmd_playFluteAnimation(ScriptState *script); + int cmd_playWinterScrollSequence(ScriptState *script); + int cmd_getIdolGem(ScriptState *script); + int cmd_setIdolGem(ScriptState *script); + int cmd_totalItemsInScene(ScriptState *script); + int cmd_restoreBrandonsMovementDelay(ScriptState *script); + int cmd_setMousePos(ScriptState *script); + int cmd_getMouseState(ScriptState *script); + int cmd_setEntranceMouseCursorTrack(ScriptState *script); + int cmd_itemAppearsOnGround(ScriptState *script); + int cmd_setNoDrawShapesFlag(ScriptState *script); + int cmd_fadeEntirePalette(ScriptState *script); + int cmd_itemOnGroundHere(ScriptState *script); + int cmd_queryCauldronState(ScriptState *script); + int cmd_setCauldronState(ScriptState *script); + int cmd_queryCrystalState(ScriptState *script); + int cmd_setCrystalState(ScriptState *script); + int cmd_setPaletteRange(ScriptState *script); + int cmd_shrinkBrandonDown(ScriptState *script); + int cmd_growBrandonUp(ScriptState *script); + int cmd_setBrandonScaleXAndY(ScriptState *script); + int cmd_resetScaleMode(ScriptState *script); + int cmd_getScaleDepthTableValue(ScriptState *script); + int cmd_setScaleDepthTableValue(ScriptState *script); + int cmd_message(ScriptState *script); + int cmd_checkClickOnNPC(ScriptState *script); + int cmd_getFoyerItem(ScriptState *script); + int cmd_setFoyerItem(ScriptState *script); + int cmd_setNoItemDropRegion(ScriptState *script); + int cmd_walkMalcolmOn(ScriptState *script); + int cmd_passiveProtection(ScriptState *script); + int cmd_setPlayingLoop(ScriptState *script); + int cmd_brandonToStoneSequence(ScriptState *script); + int cmd_brandonHealingSequence(ScriptState *script); + int cmd_protectCommandLine(ScriptState *script); + int cmd_pauseMusicSeconds(ScriptState *script); + int cmd_resetMaskRegion(ScriptState *script); + int cmd_setPaletteChangeFlag(ScriptState *script); + int cmd_fillRect(ScriptState *script); + int cmd_dummy(ScriptState *script); protected: @@ -172,6 +376,42 @@ protected: int getWidestLineWidth(int linesCount); void calcWidestLineBounds(int &x1, int &x2, int w, int cx); void printText(const char *str, int x, int y, uint8 c0, uint8 c1, uint8 c2); + void setCharacterDefaultFrame(int character); + void setCharactersPositions(int character); + void setCharactersHeight(); + int setGameFlag(int flag); + int queryGameFlag(int flag); + int resetGameFlag(int flag); + + void enterNewScene(int sceneId, int facing, int unk1, int unk2, int brandonAlive); + void moveCharacterToPos(int character, int facing, int xpos, int ypos); + void setCharacterPositionWithUpdate(int character); + int setCharacterPosition(int character, uint8 *unk1); + void setCharacterPositionHelper(int character, uint8 *unk1); + int getOppositeFacingDirection(int dir); + void loadSceneMSC(); + void blockInRegion(int x, int y, int width, int height); + void blockOutRegion(int x, int y, int width, int height); + void startSceneScript(int brandonAlive); + void initSceneData(int facing, int unk1, int brandonAlive); + void clearNoDropRects(); + void addToNoDropRects(int x, int y, int w, int h); + byte findFreeItemInScene(int scene); + byte findItemAtPos(int x, int y); + void placeItemInGenericMapScene(int item, int index); + void initSceneObjectList(int brandonAlive); + void restoreAllObjectBackgrounds(); + void preserveAnyChangedBackgrounds(); + void preserveOrRestoreBackground(AnimObject *obj, bool restore); + void prepDrawAllObjects(); + void copyChangedObjectsForward(int refreshFlag); + void updateAllObjectShapes(); + void animRefreshNPC(int character); + int findDuplicateItemShape(int shape); + + AnimObject *objectRemoveQueue(AnimObject *queue, AnimObject *rem); + AnimObject *objectAddHead(AnimObject *queue, AnimObject *head); + AnimObject *objectQueue(AnimObject *queue, AnimObject *add); void seq_demo(); void seq_intro(); @@ -188,22 +428,32 @@ protected: void snd_setSoundEffectFile(int file); void snd_playSoundEffect(int track); + static OpcodeProc _opcodeTable[]; + static const int _opcodeTableSize; + enum { RES_ALL = 0, - RES_INTRO = (1 << 0) + RES_INTRO = (1 << 0), + RES_INGAME = (1 << 1) }; void res_loadResources(int type = RES_ALL); void res_unloadResources(int type = RES_ALL); void res_loadLangTable(const char *filename, PAKFile *res, byte ***loadTo, int *size, bool nativ); void res_loadTable(const byte *src, byte ***loadTo, int *size); - - void loadRoom(uint16 roomID); - void drawRoom(); + void res_loadRoomTable(const byte *src, Room **loadTo, int *size); + void res_loadShapeTable(const byte *src, Shape **loadTo, int *size); + void delay(uint32 millis); void loadPalette(const char *filename, uint8 *palData); void loadMouseShapes(); - void setupRooms(); + void loadCharacterShapes(); + void loadSpecialEffectShapes(); + void loadItems(); + void loadMainScreen(); + void setCharactersInDefaultScene(); + void resetBrandonPosionFlags(); + void initAnimStateList(); uint8 _game; bool _fastMode; @@ -216,14 +466,60 @@ protected: uint16 _talkMessageY; uint16 _talkMessageH; bool _talkMessagePrinted; - uint8 _flagsTable[51]; - uint8 *_itemShapes[377]; + uint8 _flagsTable[53]; + uint8 *_shapes[377]; uint16 _gameSpeed; uint32 _features; int _mouseX, _mouseY; bool _needMouseUpdate; - + + WSAMovieV1 *_wsaObjects[10]; + uint16 _entranceMouseCursorTracks[8]; + uint16 _walkBlockNorth; + uint16 _walkBlockEast; + uint16 _walkBlockSouth; + uint16 _walkBlockWest; + + int32 _scaleMode; + uint16 _scaleTable[145]; + + Rect _noDropRects[11]; + + uint16 _birthstoneGemTable[4]; + uint8 _idolGemsTable[3]; + + uint16 _marbleVaseItem; + + uint16 _brandonStatusBit; + uint8 _unkBrandonPoisonFlags[256]; // this seem not to be posion flags, it is used for drawing once + int _brandonPosX; + int _brandonPosY; + int16 _brandonScaleX; + int16 _brandonScaleY; + int _brandonDrawFrame; + + int8 *_sceneAnimTable[50]; + + Item _itemTable[145]; + + uint16 *_exitListPtr; + uint16 _exitList[11]; + SceneExits _sceneExits; uint16 _currentRoom; + uint8 *_maskBuffer; + + int _movUnkVar1; + int _lastFindWayRet; + int *_movFacingTable; + + AnimObject *_objectQueue; + AnimObject *_animStates; + AnimObject *_charactersAnimState; + AnimObject *_animObjects; + AnimObject *_unkAnimsBuffer; + + int _curMusicTheme; + int _newMusicTheme; AudioStream *_currentVocFile; Audio::SoundHandle _vocHandle; @@ -232,7 +528,16 @@ protected: MusicPlayer *_midi; SeqPlayer *_seq; Sprites *_sprites; - Room _rooms[MAX_NUM_ROOMS]; + ScriptHelper *_scriptInterpreter; + + ScriptState *_scriptMain; + ScriptData *_npcScriptData; + + ScriptState *_scriptClick; // TODO: rename to a better name + ScriptData *_scriptClickData; + + Character *_characterList; + Character *_currentCharacter; uint8 *_seq_Forest; uint8 *_seq_KallakWriting; @@ -255,8 +560,22 @@ protected: int _seq_COLTable_Size; int _seq_textsTable_Size; + char **_characterImageTable; + int _characterImageTableSize; + + Shape *_defaultShapeTable; + int _defaultShapeTableSize; + + Room *_roomTable; + int _roomTableSize; + char **_roomFilenameTable; + int _roomFilenameTableSize; + static const char *_xmidiFiles[]; static const int _xmidiFilesCount; + + static const int8 _charXPosTable[]; + static const int8 _charYPosTable[]; }; } // End of namespace Kyra diff --git a/kyra/screen.cpp b/kyra/screen.cpp index f99786211b..691f1fad6b 100644 --- a/kyra/screen.cpp +++ b/kyra/screen.cpp @@ -45,6 +45,12 @@ Screen::Screen(KyraEngine *vm, OSystem *system) if (_screenPalette) { memset(_screenPalette, 0, 768); } + for (int i = 0; i < 3; ++i) { + _palettes[i] = (uint8 *)malloc(768); + if (_palettes[i]) { + memset(_palettes[i], 0, 768); + } + } _curDim = &_screenDimTable[0]; _charWidth = 0; _charOffset = 0; @@ -78,6 +84,9 @@ Screen::~Screen() { free(_animBlockPtr); free(_mouseShape); free(_mouseRect); + for (int i = 0; i < 3; ++i) { + free(_palettes[i]); + } } void Screen::updateScreen() { @@ -314,7 +323,7 @@ void Screen::copyCurPageBlock(int x, int y, int h, int w, uint8 *dst) { } const uint8 *src = getPagePtr(_curPage) + y * SCREEN_W + x * 8; while (h--) { - memcpy(dst, src, w * 8); + memcpy(dst, src, w); dst += SCREEN_W; src += SCREEN_H; } @@ -559,47 +568,67 @@ void Screen::setScreenDim(int dim) { // XXX } -void Screen::drawShapePlotPixelCallback1(uint8 *dst, uint8 color) { - debug(9, "Screen::drawShapePlotPixelCallback1(0x%X, %d)", dst, color); - *dst = color; -} - -void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int sd, int flags, int *flagsTable, bool itemShape) { - debug(9, "Screen::drawShape(%d, %d, %d, %d, %d, %d)", pageNum, x, y, sd, flags, itemShape); +// TODO: implement the other callbacks and implement all of this function +void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int sd, int flags, ...) { + debug(9, "Screen::drawShape(%d, %d, %d, %d, %d, ...)", pageNum, x, y, sd, flags); assert(shapeData); + va_list args; + va_start(args, flags); + + static int drawShapeVar1 = 0; + static int drawShapeVar2[] = { + 1, 3, 2, 5, 4, 3, 2, 1 + }; + static int drawShapeVar3 = 1; + static int drawShapeVar4 = 0; + static int drawShapeVar5 = 0; + + uint8 *table = 0; + int tableLoopCount = 0; + int var_30 = 0; + uint8 *table2 = 0; + uint8 *table3 = 0; + uint8 *table4 = 0; + if (flags & 0x8000) { - warning("unhandled (flags & 0x8000) in Screen::drawShape()"); + table2 = va_arg(args, uint8*); } if (flags & 0x100) { - warning("unhandled (flags & 0x100) in Screen::drawShape()"); + table = va_arg(args, uint8*); + tableLoopCount = va_arg(args, int); + if (!tableLoopCount) + flags &= 0xFFFFFEFF; } if (flags & 0x1000) { - warning("unhandled (flags & 0x1000) in Screen::drawShape()"); + table3 = va_arg(args, uint8*); + table4 = va_arg(args, uint8*); } if (flags & 0x200) { - warning("unhandled (flags & 0x200) in Screen::drawShape()"); + drawShapeVar1 += 1; + drawShapeVar1 &= 7; + drawShapeVar3 = drawShapeVar2[drawShapeVar1]; + drawShapeVar4 = 0; + drawShapeVar5 = 256; } if (flags & 0x4000) { - warning("unhandled (flags & 0x4000) in Screen::drawShape()"); + drawShapeVar5 = va_arg(args, int); } if (flags & 0x800) { - warning("unhandled (flags & 0x800) in Screen::drawShape()"); + var_30 = va_arg(args, int); } int scale_w, scale_h; if (flags & DSF_SCALE) { - scale_w = *flagsTable++; - scale_h = *flagsTable++; + scale_w = va_arg(args, int); + scale_h = va_arg(args, int); } else { scale_w = 0x100; scale_h = 0x100; } int ppc = (flags >> 8) & 0x3F; - assert(ppc < _drawShapePlotPixelCount); - DrawShapePlotPixelCallback plotPixel = _drawShapePlotPixelTable[ppc]; const uint8 *src = shapeData; - if (_vm->features() & GF_TALKIE && !itemShape) { + if (_vm->features() & GF_TALKIE) { src += 2; } uint16 shapeFlags = READ_LE_UINT16(src); src += 2; @@ -607,12 +636,14 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int int shapeHeight = *src++; int scaledShapeHeight = (shapeHeight * scale_h) >> 8; if (scaledShapeHeight == 0) { + va_end(args); return; } int shapeWidth = READ_LE_UINT16(src); src += 2; int scaledShapeWidth = (shapeWidth * scale_w) >> 8; if (scaledShapeWidth == 0) { + va_end(args); return; } @@ -640,6 +671,7 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int } if (!_decodeShapeBuffer) { _decodeShapeBufferSize = 0; + va_end(args); return; } memset(_decodeShapeBuffer, 0, _decodeShapeBufferSize); @@ -650,7 +682,15 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int while (count > 0) { uint8 code = *src++; if (code != 0) { - *decodedShapeFrame++ = code; + // this is guessed + if (shapeFlags & 1) { + const uint8 *colorTable = shapeData + 10; + if (_vm->features() & GF_TALKIE) + colorTable += 2; + *decodedShapeFrame++ = colorTable[code]; + } else { + *decodedShapeFrame++ = code; + } --count; } else { code = *src++; @@ -732,18 +772,294 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int j = -j; } for (x = x1; x < x2; ++x) { - int i = scaleXTable[x]; + int xpos = scaleXTable[x]; if (flags & DSF_X_FLIPPED) { - i = -i; + xpos = -xpos; } - uint8 color = shapeBuffer[j * shapeWidth + i]; + uint8 color = shapeBuffer[j * shapeWidth + xpos]; if (color != 0) { - (this->*plotPixel)(dst, color); + switch (ppc) { + case 0: + *dst = color; + break; + + case 1: + for (int i = 0; i < tableLoopCount; ++i) { + color = table[color]; + } + break; + + case 2: { + int temp = drawShapeVar4 + drawShapeVar5; + if (temp & 0xFF00) { + drawShapeVar4 = temp & 0xFF; + dst += drawShapeVar3; + color = *dst; + dst -= drawShapeVar3; + } else { + drawShapeVar4 = temp; + } + } break; + + case 7: + case 3: + color = *dst; + for (int i = 0; i < tableLoopCount; ++i) { + color = table[color]; + } + break; + + case 4: + color = table2[color]; + break; + + case 5: + color = table2[color]; + for (int i = 0; i < tableLoopCount; ++i) { + color = table[color]; + } + break; + + case 6: { + int temp = drawShapeVar4 + drawShapeVar5; + if (temp & 0xFF00) { + drawShapeVar4 = temp & 0xFF; + dst += drawShapeVar3; + color = *dst; + dst -= drawShapeVar3; + } else { + drawShapeVar4 = temp; + color = table2[color]; + } + } break; + + case 8: { + int offset = dst - shapeBuffer; + uint8 pixel = *(_shapePages[0] + offset); + pixel &= 0x7F; + pixel &= 0x87; + if (var_30 < pixel) { + color = *(_shapePages[1] + offset); + } + } break; + + case 9: { + int offset = dst - shapeBuffer; + uint8 pixel = *(_shapePages[0] + offset); + pixel &= 0x7F; + pixel &= 0x87; + if (var_30 < pixel) { + color = *(_shapePages[1] + offset); + } else { + for (int i = 0; i < tableLoopCount; ++i) { + color = table[color]; + } + } + } break; + + case 10: { + int offset = dst - shapeBuffer; + uint8 pixel = *(_shapePages[0] + offset); + pixel &= 0x7F; + pixel &= 0x87; + if (var_30 < pixel) { + color = *(_shapePages[1] + offset); + drawShapeVar4 = pixel; + } else { + int temp = drawShapeVar4 + drawShapeVar5; + if (temp & 0xFF00) { + dst += drawShapeVar3; + color = *dst; + dst -= drawShapeVar3; + } + drawShapeVar4 = temp & 0xFF; + } + } break; + + case 15: + case 11: { + int offset = dst - shapeBuffer; + uint8 pixel = *(_shapePages[0] + offset); + pixel &= 0x7F; + pixel &= 0x87; + if (var_30 < pixel) { + color = *(_shapePages[1] + offset); + } else { + color = *dst; + for (int i = 0; i < tableLoopCount; ++i) { + color = table[color]; + } + } + } break; + + case 12: { + int offset = dst - shapeBuffer; + uint8 pixel = *(_shapePages[0] + offset); + pixel &= 0x7F; + pixel &= 0x87; + if (var_30 < pixel) { + color = *(_shapePages[1] + offset); + } else { + color = table2[color]; + } + } break; + + case 13: { + int offset = dst - shapeBuffer; + uint8 pixel = *(_shapePages[0] + offset); + pixel &= 0x7F; + pixel &= 0x87; + if (var_30 < pixel) { + color = *(_shapePages[1] + offset); + } else { + color = table2[color]; + for (int i = 0; i < tableLoopCount; ++i) { + color = table[color]; + } + } + } break; + + case 14: { + int offset = dst - shapeBuffer; + uint8 pixel = *(_shapePages[0] + offset); + pixel &= 0x7F; + pixel &= 0x87; + if (var_30 < pixel) { + color = *(_shapePages[1] + offset); + drawShapeVar4 = pixel; + } else { + int temp = drawShapeVar4 + drawShapeVar5; + if (temp & 0xFF00) { + dst += drawShapeVar3; + color = *dst; + dst -= drawShapeVar3; + drawShapeVar4 = temp % 0xFF; + } else { + drawShapeVar4 = temp; + color = table2[color]; + } + } + } break; + + case 16: { + uint8 newColor = table3[color]; + if (!(newColor & 0x80)) { + color = *dst; + color = table4[color + (newColor << 8)]; + } + } break; + + case 17: { + for (int i = 0; i < tableLoopCount; ++i) { + color = table[color]; + } + uint8 newColor = table3[color]; + if (!(newColor & 0x80)) { + color = *dst; + color = table4[color + (newColor << 8)]; + } + } break; + + case 18: { + int temp = drawShapeVar4 + drawShapeVar5; + if (temp & 0xFF00) { + drawShapeVar4 = temp & 0xFF; + dst += drawShapeVar3; + color = *dst; + dst -= drawShapeVar3; + uint8 newColor = table3[color]; + if (!(newColor & 0x80)) { + color = *dst; + color = table4[color + (newColor << 8)]; + } + } else { + drawShapeVar4 = temp; + } + } break; + + case 23: + case 19: { + color = *dst; + for (int i = 0; i < tableLoopCount; ++i) { + color = table[color]; + } + uint8 newColor = table3[color]; + if (!(newColor & 0x80)) { + color = *dst; + color = table4[color + (newColor << 8)]; + } + } break; + + case 20: { + color = table2[color]; + uint8 newColor = table3[color]; + if (!(newColor & 0x80)) { + color = *dst; + color = table4[color + (newColor << 8)]; + } + } break; + + case 21: { + color = table2[color]; + for (int i = 0; i < tableLoopCount; ++i) { + color = table[color]; + } + uint8 newColor = table3[color]; + if (!(newColor & 0x80)) { + color = *dst; + color = table4[color + (newColor << 8)]; + } + } break; + + case 22: { + int temp = drawShapeVar4 + drawShapeVar5; + if (temp & 0xFF00) { + drawShapeVar4 = temp & 0xFF; + dst += drawShapeVar3; + color = *dst; + dst -= drawShapeVar3; + uint8 newColor = table3[color]; + if (!(newColor & 0x80)) { + color = *dst; + color = table4[color + (newColor << 8)]; + } + } else { + drawShapeVar4 = temp; + color = table2[color]; + uint8 newColor = table3[color]; + if (!(newColor & 0x80)) { + color = *dst; + color = table4[color + (newColor << 8)]; + } + } + } break; + + case 24: { + int offset = dst - shapeBuffer; + uint8 pixel = *(_shapePages[0] + offset); + pixel &= 0x7F; + pixel &= 0x87; + if (var_30 < pixel) { + color = *(_shapePages[1] + offset); + } + uint8 newColor = table3[color]; + if (!(newColor & 0x80)) { + color = *dst; + color = table4[color + (newColor << 8)]; + } + } break; + + default: + warning("unhandled ppc: %d", ppc); + break; + } + *dst = color; } ++dst; } dst = dstNextLine; } + va_end(args); } void Screen::decodeFrame3(const uint8 *src, uint8 *dst, uint32 size) { @@ -994,10 +1310,17 @@ uint8 *Screen::encodeShape(int x, int y, int w, int h, int flags) { static uint8 table[274]; int tableIndex = 0; - uint8 *newShape = (uint8*)malloc(shapeSize+16); + uint8 *newShape = NULL; + if (_vm->features() & GF_TALKIE) { + newShape = (uint8*)malloc(shapeSize+16); + } else { + newShape = (uint8*)malloc(shapeSize+18); + } assert(newShape); byte *dst = newShape; + if (_vm->features() & GF_TALKIE) + dst += 2; WRITE_LE_UINT16(dst, (flags & 3)); dst += 2; *dst = h; dst += 1; WRITE_LE_UINT16(dst, w); dst += 2; @@ -1026,6 +1349,7 @@ uint8 *Screen::encodeShape(int x, int y, int w, int h, int flags) { table[0x100+tableIndex] = value; table[value] = tableIndex; ++tableIndex; + value = tableIndex; } } else { value = table[value]; @@ -1063,11 +1387,15 @@ uint8 *Screen::encodeShape(int x, int y, int w, int h, int flags) { if (!(flags & 2)) { if (shapeSize > _animBlockSize) { dst = newShape; + if (_vm->features() & GF_TALKIE) + dst += 2; flags = READ_LE_UINT16(dst); flags |= 2; WRITE_LE_UINT16(dst, flags); } else { src = newShape; + if (_vm->features() & GF_TALKIE) + src += 2; if (flags & 1) { src += 16; } @@ -1097,6 +1425,8 @@ uint8 *Screen::encodeShape(int x, int y, int w, int h, int flags) { if (flags & 1) { dst = newShape + 10; + if (_vm->features() & GF_TALKIE) + dst += 2; src = &table[0x100]; memcpy(dst, src, sizeof(uint8)*16); } @@ -1281,6 +1611,9 @@ byte *Screen::setMouseCursor(int x, int y, byte *shape) { restoreMouseRect(); + if (_vm->features() & GF_TALKIE) + shape += 2; + int mouseRectSize = getRectSize((READ_LE_UINT16(shape + 3) >> 3) + 2, shape[5]); if (_mouseRectSize < mouseRectSize) { free(_mouseRect); @@ -1302,6 +1635,8 @@ byte *Screen::setMouseCursor(int x, int y, byte *shape) { byte *dst = _mouseShape; byte *src = shape; + if (_vm->features() & GF_TALKIE) + dst += 2; if (!(READ_LE_UINT16(shape) & 2)) { uint16 newFlags = 0; @@ -1338,13 +1673,10 @@ void Screen::restoreMouseRect() { // if disableMouse // return - // if mouseUnk == 0 { - if (_mouseDrawWidth && _mouseRect) { - copyScreenFromRect(_mouseDrawX, _mouseDrawY, _mouseDrawWidth, _mouseDrawHeight, _mouseRect); - } - _mouseDrawWidth = 0; - // } - // ++mouseUnk + if (_mouseDrawWidth && _mouseRect) { + copyScreenFromRect(_mouseDrawX, _mouseDrawY, _mouseDrawWidth, _mouseDrawHeight, _mouseRect); + } + _mouseDrawWidth = 0; } void Screen::copyMouseToScreen() { @@ -1352,11 +1684,6 @@ void Screen::copyMouseToScreen() { // if disableMouse // return - // if mouseUnk == 0 - // return - // --mouseUnk - // if mouseUnk != 0 - // return int width = _mouseWidth; int height = _mouseHeight; int xpos = _vm->mouseX() - _mouseXOffset; @@ -1396,14 +1723,14 @@ void Screen::copyMouseToScreen() { copyScreenToRect(_mouseDrawX, _mouseDrawY, width, height, _mouseRect); } - drawShape(0, _mouseShape, xpos, ypos, 0, 0, 0, true); + drawShape(0, _mouseShape, xpos, ypos, 0, 0, 0); } void Screen::copyScreenFromRect(int x, int y, int w, int h, uint8 *ptr) { debug(9, "copyScreenFromRect(%d, %d, %d, %d, 0x%X)", x, y, w, h, ptr); x <<= 3; w <<= 3; uint8 *src = ptr; - uint8 *dst = &_pagePtrs[0][y * SCREEN_W + x]; + uint8 *dst = &_pagePtrs[0][y * SCREEN_W + x]; for (int i = 0; i < h; ++i) { memcpy(dst, src, w); src += w; @@ -1415,7 +1742,7 @@ void Screen::copyScreenToRect(int x, int y, int w, int h, uint8 *ptr) { debug(9, "copyScreenToRect(%d, %d, %d, %d, 0x%X)", x, y, w, h, ptr); x <<= 3; w <<= 3; uint8 *src = &_pagePtrs[0][y * SCREEN_W + x]; - uint8 *dst = ptr; + uint8 *dst = ptr; for (int i = 0; i < h; ++i) { memcpy(dst, src, w); dst += w; @@ -1423,4 +1750,14 @@ void Screen::copyScreenToRect(int x, int y, int w, int h, uint8 *ptr) { } } +uint8 *Screen::getPalette(int num) { + debug(9, "getPalette(%d)", num); + assert(num >= 0 && num < 4); + if (num == 0) { + return _screenPalette; + } + + return _palettes[num-1]; +} + } // End of namespace Kyra diff --git a/kyra/screen.h b/kyra/screen.h index 2642ba782a..6cae20df88 100644 --- a/kyra/screen.h +++ b/kyra/screen.h @@ -23,6 +23,7 @@ #define KYRASCREEN_H #include "common/util.h" +#include <stdarg.h> class OSystem; @@ -110,26 +111,26 @@ public: void drawChar(uint8 c, int x, int y); void setScreenDim(int dim); void drawShapePlotPixelCallback1(uint8 *dst, uint8 color); - void drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int sd, int flags, int *flagsTable, bool itemShape=false); + void drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int sd, int flags, ...); static void decodeFrame3(const uint8 *src, uint8 *dst, uint32 size); static void decodeFrame4(const uint8 *src, uint8 *dst, uint32 dstSize); static void decodeFrameDelta(uint8 *dst, const uint8 *src); static void decodeFrameDeltaPage(uint8 *dst, const uint8 *src, int pitch); uint8 *encodeShape(int x, int y, int w, int h, int flags); void copyRegionToBuffer(int pageNum, int x, int y, int w, int h, uint8 *dest); - + int getRectSize(int x, int y); void hideMouse(); void showMouse(); void setShapePages(int page1, int page2); byte *setMouseCursor(int x, int y, byte *shape); + uint8 *getPalette(int num); int _charWidth; int _charOffset; int _curPage; uint8 *_currentPalette; - - typedef void (Screen::*DrawShapePlotPixelCallback)(uint8 *dst, uint8 c); + uint8 *_shapePages[2]; private: int16 encodeShapeAndCalculateSize(uint8 *from, uint8 *to, int size); @@ -139,8 +140,8 @@ private: void copyScreenToRect(int x, int y, int w, int h, uint8 *ptr); uint8 *_pagePtrs[16]; - uint8 *_shapePages[2]; uint8 *_screenPalette; + uint8 *_palettes[3]; const ScreenDim *_curDim; FontId _currentFont; Font _fonts[FID_NUM]; @@ -164,8 +165,6 @@ private: static const ScreenDim _screenDimTable[]; static const int _screenDimTableCount; - static const DrawShapePlotPixelCallback _drawShapePlotPixelTable[]; - static const int _drawShapePlotPixelCount; }; } // End of namespace Kyra diff --git a/kyra/script.cpp b/kyra/script.cpp index 5520079b71..c30e25208b 100644 --- a/kyra/script.cpp +++ b/kyra/script.cpp @@ -69,7 +69,7 @@ ScriptHelper::ScriptHelper(KyraEngine *vm) : _vm(vm) { ScriptHelper::~ScriptHelper() { } -bool ScriptHelper::loadScript(const char *filename, ScriptData *scriptData, byte *specialPtr) { +bool ScriptHelper::loadScript(const char *filename, ScriptData *scriptData, KyraEngine::OpcodeProc *opcodes, int opcodeSize, byte *specialPtr) { uint32 size = 0; uint8 *data = _vm->resource()->fileData(filename, &size); byte *curData = data; @@ -147,6 +147,8 @@ bool ScriptHelper::loadScript(const char *filename, ScriptData *scriptData, byte return false; } scriptData->dataSize = chunkSize / 2; + scriptData->opcodes = opcodes; + scriptData->opcodeSize = opcodeSize; delete [] data; return true; diff --git a/kyra/script.h b/kyra/script.h index 9140e3b7a4..1469ee6ef6 100644 --- a/kyra/script.h +++ b/kyra/script.h @@ -30,7 +30,8 @@ struct ScriptData { byte *data; byte *ordr; uint16 dataSize; - /*command table ptr (uint32)*/ + KyraEngine::OpcodeProc *opcodes; + int opcodeSize; uint16 mustBeFreed; }; @@ -53,10 +54,10 @@ public: ScriptHelper(KyraEngine *vm); virtual ~ScriptHelper(); - bool loadScript(const char *filename, ScriptData *data, byte *specialPtr = 0); + bool loadScript(const char *filename, ScriptData *data, KyraEngine::OpcodeProc *opcodes, int opcodeSize, byte *specialPtr = 0); void unloadScript(ScriptData *data); - void initScript(ScriptState *scriptStat, ScriptData *data); + void initScript(ScriptState *scriptState, ScriptData *data); bool startScript(ScriptState *script, int function); bool validScript(ScriptState *script); diff --git a/kyra/script_v1.cpp b/kyra/script_v1.cpp index 326de04d2c..b61aa144d8 100644 --- a/kyra/script_v1.cpp +++ b/kyra/script_v1.cpp @@ -22,6 +22,9 @@ #include "common/stdafx.h" #include "kyra/kyra.h" #include "kyra/script.h" +#include "kyra/screen.h" +#include "kyra/sprites.h" +#include "common/system.h" namespace Kyra { @@ -112,9 +115,10 @@ void ScriptHelper::c1_subSP() { } void ScriptHelper::c1_execOpcode() { - warning("c1_execOpcode STUB"); - // return 0 zero for now - _curScript->retValue = 0; + assert((int)_parameter < _curScript->dataPtr->opcodeSize); + if (_curScript->dataPtr->opcodes[_parameter] == &KyraEngine::cmd_dummy) + debug("calling unimplemented opcode(0x%.02X)", _parameter); + _curScript->retValue = (_vm->*_curScript->dataPtr->opcodes[_parameter])(_curScript); } void ScriptHelper::c1_ifNotJmp() { @@ -287,4 +291,949 @@ void ScriptHelper::c1_setRetAndJmp() { } } +#pragma mark - +#pragma mark - Opcode implementations +#pragma mark - + +#define stackPos(x) script->stack[script->sp+x] + +int KyraEngine::cmd_magicInMouseItem(ScriptState *script) { + warning("STUB: cmd_magicInMouseItem"); + return 0; +} + +int KyraEngine::cmd_characterSays(ScriptState *script) { + warning("STUB: cmd_characterSays"); + return 0; +} + +int KyraEngine::cmd_pauseTicks(ScriptState *script) { + warning("STUB: cmd_pauseTicks"); + return 0; +} + +int KyraEngine::cmd_drawSceneAnimShape(ScriptState *script) { + debug(9, "cmd_drawSceneAnimShape(0x%X)", script); + _screen->drawShape( stackPos(4), _sprites->getSceneShape(stackPos(0)), stackPos(1), stackPos(2), 0, stackPos(3) ); + return 0; +} + +int KyraEngine::cmd_queryGameFlag(ScriptState *script) { + debug(9, "cmd_queryGameFlag(0x%X)", script); + return queryGameFlag(stackPos(0)); +} + +int KyraEngine::cmd_setGameFlag(ScriptState *script) { + debug(9, "cmd_setGameFlag(0x%X)", script); + return setGameFlag(stackPos(0)); +} + +int KyraEngine::cmd_resetGameFlag(ScriptState *script) { + debug(9, "cmd_resetGameFlag(0x%X)", script); + return resetGameFlag(stackPos(0)); +} + +int KyraEngine::cmd_runNPCScript(ScriptState *script) { + warning("STUB: cmd_runNPCScript"); + return 0; +} + +int KyraEngine::cmd_setSpecialExitList(ScriptState *script) { + debug(9, "cmd_setSpecialExitList(0x%X)", script); + + for (int i = 0; i < 10; ++i) { + _exitList[i] = stackPos(i); + } + _exitListPtr = _exitList; + + return 0; +} + +int KyraEngine::cmd_blockInWalkableRegion(ScriptState *script) { + debug(9, "cmd_blockInWalkableRegion(0x%X)", script); + blockOutRegion(stackPos(0), stackPos(1), stackPos(2)-stackPos(0)+1, stackPos(3)-stackPos(1)+1); + return 0; +} + +int KyraEngine::cmd_blockOutWalkableRegion(ScriptState *script) { + debug(9, "cmd_blockOutWalkableRegion(0x%X)", script); + blockOutRegion(stackPos(0), stackPos(1), stackPos(2)-stackPos(0)+1, stackPos(3)-stackPos(1)+1); + return 0; +} + +int KyraEngine::cmd_walkPlayerToPoint(ScriptState *script) { + warning("STUB: cmd_walkPlayerToPoint"); + return 0; +} + +int KyraEngine::cmd_dropItemInScene(ScriptState *script) { + debug(9, "cmd_dropItemInScene(0x%X)", script); + int item = stackPos(0); + int xpos = stackPos(1); + int ypos = stackPos(2); + + byte freeItem = findFreeItemInScene(_currentCharacter->sceneId); + if (freeItem != 0xFF) { + int sceneId = _currentCharacter->sceneId; + Room *room = &_roomTable[sceneId]; + room->itemsXPos[freeItem] = xpos; + room->itemsYPos[freeItem] = ypos; + room->itemsTable[freeItem] = item; + + warning("PARTIALLY IMPLEMENTED: cmd_dropItemInScene"); + // XXX animAddGameItem + // XXX updateAllObjectShapes + } else { + if (item == 43) { + placeItemInGenericMapScene(item, 0); + } else { + placeItemInGenericMapScene(item, 1); + } + } + return 0; +} + +int KyraEngine::cmd_drawAnimShapeIntoScene(ScriptState *script) { + warning("STUB: cmd_drawAnimShapeIntoScene"); + return 0; +} + +int KyraEngine::cmd_createMouseItem(ScriptState *script) { + warning("STUB: cmd_createMouseItem"); + return 0; +} + +int KyraEngine::cmd_savePageToDisk(ScriptState *script) { + warning("STUB: cmd_savePageToDisk"); + return 0; +} + +int KyraEngine::cmd_sceneAnimOn(ScriptState *script) { + debug(9, "cmd_sceneAnimOn(0x%X)", script); + _sprites->enableAnim(stackPos(0)); + return 0; +} + +int KyraEngine::cmd_sceneAnimOff(ScriptState *script) { + debug(9, "cmd_sceneAnimOff(0x%X)", script); + _sprites->disableAnim(stackPos(0)); + return 0; +} + +int KyraEngine::cmd_getElapsedSeconds(ScriptState *script) { + warning("STUB: cmd_getElapsedSeconds"); + return 0; +} + +int KyraEngine::cmd_mouseIsPointer(ScriptState *script) { + warning("STUB: cmd_mouseIsPointer"); + return 0; +} + +int KyraEngine::cmd_destroyMouseItem(ScriptState *script) { + warning("STUB: cmd_destroyMouseItem"); + return 0; +} + +int KyraEngine::cmd_runSceneAnimUntilDone(ScriptState *script) { + warning("STUB: cmd_runSceneAnimUntilDone"); + return 0; +} + +int KyraEngine::cmd_fadeSpecialPalette(ScriptState *script) { + warning("STUB: cmd_fadeSpecialPalette"); + return 0; +} + +int KyraEngine::cmd_playAdlibSound(ScriptState *script) { + warning("STUB: cmd_playAdlibSound"); + return 0; +} + +int KyraEngine::cmd_playAdlibScore(ScriptState *script) { + warning("STUB: cmd_playAdlibScore"); + return 0; +} + +int KyraEngine::cmd_phaseInSameScene(ScriptState *script) { + warning("STUB: cmd_phaseInSameScene"); + return 0; +} + +int KyraEngine::cmd_setScenePhasingFlag(ScriptState *script) { + warning("STUB: cmd_setScenePhasingFlag"); + return 0; +} + +int KyraEngine::cmd_resetScenePhasingFlag(ScriptState *script) { + warning("STUB: cmd_resetScenePhasingFlag"); + return 0; +} + +int KyraEngine::cmd_queryScenePhasingFlag(ScriptState *script) { + warning("STUB: cmd_queryScenePhasingFlag"); + return 0; +} + +int KyraEngine::cmd_sceneToDirection(ScriptState *script) { + warning("STUB: cmd_sceneToDirection"); + return 0; +} + +int KyraEngine::cmd_setBirthstoneGem(ScriptState *script) { + debug(9, "cmd_setBirthstoneGem(0x%X)", script); + int index = stackPos(0); + if (index < 4 && index >= 0) { + _birthstoneGemTable[index] = stackPos(1); + return 1; + } + return 0; +} + +int KyraEngine::cmd_placeItemInGenericMapScene(ScriptState *script) { + debug(9, "cmd_placeItemInGenericMapScene(0x%X)", script); + placeItemInGenericMapScene(stackPos(0), stackPos(1)); + return 0; +} + +int KyraEngine::cmd_setBrandonStatusBit(ScriptState *script) { + warning("STUB: cmd_setBrandonStatusBit"); + return 0; +} + +int KyraEngine::cmd_pauseSeconds(ScriptState *script) { + debug(9, "cmd_pauseSeconds(0x%X)", script); + _system->delayMillis(stackPos(0)*1000); + return 0; +} + +int KyraEngine::cmd_getCharactersLocation(ScriptState *script) { + warning("STUB: cmd_getCharactersLocation"); + return 0; +} + +int KyraEngine::cmd_runNPCSubscript(ScriptState *script) { + warning("STUB: cmd_runNPCSubscript"); + return 0; +} + +int KyraEngine::cmd_magicOutMouseItem(ScriptState *script) { + warning("STUB: cmd_magicOutMouseItem"); + return 0; +} + +int KyraEngine::cmd_internalAnimOn(ScriptState *script) { + warning("STUB: cmd_internalAnimOn"); + return 0; +} + +int KyraEngine::cmd_forceBrandonToNormal(ScriptState *script) { + warning("STUB: cmd_forceBrandonToNormal"); + return 0; +} + +int KyraEngine::cmd_poisonDeathNow(ScriptState *script) { + warning("STUB: cmd_poisonDeathNow"); + return 0; +} + +int KyraEngine::cmd_setScaleMode(ScriptState *script) { + warning("STUB: cmd_setScaleMode"); + return 0; +} + +int KyraEngine::cmd_openWSAFile(ScriptState *script) { + debug(9, "cmd_openWSAFile(0x%X)", script); + + int wsaIndex = stackPos(0); + uint16 offset = READ_BE_UINT16(&script->dataPtr->text[wsaIndex]); + char *filename = (char*)&script->dataPtr->text[offset]; + + wsaIndex = stackPos(1); + // stackPos(2) is NOT used whyever + int offscreenDecode = 0; + if (!stackPos(3)) { + offscreenDecode = 1; + } else { + offscreenDecode = 0; + } + + _wsaObjects[wsaIndex] = wsa_open(filename, offscreenDecode, 0); + assert(_wsaObjects[wsaIndex]); + + return 0; +} + +int KyraEngine::cmd_closeWSAFile(ScriptState *script) { + debug(9, "cmd_closeWSAFile(0x%X)", script); + + int wsaIndex = stackPos(0); + if (_wsaObjects[wsaIndex]) { + wsa_close(_wsaObjects[wsaIndex]); + _wsaObjects[wsaIndex] = 0; + } + + return 0; +} + +int KyraEngine::cmd_runWSAFromBeginningToEnd(ScriptState *script) { + debug(9, "cmd_runWSAFromBeginningToEnd(0x%X)", script); + + _screen->hideMouse(); + + bool running = true; + + int xpos = stackPos(0); + int ypos = stackPos(1); + int waitTime = stackPos(2); + int wsaIndex = stackPos(3); + int worldUpdate = stackPos(4); + int wsaFrame = 0; + + while (running) { + wsa_play(_wsaObjects[wsaIndex], wsaFrame++, xpos, ypos, 0); + if (wsaFrame >= wsa_getNumFrames(_wsaObjects[wsaIndex])) + running = false; + + waitTicks(waitTime); + _screen->updateScreen(); + if (worldUpdate) { + updateAllObjectShapes(); + // XXX + } + } + + _screen->showMouse(); + + return 0; +} + +int KyraEngine::cmd_displayWSAFrame(ScriptState *script) { + warning("STUB: cmd_displayWSAFrame"); + return 0; +} + +int KyraEngine::cmd_enterNewScene(ScriptState *script) { + debug(9, "cmd_enterNewScene(0x%X)", script); + enterNewScene(stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4)); + return 0; +} + +int KyraEngine::cmd_setSpecialEnterXAndY(ScriptState *script) { + debug(9, "cmd_setSpecialEnterXAndY(0x%X)", script); + _brandonPosX = stackPos(0); + _brandonPosY = stackPos(1); + if (_brandonPosX + 1 == 0 && _brandonPosY + 1 == 0) + _currentCharacter->currentAnimFrame = 88; + return 0; +} + +int KyraEngine::cmd_runWSAFrames(ScriptState *script) { + warning("STUB: cmd_runWSAFrames"); + return 0; +} + +int KyraEngine::cmd_popBrandonIntoScene(ScriptState *script) { + warning("STUB: cmd_popBrandonIntoScene"); + return 0; +} + +int KyraEngine::cmd_restoreAllObjectBackgrounds(ScriptState *script) { + warning("STUB: cmd_restoreAllObjectBackgrounds"); + return 0; +} + +int KyraEngine::cmd_setCustomPaletteRange(ScriptState *script) { + warning("STUB: cmd_setCustomPaletteRange"); + return 0; +} + +int KyraEngine::cmd_loadPageFromDisk(ScriptState *script) { + warning("STUB: cmd_loadPageFromDisk"); + return 0; +} + +int KyraEngine::cmd_customPrintTalkString(ScriptState *script) { + warning("STUB: cmd_customPrintTalkString"); + return 0; +} + +int KyraEngine::cmd_restoreCustomPrintBackground(ScriptState *script) { + warning("STUB: cmd_restoreCustomPrintBackground"); + return 0; +} + +int KyraEngine::cmd_hideMouse(ScriptState *script) { + debug(9, "cmd_hideMouse(0x%X)", script); + _screen->hideMouse(); + return 0; +} + +int KyraEngine::cmd_showMouse(ScriptState *script) { + debug(9, "cmd_showMouse(0x%X)", script); + _screen->showMouse(); + return 0; +} + +int KyraEngine::cmd_getCharacterX(ScriptState *script) { + debug(9, "cmd_getCharacterX(0x%X)", script); + return _characterList[stackPos(0)].x1; +} + +int KyraEngine::cmd_getCharacterY(ScriptState *script) { + debug(9, "cmd_getCharacterY(0x%X)", script); + return _characterList[stackPos(0)].y1; +} + +int KyraEngine::cmd_changeCharactersFacing(ScriptState *script) { + warning("STUB: cmd_changeCharactersFacing"); + return 0; +} + +int KyraEngine::cmd_CopyWSARegion(ScriptState *script) { + warning("STUB: cmd_CopyWSARegion"); + return 0; +} + +int KyraEngine::cmd_printText(ScriptState *script) { + warning("STUB: cmd_printText"); + return 0; +} + +int KyraEngine::cmd_random(ScriptState *script) { + debug(9, "cmd_random(0x%X)", script); + assert(stackPos(0) < stackPos(1)); + return _rnd.getRandomNumberRng(stackPos(0), stackPos(1)); +} + +int KyraEngine::cmd_loadSoundFile(ScriptState *script) { + warning("STUB: cmd_loadSoundFile"); + return 0; +} + +int KyraEngine::cmd_displayWSAFrameOnHidPage(ScriptState *script) { + warning("STUB: cmd_displayWSAFrameOnHidPage"); + return 0; +} + +int KyraEngine::cmd_displayWSASequentialFrames(ScriptState *script) { + warning("STUB: cmd_displayWSASequentialFrames"); + return 0; +} + +int KyraEngine::cmd_drawCharacterStanding(ScriptState *script) { + debug(9, "cmd_drawCharacterStanding(0x%X)", script); + // XXX + int character = stackPos(0); + int animFrame = stackPos(1); + int newFacing = stackPos(2); + int updateShapes = stackPos(3); + _characterList[character].currentAnimFrame = animFrame; + if (newFacing != -1) { + _characterList[character].facing = newFacing; + } + animRefreshNPC(character); + if (updateShapes) { + updateAllObjectShapes(); + } + return 0; +} + +int KyraEngine::cmd_internalAnimOff(ScriptState *script) { + warning("STUB: cmd_internalAnimOff"); + return 0; +} + +int KyraEngine::cmd_changeCharactersXAndY(ScriptState *script) { + warning("STUB: cmd_changeCharactersXAndY"); + return 0; +} + +int KyraEngine::cmd_clearSceneAnimatorBeacon(ScriptState *script) { + warning("STUB: cmd_clearSceneAnimatorBeacon"); + return 0; +} + +int KyraEngine::cmd_querySceneAnimatorBeacon(ScriptState *script) { + warning("STUB: cmd_querySceneAnimatorBeacon"); + return 0; +} + +int KyraEngine::cmd_refreshSceneAnimator(ScriptState *script) { + warning("STUB: cmd_refreshSceneAnimator"); + return 0; +} + +int KyraEngine::cmd_placeItemInOffScene(ScriptState *script) { + debug(9, "cmd_placeItemInOffScene(0x%X)", script); + int item = stackPos(0); + int xpos = stackPos(1); + int ypos = stackPos(2); + int sceneId = stackPos(3); + + byte freeItem = findFreeItemInScene(sceneId); + if (freeItem != 0xFF) { + assert(sceneId < _roomTableSize); + Room *room = &_roomTable[sceneId]; + + room->itemsTable[freeItem] = item; + room->itemsXPos[freeItem] = xpos; + room->itemsYPos[freeItem] = ypos; + } + return 0; +} + +int KyraEngine::cmd_wipeDownMouseItem(ScriptState *script) { + warning("STUB: cmd_wipeDownMouseItem"); + return 0; +} + +int KyraEngine::cmd_placeCharacterInOtherScene(ScriptState *script) { + debug(9, "cmd_placeCharacterInOtherScene(0x%X)", script); + int id = stackPos(0); + int sceneId = stackPos(1); + int xpos = stackPos(2) & 0xFFFC; + int ypos = stackPos(3) & 0xFE; + int facing = stackPos(4); + int animFrame = stackPos(5); + + _characterList[id].sceneId = sceneId; + _characterList[id].x1 = _characterList[id].x2 = xpos; + _characterList[id].y1 = _characterList[id].y2 = ypos; + _characterList[id].facing = facing; + _characterList[id].currentAnimFrame = animFrame; + return 0; +} + +int KyraEngine::cmd_getKey(ScriptState *script) { + warning("STUB: cmd_getKey"); + return 0; +} + +int KyraEngine::cmd_specificItemInInventory(ScriptState *script) { + warning("STUB: cmd_specificItemInInventory"); + return 0; +} + +int KyraEngine::cmd_popMobileNPCIntoScene(ScriptState *script) { + warning("STUB: cmd_popMobileNPCIntoScene"); + return 0; +} + +int KyraEngine::cmd_mobileCharacterInScene(ScriptState *script) { + warning("STUB: cmd_mobileCharacterInScene"); + return 0; +} + +int KyraEngine::cmd_hideMobileCharacter(ScriptState *script) { + warning("STUB: cmd_hideMobileCharacter"); + return 0; +} + +int KyraEngine::cmd_unhideMobileCharacter(ScriptState *script) { + warning("STUB: cmd_unhideMobileCharacter"); + return 0; +} + +int KyraEngine::cmd_setCharactersLocation(ScriptState *script) { + warning("STUB: cmd_setCharactersLocation"); + return 0; +} + +int KyraEngine::cmd_walkCharacterToPoint(ScriptState *script) { + warning("STUB: cmd_walkCharacterToPoint"); +// debug(9, "cmd_walkCharacterToPoint(0x%X)", script); +// int character = stackPos(0); +// int toX = stackPos(1); +// int toY = stackPos(2); +// _movUnkVar1 = 1; +// int findWayReturn = findWay(_characterList[character].x1, _characterList[character].y1, toX, toY, _movFacingTable, 150); +// _movUnkVar1 = 0; +// if (_lastFindWayRet < findWayReturn) { +// _lastFindWayRet = findWayReturn; +// } +// if (findWayReturn == 0x7D00 || findWayReturn == 0) { +// return 0; +// } +// int *curPos = _movFacingTable; +// bool running = true; +// while (running) { +// // XXX +// } + return 0; +} + +int KyraEngine::cmd_specialEventDisplayBrynnsNote(ScriptState *script) { + warning("STUB: cmd_specialEventDisplayBrynnsNote"); + return 0; +} + +int KyraEngine::cmd_specialEventRemoveBrynnsNote(ScriptState *script) { + warning("STUB: cmd_specialEventRemoveBrynnsNote"); + return 0; +} + +int KyraEngine::cmd_setLogicPage(ScriptState *script) { + warning("STUB: cmd_setLogicPage"); + return 0; +} + +int KyraEngine::cmd_fatPrint(ScriptState *script) { + warning("STUB: cmd_fatPrint"); + return 0; +} + +int KyraEngine::cmd_preserveAllObjectBackgrounds(ScriptState *script) { + warning("STUB: cmd_preserveAllObjectBackgrounds"); + return 0; +} + +int KyraEngine::cmd_updateSceneAnimations(ScriptState *script) { + warning("STUB: cmd_updateSceneAnimations"); + return 0; +} + +int KyraEngine::cmd_sceneAnimationActive(ScriptState *script) { + warning("STUB: cmd_sceneAnimationActive"); + return 0; +} + +int KyraEngine::cmd_setCharactersMovementDelay(ScriptState *script) { + warning("STUB: cmd_setCharactersMovementDelay"); + return 0; +} + +int KyraEngine::cmd_getCharactersFacing(ScriptState *script) { + warning("STUB: cmd_getCharactersFacing"); + return 0; +} + +int KyraEngine::cmd_bkgdScrollSceneAndMasksRight(ScriptState *script) { + warning("STUB: cmd_bkgdScrollSceneAndMasksRight"); + return 0; +} + +int KyraEngine::cmd_dispelMagicAnimation(ScriptState *script) { + warning("STUB: cmd_dispelMagicAnimation"); + return 0; +} + +int KyraEngine::cmd_findBrightestFireberry(ScriptState *script) { + warning("STUB: cmd_findBrightestFireberry"); + return 0; +} + +int KyraEngine::cmd_setFireberryGlowPalette(ScriptState *script) { + warning("STUB: cmd_setFireberryGlowPalette"); + return 0; +} + +int KyraEngine::cmd_setDeathHandlerFlag(ScriptState *script) { + warning("STUB: cmd_setDeathHandlerFlag"); + return 0; +} + +int KyraEngine::cmd_drinkPotionAnimation(ScriptState *script) { + warning("STUB: cmd_drinkPotionAnimation"); + return 0; +} + +int KyraEngine::cmd_makeAmuletAppear(ScriptState *script) { + warning("STUB: cmd_makeAmuletAppear"); + return 0; +} + +int KyraEngine::cmd_drawItemShapeIntoScene(ScriptState *script) { + warning("STUB: cmd_drawItemShapeIntoScene"); + return 0; +} + +int KyraEngine::cmd_setCharactersCurrentFrame(ScriptState *script) { + warning("STUB: cmd_setCharactersCurrentFrame"); + return 0; +} + +int KyraEngine::cmd_waitForConfirmationMouseClick(ScriptState *script) { + warning("STUB: cmd_waitForConfirmationMouseClick"); + return 0; +} + +int KyraEngine::cmd_pageFlip(ScriptState *script) { + warning("STUB: cmd_pageFlip"); + return 0; +} + +int KyraEngine::cmd_setSceneFile(ScriptState *script) { + warning("STUB: cmd_setSceneFile"); + return 0; +} + +int KyraEngine::cmd_getItemInMarbleVase(ScriptState *script) { + warning("STUB: cmd_getItemInMarbleVase"); + return 0; +} + +int KyraEngine::cmd_setItemInMarbleVase(ScriptState *script) { + debug(9, "cmd_setItemInMarbleVase(0x%X)", script); + _marbleVaseItem = stackPos(0); + return 0; +} + +int KyraEngine::cmd_addItemToInventory(ScriptState *script) { + warning("STUB: cmd_addItemToInventory"); + return 0; +} + +int KyraEngine::cmd_intPrint(ScriptState *script) { + warning("STUB: cmd_intPrint"); + return 0; +} + +int KyraEngine::cmd_shakeScreen(ScriptState *script) { + warning("STUB: cmd_shakeScreen"); + return 0; +} + +int KyraEngine::cmd_createAmuletJewel(ScriptState *script) { + warning("STUB: cmd_createAmuletJewel"); + return 0; +} + +int KyraEngine::cmd_setSceneAnimCurrXY(ScriptState *script) { + warning("STUB: cmd_setSceneAnimCurrXY"); + return 0; +} + +int KyraEngine::cmd_Poison_Brandon_And_Remaps(ScriptState *script) { + warning("STUB: cmd_Poison_Brandon_And_Remaps"); + return 0; +} + +int KyraEngine::cmd_fillFlaskWithWater(ScriptState *script) { + warning("STUB: cmd_fillFlaskWithWater"); + return 0; +} + +int KyraEngine::cmd_getCharactersMovementDelay(ScriptState *script) { + warning("STUB: cmd_getCharactersMovementDelay"); + return 0; +} + +int KyraEngine::cmd_getBirthstoneGem(ScriptState *script) { + warning("STUB: cmd_getBirthstoneGem"); + return 0; +} + +int KyraEngine::cmd_queryBrandonStatusBit(ScriptState *script) { + warning("STUB: cmd_queryBrandonStatusBit"); + return 0; +} + +int KyraEngine::cmd_playFluteAnimation(ScriptState *script) { + warning("STUB: cmd_playFluteAnimation"); + return 0; +} + +int KyraEngine::cmd_playWinterScrollSequence(ScriptState *script) { + warning("STUB: cmd_playWinterScrollSequence"); + return 0; +} + +int KyraEngine::cmd_getIdolGem(ScriptState *script) { + warning("STUB: cmd_getIdolGem"); + return 0; +} + +int KyraEngine::cmd_setIdolGem(ScriptState *script) { + debug(9, "cmd_setIdolGem(0x%X)", script); + _idolGemsTable[stackPos(0)] = stackPos(1); + return 0; +} + +int KyraEngine::cmd_totalItemsInScene(ScriptState *script) { + warning("STUB: cmd_totalItemsInScene"); + return 0; +} + +int KyraEngine::cmd_restoreBrandonsMovementDelay(ScriptState *script) { + warning("STUB: cmd_restoreBrandonsMovementDelay"); + return 0; +} + +int KyraEngine::cmd_setMousePos(ScriptState *script) { + warning("STUB: cmd_setMousePos"); + return 0; +} + +int KyraEngine::cmd_getMouseState(ScriptState *script) { + warning("STUB: cmd_getMouseState"); + return 0; +} + +int KyraEngine::cmd_setEntranceMouseCursorTrack(ScriptState *script) { + debug(9, "cmd_setEntranceMouseCursorTrack(0x%X)", script); + _entranceMouseCursorTracks[0] = stackPos(0); + _entranceMouseCursorTracks[1] = stackPos(1); + _entranceMouseCursorTracks[2] = stackPos(0) + stackPos(2) - 1; + _entranceMouseCursorTracks[3] = stackPos(1) + stackPos(3) - 1; + _entranceMouseCursorTracks[4] = stackPos(3); + return 0; +} + +int KyraEngine::cmd_itemAppearsOnGround(ScriptState *script) { + warning("STUB: cmd_itemAppearsOnGround"); + return 0; +} + +int KyraEngine::cmd_setNoDrawShapesFlag(ScriptState *script) { + warning("STUB: cmd_setNoDrawShapesFlag"); + return 0; +} + +int KyraEngine::cmd_fadeEntirePalette(ScriptState *script) { + warning("STUB: cmd_fadeEntirePalette"); + return 0; +} + +int KyraEngine::cmd_itemOnGroundHere(ScriptState *script) { + warning("STUB: cmd_itemOnGroundHere"); + return 0; +} + +int KyraEngine::cmd_queryCauldronState(ScriptState *script) { + warning("STUB: cmd_queryCauldronState"); + return 0; +} + +int KyraEngine::cmd_setCauldronState(ScriptState *script) { + warning("STUB: cmd_setCauldronState"); + return 0; +} + +int KyraEngine::cmd_queryCrystalState(ScriptState *script) { + warning("STUB: cmd_queryCrystalState"); + return 0; +} + +int KyraEngine::cmd_setCrystalState(ScriptState *script) { + warning("STUB: cmd_setCrystalState"); + return 0; +} + +int KyraEngine::cmd_setPaletteRange(ScriptState *script) { + warning("STUB: cmd_setPaletteRange"); + return 0; +} + +int KyraEngine::cmd_shrinkBrandonDown(ScriptState *script) { + warning("STUB: cmd_shrinkBrandonDown"); + return 0; +} + +int KyraEngine::cmd_growBrandonUp(ScriptState *script) { + warning("STUB: cmd_growBrandonUp"); + return 0; +} + +int KyraEngine::cmd_setBrandonScaleXAndY(ScriptState *script) { + warning("STUB: cmd_setBrandonScaleXAndY"); + return 0; +} + +int KyraEngine::cmd_resetScaleMode(ScriptState *script) { + warning("STUB: cmd_resetScaleMode"); + return 0; +} + +int KyraEngine::cmd_getScaleDepthTableValue(ScriptState *script) { + warning("STUB: cmd_getScaleDepthTableValue"); + return 0; +} + +int KyraEngine::cmd_setScaleDepthTableValue(ScriptState *script) { + warning("STUB: cmd_setScaleDepthTableValue"); + return 0; +} + +int KyraEngine::cmd_message(ScriptState *script) { + warning("STUB: cmd_message"); + return 0; +} + +int KyraEngine::cmd_checkClickOnNPC(ScriptState *script) { + warning("STUB: cmd_checkClickOnNPC"); + return 0; +} + +int KyraEngine::cmd_getFoyerItem(ScriptState *script) { + warning("STUB: cmd_getFoyerItem"); + return 0; +} + +int KyraEngine::cmd_setFoyerItem(ScriptState *script) { + warning("STUB: cmd_setFoyerItem"); + return 0; +} + +int KyraEngine::cmd_setNoItemDropRegion(ScriptState *script) { + debug(9, "cmd_setNoItemDropRegion(0x%X)", script); + addToNoDropRects(stackPos(0), stackPos(1), stackPos(2), stackPos(3)); + return 0; +} + +int KyraEngine::cmd_walkMalcolmOn(ScriptState *script) { + warning("STUB: cmd_walkMalcolmOn"); + return 0; +} + +int KyraEngine::cmd_passiveProtection(ScriptState *script) { + warning("STUB: cmd_passiveProtection"); + return 0; +} + +int KyraEngine::cmd_setPlayingLoop(ScriptState *script) { + warning("STUB: cmd_setPlayingLoop"); + return 0; +} + +int KyraEngine::cmd_brandonToStoneSequence(ScriptState *script) { + warning("STUB: cmd_brandonToStoneSequence"); + return 0; +} + +int KyraEngine::cmd_brandonHealingSequence(ScriptState *script) { + warning("STUB: cmd_brandonHealingSequence"); + return 0; +} + +int KyraEngine::cmd_protectCommandLine(ScriptState *script) { + warning("STUB: cmd_protectCommandLine"); + return 0; +} + +int KyraEngine::cmd_pauseMusicSeconds(ScriptState *script) { + warning("STUB: cmd_pauseMusicSeconds"); + return 0; +} + +int KyraEngine::cmd_resetMaskRegion(ScriptState *script) { + warning("STUB: cmd_resetMaskRegion"); + return 0; +} + +int KyraEngine::cmd_setPaletteChangeFlag(ScriptState *script) { + warning("STUB: cmd_setPaletteChangeFlag"); + return 0; +} + +int KyraEngine::cmd_fillRect(ScriptState *script) { + warning("STUB: cmd_fillRect"); + return 0; +} + +int KyraEngine::cmd_dummy(ScriptState *script) { + debug(9, "cmd_dummy(0x%X)", script); + return 0; +} + } // end of namespace Kyra diff --git a/kyra/sprites.cpp b/kyra/sprites.cpp index a9ca8eda44..62fb5ff26f 100644 --- a/kyra/sprites.cpp +++ b/kyra/sprites.cpp @@ -37,16 +37,20 @@ Sprites::Sprites(KyraEngine *engine, OSystem *system) { _system = system; _dat = 0; memset(_anims, 0, sizeof(_anims)); + memset( _sceneShapes, 0, sizeof(_sceneShapes)); _animDelay = 16; + _spriteDefStart = 0; + } Sprites::~Sprites() { delete[] _dat; + freeSceneShapes(); } -Sprite Sprites::getSprite(uint8 spriteID) { - assert( spriteID < MAX_NUM_SPRITES); - return _sprites[spriteID]; +uint8 *Sprites::getSceneShape(uint8 sceneShapeID) { + assert( sceneShapeID < ARRAYSIZE(_sceneShapes)); + return _sceneShapes[sceneShapeID]; } void Sprites::drawSprites(uint8 srcPage, uint8 dstPage) { @@ -56,21 +60,23 @@ void Sprites::drawSprites(uint8 srcPage, uint8 dstPage) { if (_anims[i].script == 0 || !_anims[i].play) break; if (_anims[i].sprite >= 0) { - assert( _anims[i].sprite < MAX_NUM_SPRITES); - Sprite sprite = _sprites[_anims[i].sprite]; + assert( _anims[i].sprite < ARRAYSIZE(_sceneShapes)); + uint8 *sprite = _sceneShapes[_anims[i].sprite]; //debug(1, "Drawing from X %i, Y %i, to X %i, Y %i, width %i, height %i, srcPage %i, dstPage %i", // sprite.x, sprite.y, _anims[i].x, _anims[i].y, sprite.width, sprite.height, srcPage, dstPage); flags = Screen::CR_CLIPPED; if (_anims[i].flipX) flags |= Screen::CR_X_FLIPPED; - - _screen->copyRegion(sprite.x, sprite.y, _anims[i].x, _anims[i].y, sprite.width, sprite.height, srcPage, dstPage, flags); + + //_screen->copyRegion(sprite.x, sprite.y, _anims[i].x, _anims[i].y, sprite.width, sprite.height, srcPage, dstPage, flags); + _screen->drawShape(0, sprite, _anims[i].x, _anims[i].y, 0, 0, 0); } } } void Sprites::doAnims() { + debug(9, "Sprites::doAnims()"); uint32 currTime = _system->getMillis(); for (int i = 0; i < MAX_NUM_ANIMS; i++) { if (_anims[i].script == 0 || !_anims[i].play || _anims[i].nextRun != 0 && _anims[i].nextRun > currTime) @@ -363,6 +369,10 @@ void Sprites::loadDAT(const char *filename) { assert(fileSize > 0x6D); + _engine->_northExitHeight = READ_BE_UINT16(_dat + 0x15); + if (_engine->_northExitHeight & 1) + _engine->_northExitHeight += 1; + // XXX memcpy(_screen->_currentPalette + 745 - 0x3D, _dat + 0x17, 0x3D); _screen->setScreenPalette(_screen->_currentPalette); uint8 *data = _dat + 0x6B; @@ -398,27 +408,10 @@ void Sprites::loadDAT(const char *filename) { break; case 0xFF84: data += 2; + _spriteDefStart = data; while (READ_LE_UINT16(data) != 0xFF85) { - uint16 spriteNum = READ_LE_UINT16(data); - //debug(1, "Spritenum: %i", spriteNum); - assert(spriteNum < MAX_NUM_SPRITES); - data += 2; - _sprites[spriteNum].x = READ_LE_UINT16(data) * 8; - data += 2; - _sprites[spriteNum].y = READ_LE_UINT16(data); - data += 2; - _sprites[spriteNum].width = READ_LE_UINT16(data) * 8; data += 2; - _sprites[spriteNum].height = READ_LE_UINT16(data); - data += 2; - spritesLoaded++; - //debug(1, "Got sprite index: %i", spriteNum); - //debug(1, "X: %i", _sprites[spriteNum].x); - //debug(1, "Y: %i", _sprites[spriteNum].y); - //debug(1, "Width: %i", _sprites[spriteNum].width); - //debug(1, "Height: %i", _sprites[spriteNum].height); } - //debug(1, "End of sprite images."); data += 2; break; case 0xFF86: @@ -453,6 +446,48 @@ void Sprites::loadDAT(const char *filename) { assert(fileSize - (data - _dat) == 0xC); //TODO: Read in character entry coords here + SceneExits &exits = _engine->sceneExits(); + + exits.NorthXPos = READ_LE_UINT16(data) & 0xFFFC; data += 2; + exits.NorthYPos = *data++ & 0xFFFE; + exits.EastXPos = READ_LE_UINT16(data) & 0xFFFC; data += 2; + exits.EastYPos = *data++ & 0xFFFE; + exits.SouthXPos = READ_LE_UINT16(data) & 0xFFFC; data += 2; + exits.SouthYPos = *data++ & 0xFFFE; + exits.WestXPos = READ_LE_UINT16(data) & 0xFFFC; data += 2; + exits.WestYPos = *data++ & 0xFFFE; +} + +void Sprites::freeSceneShapes() { + for (int i = 0; i < ARRAYSIZE(_sceneShapes); i++ ) + free(_sceneShapes[i]); + +} + +void Sprites::loadSceneShapes() { + debug(9, "Sprites::loadSceneShapes()"); + uint8 *data = _spriteDefStart; + int spriteNum, x, y, width, height; + + assert(_spriteDefStart); + + freeSceneShapes(); + memset( _sceneShapes, 0, sizeof(_sceneShapes)); + + while (READ_LE_UINT16(data) != 0xFF85) { + spriteNum = READ_LE_UINT16(data); + assert(spriteNum < ARRAYSIZE(_sceneShapes)); + data += 2; + x = READ_LE_UINT16(data) * 8; + data += 2; + y = READ_LE_UINT16(data); + data += 2; + width = READ_LE_UINT16(data) * 8; + data += 2; + height = READ_LE_UINT16(data); + data += 2; + _sceneShapes[spriteNum] = _screen->encodeShape(x, y, width, height, 0); + } } } // end of namespace Kyra diff --git a/kyra/sprites.h b/kyra/sprites.h index 348f7da247..c64bf045cc 100644 --- a/kyra/sprites.h +++ b/kyra/sprites.h @@ -24,7 +24,6 @@ namespace Kyra { -#define MAX_NUM_SPRITES 50 #define MAX_NUM_ANIMS 11 struct Sprite { @@ -55,23 +54,27 @@ public: ~Sprites(); void doAnims(); - void loadDAT(const char* filename); - Sprite getSprite(uint8 spriteID); + void loadDAT(const char *filename); + uint8 *getSceneShape(uint8 sceneShapeID); void drawSprites(uint8 srcPage, uint8 dstPage); + void loadSceneShapes(); void enableAnim(uint8 anim) { _anims[anim].play = true; } void disableAnim(uint8 anim) { _anims[anim].play = false; } protected: + void freeSceneShapes(); + KyraEngine *_engine; Resource *_res; OSystem *_system; Screen *_screen; - Sprite _sprites[MAX_NUM_SPRITES]; + uint8 *_sceneShapes[50]; uint8 *_dat; Anim _anims[MAX_NUM_ANIMS]; Common::RandomSource _rnd; uint8 _animDelay; + uint8 *_spriteDefStart; }; } // End of namespace Kyra diff --git a/kyra/staticres.cpp b/kyra/staticres.cpp index 2918dd477f..cff46c2276 100644 --- a/kyra/staticres.cpp +++ b/kyra/staticres.cpp @@ -26,7 +26,7 @@ namespace Kyra { -#define RESFILE_VERSION 1 +#define RESFILE_VERSION 2 #define GAME_FLAGS (GF_FLOPPY | GF_TALKIE | GF_DEMO | GF_AUDIOCD) #define LANGUAGE_FLAGS (GF_ENGLISH | GF_FRENCH | GF_GERMAN | GF_SPANISH | GF_LNGUNK) @@ -129,31 +129,41 @@ void KyraEngine::res_loadResources(int type) { loadNativeLanguage = false; } -#define loadRawFile(x, y, z) \ +#define getFileEx(x, y) \ if (_features & GF_TALKIE) { \ temp = getFile(x, y ".CD"); \ } else if (_features & GF_DEMO) { \ temp = getFile(x, y ".DEM"); \ } else { \ temp = getFile(x, y); \ - } \ + } +#define loadRawFile(x, y, z) \ + getFileEx(x, y) \ if (temp) { \ z = temp; \ temp = 0; \ } #define loadTable(x, y, z, a) \ - if (_features & GF_TALKIE) { \ - temp = getFile(x, y ".CD"); \ - } else if (_features & GF_DEMO) { \ - temp = getFile(x, y ".DEM"); \ - } else { \ - temp = getFile(x, y); \ - } \ + getFileEx(x, y) \ if (temp) { \ res_loadTable(temp, z, a); \ delete [] temp; \ temp = 0; \ } +#define loadRooms(x, y, z, a) \ + getFileEx(x, y) \ + if (temp) { \ + res_loadRoomTable(temp, z, a); \ + delete [] temp; \ + temp = 0; \ + } +#define loadShapes(x, y, z, a) \ + getFileEx(x, y) \ + if (temp) { \ + res_loadShapeTable(temp, z, a); \ + delete [] temp; \ + temp = 0; \ + } if ((type & RES_INTRO) || type == RES_ALL) { loadRawFile(resFile, "FOREST.SEQ", _seq_Forest); @@ -174,8 +184,19 @@ void KyraEngine::res_loadResources(int type) { res_loadLangTable("INTRO-STRINGS.", &resFile, (byte***)&_seq_textsTable, &_seq_textsTable_Size, loadNativeLanguage); } + if ((type & RES_INGAME) || type == RES_ALL) { + loadTable(resFile, "ROOM-FILENAMES.TXT", (byte***)&_roomFilenameTable, &_roomFilenameTableSize); + loadRooms(resFile, "ROOM-TABLE.ROOM", &_roomTable, &_roomTableSize); + + loadTable(resFile, "CHAR-IMAGE.TXT", (byte***)&_characterImageTable, &_characterImageTableSize); + + loadShapes(resFile, "SHAPES-DEFAULT.SHP", &_defaultShapeTable, &_defaultShapeTableSize); + } + +#undef loadRooms #undef loadTable #undef loadRawFile +#undef getFileEx } void KyraEngine::res_unloadResources(int type) { @@ -220,6 +241,27 @@ void KyraEngine::res_unloadResources(int type) { delete [] _seq_Demo3; _seq_Demo3 = 0; delete [] _seq_Demo4; _seq_Demo4 = 0; } + + if ((type & RES_INGAME) || type == RES_ALL) { + for (int i = 0; i < _roomFilenameTableSize; ++i) { + delete [] _roomFilenameTable[i]; + } + delete [] _roomFilenameTable; + _roomFilenameTableSize = 0; + _roomFilenameTable = 0; + + delete [] _roomTable; _roomTable = 0; + _roomTableSize = 0; + + for (int i = 0; i < _characterImageTableSize; ++i) { + delete [] _characterImageTable[i]; + } + delete [] _characterImageTable; + _characterImageTableSize = 0; + + delete [] _defaultShapeTable; + _defaultShapeTableSize = 0; + } } void KyraEngine::res_loadLangTable(const char *filename, PAKFile *res, byte ***loadTo, int *size, bool nativ) { @@ -263,6 +305,41 @@ void KyraEngine::res_loadTable(const byte *src, byte ***loadTo, int *size) { } } +void KyraEngine::res_loadRoomTable(const byte *src, Room **loadTo, int *size) { + uint32 count = READ_BE_UINT32(src); src += 4; + *size = count; + *loadTo = new Room[count]; + + for (uint32 i = 0; i < count; ++i) { + (*loadTo)[i].nameIndex = *src++; + (*loadTo)[i].northExit = READ_LE_UINT16(src); src += 2; + (*loadTo)[i].eastExit = READ_LE_UINT16(src); src += 2; + (*loadTo)[i].southExit = READ_LE_UINT16(src); src += 2; + (*loadTo)[i].westExit = READ_LE_UINT16(src); src += 2; + memset(&(*loadTo)[i].itemsTable[0], 0xFF, sizeof(byte)*6); + memset(&(*loadTo)[i].itemsTable[6], 0, sizeof(byte)*6); + memset((*loadTo)[i].itemsXPos, 0, sizeof(uint16)*12); + memset((*loadTo)[i].itemsYPos, 0, sizeof(uint8)*12); + memset((*loadTo)[i].unkField3, 0, sizeof((*loadTo)[i].unkField3)); + } +} + +void KyraEngine::res_loadShapeTable(const byte *src, Shape **loadTo, int *size) { + uint32 count = READ_BE_UINT32(src); src += 4; + *size = count; + *loadTo = new Shape[count]; + + for (uint32 i = 0; i < count; ++i) { + (*loadTo)[i].imageIndex = *src++; + (*loadTo)[i].x = *src++; + (*loadTo)[i].y = *src++; + (*loadTo)[i].w = *src++; + (*loadTo)[i].h = *src++; + (*loadTo)[i].xOffset = *src++; + (*loadTo)[i].yOffset = *src++; + } +} + const ScreenDim Screen::_screenDimTable[] = { { 0x00, 0x00, 0x28, 0xC8, 0x0F, 0x0C, 0x00, 0x00 }, { 0x08, 0x48, 0x18, 0x38, 0x0F, 0x0C, 0x00, 0x00 }, @@ -279,12 +356,207 @@ const ScreenDim Screen::_screenDimTable[] = { const int Screen::_screenDimTableCount = ARRAYSIZE(_screenDimTable); -const Screen::DrawShapePlotPixelCallback Screen::_drawShapePlotPixelTable[] = { - &Screen::drawShapePlotPixelCallback1 - // XXX +// CD Version *could* use an different opcodeTable +#define Opcode(x) &KyraEngine::x +KyraEngine::OpcodeProc KyraEngine::_opcodeTable[] = { + // 0x00 + Opcode(cmd_magicInMouseItem), + Opcode(cmd_characterSays), + Opcode(cmd_pauseTicks), + Opcode(cmd_drawSceneAnimShape), + // 0x04 + Opcode(cmd_queryGameFlag), + Opcode(cmd_setGameFlag), + Opcode(cmd_resetGameFlag), + Opcode(cmd_runNPCScript), + // 0x08 + Opcode(cmd_setSpecialExitList), + Opcode(cmd_blockInWalkableRegion), + Opcode(cmd_blockOutWalkableRegion), + Opcode(cmd_walkPlayerToPoint), + // 0x0c + Opcode(cmd_dropItemInScene), + Opcode(cmd_drawAnimShapeIntoScene), + Opcode(cmd_createMouseItem), + Opcode(cmd_savePageToDisk), + // 0x10 + Opcode(cmd_sceneAnimOn), + Opcode(cmd_sceneAnimOff), + Opcode(cmd_getElapsedSeconds), + Opcode(cmd_mouseIsPointer), + // 0x14 + Opcode(cmd_destroyMouseItem), + Opcode(cmd_runSceneAnimUntilDone), + Opcode(cmd_fadeSpecialPalette), + Opcode(cmd_playAdlibSound), + // 0x18 + Opcode(cmd_playAdlibScore), + Opcode(cmd_phaseInSameScene), + Opcode(cmd_setScenePhasingFlag), + Opcode(cmd_resetScenePhasingFlag), + // 0x1c + Opcode(cmd_queryScenePhasingFlag), + Opcode(cmd_sceneToDirection), + Opcode(cmd_setBirthstoneGem), + Opcode(cmd_placeItemInGenericMapScene), + // 0x20 + Opcode(cmd_setBrandonStatusBit), + Opcode(cmd_pauseSeconds), + Opcode(cmd_getCharactersLocation), + Opcode(cmd_runNPCSubscript), + // 0x24 + Opcode(cmd_magicOutMouseItem), + Opcode(cmd_internalAnimOn), + Opcode(cmd_forceBrandonToNormal), + Opcode(cmd_poisonDeathNow), + // 0x28 + Opcode(cmd_setScaleMode), + Opcode(cmd_openWSAFile), + Opcode(cmd_closeWSAFile), + Opcode(cmd_runWSAFromBeginningToEnd), + // 0x2c + Opcode(cmd_displayWSAFrame), + Opcode(cmd_enterNewScene), + Opcode(cmd_setSpecialEnterXAndY), + Opcode(cmd_runWSAFrames), + // 0x30 + Opcode(cmd_popBrandonIntoScene), + Opcode(cmd_restoreAllObjectBackgrounds), + Opcode(cmd_setCustomPaletteRange), + Opcode(cmd_loadPageFromDisk), + // 0x34 + Opcode(cmd_customPrintTalkString), + Opcode(cmd_restoreCustomPrintBackground), + Opcode(cmd_hideMouse), + Opcode(cmd_showMouse), + // 0x38 + Opcode(cmd_getCharacterX), + Opcode(cmd_getCharacterY), + Opcode(cmd_changeCharactersFacing), + Opcode(cmd_CopyWSARegion), + // 0x3c + Opcode(cmd_printText), + Opcode(cmd_random), + Opcode(cmd_loadSoundFile), + Opcode(cmd_displayWSAFrameOnHidPage), + // 0x40 + Opcode(cmd_displayWSASequentialFrames), + Opcode(cmd_drawCharacterStanding), + Opcode(cmd_internalAnimOff), + Opcode(cmd_changeCharactersXAndY), + // 0x44 + Opcode(cmd_clearSceneAnimatorBeacon), + Opcode(cmd_querySceneAnimatorBeacon), + Opcode(cmd_refreshSceneAnimator), + Opcode(cmd_placeItemInOffScene), + // 0x48 + Opcode(cmd_wipeDownMouseItem), + Opcode(cmd_placeCharacterInOtherScene), + Opcode(cmd_getKey), + Opcode(cmd_specificItemInInventory), + // 0x4c + Opcode(cmd_popMobileNPCIntoScene), + Opcode(cmd_mobileCharacterInScene), + Opcode(cmd_hideMobileCharacter), + Opcode(cmd_unhideMobileCharacter), + // 0x50 + Opcode(cmd_setCharactersLocation), + Opcode(cmd_walkCharacterToPoint), + Opcode(cmd_specialEventDisplayBrynnsNote), + Opcode(cmd_specialEventRemoveBrynnsNote), + // 0x54 + Opcode(cmd_setLogicPage), + Opcode(cmd_fatPrint), + Opcode(cmd_preserveAllObjectBackgrounds), + Opcode(cmd_updateSceneAnimations), + // 0x58 + Opcode(cmd_sceneAnimationActive), + Opcode(cmd_setCharactersMovementDelay), + Opcode(cmd_getCharactersFacing), + Opcode(cmd_bkgdScrollSceneAndMasksRight), + // 0x5c + Opcode(cmd_dispelMagicAnimation), + Opcode(cmd_findBrightestFireberry), + Opcode(cmd_setFireberryGlowPalette), + Opcode(cmd_setDeathHandlerFlag), + // 0x60 + Opcode(cmd_drinkPotionAnimation), + Opcode(cmd_makeAmuletAppear), + Opcode(cmd_drawItemShapeIntoScene), + Opcode(cmd_setCharactersCurrentFrame), + // 0x64 + Opcode(cmd_waitForConfirmationMouseClick), + Opcode(cmd_pageFlip), + Opcode(cmd_setSceneFile), + Opcode(cmd_getItemInMarbleVase), + // 0x68 + Opcode(cmd_setItemInMarbleVase), + Opcode(cmd_addItemToInventory), + Opcode(cmd_intPrint), + Opcode(cmd_shakeScreen), + // 0x6c + Opcode(cmd_createAmuletJewel), + Opcode(cmd_setSceneAnimCurrXY), + Opcode(cmd_Poison_Brandon_And_Remaps), + Opcode(cmd_fillFlaskWithWater), + // 0x70 + Opcode(cmd_getCharactersMovementDelay), + Opcode(cmd_getBirthstoneGem), + Opcode(cmd_queryBrandonStatusBit), + Opcode(cmd_playFluteAnimation), + // 0x74 + Opcode(cmd_playWinterScrollSequence), + Opcode(cmd_getIdolGem), + Opcode(cmd_setIdolGem), + Opcode(cmd_totalItemsInScene), + // 0x78 + Opcode(cmd_restoreBrandonsMovementDelay), + Opcode(cmd_setMousePos), + Opcode(cmd_getMouseState), + Opcode(cmd_setEntranceMouseCursorTrack), + // 0x7c + Opcode(cmd_itemAppearsOnGround), + Opcode(cmd_setNoDrawShapesFlag), + Opcode(cmd_fadeEntirePalette), + Opcode(cmd_itemOnGroundHere), + // 0x80 + Opcode(cmd_queryCauldronState), + Opcode(cmd_setCauldronState), + Opcode(cmd_queryCrystalState), + Opcode(cmd_setCrystalState), + // 0x84 + Opcode(cmd_setPaletteRange), + Opcode(cmd_shrinkBrandonDown), + Opcode(cmd_growBrandonUp), + Opcode(cmd_setBrandonScaleXAndY), + // 0x88 + Opcode(cmd_resetScaleMode), + Opcode(cmd_getScaleDepthTableValue), + Opcode(cmd_setScaleDepthTableValue), + Opcode(cmd_message), + // 0x8c + Opcode(cmd_checkClickOnNPC), + Opcode(cmd_getFoyerItem), + Opcode(cmd_setFoyerItem), + Opcode(cmd_setNoItemDropRegion), + // 0x90 + Opcode(cmd_walkMalcolmOn), + Opcode(cmd_passiveProtection), + Opcode(cmd_setPlayingLoop), + Opcode(cmd_brandonToStoneSequence), + // 0x94 + Opcode(cmd_brandonHealingSequence), + Opcode(cmd_protectCommandLine), + Opcode(cmd_pauseMusicSeconds), + Opcode(cmd_resetMaskRegion), + // 0x98 + Opcode(cmd_setPaletteChangeFlag), + Opcode(cmd_fillRect), + Opcode(cmd_dummy) }; +#undef Opcode -const int Screen::_drawShapePlotPixelCount = ARRAYSIZE(_drawShapePlotPixelTable); +const int KyraEngine::_opcodeTableSize = ARRAYSIZE(_opcodeTable); const char *KyraEngine::_xmidiFiles[] = { "INTRO.XMI", @@ -301,4 +573,12 @@ const char *KyraEngine::_xmidiFiles[] = { const int KyraEngine::_xmidiFilesCount = ARRAYSIZE(_xmidiFiles); +const int8 KyraEngine::_charXPosTable[] = { + 0x00, 0x04, 0x04, 0x04, 0x00, 0xFC, 0xFC, 0xFC +}; + +const int8 KyraEngine::_charYPosTable[] = { + 0xFE, 0xFE, 0x00, 0x03, 0x02, 0x02, 0x00, 0xFE +}; + } // End of namespace Kyra |