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) { ImageFile3DO::ImageFile3DO(const Common::String &name, ImageFile3DOType imageFile3DOType) {
#if 0
Common::File *dataStream = new Common::File(); Common::File *dataStream = new Common::File();
if (!dataStream->open(name)) { if (!dataStream->open(name)) {
error("unable to open %s\n", name.c_str()); error("unable to open %s\n", name.c_str());
} }
#endif
Common::SeekableReadStream *dataStream = _vm->_res->load(name);
switch(imageFile3DOType) { switch(imageFile3DOType) {
case kImageFile3DOType_Animation: 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]; char buffer[12];
s.read(buffer, 12); s.read(buffer, 12);
_name = Common::String(buffer); _name = Common::String(buffer);
if (isRoseTattoo) { if (isRoseTattoo) {
Common::fill(&_sequences[0], &_sequences[30], 0); Common::fill(&_sequences[0], &_sequences[30], 0);
_size = s.readUint32LE(); _dataSize = s.readUint32LE();
} else { } else {
s.read(_sequences, 30); s.read(_sequences, 30);
} }
@ -1522,7 +1522,7 @@ void CAnim::load(Common::SeekableReadStream &s, bool isRoseTattoo) {
_flags = s.readByte(); _flags = s.readByte();
_scaleVal = s.readSint16LE(); _scaleVal = s.readSint16LE();
} else { } else {
_size = s.readUint32LE(); _dataSize = s.readUint32LE();
_type = (SpriteType)s.readUint16LE(); _type = (SpriteType)s.readUint16LE();
_flags = s.readByte(); _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].x = _teleport[0].x * FIXED_INT_MULTIPLIER / 100;
_teleport[0].y = _teleport[0].y * 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 // this got reordered on 3DO
// maybe it was the 3DO compiler // 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.x = s.readSint16BE();
_position.y = s.readSint16BE(); _position.y = s.readSint16BE();

View file

@ -444,7 +444,8 @@ public:
struct CAnim { struct CAnim {
Common::String _name; // Name Common::String _name; // Name
Common::Point _position; // Position 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 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 _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 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 * Load the data for the animation
*/ */
void load(Common::SeekableReadStream &s, bool isRoseTattoo); void load(Common::SeekableReadStream &s, bool isRoseTattoo, uint32 dataOffset);
void load3DO(Common::SeekableReadStream &s); void load3DO(Common::SeekableReadStream &s, uint32 dataOffset);
}; };
class CAnimStream { class CAnimStream {

View file

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

View file

@ -310,7 +310,7 @@ bool Scene::loadScene(const Common::String &filename) {
if (_vm->getPlatform() != Common::kPlatform3DO) { if (_vm->getPlatform() != Common::kPlatform3DO) {
// PC version // PC version
Common::String roomFilename = filename + ".rrm"; Common::String roomFilename = filename + ".rrm";
_rrmName = roomFilename; _roomFilename = roomFilename;
flag = _vm->_res->exists(roomFilename); flag = _vm->_res->exists(roomFilename);
if (flag) { if (flag) {
@ -464,16 +464,41 @@ bool Scene::loadScene(const Common::String &filename) {
_cAnim.clear(); _cAnim.clear();
if (bgHeader._numcAnimations) { if (bgHeader._numcAnimations) {
int animSize = IS_SERRATED_SCALPEL ? 65 : 47; int animSize = IS_SERRATED_SCALPEL ? 65 : 47;
Common::SeekableReadStream *canimStream = _lzwMode ? Common::SeekableReadStream *cAnimStream = _lzwMode ?
res.decompress(*rrmStream, animSize * bgHeader._numcAnimations) : res.decompress(*rrmStream, animSize * bgHeader._numcAnimations) :
rrmStream->readStream(animSize * bgHeader._numcAnimations); rrmStream->readStream(animSize * bgHeader._numcAnimations);
_cAnim.resize(bgHeader._numcAnimations); // Load cAnim offset table as well
for (uint idx = 0; idx < _cAnim.size(); ++idx) uint32 *cAnimOffsetTablePtr = new uint32[bgHeader._numcAnimations];
_cAnim[idx].load(*canimStream, IS_ROSE_TATTOO); uint32 *cAnimOffsetPtr = cAnimOffsetTablePtr;
memset(cAnimOffsetTablePtr, 0, bgHeader._numcAnimations);
delete canimStream; 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 // Read in the room bounding areas
int size = rrmStream->readUint16LE(); int size = rrmStream->readUint16LE();
@ -579,12 +604,12 @@ bool Scene::loadScene(const Common::String &filename) {
} else { } else {
// === 3DO version === // === 3DO version ===
Common::String roomFilename = "rooms/" + filename + ".rrm"; _roomFilename = "rooms/" + filename + ".rrm";
flag = _vm->_res->exists(roomFilename); flag = _vm->_res->exists(_roomFilename);
if (!flag) if (!flag)
error("loadScene: 3DO room data file not found"); 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 // Read 3DO header
roomStream->skip(4); // UINT32: offset graphic data? roomStream->skip(4); // UINT32: offset graphic data?
@ -690,13 +715,30 @@ bool Scene::loadScene(const Common::String &filename) {
_cAnim.clear(); _cAnim.clear();
if (header3DO_numAnimations) { if (header3DO_numAnimations) {
roomStream->seek(header3DO_cAnim_offset); 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); _cAnim.resize(header3DO_numAnimations);
for (uint idx = 0; idx < _cAnim.size(); ++idx) for (uint idx = 0; idx < _cAnim.size(); ++idx) {
_cAnim[idx].load3DO(*canimStream); _cAnim[idx].load3DO(*cAnimStream, *cAnimOffsetPtr);
cAnimOffsetPtr++;
}
delete canimStream; delete cAnimStream;
delete cAnimOffsetTablePtr;
} }
// === BOUNDING AREAS === Read in the room bounding areas // === BOUNDING AREAS === Read in the room bounding areas

View file

@ -165,7 +165,7 @@ private:
void saveSceneStatus(); void saveSceneStatus();
protected: protected:
SherlockEngine *_vm; SherlockEngine *_vm;
Common::String _rrmName; Common::String _roomFilename;
/** /**
* Loads the data associated for a given scene. The room resource file's format is: * 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"); DebugMan.addDebugChannel(kDebugLevelMusic, "Music", "Music debugging");
ImageFile::setVm(this); ImageFile::setVm(this);
ImageFile3DO::setVm(this);
Object::setVm(this); Object::setVm(this);
Sprite::setVm(this); Sprite::setVm(this);