An emulator, assembler, and disassembler for the Sega Game Gear
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 

414 行
12 KiB

  1. /* Copyright (C) 2014-2019 Ben Kurtovic <ben.kurtovic@gmail.com>
  2. Released under the terms of the MIT License. See LICENSE for details. */
  3. #include <signal.h>
  4. #include <stdint.h>
  5. #include <unistd.h>
  6. #include <SDL.h>
  7. #include "emulator.h"
  8. #include "config.h"
  9. #include "gamegear.h"
  10. #include "logging.h"
  11. #include "save.h"
  12. #include "util.h"
  13. typedef struct {
  14. SDL_GameController **items;
  15. int num, capacity;
  16. } Controllers;
  17. typedef struct {
  18. GameGear *gg;
  19. SDL_Window *window;
  20. SDL_Renderer *renderer;
  21. SDL_Texture *texture;
  22. uint32_t *pixels;
  23. Controllers controllers;
  24. } Emulator;
  25. static Emulator emu;
  26. /*
  27. Signal handler for SIGINT. Tells the GameGear to power off, if it exists.
  28. */
  29. static void handle_sigint(int sig)
  30. {
  31. (void) sig;
  32. if (emu.gg)
  33. gamegear_power_off(emu.gg); // Safe!
  34. }
  35. /*
  36. Get the name of a SDL game controller.
  37. */
  38. static const char *get_controller_name(SDL_GameController *controller)
  39. {
  40. const char *name = SDL_GameControllerName(controller);
  41. if (name)
  42. return name;
  43. return "(UNKNOWN)";
  44. }
  45. /*
  46. Set up SDL for accepting controller input.
  47. */
  48. static void setup_input()
  49. {
  50. if (!access(CONTROLLER_DB_PATH, R_OK)) {
  51. if (SDL_GameControllerAddMappingsFromFile(CONTROLLER_DB_PATH) < 0)
  52. ERROR("SDL failed to load controller mappings: %s", SDL_GetError());
  53. }
  54. int i, c = 0, n = SDL_NumJoysticks();
  55. if (n <= 0)
  56. return;
  57. SDL_GameController **items = cr_calloc(n, sizeof(SDL_GameController*));
  58. for (i = 0; i < n; i++) {
  59. if (!SDL_IsGameController(i)) {
  60. DEBUG("Ignoring joystick %i: not a game controller", i);
  61. continue;
  62. }
  63. SDL_GameController *controller = SDL_GameControllerOpen(i);
  64. if (!controller) {
  65. ERROR("SDL failed to open controller %i: %s", i, SDL_GetError());
  66. continue;
  67. }
  68. DEBUG("Loaded controller %i: %s", i, get_controller_name(controller));
  69. items[c++] = controller;
  70. }
  71. emu.controllers.items = items;
  72. emu.controllers.num = c;
  73. emu.controllers.capacity = n;
  74. }
  75. /*
  76. Set up SDL for drawing the game.
  77. */
  78. static void setup_graphics(Config *config)
  79. {
  80. SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "nearest");
  81. uint32_t flags;
  82. if (config->fullscreen)
  83. flags = SDL_WINDOW_FULLSCREEN_DESKTOP;
  84. else
  85. flags = SDL_WINDOW_RESIZABLE;
  86. int width = config->scale * GG_SCREEN_WIDTH;
  87. int height = config->scale * GG_SCREEN_HEIGHT;
  88. if (!config->square_par)
  89. height = height * GG_PIXEL_HEIGHT / GG_PIXEL_WIDTH;
  90. emu.window = SDL_CreateWindow("crater", SDL_WINDOWPOS_UNDEFINED,
  91. SDL_WINDOWPOS_UNDEFINED, width, height, flags);
  92. if (!emu.window)
  93. FATAL("SDL failed to create a window: %s", SDL_GetError());
  94. emu.renderer = SDL_CreateRenderer(emu.window, -1,
  95. SDL_RENDERER_ACCELERATED|SDL_RENDERER_PRESENTVSYNC);
  96. if (!emu.renderer) {
  97. // Fall back to software renderer (or a hardware renderer
  98. // without vsync, if one exists?)
  99. emu.renderer = SDL_CreateRenderer(emu.window, -1, 0);
  100. if (!emu.renderer)
  101. FATAL("SDL failed to create a renderer: %s", SDL_GetError());
  102. }
  103. SDL_RendererInfo info;
  104. SDL_GetRendererInfo(emu.renderer, &info);
  105. DEBUG("Using %s renderer", info.name);
  106. emu.texture = SDL_CreateTexture(emu.renderer, SDL_PIXELFORMAT_ARGB8888,
  107. SDL_TEXTUREACCESS_STREAMING, GG_SCREEN_WIDTH, GG_SCREEN_HEIGHT);
  108. if (!emu.texture)
  109. FATAL("SDL failed to create a texture: %s", SDL_GetError());
  110. emu.pixels = cr_malloc(
  111. sizeof(uint32_t) * GG_SCREEN_WIDTH * GG_SCREEN_HEIGHT);
  112. SDL_RenderSetLogicalSize(emu.renderer,
  113. config->square_par ? GG_SCREEN_WIDTH : GG_LOGICAL_WIDTH,
  114. config->square_par ? GG_SCREEN_HEIGHT : GG_LOGICAL_HEIGHT);
  115. SDL_SetTextureBlendMode(emu.texture, SDL_BLENDMODE_BLEND);
  116. SDL_ShowCursor(SDL_DISABLE);
  117. SDL_SetRenderDrawColor(emu.renderer, 0x00, 0x00, 0x00, 0xFF);
  118. SDL_RenderClear(emu.renderer);
  119. SDL_RenderPresent(emu.renderer);
  120. }
  121. /*
  122. Set up SDL.
  123. */
  124. static void setup_sdl(Config *config)
  125. {
  126. if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_GAMECONTROLLER) < 0)
  127. FATAL("SDL failed to initialize: %s", SDL_GetError());
  128. setup_input();
  129. setup_graphics(config);
  130. }
  131. /*
  132. Actually send the pixel data to the screen.
  133. */
  134. static void draw_frame()
  135. {
  136. SDL_UpdateTexture(emu.texture, NULL, emu.pixels,
  137. GG_SCREEN_WIDTH * sizeof(uint32_t));
  138. SDL_SetRenderDrawColor(emu.renderer, 0x00, 0x00, 0x00, 0xFF);
  139. SDL_RenderClear(emu.renderer);
  140. SDL_RenderCopy(emu.renderer, emu.texture, NULL, NULL);
  141. SDL_RenderPresent(emu.renderer);
  142. }
  143. /*
  144. Handle a keyboard press; translate it into a Game Gear button press.
  145. */
  146. static void handle_keypress(GameGear *gg, SDL_Keycode key, bool state)
  147. {
  148. GGButton button;
  149. switch (key) {
  150. case SDLK_UP:
  151. case SDLK_w:
  152. button = BUTTON_UP; break;
  153. case SDLK_DOWN:
  154. case SDLK_s:
  155. button = BUTTON_DOWN; break;
  156. case SDLK_LEFT:
  157. case SDLK_a:
  158. button = BUTTON_LEFT; break;
  159. case SDLK_RIGHT:
  160. case SDLK_d:
  161. button = BUTTON_RIGHT; break;
  162. case SDLK_j:
  163. case SDLK_z:
  164. case SDLK_PERIOD:
  165. button = BUTTON_TRIGGER_1; break;
  166. case SDLK_k:
  167. case SDLK_x:
  168. case SDLK_SLASH:
  169. button = BUTTON_TRIGGER_2; break;
  170. case SDLK_RETURN:
  171. case SDLK_RETURN2:
  172. case SDLK_ESCAPE:
  173. button = BUTTON_START; break;
  174. default:
  175. return;
  176. }
  177. gamegear_input(gg, button, state);
  178. }
  179. /*
  180. Handle controller input.
  181. */
  182. static void handle_controller_input(
  183. GameGear *gg, SDL_GameControllerButton input, bool state)
  184. {
  185. GGButton button;
  186. switch (input) {
  187. case SDL_CONTROLLER_BUTTON_A:
  188. button = BUTTON_TRIGGER_1; break;
  189. case SDL_CONTROLLER_BUTTON_B:
  190. button = BUTTON_TRIGGER_2; break;
  191. case SDL_CONTROLLER_BUTTON_START:
  192. button = BUTTON_START; break;
  193. case SDL_CONTROLLER_BUTTON_DPAD_UP:
  194. button = BUTTON_UP; break;
  195. case SDL_CONTROLLER_BUTTON_DPAD_DOWN:
  196. button = BUTTON_DOWN; break;
  197. case SDL_CONTROLLER_BUTTON_DPAD_LEFT:
  198. button = BUTTON_LEFT; break;
  199. case SDL_CONTROLLER_BUTTON_DPAD_RIGHT:
  200. button = BUTTON_RIGHT; break;
  201. default:
  202. return;
  203. }
  204. gamegear_input(gg, button, state);
  205. }
  206. /*
  207. Handle a controller being added.
  208. */
  209. static void handle_controller_added(int i)
  210. {
  211. SDL_Joystick *joy = SDL_JoystickOpen(i);
  212. SDL_JoystickID id = SDL_JoystickInstanceID(joy);
  213. for (int i = 0; i < emu.controllers.num; i++) {
  214. SDL_Joystick *other = SDL_GameControllerGetJoystick(
  215. emu.controllers.items[i]);
  216. if (SDL_JoystickInstanceID(other) == id) {
  217. TRACE("SDL added duplicate joystick %i", i);
  218. SDL_JoystickClose(joy);
  219. return;
  220. }
  221. }
  222. SDL_JoystickClose(joy);
  223. if (!SDL_IsGameController(i)) {
  224. DEBUG("SDL added joystick %i: not a game controller", i);
  225. return;
  226. }
  227. SDL_GameController *controller = SDL_GameControllerOpen(i);
  228. if (!controller) {
  229. ERROR("SDL failed to open controller %i: %s", i, SDL_GetError());
  230. return;
  231. }
  232. DEBUG("Added controller %i: %s", i, get_controller_name(controller));
  233. if (emu.controllers.num == 0) {
  234. int n = 4;
  235. emu.controllers.items = cr_calloc(n, sizeof(SDL_GameController*));
  236. emu.controllers.capacity = n;
  237. }
  238. else if (emu.controllers.num >= emu.controllers.capacity) {
  239. emu.controllers.capacity *= 2;
  240. emu.controllers.items = cr_realloc(emu.controllers.items,
  241. emu.controllers.capacity * sizeof(SDL_GameController*));
  242. }
  243. emu.controllers.items[emu.controllers.num++] = controller;
  244. }
  245. /*
  246. Handle a controller being removed.
  247. */
  248. static void handle_controller_removed(int id)
  249. {
  250. for (int i = 0; i < emu.controllers.num; i++) {
  251. SDL_GameController *controller = emu.controllers.items[i];
  252. SDL_Joystick *joy = SDL_GameControllerGetJoystick(controller);
  253. if (!joy)
  254. continue;
  255. if (SDL_JoystickInstanceID(joy) == id) {
  256. DEBUG("Removed controller %i: %s", i,
  257. get_controller_name(controller));
  258. SDL_GameControllerClose(controller);
  259. for (; i < emu.controllers.num; i++)
  260. emu.controllers.items[i] = emu.controllers.items[i + 1];
  261. emu.controllers.num--;
  262. return;
  263. }
  264. }
  265. DEBUG("SDL removed unknown controller: %i", id)
  266. }
  267. /*
  268. Handle SDL events, mainly quit events and button presses.
  269. */
  270. static void handle_events(GameGear *gg)
  271. {
  272. SDL_Event event;
  273. while (SDL_PollEvent(&event)) {
  274. switch (event.type) {
  275. case SDL_QUIT:
  276. gamegear_power_off(gg);
  277. return;
  278. case SDL_KEYDOWN:
  279. handle_keypress(gg, event.key.keysym.sym, true);
  280. break;
  281. case SDL_KEYUP:
  282. handle_keypress(gg, event.key.keysym.sym, false);
  283. break;
  284. case SDL_CONTROLLERBUTTONDOWN:
  285. handle_controller_input(gg, event.cbutton.button, true);
  286. break;
  287. case SDL_CONTROLLERBUTTONUP:
  288. handle_controller_input(gg, event.cbutton.button, false);
  289. break;
  290. case SDL_CONTROLLERDEVICEADDED:
  291. handle_controller_added(event.cdevice.which);
  292. break;
  293. case SDL_CONTROLLERDEVICEREMOVED:
  294. handle_controller_removed(event.cdevice.which);
  295. break;
  296. }
  297. }
  298. }
  299. /*
  300. GameGear callback: Draw the current frame and handle SDL event logic.
  301. */
  302. static void frame_callback(GameGear *gg)
  303. {
  304. draw_frame();
  305. handle_events(gg);
  306. }
  307. /*
  308. Clean up SDL stuff allocated in setup_sdl().
  309. */
  310. static void cleanup_sdl()
  311. {
  312. free(emu.pixels);
  313. SDL_DestroyTexture(emu.texture);
  314. SDL_DestroyRenderer(emu.renderer);
  315. SDL_DestroyWindow(emu.window);
  316. for (int i = 0; i < emu.controllers.num; i++)
  317. SDL_GameControllerClose(emu.controllers.items[i]);
  318. if (emu.controllers.items)
  319. free(emu.controllers.items);
  320. SDL_Quit();
  321. emu.window = NULL;
  322. emu.renderer = NULL;
  323. emu.texture = NULL;
  324. emu.controllers.items = NULL;
  325. emu.controllers.num = emu.controllers.capacity = 0;
  326. }
  327. /*
  328. Emulate a ROM in a Game Gear while handling I/O with the host computer.
  329. Block until emulation is finished.
  330. */
  331. void emulate(ROM *rom, Config *config)
  332. {
  333. Save save;
  334. if (!config->no_saving) {
  335. if (!save_init(&save, config->sav_path, rom))
  336. return;
  337. }
  338. BIOS *bios = NULL;
  339. if (config->bios_path) {
  340. if (!(bios = bios_open(config->bios_path)))
  341. return;
  342. }
  343. emu.gg = gamegear_create();
  344. signal(SIGINT, handle_sigint);
  345. setup_sdl(config);
  346. gamegear_attach_callback(emu.gg, frame_callback);
  347. gamegear_attach_display(emu.gg, emu.pixels);
  348. gamegear_load_rom(emu.gg, rom);
  349. if (bios)
  350. gamegear_load_bios(emu.gg, bios);
  351. if (!config->no_saving)
  352. gamegear_load_save(emu.gg, &save);
  353. gamegear_simulate(emu.gg);
  354. if (gamegear_get_exception(emu.gg))
  355. ERROR("caught exception: %s", gamegear_get_exception(emu.gg))
  356. else
  357. WARN("caught signal, stopping...")
  358. if (DEBUG_LEVEL)
  359. gamegear_print_state(emu.gg);
  360. cleanup_sdl();
  361. signal(SIGINT, SIG_DFL);
  362. gamegear_destroy(emu.gg);
  363. emu.gg = NULL;
  364. if (!config->no_saving)
  365. save_free(&save);
  366. }