mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-05 00:36:57 +00:00
74e43312f7
Another regression of the CoktelDecoder rewrite. Thanks to digitall for finding the offending commit. :)
1001 lines
27 KiB
C++
1001 lines
27 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.
|
|
*
|
|
*/
|
|
|
|
#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++) {
|
|
if (_vm->getGameType() == kGameTypeFascination) {
|
|
freeAnim(i);
|
|
freeStatic(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->_draw->_spritesArray[sprIndex]->clear();
|
|
_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 = Draw::kBackSurface;
|
|
_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 = Draw::kBackSurface;
|
|
_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 = Draw::kBackSurface;
|
|
_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->_draw->_spritesArray[sprIndex]->clear();
|
|
_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 ((animation < 0) &&
|
|
((_vm->getGameType() == kGameTypeWoodruff) ||
|
|
(_vm->getGameType() == kGameTypeAdibou2))) {
|
|
// 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 >= (int32)_vm->_vidPlayer->getFrameCount(obj.videoSlot - 1))
|
|
frame = _vm->_vidPlayer->getFrameCount(obj.videoSlot - 1) - 1;
|
|
|
|
if ((int32)_vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1) >= 255) {
|
|
// Allow for object videos with more than 255 frames, although the
|
|
// object frame counter is just a byte.
|
|
|
|
uint32 curFrame = _vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1) + 1;
|
|
uint16 frameWrap = curFrame / 256;
|
|
|
|
frame = ((frame + 1) % 256) + frameWrap * 256;
|
|
}
|
|
|
|
if (frame != (int32)_vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1)) {
|
|
// Seek to frame
|
|
|
|
VideoPlayer::Properties props;
|
|
|
|
props.forceSeek = true;
|
|
props.waitEndFrame = false;
|
|
props.lastFrame = frame;
|
|
|
|
if ((int32)_vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1) < frame)
|
|
props.startFrame = _vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1) + 1;
|
|
else
|
|
props.startFrame = frame;
|
|
|
|
_vm->_vidPlayer->play(obj.videoSlot - 1, props);
|
|
}
|
|
|
|
int32 subtitle = _vm->_vidPlayer->getSubtitleIndex(obj.videoSlot - 1);
|
|
if (subtitle != -1)
|
|
_vm->_draw->printTotText(subtitle);
|
|
|
|
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->copyFrame(obj.videoSlot - 1, *_vm->_draw->_backSurface,
|
|
_vm->_draw->_spriteLeft, _vm->_draw->_spriteTop,
|
|
_vm->_draw->_spriteRight, _vm->_draw->_spriteBottom,
|
|
_vm->_draw->_destSpriteX, _vm->_draw->_destSpriteY,
|
|
(_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 = Draw::kBackSurface;
|
|
|
|
_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);
|
|
|
|
// WORKAROUND - Fascination Hebrew is using scripts from the CD versions, but of course
|
|
// no CD track, so the anim syncing failed, and the anims were suppressed. But they
|
|
// didn't updated the scripts. Skipping the wrong anims is a solution.
|
|
if ((_vm->getGameType() == kGameTypeFascination) && (layer >= _animations[index].layersCount)) {
|
|
WRITE_VAR_OFFSET(varDX, 0);
|
|
WRITE_VAR_OFFSET(varDY, 0);
|
|
WRITE_VAR_OFFSET(varUnk0, 0);
|
|
WRITE_VAR_OFFSET(varFrames, 0);
|
|
} else {
|
|
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
|