Annotation of hatari/src/options.c, revision 1.1.1.6

1.1       root        1: /*
                      2:   Hatari - options.c
                      3: 
                      4:   This file is distributed under the GNU Public License, version 2 or at
                      5:   your option any later version. Read the file gpl.txt for details.
                      6: 
                      7:   Functions for showing and parsing all of Hatari's command line options.
                      8:   
                      9:   To add a new option:
                     10:   - Add option ID to the enum
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>
                     21: 
                     22: #include "main.h"
                     23: #include "options.h"
                     24: #include "configuration.h"
1.1.1.4   root       25: #include "control.h"
1.1.1.6 ! root       26: #include "debugui.h"
1.1       root       27: #include "file.h"
1.1.1.4   root       28: #include "floppy.h"
1.1       root       29: #include "screen.h"
                     30: #include "video.h"
                     31: #include "vdi.h"
                     32: #include "joy.h"
1.1.1.4   root       33: #include "log.h"
1.1.1.2   root       34: 
                     35: #include "hatari-glue.h"
                     36: 
1.1       root       37: 
1.1.1.4   root       38: bool bLoadAutoSave;        /* Load autosave memory snapshot at startup */
                     39: bool bLoadMemorySave;      /* Load memory snapshot provided via option at startup */
                     40: bool bBiosIntercept;       /* whether UAE should intercept Bios & XBios calls */
1.1       root       41: 
                     42: 
                     43: /*  List of supported options. */
                     44: enum {
1.1.1.2   root       45:        OPT_HEADER,     /* options section header */
                     46:        OPT_HELP,               /* general options */
1.1       root       47:        OPT_VERSION,
1.1.1.2   root       48:        OPT_CONFIRMQUIT,
                     49:        OPT_CONFIGFILE,
1.1.1.4   root       50:        OPT_FASTFORWARD,
1.1.1.2   root       51:        OPT_MONO,               /* display options */
                     52:        OPT_MONITOR,
1.1       root       53:        OPT_FULLSCREEN,
                     54:        OPT_WINDOW,
1.1.1.6 ! root       55:        OPT_GRAB,
1.1.1.2   root       56:        OPT_ZOOM,
                     57:        OPT_FRAMESKIPS,
                     58:        OPT_BORDERS,
1.1.1.4   root       59:        OPT_STATUSBAR,
                     60:        OPT_DRIVE_LED,
1.1.1.2   root       61:        OPT_SPEC512,
                     62:        OPT_FORCEBPP,
1.1.1.4   root       63:        OPT_VDI,                /* VDI options */
                     64:        OPT_VDI_PLANES,
1.1.1.2   root       65:        OPT_VDI_WIDTH,
                     66:        OPT_VDI_HEIGHT,
                     67:        OPT_JOYSTICK,           /* device options */
1.1.1.4   root       68:        OPT_JOYSTICK0,
                     69:        OPT_JOYSTICK1,
                     70:        OPT_JOYSTICK2,
                     71:        OPT_JOYSTICK3,
                     72:        OPT_JOYSTICK4,
                     73:        OPT_JOYSTICK5,
1.1       root       74:        OPT_PRINTER,
1.1.1.5   root       75:        OPT_MIDI_IN,
                     76:        OPT_MIDI_OUT,
                     77:        OPT_RS232_IN,
                     78:        OPT_RS232_OUT,
1.1.1.4   root       79:        OPT_DISKA,              /* disk options */
                     80:        OPT_DISKB,
1.1.1.6 ! root       81:        OPT_SLOWFLOPPY,
1.1.1.4   root       82:        OPT_HARDDRIVE,
1.1.1.2   root       83:        OPT_ACSIHDIMAGE,
                     84:        OPT_IDEHDIMAGE,
                     85:        OPT_MEMSIZE,            /* memory options */
1.1       root       86:        OPT_TOS,
                     87:        OPT_CARTRIDGE,
1.1.1.2   root       88:        OPT_MEMSTATE,
                     89:        OPT_CPULEVEL,           /* CPU options */
                     90:        OPT_CPUCLOCK,
1.1       root       91:        OPT_COMPATIBLE,
1.1.1.2   root       92:        OPT_MACHINE,            /* system options */
1.1       root       93:        OPT_BLITTER,
1.1.1.6 ! root       94:        OPT_TIMERD,
1.1.1.2   root       95:        OPT_DSP,
                     96:        OPT_SOUND,
1.1       root       97:        OPT_KEYMAPFILE,
1.1.1.2   root       98:        OPT_DEBUG,              /* debug options */
1.1.1.4   root       99:        OPT_BIOSINTERCEPT,
1.1.1.2   root      100:        OPT_TRACE,
1.1.1.4   root      101:        OPT_TRACEFILE,
                    102:        OPT_CONTROLSOCKET,
                    103:        OPT_LOGFILE,
                    104:        OPT_LOGLEVEL,
                    105:        OPT_ALERTLEVEL,
1.1.1.6 ! root      106:        OPT_RUNVBLS,
1.1.1.4   root      107:        OPT_ERROR,
                    108:        OPT_CONTINUE
1.1       root      109: };
                    110: 
                    111: typedef struct {
                    112:        unsigned int id;        /* option ID */
                    113:        const char *chr;        /* short option */
                    114:        const char *str;        /* long option */
1.1.1.2   root      115:        const char *arg;        /* type name for argument, if any */
1.1       root      116:        const char *desc;       /* option description */
                    117: } opt_t;
                    118: 
1.1.1.2   root      119: /* it's easier to edit these if they are kept in the same order as the enums */
1.1       root      120: static const opt_t HatariOptions[] = {
1.1.1.2   root      121:        
                    122:        { OPT_HEADER, NULL, NULL, NULL, "General" },
1.1       root      123:        { OPT_HELP,      "-h", "--help",
                    124:          NULL, "Print this help text and exit" },
                    125:        { OPT_VERSION,   "-v", "--version",
1.1.1.2   root      126:          NULL, "Print version number and exit" },
1.1.1.4   root      127:        { OPT_CONFIRMQUIT, NULL, "--confirm-quit",
1.1.1.2   root      128:          "<bool>", "Whether Hatari confirms quit" },
1.1.1.4   root      129:        { OPT_CONFIGFILE, "-c", "--configfile",
                    130:          "<file>", "Use <file> instead of the default hatari config file" },
                    131:        { OPT_FASTFORWARD, NULL, "--fast-forward",
                    132:          "<bool>", "Help skipping stuff on fast machine" },
                    133: 
1.1.1.2   root      134:        { OPT_HEADER, NULL, NULL, NULL, "Display" },
1.1       root      135:        { OPT_MONO,      "-m", "--mono",
                    136:          NULL, "Start in monochrome mode instead of color" },
1.1.1.2   root      137:        { OPT_MONITOR,      NULL, "--monitor",
                    138:          "<x>", "Select monitor type (x = mono/rgb/vga/tv)" },
1.1       root      139:        { OPT_FULLSCREEN,"-f", "--fullscreen",
                    140:          NULL, "Start emulator in fullscreen mode" },
                    141:        { OPT_WINDOW,    "-w", "--window",
                    142:          NULL, "Start emulator in window mode" },
1.1.1.6 ! root      143:        { OPT_GRAB, NULL, "--grab",
        !           144:          NULL, "Grab mouse (also) in window mode" },
1.1.1.2   root      145:        { OPT_ZOOM, "-z", "--zoom",
                    146:          "<x>", "Double ST low resolution (1=no, 2=yes)" },
                    147:        { OPT_FRAMESKIPS, NULL, "--frameskips",
1.1.1.4   root      148:          "<x>", "Skip <x> frames after each shown frame (0=off, >4=auto/max)" },
1.1.1.2   root      149:        { OPT_BORDERS, NULL, "--borders",
                    150:          "<bool>", "Show screen borders (for overscan demos etc)" },
1.1.1.4   root      151:        { OPT_STATUSBAR, NULL, "--statusbar",
                    152:          "<bool>", "Show statusbar (floppy leds etc)" },
                    153:        { OPT_DRIVE_LED,   NULL, "--drive-led",
                    154:          "<bool>", "Show overlay drive led when statusbar isn't shown" },
1.1.1.2   root      155:        { OPT_SPEC512, NULL, "--spec512",
                    156:          "<x>", "Spec512 palette threshold (0 <= x <= 512, 0=disable)" },
                    157:        { OPT_FORCEBPP, NULL, "--bpp",
1.1.1.4   root      158:          "<x>", "Force internal bitdepth (x = 8/15/16/32, 0=disable)" },
1.1.1.2   root      159:        
                    160:        { OPT_HEADER, NULL, NULL, NULL, "VDI" },
1.1.1.4   root      161:        { OPT_VDI,      NULL, "--vdi",
                    162:          "<bool>", "Whether to use VDI screen mode" },
1.1.1.2   root      163:        { OPT_VDI_PLANES,NULL, "--vdi-planes",
1.1.1.4   root      164:          "<x>", "VDI mode bit-depth (x = 1/2/4)" },
1.1.1.2   root      165:        { OPT_VDI_WIDTH,     NULL, "--vdi-width",
1.1.1.4   root      166:          "<w>", "VDI mode width (320 < w <= 1024)" },
1.1.1.2   root      167:        { OPT_VDI_HEIGHT,     NULL, "--vdi-height",
1.1.1.4   root      168:          "<h>", "VDI mode height (200 < h <= 768)" },
1.1.1.2   root      169:        
                    170:        { OPT_HEADER, NULL, NULL, NULL, "Devices" },
1.1       root      171:        { OPT_JOYSTICK,  "-j", "--joystick",
1.1.1.2   root      172:          "<port>", "Emulate joystick with cursor keys in given port (0-5)" },
1.1.1.4   root      173:        /* these have to be exactly the same as I'm relying compiler giving
                    174:         * them the same same string pointer when strings are identical
                    175:         */
                    176:        { OPT_JOYSTICK0, NULL, "--joy<port>",
                    177:          "<type>", "Set joystick type (none/keys/real) for given port" },
                    178:        { OPT_JOYSTICK1, NULL, "--joy<port>",
                    179:          "<type>", "Set joystick type (none/keys/real) for given port" },
                    180:        { OPT_JOYSTICK2, NULL, "--joy<port>",
                    181:          "<type>", "Set joystick type (none/keys/real) for given port" },
                    182:        { OPT_JOYSTICK3, NULL, "--joy<port>",
                    183:          "<type>", "Set joystick type (none/keys/real) for given port" },
                    184:        { OPT_JOYSTICK4, NULL, "--joy<port>",
                    185:          "<type>", "Set joystick type (none/keys/real) for given port" },
                    186:        { OPT_JOYSTICK5, NULL, "--joy<port>",
                    187:          "<type>", "Set joystick type (none/keys/real) for given port" },
1.1       root      188:        { OPT_PRINTER,   NULL, "--printer",
1.1.1.2   root      189:          "<file>", "Enable printer support and write data to <file>" },
1.1.1.5   root      190:        { OPT_MIDI_IN,   NULL, "--midi-in",
                    191:          "<file>", "Enable MIDI and use <file> as the input device" },
                    192:        { OPT_MIDI_OUT,  NULL, "--midi-out",
                    193:          "<file>", "Enable MIDI and use <file> as the output device" },
                    194:        { OPT_RS232_IN,  NULL, "--rs232-in",
                    195:          "<file>", "Enable serial port and use <file> as the input device" },
                    196:        { OPT_RS232_OUT, NULL, "--rs232-out",
                    197:          "<file>", "Enable serial port and use <file> as the output device" },
1.1.1.2   root      198:        
                    199:        { OPT_HEADER, NULL, NULL, NULL, "Disk" },
1.1.1.4   root      200:        { OPT_DISKA, NULL, "--disk-a",
                    201:          "<file>", "Set disk image for floppy drive A" },
                    202:        { OPT_DISKB, NULL, "--disk-b",
                    203:          "<file>", "Set disk image for floppy drive B" },
1.1.1.6 ! root      204:        { OPT_SLOWFLOPPY,   NULL, "--slowfdc",
        !           205:          "<bool>", "Slow down floppy disk access emulation" },
1.1       root      206:        { OPT_HARDDRIVE, "-d", "--harddrive",
1.1.1.6 ! root      207:          "<dir>", "Emulate harddrive (partitions) with <dir> contents" },
1.1.1.2   root      208:        { OPT_ACSIHDIMAGE,   NULL, "--acsi",
                    209:          "<file>", "Emulate an ACSI harddrive with an image <file>" },
                    210:        { OPT_IDEHDIMAGE,   NULL, "--ide",
1.1.1.6 ! root      211:          "<file>", "Emulate an IDE harddrive with an image <file>" },
1.1.1.2   root      212:        
                    213:        { OPT_HEADER, NULL, NULL, NULL, "Memory" },
                    214:        { OPT_MEMSIZE,   "-s", "--memsize",
1.1.1.4   root      215:          "<x>", "ST RAM size (x = size in MiB from 0 to 14, 0 = 512KiB)" },
1.1       root      216:        { OPT_TOS,       "-t", "--tos",
                    217:          "<file>", "Use TOS image <file>" },
                    218:        { OPT_CARTRIDGE, NULL, "--cartridge",
                    219:          "<file>", "Use ROM cartridge image <file>" },
1.1.1.2   root      220:        { OPT_MEMSTATE,   NULL, "--memstate",
                    221:          "<file>", "Load memory snap-shot <file>" },
                    222:        
                    223:        { OPT_HEADER, NULL, NULL, NULL, "CPU" },
1.1       root      224:        { OPT_CPULEVEL,  NULL, "--cpulevel",
1.1.1.2   root      225:          "<x>", "Set the CPU type (x => 680x0) (EmuTOS/TOS 2.06 only!)" },
                    226:        { OPT_CPUCLOCK,  NULL, "--cpuclock",
1.1.1.4   root      227:          "<x>", "Set the CPU clock (x = 8/16/32)" },
                    228:        { OPT_COMPATIBLE, NULL, "--compatible",
1.1.1.2   root      229:          "<bool>", "Use a more compatible (but slower) 68000 CPU mode" },
                    230:        
                    231:        { OPT_HEADER, NULL, NULL, NULL, "Misc system" },
                    232:        { OPT_MACHINE,   NULL, "--machine",
                    233:          "<x>", "Select machine type (x = st/ste/tt/falcon)" },
1.1       root      234:        { OPT_BLITTER,   NULL, "--blitter",
1.1.1.2   root      235:          "<bool>", "Use blitter emulation (ST only)" },
1.1.1.6 ! root      236:        { OPT_TIMERD,    NULL, "--timer-d",
        !           237:          "<bool>", "Patch Timer-D (about doubles Hatari speed)" },
1.1.1.2   root      238:        { OPT_DSP,       NULL, "--dsp",
1.1.1.4   root      239:          "<x>", "DSP emulation (x = none/dummy/emu, Falcon only)" },
1.1.1.2   root      240:        { OPT_SOUND,   NULL, "--sound",
1.1.1.6 ! root      241:          "<x>", "Sound frequency (x=off/6000-50066, off=fastest)" },
1.1.1.4   root      242:        { OPT_KEYMAPFILE, "-k", "--keymap",
1.1       root      243:          "<file>", "Read (additional) keyboard mappings from <file>" },
1.1.1.2   root      244:        
                    245:        { OPT_HEADER, NULL, NULL, NULL, "Debug" },
                    246:        { OPT_DEBUG,     "-D", "--debug",
1.1.1.6 ! root      247:          NULL, "Toggle whether CPU exceptions invoke debugger" },
1.1.1.4   root      248:        { OPT_BIOSINTERCEPT, NULL, "--bios-intercept",
                    249:          NULL, "Enable Bios/XBios interception (experimental)" },
1.1.1.2   root      250:        { OPT_TRACE,   NULL, "--trace",
1.1.1.4   root      251:          "<trace1,...>", "Activate emulation tracing, see '--trace help'" },
                    252:        { OPT_TRACEFILE, NULL, "--trace-file",
                    253:          "<file>", "Save trace output to <file> (default=stderr)" },
                    254: #if HAVE_UNIX_DOMAIN_SOCKETS
                    255:        { OPT_CONTROLSOCKET, NULL, "--control-socket",
                    256:          "<file>", "Hatari reads options from given socket at run-time" },
                    257: #endif
                    258:        { OPT_LOGFILE, NULL, "--log-file",
                    259:          "<file>", "Save log output to <file> (default=stderr)" },
                    260:        { OPT_LOGLEVEL, NULL, "--log-level",
                    261:          "<x>", "Log output level (x=debug/todo/info/warn/error/fatal)" },
                    262:        { OPT_ALERTLEVEL, NULL, "--alert-level",
                    263:          "<x>", "Show dialog for log messages above given level" },
1.1.1.6 ! root      264:        { OPT_RUNVBLS, NULL, "--run-vbls",
        !           265:          "<x>", "Exit after x VBLs" },
1.1.1.4   root      266: 
                    267:        { OPT_ERROR, NULL, NULL, NULL, NULL }
1.1       root      268: };
                    269: 
1.1.1.2   root      270: 
                    271: /**
                    272:  * Show version string and license.
1.1       root      273:  */
1.1.1.2   root      274: static void Opt_ShowVersion(void)
                    275: {
1.1.1.4   root      276:        printf("\n" PROG_NAME
                    277:               " - the Atari ST, STE, TT and Falcon emulator.\n\n");
1.1.1.2   root      278:        printf("Hatari is free software licensed under the GNU General"
                    279:               " Public License.\n\n");
                    280: }
                    281: 
                    282: 
                    283: /**
                    284:  * Calculate option + value len
                    285:  */
                    286: static unsigned int Opt_OptionLen(const opt_t *opt)
                    287: {
                    288:        unsigned int len;
                    289:        len = strlen(opt->str);
                    290:        if (opt->arg)
                    291:        {
                    292:                len += strlen(opt->arg);
                    293:                len += 1;
                    294:                /* with arg, short options go to another line */
                    295:        }
                    296:        else
                    297:        {
                    298:                if (opt->chr)
                    299:                {
                    300:                        /* ' or -c' */
                    301:                        len += 6;
                    302:                }
                    303:        }
                    304:        return len;
                    305: }
                    306: 
                    307: 
                    308: /**
                    309:  * Show single option
                    310:  */
                    311: static void Opt_ShowOption(const opt_t *opt, unsigned int maxlen)
1.1       root      312: {
                    313:        char buf[64];
1.1.1.2   root      314:        if (!maxlen)
                    315:        {
                    316:                maxlen = Opt_OptionLen(opt);
                    317:        }
                    318:        assert(maxlen < sizeof(buf));
                    319:        if (opt->arg)
                    320:        {
                    321:                sprintf(buf, "%s %s", opt->str, opt->arg);
                    322:                printf("  %-*s %s\n", maxlen, buf, opt->desc);
                    323:                if (opt->chr)
                    324:                {
                    325:                        printf("    or %s %s\n", opt->chr, opt->arg);
                    326:                }
                    327:        }
                    328:        else
                    329:        {
                    330:                if (opt->chr)
                    331:                {
                    332:                        sprintf(buf, "%s or %s", opt->str, opt->chr);
                    333:                        printf("  %-*s %s\n", maxlen, buf, opt->desc);
1.1       root      334:                }
1.1.1.2   root      335:                else
                    336:                {
                    337:                        printf("  %-*s %s\n", maxlen, opt->str, opt->desc);
                    338:                }
                    339:        }
                    340: }
                    341: 
                    342: /**
                    343:  * Show options for section starting from 'start_opt',
                    344:  * return next option after this section.
                    345:  */
                    346: static const opt_t *Opt_ShowHelpSection(const opt_t *start_opt)
                    347: {
                    348:        const opt_t *opt, *last;
                    349:        unsigned int len, maxlen = 0;
1.1.1.4   root      350:        const char *previous = NULL;
1.1.1.2   root      351: 
                    352:        /* find longest option name and check option IDs */
1.1.1.4   root      353:        for (opt = start_opt; opt->id != OPT_HEADER && opt->id != OPT_ERROR; opt++)
1.1.1.2   root      354:        {
                    355:                len = Opt_OptionLen(opt);
                    356:                if (len > maxlen)
                    357:                {
1.1       root      358:                        maxlen = len;
                    359:                }
                    360:        }
1.1.1.2   root      361:        last = opt;
1.1       root      362:        
                    363:        /* output all options */
1.1.1.2   root      364:        for (opt = start_opt; opt != last; opt++)
                    365:        {
1.1.1.4   root      366:                if (previous != opt->str)
                    367:                {
                    368:                        Opt_ShowOption(opt, maxlen);
                    369:                }
                    370:                previous = opt->str;
1.1.1.2   root      371:        }
                    372:        return last;
                    373: }
                    374: 
                    375: 
                    376: /**
                    377:  * Show help text.
                    378:  */
                    379: static void Opt_ShowHelp(void)
                    380: {
                    381:        const opt_t *opt = HatariOptions;
                    382: 
                    383:        Opt_ShowVersion();
                    384:        printf("Usage:\n hatari [options] [disk image name]\n");
                    385: 
1.1.1.4   root      386:        while(opt->id != OPT_ERROR)
1.1.1.2   root      387:        {
                    388:                if (opt->id == OPT_HEADER)
                    389:                {
                    390:                        assert(opt->desc);
                    391:                        printf("\n%s options:\n", opt->desc);
                    392:                        opt++;
1.1       root      393:                }
1.1.1.2   root      394:                opt = Opt_ShowHelpSection(opt);
1.1       root      395:        }
1.1.1.2   root      396:        printf("\nSpecial option values:\n");
                    397:        printf("<bool>\tDisable by using 'n', 'no', 'off', 'false', or '0'\n");
                    398:        printf("\tEnable by using 'y', 'yes', 'on', 'true' or '1'\n");
                    399:        printf("<file>\tDevices accept also special 'stdout' and 'stderr' file names\n");
                    400:        printf("\t(if you use stdout for midi or printer, set log to stderr).\n");
                    401:        printf("\tSetting the file to 'none', disables given device or disk\n");
                    402: }
                    403: 
                    404: 
                    405: /**
1.1.1.4   root      406:  * Show Hatari version and usage.
1.1.1.2   root      407:  * If 'error' given, show that error message.
1.1.1.4   root      408:  * If 'optid' != OPT_ERROR, tells for which option the error is,
1.1.1.2   root      409:  * otherwise 'value' is show as the option user gave.
1.1.1.6 ! root      410:  * Return false if error string was given, otherwise true
1.1.1.2   root      411:  */
1.1.1.4   root      412: static bool Opt_ShowError(unsigned int optid, const char *value, const char *error)
1.1.1.2   root      413: {
                    414:        const opt_t *opt;
                    415: 
                    416:        Opt_ShowVersion();
                    417:        printf("Usage:\n hatari [options] [disk image name]\n\n"
                    418:               "Try option \"-h\" or \"--help\" to display more information.\n");
                    419: 
                    420:        if (error)
                    421:        {
1.1.1.4   root      422:                if (optid == OPT_ERROR)
1.1.1.2   root      423:                {
1.1       root      424:                        fprintf(stderr, "\nError: %s (%s)\n", error, value);
                    425:                }
1.1.1.2   root      426:                else
                    427:                {
1.1.1.4   root      428:                        for (opt = HatariOptions; opt->id != OPT_ERROR; opt++)
1.1.1.2   root      429:                        {
                    430:                                if (optid == opt->id)
                    431:                                        break;
                    432:                        }
                    433:                        if (value != NULL)
                    434:                        {
1.1.1.6 ! root      435:                                fprintf(stderr,
        !           436:                                        "\nError while parsing argument \"%s\" for option \"%s\":\n"
        !           437:                                        "  %s\n", value, opt->str, error);
1.1.1.2   root      438:                        }
                    439:                        else
                    440:                        {
                    441:                                fprintf(stderr, "\nError (%s): %s\n", opt->str, error);
                    442:                        }
1.1.1.6 ! root      443:                        fprintf(stderr, "\nOption usage:\n");
1.1.1.2   root      444:                        Opt_ShowOption(opt, 0);
                    445:                }
1.1.1.6 ! root      446:                return false;
1.1       root      447:        }
1.1.1.6 ! root      448:        return true;
1.1       root      449: }
                    450: 
1.1.1.2   root      451: 
                    452: /**
1.1.1.4   root      453:  * If 'conf' given, set it:
1.1.1.6 ! root      454:  * - true if given option 'arg' is y/yes/on/true/1
        !           455:  * - false if given option 'arg' is n/no/off/false/0
        !           456:  * Return false for any other value, otherwise true
1.1.1.2   root      457:  */
1.1.1.4   root      458: static bool Opt_Bool(const char *arg, int optid, bool *conf)
1.1.1.2   root      459: {
                    460:        const char *enablers[] = { "y", "yes", "on", "true", "1", NULL };
                    461:        const char *disablers[] = { "n", "no", "off", "false", "0", NULL };
                    462:        const char **bool_str, *orig = arg;
                    463:        char *input, *str;
                    464: 
                    465:        input = strdup(arg);
                    466:        str = input;
                    467:        while (*str)
                    468:        {
                    469:                *str++ = tolower(*arg++);
                    470:        }
                    471:        for (bool_str = enablers; *bool_str; bool_str++)
                    472:        {
                    473:                if (strcmp(input, *bool_str) == 0)
                    474:                {
                    475:                        free(input);
1.1.1.4   root      476:                        if (conf)
                    477:                        {
1.1.1.6 ! root      478:                                *conf = true;
1.1.1.4   root      479:                        }
1.1.1.6 ! root      480:                        return true;
1.1.1.2   root      481:                }
                    482:        }
                    483:        for (bool_str = disablers; *bool_str; bool_str++)
                    484:        {
                    485:                if (strcmp(input, *bool_str) == 0)
                    486:                {
                    487:                        free(input);
1.1.1.4   root      488:                        if (conf)
                    489:                        {
1.1.1.6 ! root      490:                                *conf = false;
1.1.1.4   root      491:                        }
1.1.1.6 ! root      492:                        return true;
1.1.1.2   root      493:                }
                    494:        }
                    495:        free(input);
1.1.1.4   root      496:        return Opt_ShowError(optid, orig, "Not a <bool> value");
                    497: }
                    498: 
                    499: 
                    500: /**
                    501:  * checks str argument agaist options of type "--option<digit>".
                    502:  * If match is found, returns ID for that, otherwise OPT_CONTINUE
                    503:  * and OPT_ERROR for errors.
                    504:  */
                    505: static int Opt_CheckBracketValue(const opt_t *opt, const char *str)
                    506: {
                    507:        const char *bracket, *optstr;
                    508:        size_t offset;
                    509:        int digit, i;
                    510: 
                    511:        if (!opt->str)
                    512:        {
                    513:                return OPT_CONTINUE;
                    514:        }
                    515:        bracket = strchr(opt->str, '<');
                    516:        if (!bracket)
                    517:        {
                    518:                return OPT_CONTINUE;
                    519:        }
                    520:        offset = bracket - opt->str;
                    521:        if (strlen(str) != offset + 1)
                    522:        {
                    523:                return OPT_CONTINUE;
                    524:        }
                    525:        digit = str[offset] - '0';
                    526:        if (digit < 0 || digit > 9)
                    527:        {
                    528:                return OPT_CONTINUE;
                    529:        }
                    530:        optstr = opt->str;
                    531:        for (i = 0; opt->str == optstr; opt++, i++)
                    532:        {
                    533:                if (i == digit)
                    534:                {
                    535:                        return opt->id;
                    536:                }
                    537:        }
                    538:        /* fprintf(stderr, "opt: %s (%d), str: %s (%d), digit: %d\n",
                    539:                opt->str, offset+1, str, strlen(str), digit);
                    540:         */
                    541:        return OPT_ERROR;
1.1.1.2   root      542: }
                    543: 
                    544: 
                    545: /**
1.1       root      546:  * matches string under given index in the argv against all Hatari
                    547:  * short and long options. If match is found, returns ID for that,
1.1.1.4   root      548:  * otherwise shows help and returns OPT_ERROR.
1.1       root      549:  * 
                    550:  * Checks also that if option is supposed to have argument,
                    551:  * whether there's one.
                    552:  */
1.1.1.4   root      553: static int Opt_WhichOption(int argc, const char *argv[], int idx)
1.1       root      554: {
                    555:        const opt_t *opt;
                    556:        const char *str = argv[idx];
1.1.1.4   root      557:        int id;
1.1       root      558: 
1.1.1.4   root      559:        for (opt = HatariOptions; opt->id != OPT_ERROR; opt++)
1.1.1.2   root      560:        {       
                    561:                if ((opt->str && !strcmp(str, opt->str)) ||
                    562:                    (opt->chr && !strcmp(str, opt->chr)))
                    563:                {
                    564:                        
                    565:                        if (opt->arg)
                    566:                        {
                    567:                                if (idx+1 >= argc)
                    568:                                {
1.1.1.4   root      569:                                        Opt_ShowError(opt->id, NULL, "Missing argument");
                    570:                                        return OPT_ERROR;
1.1.1.2   root      571:                                }
                    572:                                /* early check for bools */
                    573:                                if (strcmp(opt->arg, "<bool>") == 0)
                    574:                                {
1.1.1.4   root      575:                                        if (!Opt_Bool(argv[idx+1], opt->id, NULL))
                    576:                                        {
                    577:                                                return OPT_ERROR;
                    578:                                        }
1.1.1.2   root      579:                                }
1.1       root      580:                        }
                    581:                        return opt->id;
                    582:                }
1.1.1.4   root      583:                id = Opt_CheckBracketValue(opt, str);
                    584:                if (id == OPT_ERROR)
                    585:                {
                    586:                        break;
                    587:                }
                    588:                if (id != OPT_CONTINUE)
                    589:                {
                    590:                        return id;
                    591:                }
1.1       root      592:        }
1.1.1.4   root      593:        Opt_ShowError(OPT_ERROR, argv[idx], "Unrecognized option");
                    594:        return OPT_ERROR;
1.1       root      595: }
                    596: 
1.1.1.2   root      597: 
                    598: /**
1.1.1.6 ! root      599:  * If 'checkexits' is true, assume 'src' is a file and check whether it
1.1.1.4   root      600:  * exists before copying 'src' to 'dst'. Otherwise just copy option src
                    601:  * string to dst.
1.1.1.6 ! root      602:  * If a pointer to (bool) 'option' is given, set that option to true.
        !           603:  * - However, if src is "none", leave dst unmodified & set option to false.
1.1.1.4   root      604:  *   ("none" is used to disable options related to file arguments)
1.1.1.6 ! root      605:  * Return false if there were errors, otherwise true
1.1.1.2   root      606:  */
1.1.1.4   root      607: static bool Opt_StrCpy(int optid, bool checkexist, char *dst, const char *src, size_t dstlen, bool *option)
1.1.1.2   root      608: {
1.1.1.4   root      609:        if (strlen(src) >= dstlen)
                    610:        {
                    611:                return Opt_ShowError(optid, src, "File name too long!");
                    612:        }
                    613:        if (checkexist && !File_Exists(src))
                    614:        {
                    615:                return Opt_ShowError(optid, src, "Given file doesn't exist (or has wrong file permissions)!");
                    616:        }
1.1.1.2   root      617:        if (option)
                    618:        {
                    619:                if(strcmp(src, "none") == 0)
                    620:                {
1.1.1.6 ! root      621:                        *option = false;
        !           622:                        return true;
1.1.1.2   root      623:                }
                    624:                else
                    625:                {
1.1.1.6 ! root      626:                        *option = true;
1.1.1.2   root      627:                }
                    628:        }
1.1.1.4   root      629:        strcpy(dst, src);
1.1.1.6 ! root      630:        return true;
1.1.1.2   root      631: }
                    632: 
                    633: 
                    634: /**
1.1.1.4   root      635:  * parse all Hatari command line options and set Hatari state accordingly.
1.1.1.6 ! root      636:  * Returns true if everything was OK, false otherwise.
1.1.1.2   root      637:  */
1.1.1.4   root      638: bool Opt_ParseParameters(int argc, const char *argv[])
1.1       root      639: {
1.1.1.6 ! root      640:        int ncpu, skips, zoom, planes, cpuclock, threshold, memsize, port, freq;
1.1.1.4   root      641:        const char *errstr;
1.1.1.6 ! root      642:        int i, ok = true;
1.1.1.2   root      643: 
                    644:        /* Defaults for loading initial memory snap-shots */
1.1.1.6 ! root      645:        bLoadMemorySave = false;
1.1.1.2   root      646:        bLoadAutoSave = ConfigureParams.Memory.bAutoSave;
                    647: 
                    648:        for(i = 1; i < argc; i++)
1.1.1.4   root      649:        {
1.1.1.2   root      650:                if (argv[i][0] != '-')
                    651:                {
1.1.1.4   root      652:                        if (Floppy_SetDiskFileName(0, argv[i], NULL))
1.1.1.2   root      653:                        {
1.1.1.6 ! root      654:                                ConfigureParams.HardDisk.bBootFromHardDisk = false;
        !           655:                                bLoadAutoSave = false;
1.1.1.2   root      656:                        }
                    657:                        else
1.1.1.4   root      658:                                return Opt_ShowError(OPT_ERROR, argv[i], "Not an option nor disk image");
1.1       root      659:                        continue;
                    660:                }
                    661:     
                    662:                /* WhichOption() checks also that there is an argument,
                    663:                 * so we don't need to check that below
                    664:                 */
1.1.1.2   root      665:                switch(Opt_WhichOption(argc, argv, i))
                    666:                {
                    667:                
                    668:                        /* general options */
1.1       root      669:                case OPT_HELP:
1.1.1.2   root      670:                        Opt_ShowHelp();
1.1.1.6 ! root      671:                        return false;
1.1       root      672:                        
                    673:                case OPT_VERSION:
1.1.1.2   root      674:                        Opt_ShowVersion();
1.1.1.6 ! root      675:                        return false;
1.1.1.2   root      676: 
                    677:                case OPT_CONFIRMQUIT:
1.1.1.4   root      678:                        ok = Opt_Bool(argv[++i], OPT_CONFIRMQUIT, &ConfigureParams.Log.bConfirmQuit);
                    679:                        break;
                    680: 
                    681:                case OPT_FASTFORWARD:
                    682:                        ok = Opt_Bool(argv[++i], OPT_FASTFORWARD, &ConfigureParams.System.bFastForward);
1.1       root      683:                        break;
                    684:                        
1.1.1.2   root      685:                case OPT_CONFIGFILE:
                    686:                        i += 1;
1.1.1.6 ! root      687:                        ok = Opt_StrCpy(OPT_CONFIGFILE, true, sConfigFileName,
1.1.1.4   root      688:                                        argv[i], sizeof(sConfigFileName), NULL);
                    689:                        if (ok)
                    690:                        {
                    691:                                Configuration_Load(NULL);
                    692:                                bLoadAutoSave = ConfigureParams.Memory.bAutoSave;
                    693:                        }
1.1.1.2   root      694:                        break;
                    695:                
                    696:                        /* display options */
1.1       root      697:                case OPT_MONO:
1.1.1.4   root      698:                        ConfigureParams.Screen.nMonitorType = MONITOR_TYPE_MONO;
1.1.1.6 ! root      699:                        bLoadAutoSave = false;
1.1.1.2   root      700:                        break;
                    701: 
                    702:                case OPT_MONITOR:
                    703:                        i += 1;
                    704:                        if (strcasecmp(argv[i], "mono") == 0)
                    705:                        {
1.1.1.4   root      706:                                ConfigureParams.Screen.nMonitorType = MONITOR_TYPE_MONO;
1.1.1.2   root      707:                        }
                    708:                        else if (strcasecmp(argv[i], "rgb") == 0)
                    709:                        {
1.1.1.4   root      710:                                ConfigureParams.Screen.nMonitorType = MONITOR_TYPE_RGB;
1.1.1.2   root      711:                        }
                    712:                        else if (strcasecmp(argv[i], "vga") == 0)
                    713:                        {
1.1.1.4   root      714:                                ConfigureParams.Screen.nMonitorType = MONITOR_TYPE_VGA;
1.1.1.2   root      715:                        }
                    716:                        else if (strcasecmp(argv[i], "tv") == 0)
                    717:                        {
1.1.1.4   root      718:                                ConfigureParams.Screen.nMonitorType = MONITOR_TYPE_TV;
1.1.1.2   root      719:                        }
                    720:                        else
                    721:                        {
1.1.1.4   root      722:                                return Opt_ShowError(OPT_MONITOR, argv[i], "Unknown monitor type");
1.1.1.2   root      723:                        }
1.1.1.6 ! root      724:                        bLoadAutoSave = false;
1.1       root      725:                        break;
                    726:                        
                    727:                case OPT_FULLSCREEN:
1.1.1.6 ! root      728:                        ConfigureParams.Screen.bFullScreen = true;
1.1       root      729:                        break;
                    730:                        
                    731:                case OPT_WINDOW:
1.1.1.6 ! root      732:                        ConfigureParams.Screen.bFullScreen = false;
        !           733:                        break;
        !           734: 
        !           735:                case OPT_GRAB:
        !           736:                        bGrabMouse = true;
1.1       root      737:                        break;
                    738:                        
1.1.1.2   root      739:                case OPT_ZOOM:
                    740:                        zoom = atoi(argv[++i]);
                    741:                        if (zoom < 1)
                    742:                        {
1.1.1.4   root      743:                                return Opt_ShowError(OPT_ZOOM, argv[i], "Invalid zoom value");
1.1.1.2   root      744:                        }
                    745:                        if (zoom > 1)
                    746:                        {
                    747:                                /* TODO: only doubling supported for now */
1.1.1.6 ! root      748:                                ConfigureParams.Screen.bZoomLowRes = true;
1.1.1.2   root      749:                        }
                    750:                        else
                    751:                        {
1.1.1.6 ! root      752:                                ConfigureParams.Screen.bZoomLowRes = false;
1.1       root      753:                        }
                    754:                        break;
                    755:                        
1.1.1.2   root      756:                case OPT_FRAMESKIPS:
                    757:                        skips = atoi(argv[++i]);
1.1.1.6 ! root      758:                        if (skips < 0)
1.1.1.2   root      759:                        {
1.1.1.4   root      760:                                return Opt_ShowError(OPT_FRAMESKIPS, argv[i],
                    761:                                                     "Invalid frame skip value");
1.1.1.2   root      762:                        }
1.1.1.6 ! root      763:                        else if (skips > 8)
        !           764:                        {
        !           765:                                Log_Printf(LOG_WARN, "Extravagant frame skip value %d!\n", skips);
        !           766:                        }
1.1.1.4   root      767:                        ConfigureParams.Screen.nFrameSkips = skips;
1.1       root      768:                        break;
                    769:                        
1.1.1.2   root      770:                case OPT_BORDERS:
1.1.1.4   root      771:                        ok = Opt_Bool(argv[++i], OPT_BORDERS, &ConfigureParams.Screen.bAllowOverscan);
                    772:                        break;
                    773:                        
                    774:                case OPT_STATUSBAR:
                    775:                        ok = Opt_Bool(argv[++i], OPT_STATUSBAR, &ConfigureParams.Screen.bShowStatusbar);
                    776:                        break;
                    777:                        
                    778:                case OPT_DRIVE_LED:
                    779:                        ok = Opt_Bool(argv[++i], OPT_DRIVE_LED, &ConfigureParams.Screen.bShowDriveLed);
1.1       root      780:                        break;
                    781:                        
1.1.1.2   root      782:                case OPT_SPEC512:
                    783:                        threshold = atoi(argv[++i]);
                    784:                        if (threshold < 0 || threshold > 512)
                    785:                        {
1.1.1.4   root      786:                                return Opt_ShowError(OPT_SPEC512, argv[i],
                    787:                                                     "Invalid palette writes per line threshold for Spec512");
1.1.1.2   root      788:                        }
                    789:                        ConfigureParams.Screen.nSpec512Threshold = threshold;
                    790:                        break;
                    791:                        
                    792:                case OPT_FORCEBPP:
                    793:                        planes = atoi(argv[++i]);
1.1.1.3   root      794:                        switch(planes)
1.1.1.2   root      795:                        {
1.1.1.3   root      796:                        case 32:
                    797:                        case 16:
                    798:                        case 15:
                    799:                        case 8:
                    800:                                break;       /* supported */
                    801:                        case 24:
                    802:                                planes = 32; /* We do not support 24 bpp (yet) */
                    803:                                break;
                    804:                        default:
1.1.1.4   root      805:                                return Opt_ShowError(OPT_FORCEBPP, argv[i], "Invalid bit depth");
1.1.1.2   root      806:                        }
                    807:                        ConfigureParams.Screen.nForceBpp = planes;
                    808:                        break;
                    809: 
1.1.1.4   root      810:                        /* VDI options */
                    811:                case OPT_VDI:
                    812:                        ok = Opt_Bool(argv[++i], OPT_VDI, &ConfigureParams.Screen.bUseExtVdiResolutions);
                    813:                        if (ok)
                    814:                        {
1.1.1.6 ! root      815:                                bLoadAutoSave = false;
1.1.1.4   root      816:                        }
                    817:                        break;
                    818: 
1.1.1.2   root      819:                case OPT_VDI_PLANES:
                    820:                        planes = atoi(argv[++i]);
                    821:                        switch(planes)
                    822:                        {
                    823:                         case 1:
                    824:                                ConfigureParams.Screen.nVdiColors = GEMCOLOR_2;
                    825:                                break;
                    826:                         case 2:
                    827:                                ConfigureParams.Screen.nVdiColors = GEMCOLOR_4;
                    828:                                break;
                    829:                         case 4:
                    830:                                ConfigureParams.Screen.nVdiColors = GEMCOLOR_16;
                    831:                                break;
                    832:                         default:
1.1.1.4   root      833:                                return Opt_ShowError(OPT_VDI_PLANES, argv[i], "Unsupported VDI bit-depth");
1.1.1.2   root      834:                        }
1.1.1.6 ! root      835:                        ConfigureParams.Screen.bUseExtVdiResolutions = true;
        !           836:                        bLoadAutoSave = false;
1.1.1.2   root      837:                        break;
                    838: 
                    839:                case OPT_VDI_WIDTH:
                    840:                        ConfigureParams.Screen.nVdiWidth = atoi(argv[++i]);
1.1.1.6 ! root      841:                        ConfigureParams.Screen.bUseExtVdiResolutions = true;
        !           842:                        bLoadAutoSave = false;
1.1.1.2   root      843:                        break;
                    844: 
                    845:                case OPT_VDI_HEIGHT:
                    846:                        ConfigureParams.Screen.nVdiHeight = atoi(argv[++i]);
1.1.1.6 ! root      847:                        ConfigureParams.Screen.bUseExtVdiResolutions = true;
        !           848:                        bLoadAutoSave = false;
1.1.1.2   root      849:                        break;
                    850:                
                    851:                        /* devices options */
                    852:                case OPT_JOYSTICK:
                    853:                        i++;
                    854:                        if (strlen(argv[i]) != 1 ||
                    855:                            !Joy_SetCursorEmulation(argv[i][0] - '0'))
                    856:                        {
1.1.1.4   root      857:                                return Opt_ShowError(OPT_JOYSTICK, argv[i], "Invalid joystick port");
                    858:                        }
                    859:                        break;
                    860: 
                    861:                case OPT_JOYSTICK0:
                    862:                case OPT_JOYSTICK1:
                    863:                case OPT_JOYSTICK2:
                    864:                case OPT_JOYSTICK3:
                    865:                case OPT_JOYSTICK4:
                    866:                case OPT_JOYSTICK5:
                    867:                        port = argv[i][strlen(argv[i])-1] - '0';
                    868:                        assert(port >= 0 && port < JOYSTICK_COUNT);
                    869:                        i += 1;
                    870:                        if (strcasecmp(argv[i], "none") == 0)
                    871:                        {
                    872:                                ConfigureParams.Joysticks.Joy[port].nJoystickMode = JOYSTICK_DISABLED;
                    873:                        }
                    874:                        else if (strcasecmp(argv[i], "keys") == 0)
                    875:                        {
                    876:                                ConfigureParams.Joysticks.Joy[port].nJoystickMode = JOYSTICK_KEYBOARD;
                    877:                        }
                    878:                        else if (strcasecmp(argv[i], "real") == 0)
                    879:                        {
                    880:                                ConfigureParams.Joysticks.Joy[port].nJoystickMode = JOYSTICK_REALSTICK;
                    881:                        }
                    882:                        else
                    883:                        {
                    884:                                return Opt_ShowError(OPT_JOYSTICK0+port, argv[i], "Invalid joystick type");
1.1.1.2   root      885:                        }
1.1       root      886:                        break;
                    887:                        
                    888:                case OPT_PRINTER:
1.1.1.2   root      889:                        i += 1;
1.1.1.6 ! root      890:                        ok = Opt_StrCpy(OPT_PRINTER, false, ConfigureParams.Printer.szPrintToFileName,
1.1.1.4   root      891:                                        argv[i], sizeof(ConfigureParams.Printer.szPrintToFileName),
                    892:                                        &ConfigureParams.Printer.bEnablePrinting);
1.1       root      893:                        break;
                    894:                        
1.1.1.5   root      895:                case OPT_MIDI_IN:
                    896:                        i += 1;
1.1.1.6 ! root      897:                        /* false: "" can be used to disable midi input */
        !           898:                        ok = Opt_StrCpy(OPT_MIDI_IN, false, ConfigureParams.Midi.sMidiInFileName,
1.1.1.5   root      899:                                        argv[i], sizeof(ConfigureParams.Midi.sMidiInFileName),
                    900:                                        &ConfigureParams.Midi.bEnableMidi);
                    901:                        break;
                    902:                        
                    903:                case OPT_MIDI_OUT:
1.1       root      904:                        i += 1;
1.1.1.6 ! root      905:                        ok = Opt_StrCpy(OPT_MIDI_OUT, true, ConfigureParams.Midi.sMidiOutFileName,
1.1.1.5   root      906:                                        argv[i], sizeof(ConfigureParams.Midi.sMidiOutFileName),
1.1.1.4   root      907:                                        &ConfigureParams.Midi.bEnableMidi);
1.1       root      908:                        break;
                    909:       
1.1.1.5   root      910:                case OPT_RS232_IN:
1.1       root      911:                        i += 1;
1.1.1.6 ! root      912:                        ok = Opt_StrCpy(OPT_RS232_IN, true, ConfigureParams.RS232.szInFileName,
1.1.1.4   root      913:                                        argv[i], sizeof(ConfigureParams.RS232.szInFileName),
                    914:                                        &ConfigureParams.RS232.bEnableRS232);
1.1.1.5   root      915:                        break;
                    916:       
                    917:                case OPT_RS232_OUT:
                    918:                        i += 1;
1.1.1.6 ! root      919:                        ok = Opt_StrCpy(OPT_RS232_OUT, true, ConfigureParams.RS232.szOutFileName,
1.1.1.5   root      920:                                        argv[i], sizeof(ConfigureParams.RS232.szOutFileName),
                    921:                                        &ConfigureParams.RS232.bEnableRS232);
1.1       root      922:                        break;
1.1.1.2   root      923: 
                    924:                        /* disk options */
1.1.1.4   root      925:                case OPT_DISKA:
                    926:                        i += 1;
                    927:                        if (Floppy_SetDiskFileName(0, argv[i], NULL))
                    928:                        {
1.1.1.6 ! root      929:                                ConfigureParams.HardDisk.bBootFromHardDisk = false;
        !           930:                                bLoadAutoSave = false;
1.1.1.4   root      931:                        }
                    932:                        else
                    933:                                return Opt_ShowError(OPT_ERROR, argv[i], "Not a disk image");
                    934:                        break;
                    935: 
                    936:                case OPT_DISKB:
                    937:                        i += 1;
                    938:                        if (Floppy_SetDiskFileName(1, argv[i], NULL))
1.1.1.6 ! root      939:                                bLoadAutoSave = false;
1.1.1.4   root      940:                        else
                    941:                                return Opt_ShowError(OPT_ERROR, argv[i], "Not a disk image");
                    942:                        break;
                    943: 
1.1       root      944:                case OPT_HARDDRIVE:
                    945:                        i += 1;
1.1.1.6 ! root      946:                        ok = Opt_StrCpy(OPT_HARDDRIVE, false, ConfigureParams.HardDisk.szHardDiskDirectories[0],
1.1.1.4   root      947:                                        argv[i], sizeof(ConfigureParams.HardDisk.szHardDiskDirectories[0]),
                    948:                                        &ConfigureParams.HardDisk.bUseHardDiskDirectories);
                    949:                        if (ok && ConfigureParams.HardDisk.bUseHardDiskDirectories)
1.1.1.2   root      950:                        {
1.1.1.6 ! root      951:                                ConfigureParams.HardDisk.bBootFromHardDisk = true;
1.1       root      952:                        }
1.1.1.6 ! root      953:                        bLoadAutoSave = false;
1.1.1.2   root      954:                        break;
                    955: 
                    956:                case OPT_ACSIHDIMAGE:
                    957:                        i += 1;
1.1.1.6 ! root      958:                        ok = Opt_StrCpy(OPT_ACSIHDIMAGE, true, ConfigureParams.HardDisk.szHardDiskImage,
1.1.1.4   root      959:                                        argv[i], sizeof(ConfigureParams.HardDisk.szHardDiskImage),
                    960:                                        &ConfigureParams.HardDisk.bUseHardDiskImage);
                    961:                        if (ok)
                    962:                        {
1.1.1.6 ! root      963:                                bLoadAutoSave = false;
1.1.1.4   root      964:                        }
1.1       root      965:                        break;
                    966:                        
1.1.1.2   root      967:                case OPT_IDEHDIMAGE:
1.1       root      968:                        i += 1;
1.1.1.6 ! root      969:                        ok = Opt_StrCpy(OPT_IDEHDIMAGE, true, ConfigureParams.HardDisk.szIdeHardDiskImage,
1.1.1.4   root      970:                                        argv[i], sizeof(ConfigureParams.HardDisk.szIdeHardDiskImage),
                    971:                                        &ConfigureParams.HardDisk.bUseIdeHardDiskImage);
                    972:                        if (ok)
                    973:                        {
1.1.1.6 ! root      974:                                bLoadAutoSave = false;
1.1.1.4   root      975:                        }
1.1.1.2   root      976:                        break;
1.1.1.6 ! root      977: 
        !           978:                case OPT_SLOWFLOPPY:
        !           979:                        ok = Opt_Bool(argv[++i], OPT_SLOWFLOPPY, &ConfigureParams.DiskImage.bSlowFloppy);
1.1.1.2   root      980:                        break;
                    981:                        
                    982:                        /* Memory options */
                    983:                case OPT_MEMSIZE:
1.1.1.4   root      984:                        memsize = atoi(argv[++i]);
                    985:                        if (memsize < 0 || memsize > 14)
1.1.1.2   root      986:                        {
1.1.1.4   root      987:                                return Opt_ShowError(OPT_MEMSIZE, argv[i], "Invalid memory size");
1.1       root      988:                        }
1.1.1.4   root      989:                        ConfigureParams.Memory.nMemorySize = memsize;
1.1.1.6 ! root      990:                        bLoadAutoSave = false;
1.1       root      991:                        break;
                    992:       
1.1.1.2   root      993:                case OPT_TOS:
                    994:                        i += 1;
1.1.1.6 ! root      995:                        ok = Opt_StrCpy(OPT_TOS, true, ConfigureParams.Rom.szTosImageFileName,
1.1.1.4   root      996:                                        argv[i], sizeof(ConfigureParams.Rom.szTosImageFileName),
                    997:                                        NULL);
                    998:                        if (ok)
                    999:                        {
1.1.1.6 ! root     1000:                                bLoadAutoSave = false;
1.1.1.4   root     1001:                        }
1.1.1.2   root     1002:                        break;
                   1003:                        
1.1       root     1004:                case OPT_CARTRIDGE:
                   1005:                        i += 1;
1.1.1.6 ! root     1006:                        ok = Opt_StrCpy(OPT_CARTRIDGE, true, ConfigureParams.Rom.szCartridgeImageFileName,
1.1.1.4   root     1007:                                        argv[i], sizeof(ConfigureParams.Rom.szCartridgeImageFileName),
                   1008:                                        NULL);
                   1009:                        if (ok)
                   1010:                        {
1.1.1.6 ! root     1011:                                bLoadAutoSave = false;
1.1.1.4   root     1012:                        }
1.1.1.2   root     1013:                        break;
                   1014: 
                   1015:                case OPT_MEMSTATE:
                   1016:                        i += 1;
1.1.1.6 ! root     1017:                        ok = Opt_StrCpy(OPT_MEMSTATE, true, ConfigureParams.Memory.szMemoryCaptureFileName,
1.1.1.4   root     1018:                                        argv[i], sizeof(ConfigureParams.Memory.szMemoryCaptureFileName),
                   1019:                                        NULL);
                   1020:                        if (ok)
                   1021:                        {
1.1.1.6 ! root     1022:                                bLoadMemorySave = true;
        !          1023:                                bLoadAutoSave = false;
1.1.1.4   root     1024:                        }
1.1       root     1025:                        break;
                   1026:                        
1.1.1.2   root     1027:                        /* CPU options */
1.1       root     1028:                case OPT_CPULEVEL:
                   1029:                        /* UAE core uses cpu_level variable */
1.1.1.2   root     1030:                        ncpu = atoi(argv[++i]);
                   1031:                        if(ncpu < 0 || ncpu > 4)
                   1032:                        {
1.1.1.4   root     1033:                                return Opt_ShowError(OPT_CPULEVEL, argv[i], "Invalid CPU level");
1.1.1.2   root     1034:                        }
                   1035:                        ConfigureParams.System.nCpuLevel = ncpu;
1.1.1.6 ! root     1036:                        bLoadAutoSave = false;
1.1.1.2   root     1037:                        break;
                   1038:                        
                   1039:                case OPT_CPUCLOCK:
                   1040:                        cpuclock = atoi(argv[++i]);
                   1041:                        if(cpuclock != 8 && cpuclock != 16 && cpuclock != 32)
                   1042:                        {
1.1.1.4   root     1043:                                return Opt_ShowError(OPT_CPUCLOCK, argv[i], "Invalid CPU clock");
1.1       root     1044:                        }
1.1.1.2   root     1045:                        ConfigureParams.System.nCpuFreq = cpuclock;
1.1.1.6 ! root     1046:                        bLoadAutoSave = false;
1.1       root     1047:                        break;
                   1048:                        
                   1049:                case OPT_COMPATIBLE:
1.1.1.4   root     1050:                        ok = Opt_Bool(argv[++i], OPT_COMPATIBLE, &ConfigureParams.System.bCompatibleCpu);
                   1051:                        if (ok)
                   1052:                        {
1.1.1.6 ! root     1053:                                bLoadAutoSave = false;
1.1.1.4   root     1054:                        }
1.1       root     1055:                        break;
1.1.1.2   root     1056: 
                   1057:                        /* system options */
                   1058:                case OPT_MACHINE:
                   1059:                        i += 1;
                   1060:                        if (strcasecmp(argv[i], "st") == 0)
                   1061:                        {
                   1062:                                ConfigureParams.System.nMachineType = MACHINE_ST;
                   1063:                                ConfigureParams.System.nCpuLevel = 0;
                   1064:                                ConfigureParams.System.nCpuFreq = 8;
                   1065:                        }
                   1066:                        else if (strcasecmp(argv[i], "ste") == 0)
                   1067:                        {
                   1068:                                ConfigureParams.System.nMachineType = MACHINE_STE;
                   1069:                                ConfigureParams.System.nCpuLevel = 0;
                   1070:                                ConfigureParams.System.nCpuFreq = 8;
                   1071:                        }
                   1072:                        else if (strcasecmp(argv[i], "tt") == 0)
                   1073:                        {
                   1074:                                ConfigureParams.System.nMachineType = MACHINE_TT;
                   1075:                                ConfigureParams.System.nCpuLevel = 3;
                   1076:                                ConfigureParams.System.nCpuFreq = 32;
                   1077:                        }
                   1078:                        else if (strcasecmp(argv[i], "falcon") == 0)
                   1079:                        {
                   1080:                                ConfigureParams.System.nMachineType = MACHINE_FALCON;
                   1081:                                ConfigureParams.System.nCpuLevel = 3;
                   1082:                                ConfigureParams.System.nCpuFreq = 16;
                   1083:                        }
                   1084:                        else
                   1085:                        {
1.1.1.4   root     1086:                                return Opt_ShowError(OPT_MACHINE, argv[i], "Unknown machine type");
1.1.1.2   root     1087:                        }
1.1.1.6 ! root     1088:                        bLoadAutoSave = false;
1.1       root     1089:                        break;
                   1090:                        
1.1.1.2   root     1091:                case OPT_BLITTER:
1.1.1.4   root     1092:                        ok = Opt_Bool(argv[++i], OPT_BLITTER, &ConfigureParams.System.bBlitter);
                   1093:                        if (ok)
                   1094:                        {
1.1.1.6 ! root     1095:                                bLoadAutoSave = false;
1.1.1.4   root     1096:                        }
1.1.1.2   root     1097:                        break;                  
1.1.1.6 ! root     1098:                        
        !          1099:                case OPT_TIMERD:
        !          1100:                        ok = Opt_Bool(argv[++i], OPT_TIMERD, &ConfigureParams.System.bPatchTimerD);
        !          1101:                        break;                  
1.1.1.2   root     1102: 
                   1103:                case OPT_DSP:
                   1104:                        i += 1;
                   1105:                        if (strcasecmp(argv[i], "none") == 0)
                   1106:                        {
                   1107:                                ConfigureParams.System.nDSPType = DSP_TYPE_NONE;
                   1108:                        }
                   1109:                        else if (strcasecmp(argv[i], "dummy") == 0)
                   1110:                        {
                   1111:                                ConfigureParams.System.nDSPType = DSP_TYPE_DUMMY;
                   1112:                        }
                   1113:                        else if (strcasecmp(argv[i], "emu") == 0)
                   1114:                        {
                   1115: #if ENABLE_DSP_EMU
                   1116:                                ConfigureParams.System.nDSPType = DSP_TYPE_EMU;
                   1117: #else
1.1.1.4   root     1118:                                return Opt_ShowError(OPT_DSP, argv[i], "DSP type 'emu' support not compiled in");
1.1.1.2   root     1119: #endif
                   1120:                        }
                   1121:                        else
                   1122:                        {
1.1.1.4   root     1123:                                return Opt_ShowError(OPT_DSP, argv[i], "Unknown DSP type");
1.1       root     1124:                        }
1.1.1.6 ! root     1125:                        bLoadAutoSave = false;
1.1       root     1126:                        break;
                   1127:                        
1.1.1.2   root     1128:                case OPT_SOUND:
1.1       root     1129:                        i += 1;
1.1.1.2   root     1130:                        if (strcasecmp(argv[i], "off") == 0)
                   1131:                        {
1.1.1.6 ! root     1132:                                ConfigureParams.Sound.bEnableSound = false;
1.1.1.2   root     1133:                        }
                   1134:                        else
                   1135:                        {
1.1.1.6 ! root     1136:                                freq = atoi(argv[i]);
        !          1137:                                if (freq < 6000 || freq > 50066)
        !          1138:                                {
        !          1139:                                        return Opt_ShowError(OPT_SOUND, argv[i], "Unsupported sound frequency");
        !          1140:                                }
        !          1141:                                ConfigureParams.Sound.nPlaybackFreq = freq;
        !          1142:                                ConfigureParams.Sound.bEnableSound = true;
1.1       root     1143:                        }
                   1144:                        break;
1.1.1.2   root     1145: 
1.1       root     1146:                case OPT_KEYMAPFILE:
                   1147:                        i += 1;
1.1.1.6 ! root     1148:                        ok = Opt_StrCpy(OPT_KEYMAPFILE, true, ConfigureParams.Keyboard.szMappingFileName,
1.1.1.4   root     1149:                                        argv[i], sizeof(ConfigureParams.Keyboard.szMappingFileName),
                   1150:                                        NULL);
                   1151:                        if (ok)
                   1152:                        {
                   1153:                                ConfigureParams.Keyboard.nKeymapType = KEYMAP_LOADED;
                   1154:                        }
1.1       root     1155:                        break;
                   1156:                        
1.1.1.2   root     1157:                        /* debug options */
                   1158:                case OPT_DEBUG:
1.1.1.6 ! root     1159:                        if (bExceptionDebugging)
1.1.1.4   root     1160:                        {
1.1.1.6 ! root     1161:                                fprintf(stderr, "Exception debugging disabled.\n");
        !          1162:                                bExceptionDebugging = false;
1.1.1.4   root     1163:                        }
                   1164:                        else
                   1165:                        {
1.1.1.6 ! root     1166:                                fprintf(stderr, "Exception debugging enabled.\n");
        !          1167:                                bExceptionDebugging = true;
1.1.1.4   root     1168:                        }
1.1.1.2   root     1169:                        break;
1.1.1.4   root     1170: 
                   1171:                case OPT_BIOSINTERCEPT:
1.1.1.6 ! root     1172:                        bBiosIntercept = true;
1.1       root     1173:                        break;
                   1174:                        
1.1.1.2   root     1175:                case OPT_TRACE:
                   1176:                        i += 1;
1.1.1.6 ! root     1177:                        errstr = Log_SetTraceOptions(argv[i]);
        !          1178:                        if (errstr)
1.1.1.4   root     1179:                        {
1.1.1.6 ! root     1180:                                return Opt_ShowError(OPT_TRACE, argv[i], errstr);
1.1.1.4   root     1181:                        }
                   1182:                        break;
                   1183: 
                   1184:                case OPT_TRACEFILE:
                   1185:                        i += 1;
1.1.1.6 ! root     1186:                        ok = Opt_StrCpy(OPT_TRACEFILE, false, ConfigureParams.Log.sTraceFileName,
1.1.1.4   root     1187:                                        argv[i], sizeof(ConfigureParams.Log.sTraceFileName),
                   1188:                                        NULL);
                   1189:                        break;
                   1190: 
                   1191:                case OPT_CONTROLSOCKET:
                   1192:                        i += 1;
                   1193:                        errstr = Control_SetSocket(argv[i]);
                   1194:                        if (errstr)
1.1.1.2   root     1195:                        {
1.1.1.4   root     1196:                                return Opt_ShowError(OPT_CONTROLSOCKET, argv[i], errstr);
1.1.1.2   root     1197:                        }
                   1198:                        break;
                   1199: 
1.1.1.4   root     1200:                case OPT_LOGFILE:
                   1201:                        i += 1;
1.1.1.6 ! root     1202:                        ok = Opt_StrCpy(OPT_LOGFILE, false, ConfigureParams.Log.sLogFileName,
1.1.1.4   root     1203:                                        argv[i], sizeof(ConfigureParams.Log.sLogFileName),
                   1204:                                        NULL);
                   1205:                        break;
                   1206: 
                   1207:                case OPT_LOGLEVEL:
                   1208:                        i += 1;
                   1209:                        ConfigureParams.Log.nTextLogLevel = Log_ParseOptions(argv[i]);
                   1210:                        if (ConfigureParams.Log.nTextLogLevel == LOG_NONE)
                   1211:                        {
                   1212:                                return Opt_ShowError(OPT_LOGLEVEL, argv[i], "Unknown log level!");
                   1213:                        }
                   1214:                        break;
                   1215: 
                   1216:                case OPT_ALERTLEVEL:
                   1217:                        i += 1;
                   1218:                        ConfigureParams.Log.nAlertDlgLogLevel = Log_ParseOptions(argv[i]);
                   1219:                        if (ConfigureParams.Log.nAlertDlgLogLevel == LOG_NONE)
                   1220:                        {
                   1221:                                return Opt_ShowError(OPT_ALERTLEVEL, argv[i], "Unknown alert level!");
                   1222:                        }
                   1223:                        break;
1.1.1.6 ! root     1224: 
        !          1225:                case OPT_RUNVBLS:
        !          1226:                        nRunVBLs = atol(argv[++i]);
        !          1227:                        break;
1.1.1.4   root     1228:                       
                   1229:                case OPT_ERROR:
                   1230:                        /* unknown option or missing option parameter */
1.1.1.6 ! root     1231:                        return false;
1.1.1.4   root     1232: 
1.1       root     1233:                default:
1.1.1.4   root     1234:                        return Opt_ShowError(OPT_ERROR, argv[i], "Internal Hatari error, unhandled option");
                   1235:                }
                   1236:                if (!ok)
                   1237:                {
                   1238:                        /* Opt_Bool() or Opt_StrCpy() failed */
1.1.1.6 ! root     1239:                        return false;
1.1       root     1240:                }
                   1241:        }
1.1.1.4   root     1242: 
1.1.1.6 ! root     1243:        return true;
1.1       root     1244: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.