NESe (pronounced "Nessie") is a NES emulator based on the e6502 emulator, also written in C with a focus on speed and portability for use on embedded platforms, especially ARM.
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

225 lines
7.4KB

  1. #include <SDL.h>
  2. #include "input.h"
  3. static SDL_GameController* sdl_find_gamepad() {
  4. int i = SDL_NumJoysticks() - 1;
  5. printf("Found %d joysticks\n", i + 1);
  6. for ( ; i >= 0 && !SDL_IsGameController(i); --i);
  7. if (i >= 0) printf("Joystick %d is a gamepad\n", i);
  8. return (i < 0 ? NULL : SDL_GameControllerOpen(i));
  9. }
  10. static void sdl_lose_gamepad(void* data) {
  11. SDL_GameController* gamepad = (SDL_GameController*)data;
  12. if (NULL != gamepad) SDL_GameControllerClose(gamepad);
  13. }
  14. static int sdl_match_gamepad(SDL_JoystickID id, void* data) {
  15. SDL_GameController* gamepad = (SDL_GameController*)data;
  16. return ( SDL_JoystickInstanceID(
  17. SDL_GameControllerGetJoystick(gamepad))
  18. == id);
  19. }
  20. /*
  21. static int sdl_event_filter(void*, SDL_Event* event) {
  22. return ( SDL_QUIT == event->type ||
  23. SDL_KEYDOWN == event->type ||
  24. SDL_KEYUP == event->type ||
  25. SDL_CONTROLLERBUTTONDOWN == event->type ||
  26. SDL_CONTROLLERBUTTONUP == event->type ||
  27. SDL_CONTROLLERDEVICEADDED == event->type ||
  28. SDL_CONTROLLERDEVICEREMOVED == event->type
  29. );
  30. }
  31. */
  32. static int sdl_input_init(nes_Input_Reader* reader) {
  33. int status = SDL_Init(SDL_INIT_EVENTS |
  34. SDL_INIT_GAMECONTROLLER);
  35. if (status == 0) {
  36. reader->data = sdl_find_gamepad();
  37. // SDL_SetEventFilter(sdl_event_filter, NULL);
  38. if (NULL != reader->data) {
  39. printf("Gamepad found\n");
  40. }
  41. }
  42. return status;
  43. }
  44. static void sdl_input_done(nes_Input_Reader* input) {
  45. sdl_lose_gamepad(input->data);
  46. }
  47. static const int sdl_menu_key = SDLK_ESCAPE;
  48. static const int sdl_save_key = SDLK_F1;
  49. static const int sdl_load_key = SDLK_F2;
  50. static const int sdl_keycodes[nes_controller_num_buttons] = {
  51. SDLK_a,
  52. SDLK_s,
  53. SDLK_q,
  54. SDLK_w,
  55. SDLK_UP,
  56. SDLK_DOWN,
  57. SDLK_LEFT,
  58. SDLK_RIGHT,
  59. };
  60. static const int sdl_menu_button = SDL_CONTROLLER_BUTTON_X;
  61. static const int sdl_save_button = SDL_CONTROLLER_BUTTON_LEFTSHOULDER;
  62. static const int sdl_load_button = SDL_CONTROLLER_BUTTON_RIGHTSHOULDER;
  63. static const int sdl_buttons[nes_controller_num_buttons] = {
  64. SDL_CONTROLLER_BUTTON_A,
  65. SDL_CONTROLLER_BUTTON_B,
  66. SDL_CONTROLLER_BUTTON_BACK,
  67. SDL_CONTROLLER_BUTTON_START,
  68. SDL_CONTROLLER_BUTTON_DPAD_UP,
  69. SDL_CONTROLLER_BUTTON_DPAD_DOWN,
  70. SDL_CONTROLLER_BUTTON_DPAD_LEFT,
  71. SDL_CONTROLLER_BUTTON_DPAD_RIGHT,
  72. };
  73. static int button_index(int keycode, const int* codes) {
  74. int index = nes_controller_num_buttons - 1;
  75. for ( ; index >= 0 && keycode != codes[index]; --index);
  76. return index;
  77. }
  78. static int sdl_input_update(nes_Input_Reader* reader,
  79. nes_input* input) {
  80. int status = input_Result_OK;
  81. SDL_Event event = {0};
  82. while (0 == status && 0 != SDL_PollEvent(&event)) {
  83. if (SDL_QUIT == event.type) {
  84. status = input_Result_Quit;
  85. } else if ( ( SDL_KEYDOWN == event.type ||
  86. SDL_KEYUP == event.type) &&
  87. 0 == event.key.repeat
  88. ) {
  89. int index = button_index(event.key.keysym.sym,
  90. sdl_keycodes);
  91. if (index >= 0) {
  92. uint8_t mask = (1 << index);
  93. if (SDL_KEYDOWN == event.type) {
  94. input->controllers[0].buttons |= mask;
  95. } else {
  96. input->controllers[0].buttons &= ~mask;
  97. }
  98. } else if ( sdl_menu_key == event.key.keysym.sym &&
  99. SDL_KEYDOWN == event.type) {
  100. status = input_Result_Menu;
  101. } else if (sdl_save_key == event.key.keysym.sym) {
  102. if (SDL_KEYDOWN == event.type) {
  103. status = input_Result_Save;
  104. } else {
  105. status = input_Result_Cancel;
  106. }
  107. } else if (sdl_load_key == event.key.keysym.sym) {
  108. if (SDL_KEYDOWN == event.type) {
  109. status = input_Result_Load;
  110. } else {
  111. status = input_Result_Cancel;
  112. }
  113. }
  114. } else if ( SDL_CONTROLLERBUTTONDOWN == event.type ||
  115. SDL_CONTROLLERBUTTONUP == event.type) {
  116. int index = button_index(event.cbutton.button,
  117. sdl_buttons);
  118. if (index >= 0) {
  119. uint8_t mask = (1 << index);
  120. if (SDL_CONTROLLERBUTTONDOWN == event.type) {
  121. input->controllers[0].buttons |= mask;
  122. } else {
  123. input->controllers[0].buttons &= ~mask;
  124. }
  125. } else if (sdl_menu_button == event.cbutton.button) {
  126. if (SDL_CONTROLLERBUTTONDOWN == event.type) {
  127. status = input_Result_Menu;
  128. }
  129. } else if (sdl_save_button == event.cbutton.button) {
  130. if (SDL_CONTROLLERBUTTONDOWN == event.type) {
  131. status = input_Result_Save;
  132. } else {
  133. status = input_Result_Cancel;
  134. }
  135. } else if (sdl_load_button == event.cbutton.button) {
  136. if (SDL_CONTROLLERBUTTONDOWN == event.type) {
  137. status = input_Result_Load;
  138. } else {
  139. status = input_Result_Cancel;
  140. }
  141. }
  142. } else if (SDL_CONTROLLERAXISMOTION == event.type) {
  143. const uint8_t axis = event.caxis.axis;
  144. const int16_t value = event.caxis.value;
  145. uint8_t mask_set = 0;
  146. uint8_t mask_clear = 0;
  147. if (SDL_CONTROLLER_AXIS_LEFTX == axis) {
  148. mask_clear = (1 << Button_Left) |
  149. (1 << Button_Right);
  150. if (value <= -8192) {
  151. mask_set = (1 << Button_Left);
  152. } else if (value >= 8192) {
  153. mask_set = (1 << Button_Right);
  154. }
  155. } else if (SDL_CONTROLLER_AXIS_LEFTY == axis) {
  156. mask_clear = (1 << Button_Down) |
  157. (1 << Button_Up);
  158. if (value <= -8192) {
  159. mask_set = (1 << Button_Up);
  160. } else if (value >= 8192) {
  161. mask_set = (1 << Button_Down);
  162. }
  163. }
  164. input->controllers[0].buttons &= ~mask_clear;
  165. input->controllers[0].buttons |= mask_set;
  166. } else if (SDL_CONTROLLERDEVICEADDED == event.type) {
  167. if (NULL == reader->data) {
  168. printf("New gamepad connected\n");
  169. reader->data = sdl_find_gamepad();
  170. if (reader->data) printf("Using new gamepad\n");
  171. } else {
  172. printf("Redundant gamepad connected\n");
  173. }
  174. } else if (SDL_CONTROLLERDEVICEREMOVED == event.type) {
  175. if (sdl_match_gamepad(event.cdevice.which,
  176. reader->data)) {
  177. printf("Gamepad disconnected\n");
  178. sdl_lose_gamepad(reader->data);
  179. reader->data = sdl_find_gamepad();
  180. if (reader->data) printf("Using another gamepad\n");
  181. } else {
  182. printf("Redundant gamepad disconnected\n");
  183. }
  184. }
  185. }
  186. return status;
  187. }
  188. nes_Input_Reader sdl_input = {
  189. .init = sdl_input_init,
  190. .done = sdl_input_done,
  191. .update = sdl_input_update,
  192. };