An emulator, assembler, and disassembler for the Sega Game Gear
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 
 

168 lignes
4.2 KiB

  1. /* Copyright (C) 2014-2015 Ben Kurtovic <ben.kurtovic@gmail.com>
  2. Released under the terms of the MIT License. See LICENSE for details. */
  3. #include <dirent.h>
  4. #include <errno.h>
  5. #include <stdbool.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <sys/types.h>
  10. #include "src/errors.h"
  11. #include "src/rom.h"
  12. #include "src/version.h"
  13. #define ROMS_DIR "roms"
  14. /* Print command-line help/usage. */
  15. static void print_help(const char *arg1)
  16. {
  17. printf("%s [--help|-h] [--version|-v] [rom_path]\n", arg1);
  18. }
  19. /* Print crater's version. */
  20. static void print_version()
  21. {
  22. printf("crater %s\n", CRATER_VERSION);
  23. }
  24. /* Parse the command-line arguments for any special flags. */
  25. static void parse_args(int argc, char *argv[])
  26. {
  27. char *arg;
  28. int i;
  29. for (i = 1; i < argc; i++) {
  30. arg = argv[i];
  31. if (arg[0] != '-')
  32. continue;
  33. do
  34. arg++;
  35. while (arg[0] == '-');
  36. if (!strcmp(arg, "h") || !strcmp(arg, "help")) {
  37. print_help(argv[0]);
  38. exit(0);
  39. } else if (!strcmp(arg, "v") || !strcmp(arg, "version")) {
  40. print_version();
  41. exit(0);
  42. } else {
  43. FATAL("unknown argument: %s", argv[i])
  44. }
  45. }
  46. }
  47. /* Return whether the given string ends with the given suffix. */
  48. static bool ends_with(const char *input, const char *suffix)
  49. {
  50. size_t ilen = strlen(input), slen = strlen(suffix);
  51. if (ilen < slen)
  52. return false;
  53. return strcmp(input + (ilen - slen), suffix) == 0;
  54. }
  55. /* Load all potential ROM files in roms/ into a data structure. */
  56. static int get_rom_paths(char ***path_ptr)
  57. {
  58. DIR *dirp;
  59. struct dirent *entry;
  60. char **paths = NULL, *path;
  61. int psize = 8, npaths = 0;
  62. dirp = opendir(ROMS_DIR);
  63. if (dirp) {
  64. paths = malloc(sizeof(char*) * psize);
  65. if (!paths)
  66. OUT_OF_MEMORY()
  67. while ((entry = readdir(dirp))) {
  68. path = entry->d_name;
  69. if (ends_with(path, ".gg") || ends_with(path, ".bin")) {
  70. if (npaths >= psize) {
  71. paths = realloc(paths, sizeof(char*) * (psize *= 2));
  72. if (!paths)
  73. OUT_OF_MEMORY()
  74. }
  75. paths[npaths] = malloc(sizeof(char*) *
  76. (strlen(path) + strlen(ROMS_DIR) + 1));
  77. if (!paths[npaths])
  78. OUT_OF_MEMORY()
  79. strcpy(paths[npaths], ROMS_DIR "/");
  80. strcat(paths[npaths], path);
  81. npaths++;
  82. }
  83. }
  84. closedir(dirp);
  85. } else {
  86. WARN_ERRNO("couldn't open 'roms/'")
  87. }
  88. *path_ptr = paths;
  89. return npaths;
  90. }
  91. /* Find all potential ROM files in the roms/ directory, then ask the user which
  92. one they want to run. */
  93. static char* get_rom_path_from_user()
  94. {
  95. char **paths, *path, *input = NULL;
  96. int npaths, i;
  97. long int index;
  98. size_t size = 0;
  99. ssize_t len;
  100. npaths = get_rom_paths(&paths);
  101. for (i = 0; i < npaths; i++)
  102. printf("[%2d] %s\n", i + 1, paths[i]);
  103. if (npaths)
  104. printf("Enter a ROM number from above, or the path to a ROM image: ");
  105. else
  106. printf("Enter the path to a ROM image: ");
  107. len = getline(&input, &size, stdin);
  108. if (!input)
  109. OUT_OF_MEMORY()
  110. if (len > 0 && input[len - 1] == '\n')
  111. input[len - 1] = '\0';
  112. index = strtol(input, NULL, 10);
  113. if (index < 1 || index > npaths)
  114. path = input;
  115. else
  116. path = paths[index - 1];
  117. for (i = 0; i < npaths; i++) {
  118. if (paths[i] != path)
  119. free(paths[i]);
  120. }
  121. if (paths)
  122. free(paths);
  123. return path;
  124. }
  125. int main(int argc, char *argv[])
  126. {
  127. char *rom_path;
  128. rom_type *rom;
  129. parse_args(argc, argv);
  130. printf("crater: a Sega Game Gear emulator\n\n");
  131. rom_path = argc > 1 ? argv[1] : get_rom_path_from_user();
  132. if (rom_path[0] == '\0')
  133. FATAL("no image given")
  134. if (!(rom = rom_open(rom_path))) {
  135. if (errno == ENOMEM)
  136. OUT_OF_MEMORY()
  137. else
  138. FATAL_ERRNO("couldn't load ROM image '%s'", rom_path)
  139. }
  140. if (argc <= 1)
  141. free(rom_path);
  142. printf("Loaded ROM image: %s.\n", rom->name);
  143. // TODO: start from here
  144. rom_close(rom);
  145. return 0;
  146. }