/* * Copyright (C) 2002,2003 Daniel Heck * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. * * $Id: main.cc,v 1.1 2003/01/23 22:36:04 dheck Exp $ */ #include "config.h" #include "enigma.hh" #include "display.hh" #include "game.hh" #include "lua.hh" #include "menus.hh" #include "options.hh" #include "oxyd.hh" #include "sound.hh" #include "video.hh" #include "px/argp.hh" #include "SDL.h" #include #include #include using namespace std; using namespace px; using namespace enigma; namespace { class Nulbuf : public std::streambuf {}; } //====================================================================== // APPLICATION DATA //====================================================================== namespace enigma { Application app; } /* The stream object that is used for logging messages. As defined here, it is not connected to any file or buffer. (Note: I think writing to a stream without a streambuffer *should* be a no-op, but it leads to crashes with g++ 2.95. to circumvent this, Log is initialized with a dummy streambuf in init(). ) */ std::ostream enigma::Log(0); /* This is the stream object that is used when logging to a file. In this case, enigma::Log uses this object's streambuffer. */ static std::fstream logfile; //---------------------------------------------------------------------- // Startup //---------------------------------------------------------------------- static void usage() { printf("Available command line options for Enigma:\n\n" " --nosound Disable music and sound\n" " --nomusic Disable music\n" " --window Run in a window; do not enter fullscreen mode\n" " --help -h Show this help\n" " --version Print the executable's version number\n" " --8bpp Use 256 color mode\n" " --nograb Do not use exclusive mouse/keyboard access\n" "\n"); } static void init() { lua::Init(); // Run initialization scripts lua::Dofile("init.lua"); lua::Dofile("levels/index.lua"); // Load preferences if (!options::Load()) { fprintf(stderr, "Error in configuration file.\n"); } /* ** Evaluate command line arguments. */ struct AP : public argp::ArgParser { public: enum { OPT_NOSOUND, OPT_NOMUSIC, OPT_VERSION, OPT_HELP, OPT_WINDOW, OPT_WIZARD, OPT_NOGRAB, OPT_LOG, OPT_8BPP, OPT_GAME, OPT_PEROXYD, OPT_OXYD1, OPT_EXTRA, OPT_MAGNUM }; AP() : ArgParser (app.args.begin(), app.args.end()) { nosound = nomusic = show_help = show_version = do_log = false; gamename = ""; gametype = GAMET_ENIGMA; def (OPT_NOSOUND, 0, "nosound"); def (OPT_NOMUSIC, 0, "nomusic"); def (OPT_VERSION, 0, "version"); def (OPT_HELP, 'h', "help"); def (OPT_WINDOW, 'w', "window"); def (OPT_WIZARD, 0, "wizard"); def (OPT_NOGRAB, 0, "nograb"); def (OPT_LOG, 'l', "log"); def (OPT_8BPP, '8', "8bpp"); def (OPT_GAME, 'g', "game", true); def (OPT_PEROXYD, 0, "peroxyd"); def (OPT_OXYD1, 0, "oxyd1"); def (OPT_EXTRA, 0, "oxydextra"); def (OPT_MAGNUM,0, "oxydmagnum"); } // ArgParser interface. void on_error (ErrorType t, const string &option) { cout << errormsg(t, option) << endl; show_help = true; } void on_option (int id, const string ¶m) { switch (id) { case OPT_NOSOUND: nosound=true; break; case OPT_NOMUSIC: nomusic=true; break; case OPT_VERSION: show_version=true; break; case OPT_HELP: show_help=true; break; case OPT_WINDOW: options::FullScreen=false; break; case OPT_WIZARD: options::WizardMode=true; break; case OPT_NOGRAB: options::Nograb=true; break; case OPT_8BPP: options::BitsPerPixel = 8; break; case OPT_GAME: gamename = param; break; case OPT_LOG: do_log = true; break; case OPT_PEROXYD: gametype = GAMET_PEROXYD; break; case OPT_OXYD1: gametype = GAMET_OXYD1; break; case OPT_EXTRA: gametype = GAMET_OXYDEXTRA; break; case OPT_MAGNUM: gametype = GAMET_OXYDMAGNUM; break; } } void on_argument (const string &arg) { } // Variables. bool nosound, nomusic, show_help, show_version, do_log; string gamename; GameType gametype; }; AP ap; ap.parse(); if (ap.show_help || ap.show_version) { printf("Enigma v%s\n",VERSION); if (ap.show_help) usage(); exit(0); } if (ap.do_log) { logfile.open("enigma.log", ios::out); if (logfile) enigma::Log.rdbuf(logfile.rdbuf()); else fprintf(stderr,"Could not open log file \"enigma.log\" for writing.\n"); } else enigma::Log.rdbuf(new Nulbuf); int sdl_flags = SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE; if (!ap.nosound) sdl_flags |= SDL_INIT_AUDIO; if (SDL_Init(sdl_flags) < 0) { fprintf(stderr, "Couldn't init SDL: %s\n", SDL_GetError()); exit(1); } if (ap.nosound) sound::DisableSound(); else if (ap.nomusic) sound::DisableMusic(); oxyd::Init(); if (ap.gametype == GAMET_PEROXYD) { oxyd::OpenDatFile (OxydVersion_PerOxyd); } else if (ap.gametype == GAMET_OXYD1) { oxyd::OpenDatFile (OxydVersion_Oxyd1); } else if (ap.gametype == GAMET_OXYDMAGNUM) { oxyd::OpenDatFile (OxydVersion_OxydMagnum); } else if (ap.gametype == GAMET_OXYDEXTRA) { oxyd::OpenDatFile (OxydVersion_OxydExtra); } video::Init(); video::SetPalette("enigma.pal"); display::Init(); sound::Init(); world::Init(); video::SetMouseCursor(enigma::LoadImage("cur-magic"), 4, 4); video::ShowMouse(); } static void shutdown() { video::Shutdown(); display::Shutdown(); world::Shutdown(); options::Save(); delete_sequence(enigma::LevelPacks.begin(), enigma::LevelPacks.end()); } int main(int argc, char** argv) { #ifdef MACOSX // In Mac OS X, applications are self-contained bundles, // e.g. directories like "Enigma.app". Resources are // placed in those bundles under "Enigma.app/Contents/Resources", // the main executable would be "Enigma.app/Contents/MacOS/enigma". // Here, we get the executable name, clip off the last bit, chdir into it, // then chdir to ../Resources. The original SDL implementation chdirs to // "../../..", i.e. the directory the bundle is placed in. This break // the self-containedness. char parentdir[1024]; char *c; strncpy ( parentdir, argv[0], sizeof(parentdir) ); c = (char*) parentdir; while (*c != '\0') /* go to end */ c++; while (*c != '/') /* back up to parent */ c--; *c++ = '\0'; /* cut off last part (binary name) */ chdir (parentdir); /* chdir to the binary app's parent */ chdir ("../Resources/"); /* chdir to the .app's parent */ #endif //MACOSX app.init(argc,argv); init(); GUI_MainMenu(LevelPacks[0], 0); shutdown(); return 0; }