aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--kyra/kyra.cpp1509
-rw-r--r--kyra/kyra.h355
-rw-r--r--kyra/screen.cpp417
-rw-r--r--kyra/screen.h13
-rw-r--r--kyra/script.cpp4
-rw-r--r--kyra/script.h7
-rw-r--r--kyra/script_v1.cpp955
-rw-r--r--kyra/sprites.cpp85
-rw-r--r--kyra/sprites.h11
-rw-r--r--kyra/staticres.cpp308
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