X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fsupertux%2Fmain.cpp;h=c853809f841aa64f590f27048520b5d98753013f;hb=3497f1b5834627a6e1aec925410d7dfed470582c;hp=41e22ef7b5c77ab89e4cf024fadcfadaa4e35ffd;hpb=aaba092373d753e421f2a23e26ecf5c22cf06d9d;p=supertux.git diff --git a/src/supertux/main.cpp b/src/supertux/main.cpp index 41e22ef7b..c853809f8 100644 --- a/src/supertux/main.cpp +++ b/src/supertux/main.cpp @@ -14,8 +14,6 @@ // 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 @@ -23,6 +21,13 @@ #include #include #include +#include +#include +extern "C" { +#include +} + +#include "supertux/main.hpp" #ifdef MACOSX namespace supertux_apple { @@ -30,8 +35,6 @@ namespace supertux_apple { } // namespace supertux_apple #endif -#include "tinygettext/log.hpp" - #include "addon/addon_manager.hpp" #include "audio/sound_manager.hpp" #include "control/joystickkeyboardcontroller.hpp" @@ -42,6 +45,7 @@ namespace supertux_apple { #include "scripting/squirrel_util.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/title_screen.hpp" @@ -52,6 +56,12 @@ namespace supertux_apple { namespace { DrawingContext *context_pointer; } +#ifdef _WIN32 +# define WRITEDIR_NAME PACKAGE_NAME +#else +# define WRITEDIR_NAME "." PACKAGE_NAME +#endif + void Main::init_config() { @@ -77,10 +87,16 @@ Main::init_tinygettext() if (g_config->locale != "") { dictionary_manager->set_language(tinygettext::Language::from_name(g_config->locale)); + } else { + 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); + dictionary_manager->set_language(language); } } - void +void Main::init_physfs(const char* argv0) { if(!PHYSFS_init(argv0)) { @@ -93,41 +109,48 @@ Main::init_physfs(const char* argv0) PHYSFS_permitSymbolicLinks(1); // Initialize physfs (this is a slightly modified version of - // PHYSFS_setSaneConfig - const char* application = "supertux2"; //instead of PACKAGE_NAME so we can coexist with MS1 - const char* userdir = PHYSFS_getUserDir(); - char* writedir = new char[strlen(userdir) + strlen(application) + 2]; - - // Set configuration directory - sprintf(writedir, "%s.%s", userdir, application); - if(!PHYSFS_setWriteDir(writedir)) { - // try to create the directory - char* mkdir = new char[strlen(application) + 2]; - sprintf(mkdir, ".%s", application); - if(!PHYSFS_setWriteDir(userdir) || !PHYSFS_mkdir(mkdir)) { - std::ostringstream msg; - msg << "Failed creating configuration directory '" - << writedir << "': " << PHYSFS_getLastError(); - delete[] writedir; - delete[] mkdir; - throw std::runtime_error(msg.str()); - } - delete[] mkdir; + // PHYSFS_setSaneConfig) + const char *env_writedir; + std::string writedir; - if(!PHYSFS_setWriteDir(writedir)) { + if ((env_writedir = getenv("SUPERTUX2_USER_DIR")) != NULL) { + writedir = env_writedir; + if(!PHYSFS_setWriteDir(writedir.c_str())) { std::ostringstream msg; msg << "Failed to use configuration directory '" << writedir << "': " << PHYSFS_getLastError(); - delete[] writedir; throw std::runtime_error(msg.str()); } + + } else { + std::string userdir = PHYSFS_getUserDir(); + + // Set configuration directory + writedir = userdir + WRITEDIR_NAME; + if(!PHYSFS_setWriteDir(writedir.c_str())) { + // try to create the directory + if(!PHYSFS_setWriteDir(userdir.c_str()) || !PHYSFS_mkdir(WRITEDIR_NAME)) { + std::ostringstream msg; + msg << "Failed creating configuration directory '" + << writedir << "': " << PHYSFS_getLastError(); + throw std::runtime_error(msg.str()); + } + + if(!PHYSFS_setWriteDir(writedir.c_str())) { + std::ostringstream msg; + msg << "Failed to use configuration directory '" + << writedir << "': " << PHYSFS_getLastError(); + throw std::runtime_error(msg.str()); + } + } } - PHYSFS_addToSearchPath(writedir, 0); - delete[] writedir; + PHYSFS_addToSearchPath(writedir.c_str(), 0); // when started from source dir... std::string dir = PHYSFS_getBaseDir(); - dir += "/data"; + if (dir[dir.length() - 1] != '/') + dir += "/"; + dir += "data"; std::string testfname = dir; testfname += "/credits.txt"; bool sourcedir = false; @@ -148,11 +171,14 @@ Main::init_physfs(const char* argv0) // when started from Application file on Mac OS X... char path[PATH_MAX]; CFBundleRef mainBundle = CFBundleGetMainBundle(); - assert(mainBundle != 0); + if(mainBundle == 0) + throw "Assertion failed: mainBundle != 0"; CFURLRef mainBundleURL = CFBundleCopyBundleURL(mainBundle); - assert(mainBundleURL != 0); + if(mainBundleURL == 0) + throw "Assertion failed: mainBundleURL != 0"; CFStringRef pathStr = CFURLCopyFileSystemPath(mainBundleURL, kCFURLPOSIXPathStyle); - assert(pathStr != 0); + if(pathStr == 0) + throw "Assertion failed: pathStr != 0"; CFStringGetCString(pathStr, path, PATH_MAX, kCFStringEncodingUTF8); CFRelease(mainBundleURL); CFRelease(pathStr); @@ -177,23 +203,21 @@ Main::init_physfs(const char* argv0) #endif if(!sourcedir) { -#if defined(APPDATADIR) || defined(ENABLE_BINRELOC) - std::string datadir; + 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(APPDATADIR); + dir = br_find_data_dir(datadir.c_str()); datadir = dir; free(dir); -#else - datadir = APPDATADIR; #endif if(!PHYSFS_addToSearchPath(datadir.c_str(), 1)) { log_warning << "Couldn't add '" << datadir << "' to physfs searchpath: " << PHYSFS_getLastError() << std::endl; } -#endif } //show search Path @@ -206,8 +230,13 @@ Main::init_physfs(const char* argv0) void Main::print_usage(const char* argv0) { - std::cerr << _("Usage: ") << argv0 << _(" [OPTIONS] [LEVELFILE]\n\n") - << _("Options:\n" + std::string default_user_data_dir = + std::string(PHYSFS_getUserDir()) + WRITEDIR_NAME; + + std::cerr << boost::format(_( + "\n" + "Usage: %s [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" @@ -225,7 +254,14 @@ Main::print_usage(const char* argv0) " --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") + " --print-datadir Print supertux's primary data directory.\n" + "\n" + "Environment variables:\n" + " SUPERTUX2_USER_DIR Directory for user data (savegames, etc.);\n" + " default %s\n" + "\n" + )) + % argv0 % default_user_data_dir << std::flush; } @@ -246,6 +282,20 @@ Main::pre_parse_commandline(int argc, char** argv) print_usage(argv[0]); return true; } + if(arg == "--print-datadir") { + /* + * Print the datadir searchpath to stdout, one path per + * line. Then exit. Intended for use by the supertux-editor. + */ + char **sp; + size_t sp_index; + sp = PHYSFS_getSearchPath(); + if (sp) + for (sp_index = 0; sp[sp_index]; sp_index++) + std::cout << sp[sp_index] << std::endl; + PHYSFS_freeList(sp); + return true; + } } return false; @@ -265,14 +315,9 @@ Main::parse_commandline(int argc, char** argv) } else if(arg == "--default" || arg == "-d") { g_config->use_fullscreen = false; - g_config->window_width = 800; - g_config->window_height = 600; - - g_config->fullscreen_width = 800; - g_config->fullscreen_height = 600; - - g_config->aspect_width = 0; // auto detect - g_config->aspect_height = 0; + 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; @@ -293,11 +338,8 @@ Main::parse_commandline(int argc, char** argv) } else { - g_config->window_width = width; - g_config->window_height = height; - - g_config->fullscreen_width = width; - g_config->fullscreen_height = height; + g_config->window_size = Size(width, height); + g_config->fullscreen_size = Size(width, height); } } } else if(arg == "--aspect" || arg == "-a") { @@ -323,16 +365,15 @@ Main::parse_commandline(int argc, char** argv) } else { - float aspect_ratio = static_cast(g_config->aspect_width) / - static_cast(g_config->aspect_height); + 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_width = static_cast (600 * aspect_ratio + 0.5); - g_config->aspect_height = 600; + g_config->aspect_size = Size(static_cast(600 * aspect_ratio + 0.5), + 600); } else { - g_config->aspect_width = 600; - g_config->aspect_height = static_cast (600 * 1/aspect_ratio + 0.5); + g_config->aspect_size = Size(600, + static_cast(600 * 1/aspect_ratio + 0.5)); } } } @@ -345,7 +386,7 @@ Main::parse_commandline(int argc, char** argv) } else { - g_config->video = get_video_system(argv[i]); + g_config->video = VideoSystem::get_video_system(argv[i]); } } else if(arg == "--show-fps") { g_config->show_fps = true; @@ -408,7 +449,9 @@ Main::init_sdl() void Main::init_rand() { - g_config->random_seed = systemRandom.srand(g_config->random_seed); + 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; @@ -443,18 +486,16 @@ Main::init_video() SDL_WM_SetIcon(icon, 0); SDL_FreeSurface(icon); } -#ifndef NDEBUG else { log_warning << "Couldn't load icon '" << icon_fname << "'" << std::endl; } -#endif SDL_ShowCursor(0); log_info << (g_config->use_fullscreen?"fullscreen ":"window ") - << " Window: " << g_config->window_width << "x" << g_config->window_height - << " Fullscreen: " << g_config->fullscreen_width << "x" << g_config->fullscreen_height - << " Area: " << g_config->aspect_width << "x" << g_config->aspect_height << std::endl; + << " Window: " << g_config->window_size + << " Fullscreen: " << g_config->fullscreen_size + << " Area: " << g_config->aspect_size << std::endl; } void @@ -516,7 +557,6 @@ Main::wait_for_event(float min_delay, float max_delay) } } -#ifndef NDEBUG static Uint32 last_timelog_ticks = 0; static const char* last_timelog_component = 0; @@ -531,61 +571,63 @@ static inline void timelog(const char* component) last_timelog_ticks = current_ticks; last_timelog_component = component; } -#else -static inline void timelog(const char* ) -{ -} -#endif int -Main::main(int argc, char** argv) +Main::run(int argc, char** argv) { int result = 0; try { + /* Do this before pre_parse_commandline, because --help now shows the + * default user data dir. */ + init_physfs(argv[0]); if(pre_parse_commandline(argc, argv)) return 0; - Console::instance = new Console(); - init_physfs(argv[0]); init_sdl(); + Console::instance = new Console(); timelog("controller"); - g_main_controller = new JoystickKeyboardController(); + g_jk_controller = new JoystickKeyboardController(); timelog("config"); init_config(); - timelog("addons"); - AddonManager::get_instance().load_addons(); - - timelog("tinygettext"); - init_tinygettext(); - timelog("commandline"); if(parse_commandline(argc, argv)) return 0; - timelog("audio"); - init_audio(); - timelog("video"); DrawingContext context; context_pointer = &context; init_video(); + + timelog("audio"); + init_audio(); + + timelog("tinygettext"); + init_tinygettext(); Console::instance->init_graphics(); timelog("scripting"); - Scripting::init_squirrel(g_config->enable_script_debugger); + scripting::init_squirrel(g_config->enable_script_debugger); timelog("resources"); Resources::load_shared(); + + timelog("addons"); + AddonManager::get_instance().load_addons(); timelog(0); + const std::auto_ptr default_playerstatus(new PlayerStatus()); + g_screen_manager = new ScreenManager(); + + init_rand(); + if(g_config->start_level != "") { // we have a normal path specified at commandline, not a physfs path. // So we simply mount that path here... @@ -595,14 +637,11 @@ Main::main(int argc, char** argv) if(g_config->start_level.size() > 4 && g_config->start_level.compare(g_config->start_level.size() - 5, 5, ".stwm") == 0) { - init_rand(); - g_screen_manager->push_screen(new WorldMapNS::WorldMap( - FileSystem::basename(g_config->start_level))); + g_screen_manager->push_screen(new worldmap::WorldMap( + FileSystem::basename(g_config->start_level), default_playerstatus.get())); } else { - init_rand();//If level uses random eg. for - // rain particles before we do this: std::auto_ptr session ( - new GameSession(FileSystem::basename(g_config->start_level))); + new GameSession(FileSystem::basename(g_config->start_level), default_playerstatus.get())); g_config->random_seed =session->get_demo_random_seed(g_config->start_demo); init_rand();//initialise generator with seed from session @@ -615,11 +654,9 @@ Main::main(int argc, char** argv) g_screen_manager->push_screen(session.release()); } } else { - init_rand(); - g_screen_manager->push_screen(new TitleScreen()); + g_screen_manager->push_screen(new TitleScreen(default_playerstatus.get())); } - //init_rand(); PAK: this call might subsume the above 3, but I'm chicken! g_screen_manager->run(context); } catch(std::exception& e) { log_fatal << "Unexpected exception: " << e.what() << std::endl; @@ -639,11 +676,11 @@ Main::main(int argc, char** argv) g_config->save(); delete g_config; g_config = NULL; - delete g_main_controller; - g_main_controller = NULL; + delete g_jk_controller; + g_jk_controller = NULL; delete Console::instance; Console::instance = NULL; - Scripting::exit_squirrel(); + scripting::exit_squirrel(); delete texture_manager; texture_manager = NULL; SDL_Quit();