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_ENGINE_H 24 #define ENGINES_ENGINE_H 25 26 #include "common/scummsys.h" 27 #include "common/str.h" 28 #include "common/language.h" 29 #include "common/platform.h" 30 #include "common/queue.h" 31 #include "common/singleton.h" 32 33 class OSystem; 34 class MetaEngineDetection; 35 class MetaEngine; 36 37 namespace Audio { 38 class Mixer; 39 } 40 namespace Common { 41 class Error; 42 class EventManager; 43 class SaveFileManager; 44 class TimerManager; 45 class FSNode; 46 class SeekableReadStream; 47 class WriteStream; 48 } 49 namespace GUI { 50 class Debugger; 51 class Dialog; 52 } 53 54 /** 55 * @defgroup engines_engine Engine 56 * @ingroup engines 57 * 58 * @brief API for managing various functions of the engine. 59 * 60 * @{ 61 */ 62 63 /** 64 * Initialize graphics and show an error message. 65 */ 66 void GUIErrorMessage(const Common::U32String &msg, const char *url = nullptr); 67 /** 68 * Initialize graphics and show an error message. 69 */ 70 void GUIErrorMessage(const Common::String &msg, const char *url = nullptr); 71 /** 72 * Initialize graphics and show an error message. 73 */ 74 void GUIErrorMessageWithURL(const Common::U32String &msg, const char *url); 75 /** 76 * Initialize graphics and show an error message. 77 */ 78 void GUIErrorMessageWithURL(const Common::String &msg, const char *url); 79 /** 80 * Initialize graphics and show an error message. 81 */ 82 void GUIErrorMessageFormat(Common::U32String fmt, ...); 83 /** 84 * Initialize graphics and show an error message. 85 */ 86 void GUIErrorMessageFormat(const char *fmt, ...) GCC_PRINTF(1, 2); 87 88 89 class Engine; 90 91 /** 92 * Class for managing pausing by Engine::pauseEngine that hands out pause tokens. 93 * 94 * Each token represents one requested level of pause. 95 */ 96 class PauseToken { 97 public: 98 PauseToken(); 99 /** 100 * Construct a pause token. 101 */ 102 PauseToken(const PauseToken &); 103 #if __cplusplus >= 201103L 104 PauseToken(PauseToken &&); 105 #endif 106 ~PauseToken(); 107 /** 108 * Assign the pause token. 109 */ 110 void operator=(const PauseToken &); 111 #if __cplusplus >= 201103L 112 void operator=(PauseToken &&); 113 #endif 114 /** 115 * Manually release the PauseToken. 116 * 117 * Only allowed if the token currently represents a pause request. 118 */ 119 void clear(); 120 121 /** 122 * Return true if the PauseToken represents a pause level, 123 * false if it is empty. 124 */ isActive()125 bool isActive() const { return _engine != nullptr; } 126 127 private: 128 PauseToken(Engine *); 129 130 Engine *_engine; 131 /** 132 * @see Engine 133 */ 134 friend class Engine; 135 }; 136 137 class Engine { 138 public: 139 /** 140 * The OSystem instance used by the engine. 141 */ 142 OSystem *_system; 143 /** 144 * The Mixer instance used by the engine. 145 */ 146 Audio::Mixer *_mixer; 147 148 protected: 149 /** 150 * The TimerManager instance used by the engine. 151 */ 152 Common::TimerManager *_timer; 153 /** 154 * The EventManager instance used by the engine. 155 */ 156 Common::EventManager *_eventMan; 157 /** 158 * The SaveFileMAnager used by the engine. 159 */ 160 Common::SaveFileManager *_saveFileMan; 161 162 /** 163 * The Dialog instance used by the engine. 164 */ 165 GUI::Dialog *_mainMenuDialog; 166 /** 167 * Run a GUI dialog. 168 */ 169 virtual int runDialog(GUI::Dialog &dialog); 170 171 /** 172 * Target name for saves. 173 */ 174 const Common::String _targetName; 175 176 private: 177 /** 178 * The associated metaengine 179 */ 180 MetaEngine *_metaEngine; 181 182 /** 183 * The pause level. 184 * 185 * 0 means 'running'. A positive value indicates how often the engine 186 * has been paused and thus how many times it must be unpaused before 187 * it resumes running. This makes it possible to nest the code that pauses the engine. 188 */ 189 int _pauseLevel; 190 191 /** 192 * The time when the pause was started. 193 */ 194 uint32 _pauseStartTime; 195 196 /** 197 * The time when the engine was started. 198 * 199 * This value is used to calculate the current play time of the game running. 200 */ 201 int32 _engineStartTime; 202 203 /** 204 * Autosave interval. 205 */ 206 int _autosaveInterval; 207 208 /** 209 * The last time an autosave was done. 210 */ 211 int _lastAutosaveTime; 212 213 /** 214 * Save slot selected via the global main menu. 215 * 216 * This slot will be loaded after the main menu execution (not from inside 217 * the menu loop, to avoid bugs like #4420). 218 */ 219 int _saveSlotToLoad; 220 221 /** 222 * Used for preventing recursion during autosave. 223 */ 224 bool _autoSaving; 225 226 /** 227 * Optional debugger for the engine. 228 */ 229 GUI::Debugger *_debugger; 230 public: 231 232 233 /** 234 * Engine features. 235 * 236 * A feature in this context means an ability of the engine 237 * that can be either available or not. 238 * @see Engine::hasFeature() 239 */ 240 enum EngineFeature { 241 /** 242 * Enable the subtitle speed and toggle items in the Options section 243 * of the global main menu. 244 */ 245 kSupportsSubtitleOptions, 246 247 /** 248 * The 'Return to launcher' feature is supported. 249 * 250 * This means that EVENT_RETURN_TO_LAUNCHER is handled 251 * either directly, or indirectly (the engine calls and honors 252 * the result of the Engine::shouldQuit() method appropriately). 253 */ 254 kSupportsReturnToLauncher, 255 256 /** 257 * Loading save states during runtime is supported. 258 * 259 * This means that the engine implements loadGameState() and canLoadGameStateCurrently(). 260 * If this feature is supported, then the corresponding MetaEngine *must* 261 * support the kSupportsListSaves feature. 262 */ 263 kSupportsLoadingDuringRuntime, 264 265 /** 266 * Loading save states during runtime is supported. 267 * 268 * This means that the engine implements saveGameState() and canSaveGameStateCurrently(). 269 * If this feature is supported, then the corresponding MetaEngine *must* 270 * support the kSupportsListSaves feature. 271 */ 272 kSupportsSavingDuringRuntime, 273 274 /** 275 * Changing the game settings during runtime is supported. 276 * 277 * This enables showing the Engine Options tab in the config dialog 278 * accessed through the global main menu. 279 */ 280 kSupportsChangingOptionsDuringRuntime, 281 282 /** 283 * Arbitrary resolutions are supported. 284 * 285 * This means that the engine allows the backend to override the resolution 286 * passed to OSystem::setupScreen. 287 * The engine will need to read the actual resolution used by the 288 * backend using OSystem::getWidth and OSystem::getHeight. 289 */ 290 kSupportsArbitraryResolutions 291 }; 292 293 294 295 /** @name Overloadable methods 296 * 297 * All Engine subclasses should consider overloading some or all of the following methods. 298 * @{ 299 */ 300 301 /** 302 * Create an instance of the engine. 303 */ 304 Engine(OSystem *syst); 305 /** 306 * Destroy the engine instance. 307 */ 308 virtual ~Engine(); 309 310 /** 311 * Initialize SearchMan according to the game path. 312 * 313 * By default, this adds the directory in non-flat mode with a depth of 4 as 314 * priority 0 to SearchMan. 315 * 316 * @param gamePath The base directory of the game data. 317 */ 318 virtual void initializePath(const Common::FSNode &gamePath); 319 320 /** 321 * Initialize the engine and start its main loop. 322 * 323 * @return kNoError on success, otherwise an error code. 324 */ 325 virtual Common::Error run() = 0; 326 327 /** 328 * Prepare an error string that is printed by the error() function. 329 */ 330 virtual void errorString(const char *buf_input, char *buf_output, int buf_output_size); 331 332 /** 333 * Return the engine's debugger instance, if any. 334 */ getDebugger()335 virtual GUI::Debugger *getDebugger() final { return _debugger; } 336 337 /** 338 * Set the engine's debugger. 339 * 340 * Once set, the Engine class is responsible for managing 341 * the debugger, and freeing it on exit. 342 */ setDebugger(GUI::Debugger * debugger)343 void setDebugger(GUI::Debugger *debugger) { 344 assert(!_debugger); 345 _debugger = debugger; 346 } 347 348 /** 349 * Return the engine's debugger instance, or create one if none is present. 350 * 351 * Used by error() to invoke the debugger when a severe error is reported. 352 */ 353 GUI::Debugger *getOrCreateDebugger(); 354 355 /** 356 * Determine whether the engine supports the specified feature. 357 */ hasFeature(EngineFeature f)358 virtual bool hasFeature(EngineFeature f) const { return false; } 359 360 /** 361 * Notify the engine that the sound settings in the config manager might have 362 * changed and that it should adjust any internal volume (and other) values 363 * accordingly. 364 * 365 * The default implementation sets the volume levels of all mixer sound 366 * types according to the config entries of the active domain. 367 * When overwriting, call the default implementation first, then adjust the 368 * volumes further (if required). 369 * 370 * @note When setting volume levels, respect the "mute" config entry. 371 * 372 * @note The volume for the plain sound type is reset to the maximum 373 * volume. If the engine can associate its own value for this 374 * type, it needs to overwrite this member and set it accordingly. 375 * @todo find a better name for this 376 */ 377 virtual void syncSoundSettings(); 378 379 /** 380 * Notify the engine that the settings editable from the Game tab in the 381 * in-game options dialog might have changed and that they need to be applied 382 * if necessary. 383 */ applyGameSettings()384 virtual void applyGameSettings() {} 385 386 /** 387 * Flip mute all sound options. 388 */ 389 virtual void flipMute(); 390 391 /** 392 * Generate the savegame filename. 393 */ getSaveStateName(int slot)394 virtual Common::String getSaveStateName(int slot) const { 395 return Common::String::format("%s.%03d", _targetName.c_str(), slot); 396 } 397 398 /** 399 * Load a game state. 400 * 401 * @param slot The slot from which a save state should be loaded. 402 * 403 * @return kNoError on success, otherwise an error code. 404 */ 405 virtual Common::Error loadGameState(int slot); 406 407 /** 408 * Load a game state. 409 * 410 * @param stream The stream to load the save state from. 411 * 412 * @return kNoError on success, otherwise an error code. 413 */ 414 virtual Common::Error loadGameStream(Common::SeekableReadStream *stream); 415 416 /** 417 * Set the game slot for a savegame to be loaded after the global 418 * main menu execution. 419 * 420 * This is to avoid loading a savegame from 421 * inside the menu loop which causes bugs like #4420. 422 * 423 * @param slot The slot from which a save state should be loaded. 424 */ 425 void setGameToLoadSlot(int slot); 426 427 /** 428 * Indicate whether a game state can be loaded. 429 */ 430 virtual bool canLoadGameStateCurrently(); 431 432 /** 433 * Save a game state. 434 * 435 * @param slot The slot into which the save state should be stored. 436 * @param desc Description for the save state, entered by the user. 437 * @param isAutosave Expected to be true if an autosave is being created. 438 * 439 * @return kNoError on success, otherwise an error code. 440 */ 441 virtual Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false); 442 443 /** 444 * Save a game state. 445 * 446 * @param stream The write stream to save the savegame data to. 447 * @param isAutosave Expected to be true if an autosave is being created. 448 * 449 * @return kNoError on success, otherwise an error code. 450 */ 451 virtual Common::Error saveGameStream(Common::WriteStream *stream, bool isAutosave = false); 452 453 /** 454 * Indicate whether a game state can be saved. 455 */ 456 virtual bool canSaveGameStateCurrently(); 457 458 /** 459 * Show the ScummVM save dialog, allowing users to save their game. 460 */ 461 bool saveGameDialog(); 462 463 /** 464 * Show the ScummVM Restore dialog, allowing users to load a game. 465 */ 466 bool loadGameDialog(); 467 468 protected: 469 /** 470 * Actual implementation of pauseEngine by subclasses. 471 * 472 * @see Engine::pauseEngine 473 */ 474 virtual void pauseEngineIntern(bool pause); 475 476 /** @} */ 477 478 479 public: 480 481 /** 482 * Request the engine to quit. 483 * 484 * Sends an EVENT_QUIT event to the Event Manager. 485 */ 486 static void quitGame(); 487 488 /** 489 * Return whether the engine should quit. 490 * 491 * This can mean either quitting ScummVM altogether, or returning to the launcher. 492 */ 493 static bool shouldQuit(); 494 495 /** 496 * Return the MetaEngineDetection instance used by this engine. 497 */ 498 static MetaEngineDetection &getMetaEngineDetection(); 499 500 /** 501 * Return the MetaEngine instance used by this engine. 502 */ getMetaEngine()503 inline MetaEngine *getMetaEngine() const { return _metaEngine; } 504 505 /** 506 * Set the MetaEngine instance used by this engine. 507 */ setMetaEngine(MetaEngine * metaEngine)508 inline void setMetaEngine(MetaEngine *metaEngine) { _metaEngine = metaEngine; } 509 510 /** 511 * Pause the engine. 512 * 513 * This should stop any audio playback and other operations. 514 * Called right before the system runs a global dialog 515 * (like a global pause, main menu, options, or 'confirm exit' dialog). 516 * 517 * Returns a PauseToken. Multiple pause tokens can exist. The engine will 518 * be resumed when all associated pause tokens reach the end of their lives. 519 */ 520 PauseToken pauseEngine(); 521 private: 522 /** Resume the engine. 523 * 524 * This should resume any audio playback and other operations. 525 * Only PauseToken is allowed to call this member function. Use the PauseToken 526 * that you got from pauseEngine to resume the engine. 527 */ 528 void resumeEngine(); 529 /** 530 * @see Engine::PauseToken 531 */ 532 friend class PauseToken; 533 534 /** 535 * Warns before overwriting autosave. 536 * 537 * @return true if it is safe to save, false to avoid saving. 538 */ 539 bool warnBeforeOverwritingAutosave(); 540 541 public: 542 543 /** 544 * Return whether the engine is currently paused or not. 545 */ isPaused()546 bool isPaused() const { return _pauseLevel != 0; } 547 548 /** 549 * Run the global main menu dialog. 550 */ 551 void openMainMenuDialog(); 552 553 /** 554 * Display a warning to the user that the game is not fully supported. 555 * 556 * @param msg A message that will be presented to user. If empty, then 557 * generic message regarding unsupported game is presented 558 * 559 * @return True if the user chooses to start anyway, false otherwise. 560 */ 561 static bool warnUserAboutUnsupportedGame(Common::String msg = Common::String()); 562 563 /** 564 * Display an error message to the user that the game is not supported. 565 * 566 * @param extraMsg An extra message that will be appended to the default message. 567 */ 568 static void errorUnsupportedGame(Common::String extraMsg); 569 570 /** 571 * Get the total play time. 572 * 573 * @return How long the player has been playing in ms. 574 */ 575 uint32 getTotalPlayTime() const; 576 577 /** 578 * Set the game time counter to the specified time. 579 * 580 * This can be used to set the play time counter after loading a savegame, 581 * for example. Another use case is when the engine wants to exclude from 582 * the counter the time that the user spent in original engine dialogs. 583 * 584 * @param time Play time to set up in ms. 585 */ 586 void setTotalPlayTime(uint32 time = 0); 587 588 /** 589 * Return the TimerManager instance used by this engine. 590 */ getTimerManager()591 inline Common::TimerManager *getTimerManager() { return _timer; } 592 /** 593 * Return the EventManager instance used by this engine. 594 */ getEventManager()595 inline Common::EventManager *getEventManager() { return _eventMan; } 596 /** 597 * Return the SaveFileManager instance used by this engine. 598 */ getSaveFileManager()599 inline Common::SaveFileManager *getSaveFileManager() { return _saveFileMan; } 600 601 public: 602 /** 603 * Check if extracted CD Audio files are found. 604 */ 605 bool existExtractedCDAudioFiles(); 606 /** 607 * On some systems, check whether the game appears to be run 608 * from the same CD drive, which also should play CD audio. 609 */ 610 bool isDataAndCDAudioReadFromSameCD(); 611 /** 612 *Display a warning for no extracted CD Audio files found. 613 */ 614 void warnMissingExtractedCDAudio(); 615 616 /** 617 * Check whether it is time to autosave, and if so, do it. 618 */ 619 void handleAutoSave(); 620 621 /** 622 * Autosave immediately if autosaves are enabled. 623 */ 624 void saveAutosaveIfEnabled(); 625 626 /** 627 * Indicate whether an autosave can currently be done. 628 */ canSaveAutosaveCurrently()629 virtual bool canSaveAutosaveCurrently() { 630 return canSaveGameStateCurrently(); 631 } 632 633 /** 634 * Return the slot that should be used for autosaves, or -1 for engines that 635 * don't support autosave. 636 * 637 * @note This should match the meta engine getAutosaveSlot() method. 638 */ getAutosaveSlot()639 virtual int getAutosaveSlot() const { 640 return 0; 641 } 642 }; 643 644 645 /** @name Chained games 646 * 647 * @{ 648 */ 649 650 /** 651 * Singleton class which manages chained games. 652 * 653 * A chained game is one that starts automatically, optionally loading 654 * a saved game, instead of returning to the launcher. 655 */ 656 class ChainedGamesManager : public Common::Singleton<ChainedGamesManager> { 657 private: 658 struct Game { 659 Common::String target; 660 int slot; 661 }; 662 663 Common::Queue<Game> _chainedGames; 664 665 public: 666 ChainedGamesManager(); 667 /** Clear the chained games manager of any games. */ 668 void clear(); 669 /** Load a game into a slot in the chained games manager. */ 670 void push(const Common::String target, const int slot = -1); 671 /** Pop the last game loaded into the chained games manager. */ 672 bool pop(Common::String &target, int &slot); 673 }; 674 675 /** Convenience shortcut for accessing the chained games manager. */ 676 #define ChainedGamesMan ChainedGamesManager::instance() 677 /** @} */ 678 /** Current workaround for MidiEmu & error(). */ //FIXME 679 extern Engine *g_engine; 680 /** @} */ 681 #endif 682