ENGINES: Add res-only and data-only MD5 computational methods

The current way of ADGF_MACRESFORK is an amalgam of bugs and history. Those
are clean ways for direct specification. It's not accessible yet
This commit is contained in:
Vladimir Serbinenko 2022-12-19 23:01:20 +01:00 committed by Eugene Sandulenko
parent 1ebbc4071c
commit a2233a2166
3 changed files with 58 additions and 35 deletions

View File

@ -190,16 +190,6 @@ DetectedGame AdvancedMetaEngineDetection::toDetectedGame(const ADDetectedGame &a
game.hasUnknownFiles = adGame.hasUnknownFiles;
game.matchedFiles = adGame.matchedFiles;
// Now specify the computation method for each file entry.
// TODO: This could be potentially overridden by use of upper part of adGame.fileType
// so, individual files could have their own computation method
for (FilePropertiesMap::iterator file = game.matchedFiles.begin(); file != game.matchedFiles.end(); ++file) {
if (desc->flags & ADGF_MACRESFORK)
file->_value.md5prop = (MD5Properties)(file->_value.md5prop | kMD5MacResFork);
if (desc->flags & ADGF_TAILMD5)
file->_value.md5prop = (MD5Properties)(file->_value.md5prop | kMD5Tail);
}
if (extraInfo && !extraInfo->targetID.empty()) {
game.preferredTarget = generatePreferredTarget(desc, _maxAutogenLength, extraInfo->targetID);
} else {
@ -518,7 +508,7 @@ static MD5Properties gameFlagsToDefaultMD5Props(uint32 flags) {
MD5Properties ret = kMD5Head;
if (flags & ADGF_MACRESFORK) {
ret = (MD5Properties) (ret | kMD5MacResFork);
ret = (MD5Properties) (ret | kMD5MacResOrDataFork);
}
if (flags & ADGF_TAILMD5) {
@ -556,28 +546,40 @@ bool AdvancedMetaEngine::getFilePropertiesExtern(uint md5Bytes, const FileMap &a
}
static bool getFilePropertiesIntern(uint md5Bytes, const AdvancedMetaEngine::FileMap &allFiles, MD5Properties md5prop, const Common::String &fname, FileProperties &fileProps) {
if (md5prop & kMD5MacResFork) {
if (md5prop & (kMD5MacResFork | kMD5MacDataFork)) {
FileMapArchive fileMapArchive(allFiles);
bool is_legacy = ((md5prop & kMD5MacMask) == kMD5MacResOrDataFork);
if (md5prop & kMD5MacResFork) {
Common::MacResManager macResMan;
Common::MacResManager macResMan;
if (!macResMan.open(fname, fileMapArchive))
return false;
if (!macResMan.open(fname, fileMapArchive))
return false;
fileProps.md5 = macResMan.computeResForkMD5AsString(md5Bytes, ((md5prop & kMD5Tail) != 0));
fileProps.size = macResMan.getResForkDataSize();
fileProps.md5 = macResMan.computeResForkMD5AsString(md5Bytes, ((md5prop & kMD5Tail) != 0));
fileProps.size = macResMan.getResForkDataSize();
if (fileProps.size != 0)
return true;
Common::SeekableReadStream *dataFork = Common::MacResManager::openFileOrDataFork(fname, fileMapArchive);
if (dataFork && dataFork->size()) {
fileProps.size = dataFork->size();
fileProps.md5 = Common::computeStreamMD5AsString(*dataFork, md5Bytes);
delete dataFork;
return true;
if (fileProps.size != 0) {
fileProps.md5prop = (MD5Properties)((md5prop & kMD5Tail) | kMD5MacResFork);
return true;
}
}
delete dataFork;
if (md5prop & kMD5MacDataFork) {
Common::SeekableReadStream *dataFork = Common::MacResManager::openFileOrDataFork(fname, fileMapArchive);
// Logically 0-sized data fork is valid but legacy code continues fallback
if (dataFork && (dataFork->size() || !is_legacy)) {
fileProps.size = dataFork->size();
fileProps.md5 = Common::computeStreamMD5AsString(*dataFork, md5Bytes);
fileProps.md5prop = (MD5Properties)((md5prop & kMD5Tail) | kMD5MacDataFork);
delete dataFork;
return true;
}
delete dataFork;
}
// In modern case stop here
if (!is_legacy)
return false;
}
if (!allFiles.contains(fname))
@ -595,6 +597,7 @@ static bool getFilePropertiesIntern(uint md5Bytes, const AdvancedMetaEngine::Fil
fileProps.size = testFile.size();
fileProps.md5 = Common::computeStreamMD5AsString(testFile, md5Bytes);
fileProps.md5prop = (MD5Properties) (md5prop & kMD5Tail);
return true;
}

View File

@ -166,15 +166,32 @@ Common::U32String DetectionResults::generateUnknownGameReport(bool translate, ui
}
char md5PropToCacheChar(MD5Properties flags) {
if (flags & kMD5MacResFork) {
switch (flags & kMD5MacMask) {
case kMD5MacDataFork: {
if (flags & kMD5Tail)
return 'd';
return 'z';
}
case kMD5MacResOrDataFork: {
if (flags & kMD5Tail)
return 'e';
return 'm';
}
if (flags & kMD5Tail)
return 't';
return 'f';
case kMD5MacResFork: {
if (flags & kMD5Tail)
return 'x';
return 'r';
}
default: {
if (flags & kMD5Tail)
return 't';
return 'f';
}
}
}
Common::U32String generateUnknownGameReport(const DetectedGames &detectedGames, bool translate, bool fullPath, uint32 wordwrapAt) {

View File

@ -103,9 +103,12 @@ enum GameSupportLevel {
*/
enum MD5Properties {
kMD5Head = 0 << 1, // the MD5 is calculated from the head, default
kMD5Tail = 1 << 1, // the MD5 is calculated from the tail
kMD5MacResFork = 1 << 2 // the MD5 is calculated from the Mac Resource fork (head or tail)
kMD5Head = 0 << 1, // the MD5 is calculated from the head, default
kMD5Tail = 1 << 1, // the MD5 is calculated from the tail
kMD5MacResFork = 1 << 2, // the MD5 is calculated from the Mac Resource fork (no fall back) (head or tail)
kMD5MacDataFork = 1 << 3, // the MD5 is calculated from the Mac Data fork (head or tail)
kMD5MacResOrDataFork = kMD5MacResFork | kMD5MacDataFork, // the MD5 is calculated from the Mac Resource fork falling back to data fork (head or tail). Deprecated.
kMD5MacMask = kMD5MacResFork | kMD5MacDataFork, // Mask for mac type
};
char md5PropToCacheChar(MD5Properties val);