/* Copyright (C) 2014 Ben Kurtovic Released under the terms of the MIT License. See LICENSE for details. */ #include #include #include #include #include #include #include #include "src/errors.h" #include "src/rom.h" #include "src/version.h" #define ROMS_DIR "roms" /* Print command-line help/usage. */ static void print_help(char *arg1) { printf("%s [--help|-h] [--version|-v] [rom_path]\n", arg1); } /* Print crater's version. */ static void print_version() { printf("crater %s\n", CRATER_VERSION); } /* Parse the command-line arguments for any special flags. */ static void parse_args(int argc, char *argv[]) { char *arg; int i; for (i = 1; i < argc; i++) { arg = argv[i]; if (arg[0] != '-') continue; do arg++; while (arg[0] == '-'); if (!strcmp(arg, "h") || !strcmp(arg, "help")) { print_help(argv[0]); exit(0); } else if (!strcmp(arg, "v") || !strcmp(arg, "version")) { print_version(); exit(0); } else { printf("Error: unknown argument: %s\n", argv[i]); exit(1); } } } /* Return whether the given string ends with the given suffix. */ static bool ends_with(char *input, char *suffix) { size_t ilen = strlen(input), slen = strlen(suffix); if (ilen < slen) return false; return strcmp(input + (ilen - slen), suffix) == 0; } /* Load all potential ROM files in roms/ into a data structure. */ static int load_rom_paths(char ***path_ptr) { DIR *dirp; struct dirent *entry; char **paths = NULL, *path; int psize = 8, npaths = 0; dirp = opendir(ROMS_DIR); if (dirp) { paths = malloc(sizeof(char*) * psize); if (!paths) out_of_memory(); while ((entry = readdir(dirp))) { path = entry->d_name; if (ends_with(path, ".gg") || ends_with(path, ".bin")) { if (npaths >= psize) { paths = realloc(paths, sizeof(char*) * (psize *= 2)); if (!paths) out_of_memory(); } paths[npaths] = malloc(sizeof(char*) * (strlen(path) + strlen(ROMS_DIR) + 1)); if (!paths[npaths]) out_of_memory(); strcpy(paths[npaths], ROMS_DIR "/"); strcat(paths[npaths], path); npaths++; } } closedir(dirp); } else { if (errno == ENOENT) printf("Warning: couldn't find roms/ directory.\n"); else perror("Warning: couldn't open roms/ directory"); } *path_ptr = paths; return npaths; } /* Find all potential ROM files in the roms/ directory, then ask the user which * one they want to run. */ static char* get_rom_path_from_user() { char **paths, *path, *input = NULL; int npaths, i; long int index; size_t size = 0; ssize_t len; npaths = load_rom_paths(&paths); for (i = 0; i < npaths; i++) printf("[%2d] %s\n", i + 1, paths[i]); if (npaths) printf("Enter a ROM number from above, or the path to a ROM image: "); else printf("Enter the path to a ROM image: "); len = getline(&input, &size, stdin); if (!input) out_of_memory(); if (len > 0 && input[len - 1] == '\n') input[len - 1] = '\0'; index = strtol(input, NULL, 10); if (index < 1 || index > npaths) path = input; else path = paths[index - 1]; for (i = 0; i < npaths; i++) { if (paths[i] != path) free(paths[i]); } if (paths) free(paths); return path; } int main(int argc, char *argv[]) { char *rom_path; parse_args(argc, argv); rom_path = argc > 1 ? argv[1] : get_rom_path_from_user(); // TODO: main logic hook here printf("Loading ROM: %s\n", rom_path); if (argc <= 1) free(rom_path); return 0; }