1 /* ScummVM - Graphic Adventure Engine 2 * 3 * ScummVM is the legal property of its developers, whose names 4 * are too numerous to list here. Please refer to the COPYRIGHT 5 * file distributed with this source distribution. 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * as published by the Free Software Foundation; either version 2 10 * of the License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 * 21 */ 22 23 #ifndef ENGINES_METAENGINE_H 24 #define ENGINES_METAENGINE_H 25 26 #include "common/achievements.h" 27 #include "common/scummsys.h" 28 #include "common/error.h" 29 #include "common/array.h" 30 31 #include "engines/game.h" 32 #include "engines/savestate.h" 33 34 #include "base/plugins.h" 35 36 class Engine; 37 class OSystem; 38 39 namespace Common { 40 class Keymap; 41 class FSList; 42 class OutSaveFile; 43 class String; 44 45 typedef SeekableReadStream InSaveFile; 46 } 47 48 namespace Graphics { 49 struct Surface; 50 } 51 52 namespace GUI { 53 class GuiObject; 54 class OptionsContainerWidget; 55 } 56 57 /** 58 * @defgroup engines_metaengine Meta engine 59 * @ingroup engines 60 * 61 * @brief API for managing various functions of the meta engine. 62 * 63 * @{ 64 */ 65 66 /** 67 * Per-game extra GUI options structure. 68 * Currently, this can only be used for options with checkboxes. 69 */ 70 struct ExtraGuiOption { 71 const char *label; /*!< Option label, e.g. "Fullscreen mode". */ 72 const char *tooltip; /*!< Option tooltip shown when the mouse cursor hovers over it. */ 73 const char *configOption; /*!< confMan key, e.g. "fullscreen". */ 74 bool defaultState; /*!< Default state of the checkbox (checked or not). */ 75 }; 76 77 /** 78 * debug channels structure 79 */ 80 struct DebugChannelDef { 81 uint32 channel; /*!< enum value, channel id, e.g. kDebugGlobalDetection */ 82 const char *name; /*!< name of debug channel, e.g. "detection" */ 83 const char *description; /*!< description of debug channel, e.g. "track scripts" */ 84 }; 85 86 /** 87 * delimiter of the array of DebugChannelDef 88 */ 89 #define DEBUG_CHANNEL_END {0, NULL, NULL} 90 91 /** 92 * Array of ExtraGuiOption structures. 93 */ 94 typedef Common::Array<ExtraGuiOption> ExtraGuiOptions; 95 96 /** 97 * @todo Doc required 98 */ 99 enum { kSavegameFilePattern = -99 }; 100 101 #define EXTENDED_SAVE_VERSION 4 102 103 /** 104 * Structure describing a savegame file. 105 */ 106 struct ExtendedSavegameHeader { 107 char id[6]; /*!< ID of the savegame file. */ 108 uint8 version; /*!< Version of the savegame header. */ 109 Common::String saveName; /*!< Name of the savegame. */ 110 Common::String description; /*!< Description of the savegame, as entered by the user. */ 111 uint32 date; /*!< Date of the savegame. */ 112 uint16 time; /*!< Time of the savegame. */ 113 uint32 playtime; /*!< Total play time until this savegame. */ 114 Graphics::Surface *thumbnail; /*!< Screen content shown as a thumbnail for this savegame. */ 115 bool isAutosave; /*!< Whether this savegame is an autosave. */ 116 ExtendedSavegameHeaderExtendedSavegameHeader117 ExtendedSavegameHeader() { 118 memset(id, 0, 6); 119 version = 0; 120 date = 0; 121 time = 0; 122 playtime = 0; 123 thumbnail = nullptr; 124 isAutosave = false; 125 } 126 }; 127 128 /** 129 * A meta engine factory for Engine instances with the 130 * added ability of listing and detecting supported games. 131 * 132 * Every engine "plugin" provides a hook to get an instance of a MetaEngineDetection 133 * subclass for that "engine plugin". For example, SCUMM provides ScummMetaEngineDetection. 134 * This is then in turn used by the frontend code to detect games, and other useful functionality. 135 * 136 * To instantiate actual Engine objects, see the class @ref MetaEngine. 137 */ 138 class MetaEngineDetection : public PluginObject { 139 public: ~MetaEngineDetection()140 virtual ~MetaEngineDetection() {} 141 142 /** Get the engine ID. */ 143 virtual const char *getEngineId() const = 0; 144 145 /** Return some copyright information about the original engine. */ 146 virtual const char *getOriginalCopyright() const = 0; 147 148 /** Return a list of games supported by this engine. */ 149 virtual PlainGameList getSupportedGames() const = 0; 150 151 /** Query the engine for a PlainGameDescriptor for the specified gameid, if any. */ 152 virtual PlainGameDescriptor findGame(const char *gameId) const = 0; 153 154 /** 155 * Run the engine's game detector on the given list of files, and return a 156 * (possibly empty) list of games supported by the engine that were 157 * found among the given files. 158 */ 159 virtual DetectedGames detectGames(const Common::FSList &fslist) const = 0; 160 161 /** 162 * Return a list of extra GUI options for the specified target. 163 * 164 * If no target is specified, all of the available custom GUI options are 165 * returned for the plugin (used to set default values). 166 * 167 * Currently, this only supports options with checkboxes. 168 * 169 * The default implementation returns an empty list. 170 * 171 * @param target Name of a config manager target. 172 * 173 * @return A list of extra GUI options for an engine plugin and target. 174 */ getExtraGuiOptions(const Common::String & target)175 virtual const ExtraGuiOptions getExtraGuiOptions(const Common::String &target) const { 176 return ExtraGuiOptions(); 177 } 178 179 /** 180 * Return a list of engine specified debug channels 181 * 182 * If engine has no specified debug channels or not supported yet, then it will return NULL 183 * 184 * @return A list of engine specified debug channels 185 */ getDebugChannels()186 virtual const DebugChannelDef *getDebugChannels() const { 187 return NULL; 188 } 189 190 /** 191 * Register the default values for the settings that the engine uses into the 192 * configuration manager. 193 * 194 * @param target Name of a config manager target. 195 */ 196 virtual void registerDefaultSettings(const Common::String &target) const; 197 198 /** 199 * Return a GUI widget container for configuring the specified target options. 200 * 201 * The returned widget is shown in the Engine tab in the Edit Game dialog. 202 * Engines can build custom option dialogs, but by default a simple widget 203 * allowing to configure the extra GUI options is used. 204 * 205 * Engines that are not supposed to have an Engine tab in the Edit Game dialog 206 * can return nullptr. 207 * 208 * @param boss The widget or dialog that the returned widget is a child of. 209 * @param name The name that the returned widget must use. 210 * @param target Name of a config manager target. 211 */ 212 virtual GUI::OptionsContainerWidget *buildEngineOptionsWidgetStatic(GUI::GuiObject *boss, const Common::String &name, const Common::String &target) const; 213 }; 214 215 /** 216 * A MetaEngine is another factory for Engine instances, and is very similar to MetaEngineDetection. 217 * 218 * This class, however, is made of of bridged functionalities that can be used to connect 219 * an actual Engine with a MetaEngine. Every engine "plugin" provides a hook to get an instance 220 * of the MetaEngine subclass for that "engine plugin.". For example, SCUMM provides a ScummMetaEngine. 221 * This is then in turn used for things like instantiating engine objects, listing savefiles, 222 * querying save metadata, etc. 223 * 224 * Since engine plugins can use external runtime libraries, these can live and build inside 225 * the engine, while a MetaEngine will always build into the executable to be able to detect code. 226 */ 227 class MetaEngine : public PluginObject { 228 protected: 229 /** 230 * Convert the current screen contents to a thumbnail. Can be overriden by individual 231 * engine meta engines to provide their own thumb, such as hiding any on-screen save 232 * dialog so that it won't appear in the thumbnail. 233 */ 234 virtual void getSavegameThumbnail(Graphics::Surface &thumb); 235 236 /** 237 * Finds the first empty save slot that can be used for this target 238 * @param target Name of a config manager target. 239 * 240 * @return The first empty save slot, or -1 if all are occupied. 241 */ 242 int findEmptySaveSlot(const char *target); 243 244 public: ~MetaEngine()245 virtual ~MetaEngine() {} 246 247 /** 248 * Name of the engine plugin. 249 * 250 * Classes inheriting a MetaEngine must provide an engineID here, 251 * which can then be used to match an Engine with MetaEngine. 252 * 253 * For example, ScummMetaEngineDetection inherits MetaEngineDetection and provides a 254 * engineID of "scumm". ScummMetaEngine inherits MetaEngine and provides the name 255 * "Scumm". This way, an Engine can be easily matched with a MetaEngine. 256 */ 257 virtual const char *getName() const = 0; 258 259 /** 260 * Instantiate an engine instance based on the settings of 261 * the currently active ConfMan target. 262 * 263 * The MetaEngine queries the ConfMan singleton for data like the target, 264 * gameid, path etc. 265 * 266 * @param syst Pointer to the global OSystem object. 267 * @param engine Pointer to a pointer that the MetaEngine sets to 268 * the newly created Engine, or 0 in case of an error. 269 * 270 * @return A Common::Error describing the error that occurred, or kNoError. 271 */ 272 virtual Common::Error createInstance(OSystem *syst, Engine **engine) const = 0; 273 274 /** 275 * Return a list of all save states associated with the given target. 276 * 277 * The returned list is guaranteed to be sorted by slot numbers. That 278 * means smaller slot numbers are always stored before bigger slot numbers. 279 * 280 * The caller must ensure that this (Meta)Engine is responsible 281 * for the specified target. This is done by using findGame on it respectively 282 * on the associated gameid from the relevant ConfMan entry, if present. 283 * 284 * The default implementation returns an empty list. 285 * 286 * @note MetaEngines must indicate that this function has been implemented 287 * via the kSupportsListSaves feature flag. 288 * 289 * @param target Name of a config manager target. 290 * 291 * @return A list of save state descriptors. 292 */ 293 virtual SaveStateList listSaves(const char *target) const; 294 295 /** 296 * Return a list of all save states associated with the given target. 297 * 298 * This is a wrapper around the basic listSaves virtual method, but it has 299 * some extra logic for autosave handling. 300 * 301 * @param target Name of a config manager target. 302 * @param saveMode If true, get the list for a save dialog. 303 * @return A list of save state descriptors. 304 */ 305 SaveStateList listSaves(const char *target, bool saveMode) const; 306 307 /** 308 * Return the slot number that is used for autosaves, or -1 for engines that 309 * don't support autosave. 310 * 311 * @note This should match the engine getAutosaveSlot() method. 312 */ getAutosaveSlot()313 virtual int getAutosaveSlot() const { 314 return 0; 315 } 316 317 /** 318 * Return the maximum number of save slots that the engine supports. 319 * 320 * @note MetaEngines must indicate that this function has been implemented 321 * via the kSupportsListSaves feature flag. 322 * 323 * The default implementation limits the save slots to zero (0). 324 * 325 * @return Maximum save slot number supported. 326 */ getMaximumSaveSlot()327 virtual int getMaximumSaveSlot() const { 328 // For games using the new save format, assume 99 slots by default 329 return hasFeature(kSavesUseExtendedFormat) ? 99 : 0; 330 } 331 332 /** 333 * Remove the specified save state. 334 * 335 * For most engines, this just means calling _saveFileMan->removeSaveFile(). 336 * Engines that keep an index file will also update it accordingly. 337 * 338 * @note MetaEngines must indicate that this function has been implemented 339 * via the kSupportsDeleteSave feature flag. 340 * 341 * @param target Name of a config manager target. 342 * @param slot Slot number of the save state to be removed. 343 */ 344 virtual void removeSaveState(const char *target, int slot) const; 345 346 /** 347 * Return meta information from the specified save state. 348 * 349 * Depending on the MetaEngineFeatures set, this can include 350 * thumbnails, save date and time, play time. 351 * 352 * @param target Name of a config manager target. 353 * @param slot Slot number of the save state. 354 */ 355 virtual SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const; 356 357 /** 358 * Return the name of the save file for the given slot and optional target, 359 * or a pattern for matching filenames against. 360 * 361 * @param saveGameIdx Index of the save, or kSavegameFilePattern 362 * for returning a filename pattern. 363 * @param target Game target. If omitted, then the engine ID is used. 364 */ 365 virtual Common::String getSavegameFile(int saveGameIdx, const char *target = nullptr) const; 366 367 /** 368 * Return the pattern for save files. 369 * 370 * @param target Game target. If omitted, then the engine ID is used. 371 */ 372 Common::String getSavegameFilePattern(const char *target = nullptr) const { 373 return getSavegameFile(kSavegameFilePattern, target); 374 } 375 376 /** 377 * Return the keymap used by the target. 378 */ 379 virtual Common::Array<Common::Keymap *> initKeymaps(const char *target) const; 380 381 /** 382 * Return a GUI widget container for configuring the specified target options. 383 * 384 * Engines can build custom option dialogs from here. 385 * 386 * Engines that don't have an Engine tab in the Edit Game dialog, or that use 387 * ExtraGuiOptions in MetaEngineDetection can return nullptr. 388 * 389 * @param boss The widget or dialog that the returned widget is a child of. 390 * @param name The name that the returned widget must use. 391 * @param target Name of a config manager target. 392 */ buildEngineOptionsWidgetDynamic(GUI::GuiObject * boss,const Common::String & name,const Common::String & target)393 virtual GUI::OptionsContainerWidget *buildEngineOptionsWidgetDynamic(GUI::GuiObject *boss, const Common::String &name, const Common::String &target) const { 394 return nullptr; 395 } 396 397 /** 398 * MetaEngine feature flags. 399 * 400 * A feature in this context means an ability of the engine that can be 401 * either available or not. 402 */ 403 enum MetaEngineFeature { 404 /** 405 * List all save states for a given target that is supported. 406 * 407 * For the target to be supported, the listSaves() and 408 * getMaximumSaveSlot methods must be implemented. 409 * Used for --list-saves support, as well as the GMM load dialog. 410 */ 411 kSupportsListSaves, 412 413 /** 414 * Load from the launcher or command line (-x). 415 */ 416 kSupportsLoadingDuringStartup, 417 418 /** 419 * Delete saves from the launcher. 420 * 421 * This means that the engine implements the removeSaveState() method. 422 */ 423 kSupportsDeleteSave, 424 425 /** 426 * Feature meta information for save states. 427 * 428 * This means that the engine implements the querySaveMetaInfos method properly. 429 * 430 * Engines implementing meta information always must provide 431 * the following entries in the save state descriptor queried 432 * by querySaveMetaInfos: 433 * - is_deletable - indicates whether a given save is 434 * safe for deletion 435 * - is_write_protected - indicates whether a given save 436 * can be overwritten by the user. 437 * You do not need to set this, default value is 'false'. 438 */ 439 kSavesSupportMetaInfo, 440 441 /** 442 * Feature a thumbnail in savegames. 443 * 444 * This means that the engine includes a thumbnail in save states 445 * returned via querySaveMetaInfo. 446 * This flag can only be set when kSavesSupportMetaInfo is set. 447 */ 448 kSavesSupportThumbnail, 449 450 /** 451 * Feature @c save_date and @c save_time entries in the 452 * save state returned by querySaveMetaInfo. 453 * 454 * These values indicate the date and time when the savegame was created. 455 * This flag can only be set when kSavesSupportMetaInfo is set. 456 */ 457 kSavesSupportCreationDate, 458 459 /** 460 * Feature @c play_time entry in the save state returned by 461 * querySaveMetaInfo. 462 * 463 * This indicates how long the user played the game until the save. 464 * This flag can only be set when kSavesSupportMetaInfo is set. 465 */ 466 kSavesSupportPlayTime, 467 468 /** 469 * This feature is available if the engine's saves can be detected 470 * with: 471 * @code 472 * <target>.### 473 * @endcode 474 * where ### corresponds to slot number. 475 * 476 * If that is not true, or if the engine uses some unusual way 477 * of detecting saves and slot numbers, this should be 478 * unavailable. In that case Save/Load dialog for the engine's 479 * games is locked during cloud saves sync. 480 * 481 * NOTE: This flag is used by cloud code, but also in 482 * MetaEngine::getSavegameFile(), for common save names. 483 */ 484 kSimpleSavesNames, 485 486 /** 487 * Use the default implementation of save header and thumbnail 488 * appended to the save. 489 * 490 * This flag requires the following flags to be set: 491 * - kSavesSupportMetaInfo 492 * - kSavesSupportThumbnail 493 * - kSavesSupportCreationDate 494 * - kSavesSupportPlayTime 495 */ 496 kSavesUseExtendedFormat 497 }; 498 499 /** 500 * Return a list of achievement descriptions for the specified target. 501 * 502 * @param target Name of a config manager target. 503 * 504 * @return A list of achievement descriptions for an engine plugin and target. 505 */ 506 virtual const Common::AchievementsInfo getAchievementsInfo(const Common::String &target) const; 507 508 /** 509 * Return the achievement descriptions. 510 * 511 * @note The default implementation returns @c nullptr 512 * 513 * @return a list of achievement descriptions for an engine. 514 */ getAchievementDescriptionList()515 virtual const Common::AchievementDescriptionList* getAchievementDescriptionList() const { 516 return nullptr; 517 } 518 519 /** 520 * Determine whether the engine supports the specified MetaEngine feature. 521 * 522 * Used by e.g. the launcher to determine whether to enable the Load button. 523 */ 524 virtual bool hasFeature(MetaEngineFeature f) const; 525 526 /** 527 * Write the extended savegame header to the given savegame file. 528 */ 529 void appendExtendedSave(Common::OutSaveFile *saveFile, uint32 playtime, Common::String desc, bool isAutosave); 530 531 /** 532 * Write the extended savegame header to the given WriteStream. 533 */ 534 void appendExtendedSaveToStream(Common::WriteStream *saveFile, uint32 playtime, Common::String desc, bool isAutosave, uint32 offset = 0); 535 536 /** 537 * Copies an existing save file to the first empty slot which is not autosave 538 * @param target Name of a config manager target. 539 * @param slot Slot number of the save state. 540 * 541 * @return true if an empty slot was found and the save state was copied. false otherwise. 542 */ 543 bool copySaveFileToFreeSlot(const char *target, int slot); 544 545 /** 546 * Parse the extended savegame header to retrieve the SaveStateDescriptor information. 547 */ 548 static void parseSavegameHeader(ExtendedSavegameHeader *header, SaveStateDescriptor *desc); 549 /** 550 * Populate the given extended savegame header with dummy values. 551 * 552 * This is used when failing to read the header from a savegame file. 553 */ 554 static void fillDummyHeader(ExtendedSavegameHeader *header); 555 /** 556 * Read the extended savegame header from the given savegame file. 557 */ 558 static WARN_UNUSED_RESULT bool readSavegameHeader(Common::InSaveFile *in, ExtendedSavegameHeader *header, bool skipThumbnail = true); 559 }; 560 561 /** 562 * Singleton class that manages all engine plugins. 563 */ 564 class EngineManager : public Common::Singleton<EngineManager> { 565 public: 566 /** 567 * Given a list of FSNodes in a given directory, detect a set of games contained within. 568 * 569 * Returns an empty list if none are found. 570 */ 571 DetectionResults detectGames(const Common::FSList &fslist) const; 572 573 /** Find a plugin by its engine ID. */ 574 const Plugin *findPlugin(const Common::String &engineId) const; 575 576 /** 577 * Get the list of all plugins for the type specified. 578 * 579 * By default, it will get METAENGINES, for now. 580 * If usage of actual engines never occurs, the default arguments can be skipped, 581 * and always have it return PLUGIN_TYPE_ENGINE_DETECTION. 582 */ 583 const PluginList &getPlugins(const PluginType fetchPluginType = PLUGIN_TYPE_ENGINE_DETECTION) const; 584 585 /** Find a target. */ 586 QualifiedGameDescriptor findTarget(const Common::String &target, const Plugin **plugin = NULL) const; 587 588 /** 589 * List games matching the specified criteria. 590 * 591 * If the engine ID is not specified, this scans all the plugins, 592 * loading them from the disk if necessary. This is a slow operation on 593 * some platforms and should not be used for the happy path. 594 */ 595 QualifiedGameList findGamesMatching(const Common::String &engineId, const Common::String &gameId) const; 596 597 /** 598 * Create a target from the supplied game descriptor. 599 * 600 * @return The created target name. 601 */ 602 Common::String createTargetForGame(const DetectedGame &game); 603 604 /** Upgrade a target to the current configuration format. */ 605 void upgradeTargetIfNecessary(const Common::String &target) const; 606 607 private: 608 /** Find a game across all loaded plugins. */ 609 QualifiedGameList findGameInLoadedPlugins(const Common::String &gameId) const; 610 611 /** Use heuristics to complete a target lacking an engine ID. */ 612 void upgradeTargetForEngineId(const Common::String &target) const; 613 }; 614 615 /** Convenience shortcut for accessing the engine manager. */ 616 #define EngineMan EngineManager::instance() 617 /** @} */ 618 #endif 619