Annotation of previous/src/options.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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