2014-03-12 16:55:42 +01:00
|
|
|
/* 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 "illusions/illusions.h"
|
|
|
|
#include "illusions/actorresource.h"
|
2014-03-18 11:41:14 +01:00
|
|
|
#include "illusions/dictionary.h"
|
2014-03-12 16:55:42 +01:00
|
|
|
|
|
|
|
namespace Illusions {
|
|
|
|
|
|
|
|
// ActorResourceLoader
|
|
|
|
|
|
|
|
void ActorResourceLoader::load(Resource *resource) {
|
|
|
|
debug("ActorResourceLoader::load() Loading actor %08X from %s...", resource->_resId, resource->_filename.c_str());
|
|
|
|
|
|
|
|
ActorResource *actorResource = new ActorResource();
|
2014-04-08 19:43:17 +02:00
|
|
|
actorResource->load(resource);
|
2014-03-24 10:15:04 +01:00
|
|
|
resource->_refId = actorResource;
|
2014-03-12 16:55:42 +01:00
|
|
|
|
|
|
|
ActorItem *actorItem = _vm->_actorItems->allocActorItem();
|
|
|
|
actorItem->_tag = resource->_tag;
|
|
|
|
actorItem->_pauseCtr = 0;
|
|
|
|
actorItem->_actRes = actorResource;
|
|
|
|
|
|
|
|
for (uint i = 0; i < actorResource->_actorTypes.size(); ++i) {
|
|
|
|
ActorType *actorType = &actorResource->_actorTypes[i];
|
2014-03-18 11:41:14 +01:00
|
|
|
ActorType *actorType2 = _vm->_dict->findActorType(actorType->_actorTypeId);
|
2014-03-12 16:55:42 +01:00
|
|
|
if (actorType2) {
|
|
|
|
actorType->_surfInfo._dimensions._width = MAX(actorType->_surfInfo._dimensions._width,
|
|
|
|
actorType2->_surfInfo._dimensions._width);
|
|
|
|
actorType->_surfInfo._dimensions._height = MAX(actorType->_surfInfo._dimensions._height,
|
|
|
|
actorType2->_surfInfo._dimensions._height);
|
|
|
|
if (actorType->_color.r == 255 && actorType->_color.g == 255 && actorType->_color.b == 255)
|
|
|
|
actorType->_color = actorType2->_color;
|
|
|
|
if (actorType->_value1E == 0)
|
|
|
|
actorType->_value1E = actorType2->_value1E;
|
|
|
|
}
|
2014-03-18 11:41:14 +01:00
|
|
|
_vm->_dict->addActorType(actorType->_actorTypeId, actorType);
|
2014-03-12 16:55:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
for (uint i = 0; i < actorResource->_sequences.size(); ++i) {
|
|
|
|
Sequence *sequence = &actorResource->_sequences[i];
|
2014-03-18 11:41:14 +01:00
|
|
|
_vm->_dict->addSequence(sequence->_sequenceId, sequence);
|
2014-03-12 16:55:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void ActorResourceLoader::unload(Resource *resource) {
|
2014-03-24 10:15:04 +01:00
|
|
|
debug("ActorResourceLoader::unload() Unloading actor %08X...", resource->_resId);
|
|
|
|
// TODO Move to ActorItems
|
|
|
|
ActorItem *actorItem = _vm->_actorItems->findActorByResource((ActorResource*)resource->_refId);
|
|
|
|
if (actorItem->_pauseCtr <= 0) {
|
|
|
|
for (uint i = 0; i < actorItem->_actRes->_actorTypes.size(); ++i)
|
|
|
|
_vm->_dict->removeActorType(actorItem->_actRes->_actorTypes[i]._actorTypeId);
|
|
|
|
for (uint i = 0; i < actorItem->_actRes->_sequences.size(); ++i)
|
|
|
|
_vm->_dict->removeSequence(actorItem->_actRes->_sequences[i]._sequenceId);
|
|
|
|
}
|
|
|
|
_vm->_actorItems->freeActorItem(actorItem);
|
|
|
|
delete actorItem->_actRes;
|
2014-03-12 16:55:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void ActorResourceLoader::buildFilename(Resource *resource) {
|
|
|
|
resource->_filename = Common::String::format("%08X.act", resource->_resId);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ActorResourceLoader::isFlag(int flag) {
|
|
|
|
return
|
|
|
|
flag == kRlfLoadFile;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Frame::load(byte *dataStart, Common::SeekableReadStream &stream) {
|
2014-03-18 14:53:17 +01:00
|
|
|
_flags = stream.readUint16LE();
|
|
|
|
stream.skip(2); // Skip padding
|
2014-03-18 16:00:51 +01:00
|
|
|
uint32 pointsConfigOffs = stream.readUint32LE();
|
2014-03-15 21:57:51 +01:00
|
|
|
_surfInfo.load(stream);
|
2014-03-12 16:55:42 +01:00
|
|
|
uint32 compressedPixelsOffs = stream.readUint32LE();
|
|
|
|
_compressedPixels = dataStart + compressedPixelsOffs;
|
2014-03-18 16:00:51 +01:00
|
|
|
_pointsConfig = dataStart + pointsConfigOffs;
|
2014-03-12 16:55:42 +01:00
|
|
|
|
2014-03-18 14:53:17 +01:00
|
|
|
debug(5, "Frame::load() compressedPixelsOffs: %08X",
|
2014-03-15 21:57:51 +01:00
|
|
|
compressedPixelsOffs);
|
2014-03-12 16:55:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Sequence::load(byte *dataStart, Common::SeekableReadStream &stream) {
|
|
|
|
_sequenceId = stream.readUint32LE();
|
|
|
|
_unk4 = stream.readUint32LE();
|
|
|
|
uint32 sequenceCodeOffs = stream.readUint32LE();
|
|
|
|
_sequenceCode = dataStart + sequenceCodeOffs;
|
|
|
|
|
2014-03-18 14:53:17 +01:00
|
|
|
debug(5, "Sequence::load() _sequenceId: %08X; _unk4: %d; sequenceCodeOffs: %08X",
|
2014-03-12 16:55:42 +01:00
|
|
|
_sequenceId, _unk4, sequenceCodeOffs);
|
2014-03-19 13:59:13 +01:00
|
|
|
|
2014-03-12 16:55:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void ActorType::load(byte *dataStart, Common::SeekableReadStream &stream) {
|
|
|
|
_actorTypeId = stream.readUint32LE();
|
|
|
|
_surfInfo.load(stream);
|
2014-03-18 16:00:51 +01:00
|
|
|
uint32 pointsConfigOffs = stream.readUint32LE();
|
2014-03-27 18:55:41 +01:00
|
|
|
uint namedPointsCount = stream.readUint16LE();
|
2014-03-12 16:55:42 +01:00
|
|
|
stream.skip(2); // Skip padding
|
2014-03-27 18:55:41 +01:00
|
|
|
uint32 namedPointsOffs = stream.readUint32LE();
|
2014-03-12 16:55:42 +01:00
|
|
|
_color.r = stream.readByte();
|
|
|
|
_color.g = stream.readByte();
|
|
|
|
_color.b = stream.readByte();
|
|
|
|
stream.readByte(); // Skip padding
|
|
|
|
_scale = stream.readByte();
|
|
|
|
_priority = stream.readByte();
|
|
|
|
_value1E = stream.readUint16LE();
|
2014-03-18 10:59:28 +01:00
|
|
|
_pathWalkPointsIndex = stream.readUint16LE();
|
|
|
|
_scaleLayerIndex = stream.readUint16LE();
|
|
|
|
_pathWalkRectIndex = stream.readUint16LE();
|
|
|
|
_priorityLayerIndex = stream.readUint16LE();
|
|
|
|
_regionLayerIndex = stream.readUint16LE();
|
2014-03-12 16:55:42 +01:00
|
|
|
_flags = stream.readUint16LE();
|
2014-03-18 16:00:51 +01:00
|
|
|
_pointsConfig = dataStart + pointsConfigOffs;
|
2014-03-27 18:55:41 +01:00
|
|
|
stream.seek(namedPointsOffs);
|
|
|
|
_namedPoints.load(namedPointsCount, stream);
|
2014-03-18 10:59:28 +01:00
|
|
|
|
2014-03-18 14:53:17 +01:00
|
|
|
debug(5, "ActorType::load() _actorTypeId: %08X; _color(%d,%d,%d); _scale: %d; _priority: %d; _value1E: %d",
|
2014-03-12 16:55:42 +01:00
|
|
|
_actorTypeId, _color.r, _color.g, _color.b, _scale, _priority, _value1E);
|
2014-03-18 14:53:17 +01:00
|
|
|
debug(5, "ActorType::load() _pathWalkPointsIndex: %d; _scaleLayerIndex: %d; _pathWalkRectIndex: %d",
|
2014-03-18 10:59:28 +01:00
|
|
|
_pathWalkPointsIndex, _scaleLayerIndex, _pathWalkRectIndex);
|
2014-03-18 14:53:17 +01:00
|
|
|
debug(5, "ActorType::load() _priorityLayerIndex: %d; _regionLayerIndex: %d; _flags: %04X",
|
2014-03-18 10:59:28 +01:00
|
|
|
_priorityLayerIndex, _regionLayerIndex,_flags);
|
2014-03-30 09:31:53 +02:00
|
|
|
|
2014-03-12 16:55:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// ActorResource
|
|
|
|
|
|
|
|
ActorResource::ActorResource() {
|
|
|
|
}
|
|
|
|
|
|
|
|
ActorResource::~ActorResource() {
|
|
|
|
}
|
|
|
|
|
2014-04-08 19:43:17 +02:00
|
|
|
void ActorResource::load(Resource *resource) {
|
|
|
|
byte *data = resource->_data;
|
|
|
|
uint32 dataSize = resource->_dataSize;
|
|
|
|
|
2014-03-12 16:55:42 +01:00
|
|
|
Common::MemoryReadStream stream(data, dataSize, DisposeAfterUse::NO);
|
|
|
|
|
|
|
|
_totalSize = stream.readUint32LE();
|
|
|
|
|
|
|
|
// Load actor types
|
|
|
|
stream.seek(0x06);
|
|
|
|
uint actorTypesCount = stream.readUint16LE();
|
|
|
|
stream.seek(0x10);
|
|
|
|
uint32 actorTypesOffs = stream.readUint32LE();
|
|
|
|
_actorTypes.reserve(actorTypesCount);
|
|
|
|
for (uint i = 0; i < actorTypesCount; ++i) {
|
|
|
|
ActorType actorType;
|
2014-03-27 18:55:41 +01:00
|
|
|
stream.seek(actorTypesOffs + i * 0x2C);
|
2014-03-12 16:55:42 +01:00
|
|
|
actorType.load(data, stream);
|
|
|
|
_actorTypes.push_back(actorType);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Load sequences
|
|
|
|
stream.seek(0x08);
|
|
|
|
uint sequencesCount = stream.readUint16LE();
|
|
|
|
stream.seek(0x14);
|
|
|
|
uint32 sequencesOffs = stream.readUint32LE();
|
|
|
|
stream.seek(sequencesOffs);
|
2014-03-19 13:59:13 +01:00
|
|
|
_sequences.reserve(sequencesCount);
|
2014-03-12 16:55:42 +01:00
|
|
|
for (uint i = 0; i < sequencesCount; ++i) {
|
|
|
|
Sequence sequence;
|
|
|
|
sequence.load(data, stream);
|
|
|
|
_sequences.push_back(sequence);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Load frames
|
|
|
|
stream.seek(0x0A);
|
|
|
|
uint framesCount = stream.readUint16LE();
|
|
|
|
stream.seek(0x18);
|
|
|
|
uint32 framesOffs = stream.readUint32LE();
|
|
|
|
stream.seek(framesOffs);
|
2014-03-19 13:59:13 +01:00
|
|
|
_frames.reserve(framesCount);
|
2014-03-12 16:55:42 +01:00
|
|
|
for (uint i = 0; i < framesCount; ++i) {
|
|
|
|
Frame frame;
|
|
|
|
frame.load(data, stream);
|
|
|
|
_frames.push_back(frame);
|
|
|
|
}
|
2014-03-27 18:55:41 +01:00
|
|
|
|
|
|
|
// Load named points
|
2014-04-08 19:43:17 +02:00
|
|
|
if (resource->_gameId == kGameIdBBDOU) {
|
|
|
|
// The count isn't stored explicitly so calculate it
|
|
|
|
uint namedPointsCount = (actorTypesOffs - 0x20) / 8;
|
|
|
|
stream.seek(0x20);
|
|
|
|
_namedPoints.load(namedPointsCount, stream);
|
|
|
|
}
|
|
|
|
|
|
|
|
debug("ActorResource(%08X) framesCount: %d", resource->_resId, framesCount);
|
2014-03-12 16:55:42 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2014-03-18 10:59:28 +01:00
|
|
|
bool ActorResource::containsSequence(Sequence *sequence) {
|
|
|
|
for (uint i = 0; i < _sequences.size(); ++i)
|
|
|
|
if (sequence == &_sequences[i])
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-03-27 18:55:41 +01:00
|
|
|
bool ActorResource::findNamedPoint(uint32 namedPointId, Common::Point &pt) {
|
|
|
|
return _namedPoints.findNamedPoint(namedPointId, pt);
|
|
|
|
}
|
|
|
|
|
2014-03-12 16:55:42 +01:00
|
|
|
// ActorItem
|
|
|
|
|
2014-03-18 11:41:14 +01:00
|
|
|
ActorItem::ActorItem(IllusionsEngine *vm)
|
|
|
|
: _vm(vm) {
|
2014-03-12 16:55:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
ActorItem::~ActorItem() {
|
|
|
|
}
|
|
|
|
|
|
|
|
void ActorItem::pause() {
|
|
|
|
++_pauseCtr;
|
|
|
|
if (_pauseCtr == 1) {
|
|
|
|
for (uint i = 0; i < _actRes->_actorTypes.size(); ++i)
|
2014-03-18 11:41:14 +01:00
|
|
|
_vm->_dict->removeActorType(_actRes->_actorTypes[i]._actorTypeId);
|
|
|
|
for (uint i = 0; i < _actRes->_sequences.size(); ++i)
|
|
|
|
_vm->_dict->removeSequence(_actRes->_sequences[i]._sequenceId);
|
2014-03-12 16:55:42 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ActorItem::unpause() {
|
|
|
|
--_pauseCtr;
|
|
|
|
if (_pauseCtr == 0) {
|
|
|
|
for (uint i = 0; i < _actRes->_actorTypes.size(); ++i) {
|
|
|
|
ActorType *actorType = &_actRes->_actorTypes[i];
|
2014-03-18 11:41:14 +01:00
|
|
|
_vm->_dict->addActorType(actorType->_actorTypeId, actorType);
|
2014-03-12 16:55:42 +01:00
|
|
|
}
|
|
|
|
for (uint i = 0; i < _actRes->_sequences.size(); ++i) {
|
|
|
|
Sequence *sequence = &_actRes->_sequences[i];
|
2014-03-18 11:41:14 +01:00
|
|
|
_vm->_dict->addSequence(sequence->_sequenceId, sequence);
|
2014-03-12 16:55:42 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ActorItems
|
|
|
|
|
|
|
|
ActorItems::ActorItems(IllusionsEngine *vm)
|
|
|
|
: _vm(vm) {
|
|
|
|
}
|
|
|
|
|
|
|
|
ActorItems::~ActorItems() {
|
|
|
|
}
|
|
|
|
|
|
|
|
ActorItem *ActorItems::allocActorItem() {
|
2014-03-18 11:41:14 +01:00
|
|
|
ActorItem *actorItem = new ActorItem(_vm);
|
2014-03-12 16:55:42 +01:00
|
|
|
_items.push_back(actorItem);
|
|
|
|
return actorItem;
|
|
|
|
}
|
|
|
|
|
2014-03-24 10:15:04 +01:00
|
|
|
void ActorItems::freeActorItem(ActorItem *actorItem) {
|
|
|
|
_items.remove(actorItem);
|
|
|
|
delete actorItem;
|
|
|
|
}
|
|
|
|
|
2014-03-12 16:55:42 +01:00
|
|
|
void ActorItems::pauseByTag(uint32 tag) {
|
|
|
|
for (ItemsIterator it = _items.begin(); it != _items.end(); ++it)
|
|
|
|
if ((*it)->_tag == tag)
|
|
|
|
(*it)->pause();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ActorItems::unpauseByTag(uint32 tag) {
|
|
|
|
for (ItemsIterator it = _items.begin(); it != _items.end(); ++it)
|
|
|
|
if ((*it)->_tag == tag)
|
2014-03-24 10:15:04 +01:00
|
|
|
(*it)->unpause();
|
2014-03-12 16:55:42 +01:00
|
|
|
}
|
|
|
|
|
2014-03-18 14:53:17 +01:00
|
|
|
FramesList *ActorItems::findSequenceFrames(Sequence *sequence) {
|
|
|
|
for (ItemsIterator it = _items.begin(); it != _items.end(); ++it) {
|
|
|
|
ActorItem *actorItem = *it;
|
|
|
|
if (actorItem->_pauseCtr <= 0 && actorItem->_actRes->containsSequence(sequence))
|
|
|
|
return &actorItem->_actRes->_frames;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-03-24 10:15:04 +01:00
|
|
|
ActorItem *ActorItems::findActorByResource(ActorResource *actorResource) {
|
|
|
|
for (ItemsIterator it = _items.begin(); it != _items.end(); ++it)
|
|
|
|
if ((*it)->_actRes == actorResource)
|
|
|
|
return (*it);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-03-27 18:55:41 +01:00
|
|
|
bool ActorItems::findNamedPoint(uint32 namedPointId, Common::Point &pt) {
|
|
|
|
for (ItemsIterator it = _items.begin(); it != _items.end(); ++it) {
|
|
|
|
ActorItem *actorItem = *it;
|
|
|
|
if (actorItem->_pauseCtr == 0 && actorItem->_actRes->findNamedPoint(namedPointId, pt))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-03-12 16:55:42 +01:00
|
|
|
} // End of namespace Illusions
|