|
|
1.1 root 1: /*
2: Hatari - options.c
3:
4: This file is distributed under the GNU Public License, version 2 or at
5: your option any later version. Read the file gpl.txt for details.
6:
7: Functions for showing and parsing all of Hatari's command line options.
8:
9: To add a new option:
10: - Add option ID to the enum
11: - Add the option information to HatariOptions[]
12: - Add required actions for that ID to switch in Opt_ParseParameters()
13: */
14: const char Options_fileid[] = "Hatari options.c : " __DATE__ " " __TIME__;
15:
16: #include <ctype.h>
17: #include <stdio.h>
18: #include <stdlib.h>
19: #include <string.h>
20: #include <assert.h>
21: #include <SDL.h>
22:
23: #include "main.h"
24: #include "options.h"
25: #include "configuration.h"
26: #include "control.h"
27: #include "debugui.h"
28: #include "file.h"
29: #include "screen.h"
30: #include "video.h"
31: #include "log.h"
1.1.1.2 root 32: #include "paths.h"
1.1 root 33:
34: #include "hatari-glue.h"
35:
36: static bool bNoSDLParachute;
37:
38: /* List of supported options. */
39: enum {
40: OPT_HEADER, /* options section header */
41: OPT_HELP, /* general options */
42: OPT_VERSION,
43: OPT_CONFIRMQUIT,
44: OPT_CONFIGFILE,
1.1.1.2 root 45: OPT_KEYMAPFILE,
1.1 root 46: OPT_MONITOR,
47: OPT_FULLSCREEN,
48: OPT_WINDOW,
49: OPT_GRAB,
50: OPT_STATUSBAR,
51: OPT_DRIVE_LED,
52: OPT_PRINTER,
53: OPT_WRITEPROT_HD,
54: OPT_MEMSIZE, /* memory options */
55: OPT_MEMSTATE,
56: OPT_CPULEVEL, /* CPU options */
57: OPT_CPUCLOCK,
58: OPT_COMPATIBLE,
1.1.1.4 root 59:
1.1.1.2 root 60: OPT_CPU_CYCLE_EXACT, /* WinUAE CPU/FPU/bus options */
61: OPT_CPU_ADDR24,
62: OPT_FPU_TYPE,
63: OPT_FPU_COMPATIBLE,
64: OPT_MMU,
1.1.1.4 root 65:
1.1 root 66: OPT_MACHINE, /* system options */
1.1.1.5 ! root 67: OPT_REALTIME,
1.1 root 68: OPT_DSP,
1.1.1.2 root 69: OPT_MICROPHONE,
1.1 root 70: OPT_SOUND,
71: OPT_SOUNDBUFFERSIZE,
1.1.1.2 root 72: OPT_RTC,
1.1 root 73: OPT_DEBUG, /* debug options */
74: OPT_TRACE,
75: OPT_TRACEFILE,
76: OPT_PARSE,
77: OPT_SAVECONFIG,
78: OPT_PARACHUTE,
79: OPT_CONTROLSOCKET,
80: OPT_LOGFILE,
81: OPT_LOGLEVEL,
82: OPT_ALERTLEVEL,
83: OPT_ERROR,
84: OPT_CONTINUE
85: };
86:
87: typedef struct {
88: unsigned int id; /* option ID */
89: const char *chr; /* short option */
90: const char *str; /* long option */
91: const char *arg; /* type name for argument, if any */
92: const char *desc; /* option description */
93: } opt_t;
94:
95: /* it's easier to edit these if they are kept in the same order as the enums */
96: static const opt_t HatariOptions[] = {
97:
98: { OPT_HEADER, NULL, NULL, NULL, "General" },
99: { OPT_HELP, "-h", "--help",
100: NULL, "Print this help text and exit" },
101: { OPT_VERSION, "-v", "--version",
102: NULL, "Print version number and exit" },
103: { OPT_CONFIRMQUIT, NULL, "--confirm-quit",
104: "<bool>", "Whether Hatari confirms quit" },
105: { OPT_CONFIGFILE, "-c", "--configfile",
106: "<file>", "Use <file> instead of the default hatari config file" },
1.1.1.2 root 107: { OPT_KEYMAPFILE, "-k", "--keymap",
108: "<file>", "Read (additional) keyboard mappings from <file>" },
1.1.1.5 ! root 109:
1.1.1.2 root 110: { OPT_HEADER, NULL, NULL, NULL, "Common display" },
1.1 root 111: { OPT_MONITOR, NULL, "--monitor",
112: "<x>", "Select monitor type (x = mono/rgb/vga/tv)" },
113: { OPT_FULLSCREEN,"-f", "--fullscreen",
114: NULL, "Start emulator in fullscreen mode" },
115: { OPT_WINDOW, "-w", "--window",
116: NULL, "Start emulator in window mode" },
117: { OPT_GRAB, NULL, "--grab",
118: NULL, "Grab mouse (also) in window mode" },
119: { OPT_STATUSBAR, NULL, "--statusbar",
120: "<bool>", "Show statusbar (floppy leds etc)" },
121: { OPT_DRIVE_LED, NULL, "--drive-led",
122: "<bool>", "Show overlay drive led when statusbar isn't shown" },
123:
124: { OPT_HEADER, NULL, NULL, NULL, "Devices" },
125: { OPT_PRINTER, NULL, "--printer",
126: "<file>", "Enable printer support and write data to <file>" },
127:
128: { OPT_HEADER, NULL, NULL, NULL, "Disk" },
129: { OPT_WRITEPROT_HD, NULL, "--protect-hd",
130: "<x>", "Write protect harddrive <dir> contents (on/off/auto)" },
131:
132: { OPT_HEADER, NULL, NULL, NULL, "Memory" },
133: { OPT_MEMSIZE, "-s", "--memsize",
134: "<x>", "ST RAM size (x = size in MiB from 0 to 14, 0 = 512KiB)" },
135: { OPT_MEMSTATE, NULL, "--memstate",
136: "<file>", "Load memory snap-shot <file>" },
137:
138: { OPT_HEADER, NULL, NULL, NULL, "CPU" },
139: { OPT_CPULEVEL, NULL, "--cpulevel",
140: "<x>", "Set the CPU type (x => 680x0) (EmuTOS/TOS 2.06 only!)" },
141: { OPT_CPUCLOCK, NULL, "--cpuclock",
142: "<x>", "Set the CPU clock (x = 8/16/32)" },
143: { OPT_COMPATIBLE, NULL, "--compatible",
144: "<bool>", "Use a more compatible (but slower) 68000 CPU mode" },
1.1.1.2 root 145:
146: { OPT_HEADER, NULL, NULL, NULL, "WinUAE CPU/FPU/bus" },
147: { OPT_CPU_CYCLE_EXACT, NULL, "--cpu-exact",
148: "<bool>", "Use cycle exact CPU emulation" },
149: { OPT_CPU_ADDR24, NULL, "--addr24",
150: "<bool>", "Use 24-bit instead of 32-bit addressing mode" },
151: { OPT_FPU_TYPE, NULL, "--fpu-type",
152: "<x>", "FPU type (x=none/68881/68882/internal)" },
153: { OPT_FPU_COMPATIBLE, NULL, "--fpu-compatible",
154: "<bool>", "Use more compatible, but slower FPU emulation" },
155: { OPT_MMU, NULL, "--mmu",
156: "<bool>", "Use MMU emulation" },
157:
1.1 root 158: { OPT_HEADER, NULL, NULL, NULL, "Misc system" },
1.1.1.5 ! root 159: { OPT_REALTIME, NULL, "--realtime",
! 160: "<bool>", "Use host realtime sources" },
1.1 root 161: { OPT_DSP, NULL, "--dsp",
1.1.1.5 ! root 162: "<x>", "DSP emulation (x = none/dummy/emu)" },
1.1.1.2 root 163: { OPT_MICROPHONE, NULL, "--mic",
1.1.1.5 ! root 164: "<bool>", "Enable/disable microphone" },
1.1 root 165: { OPT_SOUND, NULL, "--sound",
166: "<x>", "Sound frequency (x=off/6000-50066, off=fastest)" },
167: { OPT_SOUNDBUFFERSIZE, NULL, "--sound-buffer-size",
1.1.1.2 root 168: "<x>", "Sound buffer size for SDL in ms (x=0/10-100, 0=default)" },
169: { OPT_RTC, NULL, "--rtc",
170: "<bool>", "Enable real-time clock" },
171:
1.1 root 172: { OPT_HEADER, NULL, NULL, NULL, "Debug" },
173: { OPT_DEBUG, "-D", "--debug",
174: NULL, "Toggle whether CPU exceptions invoke debugger" },
175: { OPT_TRACE, NULL, "--trace",
176: "<trace1,...>", "Activate emulation tracing, see '--trace help'" },
177: { OPT_TRACEFILE, NULL, "--trace-file",
178: "<file>", "Save trace output to <file> (default=stderr)" },
179: { OPT_PARSE, NULL, "--parse",
180: "<file>", "Parse/execute debugger commands from <file>" },
181: { OPT_SAVECONFIG, NULL, "--saveconfig",
182: NULL, "Save current Hatari configuration and exit" },
183: { OPT_PARACHUTE, NULL, "--no-parachute",
184: NULL, "Disable SDL parachute to get Hatari core dumps" },
185: #if HAVE_UNIX_DOMAIN_SOCKETS
186: { OPT_CONTROLSOCKET, NULL, "--control-socket",
187: "<file>", "Hatari reads options from given socket at run-time" },
188: #endif
189: { OPT_LOGFILE, NULL, "--log-file",
190: "<file>", "Save log output to <file> (default=stderr)" },
191: { OPT_LOGLEVEL, NULL, "--log-level",
192: "<x>", "Log output level (x=debug/todo/info/warn/error/fatal)" },
193: { OPT_ALERTLEVEL, NULL, "--alert-level",
194: "<x>", "Show dialog for log messages above given level" },
195:
196: { OPT_ERROR, NULL, NULL, NULL, NULL }
197: };
198:
199:
200: /**
201: * Show version string and license.
202: */
203: static void Opt_ShowVersion(void)
204: {
205: printf("\n" PROG_NAME
1.1.1.5 ! root 206: " - the NeXT emulator.\n\n");
! 207: printf(PROG_NAME " is free software licensed under the GNU General"
1.1 root 208: " Public License.\n\n");
209: }
210:
211:
212: /**
213: * Calculate option + value len
214: */
215: static unsigned int Opt_OptionLen(const opt_t *opt)
216: {
217: unsigned int len;
218: len = strlen(opt->str);
219: if (opt->arg)
220: {
221: len += strlen(opt->arg);
222: len += 1;
223: /* with arg, short options go to another line */
224: }
225: else
226: {
227: if (opt->chr)
228: {
229: /* ' or -c' */
230: len += 6;
231: }
232: }
233: return len;
234: }
235:
236:
237: /**
238: * Show single option
239: */
240: static void Opt_ShowOption(const opt_t *opt, unsigned int maxlen)
241: {
242: char buf[64];
243: if (!maxlen)
244: {
245: maxlen = Opt_OptionLen(opt);
246: }
247: assert(maxlen < sizeof(buf));
248: if (opt->arg)
249: {
250: sprintf(buf, "%s %s", opt->str, opt->arg);
251: printf(" %-*s %s\n", maxlen, buf, opt->desc);
252: if (opt->chr)
253: {
254: printf(" or %s %s\n", opt->chr, opt->arg);
255: }
256: }
257: else
258: {
259: if (opt->chr)
260: {
261: sprintf(buf, "%s or %s", opt->str, opt->chr);
262: printf(" %-*s %s\n", maxlen, buf, opt->desc);
263: }
264: else
265: {
266: printf(" %-*s %s\n", maxlen, opt->str, opt->desc);
267: }
268: }
269: }
270:
271: /**
272: * Show options for section starting from 'start_opt',
273: * return next option after this section.
274: */
275: static const opt_t *Opt_ShowHelpSection(const opt_t *start_opt)
276: {
277: const opt_t *opt, *last;
278: unsigned int len, maxlen = 0;
279: const char *previous = NULL;
280:
281: /* find longest option name and check option IDs */
282: for (opt = start_opt; opt->id != OPT_HEADER && opt->id != OPT_ERROR; opt++)
283: {
284: len = Opt_OptionLen(opt);
285: if (len > maxlen)
286: {
287: maxlen = len;
288: }
289: }
290: last = opt;
291:
292: /* output all options */
293: for (opt = start_opt; opt != last; opt++)
294: {
295: if (previous != opt->str)
296: {
297: Opt_ShowOption(opt, maxlen);
298: }
299: previous = opt->str;
300: }
301: return last;
302: }
303:
304:
305: /**
306: * Show help text.
307: */
308: static void Opt_ShowHelp(void)
309: {
310: const opt_t *opt = HatariOptions;
311:
312: Opt_ShowVersion();
1.1.1.5 ! root 313: printf("Usage:\n previous [options] [directory|disk image|Atari program]\n");
1.1 root 314:
315: while(opt->id != OPT_ERROR)
316: {
317: if (opt->id == OPT_HEADER)
318: {
319: assert(opt->desc);
320: printf("\n%s options:\n", opt->desc);
321: opt++;
322: }
323: opt = Opt_ShowHelpSection(opt);
324: }
325: printf("\nSpecial option values:\n");
326: printf("<bool>\tDisable by using 'n', 'no', 'off', 'false', or '0'\n");
327: printf("\tEnable by using 'y', 'yes', 'on', 'true' or '1'\n");
328: printf("<file>\tDevices accept also special 'stdout' and 'stderr' file names\n");
329: printf("\t(if you use stdout for midi or printer, set log to stderr).\n");
330: printf("\tSetting the file to 'none', disables given device or disk\n");
331: }
332:
333:
334: /**
335: * Show Hatari version and usage.
336: * If 'error' given, show that error message.
337: * If 'optid' != OPT_ERROR, tells for which option the error is,
338: * otherwise 'value' is show as the option user gave.
339: * Return false if error string was given, otherwise true
340: */
341: static bool Opt_ShowError(unsigned int optid, const char *value, const char *error)
342: {
343: const opt_t *opt;
344:
345: Opt_ShowVersion();
346: printf("Usage:\n hatari [options] [disk image name]\n\n"
347: "Try option \"-h\" or \"--help\" to display more information.\n");
348:
349: if (error)
350: {
351: if (optid == OPT_ERROR)
352: {
353: fprintf(stderr, "\nError: %s (%s)\n", error, value);
354: }
355: else
356: {
357: for (opt = HatariOptions; opt->id != OPT_ERROR; opt++)
358: {
359: if (optid == opt->id)
360: break;
361: }
362: if (value != NULL)
363: {
364: fprintf(stderr,
365: "\nError while parsing argument \"%s\" for option \"%s\":\n"
366: " %s\n", value, opt->str, error);
367: }
368: else
369: {
370: fprintf(stderr, "\nError (%s): %s\n", opt->str, error);
371: }
372: fprintf(stderr, "\nOption usage:\n");
373: Opt_ShowOption(opt, 0);
374: }
375: return false;
376: }
377: return true;
378: }
379:
380:
381: /**
382: * If 'conf' given, set it:
383: * - true if given option 'arg' is y/yes/on/true/1
384: * - false if given option 'arg' is n/no/off/false/0
385: * Return false for any other value, otherwise true
386: */
387: static bool Opt_Bool(const char *arg, int optid, bool *conf)
388: {
389: const char *enablers[] = { "y", "yes", "on", "true", "1", NULL };
390: const char *disablers[] = { "n", "no", "off", "false", "0", NULL };
391: const char **bool_str, *orig = arg;
392: char *input, *str;
393:
394: input = strdup(arg);
395: str = input;
396: while (*str)
397: {
398: *str++ = tolower(*arg++);
399: }
400: for (bool_str = enablers; *bool_str; bool_str++)
401: {
402: if (strcmp(input, *bool_str) == 0)
403: {
404: free(input);
405: if (conf)
406: {
407: *conf = true;
408: }
409: return true;
410: }
411: }
412: for (bool_str = disablers; *bool_str; bool_str++)
413: {
414: if (strcmp(input, *bool_str) == 0)
415: {
416: free(input);
417: if (conf)
418: {
419: *conf = false;
420: }
421: return true;
422: }
423: }
424: free(input);
425: return Opt_ShowError(optid, orig, "Not a <bool> value");
426: }
427:
428:
429: /**
430: * checks str argument agaist options of type "--option<digit>".
431: * If match is found, returns ID for that, otherwise OPT_CONTINUE
432: * and OPT_ERROR for errors.
433: */
434: static int Opt_CheckBracketValue(const opt_t *opt, const char *str)
435: {
436: const char *bracket, *optstr;
437: size_t offset;
438: int digit, i;
439:
440: if (!opt->str)
441: {
442: return OPT_CONTINUE;
443: }
444: bracket = strchr(opt->str, '<');
445: if (!bracket)
446: {
447: return OPT_CONTINUE;
448: }
449: offset = bracket - opt->str;
450: if (strncmp(opt->str, str, offset) != 0)
451: {
452: return OPT_CONTINUE;
453: }
454: digit = str[offset] - '0';
455: if (digit < 0 || digit > 9)
456: {
457: return OPT_CONTINUE;
458: }
459: optstr = opt->str;
460: for (i = 0; opt->str == optstr; opt++, i++)
461: {
462: if (i == digit)
463: {
464: return opt->id;
465: }
466: }
467: /* fprintf(stderr, "opt: %s (%d), str: %s (%d), digit: %d\n",
468: opt->str, offset+1, str, strlen(str), digit);
469: */
470: return OPT_ERROR;
471: }
472:
473:
474: /**
475: * matches string under given index in the argv against all Hatari
476: * short and long options. If match is found, returns ID for that,
477: * otherwise shows help and returns OPT_ERROR.
478: *
479: * Checks also that if option is supposed to have argument,
480: * whether there's one.
481: */
1.1.1.2 root 482: static int Opt_WhichOption(int argc, const char * const argv[], int idx)
1.1 root 483: {
484: const opt_t *opt;
485: const char *str = argv[idx];
486: int id;
487:
488: for (opt = HatariOptions; opt->id != OPT_ERROR; opt++)
489: {
490: /* exact option name matches? */
491: if (!((opt->str && !strcmp(str, opt->str)) ||
492: (opt->chr && !strcmp(str, opt->chr))))
493: {
494: /* no, maybe name<digit> matches? */
495: id = Opt_CheckBracketValue(opt, str);
496: if (id == OPT_CONTINUE)
497: {
498: continue;
499: }
500: if (id == OPT_ERROR)
501: {
502: break;
503: }
504: }
505: /* matched, check args */
506: if (opt->arg)
507: {
508: if (idx+1 >= argc)
509: {
510: Opt_ShowError(opt->id, NULL, "Missing argument");
511: return OPT_ERROR;
512: }
513: /* early check for bools */
514: if (strcmp(opt->arg, "<bool>") == 0)
515: {
516: if (!Opt_Bool(argv[idx+1], opt->id, NULL))
517: {
518: return OPT_ERROR;
519: }
520: }
521: }
522: return opt->id;
523: }
524: Opt_ShowError(OPT_ERROR, argv[idx], "Unrecognized option");
525: return OPT_ERROR;
526: }
527:
528:
529: /**
530: * If 'checkexits' is true, assume 'src' is a file and check whether it
531: * exists before copying 'src' to 'dst'. Otherwise just copy option src
532: * string to dst.
533: * If a pointer to (bool) 'option' is given, set that option to true.
534: * - However, if src is "none", leave dst unmodified & set option to false.
535: * ("none" is used to disable options related to file arguments)
536: * Return false if there were errors, otherwise true
537: */
538: static bool Opt_StrCpy(int optid, bool checkexist, char *dst, const char *src, size_t dstlen, bool *option)
539: {
540: if (option)
541: {
542: *option = false;
543: if(strcasecmp(src, "none") == 0)
544: {
545: return true;
546: }
547: }
548: if (strlen(src) >= dstlen)
549: {
550: return Opt_ShowError(optid, src, "File name too long!");
551: }
552: if (checkexist && !File_Exists(src))
553: {
554: return Opt_ShowError(optid, src, "Given file doesn't exist (or has wrong file permissions)!");
555: }
556: if (option)
557: {
558: *option = true;
559: }
560: strcpy(dst, src);
561: return true;
562: }
563:
564:
565: /**
566: * Return SDL_INIT_NOPARACHUTE flag if user requested SDL parachute
567: * to be disabled to get proper Hatari core dumps. By default returns
568: * zero so that SDL parachute will be used to restore video mode on
569: * unclean Hatari termination.
570: */
571: Uint32 Opt_GetNoParachuteFlag(void)
572: {
573: if (bNoSDLParachute) {
574: return SDL_INIT_NOPARACHUTE;
575: }
576: return 0;
577: }
578:
579:
580: /**
1.1.1.2 root 581: * Handle last (non-option) argument. It can be a path or filename.
582: * Filename can be a disk image or Atari program.
583: * Return false if it's none of these.
584: */
585: static bool Opt_HandleArgument(const char *path)
586: {
587: char *dir = NULL;
588: Uint8 test[2];
589: FILE *fp;
590:
591: /* Atari program? */
592: if (File_Exists(path) && (fp = fopen(path, "rb"))) {
593:
594: /* file starts with GEMDOS magic? */
595: if (fread(test, 1, 2, fp) == 2 &&
596: test[0] == 0x60 && test[1] == 0x1A) {
597:
598: const char *prgname = strrchr(path, PATHSEP);
599: if (prgname) {
600: dir = strdup(path);
601: dir[prgname-path] = '\0';
602: prgname++;
603: } else {
604: dir = strdup(Paths_GetWorkingDir());
605: prgname = path;
606: }
607: /* after above, dir should point to valid dir,
608: * then make sure that given program from that
609: * dir will be started.
610: */
611: // TOS_AutoStart(prgname);
612: }
613: fclose(fp);
614: }
615: if (dir) {
616: path = dir;
617: }
618:
619: /* GEMDOS HDD directory (as argument, or for the Atari program)? */
620: if (File_DirExists(path)) {
1.1.1.3 root 621: // if (Opt_StrCpy(OPT_HARDDRIVE, false, ConfigureParams.HardDisk.szHardDiskDirectories[0],
622: // path, sizeof(ConfigureParams.HardDisk.szHardDiskDirectories[0]),
623: // &ConfigureParams.HardDisk.bUseHardDiskDirectories)
624: // && ConfigureParams.HardDisk.bUseHardDiskDirectories)
1.1.1.2 root 625: {
1.1.1.4 root 626: // ConfigureParams.SCSI.bBootFromHardDisk = true;
1.1.1.2 root 627: }
628: if (dir) {
629: free(dir);
630: }
631: return true;
632: } else {
633: if (dir) {
634: /* if dir is set, it should be valid... */
635: Log_Printf(LOG_ERROR, "Given atari program path '%s' doesn't exist (anymore?)!\n", dir);
636: free(dir);
637: exit(1);
638: }
639: }
640:
641: return Opt_ShowError(OPT_ERROR, path, "Not a disk image, Atari program or directory");
642: }
643:
644: /**
1.1 root 645: * parse all Hatari command line options and set Hatari state accordingly.
646: * Returns true if everything was OK, false otherwise.
647: */
1.1.1.2 root 648: bool Opt_ParseParameters(int argc, const char * const argv[])
1.1 root 649: {
1.1.1.5 ! root 650: int ncpu, cpuclock, memsize, freq, temp;
1.1 root 651: const char *errstr;
652: int i, ok = true;
653:
654: for(i = 1; i < argc; i++)
655: {
1.1.1.2 root 656: /* last argument can be a non-option */
657: if (argv[i][0] != '-' && i+1 == argc)
658: return Opt_HandleArgument(argv[i]);
1.1 root 659:
660: /* WhichOption() checks also that there is an argument,
661: * so we don't need to check that below
662: */
663: switch(Opt_WhichOption(argc, argv, i))
664: {
665:
666: /* general options */
667: case OPT_HELP:
668: Opt_ShowHelp();
669: return false;
670:
671: case OPT_VERSION:
672: Opt_ShowVersion();
673: return false;
674:
675: case OPT_CONFIRMQUIT:
676: ok = Opt_Bool(argv[++i], OPT_CONFIRMQUIT, &ConfigureParams.Log.bConfirmQuit);
677: break;
678:
679: case OPT_CONFIGFILE:
680: i += 1;
681: /* true -> file needs to exist */
682: ok = Opt_StrCpy(OPT_CONFIGFILE, true, sConfigFileName,
683: argv[i], sizeof(sConfigFileName), NULL);
684: if (ok)
685: {
686: Configuration_Load(NULL);
687: }
688: break;
689:
1.1.1.2 root 690: /* common display options */
1.1 root 691:
692: case OPT_MONITOR:
693: i += 1;
694: if (strcasecmp(argv[i], "mono") == 0)
695: {
1.1.1.4 root 696: // ConfigureParams.Screen.nMonitorType = MONITOR_TYPE_MONO;
1.1 root 697: }
698: else if (strcasecmp(argv[i], "rgb") == 0)
699: {
1.1.1.4 root 700: // ConfigureParams.Screen.nMonitorType = MONITOR_TYPE_RGB;
1.1 root 701: }
702: else if (strcasecmp(argv[i], "vga") == 0)
703: {
1.1.1.4 root 704: // ConfigureParams.Screen.nMonitorType = MONITOR_TYPE_VGA;
1.1 root 705: }
706: else if (strcasecmp(argv[i], "tv") == 0)
707: {
1.1.1.4 root 708: // ConfigureParams.Screen.nMonitorType = MONITOR_TYPE_TV;
1.1 root 709: }
710: else
711: {
712: return Opt_ShowError(OPT_MONITOR, argv[i], "Unknown monitor type");
713: }
714: break;
715:
716: case OPT_FULLSCREEN:
717: ConfigureParams.Screen.bFullScreen = true;
718: break;
719:
720: case OPT_WINDOW:
721: ConfigureParams.Screen.bFullScreen = false;
722: break;
723:
724: case OPT_GRAB:
725: bGrabMouse = true;
726: break;
1.1.1.5 ! root 727:
1.1 root 728: case OPT_STATUSBAR:
729: ok = Opt_Bool(argv[++i], OPT_STATUSBAR, &ConfigureParams.Screen.bShowStatusbar);
730: break;
731:
732: case OPT_DRIVE_LED:
733: ok = Opt_Bool(argv[++i], OPT_DRIVE_LED, &ConfigureParams.Screen.bShowDriveLed);
734: break;
1.1.1.5 ! root 735:
1.1.1.2 root 736: case OPT_PRINTER:
737: i += 1;
738: /* "none" can be used to disable printer */
739: ok = Opt_StrCpy(OPT_PRINTER, false, ConfigureParams.Printer.szPrintToFileName,
740: argv[i], sizeof(ConfigureParams.Printer.szPrintToFileName),
1.1.1.4 root 741: &ConfigureParams.Printer.bPrinterConnected);
1.1.1.2 root 742: break;
743:
744: /* disk options */
745:
746: case OPT_WRITEPROT_HD:
747: i += 1;
1.1.1.5 ! root 748: if (strcasecmp(argv[i], "off") == 0)
! 749: ConfigureParams.SCSI.nWriteProtection = WRITEPROT_OFF;
! 750: else if (strcasecmp(argv[i], "on") == 0)
! 751: ConfigureParams.SCSI.nWriteProtection = WRITEPROT_ON;
! 752: else if (strcasecmp(argv[i], "auto") == 0)
! 753: ConfigureParams.SCSI.nWriteProtection = WRITEPROT_AUTO;
! 754: else
1.1.1.2 root 755: return Opt_ShowError(OPT_WRITEPROT_HD, argv[i], "Unknown option value");
756: break;
1.1 root 757:
758: /* Memory options */
759: case OPT_MEMSIZE:
760: memsize = atoi(argv[++i]);
761: if (memsize < 0 || memsize > 14)
762: {
763: return Opt_ShowError(OPT_MEMSIZE, argv[i], "Invalid memory size");
764: }
1.1.1.3 root 765: // ConfigureParams.Memory.nMemorySize = memsize;
1.1 root 766: break;
1.1.1.5 ! root 767:
1.1 root 768: /* CPU options */
769: case OPT_CPULEVEL:
770: /* UAE core uses cpu_level variable */
771: ncpu = atoi(argv[++i]);
772: if(ncpu < 0 || ncpu > 4)
773: {
774: return Opt_ShowError(OPT_CPULEVEL, argv[i], "Invalid CPU level");
775: }
776: ConfigureParams.System.nCpuLevel = ncpu;
777: break;
778:
779: case OPT_CPUCLOCK:
780: cpuclock = atoi(argv[++i]);
781: if(cpuclock != 8 && cpuclock != 16 && cpuclock != 32)
782: {
783: return Opt_ShowError(OPT_CPUCLOCK, argv[i], "Invalid CPU clock");
784: }
785: ConfigureParams.System.nCpuFreq = cpuclock;
786: break;
787:
788: case OPT_COMPATIBLE:
789: ok = Opt_Bool(argv[++i], OPT_COMPATIBLE, &ConfigureParams.System.bCompatibleCpu);
790: break;
791:
792: /* system options */
793: case OPT_MACHINE:
794: i += 1;
795: if (strcasecmp(argv[i], "st") == 0)
796: {
797: ConfigureParams.System.nCpuLevel = 0;
798: ConfigureParams.System.nCpuFreq = 8;
799: }
800: else if (strcasecmp(argv[i], "ste") == 0)
801: {
802: ConfigureParams.System.nCpuLevel = 0;
803: ConfigureParams.System.nCpuFreq = 8;
804: }
805: else if (strcasecmp(argv[i], "tt") == 0)
806: {
807: ConfigureParams.System.nCpuLevel = 3;
808: ConfigureParams.System.nCpuFreq = 32;
809: }
810: else if (strcasecmp(argv[i], "falcon") == 0)
811: {
1.1.1.2 root 812: #if ENABLE_DSP_EMU
813: ConfigureParams.System.nDSPType = DSP_TYPE_EMU;
814: #endif
1.1 root 815: ConfigureParams.System.nCpuLevel = 3;
816: ConfigureParams.System.nCpuFreq = 16;
817: }
818: else
819: {
820: return Opt_ShowError(OPT_MACHINE, argv[i], "Unknown machine type");
821: }
822: break;
823:
1.1.1.5 ! root 824: case OPT_REALTIME:
! 825: ok = Opt_Bool(argv[++i], OPT_REALTIME, &ConfigureParams.System.bRealtime);
! 826: break;
! 827:
1.1.1.2 root 828: case OPT_RTC:
829: ok = Opt_Bool(argv[++i], OPT_RTC, &ConfigureParams.System.bRealTimeClock);
830: break;
831:
832: case OPT_DSP:
833: i += 1;
834: if (strcasecmp(argv[i], "none") == 0)
835: {
836: ConfigureParams.System.nDSPType = DSP_TYPE_NONE;
837: }
838: else if (strcasecmp(argv[i], "dummy") == 0)
839: {
840: ConfigureParams.System.nDSPType = DSP_TYPE_DUMMY;
841: }
842: else if (strcasecmp(argv[i], "emu") == 0)
843: {
844: #if ENABLE_DSP_EMU
845: ConfigureParams.System.nDSPType = DSP_TYPE_EMU;
846: #else
847: return Opt_ShowError(OPT_DSP, argv[i], "DSP type 'emu' support not compiled in");
848: #endif
849: }
850: else
851: {
852: return Opt_ShowError(OPT_DSP, argv[i], "Unknown DSP type");
853: }
854: break;
855:
856: case OPT_FPU_TYPE:
857: i += 1;
858: if (strcasecmp(argv[i], "none") == 0)
859: {
860: ConfigureParams.System.n_FPUType = FPU_NONE;
861: }
862: else if (strcasecmp(argv[i], "68881") == 0)
863: {
864: ConfigureParams.System.n_FPUType = FPU_68881;
865: }
866: else if (strcasecmp(argv[i], "68882") == 0)
867: {
868: ConfigureParams.System.n_FPUType = FPU_68882;
869: }
870: else if (strcasecmp(argv[i], "internal") == 0)
871: {
872: ConfigureParams.System.n_FPUType = FPU_CPU;
873: }
874: else
875: {
876: return Opt_ShowError(OPT_FPU_TYPE, argv[i], "Unknown FPU type");
877: }
878: break;
879:
880: case OPT_FPU_COMPATIBLE:
881: ok = Opt_Bool(argv[++i], OPT_FPU_COMPATIBLE, &ConfigureParams.System.bCompatibleFPU);
882: break;
883:
884: case OPT_MMU:
885: ok = Opt_Bool(argv[++i], OPT_MMU, &ConfigureParams.System.bMMU);
886: break;
1.1 root 887:
1.1.1.2 root 888: case OPT_SOUND:
889: i += 1;
890: if (strcasecmp(argv[i], "off") == 0)
891: {
892: ConfigureParams.Sound.bEnableSound = false;
893: }
894: else
895: {
896: freq = atoi(argv[i]);
1.1.1.5 ! root 897: if (freq != 44100)
1.1.1.2 root 898: {
1.1.1.5 ! root 899: return Opt_ShowError(OPT_SOUND, argv[i], "Unsupported sound frequency, only 44100 supported");
1.1.1.2 root 900: }
901: ConfigureParams.Sound.bEnableSound = true;
902: }
903: break;
1.1 root 904:
905: case OPT_SOUNDBUFFERSIZE:
906: i += 1;
907: temp = atoi(argv[i]);
908: if ( temp == 0 ) /* use default setting for SDL */
909: ;
910: else if (temp < 10 || temp > 100)
911: {
912: return Opt_ShowError(OPT_SOUNDBUFFERSIZE, argv[i], "Unsupported sound buffer size");
913: }
1.1.1.4 root 914: // ConfigureParams.Sound.SdlAudioBufferSize = temp;
1.1 root 915: break;
1.1.1.2 root 916:
917: case OPT_MICROPHONE:
918: ok = Opt_Bool(argv[++i], OPT_MICROPHONE, &ConfigureParams.Sound.bEnableMicrophone);
919: break;
1.1 root 920:
921: case OPT_KEYMAPFILE:
922: i += 1;
923: ok = Opt_StrCpy(OPT_KEYMAPFILE, true, ConfigureParams.Keyboard.szMappingFileName,
924: argv[i], sizeof(ConfigureParams.Keyboard.szMappingFileName),
925: NULL);
926: if (ok)
927: {
928: ConfigureParams.Keyboard.nKeymapType = KEYMAP_LOADED;
929: }
930: break;
931:
932: /* debug options */
933: case OPT_DEBUG:
934: if (bExceptionDebugging)
935: {
936: fprintf(stderr, "Exception debugging disabled.\n");
937: bExceptionDebugging = false;
938: }
939: else
940: {
941: fprintf(stderr, "Exception debugging enabled.\n");
942: bExceptionDebugging = true;
943: }
944: break;
945:
946: case OPT_PARACHUTE:
947: bNoSDLParachute = true;
948: break;
949:
950:
951: case OPT_TRACE:
952: i += 1;
953: errstr = Log_SetTraceOptions(argv[i]);
954: if (errstr)
955: {
956: if (!errstr[0]) {
957: /* silent parsing termination */
958: return false;
959: }
960: return Opt_ShowError(OPT_TRACE, argv[i], errstr);
961: }
962: break;
963:
964: case OPT_TRACEFILE:
965: i += 1;
966: ok = Opt_StrCpy(OPT_TRACEFILE, false, ConfigureParams.Log.sTraceFileName,
967: argv[i], sizeof(ConfigureParams.Log.sTraceFileName),
968: NULL);
969: break;
970:
971: case OPT_CONTROLSOCKET:
972: i += 1;
973: errstr = Control_SetSocket(argv[i]);
974: if (errstr)
975: {
976: return Opt_ShowError(OPT_CONTROLSOCKET, argv[i], errstr);
977: }
978: break;
979:
980: case OPT_LOGFILE:
981: i += 1;
982: ok = Opt_StrCpy(OPT_LOGFILE, false, ConfigureParams.Log.sLogFileName,
983: argv[i], sizeof(ConfigureParams.Log.sLogFileName),
984: NULL);
985: break;
986:
987: case OPT_PARSE:
988: i += 1;
989: ok = DebugUI_SetParseFile(argv[i]);
990: break;
991:
992: case OPT_SAVECONFIG:
993: /* Hatari-UI needs Hatari config to start */
994: Configuration_Save();
995: exit(0);
996: break;
997:
998: case OPT_LOGLEVEL:
999: i += 1;
1000: ConfigureParams.Log.nTextLogLevel = Log_ParseOptions(argv[i]);
1001: if (ConfigureParams.Log.nTextLogLevel == LOG_NONE)
1002: {
1003: return Opt_ShowError(OPT_LOGLEVEL, argv[i], "Unknown log level!");
1004: }
1005: break;
1006:
1007: case OPT_ALERTLEVEL:
1008: i += 1;
1009: ConfigureParams.Log.nAlertDlgLogLevel = Log_ParseOptions(argv[i]);
1010: if (ConfigureParams.Log.nAlertDlgLogLevel == LOG_NONE)
1011: {
1012: return Opt_ShowError(OPT_ALERTLEVEL, argv[i], "Unknown alert level!");
1013: }
1014: break;
1015:
1016: case OPT_ERROR:
1017: /* unknown option or missing option parameter */
1018: return false;
1019:
1020: default:
1021: return Opt_ShowError(OPT_ERROR, argv[i], "Internal Hatari error, unhandled option");
1022: }
1023: if (!ok)
1024: {
1025: /* Opt_Bool() or Opt_StrCpy() failed */
1026: return false;
1027: }
1028: }
1029:
1030: return true;
1031: }
1032:
1033: /**
1034: * Readline match callback for option name completion.
1035: * STATE = 0 -> different text from previous one.
1036: * Return next match or NULL if no matches.
1037: */
1038: char *Opt_MatchOption(const char *text, int state)
1039: {
1040: static int i, len;
1041: const char *name;
1042:
1043: if (!state) {
1044: /* first match */
1045: len = strlen(text);
1046: i = 0;
1047: }
1048: /* next match */
1049: while (i < ARRAYSIZE(HatariOptions)) {
1050: name = HatariOptions[i++].str;
1051: if (name && strncasecmp(name, text, len) == 0)
1052: return (strdup(name));
1053: }
1054: return NULL;
1055: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.