ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

engine.cpp

Go to the documentation of this file.
00001 /* ScummVM - Graphic Adventure Engine
00002  *
00003  * ScummVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the COPYRIGHT
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #define FORBIDDEN_SYMBOL_EXCEPTION_getcwd
00024 
00025 #if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__SYMBIAN32__)
00026 #define WIN32_LEAN_AND_MEAN
00027 #include <windows.h>
00028 #include <direct.h>
00029 #endif
00030 
00031 #include "engines/engine.h"
00032 #include "engines/dialogs.h"
00033 #include "engines/util.h"
00034 
00035 #include "common/config-manager.h"
00036 #include "common/events.h"
00037 #include "common/file.h"
00038 #include "common/system.h"
00039 #include "common/str.h"
00040 #include "common/error.h"
00041 #include "common/list.h"
00042 #include "common/memstream.h"
00043 #include "common/scummsys.h"
00044 #include "common/taskbar.h"
00045 #include "common/textconsole.h"
00046 #include "common/translation.h"
00047 #include "common/singleton.h"
00048 
00049 #include "backends/keymapper/keymapper.h"
00050 #include "base/version.h"
00051 
00052 #include "gui/gui-manager.h"
00053 #include "gui/debugger.h"
00054 #include "gui/dialog.h"
00055 #include "gui/message.h"
00056 
00057 #include "audio/mixer.h"
00058 
00059 #include "graphics/cursorman.h"
00060 #include "graphics/fontman.h"
00061 #include "graphics/pixelformat.h"
00062 #include "image/bmp.h"
00063 
00064 #ifdef _WIN32_WCE
00065 extern bool isSmartphone();
00066 #endif
00067 
00068 // FIXME: HACK for error()
00069 Engine *g_engine = 0;
00070 
00071 // Output formatter for debug() and error() which invokes
00072 // the errorString method of the active engine, if any.
00073 static void defaultOutputFormatter(char *dst, const char *src, size_t dstSize) {
00074     if (g_engine) {
00075         g_engine->errorString(src, dst, dstSize);
00076     } else {
00077         Common::strlcpy(dst, src, dstSize);
00078     }
00079 }
00080 
00081 static void defaultErrorHandler(const char *msg) {
00082     // Unless this error -originated- within the debugger itself, we
00083     // now invoke the debugger, if available / supported.
00084     if (g_engine) {
00085         GUI::Debugger *debugger = g_engine->getDebugger();
00086 #ifdef _WIN32_WCE
00087         if (isSmartphone())
00088             debugger = 0;
00089 #endif
00090 
00091 #if defined(USE_TASKBAR)
00092         g_system->getTaskbarManager()->notifyError();
00093 #endif
00094 
00095         if (debugger && !debugger->isActive()) {
00096             debugger->attach(msg);
00097             debugger->onFrame();
00098         }
00099 
00100 
00101 #if defined(USE_TASKBAR)
00102         g_system->getTaskbarManager()->clearError();
00103 #endif
00104 
00105     }
00106 }
00107 
00108 // Chained games manager
00109 
00110 ChainedGamesManager::ChainedGamesManager() {
00111     clear();
00112 }
00113 
00114 void ChainedGamesManager::clear() {
00115     _chainedGames.clear();
00116 }
00117 
00118 void ChainedGamesManager::push(const Common::String target, const int slot) {
00119     Game game;
00120     game.target = target;
00121     game.slot = slot;
00122     _chainedGames.push(game);
00123 }
00124 
00125 bool ChainedGamesManager::pop(Common::String &target, int &slot) {
00126     if (_chainedGames.empty()) {
00127         return false;
00128     }
00129     Game game = _chainedGames.pop();
00130     target = game.target;
00131     slot = game.slot;
00132     return true;
00133 }
00134 
00135 namespace Common {
00136 DECLARE_SINGLETON(ChainedGamesManager);
00137 }
00138 
00139 Engine::Engine(OSystem *syst)
00140     : _system(syst),
00141         _mixer(_system->getMixer()),
00142         _timer(_system->getTimerManager()),
00143         _eventMan(_system->getEventManager()),
00144         _saveFileMan(_system->getSavefileManager()),
00145         _targetName(ConfMan.getActiveDomainName()),
00146         _pauseLevel(0),
00147         _pauseStartTime(0),
00148         _saveSlotToLoad(-1),
00149         _engineStartTime(_system->getMillis()),
00150         _mainMenuDialog(NULL) {
00151 
00152     g_engine = this;
00153     Common::setErrorOutputFormatter(defaultOutputFormatter);
00154     Common::setErrorHandler(defaultErrorHandler);
00155 
00156     // FIXME: Get rid of the following again. It is only here
00157     // temporarily. We really should never run with a non-working Mixer,
00158     // so ought to handle this at a much earlier stage. If we *really*
00159     // want to support systems without a working mixer, then we need
00160     // more work. E.g. we could modify the Mixer to immediately drop any
00161     // streams passed to it. This way, at least we don't crash because
00162     // heaps of (sound) memory get allocated but never freed. Of course,
00163     // there still would be problems with many games...
00164     if (!_mixer->isReady())
00165         warning("Sound initialization failed. This may cause severe problems in some games");
00166 
00167     // Setup a dummy cursor and palette, so that all engines can use
00168     // CursorMan.replace without having any headaches about memory leaks.
00169     //
00170     // If an engine only used CursorMan.replaceCursor and no cursor has
00171     // been setup before, then replaceCursor just uses pushCursor. This
00172     // means that that the engine's cursor is never again removed from
00173     // CursorMan. Hence we setup a fake cursor here and remove it again
00174     // in the destructor.
00175     CursorMan.pushCursor(NULL, 0, 0, 0, 0, 0);
00176     // Note: Using this dummy palette will actually disable cursor
00177     // palettes till the user enables it again.
00178     CursorMan.pushCursorPalette(NULL, 0, 0);
00179 }
00180 
00181 Engine::~Engine() {
00182     _mixer->stopAll();
00183 
00184     delete _mainMenuDialog;
00185     g_engine = NULL;
00186 
00187     // Remove our cursors again to prevent memory leaks
00188     CursorMan.popCursor();
00189     CursorMan.popCursorPalette();
00190 }
00191 
00192 void Engine::initializePath(const Common::FSNode &gamePath) {
00193     SearchMan.addDirectory(gamePath.getPath(), gamePath, 0, 4);
00194 }
00195 
00196 void initCommonGFX() {
00197     const Common::ConfigManager::Domain *gameDomain = ConfMan.getActiveDomain();
00198 
00199     // Any global or command line settings already have been applied at the time
00200     // we get here, so we only do something if the game domain overrides those
00201     // values
00202     if (gameDomain) {
00203         if (gameDomain->contains("aspect_ratio"))
00204             g_system->setFeatureState(OSystem::kFeatureAspectRatioCorrection, ConfMan.getBool("aspect_ratio"));
00205 
00206         if (gameDomain->contains("fullscreen"))
00207             g_system->setFeatureState(OSystem::kFeatureFullscreenMode, ConfMan.getBool("fullscreen"));
00208 
00209         if (gameDomain->contains("filtering"))
00210             g_system->setFeatureState(OSystem::kFeatureFilteringMode, ConfMan.getBool("filtering"));
00211 
00212         if (gameDomain->contains("stretch_mode"))
00213             g_system->setStretchMode(ConfMan.get("stretch_mode").c_str());
00214     }
00215 }
00216 
00217 // Please leave the splash screen in working order for your releases, even if they're commercial.
00218 // This is a proper and good way to show your appreciation for our hard work over these years.
00219 bool splash = false;
00220 
00221 #include "logo_data.h"
00222 
00223 void splashScreen() {
00224     Common::MemoryReadStream stream(logo_data, ARRAYSIZE(logo_data));
00225 
00226     Image::BitmapDecoder bitmap;
00227 
00228     if (!bitmap.loadStream(stream)) {
00229         warning("Error loading logo file");
00230         return;
00231     }
00232 
00233     g_system->showOverlay();
00234 
00235     // Fill with blue - ResidualVM theme
00236     Graphics::Surface screen;
00237     screen.create(g_system->getOverlayWidth(), g_system->getOverlayHeight(), g_system->getOverlayFormat());
00238     screen.fillRect(Common::Rect(screen.w, screen.h), screen.format.ARGBToColor(0xff, 0x1e, 0x6f, 0x95)); // ResidualVM theme
00239 
00240     // Load logo
00241     Graphics::Surface *logo = bitmap.getSurface()->convertTo(g_system->getOverlayFormat(), bitmap.getPalette());
00242     int lx = MAX((g_system->getOverlayWidth() - logo->w) / 2, 0);
00243     int ly = MAX((g_system->getOverlayHeight() - logo->h) / 2, 0);
00244 
00245     // Print version information
00246     const Graphics::Font *font = FontMan.getFontByUsage(Graphics::FontManager::kConsoleFont);
00247     int w = font->getStringWidth(gScummVMVersionDate);
00248     int x = g_system->getOverlayWidth() - w - 5; // lx + logo->w - w + 5;
00249     int y = g_system->getOverlayHeight() - font->getFontHeight() - 5; //ly + logo->h + 5;
00250     font->drawString(&screen, gScummVMVersionDate, x, y, w, screen.format.ARGBToColor(0xff, 0, 0, 0));
00251 
00252     g_system->copyRectToOverlay(screen.getPixels(), screen.pitch, 0, 0, screen.w, screen.h);
00253     screen.free();
00254 
00255     // Draw logo
00256     int lw = MIN<uint16>(logo->w, g_system->getOverlayWidth() - lx);
00257     int lh = MIN<uint16>(logo->h, g_system->getOverlayHeight() - ly);
00258 
00259     g_system->copyRectToOverlay(logo->getPixels(), logo->pitch, lx, ly, lw, lh);
00260     logo->free();
00261     delete logo;
00262 
00263     g_system->updateScreen();
00264 
00265     // Delay 0.6 secs
00266     uint time0 = g_system->getMillis();
00267     Common::Event event;
00268     while (time0 + 600 > g_system->getMillis()) {
00269         (void)g_system->getEventManager()->pollEvent(event);
00270         g_system->delayMillis(10);
00271     }
00272     g_system->hideOverlay();
00273 
00274     splash = true;
00275 }
00276 
00277 void initGraphicsModes(const Graphics::ModeList &modes) {
00278     g_system->initSizeHint(modes);
00279 }
00280 
00281 void initGraphics(int width, int height, const Graphics::PixelFormat *format) {
00282 
00283     g_system->beginGFXTransaction();
00284 
00285         initCommonGFX();
00286 #ifdef USE_RGB_COLOR
00287         if (format)
00288             g_system->initSize(width, height, format);
00289         else {
00290             Graphics::PixelFormat bestFormat = g_system->getSupportedFormats().front();
00291             g_system->initSize(width, height, &bestFormat);
00292         }
00293 #else
00294         g_system->initSize(width, height);
00295 #endif
00296 
00297     OSystem::TransactionError gfxError = g_system->endGFXTransaction();
00298 
00299     if (!splash && !GUI::GuiManager::instance()._launched)
00300         splashScreen();
00301 
00302     if (gfxError == OSystem::kTransactionSuccess)
00303         return;
00304 
00305     // Error out on size switch failure
00306     if (gfxError & OSystem::kTransactionSizeChangeFailed) {
00307         Common::String message;
00308         message = Common::String::format("Could not switch to resolution: '%dx%d'.", width, height);
00309 
00310         GUIErrorMessage(message);
00311         error("%s", message.c_str());
00312     }
00313 
00314     // Just show warnings then these occur:
00315 #ifdef USE_RGB_COLOR
00316     if (gfxError & OSystem::kTransactionFormatNotSupported) {
00317         Common::String message = _("Could not initialize color format.");
00318 
00319         GUI::MessageDialog dialog(message);
00320         dialog.runModal();
00321     }
00322 #endif
00323 
00324     if (gfxError & OSystem::kTransactionModeSwitchFailed) {
00325         Common::String message = _("Could not switch to video mode: '");
00326         message += ConfMan.get("gfx_mode");
00327         message += "'.";
00328 
00329         GUI::MessageDialog dialog(message);
00330         dialog.runModal();
00331     }
00332 
00333     if (gfxError & OSystem::kTransactionStretchModeSwitchFailed) {
00334         Common::String message = _("Could not switch to stretch mode: '");
00335         message += ConfMan.get("stretch_mode");
00336         message += "'.";
00337 
00338         GUI::MessageDialog dialog(message);
00339         dialog.runModal();
00340     }
00341 
00342     if (gfxError & OSystem::kTransactionAspectRatioFailed) {
00343         GUI::MessageDialog dialog(_("Could not apply aspect ratio setting."));
00344         dialog.runModal();
00345     }
00346 
00347     if (gfxError & OSystem::kTransactionFullscreenFailed) {
00348         GUI::MessageDialog dialog(_("Could not apply fullscreen setting."));
00349         dialog.runModal();
00350     }
00351 
00352     if (gfxError & OSystem::kTransactionFilteringFailed) {
00353         GUI::MessageDialog dialog(_("Could not apply filtering setting."));
00354         dialog.runModal();
00355     }
00356 }
00357 
00366 inline Graphics::PixelFormat findCompatibleFormat(const Common::List<Graphics::PixelFormat> &backend, const Common::List<Graphics::PixelFormat> &frontend) {
00367 #ifdef USE_RGB_COLOR
00368     for (Common::List<Graphics::PixelFormat>::const_iterator i = backend.begin(); i != backend.end(); ++i) {
00369         for (Common::List<Graphics::PixelFormat>::const_iterator j = frontend.begin(); j != frontend.end(); ++j) {
00370             if (*i == *j)
00371                 return *i;
00372         }
00373     }
00374 #endif
00375     return Graphics::PixelFormat::createFormatCLUT8();
00376 }
00377 
00378 
00379 void initGraphics(int width, int height, const Common::List<Graphics::PixelFormat> &formatList) {
00380     Graphics::PixelFormat format = findCompatibleFormat(g_system->getSupportedFormats(), formatList);
00381     initGraphics(width, height, &format);
00382 }
00383 
00384 void initGraphics(int width, int height) {
00385     Graphics::PixelFormat format = Graphics::PixelFormat::createFormatCLUT8();
00386     initGraphics(width, height, &format);
00387 }
00388 
00389 void GUIErrorMessage(const Common::String &msg) {
00390     g_system->setWindowCaption("Error");
00391     g_system->beginGFXTransaction();
00392         initCommonGFX();
00393         g_system->initSize(320, 200);
00394         g_system->launcherInitSize(640, 480);//ResidualVM specific
00395     if (g_system->endGFXTransaction() == OSystem::kTransactionSuccess) {
00396         GUI::MessageDialog dialog(msg);
00397         dialog.runModal();
00398     } else {
00399         error("%s", msg.c_str());
00400     }
00401 }
00402 
00403 void GUIErrorMessageFormat(const char *fmt, ...) {
00404     Common::String msg;
00405 
00406     va_list va;
00407     va_start(va, fmt);
00408     msg = Common::String::vformat(fmt, va);
00409     va_end(va);
00410 
00411     GUIErrorMessage(msg);
00412 }
00413 
00414 void Engine::checkCD() {
00415 #if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__SYMBIAN32__)
00416     // It is a known bug under Windows that games that play CD audio cause
00417     // ScummVM to crash if the data files are read from the same CD. Check
00418     // if this appears to be the case and issue a warning.
00419 
00420     // If we can find a compressed audio track, then it should be ok even
00421     // if it's running from CD.
00422 
00423 #ifdef USE_VORBIS
00424     if (Common::File::exists("track1.ogg") ||
00425         Common::File::exists("track01.ogg"))
00426         return;
00427 #endif
00428 #ifdef USE_FLAC
00429     if (Common::File::exists("track1.fla") ||
00430             Common::File::exists("track1.flac") ||
00431         Common::File::exists("track01.fla") ||
00432         Common::File::exists("track01.flac"))
00433         return;
00434 #endif
00435 #ifdef USE_MAD
00436     if (Common::File::exists("track1.mp3") ||
00437         Common::File::exists("track01.mp3"))
00438         return;
00439 #endif
00440 
00441     char buffer[MAXPATHLEN];
00442     int i;
00443 
00444     const Common::FSNode gameDataDir(ConfMan.get("path"));
00445 
00446     if (gameDataDir.getPath().empty()) {
00447         // That's it! I give up!
00448         if (getcwd(buffer, MAXPATHLEN) == NULL)
00449             return;
00450     } else
00451         Common::strlcpy(buffer, gameDataDir.getPath().c_str(), sizeof(buffer));
00452 
00453     for (i = 0; i < MAXPATHLEN - 1; i++) {
00454         if (buffer[i] == '\\')
00455             break;
00456     }
00457 
00458     buffer[i + 1] = 0;
00459 
00460     if (GetDriveType(buffer) == DRIVE_CDROM) {
00461         GUI::MessageDialog dialog(
00462             _("You appear to be playing this game directly\n"
00463             "from the CD. This is known to cause problems,\n"
00464             "and it is therefore recommended that you copy\n"
00465             "the data files to your hard disk instead.\n"
00466             "See the README file for details."), _("OK"));
00467         dialog.runModal();
00468     } else {
00469         // If we reached here, the game has audio tracks,
00470         // it's not ran from the CD and the tracks have not
00471         // been ripped.
00472         GUI::MessageDialog dialog(
00473             _("This game has audio tracks in its disk. These\n"
00474             "tracks need to be ripped from the disk using\n"
00475             "an appropriate CD audio extracting tool in\n"
00476             "order to listen to the game's music.\n"
00477             "See the README file for details."), _("OK"));
00478         dialog.runModal();
00479     }
00480 #endif
00481 }
00482 
00483 bool Engine::shouldPerformAutoSave(int lastSaveTime) {
00484     const int diff = _system->getMillis() - lastSaveTime;
00485     const int autosavePeriod = ConfMan.getInt("autosave_period");
00486     return autosavePeriod != 0 && diff > autosavePeriod * 1000;
00487 }
00488 
00489 void Engine::errorString(const char *buf1, char *buf2, int size) {
00490     Common::strlcpy(buf2, buf1, size);
00491 }
00492 
00493 void Engine::pauseEngine(bool pause) {
00494     assert((pause && _pauseLevel >= 0) || (!pause && _pauseLevel));
00495 
00496     if (pause)
00497         _pauseLevel++;
00498     else
00499         _pauseLevel--;
00500 
00501     if (_pauseLevel == 1 && pause) {
00502         _pauseStartTime = _system->getMillis();
00503         pauseEngineIntern(true);
00504     } else if (_pauseLevel == 0) {
00505         pauseEngineIntern(false);
00506         _engineStartTime += _system->getMillis() - _pauseStartTime;
00507         _pauseStartTime = 0;
00508     }
00509 }
00510 
00511 void Engine::pauseEngineIntern(bool pause) {
00512     // By default, just (un)pause all digital sounds
00513     _mixer->pauseAll(pause);
00514 }
00515 
00516 void Engine::openMainMenuDialog() {
00517     if (!_mainMenuDialog)
00518         _mainMenuDialog = new MainMenuDialog(this);
00519 
00520     setGameToLoadSlot(-1);
00521 
00522     runDialog(*_mainMenuDialog);
00523 
00524     // Load savegame after main menu execution
00525     // (not from inside the menu loop to avoid
00526     // mouse cursor glitches and simliar bugs,
00527     // e.g. #2822778).
00528     if (_saveSlotToLoad >= 0) {
00529         Common::Error status = loadGameState(_saveSlotToLoad);
00530         if (status.getCode() != Common::kNoError) {
00531             Common::String failMessage = Common::String::format(_("Failed to load saved game (%s)! "
00532                   "Please consult the README for basic information, and for "
00533                   "instructions on how to obtain further assistance."), status.getDesc().c_str());
00534             GUI::MessageDialog dialog(failMessage);
00535             dialog.runModal();
00536         }
00537     }
00538 
00539     syncSoundSettings();
00540 }
00541 
00542 bool Engine::warnUserAboutUnsupportedGame() {
00543     if (ConfMan.getBool("enable_unsupported_game_warning")) {
00544         GUI::MessageDialog alert(_("WARNING: The game you are about to start is"
00545             " not yet fully supported by ResidualVM. As such, it is likely to be"
00546             " unstable, and any saved game you make might not work in future"
00547             " versions of ResidualVM."), _("Start anyway"), _("Cancel"));
00548         return alert.runModal() == GUI::kMessageOK;
00549     }
00550     return true;
00551 }
00552 
00553 uint32 Engine::getTotalPlayTime() const {
00554     if (!_pauseLevel)
00555         return _system->getMillis() - _engineStartTime;
00556     else
00557         return _pauseStartTime - _engineStartTime;
00558 }
00559 
00560 void Engine::setTotalPlayTime(uint32 time) {
00561     const uint32 currentTime = _system->getMillis();
00562 
00563     // We need to reset the pause start time here in case the engine is already
00564     // paused to avoid any incorrect play time counting.
00565     if (_pauseLevel > 0)
00566         _pauseStartTime = currentTime;
00567 
00568     _engineStartTime = currentTime - time;
00569 }
00570 
00571 int Engine::runDialog(GUI::Dialog &dialog) {
00572     pauseEngine(true);
00573     int result = dialog.runModal();
00574     pauseEngine(false);
00575 
00576     return result;
00577 }
00578 
00579 void Engine::setGameToLoadSlot(int slot) {
00580     _saveSlotToLoad = slot;
00581 }
00582 
00583 void Engine::syncSoundSettings() {
00584     // Sync the engine with the config manager
00585     int soundVolumeMusic = ConfMan.getInt("music_volume");
00586     int soundVolumeSFX = ConfMan.getInt("sfx_volume");
00587     int soundVolumeSpeech = ConfMan.getInt("speech_volume");
00588 
00589     bool mute = false;
00590     if (ConfMan.hasKey("mute"))
00591         mute = ConfMan.getBool("mute");
00592 
00593     // We need to handle the speech mute separately here. This is because the
00594     // engine code should be able to rely on all speech sounds muted when the
00595     // user specified subtitles only mode, which results in "speech_mute" to
00596     // be set to "true". The global mute setting has precedence over the
00597     // speech mute setting though.
00598     bool speechMute = mute;
00599     if (!speechMute)
00600         speechMute = ConfMan.getBool("speech_mute");
00601 
00602     _mixer->muteSoundType(Audio::Mixer::kPlainSoundType, mute);
00603     _mixer->muteSoundType(Audio::Mixer::kMusicSoundType, mute);
00604     _mixer->muteSoundType(Audio::Mixer::kSFXSoundType, mute);
00605     _mixer->muteSoundType(Audio::Mixer::kSpeechSoundType, speechMute);
00606 
00607     _mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, Audio::Mixer::kMaxMixerVolume);
00608     _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, soundVolumeMusic);
00609     _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, soundVolumeSFX);
00610     _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, soundVolumeSpeech);
00611 }
00612 
00613 void Engine::deinitKeymap() {
00614 #ifdef ENABLE_KEYMAPPER
00615     _eventMan->getKeymapper()->cleanupGameKeymaps();
00616 #endif
00617 }
00618 
00619 void Engine::flipMute() {
00620     // Mute will be set to true by default here. This has two reasons:
00621     // - if the game already has an "mute" config entry, it will be overwritten anyway.
00622     // - if it does not have a "mute" config entry, the sound is unmuted currently and should be muted now.
00623     bool mute = true;
00624 
00625     if (ConfMan.hasKey("mute")) {
00626         mute = !ConfMan.getBool("mute");
00627     }
00628 
00629     ConfMan.setBool("mute", mute);
00630 
00631     syncSoundSettings();
00632 }
00633 
00634 Common::Error Engine::loadGameState(int slot) {
00635     // Do nothing by default
00636     return Common::kNoError;
00637 }
00638 
00639 bool Engine::canLoadGameStateCurrently() {
00640     // Do not allow loading by default
00641     return false;
00642 }
00643 
00644 Common::Error Engine::saveGameState(int slot, const Common::String &desc) {
00645     // Do nothing by default
00646     return Common::kNoError;
00647 }
00648 
00649 bool Engine::canSaveGameStateCurrently() {
00650     // Do not allow saving by default
00651     return false;
00652 }
00653 
00654 void Engine::quitGame() {
00655     Common::Event event;
00656 
00657     event.type = Common::EVENT_QUIT;
00658     g_system->getEventManager()->pushEvent(event);
00659 }
00660 
00661 bool Engine::shouldQuit() {
00662     Common::EventManager *eventMan = g_system->getEventManager();
00663     return (eventMan->shouldQuit() || eventMan->shouldRTL());
00664 }
00665 
00666 /*
00667 EnginePlugin *Engine::getMetaEnginePlugin() const {
00668 
00669     const EnginePlugin *plugin = 0;
00670     Common::String gameid = ConfMan.get("gameid");
00671     gameid.toLowercase();
00672     EngineMan.findGame(gameid, &plugin);
00673     return plugin;
00674 }
00675 
00676 */


Generated on Sat Jul 20 2019 05:00:48 for ResidualVM by doxygen 1.7.1
curved edge   curved edge