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());
directory.skip(sizeof(uint32));
while (directory.pos() < directory.size()) {
while (directory.pos() + 4 < directory.size()) {
DirectoryEntry entry(this);
entry.readFromStream(directory);
if (entry.hasSubEntries()) {
_directory.push_back(entry);
}
if (_multipleRoom)
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;
}
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)) {
_readDirectory();
return true;

View file

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

View file

@ -27,9 +27,15 @@ namespace Myst3 {
DirectoryEntry::DirectoryEntry(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();
_unk = 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) {
for (uint i = 0; i < _subentries.size(); i++) {
_subentries[i].dumpToFile(inStream, _index);

View file

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

View file

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