LOL: Some drawing code and some opcodes so that the first scene will show up. Playing is not possible. This is still somewhat messy since a lot of stuff hasn't been figured out yet.

svn-id: r35903
This commit is contained in:
Florian Kagerer 2009-01-18 17:04:24 +00:00
parent bf08c82054
commit ff268e8fd5
20 changed files with 4575 additions and 28 deletions

Binary file not shown.

361
engines/kyra/gui_lol.cpp Normal file
View file

@ -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

186
engines/kyra/items_lol.cpp Normal file
View file

@ -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

File diff suppressed because it is too large Load diff

View file

@ -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 */ }
void snd_playSoundEffect(int track, int volume);
// opcode
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) {}

View file

@ -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 \

View file

@ -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 {

1369
engines/kyra/scene_lol.cpp Normal file

File diff suppressed because it is too large Load diff

View file

@ -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

View file

@ -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

View file

@ -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++;

View file

@ -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);

View file

@ -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])

450
engines/kyra/script_lol.cpp Normal file
View file

@ -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

View file

@ -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 },

View file

@ -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
};

View file

@ -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 {

View file

@ -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
};

View file

@ -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 }
};

View file

@ -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 }
};