1 /*
2  *  This program is free software; you can redistribute it and/or modify
3  *  it under the terms of the GNU General Public License as published by
4  *  the Free Software Foundation; either version 2 of the License, or
5  *  (at your option) any later version.
6  *
7  *  This program is distributed in the hope that it will be useful,
8  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  *  GNU Library General Public License for more details.
11  *
12  *  You should have received a copy of the GNU General Public License
13  *  along with this program; if not, write to the Free Software
14  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15  */
16 #include "iniconfig.h"
17 #include "utils.h"
18 
19 #if !defined(WIN32) && !defined(SOLARIS)
20 #include <argp.h>
21 #endif
22 
23 static int default_joy_mapping[J_MAX] = {0, 0, 0, 0,
24 	0, 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1};
25 
26 //! Filename of the cd system rom
27 char cdsystem_path[PATH_MAX];
28 
29 char sCfgFileLine[BUFSIZ];
30 // line buffer for config reading
31 
32 char temp_result[BUFSIZ];
33 // temporary return value for get_config_var function
34 
35 char config_file[PATH_MAX], config_file_tmp[PATH_MAX];
36 // name of the config file
37 
38 const int config_ar_size_max = 2000;
39 // number max of variable read off the configuration file
40 
41 int config_ar_index = 0;
42 // next entry where to insert variable / size of the config variable array
43 
44 typedef struct
45 {
46   char *section;
47   char *variable;
48   char *value;
49 } config_var;
50 
51 config_var *config_ar;
52 // actual array toward the entries
53 
54 
55 int
config_var_cmp(const void * lhs,const void * rhs)56 config_var_cmp (const void *lhs, const void *rhs)
57 {
58   int section_cmp =
59     stricmp (((config_var *) lhs)->section, ((config_var *) rhs)->section);
60 
61   if (section_cmp != 0)
62     return section_cmp;
63 
64   return stricmp (((config_var *) lhs)->variable,
65 		  ((config_var *) rhs)->variable);
66 }
67 
68 void
set_config_file(const char * filename)69 set_config_file (const char *filename)
70 {
71   strcpy (config_file_tmp, config_file);
72   strcpy (config_file, filename);
73 }
74 
75 void
set_config_file_back(void)76 set_config_file_back (void)
77 {
78   strcpy (config_file, config_file_tmp);
79 }
80 
81 char
init_config(void)82 init_config (void)
83 {
84   FILE *FCfgFile = NULL;
85   char *pWrd = NULL;
86   char *pRet;
87   char *pTmp;
88   char *section = NULL;
89 
90   config_ar_index = 0;
91   if ((config_ar =
92        (config_var *) malloc (sizeof (config_var) * config_ar_size_max)) ==
93       NULL)
94     return 0;
95 
96   /* open config file for reading */
97   if ((FCfgFile = fopen (config_file, "r")) != NULL)
98     {
99       do
100 	{
101 	  memset (sCfgFileLine, '\0', BUFSIZ);
102 	  /* note.. line must NOT be a comment */
103 	  pRet = fgets (sCfgFileLine, BUFSIZ, FCfgFile);
104 
105 	  if (sCfgFileLine[0] == '#')
106 	    continue;
107 
108 	  if (sCfgFileLine[0] == '[')
109 	    {
110 	      int section_size;
111 	      pWrd = strrchr (sCfgFileLine, ']');
112 	      if (pWrd == NULL)	/* Badly formed section line */
113 		continue;
114 
115 	      if (section != NULL)
116 		free (section);
117 
118 	      section_size = pWrd - sCfgFileLine;
119 	      section = (char *) malloc (section_size);
120 	      strncpy (section, sCfgFileLine + 1, section_size - 1);
121 	      section[section_size - 1] = '\0';
122 	      continue;
123 	    }
124 
125 	  pWrd = strchr (sCfgFileLine, '=');
126 	  if (pWrd == NULL)
127 	    continue;
128 
129 	  pTmp = strchr (pWrd, '\n');
130 	  if (pTmp != NULL)
131 	    *pTmp = '\0';
132 
133 	  if (config_ar_index < config_ar_size_max)
134 	    {
135 	      config_ar[config_ar_index].section = (char *) strdup (section);
136 
137 	      *pWrd = '\0';
138 	      pTmp = pWrd - 1;
139 	      while (*pTmp == '\t' || *pTmp == ' ')
140 		*(pTmp--) = '\0';
141 	      config_ar[config_ar_index].variable =
142 		(char *) strdup (sCfgFileLine);
143 
144 	      while (*pWrd == '\t' || *pWrd == ' ')
145 		pWrd++;
146 
147 	      config_ar[config_ar_index].value = (char *) strdup (pWrd + 1);
148 
149 	      config_ar_index++;
150 	    }
151 
152 	}
153       while (pRet != NULL);
154 
155       fclose (FCfgFile);
156     }
157 
158   if (section != NULL)
159     free (section);
160 
161   qsort (config_ar, config_ar_index, sizeof (config_var), config_var_cmp);
162 
163   return 1;
164 }
165 
166 
167 void
dispose_config(void)168 dispose_config (void)
169 {
170   int index;
171 
172   for (index = 0; index < config_ar_index; index++)
173     {
174       free (config_ar[index].section);
175       free (config_ar[index].variable);
176       free (config_ar[index].value);
177     }
178 
179   free (config_ar);
180 }
181 
182 
183 char *
get_config_var(char * section,char * variable)184 get_config_var (char *section, char *variable)
185 {
186   config_var key, *result;
187 
188   key.section = section;
189   key.variable = variable;
190 
191   result =
192     bsearch (&key, config_ar, config_ar_index, sizeof (config_var),
193 	     config_var_cmp);
194 
195   if (result != NULL)
196     {
197       strcpy (temp_result, result->value);
198       return temp_result;
199     }
200 
201   return NULL;
202 }
203 
204 
205 #if !defined(ALLEGRO)
206 
207 // Let's redefine the old allegro parsing function
208 
209 int
get_config_int(char * section,char * keyword,int default_value)210 get_config_int (char *section, char *keyword, int default_value)
211 {
212   char *p = get_config_var (section, keyword);
213   if (p == NULL)
214     return default_value;
215   return atoi (p);
216 }
217 
218 char *
get_config_string(char * section,char * keyword,char * default_value)219 get_config_string (char *section, char *keyword, char *default_value)
220 {
221   char *p = get_config_var (section, keyword);
222 
223   return (p == NULL ? default_value : p);
224 }
225 
226 #endif
227 
228 void
read_joy_mapping(void)229 read_joy_mapping (void)
230 {
231   char tmp_str[10], tmp_str2[10], section_name[10];
232   unsigned char x, y, z;
233   unsigned short temp_val;
234 
235   Log ("--[ JOYPAD MAPPING ]-------------------------------\n");
236   Log ("Loading default values\n");
237 
238   memset (tmp_str, 0, 10);
239 
240   strcpy (section_name, "CONFIG1");
241   for (z = 0; z < 16; z++)
242     {
243       if (z < 10)
244 	section_name[6] = '0' + z;
245       else
246 	section_name[6] = (z - 10) + 'a';
247 
248       Log (" * Looking for section %s\n", section_name);
249 
250       for (x = 0; x < 5; x++)
251 	{			// for each player
252 
253 	  config[z].individual_config[x].joydev = 0;
254 	  strcpy (tmp_str2, "joydev1");
255 	  tmp_str2[6] = '0' + x;
256 
257 	  strncpy (tmp_str, get_config_string (section_name, tmp_str2, "0"),
258 		   10);
259 	  config[z].individual_config[x].joydev = atoi (tmp_str);
260 
261 	  for (y = 0; y < J_MAX; y++)
262 	    {
263 	      strncpy (tmp_str, joymap_reverse[y], 10);
264 	      tmp_str[strlen (tmp_str) + 1] = 0;
265 	      tmp_str[strlen (tmp_str)] = '0' + x;
266 	      temp_val = get_config_int (section_name, tmp_str, 0xffff);
267 
268 	      if (0xffff != temp_val)
269 	      {
270 	      	config[z].individual_config[x].joy_mapping[y] = temp_val;
271 	      	Log ("    %s set to %d\n", joymap_reverse[y], temp_val);
272 	      }
273 	    }
274 
275 	}
276     }
277 
278   Log ("End of joypad mapping\n\n");
279 }
280 
281 char
set_arg(char nb_arg,const char * val)282 set_arg (char nb_arg, const char *val)
283 {
284 
285   if (!val)
286     {
287 #ifndef FINAL_RELEASE
288       fprintf (stderr, "No value for %c arg\n", nb_arg);
289 #endif
290       Log ("No value for arg %c\n", nb_arg);
291       return 1;
292     }
293 
294   switch (nb_arg)
295     {
296     case 'a':
297       option.want_fullscreen_aspect = min (1, max (0, atoi (val)));
298       Log ("Fullscreen aspect mode set to %d\n",
299 	   option.want_fullscreen_aspect);
300       return 0;
301 
302     case 'c':
303       CD_emulation = atoi (val);
304       Log ("CD emulation set to %d\n", CD_emulation);
305       return 0;
306 
307     case 'd':
308       debug_on_beginning = atoi (val);
309       Log ("Debug on beginning set to %d\n", debug_on_beginning);
310       return 0;
311 
312     case 'e':
313       use_eagle = atoi (val);
314       Log ("Eagle mode set to %d\n", use_eagle);
315       return 0;
316 
317     case 'f':
318       option.want_fullscreen = min (1, max (0, atoi (val)));
319       Log ("Start in fullscreen mode set to %d\n", option.want_fullscreen);
320       return 0;
321 
322     case 'i':
323       strcpy (ISO_filename, val);
324       Log ("ISO filename is %s\n", ISO_filename);
325       return 0;
326 
327     case 'm':
328       minimum_bios_hooking = atoi (val);
329       Log ("Minimum Bios hooking set to %d\n", minimum_bios_hooking);
330       return 0;
331 
332     case 'o':
333       option.want_hardware_scaling = min (1, max (0, atoi (val)));
334       Log ("Hardware scaling %srequested.\n",
335 	   option.want_hardware_scaling ? "" : "not ");
336       return 0;
337 
338 #if defined(ENABLE_NETPLAY)
339     case 'n':
340 #warning hardcoding of netplay protocol
341 /*       option.want_netplay = LAN_PROTOCOL; */
342       option.want_netplay = INTERNET_PROTOCOL;
343       strncpy(option.server_hostname, val, sizeof(option.server_hostname));
344       Log ("Netplay mode enabled\nServer hostname set to %s\n",
345 	   option.server_hostname);
346       return 0;
347 #endif // NETPLAY
348 
349     case 's':
350       option.want_stereo = min (1, max (0, atoi (val)));
351       Log ("Stereo mode set to %d\n", option.want_stereo);
352       return 0;
353     case 'S':
354       use_scanline = min (1, max (0, atoi (val)));
355       Log ("Scanline mode set to %d\n", use_scanline);
356       return 0;
357     case 'u':
358       US_encoded_card = atoi (val);
359       Log ("US Card encoding set to %d\n", US_encoded_card);
360       return 0;
361 #if defined(ALLEGRO)
362     case 'v':
363       vmode = atoi (val);
364       Log ("Video mode set to %d\n", vmode);
365       return 0;
366 #endif
367     case 't':
368       nb_max_track = atoi (val);
369       Log ("Number of tracks set to %d\n", nb_max_track);
370       return 0;
371     case 'w':
372       option.window_size = max (1, min (4, atoi (val)));
373       Log ("Window size set to %d\n", option.window_size);
374       return 0;
375 
376     default:
377 #ifndef FINAL_RELEASE
378       fprintf (stderr, "Unrecognized option : %c\n", nb_arg);
379 #endif
380       Log ("Unrecognize option : %c\n", nb_arg);
381       return 1;
382     }
383 }
384 
385 #if !defined(WIN32) && !defined(SOLARIS)
386 
387 //! program header for GNU argp function
388 const char *argp_program_version = "Hu-Go! 2.12";
389 
390 //! bug report address for GNU argp function
391 const char *argp_program_bug_address = "<zeograd@zeograd.com>";
392 
393 //! Program documentation
394 static char doc[] =
395   "hugo -- a program to play pc engine games (roms, cds and various kind of dumps)";
396 
397 //! A description of the arguments we accept
398 static char args_doc[] = "<rom filename> <BRAM filename>";
399 
400 //! The options we understand
401 static struct argp_option options[] = {
402   {"aspect-ratio", 'a', "0/1", OPTION_ARG_OPTIONAL,
403    "Keep aspect ratio of pc engine in fullscreen mode (default is 0)"},
404   {"cd-emulation", 'c', "<CD emulation level>", 0,
405    "CD emulation mode (default is 0, rom only)"},
406   {"debug-startup", 'd', "0/1", OPTION_ARG_OPTIONAL,
407    "Launch debugger on startup (default is 0)"},
408   {"eagle", 'e', "0/1", OPTION_ARG_OPTIONAL,
409    "Use eagle mode for rendering, if available (default is 0)"},
410   {"fullscreen", 'f', "0/1", OPTION_ARG_OPTIONAL,
411    "Start game in fullscreen (default is 0)"},
412   {"cd-device", 'i', "<CD device>", 0,
413    "CD device to use (if CD emulation mode = 1, default is /dev/cdrom)"},
414   {"no-bios-hooking", 'm', "0/1", OPTION_ARG_OPTIONAL,
415    "No hard bios hooking (slower but more compatible, default is 0)"},
416   {"overlay", 'o', "0/1", OPTION_ARG_OPTIONAL,
417    "Use hardware scaling mode for rendering, if available (default is 0)"},
418 #if defined(ENABLE_NETPLAY)
419   {"netplay", 'n', "<server ip or hostname>", 0,
420    "Enable Netplay and set server name"},
421 #endif
422   {"stereo", 's', "0/1", OPTION_ARG_OPTIONAL,
423    "Render sound in stereo (default is 0)"},
424   {"scanline", 'S', "0/1", OPTION_ARG_OPTIONAL,
425    "Use scanline mode for rendering, if available (default is 0)"},
426   {"us-decryption", 'u', "0/1", OPTION_ARG_OPTIONAL,
427    "Decrypt roms using the US -> JAP decryption algorythm (default is 0)"},
428   {"tracks-number", 't', "<track number>", 0,
429    "Number of tracks when emulating a single iso (default is 22)"},
430   {"window-size", 'w', "<zoom factor>", 0,
431    "Zoom factor when in windowed mode (Between 1 and 4, default is 1)"},
432   {0}
433 };
434 
435 static error_t
parse_opt(int key,char * arg,struct argp_state * state)436 parse_opt (int key, char *arg, struct argp_state *state)
437 {
438   switch (key)
439     {
440     case 'a':
441       option.want_fullscreen_aspect =
442 	(arg == NULL ? 1 : (min (1, max (0, atoi (arg)))));
443       Log ("Fullscreen aspect mode set to %d\n",
444 	   option.want_fullscreen_aspect);
445       break;
446     case 'c':
447       CD_emulation = atoi (arg);
448       Log ("CD emulation set to %d\n", CD_emulation);
449       break;
450     case 'd':
451       debug_on_beginning = (arg == NULL ? 1 : atoi (arg));
452       Log ("Debug on beginning set to %d\n", debug_on_beginning);
453       break;
454     case 'e':
455       use_eagle = (arg == NULL ? 1 : atoi (arg));
456       Log ("Eagle mode set to %d\n", use_eagle);
457       break;
458     case 'f':
459       option.want_fullscreen =
460 	(arg == NULL ? 1 : min (1, max (0, atoi (arg))));
461       Log ("Start in fullscreen mode set to %d\n", option.want_fullscreen);
462       break;
463     case 'i':
464       strcpy (ISO_filename, arg);
465       Log ("ISO filename is %s\n", ISO_filename);
466       break;
467     case 'm':
468       minimum_bios_hooking = (arg == NULL ? 1 : atoi (arg));
469       Log ("Minimum Bios hooking set to %d\n", minimum_bios_hooking);
470       break;
471     case 'o':
472       option.want_hardware_scaling =
473 	(arg == NULL ? 1 : min (1, max (0, atoi (arg))));
474       Log ("Hardware scaling %srequested.\n",
475 	   option.want_hardware_scaling ? "" : "not ");
476       break;
477 #if defined(ENABLE_NETPLAY)
478     case 'n':
479 /*       option.want_netplay = LAN_PROTOCOL; */
480       option.want_netplay = INTERNET_PROTOCOL;
481       strncpy(option.server_hostname, arg, sizeof(option.server_hostname));
482       Log ("Netplay mode enabled\nServer hostname set to %s\n",
483 	   option.server_hostname);
484       break;
485 #endif // NETPLAY
486     case 's':
487       option.want_stereo = (arg == NULL ? 1 : min (1, max (0, atoi (arg))));
488       Log ("Stereo mode set to %d\n", option.want_stereo);
489       break;
490     case 'S':
491       use_scanline = (arg == NULL ? 1 : min (1, max (0, atoi (arg))));
492       Log ("Scanline mode set to %d\n", use_scanline);
493       break;
494     case 'u':
495       US_encoded_card = (arg == NULL ? 1 : atoi (arg));
496       Log ("US Card encoding set to %d\n", US_encoded_card);
497       break;
498 #if defined(ALLEGRO)
499     case 'v':
500       vmode = atoi (arg);
501       Log ("Video mode set to %d\n", vmode);
502       break;
503 #endif
504     case 't':
505       nb_max_track = atoi (arg);
506       Log ("Number of tracks set to %d\n", nb_max_track);
507       break;
508     case 'w':
509       option.window_size = max (1, min (4, atoi (arg)));
510       Log ("Window size set to %d\n", option.window_size);
511       break;
512     case ARGP_KEY_ARG:
513       if (state->arg_num >= 2)
514 	{
515 	  /* Too many arguments. */
516 	  argp_usage (state);
517 	  break;
518 	}
519 
520       switch (state->arg_num)
521 	{
522 	case 0:
523 	  strcpy (cart_name, arg);
524 	  Log ("Setting card name to %s\n", cart_name);
525 	  {
526 	    int x;
527 	    for (x = 0; x < strlen (cart_name); x++)
528 	      if (cart_name[x] == '\\')
529 		cart_name[x] = '/';
530 	  }
531 	  break;
532 	case 1:
533 	  bmdefault = arg;
534 	  Log ("Setting backup mem file name to %s\n", bmdefault);
535 	  break;
536 	default:
537 	  Log
538 	    ("Internal error when parsing command line, state->arg_num = %d\n",
539 	     state->arg_num);
540 	}
541       break;
542     default:
543       return ARGP_ERR_UNKNOWN;
544     }
545   return 0;
546 }
547 
548 //! Our argp parser
549 static struct argp argp = { options, parse_opt, args_doc, doc };
550 
551 #endif
552 
553 void
parse_commandline(int argc,char ** argv)554 parse_commandline (int argc, char **argv)
555 {
556 #if defined(WIN32) || defined(SOLARIS)
557   char next_arg, i, arg_error = 0;
558 #endif
559 
560   Log ("--[ PARSING COMMAND LINE ]--------------------------\n");
561 
562 #if !defined(WIN32) && !defined(SOLARIS)
563   argp_parse (&argp, argc, argv, 0, 0, &option);
564 #else
565   next_arg = 0;
566   for (i = 1; i < argc; i++)
567     if (!next_arg)
568       {
569 	if (argv[i][0] == '-')
570 	  {
571 	    if (strlen (argv[i]) == 2)
572 	      {
573 		switch (argv[i][1])
574 		  {
575 		  default:
576 		    next_arg = argv[i][1];
577 		    break;
578 		  }
579 	      }
580 	    else
581 	      arg_error |= set_arg (argv[i][1], (char *) &argv[i][2]);
582 	  }
583 	else
584 	  {
585 	    if (!cart_name[0])
586 	      {
587 		strcpy (cart_name, argv[i]);
588 		Log ("Setting card name to %s\n", cart_name);
589 		{
590 		  int x;
591 		  for (x = 0; x < strlen (cart_name); x++)
592 		    if (cart_name[x] == '\\')
593 		      cart_name[x] = '/';
594 		}
595 	      }
596 	    else if (!bmdefault)
597 	      {
598 		Log ("Setting backup mem file name to %s\n", argv[i]);
599 		bmdefault = argv[i];
600 	      }
601 	    else
602 	      {
603 		Log ("Unrecognized option : %s\n", argv[i]);
604 		arg_error = 1;
605 	      };
606 	  }
607       }
608     else
609       {
610 	arg_error |= set_arg (next_arg, argv[i]);
611 	next_arg = 0;
612       }
613 
614   if (next_arg)
615     {
616       Log ("No value for last arg : %c\n", next_arg);
617       next_arg = 0;
618       arg_error = 1;
619     };
620 
621 #endif
622 
623   Log ("End of parsing command line\n");
624 
625   video_driver = 0;
626 
627   if (use_eagle)
628     video_driver = 1;
629   else if (use_scanline)
630     video_driver = 2;
631 }
632 
633 void
parse_INIfile_raw()634 parse_INIfile_raw ()
635 {
636 #ifdef MSDOS
637   char x;
638 #endif
639 
640   Log ("Looking in %s\n", config_file);
641 
642   read_joy_mapping ();
643 
644   strcpy (initial_path, get_config_string ("main", "rom_dir", "."));
645   if ((initial_path[0]) && (initial_path[strlen (initial_path) - 1] != '/')
646       && (initial_path[strlen (initial_path) - 1] != '\\'))
647     strcat (initial_path, "/");
648   // rom_dir setting
649 
650   Log ("Setting initial path to %s\n", initial_path);
651 
652 #if defined(ALLEGRO)
653 
654   strcpy (skin_filename, get_config_string ("main", "skin", "skin_h~1.bmp"));
655   // skin filename to look for
656 
657   Log ("Skin filename set to %s\n", skin_filename);
658 
659 #endif
660 
661   current_config = get_config_int ("main", "config", 0);
662   // choose input config
663 
664   Log ("Setting joypad config number to %d\n", current_config);
665 
666   language = min (get_config_int ("main", "language", 0), NB_LANG - 1);
667   // language setting
668 
669   Log ("Setting language to %d\n", language);
670 
671 #if defined(ALLEGRO)
672   vmode = get_config_int ("main", "vmode", 0);
673   // video mode setting
674 
675   Log ("Setting video mode to %d\n", vmode);
676 
677   static_refresh = get_config_int ("main", "static_refresh", 0);
678   // file selector refreshment
679 
680   Log ("Setting static refresh to %d\n", static_refresh);
681 
682 #endif
683 
684   smode = get_config_int ("main", "smode", -1);
685   // sound mode setting
686 
687   Log ("Setting sound mode to %d\n", smode);
688 
689   use_eagle = get_config_int ("main", "eagle", 0);
690   // do we use EAGLE ?
691 
692   Log ("Setting eagle mode to %d\n", use_eagle);
693 
694   use_scanline = get_config_int ("main", "scanline", 0);
695   // do we use EAGLE ?
696 
697   Log ("Setting scanline mode to %d\n", use_scanline);
698 
699   option.want_snd_freq = get_config_int ("main", "snd_freq", 22050);
700   // frequency of the sound generator
701 
702   Log ("Setting default frequency to %d\n", option.want_snd_freq);
703 
704 #if defined(WIN32)
705   sbuf_size = get_config_int ("main", "buffer_size", 1024);
706 #elif defined(LINUX)
707   sbuf_size = get_config_int ("main", "buffer_size", 512);
708 #else
709   sbuf_size = get_config_int ("main", "buffer_size", 256);
710 #endif
711   // size of the sound buffer
712 
713   Log ("Setting sound buffer size to %d bytes\n", sbuf_size);
714 
715   gamepad_driver = get_config_int ("main", "joy_type", -1);
716 
717   Log ("Setting joy type to %d\n", gamepad_driver);
718 
719   sound_driver = get_config_int ("main", "sound_driver", 1);
720 
721   Log ("Setting sound driver to %d\n", sound_driver);
722 
723 #if defined(ALLEGRO)
724 
725   zip_support_in_fs = get_config_int ("main", "zip_support", 1);
726 
727   Log ("Setting zip support in File Selector to %d\n", zip_support_in_fs);
728 
729 #endif
730 
731   synchro = get_config_int ("main", "limit_fps", 0);
732 
733   Log ("Setting fps limitation to %d\n", synchro);
734 
735   option.want_fullscreen = get_config_int ("main", "start_fullscreen", 0);
736 
737   Log ("Setting start in fullscreen mode to %d\n", option.want_fullscreen);
738 
739   option.want_fullscreen_aspect =
740     get_config_int ("main", "use_fullscreen_aspect", 0);
741 
742   Log ("Setting fullscreen aspect to %d\n", option.want_fullscreen_aspect);
743 
744   option.want_hardware_scaling = get_config_int ("main", "use_overlay", 0);
745   Log ("Setting hardware scaling to %d\n", option.want_hardware_scaling);
746 
747   option.want_stereo = get_config_int ("main", "stereo_sound", 0);
748 
749   Log ("Setting stereo sound to %d\n", option.want_stereo);
750 
751   option.window_size = get_config_int ("main", "window_size", 1);
752 
753   Log ("Setting window size to %d\n", option.window_size);
754 
755   option.fullscreen_width = get_config_int ("main", "fullscreen_width", 640);
756 
757   Log ("Setting preferred fullscreen width to %d\n", option.fullscreen_width);
758 
759   option.fullscreen_height =
760     get_config_int ("main", "fullscreen_height", 480);
761 
762   Log ("Setting preferred fullscreen height to %d\n",
763        option.fullscreen_height);
764 
765   option.wanted_hardware_format =
766     get_config_int ("main", "hardware_format", 0);
767 
768   Log ("Setting wanted hardware format to %x\n",
769        option.wanted_hardware_format);
770 
771 #ifdef MSDOS
772 
773   x = get_config_int ("main", "cd_driver", 0);
774 
775   if (x)
776     {
777       osd_cd_driver = aspi_driver;
778       Log ("Setting cd driver to ASPI\n");
779     }
780   else
781     {
782       osd_cd_driver = mscdex_driver;
783       Log ("Setting cd driver to MSCDEX\n");
784     }
785 
786 #endif
787 
788   minimum_bios_hooking = get_config_int ("main", "minimum_bios_hooking", 0);
789 
790   Log ("Minimum Bios hooking set to %d\n", minimum_bios_hooking);
791 
792   strcpy (cdsystem_path, get_config_string ("main", "cdsystem_path", ""));
793 
794   Log ("CD system path set to %d\n", cdsystem_path);
795 
796   strcpy (ISO_filename, get_config_string ("main", "cd_path", ""));
797 
798   Log ("CD path set to %s\n", ISO_filename);
799 
800   option.want_arcade_card_emulation =
801     get_config_int ("main", "arcade_card", 1);
802 
803   Log ("Arcade card emulation set to %d\n",
804        option.want_arcade_card_emulation);
805 
806   option.want_supergraphx_emulation =
807     get_config_int ("main", "supergraphx", 1);
808 
809   Log ("SuperGraphX emulation set to %d\n",
810        option.want_supergraphx_emulation);
811 
812   option.want_television_size_emulation =
813     get_config_int ("main", "tv_size", 0);
814 
815   Log ("Limiting graphics size to emulate tv output set to %d\n",
816        option.want_television_size_emulation);
817 
818   Log ("End of parsing INI file\n\n");
819 }
820 
821 void
parse_INIfile()822 parse_INIfile ()
823 {
824   Log ("--[ PARSING INI FILE ]------------------------------\n");
825 
826 #ifndef LINUX
827   sprintf (config_file, "%shugo.ini", short_exe_name);
828 #else
829   {
830 
831     char tmp_home[256];
832     FILE *f;
833 
834     sprintf (tmp_home, "%shugo.ini", short_exe_name);
835 
836     f = fopen (tmp_home, "rb");
837 
838     if (f != NULL)
839       {
840 	strcpy (config_file, tmp_home);
841 	fclose (f);
842       }
843     else
844       strcpy (config_file, "/etc/hugo.ini");
845   }
846 #endif
847 
848 
849   init_config ();
850 
851   parse_INIfile_raw ();
852 
853   dispose_config ();
854 
855 }
856 
857 void
set_config_var_str(char * section,char * name,char * value)858 set_config_var_str (char *section, char *name, char *value)
859 {
860   config_var key, *result;
861 
862 #if !defined(FINAL_RELEASE)
863   printf ("Setting [%s] %s to %s\n", section, name, value);
864 #endif
865 
866   key.section = section;
867   key.variable = name;
868 
869   result =
870     bsearch (&key, config_ar, config_ar_index, sizeof (config_var),
871 	     config_var_cmp);
872 
873   if (result != NULL)
874     {
875       free (result->value);
876       result->value = strdup (value);
877       return;
878     }
879 
880   if (config_ar_index < config_ar_size_max)
881     {
882 
883       config_ar[config_ar_index].section = strdup (section);
884       config_ar[config_ar_index].variable = strdup (name);
885       config_ar[config_ar_index].value = strdup (value);
886 
887       config_ar_index++;
888 
889     }
890   else
891     {
892 
893       Log ("Couldn't set [%s]%s to %sn bit enough internal space\n", section,
894 	   name, value);
895 
896     }
897 }
898 
899 void
set_config_var_int(char * section,char * name,int value)900 set_config_var_int (char *section, char *name, int value)
901 {
902   char temp_string[10];
903 
904   snprintf (temp_string, 10, "%d", value);
905 
906   set_config_var_str (section, name, temp_string);
907 }
908 
909 void
dump_config(char * filename)910 dump_config (char *filename)
911 {
912   FILE *output_file;
913   int local_index;
914   char *last_section_name;
915 
916   last_section_name = "";
917 
918   output_file = fopen (filename, "wt");
919   if (output_file == NULL)
920     {
921       Log ("Couldn't save configuration to %s\n", filename);
922       return;
923     }
924 
925   Log ("Saving %d entries in the configuration file\n", config_ar_index);
926 
927   for (local_index = 0; local_index < config_ar_index; local_index++)
928     {
929       if (strcmp (last_section_name, config_ar[local_index].section))
930 	{
931 	  last_section_name = config_ar[local_index].section;
932 	  fprintf (output_file, "[%s]\n", last_section_name);
933 	}
934       fprintf (output_file, "%s=%s\n", config_ar[local_index].variable,
935 	       config_ar[local_index].value);
936     }
937 
938   fclose (output_file);
939 
940 }
941 
942 //! makes the configuration changes permanent
943 void
save_config(void)944 save_config (void)
945 {
946 
947   char config_name[PATH_MAX];
948   unsigned char input_config_number, input_config_button, input_config_player;
949 
950   // Reads all variables in the ini file
951   init_config ();
952 
953   set_config_var_str ("main", "rom_dir", initial_path);
954   set_config_var_int ("main", "config", current_config);
955   set_config_var_int ("main", "language", language);
956   set_config_var_int ("main", "smode", smode);
957   set_config_var_int ("main", "eagle", use_eagle);
958   set_config_var_int ("main", "scanline", use_scanline);
959   set_config_var_int ("main", "snd_freq", option.want_snd_freq);
960   set_config_var_int ("main", "buffer_size", sbuf_size);
961   set_config_var_int ("main", "joy_type", gamepad_driver);
962   set_config_var_int ("main", "sound_driver", sound_driver);
963   set_config_var_int ("main", "start_fullscreen", option.want_fullscreen);
964   set_config_var_int ("main", "use_fullscreen_aspect",
965 		      option.want_fullscreen_aspect);
966   set_config_var_int ("main", "use_overlay", option.want_hardware_scaling);
967   set_config_var_int ("main", "minimum_bios_hooking", minimum_bios_hooking);
968   set_config_var_str ("main", "cdsystem_path", cdsystem_path);
969   set_config_var_str ("main", "cd_path", ISO_filename);
970   set_config_var_int ("main", "stereo_sound", option.want_stereo);
971   set_config_var_int ("main", "fullscreen_width", option.fullscreen_width);
972   set_config_var_int ("main", "fullscreen_height", option.fullscreen_height);
973   set_config_var_int ("main", "window_size", option.window_size);
974   set_config_var_int ("main", "arcade_card",
975 		      option.want_arcade_card_emulation);
976   set_config_var_int ("main", "supergraphx",
977 		      option.want_supergraphx_emulation);
978   set_config_var_int ("main", "tv_size",
979 		      option.want_television_size_emulation);
980   set_config_var_int ("main", "hardware_format",
981 		      option.wanted_hardware_format);
982 
983 	// For each input configuration ...
984   for (input_config_number = 0; input_config_number < 16;
985        input_config_number++)
986     {
987       char section_name[] = "CONFIG0";
988 
989       if (input_config_number < 10)
990 	section_name[6] = '0' + input_config_number;
991       else
992 	section_name[6] = 'a' + input_config_number - 10;
993 
994 			// For each player configuration ...
995       for (input_config_player = 0; input_config_player < 5;
996 	   input_config_player++)
997 	{
998 	  char input_name[8];
999 	  char input_type_name[10];
1000 
1001 		// If there's a joypad, dump it
1002 		if (config[input_config_number].individual_config[input_config_player].joydev)
1003 		{
1004 		  snprintf (input_name, 8, "joydev%1d", input_config_player);
1005 		  snprintf (input_type_name, 10, "%d",
1006 			    config[input_config_number].individual_config[input_config_player].joydev);
1007 		  set_config_var_str (section_name, input_name, input_type_name);
1008 		}
1009 
1010 		// For each button configuration ...
1011 	  for (input_config_button = 0; input_config_button < J_MAX;
1012 	       input_config_button++)
1013 	    {
1014 	      char temp_joy_str[15];
1015 
1016 	      // Skip empty entries in joypad mapping
1017 	      if (config[input_config_number].individual_config[input_config_player].
1018 		  joy_mapping[input_config_button] == default_joy_mapping[input_config_button])
1019 			continue;
1020 
1021 			if ((0 == config[input_config_number].individual_config[input_config_player].joydev)
1022 				&& (input_config_button >= J_PAD_START))
1023 			{
1024 				// If it is a joystick button/axis and it is disabled, we skip it
1025 				continue;
1026 			}
1027 
1028 	      snprintf (temp_joy_str, 15, "%s%1d",
1029 			joymap_reverse[input_config_button], input_config_player);
1030 
1031 	      set_config_var_int (section_name, temp_joy_str,
1032 				  config[input_config_number].individual_config[input_config_player].
1033 				  joy_mapping[input_config_button]);
1034 	    }
1035 	}
1036     }
1037 
1038   // Sorts the configuration array
1039   qsort (config_ar, config_ar_index, sizeof (config_var), config_var_cmp);
1040 
1041   // Dump the configuration into a file
1042   sprintf (config_name, "%shugo.ini", short_exe_name);
1043   dump_config (config_name);
1044 
1045   dispose_config ();
1046 
1047 }
1048