From f4c54fb636478b4bdf4a2e8c3a76b060459a0ca1 Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Sat, 12 Dec 2009 20:06:42 +0000 Subject: LOL: moved TIM animation code into a separate class svn-id: r46351 --- engines/kyra/animator_tim.cpp | 228 +++++++++++++++++++++++++++++++++++++++ engines/kyra/lol.cpp | 4 +- engines/kyra/lol.h | 2 + engines/kyra/module.mk | 1 + engines/kyra/script_lol.cpp | 18 ++-- engines/kyra/script_tim.cpp | 246 +++++++----------------------------------- engines/kyra/script_tim.h | 108 +++++++++++-------- 7 files changed, 343 insertions(+), 264 deletions(-) create mode 100644 engines/kyra/animator_tim.cpp diff --git a/engines/kyra/animator_tim.cpp b/engines/kyra/animator_tim.cpp new file mode 100644 index 0000000000..5e2245608f --- /dev/null +++ b/engines/kyra/animator_tim.cpp @@ -0,0 +1,228 @@ +/* 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 "common/endian.h" +#include "common/system.h" + +#include "kyra/script_tim.h" +#include "kyra/wsamovie.h" +#include "kyra/screen_lol.h" + +#ifdef ENABLE_LOL +#include "kyra/lol.h" +#endif ENABLE_LOL + +namespace Kyra { + +TimAnimator::TimAnimator(LoLEngine *engine, Screen_v2 *screen_v2, OSystem *system, bool useParts) : _vm(engine), _screen(screen_v2), _system(system), _useParts(useParts) { + _animations = new Animation[TIM::kWSASlots]; + memset(_animations, 0, TIM::kWSASlots * sizeof(Animation)); + + if (_useParts) { + for (int i = 0; i < TIM::kWSASlots; i++) { + _animations[i].parts = new AnimPart[TIM::kAnimParts]; + memset(_animations[i].parts, 0, TIM::kAnimParts * sizeof(AnimPart)); + } + } +} + +TimAnimator::~TimAnimator() { + for (int i = 0; i < TIM::kWSASlots; i++) { + delete _animations[i].wsa; + if (_useParts) + delete[] _animations[i].parts; + } + + delete[] _animations; +} + +void TimAnimator::init(int animIndex, Movie *wsa, int x, int y, int wsaCopyParams, int frameDelay) { + TimAnimator::Animation *anim = &_animations[animIndex]; + anim->wsa = wsa; + anim->x = x; + anim->y = y; + anim->wsaCopyParams = wsaCopyParams; + anim->frameDelay = frameDelay; + anim->enable = 0; + anim->lastPart = -1; +} + +void TimAnimator::reset(int animIndex, bool clearStruct) { + TimAnimator::Animation *anim = &_animations[animIndex]; + if (!anim) + return; + anim->field_D = 0; + anim->enable = 0; + delete anim->wsa; + anim->wsa = 0; + + if (clearStruct) { + if (_useParts) + delete[] anim->parts; + + memset(anim, 0, sizeof(Animation)); + + if (_useParts) { + anim->parts = new AnimPart[TIM::kAnimParts]; + memset(anim->parts, 0, TIM::kAnimParts * sizeof(AnimPart)); + } + } +} + +void TimAnimator::displayFrame(int animIndex, int page, int frame) { + TimAnimator::Animation *anim = &_animations[animIndex]; + if ((anim->wsaCopyParams & 0x4000) != 0) + page = 2; + // WORKAROUND for some bugged scripts that will try to display frames of non-existent animations + if (anim->wsa) + anim->wsa->displayFrame(frame, page, anim->x, anim->y, anim->wsaCopyParams & 0xF0FF, 0, 0); + if (!page) + _screen->updateScreen(); +} + +void TimAnimator::setupPart(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 TimAnimator::start(int animIndex, int part) { + if (!_vm || !_system || !_screen) + return; + + 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; + + // WORKAROUND for some bugged scripts that will try to display frames of non-existent animations + if (anim->wsa) + anim->wsa->displayFrame(anim->curFrame - 1, 0, anim->x, anim->y, 0, 0, 0); +} + +void TimAnimator::stop(int animIndex) { + Animation *anim = &_animations[animIndex]; + anim->enable = 0; + anim->field_D = 0; + if (animIndex == 5) { + delete anim->wsa; + anim->wsa = 0; + } +} + +void TimAnimator::update(int animIndex) { + if (!_vm || !_system || !_screen) + return; + + 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); + + anim->wsa->displayFrame(anim->curFrame - 1, 0, anim->x, anim->y, 0, 0, 0); + anim->nextFrame += _system->getMillis(); +} + +void TimAnimator::playPart(int animIndex, int firstFrame, int lastFrame, int delay) { + if (!_vm || !_system || !_screen) + return; + + Animation *anim = &_animations[animIndex]; + + 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); + anim->wsa->displayFrame(i - 1, 2, anim->x, anim->y, anim->wsaCopyParams & 0x1000 ? 0x5000 : 0x4000, _vm->_transparencyTable1, _vm->_transparencyTable2); + _screen->copyRegion(112, 0, 112, 0, 176, 120, 2, 0); + _screen->updateScreen(); + } else { + anim->wsa->displayFrame(i - 1, 0, anim->x, anim->y, 0, 0, 0); + _screen->updateScreen(); + } + int32 del = (int32)(next - _system->getMillis()); + if (del > 0) + _vm->delay(del, true); + } +} + +int TimAnimator::resetLastPart(int animIndex) { + Animation *anim = &_animations[animIndex]; + int8 res = -1; + SWAP(res, anim->lastPart); + return res; +} + +} // End of namespace Kyra diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp index 6f122c890e..4808223020 100644 --- a/engines/kyra/lol.cpp +++ b/engines/kyra/lol.cpp @@ -47,6 +47,7 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy _gui = 0; _txt = 0; _tim = 0; + _animator = 0; switch (_flags.lang) { case Common::EN_ANY: @@ -579,6 +580,7 @@ Common::Error LoLEngine::go() { _tim = new TIMInterpreter_LoL(this, _screen, _system); assert(_tim); + _animator = _tim->animator(); if (shouldQuit()) return Common::kNoError; @@ -1796,7 +1798,7 @@ void LoLEngine::updateSequenceBackgroundAnimations() { return; for (int i = 0; i < 6; i++) - _tim->updateBackgroundAnimation(i); + _animator->update(i); } void LoLEngine::loadTalkFile(int index) { diff --git a/engines/kyra/lol.h b/engines/kyra/lol.h index 0f2bca21e0..780b318775 100644 --- a/engines/kyra/lol.h +++ b/engines/kyra/lol.h @@ -300,6 +300,7 @@ class LoLEngine : public KyraEngine_v1 { friend class GUI_LoL; friend class TextDisplayer_LoL; friend class TIMInterpreter_LoL; +friend class TimAnimator; friend class Debugger_LoL; friend class HistoryPlayer; public: @@ -314,6 +315,7 @@ private: GUI_LoL *_gui; TIMInterpreter *_tim; + TimAnimator *_animator; Common::Error init(); Common::Error go(); diff --git a/engines/kyra/module.mk b/engines/kyra/module.mk index b484fa345f..b9006431d7 100644 --- a/engines/kyra/module.mk +++ b/engines/kyra/module.mk @@ -5,6 +5,7 @@ MODULE_OBJS := \ animator_v2.o \ animator_hof.o \ animator_mr.o \ + animator_tim.o \ debugger.o \ detection.o \ gui.o \ diff --git a/engines/kyra/script_lol.cpp b/engines/kyra/script_lol.cpp index 7fe89fb1cb..c49cc9d8d5 100644 --- a/engines/kyra/script_lol.cpp +++ b/engines/kyra/script_lol.cpp @@ -520,7 +520,7 @@ int LoLEngine::olol_initAnimStruct(EMCState *script) { int LoLEngine::olol_playAnimationPart(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_playAnimationPart(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); - _tim->playAnimationPart(stackPos(0), stackPos(1), stackPos(2), stackPos(3)); + _animator->playPart(stackPos(0), stackPos(1), stackPos(2), stackPos(3)); return 1; } @@ -589,13 +589,13 @@ int LoLEngine::olol_clearDialogueField(EMCState *script) { int LoLEngine::olol_setupBackgroundAnimationPart(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_setupBackgroundAnimationPart(%p) (%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)); - _tim->setupBackgroundAnimationPart(stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7), stackPos(8), stackPos(9)); + _animator->setupPart(stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7), stackPos(8), stackPos(9)); return 0; } int LoLEngine::olol_startBackgroundAnimation(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_startBackgroundAnimation(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); - _tim->startBackgroundAnimation(stackPos(0), stackPos(1)); + _animator->start(stackPos(0), stackPos(1)); return 1; } @@ -625,7 +625,7 @@ int LoLEngine::olol_loadBitmap(EMCState *script) { int LoLEngine::olol_stopBackgroundAnimation(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_stopBackgroundAnimation(%p) (%d)", (const void *)script, stackPos(0)); - _tim->stopBackgroundAnimation(stackPos(0)); + _animator->stop(stackPos(0)); return 1; } @@ -1978,7 +1978,7 @@ int LoLEngine::olol_removeInventoryItem(EMCState *script) { int LoLEngine::olol_getAnimationLastPart(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_getAnimationLastPart(%p) (%d)", (const void *)script, stackPos(0)); - return _tim->resetAnimationLastPart(stackPos(0)); + return _animator->resetLastPart(stackPos(0)); } int LoLEngine::olol_assignSpecialGuiShape(EMCState *script) { @@ -2393,7 +2393,7 @@ int LoLEngine::tlol_setupPaletteFadeEx(const TIM *tim, const uint16 *param) { int LoLEngine::tlol_processWsaFrame(const TIM *tim, const uint16 *param) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::tlol_processWsaFrame(%p, %p) (%d, %d, %d, %d, %d)", (const void *)tim, (const void *)param, param[0], param[1], param[2], param[3], param[4]); - TIMInterpreter::Animation *anim = (TIMInterpreter::Animation *)tim->wsa[param[0]].anim; + TimAnimator::Animation *anim = (TimAnimator::Animation *) tim->wsa[param[0]].anim; const int frame = param[1]; const int x2 = param[2]; const int y2 = param[3]; @@ -2576,13 +2576,13 @@ int LoLEngine::tlol_playSoundEffect(const TIM *tim, const uint16 *param) { int LoLEngine::tlol_startBackgroundAnimation(const TIM *tim, const uint16 *param) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::tlol_startBackgroundAnimation(%p, %p) (%d, %d)", (const void *)tim, (const void *)param, param[0], param[1]); - _tim->startBackgroundAnimation(param[0], param[1]); + _animator->start(param[0], param[1]); return 1; } int LoLEngine::tlol_stopBackgroundAnimation(const TIM *tim, const uint16 *param) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::tlol_stopBackgroundAnimation(%p, %p) (%d)", (const void *)tim, (const void *)param, param[0]); - _tim->stopBackgroundAnimation(param[0]); + _animator->stop(param[0]); return 1; } @@ -2665,7 +2665,7 @@ int LoLEngine::tlol_fadeOutSound(const TIM *tim, const uint16 *param) { int LoLEngine::tlol_displayAnimFrame(const TIM *tim, const uint16 *param) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::tlol_displayAnimFrame(%p, %p) (%d, %d)", (const void *)tim, (const void *)param, param[0], param[1]); - TIMInterpreter::Animation *anim = (TIMInterpreter::Animation *)tim->wsa[param[0]].anim; + TimAnimator::Animation *anim = (TimAnimator::Animation *)tim->wsa[param[0]].anim; if (param[1] == 0xFFFF) { _screen->copyRegion(0, 0, 0, 0, 320, 200, 0, 2, Screen::CR_NO_P_CHECK); } else { diff --git a/engines/kyra/script_tim.cpp b/engines/kyra/script_tim.cpp index 80e159433a..807d40c000 100644 --- a/engines/kyra/script_tim.cpp +++ b/engines/kyra/script_tim.cpp @@ -91,9 +91,6 @@ TIMInterpreter::TIMInterpreter(KyraEngine_v1 *engine, Screen_v2 *screen_v2, OSys _commands = commandProcs; _commandsSize = ARRAYSIZE(commandProcs); - _animations = new Animation[TIM::kWSASlots]; - memset(_animations, 0, TIM::kWSASlots * sizeof(Animation)); - _langData = 0; _textDisplayed = false; _textAreaBuffer = new uint8[320*40]; @@ -103,6 +100,8 @@ TIMInterpreter::TIMInterpreter(KyraEngine_v1 *engine, Screen_v2 *screen_v2, OSys else _drawPage2 = 8; + _animator = new TimAnimator(0, 0, 0, false); + _palDelayInc = _palDiff = _palDelayAcc = 0; _abortFlag = 0; _tim = 0; @@ -111,13 +110,7 @@ TIMInterpreter::TIMInterpreter(KyraEngine_v1 *engine, Screen_v2 *screen_v2, OSys TIMInterpreter::~TIMInterpreter() { delete[] _langData; delete[] _textAreaBuffer; - - for (int i = 0; i < TIM::kWSASlots; i++) { - delete _animations[i].wsa; - delete[] _animations[i].parts; - } - - delete[] _animations; + delete _animator; } bool TIMInterpreter::callback(Common::IFFChunk &chunk) { @@ -472,11 +465,9 @@ void TIMInterpreter::setupTextPalette(uint index, int fadePalette) { } } -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; +TimAnimator::Animation *TIMInterpreter::initAnimStruct(int index, const char *filename, int x, int y, int, int offscreenBuffer, uint16 wsaFlags) { + Movie *wsa = 0; + const bool isLoLDemo = _vm->gameFlags().isDemo && _vm->gameFlags().gameID == GI_LOL; if (isLoLDemo || _vm->gameFlags().platform == Common::kPlatformPC98 || _currentTim->isLoLOutro) @@ -502,34 +493,34 @@ TIMInterpreter::Animation *TIMInterpreter::initAnimStruct(int index, const char if (_vm->resource()->exists(file)) { if (isLoLDemo) - anim->wsa = new WSAMovie_v1(_vm); + wsa = new WSAMovie_v1(_vm); else - anim->wsa = new WSAMovie_v2(_vm); - assert(anim->wsa); + wsa = new WSAMovie_v2(_vm); + assert(wsa); - anim->wsa->open(file, wsaOpenFlags, (index == 1) ? &_screen->getPalette(0) : 0); + wsa->open(file, wsaOpenFlags, (index == 1) ? &_screen->getPalette(0) : 0); } - if (anim->wsa && anim->wsa->opened()) { + if (wsa && wsa->opened()) { if (isLoLDemo) { if (x == -1) { - int16 t = int8(320 - anim->wsa->width()); + int16 t = int8(320 - wsa->width()); uint8 v = int8(t & 0x00FF) - int8((t & 0xFF00) >> 8); v >>= 1; - anim->x = x = v; + x = v; } if (y == -1) { - int16 t = int8(200 - anim->wsa->height()); + int16 t = int8(200 - wsa->height()); uint8 v = int8(t & 0x00FF) - int8((t & 0xFF00) >> 8); v >>= 1; - anim->y = y = v; + y = v; } } else { if (x == -1) - anim->x = x = 0; + x = 0; if (y == -1) - anim->y = y = 0; + y = 0; } if (wsaFlags & 2) { @@ -551,7 +542,7 @@ TIMInterpreter::Animation *TIMInterpreter::initAnimStruct(int index, const char _screen->updateScreen(); } - anim->wsa->displayFrame(0, 0, x, y, 0, 0, 0); + wsa->displayFrame(0, 0, x, y, 0, 0, 0); } if (wsaFlags & 2) @@ -579,16 +570,13 @@ TIMInterpreter::Animation *TIMInterpreter::initAnimStruct(int index, const char _screen->fadePalette(_screen->getPalette(0), 30, 0); } - return anim; + _animator->init(index, wsa, x, y, wsaFlags, 0); + + return _animator->getAnimPtr(index); } int TIMInterpreter::freeAnimStruct(int index) { - Animation *anim = &_animations[index]; - if (!anim) - return 0; - - delete anim->wsa; - memset(anim, 0, sizeof(Animation)); + _animator->reset(index, true); return 1; } @@ -666,26 +654,13 @@ int TIMInterpreter::cmd_uninitWSA(const uint16 *param) { if (!slot.anim) return 0; - Animation &anim = _animations[index]; - if (slot.offscreen) { - delete anim.wsa; - anim.wsa = 0; + _animator->reset(index, false); slot.anim = 0; } else { //XXX - - delete anim.wsa; - bool hasParts = anim.parts ? true : false; - delete[] anim.parts; - - memset(&anim, 0, sizeof(Animation)); + _animator->reset(index, true); memset(&slot, 0, sizeof(TIM::WSASlot)); - - if (hasParts) { - anim.parts = new AnimPart[TIM::kAnimParts]; - memset(anim.parts, 0, TIM::kAnimParts * sizeof(AnimPart)); - } } return 1; @@ -709,14 +684,7 @@ int TIMInterpreter::cmd_stopFunc(const uint16 *param) { } int TIMInterpreter::cmd_wsaDisplayFrame(const uint16 *param) { - Animation &anim = _animations[param[0]]; - const int frame = param[1]; - int page = (anim.wsaCopyParams & 0x4000) != 0 ? 2 : _drawPage2; - // WORKAROUND for some bugged scripts that will try to display frames of non-existent animations - if (anim.wsa) - anim.wsa->displayFrame(frame, page, anim.x, anim.y, anim.wsaCopyParams & 0xF0FF, 0, 0); - if (!page) - _screen->updateScreen(); + _animator->displayFrame(param[0], _drawPage2, param[1]); return 1; } @@ -944,10 +912,7 @@ TIMInterpreter_LoL::TIMInterpreter_LoL(LoLEngine *engine, Screen_v2 *screen_v2, _screen = engine->_screen; - for (int i = 0; i < TIM::kWSASlots; i++) { - _animations[i].parts = new AnimPart[TIM::kAnimParts]; - memset(_animations[i].parts, 0, TIM::kAnimParts * sizeof(AnimPart)); - } + _animator = new TimAnimator(engine, screen_v2, system, true); _drawPage2 = 0; @@ -955,15 +920,8 @@ TIMInterpreter_LoL::TIMInterpreter_LoL(LoLEngine *engine, Screen_v2 *screen_v2, _dialogueButtonPosX = _dialogueButtonPosY = _dialogueNumButtons = _dialogueButtonXoffs = _dialogueHighlightedButton = 0; } -TIMInterpreter::Animation *TIMInterpreter_LoL::initAnimStruct(int index, const char *filename, int x, int y, int frameDelay, int, uint16 wsaFlags) { - Animation *anim = &_animations[index]; - anim->x = x; - anim->y = y; - anim->frameDelay = frameDelay; - anim->wsaCopyParams = wsaFlags; - anim->enable = 0; - anim->lastPart = -1; - +TimAnimator::Animation *TIMInterpreter_LoL::initAnimStruct(int index, const char *filename, int x, int y, int frameDelay, int, uint16 wsaFlags) { + Movie *wsa = 0; uint16 wsaOpenFlags = 0; if (wsaFlags & 0x10) wsaOpenFlags |= 2; @@ -974,9 +932,9 @@ TIMInterpreter::Animation *TIMInterpreter_LoL::initAnimStruct(int index, const c snprintf(file, 32, "%s.WSA", filename); if (_vm->resource()->exists(file)) { - anim->wsa = new WSAMovie_v2(_vm); - assert(anim->wsa); - anim->wsa->open(file, wsaOpenFlags, &_screen->getPalette(3)); + wsa = new WSAMovie_v2(_vm); + assert(wsa); + wsa->open(file, wsaOpenFlags, &_screen->getPalette(3)); } if (!_vm->_flags.use16ColorMode) { @@ -990,7 +948,7 @@ TIMInterpreter::Animation *TIMInterpreter_LoL::initAnimStruct(int index, const c } if (wsaFlags & 7) - anim->wsa->displayFrame(0, 0, x, y, 0, 0, 0); + wsa->displayFrame(0, 0, x, y, 0, 0, 0); if (wsaFlags & 3) { if (_vm->_flags.use16ColorMode) { @@ -1002,21 +960,13 @@ TIMInterpreter::Animation *TIMInterpreter_LoL::initAnimStruct(int index, const c _screen->_fadeFlag = 0; } - return anim; + _animator->init(index, wsa, x, y, wsaFlags, frameDelay); + + return _animator->getAnimPtr(index); } 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)); - + _animator->reset(index, true); return 1; } @@ -1067,120 +1017,6 @@ void TIMInterpreter_LoL::drawDialogueBox(int numStr, const char *s1, const char _vm->removeInputTop(); } -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; - - // WORKAROUND for some bugged scripts that will try to display frames of non-existent animations - if (anim->wsa) - anim->wsa->displayFrame(anim->curFrame - 1, 0, anim->x, anim->y, 0, 0, 0); -} - -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); - - anim->wsa->displayFrame(anim->curFrame - 1, 0, anim->x, anim->y, 0, 0, 0); - anim->nextFrame += _system->getMillis(); -} - -void TIMInterpreter_LoL::playAnimationPart(int animIndex, int firstFrame, int lastFrame, int delay) { - Animation *anim = &_animations[animIndex]; - - 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); - anim->wsa->displayFrame(i - 1, 2, anim->x, anim->y, anim->wsaCopyParams & 0x1000 ? 0x5000 : 0x4000, _vm->_transparencyTable1, _vm->_transparencyTable2); - _screen->copyRegion(112, 0, 112, 0, 176, 120, 2, 0); - _screen->updateScreen(); - } else { - anim->wsa->displayFrame(i - 1, 0, anim->x, anim->y, 0, 0, 0); - _screen->updateScreen(); - } - int32 del = (int32)(next - _system->getMillis()); - if (del > 0) - _vm->delay(del, true); - } -} - -int TIMInterpreter_LoL::resetAnimationLastPart(int animIndex) { - Animation *anim = &_animations[animIndex]; - int8 res = -1; - SWAP(res, anim->lastPart); - return res; -} - void TIMInterpreter_LoL::drawDialogueButtons() { int cp = _screen->setCurPage(0); Screen::FontId of = _screen->setFont(_vm->gameFlags().use16ColorMode ? Screen::FID_SJIS_FNT : Screen::FID_6_FNT); @@ -1316,10 +1152,7 @@ void TIMInterpreter_LoL::checkSpeechProgress() { _currentTim->dlgFunc = _currentFunc; advanceToOpcode(21); _currentTim->dlgFunc = -1; - _animations[5].field_D = 0; - _animations[5].enable = 0; - delete _animations[5].wsa; - _animations[5].wsa = 0; + _animator->reset(5, false); } } } @@ -1387,10 +1220,7 @@ int TIMInterpreter_LoL::cmd_processDialogue(const uint16 *param) { _currentTim->procFunc = -1; _currentTim->clickedButton = res; - _animations[5].field_D = 0; - _animations[5].enable = 0; - delete _animations[5].wsa; - _animations[5].wsa = 0; + _animator->reset(5, false); if (_currentTim->procParam) advanceToOpcode(21); diff --git a/engines/kyra/script_tim.h b/engines/kyra/script_tim.h index 7958dc66fc..ec9601721e 100644 --- a/engines/kyra/script_tim.h +++ b/engines/kyra/script_tim.h @@ -36,6 +36,63 @@ namespace Kyra { class WSAMovie_v2; class Screen_v2; +class LoLEngine; + +class TimAnimator { +public: + struct AnimPart { + uint16 firstFrame; + uint16 lastFrame; + uint16 cycles; + int16 nextPart; + int16 partDelay; + uint16 field_A; + int16 sfxIndex; + uint16 sfxFrame; + }; + + struct Animation { + Movie *wsa; + int16 x, y; + uint32 nextFrame; + uint8 enable; + uint8 field_D; + uint8 frameDelay; + int8 curPart; + uint8 curFrame; + uint8 cyclesCompleted; + uint16 wsaCopyParams; + int8 lastPart; + AnimPart *parts; + }; + + TimAnimator(LoLEngine *engine, Screen_v2 *screen_v2, OSystem *system, bool useParts); + ~TimAnimator(); + + Animation *getAnimPtr(int index) { return (index >= 0 && index < 6) ? &_animations[index] : 0; } + + void init(int animIndex, Movie *wsa, int x, int y, int wsaCopyParams, int frameDelay); + void reset(int animIndex, bool clearStruct); + + void displayFrame(int animIndex, int page, int frame); + + void setupPart(int animIndex, int part, int firstFrame, int lastFrame, int cycles, int nextPart, int partDelay, int f, int sfxIndex, int sfxFrame); + void start(int animIndex, int part); + void stop(int animIndex); + void update(int animIndex); + void playPart(int animIndex, int firstFrame, int lastFrame, int delay); + int resetLastPart(int animIndex); + +private: + LoLEngine *_vm; + Screen_v2 *_screen; + OSystem *_system; + + Animation *_animations; + + const bool _useParts; +}; + struct TIM; typedef Common::Functor2 TIMOpcode; @@ -89,32 +146,6 @@ struct TIM { class TIMInterpreter { public: - struct AnimPart { - uint16 firstFrame; - uint16 lastFrame; - uint16 cycles; - int16 nextPart; - int16 partDelay; - uint16 field_A; - int16 sfxIndex; - uint16 sfxFrame; - }; - - struct Animation { - Movie *wsa; - int16 x, y; - uint32 nextFrame; - uint8 enable; - uint8 field_D; - uint8 frameDelay; - int8 curPart; - uint8 curFrame; - uint8 cyclesCompleted; - uint16 wsaCopyParams; - int8 lastPart; - AnimPart *parts; - }; - TIMInterpreter(KyraEngine_v1 *engine, Screen_v2 *screen_v2, OSystem *system); virtual ~TIMInterpreter(); @@ -123,8 +154,9 @@ public: bool callback(Common::IFFChunk &chunk); - virtual Animation *initAnimStruct(int index, const char *filename, int x, int y, int, int offscreenBuffer, uint16 wsaFlags); + virtual TimAnimator::Animation *initAnimStruct(int index, const char *filename, int x, int y, int, int offscreenBuffer, uint16 wsaFlags); virtual int freeAnimStruct(int index); + TimAnimator *animator() { return _animator; } void setLangData(const char *filename); void clearLangData() { delete[] _langData; _langData = 0; } @@ -146,14 +178,6 @@ public: virtual void drawDialogueBox(int numStr, const char *s1, const char *s2, const char *s3) {} virtual uint16 processDialogue() { return 1; } - - virtual void setupBackgroundAnimationPart(int animIndex, int part, int firstFrame, int lastFrame, int cycles, int nextPart, int partDelay, int f, int sfxIndex, int sfxFrame) {} - virtual void startBackgroundAnimation(int animIndex, int part) {} - virtual void stopBackgroundAnimation(int animIndex) {} - virtual void updateBackgroundAnimation(int animIndex) {} - virtual void playAnimationPart(int animIndex, int firstFrame, int lastFrame, int delay) {} - virtual int resetAnimationLastPart(int animIndex) { return -1; } - virtual void resetDialogueState(TIM *tim) {} int _drawPage2; @@ -169,6 +193,8 @@ protected: TIM *_currentTim; int _currentFunc; + TimAnimator *_animator; + bool _finished; // used when loading @@ -178,8 +204,6 @@ protected: Common::String _vocFiles[120]; - Animation *_animations; - virtual void update() {} virtual void checkSpeechProgress() {} @@ -233,24 +257,16 @@ protected: class LoLEngine; class Screen_LoL; class TIMInterpreter_LoL : public TIMInterpreter { -friend class LoLEngine; public: TIMInterpreter_LoL(LoLEngine *engine, Screen_v2 *screen_v2, OSystem *system); - Animation *initAnimStruct(int index, const char *filename, int x, int y, int frameDelay, int, uint16 wsaCopyParams); + TimAnimator::Animation *initAnimStruct(int index, const char *filename, int x, int y, int frameDelay, int, uint16 wsaCopyParams); int freeAnimStruct(int index); void drawDialogueBox(int numStr, const char *s1, const char *s2, const char *s3); uint16 processDialogue(); void resetDialogueState(TIM *tim); - void setupBackgroundAnimationPart(int animIndex, int part, int firstFrame, int lastFrame, int cycles, int nextPart, int partDelay, int f, int sfxIndex, int sfxFrame); - void startBackgroundAnimation(int animIndex, int part); - void stopBackgroundAnimation(int animIndex); - void updateBackgroundAnimation(int animIndex); - void playAnimationPart(int animIndex, int firstFrame, int lastFrame, int delay); - int resetAnimationLastPart(int animIndex); - private: void update(); void checkSpeechProgress(); -- cgit v1.2.3