Config.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  1. //#ident "$Id: Config.cpp,v 1.29 2003/06/13 13:39:44 rzr Exp $"
  2. /***************************************************************************
  3. Config.cpp - description
  4. -------------------
  5. begin : Wed Jan 26 2000
  6. copyright : (C) 2000 by Henrik Enqvist
  7. email : henqvist@excite.com
  8. ***************************************************************************/
  9. #include "Private.h"
  10. #include "Config.h"
  11. #include "EMath.h"
  12. #include <cstdio>
  13. #include <fstream>
  14. #include <iostream>
  15. #if HAVE_SYS_STAT_H
  16. #include <sys/stat.h>
  17. #endif
  18. #if HAVE_SYS_TYPES_H
  19. #include <sys/types.h>
  20. #endif
  21. #if HAVE_UNISTD_H // !+rzr: not in msvc
  22. #include <unistd.h>
  23. #endif
  24. #ifdef WIN32
  25. //#include <io.h>
  26. #include <direct.h> // mkdir @ msvc+mingw32
  27. //#define mkdir(name, modes) mkdir(name)
  28. #endif //!-rzr
  29. #ifndef MAX_PATH
  30. # define MAX_PATH 255
  31. #endif
  32. Config * Config::p_Instance = NULL;
  33. Config::Config() {
  34. m_sDataDir = "";
  35. m_sSubDir = "";
  36. m_sDataSubDir = "";
  37. m_sExeDir = "";
  38. }
  39. Config::~Config() {
  40. }
  41. Config * Config::getInstance() {
  42. if (p_Instance == NULL) {
  43. p_Instance = new Config();
  44. p_Instance->setDefault();
  45. }
  46. return p_Instance;
  47. }
  48. void Config::setDefault() {
  49. // Default values
  50. this->setSize( CONFIG_LOCAL_WIDTH_DEFAULT, CONFIG_LOCAL_HEIGHT_DEFAULT );
  51. this->setSound(8);
  52. this->setMusic(8);
  53. this->setBpp(16);
  54. this->setGLFilter(EM_LINEAR);
  55. this->setView(0);
  56. this->setFullScreen(false);
  57. m_bExternGL = false;
  58. #ifndef RZR_PATHRELATIVE
  59. this->setDataDir(EM_DATADIR); //!rzr is it usefull, ! belongs to user cfg?
  60. #endif
  61. this->setLights(true);
  62. this->setBrightness(0.5f);
  63. this->setShowFPS(false);
  64. this->setFire(false);
  65. string const leftflip("leftflip");
  66. string const rightflip("rightflip");
  67. string const bottomnudge("bottomnudge");
  68. string const leftnudge("leftnudge");
  69. string const rightnudge("rightnudge");
  70. string const launch("launch");
  71. string const reset("reset");
  72. this->setKey(leftflip, SDLK_LSHIFT);
  73. this->setKey(rightflip, SDLK_RSHIFT);
  74. this->setKey(bottomnudge, SDLK_SPACE);
  75. this->setKey(leftnudge, SDLK_LCTRL);
  76. this->setKey(rightnudge, SDLK_RCTRL);
  77. this->setKey(launch, SDLK_RETURN);
  78. this->setKey(reset, SDLK_r); // !rzr why not use Return
  79. }
  80. void Config::setDataDir(const char* ch) {
  81. m_sDataDir = string(ch);
  82. m_sDataSubDir = m_sDataDir + "/" + m_sSubDir;
  83. }
  84. void Config::setSubDir(const char* ch) {
  85. m_sSubDir = string(ch);
  86. m_sDataSubDir = m_sDataDir + "/" + m_sSubDir;
  87. }
  88. EMKey Config::getKey(string const & str) {
  89. if (m_hKey.find(str) != m_hKey.end()) {
  90. map<string, EMKey>::iterator element = m_hKey.find(str);
  91. return (*element).second;
  92. }
  93. // failed, just return anything
  94. return SDLK_HOME;
  95. }
  96. void Config::setKey(string const & str, EMKey key) {
  97. if (m_hKey.find(str) != m_hKey.end()) {
  98. m_hKey.erase(m_hKey.find(str));
  99. }
  100. m_hKey.insert(pair<string, EMKey>(str, key));
  101. }
  102. char const * const Config::getKeyCommonName(EMKey key) {
  103. #if EM_USE_SDL
  104. return SDL_GetKeyName(key);
  105. #endif // EM_USESDL
  106. #if EM_USE_ALLEGRO
  107. switch(key) {
  108. case SDLK_a: return "a";
  109. case SDLK_b: return "b";
  110. case SDLK_c: return "c";
  111. case SDLK_d: return "d";
  112. case SDLK_e: return "e";
  113. case SDLK_f: return "f";
  114. case SDLK_g: return "g";
  115. case SDLK_h: return "h";
  116. case SDLK_i: return "i";
  117. case SDLK_j: return "j";
  118. case SDLK_k: return "k";
  119. case SDLK_l: return "l";
  120. case SDLK_m: return "m";
  121. case SDLK_n: return "n";
  122. case SDLK_o: return "o";
  123. case SDLK_p: return "p";
  124. case SDLK_q: return "q";
  125. case SDLK_r: return "r";
  126. case SDLK_s: return "s";
  127. case SDLK_t: return "t";
  128. case SDLK_u: return "u";
  129. case SDLK_v: return "v";
  130. case SDLK_w: return "w";
  131. case SDLK_x: return "x";
  132. case SDLK_y: return "y";
  133. case SDLK_z: return "z";
  134. case SDLK_0: return "0";
  135. case SDLK_1: return "1";
  136. case SDLK_2: return "2";
  137. case SDLK_3: return "3";
  138. case SDLK_4: return "4";
  139. case SDLK_5: return "5";
  140. case SDLK_6: return "6";
  141. case SDLK_7: return "7";
  142. case SDLK_8: return "8";
  143. case SDLK_9: return "9";
  144. case SDLK_RETURN: return "return";
  145. case SDLK_SPACE: return "space";
  146. case SDLK_LSHIFT: return "left shift";
  147. case SDLK_RSHIFT: return "right shift";
  148. }
  149. return "unknown";
  150. #endif
  151. }
  152. void Config::saveConfig() {
  153. string dirname = string(".emilia/");
  154. string filename = string(PACKAGE_NAME);
  155. #if HAVE_SYS_STAT_H && HAVE_SYS_TYPES_H
  156. char const * const home = getenv("HOME");
  157. if (home != NULL) {
  158. // TODO unsafe
  159. dirname = string(home) + '/' + dirname;
  160. mkdir(dirname.c_str(), S_IRUSR | S_IWUSR |S_IXUSR);
  161. } else {
  162. #ifdef RZR_PATHRELATIVE //!rzr: check w32 config save (TODO)
  163. dirname = m_sExeDir + '/' ;
  164. filename = string(PACKAGE_NAME) + ".cfg";
  165. #else
  166. cerr << "Could not find environment variable HOME." << endl;
  167. cerr << "Not able to read or write config file" << endl;
  168. return;
  169. #endif
  170. }
  171. #endif
  172. filename = dirname + filename;
  173. ofstream file(filename.c_str());
  174. if (!file) {
  175. cerr << "Couldn't open config file: " << filename << endl;
  176. cerr << "Can't save config" << endl;
  177. return;
  178. }
  179. file << "size: " << m_iWidth <<" "<< m_iHeight << endl;
  180. file << "sound: " << m_iSound << endl;
  181. file << "music: " << m_iMusic << endl;
  182. file << "view: " << m_iView << endl;
  183. file << "bpp: " << m_iBpp << endl;
  184. file << "fullscreen: " << (m_bFullScreen ? "1" : "0") << endl;
  185. file << "lights: " << (m_bLights ? "1" : "0") << endl;
  186. file << "brightness: " << m_fBrightness << endl;
  187. if (m_iGLFilter == EM_LINEAR) {
  188. file << "texture_filter: " << "0" << endl;
  189. } else if (m_iGLFilter == EM_NEAREST) {
  190. file << "texture_filter: " << "1" << endl;
  191. } else {
  192. file << "texture_filter: " << "-1" << endl;
  193. }
  194. file << "showfps: " << (m_bShowFPS ? "1" : "0") << endl;
  195. file << "fire: " << (m_bFire ? "1" : "0") << endl;
  196. map<string, EMKey>::iterator iter = m_hKey.begin();
  197. map<string, EMKey>::iterator end = m_hKey.end();
  198. for (; iter != end; ++iter) {
  199. file << "keyboard: " << (*iter).first <<" "<< (*iter).second << endl;
  200. }
  201. file << "ratio: " << m_fRatio<< endl;
  202. }
  203. void Config::loadConfig() {
  204. // loading default fixes possible problems with missing values in config file
  205. this->setDefault();
  206. string dirname = string(".emilia/");
  207. string filename = string(PACKAGE_NAME);
  208. #if HAVE_SYS_STAT_H && HAVE_SYS_TYPES_H
  209. char const * const home = getenv("HOME");
  210. if (home != NULL) { // TODO unsafe
  211. dirname = string(home) + '/' + dirname;
  212. } else {
  213. #ifdef RZR_PATHRELATIVE //!rzr: check w32 config save (TODO)
  214. dirname = m_sExeDir + '/' ;
  215. filename = string(PACKAGE_NAME) + ".cfg";
  216. #else
  217. cerr << "Could not find environment variable HOME." << endl;
  218. cerr << "Not able to read or write config file" << endl;
  219. return;
  220. #endif
  221. }
  222. #endif
  223. filename = dirname + filename;
  224. ifstream file(filename.c_str());
  225. if (!file) {
  226. cerr << "Couldn't open config file: " << filename << endl;
  227. cerr << "Using default values" << endl;
  228. return;
  229. }
  230. while (file) {
  231. string str;
  232. file >> str;
  233. if (str == "size:") {
  234. file >> m_iWidth;
  235. file >> m_iHeight;
  236. } else if (str == "sound:") {
  237. int vol=0;
  238. file >> vol;
  239. this->setSound(vol);
  240. } else if (str == "music:") {
  241. int vol=0;
  242. file >> vol;
  243. this->setMusic(vol);
  244. } else if (str == "view:") {
  245. file >> m_iView;
  246. } else if (str == "bpp:") {
  247. file >> m_iBpp;
  248. } else if (str == "fullscreen:") {
  249. file >> str;
  250. if (str == "0") this->setFullScreen(false);
  251. else this->setFullScreen(true);
  252. } else if (str == "showfps:") {
  253. file >> str;
  254. if (str == "0") this->setShowFPS(false);
  255. else this->setShowFPS(true);
  256. } else if (str == "fire:") {
  257. file >> str;
  258. if (str == "0") this->setFire(false);
  259. else this->setFire(true);
  260. } else if (str == "lights:") {
  261. file >> str;
  262. if (str == "0") this->setLights(false);
  263. else this->setLights(true);
  264. } else if (str == "texture_filter:") {
  265. file >> str;
  266. if (str == "0") {
  267. m_iGLFilter = EM_LINEAR;
  268. } else if (str == "1") {
  269. m_iGLFilter = EM_NEAREST;
  270. } else {
  271. m_iGLFilter = -1;
  272. }
  273. } else if (str == "brightness:") {
  274. float bright=0;
  275. file >> bright;
  276. this->setBrightness(bright);
  277. } else if (str == "keyboard:") {
  278. string keyname;
  279. int key=0;
  280. file >> keyname;
  281. file >> key;
  282. this->setKey(keyname, (EMKey)key);
  283. } else if (str == "ratio:") {
  284. file >> m_fRatio;
  285. }
  286. }
  287. //EM_CERR("- Config::loadConfig");
  288. }
  289. void Config::setSize(int const w, int h) {
  290. if ( h == 0 ) { h = w; }
  291. m_iWidth = EM_MIN(1600, EM_MAX(100,w));
  292. m_iHeight = EM_MIN(1200, EM_MAX(100,h));
  293. m_iWidthDiv2 = m_iWidth/2;
  294. m_iHeightDiv2 = m_iHeight/2;
  295. }
  296. void Config::loadArgs(int & argc, char *argv[]) {
  297. // Parse and remove arguments, arguments are removed so the main program does not see them
  298. // E.g. if a program wants to load a file the file name will always be arg 1
  299. // regardless of 'emilia' arguments.
  300. #define REMOVEARG(a, argc, argv) { for (int aa=a ;aa < argc-1; aa++) argv[aa] = argv[aa+1]; argc--; } //!+rzr added scope for msvc
  301. #ifdef RZR_PATHRELATIVE
  302. //!+rzr this workaround Full path to relative ones, usefull for windows port
  303. setPaths( argv[0] );
  304. #endif //!-rzr
  305. int a = 1;
  306. while (a < argc) {
  307. // for (int a=1; a<argc; a++) {
  308. if (strcmp(argv[a], "-dir") == 0) {
  309. cout << EM_DATADIR << endl;
  310. exit(0);
  311. } else if (strcmp(argv[a], "-fullscreen") == 0) {
  312. m_bFullScreen = true;
  313. EM_COUT("Using fullscreen", 1);
  314. REMOVEARG(a, argc, argv);
  315. } else if (strcmp(argv[a], "-size") == 0) {
  316. if (argc > a+2) {
  317. int const w= atoi(argv[a+1]);
  318. int const h = atoi(argv[a+2]);
  319. this->setSize(w, h);
  320. EM_COUT("Using size = " << m_iWidth <<","<< m_iHeight, 1);
  321. REMOVEARG(a, argc, argv);
  322. REMOVEARG(a, argc, argv);
  323. REMOVEARG(a, argc, argv);
  324. } else {
  325. REMOVEARG(a, argc, argv);
  326. }
  327. } else if (strcmp(argv[a], "-bpp") == 0) {
  328. if (argc > a+1) {
  329. m_iBpp = atoi(argv[a+1]);
  330. REMOVEARG(a, argc, argv);
  331. }
  332. EM_COUT("Using " << m_iBpp << " bpp", 1);
  333. REMOVEARG(a, argc, argv);
  334. } else if (strcmp(argv[a], "-nosound") == 0) {
  335. this->setSound(0);
  336. this->setMusic(0);
  337. EM_COUT("Disabling sound", 1);
  338. REMOVEARG(a, argc, argv);
  339. } else if (strcmp(argv[a], "-nolights") == 0) {
  340. this->setLights(false);
  341. EM_COUT("Disabling lights", 1);
  342. REMOVEARG(a, argc, argv);
  343. } else if (strcmp(argv[a], "-nearest") == 0) {
  344. this->setGLFilter(EM_NEAREST);
  345. EM_COUT("Using nearest for texture mapping", 1);
  346. REMOVEARG(a, argc, argv);
  347. } else if (strcmp(argv[a], "-externgl") == 0) {
  348. m_bExternGL = true;
  349. EM_COUT("Using extern GL, disabling SDL", 1);
  350. REMOVEARG(a, argc, argv);
  351. } else {
  352. EM_COUT("Unknown argument: " << argv[a], 1);
  353. a++;
  354. }
  355. }
  356. // em_width_ = m_iWidth;
  357. // em_height_ = m_iHeight;
  358. // em_width_div2_ = m_iWidth/2;
  359. // em_height_div2_ = m_iHeight/2;
  360. #undef REMOVEARG
  361. //EM_CERR("- Config::loadArgs");
  362. }
  363. ///!+rzr this workaround Full path to relative ones, usefull for windows port
  364. bool isAbsolutePath(char const * const argv0 ) ;
  365. bool isAbsolutePath(char const * const argv0 )
  366. {
  367. //EM_COUT(" check root drive c:\\ // absolute path - check for wine ?", 42);
  368. bool t = false;
  369. #ifdef WIN32
  370. // assert (strlen (argv0) > 3 );
  371. if ( ( *(argv0 +1) == ':' ) && ( *(argv0 +2) == '\\' ) )
  372. return true;
  373. #endif
  374. if ( *argv0 == '/' ) // WIN32 @ unix wine/ cygwine
  375. t = true;
  376. // check for macs, amigas etc
  377. //cout<<"- isAbsolutePath"<<endl;
  378. return t;
  379. }
  380. /// TODO; make it more robust for stranges paths
  381. /// (ie "c:\\d/i//r\like\\\\this/\\/") , wine virtual pc etc
  382. void Config::setPaths(char const * const argv0) {
  383. // EM_CERR("+ Config::setPath");
  384. //!+rzr : make it work also in relative paths use
  385. // and "/long path/quoted/paths/" etc
  386. //EM_COUT( argv0 , 0);
  387. m_sDataDir = string(EM_DATADIR) + "/";
  388. m_sExeDir = "./";
  389. if ( *( m_sDataDir.c_str() ) != '/' ) {
  390. const char* ptr=0;
  391. char* ptrw = 0;
  392. //cout<<"relative to exe file"<<endl;
  393. ptr = (strrchr(argv0,'/')); // unix /cygwin / check win32
  394. #ifdef WIN32
  395. ptrw = (strrchr(argv0,'\\'));
  396. #endif //TODO: MacOS file sep ':'
  397. if ( ptrw > ptr ) ptr = ptrw;
  398. // assert( (*ptr != 0) );
  399. string path( argv0 , ptr - argv0 );
  400. //EM_COUT( path , 42);
  401. if ( isAbsolutePath( argv0 ) ) {
  402. m_sExeDir = path ;
  403. } else {
  404. //EM_COUT("relative path from cwd",42);
  405. char cwd[MAX_PATH]; // TODO check for buffer overflow
  406. char* status = getcwd(cwd,MAX_PATH);
  407. m_sExeDir = string(cwd) + '/' + path ;
  408. }
  409. m_sDataDir = m_sExeDir + '/' + string(EM_DATADIR) ;
  410. } else { // cout<<"absolute path"<<endl;
  411. m_sDataDir = string(EM_DATADIR) ;
  412. }
  413. m_sDataSubDir = m_sDataDir + "/" + m_sSubDir ;
  414. #ifdef WIN32 // !+rzr Path are backlashed
  415. // but works fine that way on wine and win98
  416. // m_sDataSubDir.replace ( m_sDataSubDir.find(/,0) , 1, \\ );
  417. // m_sDataDir.replace ( m_sDataDir.find(\\,0) , 1, / );
  418. #endif
  419. // EM_CERR("- Config::setPath"); // EM_CERR( m_sExeDir); EM_CERR( m_sDataDir);
  420. } //!-rzr
  421. //EOF:$Id: Config.cpp,v 1.29 2003/06/13 13:39:44 rzr Exp $