2008-04-19 13:52:09 +00:00
|
|
|
/* 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/script_tim.h"
|
|
|
|
#include "kyra/script.h"
|
2008-04-19 14:31:10 +00:00
|
|
|
#include "kyra/resource.h"
|
2008-07-31 10:47:15 +00:00
|
|
|
#include "kyra/sound.h"
|
|
|
|
#include "kyra/wsamovie.h"
|
2009-03-04 00:45:34 +00:00
|
|
|
|
|
|
|
#ifdef ENABLE_LOL
|
2009-02-02 23:20:55 +00:00
|
|
|
#include "kyra/lol.h"
|
|
|
|
#include "kyra/screen_lol.h"
|
2009-03-04 00:45:34 +00:00
|
|
|
#endif // ENABLE_LOL
|
2008-04-19 13:52:09 +00:00
|
|
|
|
2009-05-12 14:18:08 +00:00
|
|
|
#include "common/iff_container.h"
|
2008-04-19 13:52:09 +00:00
|
|
|
#include "common/endian.h"
|
|
|
|
|
|
|
|
namespace Kyra {
|
|
|
|
|
2009-02-02 23:20:55 +00:00
|
|
|
TIMInterpreter::TIMInterpreter(KyraEngine_v1 *engine, Screen_v2 *screen_v2, OSystem *system) : _vm(engine), _screen(screen_v2), _system(system), _currentTim(0) {
|
2008-04-19 13:52:09 +00:00
|
|
|
#define COMMAND(x) { &TIMInterpreter::x, #x }
|
|
|
|
#define COMMAND_UNIMPL() { 0, 0 }
|
2008-07-10 11:25:43 +00:00
|
|
|
#define cmd_return(n) cmd_return_##n
|
2009-02-02 23:20:55 +00:00
|
|
|
static const CommandEntry commandProcs[] = {
|
2008-04-19 13:52:09 +00:00
|
|
|
// 0x00
|
2008-04-19 14:31:10 +00:00
|
|
|
COMMAND(cmd_initFunc0),
|
2008-04-19 13:52:09 +00:00
|
|
|
COMMAND(cmd_stopCurFunc),
|
2008-07-31 10:47:15 +00:00
|
|
|
COMMAND(cmd_initWSA),
|
|
|
|
COMMAND(cmd_uninitWSA),
|
2008-04-19 13:52:09 +00:00
|
|
|
// 0x04
|
|
|
|
COMMAND(cmd_initFunc),
|
|
|
|
COMMAND(cmd_stopFunc),
|
2008-07-31 10:47:15 +00:00
|
|
|
COMMAND(cmd_wsaDisplayFrame),
|
2009-05-18 19:53:57 +00:00
|
|
|
COMMAND(cmd_displayText),
|
2008-04-19 13:52:09 +00:00
|
|
|
// 0x08
|
2008-07-31 10:47:15 +00:00
|
|
|
COMMAND(cmd_loadVocFile),
|
|
|
|
COMMAND(cmd_unloadVocFile),
|
|
|
|
COMMAND(cmd_playVocFile),
|
2008-04-19 13:52:09 +00:00
|
|
|
COMMAND_UNIMPL(),
|
|
|
|
// 0x0C
|
2008-07-31 10:47:15 +00:00
|
|
|
COMMAND(cmd_loadSoundFile),
|
|
|
|
COMMAND(cmd_return(1)),
|
|
|
|
COMMAND(cmd_playMusicTrack),
|
2008-04-19 13:52:09 +00:00
|
|
|
COMMAND_UNIMPL(),
|
|
|
|
// 0x10
|
2008-07-31 10:47:15 +00:00
|
|
|
COMMAND(cmd_return(1)),
|
|
|
|
COMMAND(cmd_return(1)),
|
2008-04-19 13:52:09 +00:00
|
|
|
COMMAND_UNIMPL(),
|
|
|
|
COMMAND_UNIMPL(),
|
|
|
|
// 0x14
|
2008-07-31 10:47:15 +00:00
|
|
|
COMMAND(cmd_setLoopIp),
|
|
|
|
COMMAND(cmd_continueLoop),
|
|
|
|
COMMAND(cmd_resetLoopIp),
|
2008-04-19 14:31:10 +00:00
|
|
|
COMMAND(cmd_resetAllRuntimes),
|
2008-04-19 13:52:09 +00:00
|
|
|
// 0x18
|
2008-07-10 11:25:43 +00:00
|
|
|
COMMAND(cmd_return(1)),
|
2008-04-19 13:52:09 +00:00
|
|
|
COMMAND(cmd_execOpcode),
|
|
|
|
COMMAND(cmd_initFuncNow),
|
|
|
|
COMMAND(cmd_stopFuncNow),
|
|
|
|
// 0x1C
|
2009-02-01 19:27:01 +00:00
|
|
|
COMMAND(cmd_return(1)),
|
|
|
|
COMMAND(cmd_return(1)),
|
2008-07-10 11:25:43 +00:00
|
|
|
COMMAND(cmd_return(n1))
|
2009-05-21 13:13:09 +00:00
|
|
|
};
|
2008-07-10 11:25:43 +00:00
|
|
|
#undef cmd_return
|
2009-02-02 23:20:55 +00:00
|
|
|
#undef COMMAND_UNIMPL
|
|
|
|
#undef COMMAND
|
2008-04-19 13:52:09 +00:00
|
|
|
|
2009-05-12 14:18:08 +00:00
|
|
|
_commands = commandProcs;
|
2009-02-02 23:20:55 +00:00
|
|
|
_commandsSize = ARRAYSIZE(commandProcs);
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2009-03-14 13:48:12 +00:00
|
|
|
_animations = new Animation[TIM::kWSASlots];
|
|
|
|
memset(_animations, 0, TIM::kWSASlots * sizeof(Animation));
|
|
|
|
|
2008-07-31 10:47:15 +00:00
|
|
|
_langData = 0;
|
|
|
|
_textDisplayed = false;
|
|
|
|
_textAreaBuffer = new uint8[320*40];
|
|
|
|
assert(_textAreaBuffer);
|
2009-07-14 22:47:33 +00:00
|
|
|
if ((_vm->gameFlags().platform == Common::kPlatformPC98 || _vm->gameFlags().isDemo) && _vm->gameFlags().gameID == GI_LOL)
|
|
|
|
_drawPage2 = 0;
|
|
|
|
else
|
|
|
|
_drawPage2 = 8;
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2009-02-02 23:20:55 +00:00
|
|
|
_palDelayInc = _palDiff = _palDelayAcc = 0;
|
2009-02-16 17:17:15 +00:00
|
|
|
_abortFlag = 0;
|
2008-07-31 10:47:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TIMInterpreter::~TIMInterpreter() {
|
|
|
|
delete[] _langData;
|
|
|
|
delete[] _textAreaBuffer;
|
2009-03-14 13:48:12 +00:00
|
|
|
|
|
|
|
for (int i = 0; i < TIM::kWSASlots; i++) {
|
|
|
|
delete _animations[i].wsa;
|
|
|
|
delete[] _animations[i].parts;
|
|
|
|
}
|
|
|
|
|
2009-05-21 13:13:09 +00:00
|
|
|
delete[] _animations;
|
2008-04-19 13:52:09 +00:00
|
|
|
}
|
|
|
|
|
2009-06-12 09:49:38 +00:00
|
|
|
bool TIMInterpreter::callback(Common::IFFChunk &chunk) {
|
|
|
|
switch (chunk._type) {
|
|
|
|
case MKID_BE('TEXT'):
|
|
|
|
_tim->text = new byte[chunk._size];
|
|
|
|
assert(_tim->text);
|
|
|
|
if (chunk._stream->read(_tim->text, chunk._size) != chunk._size)
|
|
|
|
error("Couldn't read TEXT chunk from file '%s'", _filename);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MKID_BE('AVTL'):
|
|
|
|
_avtlChunkSize = chunk._size >> 1;
|
|
|
|
_tim->avtl = new uint16[_avtlChunkSize];
|
|
|
|
assert(_tim->avtl);
|
|
|
|
if (chunk._stream->read(_tim->avtl, chunk._size) != chunk._size)
|
|
|
|
error("Couldn't read AVTL chunk from file '%s'", _filename);
|
|
|
|
|
|
|
|
for (int i = _avtlChunkSize - 1; i >= 0; --i)
|
|
|
|
_tim->avtl[i] = READ_LE_UINT16(&_tim->avtl[i]);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
warning("Unexpected chunk '%s' of size %d found in file '%s'", Common::ID2string(chunk._type), chunk._size, _filename);
|
|
|
|
}
|
|
|
|
|
2009-06-12 10:26:15 +00:00
|
|
|
return false;
|
2009-06-12 09:49:38 +00:00
|
|
|
}
|
|
|
|
|
2009-05-12 14:18:08 +00:00
|
|
|
TIM *TIMInterpreter::load(const char *filename, const Common::Array<const TIMOpcode *> *opcodes) {
|
2009-05-31 00:42:44 +00:00
|
|
|
if (!_vm->resource()->exists(filename))
|
2008-04-19 14:31:10 +00:00
|
|
|
return 0;
|
|
|
|
|
2009-05-31 00:42:44 +00:00
|
|
|
Common::SeekableReadStream *stream = _vm->resource()->createReadStream(filename);
|
2009-05-12 14:18:08 +00:00
|
|
|
if (!stream)
|
2008-04-19 13:52:09 +00:00
|
|
|
error("Couldn't open TIM file '%s'", filename);
|
|
|
|
|
2009-06-12 09:49:38 +00:00
|
|
|
_avtlChunkSize = 0;
|
|
|
|
_filename = filename;
|
|
|
|
|
|
|
|
_tim = new TIM;
|
|
|
|
assert(_tim);
|
|
|
|
memset(_tim, 0, sizeof(TIM));
|
|
|
|
|
|
|
|
_tim->procFunc = -1;
|
|
|
|
_tim->opcodes = opcodes;
|
|
|
|
|
2009-05-12 14:18:08 +00:00
|
|
|
IFFParser iff(*stream);
|
2009-06-12 09:49:38 +00:00
|
|
|
Common::Functor1Mem< Common::IFFChunk &, bool, TIMInterpreter > c(this, &TIMInterpreter::callback);
|
|
|
|
iff.parse(c);
|
2008-04-19 13:52:09 +00:00
|
|
|
|
2009-06-12 09:49:38 +00:00
|
|
|
if (!_tim->avtl)
|
2009-05-12 14:35:50 +00:00
|
|
|
error("No AVTL chunk found in file: '%s'", filename);
|
|
|
|
|
|
|
|
if (stream->err())
|
2009-07-12 08:51:57 +00:00
|
|
|
error("Read error while parsing file '%s'", filename);
|
2009-05-12 14:35:50 +00:00
|
|
|
|
|
|
|
delete stream;
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2009-06-12 09:49:38 +00:00
|
|
|
int num = (_avtlChunkSize < TIM::kCountFuncs) ? _avtlChunkSize : (int)TIM::kCountFuncs;
|
2008-06-01 15:18:58 +00:00
|
|
|
for (int i = 0; i < num; ++i)
|
2009-06-12 09:49:38 +00:00
|
|
|
_tim->func[i].avtl = _tim->avtl + _tim->avtl[i];
|
2008-04-19 13:52:09 +00:00
|
|
|
|
2009-06-12 09:49:38 +00:00
|
|
|
strncpy(_tim->filename, filename, 13);
|
|
|
|
_tim->filename[12] = 0;
|
2008-07-10 12:12:42 +00:00
|
|
|
|
2009-06-12 09:49:38 +00:00
|
|
|
_tim->isLoLOutro = (_vm->gameFlags().gameID == GI_LOL) && !scumm_stricmp(filename, "LOLFINAL.TIM");
|
|
|
|
_tim->lolCharacter = 0;
|
2009-05-31 00:42:44 +00:00
|
|
|
|
2009-06-12 09:49:38 +00:00
|
|
|
return _tim;
|
2008-04-19 13:52:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void TIMInterpreter::unload(TIM *&tim) const {
|
|
|
|
if (!tim)
|
|
|
|
return;
|
|
|
|
|
2008-05-07 14:20:37 +00:00
|
|
|
delete[] tim->text;
|
|
|
|
delete[] tim->avtl;
|
2008-04-19 13:52:09 +00:00
|
|
|
delete tim;
|
|
|
|
tim = 0;
|
|
|
|
}
|
|
|
|
|
2008-07-31 10:47:15 +00:00
|
|
|
void TIMInterpreter::setLangData(const char *filename) {
|
|
|
|
delete[] _langData;
|
2009-05-31 00:42:44 +00:00
|
|
|
_langData = _vm->resource()->fileData(filename, 0);
|
2008-07-31 10:47:15 +00:00
|
|
|
}
|
|
|
|
|
2009-02-01 19:27:01 +00:00
|
|
|
int TIMInterpreter::exec(TIM *tim, bool loop) {
|
2008-04-19 13:52:09 +00:00
|
|
|
if (!tim)
|
2009-02-01 19:27:01 +00:00
|
|
|
return 0;
|
2008-04-19 13:52:09 +00:00
|
|
|
|
|
|
|
_currentTim = tim;
|
|
|
|
if (!_currentTim->func[0].ip) {
|
|
|
|
_currentTim->func[0].ip = _currentTim->func[0].avtl;
|
|
|
|
_currentTim->func[0].nextTime = _currentTim->func[0].lastTime = _system->getMillis();
|
|
|
|
}
|
|
|
|
|
|
|
|
do {
|
2009-02-02 23:20:55 +00:00
|
|
|
update();
|
|
|
|
|
2008-06-01 15:18:58 +00:00
|
|
|
for (_currentFunc = 0; _currentFunc < TIM::kCountFuncs; ++_currentFunc) {
|
2008-04-19 13:52:09 +00:00
|
|
|
TIM::Function &cur = _currentTim->func[_currentFunc];
|
|
|
|
|
|
|
|
if (_currentTim->procFunc != -1)
|
2008-04-19 14:31:10 +00:00
|
|
|
execCommand(28, &_currentTim->procParam);
|
2008-04-19 13:52:09 +00:00
|
|
|
|
2009-02-02 23:20:55 +00:00
|
|
|
update();
|
|
|
|
checkSpeechProgress();
|
2009-02-01 19:27:01 +00:00
|
|
|
|
2009-05-21 13:13:09 +00:00
|
|
|
bool running = true;
|
2009-02-01 19:27:01 +00:00
|
|
|
int cnt = 0;
|
2008-04-19 13:52:09 +00:00
|
|
|
while (cur.ip && cur.nextTime <= _system->getMillis() && running) {
|
2009-02-01 19:27:01 +00:00
|
|
|
if (cnt++ > 0) {
|
|
|
|
if (_currentTim->procFunc != -1)
|
|
|
|
execCommand(28, &_currentTim->procParam);
|
2009-02-02 23:20:55 +00:00
|
|
|
update();
|
2009-02-01 19:27:01 +00:00
|
|
|
}
|
|
|
|
|
2008-04-19 13:52:09 +00:00
|
|
|
int8 opcode = int8(cur.ip[2] & 0xFF);
|
|
|
|
|
|
|
|
switch (execCommand(opcode, cur.ip + 3)) {
|
|
|
|
case -1:
|
|
|
|
loop = false;
|
|
|
|
running = false;
|
|
|
|
_currentFunc = 11;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case -2:
|
|
|
|
running = false;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case -3:
|
|
|
|
_currentTim->procFunc = _currentFunc;
|
2009-02-01 19:27:01 +00:00
|
|
|
_currentTim->dlgFunc = -1;
|
2008-04-19 13:52:09 +00:00
|
|
|
break;
|
|
|
|
|
2008-07-31 10:47:15 +00:00
|
|
|
case 22:
|
|
|
|
cur.loopIp = 0;
|
|
|
|
break;
|
|
|
|
|
2008-04-19 13:52:09 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cur.ip) {
|
|
|
|
cur.ip += cur.ip[0];
|
|
|
|
cur.lastTime = cur.nextTime;
|
2009-05-31 00:42:44 +00:00
|
|
|
cur.nextTime += (cur.ip[1] ) * _vm->tickLength();
|
2008-04-19 13:52:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-05-31 00:42:44 +00:00
|
|
|
} while (loop && !_vm->shouldQuit());
|
2009-02-01 19:27:01 +00:00
|
|
|
|
|
|
|
return _currentTim->clickedButton;
|
|
|
|
}
|
|
|
|
|
2008-06-01 13:19:45 +00:00
|
|
|
void TIMInterpreter::refreshTimersAfterPause(uint32 elapsedTime) {
|
2008-06-01 15:18:58 +00:00
|
|
|
if (!_currentTim)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (int i = 0; i < TIM::kCountFuncs; i++) {
|
2008-06-01 15:15:12 +00:00
|
|
|
if (_currentTim->func[i].lastTime)
|
|
|
|
_currentTim->func[i].lastTime += elapsedTime;
|
|
|
|
if (_currentTim->func[i].nextTime)
|
|
|
|
_currentTim->func[i].nextTime += elapsedTime;
|
2008-06-01 13:19:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-07-31 10:47:15 +00:00
|
|
|
void TIMInterpreter::displayText(uint16 textId, int16 flags) {
|
|
|
|
char *text = getTableEntry(textId);
|
|
|
|
|
|
|
|
if (_textDisplayed) {
|
2009-05-31 00:42:44 +00:00
|
|
|
_screen->copyBlockToPage(0, 0, 160, 320, 40, _textAreaBuffer);
|
2008-07-31 10:47:15 +00:00
|
|
|
_textDisplayed = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!text)
|
|
|
|
return;
|
|
|
|
if (!text[0])
|
|
|
|
return;
|
|
|
|
|
|
|
|
char filename[16];
|
|
|
|
memset(filename, 0, sizeof(filename));
|
|
|
|
|
|
|
|
if (text[0] == '$') {
|
|
|
|
const char *end = strchr(text+1, '$');
|
|
|
|
if (end)
|
|
|
|
memcpy(filename, text+1, end-1-text);
|
|
|
|
}
|
|
|
|
|
2009-06-26 00:12:19 +00:00
|
|
|
const bool isPC98 = (_vm->gameFlags().platform == Common::kPlatformPC98);
|
2009-09-16 20:05:12 +00:00
|
|
|
if (filename[0] && (_vm->speechEnabled() || !_vm->gameFlags().isTalkie))
|
2009-05-31 00:42:44 +00:00
|
|
|
_vm->sound()->voicePlay(filename);
|
2008-07-31 10:47:15 +00:00
|
|
|
|
|
|
|
if (text[0] == '$')
|
|
|
|
text = strchr(text + 1, '$') + 1;
|
|
|
|
|
2009-06-26 00:12:19 +00:00
|
|
|
if (!isPC98)
|
2009-06-25 23:03:57 +00:00
|
|
|
setupTextPalette((flags < 0) ? 1 : flags, 0);
|
2008-07-31 10:47:15 +00:00
|
|
|
|
|
|
|
if (flags < 0) {
|
|
|
|
static const uint8 colorMap[] = { 0x00, 0xF0, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
|
|
|
|
2009-05-31 00:42:44 +00:00
|
|
|
_screen->setFont(Screen::FID_8_FNT);
|
|
|
|
_screen->setTextColorMap(colorMap);
|
|
|
|
_screen->_charWidth = -2;
|
2008-07-31 10:47:15 +00:00
|
|
|
}
|
|
|
|
|
2009-05-31 00:42:44 +00:00
|
|
|
_screen->_charOffset = -4;
|
|
|
|
_screen->copyRegionToBuffer(0, 0, 160, 320, 40, _textAreaBuffer);
|
2008-07-31 10:47:15 +00:00
|
|
|
_textDisplayed = true;
|
|
|
|
|
|
|
|
char backupChar = 0;
|
|
|
|
char *str = text;
|
|
|
|
int heightAdd = 0;
|
|
|
|
|
2009-06-25 21:17:50 +00:00
|
|
|
while (str[0] && _vm->textEnabled()) {
|
2008-07-31 10:47:15 +00:00
|
|
|
char *nextLine = strchr(str, '\r');
|
|
|
|
|
|
|
|
backupChar = 0;
|
|
|
|
if (nextLine) {
|
|
|
|
backupChar = nextLine[0];
|
|
|
|
nextLine[0] = '\0';
|
|
|
|
}
|
|
|
|
|
2009-05-31 00:42:44 +00:00
|
|
|
int width = _screen->getTextWidth(str);
|
2008-07-31 10:47:15 +00:00
|
|
|
|
2009-06-26 00:12:19 +00:00
|
|
|
if (flags >= 0) {
|
|
|
|
if (isPC98) {
|
|
|
|
static const uint8 colorMap[] = { 0xE1, 0xE1, 0xC1, 0xA1, 0x81, 0x61 };
|
|
|
|
_screen->printText(str, (320 - width) >> 1, 160 + heightAdd, colorMap[flags], 0x00);
|
|
|
|
} else {
|
|
|
|
_screen->printText(str, (320 - width) >> 1, 160 + heightAdd, 0xF0, 0x00);
|
|
|
|
}
|
|
|
|
} else {
|
2009-05-31 00:42:44 +00:00
|
|
|
_screen->printText(str, (320 - width) >> 1, 188, 0xF0, 0x00);
|
2009-06-26 00:12:19 +00:00
|
|
|
}
|
2008-07-31 10:47:15 +00:00
|
|
|
|
2009-05-31 00:42:44 +00:00
|
|
|
heightAdd += _screen->getFontHeight();
|
2008-07-31 10:47:15 +00:00
|
|
|
str += strlen(str);
|
|
|
|
|
|
|
|
if (backupChar) {
|
|
|
|
nextLine[0] = backupChar;
|
|
|
|
++str;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-05-31 00:42:44 +00:00
|
|
|
_screen->_charOffset = 0;
|
2008-07-31 10:47:15 +00:00
|
|
|
|
|
|
|
if (flags < 0) {
|
|
|
|
static const uint8 colorMap[] = { 0x00, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0x00, 0x00, 0x00, 0x00 };
|
|
|
|
|
2009-05-31 00:42:44 +00:00
|
|
|
_screen->setFont(Screen::FID_INTRO_FNT);
|
|
|
|
_screen->setTextColorMap(colorMap);
|
|
|
|
_screen->_charWidth = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void TIMInterpreter::displayText(uint16 textId, int16 flags, uint8 color) {
|
|
|
|
if (!_vm->textEnabled() && !(textId & 0x8000))
|
|
|
|
return;
|
|
|
|
|
|
|
|
char *text = getTableEntry(textId & 0x7FFF);
|
|
|
|
|
|
|
|
if (flags > 0)
|
|
|
|
_screen->copyBlockToPage(0, 0, 0, 320, 40, _textAreaBuffer);
|
|
|
|
|
|
|
|
if (flags == 255)
|
|
|
|
return;
|
|
|
|
|
|
|
|
_screen->setFont(Screen::FID_INTRO_FNT);
|
|
|
|
|
|
|
|
static const uint8 colorMap[] = { 0x00, 0xA0, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
|
|
|
_screen->setTextColorMap(colorMap);
|
|
|
|
_screen->_charWidth = 0;
|
|
|
|
_screen->_charOffset = -4;
|
|
|
|
|
|
|
|
if (!flags)
|
|
|
|
_screen->copyRegionToBuffer(0, 0, 0, 320, 40, _textAreaBuffer);
|
2009-06-02 00:10:13 +00:00
|
|
|
|
2009-05-31 00:42:44 +00:00
|
|
|
char backupChar = 0;
|
|
|
|
char *str = text;
|
|
|
|
int y = 0;
|
|
|
|
|
|
|
|
while (str[0]) {
|
|
|
|
char *nextLine = strchr(str, '\r');
|
|
|
|
|
|
|
|
backupChar = 0;
|
|
|
|
if (nextLine) {
|
|
|
|
backupChar = nextLine[0];
|
|
|
|
nextLine[0] = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
int width = _screen->getTextWidth(str);
|
|
|
|
|
|
|
|
if (flags >= 0)
|
|
|
|
_screen->printText(str, (320 - width) >> 1, y, color, 0x00);
|
|
|
|
else
|
|
|
|
_screen->printText(str, 0, y, color, 0x00);
|
|
|
|
|
|
|
|
y += _screen->getFontHeight() - 4;
|
|
|
|
str += strlen(str);
|
|
|
|
|
|
|
|
if (backupChar) {
|
|
|
|
nextLine[0] = backupChar;
|
|
|
|
++str;
|
|
|
|
}
|
2008-07-31 10:47:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void TIMInterpreter::setupTextPalette(uint index, int fadePalette) {
|
|
|
|
static const uint16 palTable[] = {
|
|
|
|
0x00, 0x00, 0x00,
|
|
|
|
0x64, 0x64, 0x64,
|
|
|
|
0x61, 0x51, 0x30,
|
|
|
|
0x29, 0x48, 0x64,
|
|
|
|
0x00, 0x4B, 0x3B,
|
|
|
|
0x64, 0x1E, 0x1E,
|
|
|
|
};
|
|
|
|
|
|
|
|
for (int i = 0; i < 15; ++i) {
|
2009-06-22 02:35:45 +00:00
|
|
|
uint8 *palette = _screen->getPalette(0).getData() + (240 + i) * 3;
|
2008-07-31 10:47:15 +00:00
|
|
|
|
|
|
|
uint8 c1 = (((15 - i) << 2) * palTable[index*3+0]) / 100;
|
|
|
|
uint8 c2 = (((15 - i) << 2) * palTable[index*3+1]) / 100;
|
|
|
|
uint8 c3 = (((15 - i) << 2) * palTable[index*3+2]) / 100;
|
|
|
|
|
|
|
|
palette[0] = c1;
|
|
|
|
palette[1] = c2;
|
|
|
|
palette[2] = c3;
|
|
|
|
}
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2008-07-31 10:47:15 +00:00
|
|
|
if (!fadePalette && !_palDiff) {
|
2009-06-22 02:36:54 +00:00
|
|
|
_screen->setScreenPalette(_screen->getPalette(0));
|
2008-07-31 10:47:15 +00:00
|
|
|
} else {
|
2009-06-22 02:36:54 +00:00
|
|
|
_screen->getFadeParams(_screen->getPalette(0), fadePalette, _palDelayInc, _palDiff);
|
2008-07-31 10:47:15 +00:00
|
|
|
_palDelayAcc = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TIMInterpreter::Animation *TIMInterpreter::initAnimStruct(int index, const char *filename, int x, int y, int, int offscreenBuffer, uint16 wsaFlags) {
|
|
|
|
Animation *anim = &_animations[index];
|
|
|
|
anim->x = x;
|
|
|
|
anim->y = y;
|
|
|
|
anim->wsaCopyParams = wsaFlags;
|
2009-05-31 00:42:44 +00:00
|
|
|
const bool isLoLDemo = _vm->gameFlags().isDemo && _vm->gameFlags().gameID == GI_LOL;
|
2009-05-18 19:53:57 +00:00
|
|
|
|
2009-07-14 22:47:33 +00:00
|
|
|
if (isLoLDemo || _vm->gameFlags().platform == Common::kPlatformPC98 || _currentTim->isLoLOutro)
|
|
|
|
_drawPage2 = 0;
|
|
|
|
else
|
|
|
|
_drawPage2 = 8;
|
2008-07-31 10:47:15 +00:00
|
|
|
|
2009-05-18 21:45:09 +00:00
|
|
|
uint16 wsaOpenFlags = 0;
|
|
|
|
if (isLoLDemo) {
|
|
|
|
if (!(wsaFlags & 0x10))
|
|
|
|
wsaOpenFlags |= 1;
|
|
|
|
} else {
|
|
|
|
if (wsaFlags & 0x10)
|
|
|
|
wsaOpenFlags |= 2;
|
|
|
|
wsaOpenFlags |= 1;
|
|
|
|
|
|
|
|
if (offscreenBuffer == 2)
|
|
|
|
wsaOpenFlags = 1;
|
|
|
|
}
|
2008-07-31 10:47:15 +00:00
|
|
|
|
|
|
|
char file[32];
|
|
|
|
snprintf(file, 32, "%s.WSA", filename);
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2009-05-31 00:42:44 +00:00
|
|
|
if (_vm->resource()->exists(file)) {
|
2009-05-18 19:53:57 +00:00
|
|
|
if (isLoLDemo)
|
|
|
|
anim->wsa = new WSAMovie_v1(_vm);
|
|
|
|
else
|
2009-06-09 11:26:15 +00:00
|
|
|
anim->wsa = new WSAMovie_v2(_vm);
|
2008-07-31 10:47:15 +00:00
|
|
|
assert(anim->wsa);
|
|
|
|
|
2009-06-22 02:37:20 +00:00
|
|
|
anim->wsa->open(file, wsaOpenFlags, (index == 1) ? &_screen->getPalette(0) : 0);
|
2008-07-31 10:47:15 +00:00
|
|
|
}
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2008-07-31 10:47:15 +00:00
|
|
|
if (anim->wsa && anim->wsa->opened()) {
|
2009-05-18 19:53:57 +00:00
|
|
|
if (isLoLDemo) {
|
|
|
|
if (x == -1) {
|
|
|
|
int16 t = int8(320 - anim->wsa->width());
|
|
|
|
uint8 v = int8(t & 0x00FF) - int8((t & 0xFF00) >> 8);
|
|
|
|
v >>= 1;
|
|
|
|
anim->x = x = v;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (y == -1) {
|
|
|
|
int16 t = int8(200 - anim->wsa->height());
|
|
|
|
uint8 v = int8(t & 0x00FF) - int8((t & 0xFF00) >> 8);
|
|
|
|
v >>= 1;
|
|
|
|
anim->y = y = v;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (x == -1)
|
|
|
|
anim->x = x = 0;
|
|
|
|
if (y == -1)
|
|
|
|
anim->y = y = 0;
|
|
|
|
}
|
2008-07-31 10:47:15 +00:00
|
|
|
|
|
|
|
if (wsaFlags & 2) {
|
2009-06-22 02:36:54 +00:00
|
|
|
_screen->fadePalette(_screen->getPalette(1), 15, 0);
|
2009-05-31 00:42:44 +00:00
|
|
|
_screen->clearPage(_drawPage2);
|
2009-05-18 19:53:57 +00:00
|
|
|
if (_drawPage2)
|
2009-05-31 00:42:44 +00:00
|
|
|
_screen->checkedPageUpdate(8, 4);
|
|
|
|
_screen->updateScreen();
|
2008-07-31 10:47:15 +00:00
|
|
|
}
|
2009-05-21 13:13:09 +00:00
|
|
|
|
2008-07-31 10:47:15 +00:00
|
|
|
if (wsaFlags & 4) {
|
|
|
|
snprintf(file, 32, "%s.CPS", filename);
|
|
|
|
|
2009-05-31 00:42:44 +00:00
|
|
|
if (_vm->resource()->exists(file)) {
|
2009-06-22 02:37:20 +00:00
|
|
|
_screen->loadBitmap(file, 3, 3, &_screen->getPalette(0));
|
2009-05-31 00:42:44 +00:00
|
|
|
_screen->copyRegion(0, 0, 0, 0, 320, 200, 2, _drawPage2, Screen::CR_NO_P_CHECK);
|
2009-05-18 19:53:57 +00:00
|
|
|
if (_drawPage2)
|
2009-05-31 00:42:44 +00:00
|
|
|
_screen->checkedPageUpdate(8, 4);
|
|
|
|
_screen->updateScreen();
|
2008-07-31 10:47:15 +00:00
|
|
|
}
|
|
|
|
|
2009-06-09 11:26:15 +00:00
|
|
|
anim->wsa->displayFrame(0, 0, x, y, 0, 0, 0);
|
2009-01-01 15:06:43 +00:00
|
|
|
}
|
2008-07-31 10:47:15 +00:00
|
|
|
|
|
|
|
if (wsaFlags & 2)
|
2009-06-22 02:36:54 +00:00
|
|
|
_screen->fadePalette(_screen->getPalette(0), 30, 0);
|
2008-07-31 10:47:15 +00:00
|
|
|
} else {
|
|
|
|
if (wsaFlags & 2) {
|
2009-06-22 02:36:54 +00:00
|
|
|
_screen->fadePalette(_screen->getPalette(1), 15, 0);
|
2009-05-31 00:42:44 +00:00
|
|
|
_screen->clearPage(_drawPage2);
|
2009-05-18 19:53:57 +00:00
|
|
|
if (_drawPage2)
|
2009-05-31 00:42:44 +00:00
|
|
|
_screen->checkedPageUpdate(8, 4);
|
|
|
|
_screen->updateScreen();
|
2008-07-31 10:47:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
snprintf(file, 32, "%s.CPS", filename);
|
|
|
|
|
2009-05-31 00:42:44 +00:00
|
|
|
if (_vm->resource()->exists(file)) {
|
2009-06-22 02:37:20 +00:00
|
|
|
_screen->loadBitmap(file, 3, 3, &_screen->getPalette(0));
|
2009-05-31 00:42:44 +00:00
|
|
|
_screen->copyRegion(0, 0, 0, 0, 320, 200, 2, _drawPage2, Screen::CR_NO_P_CHECK);
|
2009-05-18 19:53:57 +00:00
|
|
|
if (_drawPage2)
|
2009-05-31 00:42:44 +00:00
|
|
|
_screen->checkedPageUpdate(8, 4);
|
|
|
|
_screen->updateScreen();
|
2008-07-31 10:47:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (wsaFlags & 2)
|
2009-06-22 02:36:54 +00:00
|
|
|
_screen->fadePalette(_screen->getPalette(0), 30, 0);
|
2009-02-01 19:27:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2008-07-31 10:47:15 +00:00
|
|
|
char *TIMInterpreter::getTableEntry(uint idx) {
|
|
|
|
if (!_langData)
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
return (char *)(_langData + READ_LE_UINT16(_langData + (idx<<1)));
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *TIMInterpreter::getCTableEntry(uint idx) const {
|
|
|
|
if (!_langData)
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
return (const char *)(_langData + READ_LE_UINT16(_langData + (idx<<1)));
|
|
|
|
}
|
|
|
|
|
2008-04-19 13:52:09 +00:00
|
|
|
int TIMInterpreter::execCommand(int cmd, const uint16 *param) {
|
|
|
|
if (cmd < 0 || cmd >= _commandsSize) {
|
2008-07-10 12:12:42 +00:00
|
|
|
warning("Calling unimplemented TIM command %d from file '%s'", cmd, _currentTim->filename);
|
2008-04-19 13:52:09 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_commands[cmd].proc == 0) {
|
2008-07-10 12:12:42 +00:00
|
|
|
warning("Calling unimplemented TIM command %d from file '%s'", cmd, _currentTim->filename);
|
2008-04-19 13:52:09 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-07-31 10:47:15 +00:00
|
|
|
debugC(5, kDebugLevelScript, "TIMInterpreter::%s(%p)", _commands[cmd].desc, (const void* )param);
|
2008-04-19 13:52:09 +00:00
|
|
|
return (this->*_commands[cmd].proc)(param);
|
|
|
|
}
|
|
|
|
|
2008-04-19 14:31:10 +00:00
|
|
|
int TIMInterpreter::cmd_initFunc0(const uint16 *param) {
|
2008-07-31 10:47:15 +00:00
|
|
|
for (int i = 0; i < TIM::kWSASlots; ++i)
|
|
|
|
memset(&_currentTim->wsa[i], 0, sizeof(TIM::WSASlot));
|
|
|
|
|
2008-04-19 13:52:09 +00:00
|
|
|
_currentTim->func[0].ip = _currentTim->func[0].avtl;
|
|
|
|
_currentTim->func[0].lastTime = _system->getMillis();
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int TIMInterpreter::cmd_stopCurFunc(const uint16 *param) {
|
2008-06-01 15:18:58 +00:00
|
|
|
if (_currentFunc < TIM::kCountFuncs)
|
2008-04-19 13:52:09 +00:00
|
|
|
_currentTim->func[_currentFunc].ip = 0;
|
|
|
|
if (!_currentFunc)
|
|
|
|
_finished = true;
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
|
2009-02-02 23:20:55 +00:00
|
|
|
void TIMInterpreter::stopAllFuncs(TIM *tim) {
|
|
|
|
for (int i = 0; i < TIM::kCountFuncs; ++i)
|
|
|
|
tim->func[i].ip = 0;
|
|
|
|
}
|
|
|
|
|
2008-07-31 10:47:15 +00:00
|
|
|
int TIMInterpreter::cmd_initWSA(const uint16 *param) {
|
|
|
|
const int index = param[0];
|
|
|
|
|
|
|
|
TIM::WSASlot &slot = _currentTim->wsa[index];
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2008-07-31 10:47:15 +00:00
|
|
|
slot.x = int16(param[2]);
|
|
|
|
slot.y = int16(param[3]);
|
|
|
|
slot.offscreen = param[4];
|
|
|
|
slot.wsaFlags = param[5];
|
|
|
|
const char *filename = (const char *)(_currentTim->text + READ_LE_UINT16(_currentTim->text + (param[1]<<1)));
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2008-07-31 10:47:15 +00:00
|
|
|
slot.anim = initAnimStruct(index, filename, slot.x, slot.y, 10, slot.offscreen, slot.wsaFlags);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int TIMInterpreter::cmd_uninitWSA(const uint16 *param) {
|
|
|
|
const int index = param[0];
|
|
|
|
|
|
|
|
TIM::WSASlot &slot = _currentTim->wsa[index];
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2008-07-31 10:47:15 +00:00
|
|
|
if (!slot.anim)
|
|
|
|
return 0;
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2008-07-31 10:47:15 +00:00
|
|
|
Animation &anim = _animations[index];
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2008-07-31 10:47:15 +00:00
|
|
|
if (slot.offscreen) {
|
|
|
|
delete anim.wsa;
|
|
|
|
anim.wsa = 0;
|
|
|
|
slot.anim = 0;
|
|
|
|
} else {
|
|
|
|
//XXX
|
|
|
|
|
|
|
|
delete anim.wsa;
|
2009-03-14 13:48:12 +00:00
|
|
|
bool hasParts = anim.parts ? true : false;
|
|
|
|
delete[] anim.parts;
|
|
|
|
|
2008-07-31 10:47:15 +00:00
|
|
|
memset(&anim, 0, sizeof(Animation));
|
|
|
|
memset(&slot, 0, sizeof(TIM::WSASlot));
|
2009-03-14 13:48:12 +00:00
|
|
|
|
|
|
|
if (hasParts) {
|
|
|
|
anim.parts = new AnimPart[TIM::kAnimParts];
|
|
|
|
memset(anim.parts, 0, TIM::kAnimParts * sizeof(AnimPart));
|
|
|
|
}
|
2008-07-31 10:47:15 +00:00
|
|
|
}
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2008-07-31 10:47:15 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2008-04-19 13:52:09 +00:00
|
|
|
int TIMInterpreter::cmd_initFunc(const uint16 *param) {
|
|
|
|
uint16 func = *param;
|
2008-06-01 15:18:58 +00:00
|
|
|
assert(func < TIM::kCountFuncs);
|
2008-04-19 13:52:09 +00:00
|
|
|
if (_currentTim->func[func].avtl)
|
|
|
|
_currentTim->func[func].ip = _currentTim->func[func].avtl;
|
|
|
|
else
|
|
|
|
_currentTim->func[func].avtl = _currentTim->func[func].ip = _currentTim->avtl + _currentTim->avtl[func];
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int TIMInterpreter::cmd_stopFunc(const uint16 *param) {
|
|
|
|
uint16 func = *param;
|
2008-06-01 15:18:58 +00:00
|
|
|
assert(func < TIM::kCountFuncs);
|
2008-04-19 13:52:09 +00:00
|
|
|
_currentTim->func[func].ip = 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2008-07-31 10:47:15 +00:00
|
|
|
int TIMInterpreter::cmd_wsaDisplayFrame(const uint16 *param) {
|
|
|
|
Animation &anim = _animations[param[0]];
|
|
|
|
const int frame = param[1];
|
2009-05-10 13:40:28 +00:00
|
|
|
int page = (anim.wsaCopyParams & 0x4000) != 0 ? 2 : _drawPage2;
|
2009-05-18 01:39:58 +00:00
|
|
|
// WORKAROUND for some bugged scripts that will try to display frames of non-existent animations
|
2009-05-17 15:54:29 +00:00
|
|
|
if (anim.wsa)
|
|
|
|
anim.wsa->displayFrame(frame, page, anim.x, anim.y, anim.wsaCopyParams & 0xF0FF, 0, 0);
|
2009-05-10 13:40:28 +00:00
|
|
|
if (!page)
|
2009-05-31 00:42:44 +00:00
|
|
|
_screen->updateScreen();
|
2008-07-31 10:47:15 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int TIMInterpreter::cmd_displayText(const uint16 *param) {
|
2009-05-31 00:42:44 +00:00
|
|
|
if (_currentTim->isLoLOutro)
|
|
|
|
displayText(param[0], param[1], 0xF2);
|
|
|
|
else
|
|
|
|
displayText(param[0], param[1]);
|
2008-07-31 10:47:15 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int TIMInterpreter::cmd_loadVocFile(const uint16 *param) {
|
|
|
|
const int stringId = param[0];
|
|
|
|
const int index = param[1];
|
|
|
|
|
|
|
|
_vocFiles[index] = (const char *)(_currentTim->text + READ_LE_UINT16(_currentTim->text + (stringId << 1)));
|
2009-05-31 00:42:44 +00:00
|
|
|
|
|
|
|
if (index == 2 && _currentTim->isLoLOutro) {
|
|
|
|
_vocFiles[index] = "CONGRATA.VOC";
|
|
|
|
|
|
|
|
switch (_currentTim->lolCharacter) {
|
|
|
|
case 0:
|
|
|
|
_vocFiles[index].setChar('K', 7);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
_vocFiles[index].setChar('A', 7);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
_vocFiles[index].setChar('M', 7);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 3:
|
|
|
|
_vocFiles[index].setChar('C', 7);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-07-31 10:47:15 +00:00
|
|
|
for (int i = 0; i < 4; ++i)
|
|
|
|
_vocFiles[index].deleteLastChar();
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int TIMInterpreter::cmd_unloadVocFile(const uint16 *param) {
|
|
|
|
const int index = param[0];
|
|
|
|
_vocFiles[index].clear();
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int TIMInterpreter::cmd_playVocFile(const uint16 *param) {
|
|
|
|
const int index = param[0];
|
|
|
|
const int volume = (param[1] * 255) / 100;
|
|
|
|
|
|
|
|
if (index < ARRAYSIZE(_vocFiles) && !_vocFiles[index].empty())
|
2009-05-31 00:42:44 +00:00
|
|
|
_vm->sound()->voicePlay(_vocFiles[index].c_str(), 0, volume, true);
|
2009-04-25 13:15:05 +00:00
|
|
|
else if (index == 7 && !_vm->gameFlags().isTalkie)
|
2009-05-31 00:42:44 +00:00
|
|
|
_vm->sound()->playTrack(index);
|
2008-07-31 10:47:15 +00:00
|
|
|
else
|
2009-05-31 00:42:44 +00:00
|
|
|
_vm->sound()->playSoundEffect(index);
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2008-07-31 10:47:15 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int TIMInterpreter::cmd_loadSoundFile(const uint16 *param) {
|
|
|
|
const char *file = (const char *)(_currentTim->text + READ_LE_UINT16(_currentTim->text + (param[0]<<1)));
|
2008-11-30 02:54:39 +00:00
|
|
|
|
2009-05-31 00:42:44 +00:00
|
|
|
_vm->sound()->loadSoundFile(file);
|
|
|
|
if (_vm->gameFlags().gameID == GI_LOL)
|
|
|
|
_vm->sound()->loadSfxFile(file);
|
2008-11-30 02:54:39 +00:00
|
|
|
|
2008-07-31 10:47:15 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int TIMInterpreter::cmd_playMusicTrack(const uint16 *param) {
|
2009-05-31 00:42:44 +00:00
|
|
|
_vm->sound()->playTrack(param[0]);
|
2008-07-31 10:47:15 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int TIMInterpreter::cmd_setLoopIp(const uint16 *param) {
|
2009-02-02 23:20:55 +00:00
|
|
|
_currentTim->func[_currentFunc].loopIp = _currentTim->func[_currentFunc].ip;
|
2008-07-31 10:47:15 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int TIMInterpreter::cmd_continueLoop(const uint16 *param) {
|
|
|
|
TIM::Function &func = _currentTim->func[_currentFunc];
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2008-07-31 10:47:15 +00:00
|
|
|
if (!func.loopIp)
|
|
|
|
return -2;
|
|
|
|
|
|
|
|
func.ip = func.loopIp;
|
|
|
|
|
2009-02-02 23:20:55 +00:00
|
|
|
uint16 factor = param[0];
|
|
|
|
if (factor) {
|
2009-05-31 00:42:44 +00:00
|
|
|
const uint32 random = _vm->_rnd.getRandomNumberRng(0, 0x8000);
|
2009-02-02 23:20:55 +00:00
|
|
|
uint32 waitTime = (random * factor) / 0x8000;
|
2009-05-31 00:42:44 +00:00
|
|
|
func.nextTime += waitTime * _vm->tickLength();
|
2008-07-31 10:47:15 +00:00
|
|
|
}
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2009-02-01 19:27:01 +00:00
|
|
|
return -2;
|
2008-07-31 10:47:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int TIMInterpreter::cmd_resetLoopIp(const uint16 *param) {
|
|
|
|
_currentTim->func[_currentFunc].loopIp = 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2008-04-19 14:31:10 +00:00
|
|
|
int TIMInterpreter::cmd_resetAllRuntimes(const uint16 *param) {
|
2008-06-01 15:18:58 +00:00
|
|
|
for (int i = 0; i < TIM::kCountFuncs; ++i) {
|
2008-04-19 13:52:09 +00:00
|
|
|
if (_currentTim->func[i].ip)
|
|
|
|
_currentTim->func[i].nextTime = _system->getMillis();
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int TIMInterpreter::cmd_execOpcode(const uint16 *param) {
|
2008-07-31 10:47:15 +00:00
|
|
|
const uint16 opcode = *param++;
|
|
|
|
|
2008-04-19 13:52:09 +00:00
|
|
|
if (!_currentTim->opcodes) {
|
2008-07-31 10:47:15 +00:00
|
|
|
warning("Trying to execute TIM opcode %d without opcode list (file '%s')", opcode, _currentTim->filename);
|
2008-04-19 13:52:09 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (opcode > _currentTim->opcodes->size()) {
|
2008-07-10 12:14:00 +00:00
|
|
|
warning("Calling unimplemented TIM opcode(0x%.02X/%d) from file '%s'", opcode, opcode, _currentTim->filename);
|
2008-04-19 13:52:09 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-07-31 10:47:15 +00:00
|
|
|
if (!(*_currentTim->opcodes)[opcode]->isValid()) {
|
|
|
|
warning("Calling unimplemented TIM opcode(0x%.02X/%d) from file '%s'", opcode, opcode, _currentTim->filename);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-04-19 13:52:09 +00:00
|
|
|
return (*(*_currentTim->opcodes)[opcode])(_currentTim, param);
|
|
|
|
}
|
|
|
|
|
|
|
|
int TIMInterpreter::cmd_initFuncNow(const uint16 *param) {
|
|
|
|
uint16 func = *param;
|
2008-06-01 15:18:58 +00:00
|
|
|
assert(func < TIM::kCountFuncs);
|
2008-04-19 13:52:09 +00:00
|
|
|
_currentTim->func[func].ip = _currentTim->func[func].avtl;
|
|
|
|
_currentTim->func[func].lastTime = _currentTim->func[func].nextTime = _system->getMillis();
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int TIMInterpreter::cmd_stopFuncNow(const uint16 *param) {
|
|
|
|
uint16 func = *param;
|
2008-06-01 15:18:58 +00:00
|
|
|
assert(func < TIM::kCountFuncs);
|
2008-04-19 13:52:09 +00:00
|
|
|
_currentTim->func[func].ip = 0;
|
|
|
|
_currentTim->func[func].lastTime = _currentTim->func[func].nextTime = _system->getMillis();
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2009-02-01 19:27:01 +00:00
|
|
|
int TIMInterpreter::cmd_stopAllFuncs(const uint16 *param) {
|
2009-05-31 00:42:44 +00:00
|
|
|
while (_currentTim->dlgFunc == -1 && _currentTim->clickedButton == 0 && !_vm->shouldQuit()) {
|
2009-02-02 23:20:55 +00:00
|
|
|
update();
|
|
|
|
_currentTim->clickedButton = processDialogue();
|
2009-02-01 19:27:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < TIM::kCountFuncs; ++i)
|
|
|
|
_currentTim->func[i].ip = 0;
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2009-03-04 00:45:34 +00:00
|
|
|
// TODO: Consider moving to another file
|
|
|
|
|
|
|
|
#ifdef ENABLE_LOL
|
2009-02-02 23:20:55 +00:00
|
|
|
// LOL version of the TIM interpreter
|
|
|
|
|
|
|
|
TIMInterpreter_LoL::TIMInterpreter_LoL(LoLEngine *engine, Screen_v2 *screen_v2, OSystem *system) :
|
|
|
|
TIMInterpreter(engine, screen_v2, system), _vm(engine) {
|
|
|
|
#define COMMAND(x) { &TIMInterpreter_LoL::x, #x }
|
|
|
|
#define COMMAND_UNIMPL() { 0, 0 }
|
|
|
|
#define cmd_return(n) cmd_return_##n
|
|
|
|
static const CommandEntry commandProcs[] = {
|
|
|
|
// 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
|
|
|
|
#undef COMMAND_UNIMPL
|
|
|
|
#undef COMMAND
|
|
|
|
|
|
|
|
_commands = commandProcs ;
|
|
|
|
_commandsSize = ARRAYSIZE(commandProcs);
|
|
|
|
|
|
|
|
_screen = engine->_screen;
|
2009-03-14 13:48:12 +00:00
|
|
|
|
|
|
|
for (int i = 0; i < TIM::kWSASlots; i++) {
|
|
|
|
_animations[i].parts = new AnimPart[TIM::kAnimParts];
|
|
|
|
memset(_animations[i].parts, 0, TIM::kAnimParts * sizeof(AnimPart));
|
|
|
|
}
|
2009-05-21 13:13:09 +00:00
|
|
|
|
2009-02-02 23:20:55 +00:00
|
|
|
_drawPage2 = 0;
|
|
|
|
|
2009-05-29 12:52:03 +00:00
|
|
|
memset(_dialogueButtonString, 0, 3 * sizeof(const char *));
|
2009-02-02 23:20:55 +00:00
|
|
|
_dialogueButtonPosX = _dialogueButtonPosY = _dialogueNumButtons = _dialogueButtonXoffs = _dialogueHighlightedButton = 0;
|
|
|
|
}
|
|
|
|
|
2009-03-16 21:20:34 +00:00
|
|
|
TIMInterpreter::Animation *TIMInterpreter_LoL::initAnimStruct(int index, const char *filename, int x, int y, int frameDelay, int, uint16 wsaFlags) {
|
2009-02-02 23:20:55 +00:00
|
|
|
Animation *anim = &_animations[index];
|
|
|
|
anim->x = x;
|
|
|
|
anim->y = y;
|
2009-03-14 13:48:12 +00:00
|
|
|
anim->frameDelay = frameDelay;
|
2009-02-02 23:20:55 +00:00
|
|
|
anim->wsaCopyParams = wsaFlags;
|
2009-03-14 13:48:12 +00:00
|
|
|
anim->enable = 0;
|
|
|
|
anim->lastPart = -1;
|
2009-02-02 23:20:55 +00:00
|
|
|
|
|
|
|
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)) {
|
2009-06-09 11:26:15 +00:00
|
|
|
anim->wsa = new WSAMovie_v2(_vm);
|
2009-02-02 23:20:55 +00:00
|
|
|
assert(anim->wsa);
|
2009-06-22 02:37:20 +00:00
|
|
|
anim->wsa->open(file, wsaOpenFlags, &_screen->getPalette(3));
|
2009-02-02 23:20:55 +00:00
|
|
|
}
|
|
|
|
|
2009-09-19 13:17:55 +00:00
|
|
|
if (!_vm->_flags.use16ColorMode) {
|
|
|
|
if (wsaFlags & 1) {
|
|
|
|
if (_screen->_fadeFlag != 1)
|
|
|
|
_screen->fadeClearSceneWindow(10);
|
|
|
|
_screen->getPalette(3).copy(_screen->getPalette(0), 128, 128);
|
|
|
|
} else if (wsaFlags & 2) {
|
|
|
|
_screen->fadeToBlack(10);
|
|
|
|
}
|
2009-02-02 23:20:55 +00:00
|
|
|
}
|
|
|
|
|
2009-05-10 13:40:28 +00:00
|
|
|
if (wsaFlags & 7)
|
2009-06-09 11:26:15 +00:00
|
|
|
anim->wsa->displayFrame(0, 0, x, y, 0, 0, 0);
|
2009-02-02 23:20:55 +00:00
|
|
|
|
|
|
|
if (wsaFlags & 3) {
|
2009-09-19 13:17:55 +00:00
|
|
|
if (_vm->_flags.use16ColorMode) {
|
|
|
|
_vm->setPaletteBrightness(_screen->getPalette(0), _vm->_brightness, _vm->_lampEffect);
|
|
|
|
} else {
|
|
|
|
_screen->loadSpecialColors(_screen->getPalette(3));
|
|
|
|
_screen->fadePalette(_screen->getPalette(3), 10);
|
|
|
|
}
|
2009-02-02 23:20:55 +00:00
|
|
|
_screen->_fadeFlag = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return anim;
|
|
|
|
}
|
|
|
|
|
2009-03-14 13:48:12 +00:00
|
|
|
int TIMInterpreter_LoL::freeAnimStruct(int index) {
|
|
|
|
Animation *anim = &_animations[index];
|
|
|
|
if (!anim)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
delete anim->wsa;
|
|
|
|
delete[] anim->parts;
|
|
|
|
memset(anim, 0, sizeof(Animation));
|
|
|
|
|
|
|
|
anim->parts = new AnimPart[TIM::kAnimParts];
|
|
|
|
memset(anim->parts, 0, TIM::kAnimParts * sizeof(AnimPart));
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2009-02-02 23:20:55 +00:00
|
|
|
void TIMInterpreter_LoL::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();
|
|
|
|
}
|
|
|
|
|
|
|
|
void TIMInterpreter_LoL::drawDialogueBox(int numStr, const char *s1, const char *s2, const char *s3) {
|
2009-03-14 13:48:12 +00:00
|
|
|
_screen->setScreenDim(5);
|
|
|
|
|
2009-06-21 19:00:50 +00:00
|
|
|
if (numStr == 1 && _vm->speechEnabled()) {
|
2009-03-14 13:48:12 +00:00
|
|
|
_dialogueNumButtons = 0;
|
2009-02-02 23:20:55 +00:00
|
|
|
_dialogueButtonString[0] = _dialogueButtonString[1] = _dialogueButtonString[2] = 0;
|
|
|
|
} else {
|
|
|
|
_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;
|
2009-05-21 13:13:09 +00:00
|
|
|
_dialogueButtonPosX = d->sx + d->w - 77;
|
|
|
|
} else {
|
2009-02-02 23:20:55 +00:00
|
|
|
_dialogueButtonXoffs = d->w / numStr;
|
|
|
|
_dialogueButtonPosX = d->sx + (_dialogueButtonXoffs >> 1) - 37;
|
|
|
|
}
|
|
|
|
|
|
|
|
drawDialogueButtons();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!_vm->shouldQuit())
|
|
|
|
_vm->removeInputTop();
|
|
|
|
}
|
|
|
|
|
2009-03-14 13:48:12 +00:00
|
|
|
void TIMInterpreter_LoL::setupBackgroundAnimationPart(int animIndex, int part, int firstFrame, int lastFrame, int cycles, int nextPart, int partDelay, int f, int sfxIndex, int sfxFrame) {
|
|
|
|
AnimPart *a = &_animations[animIndex].parts[part];
|
|
|
|
a->firstFrame = firstFrame;
|
|
|
|
a->lastFrame = lastFrame;
|
|
|
|
a->cycles = cycles;
|
|
|
|
a->nextPart = nextPart;
|
|
|
|
a->partDelay = partDelay;
|
|
|
|
a->field_A = f;
|
|
|
|
a->sfxIndex = sfxIndex;
|
|
|
|
a->sfxFrame = sfxFrame;
|
|
|
|
}
|
|
|
|
|
|
|
|
void TIMInterpreter_LoL::startBackgroundAnimation(int animIndex, int part) {
|
|
|
|
Animation *anim = &_animations[animIndex];
|
|
|
|
anim->curPart = part;
|
|
|
|
AnimPart *p = &anim->parts[part];
|
|
|
|
anim->enable = 1;
|
|
|
|
anim->nextFrame = _system->getMillis() + anim->frameDelay * _vm->_tickLength;
|
|
|
|
anim->curFrame = p->firstFrame;
|
|
|
|
anim->cyclesCompleted = 0;
|
|
|
|
|
2009-05-18 01:39:58 +00:00
|
|
|
// WORKAROUND for some bugged scripts that will try to display frames of non-existent animations
|
2009-05-10 13:40:28 +00:00
|
|
|
if (anim->wsa)
|
2009-06-09 11:26:15 +00:00
|
|
|
anim->wsa->displayFrame(anim->curFrame - 1, 0, anim->x, anim->y, 0, 0, 0);
|
2009-03-14 13:48:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void TIMInterpreter_LoL::stopBackgroundAnimation(int animIndex) {
|
|
|
|
Animation *anim = &_animations[animIndex];
|
|
|
|
anim->enable = 0;
|
|
|
|
anim->field_D = 0;
|
|
|
|
if (animIndex == 5) {
|
|
|
|
delete anim->wsa;
|
|
|
|
anim->wsa = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void TIMInterpreter_LoL::updateBackgroundAnimation(int animIndex) {
|
|
|
|
Animation *anim = &_animations[animIndex];
|
|
|
|
if (!anim->enable || anim->nextFrame >= _system->getMillis())
|
|
|
|
return;
|
|
|
|
|
|
|
|
AnimPart *p = &anim->parts[anim->curPart];
|
|
|
|
anim->nextFrame = 0;
|
|
|
|
|
|
|
|
int step = 0;
|
|
|
|
if (p->lastFrame >= p->firstFrame) {
|
|
|
|
step = 1;
|
|
|
|
anim->curFrame++;
|
|
|
|
} else {
|
|
|
|
step = -1;
|
|
|
|
anim->curFrame--;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (anim->curFrame == (p->lastFrame + step)) {
|
|
|
|
anim->cyclesCompleted++;
|
|
|
|
|
|
|
|
if ((anim->cyclesCompleted > p->cycles) || anim->field_D) {
|
|
|
|
anim->lastPart = anim->curPart;
|
|
|
|
|
|
|
|
if ((p->nextPart == -1) || (anim->field_D && p->field_A)) {
|
|
|
|
anim->enable = 0;
|
|
|
|
anim->field_D = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
anim->nextFrame += (p->partDelay * _vm->_tickLength);
|
|
|
|
anim->curPart = p->nextPart;
|
|
|
|
|
|
|
|
p = &anim->parts[anim->curPart];
|
|
|
|
anim->curFrame = p->firstFrame;
|
|
|
|
anim->cyclesCompleted = 0;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
anim->curFrame = p->firstFrame;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p->sfxIndex != -1 && p->sfxFrame == anim->curFrame)
|
|
|
|
_vm->snd_playSoundEffect(p->sfxIndex, -1);
|
|
|
|
|
|
|
|
anim->nextFrame += (anim->frameDelay * _vm->_tickLength);
|
|
|
|
|
2009-06-09 11:26:15 +00:00
|
|
|
anim->wsa->displayFrame(anim->curFrame - 1, 0, anim->x, anim->y, 0, 0, 0);
|
2009-03-14 13:48:12 +00:00
|
|
|
anim->nextFrame += _system->getMillis();
|
|
|
|
}
|
|
|
|
|
2009-03-15 16:48:20 +00:00
|
|
|
void TIMInterpreter_LoL::playAnimationPart(int animIndex, int firstFrame, int lastFrame, int delay) {
|
|
|
|
Animation *anim = &_animations[animIndex];
|
2009-05-21 13:13:09 +00:00
|
|
|
|
2009-03-15 16:48:20 +00:00
|
|
|
int step = (lastFrame >= firstFrame) ? 1 : -1;
|
|
|
|
for (int i = firstFrame; i != (lastFrame + step) ; i += step) {
|
|
|
|
uint32 next = _system->getMillis() + delay * _vm->_tickLength;
|
|
|
|
if (anim->wsaCopyParams & 0x4000) {
|
|
|
|
_screen->copyRegion(112, 0, 112, 0, 176, 120, 6, 2);
|
2009-05-10 13:40:28 +00:00
|
|
|
anim->wsa->displayFrame(i - 1, 2, anim->x, anim->y, anim->wsaCopyParams & 0x1000 ? 0x5000 : 0x4000, _vm->_trueLightTable1, _vm->_trueLightTable2);
|
2009-03-15 16:48:20 +00:00
|
|
|
_screen->copyRegion(112, 0, 112, 0, 176, 120, 2, 0);
|
|
|
|
_screen->updateScreen();
|
|
|
|
} else {
|
2009-06-09 11:26:15 +00:00
|
|
|
anim->wsa->displayFrame(i - 1, 0, anim->x, anim->y, 0, 0, 0);
|
2009-03-15 16:48:20 +00:00
|
|
|
_screen->updateScreen();
|
|
|
|
}
|
2009-06-15 20:52:09 +00:00
|
|
|
int32 del = (int32)(next - _system->getMillis());
|
|
|
|
if (del > 0)
|
|
|
|
_vm->delay(del, true);
|
2009-03-15 16:48:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-05-30 19:48:13 +00:00
|
|
|
int TIMInterpreter_LoL::resetAnimationLastPart(int animIndex) {
|
|
|
|
Animation *anim = &_animations[animIndex];
|
|
|
|
int8 res = -1;
|
|
|
|
SWAP(res, anim->lastPart);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2009-02-02 23:20:55 +00:00
|
|
|
void TIMInterpreter_LoL::drawDialogueButtons() {
|
|
|
|
int cp = _screen->setCurPage(0);
|
2009-09-30 21:46:00 +00:00
|
|
|
Screen::FontId of;
|
2009-02-02 23:20:55 +00:00
|
|
|
|
|
|
|
int x = _dialogueButtonPosX;
|
|
|
|
|
|
|
|
for (int i = 0; i < _dialogueNumButtons; i++) {
|
2009-09-25 18:56:53 +00:00
|
|
|
if (_vm->gameFlags().use16ColorMode) {
|
2009-09-30 21:46:00 +00:00
|
|
|
of = _screen->setFont(Screen::FID_SJIS_FNT);
|
2009-09-25 18:56:53 +00:00
|
|
|
_vm->gui_drawBox(x, (_dialogueButtonPosY & ~7) - 1, 74, 10, 0xee, 0xcc, -1);
|
|
|
|
_screen->printText(_dialogueButtonString[i], (x + 37 - (_screen->getTextWidth(_dialogueButtonString[i])) / 2) & ~3,
|
2009-09-26 13:17:11 +00:00
|
|
|
(_dialogueButtonPosY + 2) & ~7, _dialogueHighlightedButton == i ? 0xc1 : 0xe1, 0);
|
2009-09-25 18:56:53 +00:00
|
|
|
} else {
|
2009-09-30 21:46:00 +00:00
|
|
|
of = _screen->setFont(Screen::FID_6_FNT);
|
2009-09-25 18:56:53 +00:00
|
|
|
_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);
|
|
|
|
}
|
|
|
|
|
2009-02-02 23:20:55 +00:00
|
|
|
x += _dialogueButtonXoffs;
|
|
|
|
}
|
|
|
|
_screen->setFont(of);
|
|
|
|
_screen->setCurPage(cp);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint16 TIMInterpreter_LoL::processDialogue() {
|
|
|
|
int df = _dialogueHighlightedButton;
|
|
|
|
int res = 0;
|
|
|
|
int x = _dialogueButtonPosX;
|
2009-09-26 13:17:11 +00:00
|
|
|
int y = (_vm->gameFlags().use16ColorMode ? (_dialogueButtonPosY & ~7) - 1 : _dialogueButtonPosY);
|
2009-02-02 23:20:55 +00:00
|
|
|
|
|
|
|
for (int i = 0; i < _dialogueNumButtons; i++) {
|
2009-06-15 20:52:09 +00:00
|
|
|
Common::Point p = _vm->getMousePos();
|
2009-09-26 13:17:11 +00:00
|
|
|
if (_vm->posWithinRect(p.x, p.y, x, y, x + 74, y + 9)) {
|
2009-02-02 23:20:55 +00:00
|
|
|
_dialogueHighlightedButton = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
x += _dialogueButtonXoffs;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_dialogueNumButtons == 0) {
|
2009-02-16 17:17:15 +00:00
|
|
|
int e = _vm->checkInput(0, false) & 0xFF;
|
2009-02-02 23:20:55 +00:00
|
|
|
_vm->removeInputTop();
|
2009-05-21 13:13:09 +00:00
|
|
|
|
2009-04-27 19:38:28 +00:00
|
|
|
if (e) {
|
|
|
|
_vm->gui_notifyButtonListChanged();
|
2009-05-21 13:13:09 +00:00
|
|
|
|
2009-04-27 19:38:28 +00:00
|
|
|
if (e == 43 || e == 61) {
|
|
|
|
_vm->snd_stopSpeech(true);
|
|
|
|
//_dlgTimer = 0;
|
|
|
|
}
|
2009-02-02 23:20:55 +00:00
|
|
|
}
|
|
|
|
|
2009-05-23 23:33:31 +00:00
|
|
|
if (_vm->snd_updateCharacterSpeech() != 2) {
|
2009-02-02 23:20:55 +00:00
|
|
|
//if (_dlgTimer < _system->getMillis()) {
|
|
|
|
res = 1;
|
2009-02-16 17:17:15 +00:00
|
|
|
if (!_vm->shouldQuit()) {
|
2009-02-02 23:20:55 +00:00
|
|
|
_vm->removeInputTop();
|
2009-02-16 17:17:15 +00:00
|
|
|
_vm->gui_notifyButtonListChanged();
|
|
|
|
}
|
2009-02-02 23:20:55 +00:00
|
|
|
//}
|
|
|
|
}
|
|
|
|
} else {
|
2009-02-16 17:17:15 +00:00
|
|
|
int e = _vm->checkInput(0, false) & 0xFF;
|
2009-02-02 23:20:55 +00:00
|
|
|
_vm->removeInputTop();
|
2009-04-27 19:38:28 +00:00
|
|
|
if (e)
|
|
|
|
_vm->gui_notifyButtonListChanged();
|
|
|
|
|
2009-02-02 23:20:55 +00:00
|
|
|
switch (e) {
|
2009-05-29 13:09:26 +00:00
|
|
|
case 43:
|
|
|
|
case 61:
|
|
|
|
_vm->snd_stopSpeech(true);
|
|
|
|
//_dlgTimer = 0;
|
|
|
|
res = _dialogueHighlightedButton + 1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 92:
|
|
|
|
case 97:
|
|
|
|
if (_dialogueNumButtons > 1 && _dialogueHighlightedButton > 0)
|
|
|
|
_dialogueHighlightedButton--;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 96:
|
|
|
|
case 102:
|
|
|
|
if (_dialogueNumButtons > 1 && _dialogueHighlightedButton < (_dialogueNumButtons - 1))
|
|
|
|
_dialogueHighlightedButton++;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 200:
|
|
|
|
case 202:
|
|
|
|
x = _dialogueButtonPosX;
|
2009-02-02 23:20:55 +00:00
|
|
|
|
2009-05-29 13:09:26 +00:00
|
|
|
for (int i = 0; i < _dialogueNumButtons; i++) {
|
2009-06-15 20:52:09 +00:00
|
|
|
Common::Point p = _vm->getMousePos();
|
2009-09-26 13:17:11 +00:00
|
|
|
if (_vm->posWithinRect(p.x, p.y, x, y, x + 74, y + 9)) {
|
2009-05-29 13:09:26 +00:00
|
|
|
_dialogueHighlightedButton = i;
|
|
|
|
res = _dialogueHighlightedButton + 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
x += _dialogueButtonXoffs;
|
|
|
|
}
|
|
|
|
break;
|
2009-02-02 23:20:55 +00:00
|
|
|
|
2009-05-29 13:09:26 +00:00
|
|
|
default:
|
|
|
|
break;
|
2009-02-02 23:20:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (df != _dialogueHighlightedButton)
|
|
|
|
drawDialogueButtons();
|
2009-05-21 13:13:09 +00:00
|
|
|
|
2009-09-05 22:00:17 +00:00
|
|
|
_screen->updateScreen();
|
|
|
|
|
2009-02-02 23:20:55 +00:00
|
|
|
if (res == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
_vm->updatePortraits();
|
|
|
|
|
2009-03-24 07:18:16 +00:00
|
|
|
if (!_vm->textEnabled() && _vm->_currentControlMode) {
|
2009-02-02 23:20:55 +00:00
|
|
|
_screen->setScreenDim(5);
|
|
|
|
const ScreenDim *d = _screen->getScreenDim(5);
|
|
|
|
_screen->fillRect(d->sx, d->sy + d->h - 9, d->sx + d->w - 1, d->sy + d->h - 1, d->unkA);
|
|
|
|
} else {
|
|
|
|
const ScreenDim *d = _screen->_curDim;
|
2009-09-26 18:25:36 +00:00
|
|
|
_screen->fillRect(d->sx, d->sy, d->sx + d->w - (_vm->gameFlags().use16ColorMode ? 3 : 2), d->sy + d->h - 1, d->unkA);
|
2009-03-17 18:27:56 +00:00
|
|
|
_vm->_txt->clearDim(4);
|
|
|
|
_vm->_txt->resetDimTextPositions(4);
|
2009-02-02 23:20:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2009-04-25 13:15:05 +00:00
|
|
|
void TIMInterpreter_LoL::resetDialogueState(TIM *tim) {
|
2009-03-14 13:48:12 +00:00
|
|
|
if (!tim)
|
|
|
|
return;
|
|
|
|
|
|
|
|
tim->procFunc = 0;
|
|
|
|
tim->procParam = _dialogueNumButtons ? _dialogueNumButtons : 1;
|
|
|
|
tim->clickedButton = 0;
|
|
|
|
tim->dlgFunc = -1;
|
|
|
|
}
|
|
|
|
|
2009-02-02 23:20:55 +00:00
|
|
|
void TIMInterpreter_LoL::update() {
|
|
|
|
_vm->update();
|
|
|
|
}
|
|
|
|
|
|
|
|
void TIMInterpreter_LoL::checkSpeechProgress() {
|
|
|
|
if (_vm->speechEnabled() && _currentTim->procParam > 1 && _currentTim->func[_currentFunc].loopIp) {
|
2009-05-23 23:33:31 +00:00
|
|
|
if (_vm->snd_updateCharacterSpeech() != 2) {
|
2009-02-02 23:20:55 +00:00
|
|
|
_currentTim->func[_currentFunc].loopIp = 0;
|
|
|
|
_currentTim->dlgFunc = _currentFunc;
|
|
|
|
advanceToOpcode(21);
|
|
|
|
_currentTim->dlgFunc = -1;
|
2009-03-14 13:48:12 +00:00
|
|
|
_animations[5].field_D = 0;
|
|
|
|
_animations[5].enable = 0;
|
|
|
|
delete _animations[5].wsa;
|
|
|
|
_animations[5].wsa = 0;
|
2009-02-02 23:20:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-05-21 13:13:09 +00:00
|
|
|
|
2009-02-02 23:20:55 +00:00
|
|
|
char *TIMInterpreter_LoL::getTableString(int id) {
|
|
|
|
return _vm->getLangString(id);
|
|
|
|
}
|
|
|
|
|
|
|
|
int TIMInterpreter_LoL::execCommand(int cmd, const uint16 *param) {
|
|
|
|
if (cmd < 0 || cmd >= _commandsSize) {
|
|
|
|
warning("Calling unimplemented TIM command %d from file '%s'", cmd, _currentTim->filename);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_commands[cmd].proc == 0) {
|
|
|
|
warning("Calling unimplemented TIM command %d from file '%s'", cmd, _currentTim->filename);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
debugC(5, kDebugLevelScript, "TIMInterpreter::%s(%p)", _commands[cmd].desc, (const void* )param);
|
|
|
|
return (this->*_commands[cmd].proc)(param);
|
|
|
|
}
|
|
|
|
|
|
|
|
int TIMInterpreter_LoL::cmd_setLoopIp(const uint16 *param) {
|
|
|
|
if (_vm->speechEnabled()) {
|
2009-05-23 23:33:31 +00:00
|
|
|
if (_vm->snd_updateCharacterSpeech() == 2)
|
2009-02-02 23:20:55 +00:00
|
|
|
_currentTim->func[_currentFunc].loopIp = _currentTim->func[_currentFunc].ip;
|
|
|
|
else
|
|
|
|
advanceToOpcode(21);
|
|
|
|
} else {
|
|
|
|
_currentTim->func[_currentFunc].loopIp = _currentTim->func[_currentFunc].ip;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int TIMInterpreter_LoL::cmd_continueLoop(const uint16 *param) {
|
|
|
|
TIM::Function &func = _currentTim->func[_currentFunc];
|
|
|
|
|
|
|
|
if (!func.loopIp)
|
|
|
|
return -2;
|
|
|
|
|
|
|
|
func.ip = func.loopIp;
|
|
|
|
|
2009-05-23 23:33:31 +00:00
|
|
|
if (_vm->snd_updateCharacterSpeech() != 2) {
|
2009-02-02 23:20:55 +00:00
|
|
|
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 -2;
|
|
|
|
}
|
|
|
|
|
|
|
|
int TIMInterpreter_LoL::cmd_processDialogue(const uint16 *param) {
|
|
|
|
int res = processDialogue();
|
2009-03-14 13:48:12 +00:00
|
|
|
if (!res || !_currentTim->procParam)
|
|
|
|
return res;
|
2009-02-01 19:27:01 +00:00
|
|
|
|
2009-02-16 17:17:15 +00:00
|
|
|
_vm->snd_stopSpeech(false);
|
2009-02-01 19:27:01 +00:00
|
|
|
|
|
|
|
_currentTim->func[_currentTim->procFunc].loopIp = 0;
|
|
|
|
_currentTim->dlgFunc = _currentTim->procFunc;
|
|
|
|
_currentTim->procFunc = -1;
|
|
|
|
_currentTim->clickedButton = res;
|
|
|
|
|
2009-03-14 13:48:12 +00:00
|
|
|
_animations[5].field_D = 0;
|
|
|
|
_animations[5].enable = 0;
|
|
|
|
delete _animations[5].wsa;
|
|
|
|
_animations[5].wsa = 0;
|
|
|
|
|
2009-02-01 19:27:01 +00:00
|
|
|
if (_currentTim->procParam)
|
2009-05-21 13:13:09 +00:00
|
|
|
advanceToOpcode(21);
|
2009-02-01 19:27:01 +00:00
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2009-02-02 23:20:55 +00:00
|
|
|
int TIMInterpreter_LoL::cmd_dialogueBox(const uint16 *param) {
|
2009-02-01 19:27:01 +00:00
|
|
|
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) {
|
2009-02-02 23:20:55 +00:00
|
|
|
tmpStr[i-1] = getTableString(param[i]);
|
2009-02-01 19:27:01 +00:00
|
|
|
cnt++;
|
|
|
|
} else {
|
|
|
|
tmpStr[i-1] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-02-02 23:20:55 +00:00
|
|
|
drawDialogueBox(cnt, tmpStr[0], tmpStr[1], tmpStr[2]);
|
2009-02-16 17:17:15 +00:00
|
|
|
_vm->gui_notifyButtonListChanged();
|
2009-02-01 19:27:01 +00:00
|
|
|
|
|
|
|
return -3;
|
|
|
|
}
|
2009-03-04 00:45:34 +00:00
|
|
|
#endif // ENABLE_LOL
|
2009-02-01 19:27:01 +00:00
|
|
|
|
2008-04-19 13:52:09 +00:00
|
|
|
} // end of namespace Kyra
|
|
|
|
|