MYST3: Properly read the directory of multiple room archives

This commit is contained in:
Bastien Bouclet 2012-01-07 21:31:52 +01:00
parent 4acbdde391
commit 37586bb534
5 changed files with 32 additions and 18 deletions

View file

@ -51,12 +51,15 @@ void Archive::_readDirectory() {
Common::MemoryReadStream directory(buf.getData(), buf.size()); Common::MemoryReadStream directory(buf.getData(), buf.size());
directory.skip(sizeof(uint32)); directory.skip(sizeof(uint32));
while (directory.pos() < directory.size()) { while (directory.pos() + 4 < directory.size()) {
DirectoryEntry entry(this); DirectoryEntry entry(this);
entry.readFromStream(directory);
if (entry.hasSubEntries()) { if (_multipleRoom)
_directory.push_back(entry); entry.readFromStream(directory, 0);
} else
entry.readFromStream(directory, _roomName);
_directory.push_back(entry);
} }
} }
@ -87,7 +90,14 @@ const DirectorySubEntry *Archive::getDescription(uint16 index, uint16 face, Dire
return 0; return 0;
} }
bool Archive::open(const char *fileName) { bool Archive::open(const char *fileName, const char *room) {
// Copy the room name if provided
// If the room name is not provided, it is assumed that
// we are opening a multi-room archive
_multipleRoom = room == 0;
if (!_multipleRoom)
Common::strlcpy(_roomName, room, sizeof(_roomName));
if (_file.open(fileName)) { if (_file.open(fileName)) {
_readDirectory(); _readDirectory();
return true; return true;

View file

@ -32,6 +32,8 @@ namespace Myst3 {
class Archive { class Archive {
private: private:
bool _multipleRoom;
char _roomName[5];
Common::File _file; Common::File _file;
Common::Array<DirectoryEntry> _directory; Common::Array<DirectoryEntry> _directory;
@ -44,7 +46,7 @@ class Archive {
void dumpDirectory(); void dumpDirectory();
void dumpToFiles(); void dumpToFiles();
bool open(const char *fileName); bool open(const char *fileName, const char *room);
void close(); void close();
}; };

View file

@ -27,9 +27,15 @@ namespace Myst3 {
DirectoryEntry::DirectoryEntry(Archive *archive) : DirectoryEntry::DirectoryEntry(Archive *archive) :
_archive(archive) { _archive(archive) {
memset(_roomName, 0, sizeof(_roomName));
} }
void DirectoryEntry::readFromStream(Common::SeekableReadStream &inStream) { void DirectoryEntry::readFromStream(Common::SeekableReadStream &inStream, const char *room) {
if (room == 0)
inStream.read(_roomName, 4);
else
Common::strlcpy(_roomName, room, sizeof(_roomName));
_index = inStream.readUint16LE(); _index = inStream.readUint16LE();
_unk = inStream.readByte(); _unk = inStream.readByte();
byte subItemCount = inStream.readByte(); byte subItemCount = inStream.readByte();
@ -55,10 +61,6 @@ void DirectoryEntry::dump() {
} }
} }
bool DirectoryEntry::hasSubEntries() {
return !_subentries.empty();
}
void DirectoryEntry::dumpToFiles(Common::SeekableReadStream &inStream) { void DirectoryEntry::dumpToFiles(Common::SeekableReadStream &inStream) {
for (uint i = 0; i < _subentries.size(); i++) { for (uint i = 0; i < _subentries.size(); i++) {
_subentries[i].dumpToFile(inStream, _index); _subentries[i].dumpToFile(inStream, _index);

View file

@ -31,6 +31,7 @@ namespace Myst3 {
class DirectoryEntry { class DirectoryEntry {
private: private:
char _roomName[5];
uint16 _index; uint16 _index;
uint8 _unk; uint8 _unk;
Common::Array<DirectorySubEntry> _subentries; Common::Array<DirectorySubEntry> _subentries;
@ -41,11 +42,10 @@ class DirectoryEntry {
DirectoryEntry() {} DirectoryEntry() {}
DirectoryEntry(Archive *archive); DirectoryEntry(Archive *archive);
void readFromStream(Common::SeekableReadStream &inStream); void readFromStream(Common::SeekableReadStream &inStream, const char *room);
void dump(); void dump();
void dumpToFiles(Common::SeekableReadStream &inStream); void dumpToFiles(Common::SeekableReadStream &inStream);
DirectorySubEntry *getItemDescription(uint16 face, DirectorySubEntry::ResourceType type); DirectorySubEntry *getItemDescription(uint16 face, DirectorySubEntry::ResourceType type);
bool hasSubEntries();
uint16 getIndex() { return _index; } uint16 getIndex() { return _index; }
}; };

View file

@ -107,15 +107,15 @@ Common::Error Myst3Engine::run() {
_system->setupScreen(w, h, false, true); _system->setupScreen(w, h, false, true);
_system->showMouse(false); _system->showMouse(false);
if (!_archiveLANG->open("ENGLISH.m3t")) { if (!_archiveLANG->open("ENGLISH.m3t", 0)) {
error("Unable to open archive ENGLISH.m3t"); error("Unable to open archive ENGLISH.m3t");
} }
if (!_archiveRSRC->open("RSRC.m3r")) { if (!_archiveRSRC->open("RSRC.m3r", 0)) {
error("Unable to open archive RSRC.m3r"); error("Unable to open archive RSRC.m3r");
} }
if (!_archiveOVER->open("OVER101.m3o")) { if (!_archiveOVER->open("OVER101.m3o", 0)) {
// OVER101 is not required // OVER101 is not required
delete _archiveOVER; delete _archiveOVER;
_archiveOVER = 0; _archiveOVER = 0;
@ -331,7 +331,7 @@ void Myst3Engine::loadNode(uint16 nodeID, uint32 roomID, uint32 ageID) {
Common::String nodeFile = Common::String::format("%snodes.m3a", newRoomName); Common::String nodeFile = Common::String::format("%snodes.m3a", newRoomName);
_archive->close(); _archive->close();
if (!_archive->open(nodeFile.c_str())) { if (!_archive->open(nodeFile.c_str(), newRoomName)) {
error("Unable to open archive %s", nodeFile.c_str()); error("Unable to open archive %s", nodeFile.c_str());
} }
} }