Xemu [doxygen]  hyppo 0a42be3a057156924bc1b626a687bd6e27349c45 @ Sat 19 Mar 02:15:11 CET 2022
configuration.c
Go to the documentation of this file.
1 /* Xep128: Minimalistic Enterprise-128 emulator with focus on "exotic" hardware
2  Copyright (C)2016 LGB (Gábor Lénárt) <lgblgblgb@gmail.com>
3  http://xep128.lgb.hu/
4 
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
18 
19 
20 #include "xep128.h"
21 #include "configuration.h"
22 #include "console.h"
23 #include "keyboard_mapping.h"
24 
25 #include <SDL.h>
26 #include <unistd.h>
27 #ifdef __EMSCRIPTEN__
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #endif
31 
32 
38 };
39 
41  const char *name;
42  const int type;
43  const char *defval;
44  const int subopt;
45  const char *help;
46 };
47 
49  const struct configOption_st *opt;
50  int subopt;
51  char *value;
52 };
53 
54 
55 #define DEBUGFILE_OPT "debug"
56 
57 /* Default keyboard mapping can be found in keyboard_mapping.c */
58 static const struct configOption_st configOptions[] = {
59  { "audio", CONFITEM_BOOL, "0", 0, "Enable audio output" },
60  { "console", CONFITEM_BOOL, "0", 0, "Keep (1) console window open (or give console prompt on STDIN on Linux by default)" },
61  { DEBUGFILE_OPT,CONFITEM_STR, "none", 0, "Enable debug messages written to a specified file" },
62  { "ddn", CONFITEM_STR, "none", 0, "Default device name (none = not to set)" },
63  { "filedir", CONFITEM_STR, "@files", 0, "Default directory for FILE: device" },
64  { "fullscreen", CONFITEM_BOOL, "0", 0, "Start in full screen" },
65  { "mousemode", CONFITEM_INT, "1", 0, "Set mouse mode, 1-3 = J-column 2,4,8 bytes and 4-6 the same for K-column" },
66  { "primo", CONFITEM_STR, "none", 0, "Start in Primo emulator mode (if not \"none\")" },
67  { "printfile", CONFITEM_STR, PRINT_OUT_FN, 0, "Printing into this file" },
68  { "ram", CONFITEM_STR, "128", 0, "RAM size in Kbytes (decimal) or segment specification(s) prefixed with @ in hex (VRAM is always assumed), like: @C0-CF,E0,E3-E7" },
69  { "rom", CONFITEM_STR, NULL, 1, "ROM image, format is \"rom@xx=filename\" (xx=start segment in hex), use rom@00 for EXOS or combined ROM set" },
70  { "sdimg", CONFITEM_STR, SDCARD_IMG_FN, 0, "SD-card disk image (VHD) file name/path" },
71  { "sdl", CONFITEM_STR, "auto", 0, "Sets SDL specific option(s) including rendering related stuffs" },
72  { "skiplogo", CONFITEM_INT, "0", 0, "Disables (1) Enterprise logo on start-up via XEP ROM" },
73  { "snapshot", CONFITEM_STR, "none", 0, "Load and use ep128emu snapshot" },
74  { "wdimg", CONFITEM_STR, "none", 0, "EXDOS WD disk image file name/path" },
75  { "xeprom", CONFITEM_INT, "1", 0, "Enables XEP internal ROM (non-zero value), otherwise disable" },
76  /* should be the last on the list, as this is handled specially not in the config storage for real */
77  { "epkey", CONFITEM_STR, NULL, 1, "Define a given EP/emu key, format epkey@xy=SDLname, where x/y are row/col in hex or spec code (ie screenshot, etc)." },
78  { NULL, 0, NULL, 0, NULL }
79 };
80 
81 
82 static struct configSetting_st *config = NULL;
83 static int config_size = 0;
85 char current_directory[PATH_MAX + 1];
87 FILE *debug_fp = NULL;
88 
89 
90 
91 static const char *disclaimer =
92  "LICENSE: " WINDOW_TITLE " is a GNU/GPL version 2 (or later) software. <http://gnu.org/licenses/gpl.html>" NL
93  "LICENSE: This is free software; you are free to change and redistribute it." NL
94  "LICENSE: There is NO WARRANTY, to the extent permitted by law.";
95 
96 
97 
98 void forget_emu_file ( const char *path )
99 {
100 #ifdef __EMSCRIPTEN__
101  DEBUGPRINT("FILE: trying to delete file \"%s\" as used only once, return code: %d" NL,
102  path,
103  unlink(path)
104  );
105 #endif
106 }
107 
108 
109 FILE *open_emu_file ( const char *name, const char *mode, char *pathbuffer )
110 {
111  const char *name_used = name;
112  const char *policy = "guessing";
113  const char *prefixes[] = {
114 #ifdef __EMSCRIPTEN__
115  "/files/",
116 #else
117  current_directory, // try in the current directory first
118  app_pref_path, // try at pref path (user writable area)
119  app_base_path, // try at base path (where executable is)
120 #ifndef _WIN32
121  DATADIR "/", // try in the DATADIR, it makes sense on UNIX like sys
122 #endif
123 #endif
124  NULL
125  };
126  int a = 0;
127  FILE *f;
128  // try to detect absolute path, Win32 related part tries to detect the possibility of X:\... syntax
129  if (
130  name[0] == DIRSEP[0]
131 #ifdef _WIN32
132  || (strlen(name) > 3 && name[1] == ':' && name[2] == DIRSEP[0])
133 #endif
134  ) {
135  prefixes[0] = "";
136  prefixes[1] = NULL;
137  policy = "absolute";
138  } else if (name[0] == '@') { // @ means user preference directory related path names
139 #ifdef __EMSCRIPTEN__
140  prefixes[0] = "/files/";
141 #else
142  prefixes[0] = app_pref_path;
143 #endif
144  prefixes[1] = NULL;
145  name_used = name + 1;
146  policy = "pref-dir";
147  }
148  while (prefixes[a] != NULL)
149  if (strcmp(prefixes[a], "?")) {
150  snprintf(pathbuffer, PATH_MAX, "%s%s", prefixes[a], name_used);
151  DEBUGPRINT("OPEN: trying file \"%s\" [mode: %s] as path \"%s\" [%s]: ",
152  name, mode, pathbuffer, policy
153  );
154  f = fopen(pathbuffer, mode);
155  if (f == NULL) {
156  a++;
157  DEBUGPRINT("*FAILED*: %s" NL, ERRSTR());
158  } else {
159  DEBUGPRINT("(fd=%d) OK" NL, fileno(f));
160  return f;
161  }
162  }
163  DEBUGPRINT("OPEN: no file could be open for \"%s\"" NL, name);
164  strcpy(pathbuffer, name);
165  return NULL;
166 }
167 
168 
169 
170 static const struct configOption_st *search_opt ( const char *name, int subopt )
171 {
172  const struct configOption_st *opt = configOptions;
173  while (opt->name && strcasecmp(name, opt->name))
174  opt++;
175  if (!opt->name)
176  return NULL;
177  if ((subopt >= 0 && !opt->subopt) || (subopt < 0 && opt->subopt))
178  return NULL;
179  return opt;
180 }
181 
182 
183 
184 static struct configSetting_st *search_setting ( const struct configOption_st *opt, int subopt )
185 {
186  struct configSetting_st *st = config;
187  int n = config_size;
188  while (n--) {
189  if (st->opt == opt && st->subopt == subopt)
190  return st;
191  st++;
192  }
193  return NULL;
194 }
195 
196 
197 
198 int config_set ( const char *name, int subopt, const char *value )
199 {
200  struct configSetting_st *st;
201  const struct configOption_st *opt = search_opt(name, subopt);
202  if (!opt)
203  return 1;
204  st = search_setting(opt, subopt);
205  if (st) {
206  free(st->value);
207  } else {
208  config = realloc(config, (config_size + 1) * sizeof(struct configOption_st));
209  CHECK_MALLOC(config);
210  st = config + (config_size++);
211  st->opt = opt;
212  st->subopt = subopt;
213  }
214  st->value = strdup(value);
215  CHECK_MALLOC(st->value);
216  return 0;
217 }
218 
219 
220 
221 static void config_set_internal ( const char *name, int subopt, const char *value )
222 {
223  if (config_set(name, subopt, value))
224  FATAL("Internal built-in configuration error: config_set_internal(\"%s\",%d,\"%s\")", name, subopt, value);
225 }
226 
227 
228 
229 static int config_set_user ( const char *name, int subopt, const char *value, int gui_error )
230 {
231  if (!strcmp(name, "epkey")) {
233  if (gui_error)
234  ERROR_WINDOW("Invalid SDL PC key scan code name: %s", value);
235  else
236  fprintf(stderr, "ERROR: Invalid SDL PC key scan code name: %s" NL, value);
237  return 1;
238  }
239  return 0;
240  }
241  return config_set(name, subopt, value);
242 }
243 
244 
245 /* Emulator should call this function to query a value of an option.
246  Note: for frequent usage, time critical situation, value should be asked ONCE,
247  and then should be stored and used to avoid looking it up again and again.
248  Caller must be careful, the casting of "value" is based on the config key type,
249  you should give pointer of the right type! You MUST NOT modify the returned
250  entity pointed by value!!
251  In case of a non-existent key query, program will exit.
252  value = NULL can be passed to *test* the existence of a setting (without exiting in case of failure)
253  Returned pointer (if not NULL) can be used to re-fetch the value with function config_getopt_pointed() */
254 void *config_getopt ( const char *name, const int subopt, void *value )
255 {
256  struct configSetting_st *st;
257  const struct configOption_st *opt = search_opt(name, subopt);
258  if (!opt) {
259  if (!value)
260  return NULL;
261  FATAL("config_getopt(\"%s\",%d) failed, no optname found", name, subopt);
262  }
263  st = search_setting(opt, subopt);
264  if (!st) {
265  if (!value)
266  return NULL;
267  FATAL("config_getopt(\"%s\",%d) failed, no setting found", name, subopt);
268  }
269  if (value)
271  return st;
272 }
273 
274 
275 void config_getopt_pointed ( void *st_in, void *value )
276 {
277  struct configSetting_st *st = st_in;
278  switch (st->opt->type) {
279  case CONFITEM_FLOAT:
280  *(double*)value = atof(st->value);
281  break;
282  case CONFITEM_BOOL:
283  case CONFITEM_INT:
284  *(int*)value = atoi(st->value);
285  break;
286  case CONFITEM_STR:
287  *(char**)value = st->value;
288  break;
289  default:
290  FATAL("config_getopt(\"%s\",%d) failed, unknown config item type %d", st->opt->name, st->subopt, st->opt->type);
291  break;
292  }
293 }
294 
295 
296 
297 static void str_rstrip ( char *p )
298 {
299  char *e = p + strlen(p) - 1;
300  while (e >= p && (*e == '\r' || *e == '\n' || *e == '\t' || *e == ' '))
301  *(e--) = '\0';
302 }
303 
304 
305 
306 static int parse_cfgfile_line ( char *buffer, char **key, char **value )
307 {
308  char *p;
309  *key = *value = NULL;
310  while (*buffer == ' ' || *buffer == '\t') buffer++;
311  p = strchr(buffer, '#');
312  if (p) *p = 0;
313  str_rstrip(buffer);
314  if (!*buffer) return 0; // empty line, or only comment in this line
315  p = strchr(buffer, '=');
316  if (!p) return 1;
317  *(p++) = 0;
318  while (*p == ' ' || *p == '\t') p++;
319  *value = p;
320  *key = buffer;
321  //str_rstrip(p);
322  str_rstrip(buffer);
323  return !*p || !*buffer;
324 }
325 
326 
327 
328 static int separate_key ( const char *buffer, char *key )
329 {
330  int ret;
331  char *p = strchr(buffer, '@');
332  if (!p) {
333  strcpy(key, buffer);
334  return -1;
335  }
336  memcpy(key, buffer, p - buffer);
337  key[p - buffer] = 0;
338  p++;
339  if (strlen(p) != 2)
340  return -2;
341  if (sscanf(p, "%02x", &ret) != 1)
342  return -2;
343  return ret;
344 }
345 
346 
347 
348 static int load_config_file_stream ( FILE *f, const char *name )
349 {
350  char buffer[1024];
351  int lineno = 1;
352  while (fgets(buffer, sizeof(buffer), f)) {
353  char *key, *val;
354  char orig_line[sizeof(buffer)];
355  if (strlen(buffer) > sizeof(buffer) - 4) {
356  ERROR_WINDOW("Config file %s has too long line at lineno %d", name, lineno);
357  return 1;
358  }
359  strcpy(orig_line, buffer);
360  str_rstrip(orig_line);
361  if (parse_cfgfile_line(buffer, &key, &val)) {
362  ERROR_WINDOW("Config file %s has syntax error at lineno %d line \"%s\"", name, lineno, orig_line);
363  return 1;
364  }
365  if (key && val) {
366  char cleankey[sizeof(buffer)];
367  int subopt = separate_key(buffer, cleankey);
368  //str_rstrip(buffer);
369  //printf("[%d][%s]%s = %s\n", lineno, orig_line, key, val);
370  DEBUG("CONFIG: FILE: %s@%d = %s" NL, cleankey, subopt, val);
371  if (subopt < -1 || config_set_user(cleankey, subopt, val, 1)) {
372  ERROR_WINDOW("Config file %s has invalid option key/value at lineno %d: %s = %s", name, lineno, key, val);
373  return 1;
374  }
375  }
376  lineno++;
377  }
378  return 0;
379 }
380 
381 
382 
383 /* Must be already sure, that even number of arguments exist in the command line */
384 static int parse_command_line ( int argc , char **argv )
385 {
386  while (argc) {
387  char cleankey[1024];
388  int subopt;
389  if (argv[0][0] != '-') {
390  fprintf(stderr, "FATAL: Command line error: option name should begin with '-' for option: %s" NL, argv[0]);
391  return 1;
392  }
393  subopt = separate_key(argv[0] + 1, cleankey);
394  DEBUG("CONFIG: CLI: %s@%d = %s" NL, cleankey, subopt, argv[1]);
395  if (subopt < -1 || config_set_user(cleankey, subopt, argv[1], 0)) {
396  fprintf(stderr, "FATAL: Command line error: invalid key/value %s %s" NL, argv[0], argv[1]);
397  return 1;
398  }
399  argv += 2;
400  argc -= 2;
401  }
402  return 0;
403 }
404 
405 
406 
407 static void dump_config ( FILE *fp )
408 {
409  const struct configOption_st *opt = configOptions;
410  struct configSetting_st *st = config;
411  int n = config_size;
412  /* header */
413  fprintf(fp,
414  "# Xep128 default built-in configuration as a sample / template file." NL
415  "# Feel free to customize for your needs, and rename to config to be loaded automatically." NL
416  "# Delete this _template_ file (not the one renamed as config) Xep128 to allow to re-create" NL
417  "# in case of some new options with a new version." NL NL
418  "# Generic, simple options" NL NL
419  );
420  /* dump options without subopt */
421  while (n--) {
422  if (st->subopt == -1)
423  fprintf(fp, "%s = %s\t# %s" NL, st->opt->name, st->value, st->opt->help);
424  st++;
425  }
426  /* dump options with subopt */
427  while (opt->name) {
428  if (opt->subopt) {
429  /*char *keydesc = NULL;
430  if (!strcmp(opt->name, "epkey"))
431  keydesc = "\t# ";*/
432  n = config_size;
433  st = config;
434  fprintf(fp, NL "# %s" NL NL, opt->help);
435  while (n--) {
436  if (st->opt == opt)
437  fprintf(fp, "%s@%02x = %s" NL,
438  opt->name, st->subopt, st->value
439  );
440  st++;
441  }
442  }
443  opt++;
444  }
445  // dump the keyboard mapping ...
446  keymap_dump_config(fp);
447 }
448 
449 
450 
451 static void save_sample_config ( const char *name )
452 {
453 #ifdef __EMSCRIPTEN__
454  DEBUGPRINT("CONFIG: no configuration is saved in case of emscripten." NL);
455 #else
456  char path[PATH_MAX + 1];
457  FILE *f = open_emu_file(name, "r", path);
458  if (f) {
459  fclose(f);
460  DEBUGPRINT("CONFIG: sample configuration %s (%s) already exists, skipping to create." NL, name, path);
461  return;
462  }
463  f = open_emu_file(name, "w", path);
464  if (f) {
465  dump_config(f);
466  fclose(f);
467  INFO_WINDOW("Note: created sample config file %s", path);
468  } else
469  INFO_WINDOW("Note: cannot create sample config file %s", path);
470 #endif
471 }
472 
473 
474 
475 #if !SDL_VERSION_ATLEAST(2, 0, 4)
476 # error "We need SDL2 version 2.0.4 at least!"
477 #endif
478 
479 
480 
481 int is_help_request_option ( const char *opt )
482 {
483  char c = *(opt++);
484  if ((
485  c == '-' || c == '/'
486  ) && (
487  !strcasecmp(opt, "h") || !strcasecmp(opt, "-h") ||
488  !strcasecmp(opt, "help") || !strcasecmp(opt, "-help") ||
489  !strcasecmp(opt, "?") || !strcasecmp(opt, "-?")
490  )) {
491  if (c == '/')
492  ERROR_WINDOW("Plesse note that you MUST use - instead of / with options!\nSo use -h or -? instead of ugly /h or /?");
493  return 1;
494  }
495  return 0;
496 }
497 
498 
499 
500 static int get_path_info ( void )
501 {
502  FILE *f;
503  char buffer[PATH_MAX + 1];
504  app_pref_path = NULL; // to signal that it's not got yet
505  /* Get base path (where executable is */
506 #ifdef __EMSCRIPTEN__
507  app_base_path = strdup("/files/");
508 #else
509  app_base_path = SDL_GetBasePath();
510  if (!app_base_path) {
511  ERROR_WINDOW("Cannot query base directory: %s", ERRSTR());
512  return 1;
513  }
514 #endif
515  /* Check for pref dir override file in the same directory where executable is (base path) */
516  snprintf(buffer, sizeof buffer, "%s%cxep128.dir", app_base_path, DIRSEP[0]);
517  f = fopen(buffer, "r");
518  if (f) {
519  char *p = fgets(buffer, sizeof buffer, f);
520  fclose(f);
521  if (p) {
522  p = strchr(buffer, 13);
523  if (p)
524  *p = 0;
525  p = strchr(buffer, 10);
526  if (p)
527  *p = 0;
528  if (*buffer == '.')
529  app_pref_path = strdup(app_base_path);
530  else if (*buffer)
531  app_pref_path = strdup(buffer);
532  }
533  }
534  /* Pref dir stuff */
535  if (app_pref_path) {
536  printf("CONFIG: Overriding pref path to: %s" NL, app_pref_path);
537  } else {
538 #ifdef __EMSCRIPTEN__
539  app_pref_path = strdup("/files/");
540 #else
541  app_pref_path = SDL_GetPrefPath("nemesys.lgb", "xep128");
542  if (!app_pref_path) {
543  ERROR_WINDOW("Cannot query preferences directory: %s", ERRSTR());
544  return 1;
545  }
546 #endif
547  }
548  /* Get current directory */
549 #ifdef __EMSCRIPTEN__
550  mkdir("/files", 0777);
551  chdir("/files");
552 #endif
553  if (getcwd(current_directory, sizeof current_directory) == NULL) {
554  ERROR_WINDOW("Cannot query current directory: %s", ERRSTR());
555  return 1;
556  }
557  strcat(current_directory, DIRSEP);
558  return 0;
559 }
560 
561 
562 
563 
564 
565 int config_init ( int argc, char **argv )
566 {
567  const char *config_name = DEFAULT_CONFIG_FILE; // name of the used config file, can be overwritten via CLI
568  const struct configOption_st *opt;
569  const char *exe = argv[0];
570  int default_config = 1;
571  int testparsing = 0;
572  argc--; argv++;
573 #ifdef __EMSCRIPTEN__
574  exe = strdup("/files/emscripten-virtual-executable");
575 #endif
576 #ifdef _WIN32
578 #endif
579  SDL_VERSION(&sdlver_compiled);
580  SDL_GetVersion(&sdlver_linked);
581  if (sdlver_linked.major < 2 || (sdlver_linked.minor == 0 && sdlver_linked.patch < 4)) {
582  ERROR_WINDOW("Too old SDL library linked, at least version 2.0.4 is required.");
583  return 1;
584  }
585  /* SDL info on paths */
586  if (get_path_info())
587  return 1;
588  /* ugly hack: pre-parse comand line to find debug statement (to be worse, it does not handle single argument options too well ... */
589 #ifdef DISABLE_DEBUG
590  printf("DEBUG: disabled at compilation time." NL);
591 #else
592  while (testparsing < argc) {
593  if (!strcmp(argv[testparsing], "-" DEBUGFILE_OPT) && testparsing != argc - 1 && strcmp(argv[testparsing + 1], "none")) {
594  debug_fp = fopen(argv[testparsing + 1], "w");
595  DEBUGPRINT("DEBUG: enable logging into file: %s" NL, argv[testparsing + 1]);
596  if (debug_fp == NULL)
597  fprintf(stderr, "Cannot open debug logging file: %s" NL, argv[testparsing + 1]);
598  break;
599  }
600  testparsing++;
601  }
602  testparsing = 0;
603 #endif
604  /* end of ugly hack */
605  /* let's continue with the info block ... */
606  DEBUGPRINT("%s %s v%s %s %s" NL
607  "GIT %s compiled by (%s) at (%s) with (%s)-(%s)" NL
608  "Platform: (%s) (%d-bit), video: (%s), audio: (%s), "
609  "SDL version compiled: (%d.%d.%d) and linked: (%d.%d.%d) rev (%s)" NL NL,
612  SDL_GetPlatform(), ARCH_BITS, SDL_GetCurrentVideoDriver(), SDL_GetCurrentAudioDriver(),
613  sdlver_compiled.major, sdlver_compiled.minor, sdlver_compiled.patch,
614  sdlver_linked.major, sdlver_linked.minor, sdlver_linked.patch, SDL_GetRevision()
615  );
616  DEBUGPRINT("PATH: executable: %s" NL, exe);
617  /* SDL path info block printout */
618  DEBUGPRINT("PATH: SDL base path: %s" NL, app_base_path);
619  DEBUGPRINT("PATH: SDL pref path: %s" NL, app_pref_path);
620 #ifndef _WIN32
621  DEBUGPRINT("PATH: data directory: %s/" NL, DATADIR);
622 #endif
623  DEBUGPRINT("PATH: Current directory: %s" NL NL, current_directory);
624  /* Look the very basic command line switches first */
625  if (argc && is_help_request_option(argv[0])) {
626  opt = configOptions;
627  printf("USAGE:" NL NL
628  "\t%s -optname optval -optname2 optval2 ..." NL NL "OPTIONS:" NL NL
629  "-config" NL "\tUse config file (or do not use the default one, if \"none\" is specified). This must be the first option if used! [default: @config]" NL,
630  exe
631  );
632  while (opt->name) {
633  printf("-%s" NL "\t%s [default: %s]" NL, opt->name, opt->help, opt->defval ? opt->defval : "-");
634  opt++;
635  }
636  printf(NL "%s" NL, disclaimer);
637 #ifdef _WIN32
638  if (!console_is_open)
639  ERROR_WINDOW("Could not dump help, since console couldn't be allocated.");
640 #endif
641  XEMUEXIT(0);
642  }
643  DEBUGPRINT("%s" NL NL, disclaimer);
644  if (argc && !strcasecmp(argv[0], "-testparsing")) {
645  testparsing = 1;
646  argc--; argv++;
647  }
648  if (argc & 1) {
649  fprintf(stderr, "FATAL: Bad command line: should be even number of parameters (two for an option as key and its value)" NL);
650  return 1;
651  }
652  if (argc > 1 && !strcmp(argv[0], "-config")) {
653  default_config = 0;
654  config_name = argv[1];
655  argc -= 2;
656  argv += 2;
657  }
658  /* Set default (built-in) values */
659  opt = configOptions;
660  while (opt->name) {
661  if (opt->defval)
662  config_set_internal(opt->name, -1, opt->defval);
663  opt++;
664  }
665  config_set_internal("rom", 0, COMBINED_ROM_FN); // set default "combined" ROM image set (from segment 0, starting with EXOS)
666  /* Default values for the keyboard follows ... */
668  /* check if we have written sample config file, if there is not, let's create one */
669  save_sample_config(DEFAULT_CONFIG_SAMPLE_FILE);
670  /* now parse config file (not the sample one!) if there is any */
671  if (strcasecmp(config_name, "none")) {
672  char path[PATH_MAX + 1];
673  FILE *f = open_emu_file(config_name, "r", path);
674  DEBUGPRINT("CONFIG: config file: %s (%s)" NL, config_name, f ? path : "*** CANNOT OPEN, NOT USING CONFIG FILE ***");
675  if (f) {
676  if (load_config_file_stream(f, path)) {
677  fclose(f);
678  return 1;
679  }
680  fclose(f);
681  } else if (!default_config) {
682  fprintf(stderr, "FATAL: Cannot open requested config file: %s" NL, config_name);
683  return 1;
684  } else
685  DEBUGPRINT("CONFIG: Skipping default config file (cannot open), using built-in defaults." NL);
686  } else
687  DEBUGPRINT("CONFIG: Using config file: DISABLED in command line" NL);
688  /* parse command line ... */
689  if (parse_command_line(argc, argv))
690  return -1;
691  /* open debug file, if it was not requested via command line at the beginning ... */
692  if (!debug_fp && strcmp(config_getopt_str(DEBUGFILE_OPT), "none")) {
693  debug_fp = fopen(config_getopt_str(DEBUGFILE_OPT), "w");
694  DEBUGPRINT("DEBUG: enable logging into file: %s" NL, config_getopt_str(DEBUGFILE_OPT));
695  if (!debug_fp)
696  ERROR_WINDOW("Cannot open debug messages log file requested: %s", config_getopt_str(DEBUGFILE_OPT));
697  }
698  if (debug_fp)
699  INFO_WINDOW("DEBUG: Debug messages logging is active");
700  else
701  printf("DEBUG: No debug messages logging is active." NL);
702  /* test parsing mode? */
703  if (testparsing) {
704  printf(NL "--- TEST DUMP OF *PARSED* CONFIGURATION (requested)" NL NL);
705  dump_config(stdout);
706  printf(NL "--- END OF TEST PARSING MODE (requested)" NL);
707  XEMUEXIT(0);
708  }
709  DEBUG("CONFIG: End of configuration step." NL NL);
710  /* Close console, unless user requested it with the -console option */
711 #ifdef _WIN32
712  if (!config_getopt_int("console"))
714 #else
715  if (config_getopt_int("console"))
716  console_open_window(); // on non-windows, it only will mark console as open for monitor to be used ..
717 #endif
718  return 0;
719 }
720 
COPYRIGHT
#define COPYRIGHT
Definition: xep128.h:52
console_is_open
int console_is_open
Definition: console.c:54
configOption_st::help
const char * help
Definition: configuration.c:45
configSetting_st::value
char * value
Definition: configuration.c:51
CC_TYPE
#define CC_TYPE
Definition: emutools_basicdefs.h:104
COMBINED_ROM_FN
#define COMBINED_ROM_FN
Definition: xep128.h:63
console.h
DEFAULT_CONFIG_FILE
#define DEFAULT_CONFIG_FILE
Definition: xep128.h:66
CONFITEM_STR
@ CONFITEM_STR
Definition: configuration.c:35
keyboard_mapping.h
DEFAULT_CONFIG_SAMPLE_FILE
#define DEFAULT_CONFIG_SAMPLE_FILE
Definition: xep128.h:67
INFO_WINDOW
#define INFO_WINDOW(...)
Definition: xep128.h:114
configOption_st::name
const char * name
Definition: configuration.c:41
app_pref_path
char * app_pref_path
Definition: configuration.c:84
XEMU_BUILDINFO_GIT
const char XEMU_BUILDINFO_GIT[]
Definition: emutools_basicdefs.h:251
configSetting_st::opt
const struct configOption_st * opt
Definition: configuration.c:49
config_getopt
void * config_getopt(const char *name, const int subopt, void *value)
Definition: configuration.c:254
config_init
int config_init(int argc, char **argv)
Definition: configuration.c:565
configSetting_st
Definition: configuration.c:48
configItemEnum_t
configItemEnum_t
Definition: configuration.c:33
ARCH_BITS
#define ARCH_BITS
Definition: emutools_basicdefs.h:89
debug_fp
FILE * debug_fp
Definition: configuration.c:87
DEBUGFILE_OPT
#define DEBUGFILE_OPT
Definition: configuration.c:55
keymap_preinit_config_internal
void keymap_preinit_config_internal(void)
Definition: keyboard_mapping.c:173
configOption_st::defval
const char * defval
Definition: configuration.c:43
open_emu_file
FILE * open_emu_file(const char *name, const char *mode, char *pathbuffer)
Definition: configuration.c:109
XEMU_BUILDINFO_CC
const char XEMU_BUILDINFO_CC[]
Definition: emutools_basicdefs.h:251
DEBUGPRINT
#define DEBUGPRINT(...)
Definition: emutools_basicdefs.h:171
CONFITEM_BOOL
@ CONFITEM_BOOL
Definition: configuration.c:36
console_open_window
void console_open_window(void)
Definition: console.c:135
CHECK_MALLOC
#define CHECK_MALLOC(p)
Definition: xep128.h:119
DIRSEP
#define DIRSEP
Definition: xep128.h:27
sdlver_linked
SDL_version sdlver_linked
Definition: configuration.c:86
CONFITEM_FLOAT
@ CONFITEM_FLOAT
Definition: configuration.c:37
ERROR_WINDOW
#define ERROR_WINDOW(...)
Definition: xep128.h:116
sdlver_compiled
SDL_version sdlver_compiled
Definition: configuration.c:86
DATADIR
#define DATADIR
Definition: xep128.h:36
mode
int mode
Definition: vera.c:61
is_help_request_option
int is_help_request_option(const char *opt)
Definition: configuration.c:481
NL
#define NL
Definition: fat32.c:37
configSetting_st::subopt
int subopt
Definition: configuration.c:50
keymap_set_key_by_name
int keymap_set_key_by_name(const char *name, int posep)
Definition: keyboard_mapping.c:162
XEMUEXIT
#define XEMUEXIT(n)
Definition: emutools_basicdefs.h:246
configOption_st::subopt
const int subopt
Definition: configuration.c:44
console_close_window
void console_close_window(void)
Definition: console.c:189
xep128.h
config_getopt_pointed
void config_getopt_pointed(void *st_in, void *value)
Definition: configuration.c:275
CONFITEM_INT
@ CONFITEM_INT
Definition: configuration.c:34
XEMU_BUILDINFO_ON
const char XEMU_BUILDINFO_ON[]
DESCRIPTION
#define DESCRIPTION
Definition: xep128.h:49
config_set
int config_set(const char *name, int subopt, const char *value)
Definition: configuration.c:198
configuration.h
forget_emu_file
void forget_emu_file(const char *path)
Definition: configuration.c:98
value
int value
Definition: dma65.c:90
keymap_dump_config
void keymap_dump_config(FILE *fp)
Definition: keyboard_mapping.c:184
ERRSTR
#define ERRSTR()
Definition: enterprise128.h:56
name
const char * name
Definition: joystick.c:46
configOption_st::type
const int type
Definition: configuration.c:42
XEMU_BUILDINFO_AT
const char XEMU_BUILDINFO_AT[]
Definition: emutools_basicdefs.h:251
DEBUG
#define DEBUG(...)
Definition: emutools_basicdefs.h:167
PRINT_OUT_FN
#define PRINT_OUT_FN
Definition: enterprise128.h:30
app_base_path
char * app_base_path
Definition: configuration.c:84
WINDOW_TITLE
#define WINDOW_TITLE
Definition: xep128.h:50
FATAL
#define FATAL(...)
Definition: xep128.h:117
PROJECT_PAGE
#define PROJECT_PAGE
Definition: xep128.h:53
current_directory
char current_directory[PATH_MAX+1]
Definition: configuration.c:85
configOption_st
Definition: configuration.c:40
VERSION
#define VERSION
Definition: xep128.h:51
SDCARD_IMG_FN
#define SDCARD_IMG_FN
Definition: enterprise128.h:29
st
struct stat st
Definition: cpmfs.c:43