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