svn-id: r36178

This commit is contained in:
Florian Kagerer 2009-02-01 19:27:01 +00:00
parent f90e4545c2
commit 784c99b3da
19 changed files with 2718 additions and 352 deletions

View file

@ -158,6 +158,13 @@ public:
// utilities for thumbnail creation
virtual void createScreenThumbnail(Graphics::Surface &dst) = 0;
// LOL tim player specific
virtual void drawDialogueBox(int numStr, const char *s1, const char *s2, const char *s3) {}
virtual uint16 processDialogue() { return 0; }
virtual void update() {}
virtual char *getTableString(int id) { return 0; }
protected:
KyraEngine_v1 *_vm;
Screen *_screen;

View file

@ -25,6 +25,7 @@
#include "kyra/lol.h"
#include "kyra/screen_lol.h"
#include "kyra/gui_lol.h"
namespace Kyra {
@ -35,7 +36,7 @@ void LoLEngine::gui_drawPlayField() {
// 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;
_compassDirection = -1;
}
if (_screen->_drawGuiFlag & 0x1000)
@ -51,28 +52,27 @@ void LoLEngine::gui_drawPlayField() {
}
if (_screen->_drawGuiFlag & 0x800)
turnOnLamp();
resetLampStatus();
//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)
if (!(_updateFlags & 1) && _weaponsDisabled == false && _unkDrawLevelBool && _vcnBlocks)
drawScene(pageNum);
}
void LoLEngine::gui_drawInventory() {
if (!_unkInventFlag || !_updateCharV6) {
if (!_hideControls || !_hideInventory) {
for (int i = 0; i < 9; i++)
gui_drawInventoryItem(i);
}
@ -89,8 +89,8 @@ void LoLEngine::gui_drawInventoryItem(int index) {
_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);
if (_inventory[index])
_screen->drawShape(_screen->_curPage, getItemIconShapePtr(_inventory[index]), x + 1, 180, 0, 0);
_screen->showMouse();
}
@ -134,13 +134,13 @@ void LoLEngine::gui_drawAllCharPortraitsWithStats() {
}
void LoLEngine::gui_drawCharPortraitWithStats(int charNum) {
if (!(_characters[charNum].flags & 1) || _charFlagUnk & 2)
if (!(_characters[charNum].flags & 1) || _updateFlags & 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_drawBox(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);
@ -165,22 +165,22 @@ void LoLEngine::gui_drawCharPortraitWithStats(int charNum) {
_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;
int handIndex = 0;
if (_characters[charNum].items[0]) {
if (_itemProperties[_itemsInPlay[_characters[charNum].items[0]].itemPropertyIndex].unk8 != -1)
handIndex = _itemsInPlay[_characters[charNum].items[0]].itemPropertyIndex;
}
handIndex = _gameShapeMap[_itemProperties[handIndex].shpIndex << 1];
if (handIndex == 0x5a) { // draw raceClassSex specific hand shape
handIndex = _characters[charNum].raceClassSex - 1;
if (handIndex < 0)
handIndex = 0;
handIndex += 68;
}
// draw hand/weapon
_screen->drawShape(_screen->_curPage, _gameShapes[shapeNum], 44, 0, 0, 0);
_screen->drawShape(_screen->_curPage, _gameShapes[handIndex], 44, 0, 0, 0);
// draw magic symbol
_screen->drawShape(_screen->_curPage, _gameShapes[72 + _characters[charNum].field_41], 44, 17, 0, 0);
@ -189,7 +189,7 @@ void LoLEngine::gui_drawCharPortraitWithStats(int charNum) {
}
uint16 f = _characters[charNum].flags & 0x314C;
if ((f == 0 && (f != 4 || _characters[charNum].weaponHit == 0)) || _weaponsDisabled)
if ((f == 0 && _weaponsDisabled) || (f && (f != 4 || _characters[charNum].weaponHit == 0 || _weaponsDisabled)))
_screen->drawGridBox(44, 0, 22, 34, 1);
if (_characters[charNum].weaponHit) {
@ -202,7 +202,7 @@ void LoLEngine::gui_drawCharPortraitWithStats(int charNum) {
if (!cp)
_screen->hideMouse();
uint8 col = (charNum != _unkDrawPortraitIndex || countActiveCharacters() == 1) ? 1 : 212;
uint8 col = (charNum != _selectedCharacter || 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);
@ -214,7 +214,7 @@ void LoLEngine::gui_drawCharPortraitWithStats(int charNum) {
_screen->setFont(tmpFid);
}
void LoLEngine::gui_drawPortraitBox(int x, int y, int w, int h, int frameColor1, int frameColor2, int fillColor) {
void LoLEngine::gui_drawBox(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);
@ -334,12 +334,12 @@ void LoLEngine::gui_drawCompass() {
if (!(_screen->_drawGuiFlag & 0x4000))
return;
if (_updateUnk2 == -1) {
if (_compassDirection == -1) {
_compassDirectionIndex = -1;
_updateUnk2 = _currentDirection << 6;
_compassDirection = _currentDirection << 6;
}
int t = ((_updateUnk2 + 4) >> 3) & 0x1f;
int t = ((_compassDirection + 4) >> 3) & 0x1f;
if (t == _compassDirectionIndex)
return;
@ -352,12 +352,502 @@ void LoLEngine::gui_drawCompass() {
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], 298 + c->x, c->y + 9, 0, c->flags | 0x300, _screen->_paletteOverlay1, 1);
_screen->drawShape(_screen->_curPage, _gameShapes[25 + c->shapeIndex], 299 + c->x, c->y + 8, 0, c->flags);
if (!_screen->_curPage)
_screen->showMouse();
}
int LoLEngine::gui_enableControls() {
_floatingMouseArrowControl = 0;
if (!_hideControls) {
for (int i = 76; i < 85; i++)
gui_disableArrowButton(i, 2);
}
gui_toggleFightButtons(false);
return 1;
}
int LoLEngine::gui_disableControls(int controlMode) {
if (_hideControls)
return 0;
_floatingMouseArrowControl = (controlMode & 2) ? 2 : 1;
gui_toggleFightButtons(true);
for (int i = 76; i < 85; i++)
gui_disableArrowButton(i, ((controlMode & 2) && (i > 78)) ? 2 : 3);
return 1;
}
void LoLEngine::gui_disableArrowButton(int shapeIndex, int mode) {
static const int16 arrowButtonX[] = { 0x000C, 0x0021, 0x0122, 0x000C, 0x0021, 0x0036, 0x000C, 0x0021, 0x0036 };
static const int16 arrowButtonY[] = { 0x00B4, 0x00B4, 0x0020, 0x0084, 0x0084, 0x0084, 0x0096, 0x0096, 0x0096 };
if (shapeIndex == 78 && !(_screen->_drawGuiFlag & 0x1000))
return;
if (_hideControls && _hideInventory)
return;
if (mode == 0)
shapeIndex = _lastArrowButtonShape;
int pageNum = 0;
int16 x1 = arrowButtonX[shapeIndex - 76];
int16 y1 = arrowButtonY[shapeIndex - 76];
int16 x2 = 0;
int16 y2 = 0;
uint32 t = 0;
switch (mode) {
case 1:
mode = 0x100;
_lastArrowButtonShape = shapeIndex;
break;
case 0:
if (!_lastArrowButtonShape)
return;
t = _system->getMillis();
if (_arrowButtonTimer > t)
delay(_arrowButtonTimer - t);
case 2:
mode = 0;
_lastArrowButtonShape = 0;
break;
case 3:
mode = 0;
_lastArrowButtonShape = 0;
pageNum = 6;
x2 = x1;
y2 = y1;
x1 = 0;
y1 = 0;
break;
default:
break;
}
_screen->drawShape(pageNum, _gameShapes[shapeIndex], x1, y1, 0, mode, _screen->_paletteOverlay1, 1);
if (pageNum != 6)
return;
int cp = _screen->setCurPage(6);
_screen->drawGridBox(x1, y1, _gameShapes[shapeIndex][3], _gameShapes[shapeIndex][2], 1);
_screen->copyRegion(x1, y1, x2, y2, _gameShapes[shapeIndex][3], _gameShapes[shapeIndex][2], pageNum, 0, Screen::CR_NO_P_CHECK);
_screen->setCurPage(cp);
_arrowButtonTimer = _system->getMillis() + 6 * _tickLength;
}
void LoLEngine::gui_toggleFightButtons(bool disable) {
for (int i = 0; i < 3; i++) {
if (!(_characters[i].flags & 1))
continue;
if (disable)
_characters[i].flags |= 0x2000;
else
_characters[i].flags &= 0xdfff;
if (disable && !textEnabled()) {
int u = _selectedCharacter;
_selectedCharacter = 99;
int f = _updateFlags;
_updateFlags &= 0xfffd;
gui_drawCharPortraitWithStats(i);
_updateFlags = f;
_selectedCharacter = u;
} else {
gui_drawCharPortraitWithStats(i);
}
}
}
int LoLEngine::clickedUpArrow(Button *button) {
return 1;
}
int LoLEngine::clickedDownArrow(Button *button) {
return 1;
}
int LoLEngine::clickedLeftArrow(Button *button) {
return 1;
}
int LoLEngine::clickedRightArrow(Button *button) {
return 1;
}
int LoLEngine::clickedTurnLeftArrow(Button *button) {
return 1;
}
int LoLEngine::clickedTurnRightArrow(Button *button) {
return 1;
}
int LoLEngine::clickedAttackButton(Button *button) {
return 1;
}
int LoLEngine::clickedMagicButton(Button *button) {
return 1;
}
int LoLEngine::clickedUnk9(Button *button) {
return 1;
}
int LoLEngine::clickedScreen(Button *button) {
return 1;
}
int LoLEngine::clickedPortraitLeft(Button *button) {
return 1;
}
int LoLEngine::clickedLiveMagicBarsLeft(Button *button) {
return 1;
}
int LoLEngine::clickedPortraitEtcRight(Button *button) {
return 1;
}
int LoLEngine::clickedUnk14(Button *button) {
return 1;
}
int LoLEngine::clickedUnk15(Button *button) {
return 1;
}
int LoLEngine::clickedUnk16(Button *button) {
return 1;
}
int LoLEngine::clickedUnk17(Button *button) {
return 1;
}
int LoLEngine::clickedInventorySlot(Button *button) {
return 1;
}
int LoLEngine::clickedInventoryScroll(Button *button) {
return 1;
}
int LoLEngine::clickedUnk20(Button *button) {
return 1;
}
int LoLEngine::clickedUnk21(Button *button) {
return 1;
}
int LoLEngine::clickedScroll(Button *button) {
return 1;
}
int LoLEngine::clickedUnk23(Button *button) {
return 1;
}
int LoLEngine::clickedUnk24(Button *button) {
return 1;
}
int LoLEngine::clickedUnk25(Button *button) {
return 1;
}
int LoLEngine::clickedOptions(Button *button) {
return 1;
}
int LoLEngine::clickedRestParty(Button *button) {
return 1;
}
int LoLEngine::clickedUnk28(Button *button) {
return 1;
}
int LoLEngine::clickedUnk29(Button *button) {
return 1;
}
int LoLEngine::clickedUnk30(Button *button) {
return 1;
}
int LoLEngine::clickedUnk31(Button *button) {
return 1;
}
int LoLEngine::clickedUnk32(Button *button) {
return 1;
}
GUI_LoL::GUI_LoL(LoLEngine *vm) : GUI(vm), _vm(vm), _screen(vm->_screen) {
memset(_dialogueButtonString, 0, 3 * sizeof(const char*));
_dialogueButtonPosX = _dialogueButtonPosY = _dialogueNumButtons = _dialogueButtonXoffs = _dialogueHighlightedButton = 0;
_scrollUpFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::scrollUp);
_scrollDownFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::scrollDown);
}
int GUI_LoL::processButtonList(Button *list, uint16 inputFlag, int8 mouseWheel) {
if ((inputFlag & 0xFF) == 199)
_pressFlag = true;
else if ((inputFlag & 0xFF) == 200)
_pressFlag = false;
int returnValue = 0;
while (list) {
/*if (list->flags & 8) {
list = list->nextButton;
continue;
}
if (mouseWheel && list->mouseWheel == mouseWheel && list->buttonCallback) {
if ((*list->buttonCallback.get())(list))
break;
}
int x = list->x;
int y = list->y;
assert(_screen->getScreenDim(list->dimTableIndex) != 0);
if (x < 0)
x += _screen->getScreenDim(list->dimTableIndex)->w << 3;
x += _screen->getScreenDim(list->dimTableIndex)->sx << 3;
if (y < 0)
y += _screen->getScreenDim(list->dimTableIndex)->h;
y += _screen->getScreenDim(list->dimTableIndex)->sy;
if (_vm->_mouseX >= x && _vm->_mouseY >= y && x + list->width >= _vm->_mouseX && y + list->height >= _vm->_mouseY) {
int processMouseClick = 0;
if (list->flags & 0x400) {
if ((inputFlag & 0xFF) == 199 || _pressFlag) {
if (!(list->flags2 & 1)) {
list->flags2 |= 1;
list->flags2 |= 4;
processButton(list);
_screen->updateScreen();
inputFlag = 0;
}
} else if ((inputFlag & 0xFF) == 200) {
if (list->flags2 & 1) {
list->flags2 &= 0xFFFE;
processButton(list);
processMouseClick = 1;
inputFlag = 0;
}
}
}
if (processMouseClick) {
if (list->buttonCallback) {
if ((*list->buttonCallback.get())(list))
break;
}
}
} else {
if (list->flags2 & 1) {
list->flags2 &= 0xFFFE;
processButton(list);
}
if (list->flags2 & 4) {
list->flags2 &= 0xFFFB;
processButton(list);
_screen->updateScreen();
}
}
list = list->nextButton;*/
}
if (!returnValue)
returnValue = inputFlag & 0xFF;
return returnValue;
}
void GUI_LoL::drawDialogueBox(int numStr, const char *s1, const char *s2, const char *s3) {
if (numStr == 1 && _vm->_speechFlag) {
_screen->setScreenDim(5);
_dialogueButtonString[0] = _dialogueButtonString[1] = _dialogueButtonString[2] = 0;
} else {
_screen->setScreenDim(5);
_dialogueNumButtons = numStr;
_dialogueButtonString[0] = s1;
_dialogueButtonString[1] = s2;
_dialogueButtonString[2] = s3;
_dialogueHighlightedButton = 0;
const ScreenDim *d = _screen->getScreenDim(5);
_dialogueButtonPosY = d->sy + d->h - 9;
if (numStr == 1) {
_dialogueButtonXoffs = 0;
_dialogueButtonPosX = d->sx + d->w - 77;
} else {
_dialogueButtonXoffs = d->w / numStr;
_dialogueButtonPosX = d->sx + (_dialogueButtonXoffs >> 1) - 37;
}
drawDialogueButtons();
}
if (!_vm->shouldQuit())
_vm->removeInputTop();
}
void GUI_LoL::drawDialogueButtons() {
int cp = _screen->setCurPage(0);
Screen::FontId of = _screen->setFont(Screen::FID_6_FNT);
int x = _dialogueButtonPosX;
for (int i = 0; i < _dialogueNumButtons; i++) {
_vm->gui_drawBox(x, _dialogueButtonPosY, 74, 9, 136, 251, -1);
_screen->printText(_dialogueButtonString[i], x + 37 - (_screen->getTextWidth(_dialogueButtonString[i])) / 2,
_dialogueButtonPosY + 2, _dialogueHighlightedButton == i ? 144 : 254, 0);
x += _dialogueButtonXoffs;
}
_screen->setFont(of);
_screen->setCurPage(cp);
}
uint16 GUI_LoL::processDialogue() {
int df = _dialogueHighlightedButton;
int res = 0;
int x = _dialogueButtonPosX;
for (int i = 0; i < _dialogueNumButtons; i++) {
if (_vm->posWithinRect(_vm->_mouseX, _vm->_mouseY, x, _dialogueButtonPosY, x + 74, _dialogueButtonPosY + 9)) {
_dialogueHighlightedButton = i;
break;
}
x += _dialogueButtonXoffs;
}
if (_dialogueNumButtons == 0) {
int e = _vm->checkInput(0, false) & 0xCF;
_vm->removeInputTop();
if (e == 200) {
_vm->snd_dialogueSpeechUpdate(1);
//_dlgTimer = 0;
}
if (_vm->snd_characterSpeaking() != 2) {
//if (_dlgTimer < _system->getMillis()) {
res = 1;
if (!_vm->shouldQuit())
_vm->removeInputTop();
//}
}
} else {
int e = _vm->checkInput(0, false);
_vm->removeInputTop();
switch (e) {
case 100:
case 101:
_vm->snd_dialogueSpeechUpdate(1);
//_dlgTimer = 0;
res = _dialogueHighlightedButton + 1;
break;
case 110:
case 111:
if (_dialogueNumButtons > 1 && _dialogueHighlightedButton > 0)
_dialogueHighlightedButton--;
break;
case 112:
case 113:
if (_dialogueNumButtons > 1 && _dialogueHighlightedButton < (_dialogueNumButtons - 1))
_dialogueHighlightedButton++;
break;
case 200:
case 300:
x = _dialogueButtonPosX;
for (int i = 0; i < _dialogueNumButtons; i++) {
if (_vm->posWithinRect(_vm->_mouseX, _vm->_mouseY, x, _dialogueButtonPosY, x + 74, _dialogueButtonPosY + 9)) {
_dialogueHighlightedButton = i;
res = _dialogueHighlightedButton + 1;
break;
}
x += _dialogueButtonXoffs;
}
break;
default:
break;
}
}
if (df != _dialogueHighlightedButton)
drawDialogueButtons();
if (res == 0)
return 0;
_vm->updatePortraits();
if (!_vm->textEnabled() && _vm->_hideControls) {
_screen->setScreenDim(5);
const ScreenDim *d = _screen->getScreenDim(5);
_screen->hideMouse();
_screen->fillRect(d->sx, d->sy + d->h - 9, d->sx + d->w - 1, d->sy + d->h - 1, d->unkA);
_screen->showMouse();
} else {
const ScreenDim *d = _screen->_curDim;
_screen->hideMouse();
_screen->fillRect(d->sx, d->sy, d->sx + d->w - 2, d->sy + d->h - 1, d->unkA);
_screen->clearDim(4);
_screen->setScreenDim(4);
_screen->showMouse();
//_screen->setDialogueColumn(8, 0);
//_screen->setDialogueLine(8, 0);
}
return res;
}
char *GUI_LoL::getTableString(int id) {
return (char *) _vm->getLangString(id);
}
void GUI_LoL::update() {
_vm->update();
}
} // end of namespace Kyra

94
engines/kyra/gui_lol.h Normal file
View file

@ -0,0 +1,94 @@
/* 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$
*
*/
#ifndef KYRA_GUI_LOL_H
#define KYRA_GUI_LOL_H
#include "kyra/gui.h"
namespace Kyra {
class LoLEngine;
class Screen_LoL;
class GUI_LoL : public GUI {
friend class LoLEngine;
public:
GUI_LoL(LoLEngine *vm);
void initStaticData();
// button specific
void processButton(Button *button) {}
int processButtonList(Button *buttonList, uint16 inputFlags, int8 mouseWheel);
// utilities for thumbnail creation
void createScreenThumbnail(Graphics::Surface &dst) {}
// tim player specific
void drawDialogueBox(int numStr, const char *s1, const char *s2, const char *s3);
uint16 processDialogue();
void update();
char *getTableString(int id);
private:
LoLEngine *_vm;
Screen_LoL *_screen;
bool _pressFlag;
int scrollUp(Button *button) { return 0; }
int scrollDown(Button *button) { return 0; }
Button *getButtonListData() { return 0; }
Button *getScrollUpButton() { return 0; }
Button *getScrollDownButton() { return 0; }
Button::Callback _scrollUpFunctor;
Button::Callback _scrollDownFunctor;
Button::Callback getScrollUpButtonHandler() const { return _scrollUpFunctor; }
Button::Callback getScrollDownButtonHandler() const { return _scrollDownFunctor; }
uint8 defaultColor1() const { return 0; }
uint8 defaultColor2() const { return 0; }
const char *getMenuTitle(const Menu &menu) { return 0; }
const char *getMenuItemTitle(const MenuItem &menuItem) { return 0; }
const char *getMenuItemLabel(const MenuItem &menuItem) { return 0; }
void drawDialogueButtons();
const char *_dialogueButtonString[3];
uint16 _dialogueButtonPosX;
uint16 _dialogueButtonPosY;
int _dialogueNumButtons;
uint16 _dialogueButtonXoffs;
int _dialogueHighlightedButton;
};
} // end of namespace Kyra
#endif

View file

@ -62,8 +62,8 @@ void LoLEngine::giveCredits(int credits, int redraw) {
if (redraw) {
gui_drawMoneyBox(6);
//if (credits)
// TODO: delay/update
if (credits)
update();
}
credits -= t;
}
@ -153,18 +153,18 @@ void LoLEngine::clearItemTableEntry(int itemIndex) {
_itemsInPlay[itemIndex].shpCurFrame_flg |= 0x8000;
}
void *LoLEngine::cmzGetItemOffset(uint16 index) {
CLevelItem *LoLEngine::findItem(uint16 index) {
if (index & 0x8000)
return &_lvlBuffer[index & 0x7fff];
return &_cLevelItems[index & 0x7fff];
else
return &_itemsInPlay[index];
return (CLevelItem *)&_itemsInPlay[index];
}
void LoLEngine::runItemScript(int reg1, int slot, int reg0, int reg3, int reg4) {
void LoLEngine::runItemScript(int reg1, int item, int reg0, int reg3, int reg4) {
EMCState scriptState;
memset(&scriptState, 0, sizeof(EMCState));
uint8 func = slot ? _itemProperties[_itemsInPlay[slot].itemPropertyIndex].itemScriptFunc : 3;
uint8 func = item ? _itemProperties[_itemsInPlay[item].itemPropertyIndex].itemScriptFunc : 3;
if (func == 0xff)
return;
@ -173,7 +173,7 @@ void LoLEngine::runItemScript(int reg1, int slot, int reg0, int reg3, int reg4)
scriptState.regs[0] = reg0;
scriptState.regs[1] = reg1;
scriptState.regs[2] = slot;
scriptState.regs[2] = item;
scriptState.regs[3] = reg3;
scriptState.regs[4] = reg4;

View file

@ -257,6 +257,29 @@ int KyraEngine_v1::checkInput(Button *buttonList, bool mainLoop) {
_debugger->attach();
else if (event.kbd.keycode == 'q')
quitGame();
} else {
switch(event.kbd.keycode) {
case Common::KEYCODE_SPACE:
keys = 100;
break;
case Common::KEYCODE_RETURN:
keys = 101;
break;
case Common::KEYCODE_UP:
keys = 110;
break;
case Common::KEYCODE_RIGHT:
keys = 111;
break;
case Common::KEYCODE_DOWN:
keys = 112;
break;
case Common::KEYCODE_LEFT:
keys = 113;
break;
default:
break;
}
}
break;
@ -275,6 +298,15 @@ int KyraEngine_v1::checkInput(Button *buttonList, bool mainLoop) {
breakLoop = true;
} break;
case Common::EVENT_RBUTTONDOWN:
case Common::EVENT_RBUTTONUP: {
Common::Point pos = getMousePos();
_mouseX = pos.x;
_mouseY = pos.y;
keys = (event.type == Common::EVENT_RBUTTONDOWN ? 299 : (300 | 0x800));
breakLoop = true;
} break;
case Common::EVENT_WHEELUP:
mouseWheel = -1;
break;

View file

@ -29,6 +29,9 @@
#include "kyra/sound.h"
#include "kyra/util.h"
#include "sound/voc.h"
#include "sound/audiostream.h"
#include "common/endian.h"
#include "base/version.h"
@ -36,6 +39,8 @@ namespace Kyra {
LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(system, flags) {
_screen = 0;
_gui = 0;
_dlg = 0;
switch (_flags.lang) {
case Common::EN_ANY:
@ -66,6 +71,7 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy
_lastMusicTrack = -1;
_lastSfxTrack = -1;
_curTlkFile = -1;
_lastSpeaker = _lastSpeechId = -1;
memset(_moneyColumnHeight, 0, 5);
_credits = 0;
@ -73,9 +79,9 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy
_itemsInPlay = 0;
_itemProperties = 0;
_itemInHand = 0;
memset(_inventoryItemIndex, 0, 48);
memset(_inventory, 0, 48);
_inventoryCurItem = 0;
_unkInventFlag = 0;
_hideControls = 0;
_itemIconShapes = _itemShapes = _gameShapes = _thrownShapes = _iceShapes = _fireballShapes = 0;
_levelShpList = _levelDatList = 0;
@ -87,16 +93,18 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy
_charSelection = -1;
_characters = 0;
_spellProperties = 0;
_charFlagUnk = 0;
_updateFlags = 0;
_selectedSpell = 0;
_updateCharNum = _updateCharV1 = _updateCharV2 = _updateCharV3 = _updateCharV4 = _updateCharV5 = _updateCharV6 = 0;
_updateCharTime = _updatePortraitNext = 0;
_updateCharNum = _updateCharV1 = _updateCharV2 = _updateCharV3 = _updateCharV4 = _restorePalette = _hideInventory = 0;
_palUpdateTimer = _updatePortraitNext = 0;
_lampStatusTimer = 0xffffffff;
_weaponsDisabled = false;
_unkDrawPortraitIndex = 0;
_lastArrowButtonShape = 0;
_arrowButtonTimer = 0;
_selectedCharacter = 0;
_unkFlag = 0;
_scriptBoolSkipExec = _boolScriptFuncDone = false;
_scriptBoolSkipExec = _sceneUpdateRequired = false;
_unkScriptByte = 0;
_currentDirection = 0;
_currentBlock = 0;
@ -106,16 +114,16 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy
_wllShapeMap = 0;
_lvlShapeTop = _lvlShapeBottom = _lvlShapeLeftRight = 0;
_levelBlockProperties = 0;
_lvlBuffer = 0;
_lvl415 = 0;
_cLevelItems = 0;
_monsterProperties = 0;
_lvlBlockIndex = _lvlShapeIndex = 0;
_unkDrawLevelBool = true;
_vcnBlocks = 0;
_vcnShift = 0;
_vcnExpTable = 0;
_vmpPtr = 0;
_tlcTable2 = 0;
_tlcTable1 = 0;
_trueLightTable2 = 0;
_trueLightTable1 = 0;
_levelShapeProperties = 0;
_levelShapes = 0;
_blockDrawingBuffer = 0;
@ -125,8 +133,10 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy
_lampOilStatus = _brightness = _lampStatusUnk = 0;
_tempBuffer5120 = 0;
_tmpData136 = 0;
_lvlBuffer = 0;
_cLevelItems = 0;
_unkGameFlag = 0;
_lastMouseRegion = 0;
_preSeq_X1 = _preSeq_Y1 = _preSeq_X2 = _preSeq_Y2 = 0;
_dscUnk1 = 0;
_dscShapeIndex = 0;
@ -155,8 +165,16 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy
_curMusicFileIndex = -1;
_sceneDrawVar1 = _sceneDrawVar2 = _sceneDrawVar3 = _wllProcessFlag = 0;
_unkCmzU1 = _unkCmzU2 = 0;
_partyPosX = _partyPosY = 0;
_shpDmX = _shpDmY = _dmScaleW = _dmScaleH = 0;
_intFlag3 = 3;
_floatingMouseArrowControl = 0;
memset(_activeTim, 0, 10 * sizeof(TIM*));
memset(_activeVoiceFile, 0, sizeof(_activeVoiceFile));
//_dlgAnimCallback = &TextDisplayer_LoL::portraitAnimation1;
}
LoLEngine::~LoLEngine() {
@ -166,7 +184,9 @@ LoLEngine::~LoLEngine() {
delete[] _levelLangFile;
delete _screen;
delete _gui;
delete _tim;
delete _dlg;
delete[] _itemsInPlay;
delete[] _itemProperties;
@ -224,6 +244,11 @@ LoLEngine::~LoLEngine() {
delete *i;
_timIntroOpcodes.clear();
for (Common::Array<const TIMOpcode*>::iterator i = _timIngameOpcodes.begin(); i != _timIngameOpcodes.end(); ++i)
delete *i;
_timIngameOpcodes.clear();
delete[] _wllVmpMap;
delete[] _wllShapeMap;
delete[] _wllBuffer3;
@ -234,17 +259,17 @@ LoLEngine::~LoLEngine() {
delete[] _lvlShapeLeftRight;
delete[] _tempBuffer5120;
delete[] _tmpData136;
delete[] _lvlBuffer;
delete[] _cLevelItems;
delete[] _levelBlockProperties;
delete[] _lvl415;
delete[] _monsterProperties;
delete[] _levelFileData;
delete[] _vcnExpTable;
delete[] _vcnBlocks;
delete[] _vcnShift;
delete[] _vmpPtr;
delete[] _tlcTable2;
delete[] _tlcTable1;
delete[] _trueLightTable2;
delete[] _trueLightTable1;
delete[] _levelShapeProperties;
delete[] _blockDrawingBuffer;
delete[] _sceneWindowBuffer;
@ -271,6 +296,10 @@ Screen *LoLEngine::screen() {
return _screen;
}
GUI *LoLEngine::gui() const {
return _gui;
}
Common::Error LoLEngine::init() {
_screen = new Screen_LoL(this, _system);
assert(_screen);
@ -279,9 +308,16 @@ Common::Error LoLEngine::init() {
KyraEngine_v1::init();
initStaticResource();
_gui = new GUI_LoL(this);
assert(_gui);
_gui->initStaticData();
initButtonList();
_tim = new TIMInterpreter(this, _screen, _system);
assert(_tim);
_dlg = new TextDisplayer_LoL(this, _screen);
_screen->setAnimBlockPtr(10000);
_screen->setScreenDim(0);
@ -294,8 +330,7 @@ Common::Error LoLEngine::init() {
if (!_sound->init())
error("Couldn't init sound");
_unkAudioSpecOffs = 0x48;
_unkLangAudio = _lang ? true : false;
_speechFlag = speechEnabled() ? 0x48 : 0;
_wllVmpMap = new uint8[80];
memset(_wllVmpMap, 0, 80);
@ -324,10 +359,10 @@ Common::Error LoLEngine::init() {
_levelBlockProperties = new LevelBlockProperty[1025];
memset(_levelBlockProperties, 0, 1025 * sizeof(LevelBlockProperty));
_lvlBuffer = new LVL[30];
memset(_lvlBuffer, 0, 30 * sizeof(LVL));
_lvl415 = new uint8[415];
memset(_lvl415, 0, 415);
_cLevelItems = new CLevelItem[30];
memset(_cLevelItems, 0, 30 * sizeof(CLevelItem));
_monsterProperties = new MonsterProperty[5];
memset(_monsterProperties, 0, 5 * sizeof(MonsterProperty));
_vcnExpTable = new uint8[128];
for (int i = 0; i < 128; i++)
@ -363,11 +398,10 @@ Common::Error LoLEngine::init() {
}
Common::Error LoLEngine::go() {
if (!saveFileLoadable(0)) {
setupPrologueData(true);
setupPrologueData(true);
if (!saveFileLoadable(0))
showIntro();
setupPrologueData(false);
}
preInit();
@ -400,7 +434,6 @@ Common::Error LoLEngine::go() {
case 1: // Show intro
setupPrologueData(true);
showIntro();
setupPrologueData(true);
break;
case 2: // "Lore of the Lands" (only CD version)
@ -425,21 +458,27 @@ Common::Error LoLEngine::go() {
if (processSelection == 0) {
setupPrologueData(true);
_sound->loadSoundFile("LOREINTR");
_sound->playTrack(6);
_sound->playTrack(6);
/*int character = */chooseCharacter();
_sound->playTrack(1);
_screen->fadeToBlack();
setupPrologueData(true);
}
setupPrologueData(false);
if (!shouldQuit() && (processSelection == 0 || processSelection == 3))
startup();
if (!shouldQuit() && processSelection == 0)
startupNew();
if (!shouldQuit() && (processSelection == 0 || processSelection == 3))
if (!shouldQuit() && (processSelection == 0 || processSelection == 3)) {
//_dlgAnimCallback = &TextDisplayer_LoL::portraitAnimation2;
_screen->_fadeFlag = 3;
_sceneUpdateRequired = true;
setUnkFlags(1);
runLoop();
}
return Common::kNoError;
}
@ -449,44 +488,30 @@ Common::Error LoLEngine::go() {
void LoLEngine::preInit() {
debugC(9, kDebugLevelMain, "LoLEngine::preInit()");
if (!_res->loadFileList("FILEDATA.FDT"))
error("Couldn't load file list: 'FILEDATA.FDT'");
_res->loadPakFile("GENERAL.PAK");
if (_flags.isTalkie)
_res->loadPakFile("STARTUP.PAK");
_screen->loadFont(Screen::FID_9_FNT, "FONT9P.FNT");
_screen->loadFont(Screen::FID_6_FNT, "FONT6P.FNT");
uint8 *pal = _screen->getPalette(0);
memset(pal, 0, 768);
_screen->setScreenPalette(pal);
// TODO: We need to check if the SYSEX events of intro and ingame differ.
// If they differ, we really need to setup the proper ingame SYSEX when starting
// the game. But the proper place to do it would not be in this function.
/*if (_sound->getMusicType() == Sound::kMidiMT32 || _sound->getSfxType() == Sound::kMidiMT32) {
_sound->loadSoundFile("LOLSYSEX");
_sound->playTrack(0);
while (_sound->isPlaying() && !shouldQuit())
delay(10);
}*/
if (shouldQuit())
return;
_eventList.clear();
loadTalkFile(0);
char filename[32];
snprintf(filename, sizeof(filename), "LANDS.%s", _languageExt[_lang]);
_res->exists(filename, true);
_landsFile = _res->fileData(filename, 0);
initializeCursors();
loadItemIconShapes();
}
void LoLEngine::initializeCursors() {
debugC(9, kDebugLevelMain, "LoLEngine::initializeCursors()");
void LoLEngine::loadItemIconShapes() {
debugC(9, kDebugLevelMain, "LoLEngine::loadItemIconShapes()");
if (_itemIconShapes) {
for (int i = 0; i < _numItemIconShapes; i++)
delete[] _itemIconShapes[i];
delete[] _itemIconShapes;
}
_screen->loadBitmap("ITEMICN.SHP", 3, 3, 0);
const uint8 *shp = _screen->getCPagePtr(3);
@ -512,6 +537,12 @@ void LoLEngine::setMouseCursorToItemInHand() {
_screen->setMouseCursor(o, o, getItemIconShapePtr(_itemInHand));
}
bool LoLEngine::posWithinRect(int mouseX, int mouseY, int x1, int y1, int x2, int y2) {
if (mouseX < x1 || mouseX > x2 || mouseY < y1 || mouseY > y2)
return false;
return true;
}
uint8 *LoLEngine::getItemIconShapePtr(int index) {
int ix = _itemProperties[_itemsInPlay[index].itemPropertyIndex].shpIndex;
if (_itemProperties[_itemsInPlay[index].itemPropertyIndex].flags & 0x200)
@ -585,6 +616,7 @@ void LoLEngine::startup() {
memset(_screen->getPalette(1), 0, 0x300);
memset(_screen->getPalette(2), 0, 0x300);
loadItemIconShapes();
_screen->setMouseCursor(0, 0, _itemIconShapes[0x85]);
_screen->loadBitmap("ITEMSHP.SHP", 3, 3, 0);
@ -629,19 +661,29 @@ void LoLEngine::startup() {
runInitScript("ONETIME.INF", 0);
_emc->load("ITEM.INF", &_itemScript, &_opcodes);
_tlcTable1 = new uint8[256];
_tlcTable2 = new uint8[5120];
_trueLightTable1 = new uint8[256];
_trueLightTable2 = new uint8[5120];
_loadSuppFilesFlag = 1;
_dlg->setAnimParameters("<MORE>", 10, 31, 0);
_dlg->setAnimFlag(true);
_screen->_dimLineCount = 0;
// reconfigure TIM player for ingame scripts
_tim->toggleDialogueSpeech(speechEnabled());
_tim->toggleRefresh(true);
setMouseCursorToItemInHand();
}
void LoLEngine::startupNew() {
_selectedSpell = 0;
_updateUnk2 = _compassDirectionIndex = -1;
/*
_unk3 = -1;*/
_compassUnk = 0;
_compassDirection = _compassDirectionIndex = -1;
_lastMouseRegion = -1;
_unkGameFlag |= 0x1B;
/*
_unk5 = 1;
@ -651,11 +693,12 @@ void LoLEngine::startupNew() {
_currentLevel = 1;
giveCredits(41, 0);
_inventoryItemIndex[0] = makeItem(0xd8, 0, 0);
_inventoryItemIndex[1] = makeItem(0xd9, 0, 0);
_inventoryItemIndex[2] = makeItem(0xda, 0, 0);
_inventory[0] = makeItem(0xd8, 0, 0);
_inventory[1] = makeItem(0xd9, 0, 0);
_inventory[2] = makeItem(0xda, 0, 0);
memset(_availableSpells, -1, 7);
_availableSpells[0] = 0;
setupScreenDims();
//memset(_unkWordArraySize8, 0x100, 8);
@ -670,21 +713,80 @@ void LoLEngine::startupNew() {
_screen->showMouse();
}
int LoLEngine::setUnkFlags(int unk) {
if (unk < 1 || unk > 14)
return 0;
int r = (_intFlag3 & (2 << unk)) ? 1 : 0;
_intFlag3 |= (2 << unk);
return r;
}
int LoLEngine::removeUnkFlags(int unk) {
if (unk < 1 || unk > 14)
return 0;
int r = (_intFlag3 & (2 << unk)) ? 1 : 0;
_intFlag3 &= ~(2 << unk);
return r;
}
void LoLEngine::runLoop() {
_screen->updateScreen();
setUnkFlags(2);
bool _runFlag = true;
_unkFlag |= 0x800;
while (!shouldQuit() && _runFlag) {
checkInput(0, false);
removeInputTop();
_screen->updateScreen();
_system->delayMillis(10);
if (_nextScriptFunc) {
runResidentScript(_nextScriptFunc, 2);
_nextScriptFunc = 0;
}
//processUnkAnimStructs();
//checkFloatingPointerRegions();
//processCharacters();
checkInput(0, true);
update();
if (_sceneUpdateRequired)
gui_drawScene(0);
else
runLoopSub4(0);
/*if (_partyDeathFlag != -1) {
checkForPartyDeath(_partyDeathFlag);
_partyDeathFlag = -1;
}*/
_system->delayMillis(_tickLength);
}
}
void LoLEngine::update() {
updateWsaAnimations();
if (_updateCharNum != -1 && _system->getMillis() > _updatePortraitNext)
updatePortraitWithStats();
if (_screen->_drawGuiFlag & 0x800 || !(_updateFlags & 4))
updateLampStatus();
if (_screen->_drawGuiFlag & 0x4000 && !(_updateFlags & 4) && (_compassDirection == -1 || (_currentDirection << 6) != _compassDirection || _compassUnk))
updateCompass();
snd_characterSpeaking();
restorePaletteEntry();
_screen->updateScreen();
}
#pragma mark - Localization
const char *LoLEngine::getLangString(uint16 id) {
char *LoLEngine::getLangString(uint16 id) {
debugC(9, kDebugLevelMain, "LoLEngine::getLangString(0x%.04X)", id);
if (id == 0xFFFF)
@ -701,7 +803,7 @@ const char *LoLEngine::getLangString(uint16 id) {
if (!buffer)
return 0;
const char *string = (const char *)getTableEntry(buffer, realId);
char *string = (char *)getTableEntry(buffer, realId);
char *srcBuffer = _stringBuffer[_lastUsedStringBuffer];
Util::decodeString1(string, srcBuffer);
@ -780,12 +882,39 @@ void LoLEngine::setupPrologueData(bool load) {
memset(_screen->getPalette(1), 0, 768);
} else {
delete _chargenWSA; _chargenWSA = 0;
if (!_res->loadFileList("FILEDATA.FDT"))
error("Couldn't load file list: 'FILEDATA.FDT'");
uint8 *pal = _screen->getPalette(0);
memset(pal, 0, 768);
_screen->setScreenPalette(pal);
// TODO: We need to check if the SYSEX events of intro and ingame differ.
// If they differ, we really need to setup the proper ingame SYSEX when starting
// the game. But the proper place to do it would not be in this function.
/*if (_sound->getMusicType() == Sound::kMidiMT32 || _sound->getSfxType() == Sound::kMidiMT32) {
_sound->loadSoundFile("LOLSYSEX");
_sound->playTrack(0);
while (_sound->isPlaying() && !shouldQuit())
delay(10);
}*/
if (shouldQuit())
return;
_eventList.clear();
}
}
void LoLEngine::showIntro() {
debugC(9, kDebugLevelMain, "LoLEngine::showIntro()");
uint8 *pal = _screen->getPalette(0);
memset(pal, 0, 768);
_screen->setScreenPalette(pal);
TIM *intro = _tim->load("LOLINTRO.TIM", &_timIntroOpcodes);
_screen->loadFont(Screen::FID_8_FNT, "NEW8P.FNT");
@ -828,6 +957,9 @@ void LoLEngine::showIntro() {
_tim->unload(intro);
_tim->clearLangData();
for (int i = 0; i < TIM::kWSASlots; i++)
_tim->freeAnimStruct(i);
_screen->fadePalette(_screen->getPalette(1), 30, 0);
}
@ -1236,10 +1368,9 @@ bool LoLEngine::addCharacter(int id) {
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);
if (_characters[numChars].items[i]) {
_characters[numChars].items[i] = makeItem(_characters[numChars].items[i], 0, 0);
runItemScript(numChars, _characters[numChars].items[i], 0x80, 0, 0);
}
}
@ -1301,7 +1432,7 @@ void LoLEngine::updatePortraitWithStats() {
y = 144;
redraw = true;
} else if (_updateCharV2 == 1) {
if (_unkLangAudio) {
if (textEnabled()) {
x = 90;
y = 130;
} else {
@ -1309,7 +1440,7 @@ void LoLEngine::updatePortraitWithStats() {
y = 144;
}
} else if (_updateCharV2 == 2) {
if (_unkLangAudio) {
if (textEnabled()) {
x = 16;
y = 134;
} else {
@ -1325,11 +1456,10 @@ void LoLEngine::updatePortraitWithStats() {
f -= 5;
f += 7;
if (_unkAudioSpecOffs) {
//TODO
//if (unk() == 2)
// _updateCharV1 = 2;
//else
if (_speechFlag) {
if (snd_characterSpeaking() == 2)
_updateCharV1 = 2;
else
_updateCharV1 = 1;
}
@ -1367,24 +1497,44 @@ void LoLEngine::updatePortraits() {
void LoLEngine::updatePortraitUnkTimeSub(int unk1, int unk2) {
if (_updateCharV4 == unk1 || !unk1) {
_updateCharV5 = 1;
_updateCharTime = _system->getMillis();
_restorePalette = 1;
_palUpdateTimer = _system->getMillis();
}
if (!unk2)
return;
updatePortraits();
if (_updateCharV6) {
if (_hideInventory) {
_screen->hideMouse();
_screen->clearDim(3);
_screen->showMouse();
}
_updateCharV5 = 0;
_restorePalette = 0;
//initGuiUnk(11);
}
void LoLEngine::charCallback4(int redraw) {
for (int i = 0; i < 3; i++) {
if (!(_characters[i].flags & 1) || (_characters[i].flags & 8) || (_characters[i].curFaceFrame > 1))
continue;
if (_characters[i].curFaceFrame == 1) {
_characters[i].curFaceFrame = 0;
gui_drawCharPortraitWithStats(i);
_characters[i].rand = _rnd.getRandomNumberRng(1, 12);
} else {
_characters[i].rand--;
if (_characters[i].rand <= 0 && !redraw) {
_characters[i].curFaceFrame = 1;
gui_drawCharPortraitWithStats(i);
//resetAnimStructs(9, 0, 1);
}
}
}
}
void LoLEngine::setCharFaceFrame(int charNum, int frameNum) {
_characters[charNum].curFaceFrame = frameNum;
}
@ -1402,32 +1552,224 @@ void LoLEngine::faceFrameRefresh(int charNum) {
}
void LoLEngine::setupScreenDims() {
if (_unkLangAudio)
if (textEnabled()) {
_screen->modifyScreenDim(4, 11, 124, 28, 45);
else
_screen->modifyScreenDim(5, 85, 123, 233, 54);
} else {
_screen->modifyScreenDim(4, 11, 124, 28, 9);
_screen->modifyScreenDim(5, 85, 123, 233, 18);
_screen->modifyScreenDim(5, 85, 123, 233, 18);
}
}
void LoLEngine::initDialogueSequence(int controlMode) {
unkHideInventory();
gui_prepareForSequence(112, 0, 176, 120, controlMode);
_updateFlags |= 3;
_dlg->setupField(true);
_dlg->expandField();
setupScreenDims();
gui_disableControls(controlMode);
}
void LoLEngine::toggleSelectedCharacterFrame(bool mode) {
if (countActiveCharacters() == 1)
return;
int col = mode ? 212 : 1;
int cp = _screen->setCurPage(0);
int x = _activeCharsXpos[_selectedCharacter];
_screen->drawBox(x, 143, x + 65, 176, col);
_screen->setCurPage(cp);
}
void LoLEngine::unkHideInventory() {
_hideInventory = 1;
if (!textEnabled() || !(_hideControls & 2))
charCallback4(1);
removeUnkFlags(2);
}
void LoLEngine::gui_prepareForSequence(int x, int y, int w, int h, int unk) {
//resetGuiUnk(x, y, w, h, unk);
_preSeq_X1 = x;
_preSeq_Y1 = y;
_preSeq_X2 = x + w;
_preSeq_Y2 = y + h;
int mouseOffs = _itemInHand ? 10 : 0;
_screen->setMouseCursor(mouseOffs, mouseOffs, getItemIconShapePtr(_itemInHand));
_lastMouseRegion = -1;
if (w == 320) {
setLampMode(0);
_lampStatusSuspended = true;
}
}
void LoLEngine::restoreSceneAfterDialogueSequence(int redraw) {
gui_enableControls();
_dlg->setupField(false);
_updateFlags &= 0xffdf;
//loadLevel_initGui()
for (int i = 0; i < 6; i++)
_tim->freeAnimStruct(i);
_updateFlags = 0;
if (redraw) {
if (_screen->_fadeFlag != 2)
_screen->fadeClearSceneWindow(10);
gui_drawPlayField();
_screen->setPaletteBrightness(_screen->_currentPalette, _brightness, _lampOilStatus);
_screen->_fadeFlag = 0;
}
_hideInventory = 0;
}
void LoLEngine::restorePaletteEntry() {
if (!_restorePalette)
return;
_screen->copyColour(192, 252, _system->getMillis() - _palUpdateTimer, 60 * _tickLength);
if (_hideInventory)
return;
_screen->clearDim(3);
///initGuiUnk(11);
_restorePalette = 0;
}
void LoLEngine::updateWsaAnimations() {
if (_updateFlags & 8)
return;
//TODO
}
void LoLEngine::loadTalkFile(int index) {
char file[8];
if (index == _curTlkFile)
return;
if (_curTlkFile >= 0) {
if (_curTlkFile > 0 && index > 0) {
snprintf(file, sizeof(file), "%02d.TLK", _curTlkFile);
_res->unloadPakFile(file);
}
if (index > 0)
_curTlkFile = index;
snprintf(file, sizeof(file), "%02d.TLK", index);
_res->loadPakFile(file);
_curTlkFile = index;
}
void LoLEngine::snd_playVoiceFile(int) {
bool LoLEngine::snd_playCharacterSpeech(int id, int8 speaker, int) {
if (!_speechFlag)
return true;
if (speaker < 65) {
if (_characters[speaker].flags & 1)
speaker = (int) _characters[speaker].name[0];
else
speaker = 0;
}
if (_lastSpeechId == id && speaker == _lastSpeaker)
return true;
_lastSpeechId = id;
_lastSpeaker = speaker;
Common::List<const char*> playList;
char pattern1[8];
char pattern2[5];
char file1[13];
char file2[13];
snprintf(pattern2, sizeof(pattern2), "%02d", id & 0x4000 ? 0 : _curTlkFile);
if (id & 0x4000) {
snprintf(pattern1, sizeof(pattern1), "%03X", id & 0x3fff);
} else if (id < 1000) {
snprintf(pattern1, sizeof(pattern1), "%03d", id);
} else {
snprintf(pattern1, sizeof(pattern1), "@%04d", id - 1000);
}
for (char i = '0'; i != -1; i++) {
snprintf(file1, sizeof(file1), "%s%c%c.%s", pattern1, (char)speaker, i, pattern2);
snprintf(file2, sizeof(file2), "%s%c%c.%s", pattern1, '_', i, pattern2);
if (_res->exists(file1)) {
char *f = new char[strlen(file1) + 1];
strcpy(f, file1);
playList.push_back(f);
} else if (_res->exists(file2)) {
char *f = new char[strlen(file2) + 1];
strcpy(f, file2);
playList.push_back(f);
} else {
i = -2;
}
}
if (playList.empty())
return false;
do {
update();
if (snd_characterSpeaking() == 0)
break;
} while (_sound->voiceIsPlaying());
strcpy(_activeVoiceFile, *playList.begin());
_tim->setActiveSpeechFile(_activeVoiceFile);
_sound->voicePlayFromList(playList);
for (Common::List<const char*>::iterator i = playList.begin(); i != playList.end(); i++)
delete []*i;
playList.clear();
_tim->setDialogueCompleteFlag(0);
return true;
}
int LoLEngine::snd_characterSpeaking() {
if (_sound->voiceIsPlaying(_activeVoiceFile))
return 2;
_lastSpeechId = _lastSpeaker = -1;
return 1;
}
int LoLEngine::snd_dialogueSpeechUpdate(int finish) {
if (!_sound->voiceIsPlaying(_activeVoiceFile))
return -1;
//_dlgTimer = 0;
if (finish)
_tim->setDialogueCompleteFlag(1);
return 1;
}
void LoLEngine::snd_playSoundEffect(int track, int volume) {
@ -1508,5 +1850,14 @@ int LoLEngine::snd_stopMusic() {
return snd_playTrack(-1);
}
void LoLEngine::runLoopSub4(int a) {
cmzS7(a, _currentBlock);
}
void LoLEngine::calcCoordinates(uint16 & x, uint16 & y, int block, uint16 xOffs, uint16 yOffs) {
x = (block & 0x1f) << 8 | xOffs;
y = ((block & 0xffe0) << 3) | yOffs;
}
} // end of namespace Kyra

View file

@ -29,6 +29,9 @@
#include "kyra/kyra_v1.h"
#include "kyra/script_tim.h"
#include "kyra/script.h"
#include "kyra/sound.h"
#include "kyra/gui_lol.h"
#include "kyra/text_lol.h"
#include "common/list.h"
@ -107,20 +110,35 @@ struct LevelBlockProperty {
uint8 flags;
};
struct LVL {
struct MonsterProperty {
uint8 id;
uint8 maxWidth;
uint16 unk[9];
uint16 *pos;
uint16 unk2[8];
uint16 unk3[8];
uint16 unk4[2];
uint8 b;
uint16 unk5[2];
uint16 unk6[5];
uint8 unk7[4];
uint8 unk8[3];
};
struct CLevelItem {
uint16 itemIndexUnk;
uint8 field_2;
uint16 field_3;
uint8 unk2;
uint16 unk3;
uint16 blockPropertyIndex;
uint16 p_1a;
uint16 p_1b;
int8 level;
uint16 p_2a;
uint16 p_2b;
uint8 field_10;
uint8 field_11;
uint8 field_12;
uint8 field_13;
uint16 itemPosX;
uint16 itemPosY;
uint8 field10;
uint16 anon8;
uint8 anon9;
uint8 field_14;
uint8 field_15;
uint8 field_16;
@ -132,7 +150,7 @@ struct LVL {
int16 field_1D;
uint8 field_1F;
uint8 field_20;
uint8 *offs_lvl415;
MonsterProperty *monsters;
uint8 field_25;
uint8 field_26;
uint8 field_27;
@ -145,6 +163,34 @@ struct LVL {
uint8 field_2E;
};
struct ItemInPlay {
uint16 itemIndexUnk;
uint8 unk2;
uint16 unk3;
uint16 blockPropertyIndex;
uint16 p_1a;
uint16 p_1b;
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;
int8 unk8;
uint8 unk9;
uint8 unkA;
uint16 unkB;
uint8 unkD;
};
struct LevelShapeProperty {
uint16 shapeIndex[10];
uint8 scaleFlag[10];
@ -161,26 +207,31 @@ struct CompassDef {
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;
struct ButtonDef {
uint16 buttonflags;
uint8 clickedShapeId;
uint8 unk1;
uint16 unk2;
int16 x;
int16 y;
uint16 w;
uint16 h;
uint16 index;
uint16 flag;
};
class LoLEngine : public KyraEngine_v1 {
friend class GUI_LoL;
friend class TextDisplayer_LoL;
public:
LoLEngine(OSystem *system, const GameFlags &flags);
~LoLEngine();
Screen *screen();
GUI *gui() const;
private:
Screen_LoL *_screen;
GUI_LoL *_gui;
TIMInterpreter *_tim;
Common::Error init();
@ -190,18 +241,28 @@ private:
void initStaticResource();
void preInit();
void initializeCursors();
void loadItemIconShapes();
int mainMenu();
void startup();
void startupNew();
// main loop
void runLoop();
void update();
int setUnkFlags(int unk);
int removeUnkFlags(int unk);
int _intFlag3;
// mouse
void setMouseCursorToIcon(int icon);
void setMouseCursorToItemInHand();
uint8 *getItemIconShapePtr(int index);
bool posWithinRect(int mouseX, int mouseY, int x1, int y1, int x2, int y2);
int _floatingMouseArrowControl;
// intro
void setupPrologueData(bool load);
@ -257,20 +318,25 @@ private:
// sound
void loadTalkFile(int index);
void snd_playVoiceFile(int);
void snd_playVoiceFile(int track) {}
bool snd_playCharacterSpeech(int id, int8 speaker, int);
int snd_characterSpeaking();
int snd_dialogueSpeechUpdate(int finish);
void snd_playSoundEffect(int track, int volume);
void snd_loadSoundFile(int track);
int snd_playTrack(int track);
int snd_stopMusic();
int _lastSpeechId;
int _lastSpeaker;
char _activeVoiceFile[13];
int _lastSfxTrack;
int _lastMusicTrack;
int _curMusicFileIndex;
char _curMusicFileExt;
int _curTlkFile;
int _unkAudioSpecOffs;
bool _unkLangAudio;
int _curTlkFile;
int _speechFlag;
char **_ingameSoundList;
int _ingameSoundListSize;
@ -289,7 +355,7 @@ private:
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_drawBox(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);
@ -298,14 +364,63 @@ private:
void gui_drawCompass();
void gui_drawScroll();
int gui_enableControls();
int gui_disableControls(int controlMode);
void gui_disableArrowButton(int shapeIndex, int mode);
void gui_toggleFightButtons(bool disable);
void gui_prepareForSequence(int x, int y, int w, int h, int unk);
bool _weaponsDisabled;
int _unkDrawPortraitIndex;
int _updateUnk2;
int _lastArrowButtonShape;
uint32 _arrowButtonTimer;
int _selectedCharacter;
int _compassDirection;
int _compassUnk;
int _compassDirectionIndex;
const CompassDef *_compassDefs;
int _compassDefsSize;
void initButtonList();
ButtonDef *_buttonData;
Button *_buttonList;
int clickedUpArrow(Button *button);
int clickedDownArrow(Button *button);
int clickedLeftArrow(Button *button);
int clickedRightArrow(Button *button);
int clickedTurnLeftArrow(Button *button);
int clickedTurnRightArrow(Button *button);
int clickedAttackButton(Button *button);
int clickedMagicButton(Button *button);
int clickedUnk9(Button *button);
int clickedScreen(Button *button);
int clickedPortraitLeft(Button *button);
int clickedLiveMagicBarsLeft(Button *button);
int clickedPortraitEtcRight(Button *button);
int clickedUnk14(Button *button);
int clickedUnk15(Button *button);
int clickedUnk16(Button *button);
int clickedUnk17(Button *button);
int clickedInventorySlot(Button *button);
int clickedInventoryScroll(Button *button);
int clickedUnk20(Button *button);
int clickedUnk21(Button *button);
int clickedScroll(Button *button);
int clickedUnk23(Button *button);
int clickedUnk24(Button *button);
int clickedUnk25(Button *button);
int clickedOptions(Button *button);
int clickedRestParty(Button *button);
int clickedUnk28(Button *button);
int clickedUnk29(Button *button);
int clickedUnk30(Button *button);
int clickedUnk31(Button *button);
int clickedUnk32(Button *button);
// text
TextDisplayer_LoL *_dlg;
// emc scripts
void runInitScript(const char *filename, int func);
void runInfScript(const char *filename);
@ -318,7 +433,7 @@ private:
uint8 _unkScriptByte;
uint16 _currentDirection;
uint16 _currentBlock;
bool _boolScriptFuncDone;
bool _sceneUpdateRequired;
int16 _scriptExecutedFuncs[18];
uint16 _gameFlags[15];
uint16 _unkEMC46[16];
@ -338,17 +453,32 @@ private:
int olol_loadLevelShapes(EMCState *script);
int olol_closeLevelShapeFile(EMCState *script);
int olol_loadDoorShapes(EMCState *script);
int olol_initAnimStruct(EMCState *script);
int olol_freeAnimStruct(EMCState *script);
int olol_setMusicTrack(EMCState *script);
int olol_getUnkArrayVal(EMCState *script);
int olol_setUnkArrayVal(EMCState *script);
int olol_setGlobalVar(EMCState *script);
int olol_mapShapeToBlock(EMCState *script);
int olol_resetBlockShapeAssignment(EMCState *script);
int olol_loadMonsterProperties(EMCState *script);
int olol_loadTimScript(EMCState *script);
int olol_runTimScript(EMCState *script);
int olol_releaseTimScript(EMCState *script);
int olol_initDialogueSequence(EMCState *script);
int olol_restoreSceneAfterDialogueSequence(EMCState *script);
int olol_loadLangFile(EMCState *script);
int olol_stopTimScript(EMCState *script);
int olol_loadSoundFile(EMCState *script);
int olol_setPaletteBrightness(EMCState *script);
int olol_playDialogueTalkText(EMCState *script);
int olol_setNextFunc(EMCState *script);
int olol_assignCustomSfx(EMCState *script);
// tim scripts
TIMInterpreter::Animation *initTimAnimStruct(int index, const char *filename, int x, int y, uint16 copyPara, uint16 wsaFlags);
TIM *_activeTim[10];
// tim opcode
void setupOpcodeTable();
@ -359,6 +489,8 @@ private:
int tlol_processWsaFrame(const TIM *tim, const uint16 *param);
int tlol_displayText(const TIM *tim, const uint16 *param);
Common::Array<const TIMOpcode*> _timIngameOpcodes;
// translation
int _lang;
@ -368,13 +500,19 @@ private:
int _lastUsedStringBuffer;
char _stringBuffer[5][512]; // TODO: The original used a size of 512, it looks a bit large.
// Maybe we can someday reduce the size.
const char *getLangString(uint16 id);
char *getLangString(uint16 id);
uint8 *getTableEntry(uint8 *buffer, uint16 id);
static const char * const _languageExt[];
// graphics
void setupScreenDims();
void initDialogueSequence(int controlMode);
void unkHideInventory();
void restoreSceneAfterDialogueSequence(int redraw);
void toggleSelectedCharacterFrame(bool mode);
void restorePaletteEntry();
void updateWsaAnimations();
uint8 **_itemIconShapes;
int _numItemIconShapes;
@ -405,21 +543,21 @@ private:
void updatePortraitWithStats();
void updatePortraits();
void updatePortraitUnkTimeSub(int unk1, int unk2);
void charCallback4(int redraw);
void setCharFaceFrame(int charNum, int frameNum);
void faceFrameRefresh(int charNum);
LoLCharacter *_characters;
uint16 _activeCharsXpos[3];
int _charFlagUnk;
int _updateFlags;
int _updateCharNum;
int _updateCharV1;
int _updateCharV2;
int _updateCharV3;
int _updateCharV4;
int _updateCharV5;
int _updateCharV6;
uint32 _updateCharTime;
int _restorePalette;
int _hideInventory;
uint32 _palUpdateTimer;
uint32 _updatePortraitNext;
int _loadLevelFlag;
@ -433,19 +571,30 @@ private:
const LoLCharacter *_charDefaults;
int _charDefaultsSize;
// lamp
void resetLampStatus();
void setLampMode(bool lampOn);
void updateLampStatus();
int _lampOilStatus;
int _brightness;
int _lampStatusUnk;
uint32 _lampStatusTimer;
bool _lampStatusSuspended;
// 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 initCMZ1(CLevelItem *l, int a);
void initCMZ2(CLevelItem *l, uint16 a, uint16 b);
int cmzS1(uint16 x1, uint16 y1, uint16 x2, uint16 y2);
void cmzS2(CLevelItem *l, int a);
void cmzS3(CLevelItem *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 cmzS7(int a, int block);
void loadLevelWLL(int index, bool mapShapes);
void moveItemToBlock(uint16 *cmzItemIndex, uint16 item);
int assignLevelShapes(int index);
@ -484,17 +633,15 @@ private:
void drawScriptShapes(int pageNum);
void updateSceneWindow();
void turnOnLamp();
void updateLampStatus();
void updateCompass();
void moveParty(uint16 direction, int unk1, int unk2, int unk3);
uint16 calcNewBlockPostion(uint16 curBlock, uint16 direction);
void setLF1(uint16 & a, uint16 & b, int block, uint16 d, uint16 e);
void setLF2(int block);
int _unkFlag;
int _scriptFuncIndex;
int _nextScriptFunc;
uint8 _currentLevel;
bool _loadLevelFlag2;
int _lvlBlockIndex;
@ -520,16 +667,11 @@ private:
int _sceneDrawVar3;
int _wllProcessFlag;
uint8 *_tlcTable2;
uint8 *_tlcTable1;
uint8 *_trueLightTable2;
uint8 *_trueLightTable1;
int _loadSuppFilesFlag;
int _lampOilStatus;
int _brightness;
int _lampStatusUnk;
uint32 _lampStatusTimer;
uint8 *_wllVmpMap;
int8 *_wllShapeMap;
uint8 *_wllBuffer3;
@ -542,11 +684,11 @@ private:
LevelBlockProperty *_levelBlockProperties;
LevelBlockProperty *_curBlockCaps[18];
LVL *_lvlBuffer;
uint8 *_lvl415;
CLevelItem *_cLevelItems;
MonsterProperty *_monsterProperties;
uint16 _unkCmzU1;
uint16 _unkCmzU2;
uint16 _partyPosX;
uint16 _partyPosY;
Common::SeekableReadStream *_lvlShpFileHandle;
uint16 _lvlShpNum;
@ -559,6 +701,8 @@ private:
int16 _dmScaleW;
int16 _dmScaleH;
int _lastMouseRegion;
int _preSeq_X1, _preSeq_Y1, _preSeq_X2, _preSeq_Y2;
uint8 _unkGameFlag;
uint8 *_tempBuffer5120;
@ -616,39 +760,11 @@ private:
int _sceneDrawPage2;
// items
struct ItemInPlay {
uint16 itemIndexUnk;
uint8 unk2;
uint16 unk3;
uint16 blockPropertyIndex;
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);
CLevelItem *findItem(uint16 index);
void runItemScript(int reg1, int item, int reg0, int reg3, int reg4);
uint8 _moneyColumnHeight[5];
@ -658,12 +774,16 @@ private:
ItemProperty *_itemProperties;
int _itemInHand;
uint16 _inventoryItemIndex[48];
uint16 _inventory[48];
int _inventoryCurItem;
int _unkInventFlag;
int _hideControls;
EMCData _itemScript;
// misc
void runLoopSub4(int a);
void calcCoordinates(uint16 & x, uint16 & y, int block, uint16 xOffs, uint16 yOffs);
// spells
int8 _availableSpells[7];
int _selectedSpell;

View file

@ -65,6 +65,7 @@ MODULE_OBJS := \
staticres.o \
text.o \
text_lok.o \
text_lol.o \
text_hof.o \
text_mr.o \
timer.o \

View file

@ -35,7 +35,7 @@ namespace Kyra {
void LoLEngine::loadLevel(int index) {
_unkFlag |= 0x800;
setMouseCursorToIcon(0x85);
_scriptFuncIndex = 0;
_nextScriptFunc = 0;
snd_stopMusic();
@ -57,7 +57,7 @@ void LoLEngine::loadLevel(int index) {
// TODO
_currentLevel = index;
_charFlagUnk = 0;
_updateFlags = 0;
// TODO
@ -111,32 +111,33 @@ void LoLEngine::addLevelItems() {
int LoLEngine::initCmzWithScript(int block) {
int i = _levelBlockProperties[block].itemIndex;
int cnt = 0;
CLevelItem *t = 0;
while (i) {
void *t = cmzGetItemOffset(i);
i = (i & 0x8000) ? ((LVL*)t)->itemIndexUnk : ((ItemInPlay*)t)->itemIndexUnk;
while (i) {
t = findItem(i);
i = t->itemIndexUnk;
if (!(i & 0x8000))
continue;
i &= 0x7fff;
LVL *l = &_lvlBuffer[i];
t = &_cLevelItems[i];
cnt++;
initCMZ1(l, 14);
initCMZ1(t, 14);
checkScriptUnk(l->blockPropertyIndex);
checkScriptUnk(t->blockPropertyIndex);
initCMZ2(l, 0, 0);
initCMZ2(t, 0, 0);
}
return cnt;
}
void LoLEngine::initCMZ1(LVL *l, int a) {
void LoLEngine::initCMZ1(CLevelItem *l, int a) {
if (l->field_14 == 13 && a != 14)
return;
if (a == 7) {
l->p_2a = _unkCmzU1;
l->p_2b = _unkCmzU2;
l->itemPosX = _partyPosX;
l->itemPosY = _partyPosX;
}
if (l->field_14 == 1 && a == 7) {
@ -145,9 +146,9 @@ void LoLEngine::initCMZ1(LVL *l, int a) {
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));
l->itemPosX = _partyPosX;
l->itemPosY = _partyPosY;
cmzS2(l, cmzS1(l->p_1a, l->p_1b, l->itemPosX, l->itemPosY));
}
} else {
l->field_14 = a;
@ -168,7 +169,7 @@ void LoLEngine::initCMZ1(LVL *l, int a) {
}
void LoLEngine::initCMZ2(LVL *l, uint16 a, uint16 b) {
void LoLEngine::initCMZ2(CLevelItem *l, uint16 a, uint16 b) {
bool cont = true;
int t = l->blockPropertyIndex;
if (l->blockPropertyIndex) {
@ -184,7 +185,7 @@ void LoLEngine::initCMZ2(LVL *l, uint16 a, uint16 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;
l->anon9 = (++l->anon9) & 3;
}
if (l->blockPropertyIndex == 0)
@ -193,34 +194,64 @@ void LoLEngine::initCMZ2(LVL *l, uint16 a, uint16 b) {
cmzS6(_levelBlockProperties[l->blockPropertyIndex].itemIndex, ((uint16)l->field_16) | 0x8000);
_levelBlockProperties[l->blockPropertyIndex].field_8 = 5;
checkScriptUnk(l->blockPropertyIndex);
uint8 *v = l->offs_lvl415;
if (v[80] == 0 || cont == false)
if (l->monsters->unk8[0] == 0 || cont == false)
return;
if ((!(READ_LE_UINT16(&v[62]) & 0x100) || ((l->field_13 & 1) == 0)) && l->blockPropertyIndex == t)
if ((!(l->monsters->unk5[0] & 0x100) || ((l->anon9 & 1) == 0)) && l->blockPropertyIndex == t)
return;
if (l->blockPropertyIndex != t)
runResidentScriptCustom(l->blockPropertyIndex, 0x800, -1, l->field_16, 0, 0);
if (_charFlagUnk & 1)
if (_updateFlags & 1)
return;
cmzS7(l->offs_lvl415[50], l->blockPropertyIndex);
cmzS7(l->monsters->unk3[5], l->blockPropertyIndex);
}
int LoLEngine::cmzS1(uint16 a, uint16 b, uint16 c, uint16 d) {
// TODO
int LoLEngine::cmzS1(uint16 x1, uint16 y1, uint16 x2, uint16 y2) {
int16 r = 0;
int16 t1 = y1 - y2;
if (t1 < 0) {
r++;
t1 = -t1;
}
return 0;
r <<= 1;
int16 t2 = x2 - x1;
if (t2 < 0) {
r++;
t2 = -t2;
}
uint8 f = 0;
if (t2 >= t1) {
if (t2 > t1)
f = 1;
SWAP(t1, t2);
}
r = (r << 1) | f;
t1 = (t1 + 1) >> 1;
f = 0;
f = (t2 > t1) ? 1 : 0;
r = (r << 1) | f;
static const uint8 Retv[] = { 1, 2, 1, 0, 7, 6, 7, 0, 3, 2, 3, 4, 5, 6, 5, 4};
return Retv[r];
}
void LoLEngine::cmzS2(LVL *l, int a) {
void LoLEngine::cmzS2(CLevelItem *l, int a) {
// TODO
}
void LoLEngine::cmzS3(LVL *l) {
void LoLEngine::cmzS3(CLevelItem *l) {
// TODO
}
@ -237,7 +268,7 @@ void LoLEngine::cmzS6(uint16 &itemIndex, int a) {
// TODO
}
void LoLEngine::cmzS7(int itemIndex, int a) {
void LoLEngine::cmzS7(int a, int block) {
if (!(_unkGameFlag & 1))
return;
@ -245,24 +276,28 @@ void LoLEngine::cmzS7(int itemIndex, int a) {
}
void LoLEngine::moveItemToBlock(uint16 *cmzItemIndex, uint16 item) {
uint16 *tmp = 0;
while (*cmzItemIndex & 0x8000) {
tmp = (uint16*) cmzGetItemOffset(*cmzItemIndex);
cmzItemIndex = tmp;
}
uint16 *t = (uint16*) cmzGetItemOffset(*cmzItemIndex);
CLevelItem *tmp = 0;
while (*cmzItemIndex & 0x8000) {
tmp = findItem(*cmzItemIndex);
cmzItemIndex = &tmp->itemIndexUnk;
}
tmp = findItem(item);
tmp->level = -1;
((ItemInPlay*)t)->level = -1;
uint16 ix = *cmzItemIndex;
if (ix == item)
return;
*cmzItemIndex = item;
cmzItemIndex = t;
cmzItemIndex = &tmp->itemIndexUnk;
while (*cmzItemIndex)
cmzItemIndex = (uint16*) cmzGetItemOffset(*cmzItemIndex);
while (*cmzItemIndex) {
tmp = findItem(*cmzItemIndex);
cmzItemIndex = &tmp->itemIndexUnk;
}
*cmzItemIndex = ix;
}
@ -394,10 +429,10 @@ void LoLEngine::loadLevelCmzFile(int index) {
_levelBlockProperties[i].flags = *t++;
for (int i = 0; i < 30; i++) {
if (_lvlBuffer[i].blockPropertyIndex) {
_lvlBuffer[i].blockPropertyIndex = 0;
_lvlBuffer[i].offs_lvl415 = _lvl415 + _lvlBuffer[i].field_20;
initCMZ2(&_lvlBuffer[i], _lvlBuffer[i].p_1a, _lvlBuffer[i].p_1b);
if (_cLevelItems[i].blockPropertyIndex) {
_cLevelItems[i].blockPropertyIndex = 0;
_cLevelItems[i].monsters = _monsterProperties + _cLevelItems[i].field_20;
initCMZ2(&_cLevelItems[i], _cLevelItems[i].p_1a, _cLevelItems[i].p_1b);
}
}
@ -413,15 +448,15 @@ void LoLEngine::loadCMZ_Sub(int index1, int index2) {
//int r = 0;
for (int i = 0; i < 30; i++) {
if (_lvlBuffer[i].field_14 >= 14 || _lvlBuffer[i].blockPropertyIndex == 0 || _lvlBuffer[i].field_1D <= 0)
if (_cLevelItems[i].field_14 >= 14 || _cLevelItems[i].blockPropertyIndex == 0 || _cLevelItems[i].field_1D <= 0)
continue;
int t = (val * _lvlBuffer[i].field_1D) >> 8;
_lvlBuffer[i].field_1D = t;
int t = (val * _cLevelItems[i].field_1D) >> 8;
_cLevelItems[i].field_1D = t;
if (index2 < index1)
_lvlBuffer[i].field_1D++;
if (_lvlBuffer[i].field_1D == 0)
_lvlBuffer[i].field_1D = 1;
_cLevelItems[i].field_1D++;
if (_cLevelItems[i].field_1D == 0)
_cLevelItems[i].field_1D = 1;
}
}
@ -475,7 +510,7 @@ void LoLEngine::loadMonsterShapes(const char *file, int monsterIndex, int b) {
memset(_monsterPalettes[pos + i], 0, size);
}
/*for (int i = 0; i < 4; i++) {
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;
@ -483,7 +518,7 @@ void LoLEngine::loadMonsterShapes(const char *file, int monsterIndex, int b) {
////TODO
}
}*/
}
_monsterUnk[monsterIndex] = b & 0xff;
uint8 *tsh = _screen->makeShapeCopy(p, 16);
@ -678,8 +713,8 @@ void LoLEngine::loadLevelGraphics(const char *file, int specialColor, int weight
char tname[13];
snprintf(tname, sizeof(tname), "LEVEL%.02d.TLC", _currentLevel);
Common::SeekableReadStream *s = _res->createReadStream(tname);
s->read(_tlcTable1, 256);
s->read(_tlcTable2, 5120);
s->read(_trueLightTable1, 256);
s->read(_trueLightTable2, 5120);
delete s;
_loadSuppFilesFlag = 1;
@ -689,10 +724,10 @@ void LoLEngine::resetItems(int flag) {
for (int i = 0; i < 1024; i++) {
_levelBlockProperties[i].field_8 = 5;
uint16 id = _levelBlockProperties[i].itemIndex;
LVL *r = 0;
CLevelItem *r = 0;
while (id & 0x8000) {
r = (LVL*)cmzGetItemOffset(id);
r = (CLevelItem*)findItem(id);
assert(r);
id = r->itemIndexUnk;
}
@ -711,9 +746,9 @@ void LoLEngine::resetItems(int flag) {
}
void LoLEngine::resetLvlBuffer() {
memset(_lvlBuffer, 0, 30 * sizeof(LVL));
memset(_cLevelItems, 0, 30 * sizeof(CLevelItem));
for (int i = 0; i < 30; i++)
_lvlBuffer[i].field_14 = 0x10;
_cLevelItems[i].field_14 = 0x10;
}
void LoLEngine::resetBlockProperties() {
@ -739,17 +774,26 @@ bool LoLEngine::testWallInvisibility(int block, int direction) {
return true;
}
void LoLEngine::turnOnLamp() {
void LoLEngine::resetLampStatus() {
_screen->_drawGuiFlag |= 0x400;
_lampOilStatus = 255;
updateLampStatus();
}
void LoLEngine::setLampMode(bool lampOn) {
_screen->_drawGuiFlag &= 0xFBFF;
if (!(_screen->_drawGuiFlag & 0x800) || !lampOn)
return;
_screen->drawShape(0, _gameShapes[43], 291, 56, 0, 0);
_lampOilStatus = 8;
}
void LoLEngine::updateLampStatus() {
uint8 newLampOilStatus = 0;
uint8 tmp2 = 0;
if ((_charFlagUnk & 4) || !(_screen->_drawGuiFlag & 0x800))
if ((_updateFlags & 4) || !(_screen->_drawGuiFlag & 0x800))
return;
if (!_brightness || !_lampStatusUnk) {
@ -790,6 +834,10 @@ void LoLEngine::updateLampStatus() {
_lampOilStatus = newLampOilStatus;
}
void LoLEngine::updateCompass() {
}
void LoLEngine::moveParty(uint16 direction, int unk1, int unk2, int unk3) {
// TODO
_currentBlock = calcNewBlockPostion(_currentBlock, direction);
@ -801,12 +849,6 @@ uint16 LoLEngine::calcNewBlockPostion(uint16 curBlock, uint16 direction) {
return (curBlock + blockPosTable[direction]) & 0x3ff;
}
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;
@ -833,23 +875,24 @@ void LoLEngine::drawScene(int pageNum) {
drawVcnBlocks(_vcnBlocks, _blockDrawingBuffer, _vcnShift, _sceneDrawPage1);
drawSceneShapes();
if (pageNum) {
if (!pageNum) {
drawScriptShapes(_sceneDrawPage1);
_screen->copyRegion(112, 112, 0, 0, 176, 120, _sceneDrawPage1, _sceneDrawPage2);
_screen->copyRegion(112, 112, 0, 0, 176, 120, _sceneDrawPage1, 0);
_screen->copyRegion(112, 0, 112, 0, 176, 120, _sceneDrawPage1, _sceneDrawPage2, Screen::CR_NO_P_CHECK);
_screen->copyRegion(112, 0, 112, 0, 176, 120, _sceneDrawPage1, 0, Screen::CR_NO_P_CHECK);
_sceneDrawPage1 ^= _sceneDrawPage2;
_sceneDrawPage2 ^= _sceneDrawPage1;
_sceneDrawPage1 ^= _sceneDrawPage2;
}
runLoopSub4(0);
gui_drawCompass();
_boolScriptFuncDone = false;
_sceneUpdateRequired = false;
}
void LoLEngine::updateSceneWindow() {
_screen->hideMouse();
_screen->copyRegion(112, 0, 112, 0, 176, 120, 0, _sceneDrawPage2);
_screen->copyRegion(112, 0, 112, 0, 176, 120, 0, _sceneDrawPage2, Screen::CR_NO_P_CHECK);
_screen->showMouse();
}
@ -1427,9 +1470,9 @@ void LoLEngine::drawDoorOrMonsterShape(uint8 *shape, uint8 *table, int x, int y,
if (flg & 0x1000) {
if (table)
_screen->drawShape(_sceneDrawPage1, shape, x, y, 13, flg | 0x9104, table, ovl, 1, _tlcTable1, _tlcTable2, _dmScaleW, _dmScaleH);
_screen->drawShape(_sceneDrawPage1, shape, x, y, 13, flg | 0x9104, table, ovl, 1, _trueLightTable1, _trueLightTable2, _dmScaleW, _dmScaleH);
else
_screen->drawShape(_sceneDrawPage1, shape, x, y, 13, flg | 0x1104, ovl, 1, _tlcTable1, _tlcTable2, _dmScaleW, _dmScaleH);
_screen->drawShape(_sceneDrawPage1, shape, x, y, 13, flg | 0x1104, ovl, 1, _trueLightTable1, _trueLightTable2, _dmScaleW, _dmScaleH);
} else {
if (table)
_screen->drawShape(_sceneDrawPage1, shape, x, y, 13, flg | 0x8104, table, ovl, 1, _dmScaleW, _dmScaleH);

View file

@ -44,6 +44,8 @@ Screen_LoL::Screen_LoL(LoLEngine *vm, OSystem *system) : Screen_v2(vm, system),
_fadeFlag = 2;
_drawGuiFlag = 0;
_curDimIndex = 0;
_dimLineCount = 0;
}
Screen_LoL::~Screen_LoL() {
@ -63,6 +65,8 @@ void Screen_LoL::setScreenDim(int dim) {
debugC(9, kDebugLevelScreen, "Screen_LoL::setScreenDim(%d)", dim);
assert(dim < _screenDimTableCount);
_curDim = _customDimTable[dim] ? (const ScreenDim *)_customDimTable[dim] : &_screenDimTable[dim];
_curDimIndex = dim;
_dimLineCount = 0;
}
const ScreenDim *Screen_LoL::getScreenDim(int dim) {
@ -89,6 +93,7 @@ void Screen_LoL::clearDim(int dim) {
void Screen_LoL::clearCurDim() {
fillRect(_curDim->sx << 3, _curDim->sy, ((_curDim->sx + _curDim->w) << 3) - 1, (_curDim->sy + _curDim->h) - 1, _curDim->unkA);
_dimLineCount = 0;
}
void Screen_LoL::fprintString(const char *format, int x, int y, uint8 col1, uint8 col2, uint16 flags, ...) {
@ -277,6 +282,22 @@ void Screen_LoL::drawGridBox(int x, int y, int w, int h, int col) {
}
}
void Screen_LoL::fadeClearSceneWindow(int delay) {
if (_fadeFlag == 1)
return;
uint8 *tpal = new uint8[768];
memcpy(tpal, _currentPalette, 768);
memset(tpal, 0, 384);
loadSpecialColours(tpal);
fadePalette(tpal, delay);
fillRect(112, 0, 288, 120, 0);
delete[] tpal;
_fadeFlag = 1;
}
void Screen_LoL::fadeToBlack(int delay, const UpdateFunctor *upFunc) {
Screen::fadeToBlack(delay, upFunc);
_fadeFlag = 2;
@ -290,7 +311,7 @@ void Screen_LoL::setPaletteBrightness(uint8 *palette, int brightness, int modifi
void Screen_LoL::generateBrightnessPalette(uint8 *src, uint8 *dst, int brightness, int modifier) {
memcpy(dst, src, 0x300);
setPaletteColoursSpecial(dst);
loadSpecialColours(dst);
brightness = (8 - brightness) << 5;
if (modifier >= 0 && modifier < 8 && _drawGuiFlag & 0x800) {
brightness = 256 - ((((modifier & 0xfffe) << 5) * (256 - brightness)) >> 8);
@ -304,10 +325,55 @@ void Screen_LoL::generateBrightnessPalette(uint8 *src, uint8 *dst, int brightnes
}
}
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);
void Screen_LoL::loadSpecialColours(uint8 *destPalette) {
memcpy(destPalette + 0x240, _screenPalette + 0x240, 12);
}
void Screen_LoL::loadColour254(uint8 *destPalEntry) {
memcpy(destPalEntry, _screenPalette + 0x2fa, 3);
}
bool Screen_LoL::copyColour(int dstColorIndex, int srcColorIndex, uint32 time1, uint32 time2) {
uint8 *s = _screenPalette + 3 * dstColorIndex;
uint8 *e = _screenPalette + 3 * srcColorIndex;
uint8 *p = getPalette(1) + 3 * dstColorIndex;
bool res = false;
uint16 t1 = 0;
uint16 t2 = 0;
int32 t3 = 0;
uint8 tmpPalEntry[3];
for (int i = 0; i < 3; i++) {
if (time1 < time2) {
t1 = *e & 0x3f;
t2 = *s & 0x3f;
t3 = t1 - t2;
if (!t3)
res = true;
t3 = (((((t3 << 8) / time2) * time1) >> 8) & 0xffff) + t2;
} else {
t1 = *e & 0x3f;
*p = t3 = t1;
res = false;
}
tmpPalEntry[i] = t3 & 0xff;
s++;
e++;
p++;
}
uint8 tpal[768];
memcpy(tpal, _screenPalette, 768);
memcpy(tpal + dstColorIndex * 3, tmpPalEntry, 3);
setScreenPalette(tpal);
return res;
}
uint8 Screen_LoL::getShapePaletteSize(const uint8 *shp) {

View file

@ -39,6 +39,7 @@ public:
void setScreenDim(int dim);
const ScreenDim *getScreenDim(int dim);
int curDimIndex() { return _curDimIndex; }
void modifyScreenDim(int dim, int x, int y, int w, int h);
void clearDim(int dim);
void clearCurDim();
@ -47,15 +48,17 @@ public:
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 fadeClearSceneWindow(int delay);
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 loadSpecialColours(uint8 *destPalette);
void loadColour254(uint8 *destPalEntry);
bool copyColour(int dstColorIndex, int srcColorIndex, uint32 time1, uint32 time2);
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);
@ -65,6 +68,7 @@ public:
uint8 *_grayOverlay;
int _fadeFlag;
int _drawGuiFlag;
int _dimLineCount;
private:
LoLEngine *_vm;
@ -73,6 +77,7 @@ private:
static const int _screenDimTableCount;
ScreenDim **_customDimTable;
int _curDimIndex;
uint8 *_levelOverlays[8];
};

View file

@ -85,18 +85,18 @@ void LoLEngine::runResidentScriptCustom(int func, int reg0, int reg1, int reg2,
}
bool LoLEngine::checkScriptUnk(int func) {
if (_boolScriptFuncDone)
if (_sceneUpdateRequired)
return true;
for (int i = 0; i < 15; i++) {
if (_scriptExecutedFuncs[i] == func) {
_boolScriptFuncDone = true;
_sceneUpdateRequired = true;
return true;
}
}
if (_currentBlock == func){
_boolScriptFuncDone = true;
_sceneUpdateRequired = true;
return true;
}
@ -182,9 +182,9 @@ int LoLEngine::olol_getItemPara(EMCState *script) {
case 0:
return i->blockPropertyIndex;
case 1:
return i->unk7;
return i->p_1a;
case 2:
return i->anonymous_4;
return i->p_1b;
case 3:
return i->level;
case 4:
@ -228,35 +228,45 @@ int LoLEngine::olol_getCharacterStat(EMCState *script) {
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;
default:
break;
}
return 0;
@ -275,40 +285,60 @@ int LoLEngine::olol_setCharacterStat(EMCState *script) {
// fall through please add "// fall through" at the end of the
// case.
switch (stackPos(1)) {
case 0:
c->flags = e;
break;
case 1:
c->raceClassSex = e & 0x0f;
case 2:
case 3:
case 4:
default:
break;
case 5:
//// TODO
break;
case 6:
c->hitPointsMax = e;
break;
case 7:
//// TODO
break;
case 8:
c->magicPointsMax = e;
break;
case 9:
c->field_37 = e;
break;
case 10:
c->items[d] = 0;
break;
case 11:
c->field_66[d] = e;
break;
case 12:
c->field_27[d] = e;
break;
case 13:
if (d & 0x80)
c->field_25 = e;
else
c->field_17[d] = e;
break;
case 14:
c->field_69[d] = e;
break;
default:
break;
}
return 0;
@ -360,6 +390,18 @@ int LoLEngine::olol_loadDoorShapes(EMCState *script) {
return 1;
}
int LoLEngine::olol_initAnimStruct(EMCState *script) {
if (initTimAnimStruct(stackPos(1), stackPosString(0), stackPos(2), stackPos(3), stackPos(4), stackPos(5)))
return 1;
return 0;
}
int LoLEngine::olol_freeAnimStruct(EMCState *script) {
if (_tim->freeAnimStruct(stackPos(0)))
return 1;
return 0;
}
int LoLEngine::olol_setMusicTrack(EMCState *script) {
_curMusicTheme = stackPos(0);
return 1;
@ -382,7 +424,7 @@ int LoLEngine::olol_setGlobalVar(EMCState *script) {
switch (stackPos(0)) {
case 0:
_currentBlock = b;
setLF1(_unkCmzU1, _unkCmzU2, _currentBlock, 0x80, 0x80);
calcCoordinates(_partyPosX, _partyPosY, _currentBlock, 0x80, 0x80);
setLF2(_currentBlock);
break;
case 1:
@ -405,8 +447,14 @@ int LoLEngine::olol_setGlobalVar(EMCState *script) {
case 7:
break;
case 8:
_charFlagUnk = b;
//TODO
_updateFlags = b;
if (b == 1) {
if (!textEnabled() || !(_hideControls & 2))
charCallback4(1);
removeUnkFlags(2);
} else {
setUnkFlags(2);
}
break;
case 9:
_lampStatusUnk = b & 0xff;
@ -441,6 +489,95 @@ int LoLEngine::olol_resetBlockShapeAssignment(EMCState *script) {
return 1;
}
int LoLEngine::olol_loadMonsterProperties(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_loadMonsterProperties(%p) (%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d)",
(const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5),
stackPos(6), stackPos(7), stackPos(8), stackPos(9), stackPos(10), stackPos(11), stackPos(12), stackPos(13),
stackPos(14), stackPos(15), stackPos(16), stackPos(17), stackPos(18), stackPos(19), stackPos(20),
stackPos(21), stackPos(22), stackPos(23), stackPos(24), stackPos(25), stackPos(26), stackPos(27),
stackPos(28), stackPos(29), stackPos(30), stackPos(31), stackPos(32), stackPos(33), stackPos(34),
stackPos(35), stackPos(36), stackPos(37), stackPos(38), stackPos(39), stackPos(40), stackPos(41));
MonsterProperty *l = &_monsterProperties[stackPos(0) * 83];
l->id = stackPos(1) & 0xff;
int shpWidthMax = 0;
for (int i = 0; i < 16; i++) {
uint8 m = _monsterShapes[(l->id << 4) + i][3];
if (m > shpWidthMax)
shpWidthMax = m;
}
l->maxWidth = shpWidthMax;
l->unk[0] = (stackPos(2) << 8) / 100;
l->unk[1] = 256;
l->unk[2] = (stackPos(3) << 8) / 100;
l->unk[3] = stackPos(4);
l->unk[4] = (stackPos(5) << 8) / 100;
l->unk[5] = (stackPos(6) << 8) / 100;
l->unk[6] = (stackPos(7) << 8) / 100;
l->unk[7] = (stackPos(8) << 8) / 100;
l->unk[8] = 0;
for (int i = 0; i < 8; i++) {
l->unk2[i] = stackPos(9 + i);
l->unk3[i] = (stackPos(17 + i) << 8) / 100;
}
l->pos = &l->unk[0];
l->unk4[0] = stackPos(25);
l->unk4[1] = stackPos(26);
l->b = 1;
l->unk5[0] = stackPos(27);
l->unk5[1] = stackPos(28);
// FIXME???
l->unk5[1] = stackPos(29);
//
for (int i = 0; i < 5; i++)
l->unk6[2 + i] = stackPos(30 + i);
for (int i = 0; i < 2; i++) {
l->unk7[i] = stackPos(35 + i);
l->unk7[i + 2] = stackPos(37 + i);
}
for (int i = 0; i < 3; i++)
l->unk8[2 + i] = stackPos(39 + i);
return 1;
}
int LoLEngine::olol_loadTimScript(EMCState *script) {
if (_activeTim[stackPos(0)])
return 1;
char file[13];
snprintf(file, sizeof(file), "%s.TIM", stackPosString(1));
_activeTim[stackPos(0)] = _tim->load(file, &_timIngameOpcodes);
return 1;
}
int LoLEngine::olol_runTimScript(EMCState *script) {
return _tim->exec(_activeTim[stackPos(0)], stackPos(1));
}
int LoLEngine::olol_releaseTimScript(EMCState *script) {
_tim->unload(_activeTim[stackPos(0)]);
return 1;
}
int LoLEngine::olol_initDialogueSequence(EMCState *script) {
initDialogueSequence(stackPos(0));
return 1;
}
int LoLEngine::olol_restoreSceneAfterDialogueSequence(EMCState *script) {
restoreSceneAfterDialogueSequence(stackPos(0));
return 1;
}
int LoLEngine::olol_loadLangFile(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_loadLangFile(%p) (%s)", (const void *)script, stackPosString(0));
char filename[13];
@ -451,6 +588,11 @@ int LoLEngine::olol_loadLangFile(EMCState *script) {
return 1;
}
int LoLEngine::olol_stopTimScript(EMCState *script) {
_tim->stopAllFuncs(_activeTim[stackPos(0)]);
return 1;
}
int LoLEngine::olol_loadSoundFile(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_loadSoundFile(%p) (%d)", (const void *)script, stackPos(0));
snd_loadSoundFile(stackPos(0));
@ -466,6 +608,23 @@ int LoLEngine::olol_setPaletteBrightness(EMCState *script) {
return old;
}
int LoLEngine::olol_playDialogueTalkText(EMCState *script) {
int track = stackPos(0);
if (!snd_playCharacterSpeech(track, 0, 0) || textEnabled()) {
char *s = getLangString(track);
_dlg->play(4, s, script, 0, 1);
}
return 1;
}
int LoLEngine::olol_setNextFunc(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_setNextFunc(%p) (%d)", (const void *)script, stackPos(0));
_nextScriptFunc = stackPos(0);
return 1;
}
int LoLEngine::olol_assignCustomSfx(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_assignCustomSfx(%p) (%s, %d)", (const void *)script, stackPosString(0), stackPos(1));
const char *c = stackPosString(0);
@ -484,6 +643,37 @@ int LoLEngine::olol_assignCustomSfx(EMCState *script) {
#pragma mark -
TIMInterpreter::Animation *LoLEngine::initTimAnimStruct(int index, const char *filename, int x, int y, uint16 copyPara, uint16 wsaFlags) {
TIMInterpreter::Animation *a = _tim->initAnimStructIntern(index, filename, x, y, copyPara, wsaFlags);
_tim->setWsaDrawPage2(0);
if (wsaFlags & 1) {
if (_screen->_fadeFlag != 1)
_screen->fadeClearSceneWindow(10);
memcpy(_screen->getPalette(3) + 384, _screen->_currentPalette + 384, 384);
} else if (wsaFlags & 2) {
_screen->fadeToBlack(10);
}
if (wsaFlags & 7) {
_screen->hideMouse();
a->wsa->setDrawPage(0);
a->wsa->setX(x);
a->wsa->setY(y);
a->wsa->displayFrame(0, 0);
_screen->showMouse();
}
if (wsaFlags & 3) {
_screen->loadSpecialColours(_screen->getPalette(3));
_screen->fadePalette(_screen->getPalette(3), 10);
_screen->_fadeFlag = 0;
}
return a;
}
int LoLEngine::tlol_setupPaletteFade(const TIM *tim, const uint16 *param) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::t2_playSoundEffect(%p, %p) (%d)", (const void*)tim, (const void*)param, param[0]);
_screen->getFadeParams(_screen->getPalette(0), param[0], _tim->_palDelayInc, _tim->_palDiff);
@ -595,9 +785,9 @@ void LoLEngine::setupOpcodeTable() {
// 0x18
Opcode(olol_loadDoorShapes);
Opcode(olol_initAnimStruct);
OpcodeUnImpl();
OpcodeUnImpl();
OpcodeUnImpl();
Opcode(olol_freeAnimStruct);
// 0x1C
OpcodeUnImpl();
@ -651,7 +841,7 @@ void LoLEngine::setupOpcodeTable() {
OpcodeUnImpl();
OpcodeUnImpl();
OpcodeUnImpl();
OpcodeUnImpl();
Opcode(olol_loadMonsterProperties);
// 0x40
OpcodeUnImpl();
@ -674,13 +864,13 @@ void LoLEngine::setupOpcodeTable() {
// 0x4C
OpcodeUnImpl();
OpcodeUnImpl();
OpcodeUnImpl();
OpcodeUnImpl();
Opcode(olol_loadTimScript);
Opcode(olol_runTimScript);
// 0x50
OpcodeUnImpl();
OpcodeUnImpl();
OpcodeUnImpl();
Opcode(olol_releaseTimScript);
Opcode(olol_initDialogueSequence);
Opcode(olol_restoreSceneAfterDialogueSequence);
OpcodeUnImpl();
// 0x54
@ -691,7 +881,7 @@ void LoLEngine::setupOpcodeTable() {
// 0x58
OpcodeUnImpl();
OpcodeUnImpl();
Opcode(olol_stopTimScript);
OpcodeUnImpl();
OpcodeUnImpl();
@ -740,11 +930,11 @@ void LoLEngine::setupOpcodeTable() {
// 0x78
OpcodeUnImpl();
OpcodeUnImpl();
OpcodeUnImpl();
Opcode(olol_playDialogueTalkText);
OpcodeUnImpl();
// 0x7C
OpcodeUnImpl();
Opcode(olol_setNextFunc);
OpcodeUnImpl();
OpcodeUnImpl();
OpcodeUnImpl();
@ -846,7 +1036,6 @@ void LoLEngine::setupOpcodeTable() {
OpcodeUnImpl();
Common::Array<const TIMOpcode*> *timTable = 0;
SetTimOpcodeTable(_timIntroOpcodes);
// 0x00
@ -860,6 +1049,35 @@ void LoLEngine::setupOpcodeTable() {
OpcodeTim(tlol_displayText);
OpcodeTimUnImpl();
OpcodeTimUnImpl();
SetTimOpcodeTable(_timIngameOpcodes);
// 0x00
OpcodeTimUnImpl();
OpcodeTimUnImpl();
OpcodeTimUnImpl();
OpcodeTimUnImpl();
// 0x04
OpcodeTimUnImpl();
OpcodeTimUnImpl();
OpcodeTimUnImpl();
OpcodeTimUnImpl();
// 0x08
OpcodeTimUnImpl();
OpcodeTimUnImpl();
OpcodeTimUnImpl();
OpcodeTimUnImpl();
// 0x0C
OpcodeTimUnImpl();
OpcodeTimUnImpl();
OpcodeTimUnImpl();
OpcodeTimUnImpl();
// 0x10
OpcodeTimUnImpl();
}
} // end of namespace Kyra

View file

@ -28,6 +28,7 @@
#include "kyra/resource.h"
#include "kyra/sound.h"
#include "kyra/wsamovie.h"
#include "kyra/gui_lol.h"
#include "common/endian.h"
@ -37,7 +38,7 @@ TIMInterpreter::TIMInterpreter(KyraEngine_v1 *vm, Screen_v2 *screen, OSystem *sy
#define COMMAND(x) { &TIMInterpreter::x, #x }
#define COMMAND_UNIMPL() { 0, 0 }
#define cmd_return(n) cmd_return_##n
static const CommandEntry commandProcs[] = {
static const CommandEntry commandProcsHOF[] = {
// 0x00
COMMAND(cmd_initFunc0),
COMMAND(cmd_stopCurFunc),
@ -74,22 +75,69 @@ TIMInterpreter::TIMInterpreter(KyraEngine_v1 *vm, Screen_v2 *screen, OSystem *sy
COMMAND(cmd_initFuncNow),
COMMAND(cmd_stopFuncNow),
// 0x1C
COMMAND(cmd_processDialogue),
COMMAND(cmd_dialogueBox),
COMMAND(cmd_return(n1))
};
static const CommandEntry commandProcsLOL[] = {
// 0x00
COMMAND(cmd_initFunc0),
COMMAND(cmd_stopAllFuncs),
COMMAND(cmd_initWSA),
COMMAND(cmd_uninitWSA),
// 0x04
COMMAND(cmd_initFunc),
COMMAND(cmd_stopFunc),
COMMAND(cmd_wsaDisplayFrame),
COMMAND_UNIMPL(),
// 0x08
COMMAND(cmd_loadVocFile),
COMMAND(cmd_unloadVocFile),
COMMAND(cmd_playVocFile),
COMMAND_UNIMPL(),
// 0x0C
COMMAND(cmd_loadSoundFile),
COMMAND(cmd_return(1)),
COMMAND(cmd_playMusicTrack),
COMMAND_UNIMPL(),
// 0x10
COMMAND(cmd_return(1)),
COMMAND(cmd_return(1)),
COMMAND_UNIMPL(),
COMMAND_UNIMPL(),
// 0x14
COMMAND(cmd_setLoopIp),
COMMAND(cmd_continueLoop),
COMMAND(cmd_resetLoopIp),
COMMAND(cmd_resetAllRuntimes),
// 0x18
COMMAND(cmd_return(1)),
COMMAND(cmd_execOpcode),
COMMAND(cmd_initFuncNow),
COMMAND(cmd_stopFuncNow),
// 0x1C
COMMAND(cmd_processDialogue),
COMMAND(cmd_dialogueBox),
COMMAND(cmd_return(n1))
};
#undef cmd_return
_commands = commandProcs;
_commandsSize = ARRAYSIZE(commandProcs);
_commands = vm->game() == GI_LOL ? commandProcsLOL : commandProcsHOF ;
_commandsSize = vm->game() == GI_LOL ? ARRAYSIZE(commandProcsLOL) : ARRAYSIZE(commandProcsHOF);
memset(&_animations, 0, sizeof(_animations));
_langData = 0;
_textDisplayed = false;
_textAreaBuffer = new uint8[320*40];
assert(_textAreaBuffer);
_dlgSpeechEnabled = false;
_refresh = false;
_drawPage2 = 8;
_palDelayInc = _palDiff = _palDelayAcc = 0;
_palDelayInc = _palDiff = _palDelayAcc = 0;
_dialogueComplete = 0;
_activeVoiceFile = 0;
}
TIMInterpreter::~TIMInterpreter() {
@ -159,9 +207,9 @@ void TIMInterpreter::setLangData(const char *filename) {
_langData = _vm->resource()->fileData(filename, 0);
}
void TIMInterpreter::exec(TIM *tim, bool loop) {
int TIMInterpreter::exec(TIM *tim, bool loop) {
if (!tim)
return;
return 0;
_currentTim = tim;
if (!_currentTim->func[0].ip) {
@ -170,14 +218,37 @@ void TIMInterpreter::exec(TIM *tim, bool loop) {
}
do {
if (_refresh)
_vm->gui()->update();
for (_currentFunc = 0; _currentFunc < TIM::kCountFuncs; ++_currentFunc) {
TIM::Function &cur = _currentTim->func[_currentFunc];
if (_currentTim->procFunc != -1)
execCommand(28, &_currentTim->procParam);
bool running = true;
if (_refresh)
_vm->gui()->update();
if (_dlgSpeechEnabled && _currentTim->procParam > 1 && cur.loopIp) {
if (!_vm->sound()->voiceIsPlaying(_activeVoiceFile)) {
cur.loopIp = 0;
_currentTim->dlgFunc = _currentFunc;
advanceToOpcode(21);
_currentTim->dlgFunc = -1;
}
}
bool running = true;
int cnt = 0;
while (cur.ip && cur.nextTime <= _system->getMillis() && running) {
if (cnt++ > 0) {
if (_currentTim->procFunc != -1)
execCommand(28, &_currentTim->procParam);
if (_refresh)
_vm->gui()->update();
}
int8 opcode = int8(cur.ip[2] & 0xFF);
switch (execCommand(opcode, cur.ip + 3)) {
@ -193,6 +264,7 @@ void TIMInterpreter::exec(TIM *tim, bool loop) {
case -3:
_currentTim->procFunc = _currentFunc;
_currentTim->dlgFunc = -1;
break;
case 22:
@ -206,11 +278,18 @@ void TIMInterpreter::exec(TIM *tim, bool loop) {
if (cur.ip) {
cur.ip += cur.ip[0];
cur.lastTime = cur.nextTime;
cur.nextTime += cur.ip[1] * _vm->tickLength();
cur.nextTime += (cur.ip[1] ) * _vm->tickLength();
}
}
}
} while (loop);
} while (loop && !_vm->shouldQuit());
return _currentTim->clickedButton;
}
void TIMInterpreter::stopAllFuncs(TIM *tim) {
for (int i = 0; i < TIM::kCountFuncs; ++i)
tim->func[i].ip = 0;
}
void TIMInterpreter::refreshTimersAfterPause(uint32 elapsedTime) {
@ -342,6 +421,7 @@ TIMInterpreter::Animation *TIMInterpreter::initAnimStruct(int index, const char
anim->x = x;
anim->y = y;
anim->wsaCopyParams = wsaFlags;
_drawPage2 = 8;
uint16 wsaOpenFlags = ((wsaFlags & 0x10) != 0) ? 2 : 0;
@ -367,7 +447,7 @@ TIMInterpreter::Animation *TIMInterpreter::initAnimStruct(int index, const char
_screen->checkedPageUpdate(8, 4);
_screen->updateScreen();
}
if (wsaFlags & 4) {
snprintf(file, 32, "%s.CPS", filename);
@ -410,6 +490,41 @@ TIMInterpreter::Animation *TIMInterpreter::initAnimStruct(int index, const char
return anim;
}
TIMInterpreter::Animation *TIMInterpreter::initAnimStructIntern(int index, const char *filename, int x, int y, uint16 copyPara, uint16 wsaFlags) {
Animation *anim = &_animations[index];
anim->x = x;
anim->y = y;
anim->wsaCopyParams = wsaFlags;
uint16 wsaOpenFlags = 0;
if (wsaFlags & 0x10)
wsaOpenFlags |= 2;
if (wsaFlags & 8)
wsaOpenFlags |= 1;
char file[32];
snprintf(file, 32, "%s.WSA", filename);
if (_vm->resource()->exists(file)) {
anim->wsa = new WSAMovie_v2(_vm, _screen);
assert(anim->wsa);
anim->wsa->open(file, wsaOpenFlags, _screen->getPalette(3));
}
return anim;
}
int TIMInterpreter::freeAnimStruct(int index) {
Animation *anim = &_animations[index];
if (!anim)
return 0;
delete anim->wsa;
memset(anim, 0, sizeof(Animation));
return 1;
}
char *TIMInterpreter::getTableEntry(uint idx) {
if (!_langData)
return 0;
@ -424,6 +539,22 @@ const char *TIMInterpreter::getCTableEntry(uint idx) const {
return (const char *)(_langData + READ_LE_UINT16(_langData + (idx<<1)));
}
void TIMInterpreter::advanceToOpcode(int opcode) {
TIM::Function *f = &_currentTim->func[_currentTim->dlgFunc];
uint16 len = f->ip[0];
while ((f->ip[2] & 0xFF) != opcode) {
if ((f->ip[2] & 0xFF) == 1) {
f->ip[0] = len;
break;
}
len = f->ip[0];
f->ip += len;
}
f->nextTime = _system->getMillis();
}
int TIMInterpreter::execCommand(int cmd, const uint16 *param) {
if (cmd < 0 || cmd >= _commandsSize) {
warning("Calling unimplemented TIM command %d from file '%s'", cmd, _currentTim->filename);
@ -519,8 +650,10 @@ int TIMInterpreter::cmd_wsaDisplayFrame(const uint16 *param) {
anim.wsa->setX(anim.x);
anim.wsa->setY(anim.y);
anim.wsa->setDrawPage((anim.wsaCopyParams & 0x4000) != 0 ? 2 : 8);
anim.wsa->setDrawPage((anim.wsaCopyParams & 0x4000) != 0 ? 2 : _drawPage2);
anim.wsa->displayFrame(frame, anim.wsaCopyParams & 0xF0FF, 0, 0);
if (!_drawPage2)
_screen->updateScreen();
return 1;
}
@ -573,7 +706,14 @@ int TIMInterpreter::cmd_playMusicTrack(const uint16 *param) {
}
int TIMInterpreter::cmd_setLoopIp(const uint16 *param) {
_currentTim->func[_currentFunc].loopIp = _currentTim->func[_currentFunc].ip;
if (_dlgSpeechEnabled) {
if (_vm->sound()->voiceIsPlaying(_activeVoiceFile))
_currentTim->func[_currentFunc].loopIp = _currentTim->func[_currentFunc].ip;
else
advanceToOpcode(21);
} else {
_currentTim->func[_currentFunc].loopIp = _currentTim->func[_currentFunc].ip;
}
return 1;
}
@ -585,14 +725,16 @@ int TIMInterpreter::cmd_continueLoop(const uint16 *param) {
func.ip = func.loopIp;
uint16 factor = param[0];
if (factor) {
const uint32 random = _vm->_rnd.getRandomNumberRng(0, 0x8000);
uint32 waitTime = (random * factor) / 0x8000;
func.nextTime += waitTime * _vm->tickLength();
if (!_vm->sound()->voiceIsPlaying(_activeVoiceFile)) {
uint16 factor = param[0];
if (factor) {
const uint32 random = _vm->_rnd.getRandomNumberRng(0, 0x8000);
uint32 waitTime = (random * factor) / 0x8000;
func.nextTime += waitTime * _vm->tickLength();
}
}
return 1;
return -2;
}
int TIMInterpreter::cmd_resetLoopIp(const uint16 *param) {
@ -645,5 +787,59 @@ int TIMInterpreter::cmd_stopFuncNow(const uint16 *param) {
return 1;
}
int TIMInterpreter::cmd_stopAllFuncs(const uint16 *param) {
while (_currentTim->dlgFunc == -1 && _currentTim->clickedButton == 0 && !_vm->shouldQuit()) {
_vm->gui()->update();
_currentTim->clickedButton = _vm->gui()->processDialogue();
}
for (int i = 0; i < TIM::kCountFuncs; ++i)
_currentTim->func[i].ip = 0;
return -1;
}
int TIMInterpreter::cmd_processDialogue(const uint16 *param) {
int res = _vm->gui()->processDialogue();
if (!res ||!_currentTim->procParam)
return 0;
if (_vm->sound()->voiceIsPlaying(_activeVoiceFile))
_dialogueComplete = 0;
_currentTim->func[_currentTim->procFunc].loopIp = 0;
_currentTim->dlgFunc = _currentTim->procFunc;
_currentTim->procFunc = -1;
_currentTim->clickedButton = res;
if (_currentTim->procParam)
advanceToOpcode(21);
return res;
}
int TIMInterpreter::cmd_dialogueBox(const uint16 *param) {
uint16 func = *param;
assert(func < TIM::kCountFuncs);
_currentTim->procParam = func;
_currentTim->clickedButton = 0;
const char *tmpStr[3];
int cnt = 0;
for (int i = 1; i < 4; i++) {
if (param[i] != 0xffff) {
tmpStr[i-1] = _vm->gui()->getTableString(param[i]);
cnt++;
} else {
tmpStr[i-1] = 0;
}
}
_vm->gui()->drawDialogueBox(cnt, tmpStr[0], tmpStr[1], tmpStr[2]);
return -3;
}
} // end of namespace Kyra

View file

@ -42,6 +42,9 @@ typedef Common::Functor2<const TIM*, const uint16*, int> TIMOpcode;
struct TIM {
char filename[13];
uint16 clickedButton;
int16 dlgFunc;
int16 procFunc;
uint16 procParam;
@ -50,14 +53,14 @@ struct TIM {
};
struct Function {
const uint16 *ip;
uint16 *ip;
uint32 lastTime;
uint32 nextTime;
const uint16 *loopIp;
uint16 *loopIp;
const uint16 *avtl;
uint16 *avtl;
} func[kCountFuncs];
enum {
@ -92,16 +95,26 @@ public:
TIM *load(const char *filename, const Common::Array<const TIMOpcode*> *opcodes);
void unload(TIM *&tim) const;
Animation *initAnimStructIntern(int index, const char *filename, int x, int y, uint16 copyPara, uint16 wsaFlags);
int freeAnimStruct(int index);
void setLangData(const char *filename);
void clearLangData() { delete[] _langData; _langData = 0; }
void toggleDialogueSpeech(bool enable) { _dlgSpeechEnabled = enable; }
void toggleRefresh(bool enable) { _refresh = enable; }
void setWsaDrawPage2(int pageNum) { _drawPage2 = pageNum; }
void setDialogueCompleteFlag(int val) { _dialogueComplete = val; }
void setActiveSpeechFile(const char *filename) { _activeVoiceFile = filename; }
const char *getCTableEntry(uint idx) const;
void resetFinishedFlag() { _finished = false; }
bool finished() const { return _finished; }
void exec(TIM *tim, bool loop);
int exec(TIM *tim, bool loop);
void stopCurFunc() { if (_currentTim) cmd_stopCurFunc(0); }
void stopAllFuncs(TIM *tim);
void refreshTimersAfterPause(uint32 elapsedTime);
@ -109,6 +122,7 @@ public:
void setupTextPalette(uint index, int fadePalette);
int _palDelayInc, _palDiff, _palDelayAcc;
private:
KyraEngine_v1 *_vm;
Screen_v2 *_screen;
@ -121,9 +135,8 @@ private:
Common::String _vocFiles[120];
Animation _animations[TIM::kWSASlots];
Animation *initAnimStruct(int index, const char *filename, int x, int y, int, int offscreenBuffer, uint16 wsaFlags);
Animation _animations[TIM::kWSASlots];
char _audioFilename[32];
@ -132,6 +145,14 @@ private:
bool _textDisplayed;
uint8 *_textAreaBuffer;
bool _dlgSpeechEnabled;
bool _refresh;
int _drawPage2;
int _dialogueComplete;
const char *_activeVoiceFile;
void advanceToOpcode(int del);
int execCommand(int cmd, const uint16 *param);
typedef int (TIMInterpreter::*CommandProc)(const uint16 *);
@ -163,6 +184,11 @@ private:
int cmd_execOpcode(const uint16 *param);
int cmd_initFuncNow(const uint16 *param);
int cmd_stopFuncNow(const uint16 *param);
int cmd_stopAllFuncs(const uint16 *param);
int cmd_processDialogue(const uint16 *param);
int cmd_dialogueBox(const uint16 *param);
#define cmd_return(n, v) \
int cmd_return_##n(const uint16 *) { return v; }

View file

@ -115,6 +115,29 @@ int32 Sound::voicePlay(const char *file, bool isSfx) {
return audioStream->getTotalPlayTime();
}
void Sound::voicePlayFromList(Common::List<const char*> fileList) {
int h = 0;
while (_mixer->isSoundHandleActive(_soundChannels[h].channelHandle) && h < kNumChannelHandles)
h++;
if (h >= kNumChannelHandles)
return;
Audio::AppendableAudioStream *out = Audio::makeAppendableAudioStream(22050, Audio::Mixer::FLAG_AUTOFREE | Audio::Mixer::FLAG_UNSIGNED);
for (Common::List<const char*>::iterator i = fileList.begin(); i != fileList.end(); i++) {
int size;
int rate;
uint8 *file = _vm->resource()->fileData(*i, (uint32*)&size);
Common::MemoryReadStream vocStream(file, (uint32)size);
uint8 *data = Audio::loadVOCFromStream(vocStream, size, rate);
out->queueBuffer(data, size);
}
out->finish();
_soundChannels[h].file = *fileList.begin();
_mixer->playInputStream(Audio::Mixer::kSpeechSoundType, &_soundChannels[h].channelHandle, out);
}
void Sound::voiceStop(const char *file) {
if (!file) {
for (int h = 0; h < kNumChannelHandles; h++) {

View file

@ -196,6 +196,14 @@ public:
*/
virtual int32 voicePlay(const char *file, bool isSfx = false);
/**
* Queues the specified voice files in an AppendableAudioStream
* and plays them.
*
* @param fileList: files to be played
*/
virtual void voicePlayFromList(Common::List<const char*> fileList);
/**
* Checks if a voice is being played.
*

View file

@ -40,6 +40,7 @@
#include "kyra/gui_lok.h"
#include "kyra/gui_hof.h"
#include "kyra/gui_mr.h"
#include "kyra/gui_lol.h"
namespace Kyra {
@ -2622,6 +2623,14 @@ const int8 KyraEngine_MR::_albumWSAY[] = {
// lands of lore static res
void GUI_LoL::initStaticData() {
}
void LoLEngine::initButtonList() {
}
const ScreenDim Screen_LoL::_screenDimTable[] = {
{ 0x00, 0x00, 0x28, 0xC8, 0xC7, 0xCF, 0x00, 0x00 }, // Taken from Intro
{ 0x08, 0x48, 0x18, 0x38, 0xFE, 0x01, 0x00, 0x00 },

573
engines/kyra/text_lol.cpp Normal file
View file

@ -0,0 +1,573 @@
/* 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/util.h"
namespace Kyra {
TextDisplayer_LoL::TextDisplayer_LoL(LoLEngine *vm, Screen_LoL *screen) : _vm(vm), _screen(screen),
_scriptParameter(0), _stringLength(0), _animWidth(0), _animColour1(0), _animColour2(0), _animFlag(true),
_printFlag(false), _lineWidth(0), _numChars(0), _numCharsPrinted(0), _posX(0), _posY(0), _colour1(0), _colour2(0) {
memset(_stringParameters, 0, 15 * sizeof(char*));
_buffer = new char[600];
memset(_buffer, 0, 600);
_out = new char[1024];
memset(_out, 0, 1024);
_backupBuffer = new char[40];
memset(_out, 0, 40);
_currentLine = new char[85];
memset(_out, 0, 85);
_pageBuffer1 = new uint8[0xfa00];
_pageBuffer2 = new uint8[0xfa00];
}
TextDisplayer_LoL::~TextDisplayer_LoL() {
delete[] _buffer;
delete[] _out;
delete[] _backupBuffer;
delete[] _currentLine;
delete[] _pageBuffer1;
delete[] _pageBuffer2;
}
void TextDisplayer_LoL::setupField(bool mode) {
if (_vm->textEnabled()) {
if (mode) {
_screen->copyRegionToBuffer(3, 0, 0, 320, 200, _pageBuffer1);
_screen->copyRegion(80, 142, 0, 0, 240, 37, 0, 3, Screen::CR_NO_P_CHECK);
_screen->copyRegionToBuffer(3, 0, 0, 320, 200, _pageBuffer2);
_screen->copyBlockToPage(3, 0, 0, 320, 200, _pageBuffer1);
} else {
_screen->clearDim(4);
int cp = _screen->setCurPage(2);
_screen->copyRegionToBuffer(3, 0, 0, 320, 200, _pageBuffer1);
_screen->copyBlockToPage(3, 0, 0, 320, 200, _pageBuffer2);
_screen->copyRegion(80, 142, 0, 0, 240, 37, 3, 2, Screen::CR_NO_P_CHECK);
for (int i = 177; i > 141; i--) {
uint32 endTime = _vm->_system->getMillis() + _vm->_tickLength;
_screen->hideMouse();
_screen->copyRegion(83, i, 83, i - 1, 235, 3, 0, 0, Screen::CR_NO_P_CHECK);
_screen->copyRegion(83, i + 1, 83, i + 1, 235, 1, 2, 0, Screen::CR_NO_P_CHECK);
_screen->updateScreen();
_screen->showMouse();
_vm->delayUntil(endTime);
}
_screen->copyBlockToPage(3, 0, 0, 320, 200, _pageBuffer1);
_screen->setCurPage(cp);
_vm->_updateFlags &= 0xfffd;
}
} else {
if (!mode)
_screen->clearDim(4);
_vm->toggleSelectedCharacterFrame(1);
}
}
void TextDisplayer_LoL::expandField() {
if (_vm->textEnabled()) {
_vm->_restorePalette = 0;
_vm->_updateCharV4 = 0;
//_vm->toggleGuiUnk(11, 0);
_screen->clearDim(3);
_screen->copyRegionToBuffer(3, 0, 0, 320, 200, _pageBuffer1);
_screen->copyRegion(83, 140, 0, 0, 235, 3, 0, 2, Screen::CR_NO_P_CHECK);
for (int i = 140; i < 177; i++) {
uint32 endTime = _vm->_system->getMillis() + _vm->_tickLength;
_screen->hideMouse();
_screen->copyRegion(0, 0, 83, i, 235, 3, 2, 0, Screen::CR_NO_P_CHECK);
_screen->updateScreen();
_screen->showMouse();
_vm->delayUntil(endTime);
}
_screen->copyBlockToPage(3, 0, 0, 320, 200, _pageBuffer1);
_vm->_updateFlags |= 2;
} else {
_screen->clearDim(3);
_vm->toggleSelectedCharacterFrame(0);
}
}
void TextDisplayer_LoL::setAnimParameters(const char *str, int x, uint8 col1, uint8 col2) {
static const char defaultStr[] = "<MORE>";
if (str) {
_animString = str;
_animWidth = x;
_animColour1 = col1;
_animColour2 = col2;
} else {
_animString = defaultStr;
_animWidth = 7;
_animColour1 = 0;
_animColour2 = 0;
}
}
void TextDisplayer_LoL::play(int dim, char *str, EMCState *script, int16 *paramList, int16 paramIndex) {
memcpy(_curPara, _stringParameters, 15 * sizeof(char*));
char *cmds = _curPara[0];
if (dim == 3) {
if (_vm->_updateFlags & 2) {
_screen->clearDim(4);
dim = _screen->curDimIndex();
_colour1 = 254;
} else {
_screen->clearDim(3);
dim = _screen->curDimIndex();
_colour1 = 192;
uint8 col[3];
_screen->loadColour254(col);
_screen->setPaletteIndex(192, col[0], col[1], col[2]);
//toggleGuiUnk(11, 1);
_vm->_updateCharV4 = 0;
_vm->_restorePalette = 0;
}
} else {
_screen->setScreenDim(dim);
_colour1 = 254;
}
int cp = _screen->setCurPage(0);
Screen::FontId of = _screen->setFont(Screen::FID_9_FNT);
memset(_backupBuffer, 0, 40);
if (preprocessString(str, script, paramList, paramIndex)) {
vsnprintf(_out, 1024, str, cmds);
_stringLength = strlen(_out);
displayText(_out);
} else {
_stringLength = strlen(str);
displayText(str);
displayText(str);
}
for (int i = 0; i < 10; i++) {
if (!_backupBuffer[i << 1])
break;
str[_backupBuffer[(i << 1) + 1]] = _backupBuffer[i << 1];
}
_screen->setScreenDim(dim);
_screen->setCurPage(cp);
_screen->setFont(of);
_vm->_restorePalette = 0;
}
bool TextDisplayer_LoL::preprocessString(char *str, EMCState *script, int16 *paramList, int16 paramIndex) {
int cnt = 0;
bool res = false;
char *tmpd = _buffer;
char **cmds = _curPara;
for (char *s = str; *s;) {
if (*s++ != '%')
continue;
char pos = *s;
char para1 = 0;
bool eos = false;
switch (pos) {
case '\0':
eos = true;
break;
case '#':
para1 = *++s;
switch (para1) {
case 'E':
case 'G':
case 'X':
case 'c':
case 'd':
case 'e':
case 'f':
case 'g':
case 's':
case 'u':
case 'x':
break;
default:
eos = true;
break;
}
break;
case ' ':
case '+':
case '-':
++s;
default:
break;
}
if (eos)
continue;
char para2 = *s;
switch (para2) {
case '\0':
eos = true;
break;
case '0':
++s;
break;
default:
while(para2 && para2 > 47 && para2 < 58)
para2 = *++s;
break;
}
if (eos)
continue;
char para3 = *++s;
switch (para3) {
case 'a':
_backupBuffer[cnt++] = para3;
_backupBuffer[cnt++] = (int16) (s - str);
snprintf(tmpd, 7, "%d", _scriptParameter);
*cmds++ = tmpd;
tmpd += strlen(tmpd) + 1;
res = true;
*s++ = 's';
break;
case 'n':
_backupBuffer[cnt++] = para3;
_backupBuffer[cnt++] = (int16) (s - str);
*cmds++ = _vm->_characters[script ? script->stack[script->sp + paramIndex] : paramList[paramIndex]].name;
paramIndex++;
res = true;
*s++ = 's';
break;
case 's':
*cmds++ = _vm->getLangString(script ? script->stack[script->sp + paramIndex] : paramList[paramIndex]);
paramIndex++;
res = true;
s++;
break;
case 'X':
case 'd':
case 'u':
case 'x':
snprintf(tmpd, 7, "%d", script ? script->stack[script->sp + paramIndex] : paramList[paramIndex]);
*cmds++ = tmpd;
tmpd += strlen(tmpd) + 1;
paramIndex++;
res = true;
*s++ = 's';
break;
case '\0':
default:
continue;
}
}
return res;
}
void TextDisplayer_LoL::displayText(char *str, ...) {
_printFlag = false;
_lineWidth = 0;
_numChars = 0;
_numCharsPrinted = 0;
_tempString1 = str;
_tempString2 = 0;
_currentLine[0] = 0;
memset(_ctrl, 0, 3);
_colour1 = _screen->_curDim->unk8;
_colour2 = _screen->_curDim->unkA;
_posX = _screen->_curDim->unkC;
_posY = _screen->_curDim->unkE;
char c = parseCommand();
va_list args;
va_start(args, str);
const ScreenDim *sd = _screen->_curDim;
while (c) {
char a = tolower(_ctrl[1]);
if (!_tempString2 && c == '%' ) {
if (a == 'd') {
snprintf(_scriptParaString, 11, "%d", va_arg(args, int));
_tempString2 = _scriptParaString;
} else if (a == 's') {
_tempString2 = va_arg(args, char*);
} else {
break;
}
_ctrl[0] = _ctrl[2];
_ctrl[2] = _ctrl[1] = 0;
c = parseCommand();
}
switch (c - 1) {
case 0:
printLine(_currentLine);
//if (!_dlgAnimCallback)
// break;
portraitAnimation2();
_numCharsPrinted = 0;
break;
case 1:
printLine(_currentLine);
_colour2 = parseCommand();
break;
case 5:
printLine(_currentLine);
_colour1 = parseCommand();
break;
case 8:
//TODO
break;
case 11:
//TODO
break;
case 12:
printLine(_currentLine);
_screen->_dimLineCount++;
_posX = 0;
_posY++;
break;
case 18:
//TODO
break;
case 23:
//TODO
break;
case 24:
//TODO
break;
case 26:
//TODO
break;
case 28:
//TODO
break;
default:
_lineWidth += _screen->getCharWidth(c);
_currentLine[_numChars++] = c;
_currentLine[_numChars] = 0;
if ((_posX + _lineWidth) > (sd->w << 3))
printLine(_currentLine);
break;
}
c = parseCommand();
}
va_end(args);
if (_numChars)
printLine(_currentLine);
}
char TextDisplayer_LoL::parseCommand() {
if (!_ctrl[1])
readNextPara();
char res = _ctrl[1];
_ctrl[1] = _ctrl[2];
_ctrl[2] = 0;
if (!_ctrl[1])
readNextPara();
return res;
}
void TextDisplayer_LoL::readNextPara() {
char d = 0;
if (_tempString2) {
if (*_tempString2) {
d = *_tempString2++;
} else {
_tempString2 = 0;
d = _ctrl[0];
}
}
if (!d && _tempString1) {
if (*_tempString1)
d = *_tempString1++;
else
_tempString1 = 0;
}
_ctrl[1] = d;
_ctrl[2] = 0;
}
void TextDisplayer_LoL::printLine(char *str) {
const ScreenDim *sd = _screen->_curDim;
int fh = (_screen->getFontHeight() + _screen->_charOffset);
int lines = (sd->h - _screen->_charOffset) / fh;
while (_posY >= lines) {
if (lines <= _screen->_dimLineCount && _animFlag) {
_screen->_dimLineCount = 0;
//if (_dlgAnimCallback) {
portraitAnimation2();
_numCharsPrinted = 0;
//}
}
int h1 = ((sd->h / fh) - 1) * fh;
int h2 = sd->h - fh;
if (h2)
_screen->copyRegion(sd->sx << 3, sd->sy + fh, sd->sx << 3, sd->sy, sd->w << 3, h2, _screen->_curPage, _screen->_curPage, Screen::CR_NO_P_CHECK);
_screen->fillRect(sd->sx << 3, sd->sy + h1, (sd->sx + sd->w - 1) << 3, sd->sy + sd->h - 1, _colour2);
_posY--;
}
int x1 = (sd->sx << 3) + _posX;
int y = sd->sy + fh * _posY;
int w = sd->w << 3;
int lw = _lineWidth;
int s = _numChars;
char c = 0;
if ((lw + _posX) > w) {
if ((lines - 1) <= _screen->_dimLineCount && _animFlag)
w -= (_animWidth * (_screen->getFontWidth() + _screen->_charWidth));
w -= _posX;
int n2 = 0;
int n1 = s - 1;
while (n1 > 0) {
//cut off line after last space
c = str[n1];
lw -= _screen->getCharWidth(c);
if (!n2 && lw <= w)
n2 = n1;
if (n2 && c == ' ') {
s = n1;
_printFlag = false;
break;
}
n1--;
}
if (!n1) {
if (_posX && !_printFlag) {
s = lw = 0;
_printFlag = true;
} else {
s = n2;
}
}
}
c = str[s];
str[s] = 0;
_screen->printText(str, x1, y, _colour1, _colour2);
_posX += lw;
_numCharsPrinted += strlen(str);
str[s] = c;
if (c == ' ')
s++;
if (str[s] == ' ')
s++;
strcpy(str, &str[s]);
_numChars = strlen(str);
_lineWidth = _screen->getTextWidth(str);
if (!_numChars && _posX < (sd->w << 3))
return;
_posX = 0;
_posY++;
_screen->_dimLineCount++;
printLine(str);
}
/*void TextDisplayer_LoL::portraitAnimation1(const char *str, uint16 lineWidth, uint8 col1, uint8 col2, uint16 numCharsPrinted) {
}*/
void TextDisplayer_LoL::portraitAnimation2() {
// TODO
}
} // end of namespace Kyra

104
engines/kyra/text_lol.h Normal file
View file

@ -0,0 +1,104 @@
/* 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$
*
*/
#ifndef KYRA_TEXT_LOL_H
#define KYRA_TEXT_LOL_H
namespace Kyra {
class Screen_v2;
class LoLEngine;
struct EMCState;
class TextDisplayer_LoL {
friend class LoLEngine;
public:
TextDisplayer_LoL(LoLEngine *vm, Screen_LoL *screen);
~TextDisplayer_LoL();
void setAnimParameters(const char *str, int x, uint8 col1, uint8 col2);
void setAnimFlag(bool flag) { _animFlag = flag; }
void setupField(bool mode);
void expandField();
void play(int dim, char *str, EMCState *script, int16 *paramList, int16 paramIndex);
int16 _scriptParameter;
private:
void displayText(char *str, ...);
char parseCommand();
void readNextPara();
void printLine(char *str);
bool preprocessString(char *str, EMCState *script, int16 *paramList, int16 paramIndex);
//typedef void (LoLEngine::*DialogueAnimCallback)(const char *str, uint16 lineWidth, uint8 col1, uint8 col2);
//DialogueAnimCallback _dlgAnimCallback;
//void portraitAnimation1(const char *str);
void portraitAnimation2();
char *_stringParameters[15];
char *_curPara[15];
char *_buffer;
char *_out;
char *_backupBuffer;
char *_tempString1;
char *_tempString2;
char *_currentLine;
char _ctrl[3];
char _scriptParaString[11];
uint32 _stringLength;
uint16 _lineWidth;
uint32 _numChars;
uint32 _numCharsPrinted;
const char *_animString;
int16 _animWidth;
uint8 _animColour1;
uint8 _animColour2;
bool _animFlag;
bool _printFlag;
uint8 _posX;
uint8 _posY;
uint8 _colour1;
uint8 _colour2;
uint8 *_pageBuffer1;
uint8 *_pageBuffer2;
LoLEngine *_vm;
Screen_LoL *_screen;
};
} // end of namespace Kyra
#endif