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.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

231 lines
7.7KB

  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_WINDOWEVENT == event.type) {
  86. if ( SDL_WINDOWEVENT_EXPOSED ==
  87. event.window.event) {
  88. status = input_Result_Refresh;
  89. }
  90. } else if ( ( SDL_KEYDOWN == event.type ||
  91. SDL_KEYUP == event.type) &&
  92. 0 == event.key.repeat
  93. ) {
  94. int index = button_index(event.key.keysym.sym,
  95. sdl_keycodes);
  96. if (index >= 0) {
  97. uint8_t mask = (1 << index);
  98. if (SDL_KEYDOWN == event.type) {
  99. input->controllers[0].buttons |= mask;
  100. } else {
  101. input->controllers[0].buttons &= ~mask;
  102. }
  103. } else if ( sdl_menu_key == event.key.keysym.sym &&
  104. SDL_KEYDOWN == event.type) {
  105. status = input_Result_Menu;
  106. } else if (sdl_save_key == event.key.keysym.sym) {
  107. if (SDL_KEYDOWN == event.type) {
  108. status = input_Result_Save;
  109. } else {
  110. status = input_Result_Cancel;
  111. }
  112. } else if (sdl_load_key == event.key.keysym.sym) {
  113. if (SDL_KEYDOWN == event.type) {
  114. status = input_Result_Load;
  115. } else {
  116. status = input_Result_Cancel;
  117. }
  118. }
  119. } else if ( SDL_CONTROLLERBUTTONDOWN == event.type ||
  120. SDL_CONTROLLERBUTTONUP == event.type) {
  121. int index = button_index(event.cbutton.button,
  122. sdl_buttons);
  123. if (index >= 0) {
  124. uint8_t mask = (1 << index);
  125. if (SDL_CONTROLLERBUTTONDOWN == event.type) {
  126. input->controllers[0].buttons |= mask;
  127. } else {
  128. input->controllers[0].buttons &= ~mask;
  129. }
  130. } else if (sdl_menu_button == event.cbutton.button) {
  131. if (SDL_CONTROLLERBUTTONDOWN == event.type) {
  132. status = input_Result_Menu;
  133. }
  134. } else if (sdl_save_button == event.cbutton.button) {
  135. if (SDL_CONTROLLERBUTTONDOWN == event.type) {
  136. status = input_Result_Save;
  137. } else {
  138. status = input_Result_Cancel;
  139. }
  140. } else if (sdl_load_button == event.cbutton.button) {
  141. if (SDL_CONTROLLERBUTTONDOWN == event.type) {
  142. status = input_Result_Load;
  143. } else {
  144. status = input_Result_Cancel;
  145. }
  146. }
  147. } else if (SDL_CONTROLLERAXISMOTION == event.type) {
  148. const uint8_t axis = event.caxis.axis;
  149. const int16_t value = event.caxis.value;
  150. uint8_t mask_set = 0;
  151. uint8_t mask_clear = 0;
  152. if (SDL_CONTROLLER_AXIS_LEFTX == axis) {
  153. mask_clear = (1 << Button_Left) |
  154. (1 << Button_Right);
  155. if (value <= -8192) {
  156. mask_set = (1 << Button_Left);
  157. } else if (value >= 8192) {
  158. mask_set = (1 << Button_Right);
  159. }
  160. } else if (SDL_CONTROLLER_AXIS_LEFTY == axis) {
  161. mask_clear = (1 << Button_Down) |
  162. (1 << Button_Up);
  163. if (value <= -8192) {
  164. mask_set = (1 << Button_Up);
  165. } else if (value >= 8192) {
  166. mask_set = (1 << Button_Down);
  167. }
  168. }
  169. input->controllers[0].buttons &= ~mask_clear;
  170. input->controllers[0].buttons |= mask_set;
  171. } else if (SDL_CONTROLLERDEVICEADDED == event.type) {
  172. if (NULL == reader->data) {
  173. printf("New gamepad connected\n");
  174. reader->data = sdl_find_gamepad();
  175. if (reader->data) printf("Using new gamepad\n");
  176. } else {
  177. printf("Redundant gamepad connected\n");
  178. }
  179. } else if (SDL_CONTROLLERDEVICEREMOVED == event.type) {
  180. if (sdl_match_gamepad(event.cdevice.which,
  181. reader->data)) {
  182. printf("Gamepad disconnected\n");
  183. sdl_lose_gamepad(reader->data);
  184. reader->data = sdl_find_gamepad();
  185. if (reader->data) printf("Using another gamepad\n");
  186. } else {
  187. printf("Redundant gamepad disconnected\n");
  188. }
  189. }
  190. }
  191. return status;
  192. }
  193. nes_Input_Reader sdl_input = {
  194. .init = sdl_input_init,
  195. .done = sdl_input_done,
  196. .update = sdl_input_update,
  197. };