X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fsupertux%2Fmain.cpp;h=1cfba9c4cb753680fbf1a9134ed892e7744b16da;hb=b9f40748d04747d81cf79812a900e380d8f45c72;hp=98a6cc3d6171b2c40cf239e6fb943f9b2c0b9557;hpb=bb83166e903f0bfc44b8fab7026cb36c3884022d;p=supertux.git diff --git a/src/supertux/main.cpp b/src/supertux/main.cpp index 98a6cc3d6..1cfba9c4c 100644 --- a/src/supertux/main.cpp +++ b/src/supertux/main.cpp @@ -14,518 +14,270 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +#include "supertux/main.hpp" + #include #include #include -#include +#include +#include #include -#include +#include +#include #include - -#include "supertux/main.hpp" - -#ifdef MACOSX -namespace supertux_apple { -# include -} // namespace supertux_apple -#endif +extern "C" { +#include +} #include "addon/addon_manager.hpp" #include "audio/sound_manager.hpp" -#include "control/joystickkeyboardcontroller.hpp" +#include "control/input_manager.hpp" #include "math/random_generator.hpp" #include "physfs/ifile_stream.hpp" -#include "physfs/physfs_sdl.hpp" #include "physfs/physfs_file_system.hpp" +#include "physfs/physfs_sdl.hpp" #include "scripting/squirrel_util.hpp" +#include "scripting/scripting.hpp" +#include "sprite/sprite_manager.hpp" +#include "supertux/command_line_arguments.hpp" +#include "supertux/game_manager.hpp" #include "supertux/gameconfig.hpp" #include "supertux/globals.hpp" #include "supertux/player_status.hpp" -#include "supertux/screen_manager.hpp" #include "supertux/resources.hpp" +#include "supertux/screen_fade.hpp" +#include "supertux/screen_manager.hpp" #include "supertux/title_screen.hpp" #include "util/file_system.hpp" #include "util/gettext.hpp" #include "video/drawing_context.hpp" +#include "video/lightmap.hpp" +#include "video/renderer.hpp" #include "worldmap/worldmap.hpp" -namespace { DrawingContext *context_pointer; } - -void -Main::init_config() +class ConfigSubsystem { - g_config = new Config(); - try { - g_config->load(); - } catch(std::exception& e) { - log_info << "Couldn't load config file: " << e.what() << ", using default settings" << std::endl; +public: + ConfigSubsystem() + { + g_config.reset(new Config); + try { + g_config->load(); + } + catch(const std::exception& e) + { + log_info << "Couldn't load config file: " << e.what() << ", using default settings" << std::endl; + } + + // init random number stuff + g_config->random_seed = gameRandom.srand(g_config->random_seed); + graphicsRandom.srand(0); + //const char *how = config->random_seed? ", user fixed.": ", from time()."; + //log_info << "Using random seed " << config->random_seed << how << std::endl; } -} + + ~ConfigSubsystem() + { + if (g_config) + { + g_config->save(); + } + g_config.reset(); + } +}; void Main::init_tinygettext() { - dictionary_manager = new tinygettext::DictionaryManager(); + g_dictionary_manager.reset(new tinygettext::DictionaryManager); tinygettext::Log::set_log_info_callback(0); - dictionary_manager->set_filesystem(std::auto_ptr(new PhysFSFileSystem)); + g_dictionary_manager->set_filesystem(std::unique_ptr(new PhysFSFileSystem)); - dictionary_manager->add_directory("locale"); - dictionary_manager->set_charset("UTF-8"); + g_dictionary_manager->add_directory("locale"); + g_dictionary_manager->set_charset("UTF-8"); // Config setting "locale" overrides language detection - if (g_config->locale != "") + if (g_config->locale != "") + { + g_dictionary_manager->set_language(tinygettext::Language::from_name(g_config->locale)); + } + else { - dictionary_manager->set_language(tinygettext::Language::from_name(g_config->locale)); + FL_Locale *locale; + FL_FindLocale(&locale); + tinygettext::Language language = tinygettext::Language::from_spec( locale->lang?locale->lang:"", locale->country?locale->country:"", locale->variant?locale->variant:""); + FL_FreeLocale(&locale); + g_dictionary_manager->set_language(language); } } -void -Main::init_physfs(const char* argv0) +class PhysfsSubsystem { - if(!PHYSFS_init(argv0)) { - std::stringstream msg; - msg << "Couldn't initialize physfs: " << PHYSFS_getLastError(); - throw std::runtime_error(msg.str()); - } - - // allow symbolic links - PHYSFS_permitSymbolicLinks(1); - - // Initialize physfs (this is a slightly modified version of - // PHYSFS_setSaneConfig) - const char* application = PACKAGE_NAME; - const char* userdir = PHYSFS_getUserDir(); - - char* writedir = new char[strlen(userdir) + strlen(application) + -#ifndef _WIN32 - 2]; -#else - 1]; -#endif - - // Set configuration directory - sprintf(writedir, -#ifndef _WIN32 - "%s.%s", -#else - "%s%s", -#endif - userdir, application); - if(!PHYSFS_setWriteDir(writedir)) { - // try to create the directory - char* mkdir = new char[strlen(application) + -#ifndef _WIN32 - 2]; -#else - 1]; -#endif - sprintf(mkdir, -#ifndef _WIN32 - ".%s", -#else - "%s", -#endif - application); - if(!PHYSFS_setWriteDir(userdir) || !PHYSFS_mkdir(mkdir)) { - std::ostringstream msg; - msg << "Failed creating configuration directory '" - << writedir << "': " << PHYSFS_getLastError(); - delete[] writedir; - delete[] mkdir; +private: + boost::optional m_forced_datadir; + boost::optional m_forced_userdir; + +public: + PhysfsSubsystem(const char* argv0, + boost::optional forced_datadir, + boost::optional forced_userdir) : + m_forced_datadir(forced_datadir), + m_forced_userdir(forced_userdir) + { + if (!PHYSFS_init(argv0)) + { + std::stringstream msg; + msg << "Couldn't initialize physfs: " << PHYSFS_getLastError(); throw std::runtime_error(msg.str()); } - delete[] mkdir; + else + { + // allow symbolic links + PHYSFS_permitSymbolicLinks(1); - if(!PHYSFS_setWriteDir(writedir)) { - std::ostringstream msg; - msg << "Failed to use configuration directory '" - << writedir << "': " << PHYSFS_getLastError(); - delete[] writedir; - throw std::runtime_error(msg.str()); - } - } - PHYSFS_addToSearchPath(writedir, 0); - delete[] writedir; - - // when started from source dir... - std::string dir = PHYSFS_getBaseDir(); - dir += "/data"; - std::string testfname = dir; - testfname += "/credits.txt"; - bool sourcedir = false; - FILE* f = fopen(testfname.c_str(), "r"); - if(f) { - fclose(f); - if(!PHYSFS_addToSearchPath(dir.c_str(), 1)) { - log_warning << "Couldn't add '" << dir << "' to physfs searchpath: " << PHYSFS_getLastError() << std::endl; - } else { - sourcedir = true; + find_userdir(); + find_datadir(); } } -#ifdef MACOSX + void find_datadir() { - using namespace supertux_apple; - - // when started from Application file on Mac OS X... - char path[PATH_MAX]; - CFBundleRef mainBundle = CFBundleGetMainBundle(); - assert(mainBundle != 0); - CFURLRef mainBundleURL = CFBundleCopyBundleURL(mainBundle); - assert(mainBundleURL != 0); - CFStringRef pathStr = CFURLCopyFileSystemPath(mainBundleURL, kCFURLPOSIXPathStyle); - assert(pathStr != 0); - CFStringGetCString(pathStr, path, PATH_MAX, kCFStringEncodingUTF8); - CFRelease(mainBundleURL); - CFRelease(pathStr); - - dir = std::string(path) + "/Contents/Resources/data"; - testfname = dir + "/credits.txt"; - sourcedir = false; - f = fopen(testfname.c_str(), "r"); - if(f) { - fclose(f); - if(!PHYSFS_addToSearchPath(dir.c_str(), 1)) { - log_warning << "Couldn't add '" << dir << "' to physfs searchpath: " << PHYSFS_getLastError() << std::endl; - } else { - sourcedir = true; + std::string datadir; + if (m_forced_datadir) + { + datadir = *m_forced_datadir; + } + else if (const char* env_datadir = getenv("SUPERTUX2_DATA_DIR")) + { + datadir = env_datadir; + } + else + { + // check if we run from source dir + char* basepath_c = SDL_GetBasePath(); + std::string basepath = basepath_c; + SDL_free(basepath_c); + + datadir = FileSystem::join(basepath, "data"); + std::string testfname = FileSystem::join(datadir, "credits.txt"); + if (!FileSystem::exists(testfname)) + { + // if the game is not run from the source directory, try to find + // the global install location + datadir = datadir.substr(0, datadir.rfind(INSTALL_SUBDIR_BIN)); + datadir = FileSystem::join(datadir, INSTALL_SUBDIR_SHARE); } } + + if (!PHYSFS_addToSearchPath(datadir.c_str(), 1)) + { + log_warning << "Couldn't add '" << datadir << "' to physfs searchpath: " << PHYSFS_getLastError() << std::endl; + } } -#endif + void find_userdir() + { + std::string userdir; + if (m_forced_userdir) + { + userdir = *m_forced_userdir; + } + else if (const char* env_userdir = getenv("SUPERTUX2_USER_DIR")) + { + userdir = env_userdir; + } + else + { + std::string physfs_userdir = PHYSFS_getUserDir(); #ifdef _WIN32 - PHYSFS_addToSearchPath(".\\data", 1); -#endif - - if(!sourcedir) { - std::string datadir = PHYSFS_getBaseDir(); - datadir = datadir.substr(0, datadir.rfind(INSTALL_SUBDIR_BIN)); - datadir += "/" INSTALL_SUBDIR_SHARE; -#ifdef ENABLE_BINRELOC - - char* dir; - br_init (NULL); - dir = br_find_data_dir(datadir.c_str()); - datadir = dir; - free(dir); - + userdir = FileSystem::join(physfs_userdir, PACKAGE_NAME); +#else + userdir = FileSystem::join(physfs_userdir, "." PACKAGE_NAME); #endif - if(!PHYSFS_addToSearchPath(datadir.c_str(), 1)) { - log_warning << "Couldn't add '" << datadir << "' to physfs searchpath: " << PHYSFS_getLastError() << std::endl; } - } - //show search Path - char** searchpath = PHYSFS_getSearchPath(); - for(char** i = searchpath; *i != NULL; i++) - log_info << "[" << *i << "] is in the search path" << std::endl; - PHYSFS_freeList(searchpath); -} + if (!FileSystem::is_directory(userdir)) + { + FileSystem::mkdir(userdir); + log_info << "Created SuperTux userdir: " << userdir << std::endl; + } -void -Main::print_usage(const char* argv0) -{ - std::cerr << _("Usage: ") << argv0 << _(" [OPTIONS] [LEVELFILE]\n\n") - << _("Options:\n" - " -f, --fullscreen Run in fullscreen mode\n" - " -w, --window Run in window mode\n" - " -g, --geometry WIDTHxHEIGHT Run SuperTux in given resolution\n" - " -a, --aspect WIDTH:HEIGHT Run SuperTux with given aspect ratio\n" - " -d, --default Reset video settings to default values\n" - " --renderer RENDERER Use sdl, opengl, or auto to render\n" - " --disable-sfx Disable sound effects\n" - " --disable-music Disable music\n" - " -h, --help Show this help message and quit\n" - " -v, --version Show SuperTux version and quit\n" - " --console Enable ingame scripting console\n" - " --noconsole Disable ingame scripting console\n" - " --show-fps Display framerate in levels\n" - " --no-show-fps Do not display framerate in levels\n" - " --record-demo FILE LEVEL Record a demo to FILE\n" - " --play-demo FILE LEVEL Play a recorded demo\n" - " -s, --debug-scripts Enable script debugger.\n" - "\n") - << std::flush; -} + if (!PHYSFS_setWriteDir(userdir.c_str())) + { + std::ostringstream msg; + msg << "Failed to use userdir directory '" + << userdir << "': " << PHYSFS_getLastError(); + throw std::runtime_error(msg.str()); + } -/** - * Options that should be evaluated prior to any initializations at all go here - */ -bool -Main::pre_parse_commandline(int argc, char** argv) -{ - for(int i = 1; i < argc; ++i) { - std::string arg = argv[i]; + PHYSFS_addToSearchPath(userdir.c_str(), 0); + } - if(arg == "--version" || arg == "-v") { - std::cout << PACKAGE_NAME << " " << PACKAGE_VERSION << std::endl; - return true; - } - if(arg == "--help" || arg == "-h") { - print_usage(argv[0]); - return true; + void print_search_path() + { + const char* writedir = PHYSFS_getWriteDir(); + log_info << "PhysfsWritedDir: " << (writedir ? writedir : "(null)") << std::endl; + log_info << "PhysfsSearchPath:" << std::endl; + char** searchpath = PHYSFS_getSearchPath(); + for(char** i = searchpath; *i != NULL; ++i) + { + log_info << " " << *i << std::endl; } + PHYSFS_freeList(searchpath); } - return false; -} + ~PhysfsSubsystem() + { + PHYSFS_deinit(); + } +}; -/** - * Options that should be evaluated after config is read go here - */ -bool -Main::parse_commandline(int argc, char** argv) +class SDLSubsystem { - for(int i = 1; i < argc; ++i) { - std::string arg = argv[i]; - - if(arg == "--fullscreen" || arg == "-f") { - g_config->use_fullscreen = true; - } else if(arg == "--default" || arg == "-d") { - g_config->use_fullscreen = false; - - g_config->window_size = Size(800, 600); - g_config->fullscreen_size = Size(800, 600); - g_config->aspect_size = Size(0, 0); // auto detect - - } else if(arg == "--window" || arg == "-w") { - g_config->use_fullscreen = false; - } else if(arg == "--geometry" || arg == "-g") { - i += 1; - if(i >= argc) - { - print_usage(argv[0]); - throw std::runtime_error("Need to specify a size (WIDTHxHEIGHT) for geometry argument"); - } - else - { - int width, height; - if (sscanf(argv[i], "%dx%d", &width, &height) != 2) - { - print_usage(argv[0]); - throw std::runtime_error("Invalid geometry spec, should be WIDTHxHEIGHT"); - } - else - { - g_config->window_size = Size(width, height); - g_config->fullscreen_size = Size(width, height); - } - } - } else if(arg == "--aspect" || arg == "-a") { - i += 1; - if(i >= argc) - { - print_usage(argv[0]); - throw std::runtime_error("Need to specify a ratio (WIDTH:HEIGHT) for aspect ratio"); - } - else - { - int aspect_width = 0; - int aspect_height = 0; - if (strcmp(argv[i], "auto") == 0) - { - aspect_width = 0; - aspect_height = 0; - } - else if (sscanf(argv[i], "%d:%d", &aspect_width, &aspect_height) != 2) - { - print_usage(argv[0]); - throw std::runtime_error("Invalid aspect spec, should be WIDTH:HEIGHT or auto"); - } - else - { - float aspect_ratio = static_cast(aspect_width) / static_cast(aspect_height); - - // use aspect ratio to calculate logical resolution - if (aspect_ratio > 1) { - g_config->aspect_size = Size(static_cast(600 * aspect_ratio + 0.5), - 600); - } else { - g_config->aspect_size = Size(600, - static_cast(600 * 1/aspect_ratio + 0.5)); - } - } - } - } else if(arg == "--renderer") { - i += 1; - if(i >= argc) - { - print_usage(argv[0]); - throw std::runtime_error("Need to specify a renderer for renderer argument"); - } - else - { - g_config->video = VideoSystem::get_video_system(argv[i]); - } - } else if(arg == "--show-fps") { - g_config->show_fps = true; - } else if(arg == "--no-show-fps") { - g_config->show_fps = false; - } else if(arg == "--console") { - g_config->console_enabled = true; - } else if(arg == "--noconsole") { - g_config->console_enabled = false; - } else if(arg == "--disable-sfx") { - g_config->sound_enabled = false; - } else if(arg == "--disable-music") { - g_config->music_enabled = false; - } else if(arg == "--play-demo") { - if(i+1 >= argc) { - print_usage(argv[0]); - throw std::runtime_error("Need to specify a demo filename"); - } - g_config->start_demo = argv[++i]; - } else if(arg == "--record-demo") { - if(i+1 >= argc) { - print_usage(argv[0]); - throw std::runtime_error("Need to specify a demo filename"); - } - g_config->record_demo = argv[++i]; - } else if(arg == "--debug-scripts" || arg == "-s") { - g_config->enable_script_debugger = true; - } else if(arg[0] != '-') { - g_config->start_level = arg; - } else { - log_warning << "Unknown option '" << arg << "'. Use --help to see a list of options" << std::endl; - return true; +public: + SDLSubsystem() + { + if(SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER) < 0) + { + std::stringstream msg; + msg << "Couldn't initialize SDL: " << SDL_GetError(); + throw std::runtime_error(msg.str()); } + // just to be sure + atexit(SDL_Quit); } - return false; -} - -void -Main::init_sdl() -{ - if(SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) { - std::stringstream msg; - msg << "Couldn't initialize SDL: " << SDL_GetError(); - throw std::runtime_error(msg.str()); + ~SDLSubsystem() + { + SDL_Quit(); } - // just to be sure - atexit(SDL_Quit); - - SDL_EnableUNICODE(1); - - // wait 100ms and clear SDL event queue because sometimes we have random - // joystick events in the queue on startup... - SDL_Delay(100); - SDL_Event dummy; - while(SDL_PollEvent(&dummy)) - ; -} - -void -Main::init_rand() -{ - g_config->random_seed = systemRandom.srand(g_config->random_seed); - - //const char *how = config->random_seed? ", user fixed.": ", from time()."; - //log_info << "Using random seed " << config->random_seed << how << std::endl; -} +}; void Main::init_video() { - // FIXME: Add something here - SCREEN_WIDTH = 800; - SCREEN_HEIGHT = 600; + SDL_SetWindowTitle(VideoSystem::current()->get_renderer().get_window(), PACKAGE_NAME " " PACKAGE_VERSION); - context_pointer->init_renderer(); - g_screen = SDL_GetVideoSurface(); - - SDL_WM_SetCaption(PACKAGE_NAME " " PACKAGE_VERSION, 0); - - // set icon -#ifdef MACOSX const char* icon_fname = "images/engine/icons/supertux-256x256.png"; -#else - const char* icon_fname = "images/engine/icons/supertux.xpm"; -#endif - SDL_Surface* icon; - try { - icon = IMG_Load_RW(get_physfs_SDLRWops(icon_fname), true); - } catch (const std::runtime_error& err) { - icon = 0; - log_warning << "Couldn't load icon '" << icon_fname << "': " << err.what() << std::endl; + SDL_Surface* icon = IMG_Load_RW(get_physfs_SDLRWops(icon_fname), true); + if (!icon) + { + log_warning << "Couldn't load icon '" << icon_fname << "': " << SDL_GetError() << std::endl; } - if(icon != 0) { - SDL_WM_SetIcon(icon, 0); + else + { + SDL_SetWindowIcon(VideoSystem::current()->get_renderer().get_window(), icon); SDL_FreeSurface(icon); } - else { - log_warning << "Couldn't load icon '" << icon_fname << "'" << std::endl; - } - SDL_ShowCursor(0); log_info << (g_config->use_fullscreen?"fullscreen ":"window ") << " Window: " << g_config->window_size - << " Fullscreen: " << g_config->fullscreen_size + << " Fullscreen: " << g_config->fullscreen_size << "@" << g_config->fullscreen_refresh_rate << " Area: " << g_config->aspect_size << std::endl; } -void -Main::init_audio() -{ - sound_manager = new SoundManager(); - - sound_manager->enable_sound(g_config->sound_enabled); - sound_manager->enable_music(g_config->music_enabled); -} - -void -Main::quit_audio() -{ - if(sound_manager != NULL) { - delete sound_manager; - sound_manager = NULL; - } -} - -void -Main::wait_for_event(float min_delay, float max_delay) -{ - assert(min_delay <= max_delay); - - Uint32 min = (Uint32) (min_delay * 1000); - Uint32 max = (Uint32) (max_delay * 1000); - - Uint32 ticks = SDL_GetTicks(); - while(SDL_GetTicks() - ticks < min) { - SDL_Delay(10); - sound_manager->update(); - } - - // clear event queue - SDL_Event event; - while (SDL_PollEvent(&event)) - {} - - /* Handle events: */ - bool running = false; - ticks = SDL_GetTicks(); - while(running) { - while(SDL_PollEvent(&event)) { - switch(event.type) { - case SDL_QUIT: - g_screen_manager->quit(); - break; - case SDL_KEYDOWN: - case SDL_JOYBUTTONDOWN: - case SDL_MOUSEBUTTONDOWN: - running = false; - } - } - if(SDL_GetTicks() - ticks >= (max - min)) - running = false; - sound_manager->update(); - SDL_Delay(10); - } -} - static Uint32 last_timelog_ticks = 0; static const char* last_timelog_component = 0; @@ -541,117 +293,148 @@ static inline void timelog(const char* component) last_timelog_component = component; } -int -Main::run(int argc, char** argv) +void +Main::launch_game() { - int result = 0; + SDLSubsystem sdl_subsystem; + ConsoleBuffer console_buffer; - try { + timelog("controller"); + InputManager input_manager(g_config->keyboard_config, g_config->joystick_config); - if(pre_parse_commandline(argc, argv)) - return 0; + timelog("commandline"); - Console::instance = new Console(); - init_physfs(argv[0]); - init_sdl(); + timelog("video"); + std::unique_ptr video_system = VideoSystem::create(g_config->video); + DrawingContext context(*video_system); + init_video(); - timelog("controller"); - g_main_controller = new JoystickKeyboardController(); + timelog("audio"); + SoundManager sound_manager; + sound_manager.enable_sound(g_config->sound_enabled); + sound_manager.enable_music(g_config->music_enabled); - timelog("config"); - init_config(); + Console console(console_buffer); - timelog("addons"); - AddonManager::get_instance().load_addons(); + timelog("scripting"); + scripting::Scripting scripting(g_config->enable_script_debugger); - timelog("tinygettext"); - init_tinygettext(); + timelog("resources"); + TileManager tile_manager; + SpriteManager sprite_manager; + Resources resources; - timelog("commandline"); - if(parse_commandline(argc, argv)) - return 0; + timelog("addons"); + AddonManager addon_manager("addons", g_config->addons); - timelog("audio"); - init_audio(); + timelog(0); - timelog("video"); - DrawingContext context; - context_pointer = &context; - init_video(); + const std::unique_ptr default_savegame(new Savegame(std::string())); - Console::instance->init_graphics(); + GameManager game_manager; + ScreenManager screen_manager; - timelog("scripting"); - scripting::init_squirrel(g_config->enable_script_debugger); + if(g_config->start_level != "") { + // we have a normal path specified at commandline, not a physfs path. + // So we simply mount that path here... + std::string dir = FileSystem::dirname(g_config->start_level); + std::string fileProtocol = "file://"; + std::string::size_type position = dir.find(fileProtocol); + if(position != std::string::npos) { + dir = dir.replace(position, fileProtocol.length(), ""); + } + log_debug << "Adding dir: " << dir << std::endl; + PHYSFS_addToSearchPath(dir.c_str(), true); + + if(g_config->start_level.size() > 4 && + g_config->start_level.compare(g_config->start_level.size() - 5, 5, ".stwm") == 0) + { + screen_manager.push_screen(std::unique_ptr( + new worldmap::WorldMap( + FileSystem::basename(g_config->start_level), *default_savegame))); + } else { + std::unique_ptr session ( + new GameSession(FileSystem::basename(g_config->start_level), *default_savegame)); - timelog("resources"); - Resources::load_shared(); + g_config->random_seed = session->get_demo_random_seed(g_config->start_demo); + g_config->random_seed = gameRandom.srand(g_config->random_seed); + graphicsRandom.srand(0); - timelog(0); + if(g_config->start_demo != "") + session->play_demo(g_config->start_demo); - const std::auto_ptr default_playerstatus(new PlayerStatus()); + if(g_config->record_demo != "") + session->record_demo(g_config->record_demo); + screen_manager.push_screen(std::move(session)); + } + } else { + screen_manager.push_screen(std::unique_ptr(new TitleScreen(*default_savegame))); + } - g_screen_manager = new ScreenManager(); + screen_manager.run(context); +} - init_rand(); +int +Main::run(int argc, char** argv) +{ + int result = 0; - if(g_config->start_level != "") { - // we have a normal path specified at commandline, not a physfs path. - // So we simply mount that path here... - std::string dir = FileSystem::dirname(g_config->start_level); - log_debug << "Adding dir: " << dir << std::endl; - PHYSFS_addToSearchPath(dir.c_str(), true); + try + { + CommandLineArguments args; - if(g_config->start_level.size() > 4 && - g_config->start_level.compare(g_config->start_level.size() - 5, 5, ".stwm") == 0) { - g_screen_manager->push_screen(new worldmap::WorldMap( - FileSystem::basename(g_config->start_level), default_playerstatus.get())); - } else { - std::auto_ptr session ( - new GameSession(FileSystem::basename(g_config->start_level), default_playerstatus.get())); + try + { + args.parse_args(argc, argv); + g_log_level = args.get_log_level(); + } + catch(const std::exception& err) + { + std::cout << "Error: " << err.what() << std::endl; + return EXIT_FAILURE; + } - g_config->random_seed =session->get_demo_random_seed(g_config->start_demo); - init_rand();//initialise generator with seed from session + PhysfsSubsystem physfs_subsystem(argv[0], args.datadir, args.userdir); + physfs_subsystem.print_search_path(); - if(g_config->start_demo != "") - session->play_demo(g_config->start_demo); + timelog("config"); + ConfigSubsystem config_subsystem; + args.merge_into(*g_config); - if(g_config->record_demo != "") - session->record_demo(g_config->record_demo); - g_screen_manager->push_screen(session.release()); - } - } else { - g_screen_manager->push_screen(new TitleScreen(default_playerstatus.get())); - } + timelog("tinygettext"); + init_tinygettext(); + + switch (args.get_action()) + { + case CommandLineArguments::PRINT_VERSION: + args.print_version(); + return 0; + + case CommandLineArguments::PRINT_HELP: + args.print_help(argv[0]); + return 0; + + case CommandLineArguments::PRINT_DATADIR: + args.print_datadir(); + return 0; - g_screen_manager->run(context); - } catch(std::exception& e) { + default: + launch_game(); + break; + } + } + catch(const std::exception& e) + { log_fatal << "Unexpected exception: " << e.what() << std::endl; result = 1; - } catch(...) { + } + catch(...) + { log_fatal << "Unexpected exception" << std::endl; result = 1; } - delete g_screen_manager; - g_screen_manager = NULL; - - Resources::unload_shared(); - quit_audio(); - - if(g_config) - g_config->save(); - delete g_config; - g_config = NULL; - delete g_main_controller; - g_main_controller = NULL; - delete Console::instance; - Console::instance = NULL; - scripting::exit_squirrel(); - delete texture_manager; - texture_manager = NULL; - SDL_Quit(); - PHYSFS_deinit(); + g_dictionary_manager.reset(); return result; }