AGI: Switched booters detection to AD

This commit is contained in:
Eugene Sandulenko 2011-08-13 23:25:19 +01:00
parent 3cb41b5dfc
commit 46354d5772
4 changed files with 82 additions and 135 deletions

View File

@ -137,6 +137,11 @@ enum AgiGameType {
GType_V3 = 3
};
enum BooterDisks {
BooterDisk1 = 0,
BooterDisk2 = 1
};
//
// GF_OLDAMIGAV20 means that the interpreter is an old Amiga AGI interpreter that
// uses value 20 for the computer type (v20 i.e. vComputer) rather than the usual value 5.
@ -647,24 +652,6 @@ struct AgiGame {
int logic_list[256];
};
/**
* 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:
@ -846,6 +833,8 @@ public:
void initVersion();
void setVersion(uint16 version);
const char *getDiskName(uint16 id);
bool canLoadGameStateCurrently();
bool canSaveGameStateCurrently();
};

View File

@ -94,19 +94,13 @@ 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;
};
const char *AgiBase::getDiskName(uint16 id) {
for (int i = 0; _gameDescription->desc.filesDescriptions[i].fileName != NULL; i++)
if (_gameDescription->desc.filesDescriptions[i].fileType == id)
return _gameDescription->desc.filesDescriptions[i].fileName;
bool isDiskImage(Common::SeekableReadStream *stream, Common::String filename, Common::String md5);
bool diskImageExistsInFSList(const Common::FSList &fslist, Common::String md5, Common::String &filename);
return "";
}
}
@ -436,30 +430,6 @@ const ADGameDescription *AgiMetaEngine::fallbackDetect(const FileMap &allFilesXX
warning("More than one (%d) *.wag files found. WAG files ignored", wagFileCount);
}
// Try to detect disk images of AGI v1 and AGI v2.001 booter games
if (!matchedUsingFilenames && !matchedUsingWag) {
for (int i = 0; !booterDescription[i].md5Disk0.empty(); i++) {
Common::String filenameDisk0;
Common::String filenameDisk1;
if (!diskImageExistsInFSList(fslist, booterDescription[i].md5Disk0, filenameDisk0))
continue;
if (!booterDescription[i].md5Disk1.empty())
if (!diskImageExistsInFSList(fslist, booterDescription[i].md5Disk1, filenameDisk1))
continue;
g_fallbackDesc.gameID = booterDescription[i].gameID;
g_fallbackDesc.gameType = booterDescription[i].gameType;
g_fallbackDesc.features = booterDescription[i].features;
g_fallbackDesc.version = booterDescription[i].version;
g_fallbackDesc.desc.gameid = booterDescription[i].id.c_str();
g_fallbackDesc.desc.extra = booterDescription[i].extra.c_str();
return (const ADGameDescription *)&g_fallbackDesc;
}
}
// Check that the AGI interpreter version is a supported one
if (!(g_fallbackDesc.version >= 0x2000 && g_fallbackDesc.version < 0x4000)) {
warning("Unsupported AGI interpreter version 0x%x in AGI's fallback detection. Using default 0x2917", g_fallbackDesc.version);
@ -501,66 +471,6 @@ 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);
}

View File

@ -56,6 +56,7 @@ using Common::GUIO_NONE;
ver \
}
#define BOOTER2(id,extra,fname,md5,size,ver,gid) GAME_LVFPN(id,extra,fname,md5,size,Common::EN_ANY,ver,0,gid,Common::kPlatformPC,GType_V2)
#define GAME(id,extra,md5,ver,gid) GAME_LVFPN(id,extra,"logdir",md5,-1,Common::EN_ANY,ver,0,gid,Common::kPlatformPC,GType_V2)
#define GAME3(id,extra,fname,md5,ver,gid) GAME_LVFPN(id,extra,fname,md5,-1,Common::EN_ANY,ver,0,gid,Common::kPlatformPC,GType_V3)
@ -118,6 +119,69 @@ static const AGIGameDescription gameDescriptions[] = {
// AGI Demo for Kings Quest III and Space Quest I
GAME("agidemo", "Demo Kings Quest III and Space Quest I", "502e6bf96827b6c4d3e67c9cdccd1033", 0x2272, GID_AGIDEMO),
{
// Black Cauldron (PC 3.5" booter) 1.1J [AGI 1.12]
{
"bc",
"Booter 1.1J",
{
{ "bc-d1.img", BooterDisk1, "1d29a82b41c9c7491e2b68d16864bd11", 368640},
{ "bc-d2.img", BooterDisk2, "5568f7a52e787305656246f95e2aa375", 368640},
{ NULL, 0, NULL, 0}
},
Common::EN_ANY,
Common::kPlatformPC,
ADGF_NO_FLAGS,
GUIO_NONE
},
GID_BC,
GType_V1,
0,
0x1120
},
{
// Black Cauldron (PC 3.5" booter) 1.1K [AGI 1.12]
{
"bc",
"Booter 1.1K",
{
{ "bc-d1.img", BooterDisk1, "98a51d3a372baa9df288b6c0f0232567", 368640},
{ "bc-d2.img", BooterDisk2, "5568f7a52e787305656246f95e2aa375", 368640},
{ NULL, 0, NULL, 0}
},
Common::EN_ANY,
Common::kPlatformPC,
ADGF_NO_FLAGS,
GUIO_NONE
},
GID_BC,
GType_V1,
0,
0x1120
},
{
// Black Cauldron (PC 3.5" booter) 1.1M [AGI 1.12]
{
"bc",
"Booter 1.1M",
{
{ "bc-d1.img", BooterDisk1, "edc0e5befbe5e44bb109cdf9137ee12d", 368640},
{ "bc-d2.img", BooterDisk2, "5568f7a52e787305656246f95e2aa375", 368640},
{ NULL, 0, NULL, 0}
},
Common::EN_ANY,
Common::kPlatformPC,
ADGF_NO_FLAGS,
GUIO_NONE
},
GID_BC,
GType_V1,
0,
0x1120
},
// Black Cauldron (Amiga) 2.00 6/14/87
GAME_P("bc", "2.00 1987-06-14", "7b01694af21213b4727bb94476f64eb5", 0x2440, GID_BC, Common::kPlatformAmiga),
@ -143,9 +207,9 @@ static const AGIGameDescription gameDescriptions[] = {
// Black Cauldron (CoCo3 360k) [AGI 2.072]
GAME_PS("bc", "updated", "c4e1937f74e8100cd0152b904434d8b4", 357, 0x2440, GID_BC, Common::kPlatformCoCo3),
// TODO
// These aren't supposed to work now as they require unsupported agi engine 2.01
#if 0
// Donald Duck's Playground (PC Booter) 1.0Q
BOOTER2("ddp", "Booter 1.0Q", "ddp.img", "f323f10abf8140ffb2668b09af2e7b87", 368640, 0x2001, GID_DDP),
// Donald Duck's Playground (Amiga) 1.0C
// Menus not tested
GAME_P("ddp", "1.0C 1987-04-27", "550971d196f65190a5c760d2479406ef", 0x2272, GID_DDP, Common::kPlatformAmiga),
@ -157,7 +221,6 @@ static const AGIGameDescription gameDescriptions[] = {
// reported by Filippos (thebluegr) in bugreport #1654500
// Menus not tested
GAME_PS("ddp", "1.0C 1986-06-09", "550971d196f65190a5c760d2479406ef", 132, 0x2272, GID_DDP, Common::kPlatformPC),
#endif
// Gold Rush! (Amiga) 1.01 1/13/89 aka 2.05 3/9/89 # 2.316
GAME3_PS("goldrush", "1.01 1989-01-13 aka 2.05 1989-03-09", "dirs", "a1d4de3e75c2688c1e2ca2634ffc3bd8", 2399, 0x3149, 0, GID_GOLDRUSH, Common::kPlatformAmiga),
@ -862,16 +925,4 @@ static AGIGameDescription g_fallbackDesc = {
0x2917
};
/**
* Descriptor table for booter games
*/
#define BOOTER_V1(id, extra, md50, md51, gid) { md50, md51, id, extra, gid, GType_V1, ADGF_NO_FLAGS, 0x1120 },
#define BOOTER_V2(id, extra, md50, md51, gid) { md50, md51, id, extra, gid, GType_V2, ADGF_NO_FLAGS, 0x2001 },
static AGIBooterDescription booterDescription[] = {
BOOTER_V1("bc", "booter", "98a51d3a372baa9df288b6c0f0232567", "5568f7a52e787305656246f95e2aa375", GID_BC)
BOOTER_V2("ddp", "booter", "f323f10abf8140ffb2668b09af2e7b87", "", GID_DDP)
{ "", "", "", "", 0, 0, 0, 0 }
};
} // End of namespace Agi

View File

@ -56,11 +56,8 @@ AgiLoader_v1::AgiLoader_v1(AgiEngine *vm) {
int AgiLoader_v1::detectGame() {
// 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);
_filenameDisk0 = _vm->getDiskName(BooterDisk1);
_filenameDisk1 = _vm->getDiskName(BooterDisk2);
return _vm->setupV2Game(_vm->getVersion());
}