SHERLOCK: some work on 3DO room data

This commit is contained in:
Martin Kiewitz 2015-06-11 19:52:41 +02:00
parent d6ca620a7c
commit 515d5422a7
4 changed files with 541 additions and 186 deletions

View File

@ -674,6 +674,27 @@ void UseType::load(Common::SeekableReadStream &s, bool isRoseTattoo) {
_target = Common::String(buffer);
}
void UseType::load3DO(Common::SeekableReadStream &s) {
char buffer[12];
_cAnimNum = s.readByte();
_cAnimSpeed = s.readByte();
if (_cAnimSpeed & 0x80)
_cAnimSpeed = -(_cAnimSpeed & 0x7f);
for (int idx = 0; idx < NAMES_COUNT; ++idx) {
s.read(buffer, 12);
_names[idx] = Common::String(buffer);
}
_useFlag = s.readSint16BE();
s.skip(6);
s.read(buffer, 12);
_target = Common::String(buffer);
}
/*----------------------------------------------------------------*/
SherlockEngine *Object::_vm;
@ -781,6 +802,98 @@ void Object::load(Common::SeekableReadStream &s, bool isRoseTattoo) {
}
}
void Object::load3DO(Common::SeekableReadStream &s) {
char buffer[41];
_examine.clear();
_sequences = nullptr;
_images = nullptr;
_imageFrame = nullptr;
// on 3DO all of this data is reordered!!!
s.skip(4);
_sequenceOffset = s.readUint16LE(); // weird that this seems to be LE
s.seek(10, SEEK_CUR);
_walkCount = 0; // ??? s.readByte();
_allow = 0; // ??? s.readByte();
_frameNumber = s.readSint16BE();
_sequenceNumber = s.readSint16BE();
_position.x = s.readSint16BE();
_position.y = s.readSint16BE();
_delta.x = s.readSint16BE();
_delta.y = s.readSint16BE();
_type = (SpriteType)s.readUint16BE();
_oldPosition.x = s.readSint16BE();
_oldPosition.y = s.readSint16BE();
_oldSize.x = s.readUint16BE();
_oldSize.y = s.readUint16BE();
_goto.x = s.readSint16BE();
_goto.y = s.readSint16BE();
_goto.x = _goto.x * FIXED_INT_MULTIPLIER / 100;
_goto.y = _goto.y * FIXED_INT_MULTIPLIER / 100;
s.skip(16); // Unknown
#if 0
_pickup = s.readByte();
_defaultCommand = s.readByte();
_lookFlag = s.readSint16BE();
_pickupFlag = s.readSint16BE();
_requiredFlag = s.readSint16BE();
_noShapeSize.x = s.readUint16BE();
_noShapeSize.y = s.readUint16BE();
_status = s.readUint16BE();
_maxFrames = s.readUint16BE();
_aOpen.load(s);
_aType = (AType)s.readByte();
_lookFrames = s.readByte();
_seqCounter = s.readByte();
_lookPosition.x = s.readUint16BE() * FIXED_INT_MULTIPLIER / 100;
_lookPosition.y = s.readByte() * FIXED_INT_MULTIPLIER;
_lookFacing = s.readByte();
_lookcAnim = s.readByte();
_aClose.load(s);
_seqStack = s.readByte();
_seqTo = s.readByte();
#endif
warning("pos %d", s.pos());
_descOffset = s.readUint16BE();
_seqCounter2 = 0; // ???
_seqSize = s.readUint16BE();
s.skip(446);
#if 0
s.skip(1);
_aMove.load(s);
s.skip(8);
for (int idx = 0; idx < 4; ++idx)
_use[idx].load(s, false);
#endif
// 3DO: name is at the end
s.read(buffer, 12);
_name = Common::String(buffer);
s.read(buffer, 41);
_description = Common::String(buffer);
s.skip(4); // Unknown
// Probably those here?!?!
_misc = s.readByte();
_flags = s.readByte();
s.skip(21); // Unknown
}
void Object::toggleHidden() {
if (_type != HIDDEN && _type != HIDE_SHAPE && _type != INVALID) {
if (_seqTo != 0)
@ -1516,6 +1629,33 @@ void CAnim::load(Common::SeekableReadStream &s, bool isRoseTattoo) {
_teleportDir = s.readSint16LE();
}
void CAnim::load3DO(Common::SeekableReadStream &s) {
char buffer[12];
s.read(buffer, 12);
_name = Common::String(buffer);
s.read(_sequences, 30);
_position.x = s.readSint16BE();
_position.y = s.readSint16BE();
_size = s.readUint32BE();
_type = (SpriteType)s.readUint16BE();
_flags = s.readByte();
_goto.x = s.readSint16BE();
_goto.y = s.readSint16BE();
_gotoDir = s.readSint16BE();
_teleportPos.x = s.readSint16BE();
_teleportPos.y = s.readSint16BE();
_goto.x = _goto.x * FIXED_INT_MULTIPLIER / 100;
_goto.y = _goto.y * FIXED_INT_MULTIPLIER / 100;
_teleportPos.x = _teleportPos.x * FIXED_INT_MULTIPLIER / 100;
_teleportPos.y = _teleportPos.y * FIXED_INT_MULTIPLIER / 100;
_teleportDir = s.readSint16BE();
}
/*----------------------------------------------------------------*/
CAnimStream::CAnimStream() {

View File

@ -159,6 +159,7 @@ struct UseType {
* Load the data for the UseType
*/
void load(Common::SeekableReadStream &s, bool isRoseTattoo);
void load3DO(Common::SeekableReadStream &s);
};
class BaseObject {
@ -344,6 +345,7 @@ public:
* Load the data for the object
*/
void load(Common::SeekableReadStream &s, bool isRoseTattoo);
void load3DO(Common::SeekableReadStream &s);
/**
* Toggle the type of an object between hidden and active
@ -436,6 +438,7 @@ struct CAnim {
* Load the data for the animation
*/
void load(Common::SeekableReadStream &s, bool isRoseTattoo);
void load3DO(Common::SeekableReadStream &s);
};
class CAnimStream {

View File

@ -84,6 +84,16 @@ void BgFileHeaderInfo::load(Common::SeekableReadStream &s) {
_filename = Common::String(buffer);
}
void BgFileHeaderInfo::load3DO(Common::SeekableReadStream &s) {
_filesize = s.readUint32BE();
_maxFrames = s.readByte();
char buffer[9];
s.read(buffer, 9);
_filename = Common::String(buffer);
s.skip(2); // only on 3DO!
}
/*----------------------------------------------------------------*/
void Exit::load(Common::SeekableReadStream &s, bool isRoseTattoo) {
@ -121,6 +131,13 @@ void SceneEntry::load(Common::SeekableReadStream &s) {
_allow = s.readByte();
}
void SceneEntry::load3DO(Common::SeekableReadStream &s) {
_startPosition.x = s.readSint16BE();
_startPosition.y = s.readSint16BE();
_startDir = s.readByte();
_allow = s.readByte();
}
void SceneSound::load(Common::SeekableReadStream &s) {
char buffer[9];
s.read(buffer, 8);
@ -130,6 +147,10 @@ void SceneSound::load(Common::SeekableReadStream &s) {
_priority = s.readByte();
}
void SceneSound::load3DO(Common::SeekableReadStream &s) {
load(s);
}
/*----------------------------------------------------------------*/
int ObjectArray::indexOf(const Object &obj) const {
@ -285,6 +306,8 @@ bool Scene::loadScene(const Common::String &filename) {
// Load the room resource file for the scene
//
if (_vm->getPlatform() != Common::kPlatform3DO) {
// PC version
Common::String rrmFile = filename + ".rrm";
flag = _vm->_res->exists(rrmFile);
if (flag) {
@ -549,6 +572,192 @@ bool Scene::loadScene(const Common::String &filename) {
screen.setPalette(screen._cMap);
delete rrmStream;
}
} else {
// === 3DO version ===
Common::String roomFile = "rooms/" + filename + ".rrm";
flag = _vm->_res->exists(roomFile);
if (!flag)
error("loadScene: 3DO room file not found");
Common::SeekableReadStream *roomStream = _vm->_res->load(roomFile);
// Read 3DO header
roomStream->skip(4); // UINT32: offset graphic data?
uint16 header3DO_numStructs = roomStream->readUint16BE();
uint16 header3DO_numImages = roomStream->readUint16BE();
uint16 header3DO_numAnimations = roomStream->readUint16BE();
roomStream->skip(6);
uint32 header3DO_bgInfo_offset = roomStream->readUint32BE() + 0x80;
uint32 header3DO_bgInfo_size = roomStream->readUint32BE();
uint32 header3DO_bgShapes_offset = roomStream->readUint32BE() + 0x80;
uint32 header3DO_bgShapes_size = roomStream->readUint32BE();
uint32 header3DO_descriptions_offset = roomStream->readUint32BE() + 0x80;
uint32 header3DO_descriptions_size = roomStream->readUint32BE();
uint32 header3DO_sequence_offset = roomStream->readUint32BE() + 0x80;
uint32 header3DO_sequence_size = roomStream->readUint32BE();
uint32 header3DO_cAnim_offset = roomStream->readUint32BE() + 0x80;
uint32 header3DO_cAnim_size = roomStream->readUint32BE();
uint32 header3DO_roomBounding_offset = roomStream->readUint32BE() + 0x80;
uint32 header3DO_roomBounding_size = roomStream->readUint32BE();
uint32 header3DO_walkDirectory_offset = roomStream->readUint32BE() + 0x80;
uint32 header3DO_walkDirectory_size = roomStream->readUint32BE();
uint32 header3DO_walkData_offset = roomStream->readUint32BE() + 0x80;
uint32 header3DO_walkData_size = roomStream->readUint32BE();
uint32 header3DO_exits_offset = roomStream->readUint32BE() + 0x80;
uint32 header3DO_exits_size = roomStream->readUint32BE();
uint32 header3DO_entranceData_offset = roomStream->readUint32BE() + 0x80;
uint32 header3DO_entranceData_size = roomStream->readUint32BE();
uint32 header3DO_soundList_offset = roomStream->readUint32BE() + 0x80;
uint32 header3DO_soundList_size = roomStream->readUint32BE();
uint32 header3DO_unknown_offset = roomStream->readUint32BE() + 0x80;
uint32 header3DO_unknown_size = roomStream->readUint32BE();
uint32 header3DO_bgGraphicData_offset = roomStream->readUint32BE() + 0x80;
uint32 header3DO_bgGraphicData_size = roomStream->readUint32BE();
int32 header3DO_soundList_count = header3DO_soundList_size / 9;
_invGraphicItems = header3DO_numImages + 1;
// === BGINFO === read in the shapes header info
Common::Array<BgFileHeaderInfo> bgInfo;
roomStream->seek(header3DO_bgInfo_offset);
bgInfo.resize(header3DO_numStructs);
for (uint idx = 0; idx < bgInfo.size(); ++idx)
bgInfo[idx].load3DO(*roomStream);
// === BGSHAPES === read in the shapes info
roomStream->seek(header3DO_bgShapes_offset);
_bgShapes.resize(header3DO_numStructs);
for (int idx = 0; idx < header3DO_numStructs; ++idx)
_bgShapes[idx].load3DO(*roomStream);
// === DESCRIPTION === read description text
if (header3DO_descriptions_size) {
roomStream->seek(header3DO_descriptions_offset);
_descText.resize(header3DO_descriptions_size);
roomStream->read(&_descText[0], header3DO_descriptions_size);
}
// === SEQUENCE === read sequence buffer
if (header3DO_sequence_size) {
roomStream->seek(header3DO_sequence_offset);
_sequenceBuffer.resize(header3DO_sequence_size);
roomStream->read(&_sequenceBuffer[0], header3DO_sequence_size);
}
// === IMAGES === set up the list of images used by the scene
roomStream->seek(header3DO_bgGraphicData_offset);
_images.resize(header3DO_numImages + 1);
for (int idx = 0; idx < header3DO_numImages; ++idx) {
_images[idx + 1]._filesize = bgInfo[idx]._filesize;
_images[idx + 1]._maxFrames = bgInfo[idx]._maxFrames;
// Read the image data
// It seems it's a 8 byte header per frame
// followed by a copy of the cel header
// which is then followed by cel data
// TODO
warning("image %d, maxFrames %d", idx, bgInfo[idx]._maxFrames);
warning("size %d", bgInfo[idx]._filesize);
// Read in the image data
//Common::SeekableReadStream *imageStream = roomStream->readStream(bgInfo[idx]._filesize);
//_images[idx + 1]._images = new ImageFile(*imageStream);
//delete imageStream;
warning("end");
}
// === BGSHAPES === Set up the bgShapes
for (int idx = 0; idx < header3DO_numStructs; ++idx) {
warning("%d", _bgShapes[idx]._misc);
_bgShapes[idx]._images = _images[_bgShapes[idx]._misc]._images;
_bgShapes[idx]._imageFrame = !_bgShapes[idx]._images ? (ImageFrame *)nullptr :
&(*_bgShapes[idx]._images)[0];
_bgShapes[idx]._examine = Common::String(&_descText[_bgShapes[idx]._descOffset]);
_bgShapes[idx]._sequences = &_sequenceBuffer[_bgShapes[idx]._sequenceOffset];
_bgShapes[idx]._misc = 0;
_bgShapes[idx]._seqCounter = 0;
_bgShapes[idx]._seqCounter2 = 0;
_bgShapes[idx]._seqStack = 0;
_bgShapes[idx]._frameNumber = -1;
_bgShapes[idx]._oldPosition = Common::Point(0, 0);
_bgShapes[idx]._oldSize = Common::Point(1, 1);
}
// === CANIM === read cAnim list
_cAnim.clear();
if (header3DO_numAnimations) {
int animSize = 65;
roomStream->seek(header3DO_cAnim_offset);
Common::SeekableReadStream *canimStream = roomStream->readStream(animSize * header3DO_numAnimations);
_cAnim.resize(header3DO_numAnimations);
for (uint idx = 0; idx < _cAnim.size(); ++idx)
_cAnim[idx].load3DO(*canimStream);
delete canimStream;
}
// === BOUNDING AREAS === Read in the room bounding areas
int roomBoundingCount = header3DO_roomBounding_size / 12;
roomStream->seek(header3DO_roomBounding_offset);
_zones.resize(roomBoundingCount);
for (uint idx = 0; idx < _zones.size(); ++idx) {
_zones[idx].left = roomStream->readSint16BE();
_zones[idx].top = roomStream->readSint16BE();
_zones[idx].setWidth(roomStream->readSint16BE() + 1);
_zones[idx].setHeight(roomStream->readSint16BE() + 1);
roomStream->skip(4); // skip UINT32
}
// === WALK DIRECTORY === Load the walk directory
roomStream->seek(header3DO_walkDirectory_offset);
assert(_zones.size() < MAX_ZONES);
for (uint idx1 = 0; idx1 < _zones.size(); ++idx1) {
for (uint idx2 = 0; idx2 < _zones.size(); ++idx2)
_walkDirectory[idx1][idx2] = roomStream->readSint16BE();
}
// === WALK DATA === Read in the walk data
roomStream->seek(header3DO_walkData_offset);
_walkData.resize(header3DO_walkData_size);
roomStream->read(&_walkData[0], header3DO_walkData_size);
// === EXITS === Read in the exits
_exitZone = -1;
_exits.resize(header3DO_exits_size); // TODO!!!!
//for (int idx = 0; idx < numExits; ++idx)
// _exits[idx].load(*rrmStream, IS_ROSE_TATTOO);
// === ENTRANCE === Read in the entrance
roomStream->seek(header3DO_entranceData_offset);
_entrance.load(*roomStream);
// === SOUND LIST === Initialize sound list
roomStream->seek(header3DO_soundList_offset);
_sounds.resize(header3DO_soundList_count);
for (int idx = 0; idx < header3DO_soundList_count; ++idx)
_sounds[idx].load3DO(*roomStream);
// === BACKGROUND PICTURE ===
// load from file rooms\[filename].bg
// it's uncompressed 15-bit RGB555 data
}
// Handle drawing any on-screen interface

View File

@ -72,6 +72,7 @@ struct BgFileHeaderInfo {
* Load the data for the object
*/
void load(Common::SeekableReadStream &s);
void load3DO(Common::SeekableReadStream &s);
};
class Exit: public Common::Rect {
@ -99,6 +100,7 @@ struct SceneEntry {
* Load the data for the object
*/
void load(Common::SeekableReadStream &s);
void load3DO(Common::SeekableReadStream &s);
};
struct SceneSound {
@ -109,6 +111,7 @@ struct SceneSound {
* Load the data for the object
*/
void load(Common::SeekableReadStream &s);
void load3DO(Common::SeekableReadStream &s);
};
class ObjectArray : public Common::Array<Object> {