scummvm/engines/illusions/resources/actorresource.cpp
2018-07-20 06:43:33 +00:00

316 lines
9.8 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 "illusions/actor.h"
#include "illusions/illusions.h"
#include "illusions/resources/actorresource.h"
#include "illusions/dictionary.h"
namespace Illusions {
// ActorResourceLoader
void ActorResourceLoader::load(Resource *resource) {
resource->_instance = _vm->_actorInstances->createActorInstance(resource);
}
bool ActorResourceLoader::isFlag(int flag) {
return
flag == kRlfLoadFile;
}
// Frame
void Frame::load(byte *dataStart, Common::SeekableReadStream &stream) {
_flags = stream.readUint16LE();
stream.skip(2); // Skip padding
uint32 pointsConfigOffs = stream.readUint32LE();
_surfInfo.load(stream);
uint32 compressedPixelsOffs = stream.readUint32LE();
_compressedPixels = dataStart + compressedPixelsOffs;
_pointsConfig = dataStart + pointsConfigOffs;
debug(5, "Frame::load() compressedPixelsOffs: %08X",
compressedPixelsOffs);
}
// Sequence
void Sequence::load(byte *dataStart, Common::SeekableReadStream &stream) {
_sequenceId = stream.readUint32LE();
_unk4 = stream.readUint32LE();
uint32 sequenceCodeOffs = stream.readUint32LE();
_sequenceCode = dataStart + sequenceCodeOffs;
debug(5, "Sequence::load() _sequenceId: %08X; _unk4: %d; sequenceCodeOffs: %08X",
_sequenceId, _unk4, sequenceCodeOffs);
}
// ActorType
void ActorType::load(byte *dataStart, Common::SeekableReadStream &stream) {
_actorTypeId = stream.readUint32LE();
_surfInfo.load(stream);
uint32 pointsConfigOffs = stream.readUint32LE();
uint namedPointsCount = stream.readUint16LE();
stream.skip(2); // Skip padding
uint32 namedPointsOffs = stream.readUint32LE();
_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();
_pathWalkPointsIndex = stream.readUint16LE();
_scaleLayerIndex = stream.readUint16LE();
_pathWalkRectIndex = stream.readUint16LE();
_priorityLayerIndex = stream.readUint16LE();
_regionLayerIndex = stream.readUint16LE();
_flags = stream.readUint16LE();
_pointsConfig = dataStart + pointsConfigOffs;
stream.seek(namedPointsOffs);
_namedPoints.load(namedPointsCount, stream);
debug(5, "ActorType::load() _actorTypeId: %08X; _color(%d,%d,%d); _scale: %d; _priority: %d; _value1E: %d",
_actorTypeId, _color.r, _color.g, _color.b, _scale, _priority, _value1E);
debug(5, "ActorType::load() _pathWalkPointsIndex: %d; _scaleLayerIndex: %d; _pathWalkRectIndex: %d",
_pathWalkPointsIndex, _scaleLayerIndex, _pathWalkRectIndex);
debug(5, "ActorType::load() _priorityLayerIndex: %d; _regionLayerIndex: %d; _flags: %04X",
_priorityLayerIndex, _regionLayerIndex,_flags);
}
// ActorResource
ActorResource::ActorResource() {
}
ActorResource::~ActorResource() {
}
void ActorResource::load(Resource *resource) {
byte *data = resource->_data;
uint32 dataSize = resource->_dataSize;
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;
stream.seek(actorTypesOffs + i * 0x2C);
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);
_sequences.reserve(sequencesCount);
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);
_frames.reserve(framesCount);
for (uint i = 0; i < framesCount; ++i) {
Frame frame;
frame.load(data, stream);
_frames.push_back(frame);
}
// Load named points
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(1, "ActorResource(%08X) framesCount: %d", resource->_resId, framesCount);
}
bool ActorResource::containsSequence(Sequence *sequence) {
for (uint i = 0; i < _sequences.size(); ++i) {
if (sequence == &_sequences[i])
return true;
}
return false;
}
bool ActorResource::findNamedPoint(uint32 namedPointId, Common::Point &pt) {
return _namedPoints.findNamedPoint(namedPointId, pt);
}
// ActorInstance
ActorInstance::ActorInstance(IllusionsEngine *vm)
: _vm(vm) {
}
void ActorInstance::load(Resource *resource) {
_actorResource = new ActorResource();
_actorResource->load(resource);
_sceneId = resource->_sceneId;
_pauseCtr = 0;
initActorTypes(resource->_gameId);
}
void ActorInstance::unload() {
if (_pauseCtr <= 0)
unregisterResources();
_vm->_actorInstances->removeActorInstance(this);
delete _actorResource;
}
void ActorInstance::pause() {
++_pauseCtr;
if (_pauseCtr == 1)
unregisterResources();
}
void ActorInstance::unpause() {
--_pauseCtr;
if (_pauseCtr == 0)
registerResources();
}
void ActorInstance::initActorTypes(int gameId) {
for (uint i = 0; i < _actorResource->_actorTypes.size(); ++i) {
ActorType *actorType = &_actorResource->_actorTypes[i];
ActorType *actorType2 = _vm->_dict->findActorType(actorType->_actorTypeId);
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;
}
_vm->_dict->addActorType(actorType->_actorTypeId, actorType);
}
for (uint i = 0; i < _actorResource->_sequences.size(); ++i) {
Sequence *sequence = &_actorResource->_sequences[i];
_vm->_dict->addSequence(sequence->_sequenceId, sequence);
if (gameId == kGameIdDuckman && sequence->_sequenceId == 0x60101) {
// TODO check that this is the correct location for this logic.
_vm->_controls->placeActor(0x50023, Common::Point(0,0), sequence->_sequenceId, 0x400d7, 0);
}
}
}
void ActorInstance::registerResources() {
for (uint i = 0; i < _actorResource->_actorTypes.size(); ++i) {
ActorType *actorType = &_actorResource->_actorTypes[i];
_vm->_dict->addActorType(actorType->_actorTypeId, actorType);
}
for (uint i = 0; i < _actorResource->_sequences.size(); ++i) {
Sequence *sequence = &_actorResource->_sequences[i];
_vm->_dict->addSequence(sequence->_sequenceId, sequence);
}
}
void ActorInstance::unregisterResources() {
for (uint i = 0; i < _actorResource->_actorTypes.size(); ++i) {
_vm->_dict->removeActorType(_actorResource->_actorTypes[i]._actorTypeId);
}
for (uint i = 0; i < _actorResource->_sequences.size(); ++i) {
_vm->_dict->removeSequence(_actorResource->_sequences[i]._sequenceId);
}
}
// ActorInstanceList
ActorInstanceList::ActorInstanceList(IllusionsEngine *vm)
: _vm(vm) {
}
ActorInstanceList::~ActorInstanceList() {
}
ActorInstance *ActorInstanceList::createActorInstance(Resource *resource) {
ActorInstance *actorInstance = new ActorInstance(_vm);
actorInstance->load(resource);
_items.push_back(actorInstance);
return actorInstance;
}
void ActorInstanceList::removeActorInstance(ActorInstance *actorInstance) {
_items.remove(actorInstance);
}
void ActorInstanceList::pauseBySceneId(uint32 sceneId) {
for (ItemsIterator it = _items.begin(); it != _items.end(); ++it) {
if ((*it)->_sceneId == sceneId)
(*it)->pause();
}
}
void ActorInstanceList::unpauseBySceneId(uint32 sceneId) {
for (ItemsIterator it = _items.begin(); it != _items.end(); ++it) {
if ((*it)->_sceneId == sceneId)
(*it)->unpause();
}
}
FramesList *ActorInstanceList::findSequenceFrames(Sequence *sequence) {
for (ItemsIterator it = _items.begin(); it != _items.end(); ++it) {
ActorInstance *actorInstance = *it;
if (actorInstance->_pauseCtr <= 0 && actorInstance->_actorResource->containsSequence(sequence))
return &actorInstance->_actorResource->_frames;
}
return 0;
}
ActorInstance *ActorInstanceList::findActorByResource(ActorResource *actorResource) {
for (ItemsIterator it = _items.begin(); it != _items.end(); ++it) {
if ((*it)->_actorResource == actorResource)
return (*it);
}
return 0;
}
bool ActorInstanceList::findNamedPoint(uint32 namedPointId, Common::Point &pt) {
for (ItemsIterator it = _items.begin(); it != _items.end(); ++it) {
ActorInstance *actorInstance = *it;
if (actorInstance->_pauseCtr == 0 && actorInstance->_actorResource->findNamedPoint(namedPointId, pt))
return true;
}
return false;
}
} // End of namespace Illusions