Initial commit

This commit is contained in:
2026-02-02 04:50:13 +01:00
commit 5b11698731
22592 changed files with 7677434 additions and 0 deletions

View File

@@ -0,0 +1,312 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#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 (auto &it : _items) {
if (it->_sceneId == sceneId)
it->pause();
}
}
void ActorInstanceList::unpauseBySceneId(uint32 sceneId) {
for (auto &it : _items) {
if (it->_sceneId == sceneId)
it->unpause();
}
}
FramesList *ActorInstanceList::findSequenceFrames(Sequence *sequence) {
for (auto &actorInstance : _items) {
if (actorInstance->_pauseCtr <= 0 && actorInstance->_actorResource->containsSequence(sequence))
return &actorInstance->_actorResource->_frames;
}
return nullptr;
}
ActorInstance *ActorInstanceList::findActorByResource(ActorResource *actorResource) {
for (auto &it : _items) {
if (it->_actorResource == actorResource)
return (it);
}
return nullptr;
}
bool ActorInstanceList::findNamedPoint(uint32 namedPointId, Common::Point &pt) {
for (auto &actorInstance : _items) {
if (actorInstance->_pauseCtr == 0 && actorInstance->_actorResource->findNamedPoint(namedPointId, pt))
return true;
}
return false;
}
} // End of namespace Illusions

View File

@@ -0,0 +1,132 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef ILLUSIONS_ACTORRESOURCE_H
#define ILLUSIONS_ACTORRESOURCE_H
#include "illusions/graphics.h"
#include "illusions/resourcesystem.h"
#include "graphics/surface.h"
namespace Illusions {
class IllusionsEngine;
class ActorResourceLoader : public BaseResourceLoader {
public:
ActorResourceLoader(IllusionsEngine *vm) : _vm(vm) {}
~ActorResourceLoader() override {}
void load(Resource *resource) override;
bool isFlag(int flag) override;
protected:
IllusionsEngine *_vm;
};
struct Frame {
uint16 _flags;
byte *_pointsConfig;
SurfInfo _surfInfo;
byte *_compressedPixels;
void load(byte *dataStart, Common::SeekableReadStream &stream);
};
struct Sequence {
uint32 _sequenceId;
uint32 _unk4;
byte *_sequenceCode;
void load(byte *dataStart, Common::SeekableReadStream &stream);
};
struct ActorType {
uint32 _actorTypeId;
SurfInfo _surfInfo;
byte *_pointsConfig;
NamedPoints _namedPoints;
RGB _color;
byte _scale;
byte _priority;
int16 _value1E;
uint16 _pathWalkPointsIndex;
uint16 _scaleLayerIndex;
uint16 _pathWalkRectIndex;
uint16 _priorityLayerIndex;
uint16 _regionLayerIndex;
uint16 _flags;
void load(byte *dataStart, Common::SeekableReadStream &stream);
};
class FramesList : public Common::Array<Frame> {
};
class ActorResource {
public:
ActorResource();
~ActorResource();
void load(Resource *resource);
bool containsSequence(Sequence *sequence);
bool findNamedPoint(uint32 namedPointId, Common::Point &pt);
public:
uint32 _totalSize;
Common::Array<ActorType> _actorTypes;
Common::Array<Sequence> _sequences;
FramesList _frames;
NamedPoints _namedPoints;
};
class ActorInstance : public ResourceInstance {
public:
ActorInstance(IllusionsEngine *vm);
void load(Resource *resource) override;
void unload() override;
void pause() override;
void unpause() override;
public:
IllusionsEngine *_vm;
uint32 _sceneId;
int _pauseCtr;
ActorResource *_actorResource;
protected:
void initActorTypes(int gameId);
void registerResources();
void unregisterResources();
};
class ActorInstanceList {
public:
ActorInstanceList(IllusionsEngine *vm);
~ActorInstanceList();
ActorInstance *createActorInstance(Resource *resource);
void removeActorInstance(ActorInstance *actorInstance);
void pauseBySceneId(uint32 sceneId);
void unpauseBySceneId(uint32 sceneId);
FramesList *findSequenceFrames(Sequence *sequence);
ActorInstance *findActorByResource(ActorResource *actorResource);
bool findNamedPoint(uint32 namedPointId, Common::Point &pt);
protected:
typedef Common::List<ActorInstance*> Items;
typedef Items::iterator ItemsIterator;
IllusionsEngine *_vm;
Items _items;
};
} // End of namespace Illusions
#endif // ILLUSIONS_ACTORRESOURCE_H

View File

@@ -0,0 +1,641 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "illusions/illusions.h"
#include "illusions/resources/backgroundresource.h"
#include "illusions/actor.h"
#include "illusions/camera.h"
#include "illusions/dictionary.h"
#include "illusions/resources/actorresource.h"
#include "illusions/screen.h"
#include "illusions/sequenceopcodes.h"
#include "common/str.h"
namespace Illusions {
// BackgroundResourceLoader
void BackgroundResourceLoader::load(Resource *resource) {
resource->_instance = _vm->_backgroundInstances->createBackgroundInstance(resource);
}
bool BackgroundResourceLoader::isFlag(int flag) {
return
flag == kRlfLoadFile;
}
// TileMap
void TileMap::load(byte *dataStart, Common::SeekableReadStream &stream) {
_width = stream.readSint16LE();
_height = stream.readSint16LE();
stream.skip(4); // Unknown
uint32 mapOffs = stream.pos();
_map = dataStart + mapOffs;
debug(0, "TileMap::load() _width: %d; _height: %d",
_width, _height);
}
// BgInfo
void BgInfo::load(byte *dataStart, Common::SeekableReadStream &stream) {
_flags = stream.readUint32LE();
uint16 unknown = stream.readUint16LE(); // TODO Unknown
_priorityBase = stream.readSint16LE();
_surfInfo.load(stream);
loadPoint(stream, _panPoint);
uint32 tileMapOffs = stream.readUint32LE();
uint32 tilePixelsOffs = stream.readUint32LE();
stream.seek(tileMapOffs);
_tileMap.load(dataStart, stream);
_tilePixels = dataStart + tilePixelsOffs;
debug(0, "BgInfo::load() _flags: %08X; unknown: %04X; _priorityBase: %d; tileMapOffs: %08X; tilePixelsOffs: %08X",
_flags, unknown, _priorityBase, tileMapOffs, tilePixelsOffs);
}
// PriorityLayer
void PriorityLayer::load(byte *dataStart, Common::SeekableReadStream &stream) {
_width = stream.readUint16LE();
_height = stream.readUint16LE();
uint32 mapOffs = stream.readUint32LE();
uint32 valuesOffs = stream.readUint32LE();
_map = dataStart + mapOffs;
_mapWidth = READ_LE_UINT16(_map + 0);
_mapHeight = READ_LE_UINT16(_map + 2);
_map += 8;
_values = dataStart + valuesOffs;
debug(0, "PriorityLayer::load() _width: %d; _height: %d; mapOffs: %08X; valuesOffs: %08X; _mapWidth: %d; _mapHeight: %d",
_width, _height, mapOffs, valuesOffs, _mapWidth, _mapHeight);
}
int PriorityLayer::getPriority(Common::Point pos) {
pos.x = CLIP<int16>(pos.x, 0, _width - 1);
pos.y = CLIP<int16>(pos.y, 0, _height - 1);
const int16 tx = pos.x / 32, sx = pos.x % 32;
const int16 ty = pos.y / 8, sy = pos.y % 8;
uint16 mapIndex = READ_LE_UINT16(_map + 2 * (tx + ty * _mapWidth)) - 1;
return _values[mapIndex * 32 * 8 + sx + sy * 32];
}
// ScaleLayer
void ScaleLayer::load(byte *dataStart, Common::SeekableReadStream &stream) {
_height = stream.readUint16LE();
stream.skip(2);
uint32 valuesOffs = stream.readUint32LE();
_values = dataStart + valuesOffs;
debug(0, "ScaleLayer::load() _height: %d; valuesOffs: %08X",
_height, valuesOffs);
}
int ScaleLayer::getScale(Common::Point pos) {
pos.y = CLIP<int16>(pos.y, 0, _height - 1);
return _values[pos.y];
}
// RegionLayer
void RegionLayer::load(byte *dataStart, Common::SeekableReadStream &stream) {
_unk = stream.readUint32LE();
uint32 regionSequenceIdsOffs = stream.readUint32LE();
_width = stream.readUint16LE();
_height = stream.readUint16LE();
uint32 mapOffs = stream.readUint32LE();
uint32 valuesOffs = stream.readUint32LE();
_regionSequenceIds = dataStart + regionSequenceIdsOffs;
_map = dataStart + mapOffs;
_values = dataStart + valuesOffs;
_mapWidth = READ_LE_UINT16(_map + 0);
_mapHeight = READ_LE_UINT16(_map + 2);
_map += 8;
debug(1, "RegionLayer::load() %d; regionSequenceIdsOffs: %08X; _width: %d; _height: %d; mapOffs: %08X; valuesOffs: %08X",
_unk, regionSequenceIdsOffs, _width, _height, mapOffs, valuesOffs);
}
int RegionLayer::getRegionIndex(Common::Point pos) {
pos.x = CLIP<int16>(pos.x, 0, _width - 1);
pos.y = CLIP<int16>(pos.y, 0, _height - 1);
const int16 tx = pos.x / 32, sx = pos.x % 32;
const int16 ty = pos.y / 8, sy = pos.y % 8;
uint16 mapIndex = READ_LE_UINT16(_map + 2 * (tx + ty * _mapWidth)) - 1;
return _values[mapIndex * 32 * 8 + sx + sy * 32];
}
uint32 RegionLayer::getRegionSequenceId(int regionIndex) {
return READ_LE_UINT32(_regionSequenceIds + 4 * regionIndex);
}
// Palette
void Palette::load(byte *dataStart, Common::SeekableReadStream &stream) {
_count = stream.readUint16LE();
_unk = stream.readUint16LE();
uint32 paletteOffs = stream.readUint32LE();
_palette = dataStart + paletteOffs;
}
// BackgroundObject
void BackgroundObject::load(byte *dataStart, Common::SeekableReadStream &stream) {
_objectId = stream.readUint32LE();
_flags = stream.readUint16LE();
_priority = stream.readUint16LE();
uint32 pointsConfigOffs = stream.readUint32LE();
_pointsConfig = dataStart + pointsConfigOffs;
debug(0, "BackgroundObject::load() _objectId: %08X; _flags: %04X; _priority: %d; pointsConfigOffs: %08X",
_objectId, _flags, _priority, pointsConfigOffs);
}
// PathWalkPoints
void PathWalkPoints::load(byte *dataStart, Common::SeekableReadStream &stream) {
_points = new PointArray();
uint count = stream.readUint32LE();
uint32 pointsOffs = stream.readUint32LE();
_points->reserve(count);
stream.seek(pointsOffs);
for (uint i = 0; i < count; ++i) {
Common::Point pt;
loadPoint(stream, pt);
_points->push_back(pt);
}
debug(0, "PathWalkPoints::load() count: %d; pointsOffs: %08X",
count, pointsOffs);
}
// PathWalkRects
void PathWalkRects::load(byte *dataStart, Common::SeekableReadStream &stream) {
_rects = new PathLines();
uint count = stream.readUint32LE();
uint32 rectsOffs = stream.readUint32LE();
_rects->reserve(count);
stream.seek(rectsOffs);
for (uint i = 0; i < count; ++i) {
PathLine rect;
loadPoint(stream, rect.p0);
loadPoint(stream, rect.p1);
_rects->push_back(rect);
}
debug(0, "PathWalkRects::load() count: %d; rectsOffs: %08X",
count, rectsOffs);
}
// BackgroundResource
BackgroundResource::BackgroundResource()
: _bgInfos(nullptr), _scaleLayers(nullptr), _priorityLayers(nullptr), _regionLayers(nullptr),
_regionSequences(nullptr), _backgroundObjects(nullptr), _pathWalkPoints(nullptr),
_pathWalkRects(nullptr), _palettes(nullptr) {
}
BackgroundResource::~BackgroundResource() {
delete[] _bgInfos;
delete[] _scaleLayers;
delete[] _priorityLayers;
delete[] _regionLayers;
delete[] _regionSequences;
delete[] _backgroundObjects;
delete[] _pathWalkPoints;
delete[] _pathWalkRects;
delete[] _palettes;
}
void BackgroundResource::load(byte *data, uint32 dataSize) {
Common::MemoryReadStream stream(data, dataSize, DisposeAfterUse::NO);
stream.seek(8);
_paletteIndex = stream.readUint16LE();
// Load background pixels
stream.seek(0x0A);
_bgInfosCount = stream.readUint16LE();
_bgInfos = new BgInfo[_bgInfosCount];
stream.seek(0x20);
uint32 bgInfosOffs = stream.readUint32LE();
for (uint i = 0; i < _bgInfosCount; ++i) {
stream.seek(bgInfosOffs + i * 0x1C);
_bgInfos[i].load(data, stream);
}
// Load scale layers
stream.seek(0x10);
_scaleLayersCount = stream.readUint16LE();
_scaleLayers = new ScaleLayer[_scaleLayersCount];
stream.seek(0x2C);
uint32 scaleLayersOffs = stream.readUint32LE();
debug(0, "_scaleLayersCount: %d", _scaleLayersCount);
for (uint i = 0; i < _scaleLayersCount; ++i) {
stream.seek(scaleLayersOffs + i * 8);
_scaleLayers[i].load(data, stream);
}
// Load priority layers
stream.seek(0x14);
_priorityLayersCount = stream.readUint16LE();
_priorityLayers = new PriorityLayer[_priorityLayersCount];
stream.seek(0x34);
uint32 priorityLayersOffs = stream.readUint32LE();
debug(1, "_priorityLayersCount: %d", _priorityLayersCount);
for (uint i = 0; i < _priorityLayersCount; ++i) {
stream.seek(priorityLayersOffs + i * 12);
_priorityLayers[i].load(data, stream);
}
// Load region layers
stream.seek(0x16);
_regionLayersCount = stream.readUint16LE();
_regionLayers = new RegionLayer[_regionLayersCount];
stream.seek(0x38);
uint32 regionLayersOffs = stream.readUint32LE();
debug(1, "_regionLayersCount: %d", _regionLayersCount);
for (uint i = 0; i < _regionLayersCount; ++i) {
stream.seek(regionLayersOffs + i * 20);
_regionLayers[i].load(data, stream);
}
// Load region sequences
stream.seek(0x1E);
_regionSequencesCount = stream.readUint16LE();
_regionSequences = new Sequence[_regionSequencesCount];
stream.seek(0x48);
uint32 regionSequencesOffs = stream.readUint32LE();
stream.seek(regionSequencesOffs);
for (uint i = 0; i < _regionSequencesCount; ++i) {
_regionSequences[i].load(data, stream);
}
// Load background objects
stream.seek(0x1C);
_backgroundObjectsCount = stream.readUint16LE();
_backgroundObjects = new BackgroundObject[_backgroundObjectsCount];
stream.seek(0x44);
uint32 backgroundObjectsOffs = stream.readUint32LE();
debug(0, "_backgroundObjectsCount: %d", _backgroundObjectsCount);
for (uint i = 0; i < _backgroundObjectsCount; ++i) {
stream.seek(backgroundObjectsOffs + i * 12);
_backgroundObjects[i].load(data, stream);
}
// Load path walk points
stream.seek(0x0E);
_pathWalkPointsCount = stream.readUint16LE();
debug(1, "_pathWalkPointsCount: %d", _pathWalkPointsCount);
_pathWalkPoints = new PathWalkPoints[_pathWalkPointsCount];
stream.seek(0x28);
uint32 pathWalkPointsOffs = stream.readUint32LE();
for (uint i = 0; i < _pathWalkPointsCount; ++i) {
stream.seek(pathWalkPointsOffs + i * 8);
_pathWalkPoints[i].load(data, stream);
}
// Load path walk rects
stream.seek(0x12);
_pathWalkRectsCount = stream.readUint16LE();
debug(1, "_pathWalkRectsCount: %d", _pathWalkRectsCount);
_pathWalkRects = new PathWalkRects[_pathWalkRectsCount];
stream.seek(0x30);
uint32 pathWalkRectsOffs = stream.readUint32LE();
for (uint i = 0; i < _pathWalkRectsCount; ++i) {
stream.seek(pathWalkRectsOffs + i * 8);
_pathWalkRects[i].load(data, stream);
}
// Load named points
stream.seek(0xC);
uint namedPointsCount = stream.readUint16LE();
stream.seek(0x24);
uint32 namedPointsOffs = stream.readUint32LE();
stream.seek(namedPointsOffs);
_namedPoints.load(namedPointsCount, stream);
// Load palettes
stream.seek(0x18);
_palettesCount = stream.readUint16LE();
_palettes = new Palette[_palettesCount];
stream.seek(0x3C);
uint32 palettesOffs = stream.readUint32LE();
debug(0, "_palettesCount: %d", _palettesCount);
for (uint i = 0; i < _palettesCount; ++i) {
stream.seek(palettesOffs + i * 8);
_palettes[i].load(data, stream);
}
}
int BackgroundResource::findMasterBgIndex() {
int index = 1;
while (!(_bgInfos[index - 1]._flags & 1)) { // TODO check if this is correct
++index;
}
return index;
}
PriorityLayer *BackgroundResource::getPriorityLayer(uint index) {
return &_priorityLayers[index];
}
ScaleLayer *BackgroundResource::getScaleLayer(uint index) {
return &_scaleLayers[index];
}
RegionLayer *BackgroundResource::getRegionLayer(uint index) {
return &_regionLayers[index];
}
PathWalkPoints *BackgroundResource::getPathWalkPoints(uint index) {
return &_pathWalkPoints[index];
}
PathWalkRects *BackgroundResource::getPathWalkRects(uint index) {
return &_pathWalkRects[index];
}
Palette *BackgroundResource::getPalette(uint index) {
return &_palettes[index];
}
bool BackgroundResource::findNamedPoint(uint32 namedPointId, Common::Point &pt) {
return _namedPoints.findNamedPoint(namedPointId, pt);
}
// BackgroundInstance
BackgroundInstance::BackgroundInstance(IllusionsEngine *vm)
: _vm(vm), _sceneId(0), _pauseCtr(0), _bgRes(nullptr), _savedPalette(nullptr) {
}
BackgroundInstance::~BackgroundInstance() {
delete[] _savedPalette;
}
void BackgroundInstance::load(Resource *resource) {
debug(1, "BackgroundResourceLoader::load() Loading background %08X from %s...", resource->_resId, resource->_filename.c_str());
BackgroundResource *backgroundResource = new BackgroundResource();
backgroundResource->load(resource->_data, resource->_dataSize);
_bgRes = backgroundResource;
_sceneId = resource->_sceneId;
initSurface();
// Insert background objects
for (uint i = 0; i < backgroundResource->_backgroundObjectsCount; ++i) {
_vm->_controls->placeBackgroundObject(&backgroundResource->_backgroundObjects[i]);
}
registerResources();
_vm->clearFader();
int index = _bgRes->findMasterBgIndex();
_vm->_camera->set(_bgRes->_bgInfos[index - 1]._panPoint, _bgRes->_bgInfos[index - 1]._surfInfo._dimensions);
if (_bgRes->_palettesCount > 0) {
Palette *palette = _bgRes->getPalette(_bgRes->_paletteIndex - 1);
_vm->_screenPalette->setPalette(palette->_palette, 1, palette->_count);
}
}
void BackgroundInstance::unload() {
debug(1, "BackgroundInstance::unload()");
freeSurface();
unregisterResources();
delete _bgRes;
_vm->_backgroundInstances->removeBackgroundInstance(this);
_vm->setDefaultTextCoords();
}
void BackgroundInstance::pause() {
++_pauseCtr;
if (_pauseCtr <= 1) {
unregisterResources();
_vm->setDefaultTextCoords();
_vm->_camera->getActiveState(_savedCameraState);
_savedPalette = new byte[1024];
_vm->_screenPalette->getPalette(_savedPalette);
freeSurface();
}
}
void BackgroundInstance::unpause() {
--_pauseCtr;
if (_pauseCtr <= 0) {
registerResources();
initSurface();
_vm->_screenPalette->setPalette(_savedPalette, 1, 256);
delete[] _savedPalette;
_savedPalette = nullptr;
_vm->clearFader();
_vm->_camera->setActiveState(_savedCameraState);
_vm->_backgroundInstances->refreshPan();
}
}
void BackgroundInstance::registerResources() {
for (uint i = 0; i < _bgRes->_regionSequencesCount; ++i) {
Sequence *sequence = &_bgRes->_regionSequences[i];
_vm->_dict->addSequence(sequence->_sequenceId, sequence);
}
}
void BackgroundInstance::unregisterResources() {
for (uint i = 0; i < _bgRes->_regionSequencesCount; ++i) {
Sequence *sequence = &_bgRes->_regionSequences[i];
_vm->_dict->removeSequence(sequence->_sequenceId);
}
}
void BackgroundInstance::initSurface() {
for (uint i = 0; i < kMaxBackgroundItemSurfaces; ++i) {
_surfaces[i] = nullptr;
}
for (uint i = 0; i < _bgRes->_bgInfosCount; ++i) {
BgInfo *bgInfo = &_bgRes->_bgInfos[i];
_panPoints[i] = bgInfo->_panPoint;
_surfaces[i] = _vm->_screen->allocSurface(bgInfo->_surfInfo);
drawTiles(_surfaces[i], bgInfo->_tileMap, bgInfo->_tilePixels);
#if 0
if (_bgRes->_pathWalkRectsCount > 0) {
PathLines *pl = _bgRes->_pathWalkRects->_rects;
for (int j=0; j < pl->size(); j++) {
PathLine pathLine = (*pl)[j];
debug(0, "walk path rect line[%d]. (%d,%d)->(%d,%d)", j, pathLine.p0.x, pathLine.p0.y, pathLine.p1.x, pathLine.p1.y);
_surfaces[i]->drawLine(pathLine.p0.x, pathLine.p0.y, pathLine.p1.x, pathLine.p1.y, 5);
}
}
#endif
}
}
void BackgroundInstance::freeSurface() {
for (uint i = 0; i < _bgRes->_bgInfosCount; ++i) {
if (_surfaces[i]) {
_surfaces[i]->free();
delete _surfaces[i];
_surfaces[i] = nullptr;
}
}
}
void BackgroundInstance::drawTiles(Graphics::Surface *surface, TileMap &tileMap, byte *tilePixels) {
switch (_vm->getGameId()) {
case kGameIdDuckman:
drawTiles8(surface, tileMap, tilePixels);
break;
case kGameIdBBDOU:
drawTiles16(surface, tileMap, tilePixels);
break;
default:
break;
}
}
void BackgroundInstance::drawTiles8(Graphics::Surface *surface, TileMap &tileMap, byte *tilePixels) {
const int kTileWidth = 32;
const int kTileHeight = 8;
const int kTileSize = kTileWidth * kTileHeight;
uint tileMapIndex = 0;
for (int tileY = 0; tileY < tileMap._height; ++tileY) {
int tileDestY = tileY * kTileHeight;
int tileDestH = MIN(kTileHeight, surface->h - tileDestY);
for (int tileX = 0; tileX < tileMap._width; ++tileX) {
int tileDestX = tileX * kTileWidth;
int tileDestW = MIN(kTileWidth, surface->w - tileDestX);
uint16 tileIndex = READ_LE_UINT16(tileMap._map + 2 * tileMapIndex);
++tileMapIndex;
byte *src = tilePixels + (tileIndex - 1) * kTileSize;
byte *dst = (byte*)surface->getBasePtr(tileDestX, tileDestY);
for (int h = 0; h < tileDestH; ++h) {
memcpy(dst, src, tileDestW);
dst += surface->pitch;
src += kTileWidth;
}
}
}
}
void BackgroundInstance::drawTiles16(Graphics::Surface *surface, TileMap &tileMap, byte *tilePixels) {
const int kTileWidth = 32;
const int kTileHeight = 8;
const int kTileSize = kTileWidth * kTileHeight * 2;
uint tileMapIndex = 0;
for (int tileY = 0; tileY < tileMap._height; ++tileY) {
int tileDestY = tileY * kTileHeight;
int tileDestH = MIN(kTileHeight, surface->h - tileDestY);
for (int tileX = 0; tileX < tileMap._width; ++tileX) {
int tileDestX = tileX * kTileWidth;
int tileDestW = MIN(kTileWidth, surface->w - tileDestX);
uint16 tileIndex = READ_LE_UINT16(tileMap._map + 2 * tileMapIndex);
++tileMapIndex;
byte *src = tilePixels + (tileIndex - 1) * kTileSize;
byte *dst = (byte*)surface->getBasePtr(tileDestX, tileDestY);
for (int h = 0; h < tileDestH; ++h) {
for (int w = 0; w < tileDestW; ++w) {
uint16 pixel = READ_LE_UINT16(src + w * 2);
WRITE_LE_UINT16(dst + w * 2, pixel);
}
dst += surface->pitch;
src += kTileWidth * 2;
}
}
}
}
// BackgroundInstanceList
BackgroundInstanceList::BackgroundInstanceList(IllusionsEngine *vm)
: _vm(vm) {
}
BackgroundInstanceList::~BackgroundInstanceList() {
}
BackgroundInstance *BackgroundInstanceList::createBackgroundInstance(Resource *resource) {
BackgroundInstance *backgroundInstance = new BackgroundInstance(_vm);
backgroundInstance->load(resource);
_items.push_back(backgroundInstance);
return backgroundInstance;
}
void BackgroundInstanceList::removeBackgroundInstance(BackgroundInstance *backgroundInstance) {
_items.remove(backgroundInstance);
}
void BackgroundInstanceList::pauseBySceneId(uint32 sceneId) {
for (auto &item : _items) {
if (item->_sceneId == sceneId)
item->pause();
}
}
void BackgroundInstanceList::unpauseBySceneId(uint32 sceneId) {
for (auto &item : _items) {
if (item->_sceneId == sceneId)
item->unpause();
}
}
BackgroundInstance *BackgroundInstanceList::findActiveBackgroundInstance() {
for (auto &item : _items) {
if (item->_pauseCtr == 0)
return item;
}
return nullptr;
}
BackgroundInstance *BackgroundInstanceList::findBackgroundByResource(BackgroundResource *backgroundResource) {
for (auto &item : _items) {
if (item->_bgRes == backgroundResource)
return item;
}
return nullptr;
}
BackgroundResource *BackgroundInstanceList::getActiveBgResource() {
BackgroundInstance *background = findActiveBackgroundInstance();
if (background)
return background->_bgRes;
return nullptr;
}
WidthHeight BackgroundInstanceList::getMasterBgDimensions() {
BackgroundInstance *backgroundInstance = findActiveBackgroundInstance();
int16 index = backgroundInstance->_bgRes->findMasterBgIndex();
return backgroundInstance->_bgRes->_bgInfos[index - 1]._surfInfo._dimensions;
}
void BackgroundInstanceList::refreshPan() {
BackgroundInstance *backgroundInstance = findActiveBackgroundInstance();
if (backgroundInstance) {
WidthHeight dimensions = getMasterBgDimensions();
_vm->_camera->refreshPan(backgroundInstance, dimensions);
}
}
bool BackgroundInstanceList::findActiveBackgroundNamedPoint(uint32 namedPointId, Common::Point &pt) {
BackgroundResource *backgroundResource = getActiveBgResource();
return backgroundResource ? backgroundResource->findNamedPoint(namedPointId, pt) : false;
}
} // End of namespace Illusions

View File

@@ -0,0 +1,233 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef ILLUSIONS_BACKGROUNDRESOURCE_H
#define ILLUSIONS_BACKGROUNDRESOURCE_H
#include "illusions/camera.h"
#include "illusions/graphics.h"
#include "illusions/pathfinder.h"
#include "illusions/resourcesystem.h"
#include "graphics/surface.h"
#include "common/array.h"
#include "common/file.h"
#include "common/list.h"
#include "common/memstream.h"
#include "common/rect.h"
#include "common/substream.h"
#include "common/system.h"
namespace Illusions {
class IllusionsEngine;
struct Sequence;
class BackgroundResourceLoader : public BaseResourceLoader {
public:
BackgroundResourceLoader(IllusionsEngine *vm) : _vm(vm) {}
~BackgroundResourceLoader() override {}
void load(Resource *resource) override;
bool isFlag(int flag) override;
protected:
IllusionsEngine *_vm;
};
struct TileMap {
int16 _width, _height;
//field_4 dd
byte *_map;
void load(byte *dataStart, Common::SeekableReadStream &stream);
};
struct BgInfo {
uint32 _flags;
//field_4 dw
int16 _priorityBase;
SurfInfo _surfInfo;
Common::Point _panPoint;
TileMap _tileMap;
byte *_tilePixels;
void load(byte *dataStart, Common::SeekableReadStream &stream);
};
class PriorityLayer {
public:
void load(byte *dataStart, Common::SeekableReadStream &stream);
int getPriority(Common::Point pos);
protected:
int16 _width, _height;
int16 _mapWidth, _mapHeight;
byte *_map, *_values;
};
class ScaleLayer {
public:
void load(byte *dataStart, Common::SeekableReadStream &stream);
int getScale(Common::Point pos);
protected:
int16 _height;
byte *_values;
};
class RegionLayer {
public:
void load(byte *dataStart, Common::SeekableReadStream &stream);
int getRegionIndex(Common::Point pos);
uint32 getRegionSequenceId(int regionIndex);
protected:
uint32 _unk;
byte *_regionSequenceIds;
int16 _width, _height;
int16 _mapWidth, _mapHeight;
byte *_map, *_values;
};
struct Palette {
uint16 _count;
uint16 _unk;
byte *_palette;
void load(byte *dataStart, Common::SeekableReadStream &stream);
};
struct BackgroundObject {
uint32 _objectId;
uint16 _flags;
int16 _priority;
byte *_pointsConfig;
void load(byte *dataStart, Common::SeekableReadStream &stream);
};
struct PathWalkPoints {
PointArray *_points;
PathWalkPoints() : _points(0) {}
~PathWalkPoints() { delete _points; }
void load(byte *dataStart, Common::SeekableReadStream &stream);
};
struct PathWalkRects {
PathLines *_rects;
PathWalkRects() : _rects(0) {}
~PathWalkRects() { delete _rects; }
void load(byte *dataStart, Common::SeekableReadStream &stream);
};
class BackgroundResource {
public:
BackgroundResource();
~BackgroundResource();
void load(byte *data, uint32 dataSize);
int findMasterBgIndex();
PriorityLayer *getPriorityLayer(uint index);
ScaleLayer *getScaleLayer(uint index);
RegionLayer *getRegionLayer(uint index);
PathWalkPoints *getPathWalkPoints(uint index);
PathWalkRects *getPathWalkRects(uint index);
Palette *getPalette(uint index);
bool findNamedPoint(uint32 namedPointId, Common::Point &pt);
public:
uint _paletteIndex;
uint _bgInfosCount;
BgInfo *_bgInfos;
uint _priorityLayersCount;
PriorityLayer *_priorityLayers;
uint _scaleLayersCount;
ScaleLayer *_scaleLayers;
uint _regionLayersCount;
RegionLayer *_regionLayers;
uint _regionSequencesCount;
Sequence *_regionSequences;
uint _backgroundObjectsCount;
BackgroundObject *_backgroundObjects;
uint _pathWalkPointsCount;
PathWalkPoints *_pathWalkPoints;
uint _pathWalkRectsCount;
PathWalkRects *_pathWalkRects;
NamedPoints _namedPoints;
uint _palettesCount;
Palette *_palettes;
};
const uint kMaxBackgroundItemSurfaces = 3;
class BackgroundInstance : public ResourceInstance {
public:
BackgroundInstance(IllusionsEngine *vm);
~BackgroundInstance();
void load(Resource *resource) override;
void unload() override;
void pause() override;
void unpause() override;
public:
IllusionsEngine *_vm;
uint32 _sceneId;
int _pauseCtr;
BackgroundResource *_bgRes;
Common::Point _panPoints[kMaxBackgroundItemSurfaces];
Graphics::Surface *_surfaces[kMaxBackgroundItemSurfaces];
CameraState _savedCameraState;
byte *_savedPalette;
void registerResources();
void unregisterResources();
void initSurface();
void freeSurface();
void drawTiles(Graphics::Surface *surface, TileMap &tileMap, byte *tilePixels);
void drawTiles8(Graphics::Surface *surface, TileMap &tileMap, byte *tilePixels);
void drawTiles16(Graphics::Surface *surface, TileMap &tileMap, byte *tilePixels);
};
class BackgroundInstanceList {
public:
BackgroundInstanceList(IllusionsEngine *vm);
~BackgroundInstanceList();
BackgroundInstance *createBackgroundInstance(Resource *resource);
void removeBackgroundInstance(BackgroundInstance *backgroundInstance);
void pauseBySceneId(uint32 sceneId);
void unpauseBySceneId(uint32 sceneId);
BackgroundInstance *findActiveBackgroundInstance();
BackgroundInstance *findBackgroundByResource(BackgroundResource *backgroundResource);
BackgroundResource *getActiveBgResource();
WidthHeight getMasterBgDimensions();
void refreshPan();
bool findActiveBackgroundNamedPoint(uint32 namedPointId, Common::Point &pt);
//protected:
public:
typedef Common::List<BackgroundInstance*> Items;
typedef Items::iterator ItemsIterator;
IllusionsEngine *_vm;
Items _items;
};
} // End of namespace Illusions
#endif // ILLUSIONS_BACKGROUNDRESOURCE_H

View File

@@ -0,0 +1,147 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "illusions/illusions.h"
#include "illusions/resources/fontresource.h"
#include "illusions/dictionary.h"
namespace Illusions {
// FontResourceLoader
void FontResourceLoader::load(Resource *resource) {
FontInstance *fontInstance = new FontInstance(_vm);
fontInstance->load(resource);
resource->_instance = fontInstance;
}
bool FontResourceLoader::isFlag(int flag) {
return
flag == kRlfLoadFile;
}
// CharInfo
void CharInfo::load(byte *dataStart, Common::SeekableReadStream &stream) {
_width = stream.readUint16LE();
_field_2 = stream.readUint16LE();
uint32 pixelsOffs = stream.readUint32LE();
_pixels = dataStart + pixelsOffs;
debug(2, "CharInfo::load() _width: %d; _field_2: %d; pixelsOffs: %08X",
_width, _field_2, pixelsOffs);
}
// CharRange
CharRange::CharRange() : _charInfos(nullptr) {
}
CharRange::~CharRange() {
delete[] _charInfos;
}
void CharRange::load(byte *dataStart, Common::SeekableReadStream &stream) {
_firstChar = stream.readUint16LE();
_lastChar = stream.readUint16LE();
uint count = _lastChar - _firstChar + 1;
uint32 charInfosOffs = stream.readUint32LE();
_charInfos = new CharInfo[count];
for (uint i = 0; i < count; ++i) {
stream.seek(charInfosOffs + i * 8);
_charInfos[i].load(dataStart, stream);
}
debug(2, "CharRange::load() _firstChar: %d; _lastChar: %d; charInfosOffs: %08X",
_firstChar, _lastChar, charInfosOffs);
}
CharInfo *CharRange::getCharInfo(uint16 c) {
return &_charInfos[c - _firstChar];
}
bool CharRange::containsChar(uint16 c) {
return c >= _firstChar && c <= _lastChar;
}
// FontResource
FontResource::FontResource() : _charRanges(nullptr) {
}
FontResource::~FontResource() {
delete[] _charRanges;
}
void FontResource::load(Resource *resource) {
byte *data = resource->_data;
uint32 dataSize = resource->_dataSize;
Common::MemoryReadStream stream(data, dataSize, DisposeAfterUse::NO);
_totalSize = stream.readUint32LE();
_charHeight = stream.readUint16LE();
_defaultChar = stream.readUint16LE();
_colorIndex = stream.readUint16LE();
_lineIncr = stream.readUint16LE();
_widthC = stream.readUint16LE();
_charRangesCount = stream.readUint16LE();
uint32 charRangesOffs = stream.pos();
_charRanges = new CharRange[_charRangesCount];
for (uint i = 0; i < _charRangesCount; ++i) {
stream.seek(charRangesOffs + i * 8);
_charRanges[i].load(data, stream);
}
debug(2, "FontResource::load() _charHeight: %d; _defaultChar: %d; _colorIndex: %d; _lineIncr: %d; _widthC: %d; _charRangesCount: %d",
_charHeight, _defaultChar, _colorIndex, _lineIncr, _widthC, _charRangesCount);
}
CharInfo *FontResource::getCharInfo(uint16 c) {
for (uint i = 0; i < _charRangesCount; ++i) {
if (_charRanges[i].containsChar(c))
return _charRanges[i].getCharInfo(c);
}
return nullptr;
}
const Common::Rect FontResource::calculateRectForText(uint16 *text, uint textLength) {
int16 width = 0;
for (uint i = 0; i < textLength && *text; i++) {
width += getCharInfo(*text)->_width;
text++;
}
return Common::Rect(width, getCharHeight() + getLineIncr());
}
// FontInstance
FontInstance::FontInstance(IllusionsEngine *vm) : _vm(vm) {
}
void FontInstance::load(Resource *resource) {
_fontResource = new FontResource();
_fontResource->load(resource);
_resId = resource->_resId;
_vm->_dict->addFont(resource->_resId, _fontResource);
}
void FontInstance::unload() {
delete _fontResource;
_vm->_dict->removeFont(_resId);
}
} // End of namespace Illusions

View File

@@ -0,0 +1,95 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef ILLUSIONS_FONTRESOURCE_H
#define ILLUSIONS_FONTRESOURCE_H
#include "illusions/graphics.h"
#include "illusions/resourcesystem.h"
namespace Illusions {
class IllusionsEngine;
class FontResourceLoader : public BaseResourceLoader {
public:
FontResourceLoader(IllusionsEngine *vm) : _vm(vm) {}
~FontResourceLoader() override {}
void load(Resource *resource) override;
bool isFlag(int flag) override;
protected:
IllusionsEngine *_vm;
};
struct CharInfo {
int16 _width;
int16 _field_2;
byte *_pixels;
void load(byte *dataStart, Common::SeekableReadStream &stream);
};
struct CharRange {
CharRange();
~CharRange();
uint16 _firstChar;
uint16 _lastChar;
CharInfo *_charInfos;
void load(byte *dataStart, Common::SeekableReadStream &stream);
CharInfo *getCharInfo(uint16 c);
bool containsChar(uint16 c);
};
class FontResource {
public:
FontResource();
~FontResource();
void load(Resource *resource);
CharInfo *getCharInfo(uint16 c);
int16 getColorIndex() const { return _colorIndex; }
int16 getCharHeight() const { return _charHeight; }
int16 getLineIncr() const { return _lineIncr; }
const Common::Rect calculateRectForText(uint16 *text, uint textLength);
public:
uint32 _totalSize;
int16 _charHeight;
int16 _defaultChar;
int16 _colorIndex;
int16 _lineIncr;
int16 _widthC;
uint _charRangesCount;
CharRange *_charRanges;
CharRange *getCharRange(uint16 c);
};
class FontInstance : public ResourceInstance {
public:
FontInstance(IllusionsEngine *vm);
void load(Resource *resource) override;
void unload() override;
public:
IllusionsEngine *_vm;
FontResource *_fontResource;
uint32 _resId;
};
} // End of namespace Illusions
#endif // ILLUSIONS_FONTRESOURCE_H

View File

@@ -0,0 +1,39 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "illusions/illusions.h"
#include "illusions/resources/genericresource.h"
#include "illusions/dictionary.h"
namespace Illusions {
// GenericResourceLoader
void GenericResourceLoader::load(Resource *resource) {
resource->_instance = nullptr;
}
bool GenericResourceLoader::isFlag(int flag) {
return
flag == kRlfLoadFile;
}
} // End of namespace Illusions

View File

@@ -0,0 +1,44 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef ILLUSIONS_GENERICRESOURCE_H
#define ILLUSIONS_GENERICRESOURCE_H
#include "illusions/graphics.h"
#include "illusions/resourcesystem.h"
namespace Illusions {
class IllusionsEngine;
class GenericResourceLoader : public BaseResourceLoader {
public:
GenericResourceLoader(IllusionsEngine *vm) : _vm(vm) {}
~GenericResourceLoader() override {}
void load(Resource *resource) override;
bool isFlag(int flag) override;
protected:
IllusionsEngine *_vm;
};
} // End of namespace Illusions
#endif // ILLUSIONS_GENERICRESOURCE_H

View File

@@ -0,0 +1,99 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "illusions/illusions.h"
#include "illusions/resources/midiresource.h"
namespace Illusions {
// MidiGroupResourceLoader
void MidiGroupResourceLoader::load(Resource *resource) {
debug(1, "MidiGroupResourceLoader::load() Loading midi group %08X...", resource->_resId);
MidiGroupInstance *midiGroupInstance = new MidiGroupInstance(_vm);
midiGroupInstance->load(resource);
resource->_instance = midiGroupInstance;
}
bool MidiGroupResourceLoader::isFlag(int flag) {
return
flag == kRlfLoadFile/* ||
flag == kRlfFreeDataAfterLoad*/;
}
// MidiMusic
void MidiMusic::load(Common::SeekableReadStream &stream) {
_musicId = stream.readUint32LE();
_looping = stream.readUint16LE() != 0;
stream.skip(2 + 32 + 4); // Skip unused/unknown values
debug(1, "MidiMusic::load() _musicId: %08X; _looping: %d", _musicId, _looping);
}
// MidiGroupResource
MidiGroupResource::MidiGroupResource()
: _midiMusicCount(0), _midiMusic(nullptr) {
}
MidiGroupResource::~MidiGroupResource() {
delete[] _midiMusic;
}
void MidiGroupResource::load(byte *data, uint32 dataSize) {
Common::MemoryReadStream stream(data, dataSize, DisposeAfterUse::NO);
stream.skip(4);
_midiMusicCount = stream.readUint16LE();
stream.skip(2);
uint32 midiMusicOffs = stream.readUint32LE();
debug("_midiMusicCount: %d; midiMusicOffs: %08X", _midiMusicCount, midiMusicOffs);
_midiMusic = new MidiMusic[_midiMusicCount];
stream.seek(midiMusicOffs);
for (uint i = 0; i < _midiMusicCount; ++i) {
_midiMusic[i].load(stream);
}
}
// MidiGroupInstance
MidiGroupInstance::MidiGroupInstance(IllusionsEngine *vm)
: _vm(vm), _midiGroupResource(nullptr) {
}
void MidiGroupInstance::load(Resource *resource) {
_midiGroupResource = new MidiGroupResource();
_midiGroupResource->load(resource->_data, resource->_dataSize);
for (uint i = 0; i < _midiGroupResource->_midiMusicCount; ++i) {
// TODO
// SoundEffect *soundEffect = &_soundGroupResource->_soundEffects[i];
// _vm->_soundMan->loadSound(soundEffect->_soundEffectId, resource->_resId, soundEffect->_looping);
}
_resId = resource->_resId;
}
void MidiGroupInstance::unload() {
// _vm->_soundMan->unloadSounds(_resId);
delete _midiGroupResource;
}
} // End of namespace Illusions

View File

@@ -0,0 +1,71 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef ILLUSIONS_MIDIRESOURCE_H
#define ILLUSIONS_MIDIRESOURCE_H
#include "illusions/graphics.h"
#include "illusions/resourcesystem.h"
namespace Illusions {
class IllusionsEngine;
class MidiGroupResourceLoader : public BaseResourceLoader {
public:
MidiGroupResourceLoader(IllusionsEngine *vm) : _vm(vm) {}
~MidiGroupResourceLoader() override {}
void load(Resource *resource) override;
bool isFlag(int flag) override;
protected:
IllusionsEngine *_vm;
};
struct MidiMusic {
uint32 _musicId;
bool _looping;
void load(Common::SeekableReadStream &stream);
};
class MidiGroupResource {
public:
MidiGroupResource();
~MidiGroupResource();
void load(byte *data, uint32 dataSize);
public:
uint _midiMusicCount;
MidiMusic *_midiMusic;
};
class MidiGroupInstance : public ResourceInstance {
public:
MidiGroupInstance(IllusionsEngine *vm);
void load(Resource *resource) override;
void unload() override;
public:
IllusionsEngine *_vm;
MidiGroupResource *_midiGroupResource;
uint32 _resId;
};
} // End of namespace Illusions
#endif // ILLUSIONS_SOUNDRESOURCE_H

View File

@@ -0,0 +1,413 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "illusions/illusions.h"
#include "illusions/resources/scriptresource.h"
namespace Illusions {
// ScriptResourceLoader
void ScriptResourceLoader::load(Resource *resource) {
ScriptInstance *scriptInstance = new ScriptInstance(_vm);
scriptInstance->load(resource);
resource->_instance = scriptInstance;
}
bool ScriptResourceLoader::isFlag(int flag) {
return
flag == kRlfLoadFile;
}
// Properties
Properties::Properties()
: _count(0), _properties(nullptr) {
}
void Properties::init(uint count, byte *properties) {
_count = count;
_properties = properties;
}
void Properties::clear() {
uint32 size = getSize();
for (uint32 i = 0; i < size; ++i) {
_properties[i] = 0;
}
}
bool Properties::get(uint32 propertyId) {
uint index;
byte mask;
getProperyPos(propertyId, index, mask);
return (_properties[index] & mask) != 0;
}
void Properties::set(uint32 propertyId, bool value) {
uint index;
byte mask;
getProperyPos(propertyId, index, mask);
if (value)
_properties[index] |= mask;
else
_properties[index] &= ~mask;
}
uint32 Properties::getSize() {
return (_count >> 3) + 1;
}
void Properties::writeToStream(Common::WriteStream *out) {
const uint32 size = getSize();
out->writeUint32LE(size);
out->write(_properties, size);
}
bool Properties::readFromStream(Common::ReadStream *in) {
uint32 size = in->readUint32LE();
if (size != getSize())
return false;
in->read(_properties, size);
return true;
}
void Properties::getProperyPos(uint32 propertyId, uint &index, byte &mask) {
propertyId &= 0xFFFF;
index = propertyId >> 3;
mask = 1 << (propertyId & 7);
}
// BlockCounters
BlockCounters::BlockCounters()
: _count(0), _blockCounters(nullptr) {
}
void BlockCounters::init(uint count, byte *blockCounters) {
_count = count;
_blockCounters = blockCounters;
}
void BlockCounters::clear() {
for (uint i = 0; i < _count; ++i) {
_blockCounters[i] = 0;
}
}
byte BlockCounters::get(uint index) {
return _blockCounters[index - 1] & 0x3F;
}
void BlockCounters::set(uint index, byte value) {
_blockCounters[index - 1] ^= (_blockCounters[index - 1] ^ value) & 0x3F;
}
byte BlockCounters::getC0(uint index) {
return _blockCounters[index - 1] & 0xC0;
}
void BlockCounters::setC0(uint index, byte value) {
byte oldValue = _blockCounters[index - 1] & 0x3F;
if (value & 0x80)
value = value & 0xBF;
_blockCounters[index - 1] = oldValue | (value & 0xC0);
}
uint32 BlockCounters::getSize() {
return _count;
}
void BlockCounters::writeToStream(Common::WriteStream *out) {
const uint32 size = getSize();
out->writeUint32LE(size);
out->write(_blockCounters, size);
}
bool BlockCounters::readFromStream(Common::ReadStream *in) {
uint32 size = in->readUint32LE();
if (size != getSize())
return false;
in->read(_blockCounters, size);
return true;
}
// TriggerCause
void TriggerCause::load(Common::SeekableReadStream &stream) {
_verbId = stream.readUint32LE();
_objectId2 = stream.readUint32LE();
_codeOffs = stream.readUint32LE();
debug(2, "TriggerCause::load() _verbId: %08X; _objectId2: %08X; _codeOffs: %08X",
_verbId, _objectId2, _codeOffs);
}
// TriggerObject
TriggerObject::TriggerObject()
: _causesCount(0), _causes(nullptr) {
}
TriggerObject::~TriggerObject() {
delete[] _causes;
}
void TriggerObject::load(byte *dataStart, Common::SeekableReadStream &stream) {
_objectId = stream.readUint32LE();
_causesCount = stream.readUint16LE();
stream.skip(2); // Skip padding
debug(2, "TriggerObject::load() _objectId: %08X; _causesCount: %d",
_objectId, _causesCount);
_causes = new TriggerCause[_causesCount];
for (uint i = 0; i < _causesCount; ++i) {
_causes[i].load(stream);
}
}
bool TriggerObject::findTriggerCause(uint32 verbId, uint32 objectId2, uint32 &codeOffs) {
if ((verbId & 0xFFFF0000) == 0) {
for (uint i = 0; i < _causesCount; ++i) {
if ((verbId == 7 && ((_causes[i]._verbId == 7 && _causes[i]._objectId2 == objectId2) || _causes[i]._verbId == 8)) ||
(verbId != 7 && verbId == _causes[i]._verbId)) {
codeOffs = _causes[i]._codeOffs;
return true;
}
}
} else {
for (uint i = 0; i < _causesCount; ++i) {
if (_causes[i]._verbId == verbId && _causes[i]._objectId2 == objectId2) {
codeOffs = _causes[i]._codeOffs;
return true;
}
}
}
return false;
}
void TriggerObject::fixupSceneInfosDuckman() {
for (uint i = 0; i < _causesCount; ++i) {
_causes[i]._verbId &= 0xFFFF;
}
}
// SceneInfo
SceneInfo::SceneInfo()
: _triggerObjectsCount(0), _triggerObjects(nullptr),
_resourcesCount(0), _resources(nullptr) {
}
SceneInfo::~SceneInfo() {
delete[] _triggerObjects;
delete[] _resources;
}
void SceneInfo::load(byte *dataStart, Common::SeekableReadStream &stream) {
_id = stream.readUint16LE();
_unk = stream.readUint16LE();
_name = (uint16 *)(dataStart + stream.pos());
swapBytesInWideString((byte *)_name);
stream.skip(128);
_triggerObjectsCount = stream.readUint16LE();
_resourcesCount = stream.readUint16LE();
debug(2, "\nSceneInfo::load() _id: %d; _unk: %d; _name: [%s]",
_id, _unk, debugW2I(_name));
uint32 triggerObjectsListOffs = stream.readUint32LE();
if (_resourcesCount > 0) {
_resources = new uint32[_resourcesCount];
for (uint i = 0; i < _resourcesCount; ++i) {
_resources[i] = stream.readUint32LE();
}
}
if (_triggerObjectsCount > 0) {
_triggerObjects = new TriggerObject[_triggerObjectsCount];
for (uint i = 0; i < _triggerObjectsCount; ++i) {
stream.seek(triggerObjectsListOffs + i * 4);
uint32 triggerObjectOffs = stream.readUint32LE();
stream.seek(triggerObjectOffs);
_triggerObjects[i].load(dataStart, stream);
}
}
}
bool SceneInfo::findTriggerCause(uint32 verbId, uint32 objectId2, uint32 objectId, uint32 &codeOffs) {
TriggerObject *triggerObject = findTriggerObject(objectId);
if (triggerObject)
return triggerObject->findTriggerCause(verbId, objectId2, codeOffs);
return false;
}
void SceneInfo::getResources(uint &resourcesCount, uint32 *&resources) {
resourcesCount = _resourcesCount;
resources = _resources;
}
TriggerObject *SceneInfo::findTriggerObject(uint32 objectId) {
for (uint i = 0; i < _triggerObjectsCount; ++i) {
if (_triggerObjects[i]._objectId == objectId)
return &_triggerObjects[i];
}
return nullptr;
}
void SceneInfo::fixupSceneInfosDuckman() {
for (uint i = 0; i < _triggerObjectsCount; ++i) {
_triggerObjects[i].fixupSceneInfosDuckman();
}
}
// ScriptResource
ScriptResource::ScriptResource()
: _codeOffsets(nullptr), _sceneInfos(nullptr), _objectMap(nullptr) {
}
ScriptResource::~ScriptResource() {
delete[] _codeOffsets;
delete[] _sceneInfos;
delete[] _objectMap;
}
void ScriptResource::load(Resource *resource) {
_data = resource->_data;
_dataSize = resource->_dataSize;
Common::MemoryReadStream stream(_data, _dataSize, DisposeAfterUse::NO);
uint32 objectMapOffs = 0, sceneInfosOffs = 0;
_objectMapCount = 0;
if (resource->_gameId == kGameIdBBDOU) {
sceneInfosOffs = 0x18;
} else if (resource->_gameId == kGameIdDuckman) {
for (uint i = 0; i < 27; ++i) {
_soundIds[i] = stream.readUint32LE();
}
sceneInfosOffs = 0x8C;
}
stream.skip(4); // Skip unused
// Read item counts
uint propertiesCount = stream.readUint16LE();
uint blockCountersCount = stream.readUint16LE();
if (resource->_gameId == kGameIdDuckman)
_objectMapCount = stream.readUint16LE();
_codeCount = stream.readUint16LE();
_sceneInfosCount = stream.readUint16LE();
if (resource->_gameId == kGameIdDuckman)
stream.readUint16LE();//Unused?
// Read item offsets
uint32 propertiesOffs = stream.readUint32LE();
uint32 blockCountersOffs = stream.readUint32LE();
if (resource->_gameId == kGameIdDuckman)
objectMapOffs = stream.readUint32LE(); //TODO Is this needed for BBDOU?
uint32 codeTblOffs = stream.readUint32LE();
debug(2, "ScriptResource::load() propertiesCount: %d; blockCountersCount: %d; _codeCount: %d; _sceneInfosCount: %d; _objectMapCount: %d",
propertiesCount, blockCountersCount, _codeCount, _sceneInfosCount, _objectMapCount);
debug(2, "ScriptResource::load() propertiesOffs: %08X; blockCountersOffs: %08X; codeTblOffs: %08X; objectMapOffs: %08X",
propertiesOffs, blockCountersOffs, codeTblOffs, objectMapOffs);
// Init properties
_properties.init(propertiesCount, _data + propertiesOffs);
// Init blockcounters
_blockCounters.init(blockCountersCount, _data + blockCountersOffs);
_codeOffsets = new uint32[_codeCount];
stream.seek(codeTblOffs);
for (uint i = 0; i < _codeCount; ++i) {
_codeOffsets[i] = stream.readUint32LE();
}
_sceneInfos = new SceneInfo[_sceneInfosCount];
for (uint i = 0; i < _sceneInfosCount; ++i) {
stream.seek(sceneInfosOffs + i * 4);
uint32 sceneInfoOffs = stream.readUint32LE();
stream.seek(sceneInfoOffs);
_sceneInfos[i].load(_data, stream);
}
if (_objectMapCount > 0) {
_objectMap = new uint32[_objectMapCount];
stream.seek(objectMapOffs);
for (uint i = 0; i < _objectMapCount; ++i) {
_objectMap[i] = stream.readUint32LE();
stream.skip(4);
}
}
if (resource->_gameId == kGameIdDuckman) {
stream.seek(0x6C);
_mainActorObjectId = stream.readUint32LE();
} else if (resource->_gameId == kGameIdBBDOU) {
stream.seek(0);
_mainActorObjectId = stream.readUint32LE();
}
if (resource->_gameId == kGameIdDuckman)
fixupSceneInfosDuckman();
}
byte *ScriptResource::getThreadCode(uint32 threadId) {
return _data + _codeOffsets[(threadId & 0xFFFF) - 1];
}
byte *ScriptResource::getCode(uint32 codeOffs) {
return _data + codeOffs;
}
SceneInfo *ScriptResource::getSceneInfo(uint32 index) {
if (index > 0 && index <= _sceneInfosCount)
return &_sceneInfos[index - 1];
return nullptr;
}
uint32 ScriptResource::getObjectActorTypeId(uint32 objectId) {
return _objectMap[(objectId & 0xFFFF) - 1];
}
void ScriptResource::fixupSceneInfosDuckman() {
for (uint i = 0; i < _sceneInfosCount; ++i) {
_sceneInfos[i].fixupSceneInfosDuckman();
}
}
// ScriptInstance
ScriptInstance::ScriptInstance(IllusionsEngine *vm)
: _vm(vm) {
}
void ScriptInstance::load(Resource *resource) {
_vm->_scriptResource = new ScriptResource();
_vm->_scriptResource->load(resource);
}
void ScriptInstance::unload() {
delete _vm->_scriptResource;
_vm->_scriptResource = nullptr;
}
} // End of namespace Illusions

View File

@@ -0,0 +1,152 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef ILLUSIONS_SCRIPTRESOURCE_H
#define ILLUSIONS_SCRIPTRESOURCE_H
#include "illusions/resourcesystem.h"
#include "common/file.h"
namespace Illusions {
class IllusionsEngine;
class ScriptResourceLoader : public BaseResourceLoader {
public:
ScriptResourceLoader(IllusionsEngine *vm) : _vm(vm) {}
~ScriptResourceLoader() override {}
void load(Resource *resource) override;
bool isFlag(int flag) override;
protected:
IllusionsEngine *_vm;
};
class Properties {
public:
Properties();
void init(uint count, byte *properties);
void clear();
bool get(uint32 propertyId);
void set(uint32 propertyId, bool value);
uint32 getSize();
void writeToStream(Common::WriteStream *out);
bool readFromStream(Common::ReadStream *in);
public:
uint _count;
byte *_properties;
void getProperyPos(uint32 propertyId, uint &index, byte &mask);
};
class BlockCounters {
public:
BlockCounters();
void init(uint count, byte *blockCounters);
void clear();
byte get(uint index);
void set(uint index, byte value);
byte getC0(uint index);
void setC0(uint index, byte value);
uint32 getSize();
void writeToStream(Common::WriteStream *out);
bool readFromStream(Common::ReadStream *in);
public:
uint _count;
byte *_blockCounters;
};
struct TriggerCause {
uint32 _verbId;
uint32 _objectId2;
uint32 _codeOffs;
void load(Common::SeekableReadStream &stream);
};
class TriggerObject {
public:
TriggerObject();
~TriggerObject();
void load(byte *dataStart, Common::SeekableReadStream &stream);
bool findTriggerCause(uint32 verbId, uint32 objectId2, uint32 &codeOffs);
void fixupSceneInfosDuckman();
public:
uint32 _objectId;
uint _causesCount;
TriggerCause *_causes;
};
class SceneInfo {
public:
SceneInfo();
~SceneInfo();
void load(byte *dataStart, Common::SeekableReadStream &stream);
bool findTriggerCause(uint32 verbId, uint32 objectId2, uint32 objectId, uint32 &codeOffs);
void getResources(uint &resourcesCount, uint32 *&resources);
void fixupSceneInfosDuckman();
protected:
uint16 _id;
uint16 _unk;
uint16 *_name;
uint _triggerObjectsCount;
TriggerObject *_triggerObjects;
uint _resourcesCount;
uint32 *_resources;
TriggerObject *findTriggerObject(uint32 objectId);
};
class ScriptResource {
public:
ScriptResource();
~ScriptResource();
void load(Resource *resource);
byte *getThreadCode(uint32 threadId);
byte *getCode(uint32 codeOffs);
SceneInfo *getSceneInfo(uint32 index);
uint32 getObjectActorTypeId(uint32 objectId);
uint32 getMainActorObjectId() const { return _mainActorObjectId; }
public:
byte *_data;
uint32 _dataSize;
Properties _properties;
BlockCounters _blockCounters;
uint _codeCount;
uint32 *_codeOffsets;
uint _sceneInfosCount;
SceneInfo *_sceneInfos;
// Duckman specific
uint32 _soundIds[27];
uint _objectMapCount;
uint32 *_objectMap;
uint32 _mainActorObjectId;
void fixupSceneInfosDuckman();
};
class ScriptInstance : public ResourceInstance {
public:
ScriptInstance(IllusionsEngine *vm);
void load(Resource *resource) override;
void unload() override;
public:
IllusionsEngine *_vm;
};
} // End of namespace Illusions
#endif // ILLUSIONS_ACTORRESOURCE_H

View File

@@ -0,0 +1,102 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "illusions/illusions.h"
#include "illusions/resources/soundresource.h"
#include "illusions/sound.h"
namespace Illusions {
// SoundGroupResourceLoader
void SoundGroupResourceLoader::load(Resource *resource) {
SoundGroupInstance *soundGroupInstance = new SoundGroupInstance(_vm);
soundGroupInstance->load(resource);
resource->_instance = soundGroupInstance;
}
bool SoundGroupResourceLoader::isFlag(int flag) {
return
flag == kRlfLoadFile/* ||
flag == kRlfFreeDataAfterLoad*/;
}
// SoundEffect
void SoundEffect::load(Common::SeekableReadStream &stream) {
_soundEffectId = stream.readUint32LE();
_looping = stream.readUint16LE() != 0;
_field6 = stream.readUint16LE();
_volume = stream.readUint16LE();
_frequency = stream.readUint16LE();
stream.skip(32 + 4); // Skip name
debug(1, "SoundEffect::load() _soundEffectId: %08X, _looping: %d, _field6: %d, _volume: %d, _frequency: %d",
_soundEffectId, _looping, _field6, _volume, _frequency);
}
// SoundGroupResource
SoundGroupResource::SoundGroupResource()
: _soundEffects(nullptr) {
}
SoundGroupResource::~SoundGroupResource() {
delete[] _soundEffects;
}
void SoundGroupResource::load(byte *data, uint32 dataSize) {
Common::MemoryReadStream stream(data, dataSize, DisposeAfterUse::NO);
stream.skip(4);
_soundEffectsCount = stream.readUint16LE();
stream.skip(2);
uint32 soundEffectsOffs = stream.readUint32LE();
debug(1, "_soundEffectsCount: %d; soundEffectsOffs: %08X", _soundEffectsCount, soundEffectsOffs);
_soundEffects = new SoundEffect[_soundEffectsCount];
stream.seek(soundEffectsOffs);
for (uint i = 0; i < _soundEffectsCount; ++i) {
_soundEffects[i].load(stream);
}
}
// SoundGroupInstance
SoundGroupInstance::SoundGroupInstance(IllusionsEngine *vm)
: _vm(vm), _soundGroupResource(nullptr) {
}
void SoundGroupInstance::load(Resource *resource) {
_soundGroupResource = new SoundGroupResource();
_soundGroupResource->load(resource->_data, resource->_dataSize);
for (uint i = 0; i < _soundGroupResource->_soundEffectsCount; ++i) {
SoundEffect *soundEffect = &_soundGroupResource->_soundEffects[i];
_vm->_soundMan->loadSound(soundEffect->_soundEffectId, resource->_resId, soundEffect->_looping);
}
_resId = resource->_resId;
}
void SoundGroupInstance::unload() {
_vm->_soundMan->unloadSounds(_resId);
delete _soundGroupResource;
}
} // End of namespace Illusions

View File

@@ -0,0 +1,74 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef ILLUSIONS_SOUNDRESOURCE_H
#define ILLUSIONS_SOUNDRESOURCE_H
#include "illusions/graphics.h"
#include "illusions/resourcesystem.h"
namespace Illusions {
class IllusionsEngine;
class SoundGroupResourceLoader : public BaseResourceLoader {
public:
SoundGroupResourceLoader(IllusionsEngine *vm) : _vm(vm) {}
~SoundGroupResourceLoader() override {}
void load(Resource *resource) override;
bool isFlag(int flag) override;
protected:
IllusionsEngine *_vm;
};
struct SoundEffect {
uint32 _soundEffectId;
bool _looping;
int16 _field6;
int16 _volume;
int16 _frequency;
void load(Common::SeekableReadStream &stream);
};
class SoundGroupResource {
public:
SoundGroupResource();
~SoundGroupResource();
void load(byte *data, uint32 dataSize);
public:
uint _soundEffectsCount;
SoundEffect *_soundEffects;
};
class SoundGroupInstance : public ResourceInstance {
public:
SoundGroupInstance(IllusionsEngine *vm);
void load(Resource *resource) override;
void unload() override;
public:
IllusionsEngine *_vm;
SoundGroupResource *_soundGroupResource;
uint32 _resId;
};
} // End of namespace Illusions
#endif // ILLUSIONS_SOUNDRESOURCE_H

View File

@@ -0,0 +1,178 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "illusions/illusions.h"
#include "illusions/resources/talkresource.h"
#include "illusions/dictionary.h"
namespace Illusions {
// TalkResourceLoader
void TalkResourceLoader::load(Resource *resource) {
resource->_instance = _vm->_talkItems->createTalkInstance(resource);
}
bool TalkResourceLoader::isFlag(int flag) {
return
flag == kRlfLoadFile;
}
// TalkEntry
void TalkEntry::load(byte *dataStart, Common::SeekableReadStream &stream) {
_talkId = stream.readUint32LE();
stream.readUint32LE(); // Skip unknown
uint32 textOffs = stream.readUint32LE();
uint32 tblOffs = stream.readUint32LE();
uint32 voiceNameOffs = stream.readUint32LE();
_text = (uint16 *)(dataStart + textOffs);
_tblPtr = dataStart + tblOffs;
_voiceName = dataStart + voiceNameOffs;
debug(0, "TalkEntry::load() _talkId: %08X; textOffs: %08X; tblOffs: %08X; voiceNameOffs: %08X",
_talkId, textOffs, tblOffs, voiceNameOffs);
#if defined(SCUMM_BIG_ENDIAN)
for (byte *ptr = (byte *)_text; *ptr != 0; ptr += 2) {
WRITE_UINT16(ptr, SWAP_BYTES_16(READ_UINT16(ptr)));
}
#endif
}
// TalkResource
TalkResource::TalkResource()
: _talkEntriesCount(0), _talkEntries(nullptr) {
}
TalkResource::~TalkResource() {
delete[] _talkEntries;
}
void TalkResource::load(byte *data, uint32 dataSize) {
Common::MemoryReadStream stream(data, dataSize, DisposeAfterUse::NO);
stream.skip(4); // Skip size
_talkEntriesCount = stream.readUint16LE();
stream.skip(2); // Skip padding
_talkEntries = new TalkEntry[_talkEntriesCount];
for (uint i = 0; i < _talkEntriesCount; ++i) {
stream.seek(8 + i * 0x14);
_talkEntries[i].load(data, stream);
}
}
// TalkInstance
TalkInstance::TalkInstance(IllusionsEngine *vm)
: _vm(vm), _pauseCtr(0) {
}
void TalkInstance::load(Resource *resource) {
TalkResource *talkResource = new TalkResource();
talkResource->load(resource->_data, resource->_dataSize);
_talkRes = talkResource;
_talkId = resource->_resId;
_sceneId = resource->_sceneId;
registerResources();
}
void TalkInstance::unload() {
unregisterResources();
_vm->_talkItems->removeTalkInstance(this);
delete _talkRes;
}
void TalkInstance::pause() {
++_pauseCtr;
if (_pauseCtr == 1)
unregisterResources();
}
void TalkInstance::unpause() {
--_pauseCtr;
if (_pauseCtr == 0)
registerResources();
}
void TalkInstance::registerResources() {
for (uint i = 0; i < _talkRes->_talkEntriesCount; ++i) {
TalkEntry *talkEntry = &_talkRes->_talkEntries[i];
_vm->_dict->addTalkEntry(talkEntry->_talkId, talkEntry);
}
}
void TalkInstance::unregisterResources() {
for (uint i = 0; i < _talkRes->_talkEntriesCount; ++i) {
TalkEntry *talkEntry = &_talkRes->_talkEntries[i];
_vm->_dict->removeTalkEntry(talkEntry->_talkId);
}
}
// TalkInstanceList
TalkInstanceList::TalkInstanceList(IllusionsEngine *vm)
: _vm(vm) {
}
TalkInstanceList::~TalkInstanceList() {
}
TalkInstance *TalkInstanceList::createTalkInstance(Resource *resource) {
TalkInstance *talkInstance = new TalkInstance(_vm);
talkInstance->load(resource);
_items.push_back(talkInstance);
return talkInstance;
}
void TalkInstanceList::removeTalkInstance(TalkInstance *talkInstance) {
_items.remove(talkInstance);
}
TalkInstance *TalkInstanceList::findTalkItem(uint32 talkId) {
for (auto &item : _items) {
if (item->_talkId == talkId)
return item;
}
return nullptr;
}
TalkInstance *TalkInstanceList::findTalkItemBySceneId(uint32 sceneId) {
for (auto &item : _items) {
if (item->_sceneId == sceneId)
return item;
}
return nullptr;
}
void TalkInstanceList::pauseBySceneId(uint32 sceneId) {
TalkInstance *talkInstance = findTalkItemBySceneId(sceneId);
if (talkInstance)
talkInstance->pause();
}
void TalkInstanceList::unpauseBySceneId(uint32 sceneId) {
TalkInstance *talkInstance = findTalkItemBySceneId(sceneId);
if (talkInstance)
talkInstance->unpause();
}
} // End of namespace Illusions

View File

@@ -0,0 +1,98 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef ILLUSIONS_TALKRESOURCE_H
#define ILLUSIONS_TALKRESOURCE_H
#include "illusions/graphics.h"
#include "illusions/resourcesystem.h"
namespace Illusions {
class IllusionsEngine;
class TalkResourceLoader : public BaseResourceLoader {
public:
TalkResourceLoader(IllusionsEngine *vm) : _vm(vm) {}
~TalkResourceLoader() override {}
void load(Resource *resource) override;
bool isFlag(int flag) override;
protected:
IllusionsEngine *_vm;
};
struct TalkEntry {
uint32 _talkId;
//field_4 dd
uint16 *_text;
byte *_tblPtr;
byte *_voiceName;
void load(byte *dataStart, Common::SeekableReadStream &stream);
};
class TalkResource {
public:
TalkResource();
~TalkResource();
void load(byte *data, uint32 dataSize);
public:
uint _talkEntriesCount;
TalkEntry *_talkEntries;
};
class TalkInstance : public ResourceInstance {
public:
TalkInstance(IllusionsEngine *vm);
void load(Resource *resource) override;
void unload() override;
void pause() override;
void unpause() override;
public:
IllusionsEngine *_vm;
uint32 _talkId;
uint32 _sceneId;
TalkResource *_talkRes;
int _pauseCtr;
void registerResources();
void unregisterResources();
};
class TalkInstanceList {
public:
TalkInstanceList(IllusionsEngine *vm);
~TalkInstanceList();
TalkInstance *createTalkInstance(Resource *resource);
void removeTalkInstance(TalkInstance *talkInstance);
TalkInstance *findTalkItem(uint32 talkId);
TalkInstance *findTalkItemBySceneId(uint32 sceneId);
void pauseBySceneId(uint32 sceneId);
void unpauseBySceneId(uint32 sceneId);
//protected:
public:
typedef Common::List<TalkInstance*> Items;
typedef Items::iterator ItemsIterator;
IllusionsEngine *_vm;
Items _items;
};
} // End of namespace Illusions
#endif // ILLUSIONS_TALKRESOURCE_H