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