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 if ((res = Base::processSettings(command, settings)) != Common::kArgumentNotProcessed) return res; // 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 != 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 == 0 && !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; }
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 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 // Now as the event manager is created, setup the keymapper setupKeymapper(system); #ifdef USE_UPDATES if (!ConfMan.hasKey("updates_check")) { GUI::UpdatesDialog dlg; dlg.runModal(); } #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(); } } PluginManager::instance().unloadAllPlugins(); PluginManager::destroy(); GUI::GuiManager::destroy(); Common::ConfigManager::destroy(); Common::DebugManager::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; }