svn-id: r36178

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

View file

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