mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-17 15:18:11 +00:00
AGI: Do not try to pass filenames of disk images from the detector to engine
This commit is contained in:
parent
1f680ecbc8
commit
4d4a558f7b
@ -631,6 +631,24 @@ struct AgiGame {
|
||||
Common::Rect mouseFence; /**< rectangle set by fence.mouse command */
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if a disk image with the given MD5 sum exists in the search path.
|
||||
*
|
||||
* @param md5 MD5 sum of the disk image to be searched
|
||||
* @param filename Filled with a filename in case the image is found
|
||||
* @return True if found, otherwise false.
|
||||
*/
|
||||
bool diskImageExists(Common::String md5, Common::String &filename);
|
||||
|
||||
/**
|
||||
* Get MD5 sums for a given game from the booter game description table.
|
||||
*
|
||||
* @param gid Game ID of the game
|
||||
* @param md5Disk0 Filled with the MD5 sum of disk 0
|
||||
* @param md5Disk1 Filled with the MD5 sum of disk 1 if there are two disks
|
||||
*/
|
||||
bool getBooterMD5Sums(AgiGameID gid, Common::String &md5Disk0, Common::String &md5Disk1);
|
||||
|
||||
class AgiLoader {
|
||||
public:
|
||||
|
||||
@ -649,18 +667,14 @@ public:
|
||||
class AgiLoader_v1 : public AgiLoader {
|
||||
private:
|
||||
AgiEngine *_vm;
|
||||
Common::String _dsk0Name;
|
||||
Common::String _dsk1Name;
|
||||
Common::String _filenameDisk0;
|
||||
Common::String _filenameDisk1;
|
||||
|
||||
int loadDir(AgiDir *agid, int offset, int num);
|
||||
uint8 *loadVolRes(AgiDir *agid);
|
||||
|
||||
public:
|
||||
AgiLoader_v1(AgiEngine *vm, Common::String dsk0, Common::String dsk1) {
|
||||
_vm = vm;
|
||||
_dsk0Name = dsk0;
|
||||
_dsk1Name = dsk1;
|
||||
}
|
||||
AgiLoader_v1(AgiEngine *vm);
|
||||
|
||||
virtual int init();
|
||||
virtual int deinit();
|
||||
@ -715,6 +729,7 @@ public:
|
||||
virtual int loadWords(const char *);
|
||||
};
|
||||
|
||||
|
||||
class GfxMgr;
|
||||
class SpritesMgr;
|
||||
class Menu;
|
||||
|
@ -48,9 +48,6 @@ struct AGIGameDescription {
|
||||
int gameType;
|
||||
uint32 features;
|
||||
uint16 version;
|
||||
|
||||
Common::String dsk0Name;
|
||||
Common::String dsk1Name;
|
||||
};
|
||||
|
||||
uint32 AgiBase::getGameID() const {
|
||||
@ -97,6 +94,20 @@ void AgiBase::initVersion() {
|
||||
_gameVersion = _gameDescription->version;
|
||||
}
|
||||
|
||||
struct AGIBooterDescription {
|
||||
Common::String md5Disk0;
|
||||
Common::String md5Disk1;
|
||||
Common::String id;
|
||||
Common::String extra;
|
||||
int gameID;
|
||||
int gameType;
|
||||
uint32 features;
|
||||
uint16 version;
|
||||
};
|
||||
|
||||
bool isDiskImage(Common::SeekableReadStream *stream, Common::String filename, Common::String md5);
|
||||
bool diskImageExistsInFSList(const Common::FSList &fslist, Common::String md5, Common::String &filename);
|
||||
|
||||
}
|
||||
|
||||
static const PlainGameDescriptor agiGames[] = {
|
||||
@ -294,9 +305,7 @@ SaveStateDescriptor AgiMetaEngine::querySaveMetaInfos(const char *target, int sl
|
||||
|
||||
const ADGameDescription *AgiMetaEngine::fallbackDetect(const FileMap &allFilesXXX, const Common::FSList &fslist) const {
|
||||
typedef Common::HashMap<Common::String, int32> IntMap;
|
||||
typedef Common::HashMap<Common::String, Common::FSNode> NodeMap;
|
||||
IntMap allFiles;
|
||||
NodeMap allNodes;
|
||||
bool matchedUsingFilenames = false;
|
||||
bool matchedUsingWag = false;
|
||||
int wagFileCount = 0;
|
||||
@ -324,7 +333,6 @@ const ADGameDescription *AgiMetaEngine::fallbackDetect(const FileMap &allFilesXX
|
||||
Common::String filename = file->getName();
|
||||
filename.toLowercase();
|
||||
allFiles[filename] = true; // Save the filename in a hash table
|
||||
allNodes[filename] = *file; // ...and also the FSNode
|
||||
|
||||
if (filename.hasSuffix(".wag")) {
|
||||
// Save latest found *.wag file's path (Can be used to open the file, the name can't)
|
||||
@ -429,41 +437,25 @@ const ADGameDescription *AgiMetaEngine::fallbackDetect(const FileMap &allFilesXX
|
||||
|
||||
// Try to detect disk images of AGI v1 and AGI v2.001 booter games
|
||||
if (!matchedUsingFilenames && !matchedUsingWag) {
|
||||
int index = -1;
|
||||
|
||||
for (IntMap::const_iterator f = allFiles.begin(); f != allFiles.end(); ++f) {
|
||||
if (f->_key.hasSuffix(".dsk") || f->_key.hasSuffix(".img")) {
|
||||
Common::File file;
|
||||
file.open(allNodes[f->_key]);
|
||||
Common::String md5str = Common::computeStreamMD5AsString(file, detectionParams.md5Bytes);
|
||||
debug(3, "Agi::fallbackDetector: disk image (%s) found with md5 sum (%s) ", f->_key.c_str(), md5str.c_str());
|
||||
for (int i = 0; !booterDescription[i].md5Disk0.empty(); i++) {
|
||||
Common::String filenameDisk0;
|
||||
Common::String filenameDisk1;
|
||||
|
||||
for (int i = 0; !booterDescription[i].md5str_dsk0.empty(); i++) {
|
||||
if (booterDescription[i].md5str_dsk0 == md5str) {
|
||||
index = i;
|
||||
g_fallbackDesc.dsk0Name = f->_key;
|
||||
}
|
||||
if (booterDescription[i].md5str_dsk1 == md5str) {
|
||||
index = i;
|
||||
g_fallbackDesc.dsk1Name = f->_key;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (index >= 0) {
|
||||
if ((booterDescription[index].md5str_dsk0.empty() == g_fallbackDesc.dsk0Name.empty()) &&
|
||||
(booterDescription[index].md5str_dsk1.empty() == g_fallbackDesc.dsk1Name.empty())) {
|
||||
g_fallbackDesc.gameID = booterDescription[index].gameID;
|
||||
g_fallbackDesc.gameType = booterDescription[index].gameType;
|
||||
g_fallbackDesc.features = booterDescription[index].features;
|
||||
g_fallbackDesc.version = booterDescription[index].version;
|
||||
if (!diskImageExistsInFSList(fslist, booterDescription[i].md5Disk0, filenameDisk0))
|
||||
continue;
|
||||
if (!booterDescription[i].md5Disk1.empty())
|
||||
if (!diskImageExistsInFSList(fslist, booterDescription[i].md5Disk1, filenameDisk1))
|
||||
continue;
|
||||
|
||||
g_fallbackDesc.desc.gameid = booterDescription[index].id.c_str();
|
||||
g_fallbackDesc.desc.extra = booterDescription[index].extra.c_str();
|
||||
g_fallbackDesc.gameID = booterDescription[i].gameID;
|
||||
g_fallbackDesc.gameType = booterDescription[i].gameType;
|
||||
g_fallbackDesc.features = booterDescription[i].features;
|
||||
g_fallbackDesc.version = booterDescription[i].version;
|
||||
|
||||
return (const ADGameDescription *)&g_fallbackDesc;
|
||||
}
|
||||
g_fallbackDesc.desc.gameid = booterDescription[i].id.c_str();
|
||||
g_fallbackDesc.desc.extra = booterDescription[i].extra.c_str();
|
||||
|
||||
return (const ADGameDescription *)&g_fallbackDesc;
|
||||
}
|
||||
}
|
||||
|
||||
@ -508,6 +500,66 @@ const ADGameDescription *AgiMetaEngine::fallbackDetect(const FileMap &allFilesXX
|
||||
|
||||
namespace Agi {
|
||||
|
||||
bool isDiskImage(Common::SeekableReadStream *stream, Common::String filename, Common::String md5) {
|
||||
if (!(filename.hasSuffix(".dsk") || filename.hasSuffix(".img")))
|
||||
return false;
|
||||
|
||||
if (stream->size() == 368640 && computeStreamMD5AsString(*stream, 5000) == md5)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool diskImageExistsInFSList(const Common::FSList &fslist, Common::String md5, Common::String &filename) {
|
||||
for (Common::FSList::const_iterator x = fslist.begin(); x != fslist.end(); x++) {
|
||||
if (x->isDirectory()) continue;
|
||||
|
||||
Common::SeekableReadStream *stream = x->createReadStream();
|
||||
if (isDiskImage(stream, x->getName(), md5)) {
|
||||
filename = x->getName();
|
||||
delete stream;
|
||||
return true;
|
||||
}
|
||||
delete stream;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool diskImageExists(Common::String md5, Common::String &filename) {
|
||||
Common::ArchiveMemberList files;
|
||||
SearchMan.listMembers(files);
|
||||
|
||||
Common::File file;
|
||||
for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); x++) {
|
||||
file.open((*x)->getName());
|
||||
if (isDiskImage(&file, (*x)->getName(), md5)) {
|
||||
filename = (*x)->getName();
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool getBooterMD5Sums(AgiGameID gid, Common::String &md5Disk0, Common::String &md5Disk1) {
|
||||
AGIBooterDescription *booter = NULL;
|
||||
int i = 0;
|
||||
while (!booterDescription[i].md5Disk0.empty()) {
|
||||
if (booterDescription[i].gameID == gid)
|
||||
booter = &booterDescription[i];
|
||||
i++;
|
||||
}
|
||||
if (booter == NULL)
|
||||
return false;
|
||||
|
||||
md5Disk0 = booter->md5Disk0;
|
||||
md5Disk1 = booter->md5Disk1;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AgiBase::canLoadGameStateCurrently() {
|
||||
return (!(getGameType() == GType_PreAGI) && getflag(fMenusWork) && !_noSaveLoadAllowed);
|
||||
}
|
||||
@ -525,7 +577,7 @@ int AgiEngine::agiDetectGame() {
|
||||
assert(_gameDescription != NULL);
|
||||
|
||||
if (getVersion() <= 0x2001) {
|
||||
_loader = new AgiLoader_v1(this, _gameDescription->dsk0Name, _gameDescription->dsk1Name);
|
||||
_loader = new AgiLoader_v1(this);
|
||||
} else if (getVersion() <= 0x2999) {
|
||||
_loader = new AgiLoader_v2(this);
|
||||
} else {
|
||||
|
@ -37,9 +37,7 @@ using Common::GUIO_NONE;
|
||||
gid, \
|
||||
interp, \
|
||||
features, \
|
||||
ver, \
|
||||
"", \
|
||||
"" \
|
||||
ver \
|
||||
}
|
||||
|
||||
#define GAME_LVFPNF(id,name,fname,md5,size,lang,ver,features,gid,platform,interp) { \
|
||||
@ -55,9 +53,7 @@ using Common::GUIO_NONE;
|
||||
gid, \
|
||||
interp, \
|
||||
features, \
|
||||
ver, \
|
||||
"", \
|
||||
"" \
|
||||
ver \
|
||||
}
|
||||
|
||||
#define GAME(id,extra,md5,ver,gid) GAME_LVFPN(id,extra,"logdir",md5,-1,Common::EN_ANY,ver,0,gid,Common::kPlatformPC,GType_V2)
|
||||
@ -200,9 +196,7 @@ static const AGIGameDescription gameDescriptions[] = {
|
||||
GID_GOLDRUSH,
|
||||
GType_V3,
|
||||
GF_MACGOLDRUSH,
|
||||
0x3149,
|
||||
"",
|
||||
""
|
||||
0x3149
|
||||
},
|
||||
|
||||
|
||||
@ -520,9 +514,7 @@ static const AGIGameDescription gameDescriptions[] = {
|
||||
GID_SQ2,
|
||||
GType_V2,
|
||||
0,
|
||||
0x2936,
|
||||
"",
|
||||
""
|
||||
0x2936
|
||||
},
|
||||
|
||||
|
||||
@ -667,9 +659,7 @@ static const AGIGameDescription gameDescriptions[] = {
|
||||
GID_FANMADE,
|
||||
GType_V2,
|
||||
GF_AGDS,
|
||||
0x2440,
|
||||
"",
|
||||
""
|
||||
0x2440
|
||||
},
|
||||
|
||||
{
|
||||
@ -686,9 +676,7 @@ static const AGIGameDescription gameDescriptions[] = {
|
||||
GID_GETOUTTASQ,
|
||||
GType_V2,
|
||||
0,
|
||||
0x2440,
|
||||
"",
|
||||
""
|
||||
0x2440
|
||||
},
|
||||
|
||||
FANMADE_F("Half-Death - Terror At White-Mesa", "b62c05d0ace878261392073f57ae788c", GF_AGIMOUSE),
|
||||
@ -843,9 +831,7 @@ static const AGIGameDescription gameDescriptions[] = {
|
||||
GID_FANMADE,
|
||||
GType_V3,
|
||||
GF_FANMADE,
|
||||
0x3149,
|
||||
"",
|
||||
"",
|
||||
0x3149
|
||||
},
|
||||
FANMADE_SVP("V - The Graphical Adventure", "1646eaade74f137a9041eb427a389969", 768, 0x2440, Common::kPlatformCoCo3),
|
||||
|
||||
@ -853,7 +839,7 @@ static const AGIGameDescription gameDescriptions[] = {
|
||||
FANMADE("Voodoo Girl - Queen of the Darned (v1.2 2002 Mar 29)", "11d0417b7b886f963d0b36789dac4c8f"),
|
||||
FANMADE("Wizaro (v0.1)", "abeec1eda6eaf8dbc52443ea97ff140c"),
|
||||
|
||||
{ AD_TABLE_END_MARKER, 0, 0, 0, 0, "", "" }
|
||||
{ AD_TABLE_END_MARKER, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
/**
|
||||
@ -873,25 +859,16 @@ static AGIGameDescription g_fallbackDesc = {
|
||||
GID_FANMADE,
|
||||
GType_V2,
|
||||
GF_FANMADE,
|
||||
0x2917,
|
||||
"",
|
||||
""
|
||||
0x2917
|
||||
};
|
||||
|
||||
/**
|
||||
* Detection table for booter games.
|
||||
* Descriptor table for booter games
|
||||
*/
|
||||
static const struct {
|
||||
Common::String md5str_dsk0;
|
||||
Common::String md5str_dsk1;
|
||||
Common::String id;
|
||||
Common::String extra;
|
||||
int gameID;
|
||||
int gameType;
|
||||
uint32 features;
|
||||
uint16 version;
|
||||
} booterDescription[] = {
|
||||
{ "f323f10abf8140ffb2668b09af2e7b87", "", "ddp", "booter", GID_DDP, GType_V2, ADGF_NO_FLAGS, 0x2001 },
|
||||
#define BOOTER_V2(id, extra, md50, md51, gid) { md50, md51, id, extra, gid, GType_V2, ADGF_NO_FLAGS, 0x2001 },
|
||||
|
||||
static AGIBooterDescription booterDescription[] = {
|
||||
BOOTER_V2("ddp", "booter", "f323f10abf8140ffb2668b09af2e7b87", "", GID_DDP)
|
||||
{ "", "", "", "", 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
#include "agi/agi.h"
|
||||
#include "common/md5.h"
|
||||
|
||||
#define offsetTHS(track,head,sector) (512 * ((((track) * 2 + (head)) * 9) + (sector)))
|
||||
#define offset(sector) offsetTHS(sector / 18, (sector % 18) / 9, (sector % 18) % 9)
|
||||
@ -41,6 +42,18 @@
|
||||
|
||||
namespace Agi {
|
||||
|
||||
|
||||
AgiLoader_v1::AgiLoader_v1(AgiEngine *vm) {
|
||||
_vm = vm;
|
||||
|
||||
// Find filenames for the disk images
|
||||
Common::String md5Disk0, md5Disk1;
|
||||
getBooterMD5Sums((AgiGameID)_vm->getGameID(), md5Disk0, md5Disk1);
|
||||
diskImageExists(md5Disk0, _filenameDisk0);
|
||||
if (!md5Disk1.empty())
|
||||
diskImageExists(md5Disk1, _filenameDisk1);
|
||||
}
|
||||
|
||||
int AgiLoader_v1::detectGame() {
|
||||
return _vm->setupV2Game(_vm->getVersion());
|
||||
}
|
||||
@ -48,7 +61,7 @@ int AgiLoader_v1::detectGame() {
|
||||
int AgiLoader_v1::loadDir(AgiDir *agid, int offset, int num) {
|
||||
Common::File fp;
|
||||
|
||||
if (!fp.open(_dsk0Name))
|
||||
if (!fp.open(_filenameDisk0))
|
||||
return errBadFileOpen;
|
||||
|
||||
// Cleanup
|
||||
@ -108,7 +121,7 @@ uint8 *AgiLoader_v1::loadVolRes(struct AgiDir *agid) {
|
||||
int sec = agid->offset >> 16;
|
||||
int off = agid->offset & 0xFFFF;
|
||||
|
||||
fp.open(_dsk0Name);
|
||||
fp.open(_filenameDisk0);
|
||||
fp.seek(offset(sec) + off, SEEK_SET);
|
||||
|
||||
int signature = fp.readUint16BE();
|
||||
|
Loading…
Reference in New Issue
Block a user