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