|
|
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: #include "avi_record.h"
34:
35: #include "hatari-glue.h"
36:
37:
38: bool bLoadAutoSave; /* Load autosave memory snapshot at startup */
39: bool bLoadMemorySave; /* Load memory snapshot provided via option at startup */
40: bool bBiosIntercept; /* whether UAE should intercept Bios & XBios calls */
41: bool AviRecordOnStartup; /* Start avi recording at startup */
42:
43: static bool bNoSDLParachute;
44:
45: /* List of supported options. */
46: enum {
47: OPT_HEADER, /* options section header */
48: OPT_HELP, /* general options */
49: OPT_VERSION,
50: OPT_CONFIRMQUIT,
51: OPT_CONFIGFILE,
1.1.1.2 root 52: OPT_KEYMAPFILE,
1.1 root 53: OPT_FASTFORWARD,
1.1.1.2 root 54: OPT_MONO, /* common display options */
1.1 root 55: OPT_MONITOR,
56: OPT_FULLSCREEN,
57: OPT_WINDOW,
58: OPT_GRAB,
59: OPT_FRAMESKIPS,
60: OPT_STATUSBAR,
61: OPT_DRIVE_LED,
62: OPT_FORCEBPP,
1.1.1.2 root 63: OPT_BORDERS, /* ST/STE display options */
64: OPT_SPEC512,
65: OPT_ZOOM,
66: OPT_RESOLUTION, /* Falcon/TT display options */
67: OPT_MAXWIDTH,
68: OPT_MAXHEIGHT,
69: OPT_ASPECT,
1.1 root 70: OPT_VDI, /* VDI options */
71: OPT_VDI_PLANES,
72: OPT_VDI_WIDTH,
73: OPT_VDI_HEIGHT,
1.1.1.2 root 74: OPT_SCREEN_CROP, /* screen capture options */
75: OPT_AVIRECORD,
1.1 root 76: OPT_AVIRECORD_VCODEC,
77: OPT_AVIRECORD_FPS,
78: OPT_AVIRECORD_FILE,
79: OPT_JOYSTICK, /* device options */
80: OPT_JOYSTICK0,
81: OPT_JOYSTICK1,
82: OPT_JOYSTICK2,
83: OPT_JOYSTICK3,
84: OPT_JOYSTICK4,
85: OPT_JOYSTICK5,
86: OPT_PRINTER,
87: OPT_MIDI_IN,
88: OPT_MIDI_OUT,
89: OPT_RS232_IN,
90: OPT_RS232_OUT,
91: OPT_DISKA, /* disk options */
92: OPT_DISKB,
93: OPT_SLOWFLOPPY,
94: OPT_WRITEPROT_FLOPPY,
95: OPT_WRITEPROT_HD,
96: OPT_HARDDRIVE,
97: OPT_ACSIHDIMAGE,
98: OPT_IDEMASTERHDIMAGE,
99: OPT_IDESLAVEHDIMAGE,
100: OPT_MEMSIZE, /* memory options */
101: OPT_TOS,
102: OPT_CARTRIDGE,
103: OPT_MEMSTATE,
104: OPT_CPULEVEL, /* CPU options */
105: OPT_CPUCLOCK,
106: OPT_COMPATIBLE,
1.1.1.2 root 107: #if ENABLE_WINUAE_CPU
108: OPT_CPU_CYCLE_EXACT, /* WinUAE CPU/FPU/bus options */
109: OPT_CPU_ADDR24,
110: OPT_FPU_TYPE,
111: OPT_FPU_COMPATIBLE,
112: OPT_MMU,
113: #endif
1.1 root 114: OPT_MACHINE, /* system options */
115: OPT_BLITTER,
116: OPT_DSP,
1.1.1.2 root 117: OPT_MICROPHONE,
1.1 root 118: OPT_SOUND,
119: OPT_SOUNDBUFFERSIZE,
1.1.1.2 root 120: OPT_YM_MIXING,
121: OPT_TIMERD,
122: OPT_RTC,
1.1 root 123: OPT_DEBUG, /* debug options */
124: OPT_BIOSINTERCEPT,
125: OPT_TRACE,
126: OPT_TRACEFILE,
127: OPT_PARSE,
128: OPT_SAVECONFIG,
129: OPT_PARACHUTE,
130: OPT_CONTROLSOCKET,
131: OPT_LOGFILE,
132: OPT_LOGLEVEL,
133: OPT_ALERTLEVEL,
134: OPT_RUNVBLS,
135: OPT_ERROR,
136: OPT_CONTINUE
137: };
138:
139: typedef struct {
140: unsigned int id; /* option ID */
141: const char *chr; /* short option */
142: const char *str; /* long option */
143: const char *arg; /* type name for argument, if any */
144: const char *desc; /* option description */
145: } opt_t;
146:
147: /* it's easier to edit these if they are kept in the same order as the enums */
148: static const opt_t HatariOptions[] = {
149:
150: { OPT_HEADER, NULL, NULL, NULL, "General" },
151: { OPT_HELP, "-h", "--help",
152: NULL, "Print this help text and exit" },
153: { OPT_VERSION, "-v", "--version",
154: NULL, "Print version number and exit" },
155: { OPT_CONFIRMQUIT, NULL, "--confirm-quit",
156: "<bool>", "Whether Hatari confirms quit" },
157: { OPT_CONFIGFILE, "-c", "--configfile",
158: "<file>", "Use <file> instead of the default hatari config file" },
1.1.1.2 root 159: { OPT_KEYMAPFILE, "-k", "--keymap",
160: "<file>", "Read (additional) keyboard mappings from <file>" },
1.1 root 161: { OPT_FASTFORWARD, NULL, "--fast-forward",
162: "<bool>", "Help skipping stuff on fast machine" },
163:
1.1.1.2 root 164: { OPT_HEADER, NULL, NULL, NULL, "Common display" },
1.1 root 165: { OPT_MONO, "-m", "--mono",
166: NULL, "Start in monochrome mode instead of color" },
167: { OPT_MONITOR, NULL, "--monitor",
168: "<x>", "Select monitor type (x = mono/rgb/vga/tv)" },
169: { OPT_FULLSCREEN,"-f", "--fullscreen",
170: NULL, "Start emulator in fullscreen mode" },
171: { OPT_WINDOW, "-w", "--window",
172: NULL, "Start emulator in window mode" },
173: { OPT_GRAB, NULL, "--grab",
174: NULL, "Grab mouse (also) in window mode" },
175: { OPT_FRAMESKIPS, NULL, "--frameskips",
176: "<x>", "Skip <x> frames after each shown frame (0=off, >4=auto/max)" },
177: { OPT_STATUSBAR, NULL, "--statusbar",
178: "<bool>", "Show statusbar (floppy leds etc)" },
179: { OPT_DRIVE_LED, NULL, "--drive-led",
180: "<bool>", "Show overlay drive led when statusbar isn't shown" },
181: { OPT_FORCEBPP, NULL, "--bpp",
182: "<x>", "Force internal bitdepth (x = 8/15/16/32, 0=disable)" },
183:
1.1.1.2 root 184: { OPT_HEADER, NULL, NULL, NULL, "ST/STE specific display" },
185: { OPT_BORDERS, NULL, "--borders",
186: "<bool>", "Show screen borders (for overscan demos etc)" },
187: { OPT_SPEC512, NULL, "--spec512",
188: "<x>", "Spec512 palette threshold (0 <= x <= 512, 0=disable)" },
189: { OPT_ZOOM, "-z", "--zoom",
190: "<x>", "Double small resolutions (1=no, 2=yes)" },
191:
192: { OPT_HEADER, NULL, NULL, NULL, "Falcon/TT specific display" },
193: { OPT_RESOLUTION, NULL, "--desktop",
194: "<bool>", "Keep desktop resolution on fullscreen" },
195: { OPT_MAXWIDTH, NULL, "--max-width",
196: "<x>", "Maximum window width for zooming" },
197: { OPT_MAXHEIGHT, NULL, "--max-height",
198: "<x>", "Maximum window height for zooming" },
199: { OPT_ASPECT, NULL, "--aspect",
200: "<bool>", "Monitor aspect ratio correction" },
201:
1.1 root 202: { OPT_HEADER, NULL, NULL, NULL, "VDI" },
203: { OPT_VDI, NULL, "--vdi",
204: "<bool>", "Whether to use VDI screen mode" },
205: { OPT_VDI_PLANES,NULL, "--vdi-planes",
206: "<x>", "VDI mode bit-depth (x = 1/2/4)" },
207: { OPT_VDI_WIDTH, NULL, "--vdi-width",
208: "<w>", "VDI mode width (320 < w <= 1280)" },
209: { OPT_VDI_HEIGHT, NULL, "--vdi-height",
210: "<h>", "VDI mode height (200 < h <= 960)" },
211:
1.1.1.2 root 212: { OPT_HEADER, NULL, NULL, NULL, "Screen capture" },
213: { OPT_SCREEN_CROP, NULL, "--crop",
214: "<bool>", "Remove statusbar from screen capture" },
1.1 root 215: { OPT_AVIRECORD, NULL, "--avirecord",
216: NULL, "Start AVI recording" },
217: { OPT_AVIRECORD_VCODEC, NULL, "--avi-vcodec",
218: "<x>", "Select avi video codec (x = bmp/png)" },
219: { OPT_AVIRECORD_FPS, NULL, "--avi-fps",
220: "<x>", "Force avi frame rate (x = 50/60/71/...)" },
221: { OPT_AVIRECORD_FILE, NULL, "--avi-file",
222: "<file>", "Use <file> to record avi" },
223:
224: { OPT_HEADER, NULL, NULL, NULL, "Devices" },
225: { OPT_JOYSTICK, "-j", "--joystick",
226: "<port>", "Emulate joystick with cursor keys in given port (0-5)" },
227: /* these have to be exactly the same as I'm relying compiler giving
228: * them the same same string pointer when strings are identical
229: * (Opt_ShowHelpSection() skips successive options with same help
230: * pointer).
231: */
232: { OPT_JOYSTICK0, NULL, "--joy<port>",
233: "<type>", "Set joystick type (none/keys/real) for given port" },
234: { OPT_JOYSTICK1, NULL, "--joy<port>",
235: "<type>", "Set joystick type (none/keys/real) for given port" },
236: { OPT_JOYSTICK2, NULL, "--joy<port>",
237: "<type>", "Set joystick type (none/keys/real) for given port" },
238: { OPT_JOYSTICK3, NULL, "--joy<port>",
239: "<type>", "Set joystick type (none/keys/real) for given port" },
240: { OPT_JOYSTICK4, NULL, "--joy<port>",
241: "<type>", "Set joystick type (none/keys/real) for given port" },
242: { OPT_JOYSTICK5, NULL, "--joy<port>",
243: "<type>", "Set joystick type (none/keys/real) for given port" },
244: { OPT_PRINTER, NULL, "--printer",
245: "<file>", "Enable printer support and write data to <file>" },
246: { OPT_MIDI_IN, NULL, "--midi-in",
247: "<file>", "Enable MIDI and use <file> as the input device" },
248: { OPT_MIDI_OUT, NULL, "--midi-out",
249: "<file>", "Enable MIDI and use <file> as the output device" },
250: { OPT_RS232_IN, NULL, "--rs232-in",
251: "<file>", "Enable serial port and use <file> as the input device" },
252: { OPT_RS232_OUT, NULL, "--rs232-out",
253: "<file>", "Enable serial port and use <file> as the output device" },
254:
255: { OPT_HEADER, NULL, NULL, NULL, "Disk" },
256: { OPT_DISKA, NULL, "--disk-a",
257: "<file>", "Set disk image for floppy drive A" },
258: { OPT_DISKB, NULL, "--disk-b",
259: "<file>", "Set disk image for floppy drive B" },
260: { OPT_SLOWFLOPPY, NULL, "--slowfdc",
261: "<bool>", "Slow down floppy disk access emulation" },
262: { OPT_WRITEPROT_FLOPPY, NULL, "--protect-floppy",
263: "<x>", "Write protect floppy image contents (on/off/auto)" },
264: { OPT_WRITEPROT_HD, NULL, "--protect-hd",
265: "<x>", "Write protect harddrive <dir> contents (on/off/auto)" },
266: { OPT_HARDDRIVE, "-d", "--harddrive",
267: "<dir>", "Emulate harddrive partition(s) with <dir> contents" },
268: { OPT_ACSIHDIMAGE, NULL, "--acsi",
269: "<file>", "Emulate an ACSI harddrive with an image <file>" },
270: { OPT_IDEMASTERHDIMAGE, NULL, "--ide-master",
271: "<file>", "Emulate an IDE master harddrive with an image <file>" },
272: { OPT_IDESLAVEHDIMAGE, NULL, "--ide-slave",
273: "<file>", "Emulate an IDE slave harddrive with an image <file>" },
274:
275: { OPT_HEADER, NULL, NULL, NULL, "Memory" },
276: { OPT_MEMSIZE, "-s", "--memsize",
277: "<x>", "ST RAM size (x = size in MiB from 0 to 14, 0 = 512KiB)" },
278: { OPT_TOS, "-t", "--tos",
279: "<file>", "Use TOS image <file>" },
280: { OPT_CARTRIDGE, NULL, "--cartridge",
281: "<file>", "Use ROM cartridge image <file>" },
282: { OPT_MEMSTATE, NULL, "--memstate",
283: "<file>", "Load memory snap-shot <file>" },
284:
285: { OPT_HEADER, NULL, NULL, NULL, "CPU" },
286: { OPT_CPULEVEL, NULL, "--cpulevel",
287: "<x>", "Set the CPU type (x => 680x0) (EmuTOS/TOS 2.06 only!)" },
288: { OPT_CPUCLOCK, NULL, "--cpuclock",
289: "<x>", "Set the CPU clock (x = 8/16/32)" },
290: { OPT_COMPATIBLE, NULL, "--compatible",
291: "<bool>", "Use a more compatible (but slower) 68000 CPU mode" },
1.1.1.2 root 292:
293: #if ENABLE_WINUAE_CPU
294: { OPT_HEADER, NULL, NULL, NULL, "WinUAE CPU/FPU/bus" },
295: { OPT_CPU_CYCLE_EXACT, NULL, "--cpu-exact",
296: "<bool>", "Use cycle exact CPU emulation" },
297: { OPT_CPU_ADDR24, NULL, "--addr24",
298: "<bool>", "Use 24-bit instead of 32-bit addressing mode" },
299: { OPT_FPU_TYPE, NULL, "--fpu-type",
300: "<x>", "FPU type (x=none/68881/68882/internal)" },
301: { OPT_FPU_COMPATIBLE, NULL, "--fpu-compatible",
302: "<bool>", "Use more compatible, but slower FPU emulation" },
303: { OPT_MMU, NULL, "--mmu",
304: "<bool>", "Use MMU emulation" },
305: #endif
306:
1.1 root 307: { OPT_HEADER, NULL, NULL, NULL, "Misc system" },
308: { OPT_MACHINE, NULL, "--machine",
309: "<x>", "Select machine type (x = st/ste/tt/falcon)" },
310: { OPT_BLITTER, NULL, "--blitter",
311: "<bool>", "Use blitter emulation (ST only)" },
312: { OPT_DSP, NULL, "--dsp",
313: "<x>", "DSP emulation (x = none/dummy/emu, Falcon only)" },
1.1.1.2 root 314: { OPT_MICROPHONE, NULL, "--mic",
315: "<bool>", "Enable/disable (Falcon only) microphone" },
1.1 root 316: { OPT_SOUND, NULL, "--sound",
317: "<x>", "Sound frequency (x=off/6000-50066, off=fastest)" },
318: { OPT_SOUNDBUFFERSIZE, NULL, "--sound-buffer-size",
1.1.1.2 root 319: "<x>", "Sound buffer size for SDL in ms (x=0/10-100, 0=default)" },
320: { OPT_YM_MIXING, NULL, "--ym-mixing",
321: "<x>", "YM sound mixing method (x=linear/table)" },
322: { OPT_TIMERD, NULL, "--timer-d",
323: "<bool>", "Patch Timer-D (about doubles ST emulation speed)" },
324: { OPT_RTC, NULL, "--rtc",
325: "<bool>", "Enable real-time clock" },
326:
1.1 root 327: { OPT_HEADER, NULL, NULL, NULL, "Debug" },
328: { OPT_DEBUG, "-D", "--debug",
329: NULL, "Toggle whether CPU exceptions invoke debugger" },
330: { OPT_BIOSINTERCEPT, NULL, "--bios-intercept",
1.1.1.2 root 331: NULL, "Toggle X/Bios interception & CON: redirection" },
1.1 root 332: { OPT_TRACE, NULL, "--trace",
333: "<trace1,...>", "Activate emulation tracing, see '--trace help'" },
334: { OPT_TRACEFILE, NULL, "--trace-file",
335: "<file>", "Save trace output to <file> (default=stderr)" },
336: { OPT_PARSE, NULL, "--parse",
337: "<file>", "Parse/execute debugger commands from <file>" },
338: { OPT_SAVECONFIG, NULL, "--saveconfig",
339: NULL, "Save current Hatari configuration and exit" },
340: { OPT_PARACHUTE, NULL, "--no-parachute",
341: NULL, "Disable SDL parachute to get Hatari core dumps" },
342: #if HAVE_UNIX_DOMAIN_SOCKETS
343: { OPT_CONTROLSOCKET, NULL, "--control-socket",
344: "<file>", "Hatari reads options from given socket at run-time" },
345: #endif
346: { OPT_LOGFILE, NULL, "--log-file",
347: "<file>", "Save log output to <file> (default=stderr)" },
348: { OPT_LOGLEVEL, NULL, "--log-level",
349: "<x>", "Log output level (x=debug/todo/info/warn/error/fatal)" },
350: { OPT_ALERTLEVEL, NULL, "--alert-level",
351: "<x>", "Show dialog for log messages above given level" },
352: { OPT_RUNVBLS, NULL, "--run-vbls",
353: "<x>", "Exit after x VBLs" },
354:
355: { OPT_ERROR, NULL, NULL, NULL, NULL }
356: };
357:
358:
359: /**
360: * Show version string and license.
361: */
362: static void Opt_ShowVersion(void)
363: {
364: printf("\n" PROG_NAME
365: " - the Atari ST, STE, TT and Falcon emulator.\n\n");
366: printf("Hatari is free software licensed under the GNU General"
367: " Public License.\n\n");
368: }
369:
370:
371: /**
372: * Calculate option + value len
373: */
374: static unsigned int Opt_OptionLen(const opt_t *opt)
375: {
376: unsigned int len;
377: len = strlen(opt->str);
378: if (opt->arg)
379: {
380: len += strlen(opt->arg);
381: len += 1;
382: /* with arg, short options go to another line */
383: }
384: else
385: {
386: if (opt->chr)
387: {
388: /* ' or -c' */
389: len += 6;
390: }
391: }
392: return len;
393: }
394:
395:
396: /**
397: * Show single option
398: */
399: static void Opt_ShowOption(const opt_t *opt, unsigned int maxlen)
400: {
401: char buf[64];
402: if (!maxlen)
403: {
404: maxlen = Opt_OptionLen(opt);
405: }
406: assert(maxlen < sizeof(buf));
407: if (opt->arg)
408: {
409: sprintf(buf, "%s %s", opt->str, opt->arg);
410: printf(" %-*s %s\n", maxlen, buf, opt->desc);
411: if (opt->chr)
412: {
413: printf(" or %s %s\n", opt->chr, opt->arg);
414: }
415: }
416: else
417: {
418: if (opt->chr)
419: {
420: sprintf(buf, "%s or %s", opt->str, opt->chr);
421: printf(" %-*s %s\n", maxlen, buf, opt->desc);
422: }
423: else
424: {
425: printf(" %-*s %s\n", maxlen, opt->str, opt->desc);
426: }
427: }
428: }
429:
430: /**
431: * Show options for section starting from 'start_opt',
432: * return next option after this section.
433: */
434: static const opt_t *Opt_ShowHelpSection(const opt_t *start_opt)
435: {
436: const opt_t *opt, *last;
437: unsigned int len, maxlen = 0;
438: const char *previous = NULL;
439:
440: /* find longest option name and check option IDs */
441: for (opt = start_opt; opt->id != OPT_HEADER && opt->id != OPT_ERROR; opt++)
442: {
443: len = Opt_OptionLen(opt);
444: if (len > maxlen)
445: {
446: maxlen = len;
447: }
448: }
449: last = opt;
450:
451: /* output all options */
452: for (opt = start_opt; opt != last; opt++)
453: {
454: if (previous != opt->str)
455: {
456: Opt_ShowOption(opt, maxlen);
457: }
458: previous = opt->str;
459: }
460: return last;
461: }
462:
463:
464: /**
465: * Show help text.
466: */
467: static void Opt_ShowHelp(void)
468: {
469: const opt_t *opt = HatariOptions;
470:
471: Opt_ShowVersion();
1.1.1.2 root 472: printf("Usage:\n hatari [options] [directory|disk image|Atari program]\n");
1.1 root 473:
474: while(opt->id != OPT_ERROR)
475: {
476: if (opt->id == OPT_HEADER)
477: {
478: assert(opt->desc);
479: printf("\n%s options:\n", opt->desc);
480: opt++;
481: }
482: opt = Opt_ShowHelpSection(opt);
483: }
484: printf("\nSpecial option values:\n");
485: printf("<bool>\tDisable by using 'n', 'no', 'off', 'false', or '0'\n");
486: printf("\tEnable by using 'y', 'yes', 'on', 'true' or '1'\n");
487: printf("<file>\tDevices accept also special 'stdout' and 'stderr' file names\n");
488: printf("\t(if you use stdout for midi or printer, set log to stderr).\n");
489: printf("\tSetting the file to 'none', disables given device or disk\n");
490: }
491:
492:
493: /**
494: * Show Hatari version and usage.
495: * If 'error' given, show that error message.
496: * If 'optid' != OPT_ERROR, tells for which option the error is,
497: * otherwise 'value' is show as the option user gave.
498: * Return false if error string was given, otherwise true
499: */
500: static bool Opt_ShowError(unsigned int optid, const char *value, const char *error)
501: {
502: const opt_t *opt;
503:
504: Opt_ShowVersion();
505: printf("Usage:\n hatari [options] [disk image name]\n\n"
506: "Try option \"-h\" or \"--help\" to display more information.\n");
507:
508: if (error)
509: {
510: if (optid == OPT_ERROR)
511: {
512: fprintf(stderr, "\nError: %s (%s)\n", error, value);
513: }
514: else
515: {
516: for (opt = HatariOptions; opt->id != OPT_ERROR; opt++)
517: {
518: if (optid == opt->id)
519: break;
520: }
521: if (value != NULL)
522: {
523: fprintf(stderr,
524: "\nError while parsing argument \"%s\" for option \"%s\":\n"
525: " %s\n", value, opt->str, error);
526: }
527: else
528: {
529: fprintf(stderr, "\nError (%s): %s\n", opt->str, error);
530: }
531: fprintf(stderr, "\nOption usage:\n");
532: Opt_ShowOption(opt, 0);
533: }
534: return false;
535: }
536: return true;
537: }
538:
539:
540: /**
541: * If 'conf' given, set it:
542: * - true if given option 'arg' is y/yes/on/true/1
543: * - false if given option 'arg' is n/no/off/false/0
544: * Return false for any other value, otherwise true
545: */
546: static bool Opt_Bool(const char *arg, int optid, bool *conf)
547: {
548: const char *enablers[] = { "y", "yes", "on", "true", "1", NULL };
549: const char *disablers[] = { "n", "no", "off", "false", "0", NULL };
550: const char **bool_str, *orig = arg;
551: char *input, *str;
552:
553: input = strdup(arg);
554: str = input;
555: while (*str)
556: {
557: *str++ = tolower(*arg++);
558: }
559: for (bool_str = enablers; *bool_str; bool_str++)
560: {
561: if (strcmp(input, *bool_str) == 0)
562: {
563: free(input);
564: if (conf)
565: {
566: *conf = true;
567: }
568: return true;
569: }
570: }
571: for (bool_str = disablers; *bool_str; bool_str++)
572: {
573: if (strcmp(input, *bool_str) == 0)
574: {
575: free(input);
576: if (conf)
577: {
578: *conf = false;
579: }
580: return true;
581: }
582: }
583: free(input);
584: return Opt_ShowError(optid, orig, "Not a <bool> value");
585: }
586:
587:
588: /**
589: * checks str argument agaist options of type "--option<digit>".
590: * If match is found, returns ID for that, otherwise OPT_CONTINUE
591: * and OPT_ERROR for errors.
592: */
593: static int Opt_CheckBracketValue(const opt_t *opt, const char *str)
594: {
595: const char *bracket, *optstr;
596: size_t offset;
597: int digit, i;
598:
599: if (!opt->str)
600: {
601: return OPT_CONTINUE;
602: }
603: bracket = strchr(opt->str, '<');
604: if (!bracket)
605: {
606: return OPT_CONTINUE;
607: }
608: offset = bracket - opt->str;
609: if (strncmp(opt->str, str, offset) != 0)
610: {
611: return OPT_CONTINUE;
612: }
613: digit = str[offset] - '0';
614: if (digit < 0 || digit > 9)
615: {
616: return OPT_CONTINUE;
617: }
618: optstr = opt->str;
619: for (i = 0; opt->str == optstr; opt++, i++)
620: {
621: if (i == digit)
622: {
623: return opt->id;
624: }
625: }
626: /* fprintf(stderr, "opt: %s (%d), str: %s (%d), digit: %d\n",
627: opt->str, offset+1, str, strlen(str), digit);
628: */
629: return OPT_ERROR;
630: }
631:
632:
633: /**
634: * matches string under given index in the argv against all Hatari
635: * short and long options. If match is found, returns ID for that,
636: * otherwise shows help and returns OPT_ERROR.
637: *
638: * Checks also that if option is supposed to have argument,
639: * whether there's one.
640: */
1.1.1.2 root 641: static int Opt_WhichOption(int argc, const char * const argv[], int idx)
1.1 root 642: {
643: const opt_t *opt;
644: const char *str = argv[idx];
645: int id;
646:
647: for (opt = HatariOptions; opt->id != OPT_ERROR; opt++)
648: {
649: /* exact option name matches? */
650: if (!((opt->str && !strcmp(str, opt->str)) ||
651: (opt->chr && !strcmp(str, opt->chr))))
652: {
653: /* no, maybe name<digit> matches? */
654: id = Opt_CheckBracketValue(opt, str);
655: if (id == OPT_CONTINUE)
656: {
657: continue;
658: }
659: if (id == OPT_ERROR)
660: {
661: break;
662: }
663: }
664: /* matched, check args */
665: if (opt->arg)
666: {
667: if (idx+1 >= argc)
668: {
669: Opt_ShowError(opt->id, NULL, "Missing argument");
670: return OPT_ERROR;
671: }
672: /* early check for bools */
673: if (strcmp(opt->arg, "<bool>") == 0)
674: {
675: if (!Opt_Bool(argv[idx+1], opt->id, NULL))
676: {
677: return OPT_ERROR;
678: }
679: }
680: }
681: return opt->id;
682: }
683: Opt_ShowError(OPT_ERROR, argv[idx], "Unrecognized option");
684: return OPT_ERROR;
685: }
686:
687:
688: /**
689: * If 'checkexits' is true, assume 'src' is a file and check whether it
690: * exists before copying 'src' to 'dst'. Otherwise just copy option src
691: * string to dst.
692: * If a pointer to (bool) 'option' is given, set that option to true.
693: * - However, if src is "none", leave dst unmodified & set option to false.
694: * ("none" is used to disable options related to file arguments)
695: * Return false if there were errors, otherwise true
696: */
697: static bool Opt_StrCpy(int optid, bool checkexist, char *dst, const char *src, size_t dstlen, bool *option)
698: {
699: if (option)
700: {
701: *option = false;
702: if(strcasecmp(src, "none") == 0)
703: {
704: return true;
705: }
706: }
707: if (strlen(src) >= dstlen)
708: {
709: return Opt_ShowError(optid, src, "File name too long!");
710: }
711: if (checkexist && !File_Exists(src))
712: {
713: return Opt_ShowError(optid, src, "Given file doesn't exist (or has wrong file permissions)!");
714: }
715: if (option)
716: {
717: *option = true;
718: }
719: strcpy(dst, src);
720: return true;
721: }
722:
723:
724: /**
725: * Return SDL_INIT_NOPARACHUTE flag if user requested SDL parachute
726: * to be disabled to get proper Hatari core dumps. By default returns
727: * zero so that SDL parachute will be used to restore video mode on
728: * unclean Hatari termination.
729: */
730: Uint32 Opt_GetNoParachuteFlag(void)
731: {
732: if (bNoSDLParachute) {
733: return SDL_INIT_NOPARACHUTE;
734: }
735: return 0;
736: }
737:
738:
739: /**
1.1.1.2 root 740: * Handle last (non-option) argument. It can be a path or filename.
741: * Filename can be a disk image or Atari program.
742: * Return false if it's none of these.
743: */
744: static bool Opt_HandleArgument(const char *path)
745: {
746: char *dir = NULL;
747: Uint8 test[2];
748: FILE *fp;
749:
750: /* Atari program? */
751: if (File_Exists(path) && (fp = fopen(path, "rb"))) {
752:
753: /* file starts with GEMDOS magic? */
754: if (fread(test, 1, 2, fp) == 2 &&
755: test[0] == 0x60 && test[1] == 0x1A) {
756:
757: const char *prgname = strrchr(path, PATHSEP);
758: if (prgname) {
759: dir = strdup(path);
760: dir[prgname-path] = '\0';
761: prgname++;
762: } else {
763: dir = strdup(Paths_GetWorkingDir());
764: prgname = path;
765: }
766: /* after above, dir should point to valid dir,
767: * then make sure that given program from that
768: * dir will be started.
769: */
770: // TOS_AutoStart(prgname);
771: }
772: fclose(fp);
773: }
774: if (dir) {
775: path = dir;
776: }
777:
778: /* GEMDOS HDD directory (as argument, or for the Atari program)? */
779: if (File_DirExists(path)) {
1.1.1.3 ! root 780: // if (Opt_StrCpy(OPT_HARDDRIVE, false, ConfigureParams.HardDisk.szHardDiskDirectories[0],
! 781: // path, sizeof(ConfigureParams.HardDisk.szHardDiskDirectories[0]),
! 782: // &ConfigureParams.HardDisk.bUseHardDiskDirectories)
! 783: // && ConfigureParams.HardDisk.bUseHardDiskDirectories)
1.1.1.2 root 784: {
1.1.1.3 ! root 785: ConfigureParams.SCSI.bBootFromHardDisk = true;
1.1.1.2 root 786: }
787: bLoadAutoSave = false;
788: if (dir) {
789: free(dir);
790: }
791: return true;
792: } else {
793: if (dir) {
794: /* if dir is set, it should be valid... */
795: Log_Printf(LOG_ERROR, "Given atari program path '%s' doesn't exist (anymore?)!\n", dir);
796: free(dir);
797: exit(1);
798: }
799: }
800:
801: /* disk image? */
802: // if (Floppy_SetDiskFileName(0, path, NULL))
803: // {
804: // ConfigureParams.HardDisk.bBootFromHardDisk = false;
805: // bLoadAutoSave = false;
806: // return true;
807: // }
808:
809: return Opt_ShowError(OPT_ERROR, path, "Not a disk image, Atari program or directory");
810: }
811:
812: /**
1.1 root 813: * parse all Hatari command line options and set Hatari state accordingly.
814: * Returns true if everything was OK, false otherwise.
815: */
1.1.1.2 root 816: bool Opt_ParseParameters(int argc, const char * const argv[])
1.1 root 817: {
818: int ncpu, skips, zoom, planes, cpuclock, threshold, memsize, port, freq, temp;
819: const char *errstr;
820: int i, ok = true;
821: int val;
822:
823: /* Defaults for loading initial memory snap-shots */
824: bLoadMemorySave = false;
825: bLoadAutoSave = ConfigureParams.Memory.bAutoSave;
826:
827: for(i = 1; i < argc; i++)
828: {
1.1.1.2 root 829: /* last argument can be a non-option */
830: if (argv[i][0] != '-' && i+1 == argc)
831: return Opt_HandleArgument(argv[i]);
1.1 root 832:
833: /* WhichOption() checks also that there is an argument,
834: * so we don't need to check that below
835: */
836: switch(Opt_WhichOption(argc, argv, i))
837: {
838:
839: /* general options */
840: case OPT_HELP:
841: Opt_ShowHelp();
842: return false;
843:
844: case OPT_VERSION:
845: Opt_ShowVersion();
846: return false;
847:
848: case OPT_CONFIRMQUIT:
849: ok = Opt_Bool(argv[++i], OPT_CONFIRMQUIT, &ConfigureParams.Log.bConfirmQuit);
850: break;
851:
852: case OPT_FASTFORWARD:
853: ok = Opt_Bool(argv[++i], OPT_FASTFORWARD, &ConfigureParams.System.bFastForward);
854: break;
855:
856: case OPT_CONFIGFILE:
857: i += 1;
858: /* true -> file needs to exist */
859: ok = Opt_StrCpy(OPT_CONFIGFILE, true, sConfigFileName,
860: argv[i], sizeof(sConfigFileName), NULL);
861: if (ok)
862: {
863: Configuration_Load(NULL);
864: bLoadAutoSave = ConfigureParams.Memory.bAutoSave;
865: }
866: break;
867:
1.1.1.2 root 868: /* common display options */
1.1 root 869: case OPT_MONO:
870: ConfigureParams.Screen.nMonitorType = MONITOR_TYPE_MONO;
871: bLoadAutoSave = false;
872: break;
873:
874: case OPT_MONITOR:
875: i += 1;
876: if (strcasecmp(argv[i], "mono") == 0)
877: {
878: ConfigureParams.Screen.nMonitorType = MONITOR_TYPE_MONO;
879: }
880: else if (strcasecmp(argv[i], "rgb") == 0)
881: {
882: ConfigureParams.Screen.nMonitorType = MONITOR_TYPE_RGB;
883: }
884: else if (strcasecmp(argv[i], "vga") == 0)
885: {
886: ConfigureParams.Screen.nMonitorType = MONITOR_TYPE_VGA;
887: }
888: else if (strcasecmp(argv[i], "tv") == 0)
889: {
890: ConfigureParams.Screen.nMonitorType = MONITOR_TYPE_TV;
891: }
892: else
893: {
894: return Opt_ShowError(OPT_MONITOR, argv[i], "Unknown monitor type");
895: }
896: bLoadAutoSave = false;
897: break;
898:
899: case OPT_FULLSCREEN:
900: ConfigureParams.Screen.bFullScreen = true;
901: break;
902:
903: case OPT_WINDOW:
904: ConfigureParams.Screen.bFullScreen = false;
905: break;
906:
907: case OPT_GRAB:
908: bGrabMouse = true;
909: break;
910:
911: case OPT_FRAMESKIPS:
912: skips = atoi(argv[++i]);
913: if (skips < 0)
914: {
915: return Opt_ShowError(OPT_FRAMESKIPS, argv[i],
916: "Invalid frame skip value");
917: }
918: else if (skips > 8)
919: {
920: Log_Printf(LOG_WARN, "Extravagant frame skip value %d!\n", skips);
921: }
922: ConfigureParams.Screen.nFrameSkips = skips;
923: break;
924:
925: case OPT_STATUSBAR:
926: ok = Opt_Bool(argv[++i], OPT_STATUSBAR, &ConfigureParams.Screen.bShowStatusbar);
927: break;
928:
929: case OPT_DRIVE_LED:
930: ok = Opt_Bool(argv[++i], OPT_DRIVE_LED, &ConfigureParams.Screen.bShowDriveLed);
931: break;
932:
933: case OPT_FORCEBPP:
934: planes = atoi(argv[++i]);
935: switch(planes)
936: {
937: case 32:
938: case 16:
939: case 15:
940: case 8:
941: break; /* supported */
942: case 24:
943: planes = 32; /* We do not support 24 bpp (yet) */
944: break;
945: default:
946: return Opt_ShowError(OPT_FORCEBPP, argv[i], "Invalid bit depth");
947: }
948: ConfigureParams.Screen.nForceBpp = planes;
949: break;
1.1.1.2 root 950:
951: /* ST/STE display options */
952: case OPT_BORDERS:
953: ok = Opt_Bool(argv[++i], OPT_BORDERS, &ConfigureParams.Screen.bAllowOverscan);
954: break;
955:
956: case OPT_SPEC512:
957: threshold = atoi(argv[++i]);
958: if (threshold < 0 || threshold > 512)
959: {
960: return Opt_ShowError(OPT_SPEC512, argv[i],
961: "Invalid palette writes per line threshold for Spec512");
962: }
963: ConfigureParams.Screen.nSpec512Threshold = threshold;
964: break;
965:
966: case OPT_ZOOM:
967: zoom = atoi(argv[++i]);
968: if (zoom < 1)
969: {
970: return Opt_ShowError(OPT_ZOOM, argv[i], "Invalid zoom value");
971: }
972: if (zoom > 1)
973: {
974: ConfigureParams.Screen.nMaxWidth = 320;
975: ConfigureParams.Screen.nMaxHeight = 200;
976: }
977: else
978: {
979: ConfigureParams.Screen.nMaxWidth = 1024;
980: ConfigureParams.Screen.nMaxHeight = 768;
981: }
982: break;
983:
984: /* Falcon/TT display options */
985: case OPT_RESOLUTION:
986: ok = Opt_Bool(argv[++i], OPT_RESOLUTION, &ConfigureParams.Screen.bKeepResolution);
987: break;
988:
989: case OPT_MAXWIDTH:
990: ConfigureParams.Screen.nMaxWidth = atoi(argv[++i]);
991: break;
992:
993: case OPT_MAXHEIGHT:
994: ConfigureParams.Screen.nMaxHeight = atoi(argv[++i]);
995: break;
996:
997: case OPT_ASPECT:
998: ok = Opt_Bool(argv[++i], OPT_ASPECT, &ConfigureParams.Screen.bAspectCorrect);
999: break;
1000:
1001: /* screen capture options */
1002: case OPT_SCREEN_CROP:
1003: ok = Opt_Bool(argv[++i], OPT_SCREEN_CROP, &ConfigureParams.Screen.bCrop);
1004: break;
1.1 root 1005:
1006: case OPT_AVIRECORD:
1007: AviRecordOnStartup = true;
1008: break;
1009:
1010: case OPT_AVIRECORD_VCODEC:
1011: i += 1;
1012: if (strcasecmp(argv[i], "bmp") == 0)
1013: {
1.1.1.2 root 1014: ConfigureParams.Video.AviRecordVcodec = AVI_RECORD_VIDEO_CODEC_BMP;
1.1 root 1015: }
1016: else if (strcasecmp(argv[i], "png") == 0)
1017: {
1.1.1.2 root 1018: ConfigureParams.Video.AviRecordVcodec = AVI_RECORD_VIDEO_CODEC_PNG;
1.1 root 1019: }
1020: else
1021: {
1022: return Opt_ShowError(OPT_AVIRECORD_VCODEC, argv[i], "Unknown video codec");
1023: }
1024: break;
1025:
1026: case OPT_AVIRECORD_FPS:
1027: val = atoi(argv[++i]);
1028: if (val < 0 || val > 100)
1029: {
1030: return Opt_ShowError(OPT_AVIRECORD_FPS, argv[i],
1031: "Invalid frame rate for avi recording");
1032: }
1.1.1.2 root 1033: ConfigureParams.Video.AviRecordFps = val;
1.1 root 1034: break;
1035:
1036: case OPT_AVIRECORD_FILE:
1037: i += 1;
1038: /* false -> file is created if it doesn't exist */
1.1.1.2 root 1039: ok = Opt_StrCpy(OPT_AVIRECORD_FILE, false, ConfigureParams.Video.AviRecordFile,
1040: argv[i], sizeof(ConfigureParams.Video.AviRecordFile), NULL);
1041: break;
1042:
1043: /* VDI options */
1044: case OPT_VDI:
1045: ok = Opt_Bool(argv[++i], OPT_VDI, &ConfigureParams.Screen.bUseExtVdiResolutions);
1046: if (ok)
1047: {
1048: bLoadAutoSave = false;
1049: }
1050: break;
1051:
1052: case OPT_VDI_PLANES:
1053: planes = atoi(argv[++i]);
1054: switch(planes)
1055: {
1056: case 1:
1057: // ConfigureParams.Screen.nVdiColors = GEMCOLOR_2;
1058: break;
1059: case 2:
1060: // ConfigureParams.Screen.nVdiColors = GEMCOLOR_4;
1061: break;
1062: case 4:
1063: // ConfigureParams.Screen.nVdiColors = GEMCOLOR_16;
1064: break;
1065: default:
1066: return Opt_ShowError(OPT_VDI_PLANES, argv[i], "Unsupported VDI bit-depth");
1067: }
1068: ConfigureParams.Screen.bUseExtVdiResolutions = true;
1069: bLoadAutoSave = false;
1070: break;
1071:
1072: case OPT_VDI_WIDTH:
1073: ConfigureParams.Screen.nVdiWidth = atoi(argv[++i]);
1074: ConfigureParams.Screen.bUseExtVdiResolutions = true;
1075: bLoadAutoSave = false;
1076: break;
1077:
1078: case OPT_VDI_HEIGHT:
1079: ConfigureParams.Screen.nVdiHeight = atoi(argv[++i]);
1080: ConfigureParams.Screen.bUseExtVdiResolutions = true;
1081: bLoadAutoSave = false;
1082: break;
1083:
1084: /* devices options */
1085: case OPT_JOYSTICK:
1086: i++;
1087: // if (strlen(argv[i]) != 1 ||
1088: // !Joy_SetCursorEmulation(argv[i][0] - '0'))
1089: // {
1090: // return Opt_ShowError(OPT_JOYSTICK, argv[i], "Invalid joystick port");
1091: // }
1092: break;
1093:
1094: case OPT_JOYSTICK0:
1095: case OPT_JOYSTICK1:
1096: case OPT_JOYSTICK2:
1097: case OPT_JOYSTICK3:
1098: case OPT_JOYSTICK4:
1099: case OPT_JOYSTICK5:
1100: port = argv[i][strlen(argv[i])-1] - '0';
1.1.1.3 ! root 1101: // assert(port >= 0 && port < JOYSTICK_COUNT);
1.1.1.2 root 1102: i += 1;
1103: if (strcasecmp(argv[i], "none") == 0)
1104: {
1.1.1.3 ! root 1105: // ConfigureParams.Joysticks.Joy[port].nJoystickMode = JOYSTICK_DISABLED;
1.1.1.2 root 1106: }
1107: else if (strcasecmp(argv[i], "keys") == 0)
1108: {
1.1.1.3 ! root 1109: // ConfigureParams.Joysticks.Joy[port].nJoystickMode = JOYSTICK_KEYBOARD;
1.1.1.2 root 1110: }
1111: else if (strcasecmp(argv[i], "real") == 0)
1112: {
1.1.1.3 ! root 1113: // ConfigureParams.Joysticks.Joy[port].nJoystickMode = JOYSTICK_REALSTICK;
1.1.1.2 root 1114: }
1115: else
1116: {
1117: return Opt_ShowError(OPT_JOYSTICK0+port, argv[i], "Invalid joystick type");
1118: }
1119: break;
1120:
1121: case OPT_PRINTER:
1122: i += 1;
1123: /* "none" can be used to disable printer */
1124: ok = Opt_StrCpy(OPT_PRINTER, false, ConfigureParams.Printer.szPrintToFileName,
1125: argv[i], sizeof(ConfigureParams.Printer.szPrintToFileName),
1126: &ConfigureParams.Printer.bEnablePrinting);
1127: break;
1128:
1129: case OPT_MIDI_IN:
1130: i += 1;
1131: ok = Opt_StrCpy(OPT_MIDI_IN, true, ConfigureParams.Midi.sMidiInFileName,
1132: argv[i], sizeof(ConfigureParams.Midi.sMidiInFileName),
1133: &ConfigureParams.Midi.bEnableMidi);
1134: break;
1135:
1136: case OPT_MIDI_OUT:
1137: i += 1;
1138: ok = Opt_StrCpy(OPT_MIDI_OUT, false, ConfigureParams.Midi.sMidiOutFileName,
1139: argv[i], sizeof(ConfigureParams.Midi.sMidiOutFileName),
1140: &ConfigureParams.Midi.bEnableMidi);
1141: break;
1142:
1143: case OPT_RS232_IN:
1144: i += 1;
1145: ok = Opt_StrCpy(OPT_RS232_IN, true, ConfigureParams.RS232.szInFileName,
1146: argv[i], sizeof(ConfigureParams.RS232.szInFileName),
1147: &ConfigureParams.RS232.bEnableRS232);
1148: break;
1149:
1150: case OPT_RS232_OUT:
1151: i += 1;
1152: ok = Opt_StrCpy(OPT_RS232_OUT, false, ConfigureParams.RS232.szOutFileName,
1153: argv[i], sizeof(ConfigureParams.RS232.szOutFileName),
1154: &ConfigureParams.RS232.bEnableRS232);
1155: break;
1156:
1157: /* disk options */
1158: case OPT_DISKA:
1159: i += 1;
1160: // if (Floppy_SetDiskFileName(0, argv[i], NULL))
1161: // {
1162: // ConfigureParams.HardDisk.bBootFromHardDisk = false;
1163: // bLoadAutoSave = false;
1164: // }
1165: // else
1166: // return Opt_ShowError(OPT_ERROR, argv[i], "Not a disk image");
1167: // break;
1168:
1169: case OPT_DISKB:
1170: i += 1;
1171: // if (Floppy_SetDiskFileName(1, argv[i], NULL))
1172: // bLoadAutoSave = false;
1173: // else
1174: // return Opt_ShowError(OPT_ERROR, argv[i], "Not a disk image");
1175: // break;
1176:
1177: case OPT_SLOWFLOPPY:
1178: ok = Opt_Bool(argv[++i], OPT_SLOWFLOPPY, &ConfigureParams.DiskImage.bSlowFloppy);
1179: break;
1180:
1181: case OPT_WRITEPROT_FLOPPY:
1182: i += 1;
1183: if (strcasecmp(argv[i], "off") == 0)
1184: ConfigureParams.DiskImage.nWriteProtection = WRITEPROT_OFF;
1185: else if (strcasecmp(argv[i], "on") == 0)
1186: ConfigureParams.DiskImage.nWriteProtection = WRITEPROT_ON;
1187: else if (strcasecmp(argv[i], "auto") == 0)
1188: ConfigureParams.DiskImage.nWriteProtection = WRITEPROT_AUTO;
1189: else
1190: return Opt_ShowError(OPT_WRITEPROT_FLOPPY, argv[i], "Unknown option value");
1191: break;
1192:
1193: case OPT_WRITEPROT_HD:
1194: i += 1;
1195: if (strcasecmp(argv[i], "off") == 0)
1.1.1.3 ! root 1196: ConfigureParams.SCSI.nWriteProtection = WRITEPROT_OFF;
1.1.1.2 root 1197: else if (strcasecmp(argv[i], "on") == 0)
1.1.1.3 ! root 1198: ConfigureParams.SCSI.nWriteProtection = WRITEPROT_ON;
1.1.1.2 root 1199: else if (strcasecmp(argv[i], "auto") == 0)
1.1.1.3 ! root 1200: ConfigureParams.SCSI.nWriteProtection = WRITEPROT_AUTO;
1.1.1.2 root 1201: else
1202: return Opt_ShowError(OPT_WRITEPROT_HD, argv[i], "Unknown option value");
1203: break;
1204:
1205: case OPT_HARDDRIVE:
1206: i += 1;
1.1.1.3 ! root 1207: // ok = Opt_StrCpy(OPT_HARDDRIVE, false, ConfigureParams.HardDisk.szHardDiskDirectories[0],
! 1208: // argv[i], sizeof(ConfigureParams.HardDisk.szHardDiskDirectories[0]),
! 1209: // &ConfigureParams.HardDisk.bUseHardDiskDirectories);
! 1210: // if (ok && ConfigureParams.HardDisk.bUseHardDiskDirectories)
1.1.1.2 root 1211: {
1.1.1.3 ! root 1212: ConfigureParams.SCSI.bBootFromHardDisk = true;
1.1.1.2 root 1213: }
1214: bLoadAutoSave = false;
1215: break;
1216:
1217: case OPT_ACSIHDIMAGE:
1218: i += 1;
1.1.1.3 ! root 1219: // ok = Opt_StrCpy(OPT_ACSIHDIMAGE, true, ConfigureParams.HardDisk.szHardDiskImage,
! 1220: // argv[i], sizeof(ConfigureParams.HardDisk.szHardDiskImage),
! 1221: // &ConfigureParams.HardDisk.bUseHardDiskImage);
1.1.1.2 root 1222: if (ok)
1223: {
1224: bLoadAutoSave = false;
1225: }
1226: break;
1227:
1228: case OPT_IDEMASTERHDIMAGE:
1229: i += 1;
1.1.1.3 ! root 1230: // ok = Opt_StrCpy(OPT_IDEMASTERHDIMAGE, true, ConfigureParams.HardDisk.szIdeMasterHardDiskImage,
! 1231: // argv[i], sizeof(ConfigureParams.HardDisk.szIdeMasterHardDiskImage),
! 1232: // &ConfigureParams.HardDisk.bUseIdeMasterHardDiskImage);
1.1.1.2 root 1233: if (ok)
1234: {
1235: bLoadAutoSave = false;
1236: }
1.1 root 1237: break;
1238:
1.1.1.2 root 1239: case OPT_IDESLAVEHDIMAGE:
1240: i += 1;
1.1.1.3 ! root 1241: // ok = Opt_StrCpy(OPT_IDESLAVEHDIMAGE, true, ConfigureParams.HardDisk.szIdeSlaveHardDiskImage,
! 1242: // argv[i], sizeof(ConfigureParams.HardDisk.szIdeSlaveHardDiskImage),
! 1243: // &ConfigureParams.HardDisk.bUseIdeSlaveHardDiskImage);
1.1.1.2 root 1244: if (ok)
1245: {
1246: bLoadAutoSave = false;
1247: }
1248: break;
1.1 root 1249:
1250: /* Memory options */
1251: case OPT_MEMSIZE:
1252: memsize = atoi(argv[++i]);
1253: if (memsize < 0 || memsize > 14)
1254: {
1255: return Opt_ShowError(OPT_MEMSIZE, argv[i], "Invalid memory size");
1256: }
1.1.1.3 ! root 1257: // ConfigureParams.Memory.nMemorySize = memsize;
1.1 root 1258: bLoadAutoSave = false;
1259: break;
1260:
1261: case OPT_TOS:
1262: i += 1;
1.1.1.3 ! root 1263: // ok = Opt_StrCpy(OPT_TOS, true, ConfigureParams.Rom.szTosImageFileName,
! 1264: // argv[i], sizeof(ConfigureParams.Rom.szTosImageFileName),
! 1265: // NULL);
1.1 root 1266: if (ok)
1267: {
1268: bLoadAutoSave = false;
1269: }
1270: break;
1271:
1272: case OPT_CARTRIDGE:
1273: i += 1;
1.1.1.3 ! root 1274: // ok = Opt_StrCpy(OPT_CARTRIDGE, true, ConfigureParams.Rom.szCartridgeImageFileName,
! 1275: // argv[i], sizeof(ConfigureParams.Rom.szCartridgeImageFileName),
! 1276: // NULL);
1.1 root 1277: if (ok)
1278: {
1279: bLoadAutoSave = false;
1280: }
1281: break;
1282:
1283: case OPT_MEMSTATE:
1284: i += 1;
1285: ok = Opt_StrCpy(OPT_MEMSTATE, true, ConfigureParams.Memory.szMemoryCaptureFileName,
1286: argv[i], sizeof(ConfigureParams.Memory.szMemoryCaptureFileName),
1287: NULL);
1288: if (ok)
1289: {
1290: bLoadMemorySave = true;
1291: bLoadAutoSave = false;
1292: }
1293: break;
1294:
1295: /* CPU options */
1296: case OPT_CPULEVEL:
1297: /* UAE core uses cpu_level variable */
1298: ncpu = atoi(argv[++i]);
1299: if(ncpu < 0 || ncpu > 4)
1300: {
1301: return Opt_ShowError(OPT_CPULEVEL, argv[i], "Invalid CPU level");
1302: }
1303: ConfigureParams.System.nCpuLevel = ncpu;
1304: bLoadAutoSave = false;
1305: break;
1306:
1307: case OPT_CPUCLOCK:
1308: cpuclock = atoi(argv[++i]);
1309: if(cpuclock != 8 && cpuclock != 16 && cpuclock != 32)
1310: {
1311: return Opt_ShowError(OPT_CPUCLOCK, argv[i], "Invalid CPU clock");
1312: }
1313: ConfigureParams.System.nCpuFreq = cpuclock;
1314: bLoadAutoSave = false;
1315: break;
1316:
1317: case OPT_COMPATIBLE:
1318: ok = Opt_Bool(argv[++i], OPT_COMPATIBLE, &ConfigureParams.System.bCompatibleCpu);
1319: if (ok)
1320: {
1321: bLoadAutoSave = false;
1322: }
1323: break;
1324:
1325: /* system options */
1326: case OPT_MACHINE:
1327: i += 1;
1328: if (strcasecmp(argv[i], "st") == 0)
1329: {
1.1.1.3 ! root 1330: // ConfigureParams.System.nMachineType = MACHINE_ST;
1.1 root 1331: ConfigureParams.System.nCpuLevel = 0;
1332: ConfigureParams.System.nCpuFreq = 8;
1333: }
1334: else if (strcasecmp(argv[i], "ste") == 0)
1335: {
1.1.1.3 ! root 1336: // ConfigureParams.System.nMachineType = MACHINE_STE;
1.1 root 1337: ConfigureParams.System.nCpuLevel = 0;
1338: ConfigureParams.System.nCpuFreq = 8;
1339: }
1340: else if (strcasecmp(argv[i], "tt") == 0)
1341: {
1.1.1.3 ! root 1342: // ConfigureParams.System.nMachineType = MACHINE_TT;
1.1 root 1343: ConfigureParams.System.nCpuLevel = 3;
1344: ConfigureParams.System.nCpuFreq = 32;
1345: }
1346: else if (strcasecmp(argv[i], "falcon") == 0)
1347: {
1.1.1.2 root 1348: #if ENABLE_DSP_EMU
1349: ConfigureParams.System.nDSPType = DSP_TYPE_EMU;
1350: #endif
1.1.1.3 ! root 1351: // ConfigureParams.System.nMachineType = MACHINE_FALCON;
1.1 root 1352: ConfigureParams.System.nCpuLevel = 3;
1353: ConfigureParams.System.nCpuFreq = 16;
1354: }
1355: else
1356: {
1357: return Opt_ShowError(OPT_MACHINE, argv[i], "Unknown machine type");
1358: }
1359: bLoadAutoSave = false;
1360: break;
1361:
1.1.1.2 root 1362: case OPT_BLITTER:
1363: ok = Opt_Bool(argv[++i], OPT_BLITTER, &ConfigureParams.System.bBlitter);
1364: if (ok)
1365: {
1366: bLoadAutoSave = false;
1367: }
1368: break;
1.1 root 1369:
1370: case OPT_TIMERD:
1371: ok = Opt_Bool(argv[++i], OPT_TIMERD, &ConfigureParams.System.bPatchTimerD);
1372: break;
1.1.1.2 root 1373:
1374: case OPT_RTC:
1375: ok = Opt_Bool(argv[++i], OPT_RTC, &ConfigureParams.System.bRealTimeClock);
1376: break;
1377:
1378: case OPT_DSP:
1379: i += 1;
1380: if (strcasecmp(argv[i], "none") == 0)
1381: {
1382: ConfigureParams.System.nDSPType = DSP_TYPE_NONE;
1383: }
1384: else if (strcasecmp(argv[i], "dummy") == 0)
1385: {
1386: ConfigureParams.System.nDSPType = DSP_TYPE_DUMMY;
1387: }
1388: else if (strcasecmp(argv[i], "emu") == 0)
1389: {
1390: #if ENABLE_DSP_EMU
1391: ConfigureParams.System.nDSPType = DSP_TYPE_EMU;
1392: #else
1393: return Opt_ShowError(OPT_DSP, argv[i], "DSP type 'emu' support not compiled in");
1394: #endif
1395: }
1396: else
1397: {
1398: return Opt_ShowError(OPT_DSP, argv[i], "Unknown DSP type");
1399: }
1400: bLoadAutoSave = false;
1401: break;
1402:
1403: #if ENABLE_WINUAE_CPU
1404: case OPT_CPU_ADDR24:
1405: ok = Opt_Bool(argv[++i], OPT_CPU_ADDR24, &ConfigureParams.System.bAddressSpace24);
1406: bLoadAutoSave = false;
1407: break;
1408:
1409: case OPT_CPU_CYCLE_EXACT:
1410: ok = Opt_Bool(argv[++i], OPT_CPU_CYCLE_EXACT, &ConfigureParams.System.bCycleExactCpu);
1411: bLoadAutoSave = false;
1412: break;
1413:
1414: case OPT_FPU_TYPE:
1415: i += 1;
1416: if (strcasecmp(argv[i], "none") == 0)
1417: {
1418: ConfigureParams.System.n_FPUType = FPU_NONE;
1419: }
1420: else if (strcasecmp(argv[i], "68881") == 0)
1421: {
1422: ConfigureParams.System.n_FPUType = FPU_68881;
1423: }
1424: else if (strcasecmp(argv[i], "68882") == 0)
1425: {
1426: ConfigureParams.System.n_FPUType = FPU_68882;
1427: }
1428: else if (strcasecmp(argv[i], "internal") == 0)
1429: {
1430: ConfigureParams.System.n_FPUType = FPU_CPU;
1431: }
1432: else
1433: {
1434: return Opt_ShowError(OPT_FPU_TYPE, argv[i], "Unknown FPU type");
1435: }
1436: bLoadAutoSave = false;
1437: break;
1438:
1439: case OPT_FPU_COMPATIBLE:
1440: ok = Opt_Bool(argv[++i], OPT_FPU_COMPATIBLE, &ConfigureParams.System.bCompatibleFPU);
1441: break;
1442:
1443: case OPT_MMU:
1444: ok = Opt_Bool(argv[++i], OPT_MMU, &ConfigureParams.System.bMMU);
1445: bLoadAutoSave = false;
1446: break;
1447: #endif
1448: case OPT_YM_MIXING:
1449: i += 1;
1450: if (strcasecmp(argv[i], "linear") == 0)
1451: {
1452: // ConfigureParams.Sound.YmVolumeMixing = YM_LINEAR_MIXING;
1453: }
1454: else if (strcasecmp(argv[i], "table") == 0)
1455: {
1456: // ConfigureParams.Sound.YmVolumeMixing = YM_TABLE_MIXING;
1457: }
1458: else
1459: {
1460: return Opt_ShowError(OPT_YM_MIXING, argv[i], "Unknown YM mixing method");
1461: }
1462: break;
1.1 root 1463:
1.1.1.2 root 1464: case OPT_SOUND:
1465: i += 1;
1466: if (strcasecmp(argv[i], "off") == 0)
1467: {
1468: ConfigureParams.Sound.bEnableSound = false;
1469: }
1470: else
1471: {
1472: freq = atoi(argv[i]);
1473: if (freq < 6000 || freq > 50066)
1474: {
1475: return Opt_ShowError(OPT_SOUND, argv[i], "Unsupported sound frequency");
1476: }
1477: ConfigureParams.Sound.nPlaybackFreq = freq;
1478: ConfigureParams.Sound.bEnableSound = true;
1479: }
1480: break;
1.1 root 1481:
1482: case OPT_SOUNDBUFFERSIZE:
1483: i += 1;
1484: temp = atoi(argv[i]);
1485: if ( temp == 0 ) /* use default setting for SDL */
1486: ;
1487: else if (temp < 10 || temp > 100)
1488: {
1489: return Opt_ShowError(OPT_SOUNDBUFFERSIZE, argv[i], "Unsupported sound buffer size");
1490: }
1491: ConfigureParams.Sound.SdlAudioBufferSize = temp;
1492: break;
1.1.1.2 root 1493:
1494: case OPT_MICROPHONE:
1495: ok = Opt_Bool(argv[++i], OPT_MICROPHONE, &ConfigureParams.Sound.bEnableMicrophone);
1496: break;
1.1 root 1497:
1498: case OPT_KEYMAPFILE:
1499: i += 1;
1500: ok = Opt_StrCpy(OPT_KEYMAPFILE, true, ConfigureParams.Keyboard.szMappingFileName,
1501: argv[i], sizeof(ConfigureParams.Keyboard.szMappingFileName),
1502: NULL);
1503: if (ok)
1504: {
1505: ConfigureParams.Keyboard.nKeymapType = KEYMAP_LOADED;
1506: }
1507: break;
1508:
1509: /* debug options */
1510: case OPT_DEBUG:
1511: if (bExceptionDebugging)
1512: {
1513: fprintf(stderr, "Exception debugging disabled.\n");
1514: bExceptionDebugging = false;
1515: }
1516: else
1517: {
1518: fprintf(stderr, "Exception debugging enabled.\n");
1519: bExceptionDebugging = true;
1520: }
1521: break;
1522:
1.1.1.2 root 1523: case OPT_BIOSINTERCEPT:
1524: if (bBiosIntercept)
1525: {
1526: fprintf(stderr, "X/Bios interception disabled.\n");
1527: bBiosIntercept = false;
1528: }
1529: else
1530: {
1531: fprintf(stderr, "X/Bios interception enabled.\n");
1532: bBiosIntercept = true;
1533: }
1534: break;
1535:
1.1 root 1536: case OPT_PARACHUTE:
1537: bNoSDLParachute = true;
1538: break;
1539:
1540:
1541: case OPT_TRACE:
1542: i += 1;
1543: errstr = Log_SetTraceOptions(argv[i]);
1544: if (errstr)
1545: {
1546: if (!errstr[0]) {
1547: /* silent parsing termination */
1548: return false;
1549: }
1550: return Opt_ShowError(OPT_TRACE, argv[i], errstr);
1551: }
1552: break;
1553:
1554: case OPT_TRACEFILE:
1555: i += 1;
1556: ok = Opt_StrCpy(OPT_TRACEFILE, false, ConfigureParams.Log.sTraceFileName,
1557: argv[i], sizeof(ConfigureParams.Log.sTraceFileName),
1558: NULL);
1559: break;
1560:
1561: case OPT_CONTROLSOCKET:
1562: i += 1;
1563: errstr = Control_SetSocket(argv[i]);
1564: if (errstr)
1565: {
1566: return Opt_ShowError(OPT_CONTROLSOCKET, argv[i], errstr);
1567: }
1568: break;
1569:
1570: case OPT_LOGFILE:
1571: i += 1;
1572: ok = Opt_StrCpy(OPT_LOGFILE, false, ConfigureParams.Log.sLogFileName,
1573: argv[i], sizeof(ConfigureParams.Log.sLogFileName),
1574: NULL);
1575: break;
1576:
1577: case OPT_PARSE:
1578: i += 1;
1579: ok = DebugUI_SetParseFile(argv[i]);
1580: break;
1581:
1582: case OPT_SAVECONFIG:
1583: /* Hatari-UI needs Hatari config to start */
1584: Configuration_Save();
1585: exit(0);
1586: break;
1587:
1588: case OPT_LOGLEVEL:
1589: i += 1;
1590: ConfigureParams.Log.nTextLogLevel = Log_ParseOptions(argv[i]);
1591: if (ConfigureParams.Log.nTextLogLevel == LOG_NONE)
1592: {
1593: return Opt_ShowError(OPT_LOGLEVEL, argv[i], "Unknown log level!");
1594: }
1595: break;
1596:
1597: case OPT_ALERTLEVEL:
1598: i += 1;
1599: ConfigureParams.Log.nAlertDlgLogLevel = Log_ParseOptions(argv[i]);
1600: if (ConfigureParams.Log.nAlertDlgLogLevel == LOG_NONE)
1601: {
1602: return Opt_ShowError(OPT_ALERTLEVEL, argv[i], "Unknown alert level!");
1603: }
1604: break;
1605:
1606: case OPT_RUNVBLS:
1.1.1.2 root 1607: Main_SetRunVBLs(atol(argv[++i]));
1.1 root 1608: break;
1609:
1610: case OPT_ERROR:
1611: /* unknown option or missing option parameter */
1612: return false;
1613:
1614: default:
1615: return Opt_ShowError(OPT_ERROR, argv[i], "Internal Hatari error, unhandled option");
1616: }
1617: if (!ok)
1618: {
1619: /* Opt_Bool() or Opt_StrCpy() failed */
1620: return false;
1621: }
1622: }
1623:
1624: return true;
1625: }
1626:
1627: /**
1628: * Readline match callback for option name completion.
1629: * STATE = 0 -> different text from previous one.
1630: * Return next match or NULL if no matches.
1631: */
1632: char *Opt_MatchOption(const char *text, int state)
1633: {
1634: static int i, len;
1635: const char *name;
1636:
1637: if (!state) {
1638: /* first match */
1639: len = strlen(text);
1640: i = 0;
1641: }
1642: /* next match */
1643: while (i < ARRAYSIZE(HatariOptions)) {
1644: name = HatariOptions[i++].str;
1645: if (name && strncasecmp(name, text, len) == 0)
1646: return (strdup(name));
1647: }
1648: return NULL;
1649: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.