Adonthell 0.4
|
00001 /* 00002 $Id: prefs.cc,v 1.36 2006/09/03 20:48:08 ksterker Exp $ 00003 00004 Copyright (C) 2000/2001/2002/2003 Kai Sterker <kaisterker@linuxgames.com> 00005 Part of the Adonthell Project http://adonthell.linuxgames.com 00006 00007 This program is free software; you can redistribute it and/or modify 00008 it under the terms of the GNU General Public License. 00009 This program is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY. 00011 00012 See the COPYING file for more details. 00013 */ 00014 00015 /** 00016 * @file prefs.cc 00017 * 00018 * @author Kai Sterker 00019 * @brief Adonthell's configuration 00020 */ 00021 00022 #ifdef HAVE_CONFIG_H 00023 #include <config.h> 00024 #endif 00025 #include <getopt.h> 00026 #include <stdio.h> 00027 #include <iostream> 00028 #include <sys/stat.h> 00029 #include <dirent.h> 00030 #include <unistd.h> 00031 #include "prefs.h" 00032 #include "python_class.h" 00033 #include "game.h" 00034 00035 config::config () 00036 { 00037 // set some default values where possible 00038 #if defined (WIN32) || defined (__APPLE__) 00039 screen_mode = 1; // Fullscreen 00040 #else 00041 screen_mode = 0; // Fullscreen 00042 #endif 00043 #if defined (QTOPIA) 00044 double_screen = 0; // Double screen 00045 #else 00046 double_screen = 1; // Double screen 00047 #endif 00048 quick_load = 0; // Quick-load disabled 00049 audio_channels = 1; // Stereo 00050 audio_resolution = 1; // 16 bit 00051 audio_sample_rate = 2; // 11025, 22050 or 44100 Hz 00052 audio_volume = 100; // 0 - 100% 00053 language = ""; // Let the user's environment decide 00054 font = ""; // use default font 00055 00056 // set the path to the adonthellrc file: 00057 #ifndef SINGLE_DIR_INST 00058 adonthellrc = string (getenv ("HOME")) + "/.adonthell"; 00059 #else 00060 adonthellrc = string ("."); 00061 #endif 00062 } 00063 00064 /** 00065 * Displays the help message - for internal use only. 00066 * 00067 */ 00068 void print_help_message (char * argv[]) 00069 { 00070 cout << "Usage: " << argv[0] << " [OPTIONS] GAME" << endl; 00071 cout << endl; 00072 cout << "Where [OPTIONS] can be:\n"; 00073 cout << "-h print this help message" << endl; 00074 cout << "-d print the data directory and exit" << endl; 00075 cout << "-v print version and exit" << endl; 00076 cout << "-l list installed games and exit" << endl; 00077 cout << "-g dir play the game contained in dir (for development only)" << endl; 00078 cout << "-c byte-compile all Python scripts in this directory (for " << endl; 00079 cout << " development only)" << endl; 00080 } 00081 00082 /** 00083 * Displays the available games - for internal use only. 00084 * 00085 */ 00086 void print_available_games () 00087 { 00088 struct dirent * d; 00089 DIR * mydir = opendir ((game::global_data_dir() + "/games").c_str()); 00090 bool nogames = true; 00091 00092 if (!mydir) 00093 { 00094 cerr << "Cannot open directory " << game::global_data_dir() + "/games!" << endl; 00095 exit (1); 00096 } 00097 00098 while ((d = readdir (mydir)) != NULL) 00099 { 00100 string s (d->d_name); 00101 if (s != "." && s != "..") 00102 { 00103 if (nogames) 00104 { 00105 nogames = false; 00106 cout << "Installed games (Suitable for the GAME parameter):\n"; 00107 } 00108 cout << " - " << d->d_name << endl; 00109 } 00110 } 00111 00112 if (nogames) cout << "No games available.\n"; 00113 00114 closedir (mydir); 00115 } 00116 00117 void config::parse_arguments (int argc, char * argv[]) 00118 { 00119 int c; 00120 00121 // Check for options 00122 while (1) 00123 { 00124 c = getopt (argc, argv, "lcdhvg:"); 00125 if (c == -1) 00126 break; 00127 00128 switch (c) 00129 { 00130 case 'l': 00131 print_available_games (); 00132 exit (0); 00133 break; 00134 00135 case 'd': 00136 cout << game::global_data_dir() << endl; 00137 exit (0); 00138 break; 00139 00140 case 'v': 00141 cout << VERSION << endl; 00142 exit (0); 00143 break; 00144 00145 case 'c': 00146 { 00147 python::init (); 00148 python::exec_string ("import compileall; compileall.compile_dir (\".\", 0);"); 00149 python::cleanup (); 00150 exit (0); 00151 break; 00152 } 00153 00154 case 'g': 00155 { 00156 gamedir = optarg; 00157 if (gamedir[gamedir.size () - 1] == '/') 00158 gamedir.erase (gamedir.size () - 1); 00159 00160 // Check whether the requested game directory exists 00161 DIR * mydir = opendir (gamedir.c_str ()); 00162 00163 if (!mydir) 00164 { 00165 cerr << "Cannot open directory " << gamedir << "!" << endl; 00166 exit (1); 00167 } 00168 closedir (mydir); 00169 00170 break; 00171 } 00172 00173 case '?': 00174 case 'h': 00175 print_help_message (argv); 00176 exit (0); 00177 break; 00178 } 00179 } 00180 00181 // Check whether the GAME parameter is needed 00182 if (gamedir == "") 00183 { 00184 // Check whether the GAME parameter is given 00185 if (argc - optind != 1) 00186 { 00187 print_help_message (argv); 00188 exit (0); 00189 } 00190 00191 // Check whether the requested game exists 00192 struct dirent * d; 00193 DIR * mydir = opendir ((game::global_data_dir() + "/games").c_str()); 00194 bool found = false; 00195 00196 if (!mydir) 00197 { 00198 cerr << "Cannot open directory " << game::global_data_dir() + "/games!" << endl; 00199 exit (1); 00200 } 00201 00202 while ((d = readdir (mydir)) != NULL) 00203 { 00204 if (string (d->d_name) == argv[optind]) found = true; 00205 } 00206 00207 closedir (mydir); 00208 00209 if (!found) 00210 { 00211 cerr << "Game '" << argv[optind] << "' can't be found.\n" 00212 << "Run '" << argv[0] << " -l' for a list of available games.\n"; 00213 exit (1); 00214 } 00215 00216 // The game exists, so let the show continue... 00217 gamedir = game::global_data_dir() + "/games/"; 00218 gamedir += argv[optind]; 00219 } 00220 00221 // Now check whether the directory is a valid game directory 00222 string tfile = gamedir + "/gamename.txt"; 00223 ifstream f (tfile.c_str ()); 00224 if (!f.is_open ()) 00225 { 00226 cerr << "Directory " << gamedir << " is not a valid game directory.\n"; 00227 exit (1); 00228 } 00229 char t[256]; 00230 f.getline (t, 256); 00231 game_name = t; 00232 f.close (); 00233 } 00234 00235 00236 00237 // That's more or less a move operator, as the source is destroyed 00238 config& config::operator =(const config *c) 00239 { 00240 screen_mode = c->screen_mode; 00241 audio_channels = c->audio_channels; 00242 audio_resolution = c->audio_resolution; 00243 audio_sample_rate = c->audio_sample_rate; 00244 audio_volume = c->audio_volume; 00245 adonthellrc = c->adonthellrc; 00246 00247 delete c; 00248 return *this; 00249 } 00250 00251 char *config::get_adonthellrc () 00252 { 00253 return (char *) adonthellrc.c_str (); 00254 } 00255 00256 // write a default configuration file 00257 void config::write_adonthellrc () 00258 { 00259 string fname; 00260 00261 #ifndef WIN32 00262 fname = adonthellrc + "/adonthellrc"; 00263 #else 00264 fname = adonthellrc + "/adonthell.ini"; 00265 #endif 00266 00267 ofstream rc (fname.c_str ()); 00268 00269 rc << "# Sample Adonthell configuration file;\n" 00270 << "# edit to your needs!\n\n" 00271 << "# Screen-mode num\n# 0 Windowed mode\n" 00272 << "# 1 Fullscreen mode\n Screen-mode " << (int) screen_mode 00273 << "\n\n" << "# Double-size num\n# 0 320x240 mode\n" 00274 << "# 1 640x480 (double) mode\n Double-size " 00275 << (int) double_screen << "\n\n" 00276 << "# Language [locale]\n# Where locale has the form fr_FR or de_DE, etc.\n" 00277 << " Language [" << language << "]\n\n" 00278 << "# Font [font.ttf]\n# Path to a true type font to use. Leave empty for default\n" 00279 << " Font [" << font << "]\n\n" 00280 << "# Quick-load num\n# 0 off\n# 1 on\n Quick-load " 00281 << (int) quick_load << "\n\n" 00282 << "# Audio-channels num\n# 0 Mono\n# 1 Stereo\n" 00283 << " Audio-channels " << (int) audio_channels << "\n\n" 00284 << "# Audio-resolution num\n# 0 8 bit\n# 1 16 bit\n" 00285 << " Audio-resolution " << (int) audio_resolution << "\n\n" 00286 << "# Audio-sample-rate num\n# 0 11025 Hz\n# 1 22050 Hz\n# 2 44100 Hz\n" 00287 << " Audio-sample-rate " << (int) audio_sample_rate << "\n\n" 00288 << "# Audio-volume num\n# 0 - 100 %\n" 00289 << " Audio-volume " << (int) audio_volume << "\n\n" 00290 << "# Version number of this file. Please don't edit\n Version [" << VERSION << "]\n"; 00291 00292 rc.close (); 00293 } 00294 00295 bool config::read_adonthellrc () 00296 { 00297 int n, i = 1; 00298 u_int32 major = 0, minor = 0, micro = 0, MAJOR, MINOR, MICRO; 00299 char suffix[16] = "\0", SUFFIX[16] = "\0"; 00300 string s, fname; 00301 00302 #ifndef WIN32 00303 fname = adonthellrc + "/adonthellrc"; 00304 #else 00305 fname = adonthellrc + "/adonthell.ini"; 00306 #endif 00307 00308 // try to create that directory in case it dosn't exist 00309 #ifdef WIN32 00310 mkdir (adonthellrc.c_str ()); 00311 #else 00312 mkdir (adonthellrc.c_str (), 0700); 00313 #endif 00314 00315 // prefsin is declared in lex.prefs.c 00316 prefsin = fopen (fname.c_str (), "r"); 00317 00318 // open failed -> try to write new configuration 00319 if (!prefsin) 00320 { 00321 write_adonthellrc (); 00322 00323 // now try again 00324 if (!(prefsin = fopen (fname.c_str (), "r"))) 00325 { 00326 fprintf (stderr, "*** warning: prefs::read_adonthellrc: creating config file failed\n"); 00327 return false; 00328 } 00329 } 00330 00331 // adonthellrc opened -> read configuration 00332 while (i) 00333 { 00334 switch (i = parse_adonthellrc (n, s)) 00335 { 00336 case PREFS_LANGUAGE: 00337 { 00338 if (parse_adonthellrc (n, s) == PREFS_STR) language = s; 00339 break; 00340 } 00341 case PREFS_FONT: 00342 { 00343 if (parse_adonthellrc (n, s) == PREFS_NUM) font = s; 00344 break; 00345 } 00346 case PREFS_SCREEN_MODE: 00347 { 00348 if (parse_adonthellrc (n, s) == PREFS_NUM) screen_mode = n; 00349 break; 00350 } 00351 00352 case PREFS_DOUBLE_SCREEN: 00353 { 00354 if (parse_adonthellrc (n, s) == PREFS_NUM) double_screen = n; 00355 break; 00356 } 00357 00358 case PREFS_QUICK_LOAD: 00359 { 00360 if (parse_adonthellrc (n, s) == PREFS_NUM) quick_load = n; 00361 break; 00362 } 00363 00364 case PREFS_AUDIO_RESOLUTION: 00365 { 00366 if (parse_adonthellrc (n, s) == PREFS_NUM) audio_resolution = n; 00367 break; 00368 } 00369 00370 case PREFS_AUDIO_CHANNELS: 00371 { 00372 if (parse_adonthellrc (n, s) == PREFS_NUM) audio_channels = n; 00373 break; 00374 } 00375 00376 case PREFS_AUDIO_SAMPLE_RATE: 00377 { 00378 if (parse_adonthellrc (n, s) == PREFS_NUM) audio_sample_rate = n; 00379 break; 00380 } 00381 00382 case PREFS_AUDIO_VOLUME: 00383 { 00384 if (parse_adonthellrc (n, s) == PREFS_NUM) audio_volume = n; 00385 break; 00386 } 00387 00388 case PREFS_VERSION: 00389 { 00390 // get config file version number 00391 if (parse_adonthellrc (n, s) == PREFS_STR) 00392 sscanf (s.c_str (), "%d.%d.%d%15s", &major, &minor, µ, suffix); 00393 break; 00394 } 00395 default: break; 00396 } 00397 } 00398 00399 fclose (prefsin); 00400 00401 // get engine version numbers 00402 sscanf (VERSION, "%d.%d.%d%15s", &MAJOR, &MINOR, &MICRO, SUFFIX); 00403 00404 // compare version of config file and engine 00405 if (major < MAJOR || 00406 (major == MAJOR && minor < MINOR) || 00407 (major == MAJOR && minor == MINOR && micro < MICRO) || 00408 strcmp (suffix, SUFFIX) != 0) 00409 { 00410 // update config file if engine is newer 00411 write_adonthellrc (); 00412 } 00413 00414 return true; 00415 }