aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Kagerer2009-02-01 19:27:01 +0000
committerFlorian Kagerer2009-02-01 19:27:01 +0000
commit784c99b3dac507c5ee0686cc314c96caa7349ef3 (patch)
tree1dbcd6a62bc25505623ed693161b935389ea5498
parentf90e4545c27fa92cc6ba835f80551556929df43d (diff)
downloadscummvm-rg350-784c99b3dac507c5ee0686cc314c96caa7349ef3.tar.gz
scummvm-rg350-784c99b3dac507c5ee0686cc314c96caa7349ef3.tar.bz2
scummvm-rg350-784c99b3dac507c5ee0686cc314c96caa7349ef3.zip
svn-id: r36178
-rw-r--r--engines/kyra/gui.h7
-rw-r--r--engines/kyra/gui_lol.cpp552
-rw-r--r--engines/kyra/gui_lol.h94
-rw-r--r--engines/kyra/items_lol.cpp16
-rw-r--r--engines/kyra/kyra_v1.cpp32
-rw-r--r--engines/kyra/lol.cpp539
-rw-r--r--engines/kyra/lol.h294
-rw-r--r--engines/kyra/module.mk1
-rw-r--r--engines/kyra/scene_lol.cpp183
-rw-r--r--engines/kyra/screen_lol.cpp76
-rw-r--r--engines/kyra/screen_lol.h9
-rw-r--r--engines/kyra/script_lol.cpp276
-rw-r--r--engines/kyra/script_tim.cpp232
-rw-r--r--engines/kyra/script_tim.h38
-rw-r--r--engines/kyra/sound.cpp23
-rw-r--r--engines/kyra/sound.h8
-rw-r--r--engines/kyra/staticres.cpp9
-rw-r--r--engines/kyra/text_lol.cpp573
-rw-r--r--engines/kyra/text_lol.h104
19 files changed, 2716 insertions, 350 deletions
diff --git a/engines/kyra/gui.h b/engines/kyra/gui.h
index 2ee764bfbe..1b524b7752 100644
--- a/engines/kyra/gui.h
+++ b/engines/kyra/gui.h
@@ -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;
diff --git a/engines/kyra/gui_lol.cpp b/engines/kyra/gui_lol.cpp
index 477c7937eb..3e00b32b0d 100644
--- a/engines/kyra/gui_lol.cpp
+++ b/engines/kyra/gui_lol.cpp
@@ -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
diff --git a/engines/kyra/gui_lol.h b/engines/kyra/gui_lol.h
new file mode 100644
index 0000000000..52dde8b6b5
--- /dev/null
+++ b/engines/kyra/gui_lol.h
@@ -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
+
diff --git a/engines/kyra/items_lol.cpp b/engines/kyra/items_lol.cpp
index 372fc5809e..ef81f7856f 100644
--- a/engines/kyra/items_lol.cpp
+++ b/engines/kyra/items_lol.cpp
@@ -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;
diff --git a/engines/kyra/kyra_v1.cpp b/engines/kyra/kyra_v1.cpp
index 112e5fc9fc..a5e1e432d0 100644
--- a/engines/kyra/kyra_v1.cpp
+++ b/engines/kyra/kyra_v1.cpp
@@ -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;
diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp
index bd85b892e4..c37e4b45f4 100644
--- a/engines/kyra/lol.cpp
+++ b/engines/kyra/lol.cpp
@@ -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);
+}
+
+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;
- _curTlkFile = index;
+ return 1;
}
-void LoLEngine::snd_playVoiceFile(int) {
+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
diff --git a/engines/kyra/lol.h b/engines/kyra/lol.h
index dd998d7bd9..736b2f4894 100644
--- a/engines/kyra/lol.h
+++ b/engines/kyra/lol.h
@@ -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;
diff --git a/engines/kyra/module.mk b/engines/kyra/module.mk
index 0775fe3ec4..e427ee1b43 100644
--- a/engines/kyra/module.mk
+++ b/engines/kyra/module.mk
@@ -65,6 +65,7 @@ MODULE_OBJS := \
staticres.o \
text.o \
text_lok.o \
+ text_lol.o \
text_hof.o \
text_mr.o \
timer.o \
diff --git a/engines/kyra/scene_lol.cpp b/engines/kyra/scene_lol.cpp
index a458b93fae..698330e275 100644
--- a/engines/kyra/scene_lol.cpp
+++ b/engines/kyra/scene_lol.cpp
@@ -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;
+ CLevelItem *tmp = 0;
+
+ while (*cmzItemIndex & 0x8000) {
+ tmp = findItem(*cmzItemIndex);
+ cmzItemIndex = &tmp->itemIndexUnk;
}
- uint16 *t = (uint16*) cmzGetItemOffset(*cmzItemIndex);
- ((ItemInPlay*)t)->level = -1;
+ tmp = findItem(item);
+ tmp->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);
diff --git a/engines/kyra/screen_lol.cpp b/engines/kyra/screen_lol.cpp
index a7be3e5371..78ac2c3a89 100644
--- a/engines/kyra/screen_lol.cpp
+++ b/engines/kyra/screen_lol.cpp
@@ -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) {
diff --git a/engines/kyra/screen_lol.h b/engines/kyra/screen_lol.h
index a4c7d8c749..0f8746ef00 100644
--- a/engines/kyra/screen_lol.h
+++ b/engines/kyra/screen_lol.h
@@ -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];
};
diff --git a/engines/kyra/script_lol.cpp b/engines/kyra/script_lol.cpp
index 9bbf04fa09..00ef33e3cf 100644
--- a/engines/kyra/script_lol.cpp
+++ b/engines/kyra/script_lol.cpp
@@ -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
diff --git a/engines/kyra/script_tim.cpp b/engines/kyra/script_tim.cpp
index 24f7fce576..3df1daf306 100644
--- a/engines/kyra/script_tim.cpp
+++ b/engines/kyra/script_tim.cpp
@@ -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
diff --git a/engines/kyra/script_tim.h b/engines/kyra/script_tim.h
index 3299622a19..5e31d40b9b 100644
--- a/engines/kyra/script_tim.h
+++ b/engines/kyra/script_tim.h
@@ -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; }
diff --git a/engines/kyra/sound.cpp b/engines/kyra/sound.cpp
index 5063fb5fed..487e0cfc07 100644
--- a/engines/kyra/sound.cpp
+++ b/engines/kyra/sound.cpp
@@ -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++) {
diff --git a/engines/kyra/sound.h b/engines/kyra/sound.h
index fc2e38d114..db344e7825 100644
--- a/engines/kyra/sound.h
+++ b/engines/kyra/sound.h
@@ -197,6 +197,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.
*
* @return true when playing, else false
diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp
index 36ec89f308..961f188c98 100644
--- a/engines/kyra/staticres.cpp
+++ b/engines/kyra/staticres.cpp
@@ -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 },
diff --git a/engines/kyra/text_lol.cpp b/engines/kyra/text_lol.cpp
new file mode 100644
index 0000000000..fe7ac6d81d
--- /dev/null
+++ b/engines/kyra/text_lol.cpp
@@ -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
diff --git a/engines/kyra/text_lol.h b/engines/kyra/text_lol.h
new file mode 100644
index 0000000000..3d040dc82b
--- /dev/null
+++ b/engines/kyra/text_lol.h
@@ -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
+