2007-05-30 21:56:52 +00:00
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers , whose names
* are too numerous to list here . Please refer to the COPYRIGHT
* file distributed with this source distribution .
2006-10-02 22:21:57 +00:00
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version 2
* of the License , or ( at your option ) any later version .
2014-02-18 02:34:20 +01:00
*
2006-10-02 22:21:57 +00:00
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
2014-02-18 02:34:20 +01:00
*
2006-10-02 22:21:57 +00:00
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
*
*/
2011-06-14 15:25:33 +02:00
2009-01-29 22:13:01 +00:00
# ifndef ENGINES_ADVANCED_DETECTOR_H
# define ENGINES_ADVANCED_DETECTOR_H
2006-10-02 22:21:57 +00:00
2008-02-02 00:54:52 +00:00
# include "engines/metaengine.h"
2011-04-25 15:26:38 -05:00
# include "engines/engine.h"
2006-11-12 03:23:29 +00:00
2012-06-27 04:07:32 +02:00
# include "common/hash-str.h"
2012-02-22 15:33:29 +01:00
# include "common/gui_options.h" // FIXME: Temporary hack?
2011-04-24 11:34:27 +03:00
namespace Common {
class Error ;
class FSList ;
}
2011-06-14 17:13:02 +02:00
/**
* A record describing a file to be matched for detecting a specific game
* variant . A list of such records is used inside every ADGameDescription to
* enable detection .
*/
2006-10-02 22:21:57 +00:00
struct ADGameFileDescription {
2018-04-29 00:16:42 +02:00
const char * fileName ; ///< Name of described file.
uint16 fileType ; ///< Optional. Not used during detection, only by engines.
const char * md5 ; ///< MD5 of (the beginning of) the described file. Optional. Set to NULL to ignore.
int32 fileSize ; ///< Size of the described file. Set to -1 to ignore.
2006-10-02 22:21:57 +00:00
} ;
2011-06-14 17:13:02 +02:00
/**
* A shortcut to produce an empty ADGameFileDescription record . Used to mark
* the end of a list of these .
*/
2010-08-01 20:47:46 +00:00
# define AD_LISTEND {NULL, 0, NULL, 0}
2011-06-14 17:13:02 +02:00
/**
* A shortcut to produce a list of ADGameFileDescription records with only one
* record that contains just a filename with an MD5 , and no file size .
*/
2010-08-01 20:47:46 +00:00
# define AD_ENTRY1(f, x) {{ f, 0, x, -1}, AD_LISTEND}
2011-06-14 17:13:02 +02:00
/**
* A shortcut to produce a list of ADGameFileDescription records with only one
* record that contains just a filename with an MD5 , plus a file size .
*/
2010-08-01 20:47:46 +00:00
# define AD_ENTRY1s(f, x, s) {{ f, 0, x, s}, AD_LISTEND}
2007-02-13 22:25:25 +00:00
2020-11-26 23:58:04 +01:00
/**
* A shortcut to produce a list of ADGameFileDescription records with only two
* records that contains just a filename with an MD5 , plus a file size .
*/
# define AD_ENTRY2s(f1, x1, s1, f2, x2, s2) {{f1, 0, x1, s1}, {f2, 0, x2, s2}, AD_LISTEND}
2007-02-13 01:28:18 +00:00
enum ADGameFlags {
2018-04-29 00:16:42 +02:00
ADGF_NO_FLAGS = 0 ,
2020-11-08 20:05:35 +01:00
ADGF_REMASTERED = ( 1 < < 18 ) , ///< add "-remastered' to gameid
ADGF_AUTOGENTARGET = ( 1 < < 19 ) , ///< automatically generate gameid from extra
ADGF_UNSTABLE = ( 1 < < 20 ) , ///< flag to designate not yet officially-supported games that are not fit for public testing
ADGF_TESTING = ( 1 < < 21 ) , ///< flag to designate not yet officially-supported games that are fit for public testing
ADGF_PIRATED = ( 1 < < 22 ) , ///< flag to designate well known pirated versions with cracks
ADGF_UNSUPPORTED = ( 1 < < 23 ) , ///< flag to mark certain versions (like fan translations) not to be run for various reasons. A custom message can be provided in the ADGameDescription::extra field.
2018-04-29 00:16:42 +02:00
ADGF_ADDENGLISH = ( 1 < < 24 ) , ///< always add English as language option
ADGF_MACRESFORK = ( 1 < < 25 ) , ///< the md5 for this entry will be calculated from the resource fork
2011-06-14 17:13:02 +02:00
ADGF_USEEXTRAASTITLE = ( 1 < < 26 ) , ///< Extra field value will be used as main game title, not gameid
2018-04-29 00:16:42 +02:00
ADGF_DROPLANGUAGE = ( 1 < < 27 ) , ///< don't add language to gameid
ADGF_DROPPLATFORM = ( 1 < < 28 ) , ///< don't add platform to gameid
ADGF_CD = ( 1 < < 29 ) , ///< add "-cd" to gameid
ADGF_DEMO = ( 1 < < 30 ) ///< add "-demo" to gameid
2007-02-13 01:28:18 +00:00
} ;
2006-10-02 22:21:57 +00:00
struct ADGameDescription {
2016-03-08 18:53:55 +01:00
const char * gameId ;
2006-10-02 22:21:57 +00:00
const char * extra ;
2007-01-28 23:24:16 +00:00
ADGameFileDescription filesDescriptions [ 14 ] ;
2009-01-29 22:13:01 +00:00
Common : : Language language ;
Common : : Platform platform ;
2007-11-21 21:51:21 +00:00
2007-02-13 01:28:18 +00:00
/**
2011-04-27 11:31:52 +02:00
* 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
2007-02-13 01:28:18 +00:00
* code .
*/
uint32 flags ;
2009-06-06 17:56:41 +00:00
2016-03-08 18:53:55 +01:00
const char * guiOptions ;
2006-10-02 22:21:57 +00:00
} ;
2011-06-10 22:13:51 +02:00
/**
2017-12-02 17:14:22 +01:00
* A game installation matching an AD game description
2011-06-10 22:13:51 +02:00
*/
2017-12-02 17:14:22 +01:00
struct ADDetectedGame {
bool hasUnknownFiles ;
FilePropertiesMap matchedFiles ;
const ADGameDescription * desc ;
2011-06-10 22:13:51 +02:00
2017-12-02 17:14:22 +01:00
ADDetectedGame ( ) : desc ( nullptr ) , hasUnknownFiles ( false ) { }
explicit ADDetectedGame ( const ADGameDescription * d ) : desc ( d ) , hasUnknownFiles ( false ) { }
} ;
/** A list of games detected by the AD */
typedef Common : : Array < ADDetectedGame > ADDetectedGames ;
2017-10-07 23:18:57 -05:00
2007-02-13 22:25:25 +00:00
/**
* End marker for a table of ADGameDescription structs . Use this to
* terminate a list to be passed to the AdvancedDetector API .
*/
2007-02-13 01:28:18 +00:00
# define AD_TABLE_END_MARKER \
2011-11-16 22:38:58 +01:00
{ NULL , NULL , { { NULL , 0 , NULL , 0 } } , Common : : UNK_LANG , Common : : kPlatformUnknown , ADGF_NO_FLAGS , GUIO0 ( ) }
2007-02-13 01:28:18 +00:00
2007-02-14 23:46:39 +00:00
struct ADFileBasedFallback {
/**
2007-03-08 21:33:55 +00:00
* Pointer to an ADGameDescription or subclass thereof which will get
* returned if there ' s a detection match .
2007-02-14 23:46:39 +00:00
*/
2011-06-14 18:21:44 +02:00
const ADGameDescription * desc ;
2007-11-21 21:51:21 +00:00
2007-02-14 23:46:39 +00:00
/**
2007-03-08 21:33:55 +00:00
* A zero - terminated list of filenames used for matching . All files in
* the list must be present to get a detection match .
2007-02-14 23:46:39 +00:00
*/
const char * filenames [ 10 ] ;
} ;
2007-01-28 07:31:26 +00:00
enum ADFlags {
2010-01-03 21:07:40 +00:00
/**
* Store value of extra field in config file , and use it as a hint
* on subsequent runs . Could be used when there is no way to autodetect
* game ( when more than one game sits in same directory ) , and user picks
* up a variant manually .
2011-06-14 18:15:47 +02:00
* In addition , this is useful if two variants of a game sharing the same
* gameid are contained in a single directory .
2010-01-03 21:07:40 +00:00
*/
2011-06-14 18:15:47 +02:00
kADFlagUseExtraAsHint = ( 1 < < 0 )
2007-01-28 07:31:26 +00:00
} ;
2011-06-11 17:52:32 +02:00
2012-02-29 16:48:25 +01:00
/**
* Map entry for mapping GUIO_GAMEOPTIONS * to their ExtraGuiOption
* description .
*/
struct ADExtraGuiOptionsMap {
/**
* GUIO_GAMEOPTION * string .
*/
const char * guioFlag ;
/**
* The associated option .
*/
ExtraGuiOption option ;
} ;
# define AD_EXTRA_GUI_OPTIONS_TERMINATOR { 0, { 0, 0, 0, 0 } }
2011-06-11 17:52:32 +02:00
/**
2020-10-11 23:14:39 +02:00
* A MetaEngineDetection implementation based around the advanced detector code .
2011-06-11 17:52:32 +02:00
*/
2020-10-11 23:14:39 +02:00
class AdvancedMetaEngineDetection : public MetaEngineDetection {
2011-06-11 17:52:32 +02:00
protected :
2007-02-13 22:25:25 +00:00
/**
* Pointer to an array of objects which are either ADGameDescription
* or superset structures ( i . e . start with an ADGameDescription member .
* The list is terminated by an entry with a gameid equal to 0
* ( see AD_TABLE_END_MARKER ) .
*/
2011-06-11 17:52:32 +02:00
const byte * _gameDescriptors ;
2007-02-13 22:25:25 +00:00
/**
* The size of a single entry of the above descs array . Always
* must be > = sizeof ( ADGameDescription ) .
*/
2011-06-14 17:13:02 +02:00
const uint _descItemSize ;
/**
* A list of all gameids ( and their corresponding descriptions ) supported
* by this engine .
*/
2016-03-08 18:30:58 +01:00
const PlainGameDescriptor * _gameIds ;
2007-02-13 22:25:25 +00:00
2012-02-29 16:48:25 +01:00
/**
* A map containing all the extra game GUI options the engine supports .
2012-09-26 04:17:31 +02:00
*/
2012-02-29 16:48:25 +01:00
const ADExtraGuiOptionsMap * const _extraGuiOptions ;
2007-02-13 22:25:25 +00:00
/**
* The number of bytes to compute MD5 sum for . The AdvancedDetector
* is primarily based on computing and matching MD5 checksums of files .
* Since doing that for large files can be slow , it can be restricted
* to a subset of all files .
2011-08-20 18:41:32 -04:00
* Typically this will be set to something between 5 and 50 kilobytes ,
2011-06-14 17:13:02 +02:00
* but arbitrary non - zero values are possible . The default is 5000.
2007-02-13 22:25:25 +00:00
*/
2011-06-11 17:52:32 +02:00
uint _md5Bytes ;
2007-02-13 22:25:25 +00:00
2007-02-13 23:37:44 +00:00
/**
* A bitmask of flags which can be used to configure the behavior
* of the AdvancedDetector . Refer to ADFlags for a list of flags
* that can be ORed together and passed here .
*/
2011-06-11 17:52:32 +02:00
uint32 _flags ;
2009-06-06 17:56:41 +00:00
/**
2011-10-23 15:14:41 +01:00
* A list of game GUI options which will be added to each
2009-06-06 17:56:41 +00:00
* entry in addition to per - game options . Refer to GameGUIOption
* enum for the list .
*/
2016-03-08 18:30:58 +01:00
Common : : String _guiOptions ;
2010-06-14 14:50:23 +00:00
/**
2011-06-11 17:52:32 +02:00
* Maximum depth of directories to look up .
2010-06-14 14:50:23 +00:00
* If set to 0 , the depth is 1 level
*/
2011-06-11 17:52:32 +02:00
uint32 _maxScanDepth ;
2010-06-15 10:59:23 +00:00
/**
* Case - insensitive list of directory globs which could be used for
2011-06-11 17:52:32 +02:00
* going deeper into the directory structure .
2010-06-15 10:59:23 +00:00
* @ see String : : matchString ( ) method for format description .
*
* @ note Last item must be 0
*/
2011-06-11 17:52:32 +02:00
const char * const * _directoryGlobs ;
2006-12-19 22:43:15 +00:00
2017-05-21 15:31:37 -05:00
/**
* If true , filenames will be matched against the entire path , relative to
* the root detection directory ( e . g . " foo/bar.000 " for a file at
* " <root>/foo/bar.000 " ) . Otherwise , filenames only match the basename
* ( e . g . " bar.000 " for the same file ) .
*
* @ note _maxScanDepth and _directoryGlobs must still be configured to allow
* the detector to find files inside subdirectories .
*/
bool _matchFullPaths ;
2020-10-21 19:13:12 +02:00
/**
* If we use ADGF_AUTOGENTARGET , then this specifies the max length
* of the autogenerated name . The default is 15
*/
int _maxAutogenLength ;
2008-02-02 00:54:52 +00:00
public :
2020-10-11 23:14:39 +02:00
AdvancedMetaEngineDetection ( const void * descs , uint descItemSize , const PlainGameDescriptor * gameIds , const ADExtraGuiOptionsMap * extraGuiOptions = 0 ) ;
2008-02-02 02:35:13 +00:00
2011-06-10 22:13:51 +02:00
/**
* Returns list of targets supported by the engine .
* Distinguishes engines with single ID
*/
2018-05-06 13:09:52 +02:00
PlainGameList getSupportedGames ( ) const override ;
2011-06-10 22:13:51 +02:00
2018-05-06 12:57:08 +02:00
PlainGameDescriptor findGame ( const char * gameId ) const override ;
2011-06-10 22:13:51 +02:00
2017-12-02 17:14:22 +01:00
DetectedGames detectGames ( const Common : : FSList & fslist ) const override ;
2011-06-10 22:13:51 +02:00
2020-08-02 20:37:48 +05:30
/**
* A generic createInstance .
* For instantiating engine objects , this method is called first ,
* and then the subclass implemented createInstance is called from within .
*/
Common : : Error createInstance ( OSystem * syst , Engine * * engine ) const ;
2008-02-03 18:37:41 +00:00
2020-01-31 12:25:49 +01:00
virtual const ExtraGuiOptions getExtraGuiOptions ( const Common : : String & target ) const override ;
2012-02-29 16:48:25 +01:00
2011-06-10 22:13:51 +02:00
protected :
2011-06-14 18:02:09 +02:00
typedef Common : : HashMap < Common : : String , Common : : FSNode , Common : : IgnoreCase_Hash , Common : : IgnoreCase_EqualTo > FileMap ;
2008-03-14 13:59:31 +00:00
/**
* An ( optional ) generic fallback detect function which is invoked
2011-06-14 18:11:14 +02:00
* if the regular MD5 based detection failed to detect anything .
2008-03-14 13:59:31 +00:00
*/
2017-12-02 17:14:22 +01:00
virtual ADDetectedGame fallbackDetect ( const FileMap & allFiles , const Common : : FSList & fslist ) const {
return ADDetectedGame ( ) ;
2008-03-14 13:59:31 +00:00
}
2011-06-10 15:56:56 +02:00
2013-05-17 00:18:09 +03:00
private :
void initSubSystems ( const ADGameDescription * gameDesc ) const ;
2011-06-10 15:56:56 +02:00
protected :
2011-06-10 22:13:51 +02:00
/**
* Detect games in specified directory .
* Parameters language and platform are used to pass on values
2011-06-14 17:13:02 +02:00
* specified by the user . This is used to restrict search scope .
2011-06-10 22:13:51 +02:00
*
2011-06-14 18:02:09 +02:00
* @ param allFiles list of all present files , as computed by composeFileHashMap
2011-06-14 17:13:02 +02:00
* @ param language restrict results to specified language
* @ param platform restrict results to specified platform
* @ param extra restrict results to specified extra string ( only if kADFlagUseExtraAsHint is set )
* @ return list of ADGameDescription pointers corresponding to matched games
2011-06-10 22:13:51 +02:00
*/
2017-12-02 17:14:22 +01:00
virtual ADDetectedGames detectGame ( const Common : : FSNode & parent , const FileMap & allFiles , Common : : Language language , Common : : Platform platform , const Common : : String & extra ) const ;
2011-06-10 22:13:51 +02:00
/**
2011-06-14 18:11:14 +02:00
* Iterates over all ADFileBasedFallback records inside fileBasedFallback .
2011-06-14 17:32:13 +02:00
* This then returns the record ( or rather , the ADGameDescription
* contained in it ) for which all files described by it are present , and
* among those the one with the maximal number of matching files .
* In case of a tie , the entry coming first in the list is chosen .
*
* @ param allFiles a map describing all present files
2012-06-27 04:42:36 +02:00
* @ param fslist a list of nodes for all present files
2011-06-14 17:32:13 +02:00
* @ param fileBasedFallback a list of ADFileBasedFallback records , zero - terminated
2012-06-27 04:42:36 +02:00
* @ param filesProps if not 0 , return a map of properties for all detected files here
2011-06-10 22:13:51 +02:00
*/
2020-09-12 07:00:53 +02:00
ADDetectedGame detectGameFilebased ( const FileMap & allFiles , const ADFileBasedFallback * fileBasedFallback ) const ;
2012-06-27 04:48:57 +02:00
2011-06-10 22:13:51 +02:00
/**
* Compose a hashmap of all files in fslist .
* Includes nifty stuff like removing trailing dots and ignoring case .
*/
2017-05-21 15:31:37 -05:00
void composeFileHashMap ( FileMap & allFiles , const Common : : FSList & fslist , int depth , const Common : : String & parentName = Common : : String ( ) ) const ;
2012-06-27 04:25:38 +02:00
/** Get the properties (size and MD5) of this file. */
2020-09-12 07:00:53 +02:00
bool getFileProperties ( const FileMap & allFiles , const ADGameDescription & game , const Common : : String fname , FileProperties & fileProps ) const ;
2017-12-02 17:14:22 +01:00
/** Convert an AD game description into the shared game description format */
2020-06-05 19:43:03 +02:00
virtual DetectedGame toDetectedGame ( const ADDetectedGame & adGame ) const ;
2020-09-12 07:00:53 +02:00
friend class FileMapArchive ; // for FileMap
2008-02-02 00:54:52 +00:00
} ;
2020-08-01 20:34:18 +05:30
/**
2020-10-02 13:12:50 +05:30
* A MetaEngine implementation of AdvancedMetaEngine .
2020-08-01 20:34:18 +05:30
*/
2020-10-02 11:16:09 +05:30
class AdvancedMetaEngine : public MetaEngine {
2020-08-02 20:37:48 +05:30
public :
/**
* Base createInstance for AMEC .
* The AME provides a default createInstance which is called first , so we should invoke that
* first .
* By the point of time we call this , we assume that we only have one
* plugin engine loaded in memory .
*/
virtual Common : : Error createInstance ( OSystem * syst , Engine * * engine ) const override ;
/**
* To be implemented by subclasses , which is called after we call the base
* createInstance function above .
*/
virtual bool createInstance ( OSystem * syst , Engine * * engine , const ADGameDescription * desc ) const = 0 ;
2020-08-02 21:01:55 +05:30
/**
* Provide the engineID here , must match the one from MetaEngine .
*
* @ see MetaEngineConnect : : getName ( ) .
*/
2020-08-29 23:48:53 +02:00
virtual const char * getName ( ) const override = 0 ;
2020-08-07 19:06:17 +05:30
public :
typedef Common : : HashMap < Common : : String , Common : : FSNode , Common : : IgnoreCase_Hash , Common : : IgnoreCase_EqualTo > FileMap ;
/**
* An ( optional ) generic fallback detect function which is invoked
* if the regular MD5 based detection failed to detect anything .
* NOTE : This is only meant to be used if fallback detection is heavily dependant on engine resources .
*
* To use this , implement the intended fallbackDetectExtern inside the relevant MetaEngineConnect class .
* Then , override the method " fallbackDetect " inside your MetaEngine class .
* Finally , provide a " hook " to fetch the relevant MetaEngineConnect class and then use the orignal detection
* method .
*
* An example for the way this is used can be found in the Wintermute Engine .
*/
virtual ADDetectedGame fallbackDetectExtern ( uint md5Bytes , const FileMap & allFiles , const Common : : FSList & fslist ) const {
return ADDetectedGame ( ) ;
}
/**
* Get the properties ( size and MD5 ) of this file .
* Based on MetaEngine : : getFileProperties .
*/
2020-08-07 19:24:17 +05:30
bool getFilePropertiesExtern ( uint md5Bytes , const FileMap & allFiles , const ADGameDescription & game , const Common : : String fname , FileProperties & fileProps ) const ;
2020-08-01 20:34:18 +05:30
} ;
2006-10-02 22:21:57 +00:00
# endif