#undef _GNU_SOURCE #define _GNU_SOURCE #include #include #include #include #include #include "input.h" #include "rc.h" #include "sys.h" #include "rckeys.h" #include "emu.h" #include "exports.h" #include "loader.h" #include "Version" static char *defaultconfig[] = { "bind esc quit", "bind up +up", "bind down +down", "bind left +left", "bind right +right", "bind d +a", "bind s +b", "bind enter +start", "bind space +select", "bind tab +select", "bind joyup +up", "bind joydown +down", "bind joyleft +left", "bind joyright +right", "bind joy0 +b", "bind joy1 +a", "bind joy2 +select", "bind joy3 +start", "bind 1 \"set saveslot 1\"", "bind 2 \"set saveslot 2\"", "bind 3 \"set saveslot 3\"", "bind 4 \"set saveslot 4\"", "bind 5 \"set saveslot 5\"", "bind 6 \"set saveslot 6\"", "bind 7 \"set saveslot 7\"", "bind 8 \"set saveslot 8\"", "bind 9 \"set saveslot 9\"", "bind 0 \"set saveslot 0\"", "bind ins savestate", "bind del loadstate", "source gnuboy.rc", NULL }; static void banner() { printf("\ngnuboy " VERSION "\n"); } static void copyright() { banner(); printf( "Copyright (C) 2000-2001 Laguna and Gilgamesh\n" "Portions contributed by other authors; see CREDITS for details.\n" "\n" "This program is free software; you can redistribute it and/or modify\n" "it under the terms of the GNU General Public License as published by\n" "the Free Software Foundation; either version 2 of the License, or\n" "(at your option) any later version.\n" "\n" "This program is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "GNU General Public License for more details.\n" "\n" "You should have received a copy of the GNU General Public License\n" "along with this program; if not, write to the Free Software\n" "Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n" "\n"); } static void usage(char *name) { copyright(); printf("Type %s --help for detailed help.\n\n", name); exit(1); } static void copying() { copyright(); exit(0); } static void help(char *name) { banner(); printf("Usage: %s [options] romfile\n", name); printf("\n" " --source FILE read rc commands from FILE\n" " --bind KEY COMMAND bind KEY to perform COMMAND\n" " --VAR=VALUE set rc variable VAR to VALUE\n" " --VAR set VAR to 1 (turn on boolean options)\n" " --no-VAR set VAR to 0 (turn off boolean options)\n" " --showvars list all available rc variables\n" " --help display this help and exit\n" " --version output version information and exit\n" " --copying show copying permissions\n" ""); exit(0); } static void version(char *name) { printf("%s-" VERSION "\n", name); exit(0); } void doevents() { event_t ev; int st; ev_poll(); while (ev_getevent(&ev)) { if (ev.type != EV_PRESS && ev.type != EV_RELEASE) continue; st = (ev.type != EV_RELEASE); rc_dokey(ev.code, st); } } static void shutdown() { vid_close(); pcm_close(); } void die(char *fmt, ...) { va_list ap; va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); exit(1); } static int bad_signals[] = { /* These are all standard, so no need to #ifdef them... */ SIGINT, SIGSEGV, SIGTERM, SIGFPE, SIGABRT, SIGILL, #ifdef SIGQUIT SIGQUIT, #endif #ifdef SIGPIPE SIGPIPE, #endif 0 }; static void fatalsignal(int s) { die("Signal %d\n", s); } static void catch_signals() { int i; for (i = 0; bad_signals[i]; i++) signal(bad_signals[i], fatalsignal); } static char *base(char *s) { char *p; p = strrchr(s, '/'); if (p) return p+1; return s; } int main(int argc, char *argv[]) { int i; char *opt, *arg, *cmd, *s, *rom = 0; /* Avoid initializing video if we don't have to */ for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "--help")) help(base(argv[0])); else if (!strcmp(argv[i], "--version")) version(base(argv[0])); else if (!strcmp(argv[i], "--copying")) copying(); else if (!strcmp(argv[i], "--bind")) i += 2; else if (!strcmp(argv[i], "--source")) i++; else if (!strcmp(argv[i], "--showvars")) { show_exports(); exit(0); } else if (argv[i][0] == '-' && argv[i][1] == '-'); else if (argv[i][0] == '-' && argv[i][1]); else rom = argv[i]; } if (!rom) usage(base(argv[0])); /* If we have special perms, drop them ASAP! */ vid_preinit(); init_exports(); s = strdup(argv[0]); sys_sanitize(s); sys_initpath(s); for (i = 0; defaultconfig[i]; i++) rc_command(defaultconfig[i]); cmd = malloc(strlen(rom) + 11); sprintf(cmd, "source %s", rom); s = strchr(cmd, '.'); if (s) *s = 0; strcat(cmd, ".rc"); rc_command(cmd); for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "--bind")) { if (i + 2 >= argc) die("missing arguments to bind\n"); cmd = malloc(strlen(argv[i+1]) + strlen(argv[i+2]) + 9); sprintf(cmd, "bind %s \"%s\"", argv[i+1], argv[i+2]); rc_command(cmd); free(cmd); i += 2; } else if (!strcmp(argv[i], "--source")) { if (i + 1 >= argc) die("missing argument to source\n"); cmd = malloc(strlen(argv[i+1]) + 6); sprintf(cmd, "source %s", argv[++i]); rc_command(cmd); free(cmd); } else if (!strncmp(argv[i], "--no-", 5)) { opt = strdup(argv[i]+5); while ((s = strchr(opt, '-'))) *s = '_'; cmd = malloc(strlen(opt) + 7); sprintf(cmd, "set %s 0", opt); rc_command(cmd); free(cmd); free(opt); } else if (argv[i][0] == '-' && argv[i][1] == '-') { opt = strdup(argv[i]+2); if ((s = strchr(opt, '='))) { *s = 0; arg = s+1; } else arg = "1"; while ((s = strchr(opt, '-'))) *s = '_'; while ((s = strchr(arg, ','))) *s = ' '; cmd = malloc(strlen(opt) + strlen(arg) + 6); sprintf(cmd, "set %s %s", opt, arg); rc_command(cmd); free(cmd); free(opt); } /* short options not yet implemented */ else if (argv[i][0] == '-' && argv[i][1]); } /* FIXME - make interface modules responsible for atexit() */ atexit(shutdown); catch_signals(); vid_init(); pcm_init(); rom = strdup(rom); sys_sanitize(rom); loader_init(rom); emu_reset(); emu_run(); /* never reached */ return 0; }