void Engine::openMainMenuDialog() { if (!_mainMenuDialog) _mainMenuDialog = new MainMenuDialog(this); setGameToLoadSlot(-1); runDialog(*_mainMenuDialog); // Load savegame after main menu execution // (not from inside the menu loop to avoid // mouse cursor glitches and simliar bugs, // e.g. #2822778). if (_saveSlotToLoad >= 0) { Common::Error status = loadGameState(_saveSlotToLoad); if (status.getCode() != Common::kNoError) { Common::String failMessage = Common::String::format(_("Gamestate load failed (%s)! " "Please consult the README for basic information, and for " "instructions on how to obtain further assistance."), status.getDesc().c_str()); GUI::MessageDialog dialog(failMessage); dialog.runModal(); } } syncSoundSettings(); }
void MainMenuDialog::save() { int slot = _saveDialog->runModalWithCurrentTarget(); #if defined(__PLAYSTATION2__) && defined(DYNAMIC_MODULES) char pokeme[32]; snprintf(pokeme,32,"hack"); #endif if (slot >= 0) { Common::String result(_saveDialog->getResultString()); if (result.empty()) { // If the user was lazy and entered no save name, come up with a default name. result = _saveDialog->createDefaultSaveDescription(slot); } Common::Error status = _engine->saveGameState(slot, result); if (status.getCode() != Common::kNoError) { Common::String failMessage = Common::String::format(_("Gamestate save failed (%s)! " "Please consult the README for basic information, and for " "instructions on how to obtain further assistance."), status.getDesc().c_str()); GUI::MessageDialog dialog(failMessage); dialog.runModal(); } close(); } }
void displayErrorDialog(const Common::Error &error, const char *extraText) { Common::String errorText(extraText); errorText += " "; errorText += _(error.getDesc()); GUI::MessageDialog alert(errorText); alert.runModal(); }
void MohawkEngine_Riven::loadGameStateAndDisplayError(int slot) { assert(slot >= 0); Common::Error loadError = loadGameState(slot); if (loadError.getCode() != Common::kNoError) { GUI::MessageDialog dialog(loadError.getDesc()); dialog.runModal(); } }
TestExitStatus SaveGametests::testListingSavefile() { Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); saveFileMan->clearError(); // create some savefiles const char *savefileName[] = {"tBedSavefileToList.0", "tBedSavefileToList.1", "tBedSavefileToList.2"}; writeDataToFile("tBedSavefileToList.0", "Save me!"); writeDataToFile("tBedSavefileToList.1", "Save me!"); writeDataToFile("tBedSavefileToList.2", "Save me!"); Common::Error err = saveFileMan->getError(); if (err.getCode() != Common::kNoError) { // Abort. Some Error in writing files Testsuite::logDetailedPrintf("Error while creating savefiles: %s\n", err.getDesc().c_str()); return kTestFailed; } Common::StringArray savefileList = saveFileMan->listSavefiles("tBedSavefileToList.?"); if (savefileList.size() == ARRAYSIZE(savefileName)) { // Match them exactly // As the order of savefileList may be platform specific, match them exhaustively for (uint i = 0; i < ARRAYSIZE(savefileName); i++) { for (uint j = 0; j < savefileList.size(); j++) { if (savefileList[j].equals(savefileName[i])) { break; } if (savefileList.size() == j) { // A match for this name not found Testsuite::logDetailedPrintf("Listed Names don't match\n"); return kTestFailed; } } } return kTestPassed; } Testsuite::logDetailedPrintf("listing Savefiles failed!\n"); return kTestFailed; }
extern "C" int scummvm_main(int argc, const char * const argv[]) { Common::String specialDebug; Common::String command; // Verify that the backend has been initialized (i.e. g_system has been set). assert(g_system); OSystem &system = *g_system; // Register config manager defaults Base::registerDefaults(); // Parse the command line Common::StringMap settings; command = Base::parseCommandLine(settings, argc, argv); // Load the config file (possibly overridden via command line): if (settings.contains("config")) { ConfMan.loadConfigFile(settings["config"]); settings.erase("config"); } else { ConfMan.loadDefaultConfigFile(); } // Update the config file ConfMan.set("versioninfo", gScummVMVersion, Common::ConfigManager::kApplicationDomain); // Load and setup the debuglevel and the debug flags. We do this at the // soonest possible moment to ensure debug output starts early on, if // requested. if (settings.contains("debuglevel")) { gDebugLevel = (int)strtol(settings["debuglevel"].c_str(), 0, 10); printf("Debuglevel (from command line): %d\n", gDebugLevel); settings.erase("debuglevel"); // This option should not be passed to ConfMan. } else if (ConfMan.hasKey("debuglevel")) gDebugLevel = ConfMan.getInt("debuglevel"); if (settings.contains("debugflags")) { specialDebug = settings["debugflags"]; settings.erase("debugflags"); } PluginManager::instance().init(); PluginManager::instance().loadAllPlugins(); // load plugins for cached plugin manager // If we received an invalid music parameter via command line we check this here. // We can't check this before loading the music plugins. // On the other hand we cannot load the plugins before we know the file paths (in case of external plugins). if (settings.contains("music-driver")) { if (MidiDriver::getMusicType(MidiDriver::getDeviceHandle(settings["music-driver"])) == MT_INVALID) { warning("Unrecognized music driver '%s'. Switching to default device", settings["music-driver"].c_str()); settings["music-driver"] = "auto"; } } // Process the remaining command line settings. Must be done after the // config file and the plugins have been loaded. Common::Error res; // TODO: deal with settings that require plugins to be loaded res = Base::processSettings(command, settings); if (res.getCode() != Common::kArgumentNotProcessed) { warning("%s", res.getDesc().c_str()); return res.getCode(); } // Init the backend. Must take place after all config data (including // the command line params) was read. system.initBackend(); // If we received an invalid graphics mode parameter via command line // we check this here. We can't do it until after the backend is inited, // or there won't be a graphics manager to ask for the supported modes. if (settings.contains("gfx-mode")) { const OSystem::GraphicsMode *gm = g_system->getSupportedGraphicsModes(); Common::String option = settings["gfx-mode"]; bool isValid = false; while (gm->name && !isValid) { isValid = !scumm_stricmp(gm->name, option.c_str()); gm++; } if (!isValid) { warning("Unrecognized graphics mode '%s'. Switching to default mode", option.c_str()); settings["gfx-mode"] = "default"; } } setupGraphics(system); // Init the different managers that are used by the engines. // Do it here to prevent fragmentation later system.getAudioCDManager(); MusicManager::instance(); Common::DebugManager::instance(); // Init the event manager. As the virtual keyboard is loaded here, it must // take place after the backend is initiated and the screen has been setup system.getEventManager()->init(); // Directly after initializing the event manager, we will initialize our // event recorder. // // TODO: This is just to match the current behavior, when we further extend // our event recorder, we might do this at another place. Or even change // the whole API for that ;-). g_eventRec.init(); // Now as the event manager is created, setup the keymapper setupKeymapper(system); // Unless a game was specified, show the launcher dialog if (0 == ConfMan.getActiveDomain()) launcherDialog(); // FIXME: We're now looping the launcher. This, of course, doesn't // work as well as it should. In theory everything should be destroyed // cleanly, so this is now enabled to encourage people to fix bits :) while (0 != ConfMan.getActiveDomain()) { // Try to find a plugin which feels responsible for the specified game. const EnginePlugin *plugin = detectPlugin(); if (plugin) { // Unload all plugins not needed for this game, // to save memory PluginManager::instance().unloadPluginsExcept(PLUGIN_TYPE_ENGINE, plugin); // Try to run the game Common::Error result = runGame(plugin, system, specialDebug); #if defined(UNCACHED_PLUGINS) && defined(DYNAMIC_MODULES) // do our best to prevent fragmentation by unloading as soon as we can PluginManager::instance().unloadPluginsExcept(PLUGIN_TYPE_ENGINE, NULL, false); // reallocate the config manager to get rid of any fragmentation ConfMan.defragment(); #endif // Did an error occur ? if (result.getCode() != Common::kNoError) { // Shows an informative error dialog if starting the selected game failed. GUI::displayErrorDialog(result, _("Error running game:")); } // Quit unless an error occurred, or Return to launcher was requested #ifndef FORCE_RTL if (result.getCode() == Common::kNoError && !g_system->getEventManager()->shouldRTL()) break; #endif // Reset RTL flag in case we want to load another engine g_system->getEventManager()->resetRTL(); #ifdef FORCE_RTL g_system->getEventManager()->resetQuit(); #endif // Discard any command line options. It's unlikely that the user // wanted to apply them to *all* games ever launched. ConfMan.getDomain(Common::ConfigManager::kTransientDomain)->clear(); // Clear the active config domain ConfMan.setActiveDomain(""); PluginManager::instance().loadAllPlugins(); // only for cached manager } else { GUI::displayErrorDialog(_("Could not find any engine capable of running the selected game")); } // reset the graphics to default setupGraphics(system); launcherDialog(); } PluginManager::instance().unloadAllPlugins(); PluginManager::destroy(); GUI::GuiManager::destroy(); Common::ConfigManager::destroy(); Common::SearchManager::destroy(); #ifdef USE_TRANSLATION Common::TranslationManager::destroy(); #endif return 0; }
// TODO: specify the possible return values here static Common::Error runGame(const EnginePlugin *plugin, OSystem &system, const Common::String &edebuglevels) { // Determine the game data path, for validation and error messages Common::FSNode dir(ConfMan.get("path")); Common::Error err = Common::kNoError; Engine *engine = 0; // Verify that the game path refers to an actual directory if (!(dir.exists() && dir.isDirectory())) err = Common::kPathNotDirectory; // Create the game engine if (err.getCode() == Common::kNoError) err = (*plugin)->createInstance(&system, &engine); // Check for errors if (!engine || err.getCode() != Common::kNoError) { // Print a warning; note that scummvm_main will also // display an error dialog, so we don't have to do this here. warning("%s failed to instantiate engine: %s (target '%s', path '%s')", plugin->getName(), err.getDesc().c_str(), ConfMan.getActiveDomainName().c_str(), dir.getPath().c_str() ); // Autoadded is set only when no path was provided and // the game is run from command line. // // Thus, we remove this garbage entry // // Fixes bug #1544799 if (ConfMan.hasKey("autoadded")) { ConfMan.removeGameDomain(ConfMan.getActiveDomainName().c_str()); } return err; } // Set the window caption to the game name Common::String caption(ConfMan.get("description")); if (caption.empty()) { caption = EngineMan.findGame(ConfMan.get("gameid")).description(); } if (caption.empty()) caption = ConfMan.getActiveDomainName(); // Use the domain (=target) name if (!caption.empty()) { system.setWindowCaption(caption.c_str()); } // // Setup various paths in the SearchManager // // Add the game path to the directory search list SearchMan.addDirectory(dir.getPath(), dir, 0, 4); // Add extrapath (if any) to the directory search list if (ConfMan.hasKey("extrapath")) { dir = Common::FSNode(ConfMan.get("extrapath")); SearchMan.addDirectory(dir.getPath(), dir); } // If a second extrapath is specified on the app domain level, add that as well. if (ConfMan.hasKey("extrapath", Common::ConfigManager::kApplicationDomain)) { dir = Common::FSNode(ConfMan.get("extrapath", Common::ConfigManager::kApplicationDomain)); SearchMan.addDirectory(dir.getPath(), dir); } // On creation the engine should have set up all debug levels so we can use // the command line arugments here Common::StringTokenizer tokenizer(edebuglevels, " ,"); while (!tokenizer.empty()) { Common::String token = tokenizer.nextToken(); if (!DebugMan.enableDebugChannel(token)) warning(_("Engine does not support debug level '%s'"), token.c_str()); } // Inform backend that the engine is about to be run system.engineInit(); // Run the engine Common::Error result = engine->run(); // Inform backend that the engine finished system.engineDone(); // Free up memory delete engine; // We clear all debug levels again even though the engine should do it DebugMan.clearAllDebugChannels(); // Reset the file/directory mappings SearchMan.clear(); // Return result (== 0 means no error) return result; }
void SaveLoadMenuScreen::checkError(Common::Error error) { if (error.getCode() != Common::kNoError) { GUI::MessageDialog dialog(error.getDesc()); dialog.runModal(); } }
// TODO: specify the possible return values here static Common::Error runGame(const EnginePlugin *plugin, OSystem &system, const Common::String &edebuglevels) { // Determine the game data path, for validation and error messages Common::FSNode dir(ConfMan.get("path")); Common::Error err = Common::kNoError; Engine *engine = 0; #if defined(SDL_BACKEND) && defined(USE_OPENGL) && defined(USE_RGB_COLOR) // HACK: We set up the requested graphics mode setting here to allow the // backend to switch from Surface SDL to OpenGL if necessary. This is // needed because otherwise the g_system->getSupportedFormats might return // bad values. g_system->beginGFXTransaction(); g_system->setGraphicsMode(ConfMan.get("gfx_mode").c_str()); if (g_system->endGFXTransaction() != OSystem::kTransactionSuccess) { warning("Switching graphics mode to '%s' failed", ConfMan.get("gfx_mode").c_str()); return Common::kUnknownError; } #endif // Verify that the game path refers to an actual directory if (!dir.exists()) { err = Common::kPathDoesNotExist; } else if (!dir.isDirectory()) { err = Common::kPathNotDirectory; } // Create the game engine if (err.getCode() == Common::kNoError) { // Set default values for all of the custom engine options // Appareantly some engines query them in their constructor, thus we // need to set this up before instance creation. const ExtraGuiOptions engineOptions = (*plugin)->getExtraGuiOptions(Common::String()); for (uint i = 0; i < engineOptions.size(); i++) { ConfMan.registerDefault(engineOptions[i].configOption, engineOptions[i].defaultState); } err = (*plugin)->createInstance(&system, &engine); } // Check for errors if (!engine || err.getCode() != Common::kNoError) { // Print a warning; note that scummvm_main will also // display an error dialog, so we don't have to do this here. warning("%s failed to instantiate engine: %s (target '%s', path '%s')", plugin->getName(), err.getDesc().c_str(), ConfMan.getActiveDomainName().c_str(), dir.getPath().c_str() ); // Autoadded is set only when no path was provided and // the game is run from command line. // // Thus, we remove this garbage entry // // Fixes bug #1544799 if (ConfMan.hasKey("autoadded")) { ConfMan.removeGameDomain(ConfMan.getActiveDomainName().c_str()); } return err; } // Set the window caption to the game name Common::String caption(ConfMan.get("description")); if (caption.empty()) { caption = EngineMan.findGame(ConfMan.get("gameid")).description(); } if (caption.empty()) caption = ConfMan.getActiveDomainName(); // Use the domain (=target) name if (!caption.empty()) { system.setWindowCaption(caption.c_str()); } // // Setup various paths in the SearchManager // // Add the game path to the directory search list engine->initializePath(dir); // Add extrapath (if any) to the directory search list if (ConfMan.hasKey("extrapath")) { dir = Common::FSNode(ConfMan.get("extrapath")); SearchMan.addDirectory(dir.getPath(), dir); } // If a second extrapath is specified on the app domain level, add that as well. // However, since the default hasKey() and get() check the app domain level, // verify that it's not already there before adding it. The search manager will // check for that too, so this check is mostly to avoid a warning message. if (ConfMan.hasKey("extrapath", Common::ConfigManager::kApplicationDomain)) { Common::String extraPath = ConfMan.get("extrapath", Common::ConfigManager::kApplicationDomain); if (!SearchMan.hasArchive(extraPath)) { dir = Common::FSNode(extraPath); SearchMan.addDirectory(dir.getPath(), dir); } } // On creation the engine should have set up all debug levels so we can use // the command line arguments here Common::StringTokenizer tokenizer(edebuglevels, " ,"); while (!tokenizer.empty()) { Common::String token = tokenizer.nextToken(); if (token.equalsIgnoreCase("all")) DebugMan.enableAllDebugChannels(); else if (!DebugMan.enableDebugChannel(token)) warning(_("Engine does not support debug level '%s'"), token.c_str()); } // Initialize any game-specific keymaps engine->initKeymap(); // Inform backend that the engine is about to be run system.engineInit(); // Run the engine Common::Error result = engine->run(); // Inform backend that the engine finished system.engineDone(); // Clean up any game-specific keymaps engine->deinitKeymap(); // Free up memory delete engine; // We clear all debug levels again even though the engine should do it DebugMan.clearAllDebugChannels(); // Reset the file/directory mappings SearchMan.clear(); // Return result (== 0 means no error) return result; }
extern "C" int scummvm_main(int argc, const char * const argv[]) { Common::String specialDebug; Common::String command; // Verify that the backend has been initialized (i.e. g_system has been set). assert(g_system); OSystem &system = *g_system; // Register config manager defaults Base::registerDefaults(); // Parse the command line Common::StringMap settings; command = Base::parseCommandLine(settings, argc, argv); // Load the config file (possibly overridden via command line): if (settings.contains("config")) { ConfMan.loadConfigFile(settings["config"]); settings.erase("config"); } else { ConfMan.loadDefaultConfigFile(); } // Update the config file ConfMan.set("versioninfo", gScummVMVersion, Common::ConfigManager::kApplicationDomain); // Load and setup the debuglevel and the debug flags. We do this at the // soonest possible moment to ensure debug output starts early on, if // requested. if (settings.contains("debuglevel")) { gDebugLevel = (int)strtol(settings["debuglevel"].c_str(), 0, 10); printf("Debuglevel (from command line): %d\n", gDebugLevel); settings.erase("debuglevel"); // This option should not be passed to ConfMan. } else if (ConfMan.hasKey("debuglevel")) gDebugLevel = ConfMan.getInt("debuglevel"); if (settings.contains("debugflags")) { specialDebug = settings["debugflags"]; settings.erase("debugflags"); } else if (ConfMan.hasKey("debugflags")) specialDebug = ConfMan.get("debugflags"); if (settings.contains("debug-channels-only")) gDebugChannelsOnly = true; PluginManager::instance().init(); PluginManager::instance().loadAllPlugins(); // load plugins for cached plugin manager // If we received an invalid music parameter via command line we check this here. // We can't check this before loading the music plugins. // On the other hand we cannot load the plugins before we know the file paths (in case of external plugins). if (settings.contains("music-driver")) { if (MidiDriver::getMusicType(MidiDriver::getDeviceHandle(settings["music-driver"])) == MT_INVALID) { warning("Unrecognized music driver '%s'. Switching to default device", settings["music-driver"].c_str()); settings["music-driver"] = "auto"; } } // Process the remaining command line settings. Must be done after the // config file and the plugins have been loaded. Common::Error res; // TODO: deal with settings that require plugins to be loaded if (Base::processSettings(command, settings, res)) { if (res.getCode() != Common::kNoError) warning("%s", res.getDesc().c_str()); return res.getCode(); } // Init the backend. Must take place after all config data (including // the command line params) was read. system.initBackend(); // If we received an invalid graphics mode parameter via command line // we check this here. We can't do it until after the backend is inited, // or there won't be a graphics manager to ask for the supported modes. if (settings.contains("gfx-mode")) { const OSystem::GraphicsMode *gm = g_system->getSupportedGraphicsModes(); Common::String option = settings["gfx-mode"]; bool isValid = false; while (gm->name && !isValid) { isValid = !scumm_stricmp(gm->name, option.c_str()); gm++; } if (!isValid) { warning("Unrecognized graphics mode '%s'. Switching to default mode", option.c_str()); settings["gfx-mode"] = "default"; } } if (settings.contains("disable-display")) { ConfMan.setInt("disable-display", 1, Common::ConfigManager::kTransientDomain); } setupGraphics(system); // Init the different managers that are used by the engines. // Do it here to prevent fragmentation later system.getAudioCDManager(); MusicManager::instance(); Common::DebugManager::instance(); // Init the event manager. As the virtual keyboard is loaded here, it must // take place after the backend is initiated and the screen has been setup system.getEventManager()->init(); #ifdef ENABLE_EVENTRECORDER // Directly after initializing the event manager, we will initialize our // event recorder. // // TODO: This is just to match the current behavior, when we further extend // our event recorder, we might do this at another place. Or even change // the whole API for that ;-). g_eventRec.RegisterEventSource(); #endif Common::OSDMessageQueue::instance().registerEventSource(); // Now as the event manager is created, setup the keymapper setupKeymapper(system); #ifdef USE_UPDATES if (!ConfMan.hasKey("updates_check") && g_system->getUpdateManager()) { GUI::UpdatesDialog dlg; dlg.runModal(); } #endif #if defined(USE_CLOUD) && defined(USE_LIBCURL) CloudMan.init(); CloudMan.syncSaves(); #endif // Unless a game was specified, show the launcher dialog if (0 == ConfMan.getActiveDomain()) launcherDialog(); // FIXME: We're now looping the launcher. This, of course, doesn't // work as well as it should. In theory everything should be destroyed // cleanly, so this is now enabled to encourage people to fix bits :) while (0 != ConfMan.getActiveDomain()) { // Try to find a plugin which feels responsible for the specified game. const EnginePlugin *plugin = detectPlugin(); if (plugin) { // Unload all plugins not needed for this game, // to save memory PluginManager::instance().unloadPluginsExcept(PLUGIN_TYPE_ENGINE, plugin); #ifdef ENABLE_EVENTRECORDER Common::String recordMode = ConfMan.get("record_mode"); Common::String recordFileName = ConfMan.get("record_file_name"); if (recordMode == "record") { g_eventRec.init(g_eventRec.generateRecordFileName(ConfMan.getActiveDomainName()), GUI::EventRecorder::kRecorderRecord); } else if (recordMode == "playback") { g_eventRec.init(recordFileName, GUI::EventRecorder::kRecorderPlayback); } else if ((recordMode == "info") && (!recordFileName.empty())) { Common::PlaybackFile record; record.openRead(recordFileName); debug("info:author=%s name=%s description=%s", record.getHeader().author.c_str(), record.getHeader().name.c_str(), record.getHeader().description.c_str()); break; } #endif // Try to run the game Common::Error result = runGame(plugin, system, specialDebug); #ifdef ENABLE_EVENTRECORDER // Flush Event recorder file. The recorder does not get reinitialized for next game // which is intentional. Only single game per session is allowed. g_eventRec.deinit(); #endif #if defined(UNCACHED_PLUGINS) && defined(DYNAMIC_MODULES) // do our best to prevent fragmentation by unloading as soon as we can PluginManager::instance().unloadPluginsExcept(PLUGIN_TYPE_ENGINE, NULL, false); // reallocate the config manager to get rid of any fragmentation ConfMan.defragment(); #endif // Did an error occur ? if (result.getCode() != Common::kNoError && result.getCode() != Common::kUserCanceled) { // Shows an informative error dialog if starting the selected game failed. GUI::displayErrorDialog(result, _("Error running game:")); } // Quit unless an error occurred, or Return to launcher was requested #ifndef FORCE_RTL if (result.getCode() == Common::kNoError && !g_system->getEventManager()->shouldRTL()) break; #endif // Reset RTL flag in case we want to load another engine g_system->getEventManager()->resetRTL(); #ifdef FORCE_RTL g_system->getEventManager()->resetQuit(); #endif #ifdef ENABLE_EVENTRECORDER if (g_eventRec.checkForContinueGame()) { continue; } #endif // At this point, we usually return to the launcher. However, the // game may have requested that one or more other games be "chained" // to the current one, with optional save slots to start the games // at. At the time of writing, this is used for the Maniac Mansion // easter egg in Day of the Tentacle. Common::String chainedGame; int saveSlot = -1; ChainedGamesMan.pop(chainedGame, saveSlot); // Discard any command line options. It's unlikely that the user // wanted to apply them to *all* games ever launched. ConfMan.getDomain(Common::ConfigManager::kTransientDomain)->clear(); if (!chainedGame.empty()) { if (saveSlot != -1) { ConfMan.setInt("save_slot", saveSlot, Common::ConfigManager::kTransientDomain); } // Start the chained game ConfMan.setActiveDomain(chainedGame); } else { // Clear the active config domain ConfMan.setActiveDomain(""); } PluginManager::instance().loadAllPlugins(); // only for cached manager } else { GUI::displayErrorDialog(_("Could not find any engine capable of running the selected game")); // Clear the active domain ConfMan.setActiveDomain(""); } // reset the graphics to default setupGraphics(system); if (0 == ConfMan.getActiveDomain()) { launcherDialog(); } } #ifdef USE_CLOUD #ifdef USE_SDL_NET Networking::LocalWebserver::destroy(); #endif #ifdef USE_LIBCURL Networking::ConnectionManager::destroy(); //I think it's important to destroy it after ConnectionManager Cloud::CloudManager::destroy(); #endif #endif PluginManager::instance().unloadAllPlugins(); PluginManager::destroy(); GUI::GuiManager::destroy(); Common::ConfigManager::destroy(); Common::DebugManager::destroy(); Common::OSDMessageQueue::destroy(); #ifdef ENABLE_EVENTRECORDER GUI::EventRecorder::destroy(); #endif Common::SearchManager::destroy(); #ifdef USE_TRANSLATION Common::TranslationManager::destroy(); #endif MusicManager::destroy(); Graphics::CursorManager::destroy(); Graphics::FontManager::destroy(); #ifdef USE_FREETYPE2 Graphics::shutdownTTF(); #endif EngineManager::destroy(); Graphics::YUVToRGBManager::destroy(); return 0; }