28 #include <sys/types.h>
55 #define DEBUGFILE_OPT "debug"
60 {
"console",
CONFITEM_BOOL,
"0", 0,
"Keep (1) console window open (or give console prompt on STDIN on Linux by default)" },
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\")" },
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" },
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" },
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 }
83 static int config_size = 0;
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.";
100 #ifdef __EMSCRIPTEN__
101 DEBUGPRINT(
"FILE: trying to delete file \"%s\" as used only once, return code: %d" NL,
111 const char *name_used =
name;
112 const char *policy =
"guessing";
113 const char *prefixes[] = {
114 #ifdef __EMSCRIPTEN__
138 }
else if (
name[0] ==
'@') {
139 #ifdef __EMSCRIPTEN__
140 prefixes[0] =
"/files/";
145 name_used =
name + 1;
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]: ",
154 f = fopen(pathbuffer,
mode);
164 strcpy(pathbuffer,
name);
208 config = realloc(config, (config_size + 1) *
sizeof(
struct configOption_st));
210 st = config + (config_size++);
221 static void config_set_internal (
const char *
name,
int subopt,
const char *
value )
224 FATAL(
"Internal built-in configuration error: config_set_internal(\"%s\",%d,\"%s\")",
name,
subopt,
value);
229 static int config_set_user (
const char *
name,
int subopt,
const char *
value,
int gui_error )
231 if (!strcmp(
name,
"epkey")) {
236 fprintf(stderr,
"ERROR: Invalid SDL PC key scan code name: %s" NL,
value);
261 FATAL(
"config_getopt(\"%s\",%d) failed, no optname found",
name,
subopt);
267 FATAL(
"config_getopt(\"%s\",%d) failed, no setting found",
name,
subopt);
278 switch (
st->opt->type) {
280 *(
double*)
value = atof(
st->value);
284 *(
int*)
value = atoi(
st->value);
290 FATAL(
"config_getopt(\"%s\",%d) failed, unknown config item type %d",
st->opt->name,
st->subopt,
st->opt->type);
297 static void str_rstrip (
char *p )
299 char *e = p + strlen(p) - 1;
300 while (e >= p && (*e ==
'\r' || *e ==
'\n' || *e ==
'\t' || *e ==
' '))
306 static int parse_cfgfile_line (
char *buffer,
char **key,
char **
value )
309 *key = *
value = NULL;
310 while (*buffer ==
' ' || *buffer ==
'\t') buffer++;
311 p = strchr(buffer,
'#');
314 if (!*buffer)
return 0;
315 p = strchr(buffer,
'=');
318 while (*p ==
' ' || *p ==
'\t') p++;
323 return !*p || !*buffer;
328 static int separate_key (
const char *buffer,
char *key )
331 char *p = strchr(buffer,
'@');
336 memcpy(key, buffer, p - buffer);
341 if (sscanf(p,
"%02x", &ret) != 1)
348 static int load_config_file_stream ( FILE *f,
const char *
name )
352 while (fgets(buffer,
sizeof(buffer), f)) {
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);
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);
366 char cleankey[
sizeof(buffer)];
367 int subopt = separate_key(buffer, cleankey);
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);
384 static int parse_command_line (
int argc ,
char **argv )
389 if (argv[0][0] !=
'-') {
390 fprintf(stderr,
"FATAL: Command line error: option name should begin with '-' for option: %s" NL, argv[0]);
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]);
407 static void dump_config ( FILE *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
422 if (
st->subopt == -1)
423 fprintf(fp,
"%s = %s\t# %s" NL,
st->opt->name,
st->value,
st->opt->help);
437 fprintf(fp,
"%s@%02x = %s" NL,
451 static void save_sample_config (
const char *
name )
453 #ifdef __EMSCRIPTEN__
454 DEBUGPRINT(
"CONFIG: no configuration is saved in case of emscripten." NL);
456 char path[PATH_MAX + 1];
460 DEBUGPRINT(
"CONFIG: sample configuration %s (%s) already exists, skipping to create." NL,
name, path);
467 INFO_WINDOW(
"Note: created sample config file %s", path);
469 INFO_WINDOW(
"Note: cannot create sample config file %s", path);
475 #if !SDL_VERSION_ATLEAST(2, 0, 4)
476 # error "We need SDL2 version 2.0.4 at least!"
487 !strcasecmp(
opt,
"h") || !strcasecmp(
opt,
"-h") ||
488 !strcasecmp(
opt,
"help") || !strcasecmp(
opt,
"-help") ||
489 !strcasecmp(
opt,
"?") || !strcasecmp(
opt,
"-?")
492 ERROR_WINDOW(
"Plesse note that you MUST use - instead of / with options!\nSo use -h or -? instead of ugly /h or /?");
500 static int get_path_info (
void )
503 char buffer[PATH_MAX + 1];
506 #ifdef __EMSCRIPTEN__
517 f = fopen(buffer,
"r");
519 char *p = fgets(buffer,
sizeof buffer, f);
522 p = strchr(buffer, 13);
525 p = strchr(buffer, 10);
538 #ifdef __EMSCRIPTEN__
549 #ifdef __EMSCRIPTEN__
550 mkdir(
"/files", 0777);
569 const char *exe = argv[0];
570 int default_config = 1;
573 #ifdef __EMSCRIPTEN__
574 exe = strdup(
"/files/emscripten-virtual-executable");
582 ERROR_WINDOW(
"Too old SDL library linked, at least version 2.0.4 is required.");
590 printf(
"DEBUG: disabled at compilation time." NL);
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]);
597 fprintf(stderr,
"Cannot open debug logging file: %s" NL, argv[testparsing + 1]);
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(),
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,
636 printf(
NL "%s" NL, disclaimer);
639 ERROR_WINDOW(
"Could not dump help, since console couldn't be allocated.");
644 if (argc && !strcasecmp(argv[0],
"-testparsing")) {
649 fprintf(stderr,
"FATAL: Bad command line: should be even number of parameters (two for an option as key and its value)" NL);
652 if (argc > 1 && !strcmp(argv[0],
"-config")) {
654 config_name = argv[1];
662 config_set_internal(opt->
name, -1, opt->
defval);
671 if (strcasecmp(config_name,
"none")) {
672 char path[PATH_MAX + 1];
674 DEBUGPRINT(
"CONFIG: config file: %s (%s)" NL, config_name, f ? path :
"*** CANNOT OPEN, NOT USING CONFIG FILE ***");
676 if (load_config_file_stream(f, path)) {
681 }
else if (!default_config) {
682 fprintf(stderr,
"FATAL: Cannot open requested config file: %s" NL, config_name);
685 DEBUGPRINT(
"CONFIG: Skipping default config file (cannot open), using built-in defaults." NL);
687 DEBUGPRINT(
"CONFIG: Using config file: DISABLED in command line" NL);
689 if (parse_command_line(argc, argv))
699 INFO_WINDOW(
"DEBUG: Debug messages logging is active");
701 printf(
"DEBUG: No debug messages logging is active." NL);
704 printf(
NL "--- TEST DUMP OF *PARSED* CONFIGURATION (requested)" NL NL);
706 printf(
NL "--- END OF TEST PARSING MODE (requested)" NL);
709 DEBUG(
"CONFIG: End of configuration step." NL NL);
712 if (!config_getopt_int(
"console"))
715 if (config_getopt_int(
"console"))