Addon include fixes.
[supertux.git] / src / main.cpp
index 5c27874..8a8dc7c 100644 (file)
@@ -18,7 +18,7 @@
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //  02111-1307, USA.
 #include <config.h>
-#include <cassert>
+#include <assert.h>
 
 #include "log.hpp"
 #include "main.hpp"
 #include <physfs.h>
 #include <SDL.h>
 #include <SDL_image.h>
-#include <GL/gl.h>
+
+#ifdef MACOSX
+namespace supertux_apple {
+#include <CoreFoundation/CoreFoundation.h>
+}
+#endif
 
 #include "gameconfig.hpp"
 #include "resources.hpp"
@@ -41,6 +46,7 @@
 #include "audio/sound_manager.hpp"
 #include "video/surface.hpp"
 #include "video/texture_manager.hpp"
+#include "video/drawing_context.hpp"
 #include "video/glutil.hpp"
 #include "control/joystickkeyboardcontroller.hpp"
 #include "options_menu.hpp"
 #include "physfs/physfs_sdl.hpp"
 #include "random_generator.hpp"
 #include "worldmap/worldmap.hpp"
+#include "addon/addon_manager.hpp"
 #include "binreloc/binreloc.h"
 
-SDL_Surface* screen = 0;
+namespace { DrawingContext *context_pointer; }
+SDL_Surface *screen;
 JoystickKeyboardController* main_controller = 0;
 TinyGetText::DictionaryManager dictionary_manager;
 
@@ -76,6 +84,11 @@ static void init_tinygettext()
 {
   dictionary_manager.add_directory("locale");
   dictionary_manager.set_charset("UTF-8");
+
+  // Config setting "locale" overrides language detection
+  if (config->locale != "") {
+    dictionary_manager.set_language( config->locale );
+  }
 }
 
 static void init_physfs(const char* argv0)
@@ -86,11 +99,13 @@ static void init_physfs(const char* argv0)
     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 = "supertux2"; //instead of PACKAGE_NAME so we can coexist with MS1
   const char* userdir = PHYSFS_getUserDir();
-  const char* dirsep = PHYSFS_getDirSeparator();
   char* writedir = new char[strlen(userdir) + strlen(application) + 2];
 
   // Set configuration directory
@@ -120,27 +135,6 @@ static void init_physfs(const char* argv0)
   PHYSFS_addToSearchPath(writedir, 0);
   delete[] writedir;
 
-  // Search for archives and add them to the search path
-  const char* archiveExt = "zip";
-  char** rc = PHYSFS_enumerateFiles("/");
-  size_t extlen = strlen(archiveExt);
-
-  for(char** i = rc; *i != 0; ++i) {
-    size_t l = strlen(*i);
-    if((l > extlen) && ((*i)[l - extlen - 1] == '.')) {
-      const char* ext = (*i) + (l - extlen);
-      if(strcasecmp(ext, archiveExt) == 0) {
-        const char* d = PHYSFS_getRealDir(*i);
-        char* str = new char[strlen(d) + strlen(dirsep) + l + 1];
-        sprintf(str, "%s%s%s", d, dirsep, *i);
-        PHYSFS_addToSearchPath(str, 1);
-        delete[] str;
-      }
-    }
-  }
-
-  PHYSFS_freeList(rc);
-
   // when started from source dir...
   std::string dir = PHYSFS_getBaseDir();
   dir += "/data";
@@ -158,9 +152,22 @@ static void init_physfs(const char* argv0)
   }
 
 #ifdef MACOSX
+{
+  using namespace supertux_apple;
+
   // when started from Application file on Mac OS X...
-  dir = PHYSFS_getBaseDir();
-  dir += "SuperTux.app/Contents/Resources/data";
+  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");
@@ -172,6 +179,7 @@ static void init_physfs(const char* argv0)
       sourcedir = true;
     }
   }
+}
 #endif
 
 #ifdef _WIN32
@@ -187,7 +195,6 @@ static void init_physfs(const char* argv0)
     br_init (NULL);
     dir = br_find_data_dir(APPDATADIR);
     datadir = dir;
-    datadir += "/" PACKAGE_NAME;
     free(dir);
 
 #else
@@ -199,9 +206,6 @@ static void init_physfs(const char* argv0)
 #endif
   }
 
-  // allow symbolic links
-  PHYSFS_permitSymbolicLinks(1);
-
   //show search Path
   char** searchpath = PHYSFS_getSearchPath();
   for(char** i = searchpath; *i != NULL; i++)
@@ -218,16 +222,18 @@ static void print_usage(const char* argv0)
             "  -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"
             "  --disable-sfx                Disable sound effects\n"
             "  --disable-music              Disable music\n"
-            "  --help                       Show this help message\n"
-            "  --version                    Display SuperTux version and quit\n"
+            "  -h, --help                   Show this help message\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"));
 }
 
@@ -239,10 +245,7 @@ static bool pre_parse_commandline(int argc, char** argv)
   for(int i = 1; i < argc; ++i) {
     std::string arg = argv[i];
 
-    if(arg == "--help") {
-      print_usage(argv[0]);
-      return true;
-    } else if(arg == "--version") {
+    if(arg == "--version" || arg == "-v") {
       std::cout << PACKAGE_NAME << " " << PACKAGE_VERSION << std::endl;
       return true;
     }
@@ -259,30 +262,85 @@ static bool parse_commandline(int argc, char** argv)
   for(int i = 1; i < argc; ++i) {
     std::string arg = argv[i];
 
-    if(arg == "--fullscreen" || arg == "-f") {
+    if(arg == "--help" || arg == "-h") {
+      print_usage(argv[0]);
+      return true;
+    } else if(arg == "--fullscreen" || arg == "-f") {
       config->use_fullscreen = true;
+    } else if(arg == "--default" || arg == "-d") {
+      config->use_fullscreen = false;
+      
+      config->window_width  = 800;
+      config->window_height = 600;
+
+      config->fullscreen_width  = 800;
+      config->fullscreen_height = 600;
+
+      config->aspect_width  = 0;  // auto detect
+      config->aspect_height = 0;
+      
     } else if(arg == "--window" || arg == "-w") {
       config->use_fullscreen = false;
     } else if(arg == "--geometry" || arg == "-g") {
-      if(i+1 >= argc) {
-        print_usage(argv[0]);
-        throw std::runtime_error("Need to specify a parameter for geometry switch");
-      }
-      if(sscanf(argv[++i], "%dx%d", &config->screenwidth, &config->screenheight)
-         != 2) {
-        print_usage(argv[0]);
-        throw std::runtime_error("Invalid geometry spec, should be WIDTHxHEIGHT");
-      }
+      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
+            {
+              config->window_width  = width;
+              config->window_height = height;
+
+              config->fullscreen_width  = width;
+              config->fullscreen_height = height;
+            }
+        }
     } else if(arg == "--aspect" || arg == "-a") {
-      if(i+1 >= argc) {
-        print_usage(argv[0]);
-        throw std::runtime_error("Need to specify a parameter for aspect switch");
-      }
-      if(sscanf(argv[++i], "%d:%d", &config->aspectwidth, &config->aspectheight)
-         != 2) {
-        print_usage(argv[0]);
-        throw std::runtime_error("Invalid aspect spec, should be WIDTH:HEIGHT");
-      }
+      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<double>(config->aspect_width) /
+                static_cast<double>(config->aspect_height);
+
+              // use aspect ratio to calculate logical resolution
+              if (aspect_ratio > 1) {
+                config->aspect_width  = static_cast<int> (600 * aspect_ratio + 0.5);
+                config->aspect_height = 600;
+              } else {
+                config->aspect_width  = 600;
+                config->aspect_height = static_cast<int> (600 * 1/aspect_ratio + 0.5);
+              }
+            }
+        }
     } else if(arg == "--show-fps") {
       config->show_fps = true;
     } else if(arg == "--no-show-fps") {
@@ -307,7 +365,7 @@ static bool parse_commandline(int argc, char** argv)
         throw std::runtime_error("Need to specify a demo filename");
       }
       config->record_demo = argv[++i];
-    } else if(arg == "-d") {
+    } else if(arg == "--debug-scripts" || arg == "-s") {
       config->enable_script_debugger = true;
     } else if(arg[0] != '-') {
       config->start_level = arg;
@@ -342,85 +400,52 @@ static void init_sdl()
 
 static void init_rand()
 {
-  const char *how = config->random_seed? ", user fixed.": ", from time().";
-
   config->random_seed = systemRandom.srand(config->random_seed);
 
-  log_info << "Using random seed " << config->random_seed << how << std::endl;
+  //const char *how = config->random_seed? ", user fixed.": ", from time().";
+  //log_info << "Using random seed " << config->random_seed << how << std::endl;
 }
 
 void init_video()
 {
-  if(texture_manager != NULL)
-    texture_manager->save_textures();
-
-  SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
-  SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
-  SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
-  SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
-
-  int flags = SDL_OPENGL;
-  if(config->use_fullscreen)
-    flags |= SDL_FULLSCREEN;
-  int width = config->screenwidth;
-  int height = config->screenheight;
-  int bpp = 0;
-
-  screen = SDL_SetVideoMode(width, height, bpp, flags);
-  if(screen == 0) {
-    std::stringstream msg;
-    msg << "Couldn't set video mode (" << width << "x" << height
-        << "-" << bpp << "bpp): " << SDL_GetError();
-    throw std::runtime_error(msg.str());
-  }
+  // FIXME: Add something here
+  SCREEN_WIDTH  = 800;
+  SCREEN_HEIGHT = 600;
+
+  context_pointer->init_renderer();
+  screen = SDL_GetVideoSurface();
 
   SDL_WM_SetCaption(PACKAGE_NAME " " PACKAGE_VERSION, 0);
 
   // set icon
-  SDL_Surface* icon = IMG_Load_RW(
-      get_physfs_SDLRWops("images/engine/icons/supertux.xpm"), true);
+#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;
+  }
   if(icon != 0) {
     SDL_WM_SetIcon(icon, 0);
     SDL_FreeSurface(icon);
   }
 #ifdef DEBUG
   else {
-    log_warning << "Couldn't find icon 'images/engine/icons/supertux.xpm'" << std::endl;
+    log_warning << "Couldn't load icon '" << icon_fname << "'" << std::endl;
   }
 #endif
 
-  // use aspect ratio to calculate logical resolution
-  if (config->aspectwidth > config->aspectheight) {
-       SCREEN_HEIGHT=600;
-       SCREEN_WIDTH=600*config->aspectwidth/config->aspectheight;
-  }
-  else {
-       SCREEN_WIDTH=600;
-       SCREEN_HEIGHT=600*config->aspectheight/config->aspectwidth;
-  }
+  SDL_ShowCursor(0);
 
-  // setup opengl state and transform
-  glDisable(GL_DEPTH_TEST);
-  glDisable(GL_CULL_FACE);
-  glEnable(GL_TEXTURE_2D);
-  glEnable(GL_BLEND);
-  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
-  glViewport(0, 0, screen->w, screen->h);
-  glMatrixMode(GL_PROJECTION);
-  glLoadIdentity();
-  // logical resolution here not real monitor resolution
-  glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
-  glMatrixMode(GL_MODELVIEW);
-  glLoadIdentity();
-  glTranslatef(0, 0, 0);
-
-  check_gl_error("Setting up view matrices");
-
-  if(texture_manager != NULL)
-    texture_manager->reload_textures();
-  else
-    texture_manager = new TextureManager();
+  log_info << (config->use_fullscreen?"fullscreen ":"window ")
+           << " Window: "     << config->window_width     << "x" << config->window_height
+           << " Fullscreen: " << config->fullscreen_width << "x" << config->fullscreen_height
+           << " Area: "       << config->aspect_width     << "x" << config->aspect_height << std::endl;
 }
 
 static void init_audio()
@@ -504,7 +529,7 @@ int main(int argc, char** argv)
 {
   int result = 0;
 
-#ifndef NO_CATCH
+#ifndef DEBUG
   try {
 #endif
 
@@ -517,22 +542,36 @@ int main(int argc, char** argv)
 
     timelog("controller");
     main_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();
+
     Console::instance->init_graphics();
+
     timelog("scripting");
     Scripting::init_squirrel(config->enable_script_debugger);
+
     timelog("resources");
     load_shared();
+
     timelog(0);
 
     main_loop = new MainLoop();
@@ -569,8 +608,8 @@ int main(int argc, char** argv)
     }
 
     //init_rand(); PAK: this call might subsume the above 3, but I'm chicken!
-    main_loop->run();
-#ifndef NO_CATCH
+    main_loop->run(context);
+#ifndef DEBUG
   } catch(std::exception& e) {
     log_fatal << "Unexpected exception: " << e.what() << std::endl;
     result = 1;
@@ -583,7 +622,6 @@ int main(int argc, char** argv)
   delete main_loop;
   main_loop = NULL;
 
-  free_options_menu();
   unload_shared();
   quit_audio();