ENGINES: Change mac resource fork file detection to use the file cache

Common::MacResMan is now able to open files from a specified
Common::Archive. This is a bit hacky as dynamic_cast is used to break
the Archive encapsulation to retreive the underlying FSNode. It should
however be more correct than the previous code that assumed files were
at the root of the currently running game's path.

AdvancedDetector constructs a Common::Archive from its FileMap based
filesystem cache and uses it to detect the mac resource fork files.

This cuts the time it takes to run the detection code with all the
engines enabled as dynamic plugins on the 3DS to 30 s from 280 s.
This commit is contained in:
Bastien Bouclet 2020-09-12 07:00:53 +02:00
parent 9a1e2368b2
commit 0f2c6cd9ea
14 changed files with 82 additions and 108 deletions

View file

@ -116,15 +116,20 @@ String MacResManager::computeResForkMD5AsString(uint32 length) const {
}
bool MacResManager::open(const String &fileName) {
return open(fileName, SearchMan);
}
bool MacResManager::open(const String &fileName, Archive &archive) {
close();
#ifdef MACOSX
// Check the actual fork on a Mac computer
String fullPath = ConfMan.get("path") + "/" + fileName + "/..namedfork/rsrc";
FSNode resFsNode = FSNode(fullPath);
if (resFsNode.exists()) {
const ArchiveMemberPtr archiveMember = archive.getMember(fileName);
const Common::FSNode *plainFsNode = dynamic_cast<const Common::FSNode *>(archiveMember.get());
if (plainFsNode) {
String fullPath = plainFsNode->getPath() + "/..namedfork/rsrc";
FSNode resFsNode = FSNode(fullPath);
SeekableReadStream *macResForkRawStream = resFsNode.createReadStream();
if (macResForkRawStream && loadFromRawFork(*macResForkRawStream)) {
_baseFileName = fileName;
return true;
@ -134,111 +139,37 @@ bool MacResManager::open(const String &fileName) {
}
#endif
File *file = new File();
// Prefer standalone files first, starting with raw forks
if (file->open(fileName + ".rsrc") && loadFromRawFork(*file)) {
SeekableReadStream *stream = archive.createReadStreamForMember(fileName + ".rsrc");
if (stream && loadFromRawFork(*stream)) {
_baseFileName = fileName;
return true;
}
file->close();
delete stream;
// Then try for AppleDouble using Apple's naming
if (file->open(constructAppleDoubleName(fileName)) && loadFromAppleDouble(*file)) {
stream = archive.createReadStreamForMember(constructAppleDoubleName(fileName));
if (stream && loadFromAppleDouble(*stream)) {
_baseFileName = fileName;
return true;
}
file->close();
delete stream;
// Check .bin for MacBinary next
if (file->open(fileName + ".bin") && loadFromMacBinary(*file)) {
stream = archive.createReadStreamForMember(fileName + ".bin");
if (stream && loadFromMacBinary(*stream)) {
_baseFileName = fileName;
return true;
}
file->close();
delete stream;
// As a last resort, see if just the data fork exists
if (file->open(fileName)) {
stream = archive.createReadStreamForMember(fileName);
if (stream) {
_baseFileName = fileName;
// Maybe file is in MacBinary but without .bin extension?
// Check it here
if (isMacBinary(*file)) {
file->seek(0);
if (loadFromMacBinary(*file))
return true;
}
file->seek(0);
_stream = file;
return true;
}
delete file;
// The file doesn't exist
return false;
}
bool MacResManager::open(const FSNode &path, const String &fileName) {
close();
#ifdef MACOSX
// Check the actual fork on a Mac computer
String fullPath = path.getPath() + "/" + fileName + "/..namedfork/rsrc";
FSNode resFsNode = FSNode(fullPath);
if (resFsNode.exists()) {
SeekableReadStream *macResForkRawStream = resFsNode.createReadStream();
if (macResForkRawStream && loadFromRawFork(*macResForkRawStream)) {
_baseFileName = fileName;
return true;
}
delete macResForkRawStream;
}
#endif
// Prefer standalone files first, starting with raw forks
FSNode fsNode = path.getChild(fileName + ".rsrc");
if (fsNode.exists() && !fsNode.isDirectory()) {
SeekableReadStream *stream = fsNode.createReadStream();
if (loadFromRawFork(*stream)) {
_baseFileName = fileName;
return true;
}
delete stream;
}
// Then try for AppleDouble using Apple's naming
fsNode = path.getChild(constructAppleDoubleName(fileName));
if (fsNode.exists() && !fsNode.isDirectory()) {
SeekableReadStream *stream = fsNode.createReadStream();
if (loadFromAppleDouble(*stream)) {
_baseFileName = fileName;
return true;
}
delete stream;
}
// Check .bin for MacBinary next
fsNode = path.getChild(fileName + ".bin");
if (fsNode.exists() && !fsNode.isDirectory()) {
SeekableReadStream *stream = fsNode.createReadStream();
if (loadFromMacBinary(*stream)) {
_baseFileName = fileName;
return true;
}
delete stream;
}
// As a last resort, see if just the data fork exists
fsNode = path.getChild(fileName);
if (fsNode.exists() && !fsNode.isDirectory()) {
SeekableReadStream *stream = fsNode.createReadStream();
_baseFileName = fileName;
// FIXME: Is this really needed?
if (isMacBinary(*stream)) {
stream->seek(0);
if (loadFromMacBinary(*stream))