|
|
@@ -1,10 +1,160 @@ |
|
|
|
/* Copyright (C) 2014 Ben Kurtovic <ben.kurtovic@gmail.com> |
|
|
|
Released under the terms of the MIT License. See LICENSE for details. */ |
|
|
|
|
|
|
|
#include <dirent.h> |
|
|
|
#include <errno.h> |
|
|
|
#include <stdbool.h> |
|
|
|
#include <stdio.h> |
|
|
|
#include <SDL.h> |
|
|
|
#include <stdlib.h> |
|
|
|
#include <string.h> |
|
|
|
#include <sys/types.h> |
|
|
|
|
|
|
|
int main(int argc, char* argv[]) { |
|
|
|
printf("Hello, world!\n"); |
|
|
|
#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; |
|
|
|
} |