aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dists/engine-data/kyra.datbin242675 -> 253175 bytes
-rw-r--r--engines/kyra/gui_lol.cpp361
-rw-r--r--engines/kyra/items_lol.cpp186
-rw-r--r--engines/kyra/lol.cpp936
-rw-r--r--engines/kyra/lol.h520
-rw-r--r--engines/kyra/module.mk4
-rw-r--r--engines/kyra/resource.h54
-rw-r--r--engines/kyra/scene_lol.cpp1369
-rw-r--r--engines/kyra/screen_lol.cpp225
-rw-r--r--engines/kyra/screen_lol.h29
-rw-r--r--engines/kyra/screen_v2.cpp5
-rw-r--r--engines/kyra/screen_v2.h2
-rw-r--r--engines/kyra/script.h2
-rw-r--r--engines/kyra/script_lol.cpp450
-rw-r--r--engines/kyra/staticres.cpp270
-rw-r--r--tools/create_kyradat/create_kyradat.cpp60
-rw-r--r--tools/create_kyradat/create_kyradat.h44
-rw-r--r--tools/create_kyradat/lol_cd.h42
-rw-r--r--tools/create_kyradat/lol_demo.h2
-rw-r--r--tools/create_kyradat/misc.h44
20 files changed, 4576 insertions, 29 deletions
diff --git a/dists/engine-data/kyra.dat b/dists/engine-data/kyra.dat
index 572106f4a4..d0601cdb6a 100644
--- a/dists/engine-data/kyra.dat
+++ b/dists/engine-data/kyra.dat
Binary files differ
diff --git a/engines/kyra/gui_lol.cpp b/engines/kyra/gui_lol.cpp
new file mode 100644
index 0000000000..8497e2f561
--- /dev/null
+++ b/engines/kyra/gui_lol.cpp
@@ -0,0 +1,361 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "kyra/lol.h"
+#include "kyra/screen_lol.h"
+
+namespace Kyra {
+
+void LoLEngine::gui_drawPlayField() {
+ _screen->loadBitmap("PLAYFLD.CPS", 3, 3, 0);
+
+ if (_screen->_drawGuiFlag & 0x4000) {
+ // copy compass shape
+ static const int cx[] = { 112, 152, 224 };
+ _screen->copyRegion(cx[_lang], 32, 288, 0, 32, 32, 2, 2, Screen::CR_NO_P_CHECK);
+ _updateUnk2 = -1;
+ }
+
+ if (_screen->_drawGuiFlag & 0x1000)
+ // draw automap book
+ _screen->drawShape(2, _gameShapes[78], 289, 32, 0, 0);
+
+ int cp = _screen->setCurPage(2);
+
+ if (_screen->_drawGuiFlag & 0x2000) {
+ gui_drawScroll();
+ } else {
+ _selectedSpell = 0;
+ }
+
+ if (_screen->_drawGuiFlag & 0x800)
+ turnOnLamp();
+
+ //mouseDimUnk()
+ gui_drawScene(2);
+
+ gui_drawAllCharPortraitsWithStats();
+ gui_drawInventory();
+ gui_drawMoneyBox(_screen->_curPage);
+ _screen->setCurPage(cp);
+ _screen->hideMouse();
+ _screen->copyPage(2, 0);
+ //mouseDimUnk
+ _screen->showMouse();
+}
+
+void LoLEngine::gui_drawScene(int pageNum) {
+ if (/*_charFlagUnk == 1 && */_weaponsDisabled == false && _unkDrawLevelBool && _vcnBlocks)
+ drawScene(pageNum);
+}
+
+void LoLEngine::gui_drawInventory() {
+ if (!_unkInventFlag || !_updateCharV6) {
+ for (int i = 0; i < 9; i++)
+ gui_drawInventoryItem(i);
+ }
+}
+
+void LoLEngine::gui_drawInventoryItem(int index) {
+ static const uint16 inventoryXpos[] = { 0x6A, 0x7F, 0x94, 0xA9, 0xBE, 0xD3, 0xE8, 0xFD, 0x112 };
+ int x = inventoryXpos[index];
+ int item = _inventoryCurItem + index;
+ if (item > 48)
+ item -= 48;
+
+ int flag = item & 1 ? 0 : 1;
+
+ _screen->hideMouse();
+ _screen->drawShape(_screen->_curPage, _gameShapes[4], x, 179, 0, flag);
+ if (_inventoryItemIndex[index])
+ _screen->drawShape(_screen->_curPage, getItemIconShapePtr(_inventoryItemIndex[index]), x + 1, 180, 0, 0);
+ _screen->showMouse();
+}
+
+void LoLEngine::gui_drawScroll() {
+ _screen->copyRegion(112, 0, 12, 0, 87, 15, 2, 2, Screen::CR_NO_P_CHECK);
+ int h = 0;
+
+ for (int i = 0; i < 7; i++) {
+ if (_availableSpells[i] != -1)
+ h += 9;
+ }
+
+ if (h == 18)
+ h = 27;
+
+ if (h) {
+ _screen->copyRegion(201, 1, 17, 15, 6, h, 2, 2, Screen::CR_NO_P_CHECK);
+ _screen->copyRegion(208, 1, 89, 15, 6, h, 2, 2, Screen::CR_NO_P_CHECK);
+ _screen->fillRect(21, 15, 89, h + 15, 206);
+ }
+
+ _screen->copyRegion(112, 16, 12, h + 15, 87, 14, 2, 2, Screen::CR_NO_P_CHECK);
+
+ int y = 15;
+ for (int i = 0; i < 7; i++) {
+ if (_availableSpells[i] == -1)
+ continue;
+ uint8 col = (i == _selectedSpell) ? 132 : 1;
+ _screen->fprintString(getLangString(_spellProperties[_availableSpells[i]].spellNameCode), 24, y, col, 0, 0);
+ y += 9;
+ }
+}
+
+void LoLEngine::gui_drawAllCharPortraitsWithStats() {
+ int numChars = countActiveCharacters();
+ if (!numChars)
+ return;
+
+ for (int i = 0; i < numChars; i++)
+ gui_drawCharPortraitWithStats(i);
+}
+
+void LoLEngine::gui_drawCharPortraitWithStats(int charNum) {
+ if (!(_characters[charNum].flags & 1) || _charFlagUnk & 2)
+ return;
+
+ Screen::FontId tmpFid = _screen->setFont(Screen::FID_6_FNT);
+ int cp = _screen->setCurPage(6);
+
+ gui_drawPortraitBox(0, 0, 66, 34, 1, 1, -1);
+ gui_drawCharFaceShape(0, 0, 1, _screen->_curPage);
+
+ gui_drawLiveMagicBar(33, 32, _characters[charNum].magicPointsCur, 0, _characters[charNum].magicPointsMax, 5, 32, 162, 1, 0);
+ gui_drawLiveMagicBar(39, 32, _characters[charNum].hitPointsCur, 0, _characters[charNum].hitPointsMax, 5, 32, 154, 1, 1);
+
+ _screen->printText(getLangString(0x4253), 33, 1, 160, 0);
+ _screen->printText(getLangString(0x4254), 39, 1, 152, 0);
+
+ int spellLevels = 0;
+ for (int i = 0; i < 4; i++) {
+ if (_spellProperties[_availableSpells[_selectedSpell]].mpRequired[i] <= _characters[charNum].magicPointsCur &&
+ _spellProperties[_availableSpells[_selectedSpell] + 1].unkArr[i] <= _characters[charNum].hitPointsCur)
+ spellLevels++;
+ }
+
+ if (_characters[charNum].flags & 0x10) {
+ // magic submenu open
+ _screen->drawShape(_screen->_curPage, _gameShapes[73], 44, 0, 0, 0);
+ if (spellLevels < 4)
+ _screen->drawGridBox(44, (spellLevels << 3) + 1, 22, 32 - (spellLevels << 3), 1);
+ } else {
+ // magic submenu closed
+ int shapeNum = -1;
+ /*if (_characters[charNum].items[0]) {
+ int u8 = _itemProperties[_itemsInPlay[_characters[charNum].items[0]].itemPropertyIndex].unk8 & 0xff;
+ if (u8 > shapeNum)
+ shapeNum = u8;
+ }*/
+
+ shapeNum = _gameShapeMap[_itemProperties[_itemsInPlay[_characters[charNum].items[0]].itemPropertyIndex].shpIndex];
+ if (shapeNum == 0x5a) { // draw raceClassSex specific hand shape
+ shapeNum = _characters[charNum].raceClassSex - 1;
+ if (shapeNum < 0)
+ shapeNum = 0;
+ shapeNum += 68;
+ }
+ // draw hand/weapon
+ _screen->drawShape(_screen->_curPage, _gameShapes[shapeNum], 44, 0, 0, 0);
+ // draw magic symbol
+ _screen->drawShape(_screen->_curPage, _gameShapes[72 + _characters[charNum].field_41], 44, 17, 0, 0);
+
+ if (spellLevels == 0)
+ _screen->drawGridBox(44, 17, 22, 15, 1);
+ }
+
+ uint16 f = _characters[charNum].flags & 0x314C;
+ if ((f == 0 && (f != 4 || _characters[charNum].weaponHit == 0)) || _weaponsDisabled)
+ _screen->drawGridBox(44, 0, 22, 34, 1);
+
+ if (_characters[charNum].weaponHit) {
+ _screen->drawShape(_screen->_curPage, _gameShapes[34], 44, 0, 0, 0);
+ _screen->fprintString("%d", 57, 7, 254, 0, 1, _characters[charNum].weaponHit);
+ }
+ if (_characters[charNum].damageSuffered)
+ _screen->fprintString("%d", 17, 28, 254, 0, 1, _characters[charNum].damageSuffered);
+
+ if (!cp)
+ _screen->hideMouse();
+
+ uint8 col = (charNum != _unkDrawPortraitIndex || countActiveCharacters() == 1) ? 1 : 212;
+ _screen->drawBox(0, 0, 65, 33, col);
+
+ _screen->copyRegion(0, 0, _activeCharsXpos[charNum], 143, 66, 34, _screen->_curPage, cp, Screen::CR_NO_P_CHECK);
+
+ if (!cp)
+ _screen->showMouse();
+
+ _screen->setCurPage(cp);
+ _screen->setFont(tmpFid);
+}
+
+void LoLEngine::gui_drawPortraitBox(int x, int y, int w, int h, int frameColor1, int frameColor2, int fillColor) {
+ w--; h--;
+ if (fillColor != -1)
+ _screen->fillRect(x + 1, y + 1, x + w - 1, y + h - 1, fillColor);
+
+ _screen->drawClippedLine(x + 1, y, x + w, y, frameColor2);
+ _screen->drawClippedLine(x + w, y, x + w, y + h - 1, frameColor2);
+ _screen->drawClippedLine(x, y, x, y + h, frameColor1);
+ _screen->drawClippedLine(x, y + h, x + w, y + h, frameColor1);
+}
+
+void LoLEngine::gui_drawCharFaceShape(int charNum, int x, int y, int pageNum) {
+ if (_characters[charNum].curFaceFrame < 7 && _characters[charNum].nextFaceFrame)
+ _characters[charNum].curFaceFrame = _characters[charNum].nextFaceFrame;
+
+ if (_characters[charNum].nextFaceFrame == 0 && _characters[charNum].curFaceFrame > 1 && _characters[charNum].curFaceFrame < 7)
+ _characters[charNum].curFaceFrame = _characters[charNum].nextFaceFrame;
+
+ int frm = (_characters[charNum].flags & 0x1108 && _characters[charNum].curFaceFrame < 7) ? 1 : _characters[charNum].curFaceFrame;
+
+ if (_characters[charNum].hitPointsCur <= (_characters[charNum].hitPointsMax >> 1))
+ frm += 14;
+
+ if (!pageNum)
+ _screen->hideMouse();
+
+ _screen->drawShape(pageNum, _characterFaceShapes[frm][charNum], x, y, 0, 0x100, _screen->_paletteOverlay2, (_characters[charNum].flags & 0x80 ? 1 : 0));
+
+ if (_characters[charNum].flags & 0x40)
+ // draw spider web
+ _screen->drawShape(pageNum, _gameShapes[21], x, y, 0, 0);
+
+ if (!pageNum)
+ _screen->showMouse();
+}
+
+void LoLEngine::gui_drawLiveMagicBar(int x, int y, int curPoints, int unk, int maxPoints, int w, int h, int col1, int col2, int flag) {
+ w--;
+ h--;
+
+ if (maxPoints < 1)
+ return;
+
+ int t = (curPoints < 1) ? 0 : curPoints;
+ curPoints = (maxPoints < t) ? maxPoints : t;
+
+ int barHeight = (curPoints * h) / maxPoints;
+
+ if (barHeight < 1 && curPoints < 1)
+ barHeight = 1;
+
+ _screen->drawClippedLine(x - 1, y - h, x - 1, y, 1);
+
+ if (flag) {
+ t = maxPoints >> 1;
+ if (t > curPoints)
+ col1 = 144;
+ t = maxPoints >> 2;
+ if (t > curPoints)
+ col1 = 132;
+ }
+
+ if (barHeight > 0)
+ _screen->fillRect(x, y - barHeight, x + w, y, col1);
+
+ if (barHeight < h)
+ _screen->fillRect(x, y - h, x + w, y - barHeight, col2);
+
+ if (unk > 0 && unk < maxPoints)
+ _screen->drawBox(x, y - barHeight, x + w, y, col1 - 2);
+}
+
+void LoLEngine::calcCharPortraitXpos() {
+ int nc = countActiveCharacters();
+
+ // TODO
+
+ int t = (235 - (nc * 66)) / (nc + 1);
+ for (int i = 0; i < nc; i++)
+ _activeCharsXpos[i] = i * 66 + t * (i + 1) + 83;
+}
+
+void LoLEngine::gui_drawMoneyBox(int pageNum) {
+ static const uint16 moneyX[] = { 0x128, 0x134, 0x12b, 0x131, 0x12e};
+ static const uint16 moneyY[] = { 0x73, 0x73, 0x74, 0x74, 0x75};
+
+ int backupPage = _screen->_curPage;
+ _screen->_curPage = pageNum;
+
+ _screen->fillRect(292, 97, 316, 118, 252, pageNum);
+
+ for (int i = 0; i < 5; i++) {
+ if (!_moneyColumnHeight[i])
+ continue;
+
+ uint8 h = _moneyColumnHeight[i] - 1;
+ _screen->drawClippedLine(moneyX[i], moneyY[i], moneyX[i], moneyY[i] - h, 0xd2);
+ _screen->drawClippedLine(moneyX[i] + 1, moneyY[i], moneyX[i] + 1, moneyY[i] - h, 0xd1);
+ _screen->drawClippedLine(moneyX[i] + 2, moneyY[i], moneyX[i] + 2, moneyY[i] - h, 0xd0);
+ _screen->drawClippedLine(moneyX[i] + 3, moneyY[i], moneyX[i] + 3, moneyY[i] - h, 0xd1);
+ _screen->drawClippedLine(moneyX[i] + 4, moneyY[i], moneyX[i] + 4, moneyY[i] - h, 0xd2);
+ }
+
+ Screen::FontId backupFont = _screen->setFont(Screen::FID_6_FNT);
+ _screen->fprintString("%d", 305, 98, 254, 0, 1, _credits);
+
+ _screen->setFont(backupFont);
+ _screen->_curPage = backupPage;
+
+ if (pageNum == 6) {
+ _screen->hideMouse();
+ _screen->copyRegion(292, 97, 292, 97, 25, 22, 6, 0);
+ _screen->showMouse();
+ }
+}
+
+void LoLEngine::gui_drawCompass() {
+ if (!(_screen->_drawGuiFlag & 0x4000))
+ return;
+
+ if (_updateUnk2 == -1) {
+ _compassDirectionIndex = -1;
+ _updateUnk2 = _unkPara2 << 6;
+ }
+
+ int t = ((_updateUnk2 + 4) >> 3) & 0x1f;
+
+ if (t == _compassDirectionIndex)
+ return;
+
+ _compassDirectionIndex = t;
+
+ if (!_screen->_curPage)
+ _screen->hideMouse();
+
+ const CompassDef *c = &_compassDefs[t];
+
+ _screen->drawShape(_screen->_curPage, _gameShapes[22 + _lang], 294, 3, 0, 0);
+ _screen->drawShape(_screen->_curPage, _gameShapes[25 + c->shapeIndex], 298 + c->x, c->y + 9, 0, c->flags | 0x300);
+ _screen->drawShape(_screen->_curPage, _gameShapes[25 + c->shapeIndex], 299 + c->x, c->y + 8, 0, c->flags);
+
+ if (!_screen->_curPage)
+ _screen->showMouse();
+}
+
+} // end of namespace Kyra
+
diff --git a/engines/kyra/items_lol.cpp b/engines/kyra/items_lol.cpp
new file mode 100644
index 0000000000..805df9337b
--- /dev/null
+++ b/engines/kyra/items_lol.cpp
@@ -0,0 +1,186 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+
+#include "kyra/lol.h"
+
+namespace Kyra {
+
+void LoLEngine::giveCredits(int credits, int redraw) {
+ static const uint8 stashSetupData[] = { 4, 4, 4, 4, 2, 2, 2, 3, 3, 0, 1, 1 };
+
+ if (redraw)
+ snd_playSoundEffect(0x65, 0xff);
+
+ int t = credits / 30;
+ if (!t)
+ t = 1;
+
+ int cnt = 0;
+
+ while (credits) {
+ if (t > credits)
+ t = credits;
+
+ if (_credits < 60 && t >= 0) {
+ cnt = 0;
+
+ do {
+ if (_credits < 60) {
+ int d = stashSetupData[_credits % 12] - _credits / 12;
+ if (d < 0)
+ d += 5;
+ _moneyColumnHeight[d]++;
+ }
+ _credits++;
+ } while(++cnt < t);
+ } else if (_credits >= 60) {
+ _credits += t;
+ }
+
+ if (redraw) {
+ gui_drawMoneyBox(6);
+ //if (credits)
+ // TODO: delay/update
+ }
+ credits -= t;
+ }
+}
+
+int LoLEngine::makeItem(int itemIndex, int curFrame, int flags) {
+ int cnt = 0;
+ int r = 0;
+ int i = 1;
+
+ for (; i < 400; i++) {
+ if (_itemsInPlay[i].shpCurFrame_flg & 0x8000) {
+ cnt = 0;
+ break;
+ }
+
+ if (_itemsInPlay[i].level < 1 || _itemsInPlay[i].level > 29 || _itemsInPlay[i].level == _currentLevel)
+ continue;
+
+ int diff = ABS(_currentLevel - _itemsInPlay[i].level);
+
+ if (diff <= cnt)
+ continue;
+
+ bool t = false;
+ int ii = i;
+ while (ii && !t) {
+ t = testUnkItemFlags(ii);
+ if (t)
+ break;
+ else
+ ii = _itemsInPlay[ii - 1].itemIndexUnk;
+ }
+
+ if (t) {
+ cnt = diff;
+ r = i;
+ }
+ }
+
+ int slot = i;
+ if (cnt) {
+ slot = r;
+ if (testUnkItemFlags(r)) {
+ if (_itemsInPlay[r].itemIndexUnk)
+ _itemsInPlay[_itemsInPlay[r].itemIndexUnk].level = _itemsInPlay[r].level;
+ clearItemTableEntry(r);
+ slot = r;
+ } else {
+ int ii = _itemsInPlay[slot].itemIndexUnk;
+ while(ii) {
+ if (testUnkItemFlags(ii)) {
+ _itemsInPlay[slot].itemIndexUnk = _itemsInPlay[ii].itemIndexUnk;
+ clearItemTableEntry(ii);
+ slot = ii;
+ break;
+ } else {
+ slot = ii;
+ }
+ ii = _itemsInPlay[slot].itemIndexUnk;
+ }
+ }
+ }
+
+ memset(&_itemsInPlay[slot], 0, sizeof(ItemInPlay));
+
+ _itemsInPlay[slot].itemPropertyIndex = itemIndex;
+ _itemsInPlay[slot].shpCurFrame_flg = (curFrame & 0x1fff) | flags;
+ _itemsInPlay[slot].level = -1;
+
+ return slot;
+}
+
+bool LoLEngine::testUnkItemFlags(int itemIndex) {
+ if (!(_itemsInPlay[itemIndex].shpCurFrame_flg & 0x4000))
+ return false;
+
+ if (_itemProperties[_itemsInPlay[itemIndex].itemPropertyIndex].flags & 4)
+ return false;
+
+ return true;
+
+}
+
+void LoLEngine::clearItemTableEntry(int itemIndex) {
+ memset(&_itemsInPlay[itemIndex], 0, sizeof(ItemInPlay));
+ _itemsInPlay[itemIndex].shpCurFrame_flg |= 0x8000;
+}
+
+void *LoLEngine::cmzGetItemOffset(uint16 index) {
+ if (index & 0x8000)
+ return &_lvlBuffer[index & 0x7fff];
+ else
+ return &_itemsInPlay[index];
+}
+
+void LoLEngine::runItemScript(int reg1, int slot, int reg0, int reg3, int reg4) {
+ EMCState scriptState;
+ memset(&scriptState, 0, sizeof(EMCState));
+
+ uint8 func = slot ? _itemProperties[_itemsInPlay[slot].itemPropertyIndex].itemScriptFunc : 3;
+ if (func == 0xff)
+ return;
+
+ _emc->init(&scriptState, &_itemScript);
+ _emc->start(&scriptState, func);
+
+ scriptState.regs[0] = reg0;
+ scriptState.regs[1] = reg1;
+ scriptState.regs[2] = slot;
+ scriptState.regs[3] = reg3;
+ scriptState.regs[4] = reg4;
+
+ while (_emc->isValid(&scriptState))
+ _emc->run(&scriptState);
+}
+
+} // end of namespace Kyra
+
+
diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp
index 8daf1d857f..bf52f300ad 100644
--- a/engines/kyra/lol.cpp
+++ b/engines/kyra/lol.cpp
@@ -58,26 +58,205 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy
break;
}
- memset(_shapes, 0, sizeof(_shapes));
-
_chargenWSA = 0;
_lastUsedStringBuffer = 0;
_landsFile = 0;
+ _levelLangFile = 0;
+
+ _lastSfxTrack = -1;
+
+ memset(_moneyColumnHeight, 0, 5);
+ _credits = 0;
+
+ _itemsInPlay = 0;
+ _itemProperties = 0;
+ _itemInHand = 0;
+ memset(_inventoryItemIndex, 0, 48);
+ _inventoryCurItem = 0;
+ _unkInventFlag = 0;
+
+ _itemIconShapes = _itemShapes = _gameShapes = _thrownShapes = _iceShapes = _fireballShapes = 0;
+ _levelShpList = _levelDatList = 0;
+ _monsterShapes = _monsterPalettes = 0;
+ _buf4 = 0;
+ _gameShapeMap = 0;
+ memset(_monsterUnk, 0, 3);
+
+ _charSelection = -1;
+ _characters = 0;
+ _spellProperties = 0;
+ _charFlagUnk = 0;
+ _selectedSpell = 0;
+ _updateCharNum = _updateCharV1 = _updateCharV2 = _updateCharV3 = _updateCharV4 = _updateCharV5 = _updateCharV6 = 0;
+ _updateCharTime = _updatePortraitNext = 0;
+ _lampStatusTimer = 0xffffffff;
+
+ _weaponsDisabled = false;
+ _unkDrawPortraitIndex = 0;
+ _unkFlag = 0;
+ _scriptBoolSkipExec = _boolScriptFuncDone = false;
+ _unkScriptByte = 0;
+ _unkPara2 = 0;
+ _currentBlock = 0;
+ memset(_scriptExecutedFuncs, 0, 18 * sizeof(uint16));
+
+ _wllVmpMap = _wllBuffer3 = _wllBuffer4 = _wllBuffer5 = 0;
+ _wllShapeMap = 0;
+ _lvlShapeTop = _lvlShapeBottom = _lvlShapeLeftRight = 0;
+ _cmzBuffer = 0;
+ _lvlBuffer = 0;
+ _lvl415 = 0;
+ _lvlBlockIndex = _lvlShapeIndex = 0;
+ _unkDrawLevelBool = true;
+ _vcnBlocks = 0;
+ _vcnShift = 0;
+ _vcnExpTable = 0;
+ _vmpPtr = 0;
+ _tlcTable2 = 0;
+ _tlcTable1 = 0;
+ _levelShapeProperties = 0;
+ _levelShapes = 0;
+ _blockDrawingBuffer = 0;
+ _sceneWindowBuffer = 0;
+ memset (_doorShapes, 0, 2 * sizeof(uint8*));
+
+ _lampOilStatus = _brightness = _lampStatusUnk = 0;
+ _tempBuffer5120 = 0;
+ _lvlBuffer = 0;
+ _unkGameFlag = 0;
+
+ _dscUnk1 = 0;
+ _dscShapeIndex = 0;
+ _dscOvlMap = 0;
+ _dscShapeScaleW = 0;
+ _dscShapeScaleH = 0;
+ _dscShapeX = 0;
+ _dscShapeY = 0;
+ _dscTileIndex = 0;
+ _dscUnk2 = 0;
+ _dscDoorShpIndex = 0;
+ _dscDim1 = 0;
+ _dscDim2 = 0;
+ _dscBlockMap = _dscDoor1 = _dscDoor2 = _dscShapeOvlIndex = 0;
+ _dscBlockIndex = 0;
+ _dscDimMap = 0;
+ _dscDoorX = _dscDoorY = 0;
+ _dscDoor4 = 0;
+
+ _ingameSoundList = 0;
+ _ingameSoundListSize = 0;
+
+ _sceneDrawVar1 = _sceneDrawVar2 = _sceneDrawVar3 = _wllProcessFlag = 0;
+ _unkCmzU1 = _unkCmzU2 = 0;
+ _shpDoorX = _shpDoorY = _doorScaleW = _doorScaleH = 0;
}
LoLEngine::~LoLEngine() {
setupPrologueData(false);
- for (uint i = 0; i < ARRAYSIZE(_shapes); ++i)
- delete[] _shapes[i];
delete[] _landsFile;
+ delete[] _levelLangFile;
delete _screen;
delete _tim;
+ delete [] _itemsInPlay;
+ delete [] _itemProperties;
+
+ delete [] _characters;
+
+ if (_itemIconShapes) {
+ for (int i = 0; i < _numItemIconShapes; i++)
+ delete [] _itemIconShapes[i];
+ delete []_itemIconShapes;
+ }
+ if (_itemShapes) {
+ for (int i = 0; i < _numItemShapes; i++)
+ delete [] _itemShapes[i];
+ delete []_itemShapes;
+ }
+ if (_gameShapes) {
+ for (int i = 0; i < _numGameShapes; i++)
+ delete [] _gameShapes[i];
+ delete []_gameShapes;
+ }
+ if (_thrownShapes) {
+ for (int i = 0; i < _numThrownShapes; i++)
+ delete [] _thrownShapes[i];
+ delete []_thrownShapes;
+ }
+ if (_iceShapes) {
+ for (int i = 0; i < _numIceShapes; i++)
+ delete [] _iceShapes[i];
+ delete []_iceShapes;
+ }
+ if (_fireballShapes) {
+ for (int i = 0; i < _numFireballShapes; i++)
+ delete [] _fireballShapes[i];
+ delete []_fireballShapes;
+ }
+
+ if (_monsterShapes) {
+ for (int i = 0; i < 48; i++)
+ delete [] _monsterShapes[i];
+ delete []_monsterShapes;
+ }
+ if (_monsterPalettes) {
+ for (int i = 0; i < 48; i++)
+ delete [] _monsterPalettes[i];
+ delete []_monsterPalettes;
+ }
+ if (_buf4) {
+ for (int i = 0; i < 384; i++)
+ delete [] _buf4[i];
+ delete []_buf4;
+ }
+
for (Common::Array<const TIMOpcode*>::iterator i = _timIntroOpcodes.begin(); i != _timIntroOpcodes.end(); ++i)
delete *i;
_timIntroOpcodes.clear();
+
+ delete []_wllVmpMap;
+ delete []_wllShapeMap;
+ delete []_wllBuffer3;
+ delete []_wllBuffer4;
+ delete []_wllBuffer5;
+ delete []_lvlShapeTop;
+ delete []_lvlShapeBottom;
+ delete []_lvlShapeLeftRight;
+ delete []_tempBuffer5120;
+ delete []_lvlBuffer;
+ delete []_cmzBuffer;
+ delete []_lvl415;
+
+ delete []_lvlShpHeader;
+ delete []_levelFileData;
+ delete []_vcnExpTable;
+ delete []_vcnBlocks;
+ delete []_vcnShift;
+ delete []_vmpPtr;
+ delete []_tlcTable2;
+ delete []_tlcTable1;
+ delete []_levelShapeProperties;
+ delete []_blockDrawingBuffer;
+ delete []_sceneWindowBuffer;
+
+ if (_levelShapes) {
+ for (int i = 0; i < 400; i++)
+ delete [] _levelShapes[i];
+ delete []_levelShapes;
+ }
+
+ for (int i = 0; i < 2; i++)
+ delete _doorShapes[i];
+
+ delete _lvlShpFileHandle;
+
+ if (_ingameSoundList) {
+ for (int i = 0; i < _ingameSoundListSize; i++)
+ delete []_ingameSoundList[i];
+ delete []_ingameSoundList;
+ }
}
Screen *LoLEngine::screen() {
@@ -90,6 +269,7 @@ Common::Error LoLEngine::init() {
_screen->setResolution();
KyraEngine_v1::init();
+ initStaticResource();
_tim = new TIMInterpreter(this, _screen, _system);
assert(_tim);
@@ -97,9 +277,77 @@ Common::Error LoLEngine::init() {
_screen->setAnimBlockPtr(10000);
_screen->setScreenDim(0);
+ _itemsInPlay = new ItemInPlay[401];
+ memset(_itemsInPlay, 0, sizeof(ItemInPlay) * 400);
+
+ _characters = new LoLCharacter[4];
+ memset(_characters, 0, sizeof(LoLCharacter) * 3);
+
if (!_sound->init())
error("Couldn't init sound");
+ _unkAudioSpecOffs = 0x48;
+ _unkLangAudio = _lang ? true : false;
+
+ _wllVmpMap = new uint8[80];
+ memset(_wllVmpMap, 0, 80);
+ _wllShapeMap = new int8[80];
+ memset(_wllShapeMap, 0, 80);
+ _wllBuffer3 = new uint8[80];
+ memset(_wllBuffer3, 0, 80);
+ _wllBuffer4 = new uint8[80];
+ memset(_wllBuffer4, 0, 80);
+ _wllBuffer5 = new uint8[80];
+ memset(_wllBuffer5, 0, 80);
+ _lvlShapeTop = new int16[18];
+ memset(_lvlShapeTop, 0, 18 * sizeof(int16));
+ _lvlShapeBottom = new int16[18];
+ memset(_lvlShapeBottom, 0, 18 * sizeof(int16));
+ _lvlShapeLeftRight = new int16[36];
+ memset(_lvlShapeLeftRight, 0, 36 * sizeof(int16));
+ _levelShapeProperties = new LevelShapeProperty[100];
+ memset(_levelShapeProperties, 0, 100 * sizeof(LevelShapeProperty));
+ _levelShapes = new uint8*[400];
+ memset(_levelShapes, 0, 400 * sizeof(uint8*));
+ _blockDrawingBuffer = new uint16[1320];
+ memset(_blockDrawingBuffer, 0, 1320 * sizeof(uint16));
+ _sceneWindowBuffer = new uint8[21120];
+ memset(_sceneWindowBuffer, 0, 21120);
+
+ _cmzBuffer = new CMZ[1025];
+ memset(_cmzBuffer, 0, 1025 * sizeof(CMZ));
+ _lvlBuffer = new LVL[30];
+ memset(_lvlBuffer, 0, 30 * sizeof(LVL));
+ _lvl415 = new uint8[415];
+ memset(_lvl415, 0, 415);
+
+ _vcnExpTable = new uint8[128];
+ for (int i = 0; i < 128; i++)
+ _vcnExpTable[i] = i & 0x0f;
+
+ _tempBuffer5120 = new uint8[5120];
+ memset(_tempBuffer5120, 0, 5120);
+
+ memset(_gameFlags, 0, 15 * sizeof(uint16));
+
+ _lvlShpHeader = 0;
+ _levelFileData = 0;
+ _lvlShpFileHandle = 0;
+
+ _sceneDrawPage1 = 2;
+ _sceneDrawPage2 = 6;
+
+ _monsterShapes = new uint8*[48];
+ memset(_monsterShapes, 0, 48 * sizeof(uint8*));
+ _monsterPalettes = new uint8*[48];
+ memset(_monsterPalettes, 0, 48 * sizeof(uint8*));
+
+ _buf4 = new uint8*[384];
+ memset(_buf4, 0, 384 * sizeof(uint8*));
+ memset(&_scriptData, 0, sizeof(EMCData));
+
+ _levelFlagUnk = 0;
+
return Common::kNoError;
}
@@ -171,10 +419,17 @@ Common::Error LoLEngine::go() {
_sound->playTrack(1);
_screen->fadeToBlack();
setupPrologueData(true);
- } else if (processSelection == 3) {
- //XXX
}
+ if (!shouldQuit() && (processSelection == 0 || processSelection == 3))
+ startup();
+
+ if (!shouldQuit() && processSelection == 0)
+ startupNew();
+
+ if (!shouldQuit() && (processSelection == 0 || processSelection == 3))
+ runLoop();
+
return Common::kNoError;
}
@@ -223,8 +478,35 @@ void LoLEngine::initializeCursors() {
debugC(9, kDebugLevelMain, "LoLEngine::initializeCursors()");
_screen->loadBitmap("ITEMICN.SHP", 3, 3, 0);
- _shapes[0] = _screen->makeShapeCopy(_screen->getCPagePtr(3), 0);
- _screen->setMouseCursor(0, 0, _shapes[0]);
+ const uint8 *shp = _screen->getCPagePtr(3);
+ _numItemIconShapes = READ_LE_UINT16(shp);
+ _itemIconShapes = new uint8*[_numItemIconShapes];
+ for (int i = 0; i < _numItemIconShapes; i++)
+ _itemIconShapes[i] = _screen->makeShapeCopy(shp, i);
+
+ _screen->setMouseCursor(0, 0, _itemIconShapes[0]);
+}
+
+void LoLEngine::setMouseCursorToIcon(int icon) {
+ _screen->_drawGuiFlag |= 0x200;
+ int i = _itemProperties[_itemsInPlay[_itemInHand].itemPropertyIndex].shpIndex;
+ if (i == icon)
+ return;
+ _screen->setMouseCursor(0, 0, _itemIconShapes[icon]);
+}
+
+void LoLEngine::setMouseCursorToItemInHand() {
+ _screen->_drawGuiFlag &= 0xFDFF;
+ int o = (_itemInHand == 0) ? 0 : 10;
+ _screen->setMouseCursor(o, o, getItemIconShapePtr(_itemInHand));
+}
+
+uint8 *LoLEngine::getItemIconShapePtr(int index) {
+ int ix = _itemProperties[_itemsInPlay[index].itemPropertyIndex].shpIndex;
+ if (_itemProperties[_itemsInPlay[index].itemPropertyIndex].flags & 0x200)
+ ix += (_itemsInPlay[index].shpCurFrame_flg & 0x1fff) - 1;
+
+ return _itemIconShapes[ix];
}
int LoLEngine::mainMenu() {
@@ -275,6 +557,120 @@ int LoLEngine::mainMenu() {
return selection;
}
+void LoLEngine::startup() {
+ _screen->clearPage(0);
+ _screen->loadBitmap("PLAYFLD.CPS", 3, 3, _screen->_currentPalette);
+
+ uint8 *tmpPal = new uint8[0x300];
+ memcpy(tmpPal, _screen->_currentPalette, 0x300);
+ memset(_screen->_currentPalette, 0x3f, 0x180);
+ memcpy(_screen->_currentPalette + 3, tmpPal + 3, 3);
+ memset(_screen->_currentPalette + 0x240, 0x3f, 12);
+ _screen->generateOverlay(_screen->_currentPalette, _screen->_paletteOverlay1, 1, 6);
+ _screen->generateOverlay(_screen->_currentPalette, _screen->_paletteOverlay2, 0x90, 0x41);
+ memcpy(_screen->_currentPalette, tmpPal, 0x300);
+ delete []tmpPal;
+
+ memset(_screen->getPalette(1), 0, 0x300);
+ memset(_screen->getPalette(2), 0, 0x300);
+
+ _screen->setMouseCursor(0, 0, _itemIconShapes[0x85]);
+
+ _screen->loadBitmap("ITEMSHP.SHP", 3, 3, 0);
+ const uint8 *shp = _screen->getCPagePtr(3);
+ _numItemShapes = READ_LE_UINT16(shp);
+ _itemShapes = new uint8*[_numItemShapes];
+ for (int i = 0; i < _numItemShapes; i++)
+ _itemShapes[i] = _screen->makeShapeCopy(shp, i);
+
+ _screen->loadBitmap("GAMESHP.SHP", 3, 3, 0);
+ shp = _screen->getCPagePtr(3);
+ _numGameShapes = READ_LE_UINT16(shp);
+ _gameShapes = new uint8*[_numGameShapes];
+ for (int i = 0; i < _numGameShapes; i++)
+ _gameShapes[i] = _screen->makeShapeCopy(shp, i);
+
+ _screen->loadBitmap("THROWN.SHP", 3, 3, 0);
+ shp = _screen->getCPagePtr(3);
+ _numThrownShapes = READ_LE_UINT16(shp);
+ _thrownShapes = new uint8*[_numThrownShapes];
+ for (int i = 0; i < _numThrownShapes; i++)
+ _thrownShapes[i] = _screen->makeShapeCopy(shp, i);
+
+ _screen->loadBitmap("ICE.SHP", 3, 3, 0);
+ shp = _screen->getCPagePtr(3);
+ _numIceShapes = READ_LE_UINT16(shp);
+ _iceShapes = new uint8*[_numIceShapes];
+ for (int i = 0; i < _numIceShapes; i++)
+ _iceShapes[i] = _screen->makeShapeCopy(shp, i);
+
+ _screen->loadBitmap("FIREBALL.SHP", 3, 3, 0);
+ shp = _screen->getCPagePtr(3);
+ _numFireballShapes = READ_LE_UINT16(shp);
+ _fireballShapes = new uint8*[_numFireballShapes];
+ for (int i = 0; i < _numFireballShapes; i++)
+ _fireballShapes[i] = _screen->makeShapeCopy(shp, i);
+
+ memset(_itemsInPlay, 0, 400 * sizeof(ItemInPlay));
+ for (int i = 0; i < 400; i++)
+ _itemsInPlay[i].shpCurFrame_flg |= 0x8000;
+
+ runInitScript("ONETIME.INF", 0);
+ _emc->load("ITEM.INF", &_itemScript, &_opcodes);
+
+ _tlcTable1 = new uint8[256];
+ _tlcTable2 = new uint8[5120];
+
+ _loadSuppFilesFlag = 1;
+
+ setMouseCursorToItemInHand();
+}
+
+void LoLEngine::startupNew() {
+ _selectedSpell = 0;
+ _updateUnk2 = _compassDirectionIndex = -1;
+ /*
+ _unk3 = -1;*/
+ _unkGameFlag |= 0x1B;
+ /*
+ _unk5 = 1;
+ _unk6 = 1;
+ _unk7 = 1
+ _unk8 = 1*/
+ _currentLevel = 1;
+
+ giveCredits(41, 0);
+ _inventoryItemIndex[0] = makeItem(0xd8, 0, 0);
+ _inventoryItemIndex[1] = makeItem(0xd9, 0, 0);
+ _inventoryItemIndex[2] = makeItem(0xda, 0, 0);
+
+ memset(_availableSpells, -1, 7);
+ setupScreenDims();
+
+ //memset(_unkWordArraySize8, 0x100, 8);
+
+ static int selectIds[] = { -9, -1, -8, -5 };
+ addCharacter(selectIds[_charSelection]);
+
+ // TODO
+
+ loadLevel(1);
+
+ _screen->showMouse();
+}
+
+void LoLEngine::runLoop() {
+ _screen->updateScreen();
+
+ bool _runFlag = true;
+ while (!shouldQuit() && _runFlag) {
+ checkInput(0, false);
+ removeInputTop();
+ _screen->updateScreen();
+ _system->delayMillis(10);
+ }
+}
+
#pragma mark - Localization
const char *LoLEngine::getLangString(uint16 id) {
@@ -363,7 +759,7 @@ void LoLEngine::setupPrologueData(bool load) {
_chargenWSA = new WSAMovie_v2(this, _screen);
assert(_chargenWSA);
- _charSelection = -1;
+ //_charSelection = -1;
_charSelectionInfoResult = -1;
_selectionAnimFrames[0] = _selectionAnimFrames[2] = 0;
@@ -414,6 +810,7 @@ void LoLEngine::showIntro() {
}
_screen->showMouse();
_sound->voiceStop();
+ _sound->beginFadeOut();
_eventList.clear();
@@ -807,14 +1204,535 @@ int LoLEngine::selectionCharAccept() {
return -1;
}
+bool LoLEngine::addCharacter(int id) {
+ int numChars = countActiveCharacters();
+ if (numChars == 4)
+ return false;
+
+ int i = 0;
+ for (; i < _charDefaultsSize; i++) {
+ if (_charDefaults[i].id == id) {
+ memcpy(&_characters[numChars], &_charDefaults[i], sizeof(LoLCharacter));
+ break;
+ }
+ }
+ if (i == _charDefaultsSize)
+ return false;
+
+ loadCharFaceShapes(numChars, id);
+
+ _characters[numChars].rand = _rnd.getRandomNumberRng(1, 12);
+
+ i = 0;
+ for (; i < 11; i++) {
+ uint16 *tmp = &_characters[numChars].items[i];
+ if (*tmp) {
+ *tmp = makeItem(*tmp, 0, 0);
+ runItemScript(numChars, *tmp, 0x80, 0, 0);
+ }
+ }
+
+ calcCharPortraitXpos();
+ if (numChars > 0)
+ initCharacter(numChars, 2, 6, 0);
+
+ return true;
+}
+
+void LoLEngine::initCharacter(int charNum, int firstFaceFrame, int unk2, int redraw) {
+ _characters[charNum].nextFaceFrame = firstFaceFrame;
+ if (firstFaceFrame || unk2)
+ initCharacterUnkSub(charNum, 6, unk2, 1);
+ if (redraw)
+ gui_drawCharPortraitWithStats(charNum);
+}
+
+void LoLEngine::initCharacterUnkSub(int charNum, int unk1, int unk2, int unk3) {
+ for (int i = 0; i < 5; i++) {
+ if (_characters[charNum].arrayUnk1[i] == 0 || (unk3 && _characters[charNum].arrayUnk1[i] == unk1)) {
+ _characters[charNum].arrayUnk1[i] = unk1;
+ _characters[charNum].arrayUnk2[i] = unk2;
+
+ // TODO
+
+ break;
+ }
+ }
+}
+
+int LoLEngine::countActiveCharacters() {
+ int i = 0;
+ while (_characters[i].flags & 1)
+ i++;
+ return i;
+}
+
+void LoLEngine::loadCharFaceShapes(int charNum, int id) {
+ if (id < 0)
+ id = -id;
+
+ char file[] = "FACE%02d.SHP";
+ sprintf(file, "FACE%02d.SHP", id);
+ _screen->loadBitmap(file, 3, 3, 0);
+
+ const uint8 *p = _screen->getCPagePtr(3);
+ for (int i = 0; i < 40; i++)
+ _characterFaceShapes[i][charNum] = _screen->makeShapeCopy(p, i);
+}
+
+void LoLEngine::updatePortraitWithStats() {
+ int x = 0;
+ int y = 0;
+ bool redraw = false;
+
+ if (_updateCharV2 == 0) {
+ x = _activeCharsXpos[_updateCharNum];
+ y = 144;
+ redraw = true;
+ } else if (_updateCharV2 == 1) {
+ if (_unkLangAudio) {
+ x = 90;
+ y = 130;
+ } else {
+ x = _activeCharsXpos[_updateCharNum];
+ y = 144;
+ }
+ } else if (_updateCharV2 == 2) {
+ if (_unkLangAudio) {
+ x = 16;
+ y = 134;
+ } else {
+ x = _activeCharsXpos[_updateCharNum] + 10;
+ y = 145;
+ }
+ }
+
+ int f = _rnd.getRandomNumberRng(1, 6) - 1;
+ if (f == _characters[_updateCharNum].curFaceFrame)
+ f++;
+ if (f > 5)
+ f -= 5;
+ f += 7;
+
+ if (_unkAudioSpecOffs) {
+ //TODO
+ //if (unk() == 2)
+ // _updateCharV1 = 2;
+ //else
+ _updateCharV1 = 1;
+ }
+
+ if (--_updateCharV1) {
+ setCharFaceFrame(_updateCharNum, f);
+ if (redraw)
+ gui_drawCharPortraitWithStats(_updateCharNum);
+ else
+ gui_drawCharFaceShape(_updateCharNum, x, y, 0);
+ _updatePortraitNext = _system->getMillis() + 10 * _tickLength;
+ } else if (_updateCharV1 == 0 && _updateCharV3 != 0) {
+ faceFrameRefresh(_updateCharNum);
+ if (redraw) {
+ gui_drawCharPortraitWithStats(_updateCharNum);
+ updatePortraitUnkTimeSub(0, 0);
+ } else {
+ gui_drawCharFaceShape(_updateCharNum, x, y, 0);
+ }
+ _updateCharNum = -1;
+ }
+}
+
+void LoLEngine::updatePortraits() {
+ if (_updateCharNum == -1)
+ return;
+
+ _updateCharV1 = _updateCharV3 = 1;
+ updatePortraitWithStats();
+ _updateCharV1 = 1;
+ _updateCharNum = -1;
+
+ if (!_updateCharV2)
+ updatePortraitUnkTimeSub(0, 0);
+}
+
+void LoLEngine::updatePortraitUnkTimeSub(int unk1, int unk2) {
+ if (_updateCharV4 == unk1 || !unk1) {
+ _updateCharV5 = 1;
+ _updateCharTime = _system->getMillis();
+ }
+
+ if (!unk2)
+ return;
+
+ updatePortraits();
+ if (_updateCharV6) {
+ _screen->hideMouse();
+ _screen->clearDim(3);
+ _screen->showMouse();
+ }
+
+ _updateCharV5 = 0;
+ //initGuiUnk(11);
+}
+
+void LoLEngine::setCharFaceFrame(int charNum, int frameNum) {
+ _characters[charNum].curFaceFrame = frameNum;
+}
+
+void LoLEngine::faceFrameRefresh(int charNum) {
+ if (_characters[charNum].curFaceFrame == 1)
+ initCharacter(charNum, 0, 0, 0);
+ else if (_characters[charNum].curFaceFrame == 6)
+ if (_characters[charNum].nextFaceFrame != 5)
+ initCharacter(charNum, 0, 0, 0);
+ else
+ _characters[charNum].curFaceFrame = 5;
+ else
+ _characters[charNum].curFaceFrame = 0;
+}
+
+void LoLEngine::setupScreenDims() {
+ if (_unkLangAudio)
+ _screen->modifyScreenDim(4, 11, 124, 28, 45);
+ else
+ _screen->modifyScreenDim(4, 11, 124, 28, 9);
+ _screen->modifyScreenDim(5, 85, 123, 233, 18);
+}
+
+void LoLEngine::snd_playSoundEffect(int track, int volume) {
+ debugC(9, kDebugLevelMain | kDebugLevelSound, "LoLEngine::snd_playSoundEffect(%d, %d)", track, volume);
+
+ if (track == 1 && (_lastSfxTrack == -1 || _lastSfxTrack == 1))
+ return;
+
+ _lastSfxTrack = track;
+
+ int16 volIndex = (int16)READ_LE_UINT16(&_ingameSoundIndex[track * 2 + 1]);
+
+ if (volIndex > 0)
+ volIndex = (volIndex * volume) >> 8;
+ else
+ volIndex *= -1;
+
+ // volume TODO
+
+ int16 vocIndex = (int16)READ_LE_UINT16(&_ingameSoundIndex[track * 2]);
+ if (vocIndex != -1) {
+ _sound->voicePlay(_ingameSoundList[vocIndex], true);
+ } else if (_flags.platform == Common::kPlatformPC) {
+ if (_sound->getSfxType() == Sound::kMidiMT32)
+ track = track < _ingameMT32SoundIndexSize ? _ingameMT32SoundIndex[track] - 1 : -1;
+ else if (_sound->getSfxType() == Sound::kMidiGM)
+ track = track < _ingameGMSoundIndexSize ? _ingameGMSoundIndex[track] - 1: -1;
+
+ if (track != -1)
+ KyraEngine_v1::snd_playSoundEffect(track);
+ }
+}
+
#pragma mark - Opcodes
+typedef Common::Functor1Mem<EMCState*, int, LoLEngine> OpcodeV2;
+#define SetOpcodeTable(x) table = &x;
+#define Opcode(x) table->push_back(new OpcodeV2(this, &LoLEngine::x))
+#define OpcodeUnImpl() table->push_back(new OpcodeV2(this, 0))
+
typedef Common::Functor2Mem<const TIM *, const uint16 *, int, LoLEngine> TIMOpcodeLoL;
#define SetTimOpcodeTable(x) timTable = &x;
#define OpcodeTim(x) timTable->push_back(new TIMOpcodeLoL(this, &LoLEngine::x))
#define OpcodeTimUnImpl() timTable->push_back(new TIMOpcodeLoL(this, 0))
void LoLEngine::setupOpcodeTable() {
+ Common::Array<const Opcode*> *table = 0;
+
+ SetOpcodeTable(_opcodes);
+ // 0x00
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ Opcode(o1_getRand);
+
+ // 0x04
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ Opcode(o2_setGameFlag);
+
+ // 0x08
+ Opcode(o2_testGameFlag);
+ Opcode(o2_loadLevelSupplemenaryFiles);
+ Opcode(o2_loadCmzFile);
+ Opcode(o2_loadMonsterShapes);
+
+ // 0x0C
+ OpcodeUnImpl();
+ Opcode(o2_allocItemPropertiesBuffer);
+ Opcode(o2_setItemProperty);
+ Opcode(o2_makeItem);
+
+ // 0x10
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ Opcode(o2_getItemPara);
+ Opcode(o2_getCharacterStat);
+
+ // 0x14
+ Opcode(o2_setCharacterStat);
+ Opcode(o2_loadLevelShapes);
+ Opcode(o2_closeLevelShapeFile);
+ OpcodeUnImpl();
+
+ // 0x18
+ Opcode(o2_loadDoorShapes);
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+
+ // 0x1C
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+
+ // 0x20
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+
+ // 0x24
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+
+ // 0x28
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+
+ // 0x2C
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+
+ // 0x30
+ Opcode(o2_setGlobalVar);
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+
+ // 0x34
+ OpcodeUnImpl();
+ Opcode(o2_mapShapeToBlock);
+ Opcode(o2_resetBlockShapeAssignment);
+ OpcodeUnImpl();
+
+ // 0x38
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+
+ // 0x3C
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+
+ // 0x40
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+
+ // 0x44
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+
+ // 0x48
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+
+ // 0x4C
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+
+ // 0x50
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+
+ // 0x54
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+
+ // 0x58
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+
+ // 0x5C
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+
+ // 0x60
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+
+ // 0x64
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+
+ // 0x68
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ Opcode(o2_setPaletteBrightness);
+
+ // 0x6C
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+
+ // 0x70
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+
+ // 0x74
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+
+ // 0x78
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+
+ // 0x7C
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+
+ // 0x80
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+
+ // 0x84
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+
+ // 0x88
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+
+ // 0x8C
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+
+ // 0x90
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+
+ // 0x94
+ Opcode(o2_assignCustomSfx);
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+
+ // 0x98
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+
+ // 0x9C
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+
+ // 0xA0
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+
+ // 0xA4
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+
+ // 0xA8
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+
+ // 0xAC
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+
+ // 0xB0
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+
+ // 0xB4
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+
+ // 0xB8
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+
+ // 0xBC
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+ OpcodeUnImpl();
+
Common::Array<const TIMOpcode*> *timTable = 0;
SetTimOpcodeTable(_timIntroOpcodes);
diff --git a/engines/kyra/lol.h b/engines/kyra/lol.h
index a6b7378b0f..194d24ddf8 100644
--- a/engines/kyra/lol.h
+++ b/engines/kyra/lol.h
@@ -28,6 +28,7 @@
#include "kyra/kyra_v1.h"
#include "kyra/script_tim.h"
+#include "kyra/script.h"
#include "common/list.h"
@@ -37,6 +38,143 @@ class Screen_LoL;
class WSAMovie_v2;
struct Button;
+struct LoLCharacter {
+ uint16 flags;
+ char name[11];
+ uint8 raceClassSex;
+ int16 id;
+ uint8 curFaceFrame;
+ uint8 nextFaceFrame;
+ uint16 field_12;
+ uint16 field_14;
+ uint8 field_16;
+ uint16 field_17[5];
+ uint16 field_21;
+ uint16 field_23;
+ uint16 field_25;
+ uint16 field_27[2];
+ uint8 field_2B;
+ uint16 field_2C;
+ uint16 field_2E;
+ uint16 field_30;
+ uint16 field_32;
+ uint16 field_34;
+ uint8 field_36;
+ uint16 field_37;
+ uint16 hitPointsCur;
+ uint16 hitPointsMax;
+ uint16 magicPointsCur;
+ uint16 magicPointsMax;
+ uint8 field_41;
+ uint16 damageSuffered;
+ uint16 weaponHit;
+ uint16 field_46;
+ uint16 field_48;
+ uint16 field_4A;
+ uint16 field_4C;
+ uint16 rand;
+ uint16 items[11];
+ uint8 field_66[3];
+ uint8 field_69[3];
+ uint8 field_6C;
+ uint8 field_6D;
+ uint16 field_6E;
+ uint16 field_70;
+ uint16 field_72;
+ uint16 field_74;
+ uint16 field_76;
+ uint8 arrayUnk2[5];
+ uint8 arrayUnk1[5];
+};
+
+struct SpellProperty {
+ uint16 field_0;
+ uint16 unkArr[4];
+ uint16 field_A;
+ uint16 field_C;
+ uint16 field_E;
+ uint16 spellNameCode;
+ uint16 mpRequired[4];
+ uint16 field_1A;
+};
+
+struct CMZ {
+ uint8 unk[4];
+ uint16 itemIndex;
+ uint8 field_6;
+ uint8 field_7;
+ uint8 field_8;
+ uint8 flags;
+};
+
+struct LVL {
+ uint8 field_0;
+ uint8 field_1;
+ uint8 field_2;
+ uint8 field_3;
+ uint8 field_4;
+ uint16 cmzIndex;
+ uint16 p_1a;
+ uint16 p_1b;
+ uint8 field_B;
+ uint16 p_2a;
+ uint16 p_2b;
+ uint8 field_10;
+ uint8 field_11;
+ uint8 field_12;
+ uint8 field_13;
+ uint8 field_14;
+ uint8 field_15;
+ uint8 field_16;
+ uint8 field_17;
+ uint8 field_18;
+ uint16 field_19;
+ uint8 field_1B;
+ uint8 field_1C;
+ int16 field_1D;
+ uint8 field_1F;
+ uint8 field_20;
+ uint8 *offs_lvl415;
+ uint8 field_25;
+ uint8 field_26;
+ uint8 field_27;
+ uint8 field_28;
+ uint8 field_29;
+ uint8 field_2A;
+ uint8 field_2B;
+ uint8 field_2C;
+ uint8 field_2D;
+ uint8 field_2E;
+};
+
+struct LevelShapeProperty {
+ uint16 shapeIndex[10];
+ uint8 scaleFlag[10];
+ uint16 shapeX[10];
+ uint16 shapeY[10];
+ int8 next;
+ uint8 flags;
+};
+
+struct CompassDef {
+ uint8 shapeIndex;
+ int8 x;
+ int8 y;
+ uint8 flags;
+};
+
+struct ScriptOffsUnkStruct {
+ uint8 field_0;
+ uint8 field_1;
+ uint8 field_2;
+ uint8 field_3;
+ uint8 field_4;
+ uint8 field_5;
+ uint8 field_6;
+ uint8 field_7;
+ uint8 field_8;
+};
+
class LoLEngine : public KyraEngine_v1 {
public:
LoLEngine(OSystem *system, const GameFlags &flags);
@@ -51,12 +189,22 @@ private:
Common::Error go();
// initialization
+ void initStaticResource();
void preInit();
void initializeCursors();
-
int mainMenu();
+ void startup();
+ void startupNew();
+
+ void runLoop();
+
+ // mouse
+ void setMouseCursorToIcon(int icon);
+ void setMouseCursorToItemInHand();
+ uint8 *getItemIconShapePtr(int index);
+
// intro
void setupPrologueData(bool load);
@@ -111,8 +259,84 @@ private:
// sound
void snd_playVoiceFile(int) { /* XXX */ }
-
- // opcode
+ void snd_playSoundEffect(int track, int volume);
+
+ int _lastSfxTrack;
+
+ int _unkAudioSpecOffs;
+ bool _unkLangAudio;
+
+ char **_ingameSoundList;
+ int _ingameSoundListSize;
+
+ const uint16 *_ingameSoundIndex;
+ int _ingameSoundIndexSize;
+ const uint8 *_ingameGMSoundIndex;
+ int _ingameGMSoundIndexSize;
+ const uint8 *_ingameMT32SoundIndex;
+ int _ingameMT32SoundIndexSize;
+
+ // gui
+ void gui_drawPlayField();
+ void gui_drawScene(int pageNum);
+ void gui_drawAllCharPortraitsWithStats();
+ void gui_drawCharPortraitWithStats(int charNum);
+ void gui_drawPortraitBox(int x, int y, int w, int h, int frameColor1, int frameColor2, int fillColor);
+ void gui_drawCharFaceShape(int charNum, int x, int y, int pageNum);
+ void gui_drawLiveMagicBar(int x, int y, int curPoints, int unk, int maxPoints, int w, int h, int col1, int col2, int flag);
+ void gui_drawMoneyBox(int pageNum);
+ void gui_drawInventory();
+ void gui_drawInventoryItem(int index);
+ void gui_drawCompass();
+ void gui_drawScroll();
+
+ bool _weaponsDisabled;
+ int _unkDrawPortraitIndex;
+ int _updateUnk2;
+ int _compassDirectionIndex;
+
+ const CompassDef *_compassDefs;
+ int _compassDefsSize;
+
+ // emc scripts
+ void runInitScript(const char *filename, int func);
+ void runInfScript(const char *filename);
+ void runResidentScript(int func, int reg0);
+ void runResidentScriptCustom(int func, int reg0, int reg1, int reg2, int reg3, int reg4);
+ bool checkScriptUnk(int func);
+
+ EMCData _scriptData;
+ bool _scriptBoolSkipExec;
+ uint8 _unkScriptByte;
+ uint16 _unkPara2;
+ uint16 _currentBlock;
+ bool _boolScriptFuncDone;
+ int16 _scriptExecutedFuncs[18];
+
+ uint16 _gameFlags[15];
+
+ // emc opcode
+ int o2_setGameFlag(EMCState *script);
+ int o2_testGameFlag(EMCState *script);
+ int o2_loadLevelSupplemenaryFiles(EMCState *script);
+ int o2_loadCmzFile(EMCState *script);
+ int o2_loadMonsterShapes(EMCState *script);
+ int o2_allocItemPropertiesBuffer(EMCState *script);
+ int o2_setItemProperty(EMCState *script);
+ int o2_makeItem(EMCState *script);
+ int o2_getItemPara(EMCState *script);
+ int o2_getCharacterStat(EMCState *script);
+ int o2_setCharacterStat(EMCState *script);
+ int o2_loadLevelShapes(EMCState *script);
+ int o2_closeLevelShapeFile(EMCState *script);
+ int o2_loadDoorShapes(EMCState *script);
+ int o2_setGlobalVar(EMCState *script);
+ int o2_mapShapeToBlock(EMCState *script);
+ int o2_resetBlockShapeAssignment(EMCState *script);
+ int o2_setPaletteBrightness(EMCState *script);
+ int o2_assignCustomSfx(EMCState *script);
+
+ // tim opcode
void setupOpcodeTable();
Common::Array<const TIMOpcode*> _timIntroOpcodes;
@@ -126,6 +350,7 @@ private:
int _lang;
uint8 *_landsFile;
+ uint8 *_levelLangFile;
int _lastUsedStringBuffer;
char _stringBuffer[5][512]; // TODO: The original used a size of 512, it looks a bit large.
@@ -136,7 +361,294 @@ private:
static const char * const _languageExt[];
// graphics
- uint8 *_shapes[138];
+ void setupScreenDims();
+
+ uint8 **_itemIconShapes;
+ int _numItemIconShapes;
+ uint8 **_itemShapes;
+ int _numItemShapes;
+ uint8 **_gameShapes;
+ int _numGameShapes;
+ uint8 **_thrownShapes;
+ int _numThrownShapes;
+ uint8 **_iceShapes;
+ int _numIceShapes;
+ uint8 **_fireballShapes;
+ int _numFireballShapes;
+
+ const int8 *_gameShapeMap;
+ int _gameShapeMapSize;
+
+ uint8 *_characterFaceShapes[40][3];
+
+ // characters
+ bool addCharacter(int id);
+ void initCharacter(int charNum, int firstFaceFrame, int unk2, int redraw);
+ void initCharacterUnkSub(int charNum, int unk1, int unk2, int unk3);
+ int countActiveCharacters();
+ void loadCharFaceShapes(int charNum, int id);
+ void calcCharPortraitXpos();
+
+ void updatePortraitWithStats();
+ void updatePortraits();
+ void updatePortraitUnkTimeSub(int unk1, int unk2);
+
+ void setCharFaceFrame(int charNum, int frameNum);
+ void faceFrameRefresh(int charNum);
+
+ LoLCharacter *_characters;
+ uint16 _activeCharsXpos[3];
+ int _charFlagUnk;
+ int _updateCharNum;
+ int _updateCharV1;
+ int _updateCharV2;
+ int _updateCharV3;
+ int _updateCharV4;
+ int _updateCharV5;
+ int _updateCharV6;
+ uint32 _updateCharTime;
+ uint32 _updatePortraitNext;
+
+ int _loadLevelFlag;
+ int _levelFlagUnk;
+
+ uint8 **_monsterShapes;
+ uint8 **_monsterPalettes;
+ uint8 **_buf4;
+ uint8 _monsterUnk[3];
+
+ const LoLCharacter *_charDefaults;
+ int _charDefaultsSize;
+
+ // level
+ void loadLevel(int index);
+ void addLevelItems();
+ int initCmzWithScript(int block);
+ void initCMZ1(LVL *l, int a);
+ void initCMZ2(LVL *l, uint16 a, uint16 b);
+ int cmzS1(uint16 a, uint16 b, uint16 c, uint16 d);
+ void cmzS2(LVL *l, int a);
+ void cmzS3(LVL *l);
+ void cmzS4(uint16 &itemIndex, int a);
+ int cmzS5(uint16 a, uint16 b);
+ void cmzS6(uint16 &itemIndex, int a);
+ void cmzS7(int itemIndex, int a);
+ void loadLevelWLL(int index, bool mapShapes);
+ void moveItemToCMZ(uint16 *cmzItemIndex, uint16 item);
+ int assignLevelShapes(int index);
+ uint8 *getLevelShapes(int index);
+ void loadLevelCMZ(int index);
+ void loadCMZ_Sub(int index1, int index2);
+ void loadCmzFile(const char *file);
+ void loadMonsterShapes(const char *file, int monsterIndex, int b);
+ void releaseMonsterShapes(int monsterIndex);
+ void loadLevelShpDat(const char *shpFile, const char *datFile, bool flag);
+ void loadLevelSupplemenaryFiles(const char *file, int specialColor, int weight, int vcnLen, int vmpLen, const char *langFile);
+
+ void drawScene(int pageNum);
+
+ void generateBlockDrawingBuffer(int block, int b);
+ void generateBlockDrawingBufferF0(int16 wllOffset, uint8 wllIndex, uint8 wllVmpIndex, int16 vmpOffset, uint8 len, uint8 numEntries);
+ void generateBlockDrawingBufferF1(int16 wllOffset, uint8 wllIndex, uint8 wllVmpIndex, int16 vmpOffset, uint8 len, uint8 numEntries);
+ bool testWllBuffer5Value(int index);
+ void assignBlockCaps(int a, int b);
+
+ void drawVcnBlocks(uint8 *vcnBlocks, uint16 *blockDrawingBuffer, uint8 *vcnShift, int pageNum);
+ void drawSceneShapes();
+ void setLevelShapesDim(int index, int16 &x1, int16 &x2, int dim);
+ void scaleLevelShapesDim(int index, int16 &y1, int16 &y2, int dim);
+ void drawLevelModifyScreenDim(int dim, int16 x1, int16 y1, int16 x2, int16 y2);
+ void drawDecorations(int index);
+ void drawIceShapes(int index, int iceShapeIndex);
+ void drawDoor(uint8 *shape, uint8 *table, int index, int unk2, int w, int h, int flags);
+ void drawDoorShapes(uint8 *shape, uint8 *table, int x, int y, int flags, const uint8 *ovl);
+ void drawScriptShapes(int pageNum);
+ void updateSceneWindow();
+
+ void turnOnLamp();
+ void updateLampStatus();
+
+ void setLF1(uint16 & a, uint16 & b, int block, uint16 d, uint16 e);
+ void setLF2(int block);
+
+ int _unkFlag;
+ int _scriptFuncIndex;
+ uint8 _currentLevel;
+ bool _loadLevelFlag2;
+ int _lvlBlockIndex;
+ int _lvlShapeIndex;
+ bool _unkDrawLevelBool;
+ uint8 *_vcnBlocks;
+ uint8 *_vcnShift;
+ uint8 *_vcnExpTable;
+ uint16 *_vmpPtr;
+ uint16 *_blockDrawingBuffer;
+ uint8 *_sceneWindowBuffer;
+ LevelShapeProperty *_levelShapeProperties;
+ uint8 **_levelShapes;
+
+ char _lastSuppFile[12];
+ char _lastSuppLangFile[12];
+ char *_lastSuppLangFilePtr;
+ int _lastSpecialColor;
+ int _lastSpecialColorWeight;
+
+ int _sceneDrawVar1;
+ int _sceneDrawVar2;
+ int _sceneDrawVar3;
+ int _wllProcessFlag;
+
+ uint8 *_tlcTable2;
+ uint8 *_tlcTable1;
+
+ int _loadSuppFilesFlag;
+
+ int _lampOilStatus;
+ int _brightness;
+ int _lampStatusUnk;
+ uint32 _lampStatusTimer;
+
+ uint8 *_wllVmpMap;
+ int8 *_wllShapeMap;
+ uint8 *_wllBuffer3;
+ uint8 *_wllBuffer4;
+ uint8 *_wllBuffer5;
+
+ int16 *_lvlShapeTop;
+ int16 *_lvlShapeBottom;
+ int16 *_lvlShapeLeftRight;
+
+ CMZ *_cmzBuffer;
+ CMZ *_curBlockCaps[18];
+ LVL *_lvlBuffer;
+ uint8 *_lvl415;
+
+ uint16 _unkCmzU1;
+ uint16 _unkCmzU2;
+
+ Common::SeekableReadStream *_lvlShpFileHandle;
+ uint16 _lvlShpNum;
+ uint32 *_lvlShpHeader;
+ uint16 _levelFileDataSize;
+ LevelShapeProperty *_levelFileData;
+
+ uint8 *_doorShapes[2];
+ int16 _shpDoorX;
+ int16 _shpDoorY;
+ int16 _doorScaleW;
+ int16 _doorScaleH;
+
+ uint8 _unkGameFlag;
+
+ uint8 *_tempBuffer5120;
+
+ const char *const * _levelDatList;
+ int _levelDatListSize;
+ const char *const * _levelShpList;
+ int _levelShpListSize;
+
+ const int8 *_dscUnk1;
+ int _dscUnk1Size;
+ const int8 *_dscShapeIndex;
+ int _dscShapeIndexSize;
+ const uint8 *_dscOvlMap;
+ int _dscOvlMapSize;
+ const uint16 *_dscShapeScaleW;
+ int _dscShapeScaleWSize;
+ const uint16 *_dscShapeScaleH;
+ int _dscShapeScaleHSize;
+ const int16 *_dscShapeX;
+ int _dscShapeXSize;
+ const int8 *_dscShapeY;
+ int _dscShapeYSize;
+ const uint8 *_dscTileIndex;
+ int _dscTileIndexSize;
+ const uint8 *_dscUnk2;
+ int _dscUnk2Size;
+ const uint8 *_dscDoorShpIndex;
+ int _dscDoorShpIndexSize;
+ const int8 *_dscDim1;
+ int _dscDim1Size;
+ const int8 *_dscDim2;
+ int _dscDim2Size;
+ const uint8 *_dscBlockMap;
+ int _dscBlockMapSize;
+ const uint8 *_dscDimMap;
+ int _dscDimMapSize;
+ const uint8 *_dscDoor2;
+ int _dscDoor2Size;
+ const uint16 *_dscDoorScaleTable;
+ int _dscDoorScaleTableSize;
+ const uint16 *_dscDoor4;
+ int _dscDoor4Size;
+ const uint8 *_dscShapeOvlIndex;
+ int _dscShapeOvlIndexSize;
+ const int8 *_dscBlockIndex;
+ int _dscBlockIndexSize;
+ const uint8 *_dscDoor1;
+ int _dscDoor1Size;
+ const int16 *_dscDoorX;
+ int _dscDoorXSize;
+ const int16 *_dscDoorY;
+ int _dscDoorYSize;
+
+ int _sceneDrawPage1;
+ int _sceneDrawPage2;
+
+ // items
+ struct ItemInPlay {
+ uint16 itemIndexUnk;
+ uint8 unk2;
+ uint16 unk3;
+ uint16 cmzIndex;
+ uint16 unk7;
+ uint16 anonymous_4;
+ int8 level;
+ uint16 itemPropertyIndex;
+ uint16 shpCurFrame_flg;
+ uint8 field10;
+ uint16 anon8;
+ uint8 anon9;
+ };
+
+ struct ItemProperty {
+ uint16 nameStringId;
+ uint8 shpIndex;
+ uint16 flags;
+ uint16 unk5;
+ uint8 itemScriptFunc;
+ uint8 unk8;
+ uint8 unk9;
+ uint8 unkA;
+ uint16 unkB;
+ uint8 unkD;
+ };
+
+ void giveCredits(int credits, int redraw);
+ int makeItem(int itemIndex, int curFrame, int flags);
+ bool testUnkItemFlags(int itemIndex);
+ void clearItemTableEntry(int itemIndex);
+ void *cmzGetItemOffset(uint16 index);
+ void runItemScript(int reg1, int item, int reg0, int reg3, int reg4);
+
+ uint8 _moneyColumnHeight[5];
+ uint16 _credits;
+
+ ItemInPlay *_itemsInPlay;
+ ItemProperty *_itemProperties;
+
+ int _itemInHand;
+ uint16 _inventoryItemIndex[48];
+ int _inventoryCurItem;
+ int _unkInventFlag;
+
+ EMCData _itemScript;
+
+ // spells
+ int8 _availableSpells[7];
+ int _selectedSpell;
+ const SpellProperty *_spellProperties;
+ int _spellPropertiesSize;
// unneeded
void setWalkspeed(uint8) {}
diff --git a/engines/kyra/module.mk b/engines/kyra/module.mk
index 18ab2ecdb5..0775fe3ec4 100644
--- a/engines/kyra/module.mk
+++ b/engines/kyra/module.mk
@@ -12,10 +12,12 @@ MODULE_OBJS := \
gui_v2.o \
gui_hof.o \
gui_mr.o \
+ gui_lol.o \
items_lok.o \
items_v2.o \
items_hof.o \
items_mr.o \
+ items_lol.o \
kyra_v1.o \
kyra_lok.o \
kyra_v2.o \
@@ -33,6 +35,7 @@ MODULE_OBJS := \
scene_v2.o \
scene_hof.o \
scene_mr.o \
+ scene_lol.o \
screen.o \
screen_lok.o \
screen_lol.o \
@@ -44,6 +47,7 @@ MODULE_OBJS := \
script_v2.o \
script_hof.o \
script_mr.o \
+ script_lol.o \
script.o \
script_tim.o \
seqplayer.o \
diff --git a/engines/kyra/resource.h b/engines/kyra/resource.h
index 5ef26caa78..1f865e855f 100644
--- a/engines/kyra/resource.h
+++ b/engines/kyra/resource.h
@@ -39,6 +39,7 @@
#include "kyra/kyra_v1.h"
#include "kyra/kyra_hof.h"
+#include "kyra/lol.h"
namespace Kyra {
@@ -210,6 +211,40 @@ enum kKyraResources {
k3ItemMagicTable,
k3ItemStringMap,
+ lolCharacterDefs,
+ lolIngameSfxFiles,
+ lolIngameSfxIndex,
+ lolIngameGMSfxIndex,
+ lolIngameMT32SfxIndex,
+ lolSpellProperties,
+ lolGameShapeMap,
+ lolLevelShpList,
+ lolLevelDatList,
+ lolCompassDefs,
+
+ lolDscUnk1,
+ lolDscShapeIndex,
+ lolDscOvlMap,
+ lolDscScaleWidthData,
+ lolDscScaleHeightData,
+ lolDscX,
+ lolDscY,
+ lolDscTileIndex,
+ lolDscUnk2,
+ lolDscDoorShapeIndex,
+ lolDscDimData1,
+ lolDscDimData2,
+ lolDscBlockMap,
+ lolDscDimMap,
+ lolDscDoor1,
+ lolDscDoor2,
+ lolDscDoorScale,
+ lolDscDoor4,
+ lolDscDoorX,
+ lolDscDoorY,
+ lolDscOvlIndex,
+ lolDscBlockIndex,
+
kMaxResIDs
};
@@ -236,6 +271,10 @@ public:
const HofSeqData *loadHofSequenceData(int id, int &entries);
const ItemAnimData_v1 *loadShapeAnimData_v1(int id, int &entries);
const ItemAnimData_v2 *loadShapeAnimData_v2(int id, int &entries);
+ const LoLCharacter *loadCharData(int id, int &entries);
+ const SpellProperty *loadSpellData(int id, int &entries);
+ const CompassDef *loadCompassData(int id, int &entries);
+ const uint16 *loadRawDataBe16(int id, int &entries);
// use '-1' to prefetch/unload all ids
// prefetchId retruns false if only on of the resources
@@ -267,6 +306,10 @@ private:
bool loadHofSequenceData(const char *filename, void *&ptr, int &size);
bool loadShapeAnimData_v1(const char *filename, void *&ptr, int &size);
bool loadShapeAnimData_v2(const char *filename, void *&ptr, int &size);
+ bool loadCharData(const char *filename, void *&ptr, int &size);
+ bool loadSpellData(const char *filename, void *&ptr, int &size);
+ bool loadCompassData(const char *filename, void *&ptr, int &size);
+ bool loadRawDataBe16(const char *filename, void *&ptr, int &size);
void freeRawData(void *&ptr, int &size);
void freeStringTable(void *&ptr, int &size);
@@ -276,6 +319,10 @@ private:
void freeHofSequenceData(void *&ptr, int &size);
void freeHofShapeAnimDataV1(void *&ptr, int &size);
void freeHofShapeAnimDataV2(void *&ptr, int &size);
+ void freeCharData(void *&ptr, int &size);
+ void freeSpellData(void *&ptr, int &size);
+ void freeCompassData(void *&ptr, int &size);
+ void freeRawDataBe16(void *&ptr, int &size);
const char *getFilename(const char *name);
Common::SeekableReadStream *getFile(const char *name);
@@ -290,7 +337,12 @@ private:
k2SeqData,
k2ShpAnimDataV1,
- k2ShpAnimDataV2
+ k2ShpAnimDataV2,
+
+ lolCharData,
+ lolSpellData,
+ lolCompassData,
+ lolRawDataBe16
};
struct BuiltinRes {
diff --git a/engines/kyra/scene_lol.cpp b/engines/kyra/scene_lol.cpp
new file mode 100644
index 0000000000..2fada31d9c
--- /dev/null
+++ b/engines/kyra/scene_lol.cpp
@@ -0,0 +1,1369 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "kyra/lol.h"
+#include "kyra/screen_lol.h"
+#include "kyra/resource.h"
+
+#include "common/endian.h"
+
+namespace Kyra {
+
+void LoLEngine::loadLevel(int index) {
+ _unkFlag |= 0x800;
+ setMouseCursorToIcon(0x85);
+ _scriptFuncIndex = 0;
+
+ // TODO
+
+ updatePortraits();
+
+ for (int i = 0; i < 400; i++) {
+ delete [] _levelShapes[i];
+ _levelShapes[i] = 0;
+ }
+
+ _emc->unload(&_scriptData);
+
+ _currentLevel = index;
+ _charFlagUnk = 0;
+
+ releaseMonsterShapes(0);
+ releaseMonsterShapes(1);
+
+ //TODO
+
+ //loadTalkFile(index);
+ loadLevelWLL(index, true);
+ _loadLevelFlag = 1;
+
+ char filename[] = "level%d.ini";
+ sprintf(filename, "level%d.ini", index);
+
+ int f = _levelFlagUnk & (1 << ((index + 0xff) & 0xff));
+
+ runInitScript(filename, f ? 0 : 1);
+
+ if (f)
+ loadLevelCMZ(index);
+
+ sprintf(filename, "level%d.inf", index);
+ runInfScript(filename);
+
+ addLevelItems();
+ initCmzWithScript(_currentBlock);
+
+ _screen->generateGrayOverlay(_screen->_currentPalette, _screen->_grayOverlay,32, 16, 0, 0, 128, true);
+
+ _loadLevelFlag2 = false;
+ if (_screen->_fadeFlag == 3)
+ _screen->fadeToBlack(10);
+
+ gui_drawPlayField();
+
+ _screen->setPaletteBrightness(_screen->_currentPalette, _brightness, _lampOilStatus);
+ setMouseCursorToItemInHand();
+ //TODO
+}
+
+void LoLEngine::addLevelItems() {
+ for (int i = 0; i < 400; i++) {
+ if (_itemsInPlay[i].level != _currentLevel)
+ continue;
+
+ moveItemToCMZ(&_cmzBuffer[_itemsInPlay[i].cmzIndex].itemIndex, i);
+
+ _cmzBuffer[_itemsInPlay[i].cmzIndex].field_8 = 5;
+ _itemsInPlay[i].unk2 = 0;
+ }
+}
+
+int LoLEngine::initCmzWithScript(int block) {
+ int i = _cmzBuffer[block].itemIndex;
+ int cnt = 0;
+
+ while (i) {
+ void *t = cmzGetItemOffset(i);
+ i = (i & 0x8000) ? ((LVL*)t)->field_0 : ((ItemInPlay*)t)->itemIndexUnk;
+ if (!(i & 0x8000))
+ continue;
+
+ i &= 0x7fff;
+ LVL *l = &_lvlBuffer[i];
+
+ cnt++;
+ initCMZ1(l, 14);
+
+ checkScriptUnk(l->cmzIndex);
+
+ initCMZ2(l, 0, 0);
+ }
+ return cnt;
+}
+
+void LoLEngine::initCMZ1(LVL *l, int a) {
+ if (l->field_14 == 13 && a != 14)
+ return;
+ if (a == 7) {
+ l->p_2a = _unkCmzU1;
+ l->p_2b = _unkCmzU2;
+ }
+
+ if (l->field_14 == 1 && a == 7) {
+ for (int i = 0; i < 30; i++) {
+ if (l->field_14 != 1)
+ continue;
+ l->field_14 = a;
+ l->field_15 = 0;
+ l->p_2a = _unkCmzU1;
+ l->p_2b = _unkCmzU2;
+ cmzS2(l, cmzS1(l->p_1a, l->p_1b, l->p_2a, l->p_2b));
+ }
+ } else {
+ l->field_14 = a;
+ l->field_15 = 0;
+ if (a == 14)
+ l->field_1D = 0;
+ if (a == 13 && (l->field_19 & 0x20)) {
+ l->field_14 = 0;
+ cmzS3(l);
+ if (_currentLevel != 29)
+ initCMZ1(l, 14);
+ runResidentScriptCustom(0x404, -1, l->field_16, l->field_16, 0, 0);
+ checkScriptUnk(l->cmzIndex);
+ if (l->field_14 == 14)
+ initCMZ2(l, 0, 0);
+ }
+ }
+
+}
+
+void LoLEngine::initCMZ2(LVL *l, uint16 a, uint16 b) {
+ bool cont = true;
+ int t = l->cmzIndex;
+ if (l->cmzIndex) {
+ cmzS4(_cmzBuffer[l->cmzIndex].itemIndex, ((uint16)l->field_16) | 0x8000);
+ _cmzBuffer[l->cmzIndex].field_8 = 5;
+ checkScriptUnk(l->cmzIndex);
+ } else {
+ cont = false;
+ }
+
+ l->cmzIndex = cmzS5(a, b);
+
+ if (l->p_1a != a || l->p_1b != b) {
+ l->p_1a = a;
+ l->p_1b = b;
+ l->field_13 = (++l->field_13) & 3;
+ }
+
+ if (l->cmzIndex == 0)
+ return;
+
+ cmzS6(_cmzBuffer[l->cmzIndex].itemIndex, ((uint16)l->field_16) | 0x8000);
+ _cmzBuffer[l->cmzIndex].field_8 = 5;
+ checkScriptUnk(l->cmzIndex);
+ uint8 *v = l->offs_lvl415;
+
+ if (v[80] == 0 || cont == false)
+ return;
+
+ if ((!(READ_LE_UINT16(&v[62]) & 0x100) || ((l->field_13 & 1) == 0)) && l->cmzIndex == t)
+ return;
+
+ if (l->cmzIndex != t)
+ runResidentScriptCustom(l->cmzIndex, 0x800, -1, l->field_16, 0, 0);
+
+ if (_charFlagUnk & 1)
+ return;
+
+ cmzS7(l->offs_lvl415[50], l->cmzIndex);
+}
+
+int LoLEngine::cmzS1(uint16 a, uint16 b, uint16 c, uint16 d) {
+ // TODO
+
+ return 0;
+}
+
+void LoLEngine::cmzS2(LVL *l, int a) {
+ // TODO
+}
+
+void LoLEngine::cmzS3(LVL *l) {
+ // TODO
+}
+
+void LoLEngine::cmzS4(uint16 &itemIndex, int a) {
+ // TODO
+}
+
+int LoLEngine::cmzS5(uint16 a, uint16 b) {
+ // TODO
+ return 0;
+}
+
+void LoLEngine::cmzS6(uint16 &itemIndex, int a) {
+ // TODO
+}
+
+void LoLEngine::cmzS7(int itemIndex, int a) {
+ if (!(_unkGameFlag & 1))
+ return;
+
+ // TODO
+}
+
+void LoLEngine::moveItemToCMZ(uint16 *cmzItemIndex, uint16 item) {
+ uint16 *tmp = 0;
+ while (*cmzItemIndex & 0x8000) {
+ tmp = (uint16*) cmzGetItemOffset(*cmzItemIndex);
+ cmzItemIndex = tmp;
+ }
+ uint16 *t = (uint16*) cmzGetItemOffset(*cmzItemIndex);
+
+ ((ItemInPlay*)t)->level = -1;
+ uint16 ix = *cmzItemIndex;
+
+ if (ix == item)
+ return;
+
+ *cmzItemIndex = item;
+ cmzItemIndex = t;
+
+ while (*cmzItemIndex)
+ cmzItemIndex = (uint16*) cmzGetItemOffset(*cmzItemIndex);
+
+ *cmzItemIndex = ix;
+}
+
+void LoLEngine::loadLevelWLL(int index, bool mapShapes) {
+ char filename[] = "level%00d.wll";
+ sprintf(filename, "level%00d.wll", index);
+
+ uint32 size;
+ uint8 *file = _res->fileData(filename, &size);
+
+ uint16 c = READ_LE_UINT16(file);
+ loadLevelShpDat(_levelShpList[c], _levelDatList[c], false);
+
+ uint8 *d = file + 2;
+ size = (size - 2) / 12;
+ for (uint32 i = 0; i < size; i++) {
+ c = READ_LE_UINT16(d);
+ d += 2;
+ _wllVmpMap[c] = *d;
+ d += 2;
+
+ if (mapShapes) {
+ int16 sh = (int16) READ_LE_UINT16(d);
+ if (sh > 0)
+ _wllShapeMap[c] = assignLevelShapes(sh);
+ else
+ _wllShapeMap[c] = *d;
+ }
+ d += 2;
+ _wllBuffer3[c] = *d;
+ d += 2;
+ _wllBuffer5[c] = *d;
+ d += 2;
+ _wllBuffer4[c] = *d;
+ d += 2;
+ }
+
+ delete []file;
+
+ delete _lvlShpFileHandle;
+ _lvlShpFileHandle = 0;
+}
+
+int LoLEngine::assignLevelShapes(int index) {
+ uint16 *p1 = (uint16 *) _tempBuffer5120;
+ uint16 *p2 = (uint16 *) (_tempBuffer5120 + 4000);
+
+ uint16 r = p2[index];
+ if (r)
+ return r;
+
+ uint16 o = _lvlBlockIndex++;
+
+ memcpy(&_levelShapeProperties[o], &_levelFileData[index], sizeof(LevelShapeProperty));
+
+ for (int i = 0; i < 10; i++) {
+ uint16 t = _levelShapeProperties[o].shapeIndex[i];
+ if (t == 0xffff)
+ continue;
+
+ uint16 pv = p1[t];
+ if (pv) {
+ _levelShapeProperties[o].shapeIndex[i] = pv;
+ } else {
+ _levelShapes[_lvlShapeIndex] = getLevelShapes(t);
+ p1[t] = _lvlShapeIndex;
+ _levelShapeProperties[o].shapeIndex[i] = _lvlShapeIndex++;
+ }
+ }
+
+ p2[index] = o;
+ if (_levelShapeProperties[o].next)
+ _levelShapeProperties[o].next = assignLevelShapes(_levelShapeProperties[o].next);
+
+ return o;
+}
+
+uint8 *LoLEngine::getLevelShapes(int shapeIndex) {
+ if (_lvlShpNum <= shapeIndex)
+ return 0;
+
+ uint32 offs = _lvlShpHeader[shapeIndex] + 2;
+ _lvlShpFileHandle->seek(offs, 0);
+
+ uint8 tmp[16];
+ _lvlShpFileHandle->read(tmp, 16);
+ uint16 size = _screen->getShapeSize(tmp);
+
+ _lvlShpFileHandle->seek(offs, 0);
+ uint8 *res = new uint8[size];
+ _lvlShpFileHandle->read(res, size);
+
+ return res;
+}
+
+void LoLEngine::loadLevelCMZ(int index) {
+ //char filename[] = "_LEVEL%d.TMP";
+ //sprintf(filename, "_LEVEL%d.TMP", index);
+ // TODO ???
+ memset(_tempBuffer5120, 0, 5120);
+ uint16 tmpLvlVal = 0;
+
+
+ char filename[] = "level%d.cmz";
+ sprintf(filename, "level%d.cmz", index);
+
+ _screen->loadBitmap(filename, 3, 3, 0);
+ const uint8 *p = _screen->getCPagePtr(2);
+ uint16 len = READ_LE_UINT16(p + 4);
+
+ uint8 *cmzdata = new uint8[0x1000];
+
+ for (int i = 0; i < 1024; i++)
+ memcpy(&cmzdata[i << 2], &p[i * len + 6], 4);
+
+ memset(_cmzBuffer, 0, 1024 * sizeof(CMZ));
+
+ uint8 *c = cmzdata;
+ uint8 *t = _tempBuffer5120;
+
+ for (int i = 0; i < 1024; i++) {
+ for (int ii = 0; ii < 4; ii++)
+ _cmzBuffer[i].unk[ii] = *c++ ^ *t++;
+ }
+
+ for (int i = 0; i < 1024; i++)
+ _cmzBuffer[i].flags = *t++;
+
+ for (int i = 0; i < 30; i++) {
+ if (_lvlBuffer[i].cmzIndex) {
+ _lvlBuffer[i].cmzIndex = 0;
+ _lvlBuffer[i].offs_lvl415 = _lvl415 + _lvlBuffer[i].field_20;
+ initCMZ2(&_lvlBuffer[i], _lvlBuffer[i].p_1a, _lvlBuffer[i].p_1b);
+ }
+ }
+
+ loadCMZ_Sub(tmpLvlVal, (_unkGameFlag & 0x30) >> 4);
+
+ delete []cmzdata;
+}
+
+void LoLEngine::loadCMZ_Sub(int index1, int index2) {
+ static const int table[] = { 0x66, 0x100, 0x180, 0x100, 0x100, 0xC0, 0x140, 0x100, 0x80, 0x80, 0x100, 0x100 };
+ int val = (table[index2] << 8) / table[index1];
+
+ //int r = 0;
+
+ for (int i = 0; i < 30; i++) {
+ if (_lvlBuffer[i].field_14 >= 14 || _lvlBuffer[i].cmzIndex == 0 || _lvlBuffer[i].field_1D <= 0)
+ continue;
+
+ int t = (val * _lvlBuffer[i].field_1D) >> 8;
+ _lvlBuffer[i].field_1D = t;
+ if (index2 < index1)
+ _lvlBuffer[i].field_1D++;
+ if (_lvlBuffer[i].field_1D == 0)
+ _lvlBuffer[i].field_1D = 1;
+ }
+}
+
+void LoLEngine::loadCmzFile(const char *file) {
+ memset(_cmzBuffer, 0, 1024 * sizeof(CMZ));
+ _screen->loadBitmap(file, 2, 2, 0);
+ const uint8 *h = _screen->getCPagePtr(2);
+ uint16 len = READ_LE_UINT16(&h[4]);
+ const uint8 *p = h + 6;
+
+ for (int i = 0; i < 1024; i++) {
+ for (int ii = 0; ii < 4; ii++)
+ _cmzBuffer[i].unk[ii] = p[i * len + ii];
+
+ _cmzBuffer[i].field_8 = 5;
+
+ if (_wllBuffer4[_cmzBuffer[i].unk[0]] == 17) {
+ _cmzBuffer[i].flags &= 0xef;
+ _cmzBuffer[i].flags |= 0x20;
+ }
+ }
+}
+
+void LoLEngine::loadMonsterShapes(const char *file, int monsterIndex, int b) {
+ releaseMonsterShapes(monsterIndex);
+ _screen->loadBitmap(file, 3, 3, 0);
+
+ const uint8 *p = _screen->getCPagePtr(2);
+ const uint8 *ts[16];
+
+ for (int i = 0; i < 16; i++) {
+ ts[i] = _screen->getPtrToShape(p, i);
+
+ bool replaced = false;
+ int pos = monsterIndex << 4;
+
+ for (int ii = 0; ii < i; ii++) {
+ if (ts[i] != ts[ii])
+ continue;
+
+ _monsterShapes[pos + i] = _monsterShapes[pos + ii];
+ replaced = true;
+ break;
+ }
+
+ if (!replaced)
+ _monsterShapes[pos + i] = _screen->makeShapeCopy(p, i);
+
+ int size = _screen->getShapePaletteSize(_monsterShapes[pos + i]) << 3;
+ _monsterPalettes[pos + i] = new uint8[size];
+ memset(_monsterPalettes[pos + i], 0, size);
+ }
+
+ /*for (int i = 0; i < 4; i++) {
+ for (int ii = 0; ii < 16; ii++) {
+ uint8 **of = &_buf4[(monsterIndex << 7) + (i << 5) + (ii << 1)];
+ int s = (i << 4) + ii + 17;
+ *of = _screen->makeShapeCopy(p, s);
+ ////TODO
+ }
+ }*/
+ _monsterUnk[monsterIndex] = b & 0xff;
+
+ uint8 *tsh = _screen->makeShapeCopy(p, 16);
+
+ _screen->clearPage(3);
+ _screen->drawShape(2, tsh, 0, 0, 0, 0);
+
+ uint8 *tmpPal1 = new uint8[64];
+ uint8 *tmpPal2 = new uint8[256];
+ uint16 *tmpPal3 = new uint16[256];
+ memset (tmpPal1, 0, 64);
+ memset (tmpPal2, 0, 256);
+ memset (tmpPal3, 0xff, 512);
+
+ for (int i = 0; i < 64; i++) {
+ tmpPal1[i] = *p;
+ p += 320;
+ }
+
+ p = _screen->getCPagePtr(2);
+
+ for (int i = 0; i < 16; i++) {
+ int pos = (monsterIndex << 4) + i;
+ memcpy(tmpPal2, _monsterShapes[pos] + 10, 256);
+ uint8 numCol = *tmpPal2;
+
+ for (int ii = 0; ii < numCol; ii++) {
+ uint8 *cl = (uint8*)memchr(tmpPal1, tmpPal2[1 + ii], 64);
+ if (!cl)
+ continue;
+ tmpPal3[ii] = (uint16) (cl - tmpPal1);
+ }
+
+ for (int ii = 0; ii < 8; ii++) {
+ memcpy(tmpPal2, _monsterShapes[pos] + 10, 256);
+ for (int iii = 0; iii < numCol; iii++) {
+ if (tmpPal3[iii] == 0xffff)
+ continue;
+ if (p[tmpPal3[iii] * 320 + ii + 1])
+ tmpPal2[1 + iii] = p[tmpPal3[iii] * 320 + ii + 1];
+ }
+ memcpy(_monsterPalettes[pos] + ii * numCol, &tmpPal2[1], numCol);
+ }
+ }
+
+ delete []tmpPal1;
+ delete []tmpPal2;
+ delete []tmpPal3;
+ delete [] tsh;
+}
+
+void LoLEngine::releaseMonsterShapes(int monsterIndex) {
+ for (int i = 0; i < 16; i++) {
+ int pos = (monsterIndex << 4) + i;
+ if (_monsterShapes[pos]) {
+ delete []_monsterShapes[pos];
+ _monsterShapes[pos] = 0;
+ }
+
+ if (_monsterPalettes[pos]) {
+ delete []_monsterPalettes[pos];
+ _monsterPalettes[pos] = 0;
+ }
+ }
+}
+
+void LoLEngine::loadLevelShpDat(const char *shpFile, const char *datFile, bool flag) {
+ memset(_tempBuffer5120, 0, 5120);
+
+ _lvlShpFileHandle = _res->getFileStream(shpFile);
+ _lvlShpNum = _lvlShpFileHandle->readUint16LE();
+ delete []_lvlShpHeader;
+ _lvlShpHeader = new uint32[_lvlShpNum];
+ for (int i = 0; i < _lvlShpNum; i++)
+ _lvlShpHeader[i] = _lvlShpFileHandle->readUint32LE();
+
+ Common::SeekableReadStream *s = _res->getFileStream(datFile);
+
+ _levelFileDataSize = s->readUint16LE();
+ delete []_levelFileData;
+ _levelFileData = new LevelShapeProperty[_levelFileDataSize];
+ for (int i = 0; i < _levelFileDataSize; i++) {
+ LevelShapeProperty * l = &_levelFileData[i];
+ for (int ii = 0; ii < 10; ii++)
+ l->shapeIndex[ii] = s->readUint16LE();
+ for (int ii = 0; ii < 10; ii++)
+ l->scaleFlag[ii] = s->readByte();
+ for (int ii = 0; ii < 10; ii++)
+ l->shapeX[ii] = s->readUint16LE();
+ for (int ii = 0; ii < 10; ii++)
+ l->shapeY[ii] = s->readUint16LE();
+ l->next = s->readByte();
+ l->flags = s->readByte();
+ }
+
+ delete []s;
+
+ if (!flag) {
+ _lvlBlockIndex = 1;
+ _lvlShapeIndex = 1;
+ }
+}
+
+void LoLEngine::loadLevelSupplemenaryFiles(const char *file, int specialColor, int weight, int vcnLen, int vmpLen, const char *langFile) {
+ if (file) {
+ _lastSpecialColor = specialColor;
+ _lastSpecialColorWeight = weight;
+ strcpy(_lastSuppFile, file);
+ if (langFile) {
+ strcpy(_lastSuppLangFile, langFile);
+ _lastSuppLangFilePtr = _lastSuppLangFile;
+ } else {
+ _lastSuppLangFilePtr = 0;
+ }
+ }
+
+ char fname[] = " ";
+ sprintf(fname, "%s.%s", _lastSuppFile, "VCN");
+
+ _screen->loadBitmap(fname, 3, 3, 0);
+ const uint8 *v = _screen->getCPagePtr(2);
+ int tlen = READ_LE_UINT16(v);
+ v += 2;
+
+ if (vcnLen == -1)
+ vcnLen = tlen << 5;
+
+ if (_vcnBlocks)
+ delete []_vcnBlocks;
+ _vcnBlocks = new uint8[vcnLen];
+
+ if (_vcnShift)
+ delete []_vcnShift;
+ _vcnShift = new uint8[tlen];
+
+ memcpy(_vcnShift, v, tlen);
+ v += tlen;
+
+ memcpy(_vcnExpTable, v, 128);
+ v += 128;
+
+ if (_lastSuppLangFilePtr) {
+ if (_levelLangFile)
+ delete []_levelLangFile;
+ _levelLangFile = _res->fileData(_lastSuppLangFilePtr, 0);
+ }
+
+ memcpy(_screen->_currentPalette, v, 384);
+ v += 384;
+ /*uint8 tmpPal = new uint8[384];
+ memcpy(tmpPal, _screen->_currentPalette + 384, 384);
+ memset(_screen->_currentPalette + 384, 0xff, 384);
+ memcpy(_screen->_currentPalette + 384, tmpPal, 384);*/
+
+ //loadSwampIceCol();
+
+ memcpy(_vcnBlocks, v, vcnLen);
+ v += vcnLen;
+
+ sprintf(fname, "%s.%s", _lastSuppFile, "VMP");
+ _screen->loadBitmap(fname, 3, 3, 0);
+ v = _screen->getCPagePtr(2);
+
+ if (vmpLen == -1)
+ vmpLen = READ_LE_UINT16(v);
+ v += 2;
+
+ if (_vmpPtr)
+ delete []_vmpPtr;
+ _vmpPtr = new uint16[vmpLen];
+
+ for (int i = 0; i < vmpLen; i++)
+ _vmpPtr[i] = READ_LE_UINT16(&v[i << 1]);
+
+ for (int i = 0; i < 7; i++) {
+ weight = 100 - (i * _lastSpecialColorWeight);
+ weight = (weight > 0) ? (weight * 255) / 100 : 0;
+ _screen->generateLevelOverlay(_screen->_currentPalette, _screen->getLevelOverlay(i), _lastSpecialColor, weight);
+
+ for (int ii = 0; ii < 128; ii++) {
+ if (_screen->getLevelOverlay(i)[ii] == 255)
+ _screen->getLevelOverlay(i)[ii] = 0;
+ }
+
+ for (int ii = 128; ii < 256; ii++)
+ _screen->getLevelOverlay(i)[ii] = ii & 0xff;
+ }
+
+ for (int i = 0; i < 256; i++)
+ _screen->getLevelOverlay(7)[i] = i & 0xff;
+
+ _loadSuppFilesFlag = 0;
+ _screen->generateBrightnessPalette(_screen->_currentPalette, _screen->getPalette(1), _brightness, _lampOilStatus);
+
+ char tname[] = "LEVEL%02d.TLC";
+ sprintf(tname, "LEVEL%02d.TLC", _currentLevel);
+ Common::SeekableReadStream *s = _res->getFileStream(tname);
+ s->read(_tlcTable1, 256);
+ s->read(_tlcTable2, 5120);
+ delete []s;
+
+ _loadSuppFilesFlag = 1;
+}
+
+void LoLEngine::turnOnLamp() {
+ _screen->_drawGuiFlag |= 0x400;
+ _lampOilStatus = 255;
+ updateLampStatus();
+}
+
+void LoLEngine::updateLampStatus() {
+ uint8 newLampOilStatus = 0;
+ uint8 tmp2 = 0;
+
+ if ((_charFlagUnk & 4) || !(_screen->_drawGuiFlag & 0x800))
+ return;
+
+ if (!_brightness || !_lampStatusUnk) {
+ newLampOilStatus = 8;
+ if (newLampOilStatus != _lampOilStatus && _screen->_fadeFlag == 0)
+ _screen->setPaletteBrightness(_screen->_currentPalette, _lampOilStatus, newLampOilStatus);
+ } else {
+ tmp2 = (_lampStatusUnk < 100) ? _lampStatusUnk : 100;
+ newLampOilStatus = (3 - (tmp2 - 1) / 25) << 1;
+
+ if (_lampOilStatus == 255) {
+ if (_screen->_fadeFlag == 0)
+ _screen->setPaletteBrightness(_screen->_currentPalette, _brightness, newLampOilStatus);
+ _lampStatusTimer = _system->getMillis() + (10 + _rnd.getRandomNumberRng(1, 30)) * _tickLength;
+ } else {
+ if ((_lampOilStatus & 0xfe) == (newLampOilStatus & 0xfe)) {
+ if (_system->getMillis() <= _lampStatusTimer) {
+ newLampOilStatus = _lampOilStatus;
+ } else {
+ newLampOilStatus = _lampOilStatus ^ 1;
+ _lampStatusTimer = _system->getMillis() + (10 + _rnd.getRandomNumberRng(1, 30)) * _tickLength;
+ }
+ } else {
+ if (_screen->_fadeFlag == 0)
+ _screen->setPaletteBrightness(_screen->_currentPalette, _lampOilStatus, newLampOilStatus);
+ }
+ }
+ }
+
+ if (newLampOilStatus == _lampOilStatus)
+ return;
+
+ _screen->hideMouse();
+
+ _screen->drawShape(_screen->_curPage, _gameShapes[35 + newLampOilStatus], 291, 56, 0, 0);
+ _screen->showMouse();
+
+ _lampOilStatus = newLampOilStatus;
+}
+
+void LoLEngine::setLF1(uint16 & a, uint16 & b, int block, uint16 d, uint16 e) {
+ a = block & 0x1f;
+ a = ((a >> 8) | ((a & 0xff) << 8)) | d;
+ b = ((block & 0xffe0) << 3) | e;
+}
+
+void LoLEngine::setLF2(int block) {
+ if (!(_screen->_drawGuiFlag & 0x1000))
+ return;
+ _cmzBuffer[block].flags |= 7;
+ // TODO
+}
+
+void LoLEngine::drawScene(int pageNum) {
+ if (pageNum && pageNum != _sceneDrawPage1) {
+ _sceneDrawPage1 ^= _sceneDrawPage2;
+ _sceneDrawPage2 ^= _sceneDrawPage1;
+ _sceneDrawPage1 ^= _sceneDrawPage2;
+ updateSceneWindow();
+ }
+
+ if (pageNum && pageNum != _sceneDrawPage1) {
+ _sceneDrawPage1 ^= _sceneDrawPage2;
+ _sceneDrawPage2 ^= _sceneDrawPage1;
+ _sceneDrawPage1 ^= _sceneDrawPage2;
+ updateSceneWindow();
+ }
+
+ generateBlockDrawingBuffer(_currentBlock, _unkPara2);
+ drawVcnBlocks(_vcnBlocks, _blockDrawingBuffer, _vcnShift, _sceneDrawPage1);
+ drawSceneShapes();
+
+ if (pageNum) {
+ drawScriptShapes(_sceneDrawPage1);
+ _screen->copyRegion(112, 112, 0, 0, 176, 120, _sceneDrawPage1, _sceneDrawPage2);
+ _screen->copyRegion(112, 112, 0, 0, 176, 120, _sceneDrawPage1, 0);
+ _sceneDrawPage1 ^= _sceneDrawPage2;
+ _sceneDrawPage2 ^= _sceneDrawPage1;
+ _sceneDrawPage1 ^= _sceneDrawPage2;
+ }
+
+ gui_drawCompass();
+
+ _boolScriptFuncDone = false;
+}
+
+void LoLEngine::updateSceneWindow() {
+ _screen->hideMouse();
+ _screen->copyRegion(112, 0, 112, 0, 176, 120, 0, _sceneDrawPage2);
+ _screen->showMouse();
+}
+
+void LoLEngine::generateBlockDrawingBuffer(int block, int b) {
+ _sceneDrawVar1 = _dscBlockMap[_unkPara2];
+ _sceneDrawVar2 = _dscBlockMap[_unkPara2 + 4];
+ _sceneDrawVar3 = _dscBlockMap[_unkPara2 + 8];
+
+ memset(_blockDrawingBuffer, 0, 660 * sizeof(uint16));
+
+ _wllProcessFlag = ((block >> 5) + (block & 0x1f) + _unkPara2) & 1;
+
+ if (_wllProcessFlag)
+ generateBlockDrawingBufferF1(0, 15, 1, -330, 22, 15);
+ else
+ generateBlockDrawingBufferF0(0, 15, 1, -330, 22, 15);
+
+ assignBlockCaps(block, b);
+
+ uint8 t = _curBlockCaps[0]->unk[_sceneDrawVar2];
+ if (t)
+ generateBlockDrawingBufferF0(-2, 3, t, 102, 3, 5);
+
+ t = _curBlockCaps[6]->unk[_sceneDrawVar3];
+ if (t)
+ generateBlockDrawingBufferF1(21, 3, t, 102, 3, 5);
+
+ t = _curBlockCaps[1]->unk[_sceneDrawVar2];
+ uint8 t2 = _curBlockCaps[2]->unk[_sceneDrawVar1];
+
+ if (testWllBuffer5Value(t) && !(_wllBuffer5[t2] & 8))
+ generateBlockDrawingBufferF0(2, 3, t, 102, 3, 5);
+ else if (t && (_wllBuffer5[t2] & 8))
+ generateBlockDrawingBufferF0(2, 3, t2, 102, 3, 5);
+
+ t = _curBlockCaps[5]->unk[_sceneDrawVar3];
+ t2 = _curBlockCaps[4]->unk[_sceneDrawVar1];
+
+ if (testWllBuffer5Value(t) && !(_wllBuffer5[t2] & 8))
+ generateBlockDrawingBufferF1(17, 3, t, 102, 3, 5);
+ else if(t && (_wllBuffer5[t2] & 8))
+ generateBlockDrawingBufferF1(17, 3, t2, 102, 3, 5);
+
+ t = _curBlockCaps[2]->unk[_sceneDrawVar2];
+ if (t)
+ generateBlockDrawingBufferF0(8, 3, t, 97, 1, 5);
+
+ t = _curBlockCaps[4]->unk[_sceneDrawVar3];
+ if (t)
+ generateBlockDrawingBufferF1(13, 3, t, 97, 1, 5);
+
+ t = _curBlockCaps[1]->unk[_sceneDrawVar1];
+ if (testWllBuffer5Value(t))
+ generateBlockDrawingBufferF0(-4, 3, t, 129, 6, 5);
+
+ t = _curBlockCaps[5]->unk[_sceneDrawVar1];
+ if (testWllBuffer5Value(t))
+ generateBlockDrawingBufferF0(20, 3, t, 129, 6, 5);
+
+ t = _curBlockCaps[2]->unk[_sceneDrawVar1];
+ if (testWllBuffer5Value(t))
+ generateBlockDrawingBufferF0(2, 3, t, 129, 6, 5);
+
+ t = _curBlockCaps[4]->unk[_sceneDrawVar1];
+ if (testWllBuffer5Value(t))
+ generateBlockDrawingBufferF0(14, 3, t, 129, 6, 5);
+
+ t = _curBlockCaps[3]->unk[_sceneDrawVar1];
+ if (t)
+ generateBlockDrawingBufferF0(8, 3, t, 129, 6, 5);
+
+ t = _curBlockCaps[7]->unk[_sceneDrawVar2];
+ if (t)
+ generateBlockDrawingBufferF0(0, 3, t, 117, 2, 6);
+
+ t = _curBlockCaps[11]->unk[_sceneDrawVar3];
+ if (t)
+ generateBlockDrawingBufferF1(20, 3, t, 117, 2, 6);
+
+ t = _curBlockCaps[8]->unk[_sceneDrawVar2];
+ if (t)
+ generateBlockDrawingBufferF0(6, 2, t, 81, 2, 8);
+
+ t = _curBlockCaps[10]->unk[_sceneDrawVar3];
+ if (t)
+ generateBlockDrawingBufferF1(14, 2, t, 81, 2, 8);
+
+ t = _curBlockCaps[8]->unk[_sceneDrawVar1];
+ if (testWllBuffer5Value(t))
+ generateBlockDrawingBufferF0(-4, 2, t, 159, 10, 8);
+
+ t = _curBlockCaps[10]->unk[_sceneDrawVar1];
+ if (testWllBuffer5Value(t))
+ generateBlockDrawingBufferF0(16, 2, t, 159, 10, 8);
+
+ t = _curBlockCaps[9]->unk[_sceneDrawVar1];
+ if (t)
+ generateBlockDrawingBufferF0(6, 2, t, 159, 10, 8);
+
+ t = _curBlockCaps[12]->unk[_sceneDrawVar2];
+ if (t)
+ generateBlockDrawingBufferF0(3, 1, t, 45, 3, 12);
+
+ t = _curBlockCaps[14]->unk[_sceneDrawVar3];
+ if (t)
+ generateBlockDrawingBufferF1(16, 1, t, 45, 3, 12);
+
+ t = _curBlockCaps[12]->unk[_sceneDrawVar1];
+ if (!(_wllBuffer5[t] & 8))
+ generateBlockDrawingBufferF0(-13, 1, t, 239, 16, 12);
+
+ t = _curBlockCaps[14]->unk[_sceneDrawVar1];
+ if (!(_wllBuffer5[t] & 8))
+ generateBlockDrawingBufferF0(19, 1, t, 239, 16, 12);
+
+ t = _curBlockCaps[13]->unk[_sceneDrawVar1];
+ if (t)
+ generateBlockDrawingBufferF0(3, 1, t, 239, 16, 12);
+
+ t = _curBlockCaps[15]->unk[_sceneDrawVar2];
+ t2 = _curBlockCaps[17]->unk[_sceneDrawVar3];
+ if (t)
+ generateBlockDrawingBufferF0(0, 0, t, 0, 3, 15);
+ if (t2)
+ generateBlockDrawingBufferF1(19, 0, t, 0, 3, 15);
+}
+
+void LoLEngine::generateBlockDrawingBufferF0(int16 wllOffset, uint8 wllIndex, uint8 wllVmpIndex, int16 vmpOffset, uint8 len, uint8 numEntries) {
+ if (!_wllVmpMap[wllVmpIndex])
+ return;
+
+ uint16 *vmp = &_vmpPtr[(_wllVmpMap[wllVmpIndex] - 1) * 431 + vmpOffset + 330];
+
+ for (int i = 0; i < numEntries; i++) {
+ uint16 *bl = &_blockDrawingBuffer[(wllIndex + i) * 22 + wllOffset];
+ for (int ii = 0; ii < len; ii++) {
+ if ((wllOffset + ii >= 0) && (wllOffset + ii < 22) && *vmp)
+ *bl = *vmp;
+ bl++;
+ vmp++;
+ }
+ }
+}
+
+void LoLEngine::generateBlockDrawingBufferF1(int16 wllOffset, uint8 wllIndex, uint8 wllVmpIndex, int16 vmpOffset, uint8 len, uint8 numEntries) {
+ if (!_wllVmpMap[wllVmpIndex])
+ return;
+
+ uint16 *vmp = &_vmpPtr[(_wllVmpMap[wllVmpIndex] - 1) * 431 + vmpOffset + 330];
+
+ for (int i = 0; i < numEntries; i++) {
+ for (int ii = 0; ii < len; ii++) {
+ if ((wllOffset + ii >= 0) && (wllOffset + ii < 22)) {
+ uint16 t = vmp[len * i + len - 1 - ii];
+ if (t) {
+ if (t & 04000)
+ t -= 0x4000;
+ else
+ t |= 0x4000;
+
+ _blockDrawingBuffer[(wllIndex + i) * 22 + wllOffset + ii] = t;
+ }
+ }
+ }
+ }
+}
+
+bool LoLEngine::testWllBuffer5Value(int index) {
+ if (!index || (_wllBuffer5[index] & 8))
+ return false;
+ return true;
+}
+
+void LoLEngine::assignBlockCaps(int a, int b) {
+ for (int i = 0; i < 18; i++) {
+ uint16 t = (a + _dscBlockIndex[b * 18 + i]) & 0x3ff;
+ _scriptExecutedFuncs[i] = t;
+
+ _curBlockCaps[i] = &_cmzBuffer[t];
+ _lvlShapeLeftRight[i] = _lvlShapeLeftRight[18 + i] = -1;
+ }
+}
+
+void LoLEngine::drawVcnBlocks(uint8 *vcnBlocks, uint16 *blockDrawingBuffer, uint8 *vcnShift, int pageNum) {
+ uint8 *d = _sceneWindowBuffer;
+
+ for (int y = 0; y < 15; y++) {
+ for (int x = 0; x < 22; x++) {
+ bool flag = false;
+ int remainder = 0;
+
+ uint16 vcnOffset = *blockDrawingBuffer++;
+
+ if (vcnOffset & 0x8000) {
+ remainder = vcnOffset - 0x8000;
+ vcnOffset = 0;
+ }
+
+ if (vcnOffset & 0x4000) {
+ flag = true;
+ vcnOffset &= 0x3fff;
+ }
+
+ if (!vcnOffset) {
+ vcnOffset = blockDrawingBuffer[329];
+ if (vcnOffset & 0x4000) {
+ flag = true;
+ vcnOffset &= 0x3fff;
+ }
+ }
+
+ uint8 shift = vcnShift[vcnOffset];
+ uint8 *src = &vcnBlocks[vcnOffset << 5];
+
+ if (flag) {
+ for (int blockY = 0; blockY < 8; blockY++) {
+ src += 3;
+ for (int blockX = 0; blockX < 4; blockX++) {
+ uint8 t = *src--;
+ *d++ = _vcnExpTable[(t & 0x0f) | shift];
+ *d++ = _vcnExpTable[(t >> 4) | shift];
+ }
+ src += 5;
+ d += 168;
+ }
+ } else {
+ for (int blockY = 0; blockY < 8; blockY++) {
+ for (int blockX = 0; blockX < 4; blockX++) {
+ uint8 t = *src++;
+ *d++ = _vcnExpTable[(t >> 4) | shift];
+ *d++ = _vcnExpTable[(t & 0x0f) | shift];
+ }
+ d += 168;
+ }
+ }
+ d -= 1400;
+
+ if (remainder) {
+ d -= 8;
+ flag = false;
+
+ if (remainder & 0x4000) {
+ remainder &= 0x3fff;
+ flag = true;
+ }
+
+ shift = vcnShift[remainder];
+ src = &vcnBlocks[remainder << 5];
+
+ if (flag) {
+ for (int blockY = 0; blockY < 8; blockY++) {
+ src += 3;
+ for (int blockX = 0; blockX < 4; blockX++) {
+ uint8 t = *src--;
+ uint8 h = _vcnExpTable[(t & 0x0f) | shift];
+ uint8 l = _vcnExpTable[(t >> 4) | shift];
+ if (h)
+ *d = h;
+ d++;
+ if (l)
+ *d = l;
+ d++;
+ }
+ src += 5;
+ d += 168;
+ }
+ } else {
+ for (int blockY = 0; blockY < 8; blockY++) {
+ for (int blockX = 0; blockX < 4; blockX++) {
+ uint8 t = *src++;
+ uint8 h = _vcnExpTable[(t >> 4) | shift];
+ uint8 l = _vcnExpTable[(t & 0x0f) | shift];
+ if (h)
+ *d = h;
+ d++;
+ if (l)
+ *d = l;
+ d++;
+ }
+ d += 168;
+ }
+ }
+ d -= 1400;
+ }
+ }
+ d += 1232;
+ }
+
+ _screen->copyBlockToPage(pageNum, 112, 0, 176, 120, _sceneWindowBuffer);
+}
+
+void LoLEngine::drawSceneShapes() {
+ for (int i = 0; i < 18; i++) {
+ uint8 t = _dscTileIndex[i];
+ uint8 s = _curBlockCaps[t]->unk[_sceneDrawVar1];
+
+ int16 x1 = 0;
+ int16 x2 = 0;
+
+ int16 dimY1 = 0;
+ int16 dimY2 = 0;
+
+ setLevelShapesDim(t, x1, x2, 13);
+
+ if (x2 <= x1)
+ continue;
+
+ drawDecorations(t);
+
+ uint16 w = _wllBuffer5[s];
+
+ if (i == 16)
+ w |= 0x80;
+
+ drawIceShapes(t, 0);
+
+ //if (_curBlockCaps[t]->itemIndex && (w & 0x80))
+ //sub_3AA55(t);
+
+ drawIceShapes(t, 1);
+
+ if (!(w & 8))
+ continue;
+
+ uint16 v = 20 * (s - _dscUnk2[s]);
+
+ scaleLevelShapesDim(t, dimY1, dimY2, 13);
+ drawDoor(_doorShapes[_dscDoorShpIndex[s]], 0, t, 10, 0, -v, 2);
+ setLevelShapesDim(t, dimY1, dimY2, 13);
+ }
+}
+
+void LoLEngine::setLevelShapesDim(int index, int16 &x1, int16 &x2, int dim) {
+ if (_lvlShapeLeftRight[index << 1] == -1) {
+ x1 = 0;
+ x2 = 22;
+
+ int16 y1 = 0;
+ int16 y2 = 120;
+
+ int m = index * 18;
+
+ for (int i = 0; i < 18; i++) {
+ uint8 d = _curBlockCaps[i]->unk[_sceneDrawVar1];
+ uint8 a = _wllBuffer5[d];
+
+ if (a & 8) {
+ int t = _dscDim2[(m + i) << 1];
+
+ if (t > x1) {
+ x1 = t;
+ if (!(a & 0x10))
+ scaleLevelShapesDim(index, y1, y2, -1);
+ }
+
+ t = _dscDim2[((m + i) << 1) + 1];
+
+ if (t < x2) {
+ x2 = t;
+ if (!(a & 0x10))
+ scaleLevelShapesDim(index, y1, y2, -1);
+ }
+ } else {
+ int t = _dscDim1[m + i];
+
+ if (!_wllVmpMap[d] || t == -40)
+ continue;
+
+ if (t == -41) {
+ x1 = 22;
+ x2 = 0;
+ break;
+ }
+
+ if (t > 0 && x2 > t)
+ x2 = t;
+
+ if (t < 0 && x1 < -t)
+ x1 = -t;
+ }
+
+ if (x2 < x1)
+ break;
+ }
+
+ x1 += 14;
+ x2 += 14;
+
+ _lvlShapeTop[index] = y1;
+ _lvlShapeBottom[index] = y2;
+ _lvlShapeLeftRight[index << 1] = x1;
+ _lvlShapeLeftRight[(index << 1) + 1] = x2;
+ } else {
+ x1 = _lvlShapeLeftRight[index << 1];
+ x2 = _lvlShapeLeftRight[(index << 1) + 1];
+ }
+
+ drawLevelModifyScreenDim(dim, x1, 0, x2, 15);
+}
+
+void LoLEngine::scaleLevelShapesDim(int index, int16 &y1, int16 &y2, int dim) {
+ static const int8 dscY1[] = { 0x1E, 0x18, 0x10, 0x00 };
+ static const int8 dscY2[] = { 0x3B, 0x47, 0x56, 0x78 };
+
+ uint8 a = _dscDimMap[index];
+
+ if (dim == -1 && a != 3)
+ a++;
+
+ y1 = dscY1[a];
+ y2 = dscY2[a];
+
+ if (dim == -1)
+ return;
+
+ const ScreenDim *cDim = _screen->getScreenDim(dim);
+
+ _screen->modifyScreenDim(dim, cDim->sx, y1, cDim->w, y2 - y1);
+}
+
+void LoLEngine::drawLevelModifyScreenDim(int dim, int16 x1, int16 y1, int16 x2, int16 y2) {
+ _screen->modifyScreenDim(dim, x1, y1 << 3, x2 - x1, (y2 - y1) << 3);
+}
+
+void LoLEngine::drawDecorations(int index) {
+ for (int i = 1; i >= 0; i--) {
+ int s = index * 2 + i;
+ uint16 scaleW = _dscShapeScaleW[s];
+ uint16 scaleH = _dscShapeScaleH[s];
+ int8 ix = _dscShapeIndex[s];
+ uint8 shpIx = ABS(ix);
+ uint8 ovlIndex = _dscShapeOvlIndex[_dscDimMap[index] * 5] + 2;
+ if (ovlIndex > 7)
+ ovlIndex = 7;
+
+ if (!scaleW || !scaleH)
+ continue;
+
+ uint8 d = (_unkPara2 + _dscUnk1[s]) & 3;
+ int8 l = _wllShapeMap[_curBlockCaps[index]->unk[d]];
+
+ uint8 *shapeData = 0;
+
+ int x = 0;
+ int y = 0;
+ int flags = 0;
+
+ while (l > 0) {
+ if ((_levelShapeProperties[l].flags & 8) && index != 3 && index != 9 && index != 13) {
+ l = _levelShapeProperties[l].next;
+ continue;
+ }
+
+ if (_dscOvlMap[shpIx] == 1 && ((_levelShapeProperties[l].flags & 2) || ((_levelShapeProperties[l].flags & 4) && _wllProcessFlag)))
+ ix = -ix;
+
+ int xOffs = 0;
+ int yOffs = 0;
+ uint8 *ovl = 0;
+
+ if (_levelShapeProperties[l].scaleFlag[shpIx] & 1) {
+ xOffs = _levelShapeProperties[l].shapeX[shpIx];
+ yOffs = _levelShapeProperties[l].shapeY[shpIx];
+ shpIx = _dscOvlMap[shpIx];
+ ovl = _screen->getLevelOverlay(ovlIndex);
+ } else if (_levelShapeProperties[l].shapeIndex[shpIx] != 0xffff) {
+ scaleW = scaleH = 0x100;
+ ovl = _screen->getLevelOverlay(7);
+ }
+
+ if (_levelShapeProperties[l].shapeIndex[shpIx] != 0xffff) {
+ shapeData = _levelShapes[_levelShapeProperties[l].shapeIndex[shpIx]];
+ if (shapeData) {
+ if (ix < 0) {
+ x = _dscShapeX[s] + xOffs + ((_levelShapeProperties[l].shapeX[shpIx] * scaleW) >> 8);
+ if (ix == _dscShapeIndex[s]) {
+ x = _dscShapeX[s] - ((_levelShapeProperties[l].shapeX[shpIx] * scaleW) >> 8) -
+ _screen->getShapeScaledWidth(shapeData, scaleW) - xOffs;
+ }
+ flags = 0x105;
+ } else {
+ x = _dscShapeX[s] + xOffs + ((_levelShapeProperties[l].shapeX[shpIx] * scaleW) >> 8);
+ flags = 0x104;
+ }
+
+ y = _dscShapeY[s] + yOffs + ((_levelShapeProperties[l].shapeY[shpIx] * scaleH) >> 8);
+ _screen->drawShape(_sceneDrawPage1, shapeData, x + 112, y, 13, flags, ovl, 1, scaleW, scaleH);
+
+ if ((_levelShapeProperties[l].flags & 1) && (shpIx >= 0) && (shpIx < 4)) {
+ //draw shadow
+ x += (_screen->getShapeScaledWidth(shapeData, scaleW));
+ flags ^= 1;
+ _screen->drawShape(_sceneDrawPage1, shapeData, x + 112, y, 13, flags, ovl, 1, scaleW, scaleH);
+ }
+ }
+ }
+
+ l = _levelShapeProperties[l].next;
+ shpIx = (_dscShapeIndex[s] < 0) ? -_dscShapeIndex[s] : _dscShapeIndex[s];
+ }
+ }
+}
+
+void LoLEngine::drawIceShapes(int index, int iceShapeIndex) {
+ uint8 f = _curBlockCaps[index]->flags;
+ if (!(f & 0xf0))
+ return;
+}
+
+void LoLEngine::drawDoor(uint8 *shape, uint8 *table, int index, int unk2, int w, int h, int flags) {
+ uint8 c = _dscDoor1[(_unkPara2 << 5) + unk2];
+ int r = (c / 5) + 5 * _dscDimMap[index];
+ uint16 d = _dscDoor2[r];
+ uint16 t = (index << 5) + c;
+
+ _shpDoorY = _dscDoorY[t] + 120;
+
+ if (flags & 1) {
+ // TODO
+ }
+
+ int u = 0;
+
+ if (flags & 2) {
+ uint8 w = _dscDimMap[index];
+ _doorScaleW = _dscDoorScaleTable[w << 1];
+ _doorScaleH = _dscDoorScaleTable[(w << 1) + 1];
+ u = _dscDoor4[w];
+ }
+
+ d += 2;
+
+ if (!_doorScaleW || !_doorScaleH)
+ return;
+
+ int s = _screen->getShapeScaledHeight(shape, _doorScaleH) >> 1;
+
+ if (w)
+ w = (w * _doorScaleW) >> 8;
+
+ if (h)
+ h = (h * _doorScaleH) >> 8;
+
+ _shpDoorX = _dscDoorX[t] + w + 200;
+ _shpDoorY = _shpDoorY + 4 - s + h - u;
+
+ if (d > 7)
+ d = 7;
+
+ uint8 *ovl = _screen->getLevelOverlay(d);
+ int doorScaledWitdh = _screen->getShapeScaledWidth(shape, _doorScaleW);
+
+ _shpDoorX -= (doorScaledWitdh >> 1);
+ _shpDoorY -= s;
+
+ drawDoorShapes(shape, table, _shpDoorX, _shpDoorY, flags, ovl);
+}
+
+void LoLEngine::drawDoorShapes(uint8 *shape, uint8 *table, int x, int y, int flags, const uint8 *ovl) {
+ int flg = 0;
+
+ if (flags & 0x10)
+ flg |= 1;
+
+ if (flags & 0x20)
+ flg |= 0x1000;
+
+ if (flags & 0x40)
+ flg |= 2;
+
+ if (flg & 0x1000) {
+ if (table)
+ _screen->drawShape(_sceneDrawPage1, shape, x, y, 13, flg | 0x9104, table, ovl, 1, _tlcTable1, _tlcTable2, _doorScaleW, _doorScaleH);
+ else
+ _screen->drawShape(_sceneDrawPage1, shape, x, y, 13, flg | 0x1104, ovl, 1, _tlcTable1, _tlcTable2, _doorScaleW, _doorScaleH);
+ } else {
+ if (table)
+ _screen->drawShape(_sceneDrawPage1, shape, x, y, 13, flg | 0x8104, table, ovl, 1, _doorScaleW, _doorScaleH);
+ else
+ _screen->drawShape(_sceneDrawPage1, shape, x, y, 13, flg | 0x104, ovl, 1, _doorScaleW, _doorScaleH);
+ }
+}
+
+void LoLEngine::drawScriptShapes(int pageNum) {
+ // TODO
+}
+
+} // end of namespace Kyra
+
diff --git a/engines/kyra/screen_lol.cpp b/engines/kyra/screen_lol.cpp
index 8e7abee545..4d78203d32 100644
--- a/engines/kyra/screen_lol.cpp
+++ b/engines/kyra/screen_lol.cpp
@@ -29,18 +29,66 @@
namespace Kyra {
Screen_LoL::Screen_LoL(LoLEngine *vm, OSystem *system) : Screen_v2(vm, system), _vm(vm) {
+ _customDimTable = new ScreenDim*[_screenDimTableCount];
+ memset(_customDimTable, 0, sizeof(ScreenDim*) * _screenDimTableCount);
+
+ _paletteOverlay1 = new uint8[0x100];
+ _paletteOverlay2 = new uint8[0x100];
+ _grayOverlay = new uint8[0x100];
+ memset(_paletteOverlay1, 0, 0x100);
+ memset(_paletteOverlay2, 0, 0x100);
+ memset(_grayOverlay, 0, 0x100);
+
+ for (int i = 0; i < 8; i++)
+ _levelOverlays[i] = new uint8[256];
+
+ _fadeFlag = 2;
+ _drawGuiFlag = 0;
+}
+
+Screen_LoL::~Screen_LoL() {
+ for (int i = 0; i < _screenDimTableCount; i++)
+ delete _customDimTable[i];
+ delete []_customDimTable;
+
+ for (int i = 0; i < 8; i++)
+ delete []_levelOverlays[i];
+
+ delete []_paletteOverlay1;
+ delete []_paletteOverlay2;
+ delete []_grayOverlay;
}
void Screen_LoL::setScreenDim(int dim) {
debugC(9, kDebugLevelScreen, "Screen_LoL::setScreenDim(%d)", dim);
assert(dim < _screenDimTableCount);
- _curDim = &_screenDimTable[dim];
+ _curDim = _customDimTable[dim] ? (const ScreenDim *)_customDimTable[dim] : &_screenDimTable[dim];
}
const ScreenDim *Screen_LoL::getScreenDim(int dim) {
debugC(9, kDebugLevelScreen, "Screen_LoL::getScreenDim(%d)", dim);
assert(dim < _screenDimTableCount);
- return &_screenDimTable[dim];
+ return _customDimTable[dim] ? (const ScreenDim *)_customDimTable[dim] : &_screenDimTable[dim];
+}
+
+void Screen_LoL::modifyScreenDim(int dim, int x, int y, int w, int h) {
+ delete _customDimTable[dim];
+ _customDimTable[dim] = new ScreenDim;
+ memcpy(_customDimTable[dim], &_screenDimTable[dim], sizeof(ScreenDim));
+ _customDimTable[dim]->sx = x;
+ _customDimTable[dim]->sy = y;
+ _customDimTable[dim]->w = w;
+ _customDimTable[dim]->h = h;
+ setScreenDim(dim);
+}
+
+void Screen_LoL::clearDim(int dim) {
+ const ScreenDim *tmp = getScreenDim(dim);
+ fillRect(tmp->sx << 3, tmp->sy, ((tmp->sx + tmp->w) << 3) - 1, (tmp->sy + tmp->h) - 1, tmp->unkA);
+}
+
+void Screen_LoL::clearCurDim() {
+ fillRect(_curDim->sx << 3, _curDim->sy, ((_curDim->sx + _curDim->w) << 3) - 1, (_curDim->sy + _curDim->h) - 1, _curDim->unkA);
}
void Screen_LoL::fprintString(const char *format, int x, int y, uint8 col1, uint8 col2, uint16 flags, ...) {
@@ -95,5 +143,178 @@ void Screen_LoL::fprintStringIntro(const char *format, int x, int y, uint8 c1, u
printText(buffer, x, y, c1, c2);
}
+void Screen_LoL::generateGrayOverlay(const uint8 *srcPal, uint8 *grayOverlay, int factor, int addR, int addG, int addB, int lastColor, bool skipSpecialColours) {
+ uint8 tmpPal[768];
+
+ for (int i = 0; i != lastColor; i++) {
+ int v = (((srcPal[3 * i] & 0x3f) * factor) / 0x40) + addR;
+ tmpPal[3 * i] = (v > 0x3f) ? 0x3f : v & 0xff;
+ v = (((srcPal[3 * i + 1] & 0x3f) * factor) / 0x40) + addG;
+ tmpPal[3 * i + 1] = (v > 0x3f) ? 0x3f : v & 0xff;
+ v = (((srcPal[3 * i + 2] & 0x3f) * factor) / 0x40) + addB;
+ tmpPal[3 * i + 2] = (v > 0x3f) ? 0x3f : v & 0xff;
+ }
+
+ for (int i = 0; i < lastColor; i++)
+ grayOverlay[i] = findLeastDifferentColor(tmpPal + 3 * i, srcPal, lastColor, skipSpecialColours);
+}
+
+uint8 *Screen_LoL::generateLevelOverlay(const uint8 *srcPal, uint8 *ovl, int opColor, int weight) {
+ if (!srcPal || !ovl)
+ return ovl;
+
+ if (weight > 255)
+ weight = 255;
+
+ uint16 r = srcPal[opColor * 3];
+ uint16 g = srcPal[opColor * 3 + 1];
+ uint16 b = srcPal[opColor * 3 + 2];
+
+ uint8 *d = ovl;
+ *d++ = 0;
+
+ for (int i = 1; i != 255; i++) {
+ uint16 a = srcPal[i * 3];
+ uint8 dr = a - ((((a - r) * (weight >> 1)) << 1) >> 8);
+ a = srcPal[i * 3 + 1];
+ uint8 dg = a - ((((a - g) * (weight >> 1)) << 1) >> 8);
+ a = srcPal[i * 3 + 2];
+ uint8 db = a - ((((a - b) * (weight >> 1)) << 1) >> 8);
+
+ int l = opColor;
+ int m = 0x7fff;
+ int ii = 127;
+ int x = 1;
+ const uint8 *s = srcPal + 3;
+
+ do {
+ if (i == x) {
+ s += 3;
+ } else {
+ int t = *s++ - dr;
+ int c = t * t;
+ t = *s++ - dg;
+ c += (t * t);
+ t = *s++ - db;
+ c += (t * t);
+
+ if (!c) {
+ l = x;
+ break;
+ }
+
+ if (c <= m) {
+ m = c;
+ l = x;
+ }
+ }
+ x++;
+ } while (--ii);
+
+ *d++ = l & 0xff;
+ }
+
+ return ovl;
+}
+
+void Screen_LoL::drawGridBox(int x, int y, int w, int h, int col) {
+ if (w <= 0 || x >= 320 || h <= 0 || y >= 200)
+ return;
+
+ if (x < 0) {
+ x += w;
+ if (x <= 0)
+ return;
+ w = x;
+ x = 0;
+ }
+
+ int tmp = x + w;
+ if (tmp >= 320) {
+ w = 320 - x;
+ }
+
+ int pitch = 320 - w;
+
+ if (y < 0) {
+ y += h;
+ if (y <= 0)
+ return;
+ h = y;
+ y = 0;
+ }
+
+ tmp = y + h;
+ if (tmp >= 200) {
+ h = 200 - y;
+ }
+
+ tmp = (y + x) & 1;
+ uint8 *p = getPagePtr(_curPage) + y * 320 + x;
+ uint8 s = (tmp >> 8) & 1;
+
+ w >>= 1;
+ int w2 = w;
+
+ while (h--) {
+ if (w) {
+ while (w--) {
+ *(p + tmp) = col;
+ p += 2;
+ }
+ } else {
+ w = 1;
+ }
+
+ if (s == 1) {
+ if (tmp == 0)
+ *p = col;
+ p++;
+ }
+ tmp ^= 1;
+ p += pitch;
+ w = w2;
+ }
+}
+
+void Screen_LoL::fadeToBlack(int delay, const UpdateFunctor *upFunc) {
+ Screen::fadeToBlack(delay, upFunc);
+ _fadeFlag = 2;
+}
+
+void Screen_LoL::setPaletteBrightness(uint8 *palette, int brightness, int modifier) {
+ generateBrightnessPalette(palette, getPalette(1), brightness, modifier);
+ fadePalette(getPalette(1), 5, 0);
+ _fadeFlag = 0;
+}
+
+void Screen_LoL::generateBrightnessPalette(uint8 *src, uint8 *dst, int brightness, int modifier) {
+ memcpy(dst, src, 0x300);
+ setPaletteColoursSpecial(dst);
+ brightness = (8 - brightness) << 5;
+ if (modifier >= 0 && modifier < 8 && _drawGuiFlag & 0x800) {
+ brightness = 256 - ((((modifier & 0xfffe) << 5) * (256 - brightness)) >> 8);
+ if (brightness < 0)
+ brightness = 0;
+ }
+
+ for (int i = 0; i < 384; i++) {
+ uint16 c = (dst[i] * brightness) >> 8;
+ dst[i] = c & 0xff;
+ }
+}
+
+void Screen_LoL::setPaletteColoursSpecial(uint8 *palette) {
+ const uint8 src[] = { 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00 };
+ palette += 0x240;
+ memcpy(palette, src, 12);
+}
+
+uint8 Screen_LoL::getShapePaletteSize(const uint8 *shp) {
+ debugC(9, kDebugLevelScreen, "Screen_LoL::getShapePaletteSize(%p)", (const void *)shp);
+
+ return shp[10];
+}
+
} // end of namespace Kyra
diff --git a/engines/kyra/screen_lol.h b/engines/kyra/screen_lol.h
index bba748813a..a4c7d8c749 100644
--- a/engines/kyra/screen_lol.h
+++ b/engines/kyra/screen_lol.h
@@ -35,17 +35,46 @@ class LoLEngine;
class Screen_LoL : public Screen_v2 {
public:
Screen_LoL(LoLEngine *vm, OSystem *system);
+ ~Screen_LoL();
void setScreenDim(int dim);
const ScreenDim *getScreenDim(int dim);
+ void modifyScreenDim(int dim, int x, int y, int w, int h);
+ void clearDim(int dim);
+ void clearCurDim();
void fprintString(const char *format, int x, int y, uint8 col1, uint8 col2, uint16 flags, ...);
void fprintStringIntro(const char *format, int x, int y, uint8 c1, uint8 c2, uint8 c3, uint16 flags, ...);
+
+ void drawGridBox(int x, int y, int w, int h, int col);
+
+ void fadeToBlack(int delay=0x54, const UpdateFunctor *upFunc = 0);
+ void setPaletteBrightness(uint8 *palDst, int brightness, int modifier);
+ void generateBrightnessPalette(uint8 *palSrc, uint8 *palDst, int brightness, int modifier);
+ void setPaletteColoursSpecial(uint8 *palette);
+
+ void generateGrayOverlay(const uint8 *srcPal, uint8 *grayOverlay, int factor, int addR, int addG, int addB, int lastColor, bool skipSpecialColours);
+ uint8 *generateLevelOverlay(const uint8 *srcPal, uint8 *ovl, int opColor, int weight);
+
+ uint8 *getLevelOverlay(int index) { return _levelOverlays[index]; }
+
+ uint8 getShapePaletteSize(const uint8 *shp);
+
+ uint8 *_paletteOverlay1;
+ uint8 *_paletteOverlay2;
+ uint8 *_grayOverlay;
+ int _fadeFlag;
+ int _drawGuiFlag;
+
private:
LoLEngine *_vm;
static const ScreenDim _screenDimTable[];
static const int _screenDimTableCount;
+
+ ScreenDim **_customDimTable;
+
+ uint8 *_levelOverlays[8];
};
} // end of namespace Kyra
diff --git a/engines/kyra/screen_v2.cpp b/engines/kyra/screen_v2.cpp
index b2952ee113..ff8d228c56 100644
--- a/engines/kyra/screen_v2.cpp
+++ b/engines/kyra/screen_v2.cpp
@@ -90,11 +90,14 @@ void Screen_v2::applyOverlay(int x, int y, int w, int h, int pageNum, const uint
}
}
-int Screen_v2::findLeastDifferentColor(const uint8 *paletteEntry, const uint8 *palette, uint16 numColors) {
+int Screen_v2::findLeastDifferentColor(const uint8 *paletteEntry, const uint8 *palette, uint16 numColors, bool skipSpecialColours) {
int m = 0x7fff;
int r = 0x101;
for (int i = 0; i < numColors; i++) {
+ if (skipSpecialColours && i >= 0xc0 && i <= 0xc3)
+ continue;
+
int v = paletteEntry[0] - *palette++;
int c = v * v;
v = paletteEntry[1] - *palette++;
diff --git a/engines/kyra/screen_v2.h b/engines/kyra/screen_v2.h
index d95bff35d1..dd001da731 100644
--- a/engines/kyra/screen_v2.h
+++ b/engines/kyra/screen_v2.h
@@ -45,7 +45,7 @@ public:
// palette handling
uint8 *generateOverlay(const uint8 *palette, uint8 *buffer, int color, uint16 factor);
void applyOverlay(int x, int y, int w, int h, int pageNum, const uint8 *overlay);
- int findLeastDifferentColor(const uint8 *paletteEntry, const uint8 *palette, uint16 numColors);
+ int findLeastDifferentColor(const uint8 *paletteEntry, const uint8 *palette, uint16 numColors, bool skipSpecialColours = false);
virtual void getFadeParams(const uint8 *palette, int delay, int &delayInc, int &diff);
diff --git a/engines/kyra/script.h b/engines/kyra/script.h
index 6e08017974..ae9ece8154 100644
--- a/engines/kyra/script.h
+++ b/engines/kyra/script.h
@@ -53,7 +53,7 @@ struct EMCState {
uint16 bp;
uint16 sp;
int16 regs[30]; // VM registers
- int16 stack[61]; // VM stack
+ int16 stack[100]; // VM stack
};
#define stackPos(x) (script->stack[script->sp+x])
diff --git a/engines/kyra/script_lol.cpp b/engines/kyra/script_lol.cpp
new file mode 100644
index 0000000000..488ec54d14
--- /dev/null
+++ b/engines/kyra/script_lol.cpp
@@ -0,0 +1,450 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "kyra/lol.h"
+#include "kyra/screen_lol.h"
+
+#include "common/endian.h"
+
+namespace Kyra {
+
+void LoLEngine::runInitScript(const char *filename, int func) {
+ EMCData scriptData;
+ EMCState scriptState;
+ memset(&scriptData, 0, sizeof(EMCData));
+ _emc->load(filename, &scriptData, &_opcodes);
+
+ _emc->init(&scriptState, &scriptData);
+ _emc->start(&scriptState, 0);
+ while (_emc->isValid(&scriptState))
+ _emc->run(&scriptState);
+
+ if (func) {
+ _emc->init(&scriptState, &scriptData);
+ _emc->start(&scriptState, func);
+ while (_emc->isValid(&scriptState))
+ _emc->run(&scriptState);
+ }
+
+ _emc->unload(&scriptData);
+}
+
+void LoLEngine::runInfScript(const char *filename) {
+ _emc->load(filename, &_scriptData, &_opcodes);
+ runResidentScript(0x400, -1);
+}
+
+void LoLEngine::runResidentScript(int func, int reg0) {
+ runResidentScriptCustom(func, reg0, -1, 0, 0, 0);
+}
+
+void LoLEngine::runResidentScriptCustom(int func, int reg0, int reg1, int reg2, int reg3, int reg4) {
+ EMCState scriptState;
+ memset(&scriptState, 0, sizeof(EMCState));
+
+ if (!_scriptBoolSkipExec) {
+ _emc->init(&scriptState, &_scriptData);
+ _emc->start(&scriptState, func);
+
+ scriptState.regs[0] = reg0;
+ scriptState.regs[1] = reg1;
+ scriptState.regs[2] = reg2;
+ scriptState.regs[3] = reg3;
+ scriptState.regs[4] = reg4;
+ scriptState.regs[5] = func;
+ scriptState.regs[6] = _unkScriptByte;
+
+ while (_emc->isValid(&scriptState))
+ _emc->run(&scriptState);
+ }
+
+ checkScriptUnk(func);
+}
+
+bool LoLEngine::checkScriptUnk(int func) {
+ if (_boolScriptFuncDone)
+ return true;
+
+ for (int i = 0; i < 15; i++) {
+ if (_scriptExecutedFuncs[i] == func) {
+ _boolScriptFuncDone = true;
+ return true;
+ }
+ }
+
+ if (_currentBlock == func){
+ _boolScriptFuncDone = true;
+ return true;
+ }
+
+ return false;
+}
+
+int LoLEngine::o2_setGameFlag(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::o2_setGameFlag(%p) (%d)", (const void *)script, stackPos(0));
+ if (stackPos(1))
+ _gameFlags[stackPos(0) >> 4] |= (1 << (stackPos(0) & 0x0f));
+ else
+ _gameFlags[stackPos(0) >> 4] &= (~(1 << (stackPos(0) & 0x0f)));
+
+ return 1;
+}
+
+int LoLEngine::o2_testGameFlag(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::o2_testGameFlag(%p) (%d)", (const void *)script, stackPos(0));
+ if (!stackPos(0))
+ return 0;
+
+ if (_gameFlags[stackPos(0) >> 4] & (1 << (stackPos(0) & 0x0f)))
+ return 1;
+
+ return 0;
+}
+
+int LoLEngine::o2_loadLevelSupplemenaryFiles(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::o2_loadLevelSupplemenaryFiles(%p) (%d)", (const void *)script, stackPos(0));
+ loadLevelSupplemenaryFiles(stackPosString(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), (stackPos(5) == -1) ? 0 : stackPosString(5));
+ return 1;
+}
+
+int LoLEngine::o2_loadCmzFile(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::o2_loadCmzFile(%p) (%d)", (const void *)script, stackPos(0));
+ loadCmzFile(stackPosString(0));
+ return 1;
+}
+
+int LoLEngine::o2_loadMonsterShapes(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::o2_loadMonsterShapes(%p) (%d)", (const void *)script, stackPos(0));
+ loadMonsterShapes(stackPosString(0), stackPos(1), stackPos(2));
+ return 1;
+}
+
+int LoLEngine::o2_allocItemPropertiesBuffer(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::o2_allocItemPropertiesBuffer(%p) (%d)", (const void *)script, stackPos(0));
+ delete []_itemProperties;
+ _itemProperties = new ItemProperty[stackPos(0)];
+ return 1;
+}
+
+int LoLEngine::o2_setItemProperty(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::o2_setItemProperty(%p) (%d)", (const void *)script, stackPos(0));
+ ItemProperty *tmp = &_itemProperties[stackPos(0)];
+
+ tmp->nameStringId = stackPos(1);
+ tmp->shpIndex = stackPos(2);
+ tmp->unk5 = stackPos(3);
+ tmp->itemScriptFunc = stackPos(4);
+ tmp->unk8 = stackPos(5);
+ tmp->unk9 = stackPos(6);
+ tmp->unkA = stackPos(7);
+ tmp->flags = stackPos(8);
+ tmp->unkB = stackPos(9);
+ return 1;
+}
+
+int LoLEngine::o2_makeItem(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::o2_makeItem(%p) (%d)", (const void *)script, stackPos(0));
+ return makeItem(stackPos(0), stackPos(1), stackPos(2));
+}
+
+int LoLEngine::o2_getItemPara(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::o2_getItemPara(%p) (%d)", (const void *)script, stackPos(0));
+ if(!stackPos(0))
+ return 0;
+
+ ItemInPlay *i = &_itemsInPlay[stackPos(0)];
+ ItemProperty *p = &_itemProperties[i->itemPropertyIndex];
+
+ switch(stackPos(1)) {
+ case 0:
+ return i->cmzIndex;
+ case 1:
+ return i->unk7;
+ case 2:
+ return i->anonymous_4;
+ case 3:
+ return i->level;
+ case 4:
+ return i->itemPropertyIndex;
+ case 5:
+ return i->shpCurFrame_flg;
+ case 6:
+ return p->nameStringId;
+ case 7:
+ break;
+ case 8:
+ return p->shpIndex;
+ case 9:
+ return p->unk5;
+ case 10:
+ return p->itemScriptFunc;
+ case 11:
+ case 12:
+ case 13:
+ return p[stackPos(1)].unkB & 0x0f;
+ case 14:
+ return p->unkB;
+ case 15:
+ return i->shpCurFrame_flg & 0x1fff;
+ case 16:
+ return p->flags;
+ case 17:
+ return (p->unk9 << 8) | p->unk8;
+ default:
+ break;
+ }
+
+ return -1;
+}
+
+int LoLEngine::o2_getCharacterStat(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::o2_getCharacterStat(%p) (%d)", (const void *)script, stackPos(0));
+ LoLCharacter *c = &_characters[stackPos(0)];
+ int d = stackPos(2);
+
+ switch(stackPos(1)) {
+ case 0:
+ return c->flags;
+ case 1:
+ return c->raceClassSex;
+ case 2:
+ case 3:
+ case 4:
+ default:
+ break;
+ case 5:
+ return c->hitPointsCur;
+ case 6:
+ return c->hitPointsMax;
+ case 7:
+ return c->magicPointsCur;
+ case 8:
+ return c->magicPointsMax;
+ case 9:
+ return c->field_37;
+ case 10:
+ return c->items[d];
+ case 11:
+ return c->field_66[d] + c->field_69[d];
+ case 12:
+ return c->field_27[d];
+ case 13:
+ return (d & 0x80) ? c->field_25 : c->field_17[d];
+ case 14:
+ return c->field_69[d];
+ case 15:
+ return c->id;
+ }
+
+ return 0;
+}
+
+int LoLEngine::o2_setCharacterStat(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::o2_setCharacterStat(%p) (%d)", (const void *)script, stackPos(0));
+ LoLCharacter *c = &_characters[stackPos(0)];
+ int d = stackPos(2);
+ int e = stackPos(3);
+
+ switch(stackPos(1)) {
+ case 0:
+ c->flags = e;
+ case 1:
+ c->raceClassSex = e & 0x0f;
+ case 2:
+ case 3:
+ case 4:
+ default:
+ break;
+ case 5:
+ //// TODO
+ break;
+ case 6:
+ c->hitPointsMax = e;
+ case 7:
+ //// TODO
+ break;
+ case 8:
+ c->magicPointsMax = e;
+ case 9:
+ c->field_37 = e;
+ case 10:
+ c->items[d] = 0;
+ case 11:
+ c->field_66[d] = e;
+ case 12:
+ c->field_27[d] = e;
+ case 13:
+ if (d & 0x80)
+ c->field_25 = e;
+ else
+ c->field_17[d] = e;
+ case 14:
+ c->field_69[d] = e;
+ }
+
+ return 0;
+}
+
+int LoLEngine::o2_loadLevelShapes(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::o2_loadLevelShapes(%p) (%d)", (const void *)script, stackPos(0));
+ loadLevelShpDat(stackPosString(0), stackPosString(1), true);
+ return 1;
+}
+
+int LoLEngine::o2_closeLevelShapeFile(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::o2_closeLevelShapeFile(%p) (%d)", (const void *)script, stackPos(0));
+ delete _lvlShpFileHandle;
+ _lvlShpFileHandle = 0;
+ return 1;
+}
+
+int LoLEngine::o2_loadDoorShapes(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::o2_loadDoorShapes(%p) (%d)", (const void *)script, stackPos(0));
+ _screen->loadBitmap(stackPosString(0), 3, 3, 0);
+ const uint8 *p = _screen->getCPagePtr(2);
+ if (_doorShapes[0])
+ delete []_doorShapes[0];
+ _doorShapes[0] = _screen->makeShapeCopy(p, stackPos(1));
+ if (_doorShapes[1])
+ delete []_doorShapes[1];
+ _doorShapes[1] = _screen->makeShapeCopy(p, stackPos(2));
+
+ for (int i = 0; i < 20; i++) {
+ _wllBuffer5[i + 3] |= 7;
+ int t = i % 5;
+ if (t == 4)
+ _wllBuffer5[i + 3] &= 0xf8;
+ if (t == 3)
+ _wllBuffer5[i + 3] &= 0xfd;
+ }
+
+ if (stackPos(3)) {
+ for (int i = 3; i < 13; i++)
+ _wllBuffer5[i] &= 0xfd;
+ }
+
+ if (stackPos(4)) {
+ for (int i = 13; i < 23; i++)
+ _wllBuffer5[i] &= 0xfd;
+ }
+
+ return 1;
+}
+
+int LoLEngine::o2_setGlobalVar(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::o2_setGlobalVar(%p) (%d)", (const void *)script, stackPos(0));
+ //uint16 a = stackPos(1);
+ uint16 b = stackPos(2);
+
+ switch (stackPos(0)) {
+ case 0:
+ _currentBlock = b;
+ setLF1(_unkCmzU1, _unkCmzU2, _currentBlock, 0x80, 0x80);
+ setLF2(_currentBlock);
+ break;
+ case 1:
+ _unkPara2 = b;
+ break;
+ case 2:
+ _currentLevel = b & 0xff;
+ break;
+ case 3:
+ break;
+ case 4:
+ _brightness = b & 0xff;
+ break;
+ case 5:
+ _credits = b;
+ break;
+ case 6:
+ //TODO
+ break;
+ case 7:
+ break;
+ case 8:
+ _charFlagUnk = b;
+ //TODO
+ break;
+ case 9:
+ _lampStatusUnk = b & 0xff;
+ break;
+ case 10:
+ _loadLevelFlag2 = b & 0xff;
+ //TODO
+ break;
+ case 11:
+ //TODO
+ break;
+ case 12:
+ //TODO
+ break;
+ default:
+ break;
+ }
+
+ return 1;
+}
+
+int LoLEngine::o2_mapShapeToBlock(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::o2_mapShapeToBlock(%p) (%d)", (const void *)script, stackPos(0));
+ return assignLevelShapes(stackPos(0));
+}
+
+int LoLEngine::o2_resetBlockShapeAssignment(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::o2_resetBlockShapeAssignment(%p) (%d)", (const void *)script, stackPos(0));
+ uint8 v = stackPos(0) & 0xff;
+ memset(_wllShapeMap + 3, v, 5);
+ memset(_wllShapeMap + 13, v, 5);
+ return 1;
+}
+
+int LoLEngine::o2_setPaletteBrightness(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::o2_setPaletteBrightness(%p) (%d)", (const void *)script, stackPos(0));
+ uint16 old = _brightness;
+ _brightness = stackPos(0);
+ if (stackPos(1) == 1)
+ _screen->setPaletteBrightness(_screen->_currentPalette, stackPos(0), _lampOilStatus);
+ return old;
+}
+
+int LoLEngine::o2_assignCustomSfx(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::o2_assignCustomSfx(%p) (%d)", (const void *)script, stackPos(0));
+ const char *c = stackPosString(0);
+ int i = stackPos(1);
+
+ if (!c || i > 250)
+ return 0;
+
+ if (_ingameSoundIndex[i] == 0xffff)
+ return 0;
+
+ strcpy(_ingameSoundList[_ingameSoundIndex[i]], c);
+
+ return 0;
+}
+
+} // end of namespace Kyra
+
+
diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp
index f97f5c808a..8882bed10c 100644
--- a/engines/kyra/staticres.cpp
+++ b/engines/kyra/staticres.cpp
@@ -43,7 +43,7 @@
namespace Kyra {
-#define RESFILE_VERSION 32
+#define RESFILE_VERSION 33
namespace {
bool checkKyraDat(Common::SeekableReadStream *file) {
@@ -221,6 +221,11 @@ bool StaticResource::init() {
{ k2ShpAnimDataV1, proc(loadShapeAnimData_v1), proc(freeHofShapeAnimDataV1) },
{ k2ShpAnimDataV2, proc(loadShapeAnimData_v2), proc(freeHofShapeAnimDataV2) },
+ { lolCharData, proc(loadCharData), proc(freeCharData) },
+ { lolSpellData, proc(loadSpellData), proc(freeSpellData) },
+ { lolCompassData, proc(loadCompassData), proc(freeCompassData) },
+ { lolRawDataBe16, proc(loadRawDataBe16), proc(freeRawDataBe16) },
+
{ 0, 0, 0 }
};
#undef proc
@@ -361,6 +366,42 @@ bool StaticResource::init() {
{ k2SeqplaySfxFiles, kStringList, "S_SFXFILES.TXT" },
{ k2SeqplaySeqData, k2SeqData, "S_DATA.SEQ" },
{ k2SeqplayIntroTracks, kStringList, "S_INTRO.TRA" },
+
+ // Ingame
+ { lolCharacterDefs, lolCharData, "CHARACTER.DEF" },
+ { lolIngameSfxFiles, kStringList, "SFXFILES.TRA" },
+ { lolIngameSfxIndex, kRawData, "SFXINDEX.MAP" },
+ { lolIngameGMSfxIndex, kRawData, "SFX_GM.MAP" },
+ { lolIngameMT32SfxIndex, kRawData, "SFX_MT32.MAP" },
+ { lolSpellProperties, lolSpellData, "SPELLS.DEF" },
+ { lolGameShapeMap, kRawData, "GAMESHP.MAP" },
+ { lolLevelShpList, kStringList, "SHPFILES.TXT" },
+ { lolLevelDatList, kStringList, "DATFILES.TXT" },
+ { lolCompassDefs, lolCompassData, "COMPASS.DEF" },
+
+ { lolDscUnk1, kRawData, "DSCSHPU1.DEF" },
+ { lolDscShapeIndex, kRawData, "DSCSHPI1.DEF" },
+ { lolDscOvlMap, kRawData, "DSCSHPI2.DEF" },
+ { lolDscScaleWidthData, lolRawDataBe16, "DSCSHPW.DEF" },
+ { lolDscScaleHeightData, lolRawDataBe16, "DSCSHPH.DEF" },
+ { lolDscX, lolRawDataBe16, "DSCSHPX.DEF" },
+ { lolDscY, kRawData, "DSCSHPY.DEF" },
+ { lolDscTileIndex, kRawData, "DSCSHPT.DEF" },
+ { lolDscUnk2, kRawData, "DSCSHPU2.DEF" },
+ { lolDscDoorShapeIndex, kRawData, "DSCDOOR.DEF" },
+ { lolDscDimData1, kRawData, "DSCDIM1.DEF" },
+ { lolDscDimData2, kRawData, "DSCDIM2.DEF" },
+ { lolDscBlockMap, kRawData, "DSCBLOCK1.DEF" },
+ { lolDscDimMap, kRawData, "DSCDIM.DEF" },
+ { lolDscDoorScale, lolRawDataBe16, "DSCDOOR3.DEF" },
+ { lolDscDoor2, kRawData, "DSCDOOR2.DEF" },
+ { lolDscDoor4, lolRawDataBe16, "DSCDOOR4.DEF" },
+ { lolDscOvlIndex, kRawData, "DSCBLOCK2.DEF" },
+ { lolDscBlockIndex, kRawData, "DSCBLOCKX.DEF" },
+ { lolDscDoor1, kRawData, "DSCDOOR1.DEF" },
+ { lolDscDoorX, lolRawDataBe16, "DSCDOORX.DEF" },
+ { lolDscDoorY, lolRawDataBe16, "DSCDOORY.DEF" },
+
{ 0, 0, 0 }
};
@@ -374,7 +415,7 @@ bool StaticResource::init() {
_builtIn = 0;
_filenameTable = kyra3StaticRes;
} else if (_vm->game() == GI_LOL) {
- if (!_vm->gameFlags().isDemo)
+ if (!_vm->gameFlags().isDemo && !_vm->gameFlags().isTalkie)
return true;
_builtIn = 0;
_filenameTable = lolStaticRes;
@@ -424,6 +465,22 @@ const ItemAnimData_v2 *StaticResource::loadShapeAnimData_v2(int id, int &entries
return (const ItemAnimData_v2*)getData(id, k2ShpAnimDataV2, entries);
}
+const LoLCharacter *StaticResource::loadCharData(int id, int &entries) {
+ return (const LoLCharacter*)getData(id, lolCharData, entries);
+}
+
+const SpellProperty *StaticResource::loadSpellData(int id, int &entries) {
+ return (const SpellProperty*)getData(id, lolSpellData, entries);
+}
+
+const CompassDef *StaticResource::loadCompassData(int id, int &entries) {
+ return (const CompassDef*)getData(id, lolCompassData, entries);
+}
+
+const uint16 *StaticResource::loadRawDataBe16(int id, int &entries) {
+ return (const uint16*)getData(id, lolRawDataBe16, entries);
+}
+
bool StaticResource::prefetchId(int id) {
if (id == -1) {
for (int i = 0; _filenameTable[i].filename; ++i)
@@ -852,6 +909,144 @@ bool StaticResource::loadShapeAnimData_v2(const char *filename, void *&ptr, int
return true;
}
+bool StaticResource::loadCharData(const char *filename, void *&ptr, int &size) {
+ Common::SeekableReadStream *file = getFile(filename);
+
+ if (!file)
+ return false;
+
+ size = file->size() / 130;
+ LoLCharacter *charData = new LoLCharacter[size];
+
+ for (int i = 0; i < size; i++) {
+ LoLCharacter *t = &charData[i];
+
+ t->flags = file->readUint16LE();
+ file->read(t->name, 11);
+ t->raceClassSex = file->readByte();
+ t->id = file->readSint16LE();
+ t->curFaceFrame = file->readByte();
+ t->nextFaceFrame = file->readByte();
+ t->field_12 = file->readUint16LE();
+ t->field_14 = file->readUint16LE();
+ t->field_16 = file->readByte();
+ for (int ii = 0; ii < 5; ii++)
+ t->field_17[ii] = file->readUint16LE();
+ t->field_21 = file->readUint16LE();
+ t->field_23 = file->readUint16LE();
+ t->field_25 = file->readUint16LE();
+ for (int ii = 0; ii < 2; ii++)
+ t->field_27[ii] = file->readUint16LE();
+ t->field_2B = file->readByte();
+ t->field_2C = file->readUint16LE();
+ t->field_2E = file->readUint16LE();
+ t->field_30 = file->readUint16LE();
+ t->field_32 = file->readUint16LE();
+ t->field_34 = file->readUint16LE();
+ t->field_36 = file->readByte();
+ t->field_37 = file->readUint16LE();
+ t->hitPointsCur = file->readUint16LE();;
+ t->hitPointsMax = file->readUint16LE();;
+ t->magicPointsCur = file->readUint16LE();;
+ t->magicPointsMax = file->readUint16LE();;
+ t->field_41 = file->readByte();
+ t->damageSuffered = file->readUint16LE();
+ t->weaponHit = file->readUint16LE();
+ t->field_46 = file->readUint16LE();
+ t->field_48 = file->readUint16LE();
+ t->field_4A = file->readUint16LE();
+ t->field_4C = file->readUint16LE();
+ t->rand = file->readUint16LE();
+ for (int ii = 0; ii < 11; ii++)
+ t->items[ii] = file->readUint16LE();
+ for (int ii = 0; ii < 3; ii++)
+ t->field_66[ii] = file->readByte();
+ for (int ii = 0; ii < 3; ii++)
+ t->field_69[ii] = file->readByte();
+ t->field_6C = file->readByte();
+ t->field_6D = file->readByte();
+ t->field_6E = file->readUint16LE();
+ t->field_70 = file->readUint16LE();
+ t->field_72 = file->readUint16LE();
+ t->field_74 = file->readUint16LE();
+ t->field_76 = file->readUint16LE();
+ for (int ii = 0; ii < 5; ii++)
+ t->arrayUnk2[ii] = file->readByte();
+ for (int ii = 0; ii < 5; ii++)
+ t->arrayUnk1[ii] = file->readByte();
+ };
+
+ ptr = charData;
+
+ return true;
+}
+
+bool StaticResource::loadSpellData(const char *filename, void *&ptr, int &size) {
+ Common::SeekableReadStream *file = getFile(filename);
+
+ if (!file)
+ return false;
+
+ size = file->size() / 28;
+ SpellProperty *spellData = new SpellProperty[size];
+
+ for (int i = 0; i < size; i++) {
+ SpellProperty *t = &spellData[i];
+
+ t->field_0 = file->readUint16LE();
+ for (int ii = 0; ii < 4; ii++)
+ t->unkArr[ii] = file->readUint16LE();
+ t->field_A = file->readUint16LE();
+ t->field_C = file->readUint16LE();
+ t->field_E = file->readUint16LE();
+ t->spellNameCode = file->readUint16LE();
+ for (int ii = 0; ii < 4; ii++)
+ t->mpRequired[ii] = file->readUint16LE();
+ t->field_1A = file->readUint16LE();
+ };
+
+ ptr = spellData;
+
+ return true;
+}
+
+bool StaticResource::loadCompassData(const char *filename, void *&ptr, int &size) {
+ Common::SeekableReadStream *file = getFile(filename);
+
+ if (!file)
+ return false;
+
+ size = file->size() / 4;
+ CompassDef *defs = new CompassDef[size];
+
+ for (int i = 0; i < size; i++) {
+ CompassDef *t = &defs[i];
+ t->shapeIndex = file->readByte();
+ t->x = file->readByte();
+ t->y = file->readByte();
+ t->flags = file->readByte();
+ };
+
+ ptr = defs;
+
+ return true;
+}
+
+bool StaticResource::loadRawDataBe16(const char *filename, void *&ptr, int &size) {
+ Common::SeekableReadStream *file = getFile(filename);
+
+ size = file->size() >> 1;
+
+ uint16 *r = new uint16[size];
+
+ for (int i = 0; i < size; i++)
+ r[i] = file->readUint16BE();
+
+ ptr = r;
+
+ return true;
+}
+
void StaticResource::freeRawData(void *&ptr, int &size) {
uint8 *data = (uint8*)ptr;
delete[] data;
@@ -920,6 +1115,34 @@ void StaticResource::freeHofShapeAnimDataV2(void *&ptr, int &size) {
size = 0;
}
+void StaticResource::freeCharData(void *&ptr, int &size) {
+ LoLCharacter *d = (LoLCharacter *)ptr;
+ delete[] d;
+ ptr = 0;
+ size = 0;
+}
+
+void StaticResource::freeSpellData(void *&ptr, int &size) {
+ SpellProperty *d = (SpellProperty *)ptr;
+ delete[] d;
+ ptr = 0;
+ size = 0;
+}
+
+void StaticResource::freeCompassData(void *&ptr, int &size) {
+ CompassDef *d = (CompassDef *)ptr;
+ delete[] d;
+ ptr = 0;
+ size = 0;
+}
+
+void StaticResource::freeRawDataBe16(void *&ptr, int &size) {
+ uint16 *data = (uint16*)ptr;
+ delete[] data;
+ ptr = 0;
+ size = 0;
+}
+
void StaticResource::freePaletteTable(void *&ptr, int &size) {
uint8 **data = (uint8**)ptr;
while (size--)
@@ -1403,6 +1626,49 @@ void KyraEngine_MR::initStaticResource() {
_itemStringMap = _staticres->loadRawData(k3ItemStringMap, _itemStringMapSize);
}
+void LoLEngine::initStaticResource() {
+ _charDefaults = _staticres->loadCharData(lolCharacterDefs, _charDefaultsSize);
+ _ingameSoundIndex = (const uint16 *)_staticres->loadRawData(lolIngameSfxIndex, _ingameSoundIndexSize);
+ _ingameGMSoundIndex = _staticres->loadRawData(lolIngameGMSfxIndex, _ingameGMSoundIndexSize);
+ _ingameMT32SoundIndex = _staticres->loadRawData(lolIngameMT32SfxIndex, _ingameMT32SoundIndexSize);
+ _spellProperties = _staticres->loadSpellData(lolSpellProperties, _spellPropertiesSize);
+ _gameShapeMap = (const int8*)_staticres->loadRawData(lolGameShapeMap, _gameShapeMapSize);
+ _levelShpList = _staticres->loadStrings(lolLevelShpList, _levelShpListSize);
+ _levelDatList = _staticres->loadStrings(lolLevelDatList, _levelDatListSize);
+ _compassDefs = _staticres->loadCompassData(lolCompassDefs, _compassDefsSize);
+
+ _dscUnk1 = (const int8*)_staticres->loadRawData(lolDscUnk1, _dscUnk1Size);
+ _dscShapeIndex = (const int8*)_staticres->loadRawData(lolDscShapeIndex, _dscShapeIndexSize);
+ _dscOvlMap = _staticres->loadRawData(lolDscOvlMap, _dscOvlMapSize);
+ _dscShapeScaleW = (const uint16 *)_staticres->loadRawDataBe16(lolDscScaleWidthData, _dscShapeScaleWSize);
+ _dscShapeScaleH = (const uint16 *)_staticres->loadRawDataBe16(lolDscScaleHeightData, _dscShapeScaleHSize);
+ _dscShapeX = (const int16 *)_staticres->loadRawDataBe16(lolDscX, _dscShapeXSize);
+ _dscShapeY = (const int8 *)_staticres->loadRawData(lolDscY, _dscShapeYSize);
+ _dscTileIndex = _staticres->loadRawData(lolDscTileIndex, _dscTileIndexSize);
+ _dscUnk2 = _staticres->loadRawData(lolDscUnk2, _dscUnk2Size);
+ _dscDoorShpIndex = _staticres->loadRawData(lolDscDoorShapeIndex, _dscDoorShpIndexSize);
+ _dscDim1 = (const int8 *)_staticres->loadRawData(lolDscDimData1, _dscDim1Size);
+ _dscDim2 = (const int8 *)_staticres->loadRawData(lolDscDimData2, _dscDim2Size);
+ _dscBlockMap = _staticres->loadRawData(lolDscBlockMap, _dscBlockMapSize);
+ _dscDimMap = _staticres->loadRawData(lolDscDimMap, _dscDimMapSize);
+ _dscDoorScaleTable = (const uint16 *)_staticres->loadRawDataBe16(lolDscDoorScale, _dscDoorScaleTableSize);
+ _dscDoor2 = _staticres->loadRawData(lolDscDoor2, _dscDoor2Size);
+ _dscShapeOvlIndex = _staticres->loadRawData(lolDscOvlIndex, _dscShapeOvlIndexSize);
+ _dscDoor4 = (const uint16 *)_staticres->loadRawDataBe16(lolDscDoor4, _dscDoor4Size);
+ _dscBlockIndex = (const int8 *)_staticres->loadRawData(lolDscBlockIndex, _dscBlockIndexSize);
+ _dscDoor1 = _staticres->loadRawData(lolDscDoor1, _dscDoor1Size);
+ _dscDoorX = (const int16 *)_staticres->loadRawDataBe16(lolDscDoorX, _dscDoorXSize);
+ _dscDoorY = (const int16 *)_staticres->loadRawDataBe16(lolDscDoorY, _dscDoorYSize);
+
+ const char *const *tmpSndList = _staticres->loadStrings(lolIngameSfxFiles, _ingameSoundListSize);
+ _ingameSoundList = new char*[_ingameSoundListSize];
+ for (int i = 0; i < _ingameSoundListSize; i++) {
+ _ingameSoundList[i] = new char[strlen(tmpSndList[i]) + 1];
+ strcpy(_ingameSoundList[i], tmpSndList[i]);
+ }
+ _staticres->unloadId(lolIngameSfxFiles);
+}
+
const ScreenDim Screen_LoK::_screenDimTable[] = {
{ 0x00, 0x00, 0x28, 0xC8, 0x0F, 0x0C, 0x00, 0x00 },
{ 0x08, 0x48, 0x18, 0x38, 0x0F, 0x0C, 0x00, 0x00 },
diff --git a/tools/create_kyradat/create_kyradat.cpp b/tools/create_kyradat/create_kyradat.cpp
index 456da29fa0..51524e57a0 100644
--- a/tools/create_kyradat/create_kyradat.cpp
+++ b/tools/create_kyradat/create_kyradat.cpp
@@ -31,7 +31,7 @@
#include "md5.h"
enum {
- kKyraDatVersion = 32,
+ kKyraDatVersion = 33,
kIndexSize = 12
};
@@ -53,6 +53,7 @@ enum {
#include "malcolm.h"
+#include "lol_cd.h"
#include "lol_demo.h"
const Game kyra1FanTranslations[] = {
@@ -72,6 +73,7 @@ bool extractStringsWoSuffix(PAKFile &out, const Game *g, const byte *data, const
bool extractPaddedStrings(PAKFile &out, const Game *g, const byte *data, const uint32 size, const char *filename, int fmtPatch = 0);
bool extractRaw16to8(PAKFile &out, const Game *g, const byte *data, const uint32 size, const char *filename, int fmtPatch = 0);
bool extractMrShapeAnimData(PAKFile &out, const Game *g, const byte *data, const uint32 size, const char *filename, int fmtPatch = 0);
+bool extractRaw16(PAKFile &out, const Game *g, const byte *data, const uint32 size, const char *filename, int fmtPatch = 0);
int extractHofSeqData_checkString(const void *ptr, uint8 checkSize);
int extractHofSeqData_isSequence(const void *ptr, const Game *g, uint32 maxCheckSize);
@@ -96,6 +98,8 @@ const ExtractType extractTypeTable[] = {
{ k3TypeRaw16to8, extractRaw16to8, createFilename },
{ k3TypeShpData, extractMrShapeAnimData, createFilename },
+ { lolTypeRaw16, extractRaw16, createFilename },
+
{ -1, 0, 0}
};
@@ -256,7 +260,42 @@ const ExtractFilename extractFilenames[] = {
// LANDS OF LORE
// Demo Sequence Player
- { lSeqplayIntroTracks, k2TypeSoundList, "S_INTRO.TRA" },
+ { lolSeqplayIntroTracks, k2TypeSoundList, "S_INTRO.TRA" },
+
+ // Ingame
+ { lolCharacterDefs, kTypeRawData, "CHARACTER.DEF" },
+ { lolIngameSfxFiles, k2TypeSfxList, "SFXFILES.TRA" },
+ { lolIngameSfxIndex, kTypeRawData, "SFXINDEX.MAP" },
+ { lolGMSfxIndex, kTypeRawData, "SFX_GM.MAP" },
+ { lolMT32SfxIndex, kTypeRawData, "SFX_MT32.MAP" },
+ { lolSpellProperties, kTypeRawData, "SPELLS.DEF" },
+ { lolGameShapeMap, kTypeRawData, "GAMESHP.MAP" },
+ { lolLevelShpList, kTypeStringList, "SHPFILES.TXT" },
+ { lolLevelDatList, kTypeStringList, "DATFILES.TXT" },
+ { lolCompassDefs, k3TypeRaw16to8, "COMPASS.DEF" },
+
+ { lolDscUnk1, kTypeRawData, "DSCSHPU1.DEF" },
+ { lolDscShapeIndex1, kTypeRawData, "DSCSHPI1.DEF" },
+ { lolDscShapeIndex2, kTypeRawData, "DSCSHPI2.DEF" },
+ { lolDscScaleWidthData, lolTypeRaw16, "DSCSHPW.DEF" },
+ { lolDscScaleHeightData, lolTypeRaw16, "DSCSHPH.DEF" },
+ { lolDscX, lolTypeRaw16, "DSCSHPX.DEF" },
+ { lolDscY, kTypeRawData, "DSCSHPY.DEF" },
+ { lolDscTileIndex, kTypeRawData, "DSCSHPT.DEF" },
+ { lolDscUnk2, kTypeRawData, "DSCSHPU2.DEF" },
+ { lolDscDoorShapeIndex, kTypeRawData, "DSCDOOR.DEF" },
+ { lolDscDimData1, kTypeRawData, "DSCDIM1.DEF" },
+ { lolDscDimData2, kTypeRawData, "DSCDIM2.DEF" },
+ { lolDscBlockMap, kTypeRawData, "DSCBLOCK1.DEF" },
+ { lolDscDimMap, kTypeRawData, "DSCDIM.DEF" },
+ { lolDscDoorScale, lolTypeRaw16, "DSCDOOR3.DEF" },
+ { lolDscDoor2, k3TypeRaw16to8, "DSCDOOR2.DEF" },
+ { lolDscShapeOvlIndex, k3TypeRaw16to8, "DSCBLOCK2.DEF" },
+ { lolDscBlockIndex, kTypeRawData, "DSCBLOCKX.DEF" },
+ { lolDscDoor4, lolTypeRaw16, "DSCDOOR4.DEF" },
+ { lolDscDoor1, kTypeRawData, "DSCDOOR1.DEF" },
+ { lolDscDoorX, lolTypeRaw16, "DSCDOORX.DEF" },
+ { lolDscDoorY, lolTypeRaw16, "DSCDOORY.DEF" },
{ -1, 0, 0 }
};
@@ -1012,6 +1051,20 @@ bool extractRaw16to8(PAKFile &out, const Game *g, const byte *data, const uint32
return out.addFile(filename, buffer, outsize);
}
+bool extractRaw16(PAKFile &out, const Game *g, const byte *data, const uint32 size, const char *filename, int fmtPatch) {
+ uint8 *buffer = new uint8[size];
+ const uint8 *src = data;
+ uint8 *dst = buffer;
+
+ for (int i = 0; i < (size >> 1); i++) {
+ WRITE_BE_UINT16(dst, READ_LE_UINT16(src));
+ src += 2;
+ dst += 2;
+ }
+
+ return out.addFile(filename, buffer, size);
+}
+
bool extractMrShapeAnimData(PAKFile &out, const Game *g, const byte *data, const uint32 size, const char *filename, int fmtPatch) {
int outsize = 1;
uint8 *buffer = new uint8[size + 1];
@@ -1070,7 +1123,7 @@ enum {
uint32 getFeatures(const Game *g) {
uint32 features = 0;
- if (g->special == kTalkieVersion || g->special == k2CDFile1E || g->special == k2CDFile1F || g->special == k2CDFile1G || g->special == k2CDFile1I || g->special == k2CDFile2E || g->special == k2CDFile2F || g->special == k2CDFile2G || g->game == kKyra3)
+ if (g->special == kTalkieVersion || g->special == k2CDFile1E || g->special == k2CDFile1F || g->special == k2CDFile1G || g->special == k2CDFile1I || g->special == k2CDFile2E || g->special == k2CDFile2F || g->special == k2CDFile2G || g->special == kLolCD || g->game == kKyra3)
features |= GF_TALKIE;
else if (g->special == kDemoVersion || g->special == k2DemoVersion || g->special == k2DemoLol)
features |= GF_DEMO;
@@ -1352,6 +1405,7 @@ const Game *gameDescs[] = {
kyra3Games,
lolDemos,
+ lolGames,
0
};
diff --git a/tools/create_kyradat/create_kyradat.h b/tools/create_kyradat/create_kyradat.h
index 8e985f9031..8c1fd3f84b 100644
--- a/tools/create_kyradat/create_kyradat.h
+++ b/tools/create_kyradat/create_kyradat.h
@@ -174,7 +174,41 @@ enum kExtractID {
k3ItemMagicTable,
k3ItemStringMap,
- lSeqplayIntroTracks,
+ lolSeqplayIntroTracks,
+
+ lolCharacterDefs,
+ lolIngameSfxFiles,
+ lolIngameSfxIndex,
+ lolGMSfxIndex,
+ lolMT32SfxIndex,
+ lolSpellProperties,
+ lolGameShapeMap,
+ lolLevelShpList,
+ lolLevelDatList,
+ lolCompassDefs,
+
+ lolDscUnk1,
+ lolDscShapeIndex1,
+ lolDscShapeIndex2,
+ lolDscScaleWidthData,
+ lolDscScaleHeightData,
+ lolDscX,
+ lolDscY,
+ lolDscTileIndex,
+ lolDscUnk2,
+ lolDscDoorShapeIndex,
+ lolDscDimData1,
+ lolDscDimData2,
+ lolDscBlockMap,
+ lolDscDimMap,
+ lolDscShapeOvlIndex,
+ lolDscBlockIndex,
+ lolDscDoor1,
+ lolDscDoor2,
+ lolDscDoorScale,
+ lolDscDoor4,
+ lolDscDoorX,
+ lolDscDoorY,
kMaxResIDs
};
@@ -219,7 +253,9 @@ enum kSpecial {
k2DemoVersionTlkE = 19,
k2DemoVersionTlkF = 20,
k2DemoVersionTlkG = 21,
- k2DemoLol = 22
+ k2DemoLol = 22,
+
+ kLolCD = 23
};
struct SpecialExtension {
@@ -267,7 +303,9 @@ enum kExtractType {
k2TypeSfxList,
k3TypeRaw16to8,
- k3TypeShpData
+ k3TypeShpData,
+
+ lolTypeRaw16
};
struct ExtractType {
diff --git a/tools/create_kyradat/lol_cd.h b/tools/create_kyradat/lol_cd.h
new file mode 100644
index 0000000000..8380b9961e
--- /dev/null
+++ b/tools/create_kyradat/lol_cd.h
@@ -0,0 +1,42 @@
+const ExtractEntry lolCDFile2[] = {
+ { lolCharacterDefs, 0x00029D60, 0x0002A1F2 },
+ { lolIngameSfxFiles, 0x0002A330, 0x0002AC22 },
+ { lolIngameSfxIndex, 0x0002AC22, 0x0002B00A },
+ { lolGMSfxIndex, 0x0002B010, 0x0002B10A },
+ { lolMT32SfxIndex, 0x0002B110, 0x0002B20A },
+ { lolSpellProperties, 0x0002B5D0, 0x0002B6E8 },
+ { lolGameShapeMap, 0x0002B35D, 0x0002B52C },
+ { lolLevelShpList, 0x00032826, 0x000328A5 },
+ { lolLevelDatList, 0x000328A5, 0x000329A4 },
+ { lolCompassDefs, 0x000286C4, 0x000287C4 },
+
+ { lolDscUnk1, 0x00032017, 0x0003203B },
+ { lolDscShapeIndex1, 0x0003203B, 0x0003205F },
+ { lolDscShapeIndex2, 0x0003205F, 0x00032069 },
+ { lolDscScaleWidthData, 0x00032069, 0x000320B1 },
+ { lolDscScaleHeightData, 0x000320B1, 0x000320F9 },
+ { lolDscX, 0x000320F9, 0x00032141 },
+ { lolDscY, 0x00032141, 0x00032165 },
+ { lolDscTileIndex, 0x00032165, 0x00032177 },
+ { lolDscUnk2, 0x00032177, 0x0003218E },
+ { lolDscDoorShapeIndex, 0x0003218E, 0x000321A5 },
+ { lolDscDimData1, 0x00031C03, 0x00031D47 },
+ { lolDscDimData2, 0x00031D47, 0x00031FD0 },
+ { lolDscBlockMap, 0x00031B64, 0x00031B70 },
+ { lolDscDimMap, 0x00031B70, 0x00031B82 },
+ { lolDscDoorScale, 0x00031B82, 0x00031B92 },
+ { lolDscDoor2, 0x00031B92, 0x00031B9A },
+ { lolDscShapeOvlIndex, 0x00031B9A, 0x00031BBA },
+ { lolDscDoor4, 0x00031BBA, 0x00031BC2 },
+ { lolDscBlockIndex, 0x00033B53, 0x00033B9B },
+ { lolDscDoor1, 0x0002B550, 0x0002B5D0 },
+ { lolDscDoorX, 0x00027CC0, 0x00028140 },
+ { lolDscDoorY, 0x00028140, 0x000285C0 },
+
+ { -1, 0, 0 }
+};
+
+const Game lolGames[] = {
+ { kLol, EN_ANY, kLolCD, "263998ec600afca1cc7b935c473df670", lolCDFile2},
+ GAME_DUMMY_ENTRY
+};
diff --git a/tools/create_kyradat/lol_demo.h b/tools/create_kyradat/lol_demo.h
index ce114f4e73..378b8c5dce 100644
--- a/tools/create_kyradat/lol_demo.h
+++ b/tools/create_kyradat/lol_demo.h
@@ -3,7 +3,7 @@ const ExtractEntry lolDemo[] = {
{ k2SeqplayStrings, 0x0001B5EE, 0x0001B6F0 },
{ k2SeqplaySfxFiles, 0x0001B6F0, 0x0001B7B5 },
{ k2SeqplaySeqData, 0x0001B320, 0x0001B56C },
- { lSeqplayIntroTracks, 0x0001B7B5, 0x0001B7CF },
+ { lolSeqplayIntroTracks, 0x0001B7B5, 0x0001B7CF },
{ -1, 0, 0 }
};
diff --git a/tools/create_kyradat/misc.h b/tools/create_kyradat/misc.h
index c519418d37..91ee915319 100644
--- a/tools/create_kyradat/misc.h
+++ b/tools/create_kyradat/misc.h
@@ -481,12 +481,50 @@ const int kyra3Need[] = {
-1
};
+const int lolCDFile2Need[] = {
+ lolCharacterDefs,
+ lolIngameSfxFiles,
+ lolIngameSfxIndex,
+ lolGMSfxIndex,
+ lolMT32SfxIndex,
+ lolSpellProperties,
+ lolGameShapeMap,
+ lolLevelShpList,
+ lolLevelDatList,
+ lolCompassDefs,
+ lolDscUnk1,
+ lolDscShapeIndex1,
+ lolDscShapeIndex2,
+ lolDscScaleWidthData,
+ lolDscScaleHeightData,
+ lolDscX,
+ lolDscY,
+ lolDscTileIndex,
+ lolDscUnk2,
+ lolDscDoorShapeIndex,
+ lolDscDimData1,
+ lolDscDimData2,
+ lolDscBlockMap,
+ lolDscDimMap,
+ lolDscDoor2,
+ lolDscShapeOvlIndex,
+ lolDscBlockIndex,
+ lolDscDoor1,
+ lolDscDoor2,
+ lolDscDoorScale,
+ lolDscDoor4,
+ lolDscDoorX,
+ lolDscDoorY,
+
+ -1
+};
+
const int lolDemoNeed[] = {
k2SeqplayPakFiles,
k2SeqplayStrings,
k2SeqplaySeqData,
k2SeqplaySfxFiles,
- lSeqplayIntroTracks,
+ lolSeqplayIntroTracks,
-1
};
@@ -519,6 +557,8 @@ const GameNeed gameNeedTable[] = {
{ kKyra3, -1, kyra3Need },
+ { kLol, kLolCD, lolCDFile2Need },
+
{ -1, -1, 0 }
};
@@ -544,6 +584,8 @@ const SpecialExtension specialTable[] = {
{ k2DemoVersion, "DEM" },
{ k2DemoLol, "DEM" },
+ { kLolCD, "CD" },
+
{ -1, 0 }
};