mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-20 00:41:12 +00:00
a802e1e64f
This creates a new CoktelDecoder class using the VideoDecoder interface, which will eventually become the new way to decode PreIMD, IMD and VMD videos. Since the VideoPlayer in gob is not yet ready for this, we're disabling all video playback in the gob engine for now. svn-id: r51850
978 lines
26 KiB
C++
978 lines
26 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 "common/stream.h"
|
|
|
|
#include "gob/gob.h"
|
|
#include "gob/scenery.h"
|
|
#include "gob/global.h"
|
|
#include "gob/draw.h"
|
|
#include "gob/game.h"
|
|
#include "gob/script.h"
|
|
#include "gob/resources.h"
|
|
#include "gob/inter.h"
|
|
#include "gob/map.h"
|
|
#include "gob/videoplayer.h"
|
|
|
|
namespace Gob {
|
|
|
|
Scenery::Scenery(GobEngine *vm) : _vm(vm) {
|
|
for (int i = 0; i < 20; i++) {
|
|
_spriteRefs[i] = 0;
|
|
_spriteResId[i] = 0;
|
|
}
|
|
|
|
for (int i = 0; i < 10; i++) {
|
|
_staticPictCount[i] = 0;
|
|
_staticResId[i] = 0;
|
|
_animPictCount[i] = 0;
|
|
_animResId[i] = 0;
|
|
}
|
|
|
|
_curStatic = 0;
|
|
_curStaticLayer = 0;
|
|
|
|
_toRedrawLeft = 0;
|
|
_toRedrawRight = 0;
|
|
_toRedrawTop = 0;
|
|
_toRedrawBottom = 0;
|
|
|
|
_animTop = 0;
|
|
_animLeft = 0;
|
|
|
|
_pCaptureCounter = 0;
|
|
|
|
for (int i = 0; i < 70; i++ ) {
|
|
_staticPictToSprite[i] = 0;
|
|
_animPictToSprite[i] = 0;
|
|
}
|
|
}
|
|
|
|
Scenery::~Scenery() {
|
|
for (int i = 0; i < 10; i++) {
|
|
freeStatic(i);
|
|
freeAnim(i);
|
|
}
|
|
}
|
|
|
|
void Scenery::init() {
|
|
for (int i = 0; i < 10; i++) {
|
|
_animPictCount[i] = 0;
|
|
_staticPictCount[i] = -1;
|
|
}
|
|
|
|
for (int i = 0; i < 20; i++) {
|
|
_spriteRefs[i] = 0;
|
|
_spriteResId[i] = -1;
|
|
}
|
|
|
|
_curStaticLayer = -1;
|
|
_curStatic = -1;
|
|
}
|
|
|
|
int16 Scenery::loadStatic(char search) {
|
|
int16 size;
|
|
byte *backsPtr;
|
|
int16 picsCount;
|
|
int16 resId;
|
|
int16 sceneryIndex;
|
|
Static *ptr;
|
|
int16 width;
|
|
int16 height;
|
|
int16 sprResId;
|
|
int16 sprIndex;
|
|
|
|
_vm->_game->_script->evalExpr(&sceneryIndex);
|
|
|
|
size = _vm->_game->_script->readInt16();
|
|
backsPtr = _vm->_game->_script->getData() + _vm->_game->_script->pos();
|
|
_vm->_game->_script->skip(size * 2);
|
|
picsCount = _vm->_game->_script->readInt16();
|
|
resId = _vm->_game->_script->readInt16();
|
|
|
|
if (search) {
|
|
int i;
|
|
|
|
for (i = 0; i < 10; i++) {
|
|
if ((_staticPictCount[i] != -1) && (_staticResId[i] == resId)) {
|
|
_vm->_game->_script->skip(8 * _staticPictCount[i]);
|
|
return i;
|
|
}
|
|
|
|
if (_staticPictCount[i] == -1 && i < sceneryIndex)
|
|
sceneryIndex = i;
|
|
}
|
|
}
|
|
|
|
_staticPictCount[sceneryIndex] = picsCount;
|
|
_staticResId[sceneryIndex] = resId;
|
|
|
|
Resource *resource = _vm->_game->_resources->getResource((uint16) resId);
|
|
if (!resource)
|
|
return 0;
|
|
|
|
ptr = &_statics[sceneryIndex];
|
|
|
|
ptr->layersCount = resource->stream()->readSint16LE();
|
|
|
|
ptr->layers = new StaticLayer[ptr->layersCount];
|
|
|
|
for (int i = 0; i < ptr->layersCount; i++) {
|
|
Common::SeekableReadStream &layerData = *resource->stream();
|
|
|
|
layerData.seek(2 + i * 2);
|
|
layerData.seek(layerData.readUint16LE());
|
|
|
|
ptr->layers[i].backResId = layerData.readSint16LE();
|
|
ptr->layers[i].planeCount = layerData.readSint16LE();
|
|
if (ptr->layers[i].planeCount > 0) {
|
|
ptr->layers[i].planes = new StaticPlane[ptr->layers[i].planeCount];
|
|
for (int j = 0; j < ptr->layers[i].planeCount; j++) {
|
|
ptr->layers[i].planes[j].pictIndex = layerData.readByte();
|
|
ptr->layers[i].planes[j].pieceIndex = layerData.readByte();
|
|
ptr->layers[i].planes[j].drawOrder = layerData.readByte();
|
|
ptr->layers[i].planes[j].destX = layerData.readSint16LE();
|
|
ptr->layers[i].planes[j].destY = layerData.readSint16LE();
|
|
ptr->layers[i].planes[j].transp = layerData.readSByte();
|
|
}
|
|
} else
|
|
ptr->layers[i].planes = 0;
|
|
|
|
ptr->layers[i].backResId = (int16) READ_LE_UINT16(backsPtr);
|
|
backsPtr += 2;
|
|
}
|
|
|
|
ptr->pieces = new PieceDesc*[picsCount];
|
|
ptr->piecesCount = new uint32[picsCount];
|
|
|
|
for (int i = 0; i < picsCount; i++) {
|
|
int16 pictDescId = _vm->_game->_script->readInt16();
|
|
|
|
loadPieces(pictDescId, ptr->pieces[i], ptr->piecesCount[i]);
|
|
|
|
width = _vm->_game->_script->readInt16();
|
|
height = _vm->_game->_script->readInt16();
|
|
sprResId = _vm->_game->_script->readInt16();
|
|
for (sprIndex = 0; sprIndex < 20; sprIndex++) {
|
|
if (_spriteResId[sprIndex] == sprResId)
|
|
break;
|
|
}
|
|
|
|
if (sprIndex < 20) {
|
|
_staticPictToSprite[7 * sceneryIndex + i] = sprIndex;
|
|
_spriteRefs[sprIndex]++;
|
|
} else {
|
|
for (sprIndex = 19; _vm->_draw->_spritesArray[sprIndex] != 0; sprIndex--) { }
|
|
|
|
_staticPictToSprite[7 * sceneryIndex + i] = sprIndex;
|
|
_spriteRefs[sprIndex] = 1;
|
|
_spriteResId[sprIndex] = sprResId;
|
|
_vm->_draw->initSpriteSurf(sprIndex, width, height, 2);
|
|
|
|
_vm->_video->clearSurf(*_vm->_draw->_spritesArray[sprIndex]);
|
|
_vm->_draw->_destSurface = sprIndex;
|
|
_vm->_draw->_spriteLeft = sprResId;
|
|
_vm->_draw->_transparency = 0;
|
|
_vm->_draw->_destSpriteX = 0;
|
|
_vm->_draw->_destSpriteY = 0;
|
|
_vm->_draw->spriteOperation(DRAW_LOADSPRITE);
|
|
}
|
|
}
|
|
|
|
delete resource;
|
|
return sceneryIndex + 100;
|
|
}
|
|
|
|
void Scenery::freeStatic(int16 index) {
|
|
int16 spr;
|
|
|
|
if (index == -1)
|
|
_vm->_game->_script->evalExpr(&index);
|
|
|
|
if (_staticPictCount[index] == -1)
|
|
return;
|
|
|
|
for (int i = 0; i < _staticPictCount[index]; i++) {
|
|
delete[] _statics[index].pieces[i];
|
|
|
|
spr = _staticPictToSprite[index * 7 + i];
|
|
_spriteRefs[spr]--;
|
|
if (_spriteRefs[spr] == 0) {
|
|
_vm->_draw->freeSprite(spr);
|
|
_spriteResId[spr] = -1;
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < _statics[index].layersCount; i++)
|
|
delete[] _statics[index].layers[i].planes;
|
|
|
|
delete[] _statics[index].layers;
|
|
delete[] _statics[index].pieces;
|
|
delete[] _statics[index].piecesCount;
|
|
|
|
_statics[index].layersCount = 0;
|
|
_staticPictCount[index] = -1;
|
|
}
|
|
|
|
void Scenery::renderStatic(int16 scenery, int16 layer) {
|
|
Static *ptr;
|
|
StaticLayer *layerPtr;
|
|
StaticPlane *planePtr;
|
|
int16 planeCount;
|
|
int16 order;
|
|
int16 plane;
|
|
|
|
uint16 pieceIndex;
|
|
uint16 pictIndex;
|
|
|
|
int16 left;
|
|
int16 right;
|
|
int16 top;
|
|
int16 bottom;
|
|
|
|
ptr = &_statics[scenery];
|
|
if (layer >= ptr->layersCount)
|
|
return;
|
|
|
|
layerPtr = &ptr->layers[layer];
|
|
|
|
_vm->_draw->_spriteLeft = layerPtr->backResId;
|
|
if (_vm->_draw->_spriteLeft != -1) {
|
|
_vm->_draw->_destSpriteX = 0;
|
|
_vm->_draw->_destSpriteY = 0;
|
|
_vm->_draw->_destSurface = 21;
|
|
_vm->_draw->_transparency = 0;
|
|
_vm->_draw->spriteOperation(DRAW_LOADSPRITE);
|
|
}
|
|
|
|
planeCount = layerPtr->planeCount;
|
|
for (order = 0; order < 100; order++) {
|
|
for (plane = 0, planePtr = layerPtr->planes; plane < planeCount; plane++, planePtr++) {
|
|
if (planePtr->drawOrder != order)
|
|
continue;
|
|
|
|
pieceIndex = planePtr->pieceIndex;
|
|
pictIndex = planePtr->pictIndex - 1;
|
|
|
|
if (pictIndex >= _staticPictCount[scenery])
|
|
continue;
|
|
|
|
if (!ptr->pieces || !ptr->pieces[pictIndex])
|
|
continue;
|
|
|
|
if (pieceIndex >= ptr->piecesCount[pictIndex])
|
|
continue;
|
|
|
|
_vm->_draw->_destSpriteX = planePtr->destX;
|
|
_vm->_draw->_destSpriteY = planePtr->destY;
|
|
left = ptr->pieces[pictIndex][pieceIndex].left;
|
|
right = ptr->pieces[pictIndex][pieceIndex].right;
|
|
top = ptr->pieces[pictIndex][pieceIndex].top;
|
|
bottom = ptr->pieces[pictIndex][pieceIndex].bottom;
|
|
|
|
_vm->_draw->_sourceSurface =
|
|
_staticPictToSprite[scenery * 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->_transparency = planePtr->transp ? 3 : 0;
|
|
_vm->_draw->spriteOperation(DRAW_BLITSURF);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Scenery::updateStatic(int16 orderFrom, byte index, byte layer) {
|
|
StaticLayer *layerPtr;
|
|
PieceDesc **pictPtr;
|
|
StaticPlane *planePtr;
|
|
int16 planeCount;
|
|
int16 order;
|
|
int16 plane;
|
|
uint16 pieceIndex;
|
|
uint16 pictIndex;
|
|
|
|
int16 left;
|
|
int16 right;
|
|
int16 top;
|
|
int16 bottom;
|
|
|
|
if ((index >= 10) || layer >= _statics[index].layersCount)
|
|
return;
|
|
|
|
layerPtr = &_statics[index].layers[layer];
|
|
pictPtr = _statics[index].pieces;
|
|
|
|
planeCount = layerPtr->planeCount;
|
|
|
|
for (order = orderFrom; order < 100; order++) {
|
|
for (planePtr = layerPtr->planes, plane = 0;
|
|
plane < planeCount; plane++, planePtr++) {
|
|
if (planePtr->drawOrder != order)
|
|
continue;
|
|
|
|
pieceIndex = planePtr->pieceIndex;
|
|
pictIndex = planePtr->pictIndex - 1;
|
|
|
|
if (pictIndex >= _staticPictCount[index])
|
|
continue;
|
|
|
|
if (!pictPtr || !pictPtr[pictIndex])
|
|
continue;
|
|
|
|
if (pieceIndex >= _statics[index].piecesCount[pictIndex])
|
|
continue;
|
|
|
|
_vm->_draw->_destSpriteX = planePtr->destX;
|
|
_vm->_draw->_destSpriteY = planePtr->destY;
|
|
|
|
left = pictPtr[pictIndex][pieceIndex].left;
|
|
right = pictPtr[pictIndex][pieceIndex].right;
|
|
top = pictPtr[pictIndex][pieceIndex].top;
|
|
bottom = pictPtr[pictIndex][pieceIndex].bottom;
|
|
|
|
if (_vm->_draw->_destSpriteX > _toRedrawRight)
|
|
continue;
|
|
|
|
if (_vm->_draw->_destSpriteY > _toRedrawBottom)
|
|
continue;
|
|
|
|
if (_vm->_draw->_destSpriteX < _toRedrawLeft) {
|
|
left += _toRedrawLeft - _vm->_draw->_destSpriteX;
|
|
_vm->_draw->_destSpriteX = _toRedrawLeft;
|
|
}
|
|
|
|
if (_vm->_draw->_destSpriteY < _toRedrawTop) {
|
|
top += _toRedrawTop - _vm->_draw->_destSpriteY;
|
|
_vm->_draw->_destSpriteY = _toRedrawTop;
|
|
}
|
|
|
|
_vm->_draw->_spriteLeft = left;
|
|
_vm->_draw->_spriteTop = top;
|
|
_vm->_draw->_spriteRight = right - left + 1;
|
|
_vm->_draw->_spriteBottom = bottom - top + 1;
|
|
|
|
if ((_vm->_draw->_spriteRight <= 0) ||
|
|
(_vm->_draw->_spriteBottom <= 0))
|
|
continue;
|
|
|
|
if ((_vm->_draw->_destSpriteX + _vm->_draw->_spriteRight - 1) >
|
|
_toRedrawRight)
|
|
_vm->_draw->_spriteRight =
|
|
_toRedrawRight - _vm->_draw->_destSpriteX + 1;
|
|
|
|
if ((_vm->_draw->_destSpriteY + _vm->_draw->_spriteBottom - 1) >
|
|
_toRedrawBottom)
|
|
_vm->_draw->_spriteBottom =
|
|
_toRedrawBottom - _vm->_draw->_destSpriteY + 1;
|
|
|
|
_vm->_draw->_sourceSurface =
|
|
_staticPictToSprite[index * 7 + pictIndex];
|
|
_vm->_draw->_destSurface = 21;
|
|
_vm->_draw->_transparency = planePtr->transp ? 3 : 0;
|
|
_vm->_draw->spriteOperation(DRAW_BLITSURF);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Scenery::updateStatic(int16 orderFrom) {
|
|
if (_curStatic == -1)
|
|
return;
|
|
|
|
if (_curStatic < 10000) {
|
|
updateStatic(orderFrom, _curStatic & 0xFF, _curStaticLayer & 0xFF);
|
|
|
|
if (_curStatic & 0xFF00)
|
|
updateStatic(orderFrom, ((_curStatic >> 8) & 0xFF) - 1,
|
|
(_curStaticLayer >> 8) & 0xFF);
|
|
} else
|
|
for (int i = 0; i < (_curStatic - 10000); i++)
|
|
updateStatic(orderFrom, i, 0);
|
|
}
|
|
|
|
int16 Scenery::loadAnim(char search) {
|
|
int16 picsCount;
|
|
int16 resId;
|
|
int16 i;
|
|
int16 j;
|
|
int16 sceneryIndex;
|
|
int16 framesCount;
|
|
Animation *ptr;
|
|
int16 width;
|
|
int16 height;
|
|
int16 sprResId;
|
|
int16 sprIndex;
|
|
uint32 layerPos;
|
|
|
|
_vm->_game->_script->evalExpr(&sceneryIndex);
|
|
picsCount = _vm->_game->_script->readInt16();
|
|
resId = _vm->_game->_script->readInt16();
|
|
|
|
if (search) {
|
|
for (i = 0; i < 10; i++) {
|
|
if ((_animPictCount[i] != 0) && (_animResId[i] == resId)) {
|
|
_vm->_game->_script->skip(8 * _animPictCount[i]);
|
|
return i;
|
|
}
|
|
|
|
if ((_animPictCount[i] == 0) && (i < sceneryIndex))
|
|
sceneryIndex = i;
|
|
}
|
|
}
|
|
|
|
_animPictCount[sceneryIndex] = picsCount;
|
|
_animResId[sceneryIndex] = resId;
|
|
|
|
Resource *resource = _vm->_game->_resources->getResource((uint16) resId);
|
|
if (!resource)
|
|
return 0;
|
|
|
|
ptr = &_animations[sceneryIndex];
|
|
|
|
ptr->layersCount = resource->stream()->readSint16LE();
|
|
|
|
ptr->layers = new AnimLayer[ptr->layersCount];
|
|
|
|
for (i = 0; i < ptr->layersCount; i++) {
|
|
Common::SeekableReadStream &layerData = *resource->stream();
|
|
|
|
layerData.seek(2 + i * 2);
|
|
layerData.seek(layerData.readUint16LE());
|
|
|
|
ptr->layers[i].unknown0 = layerData.readSint16LE();
|
|
ptr->layers[i].posX = layerData.readSint16LE();
|
|
ptr->layers[i].posY = layerData.readSint16LE();
|
|
ptr->layers[i].animDeltaX = layerData.readSint16LE();
|
|
ptr->layers[i].animDeltaY = layerData.readSint16LE();
|
|
ptr->layers[i].transp = layerData.readSByte();
|
|
ptr->layers[i].framesCount = layerData.readSint16LE();
|
|
|
|
// Going through the AnimFramePiece, finding the end for each
|
|
layerPos = layerData.pos();
|
|
framesCount = 0;
|
|
for (j = 0; j < ptr->layers[i].framesCount; j++) {
|
|
layerData.skip(4); // pictIndex, pieceIndex, destX, destY
|
|
while (layerData.readByte() == 1) {
|
|
framesCount++;
|
|
layerData.skip(4); // pictIndex, pieceIndex, destX, destY
|
|
}
|
|
framesCount++;
|
|
}
|
|
layerData.seek(layerPos);
|
|
|
|
ptr->layers[i].frames = new AnimFramePiece[framesCount];
|
|
for (j = 0; j < framesCount; j++) {
|
|
ptr->layers[i].frames[j].pictIndex = layerData.readByte();
|
|
ptr->layers[i].frames[j].pieceIndex = layerData.readByte();
|
|
ptr->layers[i].frames[j].destX = layerData.readSByte();
|
|
ptr->layers[i].frames[j].destY = layerData.readSByte();
|
|
ptr->layers[i].frames[j].notFinal = layerData.readSByte();
|
|
}
|
|
}
|
|
|
|
ptr->pieces = new PieceDesc*[picsCount];
|
|
ptr->piecesCount = new uint32[picsCount];
|
|
|
|
for (i = 0; i < picsCount; i++) {
|
|
int16 pictDescId = _vm->_game->_script->readInt16();
|
|
|
|
loadPieces(pictDescId, ptr->pieces[i], ptr->piecesCount[i]);
|
|
|
|
width = _vm->_game->_script->readInt16();
|
|
height = _vm->_game->_script->readInt16();
|
|
sprResId = _vm->_game->_script->readInt16();
|
|
for (sprIndex = 0; sprIndex < 20; sprIndex++)
|
|
if (_spriteResId[sprIndex] == sprResId)
|
|
break;
|
|
|
|
if (sprIndex < 20) {
|
|
_animPictToSprite[7 * sceneryIndex + i] = sprIndex;
|
|
_spriteRefs[sprIndex]++;
|
|
} else {
|
|
for (sprIndex = 19; _vm->_draw->_spritesArray[sprIndex];
|
|
sprIndex--)
|
|
;
|
|
|
|
_animPictToSprite[7 * sceneryIndex + i] = sprIndex;
|
|
_spriteRefs[sprIndex] = 1;
|
|
_spriteResId[sprIndex] = sprResId;
|
|
_vm->_draw->initSpriteSurf(sprIndex, width, height, 2);
|
|
|
|
_vm->_video->clearSurf(*_vm->_draw->_spritesArray[sprIndex]);
|
|
_vm->_draw->_destSurface = sprIndex;
|
|
_vm->_draw->_spriteLeft = sprResId;
|
|
_vm->_draw->_transparency = 0;
|
|
_vm->_draw->_destSpriteX = 0;
|
|
_vm->_draw->_destSpriteY = 0;
|
|
_vm->_draw->spriteOperation(DRAW_LOADSPRITE);
|
|
}
|
|
}
|
|
|
|
delete resource;
|
|
return sceneryIndex + 100;
|
|
}
|
|
|
|
void Scenery::freeAnim(int16 index) {
|
|
int16 spr;
|
|
|
|
if (index == -1)
|
|
_vm->_game->_script->evalExpr(&index);
|
|
|
|
if (_animPictCount[index] == 0)
|
|
return;
|
|
|
|
for (int i = 0; i < _animPictCount[index]; i++) {
|
|
delete[] _animations[index].pieces[i];
|
|
|
|
spr = _animPictToSprite[index * 7 + i];
|
|
_spriteRefs[spr]--;
|
|
if (_spriteRefs[spr] == 0) {
|
|
_vm->_draw->freeSprite(spr);
|
|
_spriteResId[spr] = -1;
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < _animations[index].layersCount; i++)
|
|
delete[] _animations[index].layers[i].frames;
|
|
|
|
delete[] _animations[index].layers;
|
|
delete[] _animations[index].pieces;
|
|
delete[] _animations[index].piecesCount;
|
|
|
|
_animPictCount[index] = 0;
|
|
}
|
|
|
|
// 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::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags,
|
|
int16 drawDeltaX, int16 drawDeltaY, char doDraw) {
|
|
AnimLayer *layerPtr;
|
|
PieceDesc **pictPtr;
|
|
AnimFramePiece *framePtr;
|
|
|
|
uint16 pieceIndex;
|
|
uint16 pictIndex;
|
|
|
|
int16 left;
|
|
int16 right;
|
|
int16 top;
|
|
int16 bottom;
|
|
|
|
byte highX;
|
|
byte highY;
|
|
|
|
int16 i;
|
|
int16 transp;
|
|
|
|
int16 destX;
|
|
int16 destY;
|
|
|
|
if ((_vm->getGameType() == kGameTypeWoodruff) && (animation < 0)) {
|
|
// Object video
|
|
|
|
if (flags & 1) { // Do capture
|
|
updateAnim(layer, frame, animation, 0, drawDeltaX, drawDeltaY, 0);
|
|
|
|
if (_toRedrawLeft == -12345)
|
|
return;
|
|
|
|
_vm->_game->capturePush(_toRedrawLeft, _toRedrawTop,
|
|
_toRedrawRight - _toRedrawLeft + 1,
|
|
_toRedrawBottom - _toRedrawTop + 1);
|
|
|
|
*_pCaptureCounter = *_pCaptureCounter + 1;
|
|
}
|
|
|
|
Mult::Mult_Object &obj = _vm->_mult->_objects[-animation - 1];
|
|
|
|
if ((obj.videoSlot == 0) || !_vm->_vidPlayer->slotIsOpen(obj.videoSlot - 1)) {
|
|
_toRedrawLeft = -12345;
|
|
return;
|
|
}
|
|
|
|
if (frame >= _vm->_vidPlayer->getFrameCount(obj.videoSlot - 1))
|
|
frame = _vm->_vidPlayer->getFrameCount(obj.videoSlot - 1) - 1;
|
|
|
|
// Seek to frame
|
|
if (_vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1) < 256) {
|
|
while (_vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1) <= frame)
|
|
_vm->_vidPlayer->slotPlay(obj.videoSlot - 1);
|
|
} else {
|
|
int16 curFrame = _vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1);
|
|
uint8 frameWrap = curFrame / 256;
|
|
frame = (frame + 1) % 256;
|
|
|
|
while (_vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1) < (frameWrap * 256 + frame))
|
|
_vm->_vidPlayer->slotPlay(obj.videoSlot - 1);
|
|
}
|
|
|
|
/*
|
|
// Subtitle
|
|
Graphics::CoktelVideo::State state = _vm->_vidPlayer->getState(obj.videoSlot - 1);
|
|
if (state.flags & Graphics::CoktelVideo::kStateSpeech)
|
|
_vm->_draw->printTotText(state.speechId);
|
|
*/
|
|
|
|
destX = 0;
|
|
destY = 0;
|
|
left = *(obj.pPosX);
|
|
top = *(obj.pPosY);
|
|
right = left + _vm->_vidPlayer->getWidth(obj.videoSlot - 1) - 1;
|
|
bottom = top + _vm->_vidPlayer->getHeight(obj.videoSlot - 1) - 1;
|
|
|
|
if (flags & 2) {
|
|
if (left < _vm->_mult->_animLeft) {
|
|
destX += _vm->_mult->_animLeft - left;
|
|
left = _vm->_mult->_animLeft;
|
|
}
|
|
|
|
if ((_vm->_mult->_animLeft + _vm->_mult->_animWidth) <= right)
|
|
right = _vm->_mult->_animLeft + _vm->_mult->_animWidth - 1;
|
|
|
|
if (top < _vm->_mult->_animTop) {
|
|
destY += _vm->_mult->_animTop - top;
|
|
top = _vm->_mult->_animTop;
|
|
}
|
|
|
|
if ((_vm->_mult->_animTop + _vm->_mult->_animHeight) <= bottom)
|
|
bottom = _vm->_mult->_animTop + _vm->_mult->_animHeight - 1;
|
|
|
|
} else if (flags & 4) {
|
|
if (left < _toRedrawLeft) {
|
|
destX += _toRedrawLeft - left;
|
|
left = _toRedrawLeft;
|
|
}
|
|
|
|
if (right > _toRedrawRight)
|
|
right = _toRedrawRight;
|
|
|
|
if (top < _toRedrawTop) {
|
|
destY += _toRedrawTop - top;
|
|
top = _toRedrawTop;
|
|
}
|
|
|
|
if (bottom > _toRedrawBottom)
|
|
bottom = _toRedrawBottom;
|
|
|
|
} else {
|
|
_toRedrawTop = top;
|
|
_toRedrawLeft = left;
|
|
_toRedrawRight = right;
|
|
_toRedrawBottom = bottom;
|
|
}
|
|
|
|
if (doDraw) {
|
|
if ((left > right) || (top > bottom))
|
|
return;
|
|
|
|
if (left < _vm->_mult->_animLeft) {
|
|
destX += _vm->_mult->_animLeft - left;
|
|
left = _vm->_mult->_animLeft;
|
|
}
|
|
|
|
if ((_vm->_mult->_animLeft + _vm->_mult->_animWidth) <= right)
|
|
right = _vm->_mult->_animLeft + _vm->_mult->_animWidth - 1;
|
|
|
|
if (top < _vm->_mult->_animTop) {
|
|
destY += _vm->_mult->_animTop - top;
|
|
top = _vm->_mult->_animTop;
|
|
}
|
|
|
|
if ((_vm->_mult->_animTop + _vm->_mult->_animHeight) <= bottom)
|
|
bottom = _vm->_mult->_animTop + _vm->_mult->_animHeight - 1;
|
|
|
|
_vm->_draw->_spriteLeft = destX;
|
|
_vm->_draw->_spriteTop = destY;
|
|
_vm->_draw->_spriteRight = right - left + 1;
|
|
_vm->_draw->_spriteBottom = bottom - top + 1;
|
|
_vm->_draw->_destSpriteX = left;
|
|
_vm->_draw->_destSpriteY = top;
|
|
_vm->_draw->_transparency = layer;
|
|
if (layer & 0x80)
|
|
_vm->_draw->_spriteLeft = _vm->_vidPlayer->getWidth(obj.videoSlot - 1) -
|
|
(destX + _vm->_draw->_spriteRight);
|
|
|
|
_vm->_vidPlayer->slotCopyFrame(obj.videoSlot - 1, _vm->_draw->_backSurface->getVidMem(),
|
|
_vm->_draw->_spriteLeft, _vm->_draw->_spriteTop,
|
|
_vm->_draw->_spriteRight, _vm->_draw->_spriteBottom,
|
|
_vm->_draw->_destSpriteX, _vm->_draw->_destSpriteY,
|
|
_vm->_draw->_backSurface->getWidth(),
|
|
(_vm->_draw->_transparency != 0) ? 0 : -1);
|
|
|
|
_vm->_draw->invalidateRect(_vm->_draw->_destSpriteX, _vm->_draw->_destSpriteY,
|
|
_vm->_draw->_destSpriteX + _vm->_draw->_spriteRight - 1,
|
|
_vm->_draw->_destSpriteY + _vm->_draw->_spriteBottom - 1);
|
|
|
|
}
|
|
|
|
if (!(flags & 4)) {
|
|
_animLeft = _toRedrawLeft = left;
|
|
_animTop = _toRedrawTop = top;
|
|
_animRight = _toRedrawRight = right;
|
|
_animBottom = _toRedrawBottom = bottom;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if ((animation < 0) || (animation >= 10))
|
|
return;
|
|
if ((_animPictCount[animation] == 0) || (layer < 0))
|
|
return;
|
|
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)
|
|
return;
|
|
|
|
_vm->_game->capturePush(_toRedrawLeft, _toRedrawTop,
|
|
_toRedrawRight - _toRedrawLeft + 1,
|
|
_toRedrawBottom - _toRedrawTop + 1);
|
|
|
|
*_pCaptureCounter = *_pCaptureCounter + 1;
|
|
}
|
|
|
|
pictPtr = _animations[animation].pieces;
|
|
framePtr = layerPtr->frames;
|
|
|
|
for (i = 0; i < frame; i++, framePtr++)
|
|
while (framePtr->notFinal == 1)
|
|
framePtr++;
|
|
|
|
if (flags & 4) {
|
|
_toRedrawLeft = MAX(_toRedrawLeft, _vm->_mult->_animLeft);
|
|
_toRedrawTop = MAX(_toRedrawTop, _vm->_mult->_animTop);
|
|
_toRedrawRight = MIN(_toRedrawRight,
|
|
(int16)(_vm->_mult->_animLeft + _vm->_mult->_animWidth - 1));
|
|
_toRedrawBottom = MIN(_toRedrawBottom,
|
|
(int16)(_vm->_mult->_animTop + _vm->_mult->_animHeight - 1));
|
|
} else
|
|
_toRedrawLeft = -12345;
|
|
|
|
transp = layerPtr->transp ? 3 : 0;
|
|
|
|
framePtr--;
|
|
do {
|
|
framePtr++;
|
|
|
|
pieceIndex = framePtr->pieceIndex;
|
|
pictIndex = framePtr->pictIndex;
|
|
|
|
destX = framePtr->destX;
|
|
destY = framePtr->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;
|
|
|
|
if (pictIndex >= _animPictCount[animation])
|
|
continue;
|
|
|
|
if (!pictPtr[pictIndex])
|
|
continue;
|
|
|
|
if (pieceIndex >= _animations[animation].piecesCount[pictIndex])
|
|
continue;
|
|
|
|
left = pictPtr[pictIndex][pieceIndex].left;
|
|
right = pictPtr[pictIndex][pieceIndex].right;
|
|
top = pictPtr[pictIndex][pieceIndex].top;
|
|
bottom = pictPtr[pictIndex][pieceIndex].bottom;
|
|
|
|
if (flags & 2) {
|
|
if (destX < _vm->_mult->_animLeft) {
|
|
left += _vm->_mult->_animLeft - destX;
|
|
destX = _vm->_mult->_animLeft;
|
|
}
|
|
|
|
if ((left <= right) && ((destX + right - left) >=
|
|
(_vm->_mult->_animLeft + _vm->_mult->_animWidth)))
|
|
right -= (destX + right - left) -
|
|
(_vm->_mult->_animLeft + _vm->_mult->_animWidth) + 1;
|
|
|
|
if (destY < _vm->_mult->_animTop) {
|
|
top += _vm->_mult->_animTop - destY;
|
|
destY = _vm->_mult->_animTop;
|
|
}
|
|
|
|
if ((top <= bottom) && ((destY + bottom - top) >=
|
|
(_vm->_mult->_animTop + _vm->_mult->_animHeight)))
|
|
bottom -= (destY + bottom - top) -
|
|
(_vm->_mult->_animTop + _vm->_mult->_animHeight) + 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)) {
|
|
if (_toRedrawLeft == -12345) {
|
|
_toRedrawLeft = destX;
|
|
_animLeft = destX;
|
|
_toRedrawTop = destY;
|
|
_animTop = destY;
|
|
_toRedrawRight = destX + right - left;
|
|
_animRight = destX + right - left;
|
|
_toRedrawBottom = destY + bottom - top;
|
|
_animBottom = 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 (framePtr->notFinal == 1);
|
|
}
|
|
|
|
void Scenery::writeAnimLayerInfo(uint16 index, uint16 layer,
|
|
int16 varDX, int16 varDY, int16 varUnk0, int16 varFrames) {
|
|
|
|
assert(index < 10);
|
|
assert(layer < _animations[index].layersCount);
|
|
|
|
AnimLayer &animLayer = _animations[index].layers[layer];
|
|
WRITE_VAR_OFFSET(varDX, animLayer.animDeltaX);
|
|
WRITE_VAR_OFFSET(varDY, animLayer.animDeltaY);
|
|
WRITE_VAR_OFFSET(varUnk0, animLayer.unknown0);
|
|
WRITE_VAR_OFFSET(varFrames, animLayer.framesCount);
|
|
}
|
|
|
|
int16 Scenery::getStaticLayersCount(uint16 index) {
|
|
assert(index < 10);
|
|
|
|
return _statics[index].layersCount;
|
|
}
|
|
|
|
int16 Scenery::getAnimLayersCount(uint16 index) {
|
|
assert(index < 10);
|
|
|
|
return _animations[index].layersCount;
|
|
}
|
|
|
|
Scenery::StaticLayer *Scenery::getStaticLayer(uint16 index, uint16 layer) {
|
|
assert(index < 10);
|
|
assert(layer < _statics[index].layersCount);
|
|
|
|
return &_statics[index].layers[layer];
|
|
}
|
|
|
|
Scenery::AnimLayer *Scenery::getAnimLayer(uint16 index, uint16 layer) {
|
|
assert(index < 10);
|
|
assert(layer < _animations[index].layersCount);
|
|
|
|
return &_animations[index].layers[layer];
|
|
}
|
|
|
|
void Scenery::loadPieces(int16 pictDescId, PieceDesc *&pieceDesc, uint32 &piecesCount) {
|
|
Resource *resource = _vm->_game->_resources->getResource(pictDescId);
|
|
if (!resource) {
|
|
warning("Scenery::loadPieces(): Can't load %d", pictDescId);
|
|
return;
|
|
}
|
|
|
|
piecesCount = resource->getSize() / 8;
|
|
pieceDesc = new PieceDesc[piecesCount];
|
|
|
|
for (uint32 i = 0; i < piecesCount; i++) {
|
|
pieceDesc[i].left = resource->stream()->readSint16LE();
|
|
pieceDesc[i].right = resource->stream()->readSint16LE();
|
|
pieceDesc[i].top = resource->stream()->readSint16LE();
|
|
pieceDesc[i].bottom = resource->stream()->readSint16LE();
|
|
}
|
|
|
|
delete resource;
|
|
}
|
|
|
|
} // End of namespace Gob
|