X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=args.c;h=3ff1412dc649ee7a31f2253ce20308c99fcee44e;hb=refs%2Fheads%2Fjoystick;hp=013121587a5c8d1e831aca8e25923ebf30ba7989;hpb=3ef599c7104a20c4f5268dbefb6590aa3e285663;p=vor.git diff --git a/args.c b/args.c index 0131215..3ff1412 100644 --- a/args.c +++ b/args.c @@ -1,88 +1,208 @@ -#include +#include +#include +#include #include "args.h" -#include "config.h" - -// Gameplay Variations -float opt_bounciness; -float opt_gamespeed; -float opt_max_lead; +#include +#include "vorconfig.h" // Look and Feel int opt_fullscreen; -int opt_music; int opt_sound; +int opt_joystick_enabled; +int opt_joystick_number; +int opt_joystick_x_axis; +int opt_joystick_y_axis; + +int opt_autopilot; + +static void +show_help(void) +{ + puts("Dodge the rocks until you die."); + putchar('\n'); + puts(" -f, --full-screen"); + puts(" -s, --silent No explosion sounds or music"); + puts(" -j x,y, --joystick=x,y set the axis numbers. defaults to 0,1"); + puts(" press a joystick button to activate that joystick"); + puts(" -V, --version Print program version"); + puts(" -?, --help Give this help list"); + putchar('\n'); + puts("Report bugs at http://jasonwoof.com/contact.html"); +} + +// Advances buf while reading a positive int, terminated by [^0-9] +// buf is left pointing at first [^0-9] +// If digits are found, the parsed number is written to *out and 0 is returned. +// Otherwise *buf and *out are left unchanged, and non-zero is returned. +int +parse_next_int(char **buf, int* out) { + int ret = 0, mul = 1; + if(!*buf) { + return 1; + } + // make sure *buf starts -?[0-9] + if(**buf == '-') { + mul = -1; + if((*buf)[1] < '0' || (*buf)[1] > '9') { + return 2; + } + *buf += 1; + } else { + if(**buf < '0' || **buf > '9') { + return 2; + } + } + while(**buf >= '0' && **buf <= '9') { + ret *= 10; + ret += **buf - '0'; + *buf += 1; + } + *out = ret * mul; + + return 0; +} + +// returns 1 on success. return 0 causes usage message +int +parse_joystick_opts(char *arg) { + char *arg_was = arg; + static char* bad_arg = "Error: invalid argument to -j/--joystick."; + + // argument is required + if(arg == NULL) { + puts(bad_arg); + return 0; + } + + // read x axis + if(parse_next_int(&arg, &opt_joystick_x_axis)) { + puts(bad_arg); + return 0; + } + + // skip comma + if(*arg != ',') { + puts(bad_arg); + return 0; + } + arg += 1; + + // read y axis + if(parse_next_int(&arg, &opt_joystick_y_axis)) { + puts(bad_arg); + return 0; + } + + // optionally joystick number + if(*arg == ',') { + arg += 1; // skip comma + if(parse_next_int(&arg, &opt_joystick_number)) { + puts(bad_arg); + return 0; + } + opt_joystick_enabled = 1; + } + + // end with a comma or end of string + if(*arg != 0 && *arg != ',') { + puts(bad_arg); + return 0; + } + + // mark arg as consumed (so it won't be parsed as a commandline switch) + arg_was[0] = 0; + + // return success + return 1; +} +int +short_opt(char c, char *arg) +{ + switch(c) { + case 'f': opt_fullscreen = 1; break; + case 's': opt_sound = 0; break; + case 'j': + return parse_joystick_opts(arg); + case 'V': + printf("Variations on Rockdodger %s\n", PACKAGE_VERSION); + exit(0); + case '?': + case 'h': return 0; + case 'a': opt_autopilot = 1; break; + default: + fprintf(stderr, "unknown option -%c\n\n", c); + return 0; + } + return 1; +} + +int +parse_short_opts(const char *s, char *arg) +{ + while(s[1]) if(!short_opt(*s++, NULL)) return 0; + return short_opt(*s, arg); +} + +static char *long_opts[] = { "full-screen", "silent", "joystick", "version", "help", "autopilot" }; -error_t parse_opt(int, char*, struct argp_state *); - -const char *argp_program_version = "Variations on Rockdodger " VERSION; -const char *argp_program_bug_address = ""; -static char doc[] = "Dodge the rocks until you die."; -static struct argp_option opts[] = { - {0, 0, 0, 0, "Gameplay Variations:"}, - {"bounciness", 'b', "N%", 0, "Keep N% of speed when hitting edges (default 50%)"}, - {"game-speed", 'g', "N%", 0, "50-100% (default 100%)"}, - {"max-lead", 'l', "#SCREENS", OPTION_HIDDEN, - "Max distance ahead you can get\n (default 1 screen; < 0 means no limit)"}, - {0, 0, 0, 0, "Look and Feel:"}, - {"full-screen", 'f', 0, 0, ""}, - {"music", 'm', 0, 0, "Enable music"}, - {"silent", 's', 0, 0, "No explosion sounds or music"}, - {0, 0, 0, 0, "Informational:", -1}, - {0} -}; - -struct argp argp = { opts, &parse_opt, 0, doc }; +static char short_opts[] = { 'f', 's', 'j', 'V', 'h', 'a' }; + +int +parse_long_opt(const char *s, char *arg) +{ + int i; + for(i=0; i 100) i = 100; - opt_bounciness = (float)i / 100; - break; - case 'f': opt_fullscreen = 1; break; - case 'g': if(!sscanf(arg, "%d%%", &i)) { - fprintf(stderr, "bad --gamespeed (-g) value (should be 50-100%%)\n"); - argp_state_help(state, stderr, ARGP_HELP_STD_HELP); - return EINVAL; - } - if(i < 0) i = 0; else if(i > 100) i = 100; - opt_gamespeed = (float)i / 100; - break; - case 'l': if(!sscanf(arg, "%f", &opt_max_lead)) { - fprintf(stderr, "bad --max-lead (-l) value (must be a number)\n"); - argp_state_help(state, stderr, ARGP_HELP_STD_HELP); - return EINVAL; - } - opt_max_lead *= XSIZE; - break; - case 'm': opt_music = 1; break; - case 's': opt_sound = 0; opt_music = 0; break; - case ARGP_KEY_END: - break; - default: - return ARGP_ERR_UNKNOWN; + init_opts(); + for(i=1; i