1 /**
2 * @file configfile.cc
3 * @brief Config file handler
4 * @created 2005-01-22
5 * @date 2014-09-28
6 * @copyright 1991-2014 TLK Games
7 * @author Bruno Ethvignot
8 * @version $Revision: 24 $
9 */
10 /*
11 * copyright (c) 1991-2014 TLK Games all rights reserved
12 * $Id: configfile.cc 24 2014-09-28 15:30:04Z bruno.ethvignot@gmail.com $
13 *
14 * TecnoballZ is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 3 of the License, or
17 * (at your option) any later version.
18 *
19 * TecnoballZ is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
27 * MA 02110-1301, USA.
28 */
29 #include "config.h"
30 #include "../include/configfile.h"
31 #include "../include/handler_display.h"
32 #include "../include/handler_audio.h"
33 #include "../include/handler_players.h"
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38
39 const char *
40 configfile::language_to_string[MAX_OF_LANGUAGES] =
41 {
42 "en",
43 "fr"
44 };
45
46 const
47 std::string
48 configfile::CONF_DIR_NAME ("tlk-games");
49 const
50 std::string
51 configfile::CONF_FILENAME ("tecnoballz.conf");
52
53 /**
54 * Create object
55 */
configfile()56 configfile::configfile ()
57 {
58 thePlayers[0] = thePlayer1;
59 thePlayers[1] = thePlayer2;
60 thePlayers[2] = thePlayer3;
61 thePlayers[3] = thePlayer4;
62 thePlayers[4] = thePlayer5;
63 thePlayers[5] = thePlayer6;
64 for (Uint32 i = 0; i < handler_players::MAX_OF_PLAYERS; i++)
65 {
66 char *p = thePlayers[i];
67 for (Uint32 j = 0; j < 8; j++)
68 {
69 p[j] = 0;
70 }
71 }
72 resetvalue ();
73 }
74
75 /**
76 * Destroy object
77 */
~configfile()78 configfile::~configfile ()
79 {
80 }
81
82 /**
83 * Reset all values
84 */
85 void
resetvalue()86 configfile::resetvalue ()
87 {
88 #ifndef SOUNDISOFF
89 handler_audio::is_audio_enable = 1;
90 #endif
91 resolution = 2;
92 has_background = false;
93 is_verbose = false;
94 handler_display::optionfull = false;
95 difficulty_level = DIFFICULTY_NORMAL;
96 initial_num_of_lifes = 5;
97 number_of_players = 1;
98 char *user = getenv ("USER");
99 if (user != NULL)
100 {
101 user = stringname;
102 }
103 for (Uint32 i = 0; i < 6; i++)
104 {
105 strncpy (thePlayers[i], user, 6);
106 }
107 language = LANGUAGE_EN;
108 absolute_mouse_positioning = false;
109 }
110
111 /**
112 * Display values
113 */
114 void
configinfo()115 configfile::configinfo ()
116 {
117 bool audio;
118 #ifndef SOUNDISOFF
119 audio = handler_audio::is_audio_enable;
120 #else
121 audio = false;
122 #endif
123 fprintf (stdout, " <config info>\n"
124 "- optionfull : %i\n- is_audio_enable: %i\n- resolution:%i\n"
125 "- is_verbose: %i\n difficulty_level : %i\n",
126 handler_display::optionfull, audio, resolution,
127 is_verbose, difficulty_level);
128 }
129
130 /**
131 * Check if config directory exists; if not create it and set config_dir
132 */
check_and_create_dir()133 bool configfile::check_and_create_dir ()
134 {
135 #ifdef _WIN32
136 /* opendir don't exist on windows
137 * create directory if not exist */
138 MKDIR (conf_dirname.c_str (), S_IRWXU);
139 #else
140 /* test and create .tlkgames */
141 DIR* dp = opendir (conf_dirname.c_str ());
142 if (!dp)
143 {
144 fprintf (stderr, "couldn't find/open config directory '%s'\n",
145 conf_dirname.c_str ());
146 fprintf (stderr, "attempting to create it... ");
147 MKDIR (conf_dirname.c_str (), S_IRWXU);
148 dp = opendir (conf_dirname.c_str ());
149 if (!dp)
150 {
151 fprintf (stderr, "opendir() was failed\n");
152 return false;
153 }
154 }
155 closedir (dp);
156 #endif
157 return true;
158 }
159
160 /**
161 * Built the full path of the configuration file.
162 */
163 void
get_fullpathname()164 configfile::get_fullpathname ()
165 {
166 if (!conf_filename.empty ())
167 {
168 return;
169 }
170 if (getenv ("XDG_CONFIG_HOME") != NULL)
171 {
172 conf_dirname = getenv ("XDG_CONFIG_HOME");
173 conf_dirname += "/" + CONF_DIR_NAME;
174 }
175 else
176 {
177 conf_dirname = (getenv ("HOME") ? getenv ("HOME") : ".");
178 conf_dirname += "/.config/" + CONF_DIR_NAME;
179 }
180 conf_filename += conf_dirname + "/" + CONF_FILENAME;
181 }
182
183 /**
184 * Load configuration file in "~/.tlkgames/tecnoballz.conf"
185 */
186 void
load()187 configfile::load ()
188 {
189 resetvalue ();
190 get_fullpathname ();
191 std::cout << conf_filename << std::endl;
192 lispreader *parser = new lispreader ();
193 lisp_object_t *root_obj = parser->lisp_read_file (conf_filename);
194 if (root_obj == NULL)
195 {
196 std::
197 cerr << "lispreader::lisp_read_file (" << conf_filename <<
198 ") was failed" << std::endl;
199 return;
200 }
201 if (root_obj->type == LISP_TYPE_EOF
202 || root_obj->type == LISP_TYPE_PARSE_ERROR)
203 {
204 fprintf (stderr, "configfile::loadconfig() / conf parsing failed\n");
205 return;
206 }
207
208 if (strcmp
209 (parser->lisp_symbol (parser->lisp_car (root_obj)),
210 "tecnoballz-config") != 0)
211 {
212 fprintf (stderr, "configfile::loadconfig() / conf parsing failed\n");
213 return;
214 }
215
216 std::string ptStr;
217
218 if (!parser->read_string ("lang", &ptStr))
219 {
220 language = LANGUAGE_EN;
221 }
222 else
223 {
224 if (ptStr == "fr")
225 {
226 language = LANGUAGE_FR;
227 }
228 else
229 {
230 language = LANGUAGE_EN;
231 }
232 }
233 //exit(0);
234 if (!parser->read_bool ("fullscreen", &handler_display::optionfull))
235 {
236 handler_display::optionfull = -1;
237 }
238 #ifndef SOUNDISOFF
239 if (!parser->read_bool ("sound", &handler_audio::is_audio_enable))
240 {
241 handler_audio::is_audio_enable = true;
242 }
243 #endif
244 if (!parser->read_bool ("verbose", &is_verbose))
245 {
246 is_verbose = false;
247 }
248 if (!parser->read_bool ("absolute_mouse", &absolute_mouse_positioning))
249 {
250 absolute_mouse_positioning = false;
251 }
252
253
254 // read window resolution: 1 = 320*240; 2 = 640*480
255 Sint32 res = 0;
256 if (!parser->read_int ("resolution", &res))
257 {
258 res = 2;
259 }
260 resolution = res;
261 if (resolution < 1 || resolution > 2)
262 {
263 resolution = 2;
264 }
265 if (resolution == 2)
266 {
267 has_background = false;
268 }
269 else
270 {
271 has_background = true;
272 }
273 has_background = false;
274
275 // read number of lifes from 1 to 9
276 if (!parser->read_int ("lifes", &initial_num_of_lifes))
277 {
278 initial_num_of_lifes = 5;
279 }
280 if (initial_num_of_lifes < 1 || initial_num_of_lifes > 9)
281 {
282 initial_num_of_lifes = 5;
283 }
284
285 // read difficulty DIFFICULTY_EASY, DIFFICULTY_NORMAL,
286 // DIFFICULTY_MEDIUM or DIFFICULTY_HARD
287 if (!parser->read_int ("difficulty", &difficulty_level))
288 {
289 difficulty_level = DIFFICULTY_NORMAL;
290 }
291 if (difficulty_level < DIFFICULTY_EASY
292 || difficulty_level > DIFFICULTY_HARD)
293 {
294 difficulty_level = DIFFICULTY_NORMAL;
295 }
296
297 // read number of players from 1 to 6
298 if (!parser->read_int ("players", &number_of_players))
299 {
300 number_of_players = handler_players::MAX_OF_PLAYERS;
301 }
302 if (number_of_players < 1
303 || number_of_players > (Sint32) handler_players::MAX_OF_PLAYERS)
304 {
305 number_of_players = 1;
306 }
307
308 // read players names
309 std::string sName (6, ' ');
310 char cName[8] = { "......." };
311 for (Uint32 i = 0; i < 6; i++)
312 {
313 sprintf (cName, "player%01d", i + 1);
314 if (parser->read_string (cName, &sName))
315 {
316 strncpy (thePlayers[i], sName.c_str (), 6);
317 }
318 }
319 delete parser;
320 #ifdef TECNOBALLZ_GP2X
321 resolution = 1;
322 #endif
323 }
324
325 /**
326 * Return current player name, which read from config file
327 * @param playernum Player number from 0 to 5
328 * @return Pointer to a player name
329 */
330 const char *
get_player_name(Uint32 playernum)331 configfile::get_player_name (Uint32 playernum)
332 {
333 if (playernum >= handler_players::MAX_OF_PLAYERS)
334 {
335 playernum = handler_players::MAX_OF_PLAYERS - 1;
336 }
337 return thePlayers[playernum];
338 }
339
340 /**
341 * Set player name
342 * @param playernum Player number from 0 to 5
343 * @param name Pointer to a string
344 */
345 void
set_player_name(Uint32 playernum,const char * name)346 configfile::set_player_name (Uint32 playernum, const char *name)
347 {
348 if (playernum >= handler_players::MAX_OF_PLAYERS)
349 {
350 playernum = handler_players::MAX_OF_PLAYERS - 1;
351 }
352 strncpy (thePlayers[playernum], name, 6);
353 }
354
355 /*
356 * Return current language
357 * @return "en" or fr
358 */
359 const char *
get_language()360 configfile::get_language ()
361 {
362 return language_to_string[language];
363 }
364
365 /**
366 * Save config file "~/.tlkgames/tecnoballz.conf"
367 */
368 void
save()369 configfile::save ()
370 {
371 bool audio;
372 #ifndef SOUNDISOFF
373 audio = handler_audio::is_audio_enable;
374 #else
375 audio = false;
376 #endif
377 if (!check_and_create_dir ())
378 {
379 return;
380 }
381 FILE *config = fopen_data (conf_filename.c_str (), "w");
382 if (config)
383 {
384 fprintf (config, "(tecnoballz-config\n");
385 fprintf (config,
386 "\t;; the following options can be set to #t or #f:\n");
387 fprintf (config, "\t(fullscreen %s)\n",
388 handler_display::optionfull ? "#t" : "#f");
389 fprintf (config, "\t(sound %s)\n", audio ? "#t" : "#f");
390 fprintf (config, "\t(verbose %s)\n", is_verbose ? "#t" : "#f");
391 fprintf (config, "\t(absolute_mouse %s)\n",
392 absolute_mouse_positioning ? "#t" : "#f");
393 fprintf (config, "\n\t;; window size 1 (low-res) or 2 (high-res):\n");
394 fprintf (config, "\t(resolution %d)\n", resolution);
395 fprintf (config,
396 "\n\t;; difficulty 1 (easy), 2 (hard), 3 (madness) or 4 (suicidal)\n");
397 fprintf (config, "\t(difficulty %d)\n", difficulty_level);
398 fprintf (config, "\n\t;; number of lifes (1 to 9)\n");
399 fprintf (config, "\t(lifes %d)\n", initial_num_of_lifes);
400 fprintf (config, "\n\t;; number of players (1 to 6)\n");
401 fprintf (config, "\t(players %d)\n", number_of_players);
402 fprintf (config, "\n\t;; players names\n");
403 for (Uint32 i = 0; i < handler_players::MAX_OF_PLAYERS; i++)
404 {
405 fprintf (config, "\t(player%i \"%s\")\n", i + 1,
406 thePlayers[i]);
407 }
408 fprintf (config, "\n\t;; language en or fr\n");
409 fprintf (config, "\t(lang ");
410 switch (language)
411 {
412 case LANGUAGE_FR:
413 fprintf (config, "\"fr\")\n");
414 break;
415 default:
416 fprintf (config, "\"en\")\n");
417 break;
418 }
419 fprintf (config, ")\n");
420 }
421 }
422
423 /**
424 * Open a file
425 * @param fname
426 * @param fmode
427 * @return
428 */
429 FILE *
fopen_data(const char * fname,const char * fmode)430 configfile::fopen_data (const char *fname, const char *fmode)
431 {
432 FILE *fi;
433 fi = fopen (fname, fmode);
434 if (fi == NULL)
435 {
436 fprintf (stderr, "configfile::fopen_data(): Warning: Unable "
437 "to open the file \"%s\" ", fname);
438 if (strcmp (fmode, "r") == 0)
439 {
440 fprintf (stderr, "for read!!!\n");
441 }
442 else if (strcmp (fmode, "w") == 0)
443 {
444 fprintf (stderr, "for write!!!\n");
445 }
446 }
447 return (fi);
448 }
449
450 /**
451 * Scan command line arguments
452 * @param arg_count the number of arguments
453 * @param arg_values he command line arguments
454 * @return FALSE if exit, TRUE otherwise
455 */
scan_arguments(Sint32 arg_count,char ** arg_values)456 Sint32 configfile::scan_arguments (Sint32 arg_count, char **arg_values)
457 {
458 Sint32 i;
459 for (i = 1; i < arg_count; i++)
460 {
461 if (*arg_values[i] != '-')
462 {
463 continue;
464 }
465
466 if (!strcmp (arg_values[i], "-h") || !strcmp (arg_values[i], "--help"))
467 {
468 printf ("\noptions:\n");
469 printf ("-h, --help print Help (this message) and exit\n");
470 printf ("--version print version information and exit\n");
471 printf ("--full full screen\n");
472 printf ("--window windowed mode\n");
473 printf ("--320 game run in a 320*200 window\n");
474 printf ("--640 game run in a 640*400 window\n");
475 printf ("--verbose verbose mode\n");
476 #ifndef SOUNDISOFF
477 printf ("--nosound force no sound\n");
478 printf ("--sound enable sound\n");
479 #endif
480 printf ("--nosync disable timer\n");
481 printf ("--bg4 Force using a four-color background\n");
482 printf
483 ("--------------------------------------------------------------\n");
484 printf ("keys recognized during the game:\n");
485 printf ("CTRL+S enable/disable sound\n");
486 printf ("CTRL+D enable/disable music\n");
487 printf ("CTRL+F enable/disable sound effects\n");
488 printf ("CTRL+X finish the play current\n");
489 printf ("CTRL+Q return to the main menu\n");
490 printf ("CTRL+ESC quit TecnoballZ\n");
491 printf ("P enable/disable pause\n");
492 printf ("F full screen/window mode\n");
493 printf ("\n");
494 return 0;
495 }
496
497 if (!strcmp (arg_values[i], "--version"))
498 {
499 printf (TECNOBALLZ_VERSION);
500 printf ("\n");
501 printf ("copyright (c) 1991-2014 TLK Games\n");
502 printf ("website: http://linux.tlk.fr/games/TecnoballZ/\n");
503 return 0;
504 }
505
506 if (!strcmp (arg_values[i], "--full"))
507 {
508 handler_display::optionfull = true;
509 continue;
510 }
511
512 if (!strcmp (arg_values[i], "--window"))
513 {
514 handler_display::optionfull = false;
515 continue;
516 }
517
518 if (!strcmp (arg_values[i], "--verbose") ||
519 !strcmp (arg_values[i], "-v"))
520 {
521 is_verbose = true;
522 continue;
523 }
524
525 if (!strcmp (arg_values[i], "--320"))
526 {
527 resolution = 1;
528 continue;
529 }
530 if (!strcmp (arg_values[i], "--640"))
531 {
532 resolution = 2;
533 continue;
534 }
535
536 if (!strcmp (arg_values[i], "--nosync"))
537 {
538 handler_display::optionsync = false;
539 continue;
540 }
541 #ifndef SOUNDISOFF
542 if (!strcmp (arg_values[i], "--sound"))
543 {
544 handler_audio::is_audio_enable = true;
545 continue;
546 }
547 if (!strcmp (arg_values[i], "--nosound"))
548 {
549 handler_audio::is_audio_enable = false;
550 continue;
551 }
552 #endif
553 /* use 4 colors background in 640x480 */
554 if (!strcmp (arg_values[i], "--bg4"))
555 {
556 force_4_colors_tiles = true;
557 continue;
558 }
559
560 #ifdef UNDER_DEVELOPMENT
561 /* start at brick or guard level */
562 if (!strcmp (arg_values[i], "--guard"))
563 {
564 arg_jumper = 3;
565 continue;
566 }
567 if (!strcmp (arg_values[i], "--brick"))
568 {
569 arg_jumper = 1;
570 continue;
571 }
572 #endif
573 }
574 return 1;
575 }
576
577 char
578 configfile::stringname[7] = "YANIS ";
579