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.
 
 
 
 
 

157 lignes
3.9 KiB

  1. /* Copyright (C) 2014-2016 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 <SDL.h>
  6. #include "emulator.h"
  7. #include "gamegear.h"
  8. #include "logging.h"
  9. #include "util.h"
  10. typedef struct {
  11. GameGear *gg;
  12. SDL_Window *window;
  13. SDL_Renderer *renderer;
  14. SDL_Texture *texture;
  15. uint32_t *pixels;
  16. } Emulator;
  17. static Emulator emu;
  18. /*
  19. Signal handler for SIGINT. Tells the GameGear to power off, if it exists.
  20. */
  21. static void handle_sigint(int sig)
  22. {
  23. (void) sig;
  24. if (emu.gg)
  25. gamegear_power_off(emu.gg); // Safe!
  26. }
  27. /*
  28. Set up SDL for drawing the game.
  29. */
  30. static void setup_graphics(bool fullscreen, unsigned scale)
  31. {
  32. if (SDL_Init(SDL_INIT_VIDEO) < 0)
  33. FATAL("SDL failed to initialize: %s", SDL_GetError());
  34. uint32_t flags;
  35. if (fullscreen)
  36. flags = SDL_WINDOW_FULLSCREEN_DESKTOP;
  37. else
  38. flags = SDL_WINDOW_BORDERLESS|SDL_WINDOW_RESIZABLE;
  39. SDL_CreateWindowAndRenderer(
  40. scale * GG_SCREEN_WIDTH, scale * GG_SCREEN_HEIGHT,
  41. flags, &emu.window, &emu.renderer);
  42. if (!emu.window)
  43. FATAL("SDL failed to create a window: %s", SDL_GetError());
  44. if (!emu.renderer)
  45. FATAL("SDL failed to create a renderer: %s", SDL_GetError());
  46. emu.texture = SDL_CreateTexture(emu.renderer, SDL_PIXELFORMAT_ARGB8888,
  47. SDL_TEXTUREACCESS_STREAMING, GG_SCREEN_WIDTH, GG_SCREEN_HEIGHT);
  48. if (!emu.texture)
  49. FATAL("SDL failed to create a texture: %s", SDL_GetError());
  50. emu.pixels = cr_malloc(
  51. sizeof(uint32_t) * GG_SCREEN_WIDTH * GG_SCREEN_HEIGHT);
  52. SDL_RenderSetLogicalSize(emu.renderer, GG_SCREEN_WIDTH, GG_SCREEN_HEIGHT);
  53. SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "nearest");
  54. SDL_SetWindowTitle(emu.window, "crater");
  55. SDL_ShowCursor(SDL_DISABLE);
  56. SDL_SetRenderDrawColor(emu.renderer, 0x00, 0x00, 0x00, 0xFF);
  57. SDL_RenderClear(emu.renderer);
  58. SDL_RenderPresent(emu.renderer);
  59. }
  60. /*
  61. Actually send the pixel data to the screen.
  62. */
  63. static void draw_frame()
  64. {
  65. SDL_UpdateTexture(emu.texture, NULL, emu.pixels,
  66. GG_SCREEN_WIDTH * sizeof(uint32_t));
  67. SDL_SetRenderDrawColor(emu.renderer, 0x00, 0x00, 0x00, 0xFF);
  68. SDL_RenderClear(emu.renderer);
  69. SDL_RenderCopy(emu.renderer, emu.texture, NULL, NULL);
  70. SDL_RenderPresent(emu.renderer);
  71. }
  72. /*
  73. Handle SDL events, mainly quit events and button presses.
  74. */
  75. static void handle_events(GameGear *gg)
  76. {
  77. SDL_Event e;
  78. while (SDL_PollEvent(&e)) {
  79. if (e.type == SDL_QUIT) {
  80. gamegear_power_off(gg);
  81. return;
  82. }
  83. // TODO: buttons
  84. }
  85. }
  86. /*
  87. GameGear callback: Draw the current frame and handle SDL event logic.
  88. */
  89. static void frame_callback(GameGear *gg)
  90. {
  91. draw_frame();
  92. handle_events(gg);
  93. }
  94. /*
  95. Clean up SDL stuff allocated in setup_graphics().
  96. */
  97. static void cleanup_graphics()
  98. {
  99. free(emu.pixels);
  100. SDL_DestroyTexture(emu.texture);
  101. SDL_DestroyRenderer(emu.renderer);
  102. SDL_DestroyWindow(emu.window);
  103. SDL_Quit();
  104. emu.window = NULL;
  105. emu.renderer = NULL;
  106. emu.texture = NULL;
  107. }
  108. /*
  109. Emulate a ROM in a Game Gear while handling I/O with the host computer.
  110. Block until emulation is finished.
  111. */
  112. void emulate(ROM *rom, bool fullscreen, unsigned scale)
  113. {
  114. emu.gg = gamegear_create();
  115. signal(SIGINT, handle_sigint);
  116. setup_graphics(fullscreen, scale);
  117. gamegear_attach_callback(emu.gg, frame_callback);
  118. gamegear_attach_display(emu.gg, emu.pixels);
  119. gamegear_load(emu.gg, rom);
  120. gamegear_simulate(emu.gg);
  121. if (gamegear_get_exception(emu.gg))
  122. ERROR("caught exception: %s", gamegear_get_exception(emu.gg))
  123. else
  124. WARN("caught signal, stopping...")
  125. if (DEBUG_LEVEL)
  126. gamegear_print_state(emu.gg);
  127. cleanup_graphics();
  128. signal(SIGINT, SIG_DFL);
  129. gamegear_destroy(emu.gg);
  130. emu.gg = NULL;
  131. }