diff options
| -rw-r--r-- | engines/kyra/gui.h | 7 | ||||
| -rw-r--r-- | engines/kyra/gui_lol.cpp | 552 | ||||
| -rw-r--r-- | engines/kyra/gui_lol.h | 94 | ||||
| -rw-r--r-- | engines/kyra/items_lol.cpp | 16 | ||||
| -rw-r--r-- | engines/kyra/kyra_v1.cpp | 32 | ||||
| -rw-r--r-- | engines/kyra/lol.cpp | 539 | ||||
| -rw-r--r-- | engines/kyra/lol.h | 294 | ||||
| -rw-r--r-- | engines/kyra/module.mk | 1 | ||||
| -rw-r--r-- | engines/kyra/scene_lol.cpp | 183 | ||||
| -rw-r--r-- | engines/kyra/screen_lol.cpp | 76 | ||||
| -rw-r--r-- | engines/kyra/screen_lol.h | 9 | ||||
| -rw-r--r-- | engines/kyra/script_lol.cpp | 276 | ||||
| -rw-r--r-- | engines/kyra/script_tim.cpp | 232 | ||||
| -rw-r--r-- | engines/kyra/script_tim.h | 38 | ||||
| -rw-r--r-- | engines/kyra/sound.cpp | 23 | ||||
| -rw-r--r-- | engines/kyra/sound.h | 8 | ||||
| -rw-r--r-- | engines/kyra/staticres.cpp | 9 | ||||
| -rw-r--r-- | engines/kyra/text_lol.cpp | 573 | ||||
| -rw-r--r-- | engines/kyra/text_lol.h | 104 | 
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 + | 
