Initial commit
This commit is contained in:
124
engines/stark/formats/biff.cpp
Normal file
124
engines/stark/formats/biff.cpp
Normal file
@@ -0,0 +1,124 @@
|
||||
/* 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 "engines/stark/formats/biff.h"
|
||||
|
||||
#include "engines/stark/services/archiveloader.h"
|
||||
|
||||
namespace Stark {
|
||||
namespace Formats {
|
||||
|
||||
BiffArchive::BiffArchive(ArchiveReadStream *stream, ObjectBuilder objectBuilder) :
|
||||
_objectBuilder(objectBuilder) {
|
||||
read(stream);
|
||||
}
|
||||
|
||||
BiffArchive::~BiffArchive() {
|
||||
for (uint i = 0; i < _rootObjects.size(); i++) {
|
||||
delete _rootObjects[i];
|
||||
}
|
||||
}
|
||||
|
||||
void BiffArchive::read(ArchiveReadStream *stream) {
|
||||
uint32 id = stream->readUint32BE();
|
||||
if (id != MKTAG('B', 'I', 'F', 'F')) {
|
||||
error("Wrong magic while reading biff archive");
|
||||
}
|
||||
|
||||
_version = stream->readUint32LE();
|
||||
/*uint32 u1 = */stream->readUint32LE();
|
||||
/*uint32 u2 = */stream->readUint32LE();
|
||||
|
||||
uint32 len = stream->readUint32LE();
|
||||
for (uint32 i = 0; i < len; i++) {
|
||||
BiffObject *object = readObject(stream, nullptr);
|
||||
|
||||
_rootObjects.push_back(object);
|
||||
}
|
||||
}
|
||||
|
||||
BiffObject *BiffArchive::readObject(ArchiveReadStream *stream, BiffObject *parent) {
|
||||
uint32 marker = stream->readUint32LE();
|
||||
if (marker != 0xf0f0f0f0) {
|
||||
error("Wrong magic while reading biff archive");
|
||||
}
|
||||
|
||||
uint32 type = stream->readUint32LE();
|
||||
BiffObject *object = _objectBuilder(type);
|
||||
if (!object) {
|
||||
error("Unimplemented BIFF object type %x", type);
|
||||
}
|
||||
|
||||
object->_parent = parent;
|
||||
object->_u3 = stream->readUint32LE();
|
||||
uint32 size = stream->readUint32LE();
|
||||
|
||||
if (_version >= 2) {
|
||||
object->_version = stream->readUint32LE();
|
||||
}
|
||||
|
||||
object->readData(stream, size);
|
||||
|
||||
marker = stream->readUint32LE();
|
||||
if (marker != 0x0f0f0f0f) {
|
||||
error("Wrong magic while reading biff archive");
|
||||
}
|
||||
|
||||
uint32 len = stream->readUint32LE();
|
||||
for (uint32 i = 0; i < len; ++i) {
|
||||
BiffObject *child = readObject(stream, object);
|
||||
object->addChild(child);
|
||||
}
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
Common::Array<BiffObject *> BiffArchive::listObjects() {
|
||||
return _rootObjects;
|
||||
}
|
||||
|
||||
BiffObject::BiffObject() :
|
||||
_u3(0),
|
||||
_version(0),
|
||||
_parent(nullptr),
|
||||
_type(0) {
|
||||
|
||||
}
|
||||
|
||||
uint32 BiffObject::getType() const {
|
||||
return _type;
|
||||
}
|
||||
|
||||
void BiffObject::addChild(BiffObject *child) {
|
||||
_children.push_back(child);
|
||||
}
|
||||
|
||||
BiffObject::~BiffObject() {
|
||||
// Delete the children objects
|
||||
Common::Array<BiffObject *>::iterator i = _children.begin();
|
||||
while (i != _children.end()) {
|
||||
delete *i;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Formats
|
||||
} // End of namespace Stark
|
||||
135
engines/stark/formats/biff.h
Normal file
135
engines/stark/formats/biff.h
Normal file
@@ -0,0 +1,135 @@
|
||||
/* 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 STARK_FORMATS_BIFF_H
|
||||
#define STARK_FORMATS_BIFF_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/scummsys.h"
|
||||
|
||||
namespace Stark {
|
||||
|
||||
class ArchiveReadStream;
|
||||
|
||||
namespace Formats {
|
||||
|
||||
class BiffObject;
|
||||
|
||||
/**
|
||||
* A tree-style container for BiffObjects
|
||||
*
|
||||
* Users of this class must provide a factory method for the BiffObject subclasses
|
||||
* contained in the archive. This class can only read the archive's structure
|
||||
* and not specific object types.
|
||||
*/
|
||||
class BiffArchive {
|
||||
public:
|
||||
typedef BiffObject *(*ObjectBuilder)(uint32 type);
|
||||
|
||||
BiffArchive(ArchiveReadStream *stream, ObjectBuilder objectBuilder);
|
||||
~BiffArchive();
|
||||
|
||||
/** List the objects at the root level of the archive */
|
||||
Common::Array<BiffObject *> listObjects();
|
||||
|
||||
/** List objects recursively matching the template parameter type */
|
||||
template<class T>
|
||||
Common::Array<T *> listObjectsRecursive();
|
||||
|
||||
private:
|
||||
void read(ArchiveReadStream *stream);
|
||||
BiffObject *readObject(ArchiveReadStream *stream, BiffObject *parent);
|
||||
|
||||
ObjectBuilder _objectBuilder;
|
||||
uint32 _version;
|
||||
|
||||
Common::Array<BiffObject *> _rootObjects;
|
||||
};
|
||||
|
||||
/**
|
||||
* An object which can be read from a BiffArchive
|
||||
*
|
||||
* Each object has a list of children objects, resulting in a tree structure
|
||||
*/
|
||||
class BiffObject {
|
||||
public:
|
||||
BiffObject();
|
||||
virtual ~BiffObject();
|
||||
|
||||
/**
|
||||
* Used to read the object data from the stream
|
||||
*/
|
||||
virtual void readData(ArchiveReadStream *stream, uint32 dataLength) = 0;
|
||||
|
||||
/** Get the object type */
|
||||
uint32 getType() const;
|
||||
|
||||
/** List children recursively matching the template parameter type */
|
||||
template<class T>
|
||||
Common::Array<T *> listChildrenRecursive();
|
||||
|
||||
/** Add an object to the children list */
|
||||
void addChild(BiffObject *child);
|
||||
|
||||
protected:
|
||||
uint32 _type;
|
||||
uint32 _u3;
|
||||
uint32 _version;
|
||||
|
||||
BiffObject *_parent;
|
||||
Common::Array<BiffObject *> _children;
|
||||
|
||||
friend class BiffArchive;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
Common::Array<T *> BiffArchive::listObjectsRecursive() {
|
||||
Common::Array<BiffObject *> objects = listObjects();
|
||||
|
||||
Common::Array<T *> array;
|
||||
for (uint i = 0; i < objects.size(); i++) {
|
||||
array.push_back(objects[i]->listChildrenRecursive<T>());
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Common::Array<T *> BiffObject::listChildrenRecursive() {
|
||||
Common::Array<T *> list;
|
||||
|
||||
for (uint i = 0; i < _children.size(); i++) {
|
||||
if (_children[i]->getType() == T::TYPE) {
|
||||
// Found a matching child
|
||||
list.push_back(static_cast<T *>(_children[i]));
|
||||
}
|
||||
|
||||
// Look for matching resources in the child's children
|
||||
list.push_back(_children[i]->listChildrenRecursive<T>());
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
} // End of namespace Formats
|
||||
} // End of namespace Stark
|
||||
|
||||
#endif // STARK_FORMATS_BIFF_H
|
||||
443
engines/stark/formats/biffmesh.cpp
Normal file
443
engines/stark/formats/biffmesh.cpp
Normal file
@@ -0,0 +1,443 @@
|
||||
/* 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 "engines/stark/formats/biffmesh.h"
|
||||
|
||||
#include "engines/stark/formats/biff.h"
|
||||
#include "engines/stark/services/archiveloader.h"
|
||||
|
||||
#include "common/hashmap.h"
|
||||
|
||||
namespace Stark {
|
||||
namespace Formats {
|
||||
|
||||
enum BiffMeshObjectType {
|
||||
kMeshObjectSceneData = 0x5a4aa94,
|
||||
kMeshObjectBase = 0x5a4aa89,
|
||||
kMeshObjectTri = 0x5a4aa8d,
|
||||
kMeshObjectMaterial = 0x5a4aa8e
|
||||
};
|
||||
|
||||
class MeshObjectSceneData : public BiffObject {
|
||||
public:
|
||||
static const uint32 TYPE = kMeshObjectSceneData;
|
||||
|
||||
MeshObjectSceneData() :
|
||||
BiffObject(),
|
||||
_animStart(0),
|
||||
_animEnd(0) {
|
||||
_type = TYPE;
|
||||
}
|
||||
|
||||
// BiffObject API
|
||||
void readData(ArchiveReadStream *stream, uint32 dataLength) override {
|
||||
_animStart = stream->readUint32LE();
|
||||
_animEnd = stream->readUint32LE();
|
||||
}
|
||||
|
||||
private:
|
||||
uint32 _animStart;
|
||||
uint32 _animEnd;
|
||||
};
|
||||
|
||||
class MeshObjectBase : public BiffObject {
|
||||
public:
|
||||
static const uint32 TYPE = kMeshObjectBase;
|
||||
|
||||
MeshObjectBase() :
|
||||
BiffObject() {
|
||||
_type = TYPE;
|
||||
}
|
||||
|
||||
// BiffObject API
|
||||
void readData(ArchiveReadStream *stream, uint32 dataLength) override {
|
||||
_name = stream->readString16();
|
||||
}
|
||||
|
||||
private:
|
||||
Common::String _name;
|
||||
};
|
||||
|
||||
class MeshObjectTri : public BiffObject {
|
||||
public:
|
||||
static const uint32 TYPE = kMeshObjectTri;
|
||||
|
||||
MeshObjectTri() :
|
||||
BiffObject(),
|
||||
_hasPhysics(false) {
|
||||
_type = TYPE;
|
||||
}
|
||||
|
||||
struct KeyFrame {
|
||||
uint32 time;
|
||||
Math::Quaternion essentialRotation;
|
||||
float determinant;
|
||||
Math::Quaternion stretchRotation;
|
||||
Math::Vector3d scale;
|
||||
Math::Vector3d translation;
|
||||
};
|
||||
|
||||
struct Vertex {
|
||||
Common::String animName1;
|
||||
Common::String animName2;
|
||||
float animInfluence1;
|
||||
float animInfluence2;
|
||||
Math::Vector3d position;
|
||||
};
|
||||
|
||||
struct RawFace {
|
||||
uint32 vertexIndex[3];
|
||||
uint32 normalIndex[3];
|
||||
uint32 textureVertexIndex[3];
|
||||
uint32 materialId;
|
||||
uint32 smoothingGroup;
|
||||
};
|
||||
|
||||
// BiffObject API
|
||||
void readData(ArchiveReadStream *stream, uint32 dataLength) override {
|
||||
_name = stream->readString16();
|
||||
|
||||
uint32 keyFrameCount = stream->readUint32LE();
|
||||
for (uint i = 0; i < keyFrameCount; i++) {
|
||||
KeyFrame keyFrame;
|
||||
keyFrame.time = stream->readUint32LE();
|
||||
keyFrame.essentialRotation = stream->readQuaternion();
|
||||
keyFrame.determinant = stream->readFloatLE();
|
||||
keyFrame.stretchRotation = stream->readQuaternion();
|
||||
keyFrame.scale = stream->readVector3();
|
||||
keyFrame.translation = stream->readVector3();
|
||||
|
||||
_keyFrames.push_back(keyFrame);
|
||||
}
|
||||
|
||||
if (_version >= 2) {
|
||||
uint32 uvKeyFrameCount = stream->readUint32LE();
|
||||
assert(uvKeyFrameCount == 0); // Reading the uv keyframes is not implemented
|
||||
uint32 attributeCount = stream->readUint32LE();
|
||||
assert(attributeCount == 0); // Reading the attributes is not implemented
|
||||
}
|
||||
|
||||
uint32 vertexCount = stream->readUint32LE();
|
||||
for (uint i = 0; i < vertexCount; i++) {
|
||||
Vertex vertex;
|
||||
vertex.animName1 = stream->readString16();
|
||||
vertex.animName2 = stream->readString16();
|
||||
vertex.animInfluence1 = stream->readFloatLE();
|
||||
vertex.animInfluence2 = stream->readFloatLE();
|
||||
vertex.position = stream->readVector3();
|
||||
|
||||
_rawVertices.push_back(vertex);
|
||||
}
|
||||
|
||||
uint32 normalCount = stream->readUint32LE();
|
||||
for (uint i = 0; i < normalCount; i++) {
|
||||
_rawNormals.push_back(stream->readVector3());
|
||||
}
|
||||
|
||||
uint32 textureVertexCount = stream->readUint32LE();
|
||||
for (uint i = 0; i < textureVertexCount; i++) {
|
||||
_rawTexturePositions.push_back(stream->readVector3());
|
||||
}
|
||||
|
||||
uint32 faceCount = stream->readUint32LE();
|
||||
for (uint i = 0; i < faceCount; i++) {
|
||||
RawFace face;
|
||||
face.vertexIndex[0] = stream->readUint32LE();
|
||||
face.vertexIndex[1] = stream->readUint32LE();
|
||||
face.vertexIndex[2] = stream->readUint32LE();
|
||||
face.normalIndex[0] = stream->readUint32LE();
|
||||
face.normalIndex[1] = stream->readUint32LE();
|
||||
face.normalIndex[2] = stream->readUint32LE();
|
||||
face.textureVertexIndex[0] = stream->readUint32LE();
|
||||
face.textureVertexIndex[1] = stream->readUint32LE();
|
||||
face.textureVertexIndex[2] = stream->readUint32LE();
|
||||
face.materialId = stream->readUint32LE();
|
||||
face.smoothingGroup = stream->readUint32LE();
|
||||
|
||||
_rawFaces.push_back(face);
|
||||
}
|
||||
|
||||
_hasPhysics = stream->readByte();
|
||||
}
|
||||
|
||||
void reindex() {
|
||||
// The raw data loaded from the BIFF archive needs to be split into faces of identical material.
|
||||
// Reserve enough faces in our faces array
|
||||
for (uint i = 0; i < _rawFaces.size(); i++) {
|
||||
if (_rawFaces[i].materialId >= _faces.size()) {
|
||||
_faces.resize(_rawFaces[i].materialId + 1);
|
||||
}
|
||||
_faces[_rawFaces[i].materialId].materialId = _rawFaces[i].materialId;
|
||||
}
|
||||
|
||||
// The raw data loaded from the BIFF archive is multi-indexed, which is not simple to use to draw.
|
||||
// Here, we reindex the data so that each vertex owns all of its related attributes, hence requiring
|
||||
// a single index list.
|
||||
Common::HashMap<VertexKey, uint32, VertexKey::Hash, VertexKey::EqualTo> vertexIndexMap;
|
||||
for (uint i = 0; i < _rawFaces.size(); i++) {
|
||||
for (uint j = 0; j < 3; j++) {
|
||||
VertexKey vertexKey(_rawFaces[i].vertexIndex[j], _rawFaces[i].normalIndex[j], _rawFaces[i].textureVertexIndex[j]);
|
||||
if (!vertexIndexMap.contains(vertexKey)) {
|
||||
BiffMesh::Vertex vertex;
|
||||
vertex.position = _rawVertices[_rawFaces[i].vertexIndex[j]].position;
|
||||
vertex.normal = _rawNormals[_rawFaces[i].normalIndex[j]];
|
||||
vertex.texturePosition = _rawTexturePositions[_rawFaces[i].textureVertexIndex[j]];
|
||||
|
||||
_vertices.push_back(vertex);
|
||||
|
||||
vertexIndexMap.setVal(vertexKey, _vertices.size() - 1);
|
||||
}
|
||||
|
||||
uint32 vertexIndex = vertexIndexMap.getVal(vertexKey);
|
||||
|
||||
// Add the index to a face according to its material
|
||||
_faces[_rawFaces[i].materialId].vertexIndices.push_back(vertexIndex);
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the raw data
|
||||
_rawVertices.clear();
|
||||
_rawNormals.clear();
|
||||
_rawTexturePositions.clear();
|
||||
_rawFaces.clear();
|
||||
}
|
||||
|
||||
Math::Matrix4 getTransform(uint keyframeIndex) const {
|
||||
const KeyFrame &keyframe = _keyFrames[keyframeIndex];
|
||||
|
||||
Math::Matrix4 translation;
|
||||
translation.setPosition(keyframe.translation);
|
||||
|
||||
Math::Matrix4 essentialRotation = keyframe.essentialRotation.toMatrix();
|
||||
|
||||
Math::Matrix4 determinant;
|
||||
determinant.setValue(0, 0, keyframe.determinant);
|
||||
determinant.setValue(1, 1, keyframe.determinant);
|
||||
determinant.setValue(2, 2, keyframe.determinant);
|
||||
|
||||
Math::Matrix4 stretchRotation = keyframe.stretchRotation.toMatrix();
|
||||
|
||||
Math::Matrix4 stretchRotationTransposed = stretchRotation;
|
||||
stretchRotationTransposed.transpose();
|
||||
|
||||
Math::Matrix4 scale;
|
||||
scale.setValue(0, 0, keyframe.scale.x());
|
||||
scale.setValue(1, 1, keyframe.scale.y());
|
||||
scale.setValue(2, 2, keyframe.scale.z());
|
||||
|
||||
return translation * essentialRotation * determinant * stretchRotationTransposed * scale * stretchRotation;
|
||||
}
|
||||
|
||||
const Common::Array<BiffMesh::Vertex> &getVertices() const {
|
||||
return _vertices;
|
||||
}
|
||||
|
||||
const Common::Array<Face> &getFaces() const {
|
||||
return _faces;
|
||||
}
|
||||
|
||||
private:
|
||||
struct VertexKey {
|
||||
uint32 _vertexIndex;
|
||||
uint32 _normalIndex;
|
||||
uint32 _textureVertexIndex;
|
||||
|
||||
VertexKey(uint32 vertexIndex, uint32 normalIndex, uint32 textureVertexIndex) {
|
||||
_vertexIndex = vertexIndex;
|
||||
_normalIndex = normalIndex;
|
||||
_textureVertexIndex = textureVertexIndex;
|
||||
}
|
||||
|
||||
struct Hash {
|
||||
uint operator() (const VertexKey &x) const {
|
||||
return x._vertexIndex + x._normalIndex + x._textureVertexIndex;
|
||||
}
|
||||
};
|
||||
|
||||
struct EqualTo {
|
||||
bool operator() (const VertexKey &x, const VertexKey &y) const {
|
||||
return x._vertexIndex == y._vertexIndex &&
|
||||
x._normalIndex == y._normalIndex &&
|
||||
x._textureVertexIndex == y._textureVertexIndex;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
Common::String _name;
|
||||
|
||||
Common::Array<KeyFrame> _keyFrames;
|
||||
|
||||
Common::Array<Vertex> _rawVertices;
|
||||
Common::Array<RawFace> _rawFaces;
|
||||
Common::Array<Math::Vector3d> _rawNormals;
|
||||
Common::Array<Math::Vector3d> _rawTexturePositions;
|
||||
|
||||
Common::Array<BiffMesh::Vertex> _vertices;
|
||||
Common::Array<Face> _faces;
|
||||
|
||||
bool _hasPhysics;
|
||||
};
|
||||
|
||||
class MeshObjectMaterial : public BiffObject {
|
||||
public:
|
||||
static const uint32 TYPE = kMeshObjectMaterial;
|
||||
|
||||
MeshObjectMaterial() :
|
||||
BiffObject(),
|
||||
_shading(0),
|
||||
_shininess(0),
|
||||
_opacity(1),
|
||||
_doubleSided(false),
|
||||
_textureTiling(0),
|
||||
_alphaTiling(0),
|
||||
_environementTiling(0),
|
||||
_isColorKey(false),
|
||||
_colorKey(0) {
|
||||
_type = TYPE;
|
||||
}
|
||||
|
||||
// BiffObject API
|
||||
void readData(ArchiveReadStream *stream, uint32 dataLength) override {
|
||||
_name = stream->readString16();
|
||||
_texture = stream->readString16();
|
||||
_alpha = stream->readString16();
|
||||
_environment = stream->readString16();
|
||||
|
||||
_shading = stream->readUint32LE();
|
||||
_ambiant = stream->readVector3();
|
||||
_diffuse = stream->readVector3();
|
||||
_specular = stream->readVector3();
|
||||
|
||||
_shininess = stream->readFloatLE();
|
||||
_opacity = stream->readFloatLE();
|
||||
|
||||
_doubleSided = stream->readByte();
|
||||
_textureTiling = stream->readUint32LE();
|
||||
_alphaTiling = stream->readUint32LE();
|
||||
_environementTiling = stream->readUint32LE();
|
||||
|
||||
_isColorKey = stream->readByte();
|
||||
_colorKey = stream->readUint32LE();
|
||||
|
||||
uint32 attributeCount = stream->readUint32LE();
|
||||
assert(attributeCount == 0); // Reading the attributes is not implemented
|
||||
}
|
||||
|
||||
Material toMaterial() const {
|
||||
Material material;
|
||||
material.name = _name;
|
||||
material.texture = _texture;
|
||||
material.r = _diffuse.x();
|
||||
material.g = _diffuse.y();
|
||||
material.b = _diffuse.z();
|
||||
material.doubleSided = _doubleSided;
|
||||
|
||||
return material;
|
||||
}
|
||||
|
||||
private:
|
||||
Common::String _name;
|
||||
Common::String _texture;
|
||||
Common::String _alpha;
|
||||
Common::String _environment;
|
||||
|
||||
uint32 _shading;
|
||||
Math::Vector3d _ambiant;
|
||||
Math::Vector3d _diffuse;
|
||||
Math::Vector3d _specular;
|
||||
|
||||
float _shininess;
|
||||
float _opacity;
|
||||
|
||||
bool _doubleSided;
|
||||
uint32 _textureTiling;
|
||||
uint32 _alphaTiling;
|
||||
uint32 _environementTiling;
|
||||
|
||||
bool _isColorKey;
|
||||
uint32 _colorKey;
|
||||
};
|
||||
|
||||
BiffMesh *BiffMeshReader::read(ArchiveReadStream *stream) {
|
||||
BiffArchive archive = BiffArchive(stream, &biffObjectBuilder);
|
||||
Common::Array<MeshObjectTri *> tris = archive.listObjectsRecursive<MeshObjectTri>();
|
||||
Common::Array<MeshObjectMaterial *> materialObjects = archive.listObjectsRecursive<MeshObjectMaterial>();
|
||||
|
||||
if (tris.size() != 1) {
|
||||
error("Unexpected tri count in BIFF archive: '%d'", tris.size());
|
||||
}
|
||||
|
||||
tris[0]->reindex();
|
||||
|
||||
Common::Array<Material> materials;
|
||||
for (uint i = 0; i < materialObjects.size(); i++) {
|
||||
materials.push_back(materialObjects[i]->toMaterial());
|
||||
}
|
||||
|
||||
BiffMesh *mesh = new BiffMesh(tris[0]->getVertices(), tris[0]->getFaces(), materials);
|
||||
mesh->setTransform(tris[0]->getTransform(0));
|
||||
return mesh;
|
||||
}
|
||||
|
||||
BiffObject *BiffMeshReader::biffObjectBuilder(uint32 type) {
|
||||
switch (type) {
|
||||
case kMeshObjectSceneData:
|
||||
return new MeshObjectSceneData();
|
||||
case kMeshObjectBase:
|
||||
return new MeshObjectBase();
|
||||
case kMeshObjectTri:
|
||||
return new MeshObjectTri();
|
||||
case kMeshObjectMaterial:
|
||||
return new MeshObjectMaterial();
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
BiffMesh::BiffMesh(const Common::Array<Vertex> &vertices, const Common::Array<Face> &faces,
|
||||
const Common::Array<Material> &materials) :
|
||||
_vertices(vertices),
|
||||
_faces(faces),
|
||||
_materials(materials) {
|
||||
}
|
||||
|
||||
const Common::Array<BiffMesh::Vertex> &BiffMesh::getVertices() const {
|
||||
return _vertices;
|
||||
}
|
||||
|
||||
const Common::Array<Face> &BiffMesh::getFaces() const {
|
||||
return _faces;
|
||||
}
|
||||
|
||||
const Common::Array<Material> &BiffMesh::getMaterials() const {
|
||||
return _materials;
|
||||
}
|
||||
|
||||
void BiffMesh::setTransform(const Math::Matrix4 &transform) {
|
||||
_transform = transform;
|
||||
}
|
||||
|
||||
Math::Matrix4 BiffMesh::getTransform() const {
|
||||
return _transform;
|
||||
}
|
||||
|
||||
} // End of namespace Formats
|
||||
} // End of namespace Stark
|
||||
87
engines/stark/formats/biffmesh.h
Normal file
87
engines/stark/formats/biffmesh.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/* 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 STARK_FORMATS_BIFF_MESH_H
|
||||
#define STARK_FORMATS_BIFF_MESH_H
|
||||
|
||||
#include "engines/stark/model/model.h"
|
||||
|
||||
#include "common/array.h"
|
||||
|
||||
#include "math/matrix4.h"
|
||||
#include "math/vector3d.h"
|
||||
|
||||
namespace Stark {
|
||||
|
||||
class ArchiveReadStream;
|
||||
|
||||
namespace Formats {
|
||||
|
||||
class BiffObject;
|
||||
class BiffMesh;
|
||||
|
||||
/**
|
||||
* A mesh reader
|
||||
*
|
||||
* Reads a mesh out of a BIFF archive
|
||||
*/
|
||||
class BiffMeshReader {
|
||||
public:
|
||||
/** Read a mesh from a BIFF archive stream */
|
||||
static BiffMesh *read(ArchiveReadStream *stream);
|
||||
|
||||
private:
|
||||
static BiffObject *biffObjectBuilder(uint32 type);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* A mesh read out of a BIFF archive
|
||||
*/
|
||||
class BiffMesh {
|
||||
public:
|
||||
struct Vertex {
|
||||
Math::Vector3d position;
|
||||
Math::Vector3d normal;
|
||||
Math::Vector3d texturePosition;
|
||||
};
|
||||
|
||||
BiffMesh(const Common::Array<Vertex> &vertices, const Common::Array<Face> &faces, const Common::Array<Material> &materials);
|
||||
|
||||
const Common::Array<Vertex> &getVertices() const;
|
||||
const Common::Array<Face> &getFaces() const;
|
||||
const Common::Array<Material> &getMaterials() const;
|
||||
Math::Matrix4 getTransform() const;
|
||||
|
||||
void setTransform(const Math::Matrix4 &transform);
|
||||
|
||||
private:
|
||||
Common::Array<Vertex> _vertices;
|
||||
Common::Array<Face> _faces;
|
||||
Common::Array<Material> _materials;
|
||||
|
||||
Math::Matrix4 _transform;
|
||||
};
|
||||
|
||||
} // End of namespace Formats
|
||||
} // End of namespace Stark
|
||||
|
||||
#endif // STARK_FORMATS_BIFF_MESH_H
|
||||
190
engines/stark/formats/dds.cpp
Normal file
190
engines/stark/formats/dds.cpp
Normal file
@@ -0,0 +1,190 @@
|
||||
/* 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 "engines/stark/formats/dds.h"
|
||||
|
||||
#include "common/textconsole.h"
|
||||
|
||||
namespace Stark {
|
||||
namespace Formats {
|
||||
|
||||
// Based on xoreos' DDS code
|
||||
|
||||
static const uint32 kDDSID = MKTAG('D', 'D', 'S', ' ');
|
||||
|
||||
static const uint32 kHeaderFlagsHasMipMaps = 0x00020000;
|
||||
|
||||
static const uint32 kPixelFlagsHasAlpha = 0x00000001;
|
||||
static const uint32 kPixelFlagsHasFourCC = 0x00000004;
|
||||
static const uint32 kPixelFlagsIsIndexed = 0x00000020;
|
||||
static const uint32 kPixelFlagsIsRGB = 0x00000040;
|
||||
|
||||
DDS::~DDS() {
|
||||
for (uint i = 0; i < _mipmaps.size(); i++) {
|
||||
_mipmaps[i].free();
|
||||
}
|
||||
}
|
||||
|
||||
bool DDS::load(Common::SeekableReadStream &dds, const Common::String &name) {
|
||||
assert(_mipmaps.empty());
|
||||
|
||||
_name = name;
|
||||
|
||||
if (!readHeader(dds)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return readData(dds);
|
||||
}
|
||||
|
||||
const DDS::MipMaps &DDS::getMipMaps() const {
|
||||
return _mipmaps;
|
||||
}
|
||||
|
||||
bool DDS::readHeader(Common::SeekableReadStream &dds) {
|
||||
// We found the FourCC of a standard DDS
|
||||
uint32 magic = dds.readUint32BE();
|
||||
if (magic != kDDSID) {
|
||||
warning("Invalid DDS magic number: %d for %s", magic, _name.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// All DDS header should be 124 bytes (+ 4 for the FourCC)
|
||||
uint32 headerSize = dds.readUint32LE();
|
||||
if (headerSize != 124) {
|
||||
warning("Invalid DDS header size: %d for %s", headerSize, _name.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// DDS features
|
||||
uint32 flags = dds.readUint32LE();
|
||||
|
||||
// Image dimensions
|
||||
uint32 height = dds.readUint32LE();
|
||||
uint32 width = dds.readUint32LE();
|
||||
|
||||
if ((width >= 0x8000) || (height >= 0x8000)) {
|
||||
warning("Unsupported DDS image dimensions (%ux%u) for %s", width, height, _name.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
dds.skip(4 + 4); // Pitch + Depth
|
||||
//uint32 pitchOrLineSize = dds.readUint32LE();
|
||||
//uint32 depth = dds.readUint32LE();
|
||||
uint32 mipMapCount = dds.readUint32LE();
|
||||
|
||||
// DDS doesn't provide any mip maps, only one full-size image
|
||||
if ((flags & kHeaderFlagsHasMipMaps) == 0) {
|
||||
mipMapCount = 1;
|
||||
}
|
||||
|
||||
dds.skip(44); // Reserved
|
||||
|
||||
// Read the pixel data format
|
||||
DDSPixelFormat format;
|
||||
format.size = dds.readUint32LE();
|
||||
format.flags = dds.readUint32LE();
|
||||
format.fourCC = dds.readUint32BE();
|
||||
format.bitCount = dds.readUint32LE();
|
||||
format.rBitMask = dds.readUint32LE();
|
||||
format.gBitMask = dds.readUint32LE();
|
||||
format.bBitMask = dds.readUint32LE();
|
||||
format.aBitMask = dds.readUint32LE();
|
||||
|
||||
// Detect which specific format it describes
|
||||
if (!detectFormat(format)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
dds.skip(16 + 4); // DDCAPS2 + Reserved
|
||||
|
||||
_mipmaps.resize(mipMapCount);
|
||||
for (uint32 i = 0; i < mipMapCount; i++) {
|
||||
_mipmaps[i].create(width, height, _format);
|
||||
|
||||
width >>= 1;
|
||||
height >>= 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DDS::readData(Common::SeekableReadStream &dds) {
|
||||
for (uint i = 0; i < _mipmaps.size(); i++) {
|
||||
Graphics::Surface &mipmap = _mipmaps[i];
|
||||
|
||||
uint32 size = mipmap.pitch * mipmap.h;
|
||||
uint32 readSize = dds.read(mipmap.getPixels(), size);
|
||||
|
||||
if (readSize != size) {
|
||||
warning("Inconsistent read size in DDS file: %d, expected %d for %s level %d",
|
||||
readSize, size, _name.c_str(), i);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DDS::detectFormat(const DDSPixelFormat &format) {
|
||||
if (format.flags & kPixelFlagsHasFourCC) {
|
||||
warning("Unsupported DDS feature: FourCC pixel format %d for %s", format.fourCC, _name.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (format.flags & kPixelFlagsIsIndexed) {
|
||||
warning("Unsupported DDS feature: Indexed %d-bits pixel format for %s", format.bitCount, _name.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(format.flags & kPixelFlagsIsRGB)) {
|
||||
warning("Only RGB DDS files are supported for %s", _name.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (format.bitCount != 24 && format.bitCount != 32) {
|
||||
warning("Only 24-bits and 32-bits DDS files are supported for %s", _name.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((format.flags & kPixelFlagsHasAlpha) &&
|
||||
(format.bitCount == 32) &&
|
||||
(format.rBitMask == 0x00FF0000) && (format.gBitMask == 0x0000FF00) &&
|
||||
(format.bBitMask == 0x000000FF) && (format.aBitMask == 0xFF000000)) {
|
||||
_format = Graphics::PixelFormat::createFormatBGRA32();
|
||||
return true;
|
||||
} else if (!(format.flags & kPixelFlagsHasAlpha) &&
|
||||
(format.bitCount == 24) &&
|
||||
(format.rBitMask == 0x00FF0000) && (format.gBitMask == 0x0000FF00) &&
|
||||
(format.bBitMask == 0x000000FF)) {
|
||||
_format = Graphics::PixelFormat::createFormatBGR24();
|
||||
return true;
|
||||
} else {
|
||||
warning("Unsupported pixel format (%X, %X, %d, %X, %X, %X, %X) for %s",
|
||||
format.flags, format.fourCC, format.bitCount,
|
||||
format.rBitMask, format.gBitMask, format.bBitMask, format.aBitMask,
|
||||
_name.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Formats
|
||||
} // End of namespace Stark
|
||||
100
engines/stark/formats/dds.h
Normal file
100
engines/stark/formats/dds.h
Normal file
@@ -0,0 +1,100 @@
|
||||
/* 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 STARK_FORMATS_DDS_H
|
||||
#define STARK_FORMATS_DDS_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/stream.h"
|
||||
#include "graphics/surface.h"
|
||||
|
||||
namespace Stark {
|
||||
namespace Formats {
|
||||
|
||||
// Based on xoreos' DDS code
|
||||
|
||||
/**
|
||||
* DDS texture
|
||||
*
|
||||
* Only a very small subset of DDS features are supported. Especially,
|
||||
* compressed formats are not supported. This class is meant to
|
||||
* load a single DDS file per instance.
|
||||
*/
|
||||
class DDS {
|
||||
public:
|
||||
~DDS();
|
||||
|
||||
typedef Common::Array<Graphics::Surface> MipMaps;
|
||||
|
||||
/** Load a DDS texture from a stream */
|
||||
bool load(Common::SeekableReadStream &dds, const Common::String &name);
|
||||
|
||||
/**
|
||||
* Retrieve the mip map levels for a loaded texture
|
||||
*
|
||||
* The first mipmap is the full size image. Each further
|
||||
* mipmap divides by two the with and the height of the
|
||||
* previous one.
|
||||
*/
|
||||
const MipMaps &getMipMaps() const;
|
||||
|
||||
private:
|
||||
/** The specific pixel format of the included image data. */
|
||||
struct DDSPixelFormat {
|
||||
/** The size of the image data in bytes */
|
||||
uint32 size;
|
||||
|
||||
/** Features of the image data */
|
||||
uint32 flags;
|
||||
|
||||
/** The FourCC to detect the format by */
|
||||
uint32 fourCC;
|
||||
|
||||
/** Number of bits per pixel */
|
||||
uint32 bitCount;
|
||||
|
||||
/** Bit mask for the red color component */
|
||||
uint32 rBitMask;
|
||||
|
||||
/** Bit mask for the green color component */
|
||||
uint32 gBitMask;
|
||||
|
||||
/** Bit mask for the blue color component */
|
||||
uint32 bBitMask;
|
||||
|
||||
/** Bit mask for the alpha component */
|
||||
uint32 aBitMask;
|
||||
};
|
||||
|
||||
bool readHeader(Common::SeekableReadStream &dds);
|
||||
bool readData(Common::SeekableReadStream &dds);
|
||||
|
||||
bool detectFormat(const DDSPixelFormat &format);
|
||||
|
||||
MipMaps _mipmaps;
|
||||
Graphics::PixelFormat _format;
|
||||
Common::String _name;
|
||||
};
|
||||
|
||||
} // End of namespace Formats
|
||||
} // End of namespace Stark
|
||||
|
||||
#endif // STARK_FORMATS_DDS_H
|
||||
154
engines/stark/formats/iss.cpp
Normal file
154
engines/stark/formats/iss.cpp
Normal file
@@ -0,0 +1,154 @@
|
||||
/* 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 "engines/stark/formats/iss.h"
|
||||
|
||||
#include "audio/decoders/adpcm_intern.h"
|
||||
#include "audio/decoders/raw.h"
|
||||
#include "common/substream.h"
|
||||
|
||||
namespace Stark {
|
||||
namespace Formats {
|
||||
|
||||
/**
|
||||
* ADPCM decoder for the .iss files
|
||||
*/
|
||||
class ISSADPCMStream : public Audio::Ima_ADPCMStream {
|
||||
public:
|
||||
ISSADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
|
||||
: Ima_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {}
|
||||
|
||||
protected:
|
||||
int readBuffer(int16 *buffer, const int numSamples) override {
|
||||
// Similar to MS IMA, but without the four-bytes-per-channel requirement
|
||||
int samples;
|
||||
|
||||
assert(numSamples % 2 == 0);
|
||||
|
||||
for (samples = 0; samples < numSamples && !endOfData(); samples += 2) {
|
||||
if (_blockPos[0] == _blockAlign) {
|
||||
// read block header
|
||||
for (byte i = 0; i < _channels; i++) {
|
||||
_status.ima_ch[i].last = _stream->readSint16LE();
|
||||
_status.ima_ch[i].stepIndex = _stream->readSint16LE();
|
||||
}
|
||||
_blockPos[0] = 4 * _channels;
|
||||
}
|
||||
|
||||
byte data = _stream->readByte();
|
||||
buffer[samples + (isStereo() ? 1 : 0)] = decodeIMA(data & 0x0f, isStereo() ? 1 : 0);
|
||||
buffer[samples + (isStereo() ? 0 : 1)] = decodeIMA((data >> 4) & 0x0f);
|
||||
_blockPos[0]++;
|
||||
}
|
||||
|
||||
return samples;
|
||||
}
|
||||
};
|
||||
|
||||
static void skipString(Common::SeekableReadStream *stream) {
|
||||
// Skip until the next space. Note that this will read past \0
|
||||
// characters as well. That's not a bug.
|
||||
byte ch;
|
||||
while ((ch = stream->readByte()) != 0x20)
|
||||
;
|
||||
}
|
||||
|
||||
static Common::String readString(Common::SeekableReadStream *stream) {
|
||||
Common::String ret = "";
|
||||
byte ch;
|
||||
while ((ch = stream->readByte()) != 0x20)
|
||||
ret += ch;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Audio::RewindableAudioStream *makeISSStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse) {
|
||||
Common::String codec;
|
||||
uint16 blockSize, channels, freq = 44100;
|
||||
uint32 size;
|
||||
byte flags;
|
||||
|
||||
codec = readString(stream);
|
||||
|
||||
if (codec.equals("IMA_ADPCM_Sound")) {
|
||||
|
||||
codec = readString(stream);
|
||||
blockSize = (uint16)strtol(codec.c_str(), 0, 10);
|
||||
|
||||
skipString(stream);
|
||||
// name ?
|
||||
|
||||
skipString(stream);
|
||||
// ?
|
||||
|
||||
codec = readString(stream);
|
||||
channels = (uint16)strtol(codec.c_str(), 0, 10) + 1;
|
||||
|
||||
skipString(stream);
|
||||
// ?
|
||||
|
||||
codec = readString(stream);
|
||||
int val = strtol(codec.c_str(), 0, 10);
|
||||
if (val)
|
||||
freq /= val;
|
||||
|
||||
skipString(stream);
|
||||
|
||||
skipString(stream);
|
||||
|
||||
codec = readString(stream);
|
||||
size = (uint32)strtol(codec.c_str(), 0, 10);
|
||||
|
||||
return new ISSADPCMStream(stream, DisposeAfterUse::YES, size, freq, channels, blockSize);
|
||||
} else if (codec.equals("Sound")) {
|
||||
|
||||
skipString(stream);
|
||||
// name ?
|
||||
|
||||
codec = readString(stream);
|
||||
// sample count ?
|
||||
|
||||
codec = readString(stream);
|
||||
channels = (uint16)strtol(codec.c_str(), 0, 10) + 1;
|
||||
|
||||
skipString(stream);
|
||||
// ?
|
||||
|
||||
codec = readString(stream);
|
||||
int val = strtol(codec.c_str(), 0, 10);
|
||||
if (val)
|
||||
freq /= val;
|
||||
|
||||
skipString(stream);
|
||||
|
||||
skipString(stream);
|
||||
|
||||
flags = Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN;
|
||||
if (channels == 2)
|
||||
flags |= Audio::FLAG_STEREO;
|
||||
return Audio::makeRawStream(new Common::SeekableSubReadStream(stream, stream->pos(), stream->size(), DisposeAfterUse::YES), freq, flags, DisposeAfterUse::YES);
|
||||
} else {
|
||||
error("Unknown ISS codec '%s'", codec.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Formats
|
||||
} // End of namespace Stark
|
||||
45
engines/stark/formats/iss.h
Normal file
45
engines/stark/formats/iss.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/* 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 STARK_ISS_H
|
||||
#define STARK_ISS_H
|
||||
|
||||
#include "common/stream.h"
|
||||
|
||||
#include "audio/audiostream.h"
|
||||
|
||||
namespace Stark {
|
||||
namespace Formats {
|
||||
|
||||
/**
|
||||
* Create a new RewindableAudioStream from the ISS data in the given stream.
|
||||
* ISS is the file format used by the 4 CD version of the game.
|
||||
*
|
||||
* @param stream the SeekableReadStream from which to read the ISS data
|
||||
* @param disposeAfterUse whether to delete the stream after use
|
||||
* @return a new RewindableAudioStream, or NULL, if an error occurred
|
||||
*/
|
||||
Audio::RewindableAudioStream *makeISSStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse);
|
||||
|
||||
} // End of namespace Formats
|
||||
} // End of namespace Stark
|
||||
|
||||
#endif // STARK_ISS_H
|
||||
155
engines/stark/formats/tm.cpp
Normal file
155
engines/stark/formats/tm.cpp
Normal file
@@ -0,0 +1,155 @@
|
||||
/* 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 "engines/stark/formats/tm.h"
|
||||
|
||||
#include "engines/stark/gfx/driver.h"
|
||||
#include "engines/stark/gfx/texture.h"
|
||||
|
||||
#include "engines/stark/formats/biff.h"
|
||||
|
||||
#include "engines/stark/services/archiveloader.h"
|
||||
#include "engines/stark/services/services.h"
|
||||
|
||||
namespace Stark {
|
||||
namespace Formats {
|
||||
|
||||
class TextureGroup : public BiffObject {
|
||||
public:
|
||||
static const uint32 TYPE = kTextureSetGroup;
|
||||
|
||||
TextureGroup() :
|
||||
BiffObject(),
|
||||
_palette(nullptr) {
|
||||
_type = TYPE;
|
||||
}
|
||||
|
||||
~TextureGroup() override {
|
||||
delete[] _palette;
|
||||
}
|
||||
|
||||
const byte *getPalette() {
|
||||
return _palette;
|
||||
}
|
||||
|
||||
// BiffObject API
|
||||
void readData(ArchiveReadStream *stream, uint32 dataLength) override {
|
||||
int entries = stream->readUint32LE();
|
||||
_palette = new byte[entries * 3];
|
||||
|
||||
byte *ptr = _palette;
|
||||
for (int i = 0; i < entries; ++i) {
|
||||
*ptr++ = (byte) stream->readUint16LE();
|
||||
*ptr++ = (byte) stream->readUint16LE();
|
||||
*ptr++ = (byte) stream->readUint16LE();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
byte *_palette;
|
||||
};
|
||||
|
||||
Texture::Texture() :
|
||||
BiffObject(),
|
||||
_texture(nullptr),
|
||||
_u(0) {
|
||||
_type = TYPE;
|
||||
}
|
||||
|
||||
Texture::~Texture() {
|
||||
_surface.free();
|
||||
delete _texture;
|
||||
}
|
||||
|
||||
void Texture::readData(ArchiveReadStream *stream, uint32 dataLength) {
|
||||
TextureGroup *textureGroup = static_cast<TextureGroup *>(_parent);
|
||||
|
||||
_name = stream->readString16();
|
||||
_u = stream->readByte();
|
||||
|
||||
uint32 w = stream->readUint32LE();
|
||||
uint32 h = stream->readUint32LE();
|
||||
uint32 levels = stream->readUint32LE();
|
||||
|
||||
_texture = StarkGfx->createTexture();
|
||||
_texture->setLevelCount(levels);
|
||||
|
||||
for (uint32 i = 0; i < levels; ++i) {
|
||||
// Read the pixel data to a surface
|
||||
Graphics::Surface level;
|
||||
Graphics::Surface *surface = i == 0 ? &_surface : &level;
|
||||
|
||||
surface->create(w, h, Graphics::PixelFormat::createFormatCLUT8());
|
||||
stream->read(surface->getPixels(), surface->w * surface->h);
|
||||
|
||||
// Add the mipmap level to the texture
|
||||
_texture->addLevel(i, surface, textureGroup->getPalette());
|
||||
|
||||
level.free();
|
||||
|
||||
w /= 2;
|
||||
h /= 2;
|
||||
}
|
||||
}
|
||||
|
||||
Gfx::Texture *Texture::acquireTexturePointer() {
|
||||
Gfx::Texture *texture = _texture;
|
||||
_texture = nullptr;
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
Graphics::Surface *Texture::getSurface() const {
|
||||
TextureGroup *textureGroup = static_cast<TextureGroup *>(_parent);
|
||||
|
||||
return _surface.convertTo(Gfx::Driver::getRGBAPixelFormat(), textureGroup->getPalette());
|
||||
}
|
||||
|
||||
Gfx::TextureSet *TextureSetReader::read(ArchiveReadStream *stream) {
|
||||
BiffArchive archive = BiffArchive(stream, &biffObjectBuilder);
|
||||
|
||||
Common::Array<Texture *> textures = archive.listObjectsRecursive<Texture>();
|
||||
|
||||
Gfx::TextureSet *textureSet = new Gfx::TextureSet();
|
||||
for (uint i = 0; i < textures.size(); i++) {
|
||||
textureSet->addTexture(textures[i]->getName(), textures[i]->acquireTexturePointer());
|
||||
}
|
||||
|
||||
return textureSet;
|
||||
}
|
||||
|
||||
BiffArchive *TextureSetReader::readArchive(ArchiveReadStream *stream) {
|
||||
return new BiffArchive(stream, &biffObjectBuilder);
|
||||
}
|
||||
|
||||
BiffObject *TextureSetReader::biffObjectBuilder(uint32 type) {
|
||||
switch (type) {
|
||||
case kTextureSetGroup:
|
||||
return new TextureGroup();
|
||||
case kTextureSetTexture:
|
||||
return new Texture();
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Formats
|
||||
} // End of namespace Stark
|
||||
107
engines/stark/formats/tm.h
Normal file
107
engines/stark/formats/tm.h
Normal file
@@ -0,0 +1,107 @@
|
||||
/* 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 STARK_FORMATS_TM_H
|
||||
#define STARK_FORMATS_TM_H
|
||||
|
||||
#include "engines/stark/formats/biff.h"
|
||||
|
||||
#include "common/str.h"
|
||||
#include "graphics/surface.h"
|
||||
|
||||
namespace Stark {
|
||||
|
||||
class ArchiveReadStream;
|
||||
|
||||
namespace Gfx {
|
||||
class TextureSet;
|
||||
class Texture;
|
||||
}
|
||||
|
||||
namespace Formats {
|
||||
|
||||
/**
|
||||
* A texture set loader able to read '.tm' files
|
||||
*/
|
||||
class TextureSetReader {
|
||||
public:
|
||||
/**
|
||||
* Load a texture set from the provided stream.
|
||||
*
|
||||
* The caller is responsible for freeing the texture set.
|
||||
*/
|
||||
static Gfx::TextureSet *read(ArchiveReadStream *stream);
|
||||
|
||||
/** Read the texture set archive from the provided stream */
|
||||
static BiffArchive *readArchive(ArchiveReadStream *stream);
|
||||
|
||||
private:
|
||||
static BiffObject *biffObjectBuilder(uint32 type);
|
||||
|
||||
};
|
||||
|
||||
enum TextureSetType {
|
||||
kTextureSetGroup = 0x02faf082,
|
||||
kTextureSetTexture = 0x02faf080
|
||||
};
|
||||
|
||||
/**
|
||||
* A texture contained in a '.tm' texture set archive
|
||||
*
|
||||
* Textures have mipmaps.
|
||||
*/
|
||||
class Texture : public BiffObject {
|
||||
public:
|
||||
static const uint32 TYPE = kTextureSetTexture;
|
||||
|
||||
Texture();
|
||||
~Texture() override;
|
||||
|
||||
Common::String getName() const {
|
||||
return _name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a pointer to a texture ready for rendering
|
||||
*
|
||||
* The caller takes ownership of the texture.
|
||||
* This method can only be called successfully once
|
||||
* per texture. Subsequent calls return a null pointer.
|
||||
*/
|
||||
Gfx::Texture *acquireTexturePointer();
|
||||
|
||||
/** Return a RGBA copy of the pixel data */
|
||||
Graphics::Surface *getSurface() const;
|
||||
|
||||
// BiffObject API
|
||||
void readData(ArchiveReadStream *stream, uint32 dataLength) override;
|
||||
|
||||
private:
|
||||
Common::String _name;
|
||||
Gfx::Texture *_texture;
|
||||
Graphics::Surface _surface;
|
||||
byte _u;
|
||||
};
|
||||
|
||||
} // End of namespace Formats
|
||||
} // End of namespace Stark
|
||||
|
||||
#endif // STARK_FORMATS_TM_H
|
||||
229
engines/stark/formats/xarc.cpp
Normal file
229
engines/stark/formats/xarc.cpp
Normal file
@@ -0,0 +1,229 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
// Based on the Xentax Wiki documentation:
|
||||
// https://web.archive.org/web/20090621212912/http://wiki.xentax.com/index.php?title=The_Longest_Journey_XARC
|
||||
|
||||
#include "engines/stark/formats/xarc.h"
|
||||
#include "engines/stark/debug.h"
|
||||
|
||||
#include "common/debug.h"
|
||||
#include "common/file.h"
|
||||
#include "common/substream.h"
|
||||
|
||||
namespace Stark {
|
||||
namespace Formats {
|
||||
|
||||
// ARCHIVE MEMBER
|
||||
|
||||
class XARCMember : public Common::ArchiveMember {
|
||||
public:
|
||||
XARCMember(const XARCArchive *xarc, Common::ReadStream &stream, uint32 offset);
|
||||
|
||||
Common::SeekableReadStream *createReadStream() const override;
|
||||
Common::SeekableReadStream *createReadStreamForAltStream(Common::AltStreamType altStreamType) const override;
|
||||
Common::String getName() const override { return _name.baseName(); }
|
||||
Common::Path getPathInArchive() const override { return _name; }
|
||||
Common::String getFileName() const override { return _name.baseName(); }
|
||||
uint32 getLength() const { return _length; }
|
||||
uint32 getOffset() const { return _offset; }
|
||||
|
||||
private:
|
||||
const XARCArchive *_xarc;
|
||||
Common::Path _name;
|
||||
uint32 _offset;
|
||||
uint32 _length;
|
||||
|
||||
// Helper function
|
||||
Common::String readString(Common::ReadStream &stream);
|
||||
};
|
||||
|
||||
XARCMember::XARCMember(const XARCArchive *xarc, Common::ReadStream &stream, uint32 offset) {
|
||||
_xarc = xarc;
|
||||
|
||||
// Read the information about this archive member
|
||||
_name = Common::Path(readString(stream));
|
||||
_offset = offset;
|
||||
_length = stream.readUint32LE();
|
||||
debugC(20, kDebugArchive, "Stark::XARC Member: \"%s\" starts at offset=%d and has length=%d", _name.toString().c_str(), _offset, _length);
|
||||
|
||||
// Unknown value. English: 0, others: 1
|
||||
uint32 unknown = stream.readUint32LE();
|
||||
debugC(kDebugUnknown, "Stark::XARC Member: \"%s\" has unknown=%d", _name.toString().c_str(), unknown);
|
||||
if (unknown != 0 && unknown != 1) {
|
||||
warning("Stark::XARC Member: \"%s\" has unknown=%d with unknown meaning", _name.toString().c_str(), unknown);
|
||||
}
|
||||
}
|
||||
|
||||
Common::SeekableReadStream *XARCMember::createReadStream() const {
|
||||
return _xarc->createReadStreamForMember(this);
|
||||
}
|
||||
|
||||
Common::SeekableReadStream *XARCMember::createReadStreamForAltStream(Common::AltStreamType altStreamType) const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Common::String XARCMember::readString(Common::ReadStream &stream) {
|
||||
Common::String str;
|
||||
|
||||
// Read until we find a 0
|
||||
char c = 1;
|
||||
while (c != 0) {
|
||||
c = stream.readByte();
|
||||
if (stream.eos()) {
|
||||
c = 0;
|
||||
}
|
||||
if (c != 0) {
|
||||
str += c;
|
||||
}
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
// ARCHIVE
|
||||
|
||||
bool XARCArchive::open(const Common::Path &filename) {
|
||||
Common::File stream;
|
||||
if (!stream.open(filename)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_filename = filename;
|
||||
|
||||
// Unknown: always 1? version?
|
||||
uint32 unknown = stream.readUint32LE();
|
||||
debugC(kDebugUnknown, "Stark::XARC: \"%s\" has unknown=%d", _filename.toString(Common::Path::kNativeSeparator).c_str(), unknown);
|
||||
if (unknown != 1) {
|
||||
warning("Stark::XARC: \"%s\" has unknown=%d with unknown meaning", _filename.toString(Common::Path::kNativeSeparator).c_str(), unknown);
|
||||
}
|
||||
|
||||
// Read the number of contained files
|
||||
uint32 numFiles = stream.readUint32LE();
|
||||
debugC(20, kDebugArchive, "Stark::XARC: \"%s\" contains %d files", _filename.toString(Common::Path::kNativeSeparator).c_str(), numFiles);
|
||||
|
||||
// Read the offset to the contents of the first file
|
||||
uint32 offset = stream.readUint32LE();
|
||||
debugC(20, kDebugArchive, "Stark::XARC: \"%s\"'s first file has offset=%d", _filename.toString(Common::Path::kNativeSeparator).c_str(), offset);
|
||||
|
||||
for (uint32 i = 0; i < numFiles; i++) {
|
||||
XARCMember *member = new XARCMember(this, stream, offset);
|
||||
_members.push_back(Common::ArchiveMemberPtr(member));
|
||||
|
||||
// Set the offset to the next member
|
||||
offset += member->getLength();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Common::Path XARCArchive::getFilename() const {
|
||||
return _filename;
|
||||
}
|
||||
|
||||
bool XARCArchive::hasFile(const Common::Path &path) const {
|
||||
Common::String name = path.toString();
|
||||
for (Common::ArchiveMemberList::const_iterator it = _members.begin(); it != _members.end(); ++it) {
|
||||
if ((*it)->getName() == name) {
|
||||
// Found it
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Not found
|
||||
return false;
|
||||
}
|
||||
|
||||
int XARCArchive::listMatchingMembers(Common::ArchiveMemberList &list, const Common::Path &pattern, bool matchPathComponents) const {
|
||||
Common::String patternString = pattern.toString();
|
||||
int matches = 0;
|
||||
for (Common::ArchiveMemberList::const_iterator it = _members.begin(); it != _members.end(); ++it) {
|
||||
if ((*it)->getName().matchString(patternString)) {
|
||||
// This file matches, add it
|
||||
list.push_back(*it);
|
||||
matches++;
|
||||
}
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
int XARCArchive::listMembers(Common::ArchiveMemberList &list) const {
|
||||
int files = 0;
|
||||
for (Common::ArchiveMemberList::const_iterator it = _members.begin(); it != _members.end(); ++it) {
|
||||
// Add all the members to the list
|
||||
list.push_back(*it);
|
||||
files++;
|
||||
}
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
const Common::ArchiveMemberPtr XARCArchive::getMember(const Common::Path &path) const {
|
||||
Common::String name = path.toString();
|
||||
for (Common::ArchiveMemberList::const_iterator it = _members.begin(); it != _members.end(); ++it) {
|
||||
if ((*it)->getName() == name) {
|
||||
// Found it
|
||||
return *it;
|
||||
}
|
||||
}
|
||||
|
||||
// Not found, return an empty ptr
|
||||
return Common::ArchiveMemberPtr();
|
||||
}
|
||||
|
||||
Common::SeekableReadStream *XARCArchive::createReadStreamForMember(const Common::Path &path) const {
|
||||
Common::String name = path.toString();
|
||||
for (Common::ArchiveMemberList::const_iterator it = _members.begin(); it != _members.end(); ++it) {
|
||||
if ((*it)->getName() == name) {
|
||||
// Found it
|
||||
return createReadStreamForMember((const XARCMember *)it->get());
|
||||
}
|
||||
}
|
||||
|
||||
// Not found
|
||||
return 0;
|
||||
}
|
||||
|
||||
Common::SeekableReadStream *XARCArchive::createReadStreamForMember(const XARCMember *member) const {
|
||||
// Open the xarc file
|
||||
Common::File *f = new Common::File;
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
if (!f->open(_filename)) {
|
||||
delete f;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Return the substream that contains the archive member
|
||||
uint32 offset = member->getOffset();
|
||||
uint32 length = member->getLength();
|
||||
return new Common::SeekableSubReadStream(f, offset, offset + length, DisposeAfterUse::YES);
|
||||
|
||||
// Different approach: keep the archive open and read full resources to memory
|
||||
//f.seek(member->getOffset());
|
||||
//return f.readStream(member->getLength());
|
||||
}
|
||||
|
||||
} // End of namespace Formats
|
||||
} // End of namespace Stark
|
||||
55
engines/stark/formats/xarc.h
Normal file
55
engines/stark/formats/xarc.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/* 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 STARK_ARCHIVE_H
|
||||
#define STARK_ARCHIVE_H
|
||||
|
||||
#include "common/archive.h"
|
||||
#include "common/stream.h"
|
||||
|
||||
namespace Stark {
|
||||
namespace Formats {
|
||||
|
||||
class XARCMember;
|
||||
|
||||
class XARCArchive : public Common::Archive {
|
||||
public:
|
||||
bool open(const Common::Path &filename);
|
||||
Common::Path getFilename() const;
|
||||
|
||||
// Archive API
|
||||
bool hasFile(const Common::Path &path) const;
|
||||
int listMatchingMembers(Common::ArchiveMemberList &list, const Common::Path &pattern, bool matchPathComponents = false) const;
|
||||
int listMembers(Common::ArchiveMemberList &list) const;
|
||||
const Common::ArchiveMemberPtr getMember(const Common::Path &path) const;
|
||||
Common::SeekableReadStream *createReadStreamForMember(const Common::Path &path) const;
|
||||
|
||||
Common::SeekableReadStream *createReadStreamForMember(const XARCMember *member) const;
|
||||
|
||||
private:
|
||||
Common::Path _filename;
|
||||
Common::ArchiveMemberList _members;
|
||||
};
|
||||
|
||||
} // End of namespace Formats
|
||||
} // End of namespace Stark
|
||||
|
||||
#endif // STARK_ARCHIVE_H
|
||||
248
engines/stark/formats/xmg.cpp
Normal file
248
engines/stark/formats/xmg.cpp
Normal file
@@ -0,0 +1,248 @@
|
||||
/* 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 "engines/stark/formats/xmg.h"
|
||||
#include "engines/stark/debug.h"
|
||||
#include "engines/stark/gfx/driver.h"
|
||||
|
||||
#include "graphics/conversion.h"
|
||||
#include "graphics/pixelformat.h"
|
||||
#include "graphics/surface.h"
|
||||
#include "common/stream.h"
|
||||
#include "common/textconsole.h"
|
||||
|
||||
namespace Stark {
|
||||
namespace Formats {
|
||||
|
||||
XMGDecoder::XMGDecoder(Common::ReadStream *stream) :
|
||||
_width(0),
|
||||
_height(0),
|
||||
_currX(0),
|
||||
_currY(0),
|
||||
_stream(stream),
|
||||
_transColor(0) {
|
||||
}
|
||||
|
||||
Graphics::Surface *XMGDecoder::decode(Common::ReadStream *stream) {
|
||||
XMGDecoder dec(stream);
|
||||
dec.readHeader();
|
||||
return dec.decodeImage();
|
||||
}
|
||||
|
||||
void XMGDecoder::readSize(Common::ReadStream *stream, uint &width, uint &height) {
|
||||
XMGDecoder dec(stream);
|
||||
dec.readHeader();
|
||||
|
||||
width = dec._width;
|
||||
height = dec._height;
|
||||
}
|
||||
|
||||
void XMGDecoder::readHeader() {
|
||||
// Read the file version
|
||||
uint32 version = _stream->readUint32LE();
|
||||
if (version != 3) {
|
||||
error("Stark::XMG: File version unknown: %d", version);
|
||||
}
|
||||
|
||||
// Read the transparency color (RGBA)
|
||||
_transColor = _stream->readUint32LE();
|
||||
|
||||
// Read the image size
|
||||
_width = _stream->readUint32LE();
|
||||
_height = _stream->readUint32LE();
|
||||
debugC(10, kDebugXMG, "Stark::XMG: Version=%d, TransparencyColor=0x%08x, size=%dx%d", version, _transColor, _width, _height);
|
||||
|
||||
// Read the scan length
|
||||
uint32 scanLen = _stream->readUint32LE();
|
||||
if (scanLen != 3 * _width) {
|
||||
error("Stark::XMG: The scan length (%d) doesn't match the width bytes (%d)", scanLen, 3 * _width);
|
||||
}
|
||||
|
||||
// Unknown
|
||||
uint32 unknown2 = _stream->readUint32LE();
|
||||
debugC(kDebugUnknown, "Stark::XMG: unknown2 = %08x = %d", unknown2, unknown2);
|
||||
uint32 unknown3 = _stream->readUint32LE();
|
||||
debugC(kDebugUnknown, "Stark::XMG: unknown3 = %08x = %d", unknown3, unknown3);
|
||||
}
|
||||
|
||||
Graphics::Surface *XMGDecoder::decodeImage() {
|
||||
// Create the destination surface
|
||||
Graphics::Surface *surface = new Graphics::Surface();
|
||||
surface->create(_width, _height, Gfx::Driver::getRGBAPixelFormat());
|
||||
|
||||
_currX = 0, _currY = 0;
|
||||
while (!_stream->eos()) {
|
||||
if (_currX >= _width) {
|
||||
assert(_currX == _width);
|
||||
_currX = 0;
|
||||
_currY += 2;
|
||||
if (_currY >= _height)
|
||||
break;
|
||||
}
|
||||
|
||||
// Read the number and mode of the tiles
|
||||
byte op = _stream->readByte();
|
||||
uint16 count;
|
||||
if ((op & 0xC0) != 0xC0) {
|
||||
count = op & 0x3F;
|
||||
} else {
|
||||
count = ((op & 0xF) << 8) + _stream->readByte();
|
||||
op <<= 2;
|
||||
}
|
||||
op &= 0xC0;
|
||||
|
||||
// Process the current serie
|
||||
for (int i = 0; i < count; i++) {
|
||||
Block block = decodeBlock(op);
|
||||
drawBlock(block, surface);
|
||||
}
|
||||
}
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
XMGDecoder::Block XMGDecoder::decodeBlock(byte op) {
|
||||
Block block;
|
||||
|
||||
switch (op) {
|
||||
case 0x00:
|
||||
// YCrCb
|
||||
block = processYCrCb();
|
||||
break;
|
||||
case 0x40:
|
||||
// Trans
|
||||
block = processTrans();
|
||||
break;
|
||||
case 0x80:
|
||||
// RGB
|
||||
block = processRGB();
|
||||
break;
|
||||
default:
|
||||
error("Unsupported color mode '%d'", op);
|
||||
}
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
void XMGDecoder::drawBlock(const Block &block, Graphics::Surface *surface) {
|
||||
uint32 *pixels = (uint32 *)surface->getBasePtr(_currX, _currY);
|
||||
|
||||
bool drawTwoColumns = _currX + 1 < _width;
|
||||
bool drawTwoLines = _currY + 1 < _height;
|
||||
|
||||
pixels[0] = TO_LE_32(block.a1);
|
||||
|
||||
if (drawTwoColumns) {
|
||||
pixels[1] = TO_LE_32(block.a2);
|
||||
}
|
||||
|
||||
if (drawTwoLines) {
|
||||
pixels[_width + 0] = TO_LE_32(block.b1);
|
||||
}
|
||||
|
||||
if (drawTwoColumns && drawTwoLines) {
|
||||
pixels[_width + 1] = TO_LE_32(block.b2);
|
||||
}
|
||||
|
||||
_currX += drawTwoColumns ? 2 : 1;
|
||||
}
|
||||
|
||||
XMGDecoder::Block XMGDecoder::processYCrCb() {
|
||||
byte y0, y1, y2, y3;
|
||||
byte cr, cb;
|
||||
|
||||
y0 = _stream->readByte();
|
||||
y1 = _stream->readByte();
|
||||
y2 = _stream->readByte();
|
||||
y3 = _stream->readByte();
|
||||
cr = _stream->readByte();
|
||||
cb = _stream->readByte();
|
||||
|
||||
byte r, g, b;
|
||||
Block block;
|
||||
|
||||
Graphics::YUV2RGB(y0, cb, cr, r, g, b);
|
||||
block.a1 = (255u << 24) + (b << 16) + (g << 8) + r;
|
||||
|
||||
Graphics::YUV2RGB(y1, cb, cr, r, g, b);
|
||||
block.a2 = (255u << 24) + (b << 16) + (g << 8) + r;
|
||||
|
||||
Graphics::YUV2RGB(y2, cb, cr, r, g, b);
|
||||
block.b1 = (255u << 24) + (b << 16) + (g << 8) + r;
|
||||
|
||||
Graphics::YUV2RGB(y3, cb, cr, r, g, b);
|
||||
block.b2 = (255u << 24) + (b << 16) + (g << 8) + r;
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
XMGDecoder::Block XMGDecoder::processTrans() {
|
||||
Block block;
|
||||
|
||||
block.a1 = 0;
|
||||
block.a2 = 0;
|
||||
block.b1 = 0;
|
||||
block.b2 = 0;
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
XMGDecoder::Block XMGDecoder::processRGB() {
|
||||
Block block;
|
||||
uint32 color;
|
||||
|
||||
color = _stream->readUint16LE();
|
||||
color += _stream->readByte() << 16;
|
||||
if (color != _transColor)
|
||||
color += 255u << 24;
|
||||
else
|
||||
color = 0;
|
||||
block.a1 = color;
|
||||
|
||||
color = _stream->readUint16LE();
|
||||
color += _stream->readByte() << 16;
|
||||
if (color != _transColor)
|
||||
color += 255u << 24;
|
||||
else
|
||||
color = 0;
|
||||
block.a2 = color;
|
||||
|
||||
color = _stream->readUint16LE();
|
||||
color += _stream->readByte() << 16;
|
||||
if (color != _transColor)
|
||||
color += 255u << 24;
|
||||
else
|
||||
color = 0;
|
||||
block.b1 = color;
|
||||
|
||||
color = _stream->readUint16LE();
|
||||
color += _stream->readByte() << 16;
|
||||
if (color != _transColor)
|
||||
color += 255u << 24;
|
||||
else
|
||||
color = 0;
|
||||
block.b2 = color;
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
} // End of namespace Formats
|
||||
} // End of namespace Stark
|
||||
78
engines/stark/formats/xmg.h
Normal file
78
engines/stark/formats/xmg.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/* 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 STARK_XMG_H
|
||||
#define STARK_XMG_H
|
||||
|
||||
#include "common/stream.h"
|
||||
|
||||
namespace Graphics {
|
||||
struct Surface;
|
||||
}
|
||||
|
||||
namespace Stark {
|
||||
namespace Formats {
|
||||
|
||||
/**
|
||||
* XMG (still image) decoder
|
||||
*/
|
||||
class XMGDecoder {
|
||||
public:
|
||||
static Graphics::Surface *decode(Common::ReadStream *stream);
|
||||
static void readSize(Common::ReadStream *stream, uint &width, uint &height);
|
||||
|
||||
private:
|
||||
explicit XMGDecoder(Common::ReadStream *stream);
|
||||
|
||||
struct Block {
|
||||
uint32 a1, a2;
|
||||
uint32 b1, b2;
|
||||
};
|
||||
|
||||
void readHeader();
|
||||
Graphics::Surface *decodeImage();
|
||||
Block decodeBlock(byte op);
|
||||
void drawBlock(const Block &block, Graphics::Surface *surface);
|
||||
|
||||
Block processYCrCb();
|
||||
Block processTrans();
|
||||
Block processRGB();
|
||||
|
||||
uint32 _width;
|
||||
uint32 _height;
|
||||
|
||||
uint32 _currX;
|
||||
uint32 _currY;
|
||||
|
||||
Common::ReadStream *_stream;
|
||||
|
||||
/**
|
||||
* The transparency color in the RGB and transparency blocks.
|
||||
* In the output surface, the transparent color is black with zero
|
||||
* alpha. So the images are effectively pre-multiplied alpha.
|
||||
*/
|
||||
uint32 _transColor;
|
||||
};
|
||||
|
||||
} // End of namespace Formats
|
||||
} // End of namespace Stark
|
||||
|
||||
#endif // STARK_XMG_H
|
||||
333
engines/stark/formats/xrc.cpp
Normal file
333
engines/stark/formats/xrc.cpp
Normal file
@@ -0,0 +1,333 @@
|
||||
/* 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 "engines/stark/formats/xrc.h"
|
||||
|
||||
#include "engines/stark/formats/xarc.h"
|
||||
#include "engines/stark/resources/anim.h"
|
||||
#include "engines/stark/resources/animhierarchy.h"
|
||||
#include "engines/stark/resources/animscript.h"
|
||||
#include "engines/stark/resources/animsoundtrigger.h"
|
||||
#include "engines/stark/resources/bonesmesh.h"
|
||||
#include "engines/stark/resources/bookmark.h"
|
||||
#include "engines/stark/resources/camera.h"
|
||||
#include "engines/stark/resources/container.h"
|
||||
#include "engines/stark/resources/command.h"
|
||||
#include "engines/stark/resources/dialog.h"
|
||||
#include "engines/stark/resources/direction.h"
|
||||
#include "engines/stark/resources/fmv.h"
|
||||
#include "engines/stark/resources/image.h"
|
||||
#include "engines/stark/resources/item.h"
|
||||
#include "engines/stark/resources/floor.h"
|
||||
#include "engines/stark/resources/floorface.h"
|
||||
#include "engines/stark/resources/floorfield.h"
|
||||
#include "engines/stark/resources/knowledge.h"
|
||||
#include "engines/stark/resources/knowledgeset.h"
|
||||
#include "engines/stark/resources/layer.h"
|
||||
#include "engines/stark/resources/level.h"
|
||||
#include "engines/stark/resources/light.h"
|
||||
#include "engines/stark/resources/lipsync.h"
|
||||
#include "engines/stark/resources/location.h"
|
||||
#include "engines/stark/resources/path.h"
|
||||
#include "engines/stark/resources/pattable.h"
|
||||
#include "engines/stark/resources/root.h"
|
||||
#include "engines/stark/resources/script.h"
|
||||
#include "engines/stark/resources/scroll.h"
|
||||
#include "engines/stark/resources/speech.h"
|
||||
#include "engines/stark/resources/sound.h"
|
||||
#include "engines/stark/resources/string.h"
|
||||
#include "engines/stark/resources/textureset.h"
|
||||
#include "engines/stark/resourcereference.h"
|
||||
|
||||
namespace Stark {
|
||||
namespace Formats {
|
||||
|
||||
XRCReadStream::XRCReadStream(const Common::Path &archiveName,
|
||||
Common::SeekableReadStream *parentStream, DisposeAfterUse::Flag disposeParentStream) :
|
||||
SeekableSubReadStream(parentStream, 0, parentStream->size(), disposeParentStream),
|
||||
_archiveName(archiveName) {
|
||||
}
|
||||
|
||||
XRCReadStream::~XRCReadStream() {
|
||||
}
|
||||
|
||||
Common::String XRCReadStream::readString() {
|
||||
// Read the string length
|
||||
uint16 length = readUint16LE();
|
||||
|
||||
// Read the string
|
||||
char *data = new char[length];
|
||||
read(data, length);
|
||||
Common::String string(data, length);
|
||||
delete[] data;
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
Resources::Type XRCReadStream::readResourceType() {
|
||||
byte rawType;
|
||||
rawType = readByte();
|
||||
return Resources::Type((Resources::Type::ResourceType) (rawType));
|
||||
}
|
||||
|
||||
ResourceReference XRCReadStream::readResourceReference() {
|
||||
ResourceReference reference;
|
||||
reference.loadFromStream(this);
|
||||
|
||||
return reference;
|
||||
}
|
||||
|
||||
Math::Vector3d XRCReadStream::readVector3() {
|
||||
Math::Vector3d v;
|
||||
v.readFromStream(this);
|
||||
return v;
|
||||
}
|
||||
|
||||
Common::Rect XRCReadStream::readRect() {
|
||||
Common::Rect r;
|
||||
r.left = readSint32LE();
|
||||
r.top = readSint32LE();
|
||||
r.right = readSint32LE();
|
||||
r.bottom = readSint32LE();
|
||||
return r;
|
||||
}
|
||||
|
||||
Common::Point XRCReadStream::readPoint() {
|
||||
uint32 x = readUint32LE();
|
||||
uint32 y = readUint32LE();
|
||||
|
||||
return Common::Point(x, y);
|
||||
}
|
||||
|
||||
bool XRCReadStream::readBool() {
|
||||
uint32 b = readUint32LE();
|
||||
return b != 0;
|
||||
}
|
||||
|
||||
bool XRCReadStream::isDataLeft() {
|
||||
return pos() < size();
|
||||
}
|
||||
|
||||
Common::Path XRCReadStream::getArchiveName() const {
|
||||
return _archiveName;
|
||||
}
|
||||
|
||||
Resources::Object *XRCReader::importTree(XARCArchive *archive) {
|
||||
// Find the XRC file
|
||||
Common::ArchiveMemberList members;
|
||||
archive->listMatchingMembers(members, "*.xrc");
|
||||
if (members.size() == 0) {
|
||||
error("No resource tree in archive '%s'", archive->getFilename().toString(Common::Path::kNativeSeparator).c_str());
|
||||
}
|
||||
if (members.size() > 1) {
|
||||
error("Too many resource scripts in archive '%s'", archive->getFilename().toString(Common::Path::kNativeSeparator).c_str());
|
||||
}
|
||||
|
||||
// Open the XRC file
|
||||
Common::SeekableReadStream *stream = archive->createReadStreamForMember(members.front()->getPathInArchive());
|
||||
XRCReadStream *xrcStream = new XRCReadStream(archive->getFilename(), stream);
|
||||
|
||||
// Import the resource tree
|
||||
Resources::Object *root = importResource(xrcStream, nullptr);
|
||||
|
||||
delete xrcStream;
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
Resources::Object *XRCReader::importResource(XRCReadStream *stream, Resources::Object *parent) {
|
||||
Resources::Object *resource = createResource(stream, parent);
|
||||
importResourceData(stream, resource);
|
||||
importResourceChildren(stream, resource);
|
||||
|
||||
// Resource lifecycle update
|
||||
resource->onPostRead();
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
Resources::Object *XRCReader::createResource(XRCReadStream *stream, Resources::Object *parent) {
|
||||
// Read the resource type and subtype
|
||||
Resources::Type type = stream->readResourceType();
|
||||
byte subType = stream->readByte();
|
||||
|
||||
// Read the resource properties
|
||||
uint16 index = stream->readUint16LE();
|
||||
Common::String name = stream->readString();
|
||||
|
||||
// Create a new resource
|
||||
Resources::Object *resource;
|
||||
switch (type.get()) {
|
||||
case Resources::Type::kRoot:
|
||||
resource = new Resources::Root(parent, subType, index, name);
|
||||
break;
|
||||
case Resources::Type::kLevel:
|
||||
resource = new Resources::Level(parent, subType, index, name);
|
||||
break;
|
||||
case Resources::Type::kLocation:
|
||||
resource = new Resources::Location(parent, subType, index, name);
|
||||
break;
|
||||
case Resources::Type::kLayer:
|
||||
resource = Resources::Layer::construct(parent, subType, index, name);
|
||||
break;
|
||||
case Resources::Type::kCamera:
|
||||
resource = new Resources::Camera(parent, subType, index, name);
|
||||
break;
|
||||
case Resources::Type::kFloor:
|
||||
resource = new Resources::Floor(parent, subType, index, name);
|
||||
break;
|
||||
case Resources::Type::kFloorFace:
|
||||
resource = new Resources::FloorFace(parent, subType, index, name);
|
||||
break;
|
||||
case Resources::Type::kItem:
|
||||
resource = Resources::Item::construct(parent, subType, index, name);
|
||||
break;
|
||||
case Resources::Type::kScript:
|
||||
resource = new Resources::Script(parent, subType, index, name);
|
||||
break;
|
||||
case Resources::Type::kAnimHierarchy:
|
||||
resource = new Resources::AnimHierarchy(parent, subType, index, name);
|
||||
break;
|
||||
case Resources::Type::kAnim:
|
||||
resource = Resources::Anim::construct(parent, subType, index, name);
|
||||
break;
|
||||
case Resources::Type::kDirection:
|
||||
resource = new Resources::Direction(parent, subType, index, name);
|
||||
break;
|
||||
case Resources::Type::kImage:
|
||||
resource = Resources::Image::construct(parent, subType, index, name);
|
||||
break;
|
||||
case Resources::Type::kAnimScript:
|
||||
resource = new Resources::AnimScript(parent, subType, index, name);
|
||||
break;
|
||||
case Resources::Type::kAnimScriptItem:
|
||||
resource = new Resources::AnimScriptItem(parent, subType, index, name);
|
||||
break;
|
||||
case Resources::Type::kSoundItem:
|
||||
resource = new Resources::Sound(parent, subType, index, name);
|
||||
break;
|
||||
case Resources::Type::kPath:
|
||||
resource = Resources::Path::construct(parent, subType, index, name);
|
||||
break;
|
||||
case Resources::Type::kFloorField:
|
||||
resource = new Resources::FloorField(parent, subType, index, name);
|
||||
break;
|
||||
case Resources::Type::kBookmark:
|
||||
resource = new Resources::Bookmark(parent, subType, index, name);
|
||||
break;
|
||||
case Resources::Type::kKnowledgeSet:
|
||||
resource = new Resources::KnowledgeSet(parent, subType, index, name);
|
||||
break;
|
||||
case Resources::Type::kKnowledge:
|
||||
resource = new Resources::Knowledge(parent, subType, index, name);
|
||||
break;
|
||||
case Resources::Type::kCommand:
|
||||
resource = new Resources::Command(parent, subType, index, name);
|
||||
break;
|
||||
case Resources::Type::kPATTable:
|
||||
resource = new Resources::PATTable(parent, subType, index, name);
|
||||
break;
|
||||
case Resources::Type::kContainer:
|
||||
resource = new Resources::Container(parent, subType, index, name);
|
||||
break;
|
||||
case Resources::Type::kDialog:
|
||||
resource = new Resources::Dialog(parent, subType, index, name);
|
||||
break;
|
||||
case Resources::Type::kSpeech:
|
||||
resource = new Resources::Speech(parent, subType, index, name);
|
||||
break;
|
||||
case Resources::Type::kLight:
|
||||
resource = new Resources::Light(parent, subType, index, name);
|
||||
break;
|
||||
case Resources::Type::kBonesMesh:
|
||||
resource = new Resources::BonesMesh(parent, subType, index, name);
|
||||
break;
|
||||
case Resources::Type::kScroll:
|
||||
resource = new Resources::Scroll(parent, subType, index, name);
|
||||
break;
|
||||
case Resources::Type::kFMV:
|
||||
resource = new Resources::FMV(parent, subType, index, name);
|
||||
break;
|
||||
case Resources::Type::kLipSync:
|
||||
resource = new Resources::LipSync(parent, subType, index, name);
|
||||
break;
|
||||
case Resources::Type::kAnimSoundTrigger:
|
||||
resource = new Resources::AnimSoundTrigger(parent, subType, index, name);
|
||||
break;
|
||||
case Resources::Type::kString:
|
||||
resource = new Resources::String(parent, subType, index, name);
|
||||
break;
|
||||
case Resources::Type::kTextureSet:
|
||||
resource = new Resources::TextureSet(parent, subType, index, name);
|
||||
break;
|
||||
default:
|
||||
resource = new Resources::UnimplementedResource(parent, type, subType, index, name);
|
||||
break;
|
||||
}
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
void XRCReader::importResourceData(XRCReadStream *stream, Resources::Object *resource) {
|
||||
// Read the data length
|
||||
uint32 dataLength = stream->readUint32LE();
|
||||
|
||||
// Read the resource type specific data using a memory stream
|
||||
if (dataLength > 0) {
|
||||
XRCReadStream *xrcDataStream = new XRCReadStream(stream->getArchiveName(), stream->readStream(dataLength));
|
||||
|
||||
resource->readData(xrcDataStream);
|
||||
|
||||
if (xrcDataStream->isDataLeft()) {
|
||||
warning("Not all XRC data was read. Type %s, subtype %d, name %s",
|
||||
resource->getType().getName(), resource->getSubType(), resource->getName().c_str());
|
||||
}
|
||||
|
||||
if (xrcDataStream->eos()) {
|
||||
warning("Too much XRC data was read. Type %s, subtype %d, name %s",
|
||||
resource->getType().getName(), resource->getSubType(), resource->getName().c_str());
|
||||
}
|
||||
|
||||
delete xrcDataStream;
|
||||
}
|
||||
}
|
||||
|
||||
void XRCReader::importResourceChildren(XRCReadStream *stream, Resources::Object *resource) {
|
||||
// Get the number of children
|
||||
uint16 numChildren = stream->readUint16LE();
|
||||
|
||||
// Read more unknown data
|
||||
uint16 unknown3 = stream->readUint16LE();
|
||||
if (unknown3 != 0) {
|
||||
warning("Stark::XRCReader: \"%s\" has unknown3=0x%04X with unknown meaning", resource->getName().c_str(), unknown3);
|
||||
}
|
||||
|
||||
// Read the children resources
|
||||
for (int i = 0; i < numChildren; i++) {
|
||||
Resources::Object *child = importResource(stream, resource);
|
||||
|
||||
// Add child to parent
|
||||
resource->addChild(child);
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Formats
|
||||
} // End of namespace Stark
|
||||
86
engines/stark/formats/xrc.h
Normal file
86
engines/stark/formats/xrc.h
Normal file
@@ -0,0 +1,86 @@
|
||||
/* 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 STARK_XRC_READER_H
|
||||
#define STARK_XRC_READER_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/rect.h"
|
||||
#include "common/str.h"
|
||||
#include "common/substream.h"
|
||||
#include "common/types.h"
|
||||
|
||||
#include "math/vector3d.h"
|
||||
#include "math/vector4d.h"
|
||||
|
||||
#include "engines/stark/resources/object.h"
|
||||
#include "engines/stark/resourcereference.h"
|
||||
|
||||
namespace Stark {
|
||||
namespace Formats {
|
||||
|
||||
class XARCArchive;
|
||||
|
||||
/**
|
||||
* A read stream with helper functions to read usual XRC data types
|
||||
*/
|
||||
class XRCReadStream : public Common::SeekableSubReadStream {
|
||||
public:
|
||||
XRCReadStream(const Common::Path &archiveName, Common::SeekableReadStream *parentStream, DisposeAfterUse::Flag disposeParentStream = DisposeAfterUse::YES);
|
||||
virtual ~XRCReadStream();
|
||||
|
||||
/** Obtain the file name of the archive containing the XRC tree */
|
||||
Common::Path getArchiveName() const;
|
||||
|
||||
Common::String readString();
|
||||
Resources::Type readResourceType();
|
||||
ResourceReference readResourceReference();
|
||||
Math::Vector3d readVector3();
|
||||
Common::Rect readRect();
|
||||
Common::Point readPoint();
|
||||
bool readBool();
|
||||
bool isDataLeft();
|
||||
|
||||
private:
|
||||
Common::Path _archiveName;
|
||||
};
|
||||
|
||||
/**
|
||||
* An XRC stream parser, used to build resource trees.
|
||||
*/
|
||||
class XRCReader {
|
||||
public:
|
||||
/**
|
||||
* Build a resource tree from a stream
|
||||
*/
|
||||
static Resources::Object *importTree(XARCArchive *archive);
|
||||
|
||||
protected:
|
||||
static Resources::Object *importResource(XRCReadStream *stream, Resources::Object *parent);
|
||||
static Resources::Object *createResource(XRCReadStream *stream, Resources::Object *parent);
|
||||
static void importResourceChildren(XRCReadStream *stream, Resources::Object *resource);
|
||||
static void importResourceData(XRCReadStream* stream, Resources::Object* resource);
|
||||
};
|
||||
|
||||
} // End of namespace Formats
|
||||
} // End of namespace Stark
|
||||
|
||||
#endif // STARK_XRC_READER_H
|
||||
Reference in New Issue
Block a user