Advanced Detector

From ScummVM :: Wiki
Revision as of 22:08, 28 February 2012 by Sev (talk | contribs) (Started to describe how AD works)
Jump to navigation Jump to search

Advanced Detector

If your engine supports a large number of games, or variants then detecting them can be tricky.

As some of the game variants will have files with the same name, but differing contents, detection by filename alone is not sufficient, and a fair number of variants may only differ by small sections of data within the entire file, so opening the file and looking for a "magic header" is not reliable either.
So instead you will take a checksum or even better a hash of the file to detect the exact version, then you will need to write this code to open the files and run this check into your custom MetaEngine...

Sounds like a lot of work?
Well to avoid every engine author having to do this themselves (and the codebase ending up with the maintenance headache of 20+ implementations of this which are almost, but not exactly the same!), the ScummVM Infrastructure Team have provided the Advanced Detector!
This provides a standard framework for filename and MD5 based game detection.

The code for this can be found in engines/advancedDetector.*

To use this, you will have to follow the instructions here, but you will subclass AdvancedMetaEngine instead within your engine's detection.h and detection.cpp.

All you will have to provide is a standard data table of ADGameDescription entries describing each game variant, which is usually placed in a separate detection_tables.h header, which is included in detection.cpp for use there.

This structure plus other parameters are passed to the AdvancedMetaEngine constructor, which can also contain overrides of the default parameters for detection e.g. _md5Bytes is the number of bytes used for the MD5 hash for each file, etc.

It is suggested you consult the code and header comments in engines/advancedDetector.* and look at the examples provided by current engines for a more complete example.

Game detection entry in ScummVM config file

When you look into your .scummvmrc or scummvm.ini (depending on the platform), you will find that generally it has following structure <syntax type="INI"> [scummvm] globalkey1=foo globalkey2=bar versioninfo=1.5.0git2516-g30a372d

[monkey2-vga] description=Monkey Island 2: LeChuck's Revenge (DOS/English) path=/Users/sev/games/scumm/monkey2 gameid=monkey2 language=en platform=pc </syntax>

What you see here is several sections designated by identifiers in square brackets and set of key/value pairs belonging to each such section.

The main section with predefined name 'scummvm' contains global options, which are mainly editable in Options dialog in GUI. Then there go sections for each separate game. Additionally some of ports define their own service sections.

Name of each game is what we are calling target. Target, which is in the sample above specified as monkey2-vga is user-editable identifier unique to the specific user, and could be used for launching the game from command line.

Then each entry has description which is also user-editable, path to the game, and gameid. gameid is a service name which uniquely identifies the game within whole ScummVM. There should be no clashes, and each engine knows which games it does support. First engine which finds a match for gameid will be used to run the game. This is why it is important to keep this ID unique, since there is no guarantee is sequence of engines which ScummVM probes when launching a game.

Keys platform and language are used for narrowing down the possible game candidate but are fully optional.

ADGameDescription table

AGGameDescription table has the following structure:

<syntax type="C++"> struct ADGameDescription { const char *gameid; const char *extra; ADGameFileDescription filesDescriptions[14]; Common::Language language; Common::Platform platform;

/** * A bitmask of extra flags. The top 16 bits are reserved for generic flags * defined in the ADGameFlags. This leaves 16 bits to be used by client * code. */ uint32 flags;

const char *guioptions; }; </syntax>

Typical ADGameDescription table will look as follows:

static const CINEGameDescription gameDescriptions[] = { { { "fw", "", AD_ENTRY1("part01", "61d003202d301c29dd399acfb1354310"), Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, GUIO0() }, GType_FW, 0, }, { AD_TABLE_END_MARKER, 0, 0 } };