scummvm/engines/gob/mult.cpp
2010-08-08 00:55:27 +00:00

459 lines
11 KiB
C++

/* 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 "gob/gob.h"
#include "gob/mult.h"
#include "gob/global.h"
#include "gob/util.h"
#include "gob/draw.h"
#include "gob/game.h"
#include "gob/script.h"
#include "gob/palanim.h"
#include "gob/scenery.h"
#include "gob/video.h"
#include "gob/videoplayer.h"
#include "gob/inter.h"
#include "gob/sound/sound.h"
namespace Gob {
Mult::Mult(GobEngine *vm) : _vm(vm) {
_multData = 0;
_frame = 0;
_objCount = 0;
_objects = 0;
_renderData = 0;
_renderObjs = 0;
_orderArray = 0;
_index = 0;
_counter = 0;
_animDataAllocated = false;
for (int i = 0; i < 8; i++)
_multDatas[i] = 0;
_doPalSubst = false;
_animArrayX = 0;
_animArrayY = 0;
_animArrayData = 0;
_palKeyIndex = 0;
_oldPalette = 0;
for (int i = 0; i < 256; i++) {
_palAnimPalette[i].red = 0;
_palAnimPalette[i].green = 0;
_palAnimPalette[i].blue = 0;
}
_palAnimKey = 0;
for (int i = 0; i < 4; i++) {
_palAnimRed[i] = 0;
_palAnimGreen[i] = 0;
_palAnimBlue[i] = 0;
}
_palFadingRed = 0;
_palFadingGreen = 0;
_palFadingBlue = 0;
_animLeft = 0;
_animTop = 0;
_animWidth = 0;
_animHeight = 0;
}
Mult::~Mult() {
if (_objects)
for (int i = 0; i < _objCount; i++) {
delete _objects[i].pPosX;
delete _objects[i].pPosY;
}
delete[] _objects;
delete[] _orderArray;
delete[] _renderData;
delete[] _renderObjs;
delete _animArrayX;
delete _animArrayY;
delete[] _animArrayData;
delete _multData;
}
void Mult::initAll() {
_objects = 0;
_animSurf.reset();
_renderData = 0;
_vm->_scenery->init();
}
void Mult::freeAll() {
freeMult();
for (int i = 0; i < 10; i++) {
_vm->_scenery->freeAnim(i);
_vm->_scenery->freeStatic(i);
}
}
void Mult::freeMult() {
clearObjectVideos();
if (_objects)
for (int i = 0; i < _objCount; i++) {
delete _objects[i].pPosX;
delete _objects[i].pPosY;
}
delete[] _objects;
delete[] _renderData;
delete[] _renderObjs;
delete[] _orderArray;
_objects = 0;
_renderData = 0;
_renderObjs = 0;
_orderArray = 0;
_animSurf.reset();
_vm->_draw->freeSprite(Draw::kAnimSurface);
}
void Mult::checkFreeMult() {
if (_multData)
freeMultKeys();
}
void Mult::zeroMultData() {
_multData = 0;
}
void Mult::playMult(int16 startFrame, int16 endFrame, char checkEscape,
char handleMouse) {
bool stopNoClear;
bool stop;
if (!_multData)
return;
stopNoClear = false;
_frame = startFrame;
if (endFrame == -1)
endFrame = 32767;
if (_frame == -1)
playMultInit();
do {
stop = true;
if (VAR(58) == 0) {
drawStatics(stop);
drawAnims(stop);
}
animate();
if (handleMouse)
_vm->_draw->animateCursor(-1);
else
_vm->_draw->blitInvalidated();
if (VAR(58) == 0)
drawText(stop, stopNoClear);
prepPalAnim(stop);
doPalAnim();
doFadeAnim(stop);
doSoundAnim(stop, _frame);
if (_frame >= endFrame)
stopNoClear = true;
if (_vm->_sound->blasterPlayingSound())
stop = false;
_vm->_util->processInput();
if (checkEscape && (_vm->_util->checkKey() == kKeyEscape))
stop = true;
_frame++;
_vm->_util->waitEndFrame();
} while (!stop && !stopNoClear && !_vm->shouldQuit());
if (!stopNoClear) {
if (_animDataAllocated) {
clearObjectVideos();
if (_objects)
for (int i = 0; i < _objCount; i++) {
delete _objects[i].pPosX;
delete _objects[i].pPosY;
}
delete[] _objects;
delete[] _renderData;
delete[] _renderObjs;
delete _animArrayX;
delete _animArrayY;
delete[] _animArrayData;
delete[] _orderArray;
_objects = 0;
_renderObjs = 0;
_renderData = 0;
_animArrayX = 0;
_animArrayY = 0;
_animArrayData = 0;
_orderArray = 0;
_animSurf.reset();
_vm->_draw->freeSprite(Draw::kAnimSurface);
_animDataAllocated = false;
}
if (_vm->_sound->blasterPlayingSound())
_vm->_sound->blasterStop(10);
WRITE_VAR(57, (uint32) -1);
} else
WRITE_VAR(57, _frame - _multData->frameStart - 1);
}
void Mult::drawText(bool &stop, bool &stopNoClear) {
int16 cmd;
for (_index = 0; _index < _multData->textKeysCount; _index++) {
if (_multData->textKeys[_index].frame != _frame)
continue;
cmd = _multData->textKeys[_index].cmd;
if (cmd == 0) {
stop = false;
} else if (cmd == 1) {
stopNoClear = true;
_multData->frameStart = 0;
} else if (cmd == 3) {
warning("Mult::drawText, cmd == 3");
stop = false;
// uint32 startPos = _vm->_game->_script->pos();
// _vm->_global->_inter_execPtr = _multData->textKeys[_index].script;
}
}
}
void Mult::prepPalAnim(bool &stop) {
_palKeyIndex = -1;
do {
_palKeyIndex++;
if (_palKeyIndex >= _multData->palKeysCount)
return;
} while (_multData->palKeys[_palKeyIndex].frame != _frame);
if (_multData->palKeys[_palKeyIndex].cmd == -1) {
stop = false;
_doPalSubst = false;
_vm->_global->_pPaletteDesc->vgaPal = _oldPalette;
_vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
} else {
stop = false;
_doPalSubst = true;
_palAnimKey = _palKeyIndex;
_multData->palAnimIndices[0] = 0;
_multData->palAnimIndices[1] = 0;
_multData->palAnimIndices[2] = 0;
_multData->palAnimIndices[3] = 0;
memcpy((char *)_palAnimPalette,
(char *)_vm->_global->_pPaletteDesc->vgaPal, 768);
_vm->_global->_pPaletteDesc->vgaPal = _palAnimPalette;
}
}
void Mult::doPalAnim() {
int16 off;
int16 off2;
Video::Color *palPtr;
Mult_PalKey *palKey;
if (!_doPalSubst)
return;
for (_index = 0; _index < 4; _index++) {
palKey = &_multData->palKeys[_palAnimKey];
if ((_frame % palKey->rates[_index]) != 0)
continue;
_palAnimRed[_index] =
_vm->_global->_pPaletteDesc->vgaPal[palKey->subst[0][_index] - 1].red;
_palAnimGreen[_index] =
_vm->_global->_pPaletteDesc->vgaPal[palKey->subst[0][_index] - 1].green;
_palAnimBlue[_index] =
_vm->_global->_pPaletteDesc->vgaPal[palKey->subst[0][_index] - 1].blue;
while (1) {
off = palKey->subst[(_multData->palAnimIndices[_index] + 1) % 16][_index];
if (off == 0) {
off = palKey->subst[_multData->palAnimIndices[_index]][_index] - 1;
_vm->_global->_pPaletteDesc->vgaPal[off].red = _palAnimRed[_index];
_vm->_global->_pPaletteDesc->vgaPal[off].green = _palAnimGreen[_index];
_vm->_global->_pPaletteDesc->vgaPal[off].blue = _palAnimBlue[_index];
} else {
off = palKey->subst[(_multData->palAnimIndices[_index] + 1) % 16][_index] - 1;
off2 = palKey->subst[_multData->palAnimIndices[_index]][_index] - 1;
_vm->_global->_pPaletteDesc->vgaPal[off2].red =
_vm->_global->_pPaletteDesc->vgaPal[off].red;
_vm->_global->_pPaletteDesc->vgaPal[off2].green =
_vm->_global->_pPaletteDesc->vgaPal[off].green;
_vm->_global->_pPaletteDesc->vgaPal[off2].blue =
_vm->_global->_pPaletteDesc->vgaPal[off].blue;
}
_multData->palAnimIndices[_index] = (_multData->palAnimIndices[_index] + 1) % 16;
off = palKey->subst[_multData->palAnimIndices[_index]][_index];
if (off == 0) {
_multData->palAnimIndices[_index] = 0;
off = palKey->subst[0][_index] - 1;
_palAnimRed[_index] = _vm->_global->_pPaletteDesc->vgaPal[off].red;
_palAnimGreen[_index] = _vm->_global->_pPaletteDesc->vgaPal[off].green;
_palAnimBlue[_index] = _vm->_global->_pPaletteDesc->vgaPal[off].blue;
}
if (_multData->palAnimIndices[_index] == 0)
break;
}
}
if (_vm->_global->_colorCount == 256) {
_vm->_video->waitRetrace();
palPtr = _vm->_global->_pPaletteDesc->vgaPal;
for (_counter = 0; _counter < 16; _counter++, palPtr++)
_vm->_video->setPalElem(_counter, palPtr->red, palPtr->green,
palPtr->blue, 0, 0x13);
palPtr = _vm->_global->_pPaletteDesc->vgaPal;
for (_counter = 0; _counter < 16; _counter++, palPtr++)
_vm->_global->_redPalette[_counter] = palPtr->red;
_vm->_global->_greenPalette[_counter] = palPtr->green;
_vm->_global->_bluePalette[_counter] = palPtr->blue;
} else
_vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
}
void Mult::doFadeAnim(bool &stop) {
Mult_PalFadeKey *fadeKey;
for (_index = 0; _index < _multData->palFadeKeysCount; _index++) {
fadeKey = &_multData->palFadeKeys[_index];
if (fadeKey->frame != _frame)
continue;
stop = false;
if (!(fadeKey->flag & 1)) {
if (fadeKey->fade == 0) {
_vm->_global->_pPaletteDesc->vgaPal =
_multData->fadePal[fadeKey->palIndex];
_vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
} else {
_vm->_global->_pPaletteDesc->vgaPal =
_multData->fadePal[fadeKey->palIndex];
_vm->_palAnim->fade(_vm->_global->_pPaletteDesc, fadeKey->fade, 0);
}
} else {
_vm->_global->_pPaletteDesc->vgaPal =
_multData->fadePal[fadeKey->palIndex];
_vm->_palAnim->fade(_vm->_global->_pPaletteDesc, fadeKey->fade, -1);
_palFadingRed = (fadeKey->flag >> 1) & 1;
_palFadingGreen = (fadeKey->flag >> 2) & 1;
_palFadingBlue = (fadeKey->flag >> 3) & 1;
}
}
if (_palFadingRed) {
_palFadingRed = !_vm->_palAnim->fadeStep(1);
stop = false;
}
if (_palFadingGreen) {
_palFadingGreen = !_vm->_palAnim->fadeStep(2);
stop = false;
}
if (_palFadingBlue) {
_palFadingBlue = !_vm->_palAnim->fadeStep(3);
stop = false;
}
}
void Mult::doSoundAnim(bool &stop, int16 frame) {
Mult_SndKey *sndKey;
for (_index = 0; _index < _multData->sndKeysCount; _index++) {
sndKey = &_multData->sndKeys[_index];
if (sndKey->frame != frame)
continue;
if (sndKey->cmd != -1) {
if ((sndKey->cmd == 1) || (sndKey->cmd == 4)) {
SoundDesc *sample = _vm->_sound->sampleGetBySlot(sndKey->soundIndex);
_vm->_sound->blasterStop(0);
if (sample && !sample->empty())
_vm->_sound->blasterPlay(sample, sndKey->repCount,
sndKey->freq, sndKey->fadeLength);
}
} else {
if (_vm->_sound->blasterPlayingSound())
_vm->_sound->blasterStop(sndKey->fadeLength);
}
}
}
void Mult::clearObjectVideos() {
if (!_objects)
return;
for (int i = 0; i < _objCount; i++)
if (_objects[i].videoSlot > 0)
_vm->_vidPlayer->closeVideo(_objects[i].videoSlot - 1);
}
} // End of namespace Gob