SHERLOCK: 3DO: support for cAnim data (startCAnim)

it's now possible to leave the first room

Conflicts:
	engines/sherlock/objects.cpp
This commit is contained in:
Martin Kiewitz 2015-06-13 10:00:36 +02:00
parent 0f1b756242
commit b5a4f622c2
7 changed files with 88 additions and 29 deletions

View file

@ -244,11 +244,14 @@ void ImageFile3DO::setVm(SherlockEngine *vm) {
}
ImageFile3DO::ImageFile3DO(const Common::String &name, ImageFile3DOType imageFile3DOType) {
#if 0
Common::File *dataStream = new Common::File();
if (!dataStream->open(name)) {
error("unable to open %s\n", name.c_str());
}
#endif
Common::SeekableReadStream *dataStream = _vm->_res->load(name);
switch(imageFile3DOType) {
case kImageFile3DOType_Animation:

View file

@ -1503,14 +1503,14 @@ const Common::Rect Object::getOldBounds() const {
/*----------------------------------------------------------------*/
void CAnim::load(Common::SeekableReadStream &s, bool isRoseTattoo) {
void CAnim::load(Common::SeekableReadStream &s, bool isRoseTattoo, uint32 dataOffset) {
char buffer[12];
s.read(buffer, 12);
_name = Common::String(buffer);
if (isRoseTattoo) {
Common::fill(&_sequences[0], &_sequences[30], 0);
_size = s.readUint32LE();
_dataSize = s.readUint32LE();
} else {
s.read(_sequences, 30);
}
@ -1522,7 +1522,7 @@ void CAnim::load(Common::SeekableReadStream &s, bool isRoseTattoo) {
_flags = s.readByte();
_scaleVal = s.readSint16LE();
} else {
_size = s.readUint32LE();
_dataSize = s.readUint32LE();
_type = (SpriteType)s.readUint16LE();
_flags = s.readByte();
}
@ -1557,13 +1557,20 @@ void CAnim::load(Common::SeekableReadStream &s, bool isRoseTattoo) {
_teleport[0].x = _teleport[0].x * FIXED_INT_MULTIPLIER / 100;
_teleport[0].y = _teleport[0].y * FIXED_INT_MULTIPLIER / 100;
}
// Save offset of data, which is actually inside another table inside the room data file
// This table is at offset 44 for Serrated Scalpel
// TODO: find it for the other game
_dataOffset = dataOffset;
}
void CAnim::load3DO(Common::SeekableReadStream &s) {
void CAnim::load3DO(Common::SeekableReadStream &s, uint32 dataOffset) {
// this got reordered on 3DO
// maybe it was the 3DO compiler
_size = s.readUint32BE();
_dataSize = s.readUint32BE();
// Save offset of data, which is inside another table inside the room data file
_dataOffset = dataOffset;
_position.x = s.readSint16BE();
_position.y = s.readSint16BE();

View file

@ -444,7 +444,8 @@ public:
struct CAnim {
Common::String _name; // Name
Common::Point _position; // Position
int _size; // Size of uncompressed animation
int _dataSize; // Size of uncompressed animation data
uint32 _dataOffset; // offset within room file of animation data
int _flags; // Tells if can be walked behind
PositionFacing _goto[2]; // Position Holmes (and NPC in Rose Tattoo) should walk to before anim starts
PositionFacing _teleport[2]; // Location Holmes (and NPC) shoul teleport to after playing canim
@ -459,8 +460,8 @@ struct CAnim {
/**
* Load the data for the animation
*/
void load(Common::SeekableReadStream &s, bool isRoseTattoo);
void load3DO(Common::SeekableReadStream &s);
void load(Common::SeekableReadStream &s, bool isRoseTattoo, uint32 dataOffset);
void load3DO(Common::SeekableReadStream &s, uint32 dataOffset);
};
class CAnimStream {

View file

@ -568,21 +568,26 @@ int ScalpelScene::startCAnim(int cAnimNum, int playRate) {
Common::String fname = cAnim._name + ".vgs";
if (!res.isInCache(fname)) {
// Set up RRM scene data
Common::SeekableReadStream *rrmStream = res.load(_rrmName);
rrmStream->seek(44 + cAnimNum * 4);
rrmStream->seek(rrmStream->readUint32LE());
Common::SeekableReadStream *roomStream = res.load(_roomFilename);
roomStream->seek(cAnim._dataOffset);
//rrmStream->seek(44 + cAnimNum * 4);
//rrmStream->seek(rrmStream->readUint32LE());
// Load the canimation into the cache
Common::SeekableReadStream *imgStream = !_lzwMode ? rrmStream->readStream(cAnim._size) :
Resources::decompressLZ(*rrmStream, cAnim._size);
Common::SeekableReadStream *imgStream = !_lzwMode ? roomStream->readStream(cAnim._dataSize) :
Resources::decompressLZ(*roomStream, cAnim._dataSize);
res.addToCache(fname, *imgStream);
delete imgStream;
delete rrmStream;
delete roomStream;
}
// Now load the resource as an image
if (_vm->getPlatform() != Common::kPlatform3DO) {
cObj._images = new ImageFile(fname);
} else {
cObj._images = new ImageFile3DO(fname, kImageFile3DOType_RoomFormat);
}
cObj._imageFrame = &(*cObj._images)[0];
cObj._maxFrames = cObj._images->size();

View file

@ -310,7 +310,7 @@ bool Scene::loadScene(const Common::String &filename) {
if (_vm->getPlatform() != Common::kPlatform3DO) {
// PC version
Common::String roomFilename = filename + ".rrm";
_rrmName = roomFilename;
_roomFilename = roomFilename;
flag = _vm->_res->exists(roomFilename);
if (flag) {
@ -464,16 +464,41 @@ bool Scene::loadScene(const Common::String &filename) {
_cAnim.clear();
if (bgHeader._numcAnimations) {
int animSize = IS_SERRATED_SCALPEL ? 65 : 47;
Common::SeekableReadStream *canimStream = _lzwMode ?
Common::SeekableReadStream *cAnimStream = _lzwMode ?
res.decompress(*rrmStream, animSize * bgHeader._numcAnimations) :
rrmStream->readStream(animSize * bgHeader._numcAnimations);
_cAnim.resize(bgHeader._numcAnimations);
for (uint idx = 0; idx < _cAnim.size(); ++idx)
_cAnim[idx].load(*canimStream, IS_ROSE_TATTOO);
delete canimStream;
// Load cAnim offset table as well
uint32 *cAnimOffsetTablePtr = new uint32[bgHeader._numcAnimations];
uint32 *cAnimOffsetPtr = cAnimOffsetTablePtr;
memset(cAnimOffsetTablePtr, 0, bgHeader._numcAnimations);
if (IS_SERRATED_SCALPEL) {
// Save current stream offset
int32 curOffset = rrmStream->pos();
rrmStream->seek(44); // Seek to cAnim-Offset-Table
for (uint16 curCAnim = 0; curCAnim < bgHeader._numcAnimations; curCAnim++) {
*cAnimOffsetPtr = rrmStream->readUint32LE();
cAnimOffsetPtr++;
}
// Seek back to original stream offset
rrmStream->seek(curOffset);
}
// TODO: load offset table for Rose Tattoo as well
// Go to the start of the cAnimOffsetTable
cAnimOffsetPtr = cAnimOffsetTablePtr;
_cAnim.resize(bgHeader._numcAnimations);
for (uint idx = 0; idx < _cAnim.size(); ++idx) {
_cAnim[idx].load(*cAnimStream, IS_ROSE_TATTOO, *cAnimOffsetPtr);
cAnimOffsetPtr++;
}
delete cAnimStream;
delete cAnimOffsetTablePtr;
}
// Read in the room bounding areas
int size = rrmStream->readUint16LE();
@ -579,12 +604,12 @@ bool Scene::loadScene(const Common::String &filename) {
} else {
// === 3DO version ===
Common::String roomFilename = "rooms/" + filename + ".rrm";
flag = _vm->_res->exists(roomFilename);
_roomFilename = "rooms/" + filename + ".rrm";
flag = _vm->_res->exists(_roomFilename);
if (!flag)
error("loadScene: 3DO room data file not found");
Common::SeekableReadStream *roomStream = _vm->_res->load(roomFilename);
Common::SeekableReadStream *roomStream = _vm->_res->load(_roomFilename);
// Read 3DO header
roomStream->skip(4); // UINT32: offset graphic data?
@ -690,13 +715,30 @@ bool Scene::loadScene(const Common::String &filename) {
_cAnim.clear();
if (header3DO_numAnimations) {
roomStream->seek(header3DO_cAnim_offset);
Common::SeekableReadStream *canimStream = roomStream->readStream(header3DO_cAnim_size);
Common::SeekableReadStream *cAnimStream = roomStream->readStream(header3DO_cAnim_size);
uint32 *cAnimOffsetTablePtr = new uint32[header3DO_numAnimations];
uint32 *cAnimOffsetPtr = cAnimOffsetTablePtr;
memset(cAnimOffsetTablePtr, 0, header3DO_numAnimations);
// Seek to end of graphics data and load cAnim offset table from there
roomStream->seek(header3DO_bgGraphicData_offset + header3DO_bgGraphicData_size);
for (uint16 curCAnim = 0; curCAnim < header3DO_numAnimations; curCAnim++) {
*cAnimOffsetPtr = roomStream->readUint32BE();
cAnimOffsetPtr++;
}
// Go to the start of the cAnimOffsetTable
cAnimOffsetPtr = cAnimOffsetTablePtr;
_cAnim.resize(header3DO_numAnimations);
for (uint idx = 0; idx < _cAnim.size(); ++idx)
_cAnim[idx].load3DO(*canimStream);
for (uint idx = 0; idx < _cAnim.size(); ++idx) {
_cAnim[idx].load3DO(*cAnimStream, *cAnimOffsetPtr);
cAnimOffsetPtr++;
}
delete canimStream;
delete cAnimStream;
delete cAnimOffsetTablePtr;
}
// === BOUNDING AREAS === Read in the room bounding areas

View file

@ -165,7 +165,7 @@ private:
void saveSceneStatus();
protected:
SherlockEngine *_vm;
Common::String _rrmName;
Common::String _roomFilename;
/**
* Loads the data associated for a given scene. The room resource file's format is:

View file

@ -78,6 +78,7 @@ void SherlockEngine::initialize() {
DebugMan.addDebugChannel(kDebugLevelMusic, "Music", "Music debugging");
ImageFile::setVm(this);
ImageFile3DO::setVm(this);
Object::setVm(this);
Sprite::setVm(this);