From b5a4f622c293733b6067a27af09b44931295fd72 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 13 Jun 2015 10:00:36 +0200 Subject: SHERLOCK: 3DO: support for cAnim data (startCAnim) it's now possible to leave the first room Conflicts: engines/sherlock/objects.cpp --- engines/sherlock/image_file.cpp | 3 ++ engines/sherlock/objects.cpp | 17 +++++--- engines/sherlock/objects.h | 7 ++-- engines/sherlock/scalpel/scalpel_scene.cpp | 19 +++++---- engines/sherlock/scene.cpp | 66 ++++++++++++++++++++++++------ engines/sherlock/scene.h | 2 +- engines/sherlock/sherlock.cpp | 1 + 7 files changed, 87 insertions(+), 28 deletions(-) (limited to 'engines/sherlock') diff --git a/engines/sherlock/image_file.cpp b/engines/sherlock/image_file.cpp index 95f34dc24b..342e5ee4e3 100644 --- a/engines/sherlock/image_file.cpp +++ b/engines/sherlock/image_file.cpp @@ -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: diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index 8e75ce7336..cbc3cbde07 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -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(); diff --git a/engines/sherlock/objects.h b/engines/sherlock/objects.h index 935b4b3cb2..6a71166ee9 100644 --- a/engines/sherlock/objects.h +++ b/engines/sherlock/objects.h @@ -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 { diff --git a/engines/sherlock/scalpel/scalpel_scene.cpp b/engines/sherlock/scalpel/scalpel_scene.cpp index 813e4188ae..c4da8e09a0 100644 --- a/engines/sherlock/scalpel/scalpel_scene.cpp +++ b/engines/sherlock/scalpel/scalpel_scene.cpp @@ -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 - cObj._images = new ImageFile(fname); + 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(); diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index da7f088a06..760307f31a 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -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,17 +464,42 @@ 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); + // 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); + for (uint idx = 0; idx < _cAnim.size(); ++idx) { + _cAnim[idx].load(*cAnimStream, IS_ROSE_TATTOO, *cAnimOffsetPtr); + cAnimOffsetPtr++; + } - delete canimStream; + delete cAnimStream; + delete cAnimOffsetTablePtr; } + + // Read in the room bounding areas int size = rrmStream->readUint16LE(); Common::SeekableReadStream *boundsStream = !_lzwMode ? rrmStream : @@ -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 diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h index a3542026e6..8c428659ae 100644 --- a/engines/sherlock/scene.h +++ b/engines/sherlock/scene.h @@ -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: diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index bc150cae92..9c397e3794 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -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); -- cgit v1.2.3