scummvm/engines/gob/scenery_v1.cpp

259 lines
6.3 KiB
C++

/* ScummVM - Scumm Interpreter
* Copyright (C) 2004 Ivan Dubrov
* Copyright (C) 2004-2006 The ScummVM project
*
* 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/stdafx.h"
#include "common/endian.h"
#include "gob/gob.h"
#include "gob/scenery.h"
#include "gob/anim.h"
#include "gob/draw.h"
#include "gob/game.h"
#include "gob/util.h"
#include "gob/cdrom.h"
namespace Gob {
Scenery_v1::Scenery_v1(GobEngine *vm) : Scenery(vm) {
}
int16 Scenery_v1::loadAnim(char search) {
if (_vm->_cdrom->_cdPlaying) {
while (_vm->_cdrom->getTrackPos() != -1)
_vm->_util->longDelay(50);
_vm->_cdrom->_cdPlaying = false;
}
return Scenery::loadAnim(search);
}
// flags & 1 - do capture all area animation is occupying
// flags & 4 == 0 - calculate animation final size
// flags & 2 != 0 - don't check with "toRedraw"'s
// flags & 4 != 0 - checkk view toRedraw
void Scenery_v1::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags,
int16 drawDeltaX, int16 drawDeltaY, char doDraw) {
AnimLayer *layerPtr;
PieceDesc **pictPtr;
uint16 pieceIndex;
uint16 pictIndex;
int16 curFrame;
int16 left;
int16 right;
int16 top;
int16 bottom;
byte highX;
byte highY;
int16 i;
int16 transp;
int16 destX;
int16 destY;
if (layer >= _animations[animation].layersCount)
return;
layerPtr = &_animations[animation].layers[layer];
if (frame >= layerPtr->framesCount)
return;
if (flags & 1) // Do capture
{
updateAnim(layer, frame, animation, 0, drawDeltaX,
drawDeltaY, 0);
if (_toRedrawLeft == -12345) // Some magic number?
return;
_vm->_game->capturePush(_toRedrawLeft, _toRedrawTop,
_toRedrawRight - _toRedrawLeft + 1,
_toRedrawBottom - _toRedrawTop + 1);
*_pCaptureCounter = *_pCaptureCounter + 1;
}
pictPtr = _animations[animation].pieces;
curFrame = 0;
for (i = 0; i < frame; i++, curFrame++) {
while (layerPtr->frames[curFrame].notFinal == 1)
curFrame++;
}
if ((flags & 4) == 0) {
_toRedrawLeft = -12345;
} else {
_toRedrawLeft =
MAX(_toRedrawLeft, _vm->_anim->_areaLeft);
_toRedrawTop =
MAX(_toRedrawTop, _vm->_anim->_areaTop);
_toRedrawRight =
MIN(_toRedrawRight,
(int16)(_vm->_anim->_areaLeft + _vm->_anim->_areaWidth - 1));
_toRedrawBottom =
MIN(_toRedrawBottom,
(int16)(_vm->_anim->_areaTop + _vm->_anim->_areaHeight - 1));
}
transp = layerPtr->transp ? 3 : 0;
curFrame--;
do {
curFrame++;
pieceIndex = layerPtr->frames[curFrame].pieceIndex;
pictIndex = layerPtr->frames[curFrame].pictIndex;
destX = layerPtr->frames[curFrame].destX;
destY = layerPtr->frames[curFrame].destY;
highX = pictIndex & 0xc0;
highY = pictIndex & 0x30;
highX >>= 6;
highY >>= 4;
if (destX >= 0)
destX += ((uint16)highX) << 7;
else
destX -= ((uint16)highX) << 7;
if (destY >= 0)
destY += ((uint16)highY) << 7;
else
destY -= ((uint16)highY) << 7;
if (drawDeltaX == 1000)
destX += layerPtr->posX;
else
destX += drawDeltaX;
if (drawDeltaY == 1000)
destY += layerPtr->posY;
else
destY += drawDeltaY;
pictIndex = (pictIndex & 15) - 1;
left = READ_LE_UINT16(&pictPtr[pictIndex][pieceIndex].left);
right = READ_LE_UINT16(&pictPtr[pictIndex][pieceIndex].right);
top = READ_LE_UINT16(&pictPtr[pictIndex][pieceIndex].top);
bottom = READ_LE_UINT16(&pictPtr[pictIndex][pieceIndex].bottom);
if (flags & 2) {
if (destX < _vm->_anim->_areaLeft) {
left += _vm->_anim->_areaLeft - destX;
destX = _vm->_anim->_areaLeft;
}
if (left <= right
&& destX + right - left >=
_vm->_anim->_areaLeft + _vm->_anim->_areaWidth)
right -=
(destX + right - left) -
(_vm->_anim->_areaLeft + _vm->_anim->_areaWidth) +
1;
if (destY < _vm->_anim->_areaTop) {
top += _vm->_anim->_areaTop - destY;
destY = _vm->_anim->_areaTop;
}
if (top <= bottom
&& destY + bottom - top >=
_vm->_anim->_areaTop + _vm->_anim->_areaHeight)
bottom -=
(destY + bottom - top) -
(_vm->_anim->_areaTop + _vm->_anim->_areaHeight) +
1;
} else if (flags & 4) {
if (destX < _toRedrawLeft) {
left += _toRedrawLeft - destX;
destX = _toRedrawLeft;
}
if (left <= right
&& destX + right - left > _toRedrawRight)
right -=
destX + right - left - _toRedrawRight;
if (destY < _toRedrawTop) {
top += _toRedrawTop - destY;
destY = _toRedrawTop;
}
if (top <= bottom
&& destY + bottom - top > _toRedrawBottom)
bottom -=
destY + bottom - top - _toRedrawBottom;
}
if (left > right || top > bottom)
continue;
if (doDraw) {
_vm->_draw->_sourceSurface =
_animPictToSprite[animation * 7 + pictIndex];
_vm->_draw->_destSurface = 21;
_vm->_draw->_spriteLeft = left;
_vm->_draw->_spriteTop = top;
_vm->_draw->_spriteRight = right - left + 1;
_vm->_draw->_spriteBottom = bottom - top + 1;
_vm->_draw->_destSpriteX = destX;
_vm->_draw->_destSpriteY = destY;
_vm->_draw->_transparency = transp;
_vm->_draw->spriteOperation(DRAW_BLITSURF);
}
if ((flags & 4) == 0) {
if (_toRedrawLeft == -12345) {
_toRedrawLeft = destX;
_animLeft = destX;
_toRedrawTop = destY;
_animTop = destY;
_toRedrawRight = destX + right - left;
_toRedrawBottom = destY + bottom - top;
} else {
_toRedrawLeft =
MIN(_toRedrawLeft, destX);
_toRedrawTop =
MIN(_toRedrawTop, destY);
_toRedrawRight =
MAX(_toRedrawRight,
(int16)(destX + right - left));
_toRedrawBottom =
MAX(_toRedrawBottom,
(int16)(destY + bottom - top));
}
}
} while (layerPtr->frames[curFrame].notFinal == 1);
}
} // End of namespace Gob